diff --git a/.github/workflows/assign_milestone.yml b/.github/workflows/assign_milestone.yml index 443d28e80d6..e39f10b541e 100644 --- a/.github/workflows/assign_milestone.yml +++ b/.github/workflows/assign_milestone.yml @@ -18,12 +18,12 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Assign Milestone run: | diff --git a/.github/workflows/auto_approve_pr.yml b/.github/workflows/auto_approve_pr.yml index 6985f78e224..de553694927 100644 --- a/.github/workflows/auto_approve_pr.yml +++ b/.github/workflows/auto_approve_pr.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Auto Approve Pull Request env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index 0daada540b8..eb94baae86b 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -29,7 +29,7 @@ jobs: if [[ "${{github.event.pull_request}}" == "" ]]; then push='true' fi - echo Push='${push}' + echo Push ${push} echo "push=${push}" >> $GITHUB_OUTPUT build_and_push_vttestserver: @@ -46,11 +46,11 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Login to Docker Hub if: needs.push.outputs.push == 'true' - uses: docker/login-action@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -61,7 +61,7 @@ jobs: - name: Build and push on main if: startsWith(github.ref, 'refs/tags/') == false - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: . file: ${{ env.DOCKERFILE }} @@ -82,7 +82,7 @@ jobs: - name: Build and push on tags if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: . file: ${{ env.DOCKERFILE }} @@ -104,11 +104,11 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Login to Docker Hub if: needs.push.outputs.push == 'true' - uses: docker/login-action@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -123,7 +123,7 @@ jobs: - name: Build and push on main if: startsWith(github.ref, 'refs/tags/') == false - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: . file: ${{ env.DOCKERFILE }} @@ -148,7 +148,7 @@ jobs: - name: Build and push on tags if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: . file: ${{ env.DOCKERFILE }} @@ -171,11 +171,11 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Login to Docker Hub if: needs.push.outputs.push == 'true' - uses: docker/login-action@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -186,7 +186,7 @@ jobs: - name: Build and push on main latest tag if: startsWith(github.ref, 'refs/tags/') == false && matrix.debian == 'bookworm' - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ${{ env.DOCKER_CTX }} push: ${{ needs.push.outputs.push }} @@ -197,7 +197,7 @@ jobs: - name: Build and push on main debian specific tag if: startsWith(github.ref, 'refs/tags/') == false - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ${{ env.DOCKER_CTX }} push: ${{ needs.push.outputs.push }} @@ -229,7 +229,7 @@ jobs: # Build and Push component image to DOCKER_TAG, applies to both debian version - name: Build and push on tags using Debian extension if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ${{ env.DOCKER_CTX }} push: true @@ -242,7 +242,7 @@ jobs: # It is fine to build a second time here when "matrix.debian == 'bookworm'" as we have cached the first build already - name: Build and push on tags without Debian extension if: startsWith(github.ref, 'refs/tags/') && matrix.debian == 'bookworm' - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ${{ env.DOCKER_CTX }} push: true diff --git a/.github/workflows/check_make_vtadmin_authz_testgen.yml b/.github/workflows/check_make_vtadmin_authz_testgen.yml index 3502c973632..b4a73b570cc 100644 --- a/.github/workflows/check_make_vtadmin_authz_testgen.yml +++ b/.github/workflows/check_make_vtadmin_authz_testgen.yml @@ -27,11 +27,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -47,10 +47,10 @@ jobs: - '.github/workflows/check_make_vtadmin_authz_testgen.yml' - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.vtadmin_changes == 'true' with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 61c83168c23..329301662c4 100644 --- a/.github/workflows/check_make_vtadmin_web_proto.yml +++ b/.github/workflows/check_make_vtadmin_web_proto.yml @@ -27,11 +27,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -49,14 +49,14 @@ jobs: - '.github/workflows/check_make_vtadmin_web_proto.yml' - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.proto_changes == 'true' with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Setup Node if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.proto_changes == 'true' - uses: actions/setup-node@v4 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: # node-version should match package.json node-version: '20.12.2' diff --git a/.github/workflows/close_stale_pull_requests.yml b/.github/workflows/close_stale_pull_requests.yml index e0201c0104b..642e7ae38b2 100644 --- a/.github/workflows/close_stale_pull_requests.yml +++ b/.github/workflows/close_stale_pull_requests.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@f7176fd3007623b69d27091f9b9d4ab7995f0a06 # v5.2.1 with: days-before-stale: 30 # Do not handle issues at all. We only want to handle PRs. diff --git a/.github/workflows/cluster_endtoend_12.yml b/.github/workflows/cluster_endtoend_12.yml index 9bbef78eeb8..663eb117c91 100644 --- a/.github/workflows/cluster_endtoend_12.yml +++ b/.github/workflows/cluster_endtoend_12.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_13.yml b/.github/workflows/cluster_endtoend_13.yml index f26195f49e5..ea7fe6e2696 100644 --- a/.github/workflows/cluster_endtoend_13.yml +++ b/.github/workflows/cluster_endtoend_13.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_15.yml b/.github/workflows/cluster_endtoend_15.yml index cae2e55e669..99cee54d09b 100644 --- a/.github/workflows/cluster_endtoend_15.yml +++ b/.github/workflows/cluster_endtoend_15.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_18.yml b/.github/workflows/cluster_endtoend_18.yml index bcac80cf804..79aa133c909 100644 --- a/.github/workflows/cluster_endtoend_18.yml +++ b/.github/workflows/cluster_endtoend_18.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_21.yml b/.github/workflows/cluster_endtoend_21.yml index 9434a280829..d9d1ba77c34 100644 --- a/.github/workflows/cluster_endtoend_21.yml +++ b/.github/workflows/cluster_endtoend_21.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_backup_pitr.yml b/.github/workflows/cluster_endtoend_backup_pitr.yml index 8a562120fdb..9597640183d 100644 --- a/.github/workflows/cluster_endtoend_backup_pitr.yml +++ b/.github/workflows/cluster_endtoend_backup_pitr.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml b/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml index 1891d1a75d2..df056b679e1 100644 --- a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml +++ b/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -154,7 +154,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml index 1d1627463b1..beb20294f41 100644 --- a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml +++ b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -169,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_mysql80.yml b/.github/workflows/cluster_endtoend_mysql80.yml index 8c2f3e4dd80..90c318bdc5d 100644 --- a/.github/workflows/cluster_endtoend_mysql80.yml +++ b/.github/workflows/cluster_endtoend_mysql80.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_mysql_server_vault.yml b/.github/workflows/cluster_endtoend_mysql_server_vault.yml index 48a4c5c1897..04a0b2b9321 100644 --- a/.github/workflows/cluster_endtoend_mysql_server_vault.yml +++ b/.github/workflows/cluster_endtoend_mysql_server_vault.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_revert.yml b/.github/workflows/cluster_endtoend_onlineddl_revert.yml index d48f9919055..d8d5e50b7e9 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_revert.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_revert.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -152,7 +152,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml b/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml index bf06949472a..456e253cc1d 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -152,7 +152,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml index c920d49cbd3..76564fc573e 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml index f58e9239bcb..bdfa7221d66 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml index 7a30bd2c476..d2b27488598 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml index f1ba097e3f9..d2a8a430ea6 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml b/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml index 0a239092a2f..a630ee9b08c 100644 --- a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml +++ b/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml b/.github/workflows/cluster_endtoend_tabletmanager_consul.yml index 27b72d07b9e..722ba33f59f 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_consul.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml b/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml index 90c07975836..3addbc6ebee 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml b/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml index f2643f2060c..a6413750d18 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_topo_connection_cache.yml b/.github/workflows/cluster_endtoend_topo_connection_cache.yml index 80883fb70d1..3bb99b0b5fc 100644 --- a/.github/workflows/cluster_endtoend_topo_connection_cache.yml +++ b/.github/workflows/cluster_endtoend_topo_connection_cache.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml index 79a154c2ead..2c6e6b8a5e7 100644 --- a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml +++ b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_basic.yml b/.github/workflows/cluster_endtoend_vreplication_basic.yml index 9af84e462c9..a17b13846d0 100644 --- a/.github/workflows/cluster_endtoend_vreplication_basic.yml +++ b/.github/workflows/cluster_endtoend_vreplication_basic.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml index 3180f0ea723..0588a642a1b 100644 --- a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml +++ b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml b/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml index b52e0cb433b..f737bd55e52 100644 --- a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml +++ b/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml b/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml index 26e670c3d08..2f34d1ab616 100644 --- a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml +++ b/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml b/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml index ab8ea8b7264..853a9fdaada 100644 --- a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml +++ b/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" 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 924a45aa439..f265156b047 100644 --- a/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml +++ b/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml b/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml index 35270501b38..080942b091b 100644 --- a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml +++ b/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" 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 d93a59e2d50..ee71dfa3bf1 100644 --- a/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml +++ b/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vreplication_v2.yml b/.github/workflows/cluster_endtoend_vreplication_v2.yml index 65a3d58b2a0..197f619ced7 100644 --- a/.github/workflows/cluster_endtoend_vreplication_v2.yml +++ b/.github/workflows/cluster_endtoend_vreplication_v2.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +173,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vstream.yml b/.github/workflows/cluster_endtoend_vstream.yml index 74ef2e73b86..45390abc20d 100644 --- a/.github/workflows/cluster_endtoend_vstream.yml +++ b/.github/workflows/cluster_endtoend_vstream.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtbackup.yml b/.github/workflows/cluster_endtoend_vtbackup.yml index c95fe428092..f3418055f78 100644 --- a/.github/workflows/cluster_endtoend_vtbackup.yml +++ b/.github/workflows/cluster_endtoend_vtbackup.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml index 72fd1c652eb..75d1d434421 100644 --- a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -169,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml b/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml index 374ac97a4d7..a8128fd20a5 100644 --- a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml +++ b/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml b/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml index 7f2c2f6e9ba..50009807e53 100644 --- a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml +++ b/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_gen4.yml b/.github/workflows/cluster_endtoend_vtgate_gen4.yml index 5890970519f..cd8f7652ad5 100644 --- a/.github/workflows/cluster_endtoend_vtgate_gen4.yml +++ b/.github/workflows/cluster_endtoend_vtgate_gen4.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml index 6ac03c17e81..4c74a304259 100644 --- a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -169,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_godriver.yml b/.github/workflows/cluster_endtoend_vtgate_godriver.yml index 9eba657c65d..44294e1eaa0 100644 --- a/.github/workflows/cluster_endtoend_vtgate_godriver.yml +++ b/.github/workflows/cluster_endtoend_vtgate_godriver.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml b/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml index 9600c48486f..6699c71b7a5 100644 --- a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml +++ b/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_queries.yml b/.github/workflows/cluster_endtoend_vtgate_queries.yml index dcc10cb9b4a..4e6d8bfbbde 100644 --- a/.github/workflows/cluster_endtoend_vtgate_queries.yml +++ b/.github/workflows/cluster_endtoend_vtgate_queries.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml b/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml index 8d95830e276..e0b83320841 100644 --- a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml +++ b/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml b/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml index ad95087a8f3..639b94f3dbd 100644 --- a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml +++ b/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_schema.yml b/.github/workflows/cluster_endtoend_vtgate_schema.yml index a3b79c0b8d0..55f6ac54c38 100644 --- a/.github/workflows/cluster_endtoend_vtgate_schema.yml +++ b/.github/workflows/cluster_endtoend_vtgate_schema.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml b/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml index 50a044c4bc2..ad3de660918 100644 --- a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml +++ b/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml b/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml index 007289158ac..a151116bd61 100644 --- a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml +++ b/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo.yml b/.github/workflows/cluster_endtoend_vtgate_topo.yml index 2384d8e6021..da060543308 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml b/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml index 906f9aa04d8..17bd5bf3893 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -156,7 +156,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml b/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml index 64861ef358a..9d08245aae0 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_transaction.yml b/.github/workflows/cluster_endtoend_vtgate_transaction.yml index 41a84f42d3f..cc9f66fd003 100644 --- a/.github/workflows/cluster_endtoend_vtgate_transaction.yml +++ b/.github/workflows/cluster_endtoend_vtgate_transaction.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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() @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml b/.github/workflows/cluster_endtoend_vtgate_unsharded.yml index a879e88ba44..868611b37f3 100644 --- a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml +++ b/.github/workflows/cluster_endtoend_vtgate_unsharded.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml index 964146c9829..c3cf3cbd8da 100644 --- a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -169,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtgate_vschema.yml b/.github/workflows/cluster_endtoend_vtgate_vschema.yml index c66c9959ab2..90730ff3437 100644 --- a/.github/workflows/cluster_endtoend_vtgate_vschema.yml +++ b/.github/workflows/cluster_endtoend_vtgate_vschema.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vtorc.yml b/.github/workflows/cluster_endtoend_vtorc.yml index d6fb811f533..6be4989ba83 100644 --- a/.github/workflows/cluster_endtoend_vtorc.yml +++ b/.github/workflows/cluster_endtoend_vtorc.yml @@ -54,11 +54,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -80,13 +80,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -160,7 +160,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml b/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml index 248a611a864..e4519d1b3bb 100644 --- a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml +++ b/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -151,7 +151,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_xb_backup.yml b/.github/workflows/cluster_endtoend_xb_backup.yml index 5a8acc66d8c..9bc4ef12aa0 100644 --- a/.github/workflows/cluster_endtoend_xb_backup.yml +++ b/.github/workflows/cluster_endtoend_xb_backup.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -154,7 +154,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/cluster_endtoend_xb_recovery.yml b/.github/workflows/cluster_endtoend_xb_recovery.yml index 94fb11320fb..c239939cb47 100644 --- a/.github/workflows/cluster_endtoend_xb_recovery.yml +++ b/.github/workflows/cluster_endtoend_xb_recovery.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -154,7 +154,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 3015309d2c2..27837fef03a 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -13,10 +13,10 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in files relevant to code coverage - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -30,13 +30,13 @@ jobs: - name: Set up Go if: steps.changes.outputs.changed_files == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.changes.outputs.changed_files == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.changes.outputs.changed_files == 'true' diff --git a/.github/workflows/codeql_analysis.yml b/.github/workflows/codeql_analysis.yml index 154ce0fa822..c85af0fb8ce 100644 --- a/.github/workflows/codeql_analysis.yml +++ b/.github/workflows/codeql_analysis.yml @@ -27,12 +27,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 # 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 diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index cb393141ae3..d4895d4d383 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -18,9 +18,9 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Setup node uses: actions/setup-node@v4 @@ -32,7 +32,7 @@ jobs: sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies run: | diff --git a/.github/workflows/docker_test_cluster_10.yml b/.github/workflows/docker_test_cluster_10.yml index 2a1c1050461..58023ee21f4 100644 --- a/.github/workflows/docker_test_cluster_10.yml +++ b/.github/workflows/docker_test_cluster_10.yml @@ -27,11 +27,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -52,9 +52,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 ba73f50252b..345f0928aca 100644 --- a/.github/workflows/docker_test_cluster_25.yml +++ b/.github/workflows/docker_test_cluster_25.yml @@ -27,11 +27,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -52,9 +52,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 cef0ea4d583..87c4cec4aae 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -26,11 +26,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -50,9 +50,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 783d3305fc8..7780d33b633 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -26,11 +26,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -50,9 +50,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 78cd2d1784f..819fc56fe7b 100644 --- a/.github/workflows/local_example.yml +++ b/.github/workflows/local_example.yml @@ -30,11 +30,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -55,9 +55,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' @@ -71,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 fa08d3d80cb..998705e6664 100644 --- a/.github/workflows/region_example.yml +++ b/.github/workflows/region_example.yml @@ -30,11 +30,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -55,9 +55,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' @@ -71,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/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 00000000000..be49fd794ea --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,67 @@ +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@v2 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@v3 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/static_checks_etc.yml b/.github/workflows/static_checks_etc.yml index 75fb01e487e..e7c6e265e35 100644 --- a/.github/workflows/static_checks_etc.yml +++ b/.github/workflows/static_checks_etc.yml @@ -31,7 +31,7 @@ jobs: - name: Checkout code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Run FOSSA scan and upload build data uses: fossa-contrib/fossa-action@v3 @@ -42,7 +42,7 @@ jobs: - name: Check for changes in Go files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -52,6 +52,7 @@ jobs: - '*.go' - 'go.sum' - 'go.mod' + - '.github/workflows/static_checks_etc.yml' parser_changes: - 'go/vt/sqlparser/**' - 'go.sum' @@ -118,12 +119,13 @@ jobs: - '.github/**' - 'Makefile' - 'test/ci_workflow_gen.go' + - '.github/workflows/static_checks_etc.yml' - name: Set up Go 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 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.go_files == 'true' @@ -193,7 +195,7 @@ jobs: - name: Install golangci-lint if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.go_files == 'true' - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.2 + run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.2 - name: Clean Env if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.go_files == 'true' diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml index 3f6de3eb6f8..a76e5c09edf 100644 --- a/.github/workflows/unit_race.yml +++ b/.github/workflows/unit_race.yml @@ -43,11 +43,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -67,13 +67,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -147,7 +147,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_race_evalengine.yml b/.github/workflows/unit_race_evalengine.yml index 77ada6729bd..94c17d7c9d3 100644 --- a/.github/workflows/unit_race_evalengine.yml +++ b/.github/workflows/unit_race_evalengine.yml @@ -43,11 +43,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -67,13 +67,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -147,7 +147,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_test_evalengine_mysql57.yml b/.github/workflows/unit_test_evalengine_mysql57.yml index 7ab842835fb..234d45f2ac9 100644 --- a/.github/workflows/unit_test_evalengine_mysql57.yml +++ b/.github/workflows/unit_test_evalengine_mysql57.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -69,13 +69,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +172,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_test_evalengine_mysql80.yml b/.github/workflows/unit_test_evalengine_mysql80.yml index f5c127a8b77..78d756a272d 100644 --- a/.github/workflows/unit_test_evalengine_mysql80.yml +++ b/.github/workflows/unit_test_evalengine_mysql80.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -69,13 +69,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -170,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_test_evalengine_mysql84.yml b/.github/workflows/unit_test_evalengine_mysql84.yml new file mode 100644 index 00000000000..7cccc19cdd3 --- /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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # 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@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 + with: + go-version: 1.23.0 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 + + - 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@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 + with: + paths: "report.xml" + show: "fail, skip" diff --git a/.github/workflows/unit_test_mysql57.yml b/.github/workflows/unit_test_mysql57.yml index cd28efef0d8..af2c53c728e 100644 --- a/.github/workflows/unit_test_mysql57.yml +++ b/.github/workflows/unit_test_mysql57.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -69,13 +69,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -173,7 +172,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_test_mysql80.yml b/.github/workflows/unit_test_mysql80.yml index e66423ad1b7..84a1784c261 100644 --- a/.github/workflows/unit_test_mysql80.yml +++ b/.github/workflows/unit_test_mysql80.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -69,13 +69,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -170,7 +169,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/.github/workflows/unit_test_mysql84.yml b/.github/workflows/unit_test_mysql84.yml new file mode 100644 index 00000000000..36b672c3c31 --- /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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # 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@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 + with: + go-version: 1.23.0 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 + + - 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@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 + with: + paths: "report.xml" + show: "fail, skip" diff --git a/.github/workflows/update_golang_dependencies.yml b/.github/workflows/update_golang_dependencies.yml index 7538090d51e..147b1681a39 100644 --- a/.github/workflows/update_golang_dependencies.yml +++ b/.github/workflows/update_golang_dependencies.yml @@ -17,12 +17,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: main diff --git a/.github/workflows/update_golang_version.yml b/.github/workflows/update_golang_version.yml index df9677e7cf4..941f501ef2a 100644 --- a/.github/workflows/update_golang_version.yml +++ b/.github/workflows/update_golang_version.yml @@ -20,12 +20,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ matrix.branch }} diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml index e8b8a688879..ee548ef2da9 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml @@ -35,7 +35,7 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -49,7 +49,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -70,13 +70,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -107,7 +107,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -129,7 +129,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' 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 0e24c534057..478613ef6ea 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml @@ -25,7 +25,7 @@ jobs: fi - name: Check out commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -51,7 +51,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -72,13 +72,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -109,7 +109,7 @@ jobs: # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -131,7 +131,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual.yml b/.github/workflows/upgrade_downgrade_test_backups_manual.yml index 3f25e2c8663..159b5fa599b 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual.yml @@ -38,7 +38,7 @@ jobs: # Checkout to this build's commit - name: Checkout to commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -74,13 +74,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -129,7 +129,7 @@ jobs: # Checkout to the last release of Vitess - name: Checkout to the 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -151,7 +151,7 @@ jobs: # Checkout to this build's commit - name: Checkout to commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' 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 83a678fc065..2ed63013215 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml @@ -27,7 +27,7 @@ jobs: # Checkout to this build's commit - name: Checkout to commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -75,13 +75,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -130,7 +130,7 @@ jobs: # Checkout to the next release of Vitess - name: Checkout to the 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -152,7 +152,7 @@ jobs: # Checkout to this build's commit - name: Checkout to commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml index a5361817739..e0847e737c4 100644 --- a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml +++ b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml @@ -38,13 +38,13 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -81,13 +81,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -127,7 +127,7 @@ jobs: # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -140,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/ @@ -149,7 +150,7 @@ jobs: # Checkout to the next release of Vitess - name: Check out next 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -162,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/ @@ -171,7 +173,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -182,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 93360699f93..34f3cfeda12 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml @@ -38,7 +38,7 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -73,13 +73,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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,46 +116,43 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - # 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 + # Build current commit's binaries + - 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 last release's binaries + - 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-other/ - cp -R bin /tmp/vitess-build-other/ + mkdir -p /tmp/vitess-build-current/ + cp -R bin /tmp/vitess-build-current/ rm -Rf bin/* - # Checkout to this build's commit - - name: Check out commit's code + # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} - - name: Get dependencies for this commit + - 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 the binaries for this commit + - 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-current/ - cp -R bin /tmp/vitess-build-current/ + mkdir -p /tmp/vitess-build-other/ + cp -R bin /tmp/vitess-build-other/ + rm -Rf bin/* # Swap the binaries in the bin. Use vtgate version n-1 and keep vttablet at version n - name: Use last release's VTGate @@ -163,12 +160,13 @@ jobs: run: | source build.env + cp -r /tmp/vitess-build-current/bin/* $PWD/bin/ rm -f $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vtgate $PWD/bin/vtgate vtgate --version - # Running a test with vtgate at version n-1 and vttablet at version n - - name: Run query serving tests (vtgate=N-1, vttablet=N) + # Running a test with vtgate at version n-1 and vttablet/vtctld at version n + - name: Run query serving tests (vtgate=N-1, vttablet=N, vtctld=N) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' run: | rm -rf /tmp/vtdataroot @@ -177,8 +175,8 @@ jobs: source build.env eatmydata -- go run test.go -skip-build -keep-data=false -docker=false -print-log -follow -tag upgrade_downgrade_query_serving_queries - # Swap the binaries again. This time, vtgate will be at version n, and vttablet will be at version n-1 - - name: Use current version VTGate, and other version VTTablet + # Swap the binaries again. This time, vtgate will be at version n, and vttablet/vtctld will be at version n-1 + - name: Use current version VTGate, and other version VTTablet/VTctld if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' run: | source build.env @@ -197,8 +195,8 @@ jobs: vtgate --version vttablet --version - # Running a test with vtgate at version n and vttablet at version n-1 - - name: Run query serving tests (vtgate=N, vttablet=N-1) + # Running a test with vtgate at version n and vttablet/vtctld at version n-1 + - name: Run query serving tests (vtgate=N, vttablet=N-1, vtctld=N-1) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' run: | rm -rf /tmp/vtdataroot 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 6c3674a1d75..ce9680e8bfa 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 @@ -27,7 +27,7 @@ jobs: fi - name: Check out commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -74,13 +74,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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,46 +117,43 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - # 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' - uses: actions/checkout@v4 - with: - ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} - - - name: Get dependencies for the next release + # Build current commit's binaries + - 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 next release's binaries + - 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-other/ - cp -R bin /tmp/vitess-build-other/ + mkdir -p /tmp/vitess-build-current/ + cp -R bin /tmp/vitess-build-current/ rm -Rf bin/* - # Checkout to this build's commit - - name: Check out commit's code + # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} - - name: Get dependencies for this commit + - name: Get dependencies for the next release 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 + - name: Building next 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-current/ - cp -R bin /tmp/vitess-build-current/ + mkdir -p /tmp/vitess-build-other/ + cp -R bin /tmp/vitess-build-other/ + rm -Rf bin/* # Swap the binaries in the bin. Use vtgate version n+1 and keep vttablet at version n - name: Use next release's VTGate @@ -164,6 +161,7 @@ jobs: run: | source build.env + cp -r /tmp/vitess-build-current/bin/* $PWD/bin/ rm -f $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vtgate $PWD/bin/vtgate vtgate --version diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml index cc519f335cf..0bca2452eef 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml @@ -38,7 +38,7 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -73,13 +73,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -119,7 +119,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -141,7 +141,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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 c1864a9a3e7..31470d2e7cc 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 @@ -27,7 +27,7 @@ jobs: fi - name: Check out commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -74,13 +74,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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,7 +120,7 @@ jobs: # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -142,7 +142,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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 66033484ce3..bd659e6d268 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml @@ -27,7 +27,7 @@ jobs: fi - name: Check out commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -74,13 +74,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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,7 +120,7 @@ jobs: # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -142,7 +142,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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 d937bc7bc11..ad5812eca1e 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml @@ -27,7 +27,7 @@ jobs: fi - name: Check out commit's code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -74,13 +74,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -127,7 +127,7 @@ jobs: # 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' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-next-release-ref.outputs.next_release_ref }} @@ -149,7 +149,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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_vtctl.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml index ac6ef068654..3812220748b 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml @@ -38,7 +38,7 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -73,13 +73,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -119,7 +119,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -141,7 +141,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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 df0cdb9c7c9..5d76d647a7c 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml @@ -38,7 +38,7 @@ jobs: - name: Check out commit's code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -73,13 +73,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.22.6 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -119,7 +119,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} @@ -141,7 +141,7 @@ jobs: # 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 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Get dependencies for this commit 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..8a8bc7f019a --- /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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + 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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # 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@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 + with: + go-version: 1.22.6 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 + + - 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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + 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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - 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 0c2965fee9c..d598bd88c76 100644 --- a/.github/workflows/vitess_tester_vtgate.yml +++ b/.github/workflows/vitess_tester_vtgate.yml @@ -45,11 +45,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -57,7 +57,7 @@ jobs: end_to_end: - 'go/**/*.go' - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' + - 'go/test/endtoend/vtgate/vitess_tester/**' - 'test.go' - 'Makefile' - 'build.env' @@ -71,13 +71,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -112,7 +112,7 @@ jobs: go install github.com/vitessio/go-junit-report@HEAD # install vitess tester - go install github.com/vitessio/vitess-tester@eb953122baba163ed8ccaa6642458ee984f5d7e4 + go install github.com/vitessio/vitess-tester@89dd933a9ea0e15f69ca58b9c8ea09a358762cca - name: Setup launchable dependencies if: steps.skip-workflow.outputs.is_draft == 'false' && steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' @@ -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 @@ -143,9 +144,9 @@ jobs: # We go over all the directories in the given path. # If there is a vschema file there, we use it, otherwise we let vitess-tester autogenerate it. if [ -f $dir/vschema.json ]; then - vitess-tester --sharded --xunit --test-dir $dir --vschema "$dir"vschema.json + vitess-tester --xunit --vschema "$dir"vschema.json $dir/*.test else - vitess-tester --sharded --xunit --test-dir $dir + vitess-tester --sharded --xunit $dir/*.test fi # Number the reports by changing their file names. mv report.xml report"$i".xml @@ -165,7 +166,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report*.xml" show: "fail, skip" diff --git a/.github/workflows/vtadmin_web_build.yml b/.github/workflows/vtadmin_web_build.yml index ccc920312c5..953d5eb058a 100644 --- a/.github/workflows/vtadmin_web_build.yml +++ b/.github/workflows/vtadmin_web_build.yml @@ -35,7 +35,7 @@ jobs: echo Skip ${skip} echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/setup-node@v4 diff --git a/.github/workflows/vtadmin_web_lint.yml b/.github/workflows/vtadmin_web_lint.yml index e40d1174953..88dc4bf1c5d 100644 --- a/.github/workflows/vtadmin_web_lint.yml +++ b/.github/workflows/vtadmin_web_lint.yml @@ -35,7 +35,7 @@ jobs: echo Skip ${skip} echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/setup-node@v4 diff --git a/.github/workflows/vtadmin_web_unit_tests.yml b/.github/workflows/vtadmin_web_unit_tests.yml index df1de751466..0f6b2ece69a 100644 --- a/.github/workflows/vtadmin_web_unit_tests.yml +++ b/.github/workflows/vtadmin_web_unit_tests.yml @@ -35,7 +35,7 @@ jobs: echo Skip ${skip} echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/setup-node@v4 diff --git a/.gitignore b/.gitignore index 70ae13ad32d..e8c441d3bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,4 @@ report # mise files .mise.toml +/errors/ diff --git a/.golangci.yml b/.golangci.yml index d20e7d1e9fd..e907f56743b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ run: - go: 1.20 + go: 1.23 timeout: 10m linters-settings: @@ -11,7 +11,38 @@ linters-settings: - pkg: "math/rand$" desc: Please use math/rand/v2 errcheck: - exclude: ./misc/errcheck_excludes.txt + exclude-functions: + - flag.Set + - (*flag.FlagSet).Parse + - (flag.Value).Set + - fmt.Fprint + - fmt.Fprintf + - io.WriteString(fmt.State) + - io.WriteString(net/http.ResponseWriter) + - (net.Listener).Close + - (net/http.ResponseWriter).Write + - (*os.File).Close + - os.Remove + - os.RemoveAll + - os.Rename + - (*github.com/spf13/cobra.Command).Help + - (*github.com/spf13/cobra.Command).MarkFlagRequired + - (*github.com/spf13/cobra.Command).MarkPersistentFlagRequired + - (*github.com/spf13/cobra.Command).MarkPersistentFlagFilename + - (*github.com/spf13/pflag.FlagSet).MarkDeprecated + - (*google.golang.org/grpc.ClientConn).Close + - (*google.golang.org/grpc.Server).Serve + - (*vitess.io/vitess/go/bytes2.Buffer).Write + - (*vitess.io/vitess/go/bytes2.Buffer).WriteByte + - (*vitess.io/vitess/go/bytes2.Buffer).WriteString + - (vitess.io/vitess/go/sqltypes.BinWriter).Write + - vitess.io/vitess/go/vt/orchestrator/external/golib/log.Errore + - vitess.io/vitess/go/vt/orchestrator/external/golib/log.Errorf + - vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatal + - vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatale + - vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatalf + - (*vitess.io/vitess/go/vt/vttest.LocalCluster).TearDown + goimports: local-prefixes: vitess.io/vitess govet: diff --git a/Makefile b/Makefile index e46f5d1ca5a..841ddfff2ed 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/... @@ -280,9 +284,9 @@ $(PROTO_GO_OUTS): minimaltools install_protoc-gen-go proto/*.proto # Please read docker/README.md to understand the different available images. # This rule builds the bootstrap images for all flavors. -DOCKER_IMAGES_FOR_TEST = mysql57 mysql80 percona57 percona80 +DOCKER_IMAGES_FOR_TEST = mysql80 percona80 DOCKER_IMAGES = common $(DOCKER_IMAGES_FOR_TEST) -BOOTSTRAP_VERSION=34 +BOOTSTRAP_VERSION=35 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 @@ -324,6 +328,7 @@ $(DOCKER_LITE_TARGETS): docker_lite_%: ${call build_docker_image,docker/lite/Dockerfile.$*,vitess/lite:$*} docker_lite_push: + echo "pushing lite image: latest" && docker push vitess/lite:latest for i in $(DOCKER_LITE_SUFFIX); do echo "pushing lite image: $$i"; docker push vitess/lite:$$i || exit 1; done docker_lite_all: docker_lite $(DOCKER_LITE_TARGETS) diff --git a/README.md b/README.md index adc8cd93c19..b1247a29469 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Go Report Card](https://goreportcard.com/badge/vitess.io/vitess)](https://goreportcard.com/report/vitess.io/vitess) [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fvitess.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fvitess?ref=badge_shield&issueType=license) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1724/badge)](https://bestpractices.coreinfrastructure.org/projects/1724) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/vitessio/vitess/badge)](https://scorecard.dev/viewer/?uri=github.com/vitessio/vitess) # Vitess diff --git a/build.env b/build.env index ba741be4211..cfddc55c11f 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.5 || echo "Go version reported: `go version`. Version 1.22.5+ recommended. See https://vitess.io/contributing/build-from-source for install instructions." +goversion_min 1.23.0 || echo "Go version reported: `go version`. Version 1.23.0+ 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.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.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 49c8b41d45f..f24b2ee87ab 100644 --- a/changelog/21.0/21.0.0/summary.md +++ b/changelog/21.0/21.0.0/summary.md @@ -7,8 +7,12 @@ - **[Deprecations and Deletions](#deprecations-and-deletions)** - [Deletion of deprecated metrics](#metric-deletion) - [VTTablet Flags](#vttablet-flags) - - **[Breaking changes](#breaking-changes)** + - [Metrics](#deprecations-metrics) - **[Traffic Mirroring](#traffic-mirroring)** + - **[New VTGate Shutdown Behavior](#new-vtgate-shutdown-behavior)** + - **[Tablet Throttler: Multi-Metric support](#tablet-throttler)** + - **[Allow Cross Cell Promotion in PRS](#allow-cross-cell)** + - **[Support for recursive CTEs](#recursive-cte)** ## Major Changes @@ -39,6 +43,20 @@ The following metrics that were deprecated in the previous release, have now bee - `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. @@ -50,3 +68,41 @@ $ vtctldclient --server :15999 MoveTables --target-keyspace customer --workflow ``` 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. + +### Allow Cross Cell Promotion in PRS +Up until now if the users wanted to promote a replica in a different cell than the current primary using `PlannedReparentShard`, they had to specify the new primary with the `--new-primary` flag. + +We have now added a new flag `--allow-cross-cell-promotion` that lets `PlannedReparentShard` choose a primary in a different cell even if no new primary is provided explicitly. + +### Experimental support for recursive CTEs +We have added experimental support for recursive CTEs in Vitess. We are marking it as experimental because it is not yet fully tested and may have some limitations. We are looking for feedback from the community to improve this feature. \ No newline at end of file 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/AtomicTransactionsWithDisruptions.md b/doc/design-docs/AtomicTransactionsWithDisruptions.md new file mode 100644 index 00000000000..4ca60778436 --- /dev/null +++ b/doc/design-docs/AtomicTransactionsWithDisruptions.md @@ -0,0 +1,51 @@ +# Handling disruptions in atomic transactions + +## Overview + +This document describes how to make atomic transactions resilient in the face of disruptions. The basic design and components involved in an atomic transaction are described in [here](./TwoPhaseCommitDesign.md) The document describes each of the disruptions that can happen in a running cluster and how atomic transactions are engineered to handle them without breaking their guarantee of being atomic. + +## `PlannedReparentShard` and `EmergencyReparentShard` + +For both Planned and Emergency reparents, we call `DemotePrimary` on the primary tablet. For Planned reparent, this call has to succeed, while on Emergency reparent, if the primary is unreachable then this call can fail, and we would still proceed further. + +As part of the `DemotePrimary` flow, when we transition the tablet to a non-serving state, we wait for all the transactions to have completed (in `TxEngine.shutdownLocked()` we have `te.txPool.WaitForEmpty()`). If the user has specified a shutdown grace-period, then after that much time elapses, we go ahead and forcefully kill all running queries. We then also rollback the prepared transactions. It is crucial that we rollback the prepared transactions only after all other writes have been killed, because when we rollback a prepared transaction, it lets go of the locks it was holding. If there were some other conflicting write in progress that hadn't been killed, then it could potentially go through and cause data corruption since we won't be able to prepare the transaction again. All the code to kill queries can be found in `stateManager.terminateAllQueries()`. + +The above outlined steps ensure that we either wait for all prepared transactions to conclude or we rollback them safely so that they can be prepared again on the new primary. + +On the new primary, when we call `PromoteReplica`, we redo all the prepared transactions before we allow any new writes to go through. This ensures that the new primary is in the same state as the old primary was before the reparent. The code for redoing the prepared transactions can be found in `TxEngine.RedoPreparedTransactions()`. + +If everything goes as described above, there is no reason for redoing of prepared transactions to fail. But in case, something unexpected happens and preparing transactions fails, we still allow the vttablet to accept new writes because we decided availability of the tablet is more important. We will however, build tooling and metrics for the users to be notified of these failures and let them handle this in the way they see fit. + +While Planned reparent is an operation where all the processes are running fine, Emergency reparent is called when something has gone wrong with the cluster. Because we call `DemotePrimary` in parallel with `StopReplicationAndBuildStatusMap`, we can run into a case wherein the primary tries to write something to the binlog after all the replicas have stopped replicating. If we were to run without semi-sync, then the primary could potentially commit a prepared transaction, and return a success to the vtgate trying to commit this transaction. The vtgate can then conclude that the transaction is safe to conclude and remove all the metadata information. However, on the new primary since the transaction commit didn't get replicated, it would re-prepare the transaction and would wait for a coordinator to either commit or rollback it, but that would never happen. Essentially we would have a transaction stuck in prepared state on a shard indefinitely. To avoid this situation, it is essential that we run with semi-sync, because this ensures that any write that is acknowledged as a success to the caller, would necessarily have to be replicated to at least one replica. This ensures that the transaction would also already be committed on the new primary. + +## MySQL Restarts + +When MySQL restarts, it loses all the ongoing transactions which includes all the prepared transactions. This is because the transaction logs are not persistent across restarts. This is a MySQL limitation and there is no way to get around this. However, at the Vitess level we must ensure that we can commit the prepared transactions even in case of MySQL restarts without any failures. + +Vttablet has the code to detect MySQL failures and call `stateManager.checkMySQL()` which transitions the tablet to a NotConnected state. This prevents any writes from going through until the vttablet has transitioned back to a serving state. + +However, we cannot rely on `checkMySQL` to ensure that no conflicting writes go through. This is because the time between MySQL restart and the vttablet transitioning to a NotConnected state can be large. During this time, the vttablet would still be accepting writes and some of them could potentially conflict with the prepared transactions. + +To handle this, we rely on the fact that when MySQL restarts, it starts with super-read-only turned on. This means that no writes can go through. It is VTOrc that registers this as an issue and fixes it by calling `UndoDemotePrimary`. As part of that call, before we set MySQL to read-write, we ensure that all the prepared transactions are redone in the read_only state. We use the dba pool (that has admin permissions) to prepare the transactions. This is safe because we know that no conflicting writes can go through until we set MySQL to read-write. The code to set MySQL to read-write after redoing prepared transactions can be found in `TabletManager.redoPreparedTransactionsAndSetReadWrite()`. + +Handling MySQL restarts is the only reason we needed to add the code to redo prepared transactions whenever MySQL transitions from super-read-only to read-write state. Even though, we only need to do this in `UndoDemotePrimary`, it not necessary that it is `UndoDemotePrimary` that sets MySQL to read-write. If the user notices that the tablet is in a read-only state before VTOrc has a chance to fix it, they can manually call `SetReadWrite` on the tablet. +Therefore, the safest option was to always check if we need to redo the prepared transactions whenever MySQL transitions from super-read-only to read-write state. + +## Vttablet Restarts + +When Vttabet restarts, all the previous connections are dropped. It starts in a non-serving state, and then after reading the shard and tablet records from the topo, it transitions to a serving state. +As part of this transition we need to ensure that we redo the prepared transactions before we start accepting any writes. This is done as part of the `TxEngine.transition` function when we transition to an `AcceptingReadWrite` state. We call the same code for redoing the prepared transactions that we called for MySQL restarts, PRS and ERS. + +## Online DDL + +During an Online DDL cutover, we need to ensure that all the prepared transactions on the online DDL table needs to be completed before we can proceed with the cutover. +This is because the cutover involves a schema change and we cannot have any prepared transactions that are dependent on the old schema. + +As part of the cut-over process, Online DDL adds query rules to buffer new queries on the table. +It then checks for any open prepared transaction on the table and waits for up to 100ms if found, then checks again. +If it finds no prepared transaction of the table, it moves forward with the cut-over, otherwise it fails. The Online DDL mechanism will later retry the cut-over. + +In the Prepare code, we check the query rules before adding the transaction to the prepared list and re-check the rules before storing the transaction logs in the transaction redo table. +Any transaction that went past the first check will fail the second check if the cutover proceeds. + +The check on both sides prevents either the cutover from proceeding or the transaction from being prepared. \ No newline at end of file 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/docker/bootstrap/CHANGELOG.md b/docker/bootstrap/CHANGELOG.md index dd9d1c19f17..0ecd5ede02f 100644 --- a/docker/bootstrap/CHANGELOG.md +++ b/docker/bootstrap/CHANGELOG.md @@ -132,4 +132,9 @@ List of changes between bootstrap image versions. ## [34] - 2024-07-02 ### Changes -- Update build to golang 1.22.5 \ No newline at end of file +- Update build to golang 1.22.5 + +## [35] - 2024-08-14 +### Changes +- Update build to golang 1.23.0 +- MySQL57 and Percona57 tags will be removed thereafter \ No newline at end of file diff --git a/docker/bootstrap/Dockerfile.common b/docker/bootstrap/Dockerfile.common index c48a485bec3..f98d4628ea4 100644 --- a/docker/bootstrap/Dockerfile.common +++ b/docker/bootstrap/Dockerfile.common @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.22.5-bullseye +FROM --platform=linux/amd64 golang:1.23.0-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 deleted file mode 100644 index 983f3640472..00000000000 --- a/docker/bootstrap/Dockerfile.mysql57 +++ /dev/null @@ -1,24 +0,0 @@ -ARG bootstrap_version -ARG image="vitess/bootstrap:${bootstrap_version}-common" - -FROM --platform=linux/amd64 "${image}" - -USER root - -# Install MySQL 5.7 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates && \ - for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com A8D3785C && break; done && \ - add-apt-repository 'deb http://repo.mysql.com/apt/debian/ buster mysql-5.7' && \ - for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys 9334A25F8507EFA5 && break; done && \ - echo 'deb http://repo.percona.com/apt buster main' > /etc/apt/sources.list.d/percona.list && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - 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/* - -USER vitess diff --git a/docker/bootstrap/Dockerfile.percona57 b/docker/bootstrap/Dockerfile.percona57 deleted file mode 100644 index e9cd5043d44..00000000000 --- a/docker/bootstrap/Dockerfile.percona57 +++ /dev/null @@ -1,22 +0,0 @@ -ARG bootstrap_version -ARG image="vitess/bootstrap:${bootstrap_version}-common" - -FROM --platform=linux/amd64 "${image}" - -USER root - -# Install Percona 5.7 -RUN for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys 9334A25F8507EFA5 && break; done && \ - add-apt-repository 'deb http://repo.percona.com/apt bullseye main' && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - 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 && \ - rm -rf /var/lib/apt/lists/* - -USER vitess diff --git a/docker/bootstrap/README.md b/docker/bootstrap/README.md index 717f4336442..b273305d6b9 100644 --- a/docker/bootstrap/README.md +++ b/docker/bootstrap/README.md @@ -6,9 +6,7 @@ after successfully running `bootstrap.sh` and `dev.env`. The `vitess/bootstrap` image comes in different flavors: * `vitess/bootstrap:common` - dependencies that are common to all flavors -* `vitess/bootstrap:mysql57` - bootstrap image for MySQL 5.7 * `vitess/bootstrap:mysql80` - bootstrap image for MySQL 8.0 -* `vitess/bootstrap:percona57` - bootstrap image for Percona Server 5.7 * `vitess/bootstrap:percona80` - bootstrap image for Percona Server 8.0 **NOTE: Unlike the base image that builds Vitess itself, this bootstrap image diff --git a/docker/lite/Dockerfile b/docker/lite/Dockerfile index 7c0b22aed3c..1c7a535ec7a 100644 --- a/docker/lite/Dockerfile +++ b/docker/lite/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder +FROM --platform=linux/amd64 golang:1.23.0-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER diff --git a/docker/lite/Dockerfile.percona80 b/docker/lite/Dockerfile.percona80 index cded55438ec..effb1e3e38d 100644 --- a/docker/lite/Dockerfile.percona80 +++ b/docker/lite/Dockerfile.percona80 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder +FROM --platform=linux/amd64 golang:1.23.0-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER diff --git a/docker/vttestserver/Dockerfile.mysql80 b/docker/vttestserver/Dockerfile.mysql80 index 2e79d389c7d..13020ca1509 100644 --- a/docker/vttestserver/Dockerfile.mysql80 +++ b/docker/vttestserver/Dockerfile.mysql80 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder +FROM --platform=linux/amd64 golang:1.23.0-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER diff --git a/examples/operator/README.md b/examples/operator/README.md index 9182b25340c..38d9fe4d6ed 100644 --- a/examples/operator/README.md +++ b/examples/operator/README.md @@ -1,8 +1,10 @@ # Instructions - +{{< info >}} +For the best experience, please refer to the [Vitess Operator Compatibility Matrix](https://github.com/planetscale/vitess-operator#compatibility) to ensure compatibility between your version of Vitess and Kubernetes. You would then specify the appropriate Kubernetes version to Minikube using the `--kubernetes-version` flag. +{{< /info >}} ``` # Start minikube -minikube start --cpus=8 --memory=11000 --disk-size=50g --kubernetes-version=v1.25.8 +minikube start --cpus=8 --memory=11000 --disk-size=50g # Install Operator kubectl apply -f operator.yaml diff --git a/go.mod b/go.mod index 47dafd671f7..c241fa9175f 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module vitess.io/vitess -go 1.22.5 +go 1.23.0 require ( - cloud.google.com/go/storage v1.42.0 - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 + cloud.google.com/go/storage v1.43.0 + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 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.13 + github.com/aws/aws-sdk-go v1.55.5 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 @@ -40,16 +40,16 @@ require ( github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1 github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 - github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e + github.com/opentracing-contrib/go-grpc v0.0.0-20240724223109-9dec25a38fa8 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/client_golang v1.20.0 github.com/prometheus/common v0.55.0 github.com/sjmudd/stopwatch v0.1.1 github.com/soheilhy/cmux v0.1.5 @@ -58,32 +58,32 @@ require ( github.com/spf13/viper v1.19.0 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/tidwall/gjson v1.17.3 + 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 github.com/z-division/go-zookeeper v1.0.0 - go.etcd.io/etcd/api/v3 v3.5.14 - go.etcd.io/etcd/client/pkg/v3 v3.5.14 - go.etcd.io/etcd/client/v3 v3.5.14 + go.etcd.io/etcd/api/v3 v3.5.15 + go.etcd.io/etcd/client/pkg/v3 v3.5.15 + go.etcd.io/etcd/client/v3 v3.5.15 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/oauth2 v0.21.0 - golang.org/x/sys v0.21.0 - golang.org/x/term v0.21.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.187.0 - google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 + golang.org/x/oauth2 v0.22.0 + golang.org/x/sys v0.24.0 + golang.org/x/term v0.23.0 + golang.org/x/text v0.17.0 // indirect + golang.org/x/time v0.6.0 + golang.org/x/tools v0.24.0 + google.golang.org/api v0.192.0 + google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // 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.1 + gopkg.in/DataDog/dd-trace-go.v1 v1.66.0 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,23 +104,23 @@ 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/sync v0.7.0 + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa + golang.org/x/sync v0.8.0 gonum.org/v1/gonum v0.14.0 - modernc.org/sqlite v1.30.1 + modernc.org/sqlite v1.32.0 ) require ( - cloud.google.com/go v0.115.0 // indirect - cloud.google.com/go/auth v0.6.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.4.0 // indirect - cloud.google.com/go/iam v1.1.10 // 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 - github.com/DataDog/go-sqllexer v0.0.12 // indirect + cloud.google.com/go v0.115.1 // indirect + cloud.google.com/go/auth v0.8.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/iam v1.1.13 // indirect + github.com/DataDog/appsec-internal-go v1.7.0 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.55.3 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.3 // indirect + github.com/DataDog/go-libddwaf/v3 v3.3.0 // indirect + github.com/DataDog/go-sqllexer v0.0.13 // indirect github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect github.com/DataDog/sketches-go v1.4.6 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -137,9 +137,9 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/s2a-go v0.1.7 // indirect + github.com/google/s2a-go v0.1.8 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.5 // indirect + github.com/googleapis/gax-go/v2 v2.13.0 // 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 @@ -152,7 +152,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-ieproxy v0.0.12 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // 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 @@ -171,27 +171,27 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cast v1.7.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect 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/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-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // 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.54.1 // indirect + modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a // indirect + modernc.org/libc v1.59.4 // 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 35df734575e..9471151982f 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,21 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= -cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= -cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= -cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= -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.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= -cloud.google.com/go/iam v1.1.10 h1:ZSAr64oEhQSClwBL670MsJAW5/RLiC6kfw3Bqmd5ZDI= -cloud.google.com/go/iam v1.1.10/go.mod h1:iEgMq62sg8zx446GCaijmA2Miwg5o3UbO+nI47WHJps= -cloud.google.com/go/longrunning v0.5.8 h1:QThI5BFSlYlS7K0wnABCdmKsXbG/htLc3nTPzrfOgeU= -cloud.google.com/go/longrunning v0.5.8/go.mod h1:oJDErR/mm5h44gzsfjQlxd6jyjFvuBPOxR1TLy2+cQk= -cloud.google.com/go/storage v1.42.0 h1:4QtGpplCVt1wz6g5o1ifXd656P5z+yNgzdw1tVfp0cU= -cloud.google.com/go/storage v1.42.0/go.mod h1:HjMXRFq65pGKFn6hxj6x3HCyR41uSB72Z0SO/Vn6JFQ= -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= +cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= +cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go/auth v0.8.1 h1:QZW9FjC5lZzN864p13YxvAtGUlQ+KgRL+8Sg45Z6vxo= +cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +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.13 h1:7zWBXG9ERbMLrzQBRhFliAV+kjcRToDTgQT3CTwYyv4= +cloud.google.com/go/iam v1.1.13/go.mod h1:K8mY0uSXwEXS30KrnVb+j54LB/ntfZu1dr+4zFMNbus= +cloud.google.com/go/longrunning v0.5.11 h1:Havn1kGjz3whCfoD8dxMLP73Ph5w+ODyZB9RUsDxtGk= +cloud.google.com/go/longrunning v0.5.11/go.mod h1:rDn7//lmlfWV1Dx6IB4RatCPenTwwmqXuiP0/RgoEO4= +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-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk= @@ -32,19 +32,19 @@ 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.3 h1:nQvuEg91m1Vehe2doGHiMzHp8b8F/Lj3LDk1JsrA0B0= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.55.3/go.mod h1:/C99KWKukVnTtIiYCQ55izSNDQceREb8vSPa3zUn6jc= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.3 h1:RHzGF8eRjBMKXzvCrHjFf81tP3vuM9e7vfaEelB+/Ag= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.3/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-sqllexer v0.0.12 h1:ncvAr5bbwtc7JMezzcU2379oKz1oHhRF1hkR6BSvhqM= -github.com/DataDog/go-sqllexer v0.0.12/go.mod h1:KwkYhpFEVIq+BfobkTC1vfqm4gTi65skV/DpDBXtexc= +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.13 h1:9mKfe+3s73GI/7dWBxi2Ds7+xZynJqMKK9cIUBrutak= +github.com/DataDog/go-sqllexer v0.0.13/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= @@ -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.13 h1:zpCuiG+/mFdDY/klKJvmSioAZWk45F4rLGq0JWVAAzk= -github.com/aws/aws-sdk-go v1.54.13/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/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= @@ -142,6 +142,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= +github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= +github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -162,8 +164,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= @@ -206,8 +208,8 @@ github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9 github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8= github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -218,8 +220,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.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= -github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= 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= @@ -229,11 +231,10 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= 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= @@ -315,6 +316,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E= github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -336,8 +339,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -378,8 +381,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= -github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= +github.com/opentracing-contrib/go-grpc v0.0.0-20240724223109-9dec25a38fa8 h1:gHTSPFezGeYzTWCvpPM6lBanwXfuksik5Hy5MEHtvUA= +github.com/opentracing-contrib/go-grpc v0.0.0-20240724223109-9dec25a38fa8/go.mod h1:z1k3YVSdAPSXtMUPS1TBWG5DaNWlT+VCbB0Qm3QJe74= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -392,8 +395,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= @@ -415,8 +418,8 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -470,8 +473,8 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -502,15 +505,15 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs= github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= -github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94= +github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 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= @@ -525,18 +528,18 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/z-division/go-zookeeper v1.0.0 h1:ULsCj0nP6+U1liDFWe+2oEF6o4amixoDcDlwEUghVUY= github.com/z-division/go-zookeeper v1.0.0/go.mod h1:6X4UioQXpvyezJJl4J9NHAJKsoffCwy5wCaaTktXjOA= -go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= -go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -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.etcd.io/etcd/api/v3 v3.5.15 h1:3KpLJir1ZEBrYuV2v+Twaa/e2MdDCEZ/70H+lzEiwsk= +go.etcd.io/etcd/api/v3 v3.5.15/go.mod h1:N9EhGzXq58WuMllgH9ZvnEr7SI9pS0k0+DHZezGp7jM= +go.etcd.io/etcd/client/pkg/v3 v3.5.15 h1:fo0HpWz/KlHGMCC+YejpiCmyWDEuIpnTDzpJLB5fWlA= +go.etcd.io/etcd/client/pkg/v3 v3.5.15/go.mod h1:mXDI4NAOwEiszrHCb0aqfAYNCrZP4e9hRca3d1YK8EU= +go.etcd.io/etcd/client/v3 v3.5.15 h1:23M0eY4Fd/inNv1ZfU3AxrbbOdW79r9V9Rl62Nm6ip4= +go.etcd.io/etcd/client/v3 v3.5.15/go.mod h1:CLSJxrYjvLtHsrPKsy7LmZEE+DK2ktfd2bN4RhBMwlU= 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/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= @@ -568,11 +571,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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= 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-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= 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= @@ -580,8 +583,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.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.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= @@ -593,7 +596,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -605,12 +607,12 @@ 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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 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= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -618,8 +620,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -657,19 +659,19 @@ 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.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.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.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -682,18 +684,18 @@ 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.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/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.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= -google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= +google.golang.org/api v0.192.0 h1:PljqpNAfZaaSpS+TnANfnNAXKdzHM/B9bKhwRlo7JP0= +google.golang.org/api v0.192.0/go.mod h1:9VcphjvAxPKLmSxVSzPlSRXy/5ARMEw5bf58WoVXafQ= 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= @@ -701,15 +703,14 @@ 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-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= -google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22duwci1+TG7bg2/L1LQsXwfjPlmuJA0= +google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= @@ -735,8 +736,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.1 h1:Ne7kzWr/br/jwhUJR7CnqPl/mUpNxa6LfgZs0S4htZM= -gopkg.in/DataDog/dd-trace-go.v1 v1.65.1/go.mod h1:beNFIWd/H04d0k96cfltgiDH2+t0T5sDbyYLF3VTXqk= +gopkg.in/DataDog/dd-trace-go.v1 v1.66.0 h1:025+lLubGtpiDWrRmSOxoFBPIiVRVYRcqP9oLabVOeg= +gopkg.in/DataDog/dd-trace-go.v1 v1.66.0/go.mod h1:Av6AXGmQCQAbDnwNoPiuUz1k3GS8TwQjj+vEdwmEpmM= 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= @@ -771,16 +772,16 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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.0 h1:f9K5VdC0nVhHKTFMvhjtZ8TbRgFQbASvE5yO1zs8eC0= -modernc.org/ccgo/v4 v4.19.0/go.mod h1:CfpAl+673iXNwMG/aqcQn+vDcu4Es/YLya7+9RHjTa4= +modernc.org/ccgo/v4 v4.20.7 h1:skrinQsjxWfvj6nbC3ztZPJy+NuwmB3hV9zX/pthNYQ= +modernc.org/ccgo/v4 v4.20.7/go.mod h1:UOkI3JSG2zT4E2ioHlncSOZsXbuDCZLvPi3uMlZT5GY= 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.54.1 h1:5vzs86ANQehsFZXqjxUam20JwgK2eODTOcGMIWcCdg4= -modernc.org/libc v1.54.1/go.mod h1:B0D6klDmSmnq26T1iocn9kzyX6NtbzjuI3+oX/xfvng= +modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M= +modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= +modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a h1:CfbpOLEo2IwNzJdMvE8aiRbPMxoTpgAJeyePh0SmO8M= +modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.59.4 h1:kas1A6v59SN7iJIy4BQ/o5djZC1VO3pPhwc7HS4Atco= +modernc.org/libc v1.59.4/go.mod h1:EY/egGEU7Ju66eU6SBqCNYaFUDuc4npICkMWnU5EE3A= 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= @@ -789,8 +790,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.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= +modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= 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/vtctldclient/command/keyspaces.go b/go/cmd/vtctldclient/command/keyspaces.go index 6330220d773..565e0c8aa82 100644 --- a/go/cmd/vtctldclient/command/keyspaces.go +++ b/go/cmd/vtctldclient/command/keyspaces.go @@ -182,7 +182,7 @@ func commandCreateKeyspace(cmd *cobra.Command, args []string) error { return errors.New("--sidecar-db-name cannot be empty when creating a keyspace") } if len(createKeyspaceOptions.SidecarDBName) > mysql.MaxIdentifierLength { - return sqlerror.NewSQLError(sqlerror.ERTooLongIdent, sqlerror.SSDataTooLong, "--sidecar-db-name identifier value of %q is too long (%d chars), max length for database identifiers is %d characters", + return sqlerror.NewSQLErrorf(sqlerror.ERTooLongIdent, sqlerror.SSDataTooLong, "--sidecar-db-name identifier value of %q is too long (%d chars), max length for database identifiers is %d characters", createKeyspaceOptions.SidecarDBName, len(createKeyspaceOptions.SidecarDBName), mysql.MaxIdentifierLength) } 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/reparents.go b/go/cmd/vtctldclient/command/reparents.go index 17b87eaba4f..8888c5a48cd 100644 --- a/go/cmd/vtctldclient/command/reparents.go +++ b/go/cmd/vtctldclient/command/reparents.go @@ -187,6 +187,7 @@ var plannedReparentShardOptions = struct { AvoidPrimaryAliasStr string WaitReplicasTimeout time.Duration TolerableReplicationLag time.Duration + AllowCrossCellPromotion bool }{} func commandPlannedReparentShard(cmd *cobra.Command, args []string) error { @@ -223,6 +224,7 @@ func commandPlannedReparentShard(cmd *cobra.Command, args []string) error { AvoidPrimary: avoidPrimaryAlias, WaitReplicasTimeout: protoutil.DurationToProto(plannedReparentShardOptions.WaitReplicasTimeout), TolerableReplicationLag: protoutil.DurationToProto(plannedReparentShardOptions.TolerableReplicationLag), + AllowCrossCellPromotion: plannedReparentShardOptions.AllowCrossCellPromotion, }) if err != nil { return err @@ -297,6 +299,7 @@ func init() { PlannedReparentShard.Flags().DurationVar(&plannedReparentShardOptions.TolerableReplicationLag, "tolerable-replication-lag", 0, "Amount of replication lag that is considered acceptable for a tablet to be eligible for promotion when Vitess makes the choice of a new primary.") PlannedReparentShard.Flags().StringVar(&plannedReparentShardOptions.NewPrimaryAliasStr, "new-primary", "", "Alias of a tablet that should be the new primary.") PlannedReparentShard.Flags().StringVar(&plannedReparentShardOptions.AvoidPrimaryAliasStr, "avoid-primary", "", "Alias of a tablet that should not be the primary; i.e. \"reparent to any other tablet if this one is the primary\".") + PlannedReparentShard.Flags().BoolVar(&plannedReparentShardOptions.AllowCrossCellPromotion, "allow-cross-cell-promotion", false, "Allow cross cell promotion") Root.AddCommand(PlannedReparentShard) Root.AddCommand(ReparentTablet) diff --git a/go/cmd/vtctldclient/command/root_test.go b/go/cmd/vtctldclient/command/root_test.go index 5efe844e1a1..86333ec0e69 100644 --- a/go/cmd/vtctldclient/command/root_test.go +++ b/go/cmd/vtctldclient/command/root_test.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "os" - "strings" "testing" "time" @@ -110,9 +109,7 @@ func TestRootWithInternalVtctld(t *testing.T) { err := command.Root.Execute() if tc.expectErr != "" { - if !strings.Contains(err.Error(), tc.expectErr) { - t.Errorf(fmt.Sprintf("%s error = %v, expectErr = %v", tc.command, err, tc.expectErr)) - } + require.ErrorContains(t, err, tc.expectErr) } else { require.NoError(t, err, "unexpected error: %v", err) } 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..da8b0763b0d 100644 --- a/go/cmd/vtctldclient/command/throttler.go +++ b/go/cmd/vtctldclient/command/throttler.go @@ -27,18 +27,40 @@ 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 ( // UpdateThrottlerConfig makes a UpdateThrottlerConfig gRPC call to a vtctld. UpdateThrottlerConfig = &cobra.Command{ - Use: "UpdateThrottlerConfig [--enable|--disable] [--threshold=] [--custom-query=] [--check-as-check-self|--check-as-check-shard] [--throttle-app|unthrottle-app=] [--throttle-app-ratio=] [--throttle-app-duration=] ", + Use: "UpdateThrottlerConfig [--enable|--disable] [--metric-name=] [--threshold=] [--custom-query=] [--throttle-app|unthrottle-app=] [--throttle-app-ratio=] [--throttle-app-duration=] [--throttle-app-exempt=] [--app-name= --app-metrics=] ", 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,19 +106,92 @@ 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") UpdateThrottlerConfig.Flags().BoolVar(&updateThrottlerConfigOptions.CheckAsCheckShard, "check-as-check-shard", false, "use standard behavior for /throttler/check requests") + UpdateThrottlerConfig.Flags().MarkDeprecated("check-as-check-self", "specify metric with scope in --app-metrics to apply to all checks, or use --scope in CheckThrottler for a specific check") + UpdateThrottlerConfig.Flags().MarkDeprecated("check-as-check-shard", "specify metric with scope in --app-metrics to apply to all checks, or use --scope in CheckThrottler for a specific check") UpdateThrottlerConfig.Flags().StringVar(&unthrottledAppRule.Name, "unthrottle-app", "", "an app name to unthrottle") UpdateThrottlerConfig.Flags().StringVar(&throttledAppRule.Name, "throttle-app", "", "an app name to throttle") 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. Example: --app-metrics=lag,custom,shard/loadavg") + 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/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 cb408add490..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 @@ -245,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/vdiff/vdiff.go b/go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go index dfca3386491..d90829f2029 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" @@ -68,6 +69,7 @@ var ( WaitUpdateInterval time.Duration AutoRetry bool MaxDiffDuration time.Duration + RowDiffColumnTruncateAt int64 }{} deleteOptions = struct { @@ -141,7 +143,7 @@ var ( Use: "create", Short: "Create and run a VDiff to compare the tables involved in a VReplication workflow between the source and target.", Example: `vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer create -vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer create b3f59678-5241-11ee-be56-0242ac120002`, +vtctldclient --server :15999 vdiff --workflow c2c --target-keyspace customer create b3f59678-5241-11ee-be56-0242ac120002 --source-cells zone1 --tablet-types "rdonly,replica" --target-cells zone1 --update-table-stats --max-report-sample-rows 1000 --wait --wait-update-interval 5s --max-diff-duration 1h --row-diff-column-truncate-at 0`, SilenceUsage: true, DisableFlagsInUseLine: true, Aliases: []string{"Create"}, @@ -198,8 +200,8 @@ vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --targe show = &cobra.Command{ Use: "show", Short: "Show the status of a VDiff.", - Example: `vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer show last -vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer show a037a9e2-5628-11ee-8c99-0242ac120002 + Example: `vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer show last --verbose --format json +vtctldclient --server :15999 vdiff --workflow commerce2customer --target-keyspace customer show a037a9e2-5628-11ee-8c99-0242ac120002 vtctldclient --server localhost:15999 vdiff --workflow commerce2customer --target-keyspace customer show all`, DisableFlagsInUseLine: true, Aliases: []string{"Show"}, @@ -293,6 +295,7 @@ func commandCreate(cmd *cobra.Command, args []string) error { AutoRetry: createOptions.AutoRetry, MaxReportSampleRows: createOptions.MaxReportSampleRows, MaxDiffDuration: protoutil.DurationToProto(createOptions.MaxDiffDuration), + RowDiffColumnTruncateAt: createOptions.RowDiffColumnTruncateAt, }) if err != nil { @@ -874,7 +877,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") @@ -886,6 +889,7 @@ func registerCommands(root *cobra.Command) { create.Flags().BoolVar(&createOptions.AutoRetry, "auto-retry", true, "Should this vdiff automatically retry and continue in case of recoverable errors.") create.Flags().BoolVar(&createOptions.UpdateTableStats, "update-table-stats", false, "Update the table statistics, using ANALYZE TABLE, on each table involved in the VDiff during initialization. This will ensure that progress estimates are as accurate as possible -- but it does involve locks and can potentially impact query processing on the target keyspace.") create.Flags().DurationVar(&createOptions.MaxDiffDuration, "max-diff-duration", 0, "How long should an individual table diff run before being stopped and restarted in order to lessen the impact on tablets due to holding open database snapshots for long periods of time (0 is the default and means no time limit).") + create.Flags().Int64Var(&createOptions.RowDiffColumnTruncateAt, "row-diff-column-truncate-at", 128, "When showing row differences, truncate the non Primary Key column values to this length. A value less than 1 means do not truncate.") base.AddCommand(create) base.AddCommand(delete) 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/mysqlctl.txt b/go/flags/endtoend/mysqlctl.txt index 044d12981d5..2b179496fff 100644 --- a/go/flags/endtoend/mysqlctl.txt +++ b/go/flags/endtoend/mysqlctl.txt @@ -40,7 +40,7 @@ Flags: --db-credentials-vault-tls-ca string Path to CA PEM for validating Vault server certificate --db-credentials-vault-tokenfile string Path to file containing Vault auth token; token can also be passed using VAULT_TOKEN environment variable --db-credentials-vault-ttl duration How long to cache DB credentials from the Vault server (default 30m0s) - --db_charset string Character set used for this tablet. (default "utf8mb4") + --db_charset string Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment. (default "utf8mb4") --db_conn_query_info enable parsing and processing of QUERY_OK info fields --db_connect_timeout_ms int connection timeout to mysqld in milliseconds (0 for no timeout) --db_dba_password string db dba password diff --git a/go/flags/endtoend/mysqlctld.txt b/go/flags/endtoend/mysqlctld.txt index 6bb1beb5bae..d60a91ae65e 100644 --- a/go/flags/endtoend/mysqlctld.txt +++ b/go/flags/endtoend/mysqlctld.txt @@ -41,7 +41,7 @@ Flags: --db-credentials-vault-tls-ca string Path to CA PEM for validating Vault server certificate --db-credentials-vault-tokenfile string Path to file containing Vault auth token; token can also be passed using VAULT_TOKEN environment variable --db-credentials-vault-ttl duration How long to cache DB credentials from the Vault server (default 30m0s) - --db_charset string Character set used for this tablet. (default "utf8mb4") + --db_charset string Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment. (default "utf8mb4") --db_conn_query_info enable parsing and processing of QUERY_OK info fields --db_connect_timeout_ms int connection timeout to mysqld in milliseconds (0 for no timeout) --db_dba_password string db dba password diff --git a/go/flags/endtoend/vtbackup.txt b/go/flags/endtoend/vtbackup.txt index 004871d7c09..fc00df479f5 100644 --- a/go/flags/endtoend/vtbackup.txt +++ b/go/flags/endtoend/vtbackup.txt @@ -92,7 +92,7 @@ Flags: --db_appdebug_password string db appdebug password --db_appdebug_use_ssl Set this flag to false to make the appdebug connection to not use ssl (default true) --db_appdebug_user string db appdebug user userKey (default "vt_appdebug") - --db_charset string Character set used for this tablet. (default "utf8mb4") + --db_charset string Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment. (default "utf8mb4") --db_conn_query_info enable parsing and processing of QUERY_OK info fields --db_connect_timeout_ms int connection timeout to mysqld in milliseconds (0 for no timeout) --db_dba_password string db dba password diff --git a/go/flags/endtoend/vtcombo.txt b/go/flags/endtoend/vtcombo.txt index b404d28f875..381f7ca48cc 100644 --- a/go/flags/endtoend/vtcombo.txt +++ b/go/flags/endtoend/vtcombo.txt @@ -76,7 +76,7 @@ Flags: --db_appdebug_password string db appdebug password --db_appdebug_use_ssl Set this flag to false to make the appdebug connection to not use ssl (default true) --db_appdebug_user string db appdebug user userKey (default "vt_appdebug") - --db_charset string Character set used for this tablet. (default "utf8mb4") + --db_charset string Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment. (default "utf8mb4") --db_conn_query_info enable parsing and processing of QUERY_OK info fields --db_connect_timeout_ms int connection timeout to mysqld in milliseconds (0 for no timeout) --db_dba_password string db dba password @@ -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) @@ -231,7 +232,6 @@ Flags: --mysql_default_workload string Default session workload (OLTP, OLAP, DBA) (default "OLTP") --mysql_port int mysql port (default 3306) --mysql_server_bind_address string Binds on this address when listening to MySQL binary protocol. Useful to restrict listening to 'localhost' only for instance. - --mysql_server_drain_onterm If set, the server waits for --onterm_timeout for connected clients to drain --mysql_server_flush_delay duration Delay after which buffered response will be flushed to the client. (default 100ms) --mysql_server_port int If set, also listen for MySQL binary protocol connections on this port. (default -1) --mysql_server_query_timeout duration mysql query timeout @@ -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 45dcae2704a..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. @@ -56,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 312dcb6f74d..37bfadd4938 100644 --- a/go/flags/endtoend/vtgate.txt +++ b/go/flags/endtoend/vtgate.txt @@ -122,6 +122,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. @@ -144,7 +145,6 @@ Flags: --mysql_ldap_auth_config_string string JSON representation of LDAP server config. --mysql_ldap_auth_method string client-side authentication method to use. Supported values: mysql_clear_password, dialog. (default "mysql_clear_password") --mysql_server_bind_address string Binds on this address when listening to MySQL binary protocol. Useful to restrict listening to 'localhost' only for instance. - --mysql_server_drain_onterm If set, the server waits for --onterm_timeout for connected clients to drain --mysql_server_flush_delay duration Delay after which buffered response will be flushed to the client. (default 100ms) --mysql_server_port int If set, also listen for MySQL binary protocol connections on this port. (default -1) --mysql_server_query_timeout duration mysql query timeout diff --git a/go/flags/endtoend/vttablet.txt b/go/flags/endtoend/vttablet.txt index 40d686979c0..d3df3c3009f 100644 --- a/go/flags/endtoend/vttablet.txt +++ b/go/flags/endtoend/vttablet.txt @@ -110,7 +110,7 @@ Flags: --db_appdebug_password string db appdebug password --db_appdebug_use_ssl Set this flag to false to make the appdebug connection to not use ssl (default true) --db_appdebug_user string db appdebug user userKey (default "vt_appdebug") - --db_charset string Character set used for this tablet. (default "utf8mb4") + --db_charset string Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment. (default "utf8mb4") --db_conn_query_info enable parsing and processing of QUERY_OK info fields --db_connect_timeout_ms int connection timeout to mysqld in milliseconds (0 for no timeout) --db_dba_password string db dba password @@ -387,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) @@ -417,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/auth_server.go b/go/mysql/auth_server.go index f4bda2655a5..64274ef3d66 100644 --- a/go/mysql/auth_server.go +++ b/go/mysql/auth_server.go @@ -428,7 +428,7 @@ func (n *mysqlNativePasswordAuthMethod) AllowClearTextWithoutTLS() bool { func (n *mysqlNativePasswordAuthMethod) HandleAuthPluginData(conn *Conn, user string, serverAuthPluginData []byte, clientAuthPluginData []byte, remoteAddr net.Addr) (Getter, error) { if serverAuthPluginData[len(serverAuthPluginData)-1] != 0x00 { - return nil, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return nil, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } salt := serverAuthPluginData[:len(serverAuthPluginData)-1] @@ -520,7 +520,7 @@ func (n *mysqlCachingSha2AuthMethod) AllowClearTextWithoutTLS() bool { func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string, serverAuthPluginData []byte, clientAuthPluginData []byte, remoteAddr net.Addr) (Getter, error) { if serverAuthPluginData[len(serverAuthPluginData)-1] != 0x00 { - return nil, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return nil, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } salt := serverAuthPluginData[:len(serverAuthPluginData)-1] @@ -532,7 +532,7 @@ func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string, switch cacheState { case AuthRejected: - return nil, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return nil, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) case AuthAccepted: // We need to write a more data packet to indicate the // handshake completed properly. This will be followed @@ -547,7 +547,7 @@ func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string, return result, nil case AuthNeedMoreData: if !c.TLSEnabled() && !c.IsUnixSocket() { - return nil, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return nil, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } data, pos := c.startEphemeralPacketWithHeader(2) @@ -563,7 +563,7 @@ func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string, return n.storage.UserEntryWithPassword(c, user, password, remoteAddr) default: // Somehow someone returned an unknown state, let's error with access denied. - return nil, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return nil, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } } diff --git a/go/mysql/auth_server_static.go b/go/mysql/auth_server_static.go index 6e3a9693c69..d9e6decf5e5 100644 --- a/go/mysql/auth_server_static.go +++ b/go/mysql/auth_server_static.go @@ -162,7 +162,7 @@ func (a *AuthServerStatic) UserEntryWithPassword(conn *Conn, user string, passwo a.mu.Unlock() if !ok { - return &StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } for _, entry := range entries { @@ -171,7 +171,7 @@ func (a *AuthServerStatic) UserEntryWithPassword(conn *Conn, user string, passwo return &StaticUserData{entry.UserData, entry.Groups}, nil } } - return &StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } // UserEntryWithHash implements password lookup based on a @@ -182,14 +182,14 @@ func (a *AuthServerStatic) UserEntryWithHash(conn *Conn, salt []byte, user strin a.mu.Unlock() if !ok { - return &StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } for _, entry := range entries { if entry.MysqlNativePassword != "" { hash, err := DecodeMysqlNativePasswordHex(entry.MysqlNativePassword) if err != nil { - return &StaticUserData{entry.UserData, entry.Groups}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{entry.UserData, entry.Groups}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } isPass := VerifyHashedMysqlNativePassword(authResponse, salt, hash) @@ -204,7 +204,7 @@ func (a *AuthServerStatic) UserEntryWithHash(conn *Conn, salt []byte, user strin } } } - return &StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } // UserEntryWithCacheHash implements password lookup based on a @@ -215,7 +215,7 @@ func (a *AuthServerStatic) UserEntryWithCacheHash(conn *Conn, salt []byte, user a.mu.Unlock() if !ok { - return &StaticUserData{}, AuthRejected, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, AuthRejected, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } for _, entry := range entries { @@ -226,7 +226,7 @@ func (a *AuthServerStatic) UserEntryWithCacheHash(conn *Conn, salt []byte, user return &StaticUserData{entry.UserData, entry.Groups}, AuthAccepted, nil } } - return &StaticUserData{}, AuthRejected, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &StaticUserData{}, AuthRejected, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } // AuthMethods returns the AuthMethod instances this auth server can handle. 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..4015059e686 100644 --- a/go/mysql/capabilities/capability.go +++ b/go/mysql/capabilities/capability.go @@ -40,7 +40,7 @@ const ( InstantAddDropColumnFlavorCapability // Adding/dropping column in any position/ordinal. InstantChangeColumnDefaultFlavorCapability // InstantExpandEnumCapability // - MySQLJSONFlavorCapability // JSON type supported + InstantChangeColumnVisibilityCapability // 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 +48,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 +89,6 @@ func MySQLVersionHasCapability(serverVersion string, capability FlavorCapability } // Capabilities sorted by version. switch capability { - case MySQLJSONFlavorCapability: - return atLeast(5, 7, 0) case InstantDDLFlavorCapability, InstantExpandEnumCapability, InstantAddLastColumnFlavorCapability, @@ -107,6 +107,8 @@ func MySQLVersionHasCapability(serverVersion string, capability FlavorCapability return atLeast(8, 0, 21) case FastDropTableFlavorCapability: return atLeast(8, 0, 23) + case InstantChangeColumnVisibilityCapability: + return atLeast(8, 0, 23) case InstantAddDropColumnFlavorCapability: return atLeast(8, 0, 29) case DynamicRedoLogCapacityFlavorCapability: @@ -119,6 +121,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/client.go b/go/mysql/client.go index 16740bf38db..2a72806a6be 100644 --- a/go/mysql/client.go +++ b/go/mysql/client.go @@ -95,11 +95,11 @@ func Connect(ctx context.Context, params *ConnParams) (*Conn, error) { // should return a 2003. if netProto == "tcp" { status <- connectResult{ - err: sqlerror.NewSQLError(sqlerror.CRConnHostError, sqlerror.SSUnknownSQLState, "net.Dial(%v) failed: %v", addr, err), + err: sqlerror.NewSQLErrorf(sqlerror.CRConnHostError, sqlerror.SSUnknownSQLState, "net.Dial(%v) failed: %v", addr, err), } } else { status <- connectResult{ - err: sqlerror.NewSQLError(sqlerror.CRConnectionError, sqlerror.SSUnknownSQLState, "net.Dial(%v) to local server failed: %v", addr, err), + err: sqlerror.NewSQLErrorf(sqlerror.CRConnectionError, sqlerror.SSUnknownSQLState, "net.Dial(%v) to local server failed: %v", addr, err), } } return @@ -179,11 +179,11 @@ func (c *Conn) Ping() error { data[pos] = ComPing if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) } data, err := c.readEphemeralPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() switch data[0] { @@ -208,7 +208,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { // Wait for the server initial handshake packet, and parse it. data, err := c.readPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, "", "initial packet read failed: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, "", "initial packet read failed: %v", err) } capabilities, salt, err := c.parseInitialHandshakePacket(data) if err != nil { @@ -219,7 +219,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { // Sanity check. if capabilities&CapabilityClientProtocol41 == 0 { - return sqlerror.NewSQLError(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "cannot connect to servers earlier than 4.1") + return sqlerror.NewSQLErrorf(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "cannot connect to servers earlier than 4.1") } // Remember a subset of the capabilities, so we can use them @@ -234,7 +234,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { // If client asked for SSL, but server doesn't support it, // stop right here. if params.SslRequired() && capabilities&CapabilityClientSSL == 0 { - return sqlerror.NewSQLError(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "server doesn't support SSL but client asked for it") + return sqlerror.NewSQLErrorf(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "server doesn't support SSL but client asked for it") } // The ServerName to verify depends on what the hostname is. @@ -255,13 +255,13 @@ func (c *Conn) clientHandshake(params *ConnParams) error { tlsVersion, err := vttls.TLSVersionToNumber(params.TLSMinVersion) if err != nil { - return sqlerror.NewSQLError(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "error parsing minimal TLS version: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "error parsing minimal TLS version: %v", err) } // Build the TLS config. clientConfig, err := vttls.ClientConfig(params.EffectiveSslMode(), params.SslCert, params.SslKey, params.SslCa, params.SslCrl, serverName, tlsVersion) if err != nil { - return sqlerror.NewSQLError(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "error loading client cert and ca: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "error loading client cert and ca: %v", err) } // Send the SSLRequest packet. @@ -292,7 +292,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { } else if params.Flags&CapabilityClientSessionTrack == CapabilityClientSessionTrack { // If client asked for ClientSessionTrack, but server doesn't support it, // stop right here. - return sqlerror.NewSQLError(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "server doesn't support ClientSessionTrack but client asked for it") + return sqlerror.NewSQLErrorf(sqlerror.CRSSLConnectionError, sqlerror.SSUnknownSQLState, "server doesn't support ClientSessionTrack but client asked for it") } // Build and send our handshake response 41. @@ -317,7 +317,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { // Wait for response, should be OK. response, err := c.readPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } switch response[0] { case OKPacket: @@ -327,7 +327,7 @@ func (c *Conn) clientHandshake(params *ConnParams) error { return ParseErrorPacket(response) default: // FIXME(alainjobart) handle extra auth cases and so on. - return sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "initial server response is asking for more information, not implemented yet: %v", response) + return sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "initial server response is asking for more information, not implemented yet: %v", response) } } @@ -342,7 +342,7 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) // Protocol version. pver, pos, ok := readByte(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no protocol version") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no protocol version") } // Server is allowed to immediately send ERR packet @@ -351,41 +351,41 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) // Normally there would be a 1-byte sql_state_marker field and a 5-byte // sql_state field here, but docs say these will not be present in this case. errorMsg, _, _ := readEOFString(data, pos) - return 0, nil, sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "immediate error from server errorCode=%v errorMsg=%v", errorCode, errorMsg) + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "immediate error from server errorCode=%v errorMsg=%v", errorCode, errorMsg) } if pver != protocolVersion { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "bad protocol version: %v", pver) + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRVersionError, sqlerror.SSUnknownSQLState, "bad protocol version: %v", pver) } // Read the server version. c.ServerVersion, pos, ok = readNullString(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no server version") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no server version") } // Read the connection id. c.ConnectionID, pos, ok = readUint32(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no connection id") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no connection id") } // Read the first part of the auth-plugin-data authPluginData, pos, ok := readBytes(data, pos, 8) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no auth-plugin-data-part-1") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no auth-plugin-data-part-1") } // One byte filler, 0. We don't really care about the value. _, pos, ok = readByte(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no filler") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no filler") } // Lower 2 bytes of the capability flags. capLower, pos, ok := readUint16(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no capability flags (lower 2 bytes)") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no capability flags (lower 2 bytes)") } var capabilities = uint32(capLower) @@ -397,20 +397,20 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) // Character set. characterSet, pos, ok := readByte(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no character set") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no character set") } c.CharacterSet = collations.ID(characterSet) // Status flags. Ignored. _, pos, ok = readUint16(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no status flags") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no status flags") } // Upper 2 bytes of the capability flags. capUpper, pos, ok := readUint16(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no capability flags (upper 2 bytes)") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no capability flags (upper 2 bytes)") } capabilities += uint32(capUpper) << 16 @@ -420,13 +420,13 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) if capabilities&CapabilityClientPluginAuth != 0 { authPluginDataLength, pos, ok = readByte(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no length of auth-plugin-data") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no length of auth-plugin-data") } } else { // One byte filler, 0. We don't really care about the value. _, pos, ok = readByte(data, pos) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no length of auth-plugin-data filler") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no length of auth-plugin-data filler") } } @@ -443,12 +443,12 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) var authPluginDataPart2 []byte authPluginDataPart2, pos, ok = readBytes(data, pos, l) if !ok { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no auth-plugin-data-part-2") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: packet has no auth-plugin-data-part-2") } // The last byte has to be 0, and is not part of the data. if authPluginDataPart2[l-1] != 0 { - return 0, nil, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: auth-plugin-data-part-2 is not 0 terminated") + return 0, nil, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "parseInitialHandshakePacket: auth-plugin-data-part-2 is not 0 terminated") } authPluginData = append(authPluginData, authPluginDataPart2[0:l-1]...) } @@ -505,7 +505,7 @@ func (c *Conn) writeSSLRequest(capabilities uint32, characterSet uint8, params * // And send it as is. if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "cannot send SSLRequest: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "cannot send SSLRequest: %v", err) } return nil } @@ -602,11 +602,11 @@ func (c *Conn) writeHandshakeResponse41(capabilities uint32, scrambledPassword [ // Sanity-check the length. if pos != len(data) { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "writeHandshakeResponse41: only packed %v bytes, out of %v allocated", pos, len(data)) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "writeHandshakeResponse41: only packed %v bytes, out of %v allocated", pos, len(data)) } if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "cannot send HandshakeResponse41: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "cannot send HandshakeResponse41: %v", err) } return nil } @@ -616,7 +616,7 @@ func (c *Conn) writeHandshakeResponse41(capabilities uint32, scrambledPassword [ func (c *Conn) handleAuthResponse(params *ConnParams) error { response, err := c.readPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } switch response[0] { @@ -636,7 +636,7 @@ func (c *Conn) handleAuthResponse(params *ConnParams) error { case ErrPacket: return ParseErrorPacket(response) default: - return sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "initial server response cannot be parsed: %v", response) + return sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "initial server response cannot be parsed: %v", response) } return nil @@ -648,7 +648,7 @@ func (c *Conn) handleAuthSwitchPacket(params *ConnParams, response []byte) error var salt []byte c.authPluginName, salt, err = parseAuthSwitchRequest(response) if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "cannot parse auth switch request: %v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "cannot parse auth switch request: %v", err) } if salt != nil { c.salt = salt @@ -669,7 +669,7 @@ func (c *Conn) handleAuthSwitchPacket(params *ConnParams, response []byte) error return err } default: - return sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "server asked for unsupported auth method: %v", c.authPluginName) + return sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "server asked for unsupported auth method: %v", c.authPluginName) } // The response could be an OKPacket, AuthMoreDataPacket or ErrPacket @@ -711,7 +711,7 @@ func (c *Conn) handleAuthMoreDataPacket(data byte, params *ConnParams) error { // Next packet should either be an OKPacket or ErrPacket return c.handleAuthResponse(params) default: - return sqlerror.NewSQLError(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "cannot parse AuthMoreDataPacket: %v", data) + return sqlerror.NewSQLErrorf(sqlerror.CRServerHandshakeErr, sqlerror.SSUnknownSQLState, "cannot parse AuthMoreDataPacket: %v", data) } } @@ -741,7 +741,7 @@ func (c *Conn) requestPublicKey() (rsaKey *rsa.PublicKey, err error) { response, err := c.readPacket() if err != nil { - return nil, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return nil, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } // Server should respond with a AuthMoreDataPacket containing the public key diff --git a/go/mysql/collations/charset/simplifiedchinese/gb18030.go b/go/mysql/collations/charset/simplifiedchinese/gb18030.go index 0e09dc8e3ab..8d6a98ba046 100644 --- a/go/mysql/collations/charset/simplifiedchinese/gb18030.go +++ b/go/mysql/collations/charset/simplifiedchinese/gb18030.go @@ -150,7 +150,7 @@ func (Charset_gb18030) DecodeRune(src []byte) (rune, int) { return utf8.RuneError, 1 } c2 := src[2] - if c2 < 0x81 || 0xff <= c2 { + if c2 < 0x81 { return utf8.RuneError, 1 } c3 := src[3] diff --git a/go/mysql/collations/colldata/cached_size.go b/go/mysql/collations/colldata/cached_size.go index 36167c69d6d..b348baaaed8 100644 --- a/go/mysql/collations/colldata/cached_size.go +++ b/go/mysql/collations/colldata/cached_size.go @@ -19,10 +19,6 @@ package colldata import hack "vitess.io/vitess/go/hack" -type cachedObject interface { - CachedSize(alloc bool) int64 -} - func (cached *eightbitWildcard) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -63,10 +59,6 @@ func (cached *unicodeWildcard) CachedSize(alloc bool) int64 { if alloc { size += int64(48) } - // field charset vitess.io/vitess/go/mysql/collations/charset/types.Charset - if cc, ok := cached.charset.(cachedObject); ok { - size += cc.CachedSize(true) - } // field pattern []rune { size += hack.RuntimeAllocSize(int64(cap(cached.pattern)) * int64(4)) 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..56c2abff06e 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -585,7 +585,7 @@ func (c *Conn) readPacket() ([]byte, error) { func (c *Conn) ReadPacket() ([]byte, error) { result, err := c.readPacket() if err != nil { - return nil, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return nil, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } return result, err } @@ -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) } @@ -1627,7 +1593,7 @@ func ParseErrorPacket(data []byte) error { // Error code is 2 bytes. code, pos, ok := readUint16(data, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRUnknownError, sqlerror.SSUnknownSQLState, "invalid error packet code: %v", data) + return sqlerror.NewSQLErrorf(sqlerror.CRUnknownError, sqlerror.SSUnknownSQLState, "invalid error packet code: %v", data) } // '#' marker of the SQL state is 1 byte. Ignored. @@ -1636,13 +1602,13 @@ func ParseErrorPacket(data []byte) error { // SQL state is 5 bytes sqlState, pos, ok := readBytes(data, pos, 5) if !ok { - return sqlerror.NewSQLError(sqlerror.CRUnknownError, sqlerror.SSUnknownSQLState, "invalid error packet sqlState: %v", data) + return sqlerror.NewSQLErrorf(sqlerror.CRUnknownError, sqlerror.SSUnknownSQLState, "invalid error packet sqlState: %v", data) } // Human readable error message is the rest. msg := string(data[pos:]) - return sqlerror.NewSQLError(sqlerror.ErrorCode(code), string(sqlState), "%v", msg) + return sqlerror.NewSQLErrorf(sqlerror.ErrorCode(code), string(sqlState), "%v", msg) } // GetTLSClientCerts gets TLS certificates. @@ -1658,12 +1624,18 @@ func (c *Conn) TLSEnabled() bool { return c.Capabilities&CapabilityClientSSL > 0 } -// IsUnixSocket returns true if this connection is over a Unix socket. +// IsUnixSocket returns true if the server connection is over a Unix socket. func (c *Conn) IsUnixSocket() bool { _, ok := c.listener.listener.(*net.UnixListener) return ok } +// IsClientUnixSocket returns true if the client connection is over a Unix socket with the server. +func (c *Conn) IsClientUnixSocket() bool { + _, ok := c.conn.(*net.UnixConn) + return ok +} + // GetRawConn returns the raw net.Conn for nefarious purposes. func (c *Conn) GetRawConn() net.Conn { return c.conn diff --git a/go/mysql/conn_test.go b/go/mysql/conn_test.go index 64b97052ead..786f4e4a19b 100644 --- a/go/mysql/conn_test.go +++ b/go/mysql/conn_test.go @@ -22,6 +22,7 @@ import ( crypto_rand "crypto/rand" "encoding/binary" "encoding/hex" + "errors" "fmt" "math/rand/v2" "net" @@ -937,7 +938,7 @@ func TestConnectionErrorWhileWritingComQuery(t *testing.T) { // this handler will return an error on the first run, and fail the test if it's run more times errorString := make([]byte, 17000) - handler := &testRun{t: t, err: fmt.Errorf(string(errorString))} + handler := &testRun{t: t, err: errors.New(string(errorString))} res := sConn.handleNextCommand(handler) require.False(t, res, "we should beak the connection in case of error writing error packet") } diff --git a/go/mysql/datetime/mydate.go b/go/mysql/datetime/mydate.go index 62cbb3f2524..5b77082055a 100644 --- a/go/mysql/datetime/mydate.go +++ b/go/mysql/datetime/mydate.go @@ -89,3 +89,48 @@ func DateFromDayNumber(daynr int) Date { d.year, d.month, d.day = mysqlDateFromDayNumber(daynr) return d } + +// ValidatePeriod validates the MySQL period. +// Returns false if period is non-positive or contains incorrect month value. +func ValidatePeriod(period int64) bool { + if period <= 0 { + return false + } + month := period % 100 + if month == 0 || month > 12 { + return false + } + return true +} + +// PeriodToMonths converts a MySQL period into number of months. +// This is an algorithm that has been reverse engineered from MySQL. +func PeriodToMonths(period int64) int64 { + p := uint64(period) + if p == 0 { + return 0 + } + y := p / 100 + if y < 70 { + y += 2000 + } else if y < 100 { + y += 1900 + } + return int64(y*12 + p%100 - 1) +} + +// MonthsToPeriod converts number of months into MySQL period. +// This is an algorithm that has been reverse engineered from MySQL. +func MonthsToPeriod(months int64) int64 { + m := uint64(months) + if m == 0 { + return 0 + } + y := m / 12 + if y < 70 { + y += 2000 + } else if y < 100 { + y += 1900 + } + return int64(y*100 + m%12 + 1) +} diff --git a/go/mysql/datetime/mydate_test.go b/go/mysql/datetime/mydate_test.go index bb5073b8ff8..a743db60709 100644 --- a/go/mysql/datetime/mydate_test.go +++ b/go/mysql/datetime/mydate_test.go @@ -65,3 +65,57 @@ func TestDayNumberFields(t *testing.T) { assert.Equal(t, wantDate, got) } } + +func TestValidatePeriod(t *testing.T) { + testCases := []struct { + period int64 + want bool + }{ + {110112, true}, + {101122, false}, + {-1112212, false}, + {7110, true}, + } + + for _, tc := range testCases { + got := ValidatePeriod(tc.period) + assert.Equal(t, tc.want, got) + } +} + +func TestPeriodToMonths(t *testing.T) { + testCases := []struct { + period int64 + want int64 + }{ + {0, 0}, + {110112, 13223}, + {100112, 12023}, + {7112, 23663}, + {200112, 24023}, + {112, 24023}, + } + + for _, tc := range testCases { + got := PeriodToMonths(tc.period) + assert.Equal(t, tc.want, got) + } +} + +func TestMonthsToPeriod(t *testing.T) { + testCases := []struct { + months int64 + want int64 + }{ + {0, 0}, + {13223, 110112}, + {12023, 100112}, + {23663, 197112}, + {24023, 200112}, + } + + for _, tc := range testCases { + got := MonthsToPeriod(tc.months) + assert.Equal(t, tc.want, got) + } +} diff --git a/go/mysql/encoding.go b/go/mysql/encoding.go index 6b33ffabfc2..20e09f32fe8 100644 --- a/go/mysql/encoding.go +++ b/go/mysql/encoding.go @@ -132,15 +132,8 @@ func writeLenEncString(data []byte, pos int, value string) int { } func writeZeroes(data []byte, pos int, len int) int { - // XXX: This implementation is optimized to leverage - // the go compiler's memclr pattern, see: https://github.com/golang/go/issues/5373 end := pos + len - data = data[pos:end] - - for i := range data { - data[i] = 0 - } - + clear(data[pos:end]) return end } @@ -332,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 @@ -397,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 41f6c416993..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) - } } @@ -355,6 +355,27 @@ func TestWriteZeroes(t *testing.T) { }) } +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) @@ -451,3 +472,10 @@ func BenchmarkEncReadInt(b *testing.B) { } }) } + +func BenchmarkEncGtidData(b *testing.B) { + b.ReportAllocs() + for range b.N { + _ = encGtidData("xxx") + } +} diff --git a/go/mysql/fakesqldb/server.go b/go/mysql/fakesqldb/server.go index 33512f23514..cd1080c862c 100644 --- a/go/mysql/fakesqldb/server.go +++ b/go/mysql/fakesqldb/server.go @@ -432,7 +432,7 @@ func (db *DB) HandleQuery(c *mysql.Conn, query string, callback func(*sqltypes.R userCallback(query) } if pat.err != "" { - return fmt.Errorf(pat.err) + return errors.New(pat.err) } return callback(pat.result) } @@ -592,6 +592,13 @@ func (db *DB) AddQueryPattern(queryPattern string, expectedResult *sqltypes.Resu db.patternData[queryPattern] = exprResult{queryPattern: queryPattern, expr: expr, result: &result} } +// RemoveQueryPattern removes a query pattern that was previously added. +func (db *DB) RemoveQueryPattern(queryPattern string) { + db.mu.Lock() + defer db.mu.Unlock() + delete(db.patternData, queryPattern) +} + // RejectQueryPattern allows a query pattern to be rejected with an error func (db *DB) RejectQueryPattern(queryPattern, error string) { expr := regexp.MustCompile("(?is)^" + queryPattern + "$") @@ -853,7 +860,7 @@ func (db *DB) GetQueryPatternResult(key string) (func(string), ExpectedResult, b userCallback, ok := db.queryPatternUserCallback[pat.expr] if ok { if pat.err != "" { - return userCallback, ExpectedResult{pat.result, nil}, true, fmt.Errorf(pat.err) + return userCallback, ExpectedResult{pat.result, nil}, true, errors.New(pat.err) } return userCallback, ExpectedResult{pat.result, nil}, true, nil } 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..01d748c66f3 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 } @@ -142,7 +148,7 @@ func (flv *filePosFlavor) readBinlogEvent(c *Conn) (BinlogEvent, error) { } switch result[0] { case EOFPacket: - return nil, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) + return nil, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) case ErrPacket: return nil, ParseErrorPacket(result) } @@ -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_mariadb.go b/go/mysql/flavor_mariadb.go index 301ec2b0596..bafb24a0c77 100644 --- a/go/mysql/flavor_mariadb.go +++ b/go/mysql/flavor_mariadb.go @@ -351,7 +351,7 @@ func (mariadbFlavor) readBinlogEvent(c *Conn) (BinlogEvent, error) { } switch result[0] { case EOFPacket: - return nil, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) + return nil, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) case ErrPacket: return nil, ParseErrorPacket(result) } diff --git a/go/mysql/flavor_mysql.go b/go/mysql/flavor_mysql.go index 5de3dc4ed46..5d92694e9f2 100644 --- a/go/mysql/flavor_mysql.go +++ b/go/mysql/flavor_mysql.go @@ -386,7 +386,7 @@ func (mysqlFlavor) readBinlogEvent(c *Conn) (BinlogEvent, error) { } switch result[0] { case EOFPacket: - return nil, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) + return nil, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", io.EOF) case ErrPacket: return nil, ParseErrorPacket(result) } 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..9126a85b2c5 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -99,36 +99,36 @@ func (c *Conn) writeComSetOption(operation uint16) error { func (c *Conn) readColumnDefinition(field *querypb.Field, index int) error { colDef, err := c.readEphemeralPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() // Catalog is ignored, always set to "def" pos, ok := skipLenEncString(colDef, 0) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v catalog failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v catalog failed", index) } // schema, table, orgTable, name and OrgName are strings. field.Database, pos, ok = readLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v schema failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v schema failed", index) } field.Table, pos, ok = readLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v table failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v table failed", index) } field.OrgTable, pos, ok = readLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v org_table failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v org_table failed", index) } field.Name, pos, ok = readLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v name failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v name failed", index) } field.OrgName, pos, ok = readLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v org_name failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v org_name failed", index) } // Skip length of fixed-length fields. @@ -137,37 +137,37 @@ func (c *Conn) readColumnDefinition(field *querypb.Field, index int) error { // characterSet is a uint16. characterSet, pos, ok := readUint16(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v characterSet failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v characterSet failed", index) } field.Charset = uint32(characterSet) // columnLength is a uint32. field.ColumnLength, pos, ok = readUint32(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v columnLength failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v columnLength failed", index) } // type is one byte. t, pos, ok := readByte(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v type failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v type failed", index) } // flags is 2 bytes. flags, pos, ok := readUint16(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v flags failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v flags failed", index) } // Convert MySQL type to Vitess type. field.Type, err = sqltypes.MySQLToType(t, int64(flags)) if err != nil { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed for column %v: %v", t, flags, index, err) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed for column %v: %v", t, flags, index, err) } // Decimals is a byte. decimals, _, ok := readByte(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v decimals failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v decimals failed", index) } field.Decimals = uint32(decimals) @@ -197,7 +197,7 @@ func (c *Conn) readColumnDefinition(field *querypb.Field, index int) error { func (c *Conn) readColumnDefinitionType(field *querypb.Field, index int) error { colDef, err := c.readEphemeralPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() @@ -205,27 +205,27 @@ func (c *Conn) readColumnDefinitionType(field *querypb.Field, index int) error { // strings, all skipped. pos, ok := skipLenEncString(colDef, 0) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v catalog failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v catalog failed", index) } pos, ok = skipLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v schema failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v schema failed", index) } pos, ok = skipLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v table failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v table failed", index) } pos, ok = skipLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v org_table failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v org_table failed", index) } pos, ok = skipLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v name failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v name failed", index) } pos, ok = skipLenEncString(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v org_name failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "skipping col %v org_name failed", index) } // Skip length of fixed-length fields. @@ -234,31 +234,31 @@ func (c *Conn) readColumnDefinitionType(field *querypb.Field, index int) error { // characterSet is a uint16. _, pos, ok = readUint16(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v characterSet failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v characterSet failed", index) } // columnLength is a uint32. _, pos, ok = readUint32(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v columnLength failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v columnLength failed", index) } // type is one byte t, pos, ok := readByte(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v type failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v type failed", index) } // flags is 2 bytes flags, _, ok := readUint16(colDef, pos) if !ok { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v flags failed", index) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "extracting col %v flags failed", index) } // Convert MySQL type to Vitess type. field.Type, err = sqltypes.MySQLToType(t, int64(flags)) if err != nil { - return sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed for column %v: %v", t, flags, index, err) + return sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed for column %v: %v", t, flags, index, err) } // skip decimals @@ -435,7 +435,7 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (*sqltypes.Result, // EOF is only present here if it's not deprecated. data, err := c.readEphemeralPacket() if err != nil { - return nil, false, 0, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return nil, false, 0, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } if c.isEOFPacket(data) { @@ -457,7 +457,7 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (*sqltypes.Result, for { data, err := c.readEphemeralPacket() if err != nil { - return nil, false, 0, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return nil, false, 0, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } if c.isEOFPacket(data) { @@ -527,7 +527,7 @@ func (c *Conn) drainResults() error { for { data, err := c.readEphemeralPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } if c.isEOFPacket(data) { c.recycleReadPacket() @@ -543,7 +543,7 @@ func (c *Conn) drainResults() error { func (c *Conn) readComQueryResponse(packetOk *PacketOK) (int, error) { data, err := c.readEphemeralPacket() if err != nil { - return 0, sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return 0, sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() if len(data) == 0 { @@ -641,7 +641,7 @@ func (c *Conn) parseComStmtExecute(prepareData map[uint32]*PrepareData, data []b // convert MySQL type to internal type. valType, err := sqltypes.MySQLToType(mysqlType, int64(flags)) if err != nil { - return stmtID, 0, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed: %v", mysqlType, flags, err) + return stmtID, 0, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "MySQLToType(%v,%v) failed: %v", mysqlType, flags, err) } prepare.ParamsType[i] = int32(valType) @@ -663,7 +663,7 @@ func (c *Conn) parseComStmtExecute(prepareData map[uint32]*PrepareData, data []b val, pos, ok = c.parseStmtArgs(payload, querypb.Type(prepare.ParamsType[i]), pos) } if !ok { - return stmtID, 0, sqlerror.NewSQLError(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "decoding parameter value failed: %v", prepare.ParamsType[i]) + return stmtID, 0, sqlerror.NewSQLErrorf(sqlerror.CRMalformedPacket, sqlerror.SSUnknownSQLState, "decoding parameter value failed: %v", prepare.ParamsType[i]) } prepare.BindVars[parameterID] = sqltypes.ValueBindVariable(val) @@ -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: @@ -696,7 +696,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V return sqltypes.NewInt64(int64(int32(val))), pos, ok case sqltypes.Float32: val, pos, ok := readUint32(data, pos) - return sqltypes.NewFloat64(float64(math.Float32frombits(uint32(val)))), pos, ok + return sqltypes.NewFloat64(float64(math.Float32frombits(val))), pos, ok case sqltypes.Uint64: val, pos, ok := readUint64(data, pos) return sqltypes.NewUint64(val), pos, ok @@ -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: @@ -1268,7 +1268,7 @@ func val2MySQL(v sqltypes.Value) ([]byte, error) { return []byte{}, err } out = make([]byte, 8) - writeUint64(out, pos, uint64(val)) + writeUint64(out, pos, val) case sqltypes.Int64: val, err := strconv.ParseInt(v.ToString(), 10, 64) if err != nil { @@ -1437,7 +1437,7 @@ func val2MySQL(v sqltypes.Value) ([]byte, error) { if err != nil { return []byte{}, err } - pos = writeUint32(out, pos, uint32(days)) + pos = writeUint32(out, pos, days) pos = writeByte(out, pos, byte(hours)) pos = writeByte(out, pos, byte(minutes)) pos = writeByte(out, pos, byte(seconds)) @@ -1493,7 +1493,7 @@ func val2MySQL(v sqltypes.Value) ([]byte, error) { if err != nil { return []byte{}, err } - pos = writeUint32(out, pos, uint32(days)) + pos = writeUint32(out, pos, days) pos = writeByte(out, pos, byte(hours)) pos = writeByte(out, pos, byte(minutes)) writeByte(out, pos, byte(seconds)) 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/replication.go b/go/mysql/replication.go index 08baaa169c8..84c65842c7e 100644 --- a/go/mysql/replication.go +++ b/go/mysql/replication.go @@ -48,7 +48,7 @@ func (c *Conn) WriteComBinlogDump(serverID uint32, binlogFilename string, binlog pos = writeUint32(data, pos, serverID) _ = writeEOFString(data, pos, binlogFilename) if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) } return nil } @@ -86,16 +86,16 @@ func (c *Conn) WriteComBinlogDumpGTID(serverID uint32, binlogFilename string, bi 4 + // data-size len(gtidSet) // data data, pos := c.startEphemeralPacketWithHeader(length) - pos = writeByte(data, pos, ComBinlogDumpGTID) //nolint - pos = writeUint16(data, pos, flags) //nolint - pos = writeUint32(data, pos, serverID) //nolint - pos = writeUint32(data, pos, uint32(len(binlogFilename))) //nolint - pos = writeEOFString(data, pos, binlogFilename) //nolint - pos = writeUint64(data, pos, binlogPos) //nolint - pos = writeUint32(data, pos, uint32(len(gtidSet))) //nolint - pos += copy(data[pos:], gtidSet) //nolint + pos = writeByte(data, pos, ComBinlogDumpGTID) // nolint + pos = writeUint16(data, pos, flags) // nolint + pos = writeUint32(data, pos, serverID) // nolint + pos = writeUint32(data, pos, uint32(len(binlogFilename))) // nolint + pos = writeEOFString(data, pos, binlogFilename) // nolint + pos = writeUint64(data, pos, binlogPos) // nolint + pos = writeUint32(data, pos, uint32(len(gtidSet))) // nolint + pos += copy(data[pos:], gtidSet) // nolint if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) } return nil } @@ -113,7 +113,7 @@ func (c *Conn) SendSemiSyncAck(binlogFilename string, binlogPos uint64) error { pos = writeUint64(data, pos, binlogPos) _ = writeEOFString(data, pos, binlogFilename) if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) } return nil @@ -135,7 +135,7 @@ func (c *Conn) WriteBinlogEvent(ev BinlogEvent, semiSyncEnabled bool) error { } _ = writeEOFString(data, pos, string(ev.Bytes())) if err := c.writeEphemeralPacket(); err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerGone, sqlerror.SSUnknownSQLState, "%v", err) } return nil } diff --git a/go/mysql/replication/mysql56_gtid.go b/go/mysql/replication/mysql56_gtid.go index dd23fb2092b..dd55caf1949 100644 --- a/go/mysql/replication/mysql56_gtid.go +++ b/go/mysql/replication/mysql56_gtid.go @@ -153,11 +153,11 @@ func DecodePositionMySQL56(s string) (rp Position, gtidSet Mysql56GTIDSet, err e return rp, nil, err } if !rp.MatchesFlavor(Mysql56FlavorID) { - return rp, nil, vterrors.Wrapf(ErrExpectMysql56Flavor, s) + return rp, nil, vterrors.Wrap(ErrExpectMysql56Flavor, s) } gtidSet, ok = rp.GTIDSet.(Mysql56GTIDSet) if !ok { - return rp, nil, vterrors.Wrapf(ErrExpectMysql56Flavor, s) + return rp, nil, vterrors.Wrap(ErrExpectMysql56Flavor, s) } return rp, gtidSet, nil } diff --git a/go/mysql/sqlerror/constants.go b/go/mysql/sqlerror/constants.go index a247ca15aa4..a61239ce17b 100644 --- a/go/mysql/sqlerror/constants.go +++ b/go/mysql/sqlerror/constants.go @@ -34,8 +34,9 @@ func (e ErrorCode) ToString() string { // See above reference for more information on each code. const ( // Vitess specific errors, (100-999) - ERNotReplica = ErrorCode(100) - ERNonAtomicCommit = ErrorCode(301) + ERNotReplica = ErrorCode(100) + ERNonAtomicCommit = ErrorCode(301) + ERInAtomicRecovery = ErrorCode(302) // unknown ERUnknownError = ErrorCode(1105) @@ -125,6 +126,8 @@ const ( ERDupIndex = ErrorCode(1831) ERInnodbReadOnly = ErrorCode(1874) + ERVectorConversion = ErrorCode(6138) + // already exists ERDbCreateExists = ErrorCode(1007) ERTableExists = ErrorCode(1050) @@ -252,27 +255,32 @@ const ( ERJSONValueTooBig = ErrorCode(3150) ERJSONDocumentTooDeep = ErrorCode(3157) - ERLockNowait = ErrorCode(3572) - ERRegexpStringNotTerminated = ErrorCode(3684) - ERRegexpBufferOverflow = ErrorCode(3684) - ERRegexpIllegalArgument = ErrorCode(3685) - ERRegexpIndexOutOfBounds = ErrorCode(3686) - ERRegexpInternal = ErrorCode(3687) - ERRegexpRuleSyntax = ErrorCode(3688) - ERRegexpBadEscapeSequence = ErrorCode(3689) - ERRegexpUnimplemented = ErrorCode(3690) - ERRegexpMismatchParen = ErrorCode(3691) - ERRegexpBadInterval = ErrorCode(3692) - ERRRegexpMaxLtMin = ErrorCode(3693) - ERRegexpInvalidBackRef = ErrorCode(3694) - ERRegexpLookBehindLimit = ErrorCode(3695) - ERRegexpMissingCloseBracket = ErrorCode(3696) - ERRegexpInvalidRange = ErrorCode(3697) - ERRegexpStackOverflow = ErrorCode(3698) - ERRegexpTimeOut = ErrorCode(3699) - ERRegexpPatternTooBig = ErrorCode(3700) - ERRegexpInvalidCaptureGroup = ErrorCode(3887) - ERRegexpInvalidFlag = ErrorCode(3900) + ERLockNowait = ErrorCode(3572) + ERCTERecursiveRequiresUnion = ErrorCode(3573) + ERCTERecursiveForbidsAggregation = ErrorCode(3575) + ERCTERecursiveForbiddenJoinOrder = ErrorCode(3576) + ERCTERecursiveRequiresSingleReference = ErrorCode(3577) + ERCTEMaxRecursionDepth = ErrorCode(3636) + ERRegexpStringNotTerminated = ErrorCode(3684) + ERRegexpBufferOverflow = ErrorCode(3684) + ERRegexpIllegalArgument = ErrorCode(3685) + ERRegexpIndexOutOfBounds = ErrorCode(3686) + ERRegexpInternal = ErrorCode(3687) + ERRegexpRuleSyntax = ErrorCode(3688) + ERRegexpBadEscapeSequence = ErrorCode(3689) + ERRegexpUnimplemented = ErrorCode(3690) + ERRegexpMismatchParen = ErrorCode(3691) + ERRegexpBadInterval = ErrorCode(3692) + ERRRegexpMaxLtMin = ErrorCode(3693) + ERRegexpInvalidBackRef = ErrorCode(3694) + ERRegexpLookBehindLimit = ErrorCode(3695) + ERRegexpMissingCloseBracket = ErrorCode(3696) + ERRegexpInvalidRange = ErrorCode(3697) + ERRegexpStackOverflow = ErrorCode(3698) + ERRegexpTimeOut = ErrorCode(3699) + ERRegexpPatternTooBig = ErrorCode(3700) + ERRegexpInvalidCaptureGroup = ErrorCode(3887) + ERRegexpInvalidFlag = ErrorCode(3900) ERCharacterSetMismatch = ErrorCode(3995) diff --git a/go/mysql/sqlerror/sql_error.go b/go/mysql/sqlerror/sql_error.go index 935fd77a12f..f2a5fb46388 100644 --- a/go/mysql/sqlerror/sql_error.go +++ b/go/mysql/sqlerror/sql_error.go @@ -38,14 +38,18 @@ type SQLError struct { // NewSQLError creates a new SQLError. // If sqlState is left empty, it will default to "HY000" (general error). // TODO: Should be aligned with vterrors, stack traces and wrapping -func NewSQLError(number ErrorCode, sqlState string, format string, args ...any) *SQLError { +func NewSQLErrorf(number ErrorCode, sqlState string, format string, args ...any) *SQLError { + return NewSQLError(number, sqlState, fmt.Sprintf(format, args...)) +} + +func NewSQLError(number ErrorCode, sqlState string, msg string) *SQLError { if sqlState == "" { sqlState = SSUnknownSQLState } return &SQLError{ Num: number, State: sqlState, - Message: fmt.Sprintf(format, args...), + Message: msg, } } @@ -172,79 +176,85 @@ type mysqlCode struct { } var stateToMysqlCode = map[vterrors.State]mysqlCode{ - vterrors.Undefined: {num: ERUnknownError, state: SSUnknownSQLState}, - vterrors.AccessDeniedError: {num: ERAccessDeniedError, state: SSAccessDeniedError}, - vterrors.BadDb: {num: ERBadDb, state: SSClientError}, - vterrors.BadFieldError: {num: ERBadFieldError, state: SSBadFieldError}, - vterrors.BadTableError: {num: ERBadTable, state: SSUnknownTable}, - vterrors.CantUseOptionHere: {num: ERCantUseOptionHere, state: SSClientError}, - vterrors.DataOutOfRange: {num: ERDataOutOfRange, state: SSDataOutOfRange}, - vterrors.DbCreateExists: {num: ERDbCreateExists, state: SSUnknownSQLState}, - vterrors.DbDropExists: {num: ERDbDropExists, state: SSUnknownSQLState}, - vterrors.DupFieldName: {num: ERDupFieldName, state: SSDupFieldName}, - vterrors.EmptyQuery: {num: EREmptyQuery, state: SSClientError}, - vterrors.IncorrectGlobalLocalVar: {num: ERIncorrectGlobalLocalVar, state: SSUnknownSQLState}, - vterrors.InnodbReadOnly: {num: ERInnodbReadOnly, state: SSUnknownSQLState}, - vterrors.LockOrActiveTransaction: {num: ERLockOrActiveTransaction, state: SSUnknownSQLState}, - vterrors.NoDB: {num: ERNoDb, state: SSNoDB}, - vterrors.NoSuchTable: {num: ERNoSuchTable, state: SSUnknownTable}, - vterrors.NotSupportedYet: {num: ERNotSupportedYet, state: SSClientError}, - vterrors.ForbidSchemaChange: {num: ERForbidSchemaChange, state: SSUnknownSQLState}, - vterrors.MixOfGroupFuncAndFields: {num: ERMixOfGroupFuncAndFields, state: SSClientError}, - vterrors.NetPacketTooLarge: {num: ERNetPacketTooLarge, state: SSNetError}, - vterrors.NonUniqError: {num: ERNonUniq, state: SSConstraintViolation}, - vterrors.NonUniqTable: {num: ERNonUniqTable, state: SSClientError}, - vterrors.NonUpdateableTable: {num: ERNonUpdateableTable, state: SSUnknownSQLState}, - vterrors.QueryInterrupted: {num: ERQueryInterrupted, state: SSQueryInterrupted}, - vterrors.SPDoesNotExist: {num: ERSPDoesNotExist, state: SSClientError}, - vterrors.SyntaxError: {num: ERSyntaxError, state: SSClientError}, - vterrors.UnsupportedPS: {num: ERUnsupportedPS, state: SSUnknownSQLState}, - vterrors.UnknownSystemVariable: {num: ERUnknownSystemVariable, state: SSUnknownSQLState}, - vterrors.UnknownTable: {num: ERUnknownTable, state: SSUnknownTable}, - vterrors.WrongGroupField: {num: ERWrongGroupField, state: SSClientError}, - vterrors.WrongNumberOfColumnsInSelect: {num: ERWrongNumberOfColumnsInSelect, state: SSWrongNumberOfColumns}, - vterrors.WrongTypeForVar: {num: ERWrongTypeForVar, state: SSClientError}, - vterrors.WrongValueForVar: {num: ERWrongValueForVar, state: SSClientError}, - vterrors.WrongValue: {num: ERWrongValue, state: SSUnknownSQLState}, - vterrors.WrongFieldWithGroup: {num: ERWrongFieldWithGroup, state: SSClientError}, - vterrors.ServerNotAvailable: {num: ERServerIsntAvailable, state: SSNetError}, - vterrors.CantDoThisInTransaction: {num: ERCantDoThisDuringAnTransaction, state: SSCantDoThisDuringAnTransaction}, - vterrors.RequiresPrimaryKey: {num: ERRequiresPrimaryKey, state: SSClientError}, - vterrors.RowIsReferenced2: {num: ERRowIsReferenced2, state: SSConstraintViolation}, - vterrors.NoReferencedRow2: {num: ErNoReferencedRow2, state: SSConstraintViolation}, - vterrors.NoSuchSession: {num: ERUnknownComError, state: SSNetError}, - vterrors.OperandColumns: {num: EROperandColumns, state: SSWrongNumberOfColumns}, - vterrors.WrongValueCountOnRow: {num: ERWrongValueCountOnRow, state: SSWrongValueCountOnRow}, - vterrors.WrongArguments: {num: ERWrongArguments, state: SSUnknownSQLState}, - vterrors.ViewWrongList: {num: ERViewWrongList, state: SSUnknownSQLState}, - vterrors.UnknownStmtHandler: {num: ERUnknownStmtHandler, state: SSUnknownSQLState}, - vterrors.KeyDoesNotExist: {num: ERKeyDoesNotExist, state: SSClientError}, - vterrors.UnknownTimeZone: {num: ERUnknownTimeZone, state: SSUnknownSQLState}, - vterrors.RegexpStringNotTerminated: {num: ERRegexpStringNotTerminated, state: SSUnknownSQLState}, - vterrors.RegexpBufferOverflow: {num: ERRegexpBufferOverflow, state: SSUnknownSQLState}, - vterrors.RegexpIllegalArgument: {num: ERRegexpIllegalArgument, state: SSUnknownSQLState}, - vterrors.RegexpIndexOutOfBounds: {num: ERRegexpIndexOutOfBounds, state: SSUnknownSQLState}, - vterrors.RegexpInternal: {num: ERRegexpInternal, state: SSUnknownSQLState}, - vterrors.RegexpRuleSyntax: {num: ERRegexpRuleSyntax, state: SSUnknownSQLState}, - vterrors.RegexpBadEscapeSequence: {num: ERRegexpBadEscapeSequence, state: SSUnknownSQLState}, - vterrors.RegexpUnimplemented: {num: ERRegexpUnimplemented, state: SSUnknownSQLState}, - vterrors.RegexpMismatchParen: {num: ERRegexpMismatchParen, state: SSUnknownSQLState}, - vterrors.RegexpBadInterval: {num: ERRegexpBadInterval, state: SSUnknownSQLState}, - vterrors.RegexpMaxLtMin: {num: ERRRegexpMaxLtMin, state: SSUnknownSQLState}, - vterrors.RegexpInvalidBackRef: {num: ERRegexpInvalidBackRef, state: SSUnknownSQLState}, - vterrors.RegexpLookBehindLimit: {num: ERRegexpLookBehindLimit, state: SSUnknownSQLState}, - vterrors.RegexpMissingCloseBracket: {num: ERRegexpMissingCloseBracket, state: SSUnknownSQLState}, - vterrors.RegexpInvalidRange: {num: ERRegexpInvalidRange, state: SSUnknownSQLState}, - vterrors.RegexpStackOverflow: {num: ERRegexpStackOverflow, state: SSUnknownSQLState}, - vterrors.RegexpTimeOut: {num: ERRegexpTimeOut, state: SSUnknownSQLState}, - vterrors.RegexpPatternTooBig: {num: ERRegexpPatternTooBig, state: SSUnknownSQLState}, - vterrors.RegexpInvalidFlag: {num: ERRegexpInvalidFlag, state: SSUnknownSQLState}, - vterrors.RegexpInvalidCaptureGroup: {num: ERRegexpInvalidCaptureGroup, state: SSUnknownSQLState}, - vterrors.CharacterSetMismatch: {num: ERCharacterSetMismatch, state: SSUnknownSQLState}, - vterrors.WrongParametersToNativeFct: {num: ERWrongParametersToNativeFct, state: SSUnknownSQLState}, - vterrors.KillDeniedError: {num: ERKillDenied, state: SSUnknownSQLState}, - vterrors.BadNullError: {num: ERBadNullError, state: SSConstraintViolation}, - vterrors.InvalidGroupFuncUse: {num: ERInvalidGroupFuncUse, state: SSUnknownSQLState}, + vterrors.Undefined: {num: ERUnknownError, state: SSUnknownSQLState}, + vterrors.AccessDeniedError: {num: ERAccessDeniedError, state: SSAccessDeniedError}, + vterrors.BadDb: {num: ERBadDb, state: SSClientError}, + vterrors.BadFieldError: {num: ERBadFieldError, state: SSBadFieldError}, + vterrors.BadTableError: {num: ERBadTable, state: SSUnknownTable}, + vterrors.CantUseOptionHere: {num: ERCantUseOptionHere, state: SSClientError}, + vterrors.DataOutOfRange: {num: ERDataOutOfRange, state: SSDataOutOfRange}, + vterrors.DbCreateExists: {num: ERDbCreateExists, state: SSUnknownSQLState}, + vterrors.DbDropExists: {num: ERDbDropExists, state: SSUnknownSQLState}, + vterrors.DupFieldName: {num: ERDupFieldName, state: SSDupFieldName}, + vterrors.EmptyQuery: {num: EREmptyQuery, state: SSClientError}, + vterrors.IncorrectGlobalLocalVar: {num: ERIncorrectGlobalLocalVar, state: SSUnknownSQLState}, + vterrors.InnodbReadOnly: {num: ERInnodbReadOnly, state: SSUnknownSQLState}, + vterrors.LockOrActiveTransaction: {num: ERLockOrActiveTransaction, state: SSUnknownSQLState}, + vterrors.NoDB: {num: ERNoDb, state: SSNoDB}, + vterrors.NoSuchTable: {num: ERNoSuchTable, state: SSUnknownTable}, + vterrors.NotSupportedYet: {num: ERNotSupportedYet, state: SSClientError}, + vterrors.ForbidSchemaChange: {num: ERForbidSchemaChange, state: SSUnknownSQLState}, + vterrors.MixOfGroupFuncAndFields: {num: ERMixOfGroupFuncAndFields, state: SSClientError}, + vterrors.NetPacketTooLarge: {num: ERNetPacketTooLarge, state: SSNetError}, + vterrors.NonUniqError: {num: ERNonUniq, state: SSConstraintViolation}, + vterrors.NonUniqTable: {num: ERNonUniqTable, state: SSClientError}, + vterrors.NonUpdateableTable: {num: ERNonUpdateableTable, state: SSUnknownSQLState}, + vterrors.QueryInterrupted: {num: ERQueryInterrupted, state: SSQueryInterrupted}, + vterrors.SPDoesNotExist: {num: ERSPDoesNotExist, state: SSClientError}, + vterrors.SyntaxError: {num: ERSyntaxError, state: SSClientError}, + vterrors.UnsupportedPS: {num: ERUnsupportedPS, state: SSUnknownSQLState}, + vterrors.UnknownSystemVariable: {num: ERUnknownSystemVariable, state: SSUnknownSQLState}, + vterrors.UnknownTable: {num: ERUnknownTable, state: SSUnknownTable}, + vterrors.WrongGroupField: {num: ERWrongGroupField, state: SSClientError}, + vterrors.WrongNumberOfColumnsInSelect: {num: ERWrongNumberOfColumnsInSelect, state: SSWrongNumberOfColumns}, + vterrors.WrongTypeForVar: {num: ERWrongTypeForVar, state: SSClientError}, + vterrors.WrongValueForVar: {num: ERWrongValueForVar, state: SSClientError}, + vterrors.WrongValue: {num: ERWrongValue, state: SSUnknownSQLState}, + vterrors.WrongFieldWithGroup: {num: ERWrongFieldWithGroup, state: SSClientError}, + vterrors.ServerNotAvailable: {num: ERServerIsntAvailable, state: SSNetError}, + vterrors.CantDoThisInTransaction: {num: ERCantDoThisDuringAnTransaction, state: SSCantDoThisDuringAnTransaction}, + vterrors.RequiresPrimaryKey: {num: ERRequiresPrimaryKey, state: SSClientError}, + vterrors.RowIsReferenced2: {num: ERRowIsReferenced2, state: SSConstraintViolation}, + vterrors.NoReferencedRow2: {num: ErNoReferencedRow2, state: SSConstraintViolation}, + vterrors.NoSuchSession: {num: ERUnknownComError, state: SSNetError}, + vterrors.OperandColumns: {num: EROperandColumns, state: SSWrongNumberOfColumns}, + vterrors.WrongValueCountOnRow: {num: ERWrongValueCountOnRow, state: SSWrongValueCountOnRow}, + vterrors.WrongArguments: {num: ERWrongArguments, state: SSUnknownSQLState}, + vterrors.ViewWrongList: {num: ERViewWrongList, state: SSUnknownSQLState}, + vterrors.UnknownStmtHandler: {num: ERUnknownStmtHandler, state: SSUnknownSQLState}, + vterrors.KeyDoesNotExist: {num: ERKeyDoesNotExist, state: SSClientError}, + vterrors.UnknownTimeZone: {num: ERUnknownTimeZone, state: SSUnknownSQLState}, + vterrors.RegexpStringNotTerminated: {num: ERRegexpStringNotTerminated, state: SSUnknownSQLState}, + vterrors.RegexpBufferOverflow: {num: ERRegexpBufferOverflow, state: SSUnknownSQLState}, + vterrors.RegexpIllegalArgument: {num: ERRegexpIllegalArgument, state: SSUnknownSQLState}, + vterrors.RegexpIndexOutOfBounds: {num: ERRegexpIndexOutOfBounds, state: SSUnknownSQLState}, + vterrors.RegexpInternal: {num: ERRegexpInternal, state: SSUnknownSQLState}, + vterrors.RegexpRuleSyntax: {num: ERRegexpRuleSyntax, state: SSUnknownSQLState}, + vterrors.RegexpBadEscapeSequence: {num: ERRegexpBadEscapeSequence, state: SSUnknownSQLState}, + vterrors.RegexpUnimplemented: {num: ERRegexpUnimplemented, state: SSUnknownSQLState}, + vterrors.RegexpMismatchParen: {num: ERRegexpMismatchParen, state: SSUnknownSQLState}, + vterrors.RegexpBadInterval: {num: ERRegexpBadInterval, state: SSUnknownSQLState}, + vterrors.RegexpMaxLtMin: {num: ERRRegexpMaxLtMin, state: SSUnknownSQLState}, + vterrors.RegexpInvalidBackRef: {num: ERRegexpInvalidBackRef, state: SSUnknownSQLState}, + vterrors.RegexpLookBehindLimit: {num: ERRegexpLookBehindLimit, state: SSUnknownSQLState}, + vterrors.RegexpMissingCloseBracket: {num: ERRegexpMissingCloseBracket, state: SSUnknownSQLState}, + vterrors.RegexpInvalidRange: {num: ERRegexpInvalidRange, state: SSUnknownSQLState}, + vterrors.RegexpStackOverflow: {num: ERRegexpStackOverflow, state: SSUnknownSQLState}, + vterrors.RegexpTimeOut: {num: ERRegexpTimeOut, state: SSUnknownSQLState}, + vterrors.RegexpPatternTooBig: {num: ERRegexpPatternTooBig, state: SSUnknownSQLState}, + vterrors.RegexpInvalidFlag: {num: ERRegexpInvalidFlag, state: SSUnknownSQLState}, + vterrors.RegexpInvalidCaptureGroup: {num: ERRegexpInvalidCaptureGroup, state: SSUnknownSQLState}, + vterrors.CharacterSetMismatch: {num: ERCharacterSetMismatch, state: SSUnknownSQLState}, + vterrors.WrongParametersToNativeFct: {num: ERWrongParametersToNativeFct, state: SSUnknownSQLState}, + vterrors.KillDeniedError: {num: ERKillDenied, state: SSUnknownSQLState}, + vterrors.BadNullError: {num: ERBadNullError, state: SSConstraintViolation}, + vterrors.InvalidGroupFuncUse: {num: ERInvalidGroupFuncUse, state: SSUnknownSQLState}, + vterrors.VectorConversion: {num: ERVectorConversion, state: SSUnknownSQLState}, + vterrors.CTERecursiveRequiresSingleReference: {num: ERCTERecursiveRequiresSingleReference, state: SSUnknownSQLState}, + vterrors.CTERecursiveRequiresUnion: {num: ERCTERecursiveRequiresUnion, state: SSUnknownSQLState}, + vterrors.CTERecursiveForbidsAggregation: {num: ERCTERecursiveForbidsAggregation, state: SSUnknownSQLState}, + vterrors.CTERecursiveForbiddenJoinOrder: {num: ERCTERecursiveForbiddenJoinOrder, state: SSUnknownSQLState}, + vterrors.CTEMaxRecursionDepth: {num: ERCTEMaxRecursionDepth, state: SSUnknownSQLState}, } func getStateToMySQLState(state vterrors.State) mysqlCode { @@ -284,7 +294,7 @@ func convertToMysqlError(err error) error { if !ok { return err } - return NewSQLError(mysqlCode.num, mysqlCode.state, err.Error()) + return NewSQLError(mysqlCode.num, mysqlCode.state, err.Error()) //nolint:govet } var isGRPCOverflowRE = regexp.MustCompile(`.*?grpc: (received|trying to send) message larger than max \(\d+ vs. \d+\)`) diff --git a/go/mysql/streaming_query.go b/go/mysql/streaming_query.go index 3d0d9ef49e8..95b4e293601 100644 --- a/go/mysql/streaming_query.go +++ b/go/mysql/streaming_query.go @@ -78,7 +78,7 @@ func (c *Conn) ExecuteStreamFetch(query string) (err error) { // EOF is only present here if it's not deprecated. data, err := c.readEphemeralPacket() if err != nil { - return sqlerror.NewSQLError(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) + return sqlerror.NewSQLErrorf(sqlerror.CRServerLost, sqlerror.SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() if c.isEOFPacket(data) { @@ -88,7 +88,7 @@ func (c *Conn) ExecuteStreamFetch(query string) (err error) { } else if isErrorPacket(data) { return ParseErrorPacket(data) } else { - return sqlerror.NewSQLError(sqlerror.CRCommandsOutOfSync, sqlerror.SSUnknownSQLState, "unexpected packet after fields: %v", data) + return sqlerror.NewSQLErrorf(sqlerror.CRCommandsOutOfSync, sqlerror.SSUnknownSQLState, "unexpected packet after fields: %v", data) } } diff --git a/go/mysql/vault/auth_server_vault.go b/go/mysql/vault/auth_server_vault.go index d2bc2548817..1f86d84ac40 100644 --- a/go/mysql/vault/auth_server_vault.go +++ b/go/mysql/vault/auth_server_vault.go @@ -159,14 +159,14 @@ func (a *AuthServerVault) UserEntryWithHash(conn *mysql.Conn, salt []byte, user a.mu.Unlock() if !ok { - return &mysql.StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &mysql.StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } for _, entry := range userEntries { if entry.MysqlNativePassword != "" { hash, err := mysql.DecodeMysqlNativePasswordHex(entry.MysqlNativePassword) if err != nil { - return &mysql.StaticUserData{Username: entry.UserData, Groups: entry.Groups}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &mysql.StaticUserData{Username: entry.UserData, Groups: entry.Groups}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } isPass := mysql.VerifyHashedMysqlNativePassword(authResponse, salt, hash) if mysql.MatchSourceHost(remoteAddr, entry.SourceHost) && isPass { @@ -180,7 +180,7 @@ func (a *AuthServerVault) UserEntryWithHash(conn *mysql.Conn, salt []byte, user } } } - return &mysql.StaticUserData{}, sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) + return &mysql.StaticUserData{}, sqlerror.NewSQLErrorf(sqlerror.ERAccessDeniedError, sqlerror.SSAccessDeniedError, "Access denied for user '%v'", user) } func (a *AuthServerVault) setTTLTicker(ttl time.Duration) { diff --git a/go/sqltypes/cached_size.go b/go/sqltypes/cached_size.go index 2a488f8450e..632c8249455 100644 --- a/go/sqltypes/cached_size.go +++ b/go/sqltypes/cached_size.go @@ -34,17 +34,9 @@ func (cached *Result) CachedSize(alloc bool) int64 { size += elem.CachedSize(true) } } - // field Rows [][]vitess.io/vitess/go/sqltypes.Value + // field Rows []vitess.io/vitess/go/sqltypes.Row { size += hack.RuntimeAllocSize(int64(cap(cached.Rows)) * int64(24)) - for _, elem := range cached.Rows { - { - size += hack.RuntimeAllocSize(int64(cap(elem)) * int64(32)) - for _, elem := range elem { - size += elem.CachedSize(false) - } - } - } } // field SessionStateChanges string size += hack.RuntimeAllocSize(int64(len(cached.SessionStateChanges))) 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/test/endtoend/backup/vtbackup/backup_only_test.go b/go/test/endtoend/backup/vtbackup/backup_only_test.go index 7dada7a77d2..4e018986100 100644 --- a/go/test/endtoend/backup/vtbackup/backup_only_test.go +++ b/go/test/endtoend/backup/vtbackup/backup_only_test.go @@ -69,15 +69,10 @@ func TestTabletInitialBackup(t *testing.T) { // Initialize the tablets initTablets(t, false, false) - vtTabletVersion, err := cluster.GetMajorVersion("vttablet") - require.NoError(t, err) - // For all version at or above v17.0.0, each replica will start in super_read_only mode. Let's verify that is working correctly. - if vtTabletVersion >= 17 { - err := primary.VttabletProcess.CreateDB("testDB") - require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") - err = replica1.VttabletProcess.CreateDB("testDB") - require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") - } + err := primary.VttabletProcess.CreateDB("testDB") + require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") + err = replica1.VttabletProcess.CreateDB("testDB") + require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") // Restore the Tablet restore(t, primary, "replica", "NOT_SERVING") @@ -172,7 +167,7 @@ func firstBackupTest(t *testing.T, tabletType string) { restore(t, replica2, "replica", "SERVING") // Replica2 takes time to serve. Sleeping for 5 sec. time.Sleep(5 * time.Second) - //check the new replica has the data + // check the new replica has the data cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) removeBackups(t) diff --git a/go/test/endtoend/backup/vtctlbackup/backup_utils.go b/go/test/endtoend/backup/vtctlbackup/backup_utils.go index 707c9010b0c..3a0150cc87c 100644 --- a/go/test/endtoend/backup/vtctlbackup/backup_utils.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_utils.go @@ -1032,7 +1032,7 @@ func verifySemiSyncStatus(t *testing.T, vttablet *cluster.Vttablet, expectedStat } func terminateBackup(t *testing.T, alias string) { - stopBackupMsg := "Done taking Backup" + stopBackupMsg := "Completed backing up" if useXtrabackup { stopBackupMsg = "Starting backup with" useXtrabackup = false diff --git a/go/test/endtoend/cluster/cluster_process.go b/go/test/endtoend/cluster/cluster_process.go index 44636b3cdb6..95995903a83 100644 --- a/go/test/endtoend/cluster/cluster_process.go +++ b/go/test/endtoend/cluster/cluster_process.go @@ -151,11 +151,12 @@ type Vttablet struct { // Keyspace : Cluster accepts keyspace to launch it type Keyspace struct { - Name string - SchemaSQL string - VSchema string - SidecarDBName string - Shards []Shard + Name string + SchemaSQL string + VSchema string + SidecarDBName string + DurabilityPolicy string + Shards []Shard } // Shard with associated vttablets @@ -284,9 +285,10 @@ func (cluster *LocalProcessCluster) startPartialKeyspace(keyspace Keyspace, shar cluster.HasPartialKeyspaces = true routedKeyspace := &Keyspace{ - Name: fmt.Sprintf("%s_routed", keyspace.Name), - SchemaSQL: keyspace.SchemaSQL, - VSchema: keyspace.VSchema, + Name: fmt.Sprintf("%s_routed", keyspace.Name), + SchemaSQL: keyspace.SchemaSQL, + VSchema: keyspace.VSchema, + DurabilityPolicy: keyspace.DurabilityPolicy, } err = cluster.startKeyspace(*routedKeyspace, shardNames, replicaCount, rdonly, customizers...) @@ -374,7 +376,7 @@ func (cluster *LocalProcessCluster) startKeyspace(keyspace Keyspace, shardNames keyspace.SidecarDBName = sidecar.DefaultName } // Create the keyspace if it doesn't already exist. - _ = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName) + _ = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName, keyspace.DurabilityPolicy) for _, shardName := range shardNames { shard := &Shard{ Name: shardName, @@ -538,7 +540,7 @@ func (cluster *LocalProcessCluster) StartKeyspaceLegacy(keyspace Keyspace, shard keyspace.SidecarDBName = sidecar.DefaultName } // Create the keyspace if it doesn't already exist. - _ = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName) + _ = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName, keyspace.DurabilityPolicy) var mysqlctlProcessList []*exec.Cmd for _, shardName := range shardNames { shard := &Shard{ @@ -681,7 +683,7 @@ func (cluster *LocalProcessCluster) SetupCluster(keyspace *Keyspace, shards []Sh if !cluster.ReusingVTDATAROOT { // Create Keyspace - err = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName) + err = cluster.VtctlProcess.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName, keyspace.DurabilityPolicy) if err != nil { log.Error(err) return diff --git a/go/test/endtoend/cluster/vtctl_process.go b/go/test/endtoend/cluster/vtctl_process.go index b9d8a5b46ce..185c3079d34 100644 --- a/go/test/endtoend/cluster/vtctl_process.go +++ b/go/test/endtoend/cluster/vtctl_process.go @@ -60,15 +60,15 @@ func (vtctl *VtctlProcess) AddCellInfo(Cell string) (err error) { } // CreateKeyspace executes vtctl command to create keyspace -func (vtctl *VtctlProcess) CreateKeyspace(keyspace, sidecarDBName string) (err error) { - var output string - // For upgrade/downgrade tests where an older version is also used. - if vtctl.VtctlMajorVersion < 17 { - log.Errorf("CreateKeyspace does not support the --sidecar-db-name flag in vtctl version %d; ignoring...", vtctl.VtctlMajorVersion) - output, err = vtctl.ExecuteCommandWithOutput("CreateKeyspace", keyspace) - } else { - output, err = vtctl.ExecuteCommandWithOutput("CreateKeyspace", keyspace, "--sidecar-db-name", sidecarDBName) +func (vtctl *VtctlProcess) CreateKeyspace(keyspace, sidecarDBName, durabilityPolicy string) error { + args := []string{ + "CreateKeyspace", keyspace, + "--sidecar-db-name", sidecarDBName, } + if durabilityPolicy != "" { + args = append(args, "--durability-policy", durabilityPolicy) + } + output, err := vtctl.ExecuteCommandWithOutput(args...) if err != nil { log.Errorf("CreateKeyspace returned err: %s, output: %s", err, output) } diff --git a/go/test/endtoend/cluster/vtctld_process.go b/go/test/endtoend/cluster/vtctld_process.go index d87427af9b9..6ac6ed5d2b0 100644 --- a/go/test/endtoend/cluster/vtctld_process.go +++ b/go/test/endtoend/cluster/vtctld_process.go @@ -65,15 +65,10 @@ func (vtctld *VtctldProcess) Setup(cell string, extraArgs ...string) (err error) "--log_dir", vtctld.LogDir, "--port", fmt.Sprintf("%d", vtctld.Port), "--grpc_port", fmt.Sprintf("%d", vtctld.GrpcPort), + "--bind-address", "127.0.0.1", + "--grpc_bind_address", "127.0.0.1", ) - if v, err := GetMajorVersion("vtctld"); err != nil { - return err - } else if v >= 18 { - vtctld.proc.Args = append(vtctld.proc.Args, "--bind-address", "127.0.0.1") - vtctld.proc.Args = append(vtctld.proc.Args, "--grpc_bind_address", "127.0.0.1") - } - if *isCoverage { vtctld.proc.Args = append(vtctld.proc.Args, "--test.coverprofile="+getCoveragePath("vtctld.out")) } diff --git a/go/test/endtoend/cluster/vtctldclient_process.go b/go/test/endtoend/cluster/vtctldclient_process.go index 5373f351f86..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) { diff --git a/go/test/endtoend/cluster/vtgate_process.go b/go/test/endtoend/cluster/vtgate_process.go index 5143e9ad8a4..d7f5dc3dc01 100644 --- a/go/test/endtoend/cluster/vtgate_process.go +++ b/go/test/endtoend/cluster/vtgate_process.go @@ -85,12 +85,8 @@ func (vtgate *VtgateProcess) Setup() (err error) { "--tablet_types_to_wait", vtgate.TabletTypesToWait, "--service_map", vtgate.ServiceMap, "--mysql_auth_server_impl", vtgate.MySQLAuthServerImpl, - } - if v, err := GetMajorVersion("vtgate"); err != nil { - return err - } else if v >= 18 { - args = append(args, "--bind-address", "127.0.0.1") - args = append(args, "--grpc_bind_address", "127.0.0.1") + "--bind-address", "127.0.0.1", + "--grpc_bind_address", "127.0.0.1", } // If no explicit mysql_server_version has been specified then we autodetect // the MySQL version that will be used for the test and base the vtgate's diff --git a/go/test/endtoend/cluster/vtorc_process.go b/go/test/endtoend/cluster/vtorc_process.go index cac5921d01d..31cf03606e5 100644 --- a/go/test/endtoend/cluster/vtorc_process.go +++ b/go/test/endtoend/cluster/vtorc_process.go @@ -126,14 +126,9 @@ func (orc *VTOrcProcess) Setup() (err error) { "--instance-poll-time", "1s", // Faster topo information refresh speeds up the tests. This doesn't add any significant load either "--topo-information-refresh-duration", "3s", + "--bind-address", "127.0.0.1", ) - if v, err := GetMajorVersion("vtorc"); err != nil { - return err - } else if v >= 18 { - orc.proc.Args = append(orc.proc.Args, "--bind-address", "127.0.0.1") - } - if *isCoverage { orc.proc.Args = append(orc.proc.Args, "--test.coverprofile="+getCoveragePath("orc.out")) } diff --git a/go/test/endtoend/cluster/vttablet_process.go b/go/test/endtoend/cluster/vttablet_process.go index 6bd60b63191..d4f0e3f1963 100644 --- a/go/test/endtoend/cluster/vttablet_process.go +++ b/go/test/endtoend/cluster/vttablet_process.go @@ -111,13 +111,9 @@ func (vttablet *VttabletProcess) Setup() (err error) { "--file_backup_storage_root", vttablet.FileBackupStorageRoot, "--service_map", vttablet.ServiceMap, "--db_charset", vttablet.Charset, + "--bind-address", "127.0.0.1", + "--grpc_bind_address", "127.0.0.1", ) - if v, err := GetMajorVersion("vttablet"); err != nil { - return err - } else if v >= 18 { - vttablet.proc.Args = append(vttablet.proc.Args, "--bind-address", "127.0.0.1") - vttablet.proc.Args = append(vttablet.proc.Args, "--grpc_bind_address", "127.0.0.1") - } if *isCoverage { vttablet.proc.Args = append(vttablet.proc.Args, "--test.coverprofile="+getCoveragePath("vttablet.out")) diff --git a/go/test/endtoend/encryption/encryptedreplication/encrypted_replication_test.go b/go/test/endtoend/encryption/encryptedreplication/encrypted_replication_test.go index 4c759ff577a..7dea6cf525f 100644 --- a/go/test/endtoend/encryption/encryptedreplication/encrypted_replication_test.go +++ b/go/test/endtoend/encryption/encryptedreplication/encrypted_replication_test.go @@ -131,7 +131,7 @@ func initializeCluster(t *testing.T) (int, error) { for _, keyspaceStr := range []string{keyspace} { KeyspacePtr := &cluster.Keyspace{Name: keyspaceStr} keyspace := *KeyspacePtr - if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name, sidecar.DefaultName); err != nil { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name, sidecar.DefaultName, ""); err != nil { return 1, err } shard := &cluster.Shard{ diff --git a/go/test/endtoend/encryption/encryptedtransport/encrypted_transport_test.go b/go/test/endtoend/encryption/encryptedtransport/encrypted_transport_test.go index 9147b7b9080..1363e07b2cd 100644 --- a/go/test/endtoend/encryption/encryptedtransport/encrypted_transport_test.go +++ b/go/test/endtoend/encryption/encryptedtransport/encrypted_transport_test.go @@ -350,7 +350,7 @@ func clusterSetUp(t *testing.T) (int, error) { for _, keyspaceStr := range []string{keyspace} { KeyspacePtr := &cluster.Keyspace{Name: keyspaceStr} keyspace := *KeyspacePtr - if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name, sidecar.DefaultName); err != nil { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name, sidecar.DefaultName, ""); err != nil { return 1, err } shard := &cluster.Shard{ diff --git a/go/test/endtoend/mysqlctl/mysqlctl_test.go b/go/test/endtoend/mysqlctl/mysqlctl_test.go index 6c3d65226e3..f93724fa4a8 100644 --- a/go/test/endtoend/mysqlctl/mysqlctl_test.go +++ b/go/test/endtoend/mysqlctl/mysqlctl_test.go @@ -53,7 +53,7 @@ func TestMain(m *testing.M) { return 1 } - if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName); err != nil { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName, ""); err != nil { return 1 } diff --git a/go/test/endtoend/mysqlctld/mysqlctld_test.go b/go/test/endtoend/mysqlctld/mysqlctld_test.go index 328bc563377..beb155830e2 100644 --- a/go/test/endtoend/mysqlctld/mysqlctld_test.go +++ b/go/test/endtoend/mysqlctld/mysqlctld_test.go @@ -57,7 +57,7 @@ func TestMain(m *testing.M) { return 1 } - if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName); err != nil { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName, ""); err != nil { return 1 } diff --git a/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go b/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go index eee244ea6ed..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) }) @@ -341,7 +335,7 @@ func TestSchemaChange(t *testing.T) { t.Run("optimistic wait for migration completion", func(t *testing.T) { 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) { @@ -350,7 +344,7 @@ func TestSchemaChange(t *testing.T) { t.Run("another optimistic wait for migration completion", func(t *testing.T) { 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..33cd9ea4305 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) @@ -441,6 +455,19 @@ func testScheduler(t *testing.T) { }) } + var originalLockWaitTimeout int64 + t.Run("set low lock_wait_timeout", func(t *testing.T) { + rs, err := primaryTablet.VttabletProcess.QueryTablet("select @@lock_wait_timeout as lock_wait_timeout", keyspaceName, false) + require.NoError(t, err) + row := rs.Named().Row() + require.NotNil(t, row) + originalLockWaitTimeout = row.AsInt64("lock_wait_timeout", 0) + require.NotZero(t, originalLockWaitTimeout) + + _, err = primaryTablet.VttabletProcess.QueryTablet("set global lock_wait_timeout=1", keyspaceName, false) + require.NoError(t, err) + }) + // CREATE t.Run("CREATE TABLEs t1, t2", func(t *testing.T) { { // The table does not exist @@ -558,12 +585,27 @@ 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) + }) + + t.Run("low @@lock_wait_timeout", func(t *testing.T) { + defer primaryTablet.VttabletProcess.QueryTablet(fmt.Sprintf("set global lock_wait_timeout=%d", originalLockWaitTimeout), keyspaceName, false) + + t1uuid = testOnlineDDLStatement(t, createParams(trivialAlterT1Statement, ddlStrategy, "vtgate", "", "", false)) // wait + t.Run("trivial t1 migration", func(t *testing.T) { + onlineddl.CheckMigrationStatus(t, &vtParams, shards, t1uuid, schema.OnlineDDLStatusComplete) + checkTable(t, t1Name, true) + }) + }) 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 +628,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 +1091,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 +1143,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 +1164,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 +1279,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") }) }) @@ -1146,6 +1320,7 @@ func testScheduler(t *testing.T) { for _, row := range rs.Named().Rows { message := row["message"].ToString() require.Contains(t, message, "errno 1146") + require.False(t, row["message_timestamp"].IsNull()) } }) @@ -1289,6 +1464,7 @@ func testScheduler(t *testing.T) { for _, row := range rs.Named().Rows { message := row["message"].ToString() require.Contains(t, message, vuuids[2]) // Indicating this migration failed due to vuuids[2] failure + require.False(t, row["message_timestamp"].IsNull()) } } }) @@ -1463,6 +1639,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 +2610,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 f9f203c7cd9..70efe4ec8a4 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 ( @@ -246,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) }) @@ -257,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) }) } }) @@ -395,6 +397,8 @@ func TestSchemaChange(t *testing.T) { assert.GreaterOrEqual(t, lastThrottledTimestamp, startedTimestamp) component := row.AsString("component_throttled", "") assert.Contains(t, []string{throttlerapp.VCopierName.String(), throttlerapp.VPlayerName.String()}, component) + reason := row.AsString("reason_throttled", "") + assert.Contains(t, reason, "is explicitly denied access") // unthrottle onlineddl.UnthrottleAllMigrations(t, &vtParams) 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 d31f92695f1..c82b7f13a0d 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 @@ -65,6 +65,7 @@ const ( testFilterEnvVar = "ONLINEDDL_SUITE_TEST_FILTER" ) +// Use $VREPL_SUITE_TEST_FILTER environment variable to filter tests by name. func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() @@ -137,7 +138,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) { diff --git a/vitess-mixin/e2e/cypress/fixtures/.keep b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/allow_schemadiff_normalization similarity index 100% rename from vitess-mixin/e2e/cypress/fixtures/.keep rename to go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/allow_schemadiff_normalization diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/alter b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/alter new file mode 100644 index 00000000000..b5ec82b1a8b --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/alter @@ -0,0 +1 @@ +MODIFY `t1` varchar(128) CHARACTER SET utf8mb4 NOT NULL, MODIFY `t2` varchar(128) CHARACTER SET latin2 NOT NULL, MODIFY `tutf8` varchar(128) CHARACTER SET latin1 NOT NULL diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/create.sql b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/create.sql new file mode 100644 index 00000000000..79e8fda23ee --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/create.sql @@ -0,0 +1,19 @@ +drop table if exists onlineddl_test; +create table onlineddl_test ( + id int auto_increment, + t1 varchar(128) charset latin1 collate latin1_swedish_ci, + t2 varchar(128) charset latin1 collate latin1_swedish_ci, + tutf8 varchar(128) charset utf8, + tutf8mb4 varchar(128) charset utf8mb4, + tlatin1 varchar(128) charset latin1 collate latin1_swedish_ci, + primary key(id) +) auto_increment=1; + +insert into onlineddl_test values (null, md5(rand()), md5(rand()), md5(rand()), md5(rand()), md5(rand())); +insert into onlineddl_test values (null, 'átesting', 'átesting', 'átesting', 'átesting', 'átesting'); +insert into onlineddl_test values (null, 'testátest', 'testátest', 'testátest', '🍻😀', 'átesting'); +insert into onlineddl_test values (null, 'átesting-binlog', 'átesting-binlog', 'átesting-binlog', 'átesting-binlog', 'átesting-binlog'); +insert into onlineddl_test values (null, 'testátest-binlog', 'testátest-binlog', 'testátest-binlog', '🍻😀', 'átesting-binlog'); +insert into onlineddl_test values (null, 'átesting-bnull', 'átesting-bnull', 'átesting-bnull', null, null); + +drop event if exists onlineddl_test; diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/ignore_versions b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/ignore_versions new file mode 100644 index 00000000000..0790a1e68fd --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/alter-charset-non-utf8-80-vcopier/ignore_versions @@ -0,0 +1 @@ +(5.5|5.6|5.7) diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-different-pk-new-pk-column/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-different-pk-new-pk-column/expect_failure index ae3584915dd..5e227f16a3c 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-different-pk-new-pk-column/expect_failure +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-different-pk-new-pk-column/expect_failure @@ -1 +1 @@ -Found no possible +found no possible diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-drop-pk/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-drop-pk/expect_failure index ae3584915dd..5e227f16a3c 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-drop-pk/expect_failure +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-drop-pk/expect_failure @@ -1 +1 @@ -Found no possible +found no possible diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/create.sql b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/create.sql index abd7fbd4266..3712a673838 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/create.sql +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/create.sql @@ -1,6 +1,6 @@ drop table if exists onlineddl_test; create table onlineddl_test ( - f float, + f float not null, i int not null, ts timestamp default current_timestamp, dt datetime, diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/expect_failure index ae3584915dd..5e227f16a3c 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/expect_failure +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-float-unique-key/expect_failure @@ -1 +1 @@ -Found no possible +found no possible diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-no-unique-key/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-no-unique-key/expect_failure index ae3584915dd..5e227f16a3c 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-no-unique-key/expect_failure +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-no-unique-key/expect_failure @@ -1 +1 @@ -Found no possible +found no possible diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/alter b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/alter new file mode 100644 index 00000000000..0d2477f5801 --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/alter @@ -0,0 +1 @@ +add column v varchar(32) diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/create.sql b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/create.sql new file mode 100644 index 00000000000..71f112d33c2 --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/create.sql @@ -0,0 +1,11 @@ +drop table if exists onlineddl_test; +create table onlineddl_test ( + id int, + i int not null, + ts timestamp default current_timestamp, + dt datetime, + key i_idx(i), + unique key id_uidx(id) +) auto_increment=1; + +drop event if exists onlineddl_test; diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/expect_failure new file mode 100644 index 00000000000..5e227f16a3c --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-nullable-unique-key/expect_failure @@ -0,0 +1 @@ +found no possible diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/allow_schemadiff_normalization b/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/allow_schemadiff_normalization new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/create.sql b/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/create.sql new file mode 100644 index 00000000000..c0313e62c8d --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/create.sql @@ -0,0 +1,30 @@ +drop table if exists onlineddl_test; +create table onlineddl_test ( + id varchar(128) charset latin1 collate latin1_swedish_ci, + t1 varchar(128) charset latin1 collate latin1_swedish_ci, + t2 varchar(128) charset latin1 collate latin1_swedish_ci, + tutf8 varchar(128) charset utf8, + tutf8mb4 varchar(128) charset utf8mb4, + tlatin1 varchar(128) charset latin1 collate latin1_swedish_ci, + primary key(id) +) auto_increment=1; + +insert into onlineddl_test values (concat('átesting-', md5(rand())), md5(rand()), md5(rand()), md5(rand()), md5(rand()), md5(rand())); +insert into onlineddl_test values (concat('átesting-', md5(rand())), 'átesting', 'átesting', 'átesting', 'átesting', 'átesting'); +insert into onlineddl_test values (concat('átesting-', md5(rand())), 'testátest', 'testátest', 'testátest', '🍻😀', 'átesting'); + +drop event if exists onlineddl_test; +delimiter ;; +create event onlineddl_test + on schedule every 1 second + starts current_timestamp + ends current_timestamp + interval 60 second + on completion not preserve + enable + do +begin + insert into onlineddl_test values (concat('átesting-', md5(rand())), md5(rand()), md5(rand()), md5(rand()), md5(rand()), md5(rand())); + insert into onlineddl_test values (concat('átesting-', md5(rand())), 'átesting-binlog', 'átesting-binlog', 'átesting-binlog', 'átesting-binlog', 'átesting-binlog'); + insert into onlineddl_test values (concat('átesting-', md5(rand())), 'testátest-binlog', 'testátest-binlog', 'testátest-binlog', '🍻😀', 'átesting-binlog'); + insert into onlineddl_test values (concat('átesting-', md5(rand())), 'átesting-bnull', 'átesting-bnull', 'átesting-bnull', null, null); +end ;; diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/ignore_versions b/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/ignore_versions new file mode 100644 index 00000000000..0790a1e68fd --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/non-utf8-charset-pk/ignore_versions @@ -0,0 +1 @@ +(5.5|5.6|5.7) 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/reparent/plannedreparent/reparent_test.go b/go/test/endtoend/reparent/plannedreparent/reparent_test.go index ae9bd6bbc9b..5986056924e 100644 --- a/go/test/endtoend/reparent/plannedreparent/reparent_test.go +++ b/go/test/endtoend/reparent/plannedreparent/reparent_test.go @@ -125,14 +125,8 @@ func TestReparentReplicaOffline(t *testing.T) { require.Error(t, err) // Assert that PRS failed - if clusterInstance.VtctlMajorVersion <= 17 { - assert.True(t, utils.SetReplicationSourceFailed(tablets[3], out)) - utils.CheckPrimaryTablet(t, clusterInstance, tablets[1]) - } else { - assert.Contains(t, out, "rpc error: code = DeadlineExceeded desc") - utils.CheckPrimaryTablet(t, clusterInstance, tablets[0]) - } - + assert.Contains(t, out, "rpc error: code = DeadlineExceeded desc") + utils.CheckPrimaryTablet(t, clusterInstance, tablets[0]) } func TestReparentAvoid(t *testing.T) { @@ -155,20 +149,32 @@ func TestReparentAvoid(t *testing.T) { require.NoError(t, err) utils.ValidateTopology(t, clusterInstance, false) - // tablets[1 is in the same cell and tablets[3] is in a different cell, so we must land on tablets[1 + // tablets[1] is in the same cell and tablets[3] is in a different cell, so we must land on tablets[1] utils.CheckPrimaryTablet(t, clusterInstance, tablets[1]) // If we kill the tablet in the same cell as primary then reparent --avoid_tablet will fail. utils.StopTablet(t, tablets[0], true) out, err := utils.PrsAvoid(t, clusterInstance, tablets[1]) require.Error(t, err) - if clusterInstance.VtctlMajorVersion <= 17 { - assert.Contains(t, out, "cannot find a tablet to reparent to in the same cell as the current primary") - } else { - assert.Contains(t, out, "rpc error: code = DeadlineExceeded desc = latest balancer error") - } + assert.Contains(t, out, "rpc error: code = DeadlineExceeded desc = latest balancer error") utils.ValidateTopology(t, clusterInstance, false) utils.CheckPrimaryTablet(t, clusterInstance, tablets[1]) + + t.Run("Allow cross cell promotion", func(t *testing.T) { + if clusterInstance.VtctlMajorVersion <= 20 { + t.Skip("Allow Cross Cell Promotion was added in v21") + } + utils.DeleteTablet(t, clusterInstance, tablets[0]) + // Perform a graceful reparent operation and verify it fails because we have no replicas in the same cell as the primary. + out, err = utils.PrsAvoid(t, clusterInstance, tablets[1]) + require.Error(t, err) + assert.Contains(t, out, "is not in the same cell as the previous primary") + + // If we run PRS with allow cross cell promotion then it should succeed and should promote the replica in another cell. + _, err = utils.PrsAvoid(t, clusterInstance, tablets[1], "--allow-cross-cell-promotion") + require.NoError(t, err) + utils.CheckPrimaryTablet(t, clusterInstance, tablets[3]) + }) } func TestReparentFromOutside(t *testing.T) { @@ -199,13 +205,13 @@ func TestReparentFromOutsideWithNoPrimary(t *testing.T) { } func reparentFromOutside(t *testing.T, clusterInstance *cluster.LocalProcessCluster, downPrimary bool) { - //This test will start a primary and 3 replicas. - //Then: - //- one replica will be the new primary - //- one replica will be reparented to that new primary - //- one replica will be busted and dead in the water and we'll call TabletExternallyReparented. - //Args: - //downPrimary: kills the old primary first + // This test will start a primary and 3 replicas. + // Then: + // - one replica will be the new primary + // - one replica will be reparented to that new primary + // - one replica will be busted and dead in the water and we'll call TabletExternallyReparented. + // Args: + // downPrimary: kills the old primary first ctx := context.Background() tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets @@ -218,7 +224,7 @@ func reparentFromOutside(t *testing.T, clusterInstance *cluster.LocalProcessClus demoteCommands := []string{"SET GLOBAL read_only = ON", "FLUSH TABLES WITH READ LOCK", "UNLOCK TABLES"} utils.RunSQLs(ctx, t, demoteCommands, tablets[0]) - //Get the position of the old primary and wait for the new one to catch up. + // Get the position of the old primary and wait for the new one to catch up. err := utils.WaitForReplicationPosition(t, tablets[0], tablets[1]) require.NoError(t, err) } @@ -297,17 +303,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 @@ -457,14 +460,7 @@ func TestFullStatus(t *testing.T) { assert.Contains(t, primaryStatus.PrimaryStatus.String(), "vt-0000000101-bin") assert.Equal(t, primaryStatus.GtidPurged, "MySQL56/") assert.False(t, primaryStatus.ReadOnly) - vtTabletVersion, err := cluster.GetMajorVersion("vttablet") - require.NoError(t, err) - vtcltlVersion, err := cluster.GetMajorVersion("vtctl") - require.NoError(t, err) - // For all version at or above v17.0.0, each replica will start in super_read_only mode. - if vtTabletVersion >= 17 && vtcltlVersion >= 17 { - assert.False(t, primaryStatus.SuperReadOnly) - } + assert.False(t, primaryStatus.SuperReadOnly) assert.True(t, primaryStatus.SemiSyncPrimaryEnabled) assert.True(t, primaryStatus.SemiSyncReplicaEnabled) assert.True(t, primaryStatus.SemiSyncPrimaryStatus) @@ -518,10 +514,7 @@ func TestFullStatus(t *testing.T) { assert.Contains(t, replicaStatus.PrimaryStatus.String(), "vt-0000000102-bin") assert.Equal(t, replicaStatus.GtidPurged, "MySQL56/") assert.True(t, replicaStatus.ReadOnly) - // For all version at or above v17.0.0, each replica will start in super_read_only mode. - if vtTabletVersion >= 17 && vtcltlVersion >= 17 { - assert.True(t, replicaStatus.SuperReadOnly) - } + assert.True(t, replicaStatus.SuperReadOnly) assert.False(t, replicaStatus.SemiSyncPrimaryEnabled) assert.True(t, replicaStatus.SemiSyncReplicaEnabled) assert.False(t, replicaStatus.SemiSyncPrimaryStatus) 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/reparent/utils/utils.go b/go/test/endtoend/reparent/utils/utils.go index 5038352d721..0d3eddc0464 100644 --- a/go/test/endtoend/reparent/utils/utils.go +++ b/go/test/endtoend/reparent/utils/utils.go @@ -293,17 +293,17 @@ func execute(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { // region ers, prs // Prs runs PRS -func Prs(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet) (string, error) { - return PrsWithTimeout(t, clusterInstance, tab, false, "", "") +func Prs(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet, extraArgs ...string) (string, error) { + return PrsWithTimeout(t, clusterInstance, tab, false, "", "", extraArgs...) } // PrsAvoid runs PRS -func PrsAvoid(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet) (string, error) { - return PrsWithTimeout(t, clusterInstance, tab, true, "", "") +func PrsAvoid(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet, extraArgs ...string) (string, error) { + return PrsWithTimeout(t, clusterInstance, tab, true, "", "", extraArgs...) } // PrsWithTimeout runs PRS -func PrsWithTimeout(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet, avoid bool, actionTimeout, waitTimeout string) (string, error) { +func PrsWithTimeout(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet, avoid bool, actionTimeout, waitTimeout string, extraArgs ...string) (string, error) { args := []string{ "PlannedReparentShard", fmt.Sprintf("%s/%s", KeyspaceName, ShardName)} @@ -319,6 +319,7 @@ func PrsWithTimeout(t *testing.T, clusterInstance *cluster.LocalProcessCluster, args = append(args, "--new-primary") } args = append(args, tab.Alias) + args = append(args, extraArgs...) out, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput(args...) return out, err } 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/sharded/sharded_keyspace_test.go b/go/test/endtoend/sharded/sharded_keyspace_test.go index f311404ad7e..192355fa6ef 100644 --- a/go/test/endtoend/sharded/sharded_keyspace_test.go +++ b/go/test/endtoend/sharded/sharded_keyspace_test.go @@ -84,7 +84,7 @@ func TestMain(m *testing.M) { if err := clusterInstance.StartTopo(); err != nil { return 1, err } - if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName); err != nil { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName, sidecar.DefaultName, ""); err != nil { return 1, err } diff --git a/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go b/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go index c8251846fe6..08cea643940 100644 --- a/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go +++ b/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go @@ -26,17 +26,21 @@ 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" + 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 ( @@ -47,7 +51,7 @@ const ( onDemandHeartbeatDuration = 5 * time.Second throttlerEnabledTimeout = 60 * time.Second useDefaultQuery = "" - testAppName = "test" + testAppName = throttlerapp.TestingName ) var ( @@ -88,8 +92,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 +175,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 { @@ -192,44 +204,37 @@ func throttleStatus(t *testing.T, tablet *cluster.Vttablet) string { return string(b) } -func warmUpHeartbeat(t *testing.T) (respStatus int) { +func warmUpHeartbeat(t *testing.T) tabletmanagerdatapb.CheckThrottlerResponseCode { // because we run with -heartbeat_on_demand_duration=5s, the heartbeat is "cold" right now. // 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 throttle.ResponseCodeFromStatus(resp.Check.ResponseCode, 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 tabletmanagerdatapb.CheckThrottlerResponseCode) 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 == resp.Check.ResponseCode { // 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: } } } @@ -256,81 +261,97 @@ func TestInitialThrottler(t *testing.T) { defer cluster.PanicHandler(t) t.Run("validating OK response from disabled throttler", func(t *testing.T) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) 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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) }) 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) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) 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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) }) 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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) 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) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) }) t.Run("requesting heartbeats", func(t *testing.T) { respStatus := warmUpHeartbeat(t) - assert.NotEqual(t, http.StatusOK, respStatus) + assert.NotEqual(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, respStatus) }) t.Run("validating OK response from throttler with low threshold, heartbeats running", func(t *testing.T) { time.Sleep(1 * time.Second) 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()) + t.Logf("throttler primary status: %+v", throttleStatus(t, primaryTablet)) + t.Logf("throttler replica status: %+v", throttleStatus(t, replicaTablet)) + } + if !assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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 +365,18 @@ 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()) + t.Logf("throttler primary status: %+v", throttleStatus(t, primaryTablet)) + t.Logf("throttler replica status: %+v", throttleStatus(t, replicaTablet)) + } + if !assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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()) @@ -355,7 +386,7 @@ func TestInitialThrottler(t *testing.T) { }) t.Run("validating pushback response from throttler on low 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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) }) } @@ -373,6 +404,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 +426,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) }) } @@ -411,26 +439,26 @@ func TestThrottlerAfterMetricsCollected(t *testing.T) { // By this time metrics will have been collected. We expect no lag, and something like: // {"StatusCode":200,"Value":0.282278,"Threshold":1,"Message":""} t.Run("validating throttler OK", func(t *testing.T) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) t.Run("validating throttled apps", func(t *testing.T) { resp, body, err := throttledApps(primaryTablet) 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "Unexpected response from throttler: %+v", resp) }) } @@ -457,15 +485,22 @@ 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, resp.Check.ResponseCode, "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)) + } + if !assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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,27 +508,75 @@ 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, resp.Check.ResponseCode, "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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED) + }) + 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.StatusTooManyRequests) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) }) t.Run("starting replication", func(t *testing.T) { @@ -501,20 +584,20 @@ func TestLag(t *testing.T) { assert.NoError(t, err) }) t.Run("expecting replication to catch up and throttler check to return OK", func(t *testing.T) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "Unexpected response from throttler: %+v", resp) }) } @@ -526,13 +609,13 @@ func TestNoReplicas(t *testing.T) { // This makes no REPLICA servers available. We expect something like: // {"StatusCode":200,"Value":0,"Threshold":1,"Message":""} - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) t.Run("restoring to REPLICA", func(t *testing.T) { err := clusterInstance.VtctldClientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "REPLICA") assert.NoError(t, err) - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) }) } @@ -540,7 +623,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 +632,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 +641,8 @@ 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "Unexpected response from throttler: %+v", resp) }) t.Run("test threads running", func(t *testing.T) { sleepDuration := 20 * time.Second @@ -580,24 +664,24 @@ func TestCustomQuery(t *testing.T) { // Now we should be reporting ~ customThreshold+1 threads_running, and we should // hit the threshold. For example: // {"StatusCode":429,"Value":6,"Threshold":5,"Message":"Threshold exceeded"} - waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) { 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, resp.Check.ResponseCode, "Unexpected response from throttler: %+v", resp) } }) t.Run("wait for queries to terminate", func(t *testing.T) { wg.Wait() }) t.Run("restored below threshold", func(t *testing.T) { - waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) { 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "Unexpected response from throttler: %+v", resp) } }) }) @@ -608,22 +692,170 @@ 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, resp.Check.ResponseCode, "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) + waitForThrottleCheckStatus(t, primaryTablet, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) +} + +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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) +} + +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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_OK) { + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) + }) + 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, tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED) + }) }) } 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 88% rename from go/test/endtoend/vtgate/transaction/twopc/main_test.go rename to go/test/endtoend/transaction/twopc/main_test.go index 102235d672a..9a46562d1c7 100644 --- a/go/test/endtoend/vtgate/transaction/twopc/main_test.go +++ b/go/test/endtoend/transaction/twopc/main_test.go @@ -33,7 +33,7 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/endtoend/cluster" - "vitess.io/vitess/go/test/endtoend/utils" + "vitess.io/vitess/go/test/endtoend/transaction/twopc/utils" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -75,22 +75,23 @@ 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", ) // Start keyspace keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: SchemaSQL, - VSchema: VSchema, - SidecarDBName: sidecarDBName, + Name: keyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + SidecarDBName: sidecarDBName, + DurabilityPolicy: "semi_sync", } - if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, false); err != nil { + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-40", "40-80", "80-"}, 2, false); err != nil { return 1 } @@ -110,23 +111,20 @@ func start(t *testing.T) (*mysql.Conn, func()) { ctx := context.Background() 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() + cleanup(t) return conn, func() { - deleteAll() conn.Close() - cluster.PanicHandler(t) + cleanup(t) } } +func cleanup(t *testing.T) { + cluster.PanicHandler(t) + utils.ClearOutTable(t, vtParams, "twopc_user") + utils.ClearOutTable(t, vtParams, "twopc_t1") +} + type extractInterestingValues func(dtidMap map[string]string, vals []sqltypes.Value) []sqltypes.Value var tables = map[string]extractInterestingValues{ @@ -172,7 +170,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 +211,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 +233,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/transaction/twopc/schema.sql b/go/test/endtoend/transaction/twopc/schema.sql new file mode 100644 index 00000000000..7c289a03c2a --- /dev/null +++ b/go/test/endtoend/transaction/twopc/schema.sql @@ -0,0 +1,21 @@ +create table twopc_user +( + id bigint, + name varchar(64), + primary key (id) +) Engine=InnoDB; + +create table twopc_music +( + id varchar(64), + user_id bigint, + title varchar(64), + primary key (id) +) Engine=InnoDB; + +create table twopc_t1 +( + id bigint, + col bigint, + primary key (id) +) Engine=InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/transaction/twopc/stress/fuzzer_test.go b/go/test/endtoend/transaction/twopc/stress/fuzzer_test.go new file mode 100644 index 00000000000..932fcae1217 --- /dev/null +++ b/go/test/endtoend/transaction/twopc/stress/fuzzer_test.go @@ -0,0 +1,471 @@ +/* +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 stress + +import ( + "context" + "fmt" + "os" + "path" + "strconv" + "strings" + "sync" + "sync/atomic" + "syscall" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/syscallutil" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/schema" +) + +var ( + // updateRowBaseVals is the base row values that we use to ensure 1 update on each shard with the same increment. + updateRowBaseVals = [3]int{ + 4, // 4 maps to 0x20 and ends up in the first shard (-40) + 6, // 6 maps to 0x60 and ends up in the second shard (40-80) + 9, // 9 maps to 0x90 and ends up in the third shard (80-) + // We can increment all of these values by multiples of 16 and they'll always be in the same shard. + } + + insertIntoFuzzUpdate = "INSERT INTO twopc_fuzzer_update (id, col) VALUES (%d, %d)" + updateFuzzUpdate = "UPDATE twopc_fuzzer_update SET col = col + %d WHERE id = %d" + insertIntoFuzzInsert = "INSERT INTO twopc_fuzzer_insert (id, updateSet, threadId) VALUES (%d, %d, %d)" + selectFromFuzzUpdate = "SELECT col FROM twopc_fuzzer_update WHERE id = %d" + selectIdFromFuzzInsert = "SELECT threadId FROM twopc_fuzzer_insert WHERE updateSet = %d AND id = %d ORDER BY col" +) + +// TestTwoPCFuzzTest tests 2PC transactions in a fuzzer environment. +// The testing strategy involves running many transactions and checking that they all must be atomic. +// To this end, we have a very unique strategy. We have two sharded tables `twopc_fuzzer_update`, and `twopc_fuzzer_insert` with the following columns. +// - id: This is the sharding column. We use reverse_bits as the sharding vindex because it is easy to reason about where a row will end up. +// - col in `twopc_fuzzer_insert`: An auto-increment column. +// - col in `twopc_fuzzer_update`: This is a bigint value that we will use to increment on updates. +// - updateSet: This column will store which update set the inserts where done for. +// - threadId: It stores the thread id of the fuzzer thread that inserted the row. +// +// The testing strategy is as follows - +// Every transaction will do 2 things - +// - One, it will increment the `col` on 1 row in each of the shards of the `twopc_fuzzer_update` table. +// To do this, we have sets of rows that each map to one shard. We prepopulate this before the test starts. +// These sets are stored in the fuzzer in updateRowsVals. +// - Two, it will insert one row in each of the shards of the `twopc_fuzzer_insert` table and it will also store the update set that it updated the rows off. +// +// We can check that a transaction was atomic by basically checking that the `col` value for all the rows that were updated together should match. +// If any transaction was partially successful, then it would have missed an increment on one of the rows. +// Moreover, the threadIDs of rows for a given update set in the 3 shards should be the same to ensure that conflicting transactions got committed in the same exact order. +func TestTwoPCFuzzTest(t *testing.T) { + testcases := []struct { + name string + threads int + updateSets int + timeForTesting time.Duration + clusterDisruptions []func(t *testing.T) + disruptionProbability []int + }{ + { + name: "Single Thread - Single Set", + threads: 1, + updateSets: 1, + timeForTesting: 5 * time.Second, + }, + { + name: "Multiple Threads - Single Set", + threads: 2, + updateSets: 1, + timeForTesting: 5 * time.Second, + }, + { + name: "Multiple Threads - Multiple Set", + threads: 15, + updateSets: 15, + timeForTesting: 5 * time.Second, + }, + { + name: "Multiple Threads - Multiple Set - PRS, ERS, and MySQL & Vttablet restart, OnlineDDL disruptions", + threads: 15, + updateSets: 15, + timeForTesting: 5 * time.Second, + clusterDisruptions: []func(t *testing.T){prs, ers, mysqlRestarts, vttabletRestarts, onlineDDLFuzzer}, + disruptionProbability: []int{5, 5, 5, 5, 5}, + }, + } + + for _, tt := range testcases { + t.Run(tt.name, func(t *testing.T) { + conn, closer := start(t) + defer closer() + fz := newFuzzer(t, tt.threads, tt.updateSets, tt.clusterDisruptions, tt.disruptionProbability) + + fz.initialize(t, conn) + conn.Close() + // Start the fuzzer. + fz.start(t) + + // Wait for the timeForTesting so that the threads continue to run. + time.Sleep(tt.timeForTesting) + + // Signal the fuzzer to stop. + fz.stop() + + // Wait for all transactions to be resolved. + waitForResults(t, fmt.Sprintf(`show unresolved transactions for %v`, keyspaceName), "[]", 30*time.Second) + // Verify that all the transactions run were actually atomic and no data issues have occurred. + fz.verifyTransactionsWereAtomic(t) + + log.Errorf("Verification complete. All good!") + }) + } +} + +// verifyTransactionsWereAtomic verifies that the invariants of test are held. +// It checks the heuristics to ensure that the transactions run were atomic. +func (fz *fuzzer) verifyTransactionsWereAtomic(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + for updateSetIdx, updateSet := range fz.updateRowsVals { + // All the three values of the update set must be equal. + shard1Val := getColValueForIdFromFuzzUpdate(t, conn, updateSet[0]) + shard2Val := getColValueForIdFromFuzzUpdate(t, conn, updateSet[1]) + shard3Val := getColValueForIdFromFuzzUpdate(t, conn, updateSet[2]) + require.EqualValues(t, shard1Val, shard2Val) + require.EqualValues(t, shard3Val, shard2Val) + + // Next we get the IDs from all the three shards for the given update set index. + shard1IDs := getThreadIDsForUpdateSetFromFuzzInsert(t, conn, updateSetIdx, 1) + shard2IDs := getThreadIDsForUpdateSetFromFuzzInsert(t, conn, updateSetIdx, 2) + shard3IDs := getThreadIDsForUpdateSetFromFuzzInsert(t, conn, updateSetIdx, 3) + require.EqualValues(t, shard1IDs, shard2IDs) + require.EqualValues(t, shard3IDs, shard2IDs) + } +} + +// getColValueForIdFromFuzzUpdate gets the col column value for the given id in the twopc_fuzzer_update table. +func getColValueForIdFromFuzzUpdate(t *testing.T, conn *mysql.Conn, id int) uint64 { + res, err := conn.ExecuteFetch(fmt.Sprintf(selectFromFuzzUpdate, id), 1, false) + require.NoError(t, err) + require.Len(t, res.Rows, 1) + require.Len(t, res.Rows[0], 1) + val, err := res.Rows[0][0].ToUint64() + require.NoError(t, err) + return val +} + +// getThreadIDsForUpdateSetFromFuzzInsert gets the thread IDs for the given update set ordered by the col column from the twopc_fuzzer_insert table. +func getThreadIDsForUpdateSetFromFuzzInsert(t *testing.T, conn *mysql.Conn, updateSet int, shard int) []int { + // We will select all the rows for the given update set for the given shard. To get all the rows for the given shard, + // we can use the id column for filtering, since we know that the first shard will have all the values of id as 4, second shard as 6 and the last one as 9. + res, err := conn.ExecuteFetch(fmt.Sprintf(selectIdFromFuzzInsert, updateSet, updateRowBaseVals[shard-1]), 10000, false) + require.NoError(t, err) + var ids []int + for _, row := range res.Rows { + require.Len(t, row, 1) + threadId, err := row[0].ToInt() + require.NoError(t, err) + ids = append(ids, threadId) + } + return ids +} + +// fuzzer runs threads that runs queries against the databases. +// It has parameters that define the way the queries are constructed. +type fuzzer struct { + threads int + updateSets int + t *testing.T + + // shouldStop is an internal state variable, that tells the fuzzer + // whether it should stop or not. + shouldStop atomic.Bool + // wg is an internal state variable, that used to know whether the fuzzer threads are running or not. + wg sync.WaitGroup + // updateRowVals are the rows that we use to ensure 1 update on each shard with the same increment. + updateRowsVals [][]int + // clusterDisruptions are the cluster level disruptions that can happen in a running cluster. + clusterDisruptions []func(t *testing.T) + // disruptionProbability is the chance for the disruption to happen. We check this every 100 milliseconds. + disruptionProbability []int +} + +// newFuzzer creates a new fuzzer struct. +func newFuzzer(t *testing.T, threads int, updateSets int, clusterDisruptions []func(t *testing.T), disruptionProbability []int) *fuzzer { + fz := &fuzzer{ + t: t, + threads: threads, + updateSets: updateSets, + wg: sync.WaitGroup{}, + clusterDisruptions: clusterDisruptions, + disruptionProbability: disruptionProbability, + } + // Initially the fuzzer thread is stopped. + fz.shouldStop.Store(true) + return fz +} + +// stop stops the fuzzer and waits for it to finish execution. +func (fz *fuzzer) stop() { + // Mark the thread to be stopped. + fz.shouldStop.Store(true) + // Wait for the fuzzer thread to stop. + fz.wg.Wait() +} + +// start starts running the fuzzer. +func (fz *fuzzer) start(t *testing.T) { + // We mark the fuzzer thread to be running now. + fz.shouldStop.Store(false) + // fz.threads is the count of fuzzer threads, and one disruption thread. + fz.wg.Add(fz.threads + 1) + for i := 0; i < fz.threads; i++ { + go func() { + fz.runFuzzerThread(t, i) + }() + } + go func() { + fz.runClusterDisruptionThread(t) + }() +} + +// runFuzzerThread is used to run a thread of the fuzzer. +func (fz *fuzzer) runFuzzerThread(t *testing.T, threadId int) { + // Whenever we finish running this thread, we should mark the thread has stopped. + defer func() { + fz.wg.Done() + }() + + for { + // If fuzzer thread is marked to be stopped, then we should exit this go routine. + if fz.shouldStop.Load() == true { + return + } + // Run an atomic transaction + fz.generateAndExecuteTransaction(threadId) + } + +} + +// initialize initializes all the variables that will be needed for running the fuzzer. +// It also creates the rows for the `twopc_fuzzer_update` table. +func (fz *fuzzer) initialize(t *testing.T, conn *mysql.Conn) { + for i := 0; i < fz.updateSets; i++ { + fz.updateRowsVals = append(fz.updateRowsVals, []int{ + updateRowBaseVals[0] + i*16, + updateRowBaseVals[1] + i*16, + updateRowBaseVals[2] + i*16, + }) + } + + for _, updateSet := range fz.updateRowsVals { + for _, id := range updateSet { + _, err := conn.ExecuteFetch(fmt.Sprintf(insertIntoFuzzUpdate, id, 0), 0, false) + require.NoError(t, err) + } + } +} + +// generateAndExecuteTransaction generates the queries of the transaction and then executes them. +func (fz *fuzzer) generateAndExecuteTransaction(threadId int) { + // Create a connection to the vtgate to run transactions. + conn, err := mysql.Connect(context.Background(), &vtParams) + if err != nil { + return + } + defer conn.Close() + // randomly generate an update set to use and the value to increment it by. + updateSetVal := rand.Intn(fz.updateSets) + incrementVal := rand.Int31() + // We have to generate the update queries first. We can run the inserts only after the update queries. + // Otherwise, our check to see that the ids in the twopc_fuzzer_insert table in all the shards are the exact same + // for each update set ordered by the auto increment column will not be true. + // That assertion depends on all the transactions running updates first to ensure that for any given update set, + // no two transactions are running the insert queries. + queries := []string{"begin"} + queries = append(queries, fz.generateUpdateQueries(updateSetVal, incrementVal)...) + queries = append(queries, fz.generateInsertQueries(updateSetVal, threadId)...) + finalCommand := "commit" + for _, query := range queries { + _, err := conn.ExecuteFetch(query, 0, false) + // If any command fails because of deadlocks or timeout or whatever, then we need to rollback the transaction. + if err != nil { + finalCommand = "rollback" + break + } + } + _, _ = conn.ExecuteFetch(finalCommand, 0, false) +} + +// generateUpdateQueries generates the queries to run updates on the twopc_fuzzer_update table. +// It takes the update set index and the value to increment the set by. +func (fz *fuzzer) generateUpdateQueries(updateSet int, incrementVal int32) []string { + var queries []string + for _, id := range fz.updateRowsVals[updateSet] { + queries = append(queries, fmt.Sprintf(updateFuzzUpdate, incrementVal, id)) + } + rand.Shuffle(len(queries), func(i, j int) { + queries[i], queries[j] = queries[j], queries[i] + }) + return queries +} + +// generateInsertQueries generates the queries to run inserts on the twopc_fuzzer_insert table. +// It takes the update set index and the thread id that is generating these inserts. +func (fz *fuzzer) generateInsertQueries(updateSet int, threadId int) []string { + var queries []string + for _, baseVal := range updateRowBaseVals { + // In the twopc_fuzzer_insert table we are going to be inserting the following values - + // - id: We use the updateRowBaseVals to ensure that the 3 insertions happen on 3 different shards. + // This also allows us to read rows any of the shards without shard targeting by just filtering by this column. + // - updateSet: The update set index that these insertions correspond too. + // - threadId: The thread ID of the fuzzer thread that is running the transaction. + queries = append(queries, fmt.Sprintf(insertIntoFuzzInsert, baseVal, updateSet, threadId)) + } + rand.Shuffle(len(queries), func(i, j int) { + queries[i], queries[j] = queries[j], queries[i] + }) + return queries +} + +// runClusterDisruptionThread runs the cluster level disruptions in a separate thread. +func (fz *fuzzer) runClusterDisruptionThread(t *testing.T) { + // Whenever we finish running this thread, we should mark the thread has stopped. + defer func() { + fz.wg.Done() + }() + + for { + // If disruption thread is marked to be stopped, then we should exit this go routine. + if fz.shouldStop.Load() == true { + return + } + // Run a potential disruption + fz.runClusterDisruption(t) + time.Sleep(100 * time.Millisecond) + } + +} + +// runClusterDisruption tries to run a single cluster disruption. +func (fz *fuzzer) runClusterDisruption(t *testing.T) { + for idx, prob := range fz.disruptionProbability { + if rand.Intn(100) < prob { + fz.clusterDisruptions[idx](fz.t) + return + } + } +} + +/* +Cluster Level Disruptions for the fuzzer +*/ + +func prs(t *testing.T) { + shards := clusterInstance.Keyspaces[0].Shards + shard := shards[rand.Intn(len(shards))] + vttablets := shard.Vttablets + newPrimary := vttablets[rand.Intn(len(vttablets))] + log.Errorf("Running PRS for - %v/%v with new primary - %v", keyspaceName, shard.Name, newPrimary.Alias) + err := clusterInstance.VtctldClientProcess.PlannedReparentShard(keyspaceName, shard.Name, newPrimary.Alias) + if err != nil { + log.Errorf("error running PRS - %v", err) + } +} + +func ers(t *testing.T) { + shards := clusterInstance.Keyspaces[0].Shards + shard := shards[rand.Intn(len(shards))] + vttablets := shard.Vttablets + newPrimary := vttablets[rand.Intn(len(vttablets))] + log.Errorf("Running ERS for - %v/%v with new primary - %v", keyspaceName, shard.Name, newPrimary.Alias) + _, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("EmergencyReparentShard", fmt.Sprintf("%s/%s", keyspaceName, shard.Name), "--new-primary", newPrimary.Alias) + if err != nil { + log.Errorf("error running ERS - %v", err) + } +} + +func vttabletRestarts(t *testing.T) { + shards := clusterInstance.Keyspaces[0].Shards + shard := shards[rand.Intn(len(shards))] + vttablets := shard.Vttablets + tablet := vttablets[rand.Intn(len(vttablets))] + log.Errorf("Restarting vttablet for - %v/%v - %v", keyspaceName, shard.Name, tablet.Alias) + err := tablet.VttabletProcess.TearDown() + if err != nil { + log.Errorf("error stopping vttablet - %v", err) + return + } + tablet.VttabletProcess.ServingStatus = "SERVING" + for { + err = tablet.VttabletProcess.Setup() + if err == nil { + return + } + // Sometimes vttablets fail to connect to the topo server due to a minor blip there. + // We don't want to fail the test, so we retry setting up the vttablet. + log.Errorf("error restarting vttablet - %v", err) + time.Sleep(1 * time.Second) + } +} + +var orderedDDLFuzzer = []string{ + "alter table twopc_fuzzer_insert add column extra_col1 varchar(20)", + "alter table twopc_fuzzer_insert add column extra_col2 varchar(20)", + "alter table twopc_fuzzer_insert drop column extra_col1", + "alter table twopc_fuzzer_insert drop column extra_col2", +} + +// onlineDDLFuzzer runs an online DDL statement while ignoring any errors for the fuzzer. +func onlineDDLFuzzer(t *testing.T) { + output, err := clusterInstance.VtctldClientProcess.ApplySchemaWithOutput(keyspaceName, orderedDDLFuzzer[count%len(orderedDDLFuzzer)], cluster.ApplySchemaParams{ + DDLStrategy: "vitess --force-cut-over-after=1ms", + }) + count++ + if err != nil { + return + } + fmt.Println("Running online DDL with uuid: ", output) + WaitForMigrationStatus(t, &vtParams, clusterInstance.Keyspaces[0].Shards, strings.TrimSpace(output), 2*time.Minute, schema.OnlineDDLStatusComplete, schema.OnlineDDLStatusFailed) +} + +func mysqlRestarts(t *testing.T) { + shards := clusterInstance.Keyspaces[0].Shards + shard := shards[rand.Intn(len(shards))] + vttablets := shard.Vttablets + tablet := vttablets[rand.Intn(len(vttablets))] + log.Errorf("Restarting MySQL for - %v/%v tablet - %v", keyspaceName, shard.Name, tablet.Alias) + pidFile := path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/mysql.pid", tablet.TabletUID)) + pidBytes, err := os.ReadFile(pidFile) + if err != nil { + // We can't read the file which means the PID file does not exist + // The server must have stopped + return + } + pid, err := strconv.Atoi(strings.TrimSpace(string(pidBytes))) + if err != nil { + log.Errorf("Error in conversion to integer: %v", err) + return + } + err = syscallutil.Kill(pid, syscall.SIGKILL) + if err != nil { + log.Errorf("Error in killing process: %v", err) + } +} diff --git a/go/test/endtoend/transaction/twopc/stress/main_test.go b/go/test/endtoend/transaction/twopc/stress/main_test.go new file mode 100644 index 00000000000..ef8e454be15 --- /dev/null +++ b/go/test/endtoend/transaction/twopc/stress/main_test.go @@ -0,0 +1,119 @@ +/* +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 stress + +import ( + "context" + _ "embed" + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/transaction/twopc/utils" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + vtgateGrpcAddress string + keyspaceName = "ks" + cell = "zone1" + hostname = "localhost" + sidecarDBName = "vt_ks" + + //go:embed schema.sql + SchemaSQL string + + //go:embed vschema.json + VSchema string +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Reserve vtGate port in order to pass it to vtTablet + clusterInstance.VtgateGrpcPort = clusterInstance.GetAndReservePort() + + // 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_abandon_age", "1", + "--migration_check_interval", "2s", + ) + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + SidecarDBName: sidecarDBName, + DurabilityPolicy: "semi_sync", + } + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-40", "40-80", "80-"}, 2, false); err != nil { + return 1 + } + + // Start Vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + vtParams = clusterInstance.GetVTParams(keyspaceName) + vtgateGrpcAddress = fmt.Sprintf("%s:%d", clusterInstance.Hostname, clusterInstance.VtgateGrpcPort) + + return m.Run() + }() + os.Exit(exitcode) +} + +func start(t *testing.T) (*mysql.Conn, func()) { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + cleanup(t) + + return conn, func() { + conn.Close() + cleanup(t) + } +} + +func cleanup(t *testing.T) { + cluster.PanicHandler(t) + + utils.ClearOutTable(t, vtParams, "twopc_fuzzer_insert") + utils.ClearOutTable(t, vtParams, "twopc_fuzzer_update") + utils.ClearOutTable(t, vtParams, "twopc_t1") +} diff --git a/go/test/endtoend/transaction/twopc/stress/schema.sql b/go/test/endtoend/transaction/twopc/stress/schema.sql new file mode 100644 index 00000000000..5173166bfd4 --- /dev/null +++ b/go/test/endtoend/transaction/twopc/stress/schema.sql @@ -0,0 +1,20 @@ +create table twopc_fuzzer_update ( + id bigint, + col bigint, + primary key (id) +) Engine=InnoDB; + +create table twopc_fuzzer_insert ( + id bigint, + updateSet bigint, + threadId bigint, + col bigint auto_increment, + key(col), + primary key (id, col) +) Engine=InnoDB; + +create table twopc_t1 ( + id bigint, + col bigint, + primary key (id) +) Engine=InnoDB; diff --git a/go/test/endtoend/transaction/twopc/stress/stress_test.go b/go/test/endtoend/transaction/twopc/stress/stress_test.go new file mode 100644 index 00000000000..4dae0156b9d --- /dev/null +++ b/go/test/endtoend/transaction/twopc/stress/stress_test.go @@ -0,0 +1,313 @@ +/* +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 stress + +import ( + "context" + "fmt" + "os" + "path" + "strconv" + "strings" + "sync" + "syscall" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/syscallutil" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/onlineddl" + twopcutil "vitess.io/vitess/go/test/endtoend/transaction/twopc/utils" + "vitess.io/vitess/go/test/endtoend/utils" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/schema" +) + +// TestDisruptions tests that atomic transactions persevere through various disruptions. +func TestDisruptions(t *testing.T) { + testcases := []struct { + disruptionName string + commitDelayTime string + disruption func(t *testing.T) error + }{ + { + disruptionName: "No Disruption", + commitDelayTime: "1", + disruption: func(t *testing.T) error { + return nil + }, + }, + { + disruptionName: "PlannedReparentShard", + commitDelayTime: "5", + disruption: prsShard3, + }, + { + disruptionName: "MySQL Restart", + commitDelayTime: "5", + disruption: mysqlRestartShard3, + }, + { + disruptionName: "Vttablet Restart", + commitDelayTime: "5", + disruption: vttabletRestartShard3, + }, + { + disruptionName: "OnlineDDL", + commitDelayTime: "20", + disruption: onlineDDL, + }, + { + disruptionName: "EmergencyReparentShard", + commitDelayTime: "5", + disruption: ersShard3, + }, + } + for _, tt := range testcases { + t.Run(fmt.Sprintf("%s-%ss delay", tt.disruptionName, tt.commitDelayTime), func(t *testing.T) { + // Reparent all the shards to first tablet being the primary. + reparentToFirstTablet(t) + // cleanup all the old data. + conn, closer := start(t) + defer closer() + // Start an atomic transaction. + utils.Exec(t, conn, "begin") + // Insert rows such that they go to all the three shards. Given that we have sharded the table `twopc_t1` on reverse_bits + // it is very easy to figure out what value will end up in which shard. + idVals := []int{4, 6, 9} + for _, val := range idVals { + utils.Exec(t, conn, fmt.Sprintf("insert into twopc_t1(id, col) values(%d, 4)", val)) + } + // We want to delay the commit on one of the shards to simulate slow commits on a shard. + twopcutil.WriteTestCommunicationFile(t, twopcutil.DebugDelayCommitShard, "80-") + defer twopcutil.DeleteFile(twopcutil.DebugDelayCommitShard) + twopcutil.WriteTestCommunicationFile(t, twopcutil.DebugDelayCommitTime, tt.commitDelayTime) + defer twopcutil.DeleteFile(twopcutil.DebugDelayCommitTime) + // We will execute a commit in a go routine, because we know it will take some time to complete. + // While the commit is ongoing, we would like to run the disruption. + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + _, err := utils.ExecAllowError(t, conn, "commit") + if err != nil { + log.Errorf("Error in commit - %v", err) + } + }() + // Allow enough time for the commit to have started. + time.Sleep(1 * time.Second) + writeCtx, writeCancel := context.WithCancel(context.Background()) + var writerWg sync.WaitGroup + // Run multiple threads to try to write to the database on the same values of id to ensure that we don't + // allow any writes while the transaction is prepared and not committed. + for i := 0; i < 10; i++ { + writerWg.Add(1) + go func() { + defer writerWg.Done() + threadToWrite(t, writeCtx, idVals[i%3]) + }() + } + // Run the disruption. + err := tt.disruption(t) + require.NoError(t, err) + // Wait for the commit to have returned. We don't actually check for an error in the commit because the user might receive an error. + // But since we are waiting in CommitPrepared, the decision to commit the transaction should have already been taken. + wg.Wait() + // Check the data in the table. + waitForResults(t, "select id, col from twopc_t1 where col = 4 order by id", `[[INT64(4) INT64(4)] [INT64(6) INT64(4)] [INT64(9) INT64(4)]]`, 30*time.Second) + writeCancel() + writerWg.Wait() + }) + } +} + +// threadToWrite is a helper function to write to the database in a loop. +func threadToWrite(t *testing.T, ctx context.Context, id int) { + for { + select { + case <-ctx.Done(): + return + default: + } + conn, err := mysql.Connect(ctx, &vtParams) + if err != nil { + continue + } + _, _ = utils.ExecAllowError(t, conn, fmt.Sprintf("insert into twopc_t1(id, col) values(%d, %d)", id, rand.Intn(10000))) + conn.Close() + } +} + +// reparentToFirstTablet reparents all the shards to first tablet being the primary. +func reparentToFirstTablet(t *testing.T) { + ks := clusterInstance.Keyspaces[0] + for _, shard := range ks.Shards { + primary := shard.Vttablets[0] + err := clusterInstance.VtctldClientProcess.PlannedReparentShard(keyspaceName, shard.Name, primary.Alias) + require.NoError(t, err) + } +} + +// waitForResults waits for the results of the query to be as expected. +func waitForResults(t *testing.T, query string, resultExpected string, waitTime time.Duration) { + timeout := time.After(waitTime) + var prevRes []sqltypes.Row + for { + select { + case <-timeout: + t.Fatalf("didn't reach expected results for %s. Last results - %v", query, prevRes) + default: + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + if err == nil { + res, _ := utils.ExecAllowError(t, conn, query) + conn.Close() + if res != nil { + prevRes = res.Rows + if fmt.Sprintf("%v", res.Rows) == resultExpected { + return + } + } + } + time.Sleep(100 * time.Millisecond) + } + } +} + +/* +Cluster Level Disruptions for the fuzzer +*/ + +// prsShard3 runs a PRS in shard 3 of the keyspace. It promotes the second tablet to be the new primary. +func prsShard3(t *testing.T) error { + shard := clusterInstance.Keyspaces[0].Shards[2] + newPrimary := shard.Vttablets[1] + return clusterInstance.VtctldClientProcess.PlannedReparentShard(keyspaceName, shard.Name, newPrimary.Alias) +} + +// ersShard3 runs a ERS in shard 3 of the keyspace. It promotes the second tablet to be the new primary. +func ersShard3(t *testing.T) error { + shard := clusterInstance.Keyspaces[0].Shards[2] + newPrimary := shard.Vttablets[1] + _, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("EmergencyReparentShard", fmt.Sprintf("%s/%s", keyspaceName, shard.Name), "--new-primary", newPrimary.Alias) + return err +} + +// vttabletRestartShard3 restarts the first vttablet of the third shard. +func vttabletRestartShard3(t *testing.T) error { + shard := clusterInstance.Keyspaces[0].Shards[2] + tablet := shard.Vttablets[0] + return tablet.RestartOnlyTablet() +} + +// mysqlRestartShard3 restarts MySQL on the first tablet of the third shard. +func mysqlRestartShard3(t *testing.T) error { + shard := clusterInstance.Keyspaces[0].Shards[2] + vttablets := shard.Vttablets + tablet := vttablets[0] + log.Errorf("Restarting MySQL for - %v/%v tablet - %v", keyspaceName, shard.Name, tablet.Alias) + pidFile := path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/mysql.pid", tablet.TabletUID)) + pidBytes, err := os.ReadFile(pidFile) + if err != nil { + // We can't read the file which means the PID file does not exist + // The server must have stopped + return err + } + pid, err := strconv.Atoi(strings.TrimSpace(string(pidBytes))) + if err != nil { + return err + } + return syscallutil.Kill(pid, syscall.SIGKILL) +} + +var orderedDDL = []string{ + "alter table twopc_t1 add column extra_col1 varchar(20)", + "alter table twopc_t1 add column extra_col2 varchar(20)", + "alter table twopc_t1 add column extra_col3 varchar(20)", + "alter table twopc_t1 add column extra_col4 varchar(20)", +} + +var count = 0 + +// onlineDDL runs a DDL statement. +func onlineDDL(t *testing.T) error { + output, err := clusterInstance.VtctldClientProcess.ApplySchemaWithOutput(keyspaceName, orderedDDL[count%len(orderedDDL)], cluster.ApplySchemaParams{ + DDLStrategy: "vitess --force-cut-over-after=1ms", + }) + require.NoError(t, err) + count++ + fmt.Println("uuid: ", output) + status := WaitForMigrationStatus(t, &vtParams, clusterInstance.Keyspaces[0].Shards, strings.TrimSpace(output), 2*time.Minute, schema.OnlineDDLStatusComplete, schema.OnlineDDLStatusFailed) + onlineddl.CheckMigrationStatus(t, &vtParams, clusterInstance.Keyspaces[0].Shards, strings.TrimSpace(output), status) + require.Equal(t, schema.OnlineDDLStatusComplete, status) + return nil +} + +func WaitForMigrationStatus(t *testing.T, vtParams *mysql.ConnParams, shards []cluster.Shard, uuid string, timeout time.Duration, expectStatuses ...schema.OnlineDDLStatus) schema.OnlineDDLStatus { + shardNames := map[string]bool{} + for _, shard := range shards { + shardNames[shard.Name] = true + } + query := fmt.Sprintf("show vitess_migrations like '%s'", uuid) + + statusesMap := map[string]bool{} + for _, status := range expectStatuses { + statusesMap[string(status)] = true + } + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + lastKnownStatus := "" + for { + countMatchedShards := 0 + conn, err := mysql.Connect(ctx, vtParams) + if err != nil { + continue + } + r, err := utils.ExecAllowError(t, conn, query) + conn.Close() + if err != nil { + continue + } + for _, row := range r.Named().Rows { + shardName := row["shard"].ToString() + if !shardNames[shardName] { + // irrelevant shard + continue + } + lastKnownStatus = row["migration_status"].ToString() + if row["migration_uuid"].ToString() == uuid && statusesMap[lastKnownStatus] { + countMatchedShards++ + } + } + if countMatchedShards == len(shards) { + return schema.OnlineDDLStatus(lastKnownStatus) + } + select { + case <-ctx.Done(): + return schema.OnlineDDLStatus(lastKnownStatus) + case <-ticker.C: + } + } +} diff --git a/go/test/endtoend/transaction/twopc/stress/vschema.json b/go/test/endtoend/transaction/twopc/stress/vschema.json new file mode 100644 index 00000000000..415b5958f54 --- /dev/null +++ b/go/test/endtoend/transaction/twopc/stress/vschema.json @@ -0,0 +1,34 @@ +{ + "sharded":true, + "vindexes": { + "reverse_bits": { + "type": "reverse_bits" + } + }, + "tables": { + "twopc_fuzzer_update": { + "column_vindexes": [ + { + "column": "id", + "name": "reverse_bits" + } + ] + }, + "twopc_fuzzer_insert": { + "column_vindexes": [ + { + "column": "id", + "name": "reverse_bits" + } + ] + }, + "twopc_t1": { + "column_vindexes": [ + { + "column": "id", + "name": "reverse_bits" + } + ] + } + } +} \ No newline at end of file diff --git a/go/test/endtoend/transaction/twopc/twopc_test.go b/go/test/endtoend/transaction/twopc/twopc_test.go new file mode 100644 index 00000000000..cdb6b61f91a --- /dev/null +++ b/go/test/endtoend/transaction/twopc/twopc_test.go @@ -0,0 +1,1053 @@ +/* +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 transaction + +import ( + "context" + _ "embed" + "fmt" + "reflect" + "sort" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + twopcutil "vitess.io/vitess/go/test/endtoend/transaction/twopc/utils" + "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" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" +) + +// TestDTCommit tests distributed transaction commit for insert, update and delete operations +// It verifies the binlog events for the same with transaction state changes and redo statements. +func TestDTCommit(t *testing.T) { + conn, closer := start(t) + defer closer() + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) + + // 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, "insert into twopc_user(id, name) values(8,'bar')") + utils.Exec(t, conn, "insert into twopc_user(id, name) values(9,'baz')") + utils.Exec(t, conn, "insert into twopc_user(id, name) values(10,'apa')") + utils.Exec(t, conn, "commit") + + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitions(t, ch, tableMap, dtMap) + 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)) + + // 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, "update twopc_user set name='newfoo' where id = 8") + utils.Exec(t, conn, "commit") + + logTable = retrieveTransitions(t, ch, tableMap, dtMap) + expectations = map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant: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:40-80": { + "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + }, + "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: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)) + + // DELETE from multiple shard + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "delete from twopc_user where id = 9") + utils.Exec(t, conn, "delete from twopc_user where id = 10") + utils.Exec(t, conn, "commit") + + logTable = retrieveTransitions(t, ch, tableMap, dtMap) + expectations = map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + }, + "ks.redo_state:-40": { + "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + }, + "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:-40": {"delete:[INT64(10) VARCHAR(\"apa\")]"}, + "ks.twopc_user:80-": {"delete:[INT64(9) VARCHAR(\"baz\")]"}, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTRollback tests distributed transaction rollback for insert, update and delete operations +// There would not be any binlog events for rollback +func TestDTRollback(t *testing.T) { + conn, closer := start(t) + defer closer() + + // Insert initial Data + utils.Exec(t, conn, "insert into twopc_user(id, name) values(7,'foo'), (8,'bar')") + + // run vstream to stream binlogs + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) + + // Insert into multiple shards + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "insert into twopc_user(id, name) values(9,'baz')") + utils.Exec(t, conn, "insert into twopc_user(id, name) values(10,'apa')") + utils.Exec(t, conn, "rollback") + + tableMap := make(map[string][]*querypb.Field) + logTable := retrieveTransitions(t, ch, tableMap, nil) + assert.Zero(t, len(logTable), + "no change in binlog expected: got: %s", prettyPrint(logTable)) + + // 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, "update twopc_user set name='newfoo' where id = 8") + utils.Exec(t, conn, "rollback") + + logTable = retrieveTransitions(t, ch, tableMap, nil) + assert.Zero(t, len(logTable), + "no change in binlog expected: got: %s", prettyPrint(logTable)) + + // DELETE from multiple shard + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "delete from twopc_user where id = 7") + utils.Exec(t, conn, "delete from twopc_user where id = 8") + utils.Exec(t, conn, "rollback") + + logTable = retrieveTransitions(t, ch, tableMap, nil) + assert.Zero(t, len(logTable), + "no change in binlog expected: got: %s", prettyPrint(logTable)) +} + +// TestDTCommitMultiShardTxSingleShardDML tests distributed transaction commit for insert, update and delete operations +// There is DML operation only on single shard but transaction open on multiple shards. +// Metdata Manager is the one which executed the DML operation on the shard. +func TestDTCommitDMLOnlyOnMM(t *testing.T) { + conn, closer := start(t) + defer closer() + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) + + // 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 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) + dtMap := make(map[string]string) + logTable := retrieveTransitions(t, ch, tableMap, dtMap) + 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.twopc_user:80-": {"insert:[INT64(7) VARCHAR(\"foo\")]"}, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) + + // 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 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) + expectations = map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant: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\")]"}, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) + + // 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 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) + expectations = map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant: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\")]"}, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTCommitMultiShardTxSingleShardDML tests distributed transaction commit for insert, update and delete operations +// There is DML operation only on single shard but transaction open on multiple shards. +// Resource Manager is the one which executed the DML operation on the shard. +func TestDTCommitDMLOnlyOnRM(t *testing.T) { + conn, closer := start(t) + defer closer() + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) + + // Insert into multiple shards + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "insert into twopc_user(id, name) values(7,'foo')") + utils.Exec(t, conn, "commit") + + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitions(t, ch, tableMap, dtMap) + expectations := map[string][]string{ + "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:40-80": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + }, + "ks.redo_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (7, 'foo')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (7, 'foo')\")]", + }, + "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)) + + // Update from multiple shard + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "update twopc_user set name='newfoo' where id = 7") + utils.Exec(t, conn, "commit") + + logTable = retrieveTransitions(t, ch, tableMap, dtMap) + expectations = map[string][]string{ + "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:40-80": { + "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + }, + "ks.redo_state:80-": { + "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:80-": { + "insert:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 7 limit 10001 /* INT64 */\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 7 limit 10001 /* INT64 */\")]", + }, + "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)) + + // DELETE from multiple shard + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "delete from twopc_user where id = 7") + utils.Exec(t, conn, "commit") + + logTable = retrieveTransitions(t, ch, tableMap, dtMap) + expectations = map[string][]string{ + "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:40-80": { + "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", + }, + "ks.redo_state:80-": { + "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:80-": { + "insert:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 7 limit 10001 /* INT64 */\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 7 limit 10001 /* INT64 */\")]", + }, + "ks.twopc_user:80-": {"delete:[INT64(7) VARCHAR(\"newfoo\")]"}, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTPrepareFailOnRM tests distributed transaction prepare failure on resource manager +func TestDTPrepareFailOnRM(t *testing.T) { + conn, closer := start(t) + defer closer() + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) + + // 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, "insert into twopc_user(id, name) values(8,'bar')") + + ctx2 := context.Background() + conn2, err := mysql.Connect(ctx2, &vtParams) + require.NoError(t, err) + + 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(18,'apa')") + + var wg sync.WaitGroup + wg.Add(2) + var commitErr error + go func() { + _, err := utils.ExecAllowError(t, conn, "commit") + if err != nil { + commitErr = err + } + wg.Done() + }() + go func() { + _, err := utils.ExecAllowError(t, conn2, "commit") + wg.Done() + if err != nil { + commitErr = err + } + }() + wg.Wait() + require.ErrorContains(t, commitErr, "ResourceExhausted desc = prepare failed") + + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitions(t, ch, tableMap, dtMap) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + "update:[VARCHAR(\"dtid-2\") VARCHAR(\"ROLLBACK\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"ROLLBACK\")]", + }, + "ks.dt_participant: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:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "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: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 (18, 'apa')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (18, 'apa')\")]", + }}, + "ks.twopc_user:40-80": {{ + "insert:[INT64(8) VARCHAR(\"bar\")]", + }, { + "insert:[INT64(18) VARCHAR(\"apa\")]", + }}, + "ks.twopc_user:80-": {{ + "insert:[INT64(7) VARCHAR(\"foo\")]", + }, { + "insert:[INT64(9) VARCHAR(\"baz\")]", + }}, + } + + compareMaps(t, expectations, logTable, flexiExpectations) +} + +func compareMaps(t *testing.T, expected, actual map[string][]string, flexibleExp map[string][2][]string) { + assert.Equal(t, len(expected), len(actual), "mismatch in number of keys: expected: %d, got: %d", len(expected), len(actual)) + + for key, expectedValue := range expected { + actualValue, ok := actual[key] + require.Truef(t, ok, "key %s not found in actual map", key) + + if validValues, isFlexi := flexibleExp[key]; isFlexi { + // For the flexible key, check if the actual value matches one of the valid values + if !reflect.DeepEqual(actualValue, validValues[0]) && !reflect.DeepEqual(actualValue, validValues[1]) { + t.Fatalf("mismatch in values for key '%s': expected one of: %v, got: %v", key, validValues, actualValue) + } + } else { + // Sort the slices before comparison + sort.Strings(expectedValue) + sort.Strings(actualValue) + assert.Equal(t, expectedValue, actualValue, "mismatch in values for key %s: expected: %v, got: %v", key, expectedValue, actualValue) + } + } +} + +// 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") + + testWarningAndTransactionStatus(t, conn, + "distributed transaction ID failed during metadata manager commit; transaction will be committed/rollbacked based on the state on recovery", + false, "COMMIT", "ks:40-80,ks:-40") + + // 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") + + testWarningAndTransactionStatus(t, conn, + "distributed transaction ID failed during transaction prepare phase; prepare transaction rollback attempted; conclude on recovery", + true /* transaction concluded */, "", "") + + // 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") + + testWarningAndTransactionStatus(t, conn, + "distributed transaction ID failed during transaction prepare phase; prepare transaction rollback attempted; conclude on recovery", + true, "", "") + + // 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") + + testWarningAndTransactionStatus(t, conn, + "distributed transaction ID failed during resource manager commit; transaction will be committed on recovery", + false, "COMMIT", "ks:40-80,ks:-40") + + // 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") + + testWarningAndTransactionStatus(t, conn, + "distributed transaction ID failed during transaction record creation; rollback attempted; conclude on recovery", + false, "PREPARE", "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)) +} + +type warn struct { + level string + code uint16 + msg string +} + +func toWarn(row sqltypes.Row) warn { + code, _ := row[1].ToUint16() + return warn{ + level: row[0].ToString(), + code: code, + msg: row[2].ToString(), + } +} + +type txStatus struct { + dtid string + state string + rTime string + participants string +} + +func toTxStatus(row sqltypes.Row) txStatus { + return txStatus{ + dtid: row[0].ToString(), + state: row[1].ToString(), + rTime: row[2].ToString(), + participants: row[3].ToString(), + } +} + +func testWarningAndTransactionStatus(t *testing.T, conn *vtgateconn.VTGateSession, warnMsg string, + txConcluded bool, txState string, txParticipants string) { + t.Helper() + + qr, err := conn.Execute(context.Background(), "show warnings", nil) + require.NoError(t, err) + require.Len(t, qr.Rows, 1) + + // validate warning output + w := toWarn(qr.Rows[0]) + assert.Equal(t, "Warning", w.level) + assert.EqualValues(t, 302, w.code) + assert.Contains(t, w.msg, warnMsg) + + // extract transaction ID + indx := strings.Index(w.msg, " ") + require.Greater(t, indx, 0) + dtid := w.msg[:indx] + + qr, err = conn.Execute(context.Background(), fmt.Sprintf(`show transaction status for '%v'`, dtid), nil) + require.NoError(t, err) + + // validate transaction status + if txConcluded { + require.Empty(t, qr.Rows) + } else { + tx := toTxStatus(qr.Rows[0]) + assert.Equal(t, dtid, tx.dtid) + assert.Equal(t, txState, tx.state) + assert.Equal(t, txParticipants, tx.participants) + } +} + +// TestReadingUnresolvedTransactions tests the reading of unresolved transactions +func TestReadingUnresolvedTransactions(t *testing.T) { + testcases := []struct { + name string + queries []string + }{ + { + name: "show transaction status for explicit keyspace", + queries: []string{ + fmt.Sprintf("show unresolved transactions for %v", keyspaceName), + }, + }, + { + name: "show transaction status with use command", + queries: []string{ + fmt.Sprintf("use %v", keyspaceName), + "show unresolved transactions", + }, + }, + } + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + conn, closer := start(t) + defer closer() + // Start an atomic transaction. + utils.Exec(t, conn, "begin") + // Insert rows such that they go to all the three shards. Given that we have sharded the table `twopc_t1` on reverse_bits + // it is very easy to figure out what value will end up in which shard. + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(4, 4)") + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(6, 4)") + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(9, 4)") + // We want to delay the commit on one of the shards to simulate slow commits on a shard. + twopcutil.WriteTestCommunicationFile(t, twopcutil.DebugDelayCommitShard, "80-") + defer twopcutil.DeleteFile(twopcutil.DebugDelayCommitShard) + twopcutil.WriteTestCommunicationFile(t, twopcutil.DebugDelayCommitTime, "5") + defer twopcutil.DeleteFile(twopcutil.DebugDelayCommitTime) + // We will execute a commit in a go routine, because we know it will take some time to complete. + // While the commit is ongoing, we would like to check that we see the unresolved transaction. + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + _, err := utils.ExecAllowError(t, conn, "commit") + if err != nil { + fmt.Println("Error in commit: ", err.Error()) + } + }() + // Allow enough time for the commit to have started. + time.Sleep(1 * time.Second) + var lastRes *sqltypes.Result + newConn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer newConn.Close() + for _, query := range testcase.queries { + lastRes = utils.Exec(t, newConn, query) + } + require.NotNil(t, lastRes) + require.Len(t, lastRes.Rows, 1) + // This verifies that we already decided to commit the transaction, but it is still unresolved. + assert.Contains(t, fmt.Sprintf("%v", lastRes.Rows), `VARCHAR("COMMIT")`) + // Wait for the commit to have returned. + wg.Wait() + }) + } +} + +// TestSemiSyncRequiredWithTwoPC tests that semi-sync is required when using two-phase commit. +func TestSemiSyncRequiredWithTwoPC(t *testing.T) { + // cleanup all the old data. + conn, closer := start(t) + defer closer() + + out, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("SetKeyspaceDurabilityPolicy", keyspaceName, "--durability-policy=none") + require.NoError(t, err, out) + defer clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("SetKeyspaceDurabilityPolicy", keyspaceName, "--durability-policy=semi_sync") + + // After changing the durability policy for the given keyspace to none, we run PRS. + shard := clusterInstance.Keyspaces[0].Shards[2] + newPrimary := shard.Vttablets[1] + _, err = clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + fmt.Sprintf("%s/%s", keyspaceName, shard.Name), + "--new-primary", newPrimary.Alias) + require.NoError(t, err) + + // A new distributed transaction should fail. + utils.Exec(t, conn, "begin") + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(4, 4)") + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(6, 4)") + utils.Exec(t, conn, "insert into twopc_t1(id, col) values(9, 4)") + _, err = utils.ExecAllowError(t, conn, "commit") + require.Error(t, err) + require.ErrorContains(t, err, "two-pc is enabled, but semi-sync is not") +} diff --git a/go/test/endtoend/transaction/twopc/utils/utils.go b/go/test/endtoend/transaction/twopc/utils/utils.go new file mode 100644 index 00000000000..9d0ef838eb6 --- /dev/null +++ b/go/test/endtoend/transaction/twopc/utils/utils.go @@ -0,0 +1,83 @@ +/* +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 utils + +import ( + "context" + "fmt" + "os" + "path" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" +) + +const ( + DebugDelayCommitShard = "VT_DELAY_COMMIT_SHARD" + DebugDelayCommitTime = "VT_DELAY_COMMIT_TIME" +) + +// ClearOutTable deletes everything from a table. Sometimes the table might have more rows than allowed in a single delete query, +// so we have to do the deletions iteratively. +func ClearOutTable(t *testing.T, vtParams mysql.ConnParams, tableName string) { + ctx := context.Background() + for { + conn, err := mysql.Connect(ctx, &vtParams) + if err != nil { + fmt.Printf("Error in connection - %v\n", err) + continue + } + + res, err := conn.ExecuteFetch(fmt.Sprintf("SELECT count(*) FROM %v", tableName), 1, false) + if err != nil { + fmt.Printf("Error in selecting - %v\n", err) + conn.Close() + time.Sleep(100 * time.Millisecond) + continue + } + require.Len(t, res.Rows, 1) + require.Len(t, res.Rows[0], 1) + rowCount, err := res.Rows[0][0].ToInt() + require.NoError(t, err) + if rowCount == 0 { + conn.Close() + return + } + _, err = conn.ExecuteFetch(fmt.Sprintf("DELETE FROM %v LIMIT 10000", tableName), 10000, false) + conn.Close() + if err != nil { + fmt.Printf("Error in cleanup deletion - %v\n", err) + time.Sleep(100 * time.Millisecond) + continue + } + } +} + +// WriteTestCommunicationFile writes the content to the file with the given name. +// We use these files to coordinate with the vttablets running in the debug mode. +func WriteTestCommunicationFile(t *testing.T, fileName string, content string) { + err := os.WriteFile(path.Join(os.Getenv("VTDATAROOT"), fileName), []byte(content), 0644) + require.NoError(t, err) +} + +// DeleteFile deletes the file specified. +func DeleteFile(fileName string) { + _ = os.Remove(path.Join(os.Getenv("VTDATAROOT"), fileName)) +} diff --git a/go/test/endtoend/vtgate/transaction/twopc/vschema.json b/go/test/endtoend/transaction/twopc/vschema.json similarity index 65% rename from go/test/endtoend/vtgate/transaction/twopc/vschema.json rename to go/test/endtoend/transaction/twopc/vschema.json index 4ff62df6808..bca58b05c1e 100644 --- a/go/test/endtoend/vtgate/transaction/twopc/vschema.json +++ b/go/test/endtoend/transaction/twopc/vschema.json @@ -3,6 +3,9 @@ "vindexes": { "xxhash": { "type": "xxhash" + }, + "reverse_bits": { + "type": "reverse_bits" } }, "tables": { @@ -21,6 +24,14 @@ "name": "xxhash" } ] + }, + "twopc_t1": { + "column_vindexes": [ + { + "column": "id", + "name": "reverse_bits" + } + ] } } } \ No newline at end of file diff --git a/go/test/endtoend/vtgate/transaction/tx_test.go b/go/test/endtoend/transaction/tx_test.go similarity index 97% rename from go/test/endtoend/vtgate/transaction/tx_test.go rename to go/test/endtoend/transaction/tx_test.go index 8a004277b89..475b17cfa2c 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", } @@ -70,9 +69,10 @@ func TestMain(m *testing.M) { // Start keyspace keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: SchemaSQL, - VSchema: VSchema, + Name: keyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + DurabilityPolicy: "semi_sync", } if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, false); err != nil { return 1, err 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/utils/cmp.go b/go/test/endtoend/utils/cmp.go index 32c90a27a5b..3b47e1f68dc 100644 --- a/go/test/endtoend/utils/cmp.go +++ b/go/test/endtoend/utils/cmp.go @@ -138,7 +138,7 @@ func (mcmp *MySQLCompare) AssertContainsError(query, expected string) { mcmp.t.Helper() _, err := mcmp.ExecAllowAndCompareError(query, CompareOptions{}) require.Error(mcmp.t, err) - assert.Contains(mcmp.t, err.Error(), expected, "actual error: %s", err.Error()) + assert.ErrorContains(mcmp.t, err, expected, "actual error: %s", err.Error()) } // AssertMatchesNoOrder executes the given query against both Vitess and MySQL. diff --git a/go/test/endtoend/utils/utils.go b/go/test/endtoend/utils/utils.go index 345f1e787b4..35404981164 100644 --- a/go/test/endtoend/utils/utils.go +++ b/go/test/endtoend/utils/utils.go @@ -114,7 +114,7 @@ func AssertContainsError(t *testing.T, conn *mysql.Conn, query, expected string) t.Helper() _, err := ExecAllowError(t, conn, query) require.Error(t, err) - assert.Contains(t, err.Error(), expected, "actual error: %s", err.Error()) + assert.ErrorContains(t, err, expected, "actual error: %s", err.Error()) } // AssertMatchesNoOrder executes the given query and makes sure it matches the given `expected` string. diff --git a/go/test/endtoend/vreplication/cluster_test.go b/go/test/endtoend/vreplication/cluster_test.go index a758944d3d9..97adbb80a6a 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 ( @@ -88,6 +87,9 @@ type ClusterConfig struct { vtorcPort int vreplicationCompressGTID bool + // Set overrideHeartbeatOptions to true to override the default heartbeat options: + // which are set to only on demand (5s) and 250ms interval. + overrideHeartbeatOptions bool } // enableGTIDCompression enables GTID compression for the cluster and returns a function @@ -472,12 +474,12 @@ func (vc *VitessCluster) AddKeyspace(t *testing.T, cells []*Cell, ksName string, SidecarDBName: sidecarDBName, } - if err := vc.VtctldClient.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName); err != nil { - t.Fatalf(err.Error()) - } + err := vc.VtctldClient.CreateKeyspace(keyspace.Name, keyspace.SidecarDBName) + require.NoError(t, err) 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 := "" @@ -497,15 +499,13 @@ func (vc *VitessCluster) AddKeyspace(t *testing.T, cells []*Cell, ksName string, require.NoError(t, vc.AddShards(t, cells, keyspace, shards, numReplicas, numRdonly, tabletIDBase, opts)) if schema != "" { - if err := vc.VtctlClient.ApplySchema(ksName, schema); err != nil { - t.Fatalf(err.Error()) - } + err := vc.VtctlClient.ApplySchema(ksName, schema) + require.NoError(t, err) } keyspace.Schema = schema if vschema != "" { - if err := vc.VtctlClient.ApplyVSchema(ksName, vschema); err != nil { - t.Fatalf(err.Error()) - } + err := vc.VtctlClient.ApplyVSchema(ksName, vschema) + require.NoError(t, err) } keyspace.VSchema = vschema @@ -517,11 +517,15 @@ func (vc *VitessCluster) AddKeyspace(t *testing.T, cells []*Cell, ksName string, // AddTablet creates new tablet with specified attributes func (vc *VitessCluster) AddTablet(t testing.TB, cell *Cell, keyspace *Keyspace, shard *Shard, tabletType string, tabletID int) (*Tablet, *exec.Cmd, error) { tablet := &Tablet{} - - options := []string{ + var options []string + defaultHeartbeatOptions := []string{ "--heartbeat_on_demand_duration", "5s", "--heartbeat_interval", "250ms", } + if !mainClusterConfig.overrideHeartbeatOptions { + options = append(options, defaultHeartbeatOptions...) + } + options = append(options, extraVTTabletArgs...) if mainClusterConfig.vreplicationCompressGTID { @@ -681,9 +685,8 @@ func (vc *VitessCluster) AddShards(t *testing.T, cells []*Cell, keyspace *Keyspa } for ind, tablet := range tablets { log.Infof("Running Setup() for vttablet %s", tablets[ind].Name) - if err := tablet.Vttablet.Setup(); err != nil { - t.Fatalf(err.Error()) - } + err := tablet.Vttablet.Setup() + require.NoError(t, err) // Set time_zone to UTC for all tablets. Without this it fails locally on some MacOS setups. query := "SET GLOBAL time_zone = '+00:00';" qr, err := tablet.Vttablet.QueryTablet(query, tablet.Vttablet.Keyspace, false) @@ -743,7 +746,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") @@ -781,9 +784,8 @@ func (vc *VitessCluster) StartVtgate(t testing.TB, cell *Cell, cellsToWatch stri extraVTGateArgs, vc.ClusterConfig.vtgatePlannerVersion) require.NotNil(t, vtgate) - if err := vtgate.Setup(); err != nil { - t.Fatalf(err.Error()) - } + err := vtgate.Setup() + require.NoError(t, err) cell.Vtgates = append(cell.Vtgates, vtgate) } diff --git a/go/test/endtoend/vreplication/materialize_test.go b/go/test/endtoend/vreplication/materialize_test.go index 486692a58ba..3f2e3451a64 100644 --- a/go/test/endtoend/vreplication/materialize_test.go +++ b/go/test/endtoend/vreplication/materialize_test.go @@ -108,7 +108,6 @@ const smMaterializeSchemaSource = ` const smMaterializeVSchemaSource = ` { - "sharded": true, "tables": { "mat": { "column_vindexes": [ @@ -197,6 +196,8 @@ func testMaterialize(t *testing.T, useVtctldClient bool) { _, err = ks2Primary.QueryTablet(customFunc, targetKs, true) require.NoError(t, err) + testMaterializeWithNonExistentTable(t) + materialize(t, smMaterializeSpec2, useVtctldClient) catchup(t, ks2Primary, "wf1", "Materialize") diff --git a/go/test/endtoend/vreplication/multi_tenant_test.go b/go/test/endtoend/vreplication/multi_tenant_test.go index eda245ee597..b10395b08c8 100644 --- a/go/test/endtoend/vreplication/multi_tenant_test.go +++ b/go/test/endtoend/vreplication/multi_tenant_test.go @@ -203,6 +203,7 @@ func TestMultiTenantSimple(t *testing.T) { lastIndex = insertRows(lastIndex, sourceKeyspace) waitForWorkflowState(t, vc, fmt.Sprintf("%s.%s", targetKeyspace, mt.workflowName), binlogdatapb.VReplicationWorkflowState_Running.String()) + vdiff(t, targetKeyspace, workflowName, defaultCellName, false, true, nil) mt.SwitchReads() confirmOnlyReadsSwitched(t) @@ -362,6 +363,7 @@ func TestMultiTenantSharded(t *testing.T) { // Note: we cannot insert into the target keyspace since that is never routed to the source keyspace. lastIndex = insertRows(lastIndex, sourceKeyspace) waitForWorkflowState(t, vc, fmt.Sprintf("%s.%s", targetKeyspace, mt.workflowName), binlogdatapb.VReplicationWorkflowState_Running.String()) + vdiff(t, targetKeyspace, workflowName, defaultCellName, false, true, nil) mt.SwitchReadsAndWrites() // Note: here we have already switched, and we can insert into the target keyspace, and it should get reverse // replicated to the source keyspace. The source keyspace is routed to the target keyspace at this point. @@ -558,6 +560,7 @@ func (mtm *multiTenantMigration) switchTraffic(tenantId int64) { mt := mtm.getActiveMoveTables(tenantId) ksWorkflow := fmt.Sprintf("%s.%s", mtm.targetKeyspace, mt.workflowName) waitForWorkflowState(t, vc, ksWorkflow, binlogdatapb.VReplicationWorkflowState_Running.String()) + vdiff(t, mt.targetKeyspace, mt.workflowName, defaultCellName, false, true, nil) mtm.insertSomeData(t, tenantId, sourceKeyspaceName, numAdditionalRowsPerTenant) mt.SwitchReadsAndWrites() mtm.insertSomeData(t, tenantId, sourceKeyspaceName, numAdditionalRowsPerTenant) diff --git a/go/test/endtoend/vreplication/resharding_workflows_v2_test.go b/go/test/endtoend/vreplication/resharding_workflows_v2_test.go index 78ad843ca1d..1e93a54b850 100644 --- a/go/test/endtoend/vreplication/resharding_workflows_v2_test.go +++ b/go/test/endtoend/vreplication/resharding_workflows_v2_test.go @@ -750,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/vdiff2_test.go b/go/test/endtoend/vreplication/vdiff2_test.go index f4128b5c036..ce5eb693975 100644 --- a/go/test/endtoend/vreplication/vdiff2_test.go +++ b/go/test/endtoend/vreplication/vdiff2_test.go @@ -385,8 +385,9 @@ func testCLIFlagHandling(t *testing.T, targetKs, workflowName string, cell *Cell TabletTypes: "replica,primary,rdonly", }, ReportOptions: &tabletmanagerdatapb.VDiffReportOptions{ - MaxSampleRows: 888, - OnlyPks: true, + MaxSampleRows: 888, + OnlyPks: true, + RowDiffColumnTruncateAt: 444, }, } @@ -404,6 +405,7 @@ func testCLIFlagHandling(t *testing.T, targetKs, workflowName string, cell *Cell fmt.Sprintf("--update-table-stats=%t", expectedOptions.CoreOptions.UpdateTableStats), fmt.Sprintf("--auto-retry=%t", expectedOptions.CoreOptions.AutoRetry), fmt.Sprintf("--only-pks=%t", expectedOptions.ReportOptions.OnlyPks), + fmt.Sprintf("--row-diff-column-truncate-at=%d", expectedOptions.ReportOptions.RowDiffColumnTruncateAt), "--tablet-types-in-preference-order=false", // So tablet_types should not start with "in_order:", which is the default "--format=json") // So we can easily grab the UUID require.NoError(t, err, "vdiff command failed: %s", res) diff --git a/go/test/endtoend/vreplication/vreplication_test.go b/go/test/endtoend/vreplication/vreplication_test.go index 52874b5839c..6a372b3fd09 100644 --- a/go/test/endtoend/vreplication/vreplication_test.go +++ b/go/test/endtoend/vreplication/vreplication_test.go @@ -58,7 +58,7 @@ var ( targetKsOpts = make(map[string]string) httpClient = throttlebase.SetupHTTPClient(time.Second) sourceThrottlerAppName = throttlerapp.VStreamerName - targetThrottlerAppName = throttlerapp.VReplicationName + targetThrottlerAppName = throttlerapp.VPlayerName ) const ( @@ -1183,6 +1183,18 @@ func materialize(t *testing.T, spec string, useVtctldClient bool) { } } +func testMaterializeWithNonExistentTable(t *testing.T) { + t.Run("vtctldclient materialize with nonexistent table", func(t *testing.T) { + tableSettings := `[{"target_table": "table_that_doesnt_exist", "create_ddl": "create table mat_val_counts (mat_val varbinary(10), cnt int unsigned, primary key (mat_val))", "source_expression": "select val, count(*) as cnt from mat group by val"}]` + output, err := vc.VtctldClient.ExecuteCommandWithOutput("materialize", "--workflow=tablenogood", "--target-keyspace=source", + "create", "--source-keyspace=source", "--table-settings", tableSettings) + require.NoError(t, err, "Materialize create failed, err: %v, output: %s", err, output) + waitForWorkflowState(t, vc, "source.tablenogood", binlogdatapb.VReplicationWorkflowState_Stopped.String()) + output, err = vc.VtctldClient.ExecuteCommandWithOutput("materialize", "--workflow=tablenogood", "--target-keyspace=source", "cancel") + require.NoError(t, err, "Materialize cancel failed, err: %v, output: %s", err, output) + }) +} + func materializeProduct(t *testing.T, useVtctldClient bool) { t.Run("materializeProduct", func(t *testing.T) { // Materializing from "product" keyspace to "customer" keyspace. @@ -1216,18 +1228,7 @@ func materializeProduct(t *testing.T, useVtctldClient bool) { for _, tab := range customerTablets { waitForRowCountInTablet(t, tab, keyspace, workflow, 5) // Confirm that we updated the stats on the target tablets as expected. - jsVal, err := getDebugVar(t, tab.Port, []string{"VReplicationThrottledCounts"}) - require.NoError(t, err) - require.NotEqual(t, "{}", jsVal) - // The JSON value looks like this: {"cproduct.4.tablet.vstreamer": 2} - vstreamerThrottledCount := gjson.Get(jsVal, fmt.Sprintf(`%s\.*\.tablet\.vstreamer`, workflow)).Int() - require.Greater(t, vstreamerThrottledCount, int64(0)) - // We only need to do this stat check once. - val, err := getDebugVar(t, tab.Port, []string{"VReplicationThrottledCountTotal"}) - require.NoError(t, err) - throttledCount, err := strconv.ParseInt(val, 10, 64) - require.NoError(t, err) - require.GreaterOrEqual(t, throttledCount, vstreamerThrottledCount) + confirmVReplicationThrottling(t, tab, sourceKs, workflow, sourceThrottlerAppName) } }) t.Run("unthrottle-app-product", func(t *testing.T) { @@ -1262,12 +1263,7 @@ func materializeProduct(t *testing.T, useVtctldClient bool) { for _, tab := range customerTablets { waitForRowCountInTablet(t, tab, keyspace, workflow, 8) // Confirm that we updated the stats on the target tablets as expected. - jsVal, err := getDebugVar(t, tab.Port, []string{"VReplicationThrottledCounts"}) - require.NoError(t, err) - require.NotEqual(t, "{}", jsVal) - // The JSON value now looks like this: {"cproduct.4.tablet.vstreamer": 2, "cproduct.4.tablet.vplayer": 4} - vplayerThrottledCount := gjson.Get(jsVal, fmt.Sprintf(`%s\.*\.tablet\.vplayer`, workflow)).Int() - require.Greater(t, vplayerThrottledCount, int64(0)) + confirmVReplicationThrottling(t, tab, sourceKs, workflow, targetThrottlerAppName) } }) t.Run("unthrottle-app-customer", func(t *testing.T) { @@ -1697,3 +1693,52 @@ func waitForInnoDBHistoryLength(t *testing.T, tablet *cluster.VttabletProcess, e func releaseInnoDBRowHistory(t *testing.T, dbConn *mysql.Conn) { execQuery(t, dbConn, "rollback") } + +// confirmVReplicationThrottling confirms that the throttling related metrics reflect that +// the workflow is being throttled as expected, via the expected app name, and that this +// is impacting the lag as expected. +// The tablet passed should be a target tablet for the given workflow while the keyspace +// name provided should be the source keyspace as the target tablet stats note the stream's +// source keyspace and shard. +func confirmVReplicationThrottling(t *testing.T, tab *cluster.VttabletProcess, keyspace, workflow string, appname throttlerapp.Name) { + const ( + sleepTime = 5 * time.Second + zv = int64(0) + ) + time.Sleep(sleepTime) // To be sure that we accrue some lag + + jsVal, err := getDebugVar(t, tab.Port, []string{"VReplicationThrottledCounts"}) + require.NoError(t, err) + require.NotEqual(t, "{}", jsVal) + // The JSON value looks like this: {"cproduct.4.tablet.vstreamer": 2, "cproduct.4.tablet.vplayer": 4} + throttledCount := gjson.Get(jsVal, fmt.Sprintf(`%s\.*\.tablet\.%s`, workflow, appname)).Int() + require.Greater(t, throttledCount, zv, "JSON value: %s", jsVal) + + val, err := getDebugVar(t, tab.Port, []string{"VReplicationThrottledCountTotal"}) + require.NoError(t, err) + require.NotEqual(t, "", val) + throttledCountTotal, err := strconv.ParseInt(val, 10, 64) + require.NoError(t, err) + require.GreaterOrEqual(t, throttledCountTotal, throttledCount, "Value: %s", val) + + // We do not calculate replication lag for the vcopier as it's not replicating + // events. + if appname != throttlerapp.VCopierName { + jsVal, err = getDebugVar(t, tab.Port, []string{"VReplicationLagSeconds"}) + require.NoError(t, err) + require.NotEqual(t, "{}", jsVal) + // The JSON value looks like this: {"product.0.cproduct.4": 6} + vreplLagSeconds := gjson.Get(jsVal, fmt.Sprintf(`%s\.*\.%s\.*`, keyspace, workflow)).Int() + require.NoError(t, err) + // Take off 1 second to deal with timing issues in the test. + minLagSecs := int64(int64(sleepTime.Seconds()) - 1) + require.GreaterOrEqual(t, vreplLagSeconds, minLagSecs, "JSON value: %s", jsVal) + + val, err = getDebugVar(t, tab.Port, []string{"VReplicationLagSecondsMax"}) + require.NoError(t, err) + require.NotEqual(t, "", val) + vreplLagSecondsMax, err := strconv.ParseInt(val, 10, 64) + require.NoError(t, err) + require.GreaterOrEqual(t, vreplLagSecondsMax, vreplLagSeconds, "Value: %s", val) + } +} diff --git a/go/test/endtoend/vreplication/vreplication_test_env.go b/go/test/endtoend/vreplication/vreplication_test_env.go index 238242f0e65..c62d871380d 100644 --- a/go/test/endtoend/vreplication/vreplication_test_env.go +++ b/go/test/endtoend/vreplication/vreplication_test_env.go @@ -17,9 +17,9 @@ limitations under the License. package vreplication var dryRunResultsSwitchWritesCustomerShard = []string{ - "Mirroring 0.00 percent of traffic from keyspace product to keyspace customer for tablet types [PRIMARY]", "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,8 +36,8 @@ var dryRunResultsSwitchWritesCustomerShard = []string{ } var dryRunResultsReadCustomerShard = []string{ - "Mirroring 0.00 percent of traffic from keyspace product to keyspace customer for tablet types [RDONLY,REPLICA]", "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/vstream_test.go b/go/test/endtoend/vreplication/vstream_test.go index e13c3e24e80..a314b99dd94 100644 --- a/go/test/endtoend/vreplication/vstream_test.go +++ b/go/test/endtoend/vreplication/vstream_test.go @@ -747,3 +747,139 @@ func TestVStreamCopyMultiKeyspaceReshard(t *testing.T) { require.NotZero(t, ne.numDash40Events) require.NotZero(t, ne.num40DashEvents) } + +const ( + vstreamHeartbeatsTestContextTimeout = 20 * time.Second + // Expect a reasonable number of heartbeats to be received in the test duration, should ideally be ~ timeout + // since the heartbeat interval is set to 1s. But we set it to 10 to be conservative to avoid CI flakiness. + numExpectedHeartbeats = 10 +) + +func doVStream(t *testing.T, vc *VitessCluster, flags *vtgatepb.VStreamFlags) (numRowEvents map[string]int, numFieldEvents map[string]int) { + // Stream for a while to ensure heartbeats are sent. + ctx, cancel := context.WithTimeout(context.Background(), vstreamHeartbeatsTestContextTimeout) + defer cancel() + + numRowEvents = make(map[string]int) + numFieldEvents = make(map[string]int) + vstreamConn, err := vtgateconn.Dial(ctx, fmt.Sprintf("%s:%d", vc.ClusterConfig.hostname, vc.ClusterConfig.vtgateGrpcPort)) + require.NoError(t, err) + defer vstreamConn.Close() + + done := false + vgtid := &binlogdatapb.VGtid{ + ShardGtids: []*binlogdatapb.ShardGtid{{ + Keyspace: "product", + Shard: "0", + Gtid: "", + }}} + + filter := &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "customer", + Filter: "select * from customer", + }}, + } + // Stream events from the VStream API. + reader, err := vstreamConn.VStream(ctx, topodatapb.TabletType_PRIMARY, vgtid, filter, flags) + require.NoError(t, err) + for !done { + evs, err := reader.Recv() + switch err { + case nil: + for _, ev := range evs { + switch ev.Type { + case binlogdatapb.VEventType_ROW: + rowEvent := ev.RowEvent + arr := strings.Split(rowEvent.TableName, ".") + require.Equal(t, len(arr), 2) + tableName := arr[1] + require.Equal(t, "product", rowEvent.Keyspace) + require.Equal(t, "0", rowEvent.Shard) + numRowEvents[tableName]++ + + case binlogdatapb.VEventType_FIELD: + fieldEvent := ev.FieldEvent + arr := strings.Split(fieldEvent.TableName, ".") + require.Equal(t, len(arr), 2) + tableName := arr[1] + require.Equal(t, "product", fieldEvent.Keyspace) + require.Equal(t, "0", fieldEvent.Shard) + numFieldEvents[tableName]++ + default: + } + } + case io.EOF: + log.Infof("Stream Ended") + done = true + default: + log.Errorf("remote error: %v", err) + done = true + } + } + return numRowEvents, numFieldEvents +} + +// TestVStreamHeartbeats enables streaming of the internal Vitess heartbeat tables in the VStream API and +// ensures that the heartbeat events are received as expected by the client. +func TestVStreamHeartbeats(t *testing.T) { + // Enable continuous heartbeats. + extraVTTabletArgs = append(extraVTTabletArgs, + "--heartbeat_enable", + "--heartbeat_interval", "1s", + "--heartbeat_on_demand_duration", "0", + ) + setSidecarDBName("_vt") + config := *mainClusterConfig + config.overrideHeartbeatOptions = true + vc = NewVitessCluster(t, &clusterOptions{ + clusterConfig: &config, + }) + defer vc.TearDown() + + require.NotNil(t, vc) + defaultReplicas = 0 + defaultRdonly = 0 + + defaultCell := vc.Cells[vc.CellNames[0]] + vc.AddKeyspace(t, []*Cell{defaultCell}, "product", "0", initialProductVSchema, initialProductSchema, + defaultReplicas, defaultRdonly, 100, nil) + verifyClusterHealth(t, vc) + insertInitialData(t) + + expectedNumRowEvents := make(map[string]int) + expectedNumRowEvents["customer"] = 3 // 3 rows inserted in the customer table in insertInitialData() + + type testCase struct { + name string + flags *vtgatepb.VStreamFlags + expectedHeartbeats int + } + testCases := []testCase{ + { + name: "With Keyspace Heartbeats On", + flags: &vtgatepb.VStreamFlags{ + StreamKeyspaceHeartbeats: true, + }, + expectedHeartbeats: numExpectedHeartbeats, + }, + { + name: "With Keyspace Heartbeats Off", + flags: nil, + expectedHeartbeats: 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + gotNumRowEvents, gotNumFieldEvents := doVStream(t, vc, tc.flags) + for k := range expectedNumRowEvents { + require.Equalf(t, 1, gotNumFieldEvents[k], "incorrect number of field events for table %s, got %d", k, gotNumFieldEvents[k]) + } + require.GreaterOrEqual(t, gotNumRowEvents["heartbeat"], tc.expectedHeartbeats, "incorrect number of heartbeat events received") + log.Infof("Total number of heartbeat events received: %v", gotNumRowEvents["heartbeat"]) + delete(gotNumRowEvents, "heartbeat") + require.Equal(t, expectedNumRowEvents, gotNumRowEvents) + }) + } +} diff --git a/go/test/endtoend/vtcombo/recreate/recreate_test.go b/go/test/endtoend/vtcombo/recreate/recreate_test.go index e66edb7688a..15cb63c3d7d 100644 --- a/go/test/endtoend/vtcombo/recreate/recreate_test.go +++ b/go/test/endtoend/vtcombo/recreate/recreate_test.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "os/exec" + "strconv" "strings" "testing" @@ -101,6 +102,9 @@ func TestDropAndRecreateWithSameShards(t *testing.T) { cur := conn.Session(ks1+"@primary", nil) + mysqlConnCountBefore, err := getMySQLConnectionCount(ctx, cur) + require.Nil(t, err) + _, err = cur.Execute(ctx, "DROP DATABASE "+ks1, nil) require.Nil(t, err) @@ -108,6 +112,23 @@ func TestDropAndRecreateWithSameShards(t *testing.T) { require.Nil(t, err) assertTabletsPresent(t) + + // Check the connection count after the CREATE. There will be zero connections after the DROP as the database + // no longer exists, but after it gets recreated any open pools will be able to reestablish connections. + mysqlConnCountAfter, err := getMySQLConnectionCount(ctx, cur) + require.Nil(t, err) + + // Assert that we're not leaking mysql connections, but allow for some wiggle room due to transient connections + assert.InDelta(t, mysqlConnCountBefore, mysqlConnCountAfter, 5, + "not within allowable delta: mysqlConnCountBefore=%d, mysqlConnCountAfter=%d", mysqlConnCountBefore, mysqlConnCountAfter) +} + +func getMySQLConnectionCount(ctx context.Context, session *vtgateconn.VTGateSession) (int, error) { + result, err := session.Execute(ctx, "select variable_value from performance_schema.global_status where variable_name='threads_connected'", nil) + if err != nil { + return 0, err + } + return strconv.Atoi(result.Rows[0][0].ToString()) } func assertTabletsPresent(t *testing.T) { 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 index 32807b22bde..6dae9b72be9 100644 --- a/go/test/endtoend/vtgate/connectiondrain/main_test.go +++ b/go/test/endtoend/vtgate/connectiondrain/main_test.go @@ -61,7 +61,7 @@ func setupCluster(t *testing.T) (*cluster.LocalProcessCluster, mysql.ConnParams) require.NoError(t, err) // Start vtgate - clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, "--mysql_server_drain_onterm", "--onterm_timeout", "30s") + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, "--mysql-server-drain-onterm", "--onterm_timeout", "30s") err = clusterInstance.StartVtgate() require.NoError(t, err) diff --git a/go/test/endtoend/vtgate/gen4/system_schema_test.go b/go/test/endtoend/vtgate/gen4/system_schema_test.go index fba953d51ae..fc4983935e9 100644 --- a/go/test/endtoend/vtgate/gen4/system_schema_test.go +++ b/go/test/endtoend/vtgate/gen4/system_schema_test.go @@ -213,7 +213,7 @@ func TestMultipleSchemaPredicates(t *testing.T) { "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", shardedKs, shardedKs, "a") _, err = conn.ExecuteFetch(query, 1000, true) require.Error(t, err) - require.Contains(t, err.Error(), "specifying two different database in the query is not supported") + require.ErrorContains(t, err, "specifying two different database in the query is not supported") } func TestQuerySystemTables(t *testing.T) { diff --git a/go/test/endtoend/vtgate/grpc_api/acl_test.go b/go/test/endtoend/vtgate/grpc_api/acl_test.go index 2819a3e41d1..d0ac003169d 100644 --- a/go/test/endtoend/vtgate/grpc_api/acl_test.go +++ b/go/test/endtoend/vtgate/grpc_api/acl_test.go @@ -57,8 +57,8 @@ func TestEffectiveCallerIDWithNoAccess(t *testing.T) { ctx = callerid.NewContext(ctx, callerid.NewEffectiveCallerID("user_no_access", "", ""), nil) _, err = session.Execute(ctx, query, nil) require.Error(t, err) - assert.Contains(t, err.Error(), "Select command denied to user") - assert.Contains(t, err.Error(), "for table 'test_table' (ACL check error)") + assert.ErrorContains(t, err, "Select command denied to user") + assert.ErrorContains(t, err, "for table 'test_table' (ACL check error)") } // TestAuthenticatedUserWithAccess verifies that an authenticated gRPC static user with ACL access can execute queries @@ -89,8 +89,8 @@ func TestAuthenticatedUserNoAccess(t *testing.T) { query := "SELECT id FROM test_table" _, err = session.Execute(ctx, query, nil) require.Error(t, err) - assert.Contains(t, err.Error(), "Select command denied to user") - assert.Contains(t, err.Error(), "for table 'test_table' (ACL check error)") + assert.ErrorContains(t, err, "Select command denied to user") + assert.ErrorContains(t, err, "for table 'test_table' (ACL check error)") } // TestUnauthenticatedUser verifies that an unauthenticated gRPC user cannot execute queries @@ -106,5 +106,5 @@ func TestUnauthenticatedUser(t *testing.T) { query := "SELECT id FROM test_table" _, err = session.Execute(ctx, query, nil) require.Error(t, err) - assert.Contains(t, err.Error(), "invalid credentials") + assert.ErrorContains(t, err, "invalid credentials") } diff --git a/go/test/endtoend/vtgate/lookup_test.go b/go/test/endtoend/vtgate/lookup_test.go index b4b53295d8d..75f4a007076 100644 --- a/go/test/endtoend/vtgate/lookup_test.go +++ b/go/test/endtoend/vtgate/lookup_test.go @@ -131,7 +131,7 @@ func TestConsistentLookup(t *testing.T) { mysqlErr := err.(*sqlerror.SQLError) assert.Equal(t, sqlerror.ERDupEntry, mysqlErr.Num) assert.Equal(t, "23000", mysqlErr.State) - assert.Contains(t, mysqlErr.Message, "reverted partial DML execution") + assert.ErrorContains(t, mysqlErr, "reverted partial DML execution") // Simple delete. utils.Exec(t, conn, "begin") diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go index 128d930718c..1c5e6a0c1b2 100644 --- a/go/test/endtoend/vtgate/misc_test.go +++ b/go/test/endtoend/vtgate/misc_test.go @@ -95,10 +95,13 @@ func TestShowTables(t *testing.T) { conn, closer := start(t) defer closer() - query := "show tables;" - qr := utils.Exec(t, conn, query) - + qr := utils.Exec(t, conn, "show tables") assert.Equal(t, "Tables_in_ks", qr.Fields[0].Name) + + // no error on executing `show tables` on system schema + utils.Exec(t, conn, `use mysql`) + utils.Exec(t, conn, "show tables") + utils.Exec(t, conn, "show tables from information_schema") } func TestCastConvert(t *testing.T) { @@ -753,7 +756,7 @@ func TestDescribeVindex(t *testing.T) { mysqlErr := err.(*sqlerror.SQLError) assert.Equal(t, sqlerror.ERNoSuchTable, mysqlErr.Num) assert.Equal(t, "42S02", mysqlErr.State) - assert.Contains(t, mysqlErr.Message, "NotFound desc") + assert.ErrorContains(t, mysqlErr, "NotFound desc") } func TestEmptyQuery(t *testing.T) { diff --git a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go index 9a6ad90cc5b..d206f58e17c 100644 --- a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go +++ b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go @@ -71,7 +71,6 @@ func start(t *testing.T) (utils.MySQLCompare, func()) { } func TestAggrWithLimit(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") mcmp, closer := start(t) defer closer() @@ -101,11 +100,9 @@ func TestAggregateTypes(t *testing.T) { mcmp.AssertMatches("select val1 as a, count(*) from aggr_test group by a order by 2, a", `[[VARCHAR("b") INT64(1)] [VARCHAR("d") INT64(1)] [VARCHAR("a") INT64(2)] [VARCHAR("c") INT64(2)] [VARCHAR("e") INT64(2)]]`) mcmp.AssertMatches("select sum(val1) from aggr_test", `[[FLOAT64(0)]]`) mcmp.Run("Average for sharded keyspaces", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches("select avg(val1) from aggr_test", `[[FLOAT64(0)]]`) }) mcmp.Run("Average with group by without selecting the grouped columns", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(20, "vtgate") mcmp.AssertMatches("select avg(val2) from aggr_test group by val1 order by val1", `[[DECIMAL(1.0000)] [DECIMAL(1.0000)] [DECIMAL(3.5000)] [NULL] [DECIMAL(1.0000)]]`) }) } @@ -214,7 +211,6 @@ func TestAggrOnJoin(t *testing.T) { `[[VARCHAR("a")]]`) mcmp.Run("Average in join for sharded", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches(`select avg(a1.val2), avg(a2.val2) from aggr_test a1 join aggr_test a2 on a1.val2 = a2.id join t3 t on a2.val2 = t.id7`, "[[DECIMAL(1.5000) DECIMAL(1.0000)]]") @@ -372,7 +368,6 @@ func TestAggOnTopOfLimit(t *testing.T) { mcmp.AssertMatches("select val1, count(*) from (select id, val1 from aggr_test where val2 < 4 order by val1 limit 2) as x group by val1", `[[NULL INT64(1)] [VARCHAR("a") INT64(1)]]`) mcmp.AssertMatchesNoOrder("select val1, count(val2) from (select val1, val2 from aggr_test limit 8) as x group by val1", `[[NULL INT64(1)] [VARCHAR("a") INT64(2)] [VARCHAR("b") INT64(1)] [VARCHAR("c") INT64(2)]]`) mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches("select avg(val2) from (select id, val2 from aggr_test where val2 is null limit 2) as x", "[[NULL]]") mcmp.AssertMatchesNoOrder("select val1, avg(val2) from (select val1, val2 from aggr_test limit 8) as x group by val1", `[[NULL DECIMAL(2.0000)] [VARCHAR("a") DECIMAL(3.5000)] [VARCHAR("b") DECIMAL(1.0000)] [VARCHAR("c") DECIMAL(3.5000)]]`) }) @@ -384,7 +379,6 @@ func TestAggOnTopOfLimit(t *testing.T) { mcmp.AssertMatches("select count(val2), sum(val2) from (select id, val2 from aggr_test where val2 is null limit 2) as x", "[[INT64(0) NULL]]") mcmp.AssertMatches("select val1, count(*), sum(id) from (select id, val1 from aggr_test where val2 < 4 order by val1 limit 2) as x group by val1", `[[NULL INT64(1) DECIMAL(7)] [VARCHAR("a") INT64(1) DECIMAL(2)]]`) mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches("select count(*), sum(val1), avg(val1) from (select id, val1 from aggr_test where val2 < 4 order by val1 desc limit 2) as x", "[[INT64(2) FLOAT64(0) FLOAT64(0)]]") mcmp.AssertMatches("select count(val1), sum(id), avg(id) from (select id, val1 from aggr_test where val2 < 4 order by val1 desc limit 2) as x", "[[INT64(2) DECIMAL(7) DECIMAL(3.5000)]]") mcmp.AssertMatchesNoOrder("select val1, count(val2), sum(val2), avg(val2) from (select val1, val2 from aggr_test limit 8) as x group by val1", @@ -406,7 +400,6 @@ func TestEmptyTableAggr(t *testing.T) { mcmp.AssertMatches(" select t1.`name`, count(*) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]") mcmp.AssertMatches(" select t1.`name`, count(*) from t1 inner join t2 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]") mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches(" select count(t1.value) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[INT64(0)]]") mcmp.AssertMatches(" select avg(t1.value) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[NULL]]") }) @@ -422,7 +415,6 @@ func TestEmptyTableAggr(t *testing.T) { mcmp.AssertMatches(" select count(*) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[INT64(0)]]") mcmp.AssertMatches(" select t1.`name`, count(*) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]") mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches(" select count(t1.value) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[INT64(0)]]") mcmp.AssertMatches(" select avg(t1.value) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[NULL]]") mcmp.AssertMatches(" select t1.`name`, count(*) from t1 inner join t2 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]") @@ -471,7 +463,6 @@ func TestAggregateLeftJoin(t *testing.T) { mcmp.AssertMatches("SELECT count(*) FROM t2 LEFT JOIN t1 ON t1.t1_id = t2.id WHERE IFNULL(t1.name, 'NOTSET') = 'r'", `[[INT64(1)]]`) mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches("SELECT avg(t1.shardkey) FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[DECIMAL(0.5000)]]`) mcmp.AssertMatches("SELECT avg(t2.shardkey) FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[DECIMAL(1.0000)]]`) aggregations := []string{ @@ -528,7 +519,6 @@ func TestScalarAggregate(t *testing.T) { mcmp.Exec("insert into aggr_test(id, val1, val2) values(1,'a',1), (2,'A',1), (3,'b',1), (4,'c',3), (5,'c',4)") mcmp.AssertMatches("select count(distinct val1) from aggr_test", `[[INT64(3)]]`) mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.AssertMatches("select avg(val1) from aggr_test", `[[FLOAT64(0)]]`) }) } @@ -588,15 +578,11 @@ func TestComplexAggregation(t *testing.T) { mcmp.Exec(`SELECT name+COUNT(t1_id)+1 FROM t1 GROUP BY name`) mcmp.Exec(`SELECT COUNT(*)+shardkey+MIN(t1_id)+1+MAX(t1_id)*SUM(t1_id)+1+name FROM t1 GROUP BY shardkey, name`) mcmp.Run("Average in sharded query", func(mcmp *utils.MySQLCompare) { - mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate") mcmp.Exec(`SELECT COUNT(t1_id)+MAX(shardkey)+AVG(t1_id) FROM t1`) }) } func TestJoinAggregation(t *testing.T) { - // This is new functionality in Vitess 20 - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -793,7 +779,6 @@ 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() diff --git a/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go b/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go index b76ae5a35c7..5e3be7c7eff 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go +++ b/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go @@ -18,12 +18,20 @@ package dml import ( "fmt" + "maps" "math/rand/v2" "strconv" "strings" + "sync" "testing" + "time" + + "github.com/stretchr/testify/require" + mapsx "golang.org/x/exp/maps" + "google.golang.org/protobuf/encoding/protojson" "vitess.io/vitess/go/test/endtoend/utils" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) type testQuery struct { @@ -127,7 +135,7 @@ func BenchmarkShardedTblNoLookup(b *testing.B) { } for _, rows := range []int{1, 10, 100, 500, 1000, 5000, 10000} { insStmt := tq.getInsertQuery(rows) - b.Run(fmt.Sprintf("16-shards-%d-rows", rows), func(b *testing.B) { + b.Run(fmt.Sprintf("4-shards-%d-rows", rows), func(b *testing.B) { for i := 0; i < b.N; i++ { _ = utils.Exec(b, conn, insStmt) } @@ -150,7 +158,7 @@ func BenchmarkShardedTblUpdateIn(b *testing.B) { _ = utils.Exec(b, conn, insStmt) for _, rows := range []int{1, 10, 100, 500, 1000, 5000, 10000} { updStmt := tq.getUpdateQuery(rows) - b.Run(fmt.Sprintf("16-shards-%d-rows", rows), func(b *testing.B) { + b.Run(fmt.Sprintf("4-shards-%d-rows", rows), func(b *testing.B) { for i := 0; i < b.N; i++ { _ = utils.Exec(b, conn, updStmt) } @@ -168,7 +176,7 @@ func BenchmarkShardedTblDeleteIn(b *testing.B) { insStmt := tq.getInsertQuery(rows) _ = utils.Exec(b, conn, insStmt) delStmt := tq.getDeleteQuery(rows) - b.Run(fmt.Sprintf("16-shards-%d-rows", rows), func(b *testing.B) { + b.Run(fmt.Sprintf("4-shards-%d-rows", rows), func(b *testing.B) { for i := 0; i < b.N; i++ { _ = utils.Exec(b, conn, delStmt) } @@ -197,3 +205,175 @@ func BenchmarkShardedAggrPushDown(b *testing.B) { } } } + +var mirrorInitOnce sync.Once + +func BenchmarkMirror(b *testing.B) { + const numRows = 10000 + + conn, closer := start(b) + defer closer() + + // Each time this BenchmarkMirror runs, use a different source of + // randomness. But use the same source of randomness across test cases and + // mirror percentages sub test cases. + pcg := rand.NewPCG(rand.Uint64(), rand.Uint64()) + + ksTables := map[string]string{ + sKs2: "mirror_tbl1", + sKs3: "mirror_tbl2", + } + targetKeyspaces := mapsx.Keys(ksTables) + + mirrorInitOnce.Do(func() { + b.Logf("seeding database for benchmark...") + + for i := 0; i < numRows; i++ { + _, err := conn.ExecuteFetch( + fmt.Sprintf("INSERT INTO %s.mirror_tbl1(id) VALUES(%d)", sKs1, i), -1, false) + require.NoError(b, err) + + _, err = conn.ExecuteFetch( + fmt.Sprintf("INSERT INTO %s.mirror_tbl2(id) VALUES(%d)", sKs1, i), -1, false) + require.NoError(b, err) + } + + _, err := conn.ExecuteFetch( + fmt.Sprintf("SELECT COUNT(id) FROM %s.%s", sKs1, "mirror_tbl1"), 1, false) + require.NoError(b, err) + + b.Logf("finished (inserted %d rows)", numRows) + + b.Logf("using MoveTables to copy data from source keyspace to target keyspaces") + + // Set up MoveTables workflows, which is (at present) the only way to set up + // mirror rules. + for tks, tbl := range ksTables { + output, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "MoveTables", "--target-keyspace", tks, "--workflow", fmt.Sprintf("%s2%s", sKs1, tks), + "create", "--source-keyspace", sKs1, "--tables", tbl) + require.NoError(b, err, output) + } + + // Wait for tables to be copied from source to targets. + pending := make(map[string]string, len(ksTables)) + maps.Copy(pending, ksTables) + for len(pending) > 0 { + for tks := range ksTables { + output, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "Workflow", "--keyspace", tks, "show", "--workflow", fmt.Sprintf("%s2%s", sKs1, tks)) + require.NoError(b, err, output) + + var response vtctldatapb.GetWorkflowsResponse + require.NoError(b, protojson.Unmarshal([]byte(output), &response)) + + require.Len(b, response.Workflows, 1) + workflow := response.Workflows[0] + + require.Len(b, workflow.ShardStreams, 4 /*shards*/) + for _, ss := range workflow.ShardStreams { + for _, s := range ss.Streams { + if s.State == "Running" { + delete(pending, tks) + } else { + b.Logf("waiting for workflow %s.%s stream %s=>%s to be running; last state: %s", + workflow.Target, workflow.Name, s.BinlogSource.Shard, s.Shard, s.State) + time.Sleep(1 * time.Second) + } + } + } + } + } + }) + + testCases := []struct { + name string + run func(*testing.B, *rand.Rand) + }{ + { + name: "point select, { sks1 => sks2 }.mirror_tbl1", + run: func(b *testing.B, rnd *rand.Rand) { + for i := 0; i < b.N; i++ { + id := rnd.Int32N(numRows) + _, err := conn.ExecuteFetch(fmt.Sprintf( + "SELECT t1.id FROM %s.mirror_tbl1 AS t1 WHERE t1.id = %d", + sKs1, id, + ), 1, false) + if err != nil { + b.Error(err) + } + } + }, + }, + { + name: "point select, { sks1 => sks2 }.mirror_tbl1, { sks1 => sks3 }.mirror_tbl2", + run: func(b *testing.B, rnd *rand.Rand) { + for i := 0; i < b.N; i++ { + id := rnd.Int32N(numRows) + _, err := conn.ExecuteFetch(fmt.Sprintf( + "SELECT t1.id, t2.id FROM %s.mirror_tbl1 AS t1, %s.mirror_tbl2 AS t2 WHERE t1.id = %d AND t2.id = %d", + sKs1, sKs1, id, id, + ), 1, false) + if err != nil { + b.Error(err) + } + } + }, + }, + } + + for _, tc := range testCases { + b.Run(tc.name, func(b *testing.B) { + b.Run("mirror 0%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 0) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 1%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 1) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 5%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 5) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 10%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 10) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 25%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 25) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 50%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 50) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + + b.Run("mirror 100%", func(b *testing.B) { + mirrorTraffic(b, targetKeyspaces, 100) + b.ResetTimer() + tc.run(b, rand.New(pcg)) + }) + }) + } +} + +func mirrorTraffic(b *testing.B, targetKeyspaces []string, percent float32) { + for _, tks := range targetKeyspaces { + output, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "MoveTables", "--target-keyspace", tks, "--workflow", fmt.Sprintf("%s2%s", sKs1, tks), + "mirrortraffic", "--percent", fmt.Sprintf("%.02f", percent)) + require.NoError(b, err, output) + } +} diff --git a/go/test/endtoend/vtgate/queries/benchmark/main_test.go b/go/test/endtoend/vtgate/queries/benchmark/main_test.go index 6978d0b9428..40a215c8007 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/main_test.go +++ b/go/test/endtoend/vtgate/queries/benchmark/main_test.go @@ -20,8 +20,10 @@ import ( "context" _ "embed" "flag" + "fmt" "os" "testing" + "time" "github.com/stretchr/testify/require" @@ -34,36 +36,34 @@ var ( clusterInstance *cluster.LocalProcessCluster vtParams mysql.ConnParams mysqlParams mysql.ConnParams - sKs = "sks" - uKs = "uks" + sKs1 = "sks1" + sKs2 = "sks2" + sKs3 = "sks3" cell = "test" - //go:embed sharded_schema.sql - sSchemaSQL string + //go:embed sharded_schema1.sql + sSchemaSQL1 string - //go:embed vschema.json - sVSchema string -) + //go:embed vschema1.json + sVSchema1 string -var ( - shards4 = []string{ - "-40", "40-80", "80-c0", "c0-", - } + //go:embed sharded_schema2.sql + sSchemaSQL2 string - shards8 = []string{ - "-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-", - } + //go:embed vschema2.json + sVSchema2 string - shards16 = []string{ - "-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-a0", "a0-b0", "b0-c0", "c0-d0", "d0-e0", "e0-f0", "f0-", - } + //go:embed sharded_schema3.sql + sSchemaSQL3 string - shards32 = []string{ - "-05", "05-10", "10-15", "15-20", "20-25", "25-30", "30-35", "35-40", "40-45", "45-50", "50-55", "55-60", "60-65", "65-70", "70-75", "75-80", - "80-85", "85-90", "90-95", "95-a0", "a0-a5", "a5-b0", "b0-b5", "b5-c0", "c0-c5", "c5-d0", "d0-d5", "d5-e0", "e0-e5", "e5-f0", "f0-f5", "f5-", - } + //go:embed vschema3.json + sVSchema3 string ) +var shards4 = []string{ + "-40", "40-80", "80-c0", "c0-", +} + func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() @@ -78,14 +78,38 @@ func TestMain(m *testing.M) { return 1 } - // Start sharded keyspace - sKeyspace := &cluster.Keyspace{ - Name: sKs, - SchemaSQL: sSchemaSQL, - VSchema: sVSchema, + // Start sharded keyspace 1 + sKeyspace1 := &cluster.Keyspace{ + Name: sKs1, + SchemaSQL: sSchemaSQL1, + VSchema: sVSchema1, } - err = clusterInstance.StartKeyspace(*sKeyspace, shards4, 0, false) + err = clusterInstance.StartKeyspace(*sKeyspace1, shards4, 0, false) + if err != nil { + return 1 + } + + // Start sharded keyspace 2 + sKeyspace2 := &cluster.Keyspace{ + Name: sKs2, + SchemaSQL: sSchemaSQL2, + VSchema: sVSchema2, + } + + err = clusterInstance.StartKeyspace(*sKeyspace2, shards4, 0, false) + if err != nil { + return 1 + } + + // Start sharded keyspace 3 + sKeyspace3 := &cluster.Keyspace{ + Name: sKs3, + SchemaSQL: sSchemaSQL3, + VSchema: sVSchema3, + } + + err = clusterInstance.StartKeyspace(*sKeyspace3, shards4, 0, false) if err != nil { return 1 } @@ -96,7 +120,7 @@ func TestMain(m *testing.M) { return 1 } - vtParams = clusterInstance.GetVTParams(sKs) + vtParams = clusterInstance.GetVTParams("@primary") return m.Run() }() @@ -108,12 +132,38 @@ func start(b *testing.B) (*mysql.Conn, func()) { require.NoError(b, err) deleteAll := func() { - tables := []string{"tbl_no_lkp_vdx"} + tables := []string{ + fmt.Sprintf("%s.tbl_no_lkp_vdx", sKs1), + fmt.Sprintf("%s.mirror_tbl1", sKs1), + fmt.Sprintf("%s.mirror_tbl2", sKs1), + fmt.Sprintf("%s.mirror_tbl1", sKs2), + fmt.Sprintf("%s.mirror_tbl2", sKs3), + } for _, table := range tables { _, _ = utils.ExecAllowError(b, conn, "delete from "+table) } } + // Make sure all keyspaces are serving. + pending := map[string]string{ + sKs1: "mirror_tbl1", + sKs2: "mirror_tbl1", + sKs3: "mirror_tbl2", + } + for len(pending) > 0 { + for ks, tbl := range pending { + _, err := conn.ExecuteFetch( + fmt.Sprintf("SELECT COUNT(id) FROM %s.%s", ks, tbl), 1, false) + if err != nil { + b.Logf("waiting for keyspace %s to be serving; last error: %v", ks, err) + time.Sleep(1 * time.Second) + } else { + delete(pending, ks) + } + } + } + + // Delete any pre-existing data. deleteAll() return conn, func() { diff --git a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema1.sql similarity index 76% rename from go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql rename to go/test/endtoend/vtgate/queries/benchmark/sharded_schema1.sql index 92f63c40f0f..d83ffefa7ec 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql +++ b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema1.sql @@ -30,4 +30,16 @@ create table user_extra not_sharding_key bigint, col varchar(50), primary key (id) -); \ No newline at end of file +); + +create table mirror_tbl1 +( + id bigint not null, + primary key(id) +) Engine = InnoDB; + +create table mirror_tbl2 +( + id bigint not null, + primary key(id) +) Engine = InnoDB; diff --git a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema2.sql b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema2.sql new file mode 100644 index 00000000000..4cba88b68ab --- /dev/null +++ b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema2.sql @@ -0,0 +1,5 @@ +create table mirror_tbl1 +( + id bigint not null, + primary key(id) +) Engine = InnoDB; diff --git a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema3.sql b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema3.sql new file mode 100644 index 00000000000..e7e96f30357 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema3.sql @@ -0,0 +1,5 @@ +create table mirror_tbl2 +( + id bigint not null, + primary key(id) +) Engine = InnoDB; diff --git a/go/test/endtoend/vtgate/queries/benchmark/vschema.json b/go/test/endtoend/vtgate/queries/benchmark/vschema1.json similarity index 64% rename from go/test/endtoend/vtgate/queries/benchmark/vschema.json rename to go/test/endtoend/vtgate/queries/benchmark/vschema1.json index efc854af8ff..0e5366ba89f 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/vschema.json +++ b/go/test/endtoend/vtgate/queries/benchmark/vschema1.json @@ -29,6 +29,22 @@ "name": "xxhash" } ] + }, + "mirror_tbl1": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] + }, + "mirror_tbl2": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] } } -} \ No newline at end of file +} diff --git a/go/test/endtoend/vtgate/queries/benchmark/vschema2.json b/go/test/endtoend/vtgate/queries/benchmark/vschema2.json new file mode 100644 index 00000000000..2ae87ad2ae4 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/benchmark/vschema2.json @@ -0,0 +1,18 @@ +{ + "sharded": true, + "vindexes": { + "xxhash": { + "type": "xxhash" + } + }, + "tables": { + "mirror_tbl1": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] + } + } +} diff --git a/go/test/endtoend/vtgate/queries/benchmark/vschema3.json b/go/test/endtoend/vtgate/queries/benchmark/vschema3.json new file mode 100644 index 00000000000..6e71d6bc157 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/benchmark/vschema3.json @@ -0,0 +1,18 @@ +{ + "sharded": true, + "vindexes": { + "xxhash": { + "type": "xxhash" + } + }, + "tables": { + "mirror_tbl2": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] + } + } +} diff --git a/go/test/endtoend/vtgate/queries/derived/cte_test.go b/go/test/endtoend/vtgate/queries/derived/cte_test.go index 54d97261ae6..131342a8562 100644 --- a/go/test/endtoend/vtgate/queries/derived/cte_test.go +++ b/go/test/endtoend/vtgate/queries/derived/cte_test.go @@ -18,12 +18,9 @@ package misc import ( "testing" - - "vitess.io/vitess/go/test/endtoend/utils" ) func TestCTEWithOrderByLimit(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -31,7 +28,6 @@ func TestCTEWithOrderByLimit(t *testing.T) { } func TestCTEAggregationOnRHS(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -40,7 +36,6 @@ func TestCTEAggregationOnRHS(t *testing.T) { } func TestCTERemoveInnerOrderBy(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -48,7 +43,6 @@ func TestCTERemoveInnerOrderBy(t *testing.T) { } func TestCTEWithHaving(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -59,7 +53,6 @@ func TestCTEWithHaving(t *testing.T) { } func TestCTEColumns(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -68,7 +61,6 @@ func TestCTEColumns(t *testing.T) { } func TestCTEAggregationsInUnion(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/derived/derived_test.go b/go/test/endtoend/vtgate/queries/derived/derived_test.go index c41161d9bcf..cb106564b2f 100644 --- a/go/test/endtoend/vtgate/queries/derived/derived_test.go +++ b/go/test/endtoend/vtgate/queries/derived/derived_test.go @@ -92,7 +92,6 @@ func TestDerivedTableColumns(t *testing.T) { // We do this by not using the apply join we usually use, and instead use the hash join engine primitive // These tests exercise these situations func TestDerivedTablesWithLimit(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") // We need full type info before planning this, so we wait for the schema tracker require.NoError(t, utils.WaitForAuthoritative(t, keyspaceName, "user", clusterInstance.VtgateProcess.ReadVSchema)) @@ -116,7 +115,6 @@ func TestDerivedTablesWithLimit(t *testing.T) { // TestDerivedTableColumnAliasWithJoin tests the derived table having alias column and using it in the join condition func TestDerivedTableColumnAliasWithJoin(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/dml/dml_test.go b/go/test/endtoend/vtgate/queries/dml/dml_test.go index 4383f59e6c4..061cc4b9b36 100644 --- a/go/test/endtoend/vtgate/queries/dml/dml_test.go +++ b/go/test/endtoend/vtgate/queries/dml/dml_test.go @@ -47,8 +47,6 @@ func TestMultiEqual(t *testing.T) { // TestMultiTableDelete executed multi-table delete queries func TestMultiTableDelete(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") - mcmp, closer := start(t) defer closer() @@ -78,8 +76,6 @@ func TestMultiTableDelete(t *testing.T) { // TestDeleteWithLimit executed delete queries with limit func TestDeleteWithLimit(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") - mcmp, closer := start(t) defer closer() @@ -133,8 +129,6 @@ func TestDeleteWithLimit(t *testing.T) { // TestUpdateWithLimit executed update queries with limit func TestUpdateWithLimit(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -191,8 +185,6 @@ func TestUpdateWithLimit(t *testing.T) { // TestMultiTableUpdate executed multi-table update queries func TestMultiTableUpdate(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -222,8 +214,6 @@ func TestMultiTableUpdate(t *testing.T) { // TestDeleteWithSubquery executed delete queries with subqueries func TestDeleteWithSubquery(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -268,8 +258,6 @@ func TestDeleteWithSubquery(t *testing.T) { // TestMultiTargetDelete executed multi-target delete queries func TestMultiTargetDelete(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -299,8 +287,6 @@ func TestMultiTargetDelete(t *testing.T) { // TestMultiTargetDeleteMore executed multi-target delete queries with additional cases func TestMultiTargetDeleteMore(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -337,8 +323,6 @@ func TestMultiTargetDeleteMore(t *testing.T) { // TestMultiTargetUpdate executed multi-target update queries func TestMultiTargetUpdate(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -368,8 +352,6 @@ func TestMultiTargetUpdate(t *testing.T) { // TestMultiTargetNonLiteralUpdate executed multi-target update queries with non-literal values. func TestMultiTargetNonLiteralUpdate(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -400,8 +382,6 @@ func TestMultiTargetNonLiteralUpdate(t *testing.T) { // TestDMLInUnique for update/delete statement using an IN clause with the Vindexes, // the query is correctly split according to the corresponding values in the IN list. func TestDMLInUnique(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/dml/insert_test.go b/go/test/endtoend/vtgate/queries/dml/insert_test.go index 026f53fe961..9e89f4f5f3e 100644 --- a/go/test/endtoend/vtgate/queries/dml/insert_test.go +++ b/go/test/endtoend/vtgate/queries/dml/insert_test.go @@ -21,9 +21,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/utils" ) @@ -56,8 +54,6 @@ func TestSimpleInsertSelect(t *testing.T) { // TestInsertOnDup test the insert on duplicate key update feature with argument and list argument. func TestInsertOnDup(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -92,19 +88,10 @@ func TestFailureInsertSelect(t *testing.T) { // primary key same mcmp.AssertContainsError("insert into s_tbl(id, num) select id, num*20 from s_tbl where id = 1", `AlreadyExists desc = Duplicate entry '1' for key`) // lookup key same (does not fail on MySQL as there is no lookup, and we have not put unique constraint on num column) - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - if vtgateVersion >= 19 { - utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `(errno 1062) (sqlstate 23000)`) - // mismatch column count - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count with the row`) - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count with the row`) - } else { - utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `lookup.Create: Code: ALREADY_EXISTS`) - // mismatch column count - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count at row 1`) - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count at row 1`) - } + utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `(errno 1062) (sqlstate 23000)`) + // mismatch column count + mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count with the row`) + mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count with the row`) }) } } @@ -486,9 +473,6 @@ func TestMixedCases(t *testing.T) { // TestInsertAlias test the alias feature in insert statement. func TestInsertAlias(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - utils.SkipIfBinaryIsBelowVersion(t, 20, "vttablet") - mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/informationschema/informationschema_test.go b/go/test/endtoend/vtgate/queries/informationschema/informationschema_test.go index ec55711a31f..c5568b2db49 100644 --- a/go/test/endtoend/vtgate/queries/informationschema/informationschema_test.go +++ b/go/test/endtoend/vtgate/queries/informationschema/informationschema_test.go @@ -200,7 +200,7 @@ func TestMultipleSchemaPredicates(t *testing.T) { "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", keyspaceName, keyspaceName, "a") _, err := mcmp.VtConn.ExecuteFetch(query, 1000, true) require.Error(t, err) - require.Contains(t, err.Error(), "specifying two different database in the query is not supported") + require.ErrorContains(t, err, "specifying two different database in the query is not supported") if utils.BinaryIsAtLeastAtVersion(20, "vtgate") { _, _ = mcmp.ExecNoCompare("select * from information_schema.columns where table_schema = '' limit 1") @@ -225,8 +225,6 @@ func TestInfrSchemaAndUnionAll(t *testing.T) { } func TestInfoschemaTypes(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") - require.NoError(t, utils.WaitForAuthoritative(t, "ks", "t1", clusterInstance.VtgateProcess.ReadVSchema)) @@ -245,9 +243,7 @@ func TestInfoschemaTypes(t *testing.T) { } func TestTypeORMQuery(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") // This test checks that we can run queries similar to the ones that the TypeORM framework uses - require.NoError(t, utils.WaitForAuthoritative(t, "ks", "t1", clusterInstance.VtgateProcess.ReadVSchema)) @@ -294,7 +290,6 @@ WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 't2'; } func TestJoinWithSingleShardQueryOnRHS(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") // This test checks that we can run queries like this, where the RHS is a single shard query mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/misc/misc_test.go b/go/test/endtoend/vtgate/queries/misc/misc_test.go index e43171b6701..8e47bb8581a 100644 --- a/go/test/endtoend/vtgate/queries/misc/misc_test.go +++ b/go/test/endtoend/vtgate/queries/misc/misc_test.go @@ -60,15 +60,8 @@ func TestBitVals(t *testing.T) { mcmp.AssertMatches(`select b'1001', 0x9, B'010011011010'`, `[[VARBINARY("\t") VARBINARY("\t") VARBINARY("\x04\xda")]]`) mcmp.AssertMatches(`select b'1001', 0x9, B'010011011010' from t1`, `[[VARBINARY("\t") VARBINARY("\t") VARBINARY("\x04\xda")]]`) - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - if vtgateVersion >= 19 { - mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010'`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[INT64(10) UINT64(11) INT64(1245)]]`) - mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010' from t1`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[INT64(10) UINT64(11) INT64(1245)]]`) - } else { - mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010'`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[UINT64(10) UINT64(11) UINT64(1245)]]`) - mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010' from t1`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[UINT64(10) UINT64(11) UINT64(1245)]]`) - } + mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010'`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[INT64(10) UINT64(11) INT64(1245)]]`) + mcmp.AssertMatchesNoCompare(`select 1 + b'1001', 2 + 0x9, 3 + B'010011011010' from t1`, `[[INT64(10) UINT64(11) INT64(1245)]]`, `[[INT64(10) UINT64(11) INT64(1245)]]`) } // TestTimeFunctionWithPrecision tests that inserting data with NOW(1) works as intended. @@ -140,7 +133,6 @@ func TestCast(t *testing.T) { // TestVindexHints tests that vindex hints work as intended. func TestVindexHints(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() @@ -323,8 +315,6 @@ func TestAnalyze(t *testing.T) { // TestTransactionModeVar executes SELECT on `transaction_mode` variable func TestTransactionModeVar(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") - mcmp, closer := start(t) defer closer() @@ -356,8 +346,6 @@ func TestTransactionModeVar(t *testing.T) { // TestAliasesInOuterJoinQueries tests that aliases work in queries that have outer join clauses. func TestAliasesInOuterJoinQueries(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() @@ -371,10 +359,12 @@ func TestAliasesInOuterJoinQueries(t *testing.T) { mcmp.ExecWithColumnCompare("select t1.id1 as t0, t1.id1 as t1, tbl.unq_col as col from t1 left outer join tbl on t1.id2 = tbl.nonunq_col order by t1.id2 limit 2 offset 2") mcmp.ExecWithColumnCompare("select t1.id1 as t0, t1.id1 as t1, count(*) as leCount from t1 left outer join tbl on t1.id2 = tbl.nonunq_col group by 1, t1") mcmp.ExecWithColumnCompare("select t.id1, t.id2, derived.unq_col from t1 t join (select id, unq_col, nonunq_col from tbl) as derived on t.id2 = derived.nonunq_col") + if utils.BinaryIsAtLeastAtVersion(21, "vtgate") { + mcmp.ExecWithColumnCompare("select * from t1 t left join tbl on t.id1 = 666 and t.id2 = tbl.id") + } } func TestAlterTableWithView(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() @@ -428,7 +418,6 @@ func TestAlterTableWithView(t *testing.T) { // TestStraightJoin tests that Vitess respects the ordering of join in a STRAIGHT JOIN query. func TestStraightJoin(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() @@ -454,7 +443,6 @@ func TestStraightJoin(t *testing.T) { } func TestColumnAliases(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() @@ -463,7 +451,6 @@ func TestColumnAliases(t *testing.T) { } func TestHandleNullableColumn(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") require.NoError(t, utils.WaitForAuthoritative(t, keyspaceName, "tbl", clusterInstance.VtgateProcess.ReadVSchema)) mcmp, closer := start(t) @@ -477,8 +464,6 @@ func TestHandleNullableColumn(t *testing.T) { } func TestEnumSetVals(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() require.NoError(t, utils.WaitForAuthoritative(t, keyspaceName, "tbl_enum_set", clusterInstance.VtgateProcess.ReadVSchema)) diff --git a/go/test/endtoend/vtgate/queries/orderby/orderby_test.go b/go/test/endtoend/vtgate/queries/orderby/orderby_test.go index e8d8d4bfef1..c36b52a4e6a 100644 --- a/go/test/endtoend/vtgate/queries/orderby/orderby_test.go +++ b/go/test/endtoend/vtgate/queries/orderby/orderby_test.go @@ -86,8 +86,6 @@ func TestOrderBy(t *testing.T) { func TestOrderByComplex(t *testing.T) { // tests written to try to trick the ORDER BY engine and planner - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/reference/main_test.go b/go/test/endtoend/vtgate/queries/reference/main_test.go index 4c9440ca4ff..c350038bf6e 100644 --- a/go/test/endtoend/vtgate/queries/reference/main_test.go +++ b/go/test/endtoend/vtgate/queries/reference/main_test.go @@ -18,6 +18,7 @@ package reference import ( "context" + _ "embed" "flag" "fmt" "os" @@ -39,68 +40,16 @@ var ( vtParams mysql.ConnParams unshardedKeyspaceName = "uks" - unshardedSQLSchema = ` - CREATE TABLE IF NOT EXISTS zip( - id BIGINT NOT NULL AUTO_INCREMENT, - code5 INT(5) NOT NULL, - PRIMARY KEY(id) - ) ENGINE=InnoDB; + //go:embed uschema.sql + unshardedSQLSchema string + //go:embed uvschema.json + unshardedVSchema string - INSERT INTO zip(id, code5) - VALUES (1, 47107), - (2, 82845), - (3, 11237); - - CREATE TABLE IF NOT EXISTS zip_detail( - id BIGINT NOT NULL AUTO_INCREMENT, - zip_id BIGINT NOT NULL, - discontinued_at DATE, - PRIMARY KEY(id) - ) ENGINE=InnoDB; - - ` - unshardedVSchema = ` - { - "sharded":false, - "tables": { - "zip": {}, - "zip_detail": {} - } - } - ` shardedKeyspaceName = "sks" - shardedSQLSchema = ` - CREATE TABLE IF NOT EXISTS delivery_failure ( - id BIGINT NOT NULL, - zip_detail_id BIGINT NOT NULL, - reason VARCHAR(255), - PRIMARY KEY(id) - ) ENGINE=InnoDB; - ` - shardedVSchema = ` - { - "sharded": true, - "vindexes": { - "hash": { - "type": "hash" - } - }, - "tables": { - "delivery_failure": { - "columnVindexes": [ - { - "column": "id", - "name": "hash" - } - ] - }, - "zip_detail": { - "type": "reference", - "source": "` + unshardedKeyspaceName + `.zip_detail" - } - } - } - ` + //go:embed sschema.sql + shardedSQLSchema string + //go:embed svschema.json + shardedVSchema string ) func TestMain(m *testing.M) { diff --git a/go/test/endtoend/vtgate/queries/reference/reference_test.go b/go/test/endtoend/vtgate/queries/reference/reference_test.go index 0e3096e6064..08e9cbe13b1 100644 --- a/go/test/endtoend/vtgate/queries/reference/reference_test.go +++ b/go/test/endtoend/vtgate/queries/reference/reference_test.go @@ -84,20 +84,19 @@ func TestReferenceRouting(t *testing.T) { ) t.Run("Complex reference query", func(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") // Verify a complex query using reference tables with a left join having a derived table with an order by clause works as intended. utils.AssertMatches( t, conn, `SELECT t.id FROM ( - SELECT zd.id, zd.zip_id - FROM `+shardedKeyspaceName+`.zip_detail AS zd - WHERE zd.id IN (2) - ORDER BY zd.discontinued_at - LIMIT 1 - ) AS t - LEFT JOIN `+shardedKeyspaceName+`.zip_detail AS t0 ON t.zip_id = t0.zip_id - ORDER BY t.id`, + SELECT zd.id, zd.zip_id + FROM `+shardedKeyspaceName+`.zip_detail AS zd + WHERE zd.id IN (2) + ORDER BY zd.discontinued_at + LIMIT 1 + ) AS t + LEFT JOIN `+shardedKeyspaceName+`.zip_detail AS t0 ON t.zip_id = t0.zip_id + ORDER BY t.id`, `[[INT64(2)]]`, ) }) @@ -156,3 +155,19 @@ func TestReferenceRouting(t *testing.T) { `[[INT64(2)]]`, ) } + +// TestMultiReferenceQuery tests that a query with multiple references with unsharded keyspace and sharded keyspace works with join. +func TestMultiReferenceQuery(t *testing.T) { + utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") + conn, closer := start(t) + defer closer() + + query := + `select 1 + from delivery_failure df1 + join delivery_failure df2 on df1.id = df2.id + join uks.zip_detail zd1 on df1.zip_detail_id = zd1.zip_id + join uks.zip_detail zd2 on zd1.zip_id = zd2.zip_id` + + utils.Exec(t, conn, query) +} diff --git a/go/test/endtoend/vtgate/queries/reference/sschema.sql b/go/test/endtoend/vtgate/queries/reference/sschema.sql new file mode 100644 index 00000000000..0fcaf63a422 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/reference/sschema.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS delivery_failure ( + id BIGINT NOT NULL, + zip_detail_id BIGINT NOT NULL, + reason VARCHAR(255), + PRIMARY KEY(id) +) ENGINE=InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/reference/svschema.json b/go/test/endtoend/vtgate/queries/reference/svschema.json new file mode 100644 index 00000000000..815e0e8d21c --- /dev/null +++ b/go/test/endtoend/vtgate/queries/reference/svschema.json @@ -0,0 +1,22 @@ +{ + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "delivery_failure": { + "columnVindexes": [ + { + "column": "id", + "name": "hash" + } + ] + }, + "zip_detail": { + "type": "reference", + "source": "uks.zip_detail" + } + } +} \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/reference/uschema.sql b/go/test/endtoend/vtgate/queries/reference/uschema.sql new file mode 100644 index 00000000000..52737928469 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/reference/uschema.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS zip( + id BIGINT NOT NULL AUTO_INCREMENT, + code5 INT(5) NOT NULL, + PRIMARY KEY(id) +) ENGINE=InnoDB; + +INSERT INTO zip(id, code5) +VALUES (1, 47107), + (2, 82845), + (3, 11237); + +CREATE TABLE IF NOT EXISTS zip_detail( + id BIGINT NOT NULL AUTO_INCREMENT, + zip_id BIGINT NOT NULL, + discontinued_at DATE, + PRIMARY KEY(id) +) ENGINE=InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/reference/uvschema.json b/go/test/endtoend/vtgate/queries/reference/uvschema.json new file mode 100644 index 00000000000..fdcfca0d7a9 --- /dev/null +++ b/go/test/endtoend/vtgate/queries/reference/uvschema.json @@ -0,0 +1,6 @@ +{ + "tables": { + "zip": {}, + "zip_detail": {} + } +} \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/subquery/subquery_test.go b/go/test/endtoend/vtgate/queries/subquery/subquery_test.go index eb949e1c697..74af6634198 100644 --- a/go/test/endtoend/vtgate/queries/subquery/subquery_test.go +++ b/go/test/endtoend/vtgate/queries/subquery/subquery_test.go @@ -162,7 +162,6 @@ func TestSubqueryInReference(t *testing.T) { // TestSubqueryInAggregation validates that subquery work inside aggregation functions. func TestSubqueryInAggregation(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vtgate") mcmp, closer := start(t) defer closer() @@ -180,7 +179,6 @@ func TestSubqueryInAggregation(t *testing.T) { // TestSubqueryInDerivedTable tests that subqueries and derived tables // are handled correctly when there are joins inside the derived table func TestSubqueryInDerivedTable(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() @@ -194,7 +192,6 @@ func TestSubqueries(t *testing.T) { // This method tests many types of subqueries. The queries should move to a vitess-tester test file once we have a way to run them. // The commented out queries are failing because of wrong types being returned. // The tests are commented out until the issue is fixed. - utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") mcmp, closer := start(t) defer closer() queries := []string{ @@ -234,8 +231,6 @@ 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) diff --git a/go/test/endtoend/vtgate/queries/timeout/timeout_test.go b/go/test/endtoend/vtgate/queries/timeout/timeout_test.go index f7bd96dca13..09bbcf8cc96 100644 --- a/go/test/endtoend/vtgate/queries/timeout/timeout_test.go +++ b/go/test/endtoend/vtgate/queries/timeout/timeout_test.go @@ -84,8 +84,8 @@ func TestQueryTimeoutWithTables(t *testing.T) { // the query usually takes more than 5ms to return. So this should fail. _, err := utils.ExecAllowError(t, mcmp.VtConn, "select /*vt+ QUERY_TIMEOUT_MS=1 */ count(*) from uks.unsharded where id1 > 31") require.Error(t, err) - assert.Contains(t, err.Error(), "context deadline exceeded") - assert.Contains(t, err.Error(), "(errno 1317) (sqlstate 70100)") + assert.ErrorContains(t, err, "context deadline exceeded") + assert.ErrorContains(t, err, "(errno 1317) (sqlstate 70100)") // sharded utils.Exec(t, mcmp.VtConn, "insert /*vt+ QUERY_TIMEOUT_MS=1000 */ into ks_misc.t1(id1, id2) values (1,2),(2,4),(3,6),(4,8),(5,10)") @@ -94,14 +94,12 @@ func TestQueryTimeoutWithTables(t *testing.T) { utils.Exec(t, mcmp.VtConn, "select /*vt+ QUERY_TIMEOUT_MS=500 */ sleep(0.1) from t1 where id1 = 1") _, err = utils.ExecAllowError(t, mcmp.VtConn, "select /*vt+ QUERY_TIMEOUT_MS=20 */ sleep(0.1) from t1 where id1 = 1") require.Error(t, err) - assert.Contains(t, err.Error(), "context deadline exceeded") - assert.Contains(t, err.Error(), "(errno 1317) (sqlstate 70100)") + assert.ErrorContains(t, err, "context deadline exceeded") + assert.ErrorContains(t, err, "(errno 1317) (sqlstate 70100)") } // TestQueryTimeoutWithShardTargeting tests the query timeout with shard targeting. func TestQueryTimeoutWithShardTargeting(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") - mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/queries/tpch/tpch_test.go b/go/test/endtoend/vtgate/queries/tpch/tpch_test.go index bd35fe3f67c..c4bf71cafa1 100644 --- a/go/test/endtoend/vtgate/queries/tpch/tpch_test.go +++ b/go/test/endtoend/vtgate/queries/tpch/tpch_test.go @@ -48,7 +48,6 @@ func start(t *testing.T) (utils.MySQLCompare, func()) { } func TestTPCHQueries(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 20, "vtgate") mcmp, closer := start(t) defer closer() err := utils.WaitForColumn(t, clusterInstance.VtgateProcess, keyspaceName, "region", `R_COMMENT`) diff --git a/go/test/endtoend/vtgate/reservedconn/sysvar_test.go b/go/test/endtoend/vtgate/reservedconn/sysvar_test.go index 564cc671d5f..e7e0cfb0259 100644 --- a/go/test/endtoend/vtgate/reservedconn/sysvar_test.go +++ b/go/test/endtoend/vtgate/reservedconn/sysvar_test.go @@ -461,3 +461,35 @@ func TestSysVarTxIsolation(t *testing.T) { // second run, to ensuring the setting is applied on the session and not just on next query after settings. utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `SERIALIZABLE`) } + +// TestSysVarInnodbWaitTimeout tests the innodb_lock_wait_timeout system variable +func TestSysVarInnodbWaitTimeout(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + // default from mysql + utils.AssertMatches(t, conn, "select @@innodb_lock_wait_timeout", `[[UINT64(20)]]`) + utils.AssertMatches(t, conn, "select @@global.innodb_lock_wait_timeout", `[[UINT64(20)]]`) + // ensuring it goes to mysql + utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout", `UINT64(20)`) + utils.AssertContains(t, conn, "select @@global.innodb_lock_wait_timeout", `UINT64(20)`) + + // setting to different value. + utils.Exec(t, conn, "set @@innodb_lock_wait_timeout = 120") + utils.AssertMatches(t, conn, "select @@innodb_lock_wait_timeout", `[[INT64(120)]]`) + // ensuring it goes to mysql + utils.AssertContains(t, conn, "select @@global.innodb_lock_wait_timeout, connection_id()", `UINT64(20)`) + utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout, connection_id()", `INT64(120)`) + // second run, to ensuring the setting is applied on the session and not just on next query after settings. + utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout, connection_id()", `INT64(120)`) + + // changing setting to different value. + utils.Exec(t, conn, "set @@innodb_lock_wait_timeout = 240") + utils.AssertMatches(t, conn, "select @@innodb_lock_wait_timeout", `[[INT64(240)]]`) + // ensuring it goes to mysql + utils.AssertContains(t, conn, "select @@global.innodb_lock_wait_timeout, connection_id()", `UINT64(20)`) + utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout, connection_id()", `INT64(240)`) + // second run, to ensuring the setting is applied on the session and not just on next query after settings. + utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout, connection_id()", `INT64(240)`) +} 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 4c495d257b5..50042f3142a 100644 --- a/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go +++ b/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go @@ -178,13 +178,7 @@ func TestInitAndUpdate(t *testing.T) { require.NoError(t, err) defer conn.Close() - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - - expected := `[[VARCHAR("dual")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - } + expected := `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", expected, @@ -192,18 +186,13 @@ func TestInitAndUpdate(t *testing.T) { 30*time.Second, "initial table list not complete") - if vtgateVersion >= 19 { - utils.AssertMatches(t, conn, - "SHOW VSCHEMA KEYSPACES", - `[[VARCHAR("ks") VARCHAR("true") VARCHAR("unmanaged") VARCHAR("")]]`) - } + utils.AssertMatches(t, conn, + "SHOW VSCHEMA KEYSPACES", + `[[VARCHAR("ks") VARCHAR("true") VARCHAR("unmanaged") VARCHAR("")]]`) // Init _ = utils.Exec(t, conn, "create table test_sc (id bigint primary key)") - expected = `[[VARCHAR("dual")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")]]` - } + expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")]]` utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", expected, @@ -213,10 +202,7 @@ func TestInitAndUpdate(t *testing.T) { // Tables Update via health check. _ = utils.Exec(t, conn, "create table test_sc1 (id bigint primary key)") - expected = `[[VARCHAR("dual")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")] [VARCHAR("test_sc1")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")] [VARCHAR("test_sc1")]]` - } + expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")] [VARCHAR("test_sc")] [VARCHAR("test_sc1")]]` utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", expected, @@ -225,10 +211,7 @@ func TestInitAndUpdate(t *testing.T) { "test_sc1 not in vschema tables") _ = utils.Exec(t, conn, "drop table test_sc, test_sc1") - expected = `[[VARCHAR("dual")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - } + expected = `[[VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", expected, @@ -247,12 +230,7 @@ func TestDMLOnNewTable(t *testing.T) { // create a new table which is not part of the VSchema utils.Exec(t, conn, `create table new_table_tracked(id bigint, name varchar(100), primary key(id)) Engine=InnoDB`) - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - expected := `[[VARCHAR("dual")] [VARCHAR("new_table_tracked")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("new_table_tracked")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` - } + expected := `[[VARCHAR("new_table_tracked")] [VARCHAR("t2")] [VARCHAR("t2_id4_idx")] [VARCHAR("t8")]]` // wait for vttablet's schema reload interval to pass utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", diff --git a/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go b/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go index 257dd7238f3..5ecf89a5db7 100644 --- a/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go +++ b/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go @@ -182,7 +182,6 @@ func TestNewUnshardedTable(t *testing.T) { // creating two tables having the same name differing only in casing, but other operating systems don't. // More information at https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html#:~:text=Table%20names%20are%20stored%20in,lowercase%20on%20storage%20and%20lookup. func TestCaseSensitiveSchemaTracking(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 19, "vttablet") defer cluster.PanicHandler(t) // create a sql connection diff --git a/go/test/endtoend/vtgate/sequence/seq_test.go b/go/test/endtoend/vtgate/sequence/seq_test.go index dd7542becc5..1bda37094b2 100644 --- a/go/test/endtoend/vtgate/sequence/seq_test.go +++ b/go/test/endtoend/vtgate/sequence/seq_test.go @@ -293,7 +293,7 @@ func TestDotTableSeq(t *testing.T) { mysqlErr := err.(*sqlerror.SQLError) assert.Equal(t, sqlerror.ERDupEntry, mysqlErr.Num) assert.Equal(t, "23000", mysqlErr.State) - assert.Contains(t, mysqlErr.Message, "Duplicate entry") + assert.ErrorContains(t, mysqlErr, "Duplicate entry") } func TestInsertAllDefaults(t *testing.T) { diff --git a/go/test/endtoend/vtgate/transaction/twopc/schema.sql b/go/test/endtoend/vtgate/transaction/twopc/schema.sql deleted file mode 100644 index 60a7c19837c..00000000000 --- a/go/test/endtoend/vtgate/transaction/twopc/schema.sql +++ /dev/null @@ -1,12 +0,0 @@ -create table twopc_user ( - id bigint, - name varchar(64), - primary key (id) -) Engine=InnoDB; - -create table twopc_music ( - id varchar(64), - user_id bigint, - title varchar(64), - primary key (id) -) Engine=InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/transaction/twopc/twopc_test.go b/go/test/endtoend/vtgate/transaction/twopc/twopc_test.go deleted file mode 100644 index f18073c5827..00000000000 --- a/go/test/endtoend/vtgate/transaction/twopc/twopc_test.go +++ /dev/null @@ -1,523 +0,0 @@ -/* -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 transaction - -import ( - "context" - _ "embed" - "reflect" - "sort" - "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/test/endtoend/cluster" - "vitess.io/vitess/go/test/endtoend/utils" - binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" - querypb "vitess.io/vitess/go/vt/proto/query" -) - -// TestDTCommit tests distributed transaction commit for insert, update and delete operations -// It verifies the binlog events for the same with transaction state changes and redo statements. -func TestDTCommit(t *testing.T) { - conn, closer := start(t) - defer closer() - - vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) - - // 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, "insert into twopc_user(id, name) values(8,'bar')") - utils.Exec(t, conn, "insert into twopc_user(id, name) values(9,'baz')") - utils.Exec(t, conn, "insert into twopc_user(id, name) values(10,'apa')") - utils.Exec(t, conn, "commit") - - tableMap := make(map[string][]*querypb.Field) - dtMap := make(map[string]string) - logTable := retrieveTransitions(t, ch, tableMap, dtMap) - 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(\"-80\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - }, - "ks.redo_state:-80": { - "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:-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")]`, - `insert:[INT64(10) VARCHAR("apa")]`, - }, - "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)) - - // 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, "update twopc_user set name='newfoo' where id = 8") - utils.Exec(t, conn, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:80-": { - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", - "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\")]", - }, - "ks.redo_state:-80": { - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:-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\")]"}, - } - assert.Equal(t, expectations, logTable, - "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) - - // DELETE from multiple shard - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "delete from twopc_user where id = 9") - utils.Exec(t, conn, "delete from twopc_user where id = 10") - utils.Exec(t, conn, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:80-": { - "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", - "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\")]", - }, - "ks.redo_state:-80": { - "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:-80": { - "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:80-": {"delete:[INT64(9) VARCHAR(\"baz\")]"}, - } - assert.Equal(t, expectations, logTable, - "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) -} - -// TestDTRollback tests distributed transaction rollback for insert, update and delete operations -// There would not be any binlog events for rollback -func TestDTRollback(t *testing.T) { - conn, closer := start(t) - defer closer() - - // Insert initial Data - utils.Exec(t, conn, "insert into twopc_user(id, name) values(7,'foo'), (8,'bar')") - - // run vstream to stream binlogs - vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) - - // Insert into multiple shards - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "insert into twopc_user(id, name) values(9,'baz')") - utils.Exec(t, conn, "insert into twopc_user(id, name) values(10,'apa')") - utils.Exec(t, conn, "rollback") - - tableMap := make(map[string][]*querypb.Field) - logTable := retrieveTransitions(t, ch, tableMap, nil) - assert.Zero(t, len(logTable), - "no change in binlog expected: got: %s", prettyPrint(logTable)) - - // 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, "update twopc_user set name='newfoo' where id = 8") - utils.Exec(t, conn, "rollback") - - logTable = retrieveTransitions(t, ch, tableMap, nil) - assert.Zero(t, len(logTable), - "no change in binlog expected: got: %s", prettyPrint(logTable)) - - // DELETE from multiple shard - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "delete from twopc_user where id = 7") - utils.Exec(t, conn, "delete from twopc_user where id = 8") - utils.Exec(t, conn, "rollback") - - logTable = retrieveTransitions(t, ch, tableMap, nil) - assert.Zero(t, len(logTable), - "no change in binlog expected: got: %s", prettyPrint(logTable)) -} - -// TestDTCommitMultiShardTxSingleShardDML tests distributed transaction commit for insert, update and delete operations -// There is DML operation only on single shard but transaction open on multiple shards. -// Metdata Manager is the one which executed the DML operation on the shard. -func TestDTCommitDMLOnlyOnMM(t *testing.T) { - conn, closer := start(t) - defer closer() - - vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) - - // 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, "commit") - - tableMap := make(map[string][]*querypb.Field) - dtMap := make(map[string]string) - logTable := retrieveTransitions(t, ch, tableMap, dtMap) - 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(\"-80\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - }, - "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)) - - // 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, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:80-": { - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", - "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\")]", - }, - "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)) - - // 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, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:80-": { - "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", - "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\")]", - }, - "ks.twopc_user:80-": {"delete:[INT64(7) VARCHAR(\"newfoo\")]"}, - } - assert.Equal(t, expectations, logTable, - "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) -} - -// TestDTCommitMultiShardTxSingleShardDML tests distributed transaction commit for insert, update and delete operations -// There is DML operation only on single shard but transaction open on multiple shards. -// Resource Manager is the one which executed the DML operation on the shard. -func TestDTCommitDMLOnlyOnRM(t *testing.T) { - conn, closer := start(t) - defer closer() - - vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) - - // Insert into multiple shards - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "select * from twopc_user where id = 8") - utils.Exec(t, conn, "insert into twopc_user(id, name) values(7,'foo')") - utils.Exec(t, conn, "commit") - - tableMap := make(map[string][]*querypb.Field) - dtMap := make(map[string]string) - logTable := retrieveTransitions(t, ch, tableMap, dtMap) - 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(\"80-\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", - }, - "ks.redo_state:80-": { - "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:80-": { - "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (7, 'foo')\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (7, 'foo')\")]", - }, - "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)) - - // Update from multiple shard - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "select * from twopc_user where id = 8") - utils.Exec(t, conn, "update twopc_user set name='newfoo' where id = 7") - utils.Exec(t, conn, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:-80": { - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", - "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-\")]", - }, - "ks.redo_state:80-": { - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:80-": { - "insert:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 7 limit 10001 /* INT64 */\")]", - "delete:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 7 limit 10001 /* INT64 */\")]", - }, - "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)) - - // DELETE from multiple shard - utils.Exec(t, conn, "begin") - utils.Exec(t, conn, "select * from twopc_user where id = 8") - utils.Exec(t, conn, "delete from twopc_user where id = 7") - utils.Exec(t, conn, "commit") - - logTable = retrieveTransitions(t, ch, tableMap, dtMap) - expectations = map[string][]string{ - "ks.dt_state:-80": { - "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", - "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-\")]", - }, - "ks.redo_state:80-": { - "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", - }, - "ks.redo_statement:80-": { - "insert:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 7 limit 10001 /* INT64 */\")]", - "delete:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 7 limit 10001 /* INT64 */\")]", - }, - "ks.twopc_user:80-": {"delete:[INT64(7) VARCHAR(\"newfoo\")]"}, - } - assert.Equal(t, expectations, logTable, - "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) -} - -// TestDTPrepareFailOnRM tests distributed transaction prepare failure on resource manager -func TestDTPrepareFailOnRM(t *testing.T) { - conn, closer := start(t) - defer closer() - - vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "fk_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) - - // 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, "insert into twopc_user(id, name) values(8,'bar')") - - ctx2 := context.Background() - conn2, err := mysql.Connect(ctx2, &vtParams) - require.NoError(t, err) - - 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')") - - var wg sync.WaitGroup - wg.Add(2) - var commitErr error - go func() { - _, err := utils.ExecAllowError(t, conn, "commit") - if err != nil { - commitErr = err - } - wg.Done() - }() - go func() { - _, err := utils.ExecAllowError(t, conn2, "commit") - wg.Done() - if err != nil { - commitErr = err - } - }() - wg.Wait() - require.ErrorContains(t, commitErr, "ResourceExhausted desc = prepare failed") - - tableMap := make(map[string][]*querypb.Field) - dtMap := make(map[string]string) - logTable := retrieveTransitions(t, ch, tableMap, dtMap) - expectations := map[string][]string{ - "ks.dt_state:80-": { - "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", - "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", - "update:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", - "update:[VARCHAR(\"dtid-2\") VARCHAR(\"ROLLBACK\")]", - "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", - "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\")]", - }, - "ks.redo_state:-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 */ }, - } - flexiExpectations := map[string][2][]string{ - "ks.redo_statement:-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')\")]", - }}, - "ks.twopc_user:-80": {{ - "insert:[INT64(8) VARCHAR(\"bar\")]", - }, { - "insert:[INT64(10) VARCHAR(\"apa\")]", - }}, - "ks.twopc_user:80-": {{ - "insert:[INT64(7) VARCHAR(\"foo\")]", - }, { - "insert:[INT64(9) VARCHAR(\"baz\")]", - }}, - } - - compareMaps(t, expectations, logTable, flexiExpectations) -} - -func compareMaps(t *testing.T, expected, actual map[string][]string, flexibleExp map[string][2][]string) { - assert.Equal(t, len(expected), len(actual), "mismatch in number of keys: expected: %d, got: %d", len(expected), len(actual)) - - for key, expectedValue := range expected { - actualValue, ok := actual[key] - require.Truef(t, ok, "key %s not found in actual map", key) - - if validValues, isFlexi := flexibleExp[key]; isFlexi { - // For the flexible key, check if the actual value matches one of the valid values - if !reflect.DeepEqual(actualValue, validValues[0]) && !reflect.DeepEqual(actualValue, validValues[1]) { - t.Fatalf("mismatch in values for key '%s': expected one of: %v, got: %v", key, validValues, actualValue) - } - } else { - // Sort the slices before comparison - sort.Strings(expectedValue) - sort.Strings(actualValue) - assert.Equal(t, expectedValue, actualValue, "mismatch in values for key %s: expected: %v, got: %v", key, expectedValue, actualValue) - } - } -} diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index 91326acce4d..e1818735ed1 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -343,7 +343,7 @@ func TestCallProcedure(t *testing.T) { _, err = conn.ExecuteFetch(`CALL out_parameter(@foo)`, 100, true) require.Error(t, err) - require.Contains(t, err.Error(), "OUT and INOUT parameters are not supported") + require.ErrorContains(t, err, "OUT and INOUT parameters are not supported") } func TestTempTable(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 index 8861b9672b8..f4c82933d91 100644 --- a/go/test/endtoend/vtgate/vitess_tester/aggregation/aggregation.test +++ b/go/test/endtoend/vtgate/vitess_tester/aggregation/aggregation.test @@ -9,7 +9,7 @@ CREATE TABLE `t1` CREATE TABLE `t2` ( - `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `id` bigint unsigned NOT NULL AUTO_INCREMENT, `t1_id` int unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE InnoDB, @@ -38,7 +38,10 @@ values (1, 1), insert into t3 (id, name) values (1, 'A'), - (2, 'B'); + (2, 'B'), + (3, 'B'), + (4, 'B'), + (5, 'B'); -- wait_authoritative t1 -- wait_authoritative t2 @@ -47,4 +50,15 @@ 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; \ No newline at end of file +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/cte/queries.test b/go/test/endtoend/vtgate/vitess_tester/cte/queries.test new file mode 100644 index 00000000000..173dcaeb6ba --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/cte/queries.test @@ -0,0 +1,226 @@ +# Create tables +CREATE TABLE employees +( + id INT PRIMARY KEY, + name VARCHAR(100), + manager_id INT +); + +# Simple recursive CTE using a real table. Select everything from empty table +with recursive cte as (select * from employees union all select * from cte) +select * +from cte; + +# Insert data into the tables +INSERT INTO employees (id, name, manager_id) +VALUES (1, 'CEO', NULL), + (2, 'CTO', 1), + (3, 'CFO', 1), + (4, 'Engineer1', 2), + (5, 'Engineer2', 2), + (6, 'Accountant1', 3), + (7, 'Accountant2', 3); + +# Simple recursive CTE using literal values +WITH RECURSIVE numbers AS (SELECT 1 AS n + UNION ALL + SELECT n + 1 + FROM numbers + WHERE n < 5) +SELECT * +FROM numbers; + +# Recursive CTE joined with a normal table +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT * +FROM emp_cte; + +# Recursive CTE used in a derived table outside the CTE definition +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT derived.id, derived.name, derived.manager_id +FROM (SELECT * FROM emp_cte) AS derived; + +# Recursive CTE with additional computation +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id, 1 AS level + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id, cte.level + 1 + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT * +FROM emp_cte; + +# Recursive CTE with filtering in the recursive part +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id + WHERE e.name LIKE 'Engineer%') +SELECT * +FROM emp_cte; + +# Recursive CTE with limit +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT * +FROM emp_cte +LIMIT 5; + +# Recursive CTE using literal values and joined with a real table on the outside +WITH RECURSIVE literal_cte AS (SELECT 1 AS id, 100 AS value, 1 AS manager_id + UNION ALL + SELECT id + 1, value * 2, id + FROM literal_cte + WHERE id < 5) +SELECT l.id, l.value, l.manager_id, e.name AS employee_name +FROM literal_cte l + LEFT JOIN employees e ON l.id = e.id; + +# Recursive CTE with aggregation outside the CTE +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT manager_id, COUNT(*) AS employee_count +FROM emp_cte +GROUP BY manager_id; + +--error infinite recursion +with recursive cte as (select 1 as n union all select n+1 from cte) +select * +from cte; + +# Define recursive CTE and then use it on the RHS of UNION +WITH RECURSIVE foo AS (SELECT id + FROM employees + WHERE id = 1 + UNION ALL + SELECT id + 1 + FROM foo + WHERE id < 5) +SELECT id +FROM foo; + +# Recursive CTE with UNION DISTINCT +WITH RECURSIVE hierarchy AS (SELECT id, name, manager_id + FROM employees + UNION ALL + SELECT id, name, manager_id + FROM employees + UNION + DISTINCT + SELECT id * 2, name, manager_id + from hierarchy + WHERE id < 10) +SELECT * +FROM hierarchy; + +# Select with false condition +with recursive cte as (select * from employees where false union all select * from cte) +select * +from cte; + +# Select with no matching rows +with recursive cte as (select * from employees where id > 100 union all select * from cte) +select * +from cte; + +# Recursive CTE joined with a normal table. Predicate on the outside should not be pushed in +WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + INNER JOIN emp_cte cte ON e.manager_id = cte.id) +SELECT * +FROM emp_cte +where name = 'Engineer1'; + +# Query with a recursive CTE in a subquery +SELECT * +FROM (SELECT 1 UNION ALL SELECT 2) AS dt(a) +WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a * 0 AS b UNION ALL SELECT b + 1 FROM qn WHERE b = 0) + SELECT * + FROM qn + WHERE b = a); + +# Join with recursive CTE inside a derived table using data from DUAL +SELECT e.id, e.name, e.manager_id, d.id AS cte_id +FROM employees e + JOIN (WITH RECURSIVE foo AS (SELECT 1 AS id + UNION ALL + SELECT id + 1 + FROM foo + WHERE id < 5) + SELECT id + FROM foo) d ON e.id = d.id; + +# Join with recursive CTE inside a derived table using data from employees table +SELECT e.id, e.name, e.manager_id, d.id AS cte_id +FROM employees e + JOIN (WITH RECURSIVE foo AS (SELECT id + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id + FROM employees e + JOIN foo f ON e.manager_id = f.id) + SELECT id + FROM foo) d ON e.id = d.id; + +# Recursive CTE within an uncorrelated subquery as a select expression +SELECT e.id, + e.name, + e.manager_id, + (SELECT MAX(cte_id) + FROM (WITH RECURSIVE foo AS (SELECT 1 AS cte_id + UNION ALL + SELECT cte_id + 1 + FROM foo + WHERE cte_id < e.id) + SELECT cte_id + FROM foo) AS recursive_result) AS max_cte_id +FROM employees e; + +# Recursive CTE used twice in the same query +WITH RECURSIVE employee_hierarchy AS (SELECT id, name, manager_id, 1 AS level + FROM employees + WHERE manager_id IS NULL + UNION ALL + SELECT e.id, e.name, e.manager_id, h.level + 1 + FROM employees e + JOIN employee_hierarchy h ON e.manager_id = h.id) +SELECT h1.id AS employee_id, + h1.name AS employee_name, + h1.level AS employee_level, + h2.name AS manager_name, + h2.level AS manager_level +FROM employee_hierarchy h1 + LEFT JOIN + employee_hierarchy h2 ON h1.manager_id = h2.id +ORDER BY h1.level, h1.id; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/vitess_tester/dual/queries.test b/go/test/endtoend/vtgate/vitess_tester/dual/queries.test new file mode 100644 index 00000000000..77a6e1595e0 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/dual/queries.test @@ -0,0 +1,4 @@ +# file with tests that only use the dual table + +# Dual query that is using tilda operator in a complex expression +SELECT 1 WHERE (~ (1||0)) IS NULL; 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..e550145f8d5 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/join/join.test @@ -0,0 +1,78 @@ +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; + +CREATE TABLE `t4` +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `col` int unsigned 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'); + +insert into t4 (id, col) +values (1, 1), + (2, 2), + (3, 3); + +-- 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; + +# Complex query that requires hash join underneath a memory sort and ordered aggregate +select 1 +from t1 + join t2 on t1.id = t2.t1_id + join t4 on t4.col = t2.id + left join (select t4.col, count(*) as count from t4 group by t4.col) t3 on t3.col = t2.id +where t1.id IN (1, 2) +group by t2.id, t4.col; 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..1105b951e61 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/join/vschema.json @@ -0,0 +1,46 @@ +{ + "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" + } + ] + }, + "t4": { + "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/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/queries.test b/go/test/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/queries.test new file mode 100644 index 00000000000..28c55e559c9 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/queries.test @@ -0,0 +1,39 @@ +use customer; +create table if not exists customer +( + customer_id bigint not null, + email varbinary(128), + primary key (customer_id) +) ENGINE = InnoDB; + +insert into customer.customer(customer_id, email) +values (1, '[alice@domain.com](mailto:alice@domain.com)'), + (2, '[bob@domain.com](mailto:bob@domain.com)'), + (3, '[charlie@domain.com](mailto:charlie@domain.com)'), + (4, '[dan@domain.com](mailto:dan@domain.com)'), + (5, '[eve@domain.com](mailto:eve@domain.com)'); +use corder; +create table if not exists corder +( + order_id bigint not null, + customer_id bigint, + sku varbinary(128), + price bigint, + primary key (order_id) +) ENGINE = InnoDB; +insert into corder.corder(order_id, customer_id, sku, price) +values (1, 1, 'SKU-1001', 100), + (2, 2, 'SKU-1002', 30), + (3, 3, 'SKU-1002', 30), + (4, 4, 'SKU-1002', 30), + (5, 5, 'SKU-1002', 30); + +select co.order_id, co.customer_id, co.price +from corder.corder co + left join customer.customer cu on co.customer_id = cu.customer_id +where cu.customer_id = 1; + +# This query was accidentally disallowed by https://github.com/vitessio/vitess/pull/16520 +select 1 +from customer.customer +where customer_id in (select customer_id from corder.corder where price > 50); \ No newline at end of file diff --git a/go/test/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/vschema.json b/go/test/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/vschema.json new file mode 100644 index 00000000000..5672042bace --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/two_sharded_keyspaces/vschema.json @@ -0,0 +1,72 @@ +{ + "keyspaces": { + "customer": { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash", + "params": {}, + "owner": "" + } + }, + "tables": { + "customer": { + "type": "", + "column_vindexes": [ + { + "column": "customer_id", + "name": "hash", + "columns": [] + } + ], + "columns": [], + "pinned": "", + "column_list_authoritative": false, + "source": "" + } + }, + "require_explicit_routing": false, + "foreign_key_mode": 0, + "multi_tenant_spec": null + }, + "corder": { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash", + "params": {}, + "owner": "" + } + }, + "tables": { + "corder": { + "type": "", + "column_vindexes": [ + { + "column": "customer_id", + "name": "hash", + "columns": [] + } + ], + "columns": [], + "pinned": "", + "column_list_authoritative": false, + "source": "" + } + }, + "require_explicit_routing": false, + "foreign_key_mode": 0, + "multi_tenant_spec": null + } + }, + "routing_rules": { + "rules": [] + }, + "shard_routing_rules": { + "rules": [] + }, + "keyspace_routing_rules": null, + "mirror_rules": { + "rules": [] + } +} \ No newline at end of file diff --git a/go/test/endtoend/vtgate/vschema/vschema_test.go b/go/test/endtoend/vtgate/vschema/vschema_test.go index 92863ff7dc8..eec54f8f47f 100644 --- a/go/test/endtoend/vtgate/vschema/vschema_test.go +++ b/go/test/endtoend/vtgate/vschema/vschema_test.go @@ -110,16 +110,7 @@ func TestVSchema(t *testing.T) { `[[INT64(1) VARCHAR("test1")] [INT64(2) VARCHAR("test2")] [INT64(3) VARCHAR("test3")] [INT64(4) VARCHAR("test4")]]`) utils.AssertMatches(t, conn, "delete from vt_user", `[]`) - - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - - // Test empty vschema - if vtgateVersion >= 17 { - utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[]`) - } else { - utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[[VARCHAR("dual")]]`) - } + utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[]`) // Use the DDL to create an unsharded vschema and test again @@ -135,11 +126,7 @@ func TestVSchema(t *testing.T) { utils.Exec(t, conn, "commit") // Test Showing Tables - if vtgateVersion >= 17 { - utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[[VARCHAR("main")] [VARCHAR("vt_user")]]`) - } else { - utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[[VARCHAR("dual")] [VARCHAR("main")] [VARCHAR("vt_user")]]`) - } + utils.AssertMatches(t, conn, "SHOW VSCHEMA TABLES", `[[VARCHAR("main")] [VARCHAR("vt_user")]]`) // Test Showing Vindexes utils.AssertMatches(t, conn, "SHOW VSCHEMA VINDEXES", `[]`) 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/test/vschemawrapper/vschema_wrapper.go b/go/test/vschemawrapper/vschema_wrapper.go index 4d1c424dda8..a1b87f5569c 100644 --- a/go/test/vschemawrapper/vschema_wrapper.go +++ b/go/test/vschemawrapper/vschema_wrapper.go @@ -213,7 +213,6 @@ func (vw *VSchemaWrapper) TargetDestination(qualifier string) (key.Destination, return nil, nil, 0, vterrors.VT05003(keyspaceName) } return vw.Dest, keyspace.Keyspace, vw.TabletType_, nil - } func (vw *VSchemaWrapper) TabletType() topodatapb.TabletType { @@ -317,7 +316,6 @@ func (vw *VSchemaWrapper) TargetString() string { } func (vw *VSchemaWrapper) WarnUnshardedOnly(_ string, _ ...any) { - } func (vw *VSchemaWrapper) ErrorIfShardedF(keyspace *vindexes.Keyspace, _, errFmt string, params ...any) error { @@ -342,3 +340,17 @@ func (vw *VSchemaWrapper) FindRoutedShard(keyspace, shard string) (string, error func (vw *VSchemaWrapper) IsViewsEnabled() bool { return vw.EnableViews } + +// FindMirrorRule finds the mirror rule for the requested keyspace, table +// name, and the tablet type in the VSchema. +func (vs *VSchemaWrapper) FindMirrorRule(tab sqlparser.TableName) (*vindexes.MirrorRule, error) { + destKeyspace, destTabletType, _, err := topoproto.ParseDestination(tab.Qualifier.String(), topodatapb.TabletType_PRIMARY) + if err != nil { + return nil, err + } + mirrorRule, err := vs.V.FindMirrorRule(destKeyspace, tab.Name.String(), destTabletType) + if err != nil { + return nil, err + } + return mirrorRule, err +} 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 34543120202..749a7a1d43d 100644 --- a/go/tools/go-upgrade/go-upgrade.go +++ b/go/tools/go-upgrade/go-upgrade.go @@ -418,7 +418,7 @@ func replaceGoVersionInCodebase(old, new *version.Version, workflowUpdate bool) } if !isSameMajorMinorVersion(old, new) { - goModFiles := []string{"./go.mod", "./vitess-mixin/go.mod"} + goModFiles := []string{"./go.mod"} for _, file := range goModFiles { err = replaceInFile( []*regexp.Regexp{regexp.MustCompile(regexpReplaceGoModGoVersion)}, diff --git a/go/tools/sizegen/sizegen.go b/go/tools/sizegen/sizegen.go index a8fbcb1add4..7ecd50e3d8c 100644 --- a/go/tools/sizegen/sizegen.go +++ b/go/tools/sizegen/sizegen.go @@ -149,7 +149,7 @@ func (sizegen *sizegen) generateType(pkg *types.Package, file *codeFile, named * case *types.Interface: findImplementations(pkg.Scope(), tt, func(tt types.Type) { if _, isStruct := tt.Underlying().(*types.Struct); isStruct { - sizegen.generateKnownType(tt.(*types.Named)) + sizegen.generateTyp(tt) } }) default: @@ -157,6 +157,15 @@ func (sizegen *sizegen) generateType(pkg *types.Package, file *codeFile, named * } } +func (sizegen *sizegen) generateTyp(tt types.Type) { + switch tt := tt.(type) { + case *types.Named: + sizegen.generateKnownType(tt) + case *types.Alias: + sizegen.generateTyp(types.Unalias(tt)) + } +} + func (sizegen *sizegen) generateKnownType(named *types.Named) { pkgInfo := named.Obj().Pkg() file := sizegen.codegen[pkgInfo.Path()] diff --git a/go/trace/trace.go b/go/trace/trace.go index 7c43b4afedc..bcfe39eeefa 100644 --- a/go/trace/trace.go +++ b/go/trace/trace.go @@ -189,7 +189,7 @@ func StartTracing(serviceName string) io.Closer { } func fail(serviceName string) io.Closer { - options := make([]string, len(tracingBackendFactories)) + options := make([]string, 0, len(tracingBackendFactories)) for k := range tracingBackendFactories { options = append(options, k) } diff --git a/go/vt/binlog/binlogplayer/binlog_player.go b/go/vt/binlog/binlogplayer/binlog_player.go index 05685a54d3e..7936a0760c9 100644 --- a/go/vt/binlog/binlogplayer/binlog_player.go +++ b/go/vt/binlog/binlogplayer/binlog_player.go @@ -669,11 +669,11 @@ func GenerateUpdateHeartbeat(uid int32, timeUpdated int64) (string, error) { } // GenerateUpdateTimeThrottled returns a statement to record the latest throttle time in the _vt.vreplication table. -func GenerateUpdateTimeThrottled(uid int32, timeThrottledUnix int64, componentThrottled string) (string, error) { +func GenerateUpdateTimeThrottled(uid int32, timeThrottledUnix int64, componentThrottled string, reasonThrottled string) (string, error) { if timeThrottledUnix == 0 { return "", fmt.Errorf("timeUpdated cannot be zero") } - return fmt.Sprintf("update _vt.vreplication set time_updated=%v, time_throttled=%v, component_throttled='%v' where id=%v", timeThrottledUnix, timeThrottledUnix, componentThrottled, uid), nil + return fmt.Sprintf("update _vt.vreplication set time_updated=%v, time_throttled=%v, component_throttled='%v', reason_throttled=%v where id=%v", timeThrottledUnix, timeThrottledUnix, componentThrottled, encodeString(MessageTruncate(reasonThrottled)), uid), nil } // StartVReplicationUntil returns a statement to start the replication with a stop position. diff --git a/go/vt/binlog/binlogplayer/binlog_player_test.go b/go/vt/binlog/binlogplayer/binlog_player_test.go index 99b0ef496b3..697733a6d18 100644 --- a/go/vt/binlog/binlogplayer/binlog_player_test.go +++ b/go/vt/binlog/binlogplayer/binlog_player_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/mysql/sqlerror" querypb "vitess.io/vitess/go/vt/proto/query" @@ -454,3 +456,36 @@ func TestReadVReplicationStatus(t *testing.T) { t.Errorf("ReadVReplicationStatus(482821) = %#v, want %#v", got, want) } } + +func TestEncodeString(t *testing.T) { + tcases := []struct { + in, out string + }{ + { + in: "", + out: "''", + }, + { + in: "a", + out: "'a'", + }, + { + in: "here's", + out: "'here\\'s'", + }, + { + in: "online-ddl is denied access due to lag metric value 94.821447 exceeding threshold 5", + out: "'online-ddl is denied access due to lag metric value 94.821447 exceeding threshold 5'", + }, + { + in: "'a','b','c'", + out: "'\\'a\\',\\'b\\',\\'c\\''", + }, + } + for _, tcase := range tcases { + t.Run(tcase.in, func(t *testing.T) { + out := encodeString(tcase.in) + assert.Equal(t, tcase.out, out) + }) + } +} 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..03fd6232134 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" ) @@ -102,13 +103,13 @@ func NewMockDbaClient(t *testing.T) *MockDBClient { // ExpectRequest adds an expected result to the mock. // This function should not be called conncurrently with other commands. func (dc *MockDBClient) ExpectRequest(query string, result *sqltypes.Result, err error) { + dc.expectMu.Lock() + defer dc.expectMu.Unlock() select { case <-dc.done: dc.done = make(chan struct{}) default: } - dc.expectMu.Lock() - defer dc.expectMu.Unlock() dc.expect = append(dc.expect, &mockExpect{ query: query, result: result, @@ -120,13 +121,13 @@ func (dc *MockDBClient) ExpectRequest(query string, result *sqltypes.Result, err // queryRE is a regular expression. // This function should not be called conncurrently with other commands. func (dc *MockDBClient) ExpectRequestRE(queryRE string, result *sqltypes.Result, err error) { + dc.expectMu.Lock() + defer dc.expectMu.Unlock() select { case <-dc.done: dc.done = make(chan struct{}) default: } - dc.expectMu.Lock() - defer dc.expectMu.Unlock() dc.expect = append(dc.expect, &mockExpect{ query: queryRE, re: regexp.MustCompile(queryRE), @@ -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/dbconfigs/dbconfigs.go b/go/vt/dbconfigs/dbconfigs.go index 82c322e7ae9..32fb2435286 100644 --- a/go/vt/dbconfigs/dbconfigs.go +++ b/go/vt/dbconfigs/dbconfigs.go @@ -133,7 +133,7 @@ func registerBaseFlags(fs *pflag.FlagSet) { fs.StringVar(&GlobalDBConfigs.Socket, "db_socket", "", "The unix socket to connect on. If this is specified, host and port will not be used.") fs.StringVar(&GlobalDBConfigs.Host, "db_host", "", "The host name for the tcp connection.") fs.IntVar(&GlobalDBConfigs.Port, "db_port", 0, "tcp port") - fs.StringVar(&GlobalDBConfigs.Charset, "db_charset", "utf8mb4", "Character set used for this tablet.") + fs.StringVar(&GlobalDBConfigs.Charset, "db_charset", "utf8mb4", "Character set/collation used for this tablet. Make sure to configure this to a charset/collation supported by the lowest MySQL version in your environment.") fs.Uint64Var(&GlobalDBConfigs.Flags, "db_flags", 0, "Flag values as defined by MySQL.") fs.StringVar(&GlobalDBConfigs.Flavor, "db_flavor", "", "Flavor overrid. Valid value is FilePos.") fs.Var(&GlobalDBConfigs.SslMode, "db_ssl_mode", "SSL mode to connect with. One of disabled, preferred, required, verify_ca & verify_identity.") diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 70799b0f6bc..2a467301eaf 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -470,7 +470,20 @@ func (hc *HealthCheckImpl) deleteTablet(tablet *topodata.Tablet) { // delete from healthy list healthy, ok := hc.healthy[key] if ok && len(healthy) > 0 { - hc.recomputeHealthy(key) + if tabletType == topodata.TabletType_PRIMARY { + // If the deleted tablet was a primary, + // and it matches what we think is the current active primary, + // clear the healthy list for the primary. + // + // See the logic in `updateHealth` for more details. + alias := tabletAliasString(topoproto.TabletAliasString(healthy[0].Tablet.Alias)) + if alias == tabletAlias { + hc.healthy[key] = []*TabletHealth{} + } + } else { + // Simply recompute the list of healthy tablets for all other tablet types. + hc.recomputeHealthy(key) + } } } }() @@ -586,6 +599,13 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, prevTarget *query.Targ hc.broadcast(th) } +// recomputeHealthy recomputes the healthy tablets for the given key. +// +// This filters out tablets that might be healthy, but are not part of the current +// cell or cell alias. It also performs filtering of tablets based on replication lag, +// if configured to do so. +// +// This should not be called for primary tablets. func (hc *HealthCheckImpl) recomputeHealthy(key KeyspaceShardTabletType) { all := hc.healthData[key] allArray := make([]*TabletHealth, 0, len(all)) diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index c87ba699234..35c55354fb7 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -784,6 +784,127 @@ func TestRemoveTablet(t *testing.T) { assert.Empty(t, a, "wrong result, expected empty list") } +// When an external primary failover is performed, +// the demoted primary will advertise itself as a `PRIMARY` +// tablet until it recognizes that it was demoted, +// and until all in-flight operations have either finished +// (successfully or unsuccessfully, see `--shutdown_grace_period` flag). +// +// During this time, operations like `RemoveTablet` should not lead +// to multiple tablets becoming valid targets for `PRIMARY`. +func TestRemoveTabletDuringExternalReparenting(t *testing.T) { + ctx := utils.LeakCheckContext(t) + + // reset error counters + hcErrorCounters.ResetAll() + ts := memorytopo.NewServer(ctx, "cell") + defer ts.Close() + hc := createTestHc(ctx, ts) + // close healthcheck + defer hc.Close() + + firstTablet := createTestTablet(0, "cell", "a") + firstTablet.Type = topodatapb.TabletType_PRIMARY + + secondTablet := createTestTablet(1, "cell", "b") + secondTablet.Type = topodatapb.TabletType_REPLICA + + thirdTablet := createTestTablet(2, "cell", "c") + thirdTablet.Type = topodatapb.TabletType_REPLICA + + firstTabletHealthStream := make(chan *querypb.StreamHealthResponse) + firstTabletConn := createFakeConn(firstTablet, firstTabletHealthStream) + firstTabletConn.errCh = make(chan error) + + secondTabletHealthStream := make(chan *querypb.StreamHealthResponse) + secondTabletConn := createFakeConn(secondTablet, secondTabletHealthStream) + secondTabletConn.errCh = make(chan error) + + thirdTabletHealthStream := make(chan *querypb.StreamHealthResponse) + thirdTabletConn := createFakeConn(thirdTablet, thirdTabletHealthStream) + thirdTabletConn.errCh = make(chan error) + + resultChan := hc.Subscribe() + + hc.AddTablet(firstTablet) + <-resultChan + + hc.AddTablet(secondTablet) + <-resultChan + + hc.AddTablet(thirdTablet) + <-resultChan + + firstTabletPrimaryTermStartTimestamp := time.Now().Unix() - 10 + + firstTabletHealthStream <- &querypb.StreamHealthResponse{ + TabletAlias: firstTablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_PRIMARY}, + Serving: true, + + PrimaryTermStartTimestamp: firstTabletPrimaryTermStartTimestamp, + RealtimeStats: &querypb.RealtimeStats{ReplicationLagSeconds: 0, CpuUsage: 0.5}, + } + <-resultChan + + secondTabletHealthStream <- &querypb.StreamHealthResponse{ + TabletAlias: secondTablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}, + Serving: true, + + PrimaryTermStartTimestamp: 0, + RealtimeStats: &querypb.RealtimeStats{ReplicationLagSeconds: 1, CpuUsage: 0.5}, + } + <-resultChan + + thirdTabletHealthStream <- &querypb.StreamHealthResponse{ + TabletAlias: thirdTablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}, + Serving: true, + + PrimaryTermStartTimestamp: 0, + RealtimeStats: &querypb.RealtimeStats{ReplicationLagSeconds: 1, CpuUsage: 0.5}, + } + <-resultChan + + secondTabletPrimaryTermStartTimestamp := time.Now().Unix() + + // Simulate a failover + firstTabletHealthStream <- &querypb.StreamHealthResponse{ + TabletAlias: firstTablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_PRIMARY}, + Serving: true, + + PrimaryTermStartTimestamp: firstTabletPrimaryTermStartTimestamp, + RealtimeStats: &querypb.RealtimeStats{ReplicationLagSeconds: 0, CpuUsage: 0.5}, + } + <-resultChan + + secondTabletHealthStream <- &querypb.StreamHealthResponse{ + TabletAlias: secondTablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_PRIMARY}, + Serving: true, + + PrimaryTermStartTimestamp: secondTabletPrimaryTermStartTimestamp, + RealtimeStats: &querypb.RealtimeStats{ReplicationLagSeconds: 0, CpuUsage: 0.5}, + } + <-resultChan + + hc.RemoveTablet(thirdTablet) + + // `secondTablet` should be the primary now + expectedTabletStats := []*TabletHealth{{ + Tablet: secondTablet, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_PRIMARY}, + Serving: true, + Stats: &querypb.RealtimeStats{ReplicationLagSeconds: 0, CpuUsage: 0.5}, + PrimaryTermStartTime: secondTabletPrimaryTermStartTimestamp, + }} + + actualTabletStats := hc.GetHealthyTabletStats(&querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_PRIMARY}) + mustMatch(t, expectedTabletStats, actualTabletStats, "unexpected result") +} + // TestGetHealthyTablets tests the functionality of GetHealthyTabletStats. func TestGetHealthyTablets(t *testing.T) { ctx := utils.LeakCheckContext(t) diff --git a/go/vt/discovery/tablet_picker.go b/go/vt/discovery/tablet_picker.go index fd1ff64a3ce..c48905be948 100644 --- a/go/vt/discovery/tablet_picker.go +++ b/go/vt/discovery/tablet_picker.go @@ -18,7 +18,6 @@ package discovery import ( "context" - "fmt" "io" "math/rand/v2" "sort" @@ -181,7 +180,7 @@ func NewTabletPicker( } if len(missingFields) > 0 { return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, - fmt.Sprintf("Missing required field(s) for tablet picker: %s", strings.Join(missingFields, ", "))) + "Missing required field(s) for tablet picker: %s", strings.Join(missingFields, ", ")) } // Resolve tablet picker options diff --git a/go/vt/logutil/throttled.go b/go/vt/logutil/throttled.go index 4ee11912e71..fa63be328bc 100644 --- a/go/vt/logutil/throttled.go +++ b/go/vt/logutil/throttled.go @@ -54,6 +54,11 @@ var ( errorDepth = log.ErrorDepth ) +// GetLastLogTime gets the last log time for the throttled logger. +func (tl *ThrottledLogger) GetLastLogTime() time.Time { + return tl.lastlogTime +} + func (tl *ThrottledLogger) log(logF logFunc, format string, v ...any) { now := time.Now() diff --git a/go/vt/mysqlctl/builtinbackupengine.go b/go/vt/mysqlctl/builtinbackupengine.go index 3bc39e45e72..494d765f2a9 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) } @@ -768,21 +766,25 @@ func (bp *backupPipe) HashString() string { return hex.EncodeToString(bp.crc32.Sum(nil)) } -func (bp *backupPipe) ReportProgress(period time.Duration, logger logutil.Logger) { +func (bp *backupPipe) ReportProgress(period time.Duration, logger logutil.Logger, restore bool) { + messageStr := "restoring " + if !restore { + messageStr = "backing up " + } tick := time.NewTicker(period) defer tick.Stop() for { select { case <-bp.done: - logger.Infof("Done taking Backup %q", bp.filename) + logger.Infof("Completed %s %q", messageStr, bp.filename) return case <-tick.C: written := float64(atomic.LoadInt64(&bp.nn)) if bp.maxSize == 0 { - logger.Infof("Backup %q: %.02fkb", bp.filename, written/1024.0) + logger.Infof("%s %q: %.02fkb", messageStr, bp.filename, written/1024.0) } else { maxSize := float64(bp.maxSize) - logger.Infof("Backup %q: %.02f%% (%.02f/%.02fkb)", bp.filename, 100.0*written/maxSize, written/1024.0, maxSize/1024.0) + logger.Infof("%s %q: %.02f%% (%.02f/%.02fkb)", messageStr, bp.filename, 100.0*written/maxSize, written/1024.0, maxSize/1024.0) } } } @@ -815,7 +817,7 @@ func (be *BuiltinBackupEngine) backupFile(ctx context.Context, params BackupPara } br := newBackupReader(fe.Name, fi.Size(), timedSource) - go br.ReportProgress(builtinBackupProgress, params.Logger) + go br.ReportProgress(builtinBackupProgress, params.Logger, false /*restore*/) // Open the destination file for writing, and a buffer. params.Logger.Infof("Backing up file: %v", fe.Name) @@ -968,7 +970,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 @@ -1081,7 +1082,7 @@ func (be *BuiltinBackupEngine) restoreFile(ctx context.Context, params RestorePa }() br := newBackupReader(name, 0, timedSource) - go br.ReportProgress(builtinBackupProgress, params.Logger) + go br.ReportProgress(builtinBackupProgress, params.Logger, true /*restore*/) var reader io.Reader = br // Open the destination file for writing. @@ -1108,7 +1109,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/s3backupstorage/s3.go b/go/vt/mysqlctl/s3backupstorage/s3.go index cdc4e355d45..9686b4a3978 100644 --- a/go/vt/mysqlctl/s3backupstorage/s3.go +++ b/go/vt/mysqlctl/s3backupstorage/s3.go @@ -28,6 +28,7 @@ import ( "crypto/md5" "crypto/tls" "encoding/base64" + "errors" "fmt" "io" "math" @@ -412,7 +413,7 @@ func (bs *S3BackupStorage) RemoveBackup(ctx context.Context, dir, name string) e } for _, objError := range out.Errors { - return fmt.Errorf(objError.String()) + return errors.New(objError.String()) } if objs.NextContinuationToken == nil { 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/binlogdata/binlogdata.pb.go b/go/vt/proto/binlogdata/binlogdata.pb.go index aade1d049f8..58daae6b8f0 100644 --- a/go/vt/proto/binlogdata/binlogdata.pb.go +++ b/go/vt/proto/binlogdata/binlogdata.pb.go @@ -1416,11 +1416,12 @@ type RowEvent struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TableName string `protobuf:"bytes,1,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` - RowChanges []*RowChange `protobuf:"bytes,2,rep,name=row_changes,json=rowChanges,proto3" json:"row_changes,omitempty"` - Keyspace string `protobuf:"bytes,3,opt,name=keyspace,proto3" json:"keyspace,omitempty"` - Shard string `protobuf:"bytes,4,opt,name=shard,proto3" json:"shard,omitempty"` - Flags uint32 `protobuf:"varint,5,opt,name=flags,proto3" json:"flags,omitempty"` // https://dev.mysql.com/doc/dev/mysql-server/latest/classbinary__log_1_1Rows__event.html + TableName string `protobuf:"bytes,1,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` + RowChanges []*RowChange `protobuf:"bytes,2,rep,name=row_changes,json=rowChanges,proto3" json:"row_changes,omitempty"` + Keyspace string `protobuf:"bytes,3,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Shard string `protobuf:"bytes,4,opt,name=shard,proto3" json:"shard,omitempty"` + Flags uint32 `protobuf:"varint,5,opt,name=flags,proto3" json:"flags,omitempty"` // https://dev.mysql.com/doc/dev/mysql-server/latest/classbinary__log_1_1Rows__event.html + IsInternalTable bool `protobuf:"varint,6,opt,name=is_internal_table,json=isInternalTable,proto3" json:"is_internal_table,omitempty"` // set for sidecardb tables } func (x *RowEvent) Reset() { @@ -1490,6 +1491,13 @@ func (x *RowEvent) GetFlags() uint32 { return 0 } +func (x *RowEvent) GetIsInternalTable() bool { + if x != nil { + return x.IsInternalTable + } + return false +} + // FieldEvent represents the field info for a table. type FieldEvent struct { state protoimpl.MessageState @@ -1508,6 +1516,7 @@ type FieldEvent struct { // NOTE: because this is the use case, this is ONLY ever set today in // vstreams managed by the vstreamManager. EnumSetStringValues bool `protobuf:"varint,25,opt,name=enum_set_string_values,json=enumSetStringValues,proto3" json:"enum_set_string_values,omitempty"` + IsInternalTable bool `protobuf:"varint,26,opt,name=is_internal_table,json=isInternalTable,proto3" json:"is_internal_table,omitempty"` // set for sidecardb tables } func (x *FieldEvent) Reset() { @@ -1577,6 +1586,13 @@ func (x *FieldEvent) GetEnumSetStringValues() bool { return false } +func (x *FieldEvent) GetIsInternalTable() bool { + if x != nil { + return x.IsInternalTable + } + return false +} + // ShardGtid contains the GTID position for one shard. // It's used in a request for requesting a starting position. // It's used in a response to transmit the current position @@ -1913,6 +1929,8 @@ type VEvent struct { Shard string `protobuf:"bytes,23,opt,name=shard,proto3" json:"shard,omitempty"` // indicate that we are being throttled right now Throttled bool `protobuf:"varint,24,opt,name=throttled,proto3" json:"throttled,omitempty"` + // ThrottledReason is a human readable string that explains why the stream is throttled + ThrottledReason string `protobuf:"bytes,25,opt,name=throttled_reason,json=throttledReason,proto3" json:"throttled_reason,omitempty"` } func (x *VEvent) Reset() { @@ -2045,6 +2063,13 @@ func (x *VEvent) GetThrottled() bool { return false } +func (x *VEvent) GetThrottledReason() string { + if x != nil { + return x.ThrottledReason + } + return "" +} + type MinimalTable struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2166,6 +2191,53 @@ func (x *MinimalSchema) GetTables() []*MinimalTable { return nil } +type VStreamOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InternalTables []string `protobuf:"bytes,1,rep,name=internal_tables,json=internalTables,proto3" json:"internal_tables,omitempty"` +} + +func (x *VStreamOptions) Reset() { + *x = VStreamOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_binlogdata_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VStreamOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VStreamOptions) ProtoMessage() {} + +func (x *VStreamOptions) ProtoReflect() protoreflect.Message { + mi := &file_binlogdata_proto_msgTypes[20] + 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 VStreamOptions.ProtoReflect.Descriptor instead. +func (*VStreamOptions) Descriptor() ([]byte, []int) { + return file_binlogdata_proto_rawDescGZIP(), []int{20} +} + +func (x *VStreamOptions) GetInternalTables() []string { + if x != nil { + return x.InternalTables + } + return nil +} + // VStreamRequest is the payload for VStreamer type VStreamRequest struct { state protoimpl.MessageState @@ -2178,12 +2250,13 @@ type VStreamRequest struct { Position string `protobuf:"bytes,4,opt,name=position,proto3" json:"position,omitempty"` Filter *Filter `protobuf:"bytes,5,opt,name=filter,proto3" json:"filter,omitempty"` TableLastPKs []*TableLastPK `protobuf:"bytes,6,rep,name=table_last_p_ks,json=tableLastPKs,proto3" json:"table_last_p_ks,omitempty"` + Options *VStreamOptions `protobuf:"bytes,7,opt,name=options,proto3" json:"options,omitempty"` } func (x *VStreamRequest) Reset() { *x = VStreamRequest{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[20] + mi := &file_binlogdata_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2196,7 +2269,7 @@ func (x *VStreamRequest) String() string { func (*VStreamRequest) ProtoMessage() {} func (x *VStreamRequest) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[20] + mi := &file_binlogdata_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2209,7 +2282,7 @@ func (x *VStreamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamRequest.ProtoReflect.Descriptor instead. func (*VStreamRequest) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{20} + return file_binlogdata_proto_rawDescGZIP(), []int{21} } func (x *VStreamRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -2254,6 +2327,13 @@ func (x *VStreamRequest) GetTableLastPKs() []*TableLastPK { return nil } +func (x *VStreamRequest) GetOptions() *VStreamOptions { + if x != nil { + return x.Options + } + return nil +} + // VStreamResponse is the response from VStreamer type VStreamResponse struct { state protoimpl.MessageState @@ -2266,7 +2346,7 @@ type VStreamResponse struct { func (x *VStreamResponse) Reset() { *x = VStreamResponse{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[21] + mi := &file_binlogdata_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2279,7 +2359,7 @@ func (x *VStreamResponse) String() string { func (*VStreamResponse) ProtoMessage() {} func (x *VStreamResponse) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[21] + mi := &file_binlogdata_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2292,7 +2372,7 @@ func (x *VStreamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamResponse.ProtoReflect.Descriptor instead. func (*VStreamResponse) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{21} + return file_binlogdata_proto_rawDescGZIP(), []int{22} } func (x *VStreamResponse) GetEvents() []*VEvent { @@ -2318,7 +2398,7 @@ type VStreamRowsRequest struct { func (x *VStreamRowsRequest) Reset() { *x = VStreamRowsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[22] + mi := &file_binlogdata_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2331,7 +2411,7 @@ func (x *VStreamRowsRequest) String() string { func (*VStreamRowsRequest) ProtoMessage() {} func (x *VStreamRowsRequest) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[22] + mi := &file_binlogdata_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2344,7 +2424,7 @@ func (x *VStreamRowsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamRowsRequest.ProtoReflect.Descriptor instead. func (*VStreamRowsRequest) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{22} + return file_binlogdata_proto_rawDescGZIP(), []int{23} } func (x *VStreamRowsRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -2397,12 +2477,14 @@ type VStreamRowsResponse struct { Throttled bool `protobuf:"varint,6,opt,name=throttled,proto3" json:"throttled,omitempty"` // Heartbeat indicates that this is a heartbeat message Heartbeat bool `protobuf:"varint,7,opt,name=heartbeat,proto3" json:"heartbeat,omitempty"` + // ThrottledReason is a human readable string that explains why the stream is throttled + ThrottledReason string `protobuf:"bytes,8,opt,name=throttled_reason,json=throttledReason,proto3" json:"throttled_reason,omitempty"` } func (x *VStreamRowsResponse) Reset() { *x = VStreamRowsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[23] + mi := &file_binlogdata_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2415,7 +2497,7 @@ func (x *VStreamRowsResponse) String() string { func (*VStreamRowsResponse) ProtoMessage() {} func (x *VStreamRowsResponse) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[23] + mi := &file_binlogdata_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2428,7 +2510,7 @@ func (x *VStreamRowsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamRowsResponse.ProtoReflect.Descriptor instead. func (*VStreamRowsResponse) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{23} + return file_binlogdata_proto_rawDescGZIP(), []int{24} } func (x *VStreamRowsResponse) GetFields() []*query.Field { @@ -2480,6 +2562,13 @@ func (x *VStreamRowsResponse) GetHeartbeat() bool { return false } +func (x *VStreamRowsResponse) GetThrottledReason() string { + if x != nil { + return x.ThrottledReason + } + return "" +} + // VStreamTablesRequest is the payload for VStreamTables type VStreamTablesRequest struct { state protoimpl.MessageState @@ -2494,7 +2583,7 @@ type VStreamTablesRequest struct { func (x *VStreamTablesRequest) Reset() { *x = VStreamTablesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[24] + mi := &file_binlogdata_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2507,7 +2596,7 @@ func (x *VStreamTablesRequest) String() string { func (*VStreamTablesRequest) ProtoMessage() {} func (x *VStreamTablesRequest) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[24] + mi := &file_binlogdata_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2520,7 +2609,7 @@ func (x *VStreamTablesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamTablesRequest.ProtoReflect.Descriptor instead. func (*VStreamTablesRequest) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{24} + return file_binlogdata_proto_rawDescGZIP(), []int{25} } func (x *VStreamTablesRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -2561,7 +2650,7 @@ type VStreamTablesResponse struct { func (x *VStreamTablesResponse) Reset() { *x = VStreamTablesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[25] + mi := &file_binlogdata_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2574,7 +2663,7 @@ func (x *VStreamTablesResponse) String() string { func (*VStreamTablesResponse) ProtoMessage() {} func (x *VStreamTablesResponse) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[25] + mi := &file_binlogdata_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2587,7 +2676,7 @@ func (x *VStreamTablesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamTablesResponse.ProtoReflect.Descriptor instead. func (*VStreamTablesResponse) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{25} + return file_binlogdata_proto_rawDescGZIP(), []int{26} } func (x *VStreamTablesResponse) GetTableName() string { @@ -2644,7 +2733,7 @@ type LastPKEvent struct { func (x *LastPKEvent) Reset() { *x = LastPKEvent{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[26] + mi := &file_binlogdata_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2657,7 +2746,7 @@ func (x *LastPKEvent) String() string { func (*LastPKEvent) ProtoMessage() {} func (x *LastPKEvent) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[26] + mi := &file_binlogdata_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2670,7 +2759,7 @@ func (x *LastPKEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use LastPKEvent.ProtoReflect.Descriptor instead. func (*LastPKEvent) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{26} + return file_binlogdata_proto_rawDescGZIP(), []int{27} } func (x *LastPKEvent) GetTableLastPK() *TableLastPK { @@ -2699,7 +2788,7 @@ type TableLastPK struct { func (x *TableLastPK) Reset() { *x = TableLastPK{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[27] + mi := &file_binlogdata_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2712,7 +2801,7 @@ func (x *TableLastPK) String() string { func (*TableLastPK) ProtoMessage() {} func (x *TableLastPK) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[27] + mi := &file_binlogdata_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2725,7 +2814,7 @@ func (x *TableLastPK) ProtoReflect() protoreflect.Message { // Deprecated: Use TableLastPK.ProtoReflect.Descriptor instead. func (*TableLastPK) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{27} + return file_binlogdata_proto_rawDescGZIP(), []int{28} } func (x *TableLastPK) GetTableName() string { @@ -2759,7 +2848,7 @@ type VStreamResultsRequest struct { func (x *VStreamResultsRequest) Reset() { *x = VStreamResultsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[28] + mi := &file_binlogdata_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2772,7 +2861,7 @@ func (x *VStreamResultsRequest) String() string { func (*VStreamResultsRequest) ProtoMessage() {} func (x *VStreamResultsRequest) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[28] + mi := &file_binlogdata_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2785,7 +2874,7 @@ func (x *VStreamResultsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamResultsRequest.ProtoReflect.Descriptor instead. func (*VStreamResultsRequest) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{28} + return file_binlogdata_proto_rawDescGZIP(), []int{29} } func (x *VStreamResultsRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -2831,7 +2920,7 @@ type VStreamResultsResponse struct { func (x *VStreamResultsResponse) Reset() { *x = VStreamResultsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[29] + mi := &file_binlogdata_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2844,7 +2933,7 @@ func (x *VStreamResultsResponse) String() string { func (*VStreamResultsResponse) ProtoMessage() {} func (x *VStreamResultsResponse) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[29] + mi := &file_binlogdata_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2857,7 +2946,7 @@ func (x *VStreamResultsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VStreamResultsResponse.ProtoReflect.Descriptor instead. func (*VStreamResultsResponse) Descriptor() ([]byte, []int) { - return file_binlogdata_proto_rawDescGZIP(), []int{29} + return file_binlogdata_proto_rawDescGZIP(), []int{30} } func (x *VStreamResultsResponse) GetFields() []*query.Field { @@ -2897,7 +2986,7 @@ type BinlogTransaction_Statement struct { func (x *BinlogTransaction_Statement) Reset() { *x = BinlogTransaction_Statement{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[30] + mi := &file_binlogdata_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2910,7 +2999,7 @@ func (x *BinlogTransaction_Statement) String() string { func (*BinlogTransaction_Statement) ProtoMessage() {} func (x *BinlogTransaction_Statement) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[30] + mi := &file_binlogdata_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2959,7 +3048,7 @@ type RowChange_Bitmap struct { func (x *RowChange_Bitmap) Reset() { *x = RowChange_Bitmap{} if protoimpl.UnsafeEnabled { - mi := &file_binlogdata_proto_msgTypes[34] + mi := &file_binlogdata_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2972,7 +3061,7 @@ func (x *RowChange_Bitmap) String() string { func (*RowChange_Bitmap) ProtoMessage() {} func (x *RowChange_Bitmap) ProtoReflect() protoreflect.Message { - mi := &file_binlogdata_proto_msgTypes[34] + mi := &file_binlogdata_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3188,7 +3277,7 @@ var file_binlogdata_proto_rawDesc = []byte{ 0x75, 0x6d, 0x6e, 0x73, 0x1a, 0x32, 0x0a, 0x06, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x77, + 0x28, 0x0c, 0x52, 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x72, 0x6f, 0x77, 0x5f, 0x63, 0x68, 0x61, 0x6e, @@ -3199,198 +3288,177 @@ var file_binlogdata_proto_rawDesc = []byte{ 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, - 0x6c, 0x61, 0x67, 0x73, 0x22, 0xb8, 0x01, 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x65, 0x6e, - 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x75, 0x6d, - 0x53, 0x65, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, - 0x88, 0x01, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 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, 0x67, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, - 0x74, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x5f, 0x6b, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, - 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x4b, 0x73, 0x22, 0x3f, 0x0a, 0x05, 0x56, 0x47, - 0x74, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x67, 0x74, 0x69, - 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, - 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 0x52, - 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 0x73, 0x22, 0x41, 0x0a, 0x0d, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0xbc, - 0x02, 0x0a, 0x07, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x6d, 0x69, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x6d, - 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x67, 0x74, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x6c, 0x61, 0x67, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0f, 0x69, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x22, 0xe4, 0x01, 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, + 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x73, + 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x74, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, + 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x88, 0x01, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x47, 0x74, 0x69, 0x64, 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, 0x67, 0x74, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x0a, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x5f, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, + 0x4b, 0x73, 0x22, 0x3f, 0x0a, 0x05, 0x56, 0x47, 0x74, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x5f, 0x67, 0x74, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 0x52, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, - 0x69, 0x64, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, - 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x69, 0x6e, 0x6c, - 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, - 0x74, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0x8b, 0x04, - 0x0a, 0x06, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x09, 0x72, 0x6f, 0x77, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x72, - 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, - 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x27, 0x0a, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x47, 0x74, - 0x69, 0x64, 0x52, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x6a, 0x6f, 0x75, - 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x69, 0x6e, - 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x52, - 0x07, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6d, 0x6c, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x6d, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3c, 0x0a, - 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x5f, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0b, - 0x6c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x0a, - 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x22, 0x8d, 0x01, 0x0a, 0x0c, - 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x5f, 0x6b, 0x5f, 0x63, 0x6f, - 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x70, 0x4b, 0x43, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0e, 0x70, 0x5f, 0x6b, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x70, 0x4b, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x41, 0x0a, 0x0d, 0x4d, - 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x30, 0x0a, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, - 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, - 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0xc7, - 0x02, 0x0a, 0x0e, 0x56, 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, 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, 0x2a, 0x0a, 0x06, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, - 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0f, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x5f, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x52, 0x0c, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x73, 0x22, 0x3d, 0x0a, 0x0f, 0x56, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, - 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x12, 0x56, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 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, 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, 0x14, 0x0a, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x05, 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, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x22, - 0xf9, 0x01, 0x0a, 0x13, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x28, 0x0a, - 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x70, - 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x74, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x04, 0x72, - 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, 0x22, 0x0a, 0x06, 0x6c, - 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x12, 0x1c, 0x0a, - 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x22, 0xc5, 0x01, 0x0a, 0x14, - 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 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, 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, 0x22, 0xde, 0x01, 0x0a, 0x15, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, - 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x52, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x67, 0x74, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, - 0x12, 0x1e, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, - 0x12, 0x22, 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x06, 0x6c, 0x61, - 0x73, 0x74, 0x70, 0x6b, 0x22, 0x69, 0x0a, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x70, 0x5f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x69, - 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, - 0x73, 0x74, 0x50, 0x4b, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, - 0x4b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, - 0x58, 0x0a, 0x0b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x12, 0x1d, - 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, - 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x03, 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, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x22, 0xdc, 0x01, 0x0a, 0x15, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x64, 0x73, 0x22, 0x41, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x64, 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, 0xbc, 0x02, 0x0a, 0x07, 0x4a, 0x6f, 0x75, 0x72, 0x6e, + 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x62, 0x69, 0x6e, + 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x67, 0x74, 0x69, + 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, + 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 0x52, + 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x47, 0x74, 0x69, 0x64, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x70, + 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x0c, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0xb6, 0x04, 0x0a, 0x06, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, + 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x74, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x09, + 0x72, 0x6f, 0x77, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x6f, 0x77, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x72, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x37, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x76, 0x67, 0x74, 0x69, + 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x47, 0x74, 0x69, 0x64, 0x52, 0x05, 0x76, 0x67, 0x74, 0x69, + 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x07, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, + 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6d, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, + 0x6d, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x5f, + 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x50, + 0x4b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x64, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, + 0x6c, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, + 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x8d, + 0x01, 0x0a, 0x0c, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x5f, 0x6b, + 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, + 0x70, 0x4b, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0e, 0x70, 0x5f, 0x6b, + 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x70, 0x4b, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x41, + 0x0a, 0x0d, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, + 0x30, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x69, 0x6e, + 0x69, 0x6d, 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x22, 0x39, 0x0a, 0x0e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0xfd, 0x02, 0x0a, + 0x0e, 0x56, 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, 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, 0x2a, 0x0a, 0x06, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, 0x6e, + 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x5f, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x52, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4c, + 0x61, 0x73, 0x74, 0x50, 0x4b, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3d, 0x0a, 0x0f, + 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x12, + 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 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, 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, + 0x6b, 0x18, 0x05, 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, 0x6c, 0x61, 0x73, + 0x74, 0x70, 0x6b, 0x22, 0xa4, 0x02, 0x0a, 0x13, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x52, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, + 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, + 0x1e, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, + 0x22, 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x06, 0x6c, 0x61, 0x73, + 0x74, 0x70, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, + 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, + 0x29, 0x0a, 0x10, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x68, 0x72, 0x6f, 0x74, + 0x74, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xc5, 0x01, 0x0a, 0x14, 0x56, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 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, @@ -3402,61 +3470,100 @@ var file_binlogdata_proto_rawDesc = []byte{ 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x72, 0x0a, 0x16, 0x56, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x74, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x04, - 0x72, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x2a, 0x3e, 0x0a, 0x0b, - 0x4f, 0x6e, 0x44, 0x44, 0x4c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x49, - 0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, - 0x01, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x58, 0x45, 0x43, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x45, - 0x58, 0x45, 0x43, 0x5f, 0x49, 0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x03, 0x2a, 0x7b, 0x0a, 0x18, - 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x6f, 0x76, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x10, 0x02, - 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x10, 0x03, 0x12, 0x0b, 0x0a, - 0x07, 0x52, 0x65, 0x73, 0x68, 0x61, 0x72, 0x64, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x44, 0x4c, 0x10, 0x05, 0x2a, 0x44, 0x0a, 0x1b, 0x56, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x10, 0x01, 0x12, - 0x0e, 0x0a, 0x0a, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x70, 0x79, 0x10, 0x02, 0x2a, - 0x71, 0x0a, 0x19, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, - 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x6e, 0x69, - 0x74, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x10, 0x02, - 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x70, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x03, 0x12, 0x0b, 0x0a, - 0x07, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x61, 0x67, 0x67, 0x69, 0x6e, 0x67, - 0x10, 0x06, 0x2a, 0x8d, 0x02, 0x0a, 0x0a, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, - 0x0a, 0x04, 0x47, 0x54, 0x49, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x45, 0x47, 0x49, - 0x4e, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x12, - 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x04, 0x12, 0x07, 0x0a, - 0x03, 0x44, 0x44, 0x4c, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, - 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x07, 0x12, - 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x08, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x09, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x0a, - 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x07, 0x0a, 0x03, 0x52, - 0x4f, 0x57, 0x10, 0x0c, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x0d, 0x12, - 0x0d, 0x0a, 0x09, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x0e, 0x12, 0x09, - 0x0a, 0x05, 0x56, 0x47, 0x54, 0x49, 0x44, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4a, 0x4f, 0x55, - 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, - 0x4e, 0x10, 0x11, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x53, 0x54, 0x50, 0x4b, 0x10, 0x12, 0x12, - 0x0d, 0x0a, 0x09, 0x53, 0x41, 0x56, 0x45, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x13, 0x12, 0x12, - 0x0a, 0x0e, 0x43, 0x4f, 0x50, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, - 0x10, 0x14, 0x2a, 0x27, 0x0a, 0x0d, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x00, 0x12, - 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x52, 0x44, 0x53, 0x10, 0x01, 0x42, 0x29, 0x5a, 0x27, 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, 0x62, 0x69, 0x6e, 0x6c, - 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x15, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x52, 0x08, 0x70, 0x6b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, + 0x74, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, + 0x1e, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, + 0x22, 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x06, 0x6c, 0x61, 0x73, + 0x74, 0x70, 0x6b, 0x22, 0x69, 0x0a, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x70, 0x5f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, + 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, + 0x74, 0x50, 0x4b, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, + 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x58, + 0x0a, 0x0b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x12, 0x1d, 0x0a, + 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x06, + 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x18, 0x03, 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, 0x6c, 0x61, 0x73, 0x74, 0x70, 0x6b, 0x22, 0xdc, 0x01, 0x0a, 0x15, 0x56, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 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, 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x72, 0x0a, 0x16, 0x56, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, + 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x74, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x74, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x04, 0x72, + 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x2a, 0x3e, 0x0a, 0x0b, 0x4f, + 0x6e, 0x44, 0x44, 0x4c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x47, + 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, + 0x12, 0x08, 0x0a, 0x04, 0x45, 0x58, 0x45, 0x43, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x58, + 0x45, 0x43, 0x5f, 0x49, 0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x03, 0x2a, 0x7b, 0x0a, 0x18, 0x56, + 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x65, 0x72, + 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x6f, 0x76, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, + 0x52, 0x65, 0x73, 0x68, 0x61, 0x72, 0x64, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x44, 0x44, 0x4c, 0x10, 0x05, 0x2a, 0x44, 0x0a, 0x1b, 0x56, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x10, 0x01, 0x12, 0x0e, + 0x0a, 0x0a, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x70, 0x79, 0x10, 0x02, 0x2a, 0x71, + 0x0a, 0x19, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x70, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, + 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x61, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x10, + 0x06, 0x2a, 0x8d, 0x02, 0x0a, 0x0a, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, + 0x04, 0x47, 0x54, 0x49, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x45, 0x47, 0x49, 0x4e, + 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x12, 0x0c, + 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, + 0x44, 0x44, 0x4c, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x10, + 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x07, 0x12, 0x0a, + 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x08, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, + 0x4c, 0x45, 0x54, 0x45, 0x10, 0x09, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x0a, 0x12, + 0x09, 0x0a, 0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x4f, + 0x57, 0x10, 0x0c, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x0d, 0x12, 0x0d, + 0x0a, 0x09, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x0e, 0x12, 0x09, 0x0a, + 0x05, 0x56, 0x47, 0x54, 0x49, 0x44, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4a, 0x4f, 0x55, 0x52, + 0x4e, 0x41, 0x4c, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, + 0x10, 0x11, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x53, 0x54, 0x50, 0x4b, 0x10, 0x12, 0x12, 0x0d, + 0x0a, 0x09, 0x53, 0x41, 0x56, 0x45, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x13, 0x12, 0x12, 0x0a, + 0x0e, 0x43, 0x4f, 0x50, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, + 0x14, 0x2a, 0x27, 0x0a, 0x0d, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x00, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x48, 0x41, 0x52, 0x44, 0x53, 0x10, 0x01, 0x42, 0x29, 0x5a, 0x27, 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, 0x62, 0x69, 0x6e, 0x6c, 0x6f, + 0x67, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3472,7 +3579,7 @@ func file_binlogdata_proto_rawDescGZIP() []byte { } var file_binlogdata_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_binlogdata_proto_msgTypes = make([]protoimpl.MessageInfo, 35) +var file_binlogdata_proto_msgTypes = make([]protoimpl.MessageInfo, 36) var file_binlogdata_proto_goTypes = []any{ (OnDDLAction)(0), // 0: binlogdata.OnDDLAction (VReplicationWorkflowType)(0), // 1: binlogdata.VReplicationWorkflowType @@ -3502,54 +3609,55 @@ var file_binlogdata_proto_goTypes = []any{ (*VEvent)(nil), // 25: binlogdata.VEvent (*MinimalTable)(nil), // 26: binlogdata.MinimalTable (*MinimalSchema)(nil), // 27: binlogdata.MinimalSchema - (*VStreamRequest)(nil), // 28: binlogdata.VStreamRequest - (*VStreamResponse)(nil), // 29: binlogdata.VStreamResponse - (*VStreamRowsRequest)(nil), // 30: binlogdata.VStreamRowsRequest - (*VStreamRowsResponse)(nil), // 31: binlogdata.VStreamRowsResponse - (*VStreamTablesRequest)(nil), // 32: binlogdata.VStreamTablesRequest - (*VStreamTablesResponse)(nil), // 33: binlogdata.VStreamTablesResponse - (*LastPKEvent)(nil), // 34: binlogdata.LastPKEvent - (*TableLastPK)(nil), // 35: binlogdata.TableLastPK - (*VStreamResultsRequest)(nil), // 36: binlogdata.VStreamResultsRequest - (*VStreamResultsResponse)(nil), // 37: binlogdata.VStreamResultsResponse - (*BinlogTransaction_Statement)(nil), // 38: binlogdata.BinlogTransaction.Statement - nil, // 39: binlogdata.Rule.ConvertEnumToTextEntry - nil, // 40: binlogdata.Rule.ConvertCharsetEntry - nil, // 41: binlogdata.Rule.ConvertIntToEnumEntry - (*RowChange_Bitmap)(nil), // 42: binlogdata.RowChange.Bitmap - (*query.EventToken)(nil), // 43: query.EventToken - (*topodata.KeyRange)(nil), // 44: topodata.KeyRange - (topodata.TabletType)(0), // 45: topodata.TabletType - (*query.Row)(nil), // 46: query.Row - (*query.Field)(nil), // 47: query.Field - (*vtrpc.CallerID)(nil), // 48: vtrpc.CallerID - (*query.VTGateCallerID)(nil), // 49: query.VTGateCallerID - (*query.Target)(nil), // 50: query.Target - (*query.QueryResult)(nil), // 51: query.QueryResult + (*VStreamOptions)(nil), // 28: binlogdata.VStreamOptions + (*VStreamRequest)(nil), // 29: binlogdata.VStreamRequest + (*VStreamResponse)(nil), // 30: binlogdata.VStreamResponse + (*VStreamRowsRequest)(nil), // 31: binlogdata.VStreamRowsRequest + (*VStreamRowsResponse)(nil), // 32: binlogdata.VStreamRowsResponse + (*VStreamTablesRequest)(nil), // 33: binlogdata.VStreamTablesRequest + (*VStreamTablesResponse)(nil), // 34: binlogdata.VStreamTablesResponse + (*LastPKEvent)(nil), // 35: binlogdata.LastPKEvent + (*TableLastPK)(nil), // 36: binlogdata.TableLastPK + (*VStreamResultsRequest)(nil), // 37: binlogdata.VStreamResultsRequest + (*VStreamResultsResponse)(nil), // 38: binlogdata.VStreamResultsResponse + (*BinlogTransaction_Statement)(nil), // 39: binlogdata.BinlogTransaction.Statement + nil, // 40: binlogdata.Rule.ConvertEnumToTextEntry + nil, // 41: binlogdata.Rule.ConvertCharsetEntry + nil, // 42: binlogdata.Rule.ConvertIntToEnumEntry + (*RowChange_Bitmap)(nil), // 43: binlogdata.RowChange.Bitmap + (*query.EventToken)(nil), // 44: query.EventToken + (*topodata.KeyRange)(nil), // 45: topodata.KeyRange + (topodata.TabletType)(0), // 46: topodata.TabletType + (*query.Row)(nil), // 47: query.Row + (*query.Field)(nil), // 48: query.Field + (*vtrpc.CallerID)(nil), // 49: vtrpc.CallerID + (*query.VTGateCallerID)(nil), // 50: query.VTGateCallerID + (*query.Target)(nil), // 51: query.Target + (*query.QueryResult)(nil), // 52: query.QueryResult } var file_binlogdata_proto_depIdxs = []int32{ - 38, // 0: binlogdata.BinlogTransaction.statements:type_name -> binlogdata.BinlogTransaction.Statement - 43, // 1: binlogdata.BinlogTransaction.event_token:type_name -> query.EventToken - 44, // 2: binlogdata.StreamKeyRangeRequest.key_range:type_name -> topodata.KeyRange + 39, // 0: binlogdata.BinlogTransaction.statements:type_name -> binlogdata.BinlogTransaction.Statement + 44, // 1: binlogdata.BinlogTransaction.event_token:type_name -> query.EventToken + 45, // 2: binlogdata.StreamKeyRangeRequest.key_range:type_name -> topodata.KeyRange 8, // 3: binlogdata.StreamKeyRangeRequest.charset:type_name -> binlogdata.Charset 9, // 4: binlogdata.StreamKeyRangeResponse.binlog_transaction:type_name -> binlogdata.BinlogTransaction 8, // 5: binlogdata.StreamTablesRequest.charset:type_name -> binlogdata.Charset 9, // 6: binlogdata.StreamTablesResponse.binlog_transaction:type_name -> binlogdata.BinlogTransaction - 39, // 7: binlogdata.Rule.convert_enum_to_text:type_name -> binlogdata.Rule.ConvertEnumToTextEntry - 40, // 8: binlogdata.Rule.convert_charset:type_name -> binlogdata.Rule.ConvertCharsetEntry - 41, // 9: binlogdata.Rule.convert_int_to_enum:type_name -> binlogdata.Rule.ConvertIntToEnumEntry + 40, // 7: binlogdata.Rule.convert_enum_to_text:type_name -> binlogdata.Rule.ConvertEnumToTextEntry + 41, // 8: binlogdata.Rule.convert_charset:type_name -> binlogdata.Rule.ConvertCharsetEntry + 42, // 9: binlogdata.Rule.convert_int_to_enum:type_name -> binlogdata.Rule.ConvertIntToEnumEntry 15, // 10: binlogdata.Filter.rules:type_name -> binlogdata.Rule 7, // 11: binlogdata.Filter.field_event_mode:type_name -> binlogdata.Filter.FieldEventMode - 45, // 12: binlogdata.BinlogSource.tablet_type:type_name -> topodata.TabletType - 44, // 13: binlogdata.BinlogSource.key_range:type_name -> topodata.KeyRange + 46, // 12: binlogdata.BinlogSource.tablet_type:type_name -> topodata.TabletType + 45, // 13: binlogdata.BinlogSource.key_range:type_name -> topodata.KeyRange 16, // 14: binlogdata.BinlogSource.filter:type_name -> binlogdata.Filter 0, // 15: binlogdata.BinlogSource.on_ddl:type_name -> binlogdata.OnDDLAction - 46, // 16: binlogdata.RowChange.before:type_name -> query.Row - 46, // 17: binlogdata.RowChange.after:type_name -> query.Row - 42, // 18: binlogdata.RowChange.data_columns:type_name -> binlogdata.RowChange.Bitmap + 47, // 16: binlogdata.RowChange.before:type_name -> query.Row + 47, // 17: binlogdata.RowChange.after:type_name -> query.Row + 43, // 18: binlogdata.RowChange.data_columns:type_name -> binlogdata.RowChange.Bitmap 18, // 19: binlogdata.RowEvent.row_changes:type_name -> binlogdata.RowChange - 47, // 20: binlogdata.FieldEvent.fields:type_name -> query.Field - 35, // 21: binlogdata.ShardGtid.table_p_ks:type_name -> binlogdata.TableLastPK + 48, // 20: binlogdata.FieldEvent.fields:type_name -> query.Field + 36, // 21: binlogdata.ShardGtid.table_p_ks:type_name -> binlogdata.TableLastPK 21, // 22: binlogdata.VGtid.shard_gtids:type_name -> binlogdata.ShardGtid 5, // 23: binlogdata.Journal.migration_type:type_name -> binlogdata.MigrationType 21, // 24: binlogdata.Journal.shard_gtids:type_name -> binlogdata.ShardGtid @@ -3559,45 +3667,46 @@ var file_binlogdata_proto_depIdxs = []int32{ 20, // 28: binlogdata.VEvent.field_event:type_name -> binlogdata.FieldEvent 22, // 29: binlogdata.VEvent.vgtid:type_name -> binlogdata.VGtid 24, // 30: binlogdata.VEvent.journal:type_name -> binlogdata.Journal - 34, // 31: binlogdata.VEvent.last_p_k_event:type_name -> binlogdata.LastPKEvent - 47, // 32: binlogdata.MinimalTable.fields:type_name -> query.Field + 35, // 31: binlogdata.VEvent.last_p_k_event:type_name -> binlogdata.LastPKEvent + 48, // 32: binlogdata.MinimalTable.fields:type_name -> query.Field 26, // 33: binlogdata.MinimalSchema.tables:type_name -> binlogdata.MinimalTable - 48, // 34: binlogdata.VStreamRequest.effective_caller_id:type_name -> vtrpc.CallerID - 49, // 35: binlogdata.VStreamRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 50, // 36: binlogdata.VStreamRequest.target:type_name -> query.Target + 49, // 34: binlogdata.VStreamRequest.effective_caller_id:type_name -> vtrpc.CallerID + 50, // 35: binlogdata.VStreamRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 51, // 36: binlogdata.VStreamRequest.target:type_name -> query.Target 16, // 37: binlogdata.VStreamRequest.filter:type_name -> binlogdata.Filter - 35, // 38: binlogdata.VStreamRequest.table_last_p_ks:type_name -> binlogdata.TableLastPK - 25, // 39: binlogdata.VStreamResponse.events:type_name -> binlogdata.VEvent - 48, // 40: binlogdata.VStreamRowsRequest.effective_caller_id:type_name -> vtrpc.CallerID - 49, // 41: binlogdata.VStreamRowsRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 50, // 42: binlogdata.VStreamRowsRequest.target:type_name -> query.Target - 51, // 43: binlogdata.VStreamRowsRequest.lastpk:type_name -> query.QueryResult - 47, // 44: binlogdata.VStreamRowsResponse.fields:type_name -> query.Field - 47, // 45: binlogdata.VStreamRowsResponse.pkfields:type_name -> query.Field - 46, // 46: binlogdata.VStreamRowsResponse.rows:type_name -> query.Row - 46, // 47: binlogdata.VStreamRowsResponse.lastpk:type_name -> query.Row - 48, // 48: binlogdata.VStreamTablesRequest.effective_caller_id:type_name -> vtrpc.CallerID - 49, // 49: binlogdata.VStreamTablesRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 50, // 50: binlogdata.VStreamTablesRequest.target:type_name -> query.Target - 47, // 51: binlogdata.VStreamTablesResponse.fields:type_name -> query.Field - 47, // 52: binlogdata.VStreamTablesResponse.pkfields:type_name -> query.Field - 46, // 53: binlogdata.VStreamTablesResponse.rows:type_name -> query.Row - 46, // 54: binlogdata.VStreamTablesResponse.lastpk:type_name -> query.Row - 35, // 55: binlogdata.LastPKEvent.table_last_p_k:type_name -> binlogdata.TableLastPK - 51, // 56: binlogdata.TableLastPK.lastpk:type_name -> query.QueryResult - 48, // 57: binlogdata.VStreamResultsRequest.effective_caller_id:type_name -> vtrpc.CallerID - 49, // 58: binlogdata.VStreamResultsRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 50, // 59: binlogdata.VStreamResultsRequest.target:type_name -> query.Target - 47, // 60: binlogdata.VStreamResultsResponse.fields:type_name -> query.Field - 46, // 61: binlogdata.VStreamResultsResponse.rows:type_name -> query.Row - 6, // 62: binlogdata.BinlogTransaction.Statement.category:type_name -> binlogdata.BinlogTransaction.Statement.Category - 8, // 63: binlogdata.BinlogTransaction.Statement.charset:type_name -> binlogdata.Charset - 14, // 64: binlogdata.Rule.ConvertCharsetEntry.value:type_name -> binlogdata.CharsetConversion - 65, // [65:65] is the sub-list for method output_type - 65, // [65:65] is the sub-list for method input_type - 65, // [65:65] is the sub-list for extension type_name - 65, // [65:65] is the sub-list for extension extendee - 0, // [0:65] is the sub-list for field type_name + 36, // 38: binlogdata.VStreamRequest.table_last_p_ks:type_name -> binlogdata.TableLastPK + 28, // 39: binlogdata.VStreamRequest.options:type_name -> binlogdata.VStreamOptions + 25, // 40: binlogdata.VStreamResponse.events:type_name -> binlogdata.VEvent + 49, // 41: binlogdata.VStreamRowsRequest.effective_caller_id:type_name -> vtrpc.CallerID + 50, // 42: binlogdata.VStreamRowsRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 51, // 43: binlogdata.VStreamRowsRequest.target:type_name -> query.Target + 52, // 44: binlogdata.VStreamRowsRequest.lastpk:type_name -> query.QueryResult + 48, // 45: binlogdata.VStreamRowsResponse.fields:type_name -> query.Field + 48, // 46: binlogdata.VStreamRowsResponse.pkfields:type_name -> query.Field + 47, // 47: binlogdata.VStreamRowsResponse.rows:type_name -> query.Row + 47, // 48: binlogdata.VStreamRowsResponse.lastpk:type_name -> query.Row + 49, // 49: binlogdata.VStreamTablesRequest.effective_caller_id:type_name -> vtrpc.CallerID + 50, // 50: binlogdata.VStreamTablesRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 51, // 51: binlogdata.VStreamTablesRequest.target:type_name -> query.Target + 48, // 52: binlogdata.VStreamTablesResponse.fields:type_name -> query.Field + 48, // 53: binlogdata.VStreamTablesResponse.pkfields:type_name -> query.Field + 47, // 54: binlogdata.VStreamTablesResponse.rows:type_name -> query.Row + 47, // 55: binlogdata.VStreamTablesResponse.lastpk:type_name -> query.Row + 36, // 56: binlogdata.LastPKEvent.table_last_p_k:type_name -> binlogdata.TableLastPK + 52, // 57: binlogdata.TableLastPK.lastpk:type_name -> query.QueryResult + 49, // 58: binlogdata.VStreamResultsRequest.effective_caller_id:type_name -> vtrpc.CallerID + 50, // 59: binlogdata.VStreamResultsRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 51, // 60: binlogdata.VStreamResultsRequest.target:type_name -> query.Target + 48, // 61: binlogdata.VStreamResultsResponse.fields:type_name -> query.Field + 47, // 62: binlogdata.VStreamResultsResponse.rows:type_name -> query.Row + 6, // 63: binlogdata.BinlogTransaction.Statement.category:type_name -> binlogdata.BinlogTransaction.Statement.Category + 8, // 64: binlogdata.BinlogTransaction.Statement.charset:type_name -> binlogdata.Charset + 14, // 65: binlogdata.Rule.ConvertCharsetEntry.value:type_name -> binlogdata.CharsetConversion + 66, // [66:66] is the sub-list for method output_type + 66, // [66:66] is the sub-list for method input_type + 66, // [66:66] is the sub-list for extension type_name + 66, // [66:66] is the sub-list for extension extendee + 0, // [0:66] is the sub-list for field type_name } func init() { file_binlogdata_proto_init() } @@ -3847,7 +3956,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[20].Exporter = func(v any, i int) any { - switch v := v.(*VStreamRequest); i { + switch v := v.(*VStreamOptions); i { case 0: return &v.state case 1: @@ -3859,7 +3968,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[21].Exporter = func(v any, i int) any { - switch v := v.(*VStreamResponse); i { + switch v := v.(*VStreamRequest); i { case 0: return &v.state case 1: @@ -3871,7 +3980,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[22].Exporter = func(v any, i int) any { - switch v := v.(*VStreamRowsRequest); i { + switch v := v.(*VStreamResponse); i { case 0: return &v.state case 1: @@ -3883,7 +3992,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[23].Exporter = func(v any, i int) any { - switch v := v.(*VStreamRowsResponse); i { + switch v := v.(*VStreamRowsRequest); i { case 0: return &v.state case 1: @@ -3895,7 +4004,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[24].Exporter = func(v any, i int) any { - switch v := v.(*VStreamTablesRequest); i { + switch v := v.(*VStreamRowsResponse); i { case 0: return &v.state case 1: @@ -3907,7 +4016,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[25].Exporter = func(v any, i int) any { - switch v := v.(*VStreamTablesResponse); i { + switch v := v.(*VStreamTablesRequest); i { case 0: return &v.state case 1: @@ -3919,7 +4028,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[26].Exporter = func(v any, i int) any { - switch v := v.(*LastPKEvent); i { + switch v := v.(*VStreamTablesResponse); i { case 0: return &v.state case 1: @@ -3931,7 +4040,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[27].Exporter = func(v any, i int) any { - switch v := v.(*TableLastPK); i { + switch v := v.(*LastPKEvent); i { case 0: return &v.state case 1: @@ -3943,7 +4052,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[28].Exporter = func(v any, i int) any { - switch v := v.(*VStreamResultsRequest); i { + switch v := v.(*TableLastPK); i { case 0: return &v.state case 1: @@ -3955,7 +4064,7 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[29].Exporter = func(v any, i int) any { - switch v := v.(*VStreamResultsResponse); i { + switch v := v.(*VStreamResultsRequest); i { case 0: return &v.state case 1: @@ -3967,6 +4076,18 @@ func file_binlogdata_proto_init() { } } file_binlogdata_proto_msgTypes[30].Exporter = func(v any, i int) any { + switch v := v.(*VStreamResultsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_binlogdata_proto_msgTypes[31].Exporter = func(v any, i int) any { switch v := v.(*BinlogTransaction_Statement); i { case 0: return &v.state @@ -3978,7 +4099,7 @@ func file_binlogdata_proto_init() { return nil } } - file_binlogdata_proto_msgTypes[34].Exporter = func(v any, i int) any { + file_binlogdata_proto_msgTypes[35].Exporter = func(v any, i int) any { switch v := v.(*RowChange_Bitmap); i { case 0: return &v.state @@ -3997,7 +4118,7 @@ func file_binlogdata_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_binlogdata_proto_rawDesc, NumEnums: 8, - NumMessages: 35, + NumMessages: 36, NumExtensions: 0, NumServices: 0, }, diff --git a/go/vt/proto/binlogdata/binlogdata_vtproto.pb.go b/go/vt/proto/binlogdata/binlogdata_vtproto.pb.go index 1332681a976..53f307fdb2f 100644 --- a/go/vt/proto/binlogdata/binlogdata_vtproto.pb.go +++ b/go/vt/proto/binlogdata/binlogdata_vtproto.pb.go @@ -343,10 +343,11 @@ func (m *RowEvent) CloneVT() *RowEvent { return (*RowEvent)(nil) } r := &RowEvent{ - TableName: m.TableName, - Keyspace: m.Keyspace, - Shard: m.Shard, - Flags: m.Flags, + TableName: m.TableName, + Keyspace: m.Keyspace, + Shard: m.Shard, + Flags: m.Flags, + IsInternalTable: m.IsInternalTable, } if rhs := m.RowChanges; rhs != nil { tmpContainer := make([]*RowChange, len(rhs)) @@ -375,6 +376,7 @@ func (m *FieldEvent) CloneVT() *FieldEvent { Keyspace: m.Keyspace, Shard: m.Shard, EnumSetStringValues: m.EnumSetStringValues, + IsInternalTable: m.IsInternalTable, } if rhs := m.Fields; rhs != nil { tmpContainer := make([]*query.Field, len(rhs)) @@ -512,20 +514,21 @@ func (m *VEvent) CloneVT() *VEvent { return (*VEvent)(nil) } r := &VEvent{ - Type: m.Type, - Timestamp: m.Timestamp, - Gtid: m.Gtid, - Statement: m.Statement, - RowEvent: m.RowEvent.CloneVT(), - FieldEvent: m.FieldEvent.CloneVT(), - Vgtid: m.Vgtid.CloneVT(), - Journal: m.Journal.CloneVT(), - Dml: m.Dml, - CurrentTime: m.CurrentTime, - LastPKEvent: m.LastPKEvent.CloneVT(), - Keyspace: m.Keyspace, - Shard: m.Shard, - Throttled: m.Throttled, + Type: m.Type, + Timestamp: m.Timestamp, + Gtid: m.Gtid, + Statement: m.Statement, + RowEvent: m.RowEvent.CloneVT(), + FieldEvent: m.FieldEvent.CloneVT(), + Vgtid: m.Vgtid.CloneVT(), + Journal: m.Journal.CloneVT(), + Dml: m.Dml, + CurrentTime: m.CurrentTime, + LastPKEvent: m.LastPKEvent.CloneVT(), + Keyspace: m.Keyspace, + Shard: m.Shard, + Throttled: m.Throttled, + ThrottledReason: m.ThrottledReason, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -592,6 +595,27 @@ func (m *MinimalSchema) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *VStreamOptions) CloneVT() *VStreamOptions { + if m == nil { + return (*VStreamOptions)(nil) + } + r := &VStreamOptions{} + if rhs := m.InternalTables; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.InternalTables = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *VStreamOptions) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *VStreamRequest) CloneVT() *VStreamRequest { if m == nil { return (*VStreamRequest)(nil) @@ -602,6 +626,7 @@ func (m *VStreamRequest) CloneVT() *VStreamRequest { Target: m.Target.CloneVT(), Position: m.Position, Filter: m.Filter.CloneVT(), + Options: m.Options.CloneVT(), } if rhs := m.TableLastPKs; rhs != nil { tmpContainer := make([]*TableLastPK, len(rhs)) @@ -671,10 +696,11 @@ func (m *VStreamRowsResponse) CloneVT() *VStreamRowsResponse { return (*VStreamRowsResponse)(nil) } r := &VStreamRowsResponse{ - Gtid: m.Gtid, - Lastpk: m.Lastpk.CloneVT(), - Throttled: m.Throttled, - Heartbeat: m.Heartbeat, + Gtid: m.Gtid, + Lastpk: m.Lastpk.CloneVT(), + Throttled: m.Throttled, + Heartbeat: m.Heartbeat, + ThrottledReason: m.ThrottledReason, } if rhs := m.Fields; rhs != nil { tmpContainer := make([]*query.Field, len(rhs)) @@ -1732,6 +1758,16 @@ func (m *RowEvent) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.IsInternalTable { + i-- + if m.IsInternalTable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if m.Flags != 0 { i = encodeVarint(dAtA, i, uint64(m.Flags)) i-- @@ -1803,6 +1839,18 @@ func (m *FieldEvent) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.IsInternalTable { + i-- + if m.IsInternalTable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xd0 + } if m.EnumSetStringValues { i-- if m.EnumSetStringValues { @@ -2131,6 +2179,15 @@ func (m *VEvent) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.ThrottledReason) > 0 { + i -= len(m.ThrottledReason) + copy(dAtA[i:], m.ThrottledReason) + i = encodeVarint(dAtA, i, uint64(len(m.ThrottledReason))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xca + } if m.Throttled { i-- if m.Throttled { @@ -2379,6 +2436,48 @@ func (m *MinimalSchema) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *VStreamOptions) 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 *VStreamOptions) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *VStreamOptions) 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.InternalTables) > 0 { + for iNdEx := len(m.InternalTables) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.InternalTables[iNdEx]) + copy(dAtA[i:], m.InternalTables[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.InternalTables[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *VStreamRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -2409,6 +2508,16 @@ func (m *VStreamRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Options != nil { + size, err := m.Options.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } if len(m.TableLastPKs) > 0 { for iNdEx := len(m.TableLastPKs) - 1; iNdEx >= 0; iNdEx-- { size, err := m.TableLastPKs[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) @@ -2626,6 +2735,13 @@ func (m *VStreamRowsResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.ThrottledReason) > 0 { + i -= len(m.ThrottledReason) + copy(dAtA[i:], m.ThrottledReason) + i = encodeVarint(dAtA, i, uint64(len(m.ThrottledReason))) + i-- + dAtA[i] = 0x42 + } if m.Heartbeat { i-- if m.Heartbeat { @@ -3540,6 +3656,9 @@ func (m *RowEvent) SizeVT() (n int) { if m.Flags != 0 { n += 1 + sov(uint64(m.Flags)) } + if m.IsInternalTable { + n += 2 + } n += len(m.unknownFields) return n } @@ -3571,6 +3690,9 @@ func (m *FieldEvent) SizeVT() (n int) { if m.EnumSetStringValues { n += 3 } + if m.IsInternalTable { + n += 3 + } n += len(m.unknownFields) return n } @@ -3739,6 +3861,10 @@ func (m *VEvent) SizeVT() (n int) { if m.Throttled { n += 3 } + l = len(m.ThrottledReason) + if l > 0 { + n += 2 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -3790,6 +3916,22 @@ func (m *MinimalSchema) SizeVT() (n int) { return n } +func (m *VStreamOptions) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.InternalTables) > 0 { + for _, s := range m.InternalTables { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + func (m *VStreamRequest) SizeVT() (n int) { if m == nil { return 0 @@ -3822,6 +3964,10 @@ func (m *VStreamRequest) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } + if m.Options != nil { + l = m.Options.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -3910,6 +4056,10 @@ func (m *VStreamRowsResponse) SizeVT() (n int) { if m.Heartbeat { n += 2 } + l = len(m.ThrottledReason) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -6648,6 +6798,26 @@ func (m *RowEvent) UnmarshalVT(dAtA []byte) error { break } } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsInternalTable", 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.IsInternalTable = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -6849,6 +7019,26 @@ func (m *FieldEvent) UnmarshalVT(dAtA []byte) error { } } m.EnumSetStringValues = bool(v != 0) + case 26: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsInternalTable", 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.IsInternalTable = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -7951,6 +8141,38 @@ func (m *VEvent) UnmarshalVT(dAtA []byte) error { } } m.Throttled = bool(v != 0) + case 25: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ThrottledReason", 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.ThrottledReason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -8283,6 +8505,89 @@ func (m *MinimalSchema) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *VStreamOptions) 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: VStreamOptions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VStreamOptions: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InternalTables", 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.InternalTables = append(m.InternalTables, 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 *VStreamRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -8522,6 +8827,42 @@ func (m *VStreamRequest) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", 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.Options == nil { + m.Options = &VStreamOptions{} + } + if err := m.Options.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -9116,6 +9457,38 @@ func (m *VStreamRowsResponse) UnmarshalVT(dAtA []byte) error { } } m.Heartbeat = bool(v != 0) + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ThrottledReason", 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.ThrottledReason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/go/vt/proto/query/cached_size.go b/go/vt/proto/query/cached_size.go index 735bd555e55..5b613317294 100644 --- a/go/vt/proto/query/cached_size.go +++ b/go/vt/proto/query/cached_size.go @@ -27,10 +27,6 @@ func (cached *BindVariable) CachedSize(alloc bool) int64 { if alloc { size += int64(96) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Value []byte { size += hack.RuntimeAllocSize(int64(cap(cached.Value))) @@ -52,10 +48,6 @@ func (cached *Field) CachedSize(alloc bool) int64 { if alloc { size += int64(160) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Name string size += hack.RuntimeAllocSize(int64(len(cached.Name))) // field Table string @@ -78,10 +70,6 @@ func (cached *QueryWarning) CachedSize(alloc bool) int64 { if alloc { size += int64(64) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Message string size += hack.RuntimeAllocSize(int64(len(cached.Message))) return size @@ -94,10 +82,6 @@ func (cached *Target) CachedSize(alloc bool) int64 { if alloc { size += int64(96) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Keyspace string size += hack.RuntimeAllocSize(int64(len(cached.Keyspace))) // field Shard string @@ -114,10 +98,6 @@ func (cached *Value) CachedSize(alloc bool) int64 { if alloc { size += int64(80) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Value []byte { size += hack.RuntimeAllocSize(int64(cap(cached.Value))) 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/tabletmanagerdata/tabletmanagerdata.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go index c0896882735..27999620703 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go @@ -96,6 +96,64 @@ func (TabletSelectionPreference) EnumDescriptor() ([]byte, []int) { return file_tabletmanagerdata_proto_rawDescGZIP(), []int{0} } +type CheckThrottlerResponseCode int32 + +const ( + CheckThrottlerResponseCode_UNDEFINED CheckThrottlerResponseCode = 0 + CheckThrottlerResponseCode_OK CheckThrottlerResponseCode = 1 + CheckThrottlerResponseCode_THRESHOLD_EXCEEDED CheckThrottlerResponseCode = 2 + CheckThrottlerResponseCode_APP_DENIED CheckThrottlerResponseCode = 3 + CheckThrottlerResponseCode_UNKNOWN_METRIC CheckThrottlerResponseCode = 4 + CheckThrottlerResponseCode_INTERNAL_ERROR CheckThrottlerResponseCode = 5 +) + +// Enum value maps for CheckThrottlerResponseCode. +var ( + CheckThrottlerResponseCode_name = map[int32]string{ + 0: "UNDEFINED", + 1: "OK", + 2: "THRESHOLD_EXCEEDED", + 3: "APP_DENIED", + 4: "UNKNOWN_METRIC", + 5: "INTERNAL_ERROR", + } + CheckThrottlerResponseCode_value = map[string]int32{ + "UNDEFINED": 0, + "OK": 1, + "THRESHOLD_EXCEEDED": 2, + "APP_DENIED": 3, + "UNKNOWN_METRIC": 4, + "INTERNAL_ERROR": 5, + } +) + +func (x CheckThrottlerResponseCode) Enum() *CheckThrottlerResponseCode { + p := new(CheckThrottlerResponseCode) + *p = x + return p +} + +func (x CheckThrottlerResponseCode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CheckThrottlerResponseCode) Descriptor() protoreflect.EnumDescriptor { + return file_tabletmanagerdata_proto_enumTypes[1].Descriptor() +} + +func (CheckThrottlerResponseCode) Type() protoreflect.EnumType { + return &file_tabletmanagerdata_proto_enumTypes[1] +} + +func (x CheckThrottlerResponseCode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CheckThrottlerResponseCode.Descriptor instead. +func (CheckThrottlerResponseCode) EnumDescriptor() ([]byte, []int) { + return file_tabletmanagerdata_proto_rawDescGZIP(), []int{1} +} + type TableDefinition struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -5927,10 +5985,11 @@ type VDiffReportOptions struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - OnlyPks bool `protobuf:"varint,1,opt,name=only_pks,json=onlyPks,proto3" json:"only_pks,omitempty"` - DebugQuery bool `protobuf:"varint,2,opt,name=debug_query,json=debugQuery,proto3" json:"debug_query,omitempty"` - Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"` - MaxSampleRows int64 `protobuf:"varint,4,opt,name=max_sample_rows,json=maxSampleRows,proto3" json:"max_sample_rows,omitempty"` + OnlyPks bool `protobuf:"varint,1,opt,name=only_pks,json=onlyPks,proto3" json:"only_pks,omitempty"` + DebugQuery bool `protobuf:"varint,2,opt,name=debug_query,json=debugQuery,proto3" json:"debug_query,omitempty"` + Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"` + MaxSampleRows int64 `protobuf:"varint,4,opt,name=max_sample_rows,json=maxSampleRows,proto3" json:"max_sample_rows,omitempty"` + RowDiffColumnTruncateAt int64 `protobuf:"varint,5,opt,name=row_diff_column_truncate_at,json=rowDiffColumnTruncateAt,proto3" json:"row_diff_column_truncate_at,omitempty"` } func (x *VDiffReportOptions) Reset() { @@ -5993,6 +6052,13 @@ func (x *VDiffReportOptions) GetMaxSampleRows() int64 { return 0 } +func (x *VDiffReportOptions) GetRowDiffColumnTruncateAt() int64 { + if x != nil { + return x.RowDiffColumnTruncateAt + } + return 0 +} + type VDiffCoreOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6636,6 +6702,12 @@ type CheckThrottlerResponse struct { // 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"` + // AppName is the name of app that was matched by the throttler + AppName string `protobuf:"bytes,8,opt,name=app_name,json=appName,proto3" json:"app_name,omitempty"` + // Summary is a human readable analysis of the result + Summary string `protobuf:"bytes,9,opt,name=summary,proto3" json:"summary,omitempty"` + // ResponseCode is the enum representation of the response + ResponseCode CheckThrottlerResponseCode `protobuf:"varint,10,opt,name=response_code,json=responseCode,proto3,enum=tabletmanagerdata.CheckThrottlerResponseCode" json:"response_code,omitempty"` } func (x *CheckThrottlerResponse) Reset() { @@ -6719,6 +6791,27 @@ func (x *CheckThrottlerResponse) GetMetrics() map[string]*CheckThrottlerResponse return nil } +func (x *CheckThrottlerResponse) GetAppName() string { + if x != nil { + return x.AppName + } + return "" +} + +func (x *CheckThrottlerResponse) GetSummary() string { + if x != nil { + return x.Summary + } + return "" +} + +func (x *CheckThrottlerResponse) GetResponseCode() CheckThrottlerResponseCode { + if x != nil { + return x.ResponseCode + } + return CheckThrottlerResponseCode_UNDEFINED +} + type GetThrottlerStatusRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -7128,6 +7221,8 @@ type CheckThrottlerResponse_Metric struct { 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"` + // ResponseCode is the enum representation of the response + ResponseCode CheckThrottlerResponseCode `protobuf:"varint,8,opt,name=response_code,json=responseCode,proto3,enum=tabletmanagerdata.CheckThrottlerResponseCode" json:"response_code,omitempty"` } func (x *CheckThrottlerResponse_Metric) Reset() { @@ -7211,6 +7306,13 @@ func (x *CheckThrottlerResponse_Metric) GetScope() string { return "" } +func (x *CheckThrottlerResponse_Metric) GetResponseCode() CheckThrottlerResponseCode { + if x != nil { + return x.ResponseCode + } + return CheckThrottlerResponseCode_UNDEFINED +} + type GetThrottlerStatusResponse_MetricResult struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -7328,6 +7430,8 @@ type GetThrottlerStatusResponse_RecentApp struct { 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"` + // ResponseCode is the enum representation of the response + ResponseCode CheckThrottlerResponseCode `protobuf:"varint,3,opt,name=response_code,json=responseCode,proto3,enum=tabletmanagerdata.CheckThrottlerResponseCode" json:"response_code,omitempty"` } func (x *GetThrottlerStatusResponse_RecentApp) Reset() { @@ -7376,6 +7480,13 @@ func (x *GetThrottlerStatusResponse_RecentApp) GetStatusCode() int32 { return 0 } +func (x *GetThrottlerStatusResponse_RecentApp) GetResponseCode() CheckThrottlerResponseCode { + if x != nil { + return x.ResponseCode + } + return CheckThrottlerResponseCode_UNDEFINED +} + var File_tabletmanagerdata_proto protoreflect.FileDescriptor var file_tabletmanagerdata_proto_rawDesc = []byte{ @@ -8095,7 +8206,7 @@ var file_tabletmanagerdata_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x65, - 0x6c, 0x6c, 0x22, 0x90, 0x01, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, + 0x6c, 0x6c, 0x22, 0xce, 0x01, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x70, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6f, 0x6e, 0x6c, 0x79, 0x50, 0x6b, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x71, 0x75, @@ -8104,271 +8215,294 @@ var file_tabletmanagerdata_proto_rawDesc = []byte{ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x53, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x52, 0x6f, 0x77, 0x73, 0x22, 0xda, 0x02, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, - 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1a, 0x0a, 0x08, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, - 0x6c, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x63, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x12, 0x38, 0x0a, 0x19, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x6f, - 0x77, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x6f, 0x77, - 0x73, 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, - 0x64, 0x69, 0x66, 0x66, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x22, 0xf2, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, + 0x65, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x66, + 0x66, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, + 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x72, 0x6f, 0x77, 0x44, + 0x69, 0x66, 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x22, 0xda, 0x02, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x6f, 0x72, + 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, + 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x5f, 0x70, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x50, 0x63, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x38, + 0x0a, 0x19, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x6f, 0x77, 0x73, + 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x6f, 0x77, 0x73, 0x54, + 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, + 0x66, 0x66, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, + 0x22, 0xf2, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, + 0x69, 0x66, 0x66, 0x50, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x0d, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x46, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, + 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x72, 0x65, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xef, 0x02, 0x0a, 0x21, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, + 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 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, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x56, 0x44, 0x69, 0x66, 0x66, 0x50, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x0d, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x46, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, - 0x66, 0x43, 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0b, 0x63, 0x6f, - 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xef, 0x02, 0x0a, 0x21, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, - 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, - 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 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, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 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, 0x2e, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x4f, 0x6e, 0x44, 0x44, 0x4c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0x50, 0x0a, 0x22, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x9f, 0x02, 0x0a, 0x22, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x73, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 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, 0x23, 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, - 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x73, 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x51, 0x0a, - 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x22, 0x2f, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdd, 0x01, 0x0a, 0x15, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x12, 0x27, - 0x0a, 0x10, 0x6f, 0x6b, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, - 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x6b, 0x49, 0x66, 0x4e, 0x6f, - 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 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, 0x50, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 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, 0x6c, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, - 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe1, 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, 0x73, 0x0a, 0x12, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, - 0x70, 0x0a, 0x11, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, - 0x6f, 0x6c, 0x64, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x10, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, - 0x73, 0x12, 0x67, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, - 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x67, 0x0a, 0x0e, 0x74, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x0f, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, - 0x70, 0x70, 0x73, 0x12, 0x74, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x41, 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, + 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, 0x2e, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x4f, 0x6e, 0x44, 0x44, 0x4c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6f, + 0x6e, 0x44, 0x64, 0x6c, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0x50, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x9f, 0x02, 0x0a, 0x22, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x65, + 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, + 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, + 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 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, 0x23, 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, + 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x23, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x2f, + 0x0a, 0x15, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, + 0x18, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdd, 0x01, 0x0a, 0x15, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x10, + 0x6f, 0x6b, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x6b, 0x49, 0x66, 0x4e, 0x6f, 0x74, 0x45, + 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x9f, 0x06, 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, 0x5e, 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x61, - 0x70, 0x70, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, - 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, - 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, - 0x41, 0x70, 0x70, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x1a, 0x80, 0x01, 0x0a, 0x16, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, + 0x63, 0x6b, 0x65, 0x64, 0x12, 0x50, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, + 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x1a, + 0x8b, 0x02, 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, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, + 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, + 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x6c, 0x0a, + 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1b, 0x0a, 0x19, 0x47, + 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb6, 0x10, 0x0a, 0x1a, 0x47, 0x65, 0x74, + 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x69, 0x73, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x69, 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, + 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x74, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x74, + 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x61, 0x67, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x68, + 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x5f, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x64, 0x41, 0x73, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x73, 0x0a, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x70, 0x0a, 0x11, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x18, + 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, + 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, + 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x12, 0x67, 0x0a, 0x0e, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x0e, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, + 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x67, 0x0a, 0x0e, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, + 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x0d, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x12, 0x74, + 0x0a, 0x13, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x11, 0x61, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, + 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, + 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x12, + 0x5e, 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x12, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, + 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x1a, + 0x3a, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x80, 0x01, 0x0a, 0x16, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43, + 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x6c, 0x61, 0x73, + 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x41, 0x74, 0x12, 0x3b, 0x0a, 0x1a, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, + 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x4c, 0x61, 0x73, 0x74, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x1a, 0x7c, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5c, 0x0a, 0x12, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, + 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, + 0x64, 0x41, 0x70, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x41, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, + 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xad, 0x01, 0x0a, 0x09, 0x52, 0x65, + 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x12, 0x2b, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x64, 0x41, 0x74, 0x12, 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, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, - 0x2e, 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, 0x7c, 0x0a, 0x12, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, - 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5c, 0x0a, 0x12, 0x54, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x72, - 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x41, 0x70, 0x70, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 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, 0x76, 0x0a, 0x0f, 0x52, 0x65, 0x63, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x76, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, @@ -8380,10 +8514,19 @@ var file_tabletmanagerdata_proto_rawDesc = []byte{ 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x03, 0x42, 0x30, 0x5a, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6f, 0x2f, 0x76, - 0x69, 0x74, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, - 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x03, 0x2a, 0x83, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, + 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x48, 0x52, 0x45, 0x53, + 0x48, 0x4f, 0x4c, 0x44, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, + 0x0e, 0x0a, 0x0a, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, + 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x52, 0x49, + 0x43, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x30, 0x5a, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, + 0x73, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x76, + 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -8398,263 +8541,267 @@ func file_tabletmanagerdata_proto_rawDescGZIP() []byte { return file_tabletmanagerdata_proto_rawDescData } -var file_tabletmanagerdata_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_tabletmanagerdata_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_tabletmanagerdata_proto_msgTypes = make([]protoimpl.MessageInfo, 142) var file_tabletmanagerdata_proto_goTypes = []any{ (TabletSelectionPreference)(0), // 0: tabletmanagerdata.TabletSelectionPreference - (*TableDefinition)(nil), // 1: tabletmanagerdata.TableDefinition - (*SchemaDefinition)(nil), // 2: tabletmanagerdata.SchemaDefinition - (*SchemaChangeResult)(nil), // 3: tabletmanagerdata.SchemaChangeResult - (*UserPermission)(nil), // 4: tabletmanagerdata.UserPermission - (*DbPermission)(nil), // 5: tabletmanagerdata.DbPermission - (*Permissions)(nil), // 6: tabletmanagerdata.Permissions - (*PingRequest)(nil), // 7: tabletmanagerdata.PingRequest - (*PingResponse)(nil), // 8: tabletmanagerdata.PingResponse - (*SleepRequest)(nil), // 9: tabletmanagerdata.SleepRequest - (*SleepResponse)(nil), // 10: tabletmanagerdata.SleepResponse - (*ExecuteHookRequest)(nil), // 11: tabletmanagerdata.ExecuteHookRequest - (*ExecuteHookResponse)(nil), // 12: tabletmanagerdata.ExecuteHookResponse - (*GetSchemaRequest)(nil), // 13: tabletmanagerdata.GetSchemaRequest - (*GetSchemaResponse)(nil), // 14: tabletmanagerdata.GetSchemaResponse - (*GetPermissionsRequest)(nil), // 15: tabletmanagerdata.GetPermissionsRequest - (*GetPermissionsResponse)(nil), // 16: tabletmanagerdata.GetPermissionsResponse - (*GetGlobalStatusVarsRequest)(nil), // 17: tabletmanagerdata.GetGlobalStatusVarsRequest - (*GetGlobalStatusVarsResponse)(nil), // 18: tabletmanagerdata.GetGlobalStatusVarsResponse - (*SetReadOnlyRequest)(nil), // 19: tabletmanagerdata.SetReadOnlyRequest - (*SetReadOnlyResponse)(nil), // 20: tabletmanagerdata.SetReadOnlyResponse - (*SetReadWriteRequest)(nil), // 21: tabletmanagerdata.SetReadWriteRequest - (*SetReadWriteResponse)(nil), // 22: tabletmanagerdata.SetReadWriteResponse - (*ChangeTypeRequest)(nil), // 23: tabletmanagerdata.ChangeTypeRequest - (*ChangeTypeResponse)(nil), // 24: tabletmanagerdata.ChangeTypeResponse - (*RefreshStateRequest)(nil), // 25: tabletmanagerdata.RefreshStateRequest - (*RefreshStateResponse)(nil), // 26: tabletmanagerdata.RefreshStateResponse - (*RunHealthCheckRequest)(nil), // 27: tabletmanagerdata.RunHealthCheckRequest - (*RunHealthCheckResponse)(nil), // 28: tabletmanagerdata.RunHealthCheckResponse - (*ReloadSchemaRequest)(nil), // 29: tabletmanagerdata.ReloadSchemaRequest - (*ReloadSchemaResponse)(nil), // 30: tabletmanagerdata.ReloadSchemaResponse - (*PreflightSchemaRequest)(nil), // 31: tabletmanagerdata.PreflightSchemaRequest - (*PreflightSchemaResponse)(nil), // 32: tabletmanagerdata.PreflightSchemaResponse - (*ApplySchemaRequest)(nil), // 33: tabletmanagerdata.ApplySchemaRequest - (*ApplySchemaResponse)(nil), // 34: tabletmanagerdata.ApplySchemaResponse - (*LockTablesRequest)(nil), // 35: tabletmanagerdata.LockTablesRequest - (*LockTablesResponse)(nil), // 36: tabletmanagerdata.LockTablesResponse - (*UnlockTablesRequest)(nil), // 37: tabletmanagerdata.UnlockTablesRequest - (*UnlockTablesResponse)(nil), // 38: tabletmanagerdata.UnlockTablesResponse - (*ExecuteQueryRequest)(nil), // 39: tabletmanagerdata.ExecuteQueryRequest - (*ExecuteQueryResponse)(nil), // 40: tabletmanagerdata.ExecuteQueryResponse - (*ExecuteFetchAsDbaRequest)(nil), // 41: tabletmanagerdata.ExecuteFetchAsDbaRequest - (*ExecuteFetchAsDbaResponse)(nil), // 42: tabletmanagerdata.ExecuteFetchAsDbaResponse - (*ExecuteMultiFetchAsDbaRequest)(nil), // 43: tabletmanagerdata.ExecuteMultiFetchAsDbaRequest - (*ExecuteMultiFetchAsDbaResponse)(nil), // 44: tabletmanagerdata.ExecuteMultiFetchAsDbaResponse - (*ExecuteFetchAsAllPrivsRequest)(nil), // 45: tabletmanagerdata.ExecuteFetchAsAllPrivsRequest - (*ExecuteFetchAsAllPrivsResponse)(nil), // 46: tabletmanagerdata.ExecuteFetchAsAllPrivsResponse - (*ExecuteFetchAsAppRequest)(nil), // 47: tabletmanagerdata.ExecuteFetchAsAppRequest - (*ExecuteFetchAsAppResponse)(nil), // 48: tabletmanagerdata.ExecuteFetchAsAppResponse - (*ReplicationStatusRequest)(nil), // 49: tabletmanagerdata.ReplicationStatusRequest - (*ReplicationStatusResponse)(nil), // 50: tabletmanagerdata.ReplicationStatusResponse - (*PrimaryStatusRequest)(nil), // 51: tabletmanagerdata.PrimaryStatusRequest - (*PrimaryStatusResponse)(nil), // 52: tabletmanagerdata.PrimaryStatusResponse - (*PrimaryPositionRequest)(nil), // 53: tabletmanagerdata.PrimaryPositionRequest - (*PrimaryPositionResponse)(nil), // 54: tabletmanagerdata.PrimaryPositionResponse - (*WaitForPositionRequest)(nil), // 55: tabletmanagerdata.WaitForPositionRequest - (*WaitForPositionResponse)(nil), // 56: tabletmanagerdata.WaitForPositionResponse - (*StopReplicationRequest)(nil), // 57: tabletmanagerdata.StopReplicationRequest - (*StopReplicationResponse)(nil), // 58: tabletmanagerdata.StopReplicationResponse - (*StopReplicationMinimumRequest)(nil), // 59: tabletmanagerdata.StopReplicationMinimumRequest - (*StopReplicationMinimumResponse)(nil), // 60: tabletmanagerdata.StopReplicationMinimumResponse - (*StartReplicationRequest)(nil), // 61: tabletmanagerdata.StartReplicationRequest - (*StartReplicationResponse)(nil), // 62: tabletmanagerdata.StartReplicationResponse - (*StartReplicationUntilAfterRequest)(nil), // 63: tabletmanagerdata.StartReplicationUntilAfterRequest - (*StartReplicationUntilAfterResponse)(nil), // 64: tabletmanagerdata.StartReplicationUntilAfterResponse - (*GetReplicasRequest)(nil), // 65: tabletmanagerdata.GetReplicasRequest - (*GetReplicasResponse)(nil), // 66: tabletmanagerdata.GetReplicasResponse - (*ResetReplicationRequest)(nil), // 67: tabletmanagerdata.ResetReplicationRequest - (*ResetReplicationResponse)(nil), // 68: tabletmanagerdata.ResetReplicationResponse - (*VReplicationExecRequest)(nil), // 69: tabletmanagerdata.VReplicationExecRequest - (*VReplicationExecResponse)(nil), // 70: tabletmanagerdata.VReplicationExecResponse - (*VReplicationWaitForPosRequest)(nil), // 71: tabletmanagerdata.VReplicationWaitForPosRequest - (*VReplicationWaitForPosResponse)(nil), // 72: tabletmanagerdata.VReplicationWaitForPosResponse - (*InitPrimaryRequest)(nil), // 73: tabletmanagerdata.InitPrimaryRequest - (*InitPrimaryResponse)(nil), // 74: tabletmanagerdata.InitPrimaryResponse - (*PopulateReparentJournalRequest)(nil), // 75: tabletmanagerdata.PopulateReparentJournalRequest - (*PopulateReparentJournalResponse)(nil), // 76: tabletmanagerdata.PopulateReparentJournalResponse - (*InitReplicaRequest)(nil), // 77: tabletmanagerdata.InitReplicaRequest - (*InitReplicaResponse)(nil), // 78: tabletmanagerdata.InitReplicaResponse - (*DemotePrimaryRequest)(nil), // 79: tabletmanagerdata.DemotePrimaryRequest - (*DemotePrimaryResponse)(nil), // 80: tabletmanagerdata.DemotePrimaryResponse - (*UndoDemotePrimaryRequest)(nil), // 81: tabletmanagerdata.UndoDemotePrimaryRequest - (*UndoDemotePrimaryResponse)(nil), // 82: tabletmanagerdata.UndoDemotePrimaryResponse - (*ReplicaWasPromotedRequest)(nil), // 83: tabletmanagerdata.ReplicaWasPromotedRequest - (*ReplicaWasPromotedResponse)(nil), // 84: tabletmanagerdata.ReplicaWasPromotedResponse - (*ResetReplicationParametersRequest)(nil), // 85: tabletmanagerdata.ResetReplicationParametersRequest - (*ResetReplicationParametersResponse)(nil), // 86: tabletmanagerdata.ResetReplicationParametersResponse - (*FullStatusRequest)(nil), // 87: tabletmanagerdata.FullStatusRequest - (*FullStatusResponse)(nil), // 88: tabletmanagerdata.FullStatusResponse - (*SetReplicationSourceRequest)(nil), // 89: tabletmanagerdata.SetReplicationSourceRequest - (*SetReplicationSourceResponse)(nil), // 90: tabletmanagerdata.SetReplicationSourceResponse - (*ReplicaWasRestartedRequest)(nil), // 91: tabletmanagerdata.ReplicaWasRestartedRequest - (*ReplicaWasRestartedResponse)(nil), // 92: tabletmanagerdata.ReplicaWasRestartedResponse - (*StopReplicationAndGetStatusRequest)(nil), // 93: tabletmanagerdata.StopReplicationAndGetStatusRequest - (*StopReplicationAndGetStatusResponse)(nil), // 94: tabletmanagerdata.StopReplicationAndGetStatusResponse - (*PromoteReplicaRequest)(nil), // 95: tabletmanagerdata.PromoteReplicaRequest - (*PromoteReplicaResponse)(nil), // 96: tabletmanagerdata.PromoteReplicaResponse - (*BackupRequest)(nil), // 97: tabletmanagerdata.BackupRequest - (*BackupResponse)(nil), // 98: tabletmanagerdata.BackupResponse - (*RestoreFromBackupRequest)(nil), // 99: tabletmanagerdata.RestoreFromBackupRequest - (*RestoreFromBackupResponse)(nil), // 100: tabletmanagerdata.RestoreFromBackupResponse - (*CreateVReplicationWorkflowRequest)(nil), // 101: tabletmanagerdata.CreateVReplicationWorkflowRequest - (*CreateVReplicationWorkflowResponse)(nil), // 102: tabletmanagerdata.CreateVReplicationWorkflowResponse - (*DeleteVReplicationWorkflowRequest)(nil), // 103: tabletmanagerdata.DeleteVReplicationWorkflowRequest - (*DeleteVReplicationWorkflowResponse)(nil), // 104: tabletmanagerdata.DeleteVReplicationWorkflowResponse - (*HasVReplicationWorkflowsRequest)(nil), // 105: tabletmanagerdata.HasVReplicationWorkflowsRequest - (*HasVReplicationWorkflowsResponse)(nil), // 106: tabletmanagerdata.HasVReplicationWorkflowsResponse - (*ReadVReplicationWorkflowsRequest)(nil), // 107: tabletmanagerdata.ReadVReplicationWorkflowsRequest - (*ReadVReplicationWorkflowsResponse)(nil), // 108: tabletmanagerdata.ReadVReplicationWorkflowsResponse - (*ReadVReplicationWorkflowRequest)(nil), // 109: tabletmanagerdata.ReadVReplicationWorkflowRequest - (*ReadVReplicationWorkflowResponse)(nil), // 110: tabletmanagerdata.ReadVReplicationWorkflowResponse - (*VDiffRequest)(nil), // 111: tabletmanagerdata.VDiffRequest - (*VDiffResponse)(nil), // 112: tabletmanagerdata.VDiffResponse - (*VDiffPickerOptions)(nil), // 113: tabletmanagerdata.VDiffPickerOptions - (*VDiffReportOptions)(nil), // 114: tabletmanagerdata.VDiffReportOptions - (*VDiffCoreOptions)(nil), // 115: tabletmanagerdata.VDiffCoreOptions - (*VDiffOptions)(nil), // 116: tabletmanagerdata.VDiffOptions - (*UpdateVReplicationWorkflowRequest)(nil), // 117: tabletmanagerdata.UpdateVReplicationWorkflowRequest - (*UpdateVReplicationWorkflowResponse)(nil), // 118: tabletmanagerdata.UpdateVReplicationWorkflowResponse - (*UpdateVReplicationWorkflowsRequest)(nil), // 119: tabletmanagerdata.UpdateVReplicationWorkflowsRequest - (*UpdateVReplicationWorkflowsResponse)(nil), // 120: tabletmanagerdata.UpdateVReplicationWorkflowsResponse - (*ResetSequencesRequest)(nil), // 121: tabletmanagerdata.ResetSequencesRequest - (*ResetSequencesResponse)(nil), // 122: tabletmanagerdata.ResetSequencesResponse - (*CheckThrottlerRequest)(nil), // 123: tabletmanagerdata.CheckThrottlerRequest - (*CheckThrottlerResponse)(nil), // 124: tabletmanagerdata.CheckThrottlerResponse - (*GetThrottlerStatusRequest)(nil), // 125: tabletmanagerdata.GetThrottlerStatusRequest - (*GetThrottlerStatusResponse)(nil), // 126: tabletmanagerdata.GetThrottlerStatusResponse - nil, // 127: tabletmanagerdata.UserPermission.PrivilegesEntry - nil, // 128: tabletmanagerdata.DbPermission.PrivilegesEntry - nil, // 129: tabletmanagerdata.ExecuteHookRequest.ExtraEnvEntry - nil, // 130: tabletmanagerdata.GetGlobalStatusVarsResponse.StatusValuesEntry - (*ReadVReplicationWorkflowResponse_Stream)(nil), // 131: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream - (*CheckThrottlerResponse_Metric)(nil), // 132: tabletmanagerdata.CheckThrottlerResponse.Metric - nil, // 133: tabletmanagerdata.CheckThrottlerResponse.MetricsEntry - (*GetThrottlerStatusResponse_MetricResult)(nil), // 134: tabletmanagerdata.GetThrottlerStatusResponse.MetricResult - nil, // 135: tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry - nil, // 136: tabletmanagerdata.GetThrottlerStatusResponse.MetricThresholdsEntry - (*GetThrottlerStatusResponse_MetricHealth)(nil), // 137: tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth - nil, // 138: tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry - nil, // 139: tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry - nil, // 140: tabletmanagerdata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - (*GetThrottlerStatusResponse_RecentApp)(nil), // 141: tabletmanagerdata.GetThrottlerStatusResponse.RecentApp - nil, // 142: tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry - (*query.Field)(nil), // 143: query.Field - (topodata.TabletType)(0), // 144: topodata.TabletType - (*vtrpc.CallerID)(nil), // 145: vtrpc.CallerID - (*query.QueryResult)(nil), // 146: query.QueryResult - (*replicationdata.Status)(nil), // 147: replicationdata.Status - (*replicationdata.PrimaryStatus)(nil), // 148: replicationdata.PrimaryStatus - (*topodata.TabletAlias)(nil), // 149: topodata.TabletAlias - (*replicationdata.FullStatus)(nil), // 150: replicationdata.FullStatus - (replicationdata.StopReplicationMode)(0), // 151: replicationdata.StopReplicationMode - (*replicationdata.StopReplicationStatus)(nil), // 152: replicationdata.StopReplicationStatus - (*logutil.Event)(nil), // 153: logutil.Event - (*vttime.Time)(nil), // 154: vttime.Time - (*binlogdata.BinlogSource)(nil), // 155: binlogdata.BinlogSource - (binlogdata.VReplicationWorkflowType)(0), // 156: binlogdata.VReplicationWorkflowType - (binlogdata.VReplicationWorkflowSubType)(0), // 157: binlogdata.VReplicationWorkflowSubType - (binlogdata.VReplicationWorkflowState)(0), // 158: binlogdata.VReplicationWorkflowState - (binlogdata.OnDDLAction)(0), // 159: binlogdata.OnDDLAction - (*topodata.ThrottledAppRule)(nil), // 160: topodata.ThrottledAppRule + (CheckThrottlerResponseCode)(0), // 1: tabletmanagerdata.CheckThrottlerResponseCode + (*TableDefinition)(nil), // 2: tabletmanagerdata.TableDefinition + (*SchemaDefinition)(nil), // 3: tabletmanagerdata.SchemaDefinition + (*SchemaChangeResult)(nil), // 4: tabletmanagerdata.SchemaChangeResult + (*UserPermission)(nil), // 5: tabletmanagerdata.UserPermission + (*DbPermission)(nil), // 6: tabletmanagerdata.DbPermission + (*Permissions)(nil), // 7: tabletmanagerdata.Permissions + (*PingRequest)(nil), // 8: tabletmanagerdata.PingRequest + (*PingResponse)(nil), // 9: tabletmanagerdata.PingResponse + (*SleepRequest)(nil), // 10: tabletmanagerdata.SleepRequest + (*SleepResponse)(nil), // 11: tabletmanagerdata.SleepResponse + (*ExecuteHookRequest)(nil), // 12: tabletmanagerdata.ExecuteHookRequest + (*ExecuteHookResponse)(nil), // 13: tabletmanagerdata.ExecuteHookResponse + (*GetSchemaRequest)(nil), // 14: tabletmanagerdata.GetSchemaRequest + (*GetSchemaResponse)(nil), // 15: tabletmanagerdata.GetSchemaResponse + (*GetPermissionsRequest)(nil), // 16: tabletmanagerdata.GetPermissionsRequest + (*GetPermissionsResponse)(nil), // 17: tabletmanagerdata.GetPermissionsResponse + (*GetGlobalStatusVarsRequest)(nil), // 18: tabletmanagerdata.GetGlobalStatusVarsRequest + (*GetGlobalStatusVarsResponse)(nil), // 19: tabletmanagerdata.GetGlobalStatusVarsResponse + (*SetReadOnlyRequest)(nil), // 20: tabletmanagerdata.SetReadOnlyRequest + (*SetReadOnlyResponse)(nil), // 21: tabletmanagerdata.SetReadOnlyResponse + (*SetReadWriteRequest)(nil), // 22: tabletmanagerdata.SetReadWriteRequest + (*SetReadWriteResponse)(nil), // 23: tabletmanagerdata.SetReadWriteResponse + (*ChangeTypeRequest)(nil), // 24: tabletmanagerdata.ChangeTypeRequest + (*ChangeTypeResponse)(nil), // 25: tabletmanagerdata.ChangeTypeResponse + (*RefreshStateRequest)(nil), // 26: tabletmanagerdata.RefreshStateRequest + (*RefreshStateResponse)(nil), // 27: tabletmanagerdata.RefreshStateResponse + (*RunHealthCheckRequest)(nil), // 28: tabletmanagerdata.RunHealthCheckRequest + (*RunHealthCheckResponse)(nil), // 29: tabletmanagerdata.RunHealthCheckResponse + (*ReloadSchemaRequest)(nil), // 30: tabletmanagerdata.ReloadSchemaRequest + (*ReloadSchemaResponse)(nil), // 31: tabletmanagerdata.ReloadSchemaResponse + (*PreflightSchemaRequest)(nil), // 32: tabletmanagerdata.PreflightSchemaRequest + (*PreflightSchemaResponse)(nil), // 33: tabletmanagerdata.PreflightSchemaResponse + (*ApplySchemaRequest)(nil), // 34: tabletmanagerdata.ApplySchemaRequest + (*ApplySchemaResponse)(nil), // 35: tabletmanagerdata.ApplySchemaResponse + (*LockTablesRequest)(nil), // 36: tabletmanagerdata.LockTablesRequest + (*LockTablesResponse)(nil), // 37: tabletmanagerdata.LockTablesResponse + (*UnlockTablesRequest)(nil), // 38: tabletmanagerdata.UnlockTablesRequest + (*UnlockTablesResponse)(nil), // 39: tabletmanagerdata.UnlockTablesResponse + (*ExecuteQueryRequest)(nil), // 40: tabletmanagerdata.ExecuteQueryRequest + (*ExecuteQueryResponse)(nil), // 41: tabletmanagerdata.ExecuteQueryResponse + (*ExecuteFetchAsDbaRequest)(nil), // 42: tabletmanagerdata.ExecuteFetchAsDbaRequest + (*ExecuteFetchAsDbaResponse)(nil), // 43: tabletmanagerdata.ExecuteFetchAsDbaResponse + (*ExecuteMultiFetchAsDbaRequest)(nil), // 44: tabletmanagerdata.ExecuteMultiFetchAsDbaRequest + (*ExecuteMultiFetchAsDbaResponse)(nil), // 45: tabletmanagerdata.ExecuteMultiFetchAsDbaResponse + (*ExecuteFetchAsAllPrivsRequest)(nil), // 46: tabletmanagerdata.ExecuteFetchAsAllPrivsRequest + (*ExecuteFetchAsAllPrivsResponse)(nil), // 47: tabletmanagerdata.ExecuteFetchAsAllPrivsResponse + (*ExecuteFetchAsAppRequest)(nil), // 48: tabletmanagerdata.ExecuteFetchAsAppRequest + (*ExecuteFetchAsAppResponse)(nil), // 49: tabletmanagerdata.ExecuteFetchAsAppResponse + (*ReplicationStatusRequest)(nil), // 50: tabletmanagerdata.ReplicationStatusRequest + (*ReplicationStatusResponse)(nil), // 51: tabletmanagerdata.ReplicationStatusResponse + (*PrimaryStatusRequest)(nil), // 52: tabletmanagerdata.PrimaryStatusRequest + (*PrimaryStatusResponse)(nil), // 53: tabletmanagerdata.PrimaryStatusResponse + (*PrimaryPositionRequest)(nil), // 54: tabletmanagerdata.PrimaryPositionRequest + (*PrimaryPositionResponse)(nil), // 55: tabletmanagerdata.PrimaryPositionResponse + (*WaitForPositionRequest)(nil), // 56: tabletmanagerdata.WaitForPositionRequest + (*WaitForPositionResponse)(nil), // 57: tabletmanagerdata.WaitForPositionResponse + (*StopReplicationRequest)(nil), // 58: tabletmanagerdata.StopReplicationRequest + (*StopReplicationResponse)(nil), // 59: tabletmanagerdata.StopReplicationResponse + (*StopReplicationMinimumRequest)(nil), // 60: tabletmanagerdata.StopReplicationMinimumRequest + (*StopReplicationMinimumResponse)(nil), // 61: tabletmanagerdata.StopReplicationMinimumResponse + (*StartReplicationRequest)(nil), // 62: tabletmanagerdata.StartReplicationRequest + (*StartReplicationResponse)(nil), // 63: tabletmanagerdata.StartReplicationResponse + (*StartReplicationUntilAfterRequest)(nil), // 64: tabletmanagerdata.StartReplicationUntilAfterRequest + (*StartReplicationUntilAfterResponse)(nil), // 65: tabletmanagerdata.StartReplicationUntilAfterResponse + (*GetReplicasRequest)(nil), // 66: tabletmanagerdata.GetReplicasRequest + (*GetReplicasResponse)(nil), // 67: tabletmanagerdata.GetReplicasResponse + (*ResetReplicationRequest)(nil), // 68: tabletmanagerdata.ResetReplicationRequest + (*ResetReplicationResponse)(nil), // 69: tabletmanagerdata.ResetReplicationResponse + (*VReplicationExecRequest)(nil), // 70: tabletmanagerdata.VReplicationExecRequest + (*VReplicationExecResponse)(nil), // 71: tabletmanagerdata.VReplicationExecResponse + (*VReplicationWaitForPosRequest)(nil), // 72: tabletmanagerdata.VReplicationWaitForPosRequest + (*VReplicationWaitForPosResponse)(nil), // 73: tabletmanagerdata.VReplicationWaitForPosResponse + (*InitPrimaryRequest)(nil), // 74: tabletmanagerdata.InitPrimaryRequest + (*InitPrimaryResponse)(nil), // 75: tabletmanagerdata.InitPrimaryResponse + (*PopulateReparentJournalRequest)(nil), // 76: tabletmanagerdata.PopulateReparentJournalRequest + (*PopulateReparentJournalResponse)(nil), // 77: tabletmanagerdata.PopulateReparentJournalResponse + (*InitReplicaRequest)(nil), // 78: tabletmanagerdata.InitReplicaRequest + (*InitReplicaResponse)(nil), // 79: tabletmanagerdata.InitReplicaResponse + (*DemotePrimaryRequest)(nil), // 80: tabletmanagerdata.DemotePrimaryRequest + (*DemotePrimaryResponse)(nil), // 81: tabletmanagerdata.DemotePrimaryResponse + (*UndoDemotePrimaryRequest)(nil), // 82: tabletmanagerdata.UndoDemotePrimaryRequest + (*UndoDemotePrimaryResponse)(nil), // 83: tabletmanagerdata.UndoDemotePrimaryResponse + (*ReplicaWasPromotedRequest)(nil), // 84: tabletmanagerdata.ReplicaWasPromotedRequest + (*ReplicaWasPromotedResponse)(nil), // 85: tabletmanagerdata.ReplicaWasPromotedResponse + (*ResetReplicationParametersRequest)(nil), // 86: tabletmanagerdata.ResetReplicationParametersRequest + (*ResetReplicationParametersResponse)(nil), // 87: tabletmanagerdata.ResetReplicationParametersResponse + (*FullStatusRequest)(nil), // 88: tabletmanagerdata.FullStatusRequest + (*FullStatusResponse)(nil), // 89: tabletmanagerdata.FullStatusResponse + (*SetReplicationSourceRequest)(nil), // 90: tabletmanagerdata.SetReplicationSourceRequest + (*SetReplicationSourceResponse)(nil), // 91: tabletmanagerdata.SetReplicationSourceResponse + (*ReplicaWasRestartedRequest)(nil), // 92: tabletmanagerdata.ReplicaWasRestartedRequest + (*ReplicaWasRestartedResponse)(nil), // 93: tabletmanagerdata.ReplicaWasRestartedResponse + (*StopReplicationAndGetStatusRequest)(nil), // 94: tabletmanagerdata.StopReplicationAndGetStatusRequest + (*StopReplicationAndGetStatusResponse)(nil), // 95: tabletmanagerdata.StopReplicationAndGetStatusResponse + (*PromoteReplicaRequest)(nil), // 96: tabletmanagerdata.PromoteReplicaRequest + (*PromoteReplicaResponse)(nil), // 97: tabletmanagerdata.PromoteReplicaResponse + (*BackupRequest)(nil), // 98: tabletmanagerdata.BackupRequest + (*BackupResponse)(nil), // 99: tabletmanagerdata.BackupResponse + (*RestoreFromBackupRequest)(nil), // 100: tabletmanagerdata.RestoreFromBackupRequest + (*RestoreFromBackupResponse)(nil), // 101: tabletmanagerdata.RestoreFromBackupResponse + (*CreateVReplicationWorkflowRequest)(nil), // 102: tabletmanagerdata.CreateVReplicationWorkflowRequest + (*CreateVReplicationWorkflowResponse)(nil), // 103: tabletmanagerdata.CreateVReplicationWorkflowResponse + (*DeleteVReplicationWorkflowRequest)(nil), // 104: tabletmanagerdata.DeleteVReplicationWorkflowRequest + (*DeleteVReplicationWorkflowResponse)(nil), // 105: tabletmanagerdata.DeleteVReplicationWorkflowResponse + (*HasVReplicationWorkflowsRequest)(nil), // 106: tabletmanagerdata.HasVReplicationWorkflowsRequest + (*HasVReplicationWorkflowsResponse)(nil), // 107: tabletmanagerdata.HasVReplicationWorkflowsResponse + (*ReadVReplicationWorkflowsRequest)(nil), // 108: tabletmanagerdata.ReadVReplicationWorkflowsRequest + (*ReadVReplicationWorkflowsResponse)(nil), // 109: tabletmanagerdata.ReadVReplicationWorkflowsResponse + (*ReadVReplicationWorkflowRequest)(nil), // 110: tabletmanagerdata.ReadVReplicationWorkflowRequest + (*ReadVReplicationWorkflowResponse)(nil), // 111: tabletmanagerdata.ReadVReplicationWorkflowResponse + (*VDiffRequest)(nil), // 112: tabletmanagerdata.VDiffRequest + (*VDiffResponse)(nil), // 113: tabletmanagerdata.VDiffResponse + (*VDiffPickerOptions)(nil), // 114: tabletmanagerdata.VDiffPickerOptions + (*VDiffReportOptions)(nil), // 115: tabletmanagerdata.VDiffReportOptions + (*VDiffCoreOptions)(nil), // 116: tabletmanagerdata.VDiffCoreOptions + (*VDiffOptions)(nil), // 117: tabletmanagerdata.VDiffOptions + (*UpdateVReplicationWorkflowRequest)(nil), // 118: tabletmanagerdata.UpdateVReplicationWorkflowRequest + (*UpdateVReplicationWorkflowResponse)(nil), // 119: tabletmanagerdata.UpdateVReplicationWorkflowResponse + (*UpdateVReplicationWorkflowsRequest)(nil), // 120: tabletmanagerdata.UpdateVReplicationWorkflowsRequest + (*UpdateVReplicationWorkflowsResponse)(nil), // 121: tabletmanagerdata.UpdateVReplicationWorkflowsResponse + (*ResetSequencesRequest)(nil), // 122: tabletmanagerdata.ResetSequencesRequest + (*ResetSequencesResponse)(nil), // 123: tabletmanagerdata.ResetSequencesResponse + (*CheckThrottlerRequest)(nil), // 124: tabletmanagerdata.CheckThrottlerRequest + (*CheckThrottlerResponse)(nil), // 125: tabletmanagerdata.CheckThrottlerResponse + (*GetThrottlerStatusRequest)(nil), // 126: tabletmanagerdata.GetThrottlerStatusRequest + (*GetThrottlerStatusResponse)(nil), // 127: tabletmanagerdata.GetThrottlerStatusResponse + nil, // 128: tabletmanagerdata.UserPermission.PrivilegesEntry + nil, // 129: tabletmanagerdata.DbPermission.PrivilegesEntry + nil, // 130: tabletmanagerdata.ExecuteHookRequest.ExtraEnvEntry + nil, // 131: tabletmanagerdata.GetGlobalStatusVarsResponse.StatusValuesEntry + (*ReadVReplicationWorkflowResponse_Stream)(nil), // 132: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream + (*CheckThrottlerResponse_Metric)(nil), // 133: tabletmanagerdata.CheckThrottlerResponse.Metric + nil, // 134: tabletmanagerdata.CheckThrottlerResponse.MetricsEntry + (*GetThrottlerStatusResponse_MetricResult)(nil), // 135: tabletmanagerdata.GetThrottlerStatusResponse.MetricResult + nil, // 136: tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry + nil, // 137: tabletmanagerdata.GetThrottlerStatusResponse.MetricThresholdsEntry + (*GetThrottlerStatusResponse_MetricHealth)(nil), // 138: tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth + nil, // 139: tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry + nil, // 140: tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry + nil, // 141: tabletmanagerdata.GetThrottlerStatusResponse.AppCheckedMetricsEntry + (*GetThrottlerStatusResponse_RecentApp)(nil), // 142: tabletmanagerdata.GetThrottlerStatusResponse.RecentApp + nil, // 143: tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry + (*query.Field)(nil), // 144: query.Field + (topodata.TabletType)(0), // 145: topodata.TabletType + (*vtrpc.CallerID)(nil), // 146: vtrpc.CallerID + (*query.QueryResult)(nil), // 147: query.QueryResult + (*replicationdata.Status)(nil), // 148: replicationdata.Status + (*replicationdata.PrimaryStatus)(nil), // 149: replicationdata.PrimaryStatus + (*topodata.TabletAlias)(nil), // 150: topodata.TabletAlias + (*replicationdata.FullStatus)(nil), // 151: replicationdata.FullStatus + (replicationdata.StopReplicationMode)(0), // 152: replicationdata.StopReplicationMode + (*replicationdata.StopReplicationStatus)(nil), // 153: replicationdata.StopReplicationStatus + (*logutil.Event)(nil), // 154: logutil.Event + (*vttime.Time)(nil), // 155: vttime.Time + (*binlogdata.BinlogSource)(nil), // 156: binlogdata.BinlogSource + (binlogdata.VReplicationWorkflowType)(0), // 157: binlogdata.VReplicationWorkflowType + (binlogdata.VReplicationWorkflowSubType)(0), // 158: binlogdata.VReplicationWorkflowSubType + (binlogdata.VReplicationWorkflowState)(0), // 159: binlogdata.VReplicationWorkflowState + (binlogdata.OnDDLAction)(0), // 160: binlogdata.OnDDLAction + (*topodata.ThrottledAppRule)(nil), // 161: topodata.ThrottledAppRule } var file_tabletmanagerdata_proto_depIdxs = []int32{ - 143, // 0: tabletmanagerdata.TableDefinition.fields:type_name -> query.Field - 1, // 1: tabletmanagerdata.SchemaDefinition.table_definitions:type_name -> tabletmanagerdata.TableDefinition - 2, // 2: tabletmanagerdata.SchemaChangeResult.before_schema:type_name -> tabletmanagerdata.SchemaDefinition - 2, // 3: tabletmanagerdata.SchemaChangeResult.after_schema:type_name -> tabletmanagerdata.SchemaDefinition - 127, // 4: tabletmanagerdata.UserPermission.privileges:type_name -> tabletmanagerdata.UserPermission.PrivilegesEntry - 128, // 5: tabletmanagerdata.DbPermission.privileges:type_name -> tabletmanagerdata.DbPermission.PrivilegesEntry - 4, // 6: tabletmanagerdata.Permissions.user_permissions:type_name -> tabletmanagerdata.UserPermission - 5, // 7: tabletmanagerdata.Permissions.db_permissions:type_name -> tabletmanagerdata.DbPermission - 129, // 8: tabletmanagerdata.ExecuteHookRequest.extra_env:type_name -> tabletmanagerdata.ExecuteHookRequest.ExtraEnvEntry - 2, // 9: tabletmanagerdata.GetSchemaResponse.schema_definition:type_name -> tabletmanagerdata.SchemaDefinition - 6, // 10: tabletmanagerdata.GetPermissionsResponse.permissions:type_name -> tabletmanagerdata.Permissions - 130, // 11: tabletmanagerdata.GetGlobalStatusVarsResponse.status_values:type_name -> tabletmanagerdata.GetGlobalStatusVarsResponse.StatusValuesEntry - 144, // 12: tabletmanagerdata.ChangeTypeRequest.tablet_type:type_name -> topodata.TabletType - 3, // 13: tabletmanagerdata.PreflightSchemaResponse.change_results:type_name -> tabletmanagerdata.SchemaChangeResult - 2, // 14: tabletmanagerdata.ApplySchemaRequest.before_schema:type_name -> tabletmanagerdata.SchemaDefinition - 2, // 15: tabletmanagerdata.ApplySchemaRequest.after_schema:type_name -> tabletmanagerdata.SchemaDefinition - 2, // 16: tabletmanagerdata.ApplySchemaResponse.before_schema:type_name -> tabletmanagerdata.SchemaDefinition - 2, // 17: tabletmanagerdata.ApplySchemaResponse.after_schema:type_name -> tabletmanagerdata.SchemaDefinition - 145, // 18: tabletmanagerdata.ExecuteQueryRequest.caller_id:type_name -> vtrpc.CallerID - 146, // 19: tabletmanagerdata.ExecuteQueryResponse.result:type_name -> query.QueryResult - 146, // 20: tabletmanagerdata.ExecuteFetchAsDbaResponse.result:type_name -> query.QueryResult - 146, // 21: tabletmanagerdata.ExecuteMultiFetchAsDbaResponse.results:type_name -> query.QueryResult - 146, // 22: tabletmanagerdata.ExecuteFetchAsAllPrivsResponse.result:type_name -> query.QueryResult - 146, // 23: tabletmanagerdata.ExecuteFetchAsAppResponse.result:type_name -> query.QueryResult - 147, // 24: tabletmanagerdata.ReplicationStatusResponse.status:type_name -> replicationdata.Status - 148, // 25: tabletmanagerdata.PrimaryStatusResponse.status:type_name -> replicationdata.PrimaryStatus - 146, // 26: tabletmanagerdata.VReplicationExecResponse.result:type_name -> query.QueryResult - 149, // 27: tabletmanagerdata.PopulateReparentJournalRequest.primary_alias:type_name -> topodata.TabletAlias - 149, // 28: tabletmanagerdata.InitReplicaRequest.parent:type_name -> topodata.TabletAlias - 148, // 29: tabletmanagerdata.DemotePrimaryResponse.primary_status:type_name -> replicationdata.PrimaryStatus - 150, // 30: tabletmanagerdata.FullStatusResponse.status:type_name -> replicationdata.FullStatus - 149, // 31: tabletmanagerdata.SetReplicationSourceRequest.parent:type_name -> topodata.TabletAlias - 149, // 32: tabletmanagerdata.ReplicaWasRestartedRequest.parent:type_name -> topodata.TabletAlias - 151, // 33: tabletmanagerdata.StopReplicationAndGetStatusRequest.stop_replication_mode:type_name -> replicationdata.StopReplicationMode - 152, // 34: tabletmanagerdata.StopReplicationAndGetStatusResponse.status:type_name -> replicationdata.StopReplicationStatus - 153, // 35: tabletmanagerdata.BackupResponse.event:type_name -> logutil.Event - 154, // 36: tabletmanagerdata.RestoreFromBackupRequest.backup_time:type_name -> vttime.Time - 154, // 37: tabletmanagerdata.RestoreFromBackupRequest.restore_to_timestamp:type_name -> vttime.Time - 153, // 38: tabletmanagerdata.RestoreFromBackupResponse.event:type_name -> logutil.Event - 155, // 39: tabletmanagerdata.CreateVReplicationWorkflowRequest.binlog_source:type_name -> binlogdata.BinlogSource - 144, // 40: tabletmanagerdata.CreateVReplicationWorkflowRequest.tablet_types:type_name -> topodata.TabletType + 144, // 0: tabletmanagerdata.TableDefinition.fields:type_name -> query.Field + 2, // 1: tabletmanagerdata.SchemaDefinition.table_definitions:type_name -> tabletmanagerdata.TableDefinition + 3, // 2: tabletmanagerdata.SchemaChangeResult.before_schema:type_name -> tabletmanagerdata.SchemaDefinition + 3, // 3: tabletmanagerdata.SchemaChangeResult.after_schema:type_name -> tabletmanagerdata.SchemaDefinition + 128, // 4: tabletmanagerdata.UserPermission.privileges:type_name -> tabletmanagerdata.UserPermission.PrivilegesEntry + 129, // 5: tabletmanagerdata.DbPermission.privileges:type_name -> tabletmanagerdata.DbPermission.PrivilegesEntry + 5, // 6: tabletmanagerdata.Permissions.user_permissions:type_name -> tabletmanagerdata.UserPermission + 6, // 7: tabletmanagerdata.Permissions.db_permissions:type_name -> tabletmanagerdata.DbPermission + 130, // 8: tabletmanagerdata.ExecuteHookRequest.extra_env:type_name -> tabletmanagerdata.ExecuteHookRequest.ExtraEnvEntry + 3, // 9: tabletmanagerdata.GetSchemaResponse.schema_definition:type_name -> tabletmanagerdata.SchemaDefinition + 7, // 10: tabletmanagerdata.GetPermissionsResponse.permissions:type_name -> tabletmanagerdata.Permissions + 131, // 11: tabletmanagerdata.GetGlobalStatusVarsResponse.status_values:type_name -> tabletmanagerdata.GetGlobalStatusVarsResponse.StatusValuesEntry + 145, // 12: tabletmanagerdata.ChangeTypeRequest.tablet_type:type_name -> topodata.TabletType + 4, // 13: tabletmanagerdata.PreflightSchemaResponse.change_results:type_name -> tabletmanagerdata.SchemaChangeResult + 3, // 14: tabletmanagerdata.ApplySchemaRequest.before_schema:type_name -> tabletmanagerdata.SchemaDefinition + 3, // 15: tabletmanagerdata.ApplySchemaRequest.after_schema:type_name -> tabletmanagerdata.SchemaDefinition + 3, // 16: tabletmanagerdata.ApplySchemaResponse.before_schema:type_name -> tabletmanagerdata.SchemaDefinition + 3, // 17: tabletmanagerdata.ApplySchemaResponse.after_schema:type_name -> tabletmanagerdata.SchemaDefinition + 146, // 18: tabletmanagerdata.ExecuteQueryRequest.caller_id:type_name -> vtrpc.CallerID + 147, // 19: tabletmanagerdata.ExecuteQueryResponse.result:type_name -> query.QueryResult + 147, // 20: tabletmanagerdata.ExecuteFetchAsDbaResponse.result:type_name -> query.QueryResult + 147, // 21: tabletmanagerdata.ExecuteMultiFetchAsDbaResponse.results:type_name -> query.QueryResult + 147, // 22: tabletmanagerdata.ExecuteFetchAsAllPrivsResponse.result:type_name -> query.QueryResult + 147, // 23: tabletmanagerdata.ExecuteFetchAsAppResponse.result:type_name -> query.QueryResult + 148, // 24: tabletmanagerdata.ReplicationStatusResponse.status:type_name -> replicationdata.Status + 149, // 25: tabletmanagerdata.PrimaryStatusResponse.status:type_name -> replicationdata.PrimaryStatus + 147, // 26: tabletmanagerdata.VReplicationExecResponse.result:type_name -> query.QueryResult + 150, // 27: tabletmanagerdata.PopulateReparentJournalRequest.primary_alias:type_name -> topodata.TabletAlias + 150, // 28: tabletmanagerdata.InitReplicaRequest.parent:type_name -> topodata.TabletAlias + 149, // 29: tabletmanagerdata.DemotePrimaryResponse.primary_status:type_name -> replicationdata.PrimaryStatus + 151, // 30: tabletmanagerdata.FullStatusResponse.status:type_name -> replicationdata.FullStatus + 150, // 31: tabletmanagerdata.SetReplicationSourceRequest.parent:type_name -> topodata.TabletAlias + 150, // 32: tabletmanagerdata.ReplicaWasRestartedRequest.parent:type_name -> topodata.TabletAlias + 152, // 33: tabletmanagerdata.StopReplicationAndGetStatusRequest.stop_replication_mode:type_name -> replicationdata.StopReplicationMode + 153, // 34: tabletmanagerdata.StopReplicationAndGetStatusResponse.status:type_name -> replicationdata.StopReplicationStatus + 154, // 35: tabletmanagerdata.BackupResponse.event:type_name -> logutil.Event + 155, // 36: tabletmanagerdata.RestoreFromBackupRequest.backup_time:type_name -> vttime.Time + 155, // 37: tabletmanagerdata.RestoreFromBackupRequest.restore_to_timestamp:type_name -> vttime.Time + 154, // 38: tabletmanagerdata.RestoreFromBackupResponse.event:type_name -> logutil.Event + 156, // 39: tabletmanagerdata.CreateVReplicationWorkflowRequest.binlog_source:type_name -> binlogdata.BinlogSource + 145, // 40: tabletmanagerdata.CreateVReplicationWorkflowRequest.tablet_types:type_name -> topodata.TabletType 0, // 41: tabletmanagerdata.CreateVReplicationWorkflowRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 156, // 42: tabletmanagerdata.CreateVReplicationWorkflowRequest.workflow_type:type_name -> binlogdata.VReplicationWorkflowType - 157, // 43: tabletmanagerdata.CreateVReplicationWorkflowRequest.workflow_sub_type:type_name -> binlogdata.VReplicationWorkflowSubType - 146, // 44: tabletmanagerdata.CreateVReplicationWorkflowResponse.result:type_name -> query.QueryResult - 146, // 45: tabletmanagerdata.DeleteVReplicationWorkflowResponse.result:type_name -> query.QueryResult - 158, // 46: tabletmanagerdata.ReadVReplicationWorkflowsRequest.include_states:type_name -> binlogdata.VReplicationWorkflowState - 158, // 47: tabletmanagerdata.ReadVReplicationWorkflowsRequest.exclude_states:type_name -> binlogdata.VReplicationWorkflowState - 110, // 48: tabletmanagerdata.ReadVReplicationWorkflowsResponse.workflows:type_name -> tabletmanagerdata.ReadVReplicationWorkflowResponse - 144, // 49: tabletmanagerdata.ReadVReplicationWorkflowResponse.tablet_types:type_name -> topodata.TabletType + 157, // 42: tabletmanagerdata.CreateVReplicationWorkflowRequest.workflow_type:type_name -> binlogdata.VReplicationWorkflowType + 158, // 43: tabletmanagerdata.CreateVReplicationWorkflowRequest.workflow_sub_type:type_name -> binlogdata.VReplicationWorkflowSubType + 147, // 44: tabletmanagerdata.CreateVReplicationWorkflowResponse.result:type_name -> query.QueryResult + 147, // 45: tabletmanagerdata.DeleteVReplicationWorkflowResponse.result:type_name -> query.QueryResult + 159, // 46: tabletmanagerdata.ReadVReplicationWorkflowsRequest.include_states:type_name -> binlogdata.VReplicationWorkflowState + 159, // 47: tabletmanagerdata.ReadVReplicationWorkflowsRequest.exclude_states:type_name -> binlogdata.VReplicationWorkflowState + 111, // 48: tabletmanagerdata.ReadVReplicationWorkflowsResponse.workflows:type_name -> tabletmanagerdata.ReadVReplicationWorkflowResponse + 145, // 49: tabletmanagerdata.ReadVReplicationWorkflowResponse.tablet_types:type_name -> topodata.TabletType 0, // 50: tabletmanagerdata.ReadVReplicationWorkflowResponse.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 156, // 51: tabletmanagerdata.ReadVReplicationWorkflowResponse.workflow_type:type_name -> binlogdata.VReplicationWorkflowType - 157, // 52: tabletmanagerdata.ReadVReplicationWorkflowResponse.workflow_sub_type:type_name -> binlogdata.VReplicationWorkflowSubType - 131, // 53: tabletmanagerdata.ReadVReplicationWorkflowResponse.streams:type_name -> tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream - 116, // 54: tabletmanagerdata.VDiffRequest.options:type_name -> tabletmanagerdata.VDiffOptions - 146, // 55: tabletmanagerdata.VDiffResponse.output:type_name -> query.QueryResult - 113, // 56: tabletmanagerdata.VDiffOptions.picker_options:type_name -> tabletmanagerdata.VDiffPickerOptions - 115, // 57: tabletmanagerdata.VDiffOptions.core_options:type_name -> tabletmanagerdata.VDiffCoreOptions - 114, // 58: tabletmanagerdata.VDiffOptions.report_options:type_name -> tabletmanagerdata.VDiffReportOptions - 144, // 59: tabletmanagerdata.UpdateVReplicationWorkflowRequest.tablet_types:type_name -> topodata.TabletType + 157, // 51: tabletmanagerdata.ReadVReplicationWorkflowResponse.workflow_type:type_name -> binlogdata.VReplicationWorkflowType + 158, // 52: tabletmanagerdata.ReadVReplicationWorkflowResponse.workflow_sub_type:type_name -> binlogdata.VReplicationWorkflowSubType + 132, // 53: tabletmanagerdata.ReadVReplicationWorkflowResponse.streams:type_name -> tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream + 117, // 54: tabletmanagerdata.VDiffRequest.options:type_name -> tabletmanagerdata.VDiffOptions + 147, // 55: tabletmanagerdata.VDiffResponse.output:type_name -> query.QueryResult + 114, // 56: tabletmanagerdata.VDiffOptions.picker_options:type_name -> tabletmanagerdata.VDiffPickerOptions + 116, // 57: tabletmanagerdata.VDiffOptions.core_options:type_name -> tabletmanagerdata.VDiffCoreOptions + 115, // 58: tabletmanagerdata.VDiffOptions.report_options:type_name -> tabletmanagerdata.VDiffReportOptions + 145, // 59: tabletmanagerdata.UpdateVReplicationWorkflowRequest.tablet_types:type_name -> topodata.TabletType 0, // 60: tabletmanagerdata.UpdateVReplicationWorkflowRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 159, // 61: tabletmanagerdata.UpdateVReplicationWorkflowRequest.on_ddl:type_name -> binlogdata.OnDDLAction - 158, // 62: tabletmanagerdata.UpdateVReplicationWorkflowRequest.state:type_name -> binlogdata.VReplicationWorkflowState - 146, // 63: tabletmanagerdata.UpdateVReplicationWorkflowResponse.result:type_name -> query.QueryResult - 158, // 64: tabletmanagerdata.UpdateVReplicationWorkflowsRequest.state:type_name -> binlogdata.VReplicationWorkflowState - 146, // 65: tabletmanagerdata.UpdateVReplicationWorkflowsResponse.result:type_name -> query.QueryResult - 133, // 66: tabletmanagerdata.CheckThrottlerResponse.metrics:type_name -> tabletmanagerdata.CheckThrottlerResponse.MetricsEntry - 135, // 67: tabletmanagerdata.GetThrottlerStatusResponse.aggregated_metrics:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry - 136, // 68: tabletmanagerdata.GetThrottlerStatusResponse.metric_thresholds:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricThresholdsEntry - 138, // 69: tabletmanagerdata.GetThrottlerStatusResponse.metrics_health:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry - 139, // 70: tabletmanagerdata.GetThrottlerStatusResponse.throttled_apps:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry - 140, // 71: tabletmanagerdata.GetThrottlerStatusResponse.app_checked_metrics:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - 142, // 72: tabletmanagerdata.GetThrottlerStatusResponse.recent_apps:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry - 155, // 73: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.bls:type_name -> binlogdata.BinlogSource - 154, // 74: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_updated:type_name -> vttime.Time - 154, // 75: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.transaction_timestamp:type_name -> vttime.Time - 158, // 76: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.state:type_name -> binlogdata.VReplicationWorkflowState - 154, // 77: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_heartbeat:type_name -> vttime.Time - 154, // 78: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_throttled:type_name -> vttime.Time - 132, // 79: tabletmanagerdata.CheckThrottlerResponse.MetricsEntry.value:type_name -> tabletmanagerdata.CheckThrottlerResponse.Metric - 134, // 80: tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricResult - 154, // 81: tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth.last_healthy_at:type_name -> vttime.Time - 137, // 82: tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth - 160, // 83: tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry.value:type_name -> topodata.ThrottledAppRule - 154, // 84: tabletmanagerdata.GetThrottlerStatusResponse.RecentApp.checked_at:type_name -> vttime.Time - 141, // 85: tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.RecentApp - 86, // [86:86] is the sub-list for method output_type - 86, // [86:86] is the sub-list for method input_type - 86, // [86:86] is the sub-list for extension type_name - 86, // [86:86] is the sub-list for extension extendee - 0, // [0:86] is the sub-list for field type_name + 160, // 61: tabletmanagerdata.UpdateVReplicationWorkflowRequest.on_ddl:type_name -> binlogdata.OnDDLAction + 159, // 62: tabletmanagerdata.UpdateVReplicationWorkflowRequest.state:type_name -> binlogdata.VReplicationWorkflowState + 147, // 63: tabletmanagerdata.UpdateVReplicationWorkflowResponse.result:type_name -> query.QueryResult + 159, // 64: tabletmanagerdata.UpdateVReplicationWorkflowsRequest.state:type_name -> binlogdata.VReplicationWorkflowState + 147, // 65: tabletmanagerdata.UpdateVReplicationWorkflowsResponse.result:type_name -> query.QueryResult + 134, // 66: tabletmanagerdata.CheckThrottlerResponse.metrics:type_name -> tabletmanagerdata.CheckThrottlerResponse.MetricsEntry + 1, // 67: tabletmanagerdata.CheckThrottlerResponse.response_code:type_name -> tabletmanagerdata.CheckThrottlerResponseCode + 136, // 68: tabletmanagerdata.GetThrottlerStatusResponse.aggregated_metrics:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry + 137, // 69: tabletmanagerdata.GetThrottlerStatusResponse.metric_thresholds:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricThresholdsEntry + 139, // 70: tabletmanagerdata.GetThrottlerStatusResponse.metrics_health:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry + 140, // 71: tabletmanagerdata.GetThrottlerStatusResponse.throttled_apps:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry + 141, // 72: tabletmanagerdata.GetThrottlerStatusResponse.app_checked_metrics:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.AppCheckedMetricsEntry + 143, // 73: tabletmanagerdata.GetThrottlerStatusResponse.recent_apps:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry + 156, // 74: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.bls:type_name -> binlogdata.BinlogSource + 155, // 75: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_updated:type_name -> vttime.Time + 155, // 76: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.transaction_timestamp:type_name -> vttime.Time + 159, // 77: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.state:type_name -> binlogdata.VReplicationWorkflowState + 155, // 78: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_heartbeat:type_name -> vttime.Time + 155, // 79: tabletmanagerdata.ReadVReplicationWorkflowResponse.Stream.time_throttled:type_name -> vttime.Time + 1, // 80: tabletmanagerdata.CheckThrottlerResponse.Metric.response_code:type_name -> tabletmanagerdata.CheckThrottlerResponseCode + 133, // 81: tabletmanagerdata.CheckThrottlerResponse.MetricsEntry.value:type_name -> tabletmanagerdata.CheckThrottlerResponse.Metric + 135, // 82: tabletmanagerdata.GetThrottlerStatusResponse.AggregatedMetricsEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricResult + 155, // 83: tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth.last_healthy_at:type_name -> vttime.Time + 138, // 84: tabletmanagerdata.GetThrottlerStatusResponse.MetricsHealthEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.MetricHealth + 161, // 85: tabletmanagerdata.GetThrottlerStatusResponse.ThrottledAppsEntry.value:type_name -> topodata.ThrottledAppRule + 155, // 86: tabletmanagerdata.GetThrottlerStatusResponse.RecentApp.checked_at:type_name -> vttime.Time + 1, // 87: tabletmanagerdata.GetThrottlerStatusResponse.RecentApp.response_code:type_name -> tabletmanagerdata.CheckThrottlerResponseCode + 142, // 88: tabletmanagerdata.GetThrottlerStatusResponse.RecentAppsEntry.value:type_name -> tabletmanagerdata.GetThrottlerStatusResponse.RecentApp + 89, // [89:89] is the sub-list for method output_type + 89, // [89:89] is the sub-list for method input_type + 89, // [89:89] is the sub-list for extension type_name + 89, // [89:89] is the sub-list for extension extendee + 0, // [0:89] is the sub-list for field type_name } func init() { file_tabletmanagerdata_proto_init() } @@ -10241,7 +10388,7 @@ func file_tabletmanagerdata_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tabletmanagerdata_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 142, NumExtensions: 0, NumServices: 0, diff --git a/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go index d48882613d1..630d166c9f9 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go @@ -2275,10 +2275,11 @@ func (m *VDiffReportOptions) CloneVT() *VDiffReportOptions { return (*VDiffReportOptions)(nil) } r := &VDiffReportOptions{ - OnlyPks: m.OnlyPks, - DebugQuery: m.DebugQuery, - Format: m.Format, - MaxSampleRows: m.MaxSampleRows, + OnlyPks: m.OnlyPks, + DebugQuery: m.DebugQuery, + Format: m.Format, + MaxSampleRows: m.MaxSampleRows, + RowDiffColumnTruncateAt: m.RowDiffColumnTruncateAt, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -2499,13 +2500,14 @@ func (m *CheckThrottlerResponse_Metric) CloneVT() *CheckThrottlerResponse_Metric 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, + Name: m.Name, + StatusCode: m.StatusCode, + Value: m.Value, + Threshold: m.Threshold, + Error: m.Error, + Message: m.Message, + Scope: m.Scope, + ResponseCode: m.ResponseCode, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -2529,6 +2531,9 @@ func (m *CheckThrottlerResponse) CloneVT() *CheckThrottlerResponse { Error: m.Error, Message: m.Message, RecentlyChecked: m.RecentlyChecked, + AppName: m.AppName, + Summary: m.Summary, + ResponseCode: m.ResponseCode, } if rhs := m.Metrics; rhs != nil { tmpContainer := make(map[string]*CheckThrottlerResponse_Metric, len(rhs)) @@ -2607,8 +2612,9 @@ func (m *GetThrottlerStatusResponse_RecentApp) CloneVT() *GetThrottlerStatusResp return (*GetThrottlerStatusResponse_RecentApp)(nil) } r := &GetThrottlerStatusResponse_RecentApp{ - CheckedAt: m.CheckedAt.CloneVT(), - StatusCode: m.StatusCode, + CheckedAt: m.CheckedAt.CloneVT(), + StatusCode: m.StatusCode, + ResponseCode: m.ResponseCode, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -8129,6 +8135,11 @@ func (m *VDiffReportOptions) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.RowDiffColumnTruncateAt != 0 { + i = encodeVarint(dAtA, i, uint64(m.RowDiffColumnTruncateAt)) + i-- + dAtA[i] = 0x28 + } if m.MaxSampleRows != 0 { i = encodeVarint(dAtA, i, uint64(m.MaxSampleRows)) i-- @@ -8755,6 +8766,11 @@ func (m *CheckThrottlerResponse_Metric) MarshalToSizedBufferVT(dAtA []byte) (int i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.ResponseCode != 0 { + i = encodeVarint(dAtA, i, uint64(m.ResponseCode)) + i-- + dAtA[i] = 0x40 + } if len(m.Scope) > 0 { i -= len(m.Scope) copy(dAtA[i:], m.Scope) @@ -8833,6 +8849,25 @@ func (m *CheckThrottlerResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.ResponseCode != 0 { + i = encodeVarint(dAtA, i, uint64(m.ResponseCode)) + i-- + dAtA[i] = 0x50 + } + 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] = 0x4a + } + if len(m.AppName) > 0 { + i -= len(m.AppName) + copy(dAtA[i:], m.AppName) + i = encodeVarint(dAtA, i, uint64(len(m.AppName))) + i-- + dAtA[i] = 0x42 + } if len(m.Metrics) > 0 { for k := range m.Metrics { v := m.Metrics[k] @@ -9056,6 +9091,11 @@ func (m *GetThrottlerStatusResponse_RecentApp) MarshalToSizedBufferVT(dAtA []byt i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.ResponseCode != 0 { + i = encodeVarint(dAtA, i, uint64(m.ResponseCode)) + i-- + dAtA[i] = 0x18 + } if m.StatusCode != 0 { i = encodeVarint(dAtA, i, uint64(m.StatusCode)) i-- @@ -11275,6 +11315,9 @@ func (m *VDiffReportOptions) SizeVT() (n int) { if m.MaxSampleRows != 0 { n += 1 + sov(uint64(m.MaxSampleRows)) } + if m.RowDiffColumnTruncateAt != 0 { + n += 1 + sov(uint64(m.RowDiffColumnTruncateAt)) + } n += len(m.unknownFields) return n } @@ -11523,6 +11566,9 @@ func (m *CheckThrottlerResponse_Metric) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + if m.ResponseCode != 0 { + n += 1 + sov(uint64(m.ResponseCode)) + } n += len(m.unknownFields) return n } @@ -11566,6 +11612,17 @@ func (m *CheckThrottlerResponse) SizeVT() (n int) { n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) } } + l = len(m.AppName) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Summary) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.ResponseCode != 0 { + n += 1 + sov(uint64(m.ResponseCode)) + } n += len(m.unknownFields) return n } @@ -11627,6 +11684,9 @@ func (m *GetThrottlerStatusResponse_RecentApp) SizeVT() (n int) { if m.StatusCode != 0 { n += 1 + sov(uint64(m.StatusCode)) } + if m.ResponseCode != 0 { + n += 1 + sov(uint64(m.ResponseCode)) + } n += len(m.unknownFields) return n } @@ -23730,6 +23790,25 @@ func (m *VDiffReportOptions) UnmarshalVT(dAtA []byte) error { break } } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RowDiffColumnTruncateAt", wireType) + } + m.RowDiffColumnTruncateAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RowDiffColumnTruncateAt |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -25289,6 +25368,25 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { } m.Scope = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ResponseCode", wireType) + } + m.ResponseCode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ResponseCode |= CheckThrottlerResponseCode(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -25594,6 +25692,89 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { } m.Metrics[mapkey] = mapvalue iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppName", 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.AppName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + 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 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ResponseCode", wireType) + } + m.ResponseCode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ResponseCode |= CheckThrottlerResponseCode(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -25951,6 +26132,25 @@ func (m *GetThrottlerStatusResponse_RecentApp) UnmarshalVT(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ResponseCode", wireType) + } + m.ResponseCode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ResponseCode |= CheckThrottlerResponseCode(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/go/vt/proto/topodata/cached_size.go b/go/vt/proto/topodata/cached_size.go index d06ebd0d3f0..94b7fc6818c 100644 --- a/go/vt/proto/topodata/cached_size.go +++ b/go/vt/proto/topodata/cached_size.go @@ -27,10 +27,6 @@ func (cached *KeyRange) CachedSize(alloc bool) int64 { if alloc { size += int64(96) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Start []byte { size += hack.RuntimeAllocSize(int64(cap(cached.Start))) @@ -49,10 +45,6 @@ func (cached *ThrottledAppRule) CachedSize(alloc bool) int64 { if alloc { size += int64(80) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } // field Name string size += hack.RuntimeAllocSize(int64(len(cached.Name))) // field ExpiresAt *vitess.io/vitess/go/vt/proto/vttime.Time diff --git a/go/vt/proto/vtadmin/vtadmin.pb.go b/go/vt/proto/vtadmin/vtadmin.pb.go index 303af932adf..f434743a833 100644 --- a/go/vt/proto/vtadmin/vtadmin.pb.go +++ b/go/vt/proto/vtadmin/vtadmin.pb.go @@ -3943,6 +3943,195 @@ func (x *GetWorkflowRequest) GetActiveOnly() bool { return false } +type GetWorkflowStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId string `protobuf:"bytes,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"` + Keyspace string `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetWorkflowStatusRequest) Reset() { + *x = GetWorkflowStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vtadmin_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetWorkflowStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWorkflowStatusRequest) ProtoMessage() {} + +func (x *GetWorkflowStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_vtadmin_proto_msgTypes[68] + 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 GetWorkflowStatusRequest.ProtoReflect.Descriptor instead. +func (*GetWorkflowStatusRequest) Descriptor() ([]byte, []int) { + return file_vtadmin_proto_rawDescGZIP(), []int{68} +} + +func (x *GetWorkflowStatusRequest) GetClusterId() string { + if x != nil { + return x.ClusterId + } + return "" +} + +func (x *GetWorkflowStatusRequest) GetKeyspace() string { + if x != nil { + return x.Keyspace + } + return "" +} + +func (x *GetWorkflowStatusRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type StartWorkflowRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId string `protobuf:"bytes,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"` + Keyspace string `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Workflow string `protobuf:"bytes,3,opt,name=workflow,proto3" json:"workflow,omitempty"` +} + +func (x *StartWorkflowRequest) Reset() { + *x = StartWorkflowRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vtadmin_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StartWorkflowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartWorkflowRequest) ProtoMessage() {} + +func (x *StartWorkflowRequest) ProtoReflect() protoreflect.Message { + mi := &file_vtadmin_proto_msgTypes[69] + 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 StartWorkflowRequest.ProtoReflect.Descriptor instead. +func (*StartWorkflowRequest) Descriptor() ([]byte, []int) { + return file_vtadmin_proto_rawDescGZIP(), []int{69} +} + +func (x *StartWorkflowRequest) GetClusterId() string { + if x != nil { + return x.ClusterId + } + return "" +} + +func (x *StartWorkflowRequest) GetKeyspace() string { + if x != nil { + return x.Keyspace + } + return "" +} + +func (x *StartWorkflowRequest) GetWorkflow() string { + if x != nil { + return x.Workflow + } + return "" +} + +type StopWorkflowRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId string `protobuf:"bytes,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"` + Keyspace string `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Workflow string `protobuf:"bytes,3,opt,name=workflow,proto3" json:"workflow,omitempty"` +} + +func (x *StopWorkflowRequest) Reset() { + *x = StopWorkflowRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vtadmin_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StopWorkflowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StopWorkflowRequest) ProtoMessage() {} + +func (x *StopWorkflowRequest) ProtoReflect() protoreflect.Message { + mi := &file_vtadmin_proto_msgTypes[70] + 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 StopWorkflowRequest.ProtoReflect.Descriptor instead. +func (*StopWorkflowRequest) Descriptor() ([]byte, []int) { + return file_vtadmin_proto_rawDescGZIP(), []int{70} +} + +func (x *StopWorkflowRequest) GetClusterId() string { + if x != nil { + return x.ClusterId + } + return "" +} + +func (x *StopWorkflowRequest) GetKeyspace() string { + if x != nil { + return x.Keyspace + } + return "" +} + +func (x *StopWorkflowRequest) GetWorkflow() string { + if x != nil { + return x.Workflow + } + return "" +} + type GetWorkflowsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3972,7 +4161,7 @@ type GetWorkflowsRequest struct { func (x *GetWorkflowsRequest) Reset() { *x = GetWorkflowsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[68] + mi := &file_vtadmin_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3985,7 +4174,7 @@ func (x *GetWorkflowsRequest) String() string { func (*GetWorkflowsRequest) ProtoMessage() {} func (x *GetWorkflowsRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[68] + mi := &file_vtadmin_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3998,7 +4187,7 @@ func (x *GetWorkflowsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkflowsRequest.ProtoReflect.Descriptor instead. func (*GetWorkflowsRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{68} + return file_vtadmin_proto_rawDescGZIP(), []int{71} } func (x *GetWorkflowsRequest) GetClusterIds() []string { @@ -4040,7 +4229,7 @@ type GetWorkflowsResponse struct { func (x *GetWorkflowsResponse) Reset() { *x = GetWorkflowsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[69] + mi := &file_vtadmin_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4053,7 +4242,7 @@ func (x *GetWorkflowsResponse) String() string { func (*GetWorkflowsResponse) ProtoMessage() {} func (x *GetWorkflowsResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[69] + mi := &file_vtadmin_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4066,7 +4255,7 @@ func (x *GetWorkflowsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkflowsResponse.ProtoReflect.Descriptor instead. func (*GetWorkflowsResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{69} + return file_vtadmin_proto_rawDescGZIP(), []int{72} } func (x *GetWorkflowsResponse) GetWorkflowsByCluster() map[string]*ClusterWorkflows { @@ -4088,7 +4277,7 @@ type LaunchSchemaMigrationRequest struct { func (x *LaunchSchemaMigrationRequest) Reset() { *x = LaunchSchemaMigrationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[70] + mi := &file_vtadmin_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4101,7 +4290,7 @@ func (x *LaunchSchemaMigrationRequest) String() string { func (*LaunchSchemaMigrationRequest) ProtoMessage() {} func (x *LaunchSchemaMigrationRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[70] + mi := &file_vtadmin_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4114,7 +4303,7 @@ func (x *LaunchSchemaMigrationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LaunchSchemaMigrationRequest.ProtoReflect.Descriptor instead. func (*LaunchSchemaMigrationRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{70} + return file_vtadmin_proto_rawDescGZIP(), []int{73} } func (x *LaunchSchemaMigrationRequest) GetClusterId() string { @@ -4147,7 +4336,7 @@ type PingTabletRequest struct { func (x *PingTabletRequest) Reset() { *x = PingTabletRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[71] + mi := &file_vtadmin_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4160,7 +4349,7 @@ func (x *PingTabletRequest) String() string { func (*PingTabletRequest) ProtoMessage() {} func (x *PingTabletRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[71] + mi := &file_vtadmin_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4173,7 +4362,7 @@ func (x *PingTabletRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PingTabletRequest.ProtoReflect.Descriptor instead. func (*PingTabletRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{71} + return file_vtadmin_proto_rawDescGZIP(), []int{74} } func (x *PingTabletRequest) GetAlias() *topodata.TabletAlias { @@ -4202,7 +4391,7 @@ type PingTabletResponse struct { func (x *PingTabletResponse) Reset() { *x = PingTabletResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[72] + mi := &file_vtadmin_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4215,7 +4404,7 @@ func (x *PingTabletResponse) String() string { func (*PingTabletResponse) ProtoMessage() {} func (x *PingTabletResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[72] + mi := &file_vtadmin_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4228,7 +4417,7 @@ func (x *PingTabletResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PingTabletResponse.ProtoReflect.Descriptor instead. func (*PingTabletResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{72} + return file_vtadmin_proto_rawDescGZIP(), []int{75} } func (x *PingTabletResponse) GetStatus() string { @@ -4257,7 +4446,7 @@ type PlannedFailoverShardRequest struct { func (x *PlannedFailoverShardRequest) Reset() { *x = PlannedFailoverShardRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[73] + mi := &file_vtadmin_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4270,7 +4459,7 @@ func (x *PlannedFailoverShardRequest) String() string { func (*PlannedFailoverShardRequest) ProtoMessage() {} func (x *PlannedFailoverShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[73] + mi := &file_vtadmin_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4283,7 +4472,7 @@ func (x *PlannedFailoverShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PlannedFailoverShardRequest.ProtoReflect.Descriptor instead. func (*PlannedFailoverShardRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{73} + return file_vtadmin_proto_rawDescGZIP(), []int{76} } func (x *PlannedFailoverShardRequest) GetClusterId() string { @@ -4319,7 +4508,7 @@ type PlannedFailoverShardResponse struct { func (x *PlannedFailoverShardResponse) Reset() { *x = PlannedFailoverShardResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[74] + mi := &file_vtadmin_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4332,7 +4521,7 @@ func (x *PlannedFailoverShardResponse) String() string { func (*PlannedFailoverShardResponse) ProtoMessage() {} func (x *PlannedFailoverShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[74] + mi := &file_vtadmin_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4345,7 +4534,7 @@ func (x *PlannedFailoverShardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PlannedFailoverShardResponse.ProtoReflect.Descriptor instead. func (*PlannedFailoverShardResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{74} + return file_vtadmin_proto_rawDescGZIP(), []int{77} } func (x *PlannedFailoverShardResponse) GetCluster() *Cluster { @@ -4397,7 +4586,7 @@ type RebuildKeyspaceGraphRequest struct { func (x *RebuildKeyspaceGraphRequest) Reset() { *x = RebuildKeyspaceGraphRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[75] + mi := &file_vtadmin_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4410,7 +4599,7 @@ func (x *RebuildKeyspaceGraphRequest) String() string { func (*RebuildKeyspaceGraphRequest) ProtoMessage() {} func (x *RebuildKeyspaceGraphRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[75] + mi := &file_vtadmin_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4423,7 +4612,7 @@ func (x *RebuildKeyspaceGraphRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RebuildKeyspaceGraphRequest.ProtoReflect.Descriptor instead. func (*RebuildKeyspaceGraphRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{75} + return file_vtadmin_proto_rawDescGZIP(), []int{78} } func (x *RebuildKeyspaceGraphRequest) GetClusterId() string { @@ -4465,7 +4654,7 @@ type RebuildKeyspaceGraphResponse struct { func (x *RebuildKeyspaceGraphResponse) Reset() { *x = RebuildKeyspaceGraphResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[76] + mi := &file_vtadmin_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4478,7 +4667,7 @@ func (x *RebuildKeyspaceGraphResponse) String() string { func (*RebuildKeyspaceGraphResponse) ProtoMessage() {} func (x *RebuildKeyspaceGraphResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[76] + mi := &file_vtadmin_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4491,7 +4680,7 @@ func (x *RebuildKeyspaceGraphResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RebuildKeyspaceGraphResponse.ProtoReflect.Descriptor instead. func (*RebuildKeyspaceGraphResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{76} + return file_vtadmin_proto_rawDescGZIP(), []int{79} } func (x *RebuildKeyspaceGraphResponse) GetStatus() string { @@ -4513,7 +4702,7 @@ type RefreshStateRequest struct { func (x *RefreshStateRequest) Reset() { *x = RefreshStateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[77] + mi := &file_vtadmin_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4526,7 +4715,7 @@ func (x *RefreshStateRequest) String() string { func (*RefreshStateRequest) ProtoMessage() {} func (x *RefreshStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[77] + mi := &file_vtadmin_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4539,7 +4728,7 @@ func (x *RefreshStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshStateRequest.ProtoReflect.Descriptor instead. func (*RefreshStateRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{77} + return file_vtadmin_proto_rawDescGZIP(), []int{80} } func (x *RefreshStateRequest) GetAlias() *topodata.TabletAlias { @@ -4568,7 +4757,7 @@ type RefreshStateResponse struct { func (x *RefreshStateResponse) Reset() { *x = RefreshStateResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[78] + mi := &file_vtadmin_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4581,7 +4770,7 @@ func (x *RefreshStateResponse) String() string { func (*RefreshStateResponse) ProtoMessage() {} func (x *RefreshStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[78] + mi := &file_vtadmin_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4594,7 +4783,7 @@ func (x *RefreshStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshStateResponse.ProtoReflect.Descriptor instead. func (*RefreshStateResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{78} + return file_vtadmin_proto_rawDescGZIP(), []int{81} } func (x *RefreshStateResponse) GetStatus() string { @@ -4663,7 +4852,7 @@ type ReloadSchemasRequest struct { func (x *ReloadSchemasRequest) Reset() { *x = ReloadSchemasRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[79] + mi := &file_vtadmin_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4676,7 +4865,7 @@ func (x *ReloadSchemasRequest) String() string { func (*ReloadSchemasRequest) ProtoMessage() {} func (x *ReloadSchemasRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[79] + mi := &file_vtadmin_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4689,7 +4878,7 @@ func (x *ReloadSchemasRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReloadSchemasRequest.ProtoReflect.Descriptor instead. func (*ReloadSchemasRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{79} + return file_vtadmin_proto_rawDescGZIP(), []int{82} } func (x *ReloadSchemasRequest) GetKeyspaces() []string { @@ -4763,7 +4952,7 @@ type ReloadSchemasResponse struct { func (x *ReloadSchemasResponse) Reset() { *x = ReloadSchemasResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[80] + mi := &file_vtadmin_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4776,7 +4965,7 @@ func (x *ReloadSchemasResponse) String() string { func (*ReloadSchemasResponse) ProtoMessage() {} func (x *ReloadSchemasResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[80] + mi := &file_vtadmin_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4789,7 +4978,7 @@ func (x *ReloadSchemasResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReloadSchemasResponse.ProtoReflect.Descriptor instead. func (*ReloadSchemasResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{80} + return file_vtadmin_proto_rawDescGZIP(), []int{83} } func (x *ReloadSchemasResponse) GetKeyspaceResults() []*ReloadSchemasResponse_KeyspaceResult { @@ -4829,7 +5018,7 @@ type ReloadSchemaShardRequest struct { func (x *ReloadSchemaShardRequest) Reset() { *x = ReloadSchemaShardRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[81] + mi := &file_vtadmin_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4842,7 +5031,7 @@ func (x *ReloadSchemaShardRequest) String() string { func (*ReloadSchemaShardRequest) ProtoMessage() {} func (x *ReloadSchemaShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[81] + mi := &file_vtadmin_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4855,7 +5044,7 @@ func (x *ReloadSchemaShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReloadSchemaShardRequest.ProtoReflect.Descriptor instead. func (*ReloadSchemaShardRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{81} + return file_vtadmin_proto_rawDescGZIP(), []int{84} } func (x *ReloadSchemaShardRequest) GetClusterId() string { @@ -4911,7 +5100,7 @@ type ReloadSchemaShardResponse struct { func (x *ReloadSchemaShardResponse) Reset() { *x = ReloadSchemaShardResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[82] + mi := &file_vtadmin_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4924,7 +5113,7 @@ func (x *ReloadSchemaShardResponse) String() string { func (*ReloadSchemaShardResponse) ProtoMessage() {} func (x *ReloadSchemaShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[82] + mi := &file_vtadmin_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4937,7 +5126,7 @@ func (x *ReloadSchemaShardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReloadSchemaShardResponse.ProtoReflect.Descriptor instead. func (*ReloadSchemaShardResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{82} + return file_vtadmin_proto_rawDescGZIP(), []int{85} } func (x *ReloadSchemaShardResponse) GetEvents() []*logutil.Event { @@ -4959,7 +5148,7 @@ type RefreshTabletReplicationSourceRequest struct { func (x *RefreshTabletReplicationSourceRequest) Reset() { *x = RefreshTabletReplicationSourceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[83] + mi := &file_vtadmin_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4972,7 +5161,7 @@ func (x *RefreshTabletReplicationSourceRequest) String() string { func (*RefreshTabletReplicationSourceRequest) ProtoMessage() {} func (x *RefreshTabletReplicationSourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[83] + mi := &file_vtadmin_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4985,7 +5174,7 @@ func (x *RefreshTabletReplicationSourceRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use RefreshTabletReplicationSourceRequest.ProtoReflect.Descriptor instead. func (*RefreshTabletReplicationSourceRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{83} + return file_vtadmin_proto_rawDescGZIP(), []int{86} } func (x *RefreshTabletReplicationSourceRequest) GetAlias() *topodata.TabletAlias { @@ -5016,7 +5205,7 @@ type RefreshTabletReplicationSourceResponse struct { func (x *RefreshTabletReplicationSourceResponse) Reset() { *x = RefreshTabletReplicationSourceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[84] + mi := &file_vtadmin_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5029,7 +5218,7 @@ func (x *RefreshTabletReplicationSourceResponse) String() string { func (*RefreshTabletReplicationSourceResponse) ProtoMessage() {} func (x *RefreshTabletReplicationSourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[84] + mi := &file_vtadmin_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5042,7 +5231,7 @@ func (x *RefreshTabletReplicationSourceResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use RefreshTabletReplicationSourceResponse.ProtoReflect.Descriptor instead. func (*RefreshTabletReplicationSourceResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{84} + return file_vtadmin_proto_rawDescGZIP(), []int{87} } func (x *RefreshTabletReplicationSourceResponse) GetKeyspace() string { @@ -5088,7 +5277,7 @@ type RemoveKeyspaceCellRequest struct { func (x *RemoveKeyspaceCellRequest) Reset() { *x = RemoveKeyspaceCellRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[85] + mi := &file_vtadmin_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5101,7 +5290,7 @@ func (x *RemoveKeyspaceCellRequest) String() string { func (*RemoveKeyspaceCellRequest) ProtoMessage() {} func (x *RemoveKeyspaceCellRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[85] + mi := &file_vtadmin_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5114,7 +5303,7 @@ func (x *RemoveKeyspaceCellRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveKeyspaceCellRequest.ProtoReflect.Descriptor instead. func (*RemoveKeyspaceCellRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{85} + return file_vtadmin_proto_rawDescGZIP(), []int{88} } func (x *RemoveKeyspaceCellRequest) GetClusterId() string { @@ -5163,7 +5352,7 @@ type RemoveKeyspaceCellResponse struct { func (x *RemoveKeyspaceCellResponse) Reset() { *x = RemoveKeyspaceCellResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[86] + mi := &file_vtadmin_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5176,7 +5365,7 @@ func (x *RemoveKeyspaceCellResponse) String() string { func (*RemoveKeyspaceCellResponse) ProtoMessage() {} func (x *RemoveKeyspaceCellResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[86] + mi := &file_vtadmin_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5189,7 +5378,7 @@ func (x *RemoveKeyspaceCellResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveKeyspaceCellResponse.ProtoReflect.Descriptor instead. func (*RemoveKeyspaceCellResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{86} + return file_vtadmin_proto_rawDescGZIP(), []int{89} } func (x *RemoveKeyspaceCellResponse) GetStatus() string { @@ -5211,7 +5400,7 @@ type RetrySchemaMigrationRequest struct { func (x *RetrySchemaMigrationRequest) Reset() { *x = RetrySchemaMigrationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[87] + mi := &file_vtadmin_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5224,7 +5413,7 @@ func (x *RetrySchemaMigrationRequest) String() string { func (*RetrySchemaMigrationRequest) ProtoMessage() {} func (x *RetrySchemaMigrationRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[87] + mi := &file_vtadmin_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5237,7 +5426,7 @@ func (x *RetrySchemaMigrationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetrySchemaMigrationRequest.ProtoReflect.Descriptor instead. func (*RetrySchemaMigrationRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{87} + return file_vtadmin_proto_rawDescGZIP(), []int{90} } func (x *RetrySchemaMigrationRequest) GetClusterId() string { @@ -5266,7 +5455,7 @@ type RunHealthCheckRequest struct { func (x *RunHealthCheckRequest) Reset() { *x = RunHealthCheckRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[88] + mi := &file_vtadmin_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5279,7 +5468,7 @@ func (x *RunHealthCheckRequest) String() string { func (*RunHealthCheckRequest) ProtoMessage() {} func (x *RunHealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[88] + mi := &file_vtadmin_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5292,7 +5481,7 @@ func (x *RunHealthCheckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RunHealthCheckRequest.ProtoReflect.Descriptor instead. func (*RunHealthCheckRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{88} + return file_vtadmin_proto_rawDescGZIP(), []int{91} } func (x *RunHealthCheckRequest) GetAlias() *topodata.TabletAlias { @@ -5321,7 +5510,7 @@ type RunHealthCheckResponse struct { func (x *RunHealthCheckResponse) Reset() { *x = RunHealthCheckResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[89] + mi := &file_vtadmin_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5334,7 +5523,7 @@ func (x *RunHealthCheckResponse) String() string { func (*RunHealthCheckResponse) ProtoMessage() {} func (x *RunHealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[89] + mi := &file_vtadmin_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5347,7 +5536,7 @@ func (x *RunHealthCheckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RunHealthCheckResponse.ProtoReflect.Descriptor instead. func (*RunHealthCheckResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{89} + return file_vtadmin_proto_rawDescGZIP(), []int{92} } func (x *RunHealthCheckResponse) GetStatus() string { @@ -5376,7 +5565,7 @@ type SetReadOnlyRequest struct { func (x *SetReadOnlyRequest) Reset() { *x = SetReadOnlyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[90] + mi := &file_vtadmin_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5389,7 +5578,7 @@ func (x *SetReadOnlyRequest) String() string { func (*SetReadOnlyRequest) ProtoMessage() {} func (x *SetReadOnlyRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[90] + mi := &file_vtadmin_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5402,7 +5591,7 @@ func (x *SetReadOnlyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetReadOnlyRequest.ProtoReflect.Descriptor instead. func (*SetReadOnlyRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{90} + return file_vtadmin_proto_rawDescGZIP(), []int{93} } func (x *SetReadOnlyRequest) GetAlias() *topodata.TabletAlias { @@ -5428,7 +5617,7 @@ type SetReadOnlyResponse struct { func (x *SetReadOnlyResponse) Reset() { *x = SetReadOnlyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[91] + mi := &file_vtadmin_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5441,7 +5630,7 @@ func (x *SetReadOnlyResponse) String() string { func (*SetReadOnlyResponse) ProtoMessage() {} func (x *SetReadOnlyResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[91] + mi := &file_vtadmin_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5454,7 +5643,7 @@ func (x *SetReadOnlyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetReadOnlyResponse.ProtoReflect.Descriptor instead. func (*SetReadOnlyResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{91} + return file_vtadmin_proto_rawDescGZIP(), []int{94} } type SetReadWriteRequest struct { @@ -5469,7 +5658,7 @@ type SetReadWriteRequest struct { func (x *SetReadWriteRequest) Reset() { *x = SetReadWriteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[92] + mi := &file_vtadmin_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5482,7 +5671,7 @@ func (x *SetReadWriteRequest) String() string { func (*SetReadWriteRequest) ProtoMessage() {} func (x *SetReadWriteRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[92] + mi := &file_vtadmin_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5495,7 +5684,7 @@ func (x *SetReadWriteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetReadWriteRequest.ProtoReflect.Descriptor instead. func (*SetReadWriteRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{92} + return file_vtadmin_proto_rawDescGZIP(), []int{95} } func (x *SetReadWriteRequest) GetAlias() *topodata.TabletAlias { @@ -5521,7 +5710,7 @@ type SetReadWriteResponse struct { func (x *SetReadWriteResponse) Reset() { *x = SetReadWriteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[93] + mi := &file_vtadmin_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5534,7 +5723,7 @@ func (x *SetReadWriteResponse) String() string { func (*SetReadWriteResponse) ProtoMessage() {} func (x *SetReadWriteResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[93] + mi := &file_vtadmin_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5547,7 +5736,7 @@ func (x *SetReadWriteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetReadWriteResponse.ProtoReflect.Descriptor instead. func (*SetReadWriteResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{93} + return file_vtadmin_proto_rawDescGZIP(), []int{96} } type StartReplicationRequest struct { @@ -5562,7 +5751,7 @@ type StartReplicationRequest struct { func (x *StartReplicationRequest) Reset() { *x = StartReplicationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[94] + mi := &file_vtadmin_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5575,7 +5764,7 @@ func (x *StartReplicationRequest) String() string { func (*StartReplicationRequest) ProtoMessage() {} func (x *StartReplicationRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[94] + mi := &file_vtadmin_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5588,7 +5777,7 @@ func (x *StartReplicationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartReplicationRequest.ProtoReflect.Descriptor instead. func (*StartReplicationRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{94} + return file_vtadmin_proto_rawDescGZIP(), []int{97} } func (x *StartReplicationRequest) GetAlias() *topodata.TabletAlias { @@ -5617,7 +5806,7 @@ type StartReplicationResponse struct { func (x *StartReplicationResponse) Reset() { *x = StartReplicationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[95] + mi := &file_vtadmin_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5630,7 +5819,7 @@ func (x *StartReplicationResponse) String() string { func (*StartReplicationResponse) ProtoMessage() {} func (x *StartReplicationResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[95] + mi := &file_vtadmin_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5643,7 +5832,7 @@ func (x *StartReplicationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartReplicationResponse.ProtoReflect.Descriptor instead. func (*StartReplicationResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{95} + return file_vtadmin_proto_rawDescGZIP(), []int{98} } func (x *StartReplicationResponse) GetStatus() string { @@ -5672,7 +5861,7 @@ type StopReplicationRequest struct { func (x *StopReplicationRequest) Reset() { *x = StopReplicationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[96] + mi := &file_vtadmin_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5685,7 +5874,7 @@ func (x *StopReplicationRequest) String() string { func (*StopReplicationRequest) ProtoMessage() {} func (x *StopReplicationRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[96] + mi := &file_vtadmin_proto_msgTypes[99] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5698,7 +5887,7 @@ func (x *StopReplicationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopReplicationRequest.ProtoReflect.Descriptor instead. func (*StopReplicationRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{96} + return file_vtadmin_proto_rawDescGZIP(), []int{99} } func (x *StopReplicationRequest) GetAlias() *topodata.TabletAlias { @@ -5727,7 +5916,7 @@ type StopReplicationResponse struct { func (x *StopReplicationResponse) Reset() { *x = StopReplicationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[97] + mi := &file_vtadmin_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5740,7 +5929,7 @@ func (x *StopReplicationResponse) String() string { func (*StopReplicationResponse) ProtoMessage() {} func (x *StopReplicationResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[97] + mi := &file_vtadmin_proto_msgTypes[100] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5753,7 +5942,7 @@ func (x *StopReplicationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopReplicationResponse.ProtoReflect.Descriptor instead. func (*StopReplicationResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{97} + return file_vtadmin_proto_rawDescGZIP(), []int{100} } func (x *StopReplicationResponse) GetStatus() string { @@ -5784,7 +5973,7 @@ type TabletExternallyPromotedRequest struct { func (x *TabletExternallyPromotedRequest) Reset() { *x = TabletExternallyPromotedRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[98] + mi := &file_vtadmin_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5797,7 +5986,7 @@ func (x *TabletExternallyPromotedRequest) String() string { func (*TabletExternallyPromotedRequest) ProtoMessage() {} func (x *TabletExternallyPromotedRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[98] + mi := &file_vtadmin_proto_msgTypes[101] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5810,7 +5999,7 @@ func (x *TabletExternallyPromotedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TabletExternallyPromotedRequest.ProtoReflect.Descriptor instead. func (*TabletExternallyPromotedRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{98} + return file_vtadmin_proto_rawDescGZIP(), []int{101} } func (x *TabletExternallyPromotedRequest) GetAlias() *topodata.TabletAlias { @@ -5842,7 +6031,7 @@ type TabletExternallyPromotedResponse struct { func (x *TabletExternallyPromotedResponse) Reset() { *x = TabletExternallyPromotedResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[99] + mi := &file_vtadmin_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5855,7 +6044,7 @@ func (x *TabletExternallyPromotedResponse) String() string { func (*TabletExternallyPromotedResponse) ProtoMessage() {} func (x *TabletExternallyPromotedResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[99] + mi := &file_vtadmin_proto_msgTypes[102] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5868,7 +6057,7 @@ func (x *TabletExternallyPromotedResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TabletExternallyPromotedResponse.ProtoReflect.Descriptor instead. func (*TabletExternallyPromotedResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{99} + return file_vtadmin_proto_rawDescGZIP(), []int{102} } func (x *TabletExternallyPromotedResponse) GetCluster() *Cluster { @@ -5918,7 +6107,7 @@ type TabletExternallyReparentedRequest struct { func (x *TabletExternallyReparentedRequest) Reset() { *x = TabletExternallyReparentedRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[100] + mi := &file_vtadmin_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5931,7 +6120,7 @@ func (x *TabletExternallyReparentedRequest) String() string { func (*TabletExternallyReparentedRequest) ProtoMessage() {} func (x *TabletExternallyReparentedRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[100] + mi := &file_vtadmin_proto_msgTypes[103] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5944,7 +6133,7 @@ func (x *TabletExternallyReparentedRequest) ProtoReflect() protoreflect.Message // Deprecated: Use TabletExternallyReparentedRequest.ProtoReflect.Descriptor instead. func (*TabletExternallyReparentedRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{100} + return file_vtadmin_proto_rawDescGZIP(), []int{103} } func (x *TabletExternallyReparentedRequest) GetAlias() *topodata.TabletAlias { @@ -5973,7 +6162,7 @@ type ValidateRequest struct { func (x *ValidateRequest) Reset() { *x = ValidateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[101] + mi := &file_vtadmin_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5986,7 +6175,7 @@ func (x *ValidateRequest) String() string { func (*ValidateRequest) ProtoMessage() {} func (x *ValidateRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[101] + mi := &file_vtadmin_proto_msgTypes[104] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5999,7 +6188,7 @@ func (x *ValidateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateRequest.ProtoReflect.Descriptor instead. func (*ValidateRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{101} + return file_vtadmin_proto_rawDescGZIP(), []int{104} } func (x *ValidateRequest) GetClusterId() string { @@ -6029,7 +6218,7 @@ type ValidateKeyspaceRequest struct { func (x *ValidateKeyspaceRequest) Reset() { *x = ValidateKeyspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[102] + mi := &file_vtadmin_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6042,7 +6231,7 @@ func (x *ValidateKeyspaceRequest) String() string { func (*ValidateKeyspaceRequest) ProtoMessage() {} func (x *ValidateKeyspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[102] + mi := &file_vtadmin_proto_msgTypes[105] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6055,7 +6244,7 @@ func (x *ValidateKeyspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateKeyspaceRequest.ProtoReflect.Descriptor instead. func (*ValidateKeyspaceRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{102} + return file_vtadmin_proto_rawDescGZIP(), []int{105} } func (x *ValidateKeyspaceRequest) GetClusterId() string { @@ -6091,7 +6280,7 @@ type ValidateSchemaKeyspaceRequest struct { func (x *ValidateSchemaKeyspaceRequest) Reset() { *x = ValidateSchemaKeyspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[103] + mi := &file_vtadmin_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6104,7 +6293,7 @@ func (x *ValidateSchemaKeyspaceRequest) String() string { func (*ValidateSchemaKeyspaceRequest) ProtoMessage() {} func (x *ValidateSchemaKeyspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[103] + mi := &file_vtadmin_proto_msgTypes[106] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6117,7 +6306,7 @@ func (x *ValidateSchemaKeyspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateSchemaKeyspaceRequest.ProtoReflect.Descriptor instead. func (*ValidateSchemaKeyspaceRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{103} + return file_vtadmin_proto_rawDescGZIP(), []int{106} } func (x *ValidateSchemaKeyspaceRequest) GetClusterId() string { @@ -6148,7 +6337,7 @@ type ValidateShardRequest struct { func (x *ValidateShardRequest) Reset() { *x = ValidateShardRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[104] + mi := &file_vtadmin_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6161,7 +6350,7 @@ func (x *ValidateShardRequest) String() string { func (*ValidateShardRequest) ProtoMessage() {} func (x *ValidateShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[104] + mi := &file_vtadmin_proto_msgTypes[107] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6174,7 +6363,7 @@ func (x *ValidateShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateShardRequest.ProtoReflect.Descriptor instead. func (*ValidateShardRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{104} + return file_vtadmin_proto_rawDescGZIP(), []int{107} } func (x *ValidateShardRequest) GetClusterId() string { @@ -6217,7 +6406,7 @@ type ValidateVersionKeyspaceRequest struct { func (x *ValidateVersionKeyspaceRequest) Reset() { *x = ValidateVersionKeyspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[105] + mi := &file_vtadmin_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6230,7 +6419,7 @@ func (x *ValidateVersionKeyspaceRequest) String() string { func (*ValidateVersionKeyspaceRequest) ProtoMessage() {} func (x *ValidateVersionKeyspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[105] + mi := &file_vtadmin_proto_msgTypes[108] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6243,7 +6432,7 @@ func (x *ValidateVersionKeyspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateVersionKeyspaceRequest.ProtoReflect.Descriptor instead. func (*ValidateVersionKeyspaceRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{105} + return file_vtadmin_proto_rawDescGZIP(), []int{108} } func (x *ValidateVersionKeyspaceRequest) GetClusterId() string { @@ -6273,7 +6462,7 @@ type ValidateVersionShardRequest struct { func (x *ValidateVersionShardRequest) Reset() { *x = ValidateVersionShardRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[106] + mi := &file_vtadmin_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6286,7 +6475,7 @@ func (x *ValidateVersionShardRequest) String() string { func (*ValidateVersionShardRequest) ProtoMessage() {} func (x *ValidateVersionShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[106] + mi := &file_vtadmin_proto_msgTypes[109] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6299,7 +6488,7 @@ func (x *ValidateVersionShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateVersionShardRequest.ProtoReflect.Descriptor instead. func (*ValidateVersionShardRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{106} + return file_vtadmin_proto_rawDescGZIP(), []int{109} } func (x *ValidateVersionShardRequest) GetClusterId() string { @@ -6336,7 +6525,7 @@ type VTExplainRequest struct { func (x *VTExplainRequest) Reset() { *x = VTExplainRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[107] + mi := &file_vtadmin_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6349,7 +6538,7 @@ func (x *VTExplainRequest) String() string { func (*VTExplainRequest) ProtoMessage() {} func (x *VTExplainRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[107] + mi := &file_vtadmin_proto_msgTypes[110] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6362,7 +6551,7 @@ func (x *VTExplainRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VTExplainRequest.ProtoReflect.Descriptor instead. func (*VTExplainRequest) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{107} + return file_vtadmin_proto_rawDescGZIP(), []int{110} } func (x *VTExplainRequest) GetCluster() string { @@ -6397,7 +6586,7 @@ type VTExplainResponse struct { func (x *VTExplainResponse) Reset() { *x = VTExplainResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[108] + mi := &file_vtadmin_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6410,7 +6599,7 @@ func (x *VTExplainResponse) String() string { func (*VTExplainResponse) ProtoMessage() {} func (x *VTExplainResponse) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[108] + mi := &file_vtadmin_proto_msgTypes[111] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6423,7 +6612,7 @@ func (x *VTExplainResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VTExplainResponse.ProtoReflect.Descriptor instead. func (*VTExplainResponse) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{108} + return file_vtadmin_proto_rawDescGZIP(), []int{111} } func (x *VTExplainResponse) GetResponse() string { @@ -6445,7 +6634,7 @@ type Schema_ShardTableSize struct { func (x *Schema_ShardTableSize) Reset() { *x = Schema_ShardTableSize{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[112] + mi := &file_vtadmin_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6458,7 +6647,7 @@ func (x *Schema_ShardTableSize) String() string { func (*Schema_ShardTableSize) ProtoMessage() {} func (x *Schema_ShardTableSize) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[112] + mi := &file_vtadmin_proto_msgTypes[115] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6503,7 +6692,7 @@ type Schema_TableSize struct { func (x *Schema_TableSize) Reset() { *x = Schema_TableSize{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[113] + mi := &file_vtadmin_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6516,7 +6705,7 @@ func (x *Schema_TableSize) String() string { func (*Schema_TableSize) ProtoMessage() {} func (x *Schema_TableSize) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[113] + mi := &file_vtadmin_proto_msgTypes[116] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6565,7 +6754,7 @@ type GetSchemaMigrationsRequest_ClusterRequest struct { func (x *GetSchemaMigrationsRequest_ClusterRequest) Reset() { *x = GetSchemaMigrationsRequest_ClusterRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[115] + mi := &file_vtadmin_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6578,7 +6767,7 @@ func (x *GetSchemaMigrationsRequest_ClusterRequest) String() string { func (*GetSchemaMigrationsRequest_ClusterRequest) ProtoMessage() {} func (x *GetSchemaMigrationsRequest_ClusterRequest) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[115] + mi := &file_vtadmin_proto_msgTypes[118] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6626,7 +6815,7 @@ type ReloadSchemasResponse_KeyspaceResult struct { func (x *ReloadSchemasResponse_KeyspaceResult) Reset() { *x = ReloadSchemasResponse_KeyspaceResult{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[118] + mi := &file_vtadmin_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6639,7 +6828,7 @@ func (x *ReloadSchemasResponse_KeyspaceResult) String() string { func (*ReloadSchemasResponse_KeyspaceResult) ProtoMessage() {} func (x *ReloadSchemasResponse_KeyspaceResult) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[118] + mi := &file_vtadmin_proto_msgTypes[121] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6652,7 +6841,7 @@ func (x *ReloadSchemasResponse_KeyspaceResult) ProtoReflect() protoreflect.Messa // Deprecated: Use ReloadSchemasResponse_KeyspaceResult.ProtoReflect.Descriptor instead. func (*ReloadSchemasResponse_KeyspaceResult) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{80, 0} + return file_vtadmin_proto_rawDescGZIP(), []int{83, 0} } func (x *ReloadSchemasResponse_KeyspaceResult) GetKeyspace() *Keyspace { @@ -6687,7 +6876,7 @@ type ReloadSchemasResponse_ShardResult struct { func (x *ReloadSchemasResponse_ShardResult) Reset() { *x = ReloadSchemasResponse_ShardResult{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[119] + mi := &file_vtadmin_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6700,7 +6889,7 @@ func (x *ReloadSchemasResponse_ShardResult) String() string { func (*ReloadSchemasResponse_ShardResult) ProtoMessage() {} func (x *ReloadSchemasResponse_ShardResult) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[119] + mi := &file_vtadmin_proto_msgTypes[122] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6713,7 +6902,7 @@ func (x *ReloadSchemasResponse_ShardResult) ProtoReflect() protoreflect.Message // Deprecated: Use ReloadSchemasResponse_ShardResult.ProtoReflect.Descriptor instead. func (*ReloadSchemasResponse_ShardResult) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{80, 1} + return file_vtadmin_proto_rawDescGZIP(), []int{83, 1} } func (x *ReloadSchemasResponse_ShardResult) GetShard() *Shard { @@ -6749,7 +6938,7 @@ type ReloadSchemasResponse_TabletResult struct { func (x *ReloadSchemasResponse_TabletResult) Reset() { *x = ReloadSchemasResponse_TabletResult{} if protoimpl.UnsafeEnabled { - mi := &file_vtadmin_proto_msgTypes[120] + mi := &file_vtadmin_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6762,7 +6951,7 @@ func (x *ReloadSchemasResponse_TabletResult) String() string { func (*ReloadSchemasResponse_TabletResult) ProtoMessage() {} func (x *ReloadSchemasResponse_TabletResult) ProtoReflect() protoreflect.Message { - mi := &file_vtadmin_proto_msgTypes[120] + mi := &file_vtadmin_proto_msgTypes[123] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6775,7 +6964,7 @@ func (x *ReloadSchemasResponse_TabletResult) ProtoReflect() protoreflect.Message // Deprecated: Use ReloadSchemasResponse_TabletResult.ProtoReflect.Descriptor instead. func (*ReloadSchemasResponse_TabletResult) Descriptor() ([]byte, []int) { - return file_vtadmin_proto_rawDescGZIP(), []int{80, 2} + return file_vtadmin_proto_rawDescGZIP(), []int{83, 2} } func (x *ReloadSchemasResponse_TabletResult) GetTablet() *Tablet { @@ -7318,660 +7507,697 @@ var file_vtadmin_proto_rawDesc = []byte{ 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xa0, 0x01, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, - 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, - 0xe1, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x42, - 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x42, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x1a, 0x60, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x42, 0x79, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2f, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x80, 0x01, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x61, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x12, 0x50, 0x69, 0x6e, - 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x22, 0x7e, 0x0a, 0x1b, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, - 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 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, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x1c, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, - 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 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, 0x40, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 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, 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, 0x05, - 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, 0x93, 0x01, 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, 0x1d, 0x0a, 0x0a, + 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x69, 0x0a, 0x18, + 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x6d, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x1a, 0x0a, 0x08, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x6c, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x22, 0xa0, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0x1c, + 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, 0xe1, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x67, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x5f, 0x62, 0x79, + 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x42, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, + 0x42, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x1a, 0x60, 0x0a, 0x17, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x42, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x80, 0x01, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x18, 0x03, 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, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x61, 0x6c, 0x22, 0x36, 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x63, 0x0a, 0x13, 0x52, 0x65, - 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, - 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, - 0x5a, 0x0a, 0x14, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x61, + 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, + 0x73, 0x22, 0x58, 0x0a, 0x12, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x9f, 0x02, 0x0a, 0x14, - 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x03, 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, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0x12, - 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x06, 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, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0xad, 0x04, - 0x0a, 0x15, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x10, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x12, 0x52, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x67, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 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, 0x1a, - 0x5b, 0x0a, 0x0b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x64, 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, 0x1a, 0x4f, 0x0a, 0x0c, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x27, 0x0a, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, - 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x06, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xdb, 0x01, - 0x0a, 0x18, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, + 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x7e, 0x0a, 0x1b, 0x50, + 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x23, 0x0a, 0x0d, 0x77, - 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x18, 0x05, 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, 0x06, 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, 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, 0x75, 0x0a, 0x25, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x61, 0x6c, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x74, 0x63, + 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 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, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x1c, + 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 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, 0x40, 0x0a, 0x10, 0x70, 0x72, + 0x6f, 0x6d, 0x6f, 0x74, 0x65, 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, 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, 0x05, 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, 0x93, 0x01, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x64, 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, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x36, 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x63, 0x0a, 0x13, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xb7, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x66, 0x72, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5a, 0x0a, 0x14, 0x52, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x22, 0x9f, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, + 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0e, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x03, + 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, 0x07, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 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, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, + 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0xad, 0x04, 0x0a, 0x15, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x58, 0x0a, 0x10, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x76, 0x74, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x73, 0x68, + 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x52, 0x0a, 0x0e, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, + 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, + 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x67, + 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x12, 0x2d, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 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, 0x1a, 0x5b, 0x0a, 0x0b, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 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, 0x1a, 0x4f, 0x0a, 0x0c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xdb, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, + 0x64, 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, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, + 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x05, 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, 0x06, 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, 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, 0x75, 0x0a, 0x25, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 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, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x22, 0x9e, 0x01, 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, - 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 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, 0x34, 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, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x7e, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, - 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x65, 0x0a, 0x15, 0x52, 0x75, 0x6e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, - 0x5c, 0x0a, 0x16, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x62, 0x0a, - 0x12, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, - 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, - 0x73, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x16, 0x0a, - 0x14, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 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, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5e, - 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x66, - 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, 0x2b, 0x0a, 0x05, 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, 0x05, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5d, 0x0a, 0x17, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0xb7, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x12, 0x2a, 0x0a, + 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x9e, 0x01, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 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, 0x34, 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x7e, 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, + 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, + 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x65, 0x0a, 0x15, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, + 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5c, 0x0a, 0x16, 0x52, 0x75, 0x6e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x6f, 0x0a, 0x1f, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x62, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, + 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x74, + 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x63, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, + 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 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, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xf0, 0x01, 0x0a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, - 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, - 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 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, 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, - 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5e, 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x66, 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, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x5d, + 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, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x6f, 0x0a, + 0x1f, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, + 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xf0, + 0x01, 0x0a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 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, 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 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, 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, 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, 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, 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, 0x0a, 0x6f, - 0x6c, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x71, 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, 0x2b, - 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x53, 0x0a, 0x0f, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x77, 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, 0x1d, 0x0a, 0x0a, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 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, 0x5a, 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, 0x1d, 0x0a, 0x0a, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x22, 0x8a, 0x01, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x73, 0x22, 0x5b, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x64, 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, - 0x22, 0x6e, 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, - 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, - 0x22, 0x5a, 0x0a, 0x10, 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 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, 0x10, 0x0a, 0x03, 0x73, 0x71, - 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x71, 0x6c, 0x22, 0x2f, 0x0a, 0x11, - 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xad, 0x27, - 0x0a, 0x07, 0x56, 0x54, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x4c, 0x0a, 0x0b, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x16, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 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, - 0x22, 0x00, 0x12, 0x70, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x1a, 0x2a, 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, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0b, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, - 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, - 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, - 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, - 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, - 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6b, - 0x0a, 0x16, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x26, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x61, 0x69, 0x6c, - 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x65, 0x72, 0x67, + 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0a, 0x6f, 0x6c, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, + 0x79, 0x22, 0x71, 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, 0x2b, 0x0a, 0x05, 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, 0x05, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x64, 0x73, 0x22, 0x53, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x77, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x64, 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, + 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, 0x5a, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x49, 0x64, 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, 0x22, 0x8a, + 0x01, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, + 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0x5b, 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, 0x1d, 0x0a, + 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x22, 0x6e, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 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, 0x22, 0x5a, 0x0a, 0x10, 0x56, 0x54, 0x45, 0x78, + 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 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, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x73, 0x71, 0x6c, 0x22, 0x2f, 0x0a, 0x11, 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xb2, 0x29, 0x0a, 0x07, 0x56, 0x54, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x12, 0x4c, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x6a, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, + 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, + 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x28, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x16, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 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, 0x22, 0x00, 0x12, 0x70, 0x0a, 0x17, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x1a, 0x2a, + 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, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4c, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x55, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x16, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x12, 0x26, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x46, - 0x69, 0x6e, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, - 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, - 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x56, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x47, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0b, 0x47, - 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x76, - 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x09, 0x47, - 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x62, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 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, 0x1a, 0x24, 0x2e, 0x76, 0x74, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x1c, 0x47, 0x65, 0x74, 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, 0x12, 0x2c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 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, 0x1a, 0x2d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 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, - 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 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, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0f, 0x47, 0x65, - 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x61, 0x69, 0x6c, + 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x46, 0x69, 0x6e, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6e, 0x64, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, + 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1a, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, + 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, + 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x4a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, + 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, + 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x41, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x11, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, + 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, 0x12, 0x47, + 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1a, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x1c, 0x47, + 0x65, 0x74, 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, 0x12, 0x2c, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 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, 0x1a, 0x2d, 0x2e, 0x76, 0x74, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 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, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 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, - 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x72, 0x76, - 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0e, 0x47, 0x65, 0x74, - 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1e, 0x2e, 0x76, 0x74, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, 0x74, + 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0d, 0x47, 0x65, + 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, - 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x76, 0x74, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, - 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, - 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0a, - 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x74, - 0x63, 0x74, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x3f, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1b, - 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x74, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x00, - 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x6a, 0x0a, 0x15, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, - 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 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, 0x1a, - 0x28, 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, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x50, - 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, - 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x24, 0x2e, 0x76, - 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, - 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x6c, 0x61, - 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x14, 0x52, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 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, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x83, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x6f, 0x61, - 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x11, 0x52, 0x65, 0x6c, - 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x21, + 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x76, 0x74, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, + 0x00, 0x12, 0x53, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x73, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, + 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x12, + 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, + 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, + 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, + 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x73, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, + 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 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, 0x12, 0x51, 0x0a, 0x0c, 0x53, 0x74, 0x6f, + 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 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, 0x12, 0x6a, 0x0a, 0x15, + 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 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, 0x1a, 0x28, 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, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x50, 0x69, 0x6e, 0x67, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x69, 0x6e, + 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x65, 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, + 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, + 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, + 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x14, 0x52, 0x65, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x25, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 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, 0x00, 0x12, + 0x4d, 0x0a, 0x0c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x83, + 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x2e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, + 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x21, 0x2e, 0x76, 0x74, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x22, 0x2e, - 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x23, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x00, 0x12, 0x67, 0x0a, 0x14, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x27, 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, 0x22, - 0x00, 0x12, 0x53, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x75, - 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x75, - 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, - 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, - 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x59, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 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, 0x00, 0x12, 0x56, 0x0a, 0x0f, - 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, 0x18, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x22, 0x2e, 0x76, 0x74, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x23, + 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x00, 0x12, 0x67, 0x0a, 0x14, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x27, 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, 0x22, 0x00, 0x12, 0x53, + 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x12, 0x1e, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x75, 0x6e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x75, 0x6e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, + 0x6c, 0x79, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, + 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, + 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x4d, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, + 0x1c, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, + 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x57, + 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x59, + 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x00, 0x12, 0x56, 0x0a, 0x0f, 0x53, 0x74, 0x6f, + 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x71, 0x0a, 0x18, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x12, 0x28, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, - 0x12, 0x28, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, - 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x76, 0x74, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x08, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 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, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x20, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 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, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x16, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 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, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 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, 0x22, 0x00, 0x12, 0x70, 0x0a, 0x17, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x27, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 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, - 0x1a, 0x2a, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x08, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x18, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 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, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x2e, + 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 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, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x26, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 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, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 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, 0x22, 0x00, 0x12, 0x70, 0x0a, 0x17, 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, 0x22, 0x00, 0x12, 0x67, - 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2e, 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, 0x1a, 0x27, 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, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x09, 0x56, 0x54, 0x45, 0x78, 0x70, - 0x6c, 0x61, 0x69, 0x6e, 0x12, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, - 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1a, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, - 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 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, 0x74, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x27, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x2a, 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, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x14, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x12, 0x24, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 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, 0x1a, 0x27, 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, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x09, 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, + 0x6e, 0x12, 0x19, 0x2e, 0x76, 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x54, 0x45, 0x78, + 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x76, + 0x74, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x56, 0x54, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 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, 0x74, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -7987,7 +8213,7 @@ func file_vtadmin_proto_rawDescGZIP() []byte { } var file_vtadmin_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_vtadmin_proto_msgTypes = make([]protoimpl.MessageInfo, 121) +var file_vtadmin_proto_msgTypes = make([]protoimpl.MessageInfo, 124) var file_vtadmin_proto_goTypes = []any{ (Tablet_ServingState)(0), // 0: vtadmin.Tablet.ServingState (*Cluster)(nil), // 1: vtadmin.Cluster @@ -8058,217 +8284,222 @@ var file_vtadmin_proto_goTypes = []any{ (*GetVtctldsRequest)(nil), // 66: vtadmin.GetVtctldsRequest (*GetVtctldsResponse)(nil), // 67: vtadmin.GetVtctldsResponse (*GetWorkflowRequest)(nil), // 68: vtadmin.GetWorkflowRequest - (*GetWorkflowsRequest)(nil), // 69: vtadmin.GetWorkflowsRequest - (*GetWorkflowsResponse)(nil), // 70: vtadmin.GetWorkflowsResponse - (*LaunchSchemaMigrationRequest)(nil), // 71: vtadmin.LaunchSchemaMigrationRequest - (*PingTabletRequest)(nil), // 72: vtadmin.PingTabletRequest - (*PingTabletResponse)(nil), // 73: vtadmin.PingTabletResponse - (*PlannedFailoverShardRequest)(nil), // 74: vtadmin.PlannedFailoverShardRequest - (*PlannedFailoverShardResponse)(nil), // 75: vtadmin.PlannedFailoverShardResponse - (*RebuildKeyspaceGraphRequest)(nil), // 76: vtadmin.RebuildKeyspaceGraphRequest - (*RebuildKeyspaceGraphResponse)(nil), // 77: vtadmin.RebuildKeyspaceGraphResponse - (*RefreshStateRequest)(nil), // 78: vtadmin.RefreshStateRequest - (*RefreshStateResponse)(nil), // 79: vtadmin.RefreshStateResponse - (*ReloadSchemasRequest)(nil), // 80: vtadmin.ReloadSchemasRequest - (*ReloadSchemasResponse)(nil), // 81: vtadmin.ReloadSchemasResponse - (*ReloadSchemaShardRequest)(nil), // 82: vtadmin.ReloadSchemaShardRequest - (*ReloadSchemaShardResponse)(nil), // 83: vtadmin.ReloadSchemaShardResponse - (*RefreshTabletReplicationSourceRequest)(nil), // 84: vtadmin.RefreshTabletReplicationSourceRequest - (*RefreshTabletReplicationSourceResponse)(nil), // 85: vtadmin.RefreshTabletReplicationSourceResponse - (*RemoveKeyspaceCellRequest)(nil), // 86: vtadmin.RemoveKeyspaceCellRequest - (*RemoveKeyspaceCellResponse)(nil), // 87: vtadmin.RemoveKeyspaceCellResponse - (*RetrySchemaMigrationRequest)(nil), // 88: vtadmin.RetrySchemaMigrationRequest - (*RunHealthCheckRequest)(nil), // 89: vtadmin.RunHealthCheckRequest - (*RunHealthCheckResponse)(nil), // 90: vtadmin.RunHealthCheckResponse - (*SetReadOnlyRequest)(nil), // 91: vtadmin.SetReadOnlyRequest - (*SetReadOnlyResponse)(nil), // 92: vtadmin.SetReadOnlyResponse - (*SetReadWriteRequest)(nil), // 93: vtadmin.SetReadWriteRequest - (*SetReadWriteResponse)(nil), // 94: vtadmin.SetReadWriteResponse - (*StartReplicationRequest)(nil), // 95: vtadmin.StartReplicationRequest - (*StartReplicationResponse)(nil), // 96: vtadmin.StartReplicationResponse - (*StopReplicationRequest)(nil), // 97: vtadmin.StopReplicationRequest - (*StopReplicationResponse)(nil), // 98: vtadmin.StopReplicationResponse - (*TabletExternallyPromotedRequest)(nil), // 99: vtadmin.TabletExternallyPromotedRequest - (*TabletExternallyPromotedResponse)(nil), // 100: vtadmin.TabletExternallyPromotedResponse - (*TabletExternallyReparentedRequest)(nil), // 101: vtadmin.TabletExternallyReparentedRequest - (*ValidateRequest)(nil), // 102: vtadmin.ValidateRequest - (*ValidateKeyspaceRequest)(nil), // 103: vtadmin.ValidateKeyspaceRequest - (*ValidateSchemaKeyspaceRequest)(nil), // 104: vtadmin.ValidateSchemaKeyspaceRequest - (*ValidateShardRequest)(nil), // 105: vtadmin.ValidateShardRequest - (*ValidateVersionKeyspaceRequest)(nil), // 106: vtadmin.ValidateVersionKeyspaceRequest - (*ValidateVersionShardRequest)(nil), // 107: vtadmin.ValidateVersionShardRequest - (*VTExplainRequest)(nil), // 108: vtadmin.VTExplainRequest - (*VTExplainResponse)(nil), // 109: vtadmin.VTExplainResponse - nil, // 110: vtadmin.ClusterCellsAliases.AliasesEntry - nil, // 111: vtadmin.Keyspace.ShardsEntry - nil, // 112: vtadmin.Schema.TableSizesEntry - (*Schema_ShardTableSize)(nil), // 113: vtadmin.Schema.ShardTableSize - (*Schema_TableSize)(nil), // 114: vtadmin.Schema.TableSize - nil, // 115: vtadmin.Schema.TableSize.ByShardEntry - (*GetSchemaMigrationsRequest_ClusterRequest)(nil), // 116: vtadmin.GetSchemaMigrationsRequest.ClusterRequest - nil, // 117: vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry - nil, // 118: vtadmin.GetWorkflowsResponse.WorkflowsByClusterEntry - (*ReloadSchemasResponse_KeyspaceResult)(nil), // 119: vtadmin.ReloadSchemasResponse.KeyspaceResult - (*ReloadSchemasResponse_ShardResult)(nil), // 120: vtadmin.ReloadSchemasResponse.ShardResult - (*ReloadSchemasResponse_TabletResult)(nil), // 121: vtadmin.ReloadSchemasResponse.TabletResult - (*mysqlctl.BackupInfo)(nil), // 122: mysqlctl.BackupInfo - (*topodata.CellInfo)(nil), // 123: topodata.CellInfo - (*vtctldata.ShardReplicationPositionsResponse)(nil), // 124: vtctldata.ShardReplicationPositionsResponse - (*vtctldata.Keyspace)(nil), // 125: vtctldata.Keyspace - (*tabletmanagerdata.TableDefinition)(nil), // 126: tabletmanagerdata.TableDefinition - (*vtctldata.SchemaMigration)(nil), // 127: vtctldata.SchemaMigration - (*vtctldata.Shard)(nil), // 128: vtctldata.Shard - (*vschema.SrvVSchema)(nil), // 129: vschema.SrvVSchema - (*topodata.Tablet)(nil), // 130: topodata.Tablet - (*vschema.Keyspace)(nil), // 131: vschema.Keyspace - (*vtctldata.Workflow)(nil), // 132: vtctldata.Workflow - (*vtctldata.ApplySchemaRequest)(nil), // 133: vtctldata.ApplySchemaRequest - (*vtctldata.CancelSchemaMigrationRequest)(nil), // 134: vtctldata.CancelSchemaMigrationRequest - (*vtctldata.CleanupSchemaMigrationRequest)(nil), // 135: vtctldata.CleanupSchemaMigrationRequest - (*vtctldata.CompleteSchemaMigrationRequest)(nil), // 136: vtctldata.CompleteSchemaMigrationRequest - (*vtctldata.CreateKeyspaceRequest)(nil), // 137: vtctldata.CreateKeyspaceRequest - (*vtctldata.CreateShardRequest)(nil), // 138: vtctldata.CreateShardRequest - (*vtctldata.DeleteKeyspaceRequest)(nil), // 139: vtctldata.DeleteKeyspaceRequest - (*vtctldata.DeleteShardsRequest)(nil), // 140: vtctldata.DeleteShardsRequest - (*topodata.TabletAlias)(nil), // 141: topodata.TabletAlias - (*vtctldata.EmergencyReparentShardRequest)(nil), // 142: vtctldata.EmergencyReparentShardRequest - (*logutil.Event)(nil), // 143: logutil.Event - (*vtctldata.GetBackupsRequest)(nil), // 144: vtctldata.GetBackupsRequest - (*vtctldata.LaunchSchemaMigrationRequest)(nil), // 145: vtctldata.LaunchSchemaMigrationRequest - (*vtctldata.PlannedReparentShardRequest)(nil), // 146: vtctldata.PlannedReparentShardRequest - (*vtctldata.RetrySchemaMigrationRequest)(nil), // 147: vtctldata.RetrySchemaMigrationRequest - (*topodata.CellsAlias)(nil), // 148: topodata.CellsAlias - (*vtctldata.GetSchemaMigrationsRequest)(nil), // 149: vtctldata.GetSchemaMigrationsRequest - (*vtctldata.GetSrvKeyspacesResponse)(nil), // 150: vtctldata.GetSrvKeyspacesResponse - (*vtctldata.ApplySchemaResponse)(nil), // 151: vtctldata.ApplySchemaResponse - (*vtctldata.CancelSchemaMigrationResponse)(nil), // 152: vtctldata.CancelSchemaMigrationResponse - (*vtctldata.CleanupSchemaMigrationResponse)(nil), // 153: vtctldata.CleanupSchemaMigrationResponse - (*vtctldata.CompleteSchemaMigrationResponse)(nil), // 154: vtctldata.CompleteSchemaMigrationResponse - (*vtctldata.CreateShardResponse)(nil), // 155: vtctldata.CreateShardResponse - (*vtctldata.DeleteKeyspaceResponse)(nil), // 156: vtctldata.DeleteKeyspaceResponse - (*vtctldata.DeleteShardsResponse)(nil), // 157: vtctldata.DeleteShardsResponse - (*vtctldata.GetFullStatusResponse)(nil), // 158: vtctldata.GetFullStatusResponse - (*vtctldata.GetTopologyPathResponse)(nil), // 159: vtctldata.GetTopologyPathResponse - (*vtctldata.LaunchSchemaMigrationResponse)(nil), // 160: vtctldata.LaunchSchemaMigrationResponse - (*vtctldata.RetrySchemaMigrationResponse)(nil), // 161: vtctldata.RetrySchemaMigrationResponse - (*vtctldata.ValidateResponse)(nil), // 162: vtctldata.ValidateResponse - (*vtctldata.ValidateKeyspaceResponse)(nil), // 163: vtctldata.ValidateKeyspaceResponse - (*vtctldata.ValidateSchemaKeyspaceResponse)(nil), // 164: vtctldata.ValidateSchemaKeyspaceResponse - (*vtctldata.ValidateShardResponse)(nil), // 165: vtctldata.ValidateShardResponse - (*vtctldata.ValidateVersionKeyspaceResponse)(nil), // 166: vtctldata.ValidateVersionKeyspaceResponse - (*vtctldata.ValidateVersionShardResponse)(nil), // 167: vtctldata.ValidateVersionShardResponse + (*GetWorkflowStatusRequest)(nil), // 69: vtadmin.GetWorkflowStatusRequest + (*StartWorkflowRequest)(nil), // 70: vtadmin.StartWorkflowRequest + (*StopWorkflowRequest)(nil), // 71: vtadmin.StopWorkflowRequest + (*GetWorkflowsRequest)(nil), // 72: vtadmin.GetWorkflowsRequest + (*GetWorkflowsResponse)(nil), // 73: vtadmin.GetWorkflowsResponse + (*LaunchSchemaMigrationRequest)(nil), // 74: vtadmin.LaunchSchemaMigrationRequest + (*PingTabletRequest)(nil), // 75: vtadmin.PingTabletRequest + (*PingTabletResponse)(nil), // 76: vtadmin.PingTabletResponse + (*PlannedFailoverShardRequest)(nil), // 77: vtadmin.PlannedFailoverShardRequest + (*PlannedFailoverShardResponse)(nil), // 78: vtadmin.PlannedFailoverShardResponse + (*RebuildKeyspaceGraphRequest)(nil), // 79: vtadmin.RebuildKeyspaceGraphRequest + (*RebuildKeyspaceGraphResponse)(nil), // 80: vtadmin.RebuildKeyspaceGraphResponse + (*RefreshStateRequest)(nil), // 81: vtadmin.RefreshStateRequest + (*RefreshStateResponse)(nil), // 82: vtadmin.RefreshStateResponse + (*ReloadSchemasRequest)(nil), // 83: vtadmin.ReloadSchemasRequest + (*ReloadSchemasResponse)(nil), // 84: vtadmin.ReloadSchemasResponse + (*ReloadSchemaShardRequest)(nil), // 85: vtadmin.ReloadSchemaShardRequest + (*ReloadSchemaShardResponse)(nil), // 86: vtadmin.ReloadSchemaShardResponse + (*RefreshTabletReplicationSourceRequest)(nil), // 87: vtadmin.RefreshTabletReplicationSourceRequest + (*RefreshTabletReplicationSourceResponse)(nil), // 88: vtadmin.RefreshTabletReplicationSourceResponse + (*RemoveKeyspaceCellRequest)(nil), // 89: vtadmin.RemoveKeyspaceCellRequest + (*RemoveKeyspaceCellResponse)(nil), // 90: vtadmin.RemoveKeyspaceCellResponse + (*RetrySchemaMigrationRequest)(nil), // 91: vtadmin.RetrySchemaMigrationRequest + (*RunHealthCheckRequest)(nil), // 92: vtadmin.RunHealthCheckRequest + (*RunHealthCheckResponse)(nil), // 93: vtadmin.RunHealthCheckResponse + (*SetReadOnlyRequest)(nil), // 94: vtadmin.SetReadOnlyRequest + (*SetReadOnlyResponse)(nil), // 95: vtadmin.SetReadOnlyResponse + (*SetReadWriteRequest)(nil), // 96: vtadmin.SetReadWriteRequest + (*SetReadWriteResponse)(nil), // 97: vtadmin.SetReadWriteResponse + (*StartReplicationRequest)(nil), // 98: vtadmin.StartReplicationRequest + (*StartReplicationResponse)(nil), // 99: vtadmin.StartReplicationResponse + (*StopReplicationRequest)(nil), // 100: vtadmin.StopReplicationRequest + (*StopReplicationResponse)(nil), // 101: vtadmin.StopReplicationResponse + (*TabletExternallyPromotedRequest)(nil), // 102: vtadmin.TabletExternallyPromotedRequest + (*TabletExternallyPromotedResponse)(nil), // 103: vtadmin.TabletExternallyPromotedResponse + (*TabletExternallyReparentedRequest)(nil), // 104: vtadmin.TabletExternallyReparentedRequest + (*ValidateRequest)(nil), // 105: vtadmin.ValidateRequest + (*ValidateKeyspaceRequest)(nil), // 106: vtadmin.ValidateKeyspaceRequest + (*ValidateSchemaKeyspaceRequest)(nil), // 107: vtadmin.ValidateSchemaKeyspaceRequest + (*ValidateShardRequest)(nil), // 108: vtadmin.ValidateShardRequest + (*ValidateVersionKeyspaceRequest)(nil), // 109: vtadmin.ValidateVersionKeyspaceRequest + (*ValidateVersionShardRequest)(nil), // 110: vtadmin.ValidateVersionShardRequest + (*VTExplainRequest)(nil), // 111: vtadmin.VTExplainRequest + (*VTExplainResponse)(nil), // 112: vtadmin.VTExplainResponse + nil, // 113: vtadmin.ClusterCellsAliases.AliasesEntry + nil, // 114: vtadmin.Keyspace.ShardsEntry + nil, // 115: vtadmin.Schema.TableSizesEntry + (*Schema_ShardTableSize)(nil), // 116: vtadmin.Schema.ShardTableSize + (*Schema_TableSize)(nil), // 117: vtadmin.Schema.TableSize + nil, // 118: vtadmin.Schema.TableSize.ByShardEntry + (*GetSchemaMigrationsRequest_ClusterRequest)(nil), // 119: vtadmin.GetSchemaMigrationsRequest.ClusterRequest + nil, // 120: vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry + nil, // 121: vtadmin.GetWorkflowsResponse.WorkflowsByClusterEntry + (*ReloadSchemasResponse_KeyspaceResult)(nil), // 122: vtadmin.ReloadSchemasResponse.KeyspaceResult + (*ReloadSchemasResponse_ShardResult)(nil), // 123: vtadmin.ReloadSchemasResponse.ShardResult + (*ReloadSchemasResponse_TabletResult)(nil), // 124: vtadmin.ReloadSchemasResponse.TabletResult + (*mysqlctl.BackupInfo)(nil), // 125: mysqlctl.BackupInfo + (*topodata.CellInfo)(nil), // 126: topodata.CellInfo + (*vtctldata.ShardReplicationPositionsResponse)(nil), // 127: vtctldata.ShardReplicationPositionsResponse + (*vtctldata.Keyspace)(nil), // 128: vtctldata.Keyspace + (*tabletmanagerdata.TableDefinition)(nil), // 129: tabletmanagerdata.TableDefinition + (*vtctldata.SchemaMigration)(nil), // 130: vtctldata.SchemaMigration + (*vtctldata.Shard)(nil), // 131: vtctldata.Shard + (*vschema.SrvVSchema)(nil), // 132: vschema.SrvVSchema + (*topodata.Tablet)(nil), // 133: topodata.Tablet + (*vschema.Keyspace)(nil), // 134: vschema.Keyspace + (*vtctldata.Workflow)(nil), // 135: vtctldata.Workflow + (*vtctldata.ApplySchemaRequest)(nil), // 136: vtctldata.ApplySchemaRequest + (*vtctldata.CancelSchemaMigrationRequest)(nil), // 137: vtctldata.CancelSchemaMigrationRequest + (*vtctldata.CleanupSchemaMigrationRequest)(nil), // 138: vtctldata.CleanupSchemaMigrationRequest + (*vtctldata.CompleteSchemaMigrationRequest)(nil), // 139: vtctldata.CompleteSchemaMigrationRequest + (*vtctldata.CreateKeyspaceRequest)(nil), // 140: vtctldata.CreateKeyspaceRequest + (*vtctldata.CreateShardRequest)(nil), // 141: vtctldata.CreateShardRequest + (*vtctldata.DeleteKeyspaceRequest)(nil), // 142: vtctldata.DeleteKeyspaceRequest + (*vtctldata.DeleteShardsRequest)(nil), // 143: vtctldata.DeleteShardsRequest + (*topodata.TabletAlias)(nil), // 144: topodata.TabletAlias + (*vtctldata.EmergencyReparentShardRequest)(nil), // 145: vtctldata.EmergencyReparentShardRequest + (*logutil.Event)(nil), // 146: logutil.Event + (*vtctldata.GetBackupsRequest)(nil), // 147: vtctldata.GetBackupsRequest + (*vtctldata.LaunchSchemaMigrationRequest)(nil), // 148: vtctldata.LaunchSchemaMigrationRequest + (*vtctldata.PlannedReparentShardRequest)(nil), // 149: vtctldata.PlannedReparentShardRequest + (*vtctldata.RetrySchemaMigrationRequest)(nil), // 150: vtctldata.RetrySchemaMigrationRequest + (*topodata.CellsAlias)(nil), // 151: topodata.CellsAlias + (*vtctldata.GetSchemaMigrationsRequest)(nil), // 152: vtctldata.GetSchemaMigrationsRequest + (*vtctldata.GetSrvKeyspacesResponse)(nil), // 153: vtctldata.GetSrvKeyspacesResponse + (*vtctldata.ApplySchemaResponse)(nil), // 154: vtctldata.ApplySchemaResponse + (*vtctldata.CancelSchemaMigrationResponse)(nil), // 155: vtctldata.CancelSchemaMigrationResponse + (*vtctldata.CleanupSchemaMigrationResponse)(nil), // 156: vtctldata.CleanupSchemaMigrationResponse + (*vtctldata.CompleteSchemaMigrationResponse)(nil), // 157: vtctldata.CompleteSchemaMigrationResponse + (*vtctldata.CreateShardResponse)(nil), // 158: vtctldata.CreateShardResponse + (*vtctldata.DeleteKeyspaceResponse)(nil), // 159: vtctldata.DeleteKeyspaceResponse + (*vtctldata.DeleteShardsResponse)(nil), // 160: vtctldata.DeleteShardsResponse + (*vtctldata.GetFullStatusResponse)(nil), // 161: vtctldata.GetFullStatusResponse + (*vtctldata.GetTopologyPathResponse)(nil), // 162: vtctldata.GetTopologyPathResponse + (*vtctldata.WorkflowStatusResponse)(nil), // 163: vtctldata.WorkflowStatusResponse + (*vtctldata.WorkflowUpdateResponse)(nil), // 164: vtctldata.WorkflowUpdateResponse + (*vtctldata.LaunchSchemaMigrationResponse)(nil), // 165: vtctldata.LaunchSchemaMigrationResponse + (*vtctldata.RetrySchemaMigrationResponse)(nil), // 166: vtctldata.RetrySchemaMigrationResponse + (*vtctldata.ValidateResponse)(nil), // 167: vtctldata.ValidateResponse + (*vtctldata.ValidateKeyspaceResponse)(nil), // 168: vtctldata.ValidateKeyspaceResponse + (*vtctldata.ValidateSchemaKeyspaceResponse)(nil), // 169: vtctldata.ValidateSchemaKeyspaceResponse + (*vtctldata.ValidateShardResponse)(nil), // 170: vtctldata.ValidateShardResponse + (*vtctldata.ValidateVersionKeyspaceResponse)(nil), // 171: vtctldata.ValidateVersionKeyspaceResponse + (*vtctldata.ValidateVersionShardResponse)(nil), // 172: vtctldata.ValidateVersionShardResponse } var file_vtadmin_proto_depIdxs = []int32{ 1, // 0: vtadmin.ClusterBackup.cluster:type_name -> vtadmin.Cluster - 122, // 1: vtadmin.ClusterBackup.backup:type_name -> mysqlctl.BackupInfo + 125, // 1: vtadmin.ClusterBackup.backup:type_name -> mysqlctl.BackupInfo 1, // 2: vtadmin.ClusterCellsAliases.cluster:type_name -> vtadmin.Cluster - 110, // 3: vtadmin.ClusterCellsAliases.aliases:type_name -> vtadmin.ClusterCellsAliases.AliasesEntry + 113, // 3: vtadmin.ClusterCellsAliases.aliases:type_name -> vtadmin.ClusterCellsAliases.AliasesEntry 1, // 4: vtadmin.ClusterCellInfo.cluster:type_name -> vtadmin.Cluster - 123, // 5: vtadmin.ClusterCellInfo.cell_info:type_name -> topodata.CellInfo + 126, // 5: vtadmin.ClusterCellInfo.cell_info:type_name -> topodata.CellInfo 1, // 6: vtadmin.ClusterShardReplicationPosition.cluster:type_name -> vtadmin.Cluster - 124, // 7: vtadmin.ClusterShardReplicationPosition.position_info:type_name -> vtctldata.ShardReplicationPositionsResponse + 127, // 7: vtadmin.ClusterShardReplicationPosition.position_info:type_name -> vtctldata.ShardReplicationPositionsResponse 16, // 8: vtadmin.ClusterWorkflows.workflows:type_name -> vtadmin.Workflow 1, // 9: vtadmin.Keyspace.cluster:type_name -> vtadmin.Cluster - 125, // 10: vtadmin.Keyspace.keyspace:type_name -> vtctldata.Keyspace - 111, // 11: vtadmin.Keyspace.shards:type_name -> vtadmin.Keyspace.ShardsEntry + 128, // 10: vtadmin.Keyspace.keyspace:type_name -> vtctldata.Keyspace + 114, // 11: vtadmin.Keyspace.shards:type_name -> vtadmin.Keyspace.ShardsEntry 1, // 12: vtadmin.Schema.cluster:type_name -> vtadmin.Cluster - 126, // 13: vtadmin.Schema.table_definitions:type_name -> tabletmanagerdata.TableDefinition - 112, // 14: vtadmin.Schema.table_sizes:type_name -> vtadmin.Schema.TableSizesEntry + 129, // 13: vtadmin.Schema.table_definitions:type_name -> tabletmanagerdata.TableDefinition + 115, // 14: vtadmin.Schema.table_sizes:type_name -> vtadmin.Schema.TableSizesEntry 1, // 15: vtadmin.SchemaMigration.cluster:type_name -> vtadmin.Cluster - 127, // 16: vtadmin.SchemaMigration.schema_migration:type_name -> vtctldata.SchemaMigration + 130, // 16: vtadmin.SchemaMigration.schema_migration:type_name -> vtctldata.SchemaMigration 1, // 17: vtadmin.Shard.cluster:type_name -> vtadmin.Cluster - 128, // 18: vtadmin.Shard.shard:type_name -> vtctldata.Shard + 131, // 18: vtadmin.Shard.shard:type_name -> vtctldata.Shard 1, // 19: vtadmin.SrvVSchema.cluster:type_name -> vtadmin.Cluster - 129, // 20: vtadmin.SrvVSchema.srv_v_schema:type_name -> vschema.SrvVSchema + 132, // 20: vtadmin.SrvVSchema.srv_v_schema:type_name -> vschema.SrvVSchema 1, // 21: vtadmin.Tablet.cluster:type_name -> vtadmin.Cluster - 130, // 22: vtadmin.Tablet.tablet:type_name -> topodata.Tablet + 133, // 22: vtadmin.Tablet.tablet:type_name -> topodata.Tablet 0, // 23: vtadmin.Tablet.state:type_name -> vtadmin.Tablet.ServingState 1, // 24: vtadmin.VSchema.cluster:type_name -> vtadmin.Cluster - 131, // 25: vtadmin.VSchema.v_schema:type_name -> vschema.Keyspace + 134, // 25: vtadmin.VSchema.v_schema:type_name -> vschema.Keyspace 1, // 26: vtadmin.Vtctld.cluster:type_name -> vtadmin.Cluster 1, // 27: vtadmin.VTGate.cluster:type_name -> vtadmin.Cluster 1, // 28: vtadmin.Workflow.cluster:type_name -> vtadmin.Cluster - 132, // 29: vtadmin.Workflow.workflow:type_name -> vtctldata.Workflow - 133, // 30: vtadmin.ApplySchemaRequest.request:type_name -> vtctldata.ApplySchemaRequest - 134, // 31: vtadmin.CancelSchemaMigrationRequest.request:type_name -> vtctldata.CancelSchemaMigrationRequest - 135, // 32: vtadmin.CleanupSchemaMigrationRequest.request:type_name -> vtctldata.CleanupSchemaMigrationRequest - 136, // 33: vtadmin.CompleteSchemaMigrationRequest.request:type_name -> vtctldata.CompleteSchemaMigrationRequest - 137, // 34: vtadmin.CreateKeyspaceRequest.options:type_name -> vtctldata.CreateKeyspaceRequest + 135, // 29: vtadmin.Workflow.workflow:type_name -> vtctldata.Workflow + 136, // 30: vtadmin.ApplySchemaRequest.request:type_name -> vtctldata.ApplySchemaRequest + 137, // 31: vtadmin.CancelSchemaMigrationRequest.request:type_name -> vtctldata.CancelSchemaMigrationRequest + 138, // 32: vtadmin.CleanupSchemaMigrationRequest.request:type_name -> vtctldata.CleanupSchemaMigrationRequest + 139, // 33: vtadmin.CompleteSchemaMigrationRequest.request:type_name -> vtctldata.CompleteSchemaMigrationRequest + 140, // 34: vtadmin.CreateKeyspaceRequest.options:type_name -> vtctldata.CreateKeyspaceRequest 7, // 35: vtadmin.CreateKeyspaceResponse.keyspace:type_name -> vtadmin.Keyspace - 138, // 36: vtadmin.CreateShardRequest.options:type_name -> vtctldata.CreateShardRequest - 139, // 37: vtadmin.DeleteKeyspaceRequest.options:type_name -> vtctldata.DeleteKeyspaceRequest - 140, // 38: vtadmin.DeleteShardsRequest.options:type_name -> vtctldata.DeleteShardsRequest - 141, // 39: vtadmin.DeleteTabletRequest.alias:type_name -> topodata.TabletAlias + 141, // 36: vtadmin.CreateShardRequest.options:type_name -> vtctldata.CreateShardRequest + 142, // 37: vtadmin.DeleteKeyspaceRequest.options:type_name -> vtctldata.DeleteKeyspaceRequest + 143, // 38: vtadmin.DeleteShardsRequest.options:type_name -> vtctldata.DeleteShardsRequest + 144, // 39: vtadmin.DeleteTabletRequest.alias:type_name -> topodata.TabletAlias 1, // 40: vtadmin.DeleteTabletResponse.cluster:type_name -> vtadmin.Cluster - 142, // 41: vtadmin.EmergencyFailoverShardRequest.options:type_name -> vtctldata.EmergencyReparentShardRequest + 145, // 41: vtadmin.EmergencyFailoverShardRequest.options:type_name -> vtctldata.EmergencyReparentShardRequest 1, // 42: vtadmin.EmergencyFailoverShardResponse.cluster:type_name -> vtadmin.Cluster - 141, // 43: vtadmin.EmergencyFailoverShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 143, // 44: vtadmin.EmergencyFailoverShardResponse.events:type_name -> logutil.Event + 144, // 43: vtadmin.EmergencyFailoverShardResponse.promoted_primary:type_name -> topodata.TabletAlias + 146, // 44: vtadmin.EmergencyFailoverShardResponse.events:type_name -> logutil.Event 58, // 45: vtadmin.FindSchemaRequest.table_size_options:type_name -> vtadmin.GetSchemaTableSizeOptions - 144, // 46: vtadmin.GetBackupsRequest.request_options:type_name -> vtctldata.GetBackupsRequest + 147, // 46: vtadmin.GetBackupsRequest.request_options:type_name -> vtctldata.GetBackupsRequest 2, // 47: vtadmin.GetBackupsResponse.backups:type_name -> vtadmin.ClusterBackup 4, // 48: vtadmin.GetCellInfosResponse.cell_infos:type_name -> vtadmin.ClusterCellInfo 3, // 49: vtadmin.GetCellsAliasesResponse.aliases:type_name -> vtadmin.ClusterCellsAliases 1, // 50: vtadmin.GetClustersResponse.clusters:type_name -> vtadmin.Cluster - 141, // 51: vtadmin.GetFullStatusRequest.alias:type_name -> topodata.TabletAlias + 144, // 51: vtadmin.GetFullStatusRequest.alias:type_name -> topodata.TabletAlias 15, // 52: vtadmin.GetGatesResponse.gates:type_name -> vtadmin.VTGate 7, // 53: vtadmin.GetKeyspacesResponse.keyspaces:type_name -> vtadmin.Keyspace 58, // 54: vtadmin.GetSchemaRequest.table_size_options:type_name -> vtadmin.GetSchemaTableSizeOptions 58, // 55: vtadmin.GetSchemasRequest.table_size_options:type_name -> vtadmin.GetSchemaTableSizeOptions 8, // 56: vtadmin.GetSchemasResponse.schemas:type_name -> vtadmin.Schema - 116, // 57: vtadmin.GetSchemaMigrationsRequest.cluster_requests:type_name -> vtadmin.GetSchemaMigrationsRequest.ClusterRequest + 119, // 57: vtadmin.GetSchemaMigrationsRequest.cluster_requests:type_name -> vtadmin.GetSchemaMigrationsRequest.ClusterRequest 9, // 58: vtadmin.GetSchemaMigrationsResponse.schema_migrations:type_name -> vtadmin.SchemaMigration 5, // 59: vtadmin.GetShardReplicationPositionsResponse.replication_positions:type_name -> vtadmin.ClusterShardReplicationPosition - 117, // 60: vtadmin.GetSrvKeyspacesResponse.srv_keyspaces:type_name -> vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry + 120, // 60: vtadmin.GetSrvKeyspacesResponse.srv_keyspaces:type_name -> vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry 11, // 61: vtadmin.GetSrvVSchemasResponse.srv_v_schemas:type_name -> vtadmin.SrvVSchema - 141, // 62: vtadmin.GetTabletRequest.alias:type_name -> topodata.TabletAlias + 144, // 62: vtadmin.GetTabletRequest.alias:type_name -> topodata.TabletAlias 12, // 63: vtadmin.GetTabletsResponse.tablets:type_name -> vtadmin.Tablet 13, // 64: vtadmin.GetVSchemasResponse.v_schemas:type_name -> vtadmin.VSchema 14, // 65: vtadmin.GetVtctldsResponse.vtctlds:type_name -> vtadmin.Vtctld - 118, // 66: vtadmin.GetWorkflowsResponse.workflows_by_cluster:type_name -> vtadmin.GetWorkflowsResponse.WorkflowsByClusterEntry - 145, // 67: vtadmin.LaunchSchemaMigrationRequest.request:type_name -> vtctldata.LaunchSchemaMigrationRequest - 141, // 68: vtadmin.PingTabletRequest.alias:type_name -> topodata.TabletAlias + 121, // 66: vtadmin.GetWorkflowsResponse.workflows_by_cluster:type_name -> vtadmin.GetWorkflowsResponse.WorkflowsByClusterEntry + 148, // 67: vtadmin.LaunchSchemaMigrationRequest.request:type_name -> vtctldata.LaunchSchemaMigrationRequest + 144, // 68: vtadmin.PingTabletRequest.alias:type_name -> topodata.TabletAlias 1, // 69: vtadmin.PingTabletResponse.cluster:type_name -> vtadmin.Cluster - 146, // 70: vtadmin.PlannedFailoverShardRequest.options:type_name -> vtctldata.PlannedReparentShardRequest + 149, // 70: vtadmin.PlannedFailoverShardRequest.options:type_name -> vtctldata.PlannedReparentShardRequest 1, // 71: vtadmin.PlannedFailoverShardResponse.cluster:type_name -> vtadmin.Cluster - 141, // 72: vtadmin.PlannedFailoverShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 143, // 73: vtadmin.PlannedFailoverShardResponse.events:type_name -> logutil.Event - 141, // 74: vtadmin.RefreshStateRequest.alias:type_name -> topodata.TabletAlias + 144, // 72: vtadmin.PlannedFailoverShardResponse.promoted_primary:type_name -> topodata.TabletAlias + 146, // 73: vtadmin.PlannedFailoverShardResponse.events:type_name -> logutil.Event + 144, // 74: vtadmin.RefreshStateRequest.alias:type_name -> topodata.TabletAlias 1, // 75: vtadmin.RefreshStateResponse.cluster:type_name -> vtadmin.Cluster - 141, // 76: vtadmin.ReloadSchemasRequest.tablets:type_name -> topodata.TabletAlias - 119, // 77: vtadmin.ReloadSchemasResponse.keyspace_results:type_name -> vtadmin.ReloadSchemasResponse.KeyspaceResult - 120, // 78: vtadmin.ReloadSchemasResponse.shard_results:type_name -> vtadmin.ReloadSchemasResponse.ShardResult - 121, // 79: vtadmin.ReloadSchemasResponse.tablet_results:type_name -> vtadmin.ReloadSchemasResponse.TabletResult - 143, // 80: vtadmin.ReloadSchemaShardResponse.events:type_name -> logutil.Event - 141, // 81: vtadmin.RefreshTabletReplicationSourceRequest.alias:type_name -> topodata.TabletAlias - 141, // 82: vtadmin.RefreshTabletReplicationSourceResponse.primary:type_name -> topodata.TabletAlias + 144, // 76: vtadmin.ReloadSchemasRequest.tablets:type_name -> topodata.TabletAlias + 122, // 77: vtadmin.ReloadSchemasResponse.keyspace_results:type_name -> vtadmin.ReloadSchemasResponse.KeyspaceResult + 123, // 78: vtadmin.ReloadSchemasResponse.shard_results:type_name -> vtadmin.ReloadSchemasResponse.ShardResult + 124, // 79: vtadmin.ReloadSchemasResponse.tablet_results:type_name -> vtadmin.ReloadSchemasResponse.TabletResult + 146, // 80: vtadmin.ReloadSchemaShardResponse.events:type_name -> logutil.Event + 144, // 81: vtadmin.RefreshTabletReplicationSourceRequest.alias:type_name -> topodata.TabletAlias + 144, // 82: vtadmin.RefreshTabletReplicationSourceResponse.primary:type_name -> topodata.TabletAlias 1, // 83: vtadmin.RefreshTabletReplicationSourceResponse.cluster:type_name -> vtadmin.Cluster - 147, // 84: vtadmin.RetrySchemaMigrationRequest.request:type_name -> vtctldata.RetrySchemaMigrationRequest - 141, // 85: vtadmin.RunHealthCheckRequest.alias:type_name -> topodata.TabletAlias + 150, // 84: vtadmin.RetrySchemaMigrationRequest.request:type_name -> vtctldata.RetrySchemaMigrationRequest + 144, // 85: vtadmin.RunHealthCheckRequest.alias:type_name -> topodata.TabletAlias 1, // 86: vtadmin.RunHealthCheckResponse.cluster:type_name -> vtadmin.Cluster - 141, // 87: vtadmin.SetReadOnlyRequest.alias:type_name -> topodata.TabletAlias - 141, // 88: vtadmin.SetReadWriteRequest.alias:type_name -> topodata.TabletAlias - 141, // 89: vtadmin.StartReplicationRequest.alias:type_name -> topodata.TabletAlias + 144, // 87: vtadmin.SetReadOnlyRequest.alias:type_name -> topodata.TabletAlias + 144, // 88: vtadmin.SetReadWriteRequest.alias:type_name -> topodata.TabletAlias + 144, // 89: vtadmin.StartReplicationRequest.alias:type_name -> topodata.TabletAlias 1, // 90: vtadmin.StartReplicationResponse.cluster:type_name -> vtadmin.Cluster - 141, // 91: vtadmin.StopReplicationRequest.alias:type_name -> topodata.TabletAlias + 144, // 91: vtadmin.StopReplicationRequest.alias:type_name -> topodata.TabletAlias 1, // 92: vtadmin.StopReplicationResponse.cluster:type_name -> vtadmin.Cluster - 141, // 93: vtadmin.TabletExternallyPromotedRequest.alias:type_name -> topodata.TabletAlias + 144, // 93: vtadmin.TabletExternallyPromotedRequest.alias:type_name -> topodata.TabletAlias 1, // 94: vtadmin.TabletExternallyPromotedResponse.cluster:type_name -> vtadmin.Cluster - 141, // 95: vtadmin.TabletExternallyPromotedResponse.new_primary:type_name -> topodata.TabletAlias - 141, // 96: vtadmin.TabletExternallyPromotedResponse.old_primary:type_name -> topodata.TabletAlias - 141, // 97: vtadmin.TabletExternallyReparentedRequest.alias:type_name -> topodata.TabletAlias - 148, // 98: vtadmin.ClusterCellsAliases.AliasesEntry.value:type_name -> topodata.CellsAlias - 128, // 99: vtadmin.Keyspace.ShardsEntry.value:type_name -> vtctldata.Shard - 114, // 100: vtadmin.Schema.TableSizesEntry.value:type_name -> vtadmin.Schema.TableSize - 115, // 101: vtadmin.Schema.TableSize.by_shard:type_name -> vtadmin.Schema.TableSize.ByShardEntry - 113, // 102: vtadmin.Schema.TableSize.ByShardEntry.value:type_name -> vtadmin.Schema.ShardTableSize - 149, // 103: vtadmin.GetSchemaMigrationsRequest.ClusterRequest.request:type_name -> vtctldata.GetSchemaMigrationsRequest - 150, // 104: vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry.value:type_name -> vtctldata.GetSrvKeyspacesResponse + 144, // 95: vtadmin.TabletExternallyPromotedResponse.new_primary:type_name -> topodata.TabletAlias + 144, // 96: vtadmin.TabletExternallyPromotedResponse.old_primary:type_name -> topodata.TabletAlias + 144, // 97: vtadmin.TabletExternallyReparentedRequest.alias:type_name -> topodata.TabletAlias + 151, // 98: vtadmin.ClusterCellsAliases.AliasesEntry.value:type_name -> topodata.CellsAlias + 131, // 99: vtadmin.Keyspace.ShardsEntry.value:type_name -> vtctldata.Shard + 117, // 100: vtadmin.Schema.TableSizesEntry.value:type_name -> vtadmin.Schema.TableSize + 118, // 101: vtadmin.Schema.TableSize.by_shard:type_name -> vtadmin.Schema.TableSize.ByShardEntry + 116, // 102: vtadmin.Schema.TableSize.ByShardEntry.value:type_name -> vtadmin.Schema.ShardTableSize + 152, // 103: vtadmin.GetSchemaMigrationsRequest.ClusterRequest.request:type_name -> vtctldata.GetSchemaMigrationsRequest + 153, // 104: vtadmin.GetSrvKeyspacesResponse.SrvKeyspacesEntry.value:type_name -> vtctldata.GetSrvKeyspacesResponse 6, // 105: vtadmin.GetWorkflowsResponse.WorkflowsByClusterEntry.value:type_name -> vtadmin.ClusterWorkflows 7, // 106: vtadmin.ReloadSchemasResponse.KeyspaceResult.keyspace:type_name -> vtadmin.Keyspace - 143, // 107: vtadmin.ReloadSchemasResponse.KeyspaceResult.events:type_name -> logutil.Event + 146, // 107: vtadmin.ReloadSchemasResponse.KeyspaceResult.events:type_name -> logutil.Event 10, // 108: vtadmin.ReloadSchemasResponse.ShardResult.shard:type_name -> vtadmin.Shard - 143, // 109: vtadmin.ReloadSchemasResponse.ShardResult.events:type_name -> logutil.Event + 146, // 109: vtadmin.ReloadSchemasResponse.ShardResult.events:type_name -> logutil.Event 12, // 110: vtadmin.ReloadSchemasResponse.TabletResult.tablet:type_name -> vtadmin.Tablet 17, // 111: vtadmin.VTAdmin.ApplySchema:input_type -> vtadmin.ApplySchemaRequest 18, // 112: vtadmin.VTAdmin.CancelSchemaMigration:input_type -> vtadmin.CancelSchemaMigrationRequest @@ -8304,90 +8535,96 @@ var file_vtadmin_proto_depIdxs = []int32{ 64, // 142: vtadmin.VTAdmin.GetVSchemas:input_type -> vtadmin.GetVSchemasRequest 66, // 143: vtadmin.VTAdmin.GetVtctlds:input_type -> vtadmin.GetVtctldsRequest 68, // 144: vtadmin.VTAdmin.GetWorkflow:input_type -> vtadmin.GetWorkflowRequest - 69, // 145: vtadmin.VTAdmin.GetWorkflows:input_type -> vtadmin.GetWorkflowsRequest - 71, // 146: vtadmin.VTAdmin.LaunchSchemaMigration:input_type -> vtadmin.LaunchSchemaMigrationRequest - 72, // 147: vtadmin.VTAdmin.PingTablet:input_type -> vtadmin.PingTabletRequest - 74, // 148: vtadmin.VTAdmin.PlannedFailoverShard:input_type -> vtadmin.PlannedFailoverShardRequest - 76, // 149: vtadmin.VTAdmin.RebuildKeyspaceGraph:input_type -> vtadmin.RebuildKeyspaceGraphRequest - 78, // 150: vtadmin.VTAdmin.RefreshState:input_type -> vtadmin.RefreshStateRequest - 84, // 151: vtadmin.VTAdmin.RefreshTabletReplicationSource:input_type -> vtadmin.RefreshTabletReplicationSourceRequest - 80, // 152: vtadmin.VTAdmin.ReloadSchemas:input_type -> vtadmin.ReloadSchemasRequest - 82, // 153: vtadmin.VTAdmin.ReloadSchemaShard:input_type -> vtadmin.ReloadSchemaShardRequest - 86, // 154: vtadmin.VTAdmin.RemoveKeyspaceCell:input_type -> vtadmin.RemoveKeyspaceCellRequest - 88, // 155: vtadmin.VTAdmin.RetrySchemaMigration:input_type -> vtadmin.RetrySchemaMigrationRequest - 89, // 156: vtadmin.VTAdmin.RunHealthCheck:input_type -> vtadmin.RunHealthCheckRequest - 91, // 157: vtadmin.VTAdmin.SetReadOnly:input_type -> vtadmin.SetReadOnlyRequest - 93, // 158: vtadmin.VTAdmin.SetReadWrite:input_type -> vtadmin.SetReadWriteRequest - 95, // 159: vtadmin.VTAdmin.StartReplication:input_type -> vtadmin.StartReplicationRequest - 97, // 160: vtadmin.VTAdmin.StopReplication:input_type -> vtadmin.StopReplicationRequest - 99, // 161: vtadmin.VTAdmin.TabletExternallyPromoted:input_type -> vtadmin.TabletExternallyPromotedRequest - 102, // 162: vtadmin.VTAdmin.Validate:input_type -> vtadmin.ValidateRequest - 103, // 163: vtadmin.VTAdmin.ValidateKeyspace:input_type -> vtadmin.ValidateKeyspaceRequest - 104, // 164: vtadmin.VTAdmin.ValidateSchemaKeyspace:input_type -> vtadmin.ValidateSchemaKeyspaceRequest - 105, // 165: vtadmin.VTAdmin.ValidateShard:input_type -> vtadmin.ValidateShardRequest - 106, // 166: vtadmin.VTAdmin.ValidateVersionKeyspace:input_type -> vtadmin.ValidateVersionKeyspaceRequest - 107, // 167: vtadmin.VTAdmin.ValidateVersionShard:input_type -> vtadmin.ValidateVersionShardRequest - 108, // 168: vtadmin.VTAdmin.VTExplain:input_type -> vtadmin.VTExplainRequest - 151, // 169: vtadmin.VTAdmin.ApplySchema:output_type -> vtctldata.ApplySchemaResponse - 152, // 170: vtadmin.VTAdmin.CancelSchemaMigration:output_type -> vtctldata.CancelSchemaMigrationResponse - 153, // 171: vtadmin.VTAdmin.CleanupSchemaMigration:output_type -> vtctldata.CleanupSchemaMigrationResponse - 154, // 172: vtadmin.VTAdmin.CompleteSchemaMigration:output_type -> vtctldata.CompleteSchemaMigrationResponse - 22, // 173: vtadmin.VTAdmin.CreateKeyspace:output_type -> vtadmin.CreateKeyspaceResponse - 155, // 174: vtadmin.VTAdmin.CreateShard:output_type -> vtctldata.CreateShardResponse - 156, // 175: vtadmin.VTAdmin.DeleteKeyspace:output_type -> vtctldata.DeleteKeyspaceResponse - 157, // 176: vtadmin.VTAdmin.DeleteShards:output_type -> vtctldata.DeleteShardsResponse - 27, // 177: vtadmin.VTAdmin.DeleteTablet:output_type -> vtadmin.DeleteTabletResponse - 29, // 178: vtadmin.VTAdmin.EmergencyFailoverShard:output_type -> vtadmin.EmergencyFailoverShardResponse - 8, // 179: vtadmin.VTAdmin.FindSchema:output_type -> vtadmin.Schema - 32, // 180: vtadmin.VTAdmin.GetBackups:output_type -> vtadmin.GetBackupsResponse - 34, // 181: vtadmin.VTAdmin.GetCellInfos:output_type -> vtadmin.GetCellInfosResponse - 36, // 182: vtadmin.VTAdmin.GetCellsAliases:output_type -> vtadmin.GetCellsAliasesResponse - 38, // 183: vtadmin.VTAdmin.GetClusters:output_type -> vtadmin.GetClustersResponse - 158, // 184: vtadmin.VTAdmin.GetFullStatus:output_type -> vtctldata.GetFullStatusResponse - 41, // 185: vtadmin.VTAdmin.GetGates:output_type -> vtadmin.GetGatesResponse - 7, // 186: vtadmin.VTAdmin.GetKeyspace:output_type -> vtadmin.Keyspace - 44, // 187: vtadmin.VTAdmin.GetKeyspaces:output_type -> vtadmin.GetKeyspacesResponse - 8, // 188: vtadmin.VTAdmin.GetSchema:output_type -> vtadmin.Schema - 47, // 189: vtadmin.VTAdmin.GetSchemas:output_type -> vtadmin.GetSchemasResponse - 49, // 190: vtadmin.VTAdmin.GetSchemaMigrations:output_type -> vtadmin.GetSchemaMigrationsResponse - 51, // 191: vtadmin.VTAdmin.GetShardReplicationPositions:output_type -> vtadmin.GetShardReplicationPositionsResponse - 150, // 192: vtadmin.VTAdmin.GetSrvKeyspace:output_type -> vtctldata.GetSrvKeyspacesResponse - 54, // 193: vtadmin.VTAdmin.GetSrvKeyspaces:output_type -> vtadmin.GetSrvKeyspacesResponse - 11, // 194: vtadmin.VTAdmin.GetSrvVSchema:output_type -> vtadmin.SrvVSchema - 57, // 195: vtadmin.VTAdmin.GetSrvVSchemas:output_type -> vtadmin.GetSrvVSchemasResponse - 12, // 196: vtadmin.VTAdmin.GetTablet:output_type -> vtadmin.Tablet - 61, // 197: vtadmin.VTAdmin.GetTablets:output_type -> vtadmin.GetTabletsResponse - 159, // 198: vtadmin.VTAdmin.GetTopologyPath:output_type -> vtctldata.GetTopologyPathResponse - 13, // 199: vtadmin.VTAdmin.GetVSchema:output_type -> vtadmin.VSchema - 65, // 200: vtadmin.VTAdmin.GetVSchemas:output_type -> vtadmin.GetVSchemasResponse - 67, // 201: vtadmin.VTAdmin.GetVtctlds:output_type -> vtadmin.GetVtctldsResponse - 16, // 202: vtadmin.VTAdmin.GetWorkflow:output_type -> vtadmin.Workflow - 70, // 203: vtadmin.VTAdmin.GetWorkflows:output_type -> vtadmin.GetWorkflowsResponse - 160, // 204: vtadmin.VTAdmin.LaunchSchemaMigration:output_type -> vtctldata.LaunchSchemaMigrationResponse - 73, // 205: vtadmin.VTAdmin.PingTablet:output_type -> vtadmin.PingTabletResponse - 75, // 206: vtadmin.VTAdmin.PlannedFailoverShard:output_type -> vtadmin.PlannedFailoverShardResponse - 77, // 207: vtadmin.VTAdmin.RebuildKeyspaceGraph:output_type -> vtadmin.RebuildKeyspaceGraphResponse - 79, // 208: vtadmin.VTAdmin.RefreshState:output_type -> vtadmin.RefreshStateResponse - 85, // 209: vtadmin.VTAdmin.RefreshTabletReplicationSource:output_type -> vtadmin.RefreshTabletReplicationSourceResponse - 81, // 210: vtadmin.VTAdmin.ReloadSchemas:output_type -> vtadmin.ReloadSchemasResponse - 83, // 211: vtadmin.VTAdmin.ReloadSchemaShard:output_type -> vtadmin.ReloadSchemaShardResponse - 87, // 212: vtadmin.VTAdmin.RemoveKeyspaceCell:output_type -> vtadmin.RemoveKeyspaceCellResponse - 161, // 213: vtadmin.VTAdmin.RetrySchemaMigration:output_type -> vtctldata.RetrySchemaMigrationResponse - 90, // 214: vtadmin.VTAdmin.RunHealthCheck:output_type -> vtadmin.RunHealthCheckResponse - 92, // 215: vtadmin.VTAdmin.SetReadOnly:output_type -> vtadmin.SetReadOnlyResponse - 94, // 216: vtadmin.VTAdmin.SetReadWrite:output_type -> vtadmin.SetReadWriteResponse - 96, // 217: vtadmin.VTAdmin.StartReplication:output_type -> vtadmin.StartReplicationResponse - 98, // 218: vtadmin.VTAdmin.StopReplication:output_type -> vtadmin.StopReplicationResponse - 100, // 219: vtadmin.VTAdmin.TabletExternallyPromoted:output_type -> vtadmin.TabletExternallyPromotedResponse - 162, // 220: vtadmin.VTAdmin.Validate:output_type -> vtctldata.ValidateResponse - 163, // 221: vtadmin.VTAdmin.ValidateKeyspace:output_type -> vtctldata.ValidateKeyspaceResponse - 164, // 222: vtadmin.VTAdmin.ValidateSchemaKeyspace:output_type -> vtctldata.ValidateSchemaKeyspaceResponse - 165, // 223: vtadmin.VTAdmin.ValidateShard:output_type -> vtctldata.ValidateShardResponse - 166, // 224: vtadmin.VTAdmin.ValidateVersionKeyspace:output_type -> vtctldata.ValidateVersionKeyspaceResponse - 167, // 225: vtadmin.VTAdmin.ValidateVersionShard:output_type -> vtctldata.ValidateVersionShardResponse - 109, // 226: vtadmin.VTAdmin.VTExplain:output_type -> vtadmin.VTExplainResponse - 169, // [169:227] is the sub-list for method output_type - 111, // [111:169] is the sub-list for method input_type + 72, // 145: vtadmin.VTAdmin.GetWorkflows:input_type -> vtadmin.GetWorkflowsRequest + 69, // 146: vtadmin.VTAdmin.GetWorkflowStatus:input_type -> vtadmin.GetWorkflowStatusRequest + 70, // 147: vtadmin.VTAdmin.StartWorkflow:input_type -> vtadmin.StartWorkflowRequest + 71, // 148: vtadmin.VTAdmin.StopWorkflow:input_type -> vtadmin.StopWorkflowRequest + 74, // 149: vtadmin.VTAdmin.LaunchSchemaMigration:input_type -> vtadmin.LaunchSchemaMigrationRequest + 75, // 150: vtadmin.VTAdmin.PingTablet:input_type -> vtadmin.PingTabletRequest + 77, // 151: vtadmin.VTAdmin.PlannedFailoverShard:input_type -> vtadmin.PlannedFailoverShardRequest + 79, // 152: vtadmin.VTAdmin.RebuildKeyspaceGraph:input_type -> vtadmin.RebuildKeyspaceGraphRequest + 81, // 153: vtadmin.VTAdmin.RefreshState:input_type -> vtadmin.RefreshStateRequest + 87, // 154: vtadmin.VTAdmin.RefreshTabletReplicationSource:input_type -> vtadmin.RefreshTabletReplicationSourceRequest + 83, // 155: vtadmin.VTAdmin.ReloadSchemas:input_type -> vtadmin.ReloadSchemasRequest + 85, // 156: vtadmin.VTAdmin.ReloadSchemaShard:input_type -> vtadmin.ReloadSchemaShardRequest + 89, // 157: vtadmin.VTAdmin.RemoveKeyspaceCell:input_type -> vtadmin.RemoveKeyspaceCellRequest + 91, // 158: vtadmin.VTAdmin.RetrySchemaMigration:input_type -> vtadmin.RetrySchemaMigrationRequest + 92, // 159: vtadmin.VTAdmin.RunHealthCheck:input_type -> vtadmin.RunHealthCheckRequest + 94, // 160: vtadmin.VTAdmin.SetReadOnly:input_type -> vtadmin.SetReadOnlyRequest + 96, // 161: vtadmin.VTAdmin.SetReadWrite:input_type -> vtadmin.SetReadWriteRequest + 98, // 162: vtadmin.VTAdmin.StartReplication:input_type -> vtadmin.StartReplicationRequest + 100, // 163: vtadmin.VTAdmin.StopReplication:input_type -> vtadmin.StopReplicationRequest + 102, // 164: vtadmin.VTAdmin.TabletExternallyPromoted:input_type -> vtadmin.TabletExternallyPromotedRequest + 105, // 165: vtadmin.VTAdmin.Validate:input_type -> vtadmin.ValidateRequest + 106, // 166: vtadmin.VTAdmin.ValidateKeyspace:input_type -> vtadmin.ValidateKeyspaceRequest + 107, // 167: vtadmin.VTAdmin.ValidateSchemaKeyspace:input_type -> vtadmin.ValidateSchemaKeyspaceRequest + 108, // 168: vtadmin.VTAdmin.ValidateShard:input_type -> vtadmin.ValidateShardRequest + 109, // 169: vtadmin.VTAdmin.ValidateVersionKeyspace:input_type -> vtadmin.ValidateVersionKeyspaceRequest + 110, // 170: vtadmin.VTAdmin.ValidateVersionShard:input_type -> vtadmin.ValidateVersionShardRequest + 111, // 171: vtadmin.VTAdmin.VTExplain:input_type -> vtadmin.VTExplainRequest + 154, // 172: vtadmin.VTAdmin.ApplySchema:output_type -> vtctldata.ApplySchemaResponse + 155, // 173: vtadmin.VTAdmin.CancelSchemaMigration:output_type -> vtctldata.CancelSchemaMigrationResponse + 156, // 174: vtadmin.VTAdmin.CleanupSchemaMigration:output_type -> vtctldata.CleanupSchemaMigrationResponse + 157, // 175: vtadmin.VTAdmin.CompleteSchemaMigration:output_type -> vtctldata.CompleteSchemaMigrationResponse + 22, // 176: vtadmin.VTAdmin.CreateKeyspace:output_type -> vtadmin.CreateKeyspaceResponse + 158, // 177: vtadmin.VTAdmin.CreateShard:output_type -> vtctldata.CreateShardResponse + 159, // 178: vtadmin.VTAdmin.DeleteKeyspace:output_type -> vtctldata.DeleteKeyspaceResponse + 160, // 179: vtadmin.VTAdmin.DeleteShards:output_type -> vtctldata.DeleteShardsResponse + 27, // 180: vtadmin.VTAdmin.DeleteTablet:output_type -> vtadmin.DeleteTabletResponse + 29, // 181: vtadmin.VTAdmin.EmergencyFailoverShard:output_type -> vtadmin.EmergencyFailoverShardResponse + 8, // 182: vtadmin.VTAdmin.FindSchema:output_type -> vtadmin.Schema + 32, // 183: vtadmin.VTAdmin.GetBackups:output_type -> vtadmin.GetBackupsResponse + 34, // 184: vtadmin.VTAdmin.GetCellInfos:output_type -> vtadmin.GetCellInfosResponse + 36, // 185: vtadmin.VTAdmin.GetCellsAliases:output_type -> vtadmin.GetCellsAliasesResponse + 38, // 186: vtadmin.VTAdmin.GetClusters:output_type -> vtadmin.GetClustersResponse + 161, // 187: vtadmin.VTAdmin.GetFullStatus:output_type -> vtctldata.GetFullStatusResponse + 41, // 188: vtadmin.VTAdmin.GetGates:output_type -> vtadmin.GetGatesResponse + 7, // 189: vtadmin.VTAdmin.GetKeyspace:output_type -> vtadmin.Keyspace + 44, // 190: vtadmin.VTAdmin.GetKeyspaces:output_type -> vtadmin.GetKeyspacesResponse + 8, // 191: vtadmin.VTAdmin.GetSchema:output_type -> vtadmin.Schema + 47, // 192: vtadmin.VTAdmin.GetSchemas:output_type -> vtadmin.GetSchemasResponse + 49, // 193: vtadmin.VTAdmin.GetSchemaMigrations:output_type -> vtadmin.GetSchemaMigrationsResponse + 51, // 194: vtadmin.VTAdmin.GetShardReplicationPositions:output_type -> vtadmin.GetShardReplicationPositionsResponse + 153, // 195: vtadmin.VTAdmin.GetSrvKeyspace:output_type -> vtctldata.GetSrvKeyspacesResponse + 54, // 196: vtadmin.VTAdmin.GetSrvKeyspaces:output_type -> vtadmin.GetSrvKeyspacesResponse + 11, // 197: vtadmin.VTAdmin.GetSrvVSchema:output_type -> vtadmin.SrvVSchema + 57, // 198: vtadmin.VTAdmin.GetSrvVSchemas:output_type -> vtadmin.GetSrvVSchemasResponse + 12, // 199: vtadmin.VTAdmin.GetTablet:output_type -> vtadmin.Tablet + 61, // 200: vtadmin.VTAdmin.GetTablets:output_type -> vtadmin.GetTabletsResponse + 162, // 201: vtadmin.VTAdmin.GetTopologyPath:output_type -> vtctldata.GetTopologyPathResponse + 13, // 202: vtadmin.VTAdmin.GetVSchema:output_type -> vtadmin.VSchema + 65, // 203: vtadmin.VTAdmin.GetVSchemas:output_type -> vtadmin.GetVSchemasResponse + 67, // 204: vtadmin.VTAdmin.GetVtctlds:output_type -> vtadmin.GetVtctldsResponse + 16, // 205: vtadmin.VTAdmin.GetWorkflow:output_type -> vtadmin.Workflow + 73, // 206: vtadmin.VTAdmin.GetWorkflows:output_type -> vtadmin.GetWorkflowsResponse + 163, // 207: vtadmin.VTAdmin.GetWorkflowStatus:output_type -> vtctldata.WorkflowStatusResponse + 164, // 208: vtadmin.VTAdmin.StartWorkflow:output_type -> vtctldata.WorkflowUpdateResponse + 164, // 209: vtadmin.VTAdmin.StopWorkflow:output_type -> vtctldata.WorkflowUpdateResponse + 165, // 210: vtadmin.VTAdmin.LaunchSchemaMigration:output_type -> vtctldata.LaunchSchemaMigrationResponse + 76, // 211: vtadmin.VTAdmin.PingTablet:output_type -> vtadmin.PingTabletResponse + 78, // 212: vtadmin.VTAdmin.PlannedFailoverShard:output_type -> vtadmin.PlannedFailoverShardResponse + 80, // 213: vtadmin.VTAdmin.RebuildKeyspaceGraph:output_type -> vtadmin.RebuildKeyspaceGraphResponse + 82, // 214: vtadmin.VTAdmin.RefreshState:output_type -> vtadmin.RefreshStateResponse + 88, // 215: vtadmin.VTAdmin.RefreshTabletReplicationSource:output_type -> vtadmin.RefreshTabletReplicationSourceResponse + 84, // 216: vtadmin.VTAdmin.ReloadSchemas:output_type -> vtadmin.ReloadSchemasResponse + 86, // 217: vtadmin.VTAdmin.ReloadSchemaShard:output_type -> vtadmin.ReloadSchemaShardResponse + 90, // 218: vtadmin.VTAdmin.RemoveKeyspaceCell:output_type -> vtadmin.RemoveKeyspaceCellResponse + 166, // 219: vtadmin.VTAdmin.RetrySchemaMigration:output_type -> vtctldata.RetrySchemaMigrationResponse + 93, // 220: vtadmin.VTAdmin.RunHealthCheck:output_type -> vtadmin.RunHealthCheckResponse + 95, // 221: vtadmin.VTAdmin.SetReadOnly:output_type -> vtadmin.SetReadOnlyResponse + 97, // 222: vtadmin.VTAdmin.SetReadWrite:output_type -> vtadmin.SetReadWriteResponse + 99, // 223: vtadmin.VTAdmin.StartReplication:output_type -> vtadmin.StartReplicationResponse + 101, // 224: vtadmin.VTAdmin.StopReplication:output_type -> vtadmin.StopReplicationResponse + 103, // 225: vtadmin.VTAdmin.TabletExternallyPromoted:output_type -> vtadmin.TabletExternallyPromotedResponse + 167, // 226: vtadmin.VTAdmin.Validate:output_type -> vtctldata.ValidateResponse + 168, // 227: vtadmin.VTAdmin.ValidateKeyspace:output_type -> vtctldata.ValidateKeyspaceResponse + 169, // 228: vtadmin.VTAdmin.ValidateSchemaKeyspace:output_type -> vtctldata.ValidateSchemaKeyspaceResponse + 170, // 229: vtadmin.VTAdmin.ValidateShard:output_type -> vtctldata.ValidateShardResponse + 171, // 230: vtadmin.VTAdmin.ValidateVersionKeyspace:output_type -> vtctldata.ValidateVersionKeyspaceResponse + 172, // 231: vtadmin.VTAdmin.ValidateVersionShard:output_type -> vtctldata.ValidateVersionShardResponse + 112, // 232: vtadmin.VTAdmin.VTExplain:output_type -> vtadmin.VTExplainResponse + 172, // [172:233] is the sub-list for method output_type + 111, // [111:172] is the sub-list for method input_type 111, // [111:111] is the sub-list for extension type_name 111, // [111:111] is the sub-list for extension extendee 0, // [0:111] is the sub-list for field type_name @@ -9216,7 +9453,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[68].Exporter = func(v any, i int) any { - switch v := v.(*GetWorkflowsRequest); i { + switch v := v.(*GetWorkflowStatusRequest); i { case 0: return &v.state case 1: @@ -9228,7 +9465,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[69].Exporter = func(v any, i int) any { - switch v := v.(*GetWorkflowsResponse); i { + switch v := v.(*StartWorkflowRequest); i { case 0: return &v.state case 1: @@ -9240,7 +9477,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[70].Exporter = func(v any, i int) any { - switch v := v.(*LaunchSchemaMigrationRequest); i { + switch v := v.(*StopWorkflowRequest); i { case 0: return &v.state case 1: @@ -9252,7 +9489,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[71].Exporter = func(v any, i int) any { - switch v := v.(*PingTabletRequest); i { + switch v := v.(*GetWorkflowsRequest); i { case 0: return &v.state case 1: @@ -9264,7 +9501,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[72].Exporter = func(v any, i int) any { - switch v := v.(*PingTabletResponse); i { + switch v := v.(*GetWorkflowsResponse); i { case 0: return &v.state case 1: @@ -9276,7 +9513,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[73].Exporter = func(v any, i int) any { - switch v := v.(*PlannedFailoverShardRequest); i { + switch v := v.(*LaunchSchemaMigrationRequest); i { case 0: return &v.state case 1: @@ -9288,7 +9525,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[74].Exporter = func(v any, i int) any { - switch v := v.(*PlannedFailoverShardResponse); i { + switch v := v.(*PingTabletRequest); i { case 0: return &v.state case 1: @@ -9300,7 +9537,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[75].Exporter = func(v any, i int) any { - switch v := v.(*RebuildKeyspaceGraphRequest); i { + switch v := v.(*PingTabletResponse); i { case 0: return &v.state case 1: @@ -9312,7 +9549,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[76].Exporter = func(v any, i int) any { - switch v := v.(*RebuildKeyspaceGraphResponse); i { + switch v := v.(*PlannedFailoverShardRequest); i { case 0: return &v.state case 1: @@ -9324,7 +9561,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[77].Exporter = func(v any, i int) any { - switch v := v.(*RefreshStateRequest); i { + switch v := v.(*PlannedFailoverShardResponse); i { case 0: return &v.state case 1: @@ -9336,7 +9573,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[78].Exporter = func(v any, i int) any { - switch v := v.(*RefreshStateResponse); i { + switch v := v.(*RebuildKeyspaceGraphRequest); i { case 0: return &v.state case 1: @@ -9348,7 +9585,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[79].Exporter = func(v any, i int) any { - switch v := v.(*ReloadSchemasRequest); i { + switch v := v.(*RebuildKeyspaceGraphResponse); i { case 0: return &v.state case 1: @@ -9360,7 +9597,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[80].Exporter = func(v any, i int) any { - switch v := v.(*ReloadSchemasResponse); i { + switch v := v.(*RefreshStateRequest); i { case 0: return &v.state case 1: @@ -9372,7 +9609,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[81].Exporter = func(v any, i int) any { - switch v := v.(*ReloadSchemaShardRequest); i { + switch v := v.(*RefreshStateResponse); i { case 0: return &v.state case 1: @@ -9384,7 +9621,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[82].Exporter = func(v any, i int) any { - switch v := v.(*ReloadSchemaShardResponse); i { + switch v := v.(*ReloadSchemasRequest); i { case 0: return &v.state case 1: @@ -9396,7 +9633,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[83].Exporter = func(v any, i int) any { - switch v := v.(*RefreshTabletReplicationSourceRequest); i { + switch v := v.(*ReloadSchemasResponse); i { case 0: return &v.state case 1: @@ -9408,7 +9645,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[84].Exporter = func(v any, i int) any { - switch v := v.(*RefreshTabletReplicationSourceResponse); i { + switch v := v.(*ReloadSchemaShardRequest); i { case 0: return &v.state case 1: @@ -9420,7 +9657,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[85].Exporter = func(v any, i int) any { - switch v := v.(*RemoveKeyspaceCellRequest); i { + switch v := v.(*ReloadSchemaShardResponse); i { case 0: return &v.state case 1: @@ -9432,7 +9669,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[86].Exporter = func(v any, i int) any { - switch v := v.(*RemoveKeyspaceCellResponse); i { + switch v := v.(*RefreshTabletReplicationSourceRequest); i { case 0: return &v.state case 1: @@ -9444,7 +9681,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[87].Exporter = func(v any, i int) any { - switch v := v.(*RetrySchemaMigrationRequest); i { + switch v := v.(*RefreshTabletReplicationSourceResponse); i { case 0: return &v.state case 1: @@ -9456,7 +9693,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[88].Exporter = func(v any, i int) any { - switch v := v.(*RunHealthCheckRequest); i { + switch v := v.(*RemoveKeyspaceCellRequest); i { case 0: return &v.state case 1: @@ -9468,7 +9705,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[89].Exporter = func(v any, i int) any { - switch v := v.(*RunHealthCheckResponse); i { + switch v := v.(*RemoveKeyspaceCellResponse); i { case 0: return &v.state case 1: @@ -9480,7 +9717,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[90].Exporter = func(v any, i int) any { - switch v := v.(*SetReadOnlyRequest); i { + switch v := v.(*RetrySchemaMigrationRequest); i { case 0: return &v.state case 1: @@ -9492,7 +9729,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[91].Exporter = func(v any, i int) any { - switch v := v.(*SetReadOnlyResponse); i { + switch v := v.(*RunHealthCheckRequest); i { case 0: return &v.state case 1: @@ -9504,7 +9741,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[92].Exporter = func(v any, i int) any { - switch v := v.(*SetReadWriteRequest); i { + switch v := v.(*RunHealthCheckResponse); i { case 0: return &v.state case 1: @@ -9516,7 +9753,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[93].Exporter = func(v any, i int) any { - switch v := v.(*SetReadWriteResponse); i { + switch v := v.(*SetReadOnlyRequest); i { case 0: return &v.state case 1: @@ -9528,7 +9765,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[94].Exporter = func(v any, i int) any { - switch v := v.(*StartReplicationRequest); i { + switch v := v.(*SetReadOnlyResponse); i { case 0: return &v.state case 1: @@ -9540,7 +9777,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[95].Exporter = func(v any, i int) any { - switch v := v.(*StartReplicationResponse); i { + switch v := v.(*SetReadWriteRequest); i { case 0: return &v.state case 1: @@ -9552,7 +9789,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[96].Exporter = func(v any, i int) any { - switch v := v.(*StopReplicationRequest); i { + switch v := v.(*SetReadWriteResponse); i { case 0: return &v.state case 1: @@ -9564,7 +9801,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[97].Exporter = func(v any, i int) any { - switch v := v.(*StopReplicationResponse); i { + switch v := v.(*StartReplicationRequest); i { case 0: return &v.state case 1: @@ -9576,7 +9813,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[98].Exporter = func(v any, i int) any { - switch v := v.(*TabletExternallyPromotedRequest); i { + switch v := v.(*StartReplicationResponse); i { case 0: return &v.state case 1: @@ -9588,7 +9825,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[99].Exporter = func(v any, i int) any { - switch v := v.(*TabletExternallyPromotedResponse); i { + switch v := v.(*StopReplicationRequest); i { case 0: return &v.state case 1: @@ -9600,7 +9837,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[100].Exporter = func(v any, i int) any { - switch v := v.(*TabletExternallyReparentedRequest); i { + switch v := v.(*StopReplicationResponse); i { case 0: return &v.state case 1: @@ -9612,7 +9849,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[101].Exporter = func(v any, i int) any { - switch v := v.(*ValidateRequest); i { + switch v := v.(*TabletExternallyPromotedRequest); i { case 0: return &v.state case 1: @@ -9624,7 +9861,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[102].Exporter = func(v any, i int) any { - switch v := v.(*ValidateKeyspaceRequest); i { + switch v := v.(*TabletExternallyPromotedResponse); i { case 0: return &v.state case 1: @@ -9636,7 +9873,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[103].Exporter = func(v any, i int) any { - switch v := v.(*ValidateSchemaKeyspaceRequest); i { + switch v := v.(*TabletExternallyReparentedRequest); i { case 0: return &v.state case 1: @@ -9648,7 +9885,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[104].Exporter = func(v any, i int) any { - switch v := v.(*ValidateShardRequest); i { + switch v := v.(*ValidateRequest); i { case 0: return &v.state case 1: @@ -9660,7 +9897,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[105].Exporter = func(v any, i int) any { - switch v := v.(*ValidateVersionKeyspaceRequest); i { + switch v := v.(*ValidateKeyspaceRequest); i { case 0: return &v.state case 1: @@ -9672,7 +9909,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[106].Exporter = func(v any, i int) any { - switch v := v.(*ValidateVersionShardRequest); i { + switch v := v.(*ValidateSchemaKeyspaceRequest); i { case 0: return &v.state case 1: @@ -9684,7 +9921,7 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[107].Exporter = func(v any, i int) any { - switch v := v.(*VTExplainRequest); i { + switch v := v.(*ValidateShardRequest); i { case 0: return &v.state case 1: @@ -9696,6 +9933,42 @@ func file_vtadmin_proto_init() { } } file_vtadmin_proto_msgTypes[108].Exporter = func(v any, i int) any { + switch v := v.(*ValidateVersionKeyspaceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vtadmin_proto_msgTypes[109].Exporter = func(v any, i int) any { + switch v := v.(*ValidateVersionShardRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vtadmin_proto_msgTypes[110].Exporter = func(v any, i int) any { + switch v := v.(*VTExplainRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vtadmin_proto_msgTypes[111].Exporter = func(v any, i int) any { switch v := v.(*VTExplainResponse); i { case 0: return &v.state @@ -9707,7 +9980,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[112].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[115].Exporter = func(v any, i int) any { switch v := v.(*Schema_ShardTableSize); i { case 0: return &v.state @@ -9719,7 +9992,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[113].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[116].Exporter = func(v any, i int) any { switch v := v.(*Schema_TableSize); i { case 0: return &v.state @@ -9731,7 +10004,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[115].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[118].Exporter = func(v any, i int) any { switch v := v.(*GetSchemaMigrationsRequest_ClusterRequest); i { case 0: return &v.state @@ -9743,7 +10016,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[118].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[121].Exporter = func(v any, i int) any { switch v := v.(*ReloadSchemasResponse_KeyspaceResult); i { case 0: return &v.state @@ -9755,7 +10028,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[119].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[122].Exporter = func(v any, i int) any { switch v := v.(*ReloadSchemasResponse_ShardResult); i { case 0: return &v.state @@ -9767,7 +10040,7 @@ func file_vtadmin_proto_init() { return nil } } - file_vtadmin_proto_msgTypes[120].Exporter = func(v any, i int) any { + file_vtadmin_proto_msgTypes[123].Exporter = func(v any, i int) any { switch v := v.(*ReloadSchemasResponse_TabletResult); i { case 0: return &v.state @@ -9786,7 +10059,7 @@ func file_vtadmin_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vtadmin_proto_rawDesc, NumEnums: 1, - NumMessages: 121, + NumMessages: 124, NumExtensions: 0, NumServices: 1, }, diff --git a/go/vt/proto/vtadmin/vtadmin_grpc.pb.go b/go/vt/proto/vtadmin/vtadmin_grpc.pb.go index 1e377d0659f..504d7f39d61 100644 --- a/go/vt/proto/vtadmin/vtadmin_grpc.pb.go +++ b/go/vt/proto/vtadmin/vtadmin_grpc.pb.go @@ -116,6 +116,12 @@ type VTAdminClient interface { GetWorkflow(ctx context.Context, in *GetWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error) // GetWorkflows returns the Workflows for all specified clusters. GetWorkflows(ctx context.Context, in *GetWorkflowsRequest, opts ...grpc.CallOption) (*GetWorkflowsResponse, error) + // GetWorkflowStatus returns the status for a specific workflow. + GetWorkflowStatus(ctx context.Context, in *GetWorkflowStatusRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowStatusResponse, error) + // StartWorkflow starts a vreplication workflow. + StartWorkflow(ctx context.Context, in *StartWorkflowRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowUpdateResponse, error) + // StopWorkflow stops a vreplication workflow. + StopWorkflow(ctx context.Context, in *StopWorkflowRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowUpdateResponse, error) // LaunchSchemaMigration launches one or all migrations in the given // cluster executed with --postpone-launch. LaunchSchemaMigration(ctx context.Context, in *LaunchSchemaMigrationRequest, opts ...grpc.CallOption) (*vtctldata.LaunchSchemaMigrationResponse, error) @@ -515,6 +521,33 @@ func (c *vTAdminClient) GetWorkflows(ctx context.Context, in *GetWorkflowsReques return out, nil } +func (c *vTAdminClient) GetWorkflowStatus(ctx context.Context, in *GetWorkflowStatusRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowStatusResponse, error) { + out := new(vtctldata.WorkflowStatusResponse) + err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/GetWorkflowStatus", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vTAdminClient) StartWorkflow(ctx context.Context, in *StartWorkflowRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowUpdateResponse, error) { + out := new(vtctldata.WorkflowUpdateResponse) + err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/StartWorkflow", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vTAdminClient) StopWorkflow(ctx context.Context, in *StopWorkflowRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowUpdateResponse, error) { + out := new(vtctldata.WorkflowUpdateResponse) + err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/StopWorkflow", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *vTAdminClient) LaunchSchemaMigration(ctx context.Context, in *LaunchSchemaMigrationRequest, opts ...grpc.CallOption) (*vtctldata.LaunchSchemaMigrationResponse, error) { out := new(vtctldata.LaunchSchemaMigrationResponse) err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/LaunchSchemaMigration", in, out, opts...) @@ -819,6 +852,12 @@ type VTAdminServer interface { GetWorkflow(context.Context, *GetWorkflowRequest) (*Workflow, error) // GetWorkflows returns the Workflows for all specified clusters. GetWorkflows(context.Context, *GetWorkflowsRequest) (*GetWorkflowsResponse, error) + // GetWorkflowStatus returns the status for a specific workflow. + GetWorkflowStatus(context.Context, *GetWorkflowStatusRequest) (*vtctldata.WorkflowStatusResponse, error) + // StartWorkflow starts a vreplication workflow. + StartWorkflow(context.Context, *StartWorkflowRequest) (*vtctldata.WorkflowUpdateResponse, error) + // StopWorkflow stops a vreplication workflow. + StopWorkflow(context.Context, *StopWorkflowRequest) (*vtctldata.WorkflowUpdateResponse, error) // LaunchSchemaMigration launches one or all migrations in the given // cluster executed with --postpone-launch. LaunchSchemaMigration(context.Context, *LaunchSchemaMigrationRequest) (*vtctldata.LaunchSchemaMigrationResponse, error) @@ -1005,6 +1044,15 @@ func (UnimplementedVTAdminServer) GetWorkflow(context.Context, *GetWorkflowReque func (UnimplementedVTAdminServer) GetWorkflows(context.Context, *GetWorkflowsRequest) (*GetWorkflowsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetWorkflows not implemented") } +func (UnimplementedVTAdminServer) GetWorkflowStatus(context.Context, *GetWorkflowStatusRequest) (*vtctldata.WorkflowStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetWorkflowStatus not implemented") +} +func (UnimplementedVTAdminServer) StartWorkflow(context.Context, *StartWorkflowRequest) (*vtctldata.WorkflowUpdateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method StartWorkflow not implemented") +} +func (UnimplementedVTAdminServer) StopWorkflow(context.Context, *StopWorkflowRequest) (*vtctldata.WorkflowUpdateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method StopWorkflow not implemented") +} func (UnimplementedVTAdminServer) LaunchSchemaMigration(context.Context, *LaunchSchemaMigrationRequest) (*vtctldata.LaunchSchemaMigrationResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method LaunchSchemaMigration not implemented") } @@ -1717,6 +1765,60 @@ func _VTAdmin_GetWorkflows_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _VTAdmin_GetWorkflowStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetWorkflowStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VTAdminServer).GetWorkflowStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtadmin.VTAdmin/GetWorkflowStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VTAdminServer).GetWorkflowStatus(ctx, req.(*GetWorkflowStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _VTAdmin_StartWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StartWorkflowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VTAdminServer).StartWorkflow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtadmin.VTAdmin/StartWorkflow", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VTAdminServer).StartWorkflow(ctx, req.(*StartWorkflowRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _VTAdmin_StopWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StopWorkflowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VTAdminServer).StopWorkflow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtadmin.VTAdmin/StopWorkflow", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VTAdminServer).StopWorkflow(ctx, req.(*StopWorkflowRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _VTAdmin_LaunchSchemaMigration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(LaunchSchemaMigrationRequest) if err := dec(in); err != nil { @@ -2278,6 +2380,18 @@ var VTAdmin_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetWorkflows", Handler: _VTAdmin_GetWorkflows_Handler, }, + { + MethodName: "GetWorkflowStatus", + Handler: _VTAdmin_GetWorkflowStatus_Handler, + }, + { + MethodName: "StartWorkflow", + Handler: _VTAdmin_StartWorkflow_Handler, + }, + { + MethodName: "StopWorkflow", + Handler: _VTAdmin_StopWorkflow_Handler, + }, { MethodName: "LaunchSchemaMigration", Handler: _VTAdmin_LaunchSchemaMigration_Handler, diff --git a/go/vt/proto/vtadmin/vtadmin_vtproto.pb.go b/go/vt/proto/vtadmin/vtadmin_vtproto.pb.go index ce506cb7215..35b03c0090e 100644 --- a/go/vt/proto/vtadmin/vtadmin_vtproto.pb.go +++ b/go/vt/proto/vtadmin/vtadmin_vtproto.pb.go @@ -1587,6 +1587,66 @@ func (m *GetWorkflowRequest) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *GetWorkflowStatusRequest) CloneVT() *GetWorkflowStatusRequest { + if m == nil { + return (*GetWorkflowStatusRequest)(nil) + } + r := &GetWorkflowStatusRequest{ + ClusterId: m.ClusterId, + Keyspace: m.Keyspace, + Name: m.Name, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetWorkflowStatusRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *StartWorkflowRequest) CloneVT() *StartWorkflowRequest { + if m == nil { + return (*StartWorkflowRequest)(nil) + } + r := &StartWorkflowRequest{ + ClusterId: m.ClusterId, + Keyspace: m.Keyspace, + Workflow: m.Workflow, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *StartWorkflowRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *StopWorkflowRequest) CloneVT() *StopWorkflowRequest { + if m == nil { + return (*StopWorkflowRequest)(nil) + } + r := &StopWorkflowRequest{ + ClusterId: m.ClusterId, + Keyspace: m.Keyspace, + Workflow: m.Workflow, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *StopWorkflowRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *GetWorkflowsRequest) CloneVT() *GetWorkflowsRequest { if m == nil { return (*GetWorkflowsRequest)(nil) @@ -6297,6 +6357,168 @@ func (m *GetWorkflowRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GetWorkflowStatusRequest) 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 *GetWorkflowStatusRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetWorkflowStatusRequest) 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.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + 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.ClusterId) > 0 { + i -= len(m.ClusterId) + copy(dAtA[i:], m.ClusterId) + i = encodeVarint(dAtA, i, uint64(len(m.ClusterId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *StartWorkflowRequest) 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 *StartWorkflowRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *StartWorkflowRequest) 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.Workflow) > 0 { + i -= len(m.Workflow) + copy(dAtA[i:], m.Workflow) + i = encodeVarint(dAtA, i, uint64(len(m.Workflow))) + 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.ClusterId) > 0 { + i -= len(m.ClusterId) + copy(dAtA[i:], m.ClusterId) + i = encodeVarint(dAtA, i, uint64(len(m.ClusterId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *StopWorkflowRequest) 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 *StopWorkflowRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *StopWorkflowRequest) 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.Workflow) > 0 { + i -= len(m.Workflow) + copy(dAtA[i:], m.Workflow) + i = encodeVarint(dAtA, i, uint64(len(m.Workflow))) + 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.ClusterId) > 0 { + i -= len(m.ClusterId) + copy(dAtA[i:], m.ClusterId) + i = encodeVarint(dAtA, i, uint64(len(m.ClusterId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *GetWorkflowsRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -10144,6 +10366,72 @@ func (m *GetWorkflowRequest) SizeVT() (n int) { return n } +func (m *GetWorkflowStatusRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClusterId) + 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.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *StartWorkflowRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClusterId) + 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.Workflow) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *StopWorkflowRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClusterId) + 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.Workflow) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + func (m *GetWorkflowsRequest) SizeVT() (n int) { if m == nil { return 0 @@ -20037,6 +20325,447 @@ func (m *GetWorkflowRequest) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *GetWorkflowStatusRequest) 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: GetWorkflowStatusRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetWorkflowStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClusterId", 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.ClusterId = 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 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 + 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 *StartWorkflowRequest) 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: StartWorkflowRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StartWorkflowRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClusterId", 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.ClusterId = 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 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 + 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 *StopWorkflowRequest) 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: StopWorkflowRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StopWorkflowRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClusterId", 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.ClusterId = 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 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 + 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 *GetWorkflowsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/go/vt/proto/vtctldata/vtctldata.pb.go b/go/vt/proto/vtctldata/vtctldata.pb.go index ae20ac21ec1..b70105b7164 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 } @@ -9871,6 +9668,8 @@ type PlannedReparentShardRequest struct { // acceptable for a tablet to be eligible for promotion when Vitess makes the choice of a new primary. // A value of 0 indicates that Vitess shouldn't consider the replication lag at all. TolerableReplicationLag *vttime.Duration `protobuf:"bytes,6,opt,name=tolerable_replication_lag,json=tolerableReplicationLag,proto3" json:"tolerable_replication_lag,omitempty"` + // AllowCrossCellPromotion allows cross cell promotion, + AllowCrossCellPromotion bool `protobuf:"varint,7,opt,name=allow_cross_cell_promotion,json=allowCrossCellPromotion,proto3" json:"allow_cross_cell_promotion,omitempty"` } func (x *PlannedReparentShardRequest) Reset() { @@ -9947,6 +9746,13 @@ func (x *PlannedReparentShardRequest) GetTolerableReplicationLag() *vttime.Durat return nil } +func (x *PlannedReparentShardRequest) GetAllowCrossCellPromotion() bool { + if x != nil { + return x.AllowCrossCellPromotion + } + return false +} + type PlannedReparentShardResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -14358,6 +14164,7 @@ type VDiffCreateRequest struct { Verbose bool `protobuf:"varint,18,opt,name=verbose,proto3" json:"verbose,omitempty"` MaxReportSampleRows int64 `protobuf:"varint,19,opt,name=max_report_sample_rows,json=maxReportSampleRows,proto3" json:"max_report_sample_rows,omitempty"` MaxDiffDuration *vttime.Duration `protobuf:"bytes,20,opt,name=max_diff_duration,json=maxDiffDuration,proto3" json:"max_diff_duration,omitempty"` + RowDiffColumnTruncateAt int64 `protobuf:"varint,21,opt,name=row_diff_column_truncate_at,json=rowDiffColumnTruncateAt,proto3" json:"row_diff_column_truncate_at,omitempty"` } func (x *VDiffCreateRequest) Reset() { @@ -14532,6 +14339,13 @@ func (x *VDiffCreateRequest) GetMaxDiffDuration() *vttime.Duration { return nil } +func (x *VDiffCreateRequest) GetRowDiffColumnTruncateAt() int64 { + if x != nil { + return x.RowDiffColumnTruncateAt + } + return 0 +} + type VDiffCreateResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -16380,108 +16194,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[260] - 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[260] - 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 @@ -16493,7 +16205,7 @@ type GetSrvKeyspaceNamesResponse_NameList struct { func (x *GetSrvKeyspaceNamesResponse_NameList) Reset() { *x = GetSrvKeyspaceNamesResponse_NameList{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[269] + mi := &file_vtctldata_proto_msgTypes[267] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16506,7 +16218,7 @@ func (x *GetSrvKeyspaceNamesResponse_NameList) String() string { func (*GetSrvKeyspaceNamesResponse_NameList) ProtoMessage() {} func (x *GetSrvKeyspaceNamesResponse_NameList) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[269] + mi := &file_vtctldata_proto_msgTypes[267] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16529,32 +16241,33 @@ func (x *GetSrvKeyspaceNamesResponse_NameList) GetNames() []string { return nil } -type GetThrottlerStatusResponse_MetricResult struct { +type MoveTablesCreateResponse_TabletInfo 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"` + Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` + // Created is set if the workflow was created on this tablet or not. + Created bool `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"` } -func (x *GetThrottlerStatusResponse_MetricResult) Reset() { - *x = GetThrottlerStatusResponse_MetricResult{} +func (x *MoveTablesCreateResponse_TabletInfo) Reset() { + *x = MoveTablesCreateResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[272] + mi := &file_vtctldata_proto_msgTypes[271] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GetThrottlerStatusResponse_MetricResult) String() string { +func (x *MoveTablesCreateResponse_TabletInfo) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetThrottlerStatusResponse_MetricResult) ProtoMessage() {} +func (*MoveTablesCreateResponse_TabletInfo) ProtoMessage() {} -func (x *GetThrottlerStatusResponse_MetricResult) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[272] +func (x *MoveTablesCreateResponse_TabletInfo) 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 { @@ -16565,51 +16278,52 @@ func (x *GetThrottlerStatusResponse_MetricResult) ProtoReflect() protoreflect.Me 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} +// Deprecated: Use MoveTablesCreateResponse_TabletInfo.ProtoReflect.Descriptor instead. +func (*MoveTablesCreateResponse_TabletInfo) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{143, 0} } -func (x *GetThrottlerStatusResponse_MetricResult) GetValue() float64 { +func (x *MoveTablesCreateResponse_TabletInfo) GetTablet() *topodata.TabletAlias { if x != nil { - return x.Value + return x.Tablet } - return 0 + return nil } -func (x *GetThrottlerStatusResponse_MetricResult) GetError() string { +func (x *MoveTablesCreateResponse_TabletInfo) GetCreated() bool { if x != nil { - return x.Error + return x.Created } - return "" + return false } -type GetThrottlerStatusResponse_MetricHealth struct { +type WorkflowDeleteResponse_TabletInfo 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"` + Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` + // Delete is set if the workflow was deleted on this tablet. + Deleted bool `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted,omitempty"` } -func (x *GetThrottlerStatusResponse_MetricHealth) Reset() { - *x = GetThrottlerStatusResponse_MetricHealth{} +func (x *WorkflowDeleteResponse_TabletInfo) Reset() { + *x = WorkflowDeleteResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[275] + mi := &file_vtctldata_proto_msgTypes[281] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GetThrottlerStatusResponse_MetricHealth) String() string { +func (x *WorkflowDeleteResponse_TabletInfo) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetThrottlerStatusResponse_MetricHealth) ProtoMessage() {} +func (*WorkflowDeleteResponse_TabletInfo) ProtoMessage() {} -func (x *GetThrottlerStatusResponse_MetricHealth) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[275] +func (x *WorkflowDeleteResponse_TabletInfo) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[281] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16620,222 +16334,55 @@ func (x *GetThrottlerStatusResponse_MetricHealth) ProtoReflect() protoreflect.Me 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} +// Deprecated: Use WorkflowDeleteResponse_TabletInfo.ProtoReflect.Descriptor instead. +func (*WorkflowDeleteResponse_TabletInfo) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{238, 0} } -func (x *GetThrottlerStatusResponse_MetricHealth) GetLastHealthyAt() *vttime.Time { +func (x *WorkflowDeleteResponse_TabletInfo) GetTablet() *topodata.TabletAlias { if x != nil { - return x.LastHealthyAt + return x.Tablet } return nil } -func (x *GetThrottlerStatusResponse_MetricHealth) GetSecondsSinceLastHealthy() int64 { +func (x *WorkflowDeleteResponse_TabletInfo) GetDeleted() bool { if x != nil { - return x.SecondsSinceLastHealthy + return x.Deleted } - return 0 + return false } -type GetThrottlerStatusResponse_RecentApp struct { +type WorkflowStatusResponse_TableCopyState 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"` + RowsCopied int64 `protobuf:"varint,1,opt,name=rows_copied,json=rowsCopied,proto3" json:"rows_copied,omitempty"` + RowsTotal int64 `protobuf:"varint,2,opt,name=rows_total,json=rowsTotal,proto3" json:"rows_total,omitempty"` + RowsPercentage float32 `protobuf:"fixed32,3,opt,name=rows_percentage,json=rowsPercentage,proto3" json:"rows_percentage,omitempty"` + BytesCopied int64 `protobuf:"varint,4,opt,name=bytes_copied,json=bytesCopied,proto3" json:"bytes_copied,omitempty"` + BytesTotal int64 `protobuf:"varint,5,opt,name=bytes_total,json=bytesTotal,proto3" json:"bytes_total,omitempty"` + BytesPercentage float32 `protobuf:"fixed32,6,opt,name=bytes_percentage,json=bytesPercentage,proto3" json:"bytes_percentage,omitempty"` } -func (x *GetThrottlerStatusResponse_RecentApp) Reset() { - *x = GetThrottlerStatusResponse_RecentApp{} +func (x *WorkflowStatusResponse_TableCopyState) Reset() { + *x = WorkflowStatusResponse_TableCopyState{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[279] + mi := &file_vtctldata_proto_msgTypes[282] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GetThrottlerStatusResponse_RecentApp) String() string { +func (x *WorkflowStatusResponse_TableCopyState) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetThrottlerStatusResponse_RecentApp) ProtoMessage() {} +func (*WorkflowStatusResponse_TableCopyState) ProtoMessage() {} -func (x *GetThrottlerStatusResponse_RecentApp) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[279] - 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_RecentApp.ProtoReflect.Descriptor instead. -func (*GetThrottlerStatusResponse_RecentApp) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{111, 7} -} - -func (x *GetThrottlerStatusResponse_RecentApp) GetCheckedAt() *vttime.Time { - if x != nil { - return x.CheckedAt - } - 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 - unknownFields protoimpl.UnknownFields - - Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` - // Created is set if the workflow was created on this tablet or not. - Created bool `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"` -} - -func (x *MoveTablesCreateResponse_TabletInfo) Reset() { - *x = MoveTablesCreateResponse_TabletInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[282] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MoveTablesCreateResponse_TabletInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MoveTablesCreateResponse_TabletInfo) ProtoMessage() {} - -func (x *MoveTablesCreateResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[282] - 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 MoveTablesCreateResponse_TabletInfo.ProtoReflect.Descriptor instead. -func (*MoveTablesCreateResponse_TabletInfo) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{143, 0} -} - -func (x *MoveTablesCreateResponse_TabletInfo) GetTablet() *topodata.TabletAlias { - if x != nil { - return x.Tablet - } - return nil -} - -func (x *MoveTablesCreateResponse_TabletInfo) GetCreated() bool { - if x != nil { - return x.Created - } - return false -} - -type WorkflowDeleteResponse_TabletInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` - // Delete is set if the workflow was deleted on this tablet. - Deleted bool `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted,omitempty"` -} - -func (x *WorkflowDeleteResponse_TabletInfo) Reset() { - *x = WorkflowDeleteResponse_TabletInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[292] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkflowDeleteResponse_TabletInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkflowDeleteResponse_TabletInfo) ProtoMessage() {} - -func (x *WorkflowDeleteResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[292] - 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 WorkflowDeleteResponse_TabletInfo.ProtoReflect.Descriptor instead. -func (*WorkflowDeleteResponse_TabletInfo) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{238, 0} -} - -func (x *WorkflowDeleteResponse_TabletInfo) GetTablet() *topodata.TabletAlias { - if x != nil { - return x.Tablet - } - return nil -} - -func (x *WorkflowDeleteResponse_TabletInfo) GetDeleted() bool { - if x != nil { - return x.Deleted - } - return false -} - -type WorkflowStatusResponse_TableCopyState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RowsCopied int64 `protobuf:"varint,1,opt,name=rows_copied,json=rowsCopied,proto3" json:"rows_copied,omitempty"` - RowsTotal int64 `protobuf:"varint,2,opt,name=rows_total,json=rowsTotal,proto3" json:"rows_total,omitempty"` - RowsPercentage float32 `protobuf:"fixed32,3,opt,name=rows_percentage,json=rowsPercentage,proto3" json:"rows_percentage,omitempty"` - BytesCopied int64 `protobuf:"varint,4,opt,name=bytes_copied,json=bytesCopied,proto3" json:"bytes_copied,omitempty"` - BytesTotal int64 `protobuf:"varint,5,opt,name=bytes_total,json=bytesTotal,proto3" json:"bytes_total,omitempty"` - BytesPercentage float32 `protobuf:"fixed32,6,opt,name=bytes_percentage,json=bytesPercentage,proto3" json:"bytes_percentage,omitempty"` -} - -func (x *WorkflowStatusResponse_TableCopyState) Reset() { - *x = WorkflowStatusResponse_TableCopyState{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[293] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkflowStatusResponse_TableCopyState) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkflowStatusResponse_TableCopyState) ProtoMessage() {} - -func (x *WorkflowStatusResponse_TableCopyState) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[293] +func (x *WorkflowStatusResponse_TableCopyState) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[282] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16909,7 +16456,7 @@ type WorkflowStatusResponse_ShardStreamState struct { func (x *WorkflowStatusResponse_ShardStreamState) Reset() { *x = WorkflowStatusResponse_ShardStreamState{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[294] + mi := &file_vtctldata_proto_msgTypes[283] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16922,7 +16469,7 @@ func (x *WorkflowStatusResponse_ShardStreamState) String() string { func (*WorkflowStatusResponse_ShardStreamState) ProtoMessage() {} func (x *WorkflowStatusResponse_ShardStreamState) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[294] + mi := &file_vtctldata_proto_msgTypes[283] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16991,7 +16538,7 @@ type WorkflowStatusResponse_ShardStreams struct { func (x *WorkflowStatusResponse_ShardStreams) Reset() { *x = WorkflowStatusResponse_ShardStreams{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[295] + mi := &file_vtctldata_proto_msgTypes[284] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17004,7 +16551,7 @@ func (x *WorkflowStatusResponse_ShardStreams) String() string { func (*WorkflowStatusResponse_ShardStreams) ProtoMessage() {} func (x *WorkflowStatusResponse_ShardStreams) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[295] + mi := &file_vtctldata_proto_msgTypes[284] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17041,7 +16588,7 @@ type WorkflowUpdateResponse_TabletInfo struct { func (x *WorkflowUpdateResponse_TabletInfo) Reset() { *x = WorkflowUpdateResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[298] + mi := &file_vtctldata_proto_msgTypes[287] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17054,7 +16601,7 @@ func (x *WorkflowUpdateResponse_TabletInfo) String() string { func (*WorkflowUpdateResponse_TabletInfo) ProtoMessage() {} func (x *WorkflowUpdateResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[298] + mi := &file_vtctldata_proto_msgTypes[287] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17709,1228 +17256,1539 @@ 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, + 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, 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, 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, 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, - 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, + 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, 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, 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, 0x94, 0x03, 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, 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, + 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, 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, + 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, 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, 0x6f, 0x73, + 0x73, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x6f, + 0x73, 0x73, 0x43, 0x65, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 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, 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, + 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, + 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, 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, + 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, - 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, 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, + 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, - 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, + 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, 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, + 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, 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, - 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, - 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, + 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, 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, 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, - 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, + 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, 0xc6, 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, @@ -18940,733 +18798,289 @@ var file_vtctldata_proto_rawDesc = []byte{ 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, - 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, - 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, 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, + 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, 0x12, 0x3c, 0x0a, 0x1b, 0x72, + 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x74, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x17, 0x72, 0x6f, 0x77, 0x44, 0x69, 0x66, 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x41, 0x74, 0x22, 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, 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, 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, + 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, 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, 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, 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, + 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, 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, 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, - 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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 ( @@ -19682,7 +19096,7 @@ func file_vtctldata_proto_rawDescGZIP() []byte { } var file_vtctldata_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_vtctldata_proto_msgTypes = make([]protoimpl.MessageInfo, 299) +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 @@ -19948,327 +19362,307 @@ var file_vtctldata_proto_goTypes = []any{ nil, // 261: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry (*ApplyVSchemaResponse_ParamList)(nil), // 262: vtctldata.ApplyVSchemaResponse.ParamList nil, // 263: vtctldata.CancelSchemaMigrationResponse.RowsAffectedByShardEntry - (*CheckThrottlerResponse_Metric)(nil), // 264: vtctldata.CheckThrottlerResponse.Metric - nil, // 265: vtctldata.CheckThrottlerResponse.MetricsEntry - nil, // 266: vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 267: vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 268: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry - nil, // 269: vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 270: vtctldata.GetCellsAliasesResponse.AliasesEntry - nil, // 271: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry - nil, // 272: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry - (*GetSrvKeyspaceNamesResponse_NameList)(nil), // 273: vtctldata.GetSrvKeyspaceNamesResponse.NameList - nil, // 274: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry - nil, // 275: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry - (*GetThrottlerStatusResponse_MetricResult)(nil), // 276: vtctldata.GetThrottlerStatusResponse.MetricResult - nil, // 277: vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry - nil, // 278: vtctldata.GetThrottlerStatusResponse.MetricThresholdsEntry - (*GetThrottlerStatusResponse_MetricHealth)(nil), // 279: vtctldata.GetThrottlerStatusResponse.MetricHealth - nil, // 280: vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry - nil, // 281: vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry - nil, // 282: vtctldata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - (*GetThrottlerStatusResponse_RecentApp)(nil), // 283: vtctldata.GetThrottlerStatusResponse.RecentApp - nil, // 284: vtctldata.GetThrottlerStatusResponse.RecentAppsEntry - nil, // 285: vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry - (*MoveTablesCreateResponse_TabletInfo)(nil), // 286: vtctldata.MoveTablesCreateResponse.TabletInfo - nil, // 287: vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 288: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry - nil, // 289: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry - nil, // 290: vtctldata.ValidateResponse.ResultsByKeyspaceEntry - nil, // 291: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry - nil, // 292: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry - nil, // 293: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry - nil, // 294: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry - nil, // 295: vtctldata.VDiffShowResponse.TabletResponsesEntry - (*WorkflowDeleteResponse_TabletInfo)(nil), // 296: vtctldata.WorkflowDeleteResponse.TabletInfo - (*WorkflowStatusResponse_TableCopyState)(nil), // 297: vtctldata.WorkflowStatusResponse.TableCopyState - (*WorkflowStatusResponse_ShardStreamState)(nil), // 298: vtctldata.WorkflowStatusResponse.ShardStreamState - (*WorkflowStatusResponse_ShardStreams)(nil), // 299: vtctldata.WorkflowStatusResponse.ShardStreams - nil, // 300: vtctldata.WorkflowStatusResponse.TableCopyStateEntry - nil, // 301: vtctldata.WorkflowStatusResponse.ShardStreamsEntry - (*WorkflowUpdateResponse_TabletInfo)(nil), // 302: vtctldata.WorkflowUpdateResponse.TabletInfo - (*logutil.Event)(nil), // 303: logutil.Event - (tabletmanagerdata.TabletSelectionPreference)(0), // 304: tabletmanagerdata.TabletSelectionPreference - (*topodata.Keyspace)(nil), // 305: topodata.Keyspace - (*vttime.Time)(nil), // 306: vttime.Time - (*topodata.TabletAlias)(nil), // 307: topodata.TabletAlias - (*vttime.Duration)(nil), // 308: vttime.Duration - (*topodata.Shard)(nil), // 309: topodata.Shard - (*topodata.CellInfo)(nil), // 310: topodata.CellInfo - (*vschema.KeyspaceRoutingRules)(nil), // 311: vschema.KeyspaceRoutingRules - (*vschema.RoutingRules)(nil), // 312: vschema.RoutingRules - (*vschema.ShardRoutingRules)(nil), // 313: vschema.ShardRoutingRules - (*vtrpc.CallerID)(nil), // 314: vtrpc.CallerID - (*vschema.Keyspace)(nil), // 315: vschema.Keyspace - (topodata.TabletType)(0), // 316: topodata.TabletType - (*topodata.Tablet)(nil), // 317: topodata.Tablet - (topodata.KeyspaceType)(0), // 318: topodata.KeyspaceType - (*query.QueryResult)(nil), // 319: query.QueryResult - (*tabletmanagerdata.ExecuteHookRequest)(nil), // 320: tabletmanagerdata.ExecuteHookRequest - (*tabletmanagerdata.ExecuteHookResponse)(nil), // 321: tabletmanagerdata.ExecuteHookResponse - (*mysqlctl.BackupInfo)(nil), // 322: mysqlctl.BackupInfo - (*replicationdata.FullStatus)(nil), // 323: replicationdata.FullStatus - (*tabletmanagerdata.Permissions)(nil), // 324: tabletmanagerdata.Permissions - (*tabletmanagerdata.SchemaDefinition)(nil), // 325: tabletmanagerdata.SchemaDefinition - (*topodata.ThrottledAppRule)(nil), // 326: topodata.ThrottledAppRule - (*vschema.SrvVSchema)(nil), // 327: vschema.SrvVSchema - (*topodata.ShardReplicationError)(nil), // 328: topodata.ShardReplicationError - (*topodata.KeyRange)(nil), // 329: topodata.KeyRange - (*topodata.CellsAlias)(nil), // 330: topodata.CellsAlias - (*tabletmanagerdata.UpdateVReplicationWorkflowRequest)(nil), // 331: tabletmanagerdata.UpdateVReplicationWorkflowRequest - (*vschema.MirrorRules)(nil), // 332: vschema.MirrorRules - (*topodata.Shard_TabletControl)(nil), // 333: topodata.Shard.TabletControl - (*binlogdata.BinlogSource)(nil), // 334: binlogdata.BinlogSource - (*topodata.ShardReplication)(nil), // 335: topodata.ShardReplication - (*topodata.SrvKeyspace)(nil), // 336: topodata.SrvKeyspace - (*replicationdata.Status)(nil), // 337: replicationdata.Status - (*tabletmanagerdata.VDiffResponse)(nil), // 338: tabletmanagerdata.VDiffResponse + 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{ - 303, // 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 - 304, // 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 - 305, // 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 - 306, // 7: vtctldata.SchemaMigration.added_at:type_name -> vttime.Time - 306, // 8: vtctldata.SchemaMigration.requested_at:type_name -> vttime.Time - 306, // 9: vtctldata.SchemaMigration.ready_at:type_name -> vttime.Time - 306, // 10: vtctldata.SchemaMigration.started_at:type_name -> vttime.Time - 306, // 11: vtctldata.SchemaMigration.liveness_timestamp:type_name -> vttime.Time - 306, // 12: vtctldata.SchemaMigration.completed_at:type_name -> vttime.Time - 306, // 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 - 307, // 15: vtctldata.SchemaMigration.tablet:type_name -> topodata.TabletAlias - 308, // 16: vtctldata.SchemaMigration.artifact_retention:type_name -> vttime.Duration - 306, // 17: vtctldata.SchemaMigration.last_throttled_at:type_name -> vttime.Time - 306, // 18: vtctldata.SchemaMigration.cancelled_at:type_name -> vttime.Time - 306, // 19: vtctldata.SchemaMigration.reviewed_at:type_name -> vttime.Time - 306, // 20: vtctldata.SchemaMigration.ready_to_complete_at:type_name -> vttime.Time - 309, // 21: vtctldata.Shard.shard:type_name -> topodata.Shard + 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 - 310, // 26: vtctldata.AddCellInfoRequest.cell_info:type_name -> topodata.CellInfo - 311, // 27: vtctldata.ApplyKeyspaceRoutingRulesRequest.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 311, // 28: vtctldata.ApplyKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 312, // 29: vtctldata.ApplyRoutingRulesRequest.routing_rules:type_name -> vschema.RoutingRules - 313, // 30: vtctldata.ApplyShardRoutingRulesRequest.shard_routing_rules:type_name -> vschema.ShardRoutingRules - 308, // 31: vtctldata.ApplySchemaRequest.wait_replicas_timeout:type_name -> vttime.Duration - 314, // 32: vtctldata.ApplySchemaRequest.caller_id:type_name -> vtrpc.CallerID + 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 - 315, // 34: vtctldata.ApplyVSchemaRequest.v_schema:type_name -> vschema.Keyspace - 315, // 35: vtctldata.ApplyVSchemaResponse.v_schema:type_name -> vschema.Keyspace + 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 - 307, // 37: vtctldata.BackupRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 38: vtctldata.BackupResponse.tablet_alias:type_name -> topodata.TabletAlias - 303, // 39: vtctldata.BackupResponse.event:type_name -> logutil.Event + 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 - 307, // 41: vtctldata.ChangeTabletTypeRequest.tablet_alias:type_name -> topodata.TabletAlias - 316, // 42: vtctldata.ChangeTabletTypeRequest.db_type:type_name -> topodata.TabletType - 317, // 43: vtctldata.ChangeTabletTypeResponse.before_tablet:type_name -> topodata.Tablet - 317, // 44: vtctldata.ChangeTabletTypeResponse.after_tablet:type_name -> topodata.Tablet - 307, // 45: vtctldata.CheckThrottlerRequest.tablet_alias:type_name -> topodata.TabletAlias - 265, // 46: vtctldata.CheckThrottlerResponse.metrics:type_name -> vtctldata.CheckThrottlerResponse.MetricsEntry - 266, // 47: vtctldata.CleanupSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry - 267, // 48: vtctldata.CompleteSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry - 318, // 49: vtctldata.CreateKeyspaceRequest.type:type_name -> topodata.KeyspaceType - 306, // 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 - 307, // 55: vtctldata.DeleteTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias - 307, // 56: vtctldata.EmergencyReparentShardRequest.new_primary:type_name -> topodata.TabletAlias - 307, // 57: vtctldata.EmergencyReparentShardRequest.ignore_replicas:type_name -> topodata.TabletAlias - 308, // 58: vtctldata.EmergencyReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration - 307, // 59: vtctldata.EmergencyReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 303, // 60: vtctldata.EmergencyReparentShardResponse.events:type_name -> logutil.Event - 307, // 61: vtctldata.ExecuteFetchAsAppRequest.tablet_alias:type_name -> topodata.TabletAlias - 319, // 62: vtctldata.ExecuteFetchAsAppResponse.result:type_name -> query.QueryResult - 307, // 63: vtctldata.ExecuteFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias - 319, // 64: vtctldata.ExecuteFetchAsDBAResponse.result:type_name -> query.QueryResult - 307, // 65: vtctldata.ExecuteHookRequest.tablet_alias:type_name -> topodata.TabletAlias - 320, // 66: vtctldata.ExecuteHookRequest.tablet_hook_request:type_name -> tabletmanagerdata.ExecuteHookRequest - 321, // 67: vtctldata.ExecuteHookResponse.hook_result:type_name -> tabletmanagerdata.ExecuteHookResponse - 307, // 68: vtctldata.ExecuteMultiFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias - 319, // 69: vtctldata.ExecuteMultiFetchAsDBAResponse.results:type_name -> query.QueryResult - 268, // 70: vtctldata.FindAllShardsInKeyspaceResponse.shards:type_name -> vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry - 269, // 71: vtctldata.ForceCutOverSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry - 322, // 72: vtctldata.GetBackupsResponse.backups:type_name -> mysqlctl.BackupInfo - 310, // 73: vtctldata.GetCellInfoResponse.cell_info:type_name -> topodata.CellInfo - 270, // 74: vtctldata.GetCellsAliasesResponse.aliases:type_name -> vtctldata.GetCellsAliasesResponse.AliasesEntry - 307, // 75: vtctldata.GetFullStatusRequest.tablet_alias:type_name -> topodata.TabletAlias - 323, // 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 - 307, // 79: vtctldata.GetPermissionsRequest.tablet_alias:type_name -> topodata.TabletAlias - 324, // 80: vtctldata.GetPermissionsResponse.permissions:type_name -> tabletmanagerdata.Permissions - 311, // 81: vtctldata.GetKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 312, // 82: vtctldata.GetRoutingRulesResponse.routing_rules:type_name -> vschema.RoutingRules - 307, // 83: vtctldata.GetSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias - 325, // 84: vtctldata.GetSchemaResponse.schema:type_name -> tabletmanagerdata.SchemaDefinition - 3, // 85: vtctldata.GetSchemaMigrationsRequest.status:type_name -> vtctldata.SchemaMigration.Status - 308, // 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 - 271, // 89: vtctldata.GetShardReplicationResponse.shard_replication_by_cell:type_name -> vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry - 10, // 90: vtctldata.GetShardResponse.shard:type_name -> vtctldata.Shard - 313, // 91: vtctldata.GetShardRoutingRulesResponse.shard_routing_rules:type_name -> vschema.ShardRoutingRules - 272, // 92: vtctldata.GetSrvKeyspaceNamesResponse.names:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry - 274, // 93: vtctldata.GetSrvKeyspacesResponse.srv_keyspaces:type_name -> vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry - 326, // 94: vtctldata.UpdateThrottlerConfigRequest.throttled_app:type_name -> topodata.ThrottledAppRule - 327, // 95: vtctldata.GetSrvVSchemaResponse.srv_v_schema:type_name -> vschema.SrvVSchema - 275, // 96: vtctldata.GetSrvVSchemasResponse.srv_v_schemas:type_name -> vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry - 307, // 97: vtctldata.GetTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 317, // 98: vtctldata.GetTabletResponse.tablet:type_name -> topodata.Tablet - 307, // 99: vtctldata.GetTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias - 316, // 100: vtctldata.GetTabletsRequest.tablet_type:type_name -> topodata.TabletType - 317, // 101: vtctldata.GetTabletsResponse.tablets:type_name -> topodata.Tablet - 307, // 102: vtctldata.GetThrottlerStatusRequest.tablet_alias:type_name -> topodata.TabletAlias - 277, // 103: vtctldata.GetThrottlerStatusResponse.aggregated_metrics:type_name -> vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry - 278, // 104: vtctldata.GetThrottlerStatusResponse.metric_thresholds:type_name -> vtctldata.GetThrottlerStatusResponse.MetricThresholdsEntry - 280, // 105: vtctldata.GetThrottlerStatusResponse.metrics_health:type_name -> vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry - 281, // 106: vtctldata.GetThrottlerStatusResponse.throttled_apps:type_name -> vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry - 282, // 107: vtctldata.GetThrottlerStatusResponse.app_checked_metrics:type_name -> vtctldata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - 284, // 108: vtctldata.GetThrottlerStatusResponse.recent_apps:type_name -> vtctldata.GetThrottlerStatusResponse.RecentAppsEntry - 118, // 109: vtctldata.GetTopologyPathResponse.cell:type_name -> vtctldata.TopologyCell - 307, // 110: vtctldata.GetVersionRequest.tablet_alias:type_name -> topodata.TabletAlias - 315, // 111: vtctldata.GetVSchemaResponse.v_schema:type_name -> vschema.Keyspace - 12, // 112: vtctldata.GetWorkflowsResponse.workflows:type_name -> vtctldata.Workflow - 307, // 113: vtctldata.InitShardPrimaryRequest.primary_elect_tablet_alias:type_name -> topodata.TabletAlias - 308, // 114: vtctldata.InitShardPrimaryRequest.wait_replicas_timeout:type_name -> vttime.Duration - 303, // 115: vtctldata.InitShardPrimaryResponse.events:type_name -> logutil.Event - 285, // 116: vtctldata.LaunchSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry - 315, // 117: vtctldata.LookupVindexCreateRequest.vindex:type_name -> vschema.Keyspace - 316, // 118: vtctldata.LookupVindexCreateRequest.tablet_types:type_name -> topodata.TabletType - 304, // 119: vtctldata.LookupVindexCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 7, // 120: vtctldata.MaterializeCreateRequest.settings:type_name -> vtctldata.MaterializeSettings - 316, // 121: vtctldata.MigrateCreateRequest.tablet_types:type_name -> topodata.TabletType - 304, // 122: vtctldata.MigrateCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 316, // 123: vtctldata.MoveTablesCreateRequest.tablet_types:type_name -> topodata.TabletType - 304, // 124: vtctldata.MoveTablesCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 11, // 125: vtctldata.MoveTablesCreateRequest.workflow_options:type_name -> vtctldata.WorkflowOptions - 286, // 126: vtctldata.MoveTablesCreateResponse.details:type_name -> vtctldata.MoveTablesCreateResponse.TabletInfo - 307, // 127: vtctldata.PingTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 128: vtctldata.PlannedReparentShardRequest.new_primary:type_name -> topodata.TabletAlias - 307, // 129: vtctldata.PlannedReparentShardRequest.avoid_primary:type_name -> topodata.TabletAlias - 308, // 130: vtctldata.PlannedReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration - 308, // 131: vtctldata.PlannedReparentShardRequest.tolerable_replication_lag:type_name -> vttime.Duration - 307, // 132: vtctldata.PlannedReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 303, // 133: vtctldata.PlannedReparentShardResponse.events:type_name -> logutil.Event - 307, // 134: vtctldata.RefreshStateRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 135: vtctldata.ReloadSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 136: vtctldata.ReloadSchemaKeyspaceResponse.events:type_name -> logutil.Event - 303, // 137: vtctldata.ReloadSchemaShardResponse.events:type_name -> logutil.Event - 307, // 138: vtctldata.ReparentTabletRequest.tablet:type_name -> topodata.TabletAlias - 307, // 139: vtctldata.ReparentTabletResponse.primary:type_name -> topodata.TabletAlias - 316, // 140: vtctldata.ReshardCreateRequest.tablet_types:type_name -> topodata.TabletType - 304, // 141: vtctldata.ReshardCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 307, // 142: vtctldata.RestoreFromBackupRequest.tablet_alias:type_name -> topodata.TabletAlias - 306, // 143: vtctldata.RestoreFromBackupRequest.backup_time:type_name -> vttime.Time - 306, // 144: vtctldata.RestoreFromBackupRequest.restore_to_timestamp:type_name -> vttime.Time - 307, // 145: vtctldata.RestoreFromBackupResponse.tablet_alias:type_name -> topodata.TabletAlias - 303, // 146: vtctldata.RestoreFromBackupResponse.event:type_name -> logutil.Event - 287, // 147: vtctldata.RetrySchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry - 307, // 148: vtctldata.RunHealthCheckRequest.tablet_alias:type_name -> topodata.TabletAlias - 305, // 149: vtctldata.SetKeyspaceDurabilityPolicyResponse.keyspace:type_name -> topodata.Keyspace - 305, // 150: vtctldata.SetKeyspaceShardingInfoResponse.keyspace:type_name -> topodata.Keyspace - 309, // 151: vtctldata.SetShardIsPrimaryServingResponse.shard:type_name -> topodata.Shard - 316, // 152: vtctldata.SetShardTabletControlRequest.tablet_type:type_name -> topodata.TabletType - 309, // 153: vtctldata.SetShardTabletControlResponse.shard:type_name -> topodata.Shard - 307, // 154: vtctldata.SetWritableRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 155: vtctldata.ShardReplicationAddRequest.tablet_alias:type_name -> topodata.TabletAlias - 328, // 156: vtctldata.ShardReplicationFixResponse.error:type_name -> topodata.ShardReplicationError - 288, // 157: vtctldata.ShardReplicationPositionsResponse.replication_statuses:type_name -> vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry - 289, // 158: vtctldata.ShardReplicationPositionsResponse.tablet_map:type_name -> vtctldata.ShardReplicationPositionsResponse.TabletMapEntry - 307, // 159: vtctldata.ShardReplicationRemoveRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 160: vtctldata.SleepTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 308, // 161: vtctldata.SleepTabletRequest.duration:type_name -> vttime.Duration - 329, // 162: vtctldata.SourceShardAddRequest.key_range:type_name -> topodata.KeyRange - 309, // 163: vtctldata.SourceShardAddResponse.shard:type_name -> topodata.Shard - 309, // 164: vtctldata.SourceShardDeleteResponse.shard:type_name -> topodata.Shard - 307, // 165: vtctldata.StartReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 166: vtctldata.StopReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias - 307, // 167: vtctldata.TabletExternallyReparentedRequest.tablet:type_name -> topodata.TabletAlias - 307, // 168: vtctldata.TabletExternallyReparentedResponse.new_primary:type_name -> topodata.TabletAlias - 307, // 169: vtctldata.TabletExternallyReparentedResponse.old_primary:type_name -> topodata.TabletAlias - 310, // 170: vtctldata.UpdateCellInfoRequest.cell_info:type_name -> topodata.CellInfo - 310, // 171: vtctldata.UpdateCellInfoResponse.cell_info:type_name -> topodata.CellInfo - 330, // 172: vtctldata.UpdateCellsAliasRequest.cells_alias:type_name -> topodata.CellsAlias - 330, // 173: vtctldata.UpdateCellsAliasResponse.cells_alias:type_name -> topodata.CellsAlias - 290, // 174: vtctldata.ValidateResponse.results_by_keyspace:type_name -> vtctldata.ValidateResponse.ResultsByKeyspaceEntry - 291, // 175: vtctldata.ValidateKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry - 292, // 176: vtctldata.ValidateSchemaKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry - 293, // 177: vtctldata.ValidateVersionKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry - 294, // 178: vtctldata.ValidateVSchemaResponse.results_by_shard:type_name -> vtctldata.ValidateVSchemaResponse.ResultsByShardEntry - 316, // 179: vtctldata.VDiffCreateRequest.tablet_types:type_name -> topodata.TabletType - 304, // 180: vtctldata.VDiffCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 308, // 181: vtctldata.VDiffCreateRequest.filtered_replication_wait_time:type_name -> vttime.Duration - 308, // 182: vtctldata.VDiffCreateRequest.wait_update_interval:type_name -> vttime.Duration - 308, // 183: vtctldata.VDiffCreateRequest.max_diff_duration:type_name -> vttime.Duration - 295, // 184: vtctldata.VDiffShowResponse.tablet_responses:type_name -> vtctldata.VDiffShowResponse.TabletResponsesEntry - 296, // 185: vtctldata.WorkflowDeleteResponse.details:type_name -> vtctldata.WorkflowDeleteResponse.TabletInfo - 300, // 186: vtctldata.WorkflowStatusResponse.table_copy_state:type_name -> vtctldata.WorkflowStatusResponse.TableCopyStateEntry - 301, // 187: vtctldata.WorkflowStatusResponse.shard_streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamsEntry - 316, // 188: vtctldata.WorkflowSwitchTrafficRequest.tablet_types:type_name -> topodata.TabletType - 308, // 189: vtctldata.WorkflowSwitchTrafficRequest.max_replication_lag_allowed:type_name -> vttime.Duration - 308, // 190: vtctldata.WorkflowSwitchTrafficRequest.timeout:type_name -> vttime.Duration - 331, // 191: vtctldata.WorkflowUpdateRequest.tablet_request:type_name -> tabletmanagerdata.UpdateVReplicationWorkflowRequest - 302, // 192: vtctldata.WorkflowUpdateResponse.details:type_name -> vtctldata.WorkflowUpdateResponse.TabletInfo - 332, // 193: vtctldata.GetMirrorRulesResponse.mirror_rules:type_name -> vschema.MirrorRules - 316, // 194: vtctldata.WorkflowMirrorTrafficRequest.tablet_types:type_name -> topodata.TabletType - 255, // 195: vtctldata.Workflow.ShardStreamsEntry.value:type_name -> vtctldata.Workflow.ShardStream - 256, // 196: vtctldata.Workflow.ShardStream.streams:type_name -> vtctldata.Workflow.Stream - 333, // 197: vtctldata.Workflow.ShardStream.tablet_controls:type_name -> topodata.Shard.TabletControl - 307, // 198: vtctldata.Workflow.Stream.tablet:type_name -> topodata.TabletAlias - 334, // 199: vtctldata.Workflow.Stream.binlog_source:type_name -> binlogdata.BinlogSource - 306, // 200: vtctldata.Workflow.Stream.transaction_timestamp:type_name -> vttime.Time - 306, // 201: vtctldata.Workflow.Stream.time_updated:type_name -> vttime.Time - 257, // 202: vtctldata.Workflow.Stream.copy_states:type_name -> vtctldata.Workflow.Stream.CopyState - 258, // 203: vtctldata.Workflow.Stream.logs:type_name -> vtctldata.Workflow.Stream.Log - 259, // 204: vtctldata.Workflow.Stream.throttler_status:type_name -> vtctldata.Workflow.Stream.ThrottlerStatus - 316, // 205: vtctldata.Workflow.Stream.tablet_types:type_name -> topodata.TabletType - 304, // 206: vtctldata.Workflow.Stream.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 306, // 207: vtctldata.Workflow.Stream.Log.created_at:type_name -> vttime.Time - 306, // 208: vtctldata.Workflow.Stream.Log.updated_at:type_name -> vttime.Time - 306, // 209: vtctldata.Workflow.Stream.ThrottlerStatus.time_throttled:type_name -> vttime.Time - 262, // 210: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry.value:type_name -> vtctldata.ApplyVSchemaResponse.ParamList - 264, // 211: vtctldata.CheckThrottlerResponse.MetricsEntry.value:type_name -> vtctldata.CheckThrottlerResponse.Metric - 10, // 212: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry.value:type_name -> vtctldata.Shard - 330, // 213: vtctldata.GetCellsAliasesResponse.AliasesEntry.value:type_name -> topodata.CellsAlias - 335, // 214: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry.value:type_name -> topodata.ShardReplication - 273, // 215: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry.value:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NameList - 336, // 216: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry.value:type_name -> topodata.SrvKeyspace - 327, // 217: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry.value:type_name -> vschema.SrvVSchema - 276, // 218: vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.MetricResult - 306, // 219: vtctldata.GetThrottlerStatusResponse.MetricHealth.last_healthy_at:type_name -> vttime.Time - 279, // 220: vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.MetricHealth - 326, // 221: vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry.value:type_name -> topodata.ThrottledAppRule - 306, // 222: vtctldata.GetThrottlerStatusResponse.RecentApp.checked_at:type_name -> vttime.Time - 283, // 223: vtctldata.GetThrottlerStatusResponse.RecentAppsEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.RecentApp - 307, // 224: vtctldata.MoveTablesCreateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 337, // 225: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry.value:type_name -> replicationdata.Status - 317, // 226: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry.value:type_name -> topodata.Tablet - 220, // 227: vtctldata.ValidateResponse.ResultsByKeyspaceEntry.value:type_name -> vtctldata.ValidateKeyspaceResponse - 224, // 228: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 229: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 230: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 231: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 338, // 232: vtctldata.VDiffShowResponse.TabletResponsesEntry.value:type_name -> tabletmanagerdata.VDiffResponse - 307, // 233: vtctldata.WorkflowDeleteResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 307, // 234: vtctldata.WorkflowStatusResponse.ShardStreamState.tablet:type_name -> topodata.TabletAlias - 298, // 235: vtctldata.WorkflowStatusResponse.ShardStreams.streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamState - 297, // 236: vtctldata.WorkflowStatusResponse.TableCopyStateEntry.value:type_name -> vtctldata.WorkflowStatusResponse.TableCopyState - 299, // 237: vtctldata.WorkflowStatusResponse.ShardStreamsEntry.value:type_name -> vtctldata.WorkflowStatusResponse.ShardStreams - 307, // 238: vtctldata.WorkflowUpdateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 239, // [239:239] is the sub-list for method output_type - 239, // [239:239] is the sub-list for method input_type - 239, // [239:239] is the sub-list for extension type_name - 239, // [239:239] is the sub-list for extension extendee - 0, // [0:239] is the sub-list for field type_name + 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() } @@ -23349,19 +22743,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[260].Exporter = func(v any, i int) any { - switch v := v.(*CheckThrottlerResponse_Metric); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_vtctldata_proto_msgTypes[269].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[267].Exporter = func(v any, i int) any { switch v := v.(*GetSrvKeyspaceNamesResponse_NameList); i { case 0: return &v.state @@ -23373,43 +22755,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[272].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_MetricResult); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_vtctldata_proto_msgTypes[275].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_MetricHealth); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_vtctldata_proto_msgTypes[279].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_RecentApp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_vtctldata_proto_msgTypes[282].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 @@ -23421,7 +22767,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[292].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 @@ -23433,7 +22779,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[293].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 @@ -23445,7 +22791,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[294].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 @@ -23457,7 +22803,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[295].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 @@ -23469,7 +22815,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[298].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 @@ -23488,7 +22834,7 @@ func file_vtctldata_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vtctldata_proto_rawDesc, NumEnums: 4, - NumMessages: 299, + 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 cd52155d618..10fa4a62265 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)) @@ -3629,6 +3484,7 @@ func (m *PlannedReparentShardRequest) CloneVT() *PlannedReparentShardRequest { AvoidPrimary: m.AvoidPrimary.CloneVT(), WaitReplicasTimeout: m.WaitReplicasTimeout.CloneVT(), TolerableReplicationLag: m.TolerableReplicationLag.CloneVT(), + AllowCrossCellPromotion: m.AllowCrossCellPromotion, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -5268,6 +5124,7 @@ func (m *VDiffCreateRequest) CloneVT() *VDiffCreateRequest { Verbose: m.Verbose, MaxReportSampleRows: m.MaxReportSampleRows, MaxDiffDuration: m.MaxDiffDuration.CloneVT(), + RowDiffColumnTruncateAt: m.RowDiffColumnTruncateAt, } if rhs := m.SourceCells; rhs != nil { tmpContainer := make([]string, len(rhs)) @@ -8867,84 +8724,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 @@ -8975,68 +8754,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 } @@ -13066,148 +12802,6 @@ 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) { - 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_RecentApp) MarshalToVT(dAtA []byte) (int, error) { - size := m.SizeVT() - return m.MarshalToSizedBufferVT(dAtA[:size]) -} - -func (m *GetThrottlerStatusResponse_RecentApp) 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.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 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) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -13238,232 +12832,13 @@ func (m *GetThrottlerStatusResponse) MarshalToSizedBufferVT(dAtA []byte) (int, e 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 + if m.Status != nil { + size, err := m.Status.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err } - 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 -= size + i = encodeVarint(dAtA, i, uint64(size)) i-- dAtA[i] = 0xa } @@ -15714,6 +15089,16 @@ func (m *PlannedReparentShardRequest) MarshalToSizedBufferVT(dAtA []byte) (int, i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.AllowCrossCellPromotion { + i-- + if m.AllowCrossCellPromotion { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } if m.TolerableReplicationLag != nil { size, err := m.TolerableReplicationLag.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -19839,6 +19224,13 @@ func (m *VDiffCreateRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.RowDiffColumnTruncateAt != 0 { + i = encodeVarint(dAtA, i, uint64(m.RowDiffColumnTruncateAt)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa8 + } if m.MaxDiffDuration != nil { size, err := m.MaxDiffDuration.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -22700,80 +22092,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 } @@ -24230,173 +23562,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 } @@ -25258,6 +24433,9 @@ func (m *PlannedReparentShardRequest) SizeVT() (n int) { l = m.TolerableReplicationLag.SizeVT() n += 1 + l + sov(uint64(l)) } + if m.AllowCrossCellPromotion { + n += 2 + } n += len(m.unknownFields) return n } @@ -26850,6 +26028,9 @@ func (m *VDiffCreateRequest) SizeVT() (n int) { l = m.MaxDiffDuration.SizeVT() n += 2 + l + sov(uint64(l)) } + if m.RowDiffColumnTruncateAt != 0 { + n += 2 + sov(uint64(m.RowDiffColumnTruncateAt)) + } n += len(m.unknownFields) return n } @@ -35522,7 +34703,7 @@ func (m *CheckThrottlerRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { +func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -35545,17 +34726,17 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CheckThrottlerResponse_Metric: wiretype end group for non-group") + return fmt.Errorf("proto: CheckThrottlerResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CheckThrottlerResponse_Metric: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CheckThrottlerResponse: 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) + 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 @@ -35565,29 +34746,33 @@ func (m *CheckThrottlerResponse_Metric) 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.Name = string(dAtA[iNdEx:postIndex]) + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.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) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Check", wireType) } - m.StatusCode = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -35597,36 +34782,82 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.StatusCode |= int32(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - case 3: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + if msglen < 0 { + return ErrInvalidLength } - var v uint64 - if (iNdEx + 8) > l { + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > 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) + if m.Check == nil { + m.Check = &tabletmanagerdata.CheckThrottlerResponse{} } - var v uint64 - if (iNdEx + 8) > l { + if err := m.Check.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 } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Threshold = float64(math.Float64frombits(v)) - case 5: + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CleanupSchemaMigrationRequest) 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: CleanupSchemaMigrationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CleanupSchemaMigrationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -35654,11 +34885,11 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Error = string(dAtA[iNdEx:postIndex]) + m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -35686,13 +34917,64 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Message = string(dAtA[iNdEx:postIndex]) + m.Uuid = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 7: + 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 *CleanupSchemaMigrationResponse) 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: CleanupSchemaMigrationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CleanupSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Scope", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -35702,23 +34984,104 @@ func (m *CheckThrottlerResponse_Metric) 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.Scope = string(dAtA[iNdEx:postIndex]) + if m.RowsAffectedByShard == nil { + m.RowsAffectedByShard = make(map[string]uint64) + } + var mapkey string + var mapvalue uint64 + 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 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + } 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.RowsAffectedByShard[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -35742,7 +35105,7 @@ func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { +func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -35765,56 +35128,15 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CheckThrottlerResponse: wiretype end group for non-group") + return fmt.Errorf("proto: CompleteSchemaMigrationRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CheckThrottlerResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CompleteSchemaMigrationRequest: illegal tag %d (wire type %d)", fieldNum, wire) } 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 Keyspace", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -35842,11 +35164,11 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Error = string(dAtA[iNdEx:postIndex]) + m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -35874,31 +35196,62 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Message = string(dAtA[iNdEx:postIndex]) + m.Uuid = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RecentlyChecked", wireType) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - 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 - } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength } - m.RecentlyChecked = bool(v != 0) - case 7: + 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 *CompleteSchemaMigrationResponse) 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: CompleteSchemaMigrationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CompleteSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Metrics", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -35925,11 +35278,11 @@ 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.RowsAffectedByShard == nil { + m.RowsAffectedByShard = make(map[string]uint64) } var mapkey string - var mapvalue *CheckThrottlerResponse_Metric + var mapvalue uint64 for iNdEx < postIndex { entryPreIndex := iNdEx var wire uint64 @@ -35978,7 +35331,6 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { 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 @@ -35988,26 +35340,11 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - mapmsglen |= int(b&0x7F) << shift + mapvalue |= uint64(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:]) @@ -36023,7 +35360,7 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { iNdEx += skippy } } - m.Metrics[mapkey] = mapvalue + m.RowsAffectedByShard[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -36047,7 +35384,7 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CleanupSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { +func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36070,15 +35407,15 @@ func (m *CleanupSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CleanupSchemaMigrationRequest: wiretype end group for non-group") + return fmt.Errorf("proto: CreateKeyspaceRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CleanupSchemaMigrationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CreateKeyspaceRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -36106,11 +35443,70 @@ func (m *CleanupSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Keyspace = string(dAtA[iNdEx:postIndex]) + m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Force = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowEmptyVSchema", 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.AllowEmptyVSchema = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= topodata.KeyspaceType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field BaseKeyspace", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -36138,7 +35534,107 @@ func (m *CleanupSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Uuid = string(dAtA[iNdEx:postIndex]) + m.BaseKeyspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SnapshotTime", 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.SnapshotTime == nil { + m.SnapshotTime = &vttime.Time{} + } + if err := m.SnapshotTime.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DurabilityPolicy", 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.DurabilityPolicy = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SidecarDbName", 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.SidecarDbName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -36162,7 +35658,7 @@ func (m *CleanupSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CleanupSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { +func (m *CreateKeyspaceResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36185,15 +35681,15 @@ func (m *CleanupSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CleanupSchemaMigrationResponse: wiretype end group for non-group") + return fmt.Errorf("proto: CreateKeyspaceResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CleanupSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CreateKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -36220,89 +35716,12 @@ func (m *CleanupSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.RowsAffectedByShard == nil { - m.RowsAffectedByShard = make(map[string]uint64) + if m.Keyspace == nil { + m.Keyspace = &Keyspace{} } - var mapkey string - var mapvalue uint64 - 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 { - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - } 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.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.RowsAffectedByShard[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -36326,7 +35745,7 @@ func (m *CleanupSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { +func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36349,10 +35768,10 @@ func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CompleteSchemaMigrationRequest: wiretype end group for non-group") + return fmt.Errorf("proto: CreateShardRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CompleteSchemaMigrationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CreateShardRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -36389,7 +35808,7 @@ func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ShardName", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -36417,8 +35836,48 @@ func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Uuid = string(dAtA[iNdEx:postIndex]) + m.ShardName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Force = bool(v != 0) + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IncludeParent", 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.IncludeParent = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -36441,7 +35900,7 @@ func (m *CompleteSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CompleteSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { +func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36464,15 +35923,15 @@ func (m *CompleteSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CompleteSchemaMigrationResponse: wiretype end group for non-group") + return fmt.Errorf("proto: CreateShardResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CompleteSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CreateShardResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -36499,90 +35958,69 @@ func (m *CompleteSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.RowsAffectedByShard == nil { - m.RowsAffectedByShard = make(map[string]uint64) + if m.Keyspace == nil { + m.Keyspace = &Keyspace{} } - var mapkey string - var mapvalue uint64 - 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 - } + if err := m.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow } - 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 { - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - } 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 iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break } } - m.RowsAffectedByShard[mapkey] = mapvalue + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Shard == nil { + m.Shard = &Shard{} + } + if err := m.Shard.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ShardAlreadyExists", 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.ShardAlreadyExists = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -36605,7 +36043,7 @@ func (m *CompleteSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { +func (m *DeleteCellInfoRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36628,10 +36066,10 @@ func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CreateKeyspaceRequest: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteCellInfoRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CreateKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteCellInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -36686,148 +36124,111 @@ func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { } } m.Force = bool(v != 0) - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowEmptyVSchema", 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.AllowEmptyVSchema = bool(v != 0) - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) - } - m.Type = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Type |= topodata.KeyspaceType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BaseKeyspace", 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 + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - postIndex := iNdEx + intStringLen - if postIndex < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.BaseKeyspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SnapshotTime", 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 + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DeleteCellInfoResponse) 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 postIndex > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - if m.SnapshotTime == nil { - m.SnapshotTime = &vttime.Time{} + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break } - if err := m.SnapshotTime.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DeleteCellInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DeleteCellInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { return err } - iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DurabilityPolicy", 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 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DeleteCellsAliasRequest) 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 } - m.DurabilityPolicy = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 11: + 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: DeleteCellsAliasRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DeleteCellsAliasRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SidecarDbName", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -36855,7 +36256,7 @@ func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.SidecarDbName = string(dAtA[iNdEx:postIndex]) + m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -36879,7 +36280,7 @@ func (m *CreateKeyspaceRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CreateKeyspaceResponse) UnmarshalVT(dAtA []byte) error { +func (m *DeleteCellsAliasResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36902,48 +36303,12 @@ func (m *CreateKeyspaceResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CreateKeyspaceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteCellsAliasResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CreateKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteCellsAliasResponse: 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 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.Keyspace == nil { - m.Keyspace = &Keyspace{} - } - if err := m.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -36966,7 +36331,7 @@ func (m *CreateKeyspaceResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { +func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -36989,10 +36354,10 @@ func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CreateShardRequest: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteKeyspaceRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CreateShardRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -37028,10 +36393,10 @@ func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ShardName", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Recursive", wireType) } - var stringLen uint64 + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -37041,24 +36406,12 @@ func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + v |= int(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.ShardName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex + m.Recursive = bool(v != 0) case 3: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) @@ -37079,26 +36432,57 @@ func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { } } m.Force = bool(v != 0) - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IncludeParent", wireType) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - 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 - } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength } - m.IncludeParent = bool(v != 0) + 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 *DeleteKeyspaceResponse) 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: DeleteKeyspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DeleteKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37121,7 +36505,7 @@ func (m *CreateShardRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { +func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37144,15 +36528,15 @@ func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CreateShardResponse: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteShardsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CreateShardResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteShardsRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Shards", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -37179,18 +36563,16 @@ func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Keyspace == nil { - m.Keyspace = &Keyspace{} - } - if err := m.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Shards = append(m.Shards, &Shard{}) + if err := m.Shards[len(m.Shards)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Recursive", wireType) } - var msglen int + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -37200,31 +36582,35 @@ func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + v |= 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.Shard == nil { - m.Shard = &Shard{} + m.Recursive = bool(v != 0) + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EvenIfServing", wireType) } - if err := m.Shard.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + 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 + } } - iNdEx = postIndex - case 3: + m.EvenIfServing = bool(v != 0) + case 5: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ShardAlreadyExists", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -37241,7 +36627,7 @@ func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { break } } - m.ShardAlreadyExists = bool(v != 0) + m.Force = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37264,7 +36650,7 @@ func (m *CreateShardResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteCellInfoRequest) UnmarshalVT(dAtA []byte) error { +func (m *DeleteShardsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37287,15 +36673,66 @@ func (m *DeleteCellInfoRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteCellInfoRequest: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteShardsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteCellInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteShardsResponse: 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 *DeleteSrvVSchemaRequest) 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: DeleteSrvVSchemaRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DeleteSrvVSchemaRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -37323,28 +36760,8 @@ func (m *DeleteCellInfoRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Name = string(dAtA[iNdEx:postIndex]) + m.Cell = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Force = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37367,7 +36784,7 @@ func (m *DeleteCellInfoRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteCellInfoResponse) UnmarshalVT(dAtA []byte) error { +func (m *DeleteSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37390,10 +36807,10 @@ func (m *DeleteCellInfoResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteCellInfoResponse: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteSrvVSchemaResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteCellInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteSrvVSchemaResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -37418,7 +36835,7 @@ func (m *DeleteCellInfoResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteCellsAliasRequest) UnmarshalVT(dAtA []byte) error { +func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37441,17 +36858,17 @@ func (m *DeleteCellsAliasRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteCellsAliasRequest: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteTabletsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteCellsAliasRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteTabletsRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAliases", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -37461,24 +36878,46 @@ func (m *DeleteCellsAliasRequest) 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.Name = string(dAtA[iNdEx:postIndex]) + m.TabletAliases = append(m.TabletAliases, &topodata.TabletAlias{}) + if err := m.TabletAliases[len(m.TabletAliases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowPrimary", 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.AllowPrimary = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37501,7 +36940,7 @@ func (m *DeleteCellsAliasRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteCellsAliasResponse) UnmarshalVT(dAtA []byte) error { +func (m *DeleteTabletsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37524,10 +36963,10 @@ func (m *DeleteCellsAliasResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteCellsAliasResponse: wiretype end group for non-group") + return fmt.Errorf("proto: DeleteTabletsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteCellsAliasResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DeleteTabletsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -37552,7 +36991,7 @@ func (m *DeleteCellsAliasResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { +func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37575,10 +37014,10 @@ func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteKeyspaceRequest: wiretype end group for non-group") + return fmt.Errorf("proto: EmergencyReparentShardRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EmergencyReparentShardRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -37614,8 +37053,146 @@ func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + 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 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewPrimary", 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.NewPrimary == nil { + m.NewPrimary = &topodata.TabletAlias{} + } + if err := m.NewPrimary.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IgnoreReplicas", 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.IgnoreReplicas = append(m.IgnoreReplicas, &topodata.TabletAlias{}) + if err := m.IgnoreReplicas[len(m.IgnoreReplicas)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WaitReplicasTimeout", 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.WaitReplicasTimeout == nil { + m.WaitReplicasTimeout = &vttime.Duration{} + } + if err := m.WaitReplicasTimeout.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Recursive", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field PreventCrossCellPromotion", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -37632,10 +37209,10 @@ func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { break } } - m.Recursive = bool(v != 0) - case 3: + m.PreventCrossCellPromotion = bool(v != 0) + case 7: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field WaitForAllTablets", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -37652,7 +37229,7 @@ func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { break } } - m.Force = bool(v != 0) + m.WaitForAllTablets = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37675,7 +37252,7 @@ func (m *DeleteKeyspaceRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteKeyspaceResponse) UnmarshalVT(dAtA []byte) error { +func (m *EmergencyReparentShardResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37698,12 +37275,146 @@ func (m *DeleteKeyspaceResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteKeyspaceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: EmergencyReparentShardResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EmergencyReparentShardResponse: 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 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 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PromotedPrimary", 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.PromotedPrimary == nil { + m.PromotedPrimary = &topodata.TabletAlias{} + } + if err := m.PromotedPrimary.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", 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.Events = append(m.Events, &logutil.Event{}) + if err := m.Events[len(m.Events)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37726,7 +37437,7 @@ func (m *DeleteKeyspaceResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37749,15 +37460,15 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteShardsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteFetchAsAppRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteShardsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteFetchAsAppRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shards", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -37784,16 +37495,18 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Shards = append(m.Shards, &Shard{}) - if err := m.Shards[len(m.Shards)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Recursive", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -37803,17 +37516,29 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.Recursive = bool(v != 0) - case 4: + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Query = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field EvenIfServing", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) } - var v int + m.MaxRows = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -37823,15 +37548,14 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + m.MaxRows |= int64(b&0x7F) << shift if b < 0x80 { break } } - m.EvenIfServing = bool(v != 0) - case 5: + case 4: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field UsePool", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -37848,7 +37572,7 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { break } } - m.Force = bool(v != 0) + m.UsePool = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -37871,7 +37595,7 @@ func (m *DeleteShardsRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteShardsResponse) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteFetchAsAppResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37894,25 +37618,61 @@ func (m *DeleteShardsResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteShardsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteFetchAsAppResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteShardsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteFetchAsAppResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength + 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 (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF + if msglen < 0 { + return ErrInvalidLength } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Result == nil { + m.Result = &query.QueryResult{} + } + if err := m.Result.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 } } @@ -37922,7 +37682,7 @@ func (m *DeleteShardsResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -37945,15 +37705,51 @@ func (m *DeleteSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteSrvVSchemaRequest: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteFetchAsDBARequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteSrvVSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteFetchAsDBARequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", 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.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -37981,8 +37777,67 @@ func (m *DeleteSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Cell = string(dAtA[iNdEx:postIndex]) + m.Query = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) + } + m.MaxRows = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxRows |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DisableBinlogs", 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.DisableBinlogs = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReloadSchema", 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.ReloadSchema = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38005,7 +37860,7 @@ func (m *DeleteSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38028,12 +37883,48 @@ func (m *DeleteSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteSrvVSchemaResponse: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteFetchAsDBAResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteSrvVSchemaResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteFetchAsDBAResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", 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.Result == nil { + m.Result = &query.QueryResult{} + } + if err := m.Result.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38056,7 +37947,7 @@ func (m *DeleteSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteHookRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38079,15 +37970,15 @@ func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteTabletsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteHookRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteTabletsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteHookRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TabletAliases", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -38114,16 +38005,18 @@ func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.TabletAliases = append(m.TabletAliases, &topodata.TabletAlias{}) - if err := m.TabletAliases[len(m.TabletAliases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowPrimary", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TabletHookRequest", wireType) } - var v int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38133,12 +38026,28 @@ func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - m.AllowPrimary = bool(v != 0) + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TabletHookRequest == nil { + m.TabletHookRequest = &tabletmanagerdata.ExecuteHookRequest{} + } + if err := m.TabletHookRequest.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38161,7 +38070,7 @@ func (m *DeleteTabletsRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DeleteTabletsResponse) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteHookResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38184,12 +38093,48 @@ func (m *DeleteTabletsResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DeleteTabletsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteHookResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteTabletsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteHookResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HookResult", 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.HookResult == nil { + m.HookResult = &tabletmanagerdata.ExecuteHookResponse{} + } + if err := m.HookResult.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38212,7 +38157,7 @@ func (m *DeleteTabletsResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteMultiFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38235,17 +38180,17 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: EmergencyReparentShardRequest: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteMultiFetchAsDBARequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: EmergencyReparentShardRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteMultiFetchAsDBARequest: 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) + 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 @@ -38255,27 +38200,31 @@ func (m *EmergencyReparentShardRequest) 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.Keyspace = string(dAtA[iNdEx:postIndex]) + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Sql", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -38303,13 +38252,13 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Shard = string(dAtA[iNdEx:postIndex]) + m.Sql = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewPrimary", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) } - var msglen int + m.MaxRows = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38319,101 +38268,14 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.MaxRows |= int64(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.NewPrimary == nil { - m.NewPrimary = &topodata.TabletAlias{} - } - if err := m.NewPrimary.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field IgnoreReplicas", 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.IgnoreReplicas = append(m.IgnoreReplicas, &topodata.TabletAlias{}) - if err := m.IgnoreReplicas[len(m.IgnoreReplicas)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field WaitReplicasTimeout", 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.WaitReplicasTimeout == nil { - m.WaitReplicasTimeout = &vttime.Duration{} - } - if err := m.WaitReplicasTimeout.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field PreventCrossCellPromotion", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DisableBinlogs", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -38430,10 +38292,10 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { break } } - m.PreventCrossCellPromotion = bool(v != 0) - case 7: + m.DisableBinlogs = bool(v != 0) + case 5: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field WaitForAllTablets", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ReloadSchema", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -38450,7 +38312,7 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { break } } - m.WaitForAllTablets = bool(v != 0) + m.ReloadSchema = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38473,7 +38335,7 @@ func (m *EmergencyReparentShardRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *EmergencyReparentShardResponse) UnmarshalVT(dAtA []byte) error { +func (m *ExecuteMultiFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38496,115 +38358,15 @@ func (m *EmergencyReparentShardResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: EmergencyReparentShardResponse: wiretype end group for non-group") + return fmt.Errorf("proto: ExecuteMultiFetchAsDBAResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: EmergencyReparentShardResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExecuteMultiFetchAsDBAResponse: 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 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 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PromotedPrimary", 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.PromotedPrimary == nil { - m.PromotedPrimary = &topodata.TabletAlias{} - } - if err := m.PromotedPrimary.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Results", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -38631,8 +38393,8 @@ func (m *EmergencyReparentShardResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Events = append(m.Events, &logutil.Event{}) - if err := m.Events[len(m.Events)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Results = append(m.Results, &query.QueryResult{}) + if err := m.Results[len(m.Results)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -38658,7 +38420,7 @@ func (m *EmergencyReparentShardResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { +func (m *FindAllShardsInKeyspaceRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38681,17 +38443,17 @@ func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteFetchAsAppRequest: wiretype end group for non-group") + return fmt.Errorf("proto: FindAllShardsInKeyspaceRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteFetchAsAppRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FindAllShardsInKeyspaceRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38701,33 +38463,80 @@ func (m *ExecuteFetchAsAppRequest) 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Keyspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { return err } - iNdEx = postIndex - case 2: + 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 *FindAllShardsInKeyspaceResponse) 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: FindAllShardsInKeyspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FindAllShardsInKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Shards", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38737,29 +38546,177 @@ func (m *ExecuteFetchAsAppRequest) 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.Query = string(dAtA[iNdEx:postIndex]) + if m.Shards == nil { + m.Shards = make(map[string]*Shard) + } + var mapkey string + var mapvalue *Shard + 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 = &Shard{} + 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.Shards[mapkey] = mapvalue iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - m.MaxRows = 0 + 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 *ForceCutOverSchemaMigrationRequest) 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: ForceCutOverSchemaMigrationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ForceCutOverSchemaMigrationRequest: 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 @@ -38769,16 +38726,29 @@ func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.MaxRows |= int64(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field UsePool", wireType) + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength } - var v int + 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 Uuid", wireType) + } + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38788,12 +38758,24 @@ func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.UsePool = bool(v != 0) + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Uuid = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -38816,7 +38798,7 @@ func (m *ExecuteFetchAsAppRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteFetchAsAppResponse) UnmarshalVT(dAtA []byte) error { +func (m *ForceCutOverSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38839,15 +38821,15 @@ func (m *ExecuteFetchAsAppResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteFetchAsAppResponse: wiretype end group for non-group") + return fmt.Errorf("proto: ForceCutOverSchemaMigrationResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteFetchAsAppResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ForceCutOverSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -38874,12 +38856,89 @@ func (m *ExecuteFetchAsAppResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Result == nil { - m.Result = &query.QueryResult{} + if m.RowsAffectedByShard == nil { + m.RowsAffectedByShard = make(map[string]uint64) } - if err := m.Result.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + var mapkey string + var mapvalue uint64 + 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 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + } 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.RowsAffectedByShard[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -38903,7 +38962,7 @@ func (m *ExecuteFetchAsAppResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { +func (m *GetBackupsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -38926,17 +38985,17 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteFetchAsDBARequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetBackupsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteFetchAsDBARequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetBackupsRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -38946,31 +39005,27 @@ func (m *ExecuteFetchAsDBARequest) 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -38998,13 +39053,13 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Query = string(dAtA[iNdEx:postIndex]) + m.Shard = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) } - m.MaxRows = 0 + m.Limit = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -39014,14 +39069,14 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.MaxRows |= int64(b&0x7F) << shift + m.Limit |= uint32(b&0x7F) << shift if b < 0x80 { break } } case 4: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DisableBinlogs", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Detailed", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -39038,12 +39093,12 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { break } } - m.DisableBinlogs = bool(v != 0) + m.Detailed = bool(v != 0) case 5: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReloadSchema", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DetailedLimit", wireType) } - var v int + m.DetailedLimit = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -39053,12 +39108,11 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + m.DetailedLimit |= uint32(b&0x7F) << shift if b < 0x80 { break } } - m.ReloadSchema = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -39081,7 +39135,7 @@ func (m *ExecuteFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetBackupsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39104,15 +39158,15 @@ func (m *ExecuteFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteFetchAsDBAResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetBackupsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteFetchAsDBAResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetBackupsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Backups", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39139,10 +39193,8 @@ func (m *ExecuteFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Result == nil { - m.Result = &query.QueryResult{} - } - if err := m.Result.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Backups = append(m.Backups, &mysqlctl.BackupInfo{}) + if err := m.Backups[len(m.Backups)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -39168,7 +39220,7 @@ func (m *ExecuteFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteHookRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetCellInfoRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39191,53 +39243,17 @@ func (m *ExecuteHookRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteHookRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellInfoRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteHookRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellInfoRequest: 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 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TabletHookRequest", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -39247,27 +39263,23 @@ func (m *ExecuteHookRequest) 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.TabletHookRequest == nil { - m.TabletHookRequest = &tabletmanagerdata.ExecuteHookRequest{} - } - if err := m.TabletHookRequest.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Cell = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -39291,7 +39303,7 @@ func (m *ExecuteHookRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteHookResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetCellInfoResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39314,15 +39326,15 @@ func (m *ExecuteHookResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteHookResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellInfoResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteHookResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HookResult", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CellInfo", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39349,10 +39361,10 @@ func (m *ExecuteHookResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.HookResult == nil { - m.HookResult = &tabletmanagerdata.ExecuteHookResponse{} + if m.CellInfo == nil { + m.CellInfo = &topodata.CellInfo{} } - if err := m.HookResult.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.CellInfo.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -39378,7 +39390,7 @@ func (m *ExecuteHookResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteMultiFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { +func (m *GetCellInfoNamesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39401,139 +39413,12 @@ func (m *ExecuteMultiFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteMultiFetchAsDBARequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellInfoNamesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteMultiFetchAsDBARequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellInfoNamesRequest: 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 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sql", 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.Sql = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxRows", wireType) - } - m.MaxRows = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.MaxRows |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DisableBinlogs", 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.DisableBinlogs = bool(v != 0) - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReloadSchema", 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.ReloadSchema = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -39556,7 +39441,7 @@ func (m *ExecuteMultiFetchAsDBARequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ExecuteMultiFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetCellInfoNamesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39579,17 +39464,17 @@ func (m *ExecuteMultiFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExecuteMultiFetchAsDBAResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellInfoNamesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExecuteMultiFetchAsDBAResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellInfoNamesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Results", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -39599,25 +39484,23 @@ func (m *ExecuteMultiFetchAsDBAResponse) 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 } - m.Results = append(m.Results, &query.QueryResult{}) - if err := m.Results[len(m.Results)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Names = append(m.Names, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -39641,7 +39524,7 @@ func (m *ExecuteMultiFetchAsDBAResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *FindAllShardsInKeyspaceRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetCellsAliasesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39664,44 +39547,12 @@ func (m *FindAllShardsInKeyspaceRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: FindAllShardsInKeyspaceRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellsAliasesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: FindAllShardsInKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellsAliasesRequest: 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 default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -39724,7 +39575,7 @@ func (m *FindAllShardsInKeyspaceRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetCellsAliasesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39747,15 +39598,15 @@ func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: FindAllShardsInKeyspaceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetCellsAliasesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: FindAllShardsInKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetCellsAliasesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shards", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Aliases", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39782,11 +39633,11 @@ func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Shards == nil { - m.Shards = make(map[string]*Shard) + if m.Aliases == nil { + m.Aliases = make(map[string]*topodata.CellsAlias) } var mapkey string - var mapvalue *Shard + var mapvalue *topodata.CellsAlias for iNdEx < postIndex { entryPreIndex := iNdEx var wire uint64 @@ -39860,7 +39711,7 @@ func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &Shard{} + mapvalue = &topodata.CellsAlias{} if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -39880,7 +39731,7 @@ func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { iNdEx += skippy } } - m.Shards[mapkey] = mapvalue + m.Aliases[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -39904,7 +39755,7 @@ func (m *FindAllShardsInKeyspaceResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ForceCutOverSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetFullStatusRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -39927,17 +39778,17 @@ func (m *ForceCutOverSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ForceCutOverSchemaMigrationRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetFullStatusRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ForceCutOverSchemaMigrationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetFullStatusRequest: 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) + 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 @@ -39947,55 +39798,27 @@ func (m *ForceCutOverSchemaMigrationRequest) 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.Keyspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Uuid", 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.Uuid = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -40019,7 +39842,7 @@ func (m *ForceCutOverSchemaMigrationRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *ForceCutOverSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetFullStatusResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40042,15 +39865,15 @@ func (m *ForceCutOverSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ForceCutOverSchemaMigrationResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetFullStatusResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ForceCutOverSchemaMigrationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetFullStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RowsAffectedByShard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -40077,89 +39900,12 @@ func (m *ForceCutOverSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.RowsAffectedByShard == nil { - m.RowsAffectedByShard = make(map[string]uint64) + if m.Status == nil { + m.Status = &replicationdata.FullStatus{} } - var mapkey string - var mapvalue uint64 - 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 { - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - } 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.Status.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.RowsAffectedByShard[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -40183,7 +39929,7 @@ func (m *ForceCutOverSchemaMigrationResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetBackupsRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspacesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40206,134 +39952,12 @@ func (m *GetBackupsRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetBackupsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspacesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetBackupsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspacesRequest: 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 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 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) - } - m.Limit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Limit |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Detailed", 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.Detailed = bool(v != 0) - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DetailedLimit", wireType) - } - m.DetailedLimit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DetailedLimit |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -40356,7 +39980,7 @@ func (m *GetBackupsRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetBackupsResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspacesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40379,15 +40003,15 @@ func (m *GetBackupsResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetBackupsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspacesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetBackupsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Backups", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspaces", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -40414,8 +40038,8 @@ func (m *GetBackupsResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Backups = append(m.Backups, &mysqlctl.BackupInfo{}) - if err := m.Backups[len(m.Backups)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Keyspaces = append(m.Keyspaces, &Keyspace{}) + if err := m.Keyspaces[len(m.Keyspaces)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -40441,7 +40065,7 @@ func (m *GetBackupsResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellInfoRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspaceRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40464,15 +40088,15 @@ func (m *GetCellInfoRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellInfoRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspaceRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -40500,7 +40124,7 @@ func (m *GetCellInfoRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Cell = string(dAtA[iNdEx:postIndex]) + m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -40524,7 +40148,7 @@ func (m *GetCellInfoRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellInfoResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspaceResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40547,15 +40171,15 @@ func (m *GetCellInfoResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellInfoResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspaceResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CellInfo", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -40582,10 +40206,10 @@ func (m *GetCellInfoResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.CellInfo == nil { - m.CellInfo = &topodata.CellInfo{} + if m.Keyspace == nil { + m.Keyspace = &Keyspace{} } - if err := m.CellInfo.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -40611,7 +40235,7 @@ func (m *GetCellInfoResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellInfoNamesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetPermissionsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40634,12 +40258,48 @@ func (m *GetCellInfoNamesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellInfoNamesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetPermissionsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellInfoNamesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetPermissionsRequest: 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 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.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -40662,7 +40322,7 @@ func (m *GetCellInfoNamesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellInfoNamesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetPermissionsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40685,17 +40345,17 @@ func (m *GetCellInfoNamesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellInfoNamesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetPermissionsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellInfoNamesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetPermissionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -40705,23 +40365,27 @@ func (m *GetCellInfoNamesResponse) 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.Names = append(m.Names, string(dAtA[iNdEx:postIndex])) + if m.Permissions == nil { + m.Permissions = &tabletmanagerdata.Permissions{} + } + if err := m.Permissions.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -40745,7 +40409,7 @@ func (m *GetCellInfoNamesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellsAliasesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspaceRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40768,10 +40432,10 @@ func (m *GetCellsAliasesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellsAliasesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspaceRoutingRulesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellsAliasesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspaceRoutingRulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -40796,7 +40460,7 @@ func (m *GetCellsAliasesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetCellsAliasesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetKeyspaceRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40819,15 +40483,15 @@ func (m *GetCellsAliasesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetCellsAliasesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetKeyspaceRoutingRulesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetCellsAliasesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetKeyspaceRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Aliases", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field KeyspaceRoutingRules", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -40854,105 +40518,12 @@ func (m *GetCellsAliasesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Aliases == nil { - m.Aliases = make(map[string]*topodata.CellsAlias) + if m.KeyspaceRoutingRules == nil { + m.KeyspaceRoutingRules = &vschema.KeyspaceRoutingRules{} } - var mapkey string - var mapvalue *topodata.CellsAlias - 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.CellsAlias{} - 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.KeyspaceRoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.Aliases[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -40976,7 +40547,7 @@ func (m *GetCellsAliasesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetFullStatusRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -40999,48 +40570,12 @@ func (m *GetFullStatusRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetFullStatusRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetRoutingRulesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetFullStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetRoutingRulesRequest: 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 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -41063,7 +40598,7 @@ func (m *GetFullStatusRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetFullStatusResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41086,15 +40621,15 @@ func (m *GetFullStatusResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetFullStatusResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetRoutingRulesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetFullStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RoutingRules", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41121,10 +40656,10 @@ func (m *GetFullStatusResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Status == nil { - m.Status = &replicationdata.FullStatus{} + if m.RoutingRules == nil { + m.RoutingRules = &vschema.RoutingRules{} } - if err := m.Status.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.RoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -41150,58 +40685,7 @@ func (m *GetFullStatusResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetKeyspacesRequest) 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: GetKeyspacesRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspacesRequest: 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 *GetKeyspacesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSchemaRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41224,15 +40708,15 @@ func (m *GetKeyspacesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetKeyspacesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSchemaRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Keyspaces", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41259,65 +40743,48 @@ func (m *GetKeyspacesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Keyspaces = append(m.Keyspaces, &Keyspace{}) - if err := m.Keyspaces[len(m.Keyspaces)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} + } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tables", wireType) } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength + 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 + } } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GetKeyspaceRequest) 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 + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength } - if iNdEx >= l { + if postIndex > 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: GetKeyspaceRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + m.Tables = append(m.Tables, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ExcludeTables", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -41345,8 +40812,88 @@ func (m *GetKeyspaceRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Keyspace = string(dAtA[iNdEx:postIndex]) + m.ExcludeTables = append(m.ExcludeTables, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IncludeViews", 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.IncludeViews = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TableNamesOnly", 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.TableNamesOnly = bool(v != 0) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TableSizesOnly", 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.TableSizesOnly = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TableSchemaOnly", 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.TableSchemaOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -41369,7 +40916,7 @@ func (m *GetKeyspaceRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetKeyspaceResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSchemaResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41392,15 +40939,15 @@ func (m *GetKeyspaceResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetKeyspaceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSchemaResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSchemaResponse: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Schema", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41427,10 +40974,10 @@ func (m *GetKeyspaceResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Keyspace == nil { - m.Keyspace = &Keyspace{} + if m.Schema == nil { + m.Schema = &tabletmanagerdata.SchemaDefinition{} } - if err := m.Keyspace.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Schema.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -41456,7 +41003,7 @@ func (m *GetKeyspaceResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetPermissionsRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41479,17 +41026,17 @@ func (m *GetPermissionsRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetPermissionsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetSchemaMigrationsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetPermissionsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSchemaMigrationsRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -41499,51 +41046,223 @@ func (m *GetPermissionsRequest) 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Keyspace = 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 + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { + 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.Uuid = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MigrationContext", 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.MigrationContext = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= SchemaMigration_Status(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recent", 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.Recent == nil { + m.Recent = &vttime.Duration{} + } + if err := m.Recent.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Order", wireType) + } + m.Order = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Order |= QueryOrdering(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Skip", wireType) + } + m.Skip = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Skip |= uint64(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 *GetPermissionsResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSchemaMigrationsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41566,15 +41285,15 @@ func (m *GetPermissionsResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetPermissionsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSchemaMigrationsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetPermissionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSchemaMigrationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Migrations", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41601,10 +41320,8 @@ func (m *GetPermissionsResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Permissions == nil { - m.Permissions = &tabletmanagerdata.Permissions{} - } - if err := m.Permissions.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.Migrations = append(m.Migrations, &SchemaMigration{}) + if err := m.Migrations[len(m.Migrations)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -41630,7 +41347,7 @@ func (m *GetPermissionsResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetKeyspaceRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41653,12 +41370,108 @@ func (m *GetKeyspaceRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetKeyspaceRoutingRulesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardReplicationRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspaceRoutingRulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardReplicationRequest: 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 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 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cells", 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.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -41681,7 +41494,7 @@ func (m *GetKeyspaceRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetKeyspaceRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41704,15 +41517,15 @@ func (m *GetKeyspaceRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetKeyspaceRoutingRulesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardReplicationResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetKeyspaceRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardReplicationResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field KeyspaceRoutingRules", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ShardReplicationByCell", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41739,12 +41552,105 @@ func (m *GetKeyspaceRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.KeyspaceRoutingRules == nil { - m.KeyspaceRoutingRules = &vschema.KeyspaceRoutingRules{} + if m.ShardReplicationByCell == nil { + m.ShardReplicationByCell = make(map[string]*topodata.ShardReplication) } - if err := m.KeyspaceRoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + var mapkey string + var mapvalue *topodata.ShardReplication + 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.ShardReplication{} + 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.ShardReplicationByCell[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -41768,7 +41674,7 @@ func (m *GetKeyspaceRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetShardRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41791,12 +41697,76 @@ func (m *GetRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetRoutingRulesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetRoutingRulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardRequest: 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 ShardName", 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.ShardName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -41819,7 +41789,7 @@ func (m *GetRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetShardResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41842,15 +41812,15 @@ func (m *GetRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetRoutingRulesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RoutingRules", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -41877,10 +41847,10 @@ func (m *GetRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.RoutingRules == nil { - m.RoutingRules = &vschema.RoutingRules{} + if m.Shard == nil { + m.Shard = &Shard{} } - if err := m.RoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Shard.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -41906,7 +41876,7 @@ func (m *GetRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSchemaRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetShardRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -41929,192 +41899,12 @@ func (m *GetSchemaRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSchemaRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardRoutingRulesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardRoutingRulesRequest: 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 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tables", 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.Tables = append(m.Tables, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExcludeTables", 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.ExcludeTables = append(m.ExcludeTables, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IncludeViews", 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.IncludeViews = bool(v != 0) - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TableNamesOnly", 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.TableNamesOnly = bool(v != 0) - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TableSizesOnly", 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.TableSizesOnly = bool(v != 0) - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TableSchemaOnly", 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.TableSchemaOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -42137,7 +41927,7 @@ func (m *GetSchemaRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSchemaResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetShardRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42160,15 +41950,15 @@ func (m *GetSchemaResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSchemaResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetShardRoutingRulesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSchemaResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetShardRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Schema", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ShardRoutingRules", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -42195,10 +41985,10 @@ func (m *GetSchemaResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Schema == nil { - m.Schema = &tabletmanagerdata.SchemaDefinition{} + if m.ShardRoutingRules == nil { + m.ShardRoutingRules = &vschema.ShardRoutingRules{} } - if err := m.Schema.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ShardRoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -42224,7 +42014,7 @@ func (m *GetSchemaResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvKeyspaceNamesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42247,15 +42037,15 @@ func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSchemaMigrationsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvKeyspaceNamesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSchemaMigrationsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvKeyspaceNamesRequest: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -42283,43 +42073,62 @@ func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Keyspace = string(dAtA[iNdEx:postIndex]) + m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Uuid", 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 - } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetSrvKeyspaceNamesResponse_NameList) 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 } - m.Uuid = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: + 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: GetSrvKeyspaceNamesResponse_NameList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse_NameList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MigrationContext", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -42347,120 +42156,8 @@ func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.MigrationContext = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) - } - m.Status = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Status |= SchemaMigration_Status(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Recent", 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.Recent == nil { - m.Recent = &vttime.Duration{} - } - if err := m.Recent.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Names = append(m.Names, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Order", wireType) - } - m.Order = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Order |= QueryOrdering(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) - } - m.Limit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Limit |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Skip", wireType) - } - m.Skip = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Skip |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -42483,7 +42180,7 @@ func (m *GetSchemaMigrationsRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSchemaMigrationsResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42506,15 +42203,15 @@ func (m *GetSchemaMigrationsResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSchemaMigrationsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSchemaMigrationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Migrations", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -42541,10 +42238,105 @@ func (m *GetSchemaMigrationsResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Migrations = append(m.Migrations, &SchemaMigration{}) - if err := m.Migrations[len(m.Migrations)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + if m.Names == nil { + m.Names = make(map[string]*GetSrvKeyspaceNamesResponse_NameList) + } + var mapkey string + var mapvalue *GetSrvKeyspaceNamesResponse_NameList + 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 = &GetSrvKeyspaceNamesResponse_NameList{} + 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.Names[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -42568,7 +42360,7 @@ func (m *GetSchemaMigrationsResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvKeyspacesRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42591,10 +42383,10 @@ func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetShardReplicationRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvKeyspacesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardReplicationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvKeyspacesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -42631,7 +42423,7 @@ func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -42659,39 +42451,7 @@ func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Shard = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cells", 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.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) + m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -42715,7 +42475,7 @@ func (m *GetShardReplicationRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvKeyspacesResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42738,15 +42498,15 @@ func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetShardReplicationResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvKeyspacesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardReplicationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvKeyspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ShardReplicationByCell", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SrvKeyspaces", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -42773,11 +42533,11 @@ func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ShardReplicationByCell == nil { - m.ShardReplicationByCell = make(map[string]*topodata.ShardReplication) + if m.SrvKeyspaces == nil { + m.SrvKeyspaces = make(map[string]*topodata.SrvKeyspace) } var mapkey string - var mapvalue *topodata.ShardReplication + var mapvalue *topodata.SrvKeyspace for iNdEx < postIndex { entryPreIndex := iNdEx var wire uint64 @@ -42851,7 +42611,7 @@ func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &topodata.ShardReplication{} + mapvalue = &topodata.SrvKeyspace{} if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -42871,7 +42631,7 @@ func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { iNdEx += skippy } } - m.ShardReplicationByCell[mapkey] = mapvalue + m.SrvKeyspaces[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -42895,7 +42655,7 @@ func (m *GetShardReplicationResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetShardRequest) UnmarshalVT(dAtA []byte) error { +func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -42918,10 +42678,10 @@ func (m *GetShardRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetShardRequest: wiretype end group for non-group") + return fmt.Errorf("proto: UpdateThrottlerConfigRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: UpdateThrottlerConfigRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -42957,8 +42717,59 @@ func (m *GetShardRequest) UnmarshalVT(dAtA []byte) error { m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Enable", 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.Enable = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Disable", 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.Disable = bool(v != 0) + 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 ShardName", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CustomQuery", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -42986,62 +42797,71 @@ func (m *GetShardRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ShardName = string(dAtA[iNdEx:postIndex]) + m.CustomQuery = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CustomQuerySet", wireType) } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength + 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 + } } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF + m.CustomQuerySet = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckAsCheckSelf", wireType) } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GetShardResponse) 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 + 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 + } } - if iNdEx >= l { - return io.ErrUnexpectedEOF + m.CheckAsCheckSelf = bool(v != 0) + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckAsCheckShard", wireType) } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + 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 + } } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GetShardResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + m.CheckAsCheckShard = bool(v != 0) + case 9: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ThrottledApp", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -43068,13 +42888,109 @@ func (m *GetShardResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Shard == nil { - m.Shard = &Shard{} + if m.ThrottledApp == nil { + m.ThrottledApp = &topodata.ThrottledAppRule{} } - if err := m.Shard.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ThrottledApp.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetricName", 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.MetricName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppName", 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.AppName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppCheckedMetrics", 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.AppCheckedMetrics = append(m.AppCheckedMetrics, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -43097,7 +43013,7 @@ func (m *GetShardResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetShardRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { +func (m *UpdateThrottlerConfigResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43120,10 +43036,10 @@ func (m *GetShardRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetShardRoutingRulesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: UpdateThrottlerConfigResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardRoutingRulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: UpdateThrottlerConfigResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -43148,7 +43064,7 @@ func (m *GetShardRoutingRulesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetShardRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43171,17 +43087,17 @@ func (m *GetShardRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetShardRoutingRulesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvVSchemaRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetShardRoutingRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvVSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ShardRoutingRules", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -43191,27 +43107,23 @@ func (m *GetShardRoutingRulesResponse) 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.ShardRoutingRules == nil { - m.ShardRoutingRules = &vschema.ShardRoutingRules{} - } - if err := m.ShardRoutingRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Cell = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -43235,7 +43147,7 @@ func (m *GetShardRoutingRulesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvKeyspaceNamesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43258,17 +43170,17 @@ func (m *GetSrvKeyspaceNamesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvVSchemaResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvVSchemaResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SrvVSchema", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -43278,23 +43190,27 @@ func (m *GetSrvKeyspaceNamesRequest) 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.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) + if m.SrvVSchema == nil { + m.SrvVSchema = &vschema.SrvVSchema{} + } + if err := m.SrvVSchema.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -43318,7 +43234,7 @@ func (m *GetSrvKeyspaceNamesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvKeyspaceNamesResponse_NameList) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvVSchemasRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43341,15 +43257,15 @@ func (m *GetSrvKeyspaceNamesResponse_NameList) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse_NameList: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvVSchemasRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse_NameList: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvVSchemasRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -43377,7 +43293,7 @@ func (m *GetSrvKeyspaceNamesResponse_NameList) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Names = append(m.Names, string(dAtA[iNdEx:postIndex])) + m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -43401,7 +43317,7 @@ func (m *GetSrvKeyspaceNamesResponse_NameList) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetSrvVSchemasResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43424,15 +43340,15 @@ func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetSrvVSchemasResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvKeyspaceNamesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetSrvVSchemasResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SrvVSchemas", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -43459,11 +43375,11 @@ func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Names == nil { - m.Names = make(map[string]*GetSrvKeyspaceNamesResponse_NameList) + if m.SrvVSchemas == nil { + m.SrvVSchemas = make(map[string]*vschema.SrvVSchema) } var mapkey string - var mapvalue *GetSrvKeyspaceNamesResponse_NameList + var mapvalue *vschema.SrvVSchema for iNdEx < postIndex { entryPreIndex := iNdEx var wire uint64 @@ -43537,7 +43453,7 @@ func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &GetSrvKeyspaceNamesResponse_NameList{} + mapvalue = &vschema.SrvVSchema{} if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -43557,7 +43473,7 @@ func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { iNdEx += skippy } } - m.Names[mapkey] = mapvalue + m.SrvVSchemas[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -43581,7 +43497,7 @@ func (m *GetSrvKeyspaceNamesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvKeyspacesRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetTabletRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43604,17 +43520,17 @@ func (m *GetSrvKeyspacesRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvKeyspacesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetTabletRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvKeyspacesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetTabletRequest: 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) + 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 @@ -43624,55 +43540,27 @@ func (m *GetSrvKeyspacesRequest) 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.Keyspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cells", 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.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -43696,7 +43584,7 @@ func (m *GetSrvKeyspacesRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvKeyspacesResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetTabletResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43719,15 +43607,15 @@ func (m *GetSrvKeyspacesResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvKeyspacesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetTabletResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvKeyspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetTabletResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SrvKeyspaces", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Tablet", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -43754,105 +43642,12 @@ func (m *GetSrvKeyspacesResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.SrvKeyspaces == nil { - m.SrvKeyspaces = make(map[string]*topodata.SrvKeyspace) + if m.Tablet == nil { + m.Tablet = &topodata.Tablet{} } - var mapkey string - var mapvalue *topodata.SrvKeyspace - 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.SrvKeyspace{} - 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.Tablet.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.SrvKeyspaces[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -43876,7 +43671,7 @@ func (m *GetSrvKeyspacesResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetTabletsRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -43899,10 +43694,10 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: UpdateThrottlerConfigRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetTabletsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: UpdateThrottlerConfigRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetTabletsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -43938,10 +43733,10 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { m.Keyspace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Enable", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -43951,46 +43746,27 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.Enable = bool(v != 0) - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Disable", 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 - } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength } - m.Disable = bool(v != 0) - case 4: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Threshold", wireType) + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength } - var v uint64 - if (iNdEx + 8) > l { + if postIndex > l { return io.ErrUnexpectedEOF } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Threshold = float64(math.Float64frombits(v)) - case 5: + m.Shard = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CustomQuery", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44018,51 +43794,11 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.CustomQuery = string(dAtA[iNdEx:postIndex]) + m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CustomQuerySet", 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.CustomQuerySet = bool(v != 0) - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CheckAsCheckSelf", 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.CheckAsCheckSelf = bool(v != 0) - case 8: + case 4: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CheckAsCheckShard", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Strict", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -44079,10 +43815,10 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { break } } - m.CheckAsCheckShard = bool(v != 0) - case 9: + m.Strict = bool(v != 0) + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ThrottledApp", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAliases", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -44109,82 +43845,16 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ThrottledApp == nil { - m.ThrottledApp = &topodata.ThrottledAppRule{} - } - if err := m.ThrottledApp.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + m.TabletAliases = append(m.TabletAliases, &topodata.TabletAlias{}) + if err := m.TabletAliases[len(m.TabletAliases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MetricName", 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.MetricName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AppName", 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.AppName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AppCheckedMetrics", wireType) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TabletType", wireType) } - var stringLen uint64 + m.TabletType = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -44194,75 +43864,11 @@ func (m *UpdateThrottlerConfigRequest) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.TabletType |= topodata.TabletType(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.AppCheckedMetrics = append(m.AppCheckedMetrics, 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 *UpdateThrottlerConfigResponse) 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: UpdateThrottlerConfigResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: UpdateThrottlerConfigResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -44285,7 +43891,7 @@ func (m *UpdateThrottlerConfigResponse) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { +func (m *GetTabletsResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -44308,17 +43914,17 @@ func (m *GetSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvVSchemaRequest: wiretype end group for non-group") + return fmt.Errorf("proto: GetTabletsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvVSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetTabletsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cell", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Tablets", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -44328,23 +43934,25 @@ func (m *GetSrvVSchemaRequest) 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.Cell = string(dAtA[iNdEx:postIndex]) + m.Tablets = append(m.Tablets, &topodata.Tablet{}) + if err := m.Tablets[len(m.Tablets)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -44368,7 +43976,7 @@ func (m *GetSrvVSchemaRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { +func (m *GetThrottlerStatusRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -44391,360 +43999,10 @@ func (m *GetSrvVSchemaResponse) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetSrvVSchemaResponse: wiretype end group for non-group") + return fmt.Errorf("proto: GetThrottlerStatusRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvVSchemaResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SrvVSchema", 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.SrvVSchema == nil { - m.SrvVSchema = &vschema.SrvVSchema{} - } - if err := m.SrvVSchema.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 *GetSrvVSchemasRequest) 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: GetSrvVSchemasRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvVSchemasRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cells", 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.Cells = append(m.Cells, 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 *GetSrvVSchemasResponse) 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: GetSrvVSchemasResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetSrvVSchemasResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SrvVSchemas", 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.SrvVSchemas == nil { - m.SrvVSchemas = make(map[string]*vschema.SrvVSchema) - } - var mapkey string - var mapvalue *vschema.SrvVSchema - 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 = &vschema.SrvVSchema{} - 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.SrvVSchemas[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 *GetTabletRequest) 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: GetTabletRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetTabletRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetThrottlerStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -44776,1775 +44034,67 @@ func (m *GetTabletRequest) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.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 *GetTabletResponse) 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: GetTabletResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetTabletResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tablet", 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.Tablet == nil { - m.Tablet = &topodata.Tablet{} - } - if err := m.Tablet.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 *GetTabletsRequest) 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: GetTabletsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetTabletsRequest: 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 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 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Cells", 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.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Strict", 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.Strict = bool(v != 0) - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TabletAliases", 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.TabletAliases = append(m.TabletAliases, &topodata.TabletAlias{}) - if err := m.TabletAliases[len(m.TabletAliases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TabletType", wireType) - } - m.TabletType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TabletType |= topodata.TabletType(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 *GetTabletsResponse) 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: GetTabletsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetTabletsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tablets", 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.Tablets = append(m.Tablets, &topodata.Tablet{}) - if err := m.Tablets[len(m.Tablets)-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 *GetThrottlerStatusRequest) 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: GetThrottlerStatusRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusRequest: 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 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.TabletAlias == nil { - m.TabletAlias = &topodata.TabletAlias{} - } - if err := m.TabletAlias.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 *GetThrottlerStatusResponse_MetricResult) 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_MetricResult: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricResult: 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) - } - 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 - 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_MetricHealth) 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_MetricHealth: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricHealth: 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) - } - 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.LastHealthyAt == nil { - m.LastHealthyAt = &vttime.Time{} - } - if err := m.LastHealthyAt.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SecondsSinceLastHealthy", wireType) - } - m.SecondsSinceLastHealthy = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.SecondsSinceLastHealthy |= int64(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) + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} } - 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 - } + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.AppCheckedMetrics[mapkey] = mapvalue iNdEx = postIndex - case 17: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RecentlyChecked", wireType) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - 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 - } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength } - m.RecentlyChecked = bool(v != 0) - case 18: + 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 RecentApps", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -46571,105 +44121,12 @@ func (m *GetThrottlerStatusResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.RecentApps == nil { - m.RecentApps = make(map[string]*GetThrottlerStatusResponse_RecentApp) + if m.Status == nil { + m.Status = &tabletmanagerdata.GetThrottlerStatusResponse{} } - 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 - } + if err := m.Status.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.RecentApps[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -52194,6 +49651,26 @@ func (m *PlannedReparentShardRequest) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowCrossCellPromotion", 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.AllowCrossCellPromotion = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -62465,6 +59942,25 @@ func (m *VDiffCreateRequest) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RowDiffColumnTruncateAt", wireType) + } + m.RowDiffColumnTruncateAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RowDiffColumnTruncateAt |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/go/vt/proto/vtgate/vtgate.pb.go b/go/vt/proto/vtgate/vtgate.pb.go index a7a200cc93d..1b84f6c7efe 100644 --- a/go/vt/proto/vtgate/vtgate.pb.go +++ b/go/vt/proto/vtgate/vtgate.pb.go @@ -1082,6 +1082,8 @@ type VStreamFlags struct { Cells string `protobuf:"bytes,4,opt,name=cells,proto3" json:"cells,omitempty"` CellPreference string `protobuf:"bytes,5,opt,name=cell_preference,json=cellPreference,proto3" json:"cell_preference,omitempty"` TabletOrder string `protobuf:"bytes,6,opt,name=tablet_order,json=tabletOrder,proto3" json:"tablet_order,omitempty"` + // When set, all new row events from the `heartbeat` table, for all shards, in the sidecardb will be streamed. + StreamKeyspaceHeartbeats bool `protobuf:"varint,7,opt,name=stream_keyspace_heartbeats,json=streamKeyspaceHeartbeats,proto3" json:"stream_keyspace_heartbeats,omitempty"` } func (x *VStreamFlags) Reset() { @@ -1158,6 +1160,13 @@ func (x *VStreamFlags) GetTabletOrder() string { return "" } +func (x *VStreamFlags) GetStreamKeyspaceHeartbeats() bool { + if x != nil { + return x.StreamKeyspaceHeartbeats + } + return false +} + // VStreamRequest is the payload for VStream. type VStreamRequest struct { state protoimpl.MessageState @@ -1827,7 +1836,7 @@ var file_vtgate_proto_rawDesc = []byte{ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x74, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x74, 0x69, 0x64, 0x22, 0x1c, 0x0a, 0x1a, 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, 0xec, 0x01, 0x0a, 0x0c, 0x56, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xaa, 0x02, 0x0a, 0x0c, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x6b, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x53, 0x6b, 0x65, 0x77, @@ -1842,68 +1851,72 @@ var file_vtgate_proto_rawDesc = []byte{ 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x65, 0x6c, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0xf6, 0x01, 0x0a, 0x0e, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, - 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, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x0b, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 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, 0x27, 0x0a, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x47, - 0x74, 0x69, 0x64, 0x52, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x06, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, 0x6e, - 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, - 0x67, 0x73, 0x22, 0x3d, 0x0a, 0x0f, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, 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, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 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, 0x22, 0x89, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x70, 0x61, - 0x72, 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, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x22, 0x6e, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, 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, 0x08, 0x63, - 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x3d, 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 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, 0x2a, 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x49, 0x4e, 0x47, 0x4c, 0x45, 0x10, - 0x01, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, - 0x54, 0x57, 0x4f, 0x50, 0x43, 0x10, 0x03, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, - 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x52, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x50, - 0x4f, 0x53, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x55, 0x54, 0x4f, 0x43, 0x4f, 0x4d, - 0x4d, 0x49, 0x54, 0x10, 0x03, 0x42, 0x36, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, 0x65, - 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x67, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x6c, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x68, 0x65, 0x61, + 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x48, 0x65, 0x61, + 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x0e, 0x56, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, 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, 0x08, + 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 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, + 0x27, 0x0a, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x47, 0x74, 0x69, + 0x64, 0x52, 0x05, 0x76, 0x67, 0x74, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, + 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, + 0x22, 0x3d, 0x0a, 0x0f, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0x92, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, 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, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 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, 0x22, 0x89, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 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, + 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, + 0x22, 0x6e, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x09, 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, 0x08, 0x63, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x3d, 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 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, 0x2a, + 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x49, 0x4e, 0x47, 0x4c, 0x45, 0x10, 0x01, 0x12, + 0x09, 0x0a, 0x05, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x57, + 0x4f, 0x50, 0x43, 0x10, 0x03, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, + 0x12, 0x07, 0x0a, 0x03, 0x50, 0x52, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x53, + 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x55, 0x54, 0x4f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, + 0x54, 0x10, 0x03, 0x42, 0x36, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x67, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/go/vt/proto/vtgate/vtgate_vtproto.pb.go b/go/vt/proto/vtgate/vtgate_vtproto.pb.go index bec24472760..e2ac0b8c8a3 100644 --- a/go/vt/proto/vtgate/vtgate_vtproto.pb.go +++ b/go/vt/proto/vtgate/vtgate_vtproto.pb.go @@ -352,12 +352,13 @@ func (m *VStreamFlags) CloneVT() *VStreamFlags { return (*VStreamFlags)(nil) } r := &VStreamFlags{ - MinimizeSkew: m.MinimizeSkew, - HeartbeatInterval: m.HeartbeatInterval, - StopOnReshard: m.StopOnReshard, - Cells: m.Cells, - CellPreference: m.CellPreference, - TabletOrder: m.TabletOrder, + MinimizeSkew: m.MinimizeSkew, + HeartbeatInterval: m.HeartbeatInterval, + StopOnReshard: m.StopOnReshard, + Cells: m.Cells, + CellPreference: m.CellPreference, + TabletOrder: m.TabletOrder, + StreamKeyspaceHeartbeats: m.StreamKeyspaceHeartbeats, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -1479,6 +1480,16 @@ func (m *VStreamFlags) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.StreamKeyspaceHeartbeats { + i-- + if m.StreamKeyspaceHeartbeats { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } if len(m.TabletOrder) > 0 { i -= len(m.TabletOrder) copy(dAtA[i:], m.TabletOrder) @@ -2277,6 +2288,9 @@ func (m *VStreamFlags) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + if m.StreamKeyspaceHeartbeats { + n += 2 + } n += len(m.unknownFields) return n } @@ -5222,6 +5236,26 @@ func (m *VStreamFlags) UnmarshalVT(dAtA []byte) error { } m.TabletOrder = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StreamKeyspaceHeartbeats", 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.StreamKeyspaceHeartbeats = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) 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/vttime/cached_size.go b/go/vt/proto/vttime/cached_size.go index e34da16852c..62a6366ba3c 100644 --- a/go/vt/proto/vttime/cached_size.go +++ b/go/vt/proto/vttime/cached_size.go @@ -17,8 +17,6 @@ limitations under the License. package vttime -import hack "vitess.io/vitess/go/hack" - func (cached *Time) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -27,9 +25,5 @@ func (cached *Time) CachedSize(alloc bool) int64 { if alloc { size += int64(64) } - // field unknownFields []byte - { - size += hack.RuntimeAllocSize(int64(cap(cached.unknownFields))) - } return size } diff --git a/go/vt/schema/ddl_strategy_test.go b/go/vt/schema/ddl_strategy_test.go index f27f0963e80..c394907b98a 100644 --- a/go/vt/schema/ddl_strategy_test.go +++ b/go/vt/schema/ddl_strategy_test.go @@ -328,6 +328,13 @@ func TestParseDDLStrategy(t *testing.T) { runtimeOptions: "", forceCutOverAfter: 3 * time.Minute, }, + { + strategyVariable: "vitess --force-cut-over-after=-1ms", + strategy: DDLStrategyVitess, + options: "--force-cut-over-after=-1ms", + runtimeOptions: "", + forceCutOverAfter: -1 * time.Millisecond, + }, { strategyVariable: "vitess --force-cut-over-after=r3m", strategy: DDLStrategyVitess, 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/capability.go b/go/vt/schemadiff/capability.go index cde99ac18c3..1471599d390 100644 --- a/go/vt/schemadiff/capability.go +++ b/go/vt/schemadiff/capability.go @@ -61,24 +61,13 @@ func alterOptionCapableOfInstantDDL(alterOption sqlparser.AlterOption, createTab } } - isGeneratedColumn := func(col *sqlparser.ColumnDefinition) (bool, sqlparser.ColumnStorage) { - if col == nil { - return false, 0 - } - if col.Type.Options == nil { - return false, 0 - } - if col.Type.Options.As == nil { - return false, 0 - } - return true, col.Type.Options.Storage - } - colStringStrippedDown := func(col *sqlparser.ColumnDefinition, stripDefault bool, stripEnum bool) string { + colStringStrippedDown := func(col *sqlparser.ColumnDefinition, stripEnum bool) string { strippedCol := sqlparser.Clone(col) - if stripDefault { - strippedCol.Type.Options.Default = nil - strippedCol.Type.Options.DefaultLiteral = false - } + // strip `default` + strippedCol.Type.Options.Default = nil + strippedCol.Type.Options.DefaultLiteral = false + // strip `visibility` + strippedCol.Type.Options.Invisible = nil if stripEnum { strippedCol.Type.EnumValues = nil } @@ -95,15 +84,53 @@ func alterOptionCapableOfInstantDDL(alterOption sqlparser.AlterOption, createTab } return true } + changeModifyColumnCapableOfInstantDDL := func(col *sqlparser.ColumnDefinition, newCol *sqlparser.ColumnDefinition) (bool, error) { + // Check if only diff is change of default. + // We temporarily remove the DEFAULT expression (if any) from both + // table and ALTER statement, and compare the columns: if they're otherwise equal, + // then the only change can be an addition/change/removal of DEFAULT, which + // is instant-table. + tableColDefinition := colStringStrippedDown(col, false) + newColDefinition := colStringStrippedDown(newCol, false) + if tableColDefinition == newColDefinition { + return capableOf(capabilities.InstantChangeColumnDefaultFlavorCapability) + } + // Check if: + // 1. this an ENUM/SET + // 2. and the change is to append values to the end of the list + // 3. and the number of added values does not increase the storage size for the enum/set + // 4. while still not caring about a change in the default value + if len(col.Type.EnumValues) > 0 && len(newCol.Type.EnumValues) > 0 { + // both are enum or set + if !hasPrefix(newCol.Type.EnumValues, col.Type.EnumValues) { + return false, nil + } + // we know the new column definition is identical to, or extends, the old definition. + // Now validate storage: + if strings.EqualFold(col.Type.Type, "enum") { + if len(col.Type.EnumValues) <= 255 && len(newCol.Type.EnumValues) > 255 { + // this increases the SET storage size (1 byte for up to 8 values, 2 bytes beyond) + return false, nil + } + } + if strings.EqualFold(col.Type.Type, "set") { + if (len(col.Type.EnumValues)+7)/8 != (len(newCol.Type.EnumValues)+7)/8 { + // this increases the SET storage size (1 byte for up to 8 values, 2 bytes for 8-15, etc.) + return false, nil + } + } + // Now don't care about change of default: + tableColDefinition := colStringStrippedDown(col, true) + newColDefinition := colStringStrippedDown(newCol, true) + if tableColDefinition == newColDefinition { + return capableOf(capabilities.InstantExpandEnumCapability) + } + } + return false, nil + } + // Up to 8.0.26 we could only ADD COLUMN as last column switch opt := alterOption.(type) { - case *sqlparser.ChangeColumn: - // We do not support INSTANT for renaming a column (ALTER TABLE ...CHANGE) because: - // 1. We discourage column rename - // 2. We do not produce CHANGE statements in declarative diff - // 3. The success of the operation depends on whether the column is referenced by a foreign key - // in another table. Which is a bit too much to compute here. - return false, nil case *sqlparser.AddColumns: if tableHasFulltextIndex { // not supported if the table has a FULLTEXT index @@ -114,7 +141,7 @@ func alterOptionCapableOfInstantDDL(alterOption sqlparser.AlterOption, createTab return false, nil } for _, column := range opt.Columns { - if isGenerated, storage := isGeneratedColumn(column); isGenerated { + if isGenerated, storage := IsGeneratedColumn(column); isGenerated { if storage == sqlparser.StoredStorage { // Adding a generated "STORED" column is unsupported return false, nil @@ -149,7 +176,7 @@ func alterOptionCapableOfInstantDDL(alterOption sqlparser.AlterOption, createTab // not supported if the column is part of an index return false, nil } - if isGenerated, _ := isGeneratedColumn(col); isGenerated { + if isGenerated, _ := IsGeneratedColumn(col); isGenerated { // supported by all 8.0 versions // Note: according to the docs dropping a STORED generated column is not INSTANT-able, // but in practice this is supported. This is why we don't test for STORED here, like @@ -157,49 +184,30 @@ func alterOptionCapableOfInstantDDL(alterOption sqlparser.AlterOption, createTab return capableOf(capabilities.InstantAddDropVirtualColumnFlavorCapability) } return capableOf(capabilities.InstantAddDropColumnFlavorCapability) + case *sqlparser.ChangeColumn: + // We do not support INSTANT for renaming a column (ALTER TABLE ...CHANGE) because: + // 1. We discourage column rename + // 2. We do not produce CHANGE statements in declarative diff + // 3. The success of the operation depends on whether the column is referenced by a foreign key + // in another table. Which is a bit too much to compute here. + if opt.OldColumn.Name.String() != opt.NewColDefinition.Name.String() { + return false, nil + } + if col := findColumn(opt.OldColumn.Name.String()); col != nil { + return changeModifyColumnCapableOfInstantDDL(col, opt.NewColDefinition) + } + return false, nil case *sqlparser.ModifyColumn: if col := findColumn(opt.NewColDefinition.Name.String()); col != nil { - // Check if only diff is change of default. - // We temporarily remove the DEFAULT expression (if any) from both - // table and ALTER statement, and compare the columns: if they're otherwise equal, - // then the only change can be an addition/change/removal of DEFAULT, which - // is instant-table. - tableColDefinition := colStringStrippedDown(col, true, false) - newColDefinition := colStringStrippedDown(opt.NewColDefinition, true, false) - if tableColDefinition == newColDefinition { - return capableOf(capabilities.InstantChangeColumnDefaultFlavorCapability) - } - // Check if: - // 1. this an ENUM/SET - // 2. and the change is to append values to the end of the list - // 3. and the number of added values does not increase the storage size for the enum/set - // 4. while still not caring about a change in the default value - if len(col.Type.EnumValues) > 0 && len(opt.NewColDefinition.Type.EnumValues) > 0 { - // both are enum or set - if !hasPrefix(opt.NewColDefinition.Type.EnumValues, col.Type.EnumValues) { - return false, nil - } - // we know the new column definition is identical to, or extends, the old definition. - // Now validate storage: - if strings.EqualFold(col.Type.Type, "enum") { - if len(col.Type.EnumValues) <= 255 && len(opt.NewColDefinition.Type.EnumValues) > 255 { - // this increases the SET storage size (1 byte for up to 8 values, 2 bytes beyond) - return false, nil - } - } - if strings.EqualFold(col.Type.Type, "set") { - if (len(col.Type.EnumValues)+7)/8 != (len(opt.NewColDefinition.Type.EnumValues)+7)/8 { - // this increases the SET storage size (1 byte for up to 8 values, 2 bytes for 8-15, etc.) - return false, nil - } - } - // Now don't care about change of default: - tableColDefinition := colStringStrippedDown(col, true, true) - newColDefinition := colStringStrippedDown(opt.NewColDefinition, true, true) - if tableColDefinition == newColDefinition { - return capableOf(capabilities.InstantExpandEnumCapability) - } - } + return changeModifyColumnCapableOfInstantDDL(col, opt.NewColDefinition) + } + return false, nil + case *sqlparser.AlterColumn: + if opt.DropDefault || opt.DefaultLiteral || opt.DefaultVal != nil { + return capableOf(capabilities.InstantChangeColumnDefaultFlavorCapability) + } + if opt.Invisible != nil { + return capableOf(capabilities.InstantChangeColumnVisibilityCapability) } return false, nil default: diff --git a/go/vt/schemadiff/capability_test.go b/go/vt/schemadiff/capability_test.go index ca3387bb1a7..b35afb7fe22 100644 --- a/go/vt/schemadiff/capability_test.go +++ b/go/vt/schemadiff/capability_test.go @@ -19,6 +19,7 @@ func TestAlterTableCapableOfInstantDDL(t *testing.T) { capabilities.InstantAddDropVirtualColumnFlavorCapability, capabilities.InstantAddDropColumnFlavorCapability, capabilities.InstantChangeColumnDefaultFlavorCapability, + capabilities.InstantChangeColumnVisibilityCapability, capabilities.InstantExpandEnumCapability: return true, nil } @@ -272,6 +273,36 @@ func TestAlterTableCapableOfInstantDDL(t *testing.T) { alter: "alter table t modify column c1 set('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')", expectCapableOfInstantDDL: false, }, + { + name: "make a column invisible", + create: "create table t1 (id int, i1 int)", + alter: "alter table t1 modify column i1 int invisible", + expectCapableOfInstantDDL: true, + }, + { + name: "make a column visible", + create: "create table t1 (id int, i1 int)", + alter: "alter table t1 change column i1 i1 int visible", + expectCapableOfInstantDDL: true, + }, + { + name: "make a column visible with rename", + create: "create table t1 (id int, i1 int)", + alter: "alter table t1 change column i1 i2 int visible", + expectCapableOfInstantDDL: false, + }, + { + name: "make a column invisible via SET", + create: "create table t1 (id int, i1 int)", + alter: "alter table t1 alter column i1 set invisible", + expectCapableOfInstantDDL: true, + }, + { + name: "drop column default", + create: "create table t1 (id int, i1 int)", + alter: "alter table t1 alter column i1 drop default", + expectCapableOfInstantDDL: true, + }, } for _, tcase := range tcases { t.Run(tcase.name, func(t *testing.T) { diff --git a/go/vt/schemadiff/column.go b/go/vt/schemadiff/column.go index 7e55192cb06..63181cef9cb 100644 --- a/go/vt/schemadiff/column.go +++ b/go/vt/schemadiff/column.go @@ -20,6 +20,7 @@ import ( "strings" "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/ptr" "vitess.io/vitess/go/vt/sqlparser" ) @@ -71,63 +72,100 @@ func NewModifyColumnDiffByDefinition(definition *sqlparser.ColumnDefinition) *Mo } type ColumnDefinitionEntity struct { - columnDefinition *sqlparser.ColumnDefinition + ColumnDefinition *sqlparser.ColumnDefinition + inPK bool // Does this column appear in the primary key? tableCharsetCollate *charsetCollate Env *Environment } -func NewColumnDefinitionEntity(env *Environment, c *sqlparser.ColumnDefinition, tableCharsetCollate *charsetCollate) *ColumnDefinitionEntity { +func NewColumnDefinitionEntity(env *Environment, c *sqlparser.ColumnDefinition, inPK bool, tableCharsetCollate *charsetCollate) *ColumnDefinitionEntity { return &ColumnDefinitionEntity{ - columnDefinition: c, + ColumnDefinition: c, + inPK: inPK, tableCharsetCollate: tableCharsetCollate, Env: env, } } +func (c *ColumnDefinitionEntity) Name() string { + return c.ColumnDefinition.Name.String() +} + +func (c *ColumnDefinitionEntity) NameLowered() string { + return c.ColumnDefinition.Name.Lowered() +} + func (c *ColumnDefinitionEntity) Clone() *ColumnDefinitionEntity { clone := &ColumnDefinitionEntity{ - columnDefinition: sqlparser.Clone(c.columnDefinition), + ColumnDefinition: sqlparser.Clone(c.ColumnDefinition), + inPK: c.inPK, tableCharsetCollate: c.tableCharsetCollate, Env: c.Env, } return clone } +// SetExplicitDefaultAndNull sets: +// - NOT NULL, if the columns is part of the PRIMARY KEY +// - DEFAULT NULL, if the columns is NULLable and no DEFAULT was mentioned +// Normally in schemadiff we work the opposite way: we strive to have the minimal equivalent representation +// of a definition. But this function can be used (often in conjunction with Clone()) to enrich a column definition +// so as to have explicit and authoritative view on any particular column. +func (c *ColumnDefinitionEntity) SetExplicitDefaultAndNull() { + if c.inPK { + // Any column in the primary key is implicitly NOT NULL. + c.ColumnDefinition.Type.Options.Null = ptr.Of(false) + } + if c.ColumnDefinition.Type.Options.Null == nil || *c.ColumnDefinition.Type.Options.Null { + // Nullable column, let'se see if there's already a DEFAULT. + if c.ColumnDefinition.Type.Options.Default == nil { + // nope, let's add a DEFAULT NULL + c.ColumnDefinition.Type.Options.Default = &sqlparser.NullVal{} + } + } +} + // 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. +// Normally in schemadiff we work the opposite way: we strive to have the minimal equivalent representation +// of a definition. But this function can be used (often in conjunction with Clone()) to enrich a column definition +// so as to have explicit and authoritative view on any particular column. 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 == "" { + 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) + 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} + return &UnknownColumnCharsetCollationError{Column: c.ColumnDefinition.Name.String(), Charset: c.tableCharsetCollate.charset} } - c.columnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) + c.ColumnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) } - if c.columnDefinition.Type.Charset.Name == "" && c.columnDefinition.Type.Options.Collate != "" { + 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) + 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} + return &UnknownColumnCollationCharsetError{Column: c.ColumnDefinition.Name.String(), Collation: c.ColumnDefinition.Type.Options.Collate} } - c.columnDefinition.Type.Charset.Name = charset + c.ColumnDefinition.Type.Charset.Name = charset } - if c.columnDefinition.Type.Charset.Name == "" { + 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 == "" { + c.ColumnDefinition.Type.Charset.Name = c.tableCharsetCollate.charset + if c.ColumnDefinition.Type.Options.Collate == "" { + c.ColumnDefinition.Type.Options.Collate = c.tableCharsetCollate.collate + } + 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} + return &UnknownColumnCharsetCollationError{Column: c.ColumnDefinition.Name.String(), Charset: c.tableCharsetCollate.charset} } - c.columnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) + c.ColumnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) } } return nil @@ -168,7 +206,7 @@ func (c *ColumnDefinitionEntity) ColumnDiff( } } - if sqlparser.Equals.RefOfColumnDefinition(cClone.columnDefinition, otherClone.columnDefinition) { + if sqlparser.Equals.RefOfColumnDefinition(cClone.ColumnDefinition, otherClone.ColumnDefinition) { return nil, nil } @@ -181,19 +219,228 @@ func (c *ColumnDefinitionEntity) ColumnDiff( } switch hints.EnumReorderStrategy { case EnumReorderStrategyReject: - otherEnumValuesMap := getEnumValuesMap(otherClone.columnDefinition.Type.EnumValues) - for ordinal, enumValue := range cClone.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: cClone.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} } } } } - return NewModifyColumnDiffByDefinition(other.columnDefinition), nil + return NewModifyColumnDiffByDefinition(other.ColumnDefinition), nil +} + +// Type returns the column's type +func (c *ColumnDefinitionEntity) Type() string { + return c.ColumnDefinition.Type.Type } // IsTextual returns true when this column is of textual type, and is capable of having a character set property func (c *ColumnDefinitionEntity) IsTextual() bool { - return charsetTypes[strings.ToLower(c.columnDefinition.Type.Type)] + return charsetTypes[strings.ToLower(c.Type())] +} + +// IsGenerated returns true when this column is generated, and indicates the storage type (virtual/stored) +func IsGeneratedColumn(col *sqlparser.ColumnDefinition) (bool, sqlparser.ColumnStorage) { + if col == nil { + return false, 0 + } + if col.Type.Options == nil { + return false, 0 + } + if col.Type.Options.As == nil { + return false, 0 + } + return true, col.Type.Options.Storage +} + +// IsGenerated returns true when this column is generated, and indicates the storage type (virtual/stored) +func (c *ColumnDefinitionEntity) IsGenerated() bool { + isGenerated, _ := IsGeneratedColumn(c.ColumnDefinition) + return isGenerated +} + +// IsNullable returns true when this column is NULLable +func (c *ColumnDefinitionEntity) IsNullable() bool { + if c.inPK { + return false + } + return c.ColumnDefinition.Type.Options.Null == nil || *c.ColumnDefinition.Type.Options.Null +} + +// IsDefaultNull returns true when this column has DEFAULT NULL +func (c *ColumnDefinitionEntity) IsDefaultNull() bool { + if !c.IsNullable() { + return false + } + _, ok := c.ColumnDefinition.Type.Options.Default.(*sqlparser.NullVal) + return ok +} + +// IsDefaultNull returns true when this column has DEFAULT NULL +func (c *ColumnDefinitionEntity) HasDefault() bool { + if c.ColumnDefinition.Type.Options.Default == nil { + return false + } + if c.IsDefaultNull() { + return true + } + return true +} + +// IsAutoIncrement returns true when this column is AUTO_INCREMENT +func (c *ColumnDefinitionEntity) IsAutoIncrement() bool { + return c.ColumnDefinition.Type.Options.Autoincrement +} + +// IsUnsigned returns true when this column is UNSIGNED +func (c *ColumnDefinitionEntity) IsUnsigned() bool { + return c.ColumnDefinition.Type.Unsigned +} + +// IsNumeric returns true when this column is a numeric type +func (c *ColumnDefinitionEntity) IsIntegralType() bool { + return IsIntegralType(c.Type()) +} + +// IsFloatingPointType returns true when this column is a floating point type +func (c *ColumnDefinitionEntity) IsFloatingPointType() bool { + return IsFloatingPointType(c.Type()) +} + +// IsDecimalType returns true when this column is a decimal type +func (c *ColumnDefinitionEntity) IsDecimalType() bool { + return IsDecimalType(c.Type()) +} + +// HasBlobTypeStorage returns true when this column is a text/blob type +func (c *ColumnDefinitionEntity) HasBlobTypeStorage() bool { + return BlobTypeStorage(c.Type()) != 0 +} + +// Charset returns the column's charset +func (c *ColumnDefinitionEntity) Charset() string { + return c.ColumnDefinition.Type.Charset.Name +} + +// Collate returns the column's collation +func (c *ColumnDefinitionEntity) Collate() string { + return c.ColumnDefinition.Type.Options.Collate +} + +func (c *ColumnDefinitionEntity) EnumValues() []string { + return c.ColumnDefinition.Type.EnumValues +} + +func (c *ColumnDefinitionEntity) HasEnumValues() bool { + return len(c.EnumValues()) > 0 +} + +// EnumValuesOrdinals returns a map of enum values to their ordinals +func (c *ColumnDefinitionEntity) EnumValuesOrdinals() map[string]int { + m := make(map[string]int, len(c.ColumnDefinition.Type.EnumValues)) + for i, enumValue := range c.ColumnDefinition.Type.EnumValues { + m[enumValue] = i + 1 + } + return m +} + +// EnumOrdinalValues returns a map of enum ordinals to their values +func (c *ColumnDefinitionEntity) EnumOrdinalValues() map[int]string { + m := make(map[int]string, len(c.ColumnDefinition.Type.EnumValues)) + for i, enumValue := range c.ColumnDefinition.Type.EnumValues { + // SET and ENUM values are 1 indexed. + m[i+1] = enumValue + } + return m +} + +// Length returns the type length (e.g. 17 for VARCHAR(17), 10 for DECIMAL(10,2), 6 for TIMESTAMP(6), etc.) +func (c *ColumnDefinitionEntity) Length() int { + if c.ColumnDefinition.Type.Length == nil { + return 0 + } + return *c.ColumnDefinition.Type.Length +} + +// Scale returns the type scale (e.g. 2 for DECIMAL(10,2)) +func (c *ColumnDefinitionEntity) Scale() int { + if c.ColumnDefinition.Type.Scale == nil { + return 0 + } + return *c.ColumnDefinition.Type.Scale +} + +// ColumnDefinitionEntityList is a formalized list of ColumnDefinitionEntity, with some +// utility functions. +type ColumnDefinitionEntityList struct { + Entities []*ColumnDefinitionEntity + byName map[string]*ColumnDefinitionEntity +} + +func NewColumnDefinitionEntityList(entities []*ColumnDefinitionEntity) *ColumnDefinitionEntityList { + list := &ColumnDefinitionEntityList{ + Entities: entities, + byName: make(map[string]*ColumnDefinitionEntity), + } + for _, entity := range entities { + list.byName[entity.Name()] = entity + list.byName[entity.NameLowered()] = entity + } + return list +} + +func (l *ColumnDefinitionEntityList) Len() int { + return len(l.Entities) +} + +// Names returns the names of all the columns in this list +func (l *ColumnDefinitionEntityList) Names() []string { + names := make([]string, len(l.Entities)) + for i, entity := range l.Entities { + names[i] = entity.Name() + } + return names +} + +// GetColumn returns the column with the given name, or nil if not found +func (l *ColumnDefinitionEntityList) GetColumn(name string) *ColumnDefinitionEntity { + return l.byName[name] +} + +// Contains returns true when this list contains all the entities from the other list +func (l *ColumnDefinitionEntityList) Contains(other *ColumnDefinitionEntityList) bool { + for _, entity := range other.Entities { + if l.GetColumn(entity.NameLowered()) == nil { + return false + } + } + return true +} + +// Union returns a new ColumnDefinitionEntityList with all the entities from this list and the other list +func (l *ColumnDefinitionEntityList) Union(other *ColumnDefinitionEntityList) *ColumnDefinitionEntityList { + entities := append(l.Entities, other.Entities...) + return NewColumnDefinitionEntityList(entities) +} + +// Clone creates a copy of this list, with copies of the entities +func (l *ColumnDefinitionEntityList) Clone() *ColumnDefinitionEntityList { + entities := make([]*ColumnDefinitionEntity, len(l.Entities)) + for i, entity := range l.Entities { + entities[i] = entity.Clone() + } + return NewColumnDefinitionEntityList(entities) +} + +// Filter returns a new subset ColumnDefinitionEntityList with only the entities that pass the filter +func (l *ColumnDefinitionEntityList) Filter(include func(entity *ColumnDefinitionEntity) bool) *ColumnDefinitionEntityList { + var entities []*ColumnDefinitionEntity + for _, entity := range l.Entities { + if include(entity) { + entities = append(entities, entity) + } + } + return NewColumnDefinitionEntityList(entities) } diff --git a/go/vt/schemadiff/column_test.go b/go/vt/schemadiff/column_test.go new file mode 100644 index 00000000000..f1b8f9e4f75 --- /dev/null +++ b/go/vt/schemadiff/column_test.go @@ -0,0 +1,497 @@ +/* +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 schemadiff + +import ( + "fmt" + "testing" + + "golang.org/x/exp/maps" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestColumnFunctions(t *testing.T) { + table := ` + create table t ( + id int, + col1 int, + col2 int not null, + col3 int default null, + col4 int default 1, + COL5 int default 1, + ts1 timestamp, + ts2 timestamp(3) null, + ts3 timestamp(6) not null, + primary key (id) + )` + env := NewTestEnv() + createTableEntity, err := NewCreateTableEntityFromSQL(env, table) + require.NoError(t, err) + m := createTableEntity.ColumnDefinitionEntitiesMap() + for _, col := range m { + col.SetExplicitDefaultAndNull() + err := col.SetExplicitCharsetCollate() + require.NoError(t, err) + } + + t.Run("nullable", func(t *testing.T) { + assert.False(t, m["id"].IsNullable()) + assert.True(t, m["col1"].IsNullable()) + assert.False(t, m["col2"].IsNullable()) + assert.True(t, m["col3"].IsNullable()) + assert.True(t, m["col4"].IsNullable()) + assert.True(t, m["col5"].IsNullable()) + assert.True(t, m["ts1"].IsNullable()) + assert.True(t, m["ts2"].IsNullable()) + assert.False(t, m["ts3"].IsNullable()) + }) + t.Run("default null", func(t *testing.T) { + assert.False(t, m["id"].IsDefaultNull()) + assert.True(t, m["col1"].IsDefaultNull()) + assert.False(t, m["col2"].IsDefaultNull()) + assert.True(t, m["col3"].IsDefaultNull()) + assert.False(t, m["col4"].IsDefaultNull()) + assert.False(t, m["col5"].IsDefaultNull()) + assert.True(t, m["ts1"].IsDefaultNull()) + assert.True(t, m["ts2"].IsDefaultNull()) + assert.False(t, m["ts3"].IsDefaultNull()) + }) + t.Run("has default", func(t *testing.T) { + assert.False(t, m["id"].HasDefault()) + assert.True(t, m["col1"].HasDefault()) + assert.False(t, m["col2"].HasDefault()) + assert.True(t, m["col3"].HasDefault()) + assert.True(t, m["col4"].HasDefault()) + assert.True(t, m["col5"].HasDefault()) + assert.True(t, m["ts1"].HasDefault()) + assert.True(t, m["ts2"].HasDefault()) + assert.False(t, m["ts3"].HasDefault()) + }) +} + +func TestExpands(t *testing.T) { + tcases := []struct { + source string + target string + expands bool + msg string + }{ + { + source: "int", + target: "int", + }, + { + source: "int", + target: "smallint", + }, + { + source: "int", + target: "smallint unsigned", + }, + { + source: "int unsigned", + target: "tinyint", + expands: true, + msg: "source is unsigned, target is signed", + }, + { + source: "int unsigned", + target: "tinyint signed", + expands: true, + msg: "source is unsigned, target is signed", + }, + { + source: "int", + target: "tinyint", + }, + { + source: "int", + target: "bigint", + expands: true, + msg: "increased integer range", + }, + { + source: "int", + target: "bigint unsigned", + expands: true, + msg: "increased integer range", + }, + { + source: "int", + target: "int unsigned", + expands: true, + msg: "target unsigned value exceeds source unsigned value", + }, + { + source: "int unsigned", + target: "int", + expands: true, + msg: "source is unsigned, target is signed", + }, + { + source: "int", + target: "int default null", + }, + { + source: "int default null", + target: "int", + }, + { + source: "int", + target: "int not null", + }, + { + source: "int not null", + target: "int", + expands: true, + msg: "target is NULL-able, source is not", + }, + { + source: "int not null", + target: "int default null", + expands: true, + msg: "target is NULL-able, source is not", + }, + { + source: "float", + target: "int", + }, + { + source: "int", + target: "float", + expands: true, + msg: "target is floating point, source is not", + }, + { + source: "float", + target: "double", + expands: true, + msg: "increased floating point range", + }, + { + source: "decimal(5,2)", + target: "float", + expands: true, + msg: "target is floating point, source is not", + }, + { + source: "int", + target: "decimal", + expands: true, + msg: "target is decimal, source is not", + }, + { + source: "int", + target: "decimal(5,2)", + expands: true, + msg: "increased length", + }, + { + source: "int", + target: "decimal(5,0)", + expands: true, + msg: "increased length", + }, + { + source: "decimal(5,2)", // 123.45 + target: "decimal(3,2)", // 1.23 + }, + { + source: "decimal(5,2)", // 123.45 + target: "decimal(4,1)", // 123.4 + }, + { + source: "decimal(5,2)", // 123.45 + target: "decimal(5,1)", // 1234.5 + expands: true, + msg: "increased decimal range", + }, + { + source: "char(7)", + target: "char(7)", + }, + { + source: "char(7)", + target: "varchar(7)", + }, + { + source: "char(7)", + target: "varchar(5)", + }, + { + source: "char(5)", + target: "varchar(7)", + expands: true, + msg: "increased length", + }, + { + source: "varchar(5)", + target: "char(7)", + expands: true, + msg: "increased length", + }, + { + source: "tinytext", + target: "tinytext", + }, + { + source: "tinytext", + target: "tinyblob", + }, + { + source: "mediumtext", + target: "tinytext", + }, + { + source: "mediumblob", + target: "tinytext", + }, + { + source: "tinytext", + target: "text", + expands: true, + msg: "increased blob range", + }, + { + source: "tinytext", + target: "mediumblob", + expands: true, + msg: "increased blob range", + }, + { + source: "timestamp", + target: "timestamp", + }, + { + source: "timestamp", + target: "time", + }, + { + source: "datetime", + target: "timestamp", + }, + { + source: "datetime", + target: "date", + }, + { + source: "time", + target: "timestamp", + expands: true, + msg: "target is expanded data type of source", + }, + { + source: "timestamp", + target: "datetime", + expands: true, + msg: "target is expanded data type of source", + }, + { + source: "date", + target: "datetime", + expands: true, + msg: "target is expanded data type of source", + }, + { + source: "timestamp", + target: "timestamp(3)", + expands: true, + msg: "increased length", + }, + { + source: "timestamp", + target: "timestamp(6)", + expands: true, + msg: "increased length", + }, + { + source: "timestamp(3)", + target: "timestamp(6)", + expands: true, + msg: "increased length", + }, + { + source: "timestamp(6)", + target: "timestamp(3)", + }, + { + source: "timestamp(6)", + target: "timestamp", + }, + { + source: "timestamp", + target: "time(3)", + expands: true, + msg: "increased length", + }, + { + source: "datetime", + target: "time(3)", + expands: true, + msg: "increased length", + }, + { + source: "enum('a','b')", + target: "enum('a','b')", + }, + { + source: "enum('a','b')", + target: "enum('a')", + }, + { + source: "enum('a','b')", + target: "enum('b')", + expands: true, + msg: "target enum/set expands or reorders source enum/set", + }, + { + source: "enum('a','b')", + target: "enum('a','b','c')", + expands: true, + msg: "target enum/set expands or reorders source enum/set", + }, + { + source: "enum('a','b')", + target: "enum('a','x')", + expands: true, + msg: "target enum/set expands or reorders source enum/set", + }, + { + source: "set('a','b')", + target: "set('a','b')", + }, + { + source: "set('a','b')", + target: "set('a','b','c')", + expands: true, + msg: "target enum/set expands or reorders source enum/set", + }, + } + env := NewTestEnv() + for _, tcase := range tcases { + t.Run(tcase.source+" -> "+tcase.target, func(t *testing.T) { + fromCreateTableSQL := fmt.Sprintf("create table t (col %s)", tcase.source) + from, err := NewCreateTableEntityFromSQL(env, fromCreateTableSQL) + require.NoError(t, err) + + toCreateTableSQL := fmt.Sprintf("create table t (col %s)", tcase.target) + to, err := NewCreateTableEntityFromSQL(env, toCreateTableSQL) + require.NoError(t, err) + + require.Len(t, from.ColumnDefinitionEntities(), 1) + fromCol := from.ColumnDefinitionEntities()[0] + require.Len(t, to.ColumnDefinitionEntities(), 1) + toCol := to.ColumnDefinitionEntities()[0] + + expands, message := ColumnChangeExpandsDataRange(fromCol, toCol) + assert.Equal(t, tcase.expands, expands, message) + if expands { + require.NotEmpty(t, tcase.msg, message) + } + assert.Contains(t, message, tcase.msg) + }) + } +} + +func TestColumnDefinitionEntityList(t *testing.T) { + table := ` + create table t ( + id int, + col1 int, + Col2 int not null, + primary key (id) + )` + env := NewTestEnv() + createTableEntity, err := NewCreateTableEntityFromSQL(env, table) + require.NoError(t, err) + entities := createTableEntity.ColumnDefinitionEntities() + require.NotEmpty(t, entities) + list := NewColumnDefinitionEntityList(entities) + assert.NotNil(t, list.GetColumn("id")) + assert.NotNil(t, list.GetColumn("col1")) + assert.NotNil(t, list.GetColumn("Col2")) + assert.NotNil(t, list.GetColumn("col2")) // we also allow lower case + assert.Nil(t, list.GetColumn("COL2")) + assert.Nil(t, list.GetColumn("ID")) + assert.Nil(t, list.GetColumn("Col1")) + assert.Nil(t, list.GetColumn("col3")) +} + +func TestColumnDefinitionEntityListSubset(t *testing.T) { + table1 := ` + create table t ( + ID int, + col1 int, + Col2 int not null, + primary key (id) + )` + table2 := ` + create table t ( + id int, + Col1 int, + primary key (id) + )` + env := NewTestEnv() + createTableEntity1, err := NewCreateTableEntityFromSQL(env, table1) + require.NoError(t, err) + entities1 := createTableEntity1.ColumnDefinitionEntities() + require.NotEmpty(t, entities1) + list1 := NewColumnDefinitionEntityList(entities1) + + createTableEntity2, err := NewCreateTableEntityFromSQL(env, table2) + require.NoError(t, err) + entities2 := createTableEntity2.ColumnDefinitionEntities() + require.NotEmpty(t, entities2) + list2 := NewColumnDefinitionEntityList(entities2) + + assert.True(t, list1.Contains(list2)) + assert.False(t, list2.Contains(list1)) +} + +func TestColumnDefinitionEntity(t *testing.T) { + table1 := ` + create table t ( + it int, + e enum('a','b','c'), + primary key (id) + )` + env := NewTestEnv() + createTableEntity1, err := NewCreateTableEntityFromSQL(env, table1) + require.NoError(t, err) + entities1 := createTableEntity1.ColumnDefinitionEntities() + require.NotEmpty(t, entities1) + list1 := NewColumnDefinitionEntityList(entities1) + + t.Run("enum", func(t *testing.T) { + enumCol := list1.GetColumn("e") + require.NotNil(t, enumCol) + assert.Equal(t, []string{"'a'", "'b'", "'c'"}, enumCol.EnumValues()) + + { + ordinalsMap := enumCol.EnumValuesOrdinals() + assert.ElementsMatch(t, []int{1, 2, 3}, maps.Values(ordinalsMap)) + assert.ElementsMatch(t, []string{"'a'", "'b'", "'c'"}, maps.Keys(ordinalsMap)) + } + { + valuesMap := enumCol.EnumOrdinalValues() + assert.ElementsMatch(t, []int{1, 2, 3}, maps.Keys(valuesMap)) + assert.ElementsMatch(t, []string{"'a'", "'b'", "'c'"}, maps.Values(valuesMap)) + } + }) +} diff --git a/go/vt/schemadiff/key.go b/go/vt/schemadiff/key.go new file mode 100644 index 00000000000..865073a5a98 --- /dev/null +++ b/go/vt/schemadiff/key.go @@ -0,0 +1,162 @@ +/* +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 schemadiff + +import ( + "vitess.io/vitess/go/vt/sqlparser" +) + +// IndexDefinitionEntity represents an index definition in a CREATE TABLE statement, +// and includes the list of columns that are part of the index. +type IndexDefinitionEntity struct { + IndexDefinition *sqlparser.IndexDefinition + ColumnList *ColumnDefinitionEntityList + Env *Environment +} + +func NewIndexDefinitionEntity(env *Environment, indexDefinition *sqlparser.IndexDefinition, columnDefinitionEntitiesList *ColumnDefinitionEntityList) *IndexDefinitionEntity { + return &IndexDefinitionEntity{ + IndexDefinition: indexDefinition, + ColumnList: columnDefinitionEntitiesList, + Env: env, + } +} + +func (i *IndexDefinitionEntity) Name() string { + return i.IndexDefinition.Info.Name.String() +} + +func (i *IndexDefinitionEntity) NameLowered() string { + return i.IndexDefinition.Info.Name.Lowered() +} + +// Clone returns a copy of this list, with copies of all the entities. +func (i *IndexDefinitionEntity) Clone() *IndexDefinitionEntity { + clone := &IndexDefinitionEntity{ + IndexDefinition: sqlparser.Clone(i.IndexDefinition), + ColumnList: i.ColumnList.Clone(), + Env: i.Env, + } + return clone +} + +func (i *IndexDefinitionEntity) Len() int { + return len(i.IndexDefinition.Columns) +} + +// IsPrimary returns true if the index is a primary key. +func (i *IndexDefinitionEntity) IsPrimary() bool { + return i.IndexDefinition.Info.Type == sqlparser.IndexTypePrimary +} + +// IsUnique returns true if the index is a unique key. +func (i *IndexDefinitionEntity) IsUnique() bool { + return i.IndexDefinition.Info.IsUnique() +} + +// HasNullable returns true if any of the columns in the index are nullable. +func (i *IndexDefinitionEntity) HasNullable() bool { + for _, col := range i.ColumnList.Entities { + if col.IsNullable() { + return true + } + } + return false +} + +// HasFloat returns true if any of the columns in the index are floating point types. +func (i *IndexDefinitionEntity) HasFloat() bool { + for _, col := range i.ColumnList.Entities { + if col.IsFloatingPointType() { + return true + } + } + return false +} + +// HasColumnPrefix returns true if any of the columns in the index have a length prefix. +func (i *IndexDefinitionEntity) HasColumnPrefix() bool { + for _, col := range i.IndexDefinition.Columns { + if col.Length != nil { + return true + } + } + return false +} + +// ColumnNames returns the names of the columns in the index. +func (i *IndexDefinitionEntity) ColumnNames() []string { + names := make([]string, 0, len(i.IndexDefinition.Columns)) + for _, col := range i.IndexDefinition.Columns { + names = append(names, col.Column.String()) + } + return names +} + +// ContainsColumns returns true if the index contains all the columns in the given list. +func (i *IndexDefinitionEntity) ContainsColumns(columns *ColumnDefinitionEntityList) bool { + return i.ColumnList.Contains(columns) +} + +// CoveredByColumns returns true if the index is covered by the given list of columns. +func (i *IndexDefinitionEntity) CoveredByColumns(columns *ColumnDefinitionEntityList) bool { + return columns.Contains(i.ColumnList) +} + +// IndexDefinitionEntityList is a formalized list of IndexDefinitionEntity objects with a few +// utility methods. +type IndexDefinitionEntityList struct { + Entities []*IndexDefinitionEntity +} + +func NewIndexDefinitionEntityList(entities []*IndexDefinitionEntity) *IndexDefinitionEntityList { + return &IndexDefinitionEntityList{ + Entities: entities, + } +} + +func (l *IndexDefinitionEntityList) Len() int { + return len(l.Entities) +} + +// Names returns the names of the indexes in the list. +func (l *IndexDefinitionEntityList) Names() []string { + names := make([]string, len(l.Entities)) + for i, entity := range l.Entities { + names[i] = entity.Name() + } + return names +} + +// SubsetCoveredByColumns returns a new list of indexes that are covered by the given list of columns. +func (l *IndexDefinitionEntityList) SubsetCoveredByColumns(columns *ColumnDefinitionEntityList) *IndexDefinitionEntityList { + var subset []*IndexDefinitionEntity + for _, entity := range l.Entities { + if entity.CoveredByColumns(columns) { + subset = append(subset, entity) + } + } + return NewIndexDefinitionEntityList(subset) +} + +// First returns the first index in the list, or nil if the list is empty. +func (l *IndexDefinitionEntityList) First() *IndexDefinitionEntity { + if len(l.Entities) == 0 { + return nil + } + return l.Entities[0] +} diff --git a/go/vt/schemadiff/key_test.go b/go/vt/schemadiff/key_test.go new file mode 100644 index 00000000000..f11d5589ab3 --- /dev/null +++ b/go/vt/schemadiff/key_test.go @@ -0,0 +1,185 @@ +/* +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 schemadiff + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIndexDefinitionEntityMap(t *testing.T) { + table := ` + create table t ( + id int, + col1 int, + Col2 int not null, + col3 int not null default 3, + f float not null, + v varchar(32), + primary key (id), + unique key ukid (id), + unique key uk1 (col1), + unique key uk2 (Col2), + unique key uk3 (col3), + key k1 (col1), + key k2 (Col2), + key k3 (col3), + key kf (f), + key kf2 (f, Col2), + key kv (v), + key kv1 (v, col1), + key kv2 (v(10), Col2), + unique key uk12 (col1, Col2), + unique key uk21 (col2, Col1), + unique key uk23 (col2, col3), + unique key ukid3 (id, col3) + )` + tcases := []struct { + key string + unique bool + columns []string + nullable bool + float bool + prefix bool + }{ + { + key: "primary", + unique: true, + columns: []string{"id"}, + nullable: false, + }, + { + key: "ukid", + unique: true, + columns: []string{"id"}, + nullable: false, + }, + { + key: "uk1", + unique: true, + columns: []string{"col1"}, + nullable: true, + }, + { + key: "uk2", + unique: true, + columns: []string{"Col2"}, + nullable: false, + }, + { + key: "uk3", + unique: true, + columns: []string{"col3"}, + nullable: false, + }, + { + key: "k1", + unique: false, + columns: []string{"col1"}, + nullable: true, + }, + { + key: "k2", + unique: false, + columns: []string{"Col2"}, + nullable: false, + }, + { + key: "k3", + unique: false, + columns: []string{"col3"}, + nullable: false, + }, + { + key: "kf", + unique: false, + columns: []string{"f"}, + nullable: false, + float: true, + }, + { + key: "kf2", + unique: false, + columns: []string{"f", "Col2"}, + nullable: false, + float: true, + }, + { + key: "kv", + unique: false, + columns: []string{"v"}, + nullable: true, + }, + { + key: "kv1", + unique: false, + columns: []string{"v", "col1"}, + nullable: true, + }, + { + key: "kv2", + unique: false, + columns: []string{"v", "Col2"}, + nullable: true, + prefix: true, + }, + { + key: "uk12", + unique: true, + columns: []string{"col1", "Col2"}, + nullable: true, + }, + { + key: "uk21", + unique: true, + columns: []string{"col2", "Col1"}, + nullable: true, + }, + { + key: "uk23", + unique: true, + columns: []string{"col2", "col3"}, + nullable: false, + }, + { + key: "ukid3", + unique: true, + columns: []string{"id", "col3"}, + nullable: false, + }, + } + env := NewTestEnv() + createTableEntity, err := NewCreateTableEntityFromSQL(env, table) + require.NoError(t, err) + err = createTableEntity.validate() + require.NoError(t, err) + m := createTableEntity.IndexDefinitionEntitiesMap() + require.NotEmpty(t, m) + for _, tcase := range tcases { + t.Run(tcase.key, func(t *testing.T) { + key := m[tcase.key] + require.NotNil(t, key) + assert.Equal(t, tcase.unique, key.IsUnique()) + assert.Equal(t, tcase.columns, key.ColumnNames()) + assert.Equal(t, tcase.nullable, key.HasNullable()) + assert.Equal(t, tcase.float, key.HasFloat()) + assert.Equal(t, tcase.prefix, key.HasColumnPrefix()) + }) + } +} diff --git a/go/vt/schemadiff/mysql.go b/go/vt/schemadiff/mysql.go index 624897e2e43..65adcc1b7a1 100644 --- a/go/vt/schemadiff/mysql.go +++ b/go/vt/schemadiff/mysql.go @@ -21,20 +21,26 @@ var engineCasing = map[string]string{ "MYISAM": "MyISAM", } -var integralTypes = map[string]bool{ - "tinyint": true, - "smallint": true, - "mediumint": true, - "int": true, - "bigint": true, +// integralTypes maps known integer types to their byte storage size +var integralTypes = map[string]int{ + "tinyint": 1, + "smallint": 2, + "mediumint": 3, + "int": 4, + "bigint": 8, } -var floatTypes = map[string]bool{ - "float": true, - "float4": true, - "float8": true, - "double": true, - "real": true, +var floatTypes = map[string]int{ + "float": 4, + "float4": 4, + "float8": 8, + "double": 8, + "real": 8, +} + +var decimalTypes = map[string]bool{ + "decimal": true, + "numeric": true, } var charsetTypes = map[string]bool{ @@ -48,6 +54,56 @@ var charsetTypes = map[string]bool{ "set": true, } +var blobStorageExponent = map[string]int{ + "tinyblob": 8, + "tinytext": 8, + "blob": 16, + "text": 16, + "mediumblob": 24, + "mediumtext": 24, + "longblob": 32, + "longtext": 32, +} + +func IsFloatingPointType(columnType string) bool { + _, ok := floatTypes[columnType] + return ok +} + +func FloatingPointTypeStorage(columnType string) int { + return floatTypes[columnType] +} + func IsIntegralType(columnType string) bool { + _, ok := integralTypes[columnType] + return ok +} + +func IntegralTypeStorage(columnType string) int { return integralTypes[columnType] } + +func IsDecimalType(columnType string) bool { + return decimalTypes[columnType] +} + +func BlobTypeStorage(columnType string) int { + return blobStorageExponent[columnType] +} + +// expandedDataTypes maps some known and difficult-to-compute by INFORMATION_SCHEMA data types which expand other data types. +// For example, in "date:datetime", datetime expands date because it has more precision. In "timestamp:date" date expands timestamp +// because it can contain years not covered by timestamp. +var expandedDataTypes = map[string]bool{ + "time:datetime": true, + "date:datetime": true, + "timestamp:datetime": true, + "time:timestamp": true, + "date:timestamp": true, + "timestamp:date": true, +} + +func IsExpandingDataType(sourceType string, targetType string) bool { + _, ok := expandedDataTypes[sourceType+":"+targetType] + return ok +} diff --git a/go/vt/schemadiff/onlineddl.go b/go/vt/schemadiff/onlineddl.go new file mode 100644 index 00000000000..66908e502f5 --- /dev/null +++ b/go/vt/schemadiff/onlineddl.go @@ -0,0 +1,590 @@ +/* +Copyright 2022 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 schemadiff + +import ( + "fmt" + "math" + "sort" + "strings" + + "vitess.io/vitess/go/vt/sqlparser" +) + +// ColumnChangeExpandsDataRange sees if target column has any value set/range that is impossible in source column. +func ColumnChangeExpandsDataRange(source *ColumnDefinitionEntity, target *ColumnDefinitionEntity) (bool, string) { + if target.IsNullable() && !source.IsNullable() { + return true, "target is NULL-able, source is not" + } + if target.Length() > source.Length() { + return true, "increased length" + } + if target.Scale() > source.Scale() { + return true, "increased scale" + } + if source.IsUnsigned() && !target.IsUnsigned() { + return true, "source is unsigned, target is signed" + } + if IntegralTypeStorage(target.Type()) > IntegralTypeStorage(source.Type()) && IntegralTypeStorage(source.Type()) != 0 { + return true, "increased integer range" + } + if IntegralTypeStorage(source.Type()) <= IntegralTypeStorage(target.Type()) && + !source.IsUnsigned() && target.IsUnsigned() { + // e.g. INT SIGNED => INT UNSIGNED, INT SIGNED => BIGINT UNSIGNED + return true, "target unsigned value exceeds source unsigned value" + } + if FloatingPointTypeStorage(target.Type()) > FloatingPointTypeStorage(source.Type()) && FloatingPointTypeStorage(source.Type()) != 0 { + return true, "increased floating point range" + } + if target.IsFloatingPointType() && !source.IsFloatingPointType() { + return true, "target is floating point, source is not" + } + if target.IsDecimalType() && !source.IsDecimalType() { + return true, "target is decimal, source is not" + } + if target.IsDecimalType() && source.IsDecimalType() { + if target.Length()-target.Scale() > source.Length()-source.Scale() { + return true, "increased decimal range" + } + } + if IsExpandingDataType(source.Type(), target.Type()) { + return true, "target is expanded data type of source" + } + if BlobTypeStorage(target.Type()) > BlobTypeStorage(source.Type()) && BlobTypeStorage(source.Type()) != 0 { + return true, "increased blob range" + } + if source.Charset() != target.Charset() { + if target.Charset() == "utf8mb4" { + return true, "expand character set to utf8mb4" + } + if strings.HasPrefix(target.Charset(), "utf8") && !strings.HasPrefix(source.Charset(), "utf8") { + // not utf to utf + return true, "expand character set to utf8" + } + } + for _, colType := range []string{"enum", "set"} { + // enums and sets have very similar properties, and are practically identical in our analysis + if source.Type() == colType { + // this is an enum or a set + if target.Type() != colType { + return true, "conversion from enum/set to non-enum/set adds potential values" + } + // target is an enum or a set. See if all values on target exist in source + sourceEnumTokensMap := source.EnumOrdinalValues() + targetEnumTokensMap := target.EnumOrdinalValues() + for k, v := range targetEnumTokensMap { + if sourceEnumTokensMap[k] != v { + return true, "target enum/set expands or reorders source enum/set" + } + } + } + } + return false, "" +} + +// IsValidIterationKey returns true if the key is eligible for Online DDL iteration. +func IsValidIterationKey(key *IndexDefinitionEntity) bool { + if key == nil { + return false + } + if !key.IsUnique() { + return false + } + if key.HasFloat() { + return false + } + if key.HasColumnPrefix() { + return false + } + if key.HasNullable() { + return false + } + return true +} + +// PrioritizedUniqueKeys returns all unique keys on given table, ordered from "best" to "worst", +// for Online DDL purposes. The list of keys includes some that are not eligible for Online DDL +// iteration. +func PrioritizedUniqueKeys(createTableEntity *CreateTableEntity) *IndexDefinitionEntityList { + uniqueKeys := []*IndexDefinitionEntity{} + for _, key := range createTableEntity.IndexDefinitionEntities() { + if !key.IsUnique() { + continue + } + uniqueKeys = append(uniqueKeys, key) + } + sort.SliceStable(uniqueKeys, func(i, j int) bool { + if uniqueKeys[i].IsPrimary() { + // PRIMARY is always first + return true + } + if uniqueKeys[j].IsPrimary() { + // PRIMARY is always first + return false + } + if !uniqueKeys[i].HasNullable() && uniqueKeys[j].HasNullable() { + // Non NULLable comes first + return true + } + if uniqueKeys[i].HasNullable() && !uniqueKeys[j].HasNullable() { + // NULLable come last + return false + } + if !uniqueKeys[i].HasColumnPrefix() && uniqueKeys[j].HasColumnPrefix() { + // Non prefix comes first + return true + } + if uniqueKeys[i].HasColumnPrefix() && !uniqueKeys[j].HasColumnPrefix() { + // Prefix comes last + return false + } + iFirstColEntity := uniqueKeys[i].ColumnList.Entities[0] + jFirstColEntity := uniqueKeys[j].ColumnList.Entities[0] + if iFirstColEntity.IsIntegralType() && !jFirstColEntity.IsIntegralType() { + // Prioritize integers + return true + } + if !iFirstColEntity.IsIntegralType() && jFirstColEntity.IsIntegralType() { + // Prioritize integers + return false + } + if !iFirstColEntity.HasBlobTypeStorage() && jFirstColEntity.HasBlobTypeStorage() { + return true + } + if iFirstColEntity.HasBlobTypeStorage() && !jFirstColEntity.HasBlobTypeStorage() { + return false + } + if !iFirstColEntity.IsTextual() && jFirstColEntity.IsTextual() { + return true + } + if iFirstColEntity.IsTextual() && !jFirstColEntity.IsTextual() { + return false + } + if storageDiff := IntegralTypeStorage(iFirstColEntity.Type()) - IntegralTypeStorage(jFirstColEntity.Type()); storageDiff != 0 { + return storageDiff < 0 + } + if lenDiff := len(uniqueKeys[i].ColumnList.Entities) - len(uniqueKeys[j].ColumnList.Entities); lenDiff != 0 { + return lenDiff < 0 + } + return false + }) + return NewIndexDefinitionEntityList(uniqueKeys) +} + +// RemovedForeignKeyNames returns the names of removed foreign keys, ignoring mere name changes +func RemovedForeignKeyNames(source *CreateTableEntity, target *CreateTableEntity) (names []string, err error) { + if source == nil || target == nil { + return nil, nil + } + diffHints := DiffHints{ + ConstraintNamesStrategy: ConstraintNamesIgnoreAll, + } + diff, err := source.Diff(target, &diffHints) + if err != nil { + return nil, err + } + names = []string{} + validateWalk := func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *sqlparser.DropKey: + if node.Type == sqlparser.ForeignKeyType { + names = append(names, node.Name.String()) + } + } + return true, nil + } + _ = sqlparser.Walk(validateWalk, diff.Statement()) // We never return an error + return names, nil +} + +// AlterTableAnalysis contains useful Online DDL information about an AlterTable statement +type AlterTableAnalysis struct { + ColumnRenameMap map[string]string + DroppedColumnsMap map[string]bool + IsRenameTable bool + IsAutoIncrementChangeRequested bool +} + +// AnalyzeAlter looks for specific changes in the AlterTable statement, that are relevant +// to OnlineDDL/VReplication +func OnlineDDLAlterTableAnalysis(alterTable *sqlparser.AlterTable) *AlterTableAnalysis { + analysis := &AlterTableAnalysis{ + ColumnRenameMap: make(map[string]string), + DroppedColumnsMap: make(map[string]bool), + } + if alterTable == nil { + return analysis + } + for _, opt := range alterTable.AlterOptions { + switch opt := opt.(type) { + case *sqlparser.RenameTableName: + analysis.IsRenameTable = true + case *sqlparser.DropColumn: + analysis.DroppedColumnsMap[opt.Name.Name.String()] = true + case *sqlparser.ChangeColumn: + if opt.OldColumn != nil && opt.NewColDefinition != nil { + oldName := opt.OldColumn.Name.String() + newName := opt.NewColDefinition.Name.String() + analysis.ColumnRenameMap[oldName] = newName + } + case sqlparser.TableOptions: + for _, tableOption := range opt { + if strings.ToUpper(tableOption.Name) == "AUTO_INCREMENT" { + analysis.IsAutoIncrementChangeRequested = true + } + } + } + } + return analysis +} + +// GetExpandedColumnNames is given source and target shared columns, and returns the list of columns whose data type is expanded. +// An expanded data type is one where the target can have a value which the source does not. Examples: +// - any NOT NULL to NULLable (a NULL in the target cannot appear on source) +// - INT -> BIGINT (obvious) +// - BIGINT UNSIGNED -> INT SIGNED (negative values) +// - TIMESTAMP -> TIMESTAMP(3) +// etc. +func GetExpandedColumns( + sourceColumns *ColumnDefinitionEntityList, + targetColumns *ColumnDefinitionEntityList, +) ( + expandedColumns *ColumnDefinitionEntityList, + expandedDescriptions map[string]string, + err error, +) { + if len(sourceColumns.Entities) != len(targetColumns.Entities) { + return nil, nil, fmt.Errorf("source and target columns must be of same length") + } + + expandedEntities := []*ColumnDefinitionEntity{} + expandedDescriptions = map[string]string{} + for i := range sourceColumns.Entities { + // source and target columns assumed to be mapped 1:1, same length + sourceColumn := sourceColumns.Entities[i] + targetColumn := targetColumns.Entities[i] + + if isExpanded, description := ColumnChangeExpandsDataRange(sourceColumn, targetColumn); isExpanded { + expandedEntities = append(expandedEntities, sourceColumn) + expandedDescriptions[sourceColumn.Name()] = description + } + } + return NewColumnDefinitionEntityList(expandedEntities), expandedDescriptions, nil +} + +// AnalyzeSharedColumns returns the intersection of two lists of columns in same order as the first list +func AnalyzeSharedColumns( + sourceColumns, targetColumns *ColumnDefinitionEntityList, + alterTableAnalysis *AlterTableAnalysis, +) ( + sourceSharedColumns *ColumnDefinitionEntityList, + targetSharedColumns *ColumnDefinitionEntityList, + droppedSourceNonGeneratedColumns *ColumnDefinitionEntityList, + sharedColumnsMap map[string]string, +) { + sharedColumnsMap = map[string]string{} + sourceShared := []*ColumnDefinitionEntity{} + targetShared := []*ColumnDefinitionEntity{} + droppedNonGenerated := []*ColumnDefinitionEntity{} + + for _, sourceColumn := range sourceColumns.Entities { + if sourceColumn.IsGenerated() { + continue + } + isDroppedFromSource := false + // Note to a future engineer: you may be tempted to remove this loop based on the + // assumption that the later `targetColumn := targetColumns.GetColumn(expectedTargetName)` + // check is sufficient. It is not. It is possible that a columns was explicitly dropped + // and added (`DROP COLUMN c, ADD COLUMN c INT`) in the same ALTER TABLE statement. + // Without checking the ALTER TABLE statement, we would be fooled to believe that column + // `c` is unchanged in the target, when in fact it was dropped and re-added. + for droppedColumn := range alterTableAnalysis.DroppedColumnsMap { + if strings.EqualFold(sourceColumn.Name(), droppedColumn) { + isDroppedFromSource = true + break + } + } + if isDroppedFromSource { + droppedNonGenerated = append(droppedNonGenerated, sourceColumn) + // Column was dropped, hence cannot be a shared column + continue + } + expectedTargetName := sourceColumn.NameLowered() + if mappedName := alterTableAnalysis.ColumnRenameMap[sourceColumn.Name()]; mappedName != "" { + expectedTargetName = mappedName + } + targetColumn := targetColumns.GetColumn(expectedTargetName) + if targetColumn == nil { + // Column not found in target + droppedNonGenerated = append(droppedNonGenerated, sourceColumn) + continue + } + if targetColumn.IsGenerated() { + // virtual/generated columns are silently skipped. + continue + } + // OK, the column is shared (possibly renamed) between source and target. + sharedColumnsMap[sourceColumn.Name()] = targetColumn.Name() + sourceShared = append(sourceShared, sourceColumn) + targetShared = append(targetShared, targetColumn) + } + return NewColumnDefinitionEntityList(sourceShared), + NewColumnDefinitionEntityList(targetShared), + NewColumnDefinitionEntityList(droppedNonGenerated), + sharedColumnsMap +} + +// KeyAtLeastConstrainedAs returns 'true' when sourceUniqueKey is at least as constrained as targetUniqueKey. +// "More constrained" means the uniqueness constraint is "stronger". Thus, if sourceUniqueKey is as-or-more constrained than targetUniqueKey, then +// rows valid under sourceUniqueKey must also be valid in targetUniqueKey. The opposite is not necessarily so: rows that are valid in targetUniqueKey +// may cause a unique key violation under sourceUniqueKey +func KeyAtLeastConstrainedAs( + sourceUniqueKey *IndexDefinitionEntity, + targetUniqueKey *IndexDefinitionEntity, + columnRenameMap map[string]string, +) bool { + if !sourceUniqueKey.IsUnique() { + return false + } + if !targetUniqueKey.IsUnique() { + return true + } + sourceKeyLengths := map[string]int{} + for _, col := range sourceUniqueKey.IndexDefinition.Columns { + if col.Length == nil { + sourceKeyLengths[col.Column.Lowered()] = math.MaxInt64 + } else { + sourceKeyLengths[col.Column.Lowered()] = *col.Length + } + } + targetKeyLengths := map[string]int{} + for _, col := range targetUniqueKey.IndexDefinition.Columns { + if col.Length == nil { + targetKeyLengths[col.Column.Lowered()] = math.MaxInt64 + } else { + targetKeyLengths[col.Column.Lowered()] = *col.Length + } + } + // source is more constrained than target if every column in source is also in target, order is immaterial + for _, sourceCol := range sourceUniqueKey.ColumnList.Entities { + mappedColName, ok := columnRenameMap[sourceCol.Name()] + if !ok { + mappedColName = sourceCol.NameLowered() + } + targetCol := targetUniqueKey.ColumnList.GetColumn(mappedColName) + if targetCol == nil { + // source can't be more constrained if it covers *more* columns + return false + } + // We now know that sourceCol maps to targetCol + if sourceKeyLengths[sourceCol.NameLowered()] > targetKeyLengths[targetCol.NameLowered()] { + // source column covers a larger prefix than target column. It is therefore less constrained. + return false + } + } + return true +} + +// IntroducedUniqueConstraints returns the unique key constraints added in target. +// This does not necessarily mean that the unique key itself is new, +// rather that there's a new, stricter constraint on a set of columns, that didn't exist before. Example: +// +// before: +// unique key my_key (c1, c2, c3) +// after: +// unique key `other_key`(c1, c2) +// Synopsis: the constraint on (c1, c2) is new; and `other_key` in target table is considered a new key +// +// Order of columns is immaterial to uniqueness of column combination. +func IntroducedUniqueConstraints(sourceUniqueKeys *IndexDefinitionEntityList, targetUniqueKeys *IndexDefinitionEntityList, columnRenameMap map[string]string) *IndexDefinitionEntityList { + introducedUniqueConstraints := []*IndexDefinitionEntity{} + for _, targetUniqueKey := range targetUniqueKeys.Entities { + foundSourceKeyAtLeastAsConstrained := func() bool { + for _, sourceUniqueKey := range sourceUniqueKeys.Entities { + if KeyAtLeastConstrainedAs(sourceUniqueKey, targetUniqueKey, columnRenameMap) { + // target key does not add a new constraint + return true + } + } + return false + } + if !foundSourceKeyAtLeastAsConstrained() { + introducedUniqueConstraints = append(introducedUniqueConstraints, targetUniqueKey) + } + } + return NewIndexDefinitionEntityList(introducedUniqueConstraints) +} + +// RemovedUniqueConstraints returns the list of unique key constraints _removed_ going from source to target. +func RemovedUniqueConstraints(sourceUniqueKeys *IndexDefinitionEntityList, targetUniqueKeys *IndexDefinitionEntityList, columnRenameMap map[string]string) *IndexDefinitionEntityList { + reverseColumnRenameMap := map[string]string{} + for k, v := range columnRenameMap { + reverseColumnRenameMap[v] = k + } + return IntroducedUniqueConstraints(targetUniqueKeys, sourceUniqueKeys, reverseColumnRenameMap) +} + +// IterationKeysByColumns returns the Online DDL compliant unique keys from given list, +// whose columns are all covered by the given column list. +func IterationKeysByColumns(keys *IndexDefinitionEntityList, columns *ColumnDefinitionEntityList) *IndexDefinitionEntityList { + subset := []*IndexDefinitionEntity{} + for _, key := range keys.SubsetCoveredByColumns(columns).Entities { + if IsValidIterationKey(key) { + subset = append(subset, key) + } + } + return NewIndexDefinitionEntityList(subset) +} + +// MappedColumnNames +func MappedColumnNames(columnsList *ColumnDefinitionEntityList, columnNamesMap map[string]string) []string { + names := columnsList.Names() + for i := range names { + if mappedName, ok := columnNamesMap[names[i]]; ok { + names[i] = mappedName + } + } + return names +} + +// AlterTableAnalysis contains useful Online DDL information about an AlterTable statement +type MigrationTablesAnalysis struct { + SourceSharedColumns *ColumnDefinitionEntityList + TargetSharedColumns *ColumnDefinitionEntityList + DroppedNoDefaultColumns *ColumnDefinitionEntityList + ExpandedColumns *ColumnDefinitionEntityList + SharedColumnsMap map[string]string + ChosenSourceUniqueKey *IndexDefinitionEntity + ChosenTargetUniqueKey *IndexDefinitionEntity + AddedUniqueKeys *IndexDefinitionEntityList + RemovedUniqueKeys *IndexDefinitionEntityList + RemovedForeignKeyNames []string + IntToEnumMap map[string]bool + SourceAutoIncrement uint64 + RevertibleNotes []string +} + +func OnlineDDLMigrationTablesAnalysis( + sourceCreateTableEntity *CreateTableEntity, + targetCreateTableEntity *CreateTableEntity, + alterTableAnalysis *AlterTableAnalysis, +) (analysis *MigrationTablesAnalysis, err error) { + analysis = &MigrationTablesAnalysis{ + IntToEnumMap: make(map[string]bool), + RevertibleNotes: []string{}, + } + // columns: + generatedColumns := func(columns *ColumnDefinitionEntityList) *ColumnDefinitionEntityList { + return columns.Filter(func(col *ColumnDefinitionEntity) bool { + return col.IsGenerated() + }) + } + noDefaultColumns := func(columns *ColumnDefinitionEntityList) *ColumnDefinitionEntityList { + return columns.Filter(func(col *ColumnDefinitionEntity) bool { + return !col.HasDefault() + }) + } + sourceColumns := sourceCreateTableEntity.ColumnDefinitionEntitiesList() + targetColumns := targetCreateTableEntity.ColumnDefinitionEntitiesList() + + var droppedSourceNonGeneratedColumns *ColumnDefinitionEntityList + analysis.SourceSharedColumns, analysis.TargetSharedColumns, droppedSourceNonGeneratedColumns, analysis.SharedColumnsMap = AnalyzeSharedColumns(sourceColumns, targetColumns, alterTableAnalysis) + + // unique keys + sourceUniqueKeys := PrioritizedUniqueKeys(sourceCreateTableEntity) + if sourceUniqueKeys.Len() == 0 { + return nil, fmt.Errorf("found no possible unique key on `%s`", sourceCreateTableEntity.Name()) + } + + targetUniqueKeys := PrioritizedUniqueKeys(targetCreateTableEntity) + if targetUniqueKeys.Len() == 0 { + return nil, fmt.Errorf("found no possible unique key on `%s`", targetCreateTableEntity.Name()) + } + // VReplication supports completely different unique keys on source and target, covering + // some/completely different columns. The condition is that the key on source + // must use columns which all exist on target table. + eligibleSourceColumnsForUniqueKey := analysis.SourceSharedColumns.Union(generatedColumns(sourceColumns)) + analysis.ChosenSourceUniqueKey = IterationKeysByColumns(sourceUniqueKeys, eligibleSourceColumnsForUniqueKey).First() + if analysis.ChosenSourceUniqueKey == nil { + return nil, fmt.Errorf("found no possible unique key on `%s` whose columns are in target table `%s`", sourceCreateTableEntity.Name(), targetCreateTableEntity.Name()) + } + + eligibleTargetColumnsForUniqueKey := analysis.TargetSharedColumns.Union(generatedColumns(targetColumns)) + analysis.ChosenTargetUniqueKey = IterationKeysByColumns(targetUniqueKeys, eligibleTargetColumnsForUniqueKey).First() + if analysis.ChosenTargetUniqueKey == nil { + return nil, fmt.Errorf("found no possible unique key on `%s` whose columns are in source table `%s`", targetCreateTableEntity.Name(), sourceCreateTableEntity.Name()) + } + + analysis.AddedUniqueKeys = IntroducedUniqueConstraints(sourceUniqueKeys, targetUniqueKeys, alterTableAnalysis.ColumnRenameMap) + analysis.RemovedUniqueKeys = RemovedUniqueConstraints(sourceUniqueKeys, targetUniqueKeys, alterTableAnalysis.ColumnRenameMap) + analysis.RemovedForeignKeyNames, err = RemovedForeignKeyNames(sourceCreateTableEntity, targetCreateTableEntity) + if err != nil { + return nil, err + } + + formalizeColumns := func(columnsLists ...*ColumnDefinitionEntityList) error { + for _, colList := range columnsLists { + for _, col := range colList.Entities { + col.SetExplicitDefaultAndNull() + if err := col.SetExplicitCharsetCollate(); err != nil { + return err + } + } + } + return nil + } + + if err := formalizeColumns(analysis.SourceSharedColumns, analysis.TargetSharedColumns, droppedSourceNonGeneratedColumns); err != nil { + return nil, err + } + + for i := range analysis.SourceSharedColumns.Entities { + sourceColumn := analysis.SourceSharedColumns.Entities[i] + mappedColumn := analysis.TargetSharedColumns.Entities[i] + + if sourceColumn.IsIntegralType() && mappedColumn.Type() == "enum" { + analysis.IntToEnumMap[sourceColumn.Name()] = true + } + } + + analysis.DroppedNoDefaultColumns = noDefaultColumns(droppedSourceNonGeneratedColumns) + var expandedDescriptions map[string]string + analysis.ExpandedColumns, expandedDescriptions, err = GetExpandedColumns(analysis.SourceSharedColumns, analysis.TargetSharedColumns) + if err != nil { + return nil, err + } + + analysis.SourceAutoIncrement, err = sourceCreateTableEntity.AutoIncrementValue() + if err != nil { + return nil, err + } + + for _, uk := range analysis.RemovedUniqueKeys.Names() { + analysis.RevertibleNotes = append(analysis.RevertibleNotes, fmt.Sprintf("unique constraint removed: %s", uk)) + } + for _, name := range analysis.DroppedNoDefaultColumns.Names() { + analysis.RevertibleNotes = append(analysis.RevertibleNotes, fmt.Sprintf("column %s dropped, and had no default value", name)) + } + for _, name := range analysis.ExpandedColumns.Names() { + analysis.RevertibleNotes = append(analysis.RevertibleNotes, fmt.Sprintf("column %s: %s", name, expandedDescriptions[name])) + } + for _, name := range analysis.RemovedForeignKeyNames { + analysis.RevertibleNotes = append(analysis.RevertibleNotes, fmt.Sprintf("foreign key %s dropped", name)) + } + + return analysis, nil +} diff --git a/go/vt/schemadiff/onlineddl_test.go b/go/vt/schemadiff/onlineddl_test.go new file mode 100644 index 00000000000..bd08bedfe8a --- /dev/null +++ b/go/vt/schemadiff/onlineddl_test.go @@ -0,0 +1,960 @@ +/* +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 schemadiff + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/sqlparser" +) + +func TestPrioritizedUniqueKeys(t *testing.T) { + table := ` + create table t ( + idsha varchar(64), + col1 int, + col2 int not null, + col3 bigint not null default 3, + col4 smallint not null, + f float not null, + v varchar(32) not null, + primary key (idsha), + unique key ukidsha (idsha), + unique key uk1 (col1), + unique key uk2 (col2), + unique key uk3 (col3), + key k1 (col1), + key kf (f), + key k1f (col1, f), + key kv (v), + unique key ukv (v), + unique key ukvprefix (v(10)), + unique key uk2vprefix (col2, v(10)), + unique key uk1f (col1, f), + unique key uk41 (col4, col1), + unique key uk42 (col4, col2) + )` + env := NewTestEnv() + createTableEntity, err := NewCreateTableEntityFromSQL(env, table) + require.NoError(t, err) + err = createTableEntity.validate() + require.NoError(t, err) + + keys := PrioritizedUniqueKeys(createTableEntity) + require.NotEmpty(t, keys) + names := make([]string, 0, len(keys.Entities)) + for _, key := range keys.Entities { + names = append(names, key.Name()) + } + expect := []string{ + "PRIMARY", + "uk42", + "uk2", + "uk3", + "ukidsha", + "ukv", + "uk2vprefix", + "ukvprefix", + "uk41", + "uk1", + "uk1f", + } + assert.Equal(t, expect, names) +} + +func TestRemovedForeignKeyNames(t *testing.T) { + env := NewTestEnv() + + tcases := []struct { + before string + after string + names []string + }{ + { + before: "create table t (id int primary key)", + after: "create table t (id2 int primary key, i int)", + }, + { + before: "create table t (id int primary key)", + after: "create table t2 (id2 int primary key, i int)", + }, + { + before: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", + after: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", + }, + { + before: "create table t (id int primary key, i int, constraint f1 foreign key (i) references parent (id) on delete cascade)", + after: "create table t (id int primary key, i int, constraint f2 foreign key (i) references parent (id) on delete cascade)", + }, + { + before: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", + after: "create table t (id int primary key, i int)", + names: []string{"f"}, + }, + { + before: "create table t (id int primary key, i int, i2 int, constraint f1 foreign key (i) references parent (id) on delete cascade, constraint fi2 foreign key (i2) references parent (id) on delete cascade)", + after: "create table t (id int primary key, i int, i2 int, constraint f2 foreign key (i) references parent (id) on delete cascade)", + names: []string{"fi2"}, + }, + { + before: "create table t1 (id int primary key, i int, constraint `check1` CHECK ((`i` < 5)))", + after: "create table t2 (id int primary key, i int)", + }, + } + for _, tcase := range tcases { + t.Run(tcase.before, func(t *testing.T) { + before, err := NewCreateTableEntityFromSQL(env, tcase.before) + require.NoError(t, err) + err = before.validate() + require.NoError(t, err) + + after, err := NewCreateTableEntityFromSQL(env, tcase.after) + require.NoError(t, err) + err = after.validate() + require.NoError(t, err) + + names, err := RemovedForeignKeyNames(before, after) + assert.NoError(t, err) + if tcase.names == nil { + tcase.names = []string{} + } + assert.Equal(t, tcase.names, names) + }) + } +} + +func TestGetAlterTableAnalysis(t *testing.T) { + tcases := []struct { + alter string + renames map[string]string + drops map[string]bool + isrename bool + autoinc bool + }{ + { + alter: "alter table t add column t int, engine=innodb", + }, + { + alter: "alter table t add column t int, change ts ts timestamp, engine=innodb", + renames: map[string]string{"ts": "ts"}, + }, + { + alter: "alter table t AUTO_INCREMENT=7", + autoinc: true, + }, + { + alter: "alter table t add column t int, change ts ts timestamp, auto_increment=7 engine=innodb", + renames: map[string]string{"ts": "ts"}, + autoinc: true, + }, + { + alter: "alter table t add column t int, change ts ts timestamp, CHANGE f `f` float, engine=innodb", + renames: map[string]string{"ts": "ts", "f": "f"}, + }, + { + alter: `alter table t add column b bigint, change f fl float, change i count int, engine=innodb`, + renames: map[string]string{"f": "fl", "i": "count"}, + }, + { + alter: "alter table t add column b bigint, change column `f` fl float, change `i` `count` int, engine=innodb", + renames: map[string]string{"f": "fl", "i": "count"}, + }, + { + alter: "alter table t add column b bigint, change column `f` fl float, change `i` `count` int, change ts ts timestamp, engine=innodb", + renames: map[string]string{"f": "fl", "i": "count", "ts": "ts"}, + }, + { + alter: "alter table t drop column b", + drops: map[string]bool{"b": true}, + }, + { + alter: "alter table t drop column b, drop key c_idx, drop column `d`", + drops: map[string]bool{"b": true, "d": true}, + }, + { + alter: "alter table t drop column b, drop key c_idx, drop column `d`, drop `e`, drop primary key, drop foreign key fk_1", + drops: map[string]bool{"b": true, "d": true, "e": true}, + }, + { + alter: "alter table t rename as something_else", + isrename: true, + }, + { + alter: "alter table t drop column b, rename as something_else", + isrename: true, + drops: map[string]bool{"b": true}, + }, + } + for _, tcase := range tcases { + t.Run(tcase.alter, func(t *testing.T) { + if tcase.renames == nil { + tcase.renames = make(map[string]string) + } + if tcase.drops == nil { + tcase.drops = make(map[string]bool) + } + stmt, err := sqlparser.NewTestParser().ParseStrictDDL(tcase.alter) + require.NoError(t, err) + alter, ok := stmt.(*sqlparser.AlterTable) + require.True(t, ok) + + analysis := OnlineDDLAlterTableAnalysis(alter) + require.NotNil(t, analysis) + assert.Equal(t, tcase.isrename, analysis.IsRenameTable) + assert.Equal(t, tcase.autoinc, analysis.IsAutoIncrementChangeRequested) + assert.Equal(t, tcase.renames, analysis.ColumnRenameMap) + assert.Equal(t, tcase.drops, analysis.DroppedColumnsMap) + }) + } +} + +func TestAnalyzeSharedColumns(t *testing.T) { + sourceTable := ` + create table t ( + id int, + cint int, + cgen1 int generated always as (cint + 1) stored, + cgen2 int generated always as (cint + 2) stored, + cchar char(1), + cremoved int not null default 7, + cnullable int, + cnodefault int not null, + extra1 int, + primary key (id) + ) + ` + targetTable := ` + create table t ( + id int, + cint int, + cgen1 int generated always as (cint + 1) stored, + cchar_alternate char(1), + cnullable int, + cnodefault int not null, + extra2 int, + primary key (id) + ) + ` + tcases := []struct { + name string + sourceTable string + targetTable string + renameMap map[string]string + expectSourceSharedColNames []string + expectTargetSharedColNames []string + expectDroppedSourceNonGeneratedColNames []string + expectSharedColumnsMap map[string]string + }{ + { + name: "rename map empty", + renameMap: map[string]string{}, + expectSourceSharedColNames: []string{"id", "cint", "cnullable", "cnodefault"}, + expectTargetSharedColNames: []string{"id", "cint", "cnullable", "cnodefault"}, + expectDroppedSourceNonGeneratedColNames: []string{"cchar", "cremoved", "extra1"}, + expectSharedColumnsMap: map[string]string{"id": "id", "cint": "cint", "cnullable": "cnullable", "cnodefault": "cnodefault"}, + }, + { + name: "renamed column", + renameMap: map[string]string{"cchar": "cchar_alternate"}, + expectSourceSharedColNames: []string{"id", "cint", "cchar", "cnullable", "cnodefault"}, + expectTargetSharedColNames: []string{"id", "cint", "cchar_alternate", "cnullable", "cnodefault"}, + expectDroppedSourceNonGeneratedColNames: []string{"cremoved", "extra1"}, + expectSharedColumnsMap: map[string]string{"id": "id", "cint": "cint", "cchar": "cchar_alternate", "cnullable": "cnullable", "cnodefault": "cnodefault"}, + }, + } + + env := NewTestEnv() + alterTableAnalysis := OnlineDDLAlterTableAnalysis(nil) // empty + for _, tcase := range tcases { + t.Run(tcase.name, func(t *testing.T) { + if tcase.sourceTable == "" { + tcase.sourceTable = sourceTable + } + if tcase.targetTable == "" { + tcase.targetTable = targetTable + } + if tcase.renameMap != nil { + alterTableAnalysis.ColumnRenameMap = tcase.renameMap + } + + sourceEntity, err := NewCreateTableEntityFromSQL(env, tcase.sourceTable) + require.NoError(t, err) + err = sourceEntity.validate() + require.NoError(t, err) + + targetEntity, err := NewCreateTableEntityFromSQL(env, tcase.targetTable) + require.NoError(t, err) + err = targetEntity.validate() + require.NoError(t, err) + + sourceSharedCols, targetSharedCols, droppedNonGeneratedCols, sharedColumnsMap := AnalyzeSharedColumns( + sourceEntity.ColumnDefinitionEntitiesList(), + targetEntity.ColumnDefinitionEntitiesList(), + alterTableAnalysis, + ) + assert.Equal(t, tcase.expectSourceSharedColNames, sourceSharedCols.Names()) + assert.Equal(t, tcase.expectTargetSharedColNames, targetSharedCols.Names()) + assert.Equal(t, tcase.expectDroppedSourceNonGeneratedColNames, droppedNonGeneratedCols.Names()) + assert.Equal(t, tcase.expectSharedColumnsMap, sharedColumnsMap) + }) + } +} + +func TestKeyAtLeastConstrainedAs(t *testing.T) { + env := NewTestEnv() + sourceTable := ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + c9 int, + v varchar(32), + primary key (id), + unique key uk1 (c1), + unique key uk2 (c2), + unique key uk3 (c3), + unique key uk9 (c9), + unique key uk12 (c1, c2), + unique key uk13 (c1, c3), + unique key uk23 (c2, c3), + unique key uk123 (c1, c2, c3), + unique key uk21 (c2, c1), + unique key ukv (v), + unique key ukv3 (v(3)), + unique key ukv5 (v(5)), + unique key uk2v5 (c2, v(5)) + )` + targetTable := ` + create table target_table ( + id int, + c1 int, + c2 int, + c3_renamed int, + v varchar(32), + primary key (id), + unique key uk1 (c1), + unique key uk2 (c2), + unique key uk3 (c3_renamed), + unique key uk12 (c1, c2), + unique key uk13 (c1, c3_renamed), + unique key uk23 (c2, c3_renamed), + unique key uk123 (c1, c2, c3_renamed), + unique key uk21 (c2, c1), + unique key ukv (v), + unique key ukv3 (v(3)), + unique key ukv5 (v(5)), + unique key uk2v5 (c2, v(5)) + )` + renameMap := map[string]string{ + "c3": "c3_renamed", + } + tcases := []struct { + sourceKey string + targetKey string + renameMap map[string]string + expect bool + }{ + { + sourceKey: "uk1", + targetKey: "uk1", + expect: true, + }, + { + sourceKey: "uk2", + targetKey: "uk2", + expect: true, + }, + { + sourceKey: "uk3", + targetKey: "uk3", + expect: false, // c3 is renamed + }, + { + sourceKey: "uk2", + targetKey: "uk1", + expect: false, + }, + { + sourceKey: "uk12", + targetKey: "uk1", + expect: false, + }, + { + sourceKey: "uk1", + targetKey: "uk12", + expect: true, + }, + { + sourceKey: "uk1", + targetKey: "uk21", + expect: true, + }, + { + sourceKey: "uk12", + targetKey: "uk21", + expect: true, + }, + { + sourceKey: "uk123", + targetKey: "uk21", + expect: false, + }, + { + sourceKey: "uk123", + targetKey: "uk123", + expect: false, // c3 is renamed + }, + { + sourceKey: "uk1", + targetKey: "uk123", + expect: true, // c3 is renamed but not referenced + }, + { + sourceKey: "uk21", + targetKey: "uk123", + expect: true, // c3 is renamed but not referenced + }, + { + sourceKey: "uk9", + targetKey: "uk123", + expect: false, // c9 not in target + }, + { + sourceKey: "uk3", + targetKey: "uk3", + renameMap: renameMap, + expect: true, + }, + { + sourceKey: "uk123", + targetKey: "uk123", + renameMap: renameMap, + expect: true, + }, + { + sourceKey: "uk3", + targetKey: "uk123", + renameMap: renameMap, + expect: true, + }, + { + sourceKey: "ukv", + targetKey: "ukv", + expect: true, + }, + { + sourceKey: "ukv3", + targetKey: "ukv3", + expect: true, + }, + { + sourceKey: "ukv", + targetKey: "ukv3", + expect: false, + }, + { + sourceKey: "ukv5", + targetKey: "ukv3", + expect: false, + }, + { + sourceKey: "ukv3", + targetKey: "ukv5", + expect: true, + }, + { + sourceKey: "ukv3", + targetKey: "ukv", + expect: true, + }, + { + sourceKey: "uk2", + targetKey: "uk2v5", + expect: true, + }, + { + sourceKey: "ukv5", + targetKey: "uk2v5", + expect: true, + }, + { + sourceKey: "ukv3", + targetKey: "uk2v5", + expect: true, + }, + { + sourceKey: "ukv", + targetKey: "uk2v5", + expect: false, + }, + { + sourceKey: "uk2v5", + targetKey: "ukv5", + expect: false, + }, + } + + sourceEntity, err := NewCreateTableEntityFromSQL(env, sourceTable) + require.NoError(t, err) + err = sourceEntity.validate() + require.NoError(t, err) + sourceKeys := sourceEntity.IndexDefinitionEntitiesMap() + + targetEntity, err := NewCreateTableEntityFromSQL(env, targetTable) + require.NoError(t, err) + err = targetEntity.validate() + require.NoError(t, err) + targetKeys := targetEntity.IndexDefinitionEntitiesMap() + + for _, tcase := range tcases { + t.Run(tcase.sourceKey+"/"+tcase.targetKey, func(t *testing.T) { + if tcase.renameMap == nil { + tcase.renameMap = make(map[string]string) + } + sourceKey := sourceKeys[tcase.sourceKey] + require.NotNil(t, sourceKey) + + targetKey := targetKeys[tcase.targetKey] + require.NotNil(t, targetKey) + + result := KeyAtLeastConstrainedAs(sourceKey, targetKey, tcase.renameMap) + assert.Equal(t, tcase.expect, result) + }) + } +} + +func TestIntroducedUniqueConstraints(t *testing.T) { + env := NewTestEnv() + tcases := []struct { + sourceTable string + targetTable string + expectIntroduced []string + expectRemoved []string + }{ + { + sourceTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + primary key (id), + unique key uk1 (c1), + unique key uk2 (c2), + unique key uk31 (c3, c1), + key k1 (c1) + )`, + targetTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + primary key (id), + unique key uk1 (c1), + unique key uk3 (c3), + unique key uk31_alias (c3, c1), + key k2 (c2) + )`, + expectIntroduced: []string{"uk3"}, + expectRemoved: []string{"uk2"}, + }, + { + sourceTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + primary key (id), + unique key uk1 (c1), + unique key uk2 (c2), + unique key uk31 (c3, c1), + key k1 (c1) + )`, + targetTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + primary key (id), + unique key uk1 (c1), + unique key uk3 (c3), + key k2 (c2) + )`, + expectIntroduced: []string{"uk3"}, // uk31 (c3, c1) not considered removed because the new "uk3" is even more constrained + expectRemoved: []string{"uk2"}, + }, + { + sourceTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + v varchar(128), + primary key (id), + unique key uk12 (c1, c2), + unique key ukv5 (v(5)), + key k1 (c1) + )`, + targetTable: ` + create table source_table ( + id int, + c1 int, + c2 int, + c3 int, + v varchar(128), + primary key (id), + unique key uk1v2 (c1, v(2)), + unique key uk1v7 (c1, v(7)), + unique key ukv3 (v(3)), + key k2 (c2) + )`, + expectIntroduced: []string{"uk1v2", "ukv3"}, + expectRemoved: []string{"uk12"}, + }, + } + for _, tcase := range tcases { + t.Run("", func(t *testing.T) { + sourceEntity, err := NewCreateTableEntityFromSQL(env, tcase.sourceTable) + require.NoError(t, err) + err = sourceEntity.validate() + require.NoError(t, err) + sourceUniqueKeys := PrioritizedUniqueKeys(sourceEntity) + + targetEntity, err := NewCreateTableEntityFromSQL(env, tcase.targetTable) + require.NoError(t, err) + err = targetEntity.validate() + require.NoError(t, err) + targetUniqueKeys := PrioritizedUniqueKeys(targetEntity) + + introduced := IntroducedUniqueConstraints(sourceUniqueKeys, targetUniqueKeys, nil) + assert.Equal(t, tcase.expectIntroduced, introduced.Names()) + }) + } +} + +func TestUniqueKeysCoveredByColumns(t *testing.T) { + env := NewTestEnv() + table := ` + create table t ( + id int, + c1 int not null, + c2 int not null, + c3 int not null, + c9 int, + v varchar(32) not null, + primary key (id), + unique key uk1 (c1), + unique key uk3 (c3), + unique key uk9 (c9), + key k3 (c3), + unique key uk12 (c1, c2), + unique key uk13 (c1, c3), + unique key uk23 (c2, c3), + unique key uk123 (c1, c2, c3), + unique key uk21 (c2, c1), + unique key ukv (v), + unique key ukv3 (v(3)), + unique key uk2v5 (c2, v(5)), + unique key uk3v (c3, v) + ) + ` + tcases := []struct { + columns []string + expect []string + }{ + { + columns: []string{"id"}, + expect: []string{"PRIMARY"}, + }, + { + columns: []string{"c1"}, + expect: []string{"uk1"}, + }, + { + columns: []string{"id", "c1"}, + expect: []string{"PRIMARY", "uk1"}, + }, + { + columns: []string{"c1", "id"}, + expect: []string{"PRIMARY", "uk1"}, + }, + { + columns: []string{"c9"}, + expect: []string{}, // nullable column + }, + { + columns: []string{"v"}, + expect: []string{"ukv"}, + }, + { + columns: []string{"v", "c9"}, + expect: []string{"ukv"}, + }, + { + columns: []string{"v", "c2"}, + expect: []string{"ukv"}, + }, + { + columns: []string{"v", "c2", "c3"}, + expect: []string{"uk3", "uk23", "uk3v", "ukv"}, + }, + { + columns: []string{"id", "c1", "c2", "c3", "v"}, + expect: []string{"PRIMARY", "uk1", "uk3", "uk12", "uk13", "uk23", "uk21", "uk3v", "uk123", "ukv"}, + }, + } + + entity, err := NewCreateTableEntityFromSQL(env, table) + require.NoError(t, err) + err = entity.validate() + require.NoError(t, err) + tableColumns := entity.ColumnDefinitionEntitiesList() + tableKeys := PrioritizedUniqueKeys(entity) + assert.Equal(t, []string{ + "PRIMARY", + "uk1", + "uk3", + "uk12", + "uk13", + "uk23", + "uk21", + "uk3v", + "uk123", + "ukv", + "uk2v5", + "ukv3", + "uk9", + }, tableKeys.Names()) + + for _, tcase := range tcases { + t.Run(strings.Join(tcase.columns, ","), func(t *testing.T) { + columns := []*ColumnDefinitionEntity{} + for _, tcaseCol := range tcase.columns { + col := tableColumns.GetColumn(tcaseCol) + require.NotNil(t, col) + columns = append(columns, col) + } + columnsList := NewColumnDefinitionEntityList(columns) + + covered := IterationKeysByColumns(tableKeys, columnsList) + assert.Equal(t, tcase.expect, covered.Names()) + }) + } +} + +func TestRevertible(t *testing.T) { + + type revertibleTestCase struct { + name string + fromSchema string + toSchema string + // expectProblems bool + removedForeignKeyNames string + removedUniqueKeyNames string + droppedNoDefaultColumnNames string + expandedColumnNames string + } + + var testCases = []revertibleTestCase{ + { + name: "identical schemas", + fromSchema: `id int primary key, i1 int not null default 0`, + toSchema: `id int primary key, i2 int not null default 0`, + }, + { + name: "different schemas, nothing to note", + fromSchema: `id int primary key, i1 int not null default 0, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i1 int not null default 0, i2 int not null default 0, unique key i1_uidx(i1)`, + }, + { + name: "removed non-nullable unique key", + fromSchema: `id int primary key, i1 int not null default 0, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i2 int not null default 0`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "removed nullable unique key", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i2 int default null`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "expanding unique key removes unique constraint", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1, id)`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "expanding unique key prefix removes unique constraint", + fromSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(20))`, + toSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(21))`, + removedUniqueKeyNames: `v_uidx`, + }, + { + name: "reducing unique key does not remove unique constraint", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1, id)`, + toSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + removedUniqueKeyNames: ``, + }, + { + name: "reducing unique key does not remove unique constraint", + fromSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(21))`, + toSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(20))`, + }, + { + name: "removed foreign key", + fromSchema: "id int primary key, i int, constraint some_fk_1 foreign key (i) references parent (id) on delete cascade", + toSchema: "id int primary key, i int", + removedForeignKeyNames: "some_fk_1", + }, + + { + name: "renamed foreign key", + fromSchema: "id int primary key, i int, constraint f1 foreign key (i) references parent (id) on delete cascade", + toSchema: "id int primary key, i int, constraint f2 foreign key (i) references parent (id) on delete cascade", + }, + { + name: "remove column without default", + fromSchema: `id int primary key, i1 int not null, i2 int not null default 0, i3 int default null`, + toSchema: `id int primary key, i4 int not null default 0`, + droppedNoDefaultColumnNames: `i1`, + }, + { + name: "expanded: nullable", + fromSchema: `id int primary key, i1 int not null, i2 int default null`, + toSchema: `id int primary key, i1 int default null, i2 int not null`, + expandedColumnNames: `i1`, + }, + { + name: "expanded: longer text", + fromSchema: `id int primary key, i1 int default null, v1 varchar(40) not null, v2 varchar(5), v3 varchar(3)`, + toSchema: `id int primary key, i1 int not null, v1 varchar(100) not null, v2 char(3), v3 char(5)`, + expandedColumnNames: `v1,v3`, + }, + { + name: "expanded: int numeric precision and scale", + fromSchema: `id int primary key, i1 int, i2 tinyint, i3 mediumint, i4 bigint`, + toSchema: `id int primary key, i1 int, i2 mediumint, i3 int, i4 tinyint`, + expandedColumnNames: `i2,i3`, + }, + { + name: "expanded: floating point", + fromSchema: `id int primary key, i1 int, n2 bigint, n3 bigint, n4 float, n5 double`, + toSchema: `id int primary key, i1 int, n2 float, n3 double, n4 double, n5 float`, + expandedColumnNames: `n2,n3,n4`, + }, + { + name: "expanded: decimal numeric precision and scale", + fromSchema: `id int primary key, i1 int, d1 decimal(10,2), d2 decimal (10,2), d3 decimal (10,2)`, + toSchema: `id int primary key, i1 int, d1 decimal(11,2), d2 decimal (9,1), d3 decimal (10,3)`, + expandedColumnNames: `d1,d3`, + }, + { + name: "expanded: signed, unsigned", + fromSchema: `id int primary key, i1 bigint signed, i2 int unsigned, i3 bigint unsigned`, + toSchema: `id int primary key, i1 int signed, i2 int signed, i3 int signed`, + expandedColumnNames: `i2,i3`, + }, + { + name: "expanded: signed, unsigned: range", + fromSchema: `id int primary key, i1 int signed, i2 bigint signed, i3 int signed`, + toSchema: `id int primary key, i1 int unsigned, i2 int unsigned, i3 bigint unsigned`, + expandedColumnNames: `i1,i3`, + }, + { + name: "expanded: datetime precision", + fromSchema: `id int primary key, dt1 datetime, ts1 timestamp, ti1 time, dt2 datetime(3), dt3 datetime(6), ts2 timestamp(3)`, + toSchema: `id int primary key, dt1 datetime(3), ts1 timestamp(6), ti1 time(3), dt2 datetime(6), dt3 datetime(3), ts2 timestamp`, + expandedColumnNames: `dt1,ts1,ti1,dt2`, + }, + { + name: "expanded: strange data type changes", + fromSchema: `id int primary key, dt1 datetime, ts1 timestamp, i1 int, d1 date, e1 enum('a', 'b')`, + toSchema: `id int primary key, dt1 char(32), ts1 varchar(32), i1 tinytext, d1 char(2), e1 varchar(2)`, + expandedColumnNames: `dt1,ts1,i1,d1,e1`, + }, + { + name: "expanded: temporal types", + fromSchema: `id int primary key, t1 time, t2 timestamp, t3 date, t4 datetime, t5 time, t6 date`, + toSchema: `id int primary key, t1 datetime, t2 datetime, t3 timestamp, t4 timestamp, t5 timestamp, t6 datetime`, + expandedColumnNames: `t1,t2,t3,t5,t6`, + }, + { + name: "expanded: character sets", + fromSchema: `id int primary key, c1 char(3) charset utf8, c2 char(3) charset utf8mb4, c3 char(3) charset ascii, c4 char(3) charset utf8mb4, c5 char(3) charset utf8, c6 char(3) charset latin1`, + toSchema: `id int primary key, c1 char(3) charset utf8mb4, c2 char(3) charset utf8, c3 char(3) charset utf8, c4 char(3) charset ascii, c5 char(3) charset utf8, c6 char(3) charset utf8mb4`, + expandedColumnNames: `c1,c3,c6`, + }, + { + name: "expanded: enum", + fromSchema: `id int primary key, e1 enum('a', 'b'), e2 enum('a', 'b'), e3 enum('a', 'b'), e4 enum('a', 'b'), e5 enum('a', 'b'), e6 enum('a', 'b'), e7 enum('a', 'b'), e8 enum('a', 'b')`, + toSchema: `id int primary key, e1 enum('a', 'b'), e2 enum('a'), e3 enum('a', 'b', 'c'), e4 enum('a', 'x'), e5 enum('a', 'x', 'b'), e6 enum('b'), e7 varchar(1), e8 tinyint`, + expandedColumnNames: `e3,e4,e5,e6,e7,e8`, + }, + { + name: "expanded: set", + fromSchema: `id int primary key, e1 set('a', 'b'), e2 set('a', 'b'), e3 set('a', 'b'), e4 set('a', 'b'), e5 set('a', 'b'), e6 set('a', 'b'), e7 set('a', 'b'), e8 set('a', 'b')`, + toSchema: `id int primary key, e1 set('a', 'b'), e2 set('a'), e3 set('a', 'b', 'c'), e4 set('a', 'x'), e5 set('a', 'x', 'b'), e6 set('b'), e7 varchar(1), e8 tinyint`, + expandedColumnNames: `e3,e4,e5,e6,e7,e8`, + }, + } + + var ( + createTableWrapper = `CREATE TABLE t (%s)` + ) + + env := NewTestEnv() + diffHints := &DiffHints{} + for _, tcase := range testCases { + t.Run(tcase.name, func(t *testing.T) { + tcase.fromSchema = fmt.Sprintf(createTableWrapper, tcase.fromSchema) + sourceTableEntity, err := NewCreateTableEntityFromSQL(env, tcase.fromSchema) + require.NoError(t, err) + + tcase.toSchema = fmt.Sprintf(createTableWrapper, tcase.toSchema) + targetTableEntity, err := NewCreateTableEntityFromSQL(env, tcase.toSchema) + require.NoError(t, err) + + diff, err := sourceTableEntity.TableDiff(targetTableEntity, diffHints) + require.NoError(t, err) + alterTableAnalysis := OnlineDDLAlterTableAnalysis(diff.AlterTable()) + + analysis, err := OnlineDDLMigrationTablesAnalysis(sourceTableEntity, targetTableEntity, alterTableAnalysis) + require.NoError(t, err) + + toStringSlice := func(s string) []string { + if s == "" { + return []string{} + } + return strings.Split(s, ",") + } + assert.Equal(t, toStringSlice(tcase.removedForeignKeyNames), analysis.RemovedForeignKeyNames) + assert.Equal(t, toStringSlice(tcase.removedUniqueKeyNames), analysis.RemovedUniqueKeys.Names()) + assert.Equal(t, toStringSlice(tcase.droppedNoDefaultColumnNames), analysis.DroppedNoDefaultColumns.Names()) + assert.Equal(t, toStringSlice(tcase.expandedColumnNames), analysis.ExpandedColumns.Names()) + }) + } +} 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..8088cc896ed 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 @@ -1319,6 +1321,41 @@ func TestSchemaDiff(t *testing.T) { instantCapability := schemaDiff.InstantDDLCapability() assert.Equal(t, tc.instantCapability, instantCapability, "for instant capability") }) + } +} +// 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/semantics.go b/go/vt/schemadiff/semantics.go index cbba8c79497..f12f59ef6ae 100644 --- a/go/vt/schemadiff/semantics.go +++ b/go/vt/schemadiff/semantics.go @@ -79,6 +79,11 @@ func (si *declarativeSchemaInformation) GetForeignKeyChecksState() *bool { return nil } +// FindMirrorRule implements semantics.SchemaInformation. +func (si *declarativeSchemaInformation) FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) { + return nil, nil +} + // addTable adds a fake table with an empty column list func (si *declarativeSchemaInformation) addTable(tableName string) { tbl := &vindexes.Table{ diff --git a/go/vt/schemadiff/table.go b/go/vt/schemadiff/table.go index 5629210b6c1..c326b2763b3 100644 --- a/go/vt/schemadiff/table.go +++ b/go/vt/schemadiff/table.go @@ -445,6 +445,18 @@ type CreateTableEntity struct { Env *Environment } +func NewCreateTableEntityFromSQL(env *Environment, sql string) (*CreateTableEntity, error) { + stmt, err := env.Parser().ParseStrictDDL(sql) + if err != nil { + return nil, err + } + createTable, ok := stmt.(*sqlparser.CreateTable) + if !ok { + return nil, ErrExpectedCreateTable + } + return NewCreateTableEntity(env, createTable) +} + func NewCreateTableEntity(env *Environment, c *sqlparser.CreateTable) (*CreateTableEntity, error) { if !c.IsFullyParsed() { return nil, &NotFullyParsedError{Entity: c.Table.Name.String(), Statement: sqlparser.CanonicalString(c)} @@ -454,15 +466,64 @@ func NewCreateTableEntity(env *Environment, c *sqlparser.CreateTable) (*CreateTa return entity, nil } +// ColumnDefinitionEntities returns the list of column entities for the table. func (c *CreateTableEntity) ColumnDefinitionEntities() []*ColumnDefinitionEntity { cc := getTableCharsetCollate(c.Env, &c.CreateTable.TableSpec.Options) + pkColumnsMaps := c.primaryKeyColumnsMap() 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) + col := c.CreateTable.TableSpec.Columns[i] + _, inPK := pkColumnsMaps[col.Name.Lowered()] + entities[i] = NewColumnDefinitionEntity(c.Env, col, inPK, cc) } return entities } +// ColumnDefinitionEntities returns the list of column entities for the table. +func (c *CreateTableEntity) ColumnDefinitionEntitiesList() *ColumnDefinitionEntityList { + return NewColumnDefinitionEntityList(c.ColumnDefinitionEntities()) +} + +// ColumnDefinitionEntities returns column entities mapped by their lower cased name +func (c *CreateTableEntity) ColumnDefinitionEntitiesMap() map[string]*ColumnDefinitionEntity { + entities := c.ColumnDefinitionEntities() + m := make(map[string]*ColumnDefinitionEntity, len(entities)) + for _, entity := range entities { + m[entity.NameLowered()] = entity + } + return m +} + +// IndexDefinitionEntities returns the list of index entities for the table. +func (c *CreateTableEntity) IndexDefinitionEntities() []*IndexDefinitionEntity { + colMap := c.ColumnDefinitionEntitiesMap() + keys := c.CreateTable.TableSpec.Indexes + entities := make([]*IndexDefinitionEntity, len(keys)) + for i, key := range keys { + colEntities := make([]*ColumnDefinitionEntity, len(key.Columns)) + for i, keyCol := range key.Columns { + colEntities[i] = colMap[keyCol.Column.Lowered()] + } + entities[i] = NewIndexDefinitionEntity(c.Env, key, NewColumnDefinitionEntityList(colEntities)) + } + return entities +} + +// IndexDefinitionEntityList returns the list of index entities for the table. +func (c *CreateTableEntity) IndexDefinitionEntitiesList() *IndexDefinitionEntityList { + return NewIndexDefinitionEntityList(c.IndexDefinitionEntities()) +} + +// IndexDefinitionEntitiesMap returns index entities mapped by their lower cased name. +func (c *CreateTableEntity) IndexDefinitionEntitiesMap() map[string]*IndexDefinitionEntity { + entities := c.IndexDefinitionEntities() + m := make(map[string]*IndexDefinitionEntity, len(entities)) + for _, entity := range entities { + m[entity.NameLowered()] = entity + } + return m +} + // normalize cleans up the table definition: // - setting names to all keys // - table option case (upper/lower/special) @@ -1740,8 +1801,8 @@ func (c *CreateTableEntity) diffColumns(alterTable *sqlparser.AlterTable, t2ColName := t2Col.Name.Lowered() // we know that column exists in both tables t1Col := t1ColumnsMap[t2ColName] - t1ColEntity := NewColumnDefinitionEntity(c.Env, t1Col.col, t1cc) - t2ColEntity := NewColumnDefinitionEntity(c.Env, t2Col, t2cc) + t1ColEntity := NewColumnDefinitionEntity(c.Env, t1Col.col, false, t1cc) + t2ColEntity := NewColumnDefinitionEntity(c.Env, t2Col, false, t2cc) // check diff between before/after columns: modifyColumnDiff, err := t1ColEntity.ColumnDiff(c.Env, c.Name(), t2ColEntity, hints) @@ -1892,6 +1953,15 @@ func (c *CreateTableEntity) primaryKeyColumns() []*sqlparser.IndexColumn { return nil } +func (c *CreateTableEntity) primaryKeyColumnsMap() map[string]*sqlparser.IndexColumn { + columns := c.primaryKeyColumns() + m := make(map[string]*sqlparser.IndexColumn, len(columns)) + for _, col := range columns { + m[col.Column.Lowered()] = col + } + return m +} + // Create implements Entity interface func (c *CreateTableEntity) Create() EntityDiff { if c == nil { @@ -2648,3 +2718,18 @@ func (c *CreateTableEntity) identicalOtherThanName(other *CreateTableEntity) boo return sqlparser.Equals.RefOfTableSpec(c.TableSpec, other.TableSpec) && sqlparser.Equals.RefOfParsedComments(c.Comments, other.Comments) } + +// AutoIncrementValue returns the value of the AUTO_INCREMENT option, or zero if not exists. +func (c *CreateTableEntity) AutoIncrementValue() (autoIncrement uint64, err error) { + for _, option := range c.CreateTable.TableSpec.Options { + if strings.ToUpper(option.Name) == "AUTO_INCREMENT" { + autoIncrement, err := strconv.ParseUint(option.Value.Val, 10, 64) + if err != nil { + return 0, err + } + return autoIncrement, nil + } + } + // Auto increment not found + return 0, nil +} diff --git a/go/vt/schemadiff/table_test.go b/go/vt/schemadiff/table_test.go index 1168f53f3b6..389e55f447c 100644 --- a/go/vt/schemadiff/table_test.go +++ b/go/vt/schemadiff/table_test.go @@ -2781,9 +2781,10 @@ func TestValidate(t *testing.T) { func TestNormalize(t *testing.T) { tt := []struct { - name string - from string - to string + name string + from string + to string + autoinc uint64 }{ { name: "basic table", @@ -2795,6 +2796,17 @@ func TestNormalize(t *testing.T) { from: "create table t (id int primary key, i int)", to: "CREATE TABLE `t` (\n\t`id` int,\n\t`i` int,\n\tPRIMARY KEY (`id`)\n)", }, + { + name: "basic table, auto increment", + from: "create table t (id int auto_increment primary key, i int)", + to: "CREATE TABLE `t` (\n\t`id` int AUTO_INCREMENT,\n\t`i` int,\n\tPRIMARY KEY (`id`)\n)", + }, + { + name: "basic table, auto increment val", + from: "create table t (id int auto_increment primary key, i int) auto_increment = 123", + to: "CREATE TABLE `t` (\n\t`id` int AUTO_INCREMENT,\n\t`i` int,\n\tPRIMARY KEY (`id`)\n) AUTO_INCREMENT 123", + autoinc: 123, + }, { name: "removes default null", from: "create table t (id int, i int default null, primary key (id))", @@ -3067,6 +3079,10 @@ func TestNormalize(t *testing.T) { from, err := NewCreateTableEntity(env, fromCreateTable) require.NoError(t, err) assert.Equal(t, ts.to, sqlparser.CanonicalString(from)) + + autoinc, err := from.AutoIncrementValue() + require.NoError(t, err) + assert.EqualValues(t, ts.autoinc, autoinc) }) } } diff --git a/go/vt/schemadiff/view.go b/go/vt/schemadiff/view.go index d2dc4dfb76f..8783f1803bb 100644 --- a/go/vt/schemadiff/view.go +++ b/go/vt/schemadiff/view.go @@ -310,6 +310,18 @@ func NewCreateViewEntity(env *Environment, c *sqlparser.CreateView) (*CreateView return entity, nil } +func NewCreateViewEntityFromSQL(env *Environment, sql string) (*CreateViewEntity, error) { + stmt, err := env.Parser().ParseStrictDDL(sql) + if err != nil { + return nil, err + } + createView, ok := stmt.(*sqlparser.CreateView) + if !ok { + return nil, ErrExpectedCreateTable + } + return NewCreateViewEntity(env, createView) +} + func (c *CreateViewEntity) normalize() { // Drop the default algorithm if strings.EqualFold(c.CreateView.Algorithm, "undefined") { diff --git a/go/vt/schemadiff/view_test.go b/go/vt/schemadiff/view_test.go index d1a26c3cdaa..d020649b17e 100644 --- a/go/vt/schemadiff/view_test.go +++ b/go/vt/schemadiff/view_test.go @@ -150,19 +150,16 @@ func TestCreateViewDiff(t *testing.T) { for _, ts := range tt { t.Run(ts.name, func(t *testing.T) { fromStmt, err := env.Parser().ParseStrictDDL(ts.from) - assert.NoError(t, err) + require.NoError(t, err) fromCreateView, ok := fromStmt.(*sqlparser.CreateView) assert.True(t, ok) - toStmt, err := env.Parser().ParseStrictDDL(ts.to) - assert.NoError(t, err) - toCreateView, ok := toStmt.(*sqlparser.CreateView) - assert.True(t, ok) - c, err := NewCreateViewEntity(env, fromCreateView) require.NoError(t, err) - other, err := NewCreateViewEntity(env, toCreateView) + // Test from SQL: + other, err := NewCreateViewEntityFromSQL(env, ts.to) require.NoError(t, err) + alter, err := c.Diff(other, hints) switch { case ts.isError: 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/sidecardb/schema/onlineddl/schema_migrations.sql b/go/vt/sidecardb/schema/onlineddl/schema_migrations.sql index 2926ec76f28..0e1b8ecde11 100644 --- a/go/vt/sidecardb/schema/onlineddl/schema_migrations.sql +++ b/go/vt/sidecardb/schema/onlineddl/schema_migrations.sql @@ -42,6 +42,7 @@ CREATE TABLE IF NOT EXISTS schema_migrations `migration_context` varchar(1024) NOT NULL DEFAULT '', `ddl_action` varchar(16) NOT NULL DEFAULT '', `message` text NOT NULL, + `message_timestamp` timestamp(6) NULL DEFAULT NULL, `eta_seconds` bigint NOT NULL DEFAULT '-1', `rows_copied` bigint unsigned NOT NULL DEFAULT '0', `table_rows` bigint NOT NULL DEFAULT '0', @@ -63,6 +64,7 @@ CREATE TABLE IF NOT EXISTS schema_migrations `special_plan` text NOT NULL, `last_throttled_timestamp` timestamp NULL DEFAULT NULL, `component_throttled` tinytext NOT NULL, + `reason_throttled` text NOT NULL, `cancelled_timestamp` timestamp NULL DEFAULT NULL, `postpone_launch` tinyint unsigned NOT NULL DEFAULT '0', `stage` text NOT NULL, 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/sidecardb/schema/vreplication/vreplication.sql b/go/vt/sidecardb/schema/vreplication/vreplication.sql index 8d2ec41d1a6..293997056fd 100644 --- a/go/vt/sidecardb/schema/vreplication/vreplication.sql +++ b/go/vt/sidecardb/schema/vreplication/vreplication.sql @@ -36,6 +36,7 @@ CREATE TABLE IF NOT EXISTS vreplication `workflow_type` int NOT NULL DEFAULT '0', `time_throttled` bigint NOT NULL DEFAULT '0', `component_throttled` varchar(255) NOT NULL DEFAULT '', + `reason_throttled` varchar(1000) NOT NULL DEFAULT '', `workflow_sub_type` int NOT NULL DEFAULT '0', `defer_secondary_keys` tinyint(1) NOT NULL DEFAULT '0', /* diff --git a/go/vt/sidecardb/sidecardb_test.go b/go/vt/sidecardb/sidecardb_test.go index 55c2c6cd6b5..70b89f17056 100644 --- a/go/vt/sidecardb/sidecardb_test.go +++ b/go/vt/sidecardb/sidecardb_test.go @@ -18,6 +18,7 @@ package sidecardb import ( "context" + "errors" "expvar" "fmt" "sort" @@ -80,7 +81,7 @@ func TestInitErrors(t *testing.T) { if ok { for _, e := range schemaErrors { if strings.EqualFold(e.tableName, createTable.Table.Name.String()) { - return nil, fmt.Errorf(e.errorValue) + return nil, errors.New(e.errorValue) } } } diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index 35d093e2d39..938b9063011 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -161,7 +161,7 @@ type ( CommonTableExpr struct { ID IdentifierCS Columns Columns - Subquery *Subquery + Subquery SelectStatement } // ChangeColumn is used to change the column definition, can also rename the column in alter table command ChangeColumn struct { @@ -262,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 @@ -1667,6 +1671,12 @@ type ( Filter *ShowFilter } + // ShowTransactionStatus is used to see the status of a distributed transaction in progress. + ShowTransactionStatus struct { + Keyspace string + TransactionID string + } + // ShowCreate is of ShowInternal type, holds SHOW CREATE queries. ShowCreate struct { Command ShowCommandType @@ -1679,9 +1689,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 { diff --git a/go/vt/sqlparser/ast_clone.go b/go/vt/sqlparser/ast_clone.go index 2342237f806..f22a1790232 100644 --- a/go/vt/sqlparser/ast_clone.go +++ b/go/vt/sqlparser/ast_clone.go @@ -461,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: @@ -1020,7 +1022,7 @@ func CloneRefOfCommonTableExpr(n *CommonTableExpr) *CommonTableExpr { out := *n out.ID = CloneIdentifierCS(n.ID) out.Columns = CloneColumns(n.Columns) - out.Subquery = CloneRefOfSubquery(n.Subquery) + out.Subquery = CloneSelectStatement(n.Subquery) return &out } @@ -2909,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 { @@ -4147,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 c6bcf71bd6c..0e329e24f31 100644 --- a/go/vt/sqlparser/ast_copy_on_rewrite.go +++ b/go/vt/sqlparser/ast_copy_on_rewrite.go @@ -460,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: @@ -1520,12 +1522,12 @@ func (c *cow) copyOnRewriteRefOfCommonTableExpr(n *CommonTableExpr, parent SQLNo if c.pre == nil || c.pre(n, parent) { _ID, changedID := c.copyOnRewriteIdentifierCS(n.ID, n) _Columns, changedColumns := c.copyOnRewriteColumns(n.Columns, n) - _Subquery, changedSubquery := c.copyOnRewriteRefOfSubquery(n.Subquery, n) + _Subquery, changedSubquery := c.copyOnRewriteSelectStatement(n.Subquery, n) if changedID || changedColumns || changedSubquery { res := *n res.ID, _ = _ID.(IdentifierCS) res.Columns, _ = _Columns.(Columns) - res.Subquery, _ = _Subquery.(*Subquery) + res.Subquery, _ = _Subquery.(SelectStatement) out = &res if c.cloned != nil { c.cloned(n, out) @@ -5525,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 @@ -7396,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 9f798f798a6..cf076d706e7 100644 --- a/go/vt/sqlparser/ast_equals.go +++ b/go/vt/sqlparser/ast_equals.go @@ -1340,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 { @@ -2187,7 +2193,7 @@ func (cmp *Comparator) RefOfCommonTableExpr(a, b *CommonTableExpr) bool { } return cmp.IdentifierCS(a.ID, b.ID) && cmp.Columns(a.Columns, b.Columns) && - cmp.RefOfSubquery(a.Subquery, b.Subquery) + cmp.SelectStatement(a.Subquery, b.Subquery) } // RefOfComparisonExpr does deep equals between the two objects. @@ -4184,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) && @@ -4363,6 +4373,18 @@ 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.Keyspace == b.Keyspace && + a.TransactionID == b.TransactionID +} + // RefOfStarExpr does deep equals between the two objects. func (cmp *Comparator) RefOfStarExpr(a, b *StarExpr) bool { if a == b { @@ -6774,6 +6796,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 da88129ee63..587b32d4afe 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) } @@ -155,7 +167,7 @@ func (node *With) Format(buf *TrackedBuffer) { // Format formats the node. func (node *CommonTableExpr) Format(buf *TrackedBuffer) { - buf.astPrintf(node, "%v%v as %v ", node.ID, node.Columns, node.Subquery) + buf.astPrintf(node, "%v%v as (%v) ", node.ID, node.Columns, node.Subquery) } // Format formats the node. @@ -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: @@ -2137,6 +2151,17 @@ func (node *ShowBasic) Format(buf *TrackedBuffer) { buf.astPrintf(node, "%v", node.Filter) } +func (node *ShowTransactionStatus) Format(buf *TrackedBuffer) { + if node.TransactionID == "" { + buf.astPrintf(node, "show unresolved transactions") + if node.Keyspace != "" { + buf.astPrintf(node, " for %#s", node.Keyspace) + } + return + } + 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) diff --git a/go/vt/sqlparser/ast_format_fast.go b/go/vt/sqlparser/ast_format_fast.go index b1dd010f5ed..c2b02711398 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) } @@ -231,9 +243,9 @@ func (node *With) FormatFast(buf *TrackedBuffer) { func (node *CommonTableExpr) FormatFast(buf *TrackedBuffer) { node.ID.FormatFast(buf) node.Columns.FormatFast(buf) - buf.WriteString(" as ") + buf.WriteString(" as (") node.Subquery.FormatFast(buf) - buf.WriteByte(' ') + buf.WriteString(") ") } // FormatFast formats the node. @@ -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: @@ -2817,6 +2831,20 @@ func (node *ShowBasic) FormatFast(buf *TrackedBuffer) { node.Filter.FormatFast(buf) } +func (node *ShowTransactionStatus) FormatFast(buf *TrackedBuffer) { + if node.TransactionID == "" { + buf.WriteString("show unresolved transactions") + if node.Keyspace != "" { + buf.WriteString(" for ") + buf.WriteString(node.Keyspace) + } + return + } + 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") diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index f4f1e3a5455..ea7a6e93e0e 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: @@ -426,6 +428,20 @@ func (node *AliasedTableExpr) TableName() (TableName, error) { return tableName, nil } +// TableNameString returns a TableNameString pointing to this table expr +func (node *AliasedTableExpr) TableNameString() string { + if node.As.NotEmpty() { + return node.As.String() + } + + tableName, ok := node.Expr.(TableName) + if !ok { + panic(vterrors.VT13001("Derived table should have an alias. This should not be possible")) + } + + return tableName.Name.String() +} + // IsEmpty returns true if TableName is nil or empty. func (node TableName) IsEmpty() bool { // If Name is empty, Qualifier is also empty. @@ -800,7 +816,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 +827,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 +845,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, @@ -2790,3 +2818,24 @@ func (lock Lock) GetHighestOrderLock(newLock Lock) Lock { func Clone[K SQLNode](x K) K { return CloneSQLNode(x).(K) } + +// ExtractAllTables returns all the table names in the SQLNode as slice of string +func ExtractAllTables(stmt Statement) []string { + var tables []string + tableMap := make(map[string]any) + _ = Walk(func(node SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *AliasedTableExpr: + if tblName, ok := node.Expr.(TableName); ok { + name := String(tblName) + if _, exists := tableMap[name]; !exists { + tableMap[name] = nil + tables = append(tables, name) + } + return false, nil + } + } + return true, nil + }, stmt) + return tables +} diff --git a/go/vt/sqlparser/ast_funcs_test.go b/go/vt/sqlparser/ast_funcs_test.go index 7bec47df96f..a3b744729f4 100644 --- a/go/vt/sqlparser/ast_funcs_test.go +++ b/go/vt/sqlparser/ast_funcs_test.go @@ -172,3 +172,50 @@ func TestColumns_Indexes(t *testing.T) { }) } } + +// TestExtractTables verifies the functionality of extracting all the tables from the SQLNode. +func TestExtractTables(t *testing.T) { + tcases := []struct { + sql string + expected []string + }{{ + sql: "select 1 from a", + expected: []string{"a"}, + }, { + sql: "select 1 from a, b", + expected: []string{"a", "b"}, + }, { + sql: "select 1 from a join b on a.id = b.id", + expected: []string{"a", "b"}, + }, { + sql: "select 1 from a join b on a.id = b.id join c on b.id = c.id", + expected: []string{"a", "b", "c"}, + }, { + sql: "select 1 from a join (select id from b) as c on a.id = c.id", + expected: []string{"a", "b"}, + }, { + sql: "(select 1 from a) union (select 1 from b)", + expected: []string{"a", "b"}, + }, { + sql: "select 1 from a where exists (select 1 from (select id from c) b where a.id = b.id)", + expected: []string{"a", "c"}, + }, { + sql: "select 1 from k.a join k.b on a.id = b.id", + expected: []string{"k.a", "k.b"}, + }, { + sql: "select 1 from k.a join l.a on k.a.id = l.a.id", + expected: []string{"k.a", "l.a"}, + }, { + sql: "select 1 from a join (select id from a) as c on a.id = c.id", + expected: []string{"a"}, + }} + parser := NewTestParser() + for _, tcase := range tcases { + t.Run(tcase.sql, func(t *testing.T) { + stmt, err := parser.Parse(tcase.sql) + require.NoError(t, err) + tables := ExtractAllTables(stmt) + require.Equal(t, tcase.expected, tables) + }) + } +} diff --git a/go/vt/sqlparser/ast_rewrite.go b/go/vt/sqlparser/ast_rewrite.go index 9605e71a7ae..015c27a2cbd 100644 --- a/go/vt/sqlparser/ast_rewrite.go +++ b/go/vt/sqlparser/ast_rewrite.go @@ -460,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: @@ -1962,8 +1964,8 @@ func (a *application) rewriteRefOfCommonTableExpr(parent SQLNode, node *CommonTa }) { return false } - if !a.rewriteRefOfSubquery(node, node.Subquery, func(newNode, parent SQLNode) { - parent.(*CommonTableExpr).Subquery = newNode.(*Subquery) + if !a.rewriteSelectStatement(node, node.Subquery, func(newNode, parent SQLNode) { + parent.(*CommonTableExpr).Subquery = newNode.(SelectStatement) }) { return false } @@ -7934,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 @@ -10373,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_rewriting.go b/go/vt/sqlparser/ast_rewriting.go index 64de1f9d920..ef46b124875 100644 --- a/go/vt/sqlparser/ast_rewriting.go +++ b/go/vt/sqlparser/ast_rewriting.go @@ -301,10 +301,12 @@ func (er *astRewriter) rewriteVariable(cursor *Cursor, node *Variable) { if v, isSet := cursor.Parent().(*SetExpr); isSet && v.Var == node { return } + // no rewriting for global scope variable. + // this should be returned from the underlying database. switch node.Scope { case VariableScope: er.udvRewrite(cursor, node) - case GlobalScope, SessionScope, NextTxScope: + case SessionScope, NextTxScope: er.sysVarRewrite(cursor, node) } } diff --git a/go/vt/sqlparser/ast_visit.go b/go/vt/sqlparser/ast_visit.go index ecc15c47143..d33c2d1e055 100644 --- a/go/vt/sqlparser/ast_visit.go +++ b/go/vt/sqlparser/ast_visit.go @@ -460,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: @@ -1170,7 +1172,7 @@ func VisitRefOfCommonTableExpr(in *CommonTableExpr, f Visit) error { if err := VisitColumns(in.Columns, f); err != nil { return err } - if err := VisitRefOfSubquery(in.Subquery, f); err != nil { + if err := VisitSelectStatement(in.Subquery, f); err != nil { return err } return nil @@ -3714,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 @@ -5130,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 6e29c346338..391e9a84ad3 100644 --- a/go/vt/sqlparser/cached_size.go +++ b/go/vt/sqlparser/cached_size.go @@ -834,7 +834,7 @@ func (cached *CommonTableExpr) CachedSize(alloc bool) int64 { } size := int64(0) if alloc { - size += int64(48) + size += int64(64) } // field ID vitess.io/vitess/go/vt/sqlparser.IdentifierCS size += cached.ID.CachedSize(false) @@ -845,8 +845,10 @@ func (cached *CommonTableExpr) CachedSize(alloc bool) int64 { size += elem.CachedSize(false) } } - // field Subquery *vitess.io/vitess/go/vt/sqlparser.Subquery - size += cached.Subquery.CachedSize(true) + // field Subquery vitess.io/vitess/go/vt/sqlparser.SelectStatement + if cc, ok := cached.Subquery.(cachedObject); ok { + size += cc.CachedSize(true) + } return size } func (cached *ComparisonExpr) CachedSize(alloc bool) int64 { @@ -3922,6 +3924,20 @@ 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(32) + } + // field Keyspace string + size += hack.RuntimeAllocSize(int64(len(cached.Keyspace))) + // 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 228546cb422..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 @@ -945,6 +949,7 @@ const ( CancelMigrationType CancelAllMigrationType CleanupMigrationType + CleanupAllMigrationType ThrottleMigrationType ThrottleAllMigrationType UnthrottleMigrationType diff --git a/go/vt/sqlparser/goyacc/goyacc.go b/go/vt/sqlparser/goyacc/goyacc.go index 51650b0891e..14ab8c2eed7 100644 --- a/go/vt/sqlparser/goyacc/goyacc.go +++ b/go/vt/sqlparser/goyacc/goyacc.go @@ -85,7 +85,7 @@ const ( ERRCODE = 8190 ACCEPTCODE = 8191 YYLEXUNK = 3 - TOKSTART = 4 //index of first defined token + TOKSTART = 4 // index of first defined token ) // no, left, right, binary assoc. @@ -617,7 +617,7 @@ outer: } j = chfind(2, tokname) if j >= NTBASE { - lerrorf(ruleline, "nonterminal "+nontrst[j-NTBASE].name+" illegal after %%prec") + lerrorf(ruleline, "nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name) } levprd[nprod] = toklev[j] t = gettok() @@ -1730,7 +1730,7 @@ more: } if pempty[i] != OK { fatfl = 0 - errorf("nonterminal " + nontrst[i].name + " never derives any token string") + errorf("nonterminal %s never derives any token string", nontrst[i].name) } } @@ -2937,7 +2937,7 @@ func others() { aryfil(temp1, nprod, 0) // - //yyr2 is the number of rules for each production + // yyr2 is the number of rules for each production // for i = 1; i < nprod; i++ { temp1[i] = len(prdptr[i]) - 2 @@ -3276,7 +3276,7 @@ func getrune(f *bufio.Reader) rune { if err != nil { errorf("read error: %v", err) } - //fmt.Printf("rune = %v n=%v\n", string(c), n); + // fmt.Printf("rune = %v n=%v\n", string(c), n); return c } @@ -3295,7 +3295,7 @@ func open(s string) *bufio.Reader { if err != nil { errorf("error opening %v: %v", s, err) } - //fmt.Printf("open %v\n", s); + // fmt.Printf("open %v\n", s); return bufio.NewReader(fi) } @@ -3304,7 +3304,7 @@ func create(s string) *bufio.Writer { if err != nil { errorf("error creating %v: %v", s, err) } - //fmt.Printf("create %v mode %v\n", s); + // fmt.Printf("create %v mode %v\n", s); return bufio.NewWriter(fo) } diff --git a/go/vt/sqlparser/keywords.go b/go/vt/sqlparser/keywords.go index a10fbd8384a..57c52dcdac7 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}, @@ -594,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}, @@ -712,6 +713,7 @@ var keywords = []keyword{ {"to", TO}, {"trailing", TRAILING}, {"transaction", TRANSACTION}, + {"transactions", TRANSACTIONS}, {"tree", TREE}, {"traditional", TRADITIONAL}, {"trigger", TRIGGER}, @@ -728,6 +730,7 @@ var keywords = []keyword{ {"unique", UNIQUE}, {"unknown", UNKNOWN}, {"unlock", UNLOCK}, + {"unresolved", UNRESOLVED}, {"unsigned", UNSIGNED}, {"unthrottle", UNTHROTTLE}, {"update", UPDATE}, @@ -751,6 +754,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 c574b00832d..45e24407ef9 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -418,6 +418,13 @@ func TestNormalize(t *testing.T) { "bv2": sqltypes.Int64BindVariable(2), "bv3": sqltypes.TestBindVariable([]any{1, 2}), }, + }, { + in: "SELECT 1 WHERE (~ (1||0)) IS NULL", + outstmt: "select :bv1 /* INT64 */ from dual where ~(:bv1 /* INT64 */ or :bv2 /* INT64 */) is null", + outbv: map[string]*querypb.BindVariable{ + "bv1": sqltypes.Int64BindVariable(1), + "bv2": sqltypes.Int64BindVariable(0), + }, }} parser := NewTestParser() for _, tc := range testcases { @@ -508,6 +515,7 @@ func TestNormalizeOneCasae(t *testing.T) { err = Normalize(tree, NewReservedVars("vtg", known), bv) require.NoError(t, err) normalizerOutput := String(tree) + require.EqualValues(t, testOne.output, normalizerOutput) if normalizerOutput == "otheradmin" || normalizerOutput == "otherread" { return } diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 4875bcc5f63..a12a5b21f85 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -1228,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", @@ -2428,6 +2431,21 @@ 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: "show unresolved transactions", + }, { + input: "show unresolved transactions for ks", }, { input: "revert vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", }, { @@ -2436,6 +2454,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", }, { @@ -2646,9 +2666,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", @@ -5898,6 +5933,10 @@ partition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased)) 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 { @@ -6426,8 +6465,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/precedence.go b/go/vt/sqlparser/precedence.go index ec590b23f95..6df5e8e227e 100644 --- a/go/vt/sqlparser/precedence.go +++ b/go/vt/sqlparser/precedence.go @@ -38,7 +38,6 @@ const ( P14 P15 P16 - P17 ) // precedenceFor returns the precedence of an expression. @@ -83,7 +82,7 @@ func precedenceFor(in Expr) Precendence { switch node.Operator { case UPlusOp, UMinusOp: return P4 - case BangOp: + default: return P3 } } diff --git a/go/vt/sqlparser/precedence_test.go b/go/vt/sqlparser/precedence_test.go index 0d29d8b87e3..0a14df5a2c1 100644 --- a/go/vt/sqlparser/precedence_test.go +++ b/go/vt/sqlparser/precedence_test.go @@ -158,6 +158,7 @@ func TestParens(t *testing.T) { {in: "(10 - 2) - 1", expected: "10 - 2 - 1"}, {in: "10 - (2 - 1)", expected: "10 - (2 - 1)"}, {in: "0 <=> (1 and 0)", expected: "0 <=> (1 and 0)"}, + {in: "(~ (1||0)) IS NULL", expected: "~(1 or 0) is null"}, } parser := NewTestParser() diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 35bcad9362d..9912b19f323 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -40,722 +40,730 @@ 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 JSON_ARRAYAGG = 57461 -const JSON_OBJECTAGG = 57462 -const EXTRACT = 57463 -const NULL = 57464 -const UNKNOWN = 57465 -const TRUE = 57466 -const FALSE = 57467 -const OFF = 57468 -const DISCARD = 57469 -const IMPORT = 57470 -const ENABLE = 57471 -const DISABLE = 57472 -const TABLESPACE = 57473 -const VIRTUAL = 57474 -const STORED = 57475 -const BOTH = 57476 -const LEADING = 57477 -const TRAILING = 57478 -const KILL = 57479 -const EMPTY_FROM_CLAUSE = 57480 -const LOWER_THAN_CHARSET = 57481 -const CHARSET = 57482 -const UNIQUE = 57483 -const KEY = 57484 -const EXPRESSION_PREC_SETTER = 57485 -const OR = 57486 -const XOR = 57487 -const AND = 57488 -const NOT = 57489 -const BETWEEN = 57490 -const CASE = 57491 -const WHEN = 57492 -const THEN = 57493 -const ELSE = 57494 -const END = 57495 -const LE = 57496 -const GE = 57497 -const NE = 57498 -const NULL_SAFE_EQUAL = 57499 -const IS = 57500 -const LIKE = 57501 -const REGEXP = 57502 -const RLIKE = 57503 -const IN = 57504 -const ASSIGNMENT_OPT = 57505 -const SHIFT_LEFT = 57506 -const SHIFT_RIGHT = 57507 -const DIV = 57508 -const MOD = 57509 -const UNARY = 57510 -const COLLATE = 57511 -const BINARY = 57512 -const UNDERSCORE_ARMSCII8 = 57513 -const UNDERSCORE_ASCII = 57514 -const UNDERSCORE_BIG5 = 57515 -const UNDERSCORE_BINARY = 57516 -const UNDERSCORE_CP1250 = 57517 -const UNDERSCORE_CP1251 = 57518 -const UNDERSCORE_CP1256 = 57519 -const UNDERSCORE_CP1257 = 57520 -const UNDERSCORE_CP850 = 57521 -const UNDERSCORE_CP852 = 57522 -const UNDERSCORE_CP866 = 57523 -const UNDERSCORE_CP932 = 57524 -const UNDERSCORE_DEC8 = 57525 -const UNDERSCORE_EUCJPMS = 57526 -const UNDERSCORE_EUCKR = 57527 -const UNDERSCORE_GB18030 = 57528 -const UNDERSCORE_GB2312 = 57529 -const UNDERSCORE_GBK = 57530 -const UNDERSCORE_GEOSTD8 = 57531 -const UNDERSCORE_GREEK = 57532 -const UNDERSCORE_HEBREW = 57533 -const UNDERSCORE_HP8 = 57534 -const UNDERSCORE_KEYBCS2 = 57535 -const UNDERSCORE_KOI8R = 57536 -const UNDERSCORE_KOI8U = 57537 -const UNDERSCORE_LATIN1 = 57538 -const UNDERSCORE_LATIN2 = 57539 -const UNDERSCORE_LATIN5 = 57540 -const UNDERSCORE_LATIN7 = 57541 -const UNDERSCORE_MACCE = 57542 -const UNDERSCORE_MACROMAN = 57543 -const UNDERSCORE_SJIS = 57544 -const UNDERSCORE_SWE7 = 57545 -const UNDERSCORE_TIS620 = 57546 -const UNDERSCORE_UCS2 = 57547 -const UNDERSCORE_UJIS = 57548 -const UNDERSCORE_UTF16 = 57549 -const UNDERSCORE_UTF16LE = 57550 -const UNDERSCORE_UTF32 = 57551 -const UNDERSCORE_UTF8 = 57552 -const UNDERSCORE_UTF8MB4 = 57553 -const UNDERSCORE_UTF8MB3 = 57554 -const INTERVAL = 57555 -const WINDOW_EXPR = 57556 -const JSON_EXTRACT_OP = 57557 -const JSON_UNQUOTE_EXTRACT_OP = 57558 -const CREATE = 57559 -const ALTER = 57560 -const DROP = 57561 -const RENAME = 57562 -const ANALYZE = 57563 -const ADD = 57564 -const FLUSH = 57565 -const CHANGE = 57566 -const MODIFY = 57567 -const DEALLOCATE = 57568 -const REVERT = 57569 -const QUERIES = 57570 -const SCHEMA = 57571 -const TABLE = 57572 -const INDEX = 57573 -const VIEW = 57574 -const TO = 57575 -const IGNORE = 57576 -const IF = 57577 -const PRIMARY = 57578 -const COLUMN = 57579 -const SPATIAL = 57580 -const FULLTEXT = 57581 -const KEY_BLOCK_SIZE = 57582 -const CHECK = 57583 -const INDEXES = 57584 -const ACTION = 57585 -const CASCADE = 57586 -const CONSTRAINT = 57587 -const FOREIGN = 57588 -const NO = 57589 -const REFERENCES = 57590 -const RESTRICT = 57591 -const SHOW = 57592 -const DESCRIBE = 57593 -const EXPLAIN = 57594 -const DATE = 57595 -const ESCAPE = 57596 -const REPAIR = 57597 -const OPTIMIZE = 57598 -const TRUNCATE = 57599 -const COALESCE = 57600 -const EXCHANGE = 57601 -const REBUILD = 57602 -const PARTITIONING = 57603 -const REMOVE = 57604 -const PREPARE = 57605 -const EXECUTE = 57606 -const MAXVALUE = 57607 -const PARTITION = 57608 -const REORGANIZE = 57609 -const LESS = 57610 -const THAN = 57611 -const PROCEDURE = 57612 -const TRIGGER = 57613 -const VINDEX = 57614 -const VINDEXES = 57615 -const DIRECTORY = 57616 -const NAME = 57617 -const UPGRADE = 57618 -const STATUS = 57619 -const VARIABLES = 57620 -const WARNINGS = 57621 -const CASCADED = 57622 -const DEFINER = 57623 -const OPTION = 57624 -const SQL = 57625 -const UNDEFINED = 57626 -const SEQUENCE = 57627 -const MERGE = 57628 -const TEMPORARY = 57629 -const TEMPTABLE = 57630 -const INVOKER = 57631 -const SECURITY = 57632 -const FIRST = 57633 -const AFTER = 57634 -const LAST = 57635 -const VITESS_MIGRATION = 57636 -const CANCEL = 57637 -const RETRY = 57638 -const LAUNCH = 57639 -const COMPLETE = 57640 -const CLEANUP = 57641 -const THROTTLE = 57642 -const UNTHROTTLE = 57643 -const FORCE_CUTOVER = 57644 -const EXPIRE = 57645 -const RATIO = 57646 -const VITESS_THROTTLER = 57647 -const BEGIN = 57648 -const START = 57649 -const TRANSACTION = 57650 -const COMMIT = 57651 -const ROLLBACK = 57652 -const SAVEPOINT = 57653 -const RELEASE = 57654 -const WORK = 57655 -const CONSISTENT = 57656 -const SNAPSHOT = 57657 -const BIT = 57658 -const TINYINT = 57659 -const SMALLINT = 57660 -const MEDIUMINT = 57661 -const INT = 57662 -const INTEGER = 57663 -const BIGINT = 57664 -const INTNUM = 57665 -const REAL = 57666 -const DOUBLE = 57667 -const FLOAT_TYPE = 57668 -const FLOAT4_TYPE = 57669 -const FLOAT8_TYPE = 57670 -const DECIMAL_TYPE = 57671 -const NUMERIC = 57672 -const TIME = 57673 -const TIMESTAMP = 57674 -const DATETIME = 57675 -const YEAR = 57676 -const CHAR = 57677 -const VARCHAR = 57678 -const BOOL = 57679 -const CHARACTER = 57680 -const VARBINARY = 57681 -const NCHAR = 57682 -const TEXT = 57683 -const TINYTEXT = 57684 -const MEDIUMTEXT = 57685 -const LONGTEXT = 57686 -const BLOB = 57687 -const TINYBLOB = 57688 -const MEDIUMBLOB = 57689 -const LONGBLOB = 57690 -const JSON = 57691 -const JSON_SCHEMA_VALID = 57692 -const JSON_SCHEMA_VALIDATION_REPORT = 57693 -const ENUM = 57694 -const GEOMETRY = 57695 -const POINT = 57696 -const LINESTRING = 57697 -const POLYGON = 57698 -const GEOMCOLLECTION = 57699 -const GEOMETRYCOLLECTION = 57700 -const MULTIPOINT = 57701 -const MULTILINESTRING = 57702 -const MULTIPOLYGON = 57703 -const ASCII = 57704 -const UNICODE = 57705 -const NULLX = 57706 -const AUTO_INCREMENT = 57707 -const APPROXNUM = 57708 -const SIGNED = 57709 -const UNSIGNED = 57710 -const ZEROFILL = 57711 -const PURGE = 57712 -const BEFORE = 57713 -const CODE = 57714 -const COLLATION = 57715 -const COLUMNS = 57716 -const DATABASES = 57717 -const ENGINES = 57718 -const EVENT = 57719 -const EXTENDED = 57720 -const FIELDS = 57721 -const FULL = 57722 -const FUNCTION = 57723 -const GTID_EXECUTED = 57724 -const KEYSPACES = 57725 -const OPEN = 57726 -const PLUGINS = 57727 -const PRIVILEGES = 57728 -const PROCESSLIST = 57729 -const SCHEMAS = 57730 -const TABLES = 57731 -const TRIGGERS = 57732 -const USER = 57733 -const VGTID_EXECUTED = 57734 -const VITESS_KEYSPACES = 57735 -const VITESS_METADATA = 57736 -const VITESS_MIGRATIONS = 57737 -const VITESS_REPLICATION_STATUS = 57738 -const VITESS_SHARDS = 57739 -const VITESS_TABLETS = 57740 -const VITESS_TARGET = 57741 -const VSCHEMA = 57742 -const VITESS_THROTTLED_APPS = 57743 -const NAMES = 57744 -const GLOBAL = 57745 -const SESSION = 57746 -const ISOLATION = 57747 -const LEVEL = 57748 -const READ = 57749 -const WRITE = 57750 -const ONLY = 57751 -const REPEATABLE = 57752 -const COMMITTED = 57753 -const UNCOMMITTED = 57754 -const SERIALIZABLE = 57755 -const ADDDATE = 57756 -const CURRENT_TIMESTAMP = 57757 -const DATABASE = 57758 -const CURRENT_DATE = 57759 -const CURDATE = 57760 -const DATE_ADD = 57761 -const DATE_SUB = 57762 -const NOW = 57763 -const SUBDATE = 57764 -const CURTIME = 57765 -const CURRENT_TIME = 57766 -const LOCALTIME = 57767 -const LOCALTIMESTAMP = 57768 -const CURRENT_USER = 57769 -const UTC_DATE = 57770 -const UTC_TIME = 57771 -const UTC_TIMESTAMP = 57772 -const SYSDATE = 57773 -const DAY = 57774 -const DAY_HOUR = 57775 -const DAY_MICROSECOND = 57776 -const DAY_MINUTE = 57777 -const DAY_SECOND = 57778 -const HOUR = 57779 -const HOUR_MICROSECOND = 57780 -const HOUR_MINUTE = 57781 -const HOUR_SECOND = 57782 -const MICROSECOND = 57783 -const MINUTE = 57784 -const MINUTE_MICROSECOND = 57785 -const MINUTE_SECOND = 57786 -const MONTH = 57787 -const QUARTER = 57788 -const SECOND = 57789 -const SECOND_MICROSECOND = 57790 -const YEAR_MONTH = 57791 -const WEEK = 57792 -const SQL_TSI_DAY = 57793 -const SQL_TSI_WEEK = 57794 -const SQL_TSI_HOUR = 57795 -const SQL_TSI_MINUTE = 57796 -const SQL_TSI_MONTH = 57797 -const SQL_TSI_QUARTER = 57798 -const SQL_TSI_SECOND = 57799 -const SQL_TSI_MICROSECOND = 57800 -const SQL_TSI_YEAR = 57801 -const REPLACE = 57802 -const CONVERT = 57803 -const CAST = 57804 -const SUBSTR = 57805 -const SUBSTRING = 57806 -const MID = 57807 -const SEPARATOR = 57808 -const TIMESTAMPADD = 57809 -const TIMESTAMPDIFF = 57810 -const WEIGHT_STRING = 57811 -const LTRIM = 57812 -const RTRIM = 57813 -const TRIM = 57814 -const JSON_ARRAY = 57815 -const JSON_OBJECT = 57816 -const JSON_QUOTE = 57817 -const JSON_DEPTH = 57818 -const JSON_TYPE = 57819 -const JSON_LENGTH = 57820 -const JSON_VALID = 57821 -const JSON_ARRAY_APPEND = 57822 -const JSON_ARRAY_INSERT = 57823 -const JSON_INSERT = 57824 -const JSON_MERGE = 57825 -const JSON_MERGE_PATCH = 57826 -const JSON_MERGE_PRESERVE = 57827 -const JSON_REMOVE = 57828 -const JSON_REPLACE = 57829 -const JSON_SET = 57830 -const JSON_UNQUOTE = 57831 -const COUNT = 57832 -const AVG = 57833 -const MAX = 57834 -const MIN = 57835 -const SUM = 57836 -const GROUP_CONCAT = 57837 -const BIT_AND = 57838 -const BIT_OR = 57839 -const BIT_XOR = 57840 -const STD = 57841 -const STDDEV = 57842 -const STDDEV_POP = 57843 -const STDDEV_SAMP = 57844 -const VAR_POP = 57845 -const VAR_SAMP = 57846 -const VARIANCE = 57847 -const ANY_VALUE = 57848 -const REGEXP_INSTR = 57849 -const REGEXP_LIKE = 57850 -const REGEXP_REPLACE = 57851 -const REGEXP_SUBSTR = 57852 -const ExtractValue = 57853 -const UpdateXML = 57854 -const GET_LOCK = 57855 -const RELEASE_LOCK = 57856 -const RELEASE_ALL_LOCKS = 57857 -const IS_FREE_LOCK = 57858 -const IS_USED_LOCK = 57859 -const LOCATE = 57860 -const POSITION = 57861 -const ST_GeometryCollectionFromText = 57862 -const ST_GeometryFromText = 57863 -const ST_LineStringFromText = 57864 -const ST_MultiLineStringFromText = 57865 -const ST_MultiPointFromText = 57866 -const ST_MultiPolygonFromText = 57867 -const ST_PointFromText = 57868 -const ST_PolygonFromText = 57869 -const ST_GeometryCollectionFromWKB = 57870 -const ST_GeometryFromWKB = 57871 -const ST_LineStringFromWKB = 57872 -const ST_MultiLineStringFromWKB = 57873 -const ST_MultiPointFromWKB = 57874 -const ST_MultiPolygonFromWKB = 57875 -const ST_PointFromWKB = 57876 -const ST_PolygonFromWKB = 57877 -const ST_AsBinary = 57878 -const ST_AsText = 57879 -const ST_Dimension = 57880 -const ST_Envelope = 57881 -const ST_IsSimple = 57882 -const ST_IsEmpty = 57883 -const ST_GeometryType = 57884 -const ST_X = 57885 -const ST_Y = 57886 -const ST_Latitude = 57887 -const ST_Longitude = 57888 -const ST_EndPoint = 57889 -const ST_IsClosed = 57890 -const ST_Length = 57891 -const ST_NumPoints = 57892 -const ST_StartPoint = 57893 -const ST_PointN = 57894 -const ST_Area = 57895 -const ST_Centroid = 57896 -const ST_ExteriorRing = 57897 -const ST_InteriorRingN = 57898 -const ST_NumInteriorRings = 57899 -const ST_NumGeometries = 57900 -const ST_GeometryN = 57901 -const ST_LongFromGeoHash = 57902 -const ST_PointFromGeoHash = 57903 -const ST_LatFromGeoHash = 57904 -const ST_GeoHash = 57905 -const ST_AsGeoJSON = 57906 -const ST_GeomFromGeoJSON = 57907 -const MATCH = 57908 -const AGAINST = 57909 -const BOOLEAN = 57910 -const LANGUAGE = 57911 -const WITH = 57912 -const QUERY = 57913 -const EXPANSION = 57914 -const WITHOUT = 57915 -const VALIDATION = 57916 -const ROLLUP = 57917 -const UNUSED = 57918 -const ARRAY = 57919 -const BYTE = 57920 -const CUME_DIST = 57921 -const DESCRIPTION = 57922 -const DENSE_RANK = 57923 -const EMPTY = 57924 -const EXCEPT = 57925 -const FIRST_VALUE = 57926 -const GROUPING = 57927 -const GROUPS = 57928 -const JSON_TABLE = 57929 -const LAG = 57930 -const LAST_VALUE = 57931 -const LATERAL = 57932 -const LEAD = 57933 -const NTH_VALUE = 57934 -const NTILE = 57935 -const OF = 57936 -const OVER = 57937 -const PERCENT_RANK = 57938 -const RANK = 57939 -const RECURSIVE = 57940 -const ROW_NUMBER = 57941 -const SYSTEM = 57942 -const WINDOW = 57943 -const ACTIVE = 57944 -const ADMIN = 57945 -const AUTOEXTEND_SIZE = 57946 -const BUCKETS = 57947 -const CLONE = 57948 -const COLUMN_FORMAT = 57949 -const COMPONENT = 57950 -const DEFINITION = 57951 -const ENFORCED = 57952 -const ENGINE_ATTRIBUTE = 57953 -const EXCLUDE = 57954 -const FOLLOWING = 57955 -const GET_MASTER_PUBLIC_KEY = 57956 -const HISTOGRAM = 57957 -const HISTORY = 57958 -const INACTIVE = 57959 -const INVISIBLE = 57960 -const LOCKED = 57961 -const MASTER_COMPRESSION_ALGORITHMS = 57962 -const MASTER_PUBLIC_KEY_PATH = 57963 -const MASTER_TLS_CIPHERSUITES = 57964 -const MASTER_ZSTD_COMPRESSION_LEVEL = 57965 -const NESTED = 57966 -const NETWORK_NAMESPACE = 57967 -const NOWAIT = 57968 -const NULLS = 57969 -const OJ = 57970 -const OLD = 57971 -const OPTIONAL = 57972 -const ORDINALITY = 57973 -const ORGANIZATION = 57974 -const OTHERS = 57975 -const PARTIAL = 57976 -const PATH = 57977 -const PERSIST = 57978 -const PERSIST_ONLY = 57979 -const PRECEDING = 57980 -const PRIVILEGE_CHECKS_USER = 57981 -const PROCESS = 57982 -const RANDOM = 57983 -const REFERENCE = 57984 -const REQUIRE_ROW_FORMAT = 57985 -const RESOURCE = 57986 -const RESPECT = 57987 -const RESTART = 57988 -const RETAIN = 57989 -const REUSE = 57990 -const ROLE = 57991 -const SECONDARY = 57992 -const SECONDARY_ENGINE = 57993 -const SECONDARY_ENGINE_ATTRIBUTE = 57994 -const SECONDARY_LOAD = 57995 -const SECONDARY_UNLOAD = 57996 -const SIMPLE = 57997 -const SKIP = 57998 -const SRID = 57999 -const THREAD_PRIORITY = 58000 -const TIES = 58001 -const UNBOUNDED = 58002 -const VCPU = 58003 -const VISIBLE = 58004 -const RETURNING = 58005 -const FORMAT_BYTES = 58006 -const FORMAT_PICO_TIME = 58007 -const PS_CURRENT_THREAD_ID = 58008 -const PS_THREAD_ID = 58009 -const GTID_SUBSET = 58010 -const GTID_SUBTRACT = 58011 -const WAIT_FOR_EXECUTED_GTID_SET = 58012 -const WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS = 58013 -const FORMAT = 58014 -const TREE = 58015 -const VITESS = 58016 -const TRADITIONAL = 58017 -const VTEXPLAIN = 58018 -const VEXPLAIN = 58019 -const PLAN = 58020 -const LOCAL = 58021 -const LOW_PRIORITY = 58022 -const NO_WRITE_TO_BINLOG = 58023 -const LOGS = 58024 -const ERROR = 58025 -const GENERAL = 58026 -const HOSTS = 58027 -const OPTIMIZER_COSTS = 58028 -const USER_RESOURCES = 58029 -const SLOW = 58030 -const CHANNEL = 58031 -const RELAY = 58032 -const EXPORT = 58033 -const CURRENT = 58034 -const ROW = 58035 -const ROWS = 58036 -const AVG_ROW_LENGTH = 58037 -const CONNECTION = 58038 -const CHECKSUM = 58039 -const DELAY_KEY_WRITE = 58040 -const ENCRYPTION = 58041 -const ENGINE = 58042 -const INSERT_METHOD = 58043 -const MAX_ROWS = 58044 -const MIN_ROWS = 58045 -const PACK_KEYS = 58046 -const PASSWORD = 58047 -const FIXED = 58048 -const DYNAMIC = 58049 -const COMPRESSED = 58050 -const REDUNDANT = 58051 -const COMPACT = 58052 -const ROW_FORMAT = 58053 -const STATS_AUTO_RECALC = 58054 -const STATS_PERSISTENT = 58055 -const STATS_SAMPLE_PAGES = 58056 -const STORAGE = 58057 -const MEMORY = 58058 -const DISK = 58059 -const PARTITIONS = 58060 -const LINEAR = 58061 -const RANGE = 58062 -const LIST = 58063 -const SUBPARTITION = 58064 -const SUBPARTITIONS = 58065 -const HASH = 58066 +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 UNRESOLVED = 57663 +const TRANSACTIONS = 57664 +const BIT = 57665 +const TINYINT = 57666 +const SMALLINT = 57667 +const MEDIUMINT = 57668 +const INT = 57669 +const INTEGER = 57670 +const BIGINT = 57671 +const INTNUM = 57672 +const REAL = 57673 +const DOUBLE = 57674 +const FLOAT_TYPE = 57675 +const FLOAT4_TYPE = 57676 +const FLOAT8_TYPE = 57677 +const DECIMAL_TYPE = 57678 +const NUMERIC = 57679 +const TIME = 57680 +const TIMESTAMP = 57681 +const DATETIME = 57682 +const YEAR = 57683 +const CHAR = 57684 +const VARCHAR = 57685 +const BOOL = 57686 +const CHARACTER = 57687 +const VARBINARY = 57688 +const NCHAR = 57689 +const TEXT = 57690 +const TINYTEXT = 57691 +const MEDIUMTEXT = 57692 +const LONGTEXT = 57693 +const BLOB = 57694 +const TINYBLOB = 57695 +const MEDIUMBLOB = 57696 +const LONGBLOB = 57697 +const JSON = 57698 +const JSON_SCHEMA_VALID = 57699 +const JSON_SCHEMA_VALIDATION_REPORT = 57700 +const ENUM = 57701 +const GEOMETRY = 57702 +const POINT = 57703 +const LINESTRING = 57704 +const POLYGON = 57705 +const GEOMCOLLECTION = 57706 +const GEOMETRYCOLLECTION = 57707 +const MULTIPOINT = 57708 +const MULTILINESTRING = 57709 +const MULTIPOLYGON = 57710 +const ASCII = 57711 +const UNICODE = 57712 +const VECTOR = 57713 +const NULLX = 57714 +const AUTO_INCREMENT = 57715 +const APPROXNUM = 57716 +const SIGNED = 57717 +const UNSIGNED = 57718 +const ZEROFILL = 57719 +const PURGE = 57720 +const BEFORE = 57721 +const CODE = 57722 +const COLLATION = 57723 +const COLUMNS = 57724 +const DATABASES = 57725 +const ENGINES = 57726 +const EVENT = 57727 +const EXTENDED = 57728 +const FIELDS = 57729 +const FULL = 57730 +const FUNCTION = 57731 +const GTID_EXECUTED = 57732 +const KEYSPACES = 57733 +const OPEN = 57734 +const PLUGINS = 57735 +const PRIVILEGES = 57736 +const PROCESSLIST = 57737 +const SCHEMAS = 57738 +const TABLES = 57739 +const TRIGGERS = 57740 +const USER = 57741 +const VGTID_EXECUTED = 57742 +const VITESS_KEYSPACES = 57743 +const VITESS_METADATA = 57744 +const VITESS_MIGRATIONS = 57745 +const VITESS_REPLICATION_STATUS = 57746 +const VITESS_SHARDS = 57747 +const VITESS_TABLETS = 57748 +const VITESS_TARGET = 57749 +const VSCHEMA = 57750 +const VITESS_THROTTLED_APPS = 57751 +const NAMES = 57752 +const GLOBAL = 57753 +const SESSION = 57754 +const ISOLATION = 57755 +const LEVEL = 57756 +const READ = 57757 +const WRITE = 57758 +const ONLY = 57759 +const REPEATABLE = 57760 +const COMMITTED = 57761 +const UNCOMMITTED = 57762 +const SERIALIZABLE = 57763 +const ADDDATE = 57764 +const CURRENT_TIMESTAMP = 57765 +const DATABASE = 57766 +const CURRENT_DATE = 57767 +const CURDATE = 57768 +const DATE_ADD = 57769 +const DATE_SUB = 57770 +const NOW = 57771 +const SUBDATE = 57772 +const CURTIME = 57773 +const CURRENT_TIME = 57774 +const LOCALTIME = 57775 +const LOCALTIMESTAMP = 57776 +const CURRENT_USER = 57777 +const UTC_DATE = 57778 +const UTC_TIME = 57779 +const UTC_TIMESTAMP = 57780 +const SYSDATE = 57781 +const DAY = 57782 +const DAY_HOUR = 57783 +const DAY_MICROSECOND = 57784 +const DAY_MINUTE = 57785 +const DAY_SECOND = 57786 +const HOUR = 57787 +const HOUR_MICROSECOND = 57788 +const HOUR_MINUTE = 57789 +const HOUR_SECOND = 57790 +const MICROSECOND = 57791 +const MINUTE = 57792 +const MINUTE_MICROSECOND = 57793 +const MINUTE_SECOND = 57794 +const MONTH = 57795 +const QUARTER = 57796 +const SECOND = 57797 +const SECOND_MICROSECOND = 57798 +const YEAR_MONTH = 57799 +const WEEK = 57800 +const SQL_TSI_DAY = 57801 +const SQL_TSI_WEEK = 57802 +const SQL_TSI_HOUR = 57803 +const SQL_TSI_MINUTE = 57804 +const SQL_TSI_MONTH = 57805 +const SQL_TSI_QUARTER = 57806 +const SQL_TSI_SECOND = 57807 +const SQL_TSI_MICROSECOND = 57808 +const SQL_TSI_YEAR = 57809 +const REPLACE = 57810 +const CONVERT = 57811 +const CAST = 57812 +const SUBSTR = 57813 +const SUBSTRING = 57814 +const MID = 57815 +const SEPARATOR = 57816 +const TIMESTAMPADD = 57817 +const TIMESTAMPDIFF = 57818 +const WEIGHT_STRING = 57819 +const LTRIM = 57820 +const RTRIM = 57821 +const TRIM = 57822 +const JSON_ARRAY = 57823 +const JSON_OBJECT = 57824 +const JSON_QUOTE = 57825 +const JSON_DEPTH = 57826 +const JSON_TYPE = 57827 +const JSON_LENGTH = 57828 +const JSON_VALID = 57829 +const JSON_ARRAY_APPEND = 57830 +const JSON_ARRAY_INSERT = 57831 +const JSON_INSERT = 57832 +const JSON_MERGE = 57833 +const JSON_MERGE_PATCH = 57834 +const JSON_MERGE_PRESERVE = 57835 +const JSON_REMOVE = 57836 +const JSON_REPLACE = 57837 +const JSON_SET = 57838 +const JSON_UNQUOTE = 57839 +const COUNT = 57840 +const AVG = 57841 +const MAX = 57842 +const MIN = 57843 +const SUM = 57844 +const GROUP_CONCAT = 57845 +const BIT_AND = 57846 +const BIT_OR = 57847 +const BIT_XOR = 57848 +const STD = 57849 +const STDDEV = 57850 +const STDDEV_POP = 57851 +const STDDEV_SAMP = 57852 +const VAR_POP = 57853 +const VAR_SAMP = 57854 +const VARIANCE = 57855 +const ANY_VALUE = 57856 +const REGEXP_INSTR = 57857 +const REGEXP_LIKE = 57858 +const REGEXP_REPLACE = 57859 +const REGEXP_SUBSTR = 57860 +const ExtractValue = 57861 +const UpdateXML = 57862 +const GET_LOCK = 57863 +const RELEASE_LOCK = 57864 +const RELEASE_ALL_LOCKS = 57865 +const IS_FREE_LOCK = 57866 +const IS_USED_LOCK = 57867 +const LOCATE = 57868 +const POSITION = 57869 +const ST_GeometryCollectionFromText = 57870 +const ST_GeometryFromText = 57871 +const ST_LineStringFromText = 57872 +const ST_MultiLineStringFromText = 57873 +const ST_MultiPointFromText = 57874 +const ST_MultiPolygonFromText = 57875 +const ST_PointFromText = 57876 +const ST_PolygonFromText = 57877 +const ST_GeometryCollectionFromWKB = 57878 +const ST_GeometryFromWKB = 57879 +const ST_LineStringFromWKB = 57880 +const ST_MultiLineStringFromWKB = 57881 +const ST_MultiPointFromWKB = 57882 +const ST_MultiPolygonFromWKB = 57883 +const ST_PointFromWKB = 57884 +const ST_PolygonFromWKB = 57885 +const ST_AsBinary = 57886 +const ST_AsText = 57887 +const ST_Dimension = 57888 +const ST_Envelope = 57889 +const ST_IsSimple = 57890 +const ST_IsEmpty = 57891 +const ST_GeometryType = 57892 +const ST_X = 57893 +const ST_Y = 57894 +const ST_Latitude = 57895 +const ST_Longitude = 57896 +const ST_EndPoint = 57897 +const ST_IsClosed = 57898 +const ST_Length = 57899 +const ST_NumPoints = 57900 +const ST_StartPoint = 57901 +const ST_PointN = 57902 +const ST_Area = 57903 +const ST_Centroid = 57904 +const ST_ExteriorRing = 57905 +const ST_InteriorRingN = 57906 +const ST_NumInteriorRings = 57907 +const ST_NumGeometries = 57908 +const ST_GeometryN = 57909 +const ST_LongFromGeoHash = 57910 +const ST_PointFromGeoHash = 57911 +const ST_LatFromGeoHash = 57912 +const ST_GeoHash = 57913 +const ST_AsGeoJSON = 57914 +const ST_GeomFromGeoJSON = 57915 +const MATCH = 57916 +const AGAINST = 57917 +const BOOLEAN = 57918 +const LANGUAGE = 57919 +const WITH = 57920 +const QUERY = 57921 +const EXPANSION = 57922 +const WITHOUT = 57923 +const VALIDATION = 57924 +const ROLLUP = 57925 +const UNUSED = 57926 +const ARRAY = 57927 +const BYTE = 57928 +const CUME_DIST = 57929 +const DESCRIPTION = 57930 +const DENSE_RANK = 57931 +const EMPTY = 57932 +const EXCEPT = 57933 +const FIRST_VALUE = 57934 +const GROUPING = 57935 +const GROUPS = 57936 +const JSON_TABLE = 57937 +const LAG = 57938 +const LAST_VALUE = 57939 +const LATERAL = 57940 +const LEAD = 57941 +const NTH_VALUE = 57942 +const NTILE = 57943 +const OF = 57944 +const OVER = 57945 +const PERCENT_RANK = 57946 +const RANK = 57947 +const RECURSIVE = 57948 +const ROW_NUMBER = 57949 +const SYSTEM = 57950 +const WINDOW = 57951 +const ACTIVE = 57952 +const ADMIN = 57953 +const AUTOEXTEND_SIZE = 57954 +const BUCKETS = 57955 +const CLONE = 57956 +const COLUMN_FORMAT = 57957 +const COMPONENT = 57958 +const DEFINITION = 57959 +const ENFORCED = 57960 +const ENGINE_ATTRIBUTE = 57961 +const EXCLUDE = 57962 +const FOLLOWING = 57963 +const GET_MASTER_PUBLIC_KEY = 57964 +const HISTOGRAM = 57965 +const HISTORY = 57966 +const INACTIVE = 57967 +const INVISIBLE = 57968 +const LOCKED = 57969 +const MASTER_COMPRESSION_ALGORITHMS = 57970 +const MASTER_PUBLIC_KEY_PATH = 57971 +const MASTER_TLS_CIPHERSUITES = 57972 +const MASTER_ZSTD_COMPRESSION_LEVEL = 57973 +const NESTED = 57974 +const NETWORK_NAMESPACE = 57975 +const NOWAIT = 57976 +const NULLS = 57977 +const OJ = 57978 +const OLD = 57979 +const OPTIONAL = 57980 +const ORDINALITY = 57981 +const ORGANIZATION = 57982 +const OTHERS = 57983 +const PARTIAL = 57984 +const PATH = 57985 +const PERSIST = 57986 +const PERSIST_ONLY = 57987 +const PRECEDING = 57988 +const PRIVILEGE_CHECKS_USER = 57989 +const PROCESS = 57990 +const RANDOM = 57991 +const REFERENCE = 57992 +const REQUIRE_ROW_FORMAT = 57993 +const RESOURCE = 57994 +const RESPECT = 57995 +const RESTART = 57996 +const RETAIN = 57997 +const REUSE = 57998 +const ROLE = 57999 +const SECONDARY = 58000 +const SECONDARY_ENGINE = 58001 +const SECONDARY_ENGINE_ATTRIBUTE = 58002 +const SECONDARY_LOAD = 58003 +const SECONDARY_UNLOAD = 58004 +const SIMPLE = 58005 +const SKIP = 58006 +const SRID = 58007 +const THREAD_PRIORITY = 58008 +const TIES = 58009 +const UNBOUNDED = 58010 +const VCPU = 58011 +const VISIBLE = 58012 +const RETURNING = 58013 +const FORMAT_BYTES = 58014 +const FORMAT_PICO_TIME = 58015 +const PS_CURRENT_THREAD_ID = 58016 +const PS_THREAD_ID = 58017 +const GTID_SUBSET = 58018 +const GTID_SUBTRACT = 58019 +const WAIT_FOR_EXECUTED_GTID_SET = 58020 +const WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS = 58021 +const FORMAT = 58022 +const TREE = 58023 +const VITESS = 58024 +const TRADITIONAL = 58025 +const VTEXPLAIN = 58026 +const VEXPLAIN = 58027 +const PLAN = 58028 +const LOCAL = 58029 +const LOW_PRIORITY = 58030 +const NO_WRITE_TO_BINLOG = 58031 +const LOGS = 58032 +const ERROR = 58033 +const GENERAL = 58034 +const HOSTS = 58035 +const OPTIMIZER_COSTS = 58036 +const USER_RESOURCES = 58037 +const SLOW = 58038 +const CHANNEL = 58039 +const RELAY = 58040 +const EXPORT = 58041 +const CURRENT = 58042 +const ROW = 58043 +const ROWS = 58044 +const AVG_ROW_LENGTH = 58045 +const CONNECTION = 58046 +const CHECKSUM = 58047 +const DELAY_KEY_WRITE = 58048 +const ENCRYPTION = 58049 +const ENGINE = 58050 +const INSERT_METHOD = 58051 +const MAX_ROWS = 58052 +const MIN_ROWS = 58053 +const PACK_KEYS = 58054 +const PASSWORD = 58055 +const FIXED = 58056 +const DYNAMIC = 58057 +const COMPRESSED = 58058 +const REDUNDANT = 58059 +const COMPACT = 58060 +const ROW_FORMAT = 58061 +const STATS_AUTO_RECALC = 58062 +const STATS_PERSISTENT = 58063 +const STATS_SAMPLE_PAGES = 58064 +const STORAGE = 58065 +const MEMORY = 58066 +const DISK = 58067 +const PARTITIONS = 58068 +const LINEAR = 58069 +const RANGE = 58070 +const LIST = 58071 +const SUBPARTITION = 58072 +const SUBPARTITIONS = 58073 +const HASH = 58074 var yyToknames = [...]string{ "$end", @@ -766,6 +774,7 @@ var yyToknames = [...]string{ "FUNCTION_CALL_NON_KEYWORD", "STRING_TYPE_PREFIX_NON_KEYWORD", "ANY_SOME", + "SELECT_OPTIONS", "LEX_ERROR", "UNION", "SELECT", @@ -828,6 +837,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", @@ -852,6 +864,7 @@ var yyToknames = [...]string{ "','", "')'", "STRING", + "SQL_BUFFER_RESULT", "ID", "AT_ID", "AT_AT_ID", @@ -1090,6 +1103,8 @@ var yyToknames = [...]string{ "WORK", "CONSISTENT", "SNAPSHOT", + "UNRESOLVED", + "TRANSACTIONS", "BIT", "TINYINT", "SMALLINT", @@ -1138,6 +1153,7 @@ var yyToknames = [...]string{ "MULTIPOLYGON", "ASCII", "UNICODE", + "VECTOR", "NULLX", "AUTO_INCREMENT", "APPROXNUM", @@ -1514,885 +1530,1032 @@ var yyExca = [...]int{ 1, -1, -2, 0, -1, 2, - 15, 49, 16, 49, + 17, 49, -2, 40, -1, 52, 1, 157, - 742, 157, + 750, 157, -2, 165, -1, 53, - 143, 165, - 185, 165, - 355, 165, - -2, 523, + 148, 165, + 190, 165, + 362, 165, + -2, 524, -1, 61, - 37, 777, - 248, 777, - 259, 777, - 294, 791, - 295, 791, - -2, 779, + 38, 784, + 253, 784, + 264, 784, + 299, 798, + 300, 798, + -2, 786, -1, 66, - 250, 815, - -2, 813, + 255, 822, + -2, 820, -1, 122, - 247, 1608, + 252, 1619, -2, 131, -1, 124, 1, 158, - 742, 158, + 750, 158, -2, 165, -1, 135, - 144, 408, - 253, 408, - -2, 512, + 149, 409, + 258, 409, + -2, 513, -1, 154, - 143, 165, - 185, 165, - 355, 165, - -2, 532, - -1, 741, - 171, 41, + 148, 165, + 190, 165, + 362, 165, + -2, 533, + -1, 747, + 176, 41, -2, 43, - -1, 950, - 91, 1625, - -2, 1469, - -1, 951, - 91, 1626, - 230, 1630, - -2, 1470, - -1, 952, - 230, 1629, + -1, 956, + 95, 1636, + -2, 1480, + -1, 957, + 95, 1637, + 235, 1641, + -2, 1481, + -1, 958, + 235, 1640, -2, 42, - -1, 1036, - 64, 887, - -2, 900, - -1, 1124, - 258, 1096, - 263, 1096, - -2, 419, - -1, 1209, - 1, 580, - 742, 580, - -2, 165, - -1, 1513, - 230, 1630, - -2, 1470, - -1, 1726, - 64, 888, - -2, 904, - -1, 1727, - 64, 889, - -2, 905, - -1, 1783, - 143, 165, - 185, 165, - 355, 165, - -2, 458, - -1, 1864, - 144, 408, - 253, 408, - -2, 512, - -1, 1873, - 258, 1097, - 263, 1097, + -1, 1042, + 65, 894, + -2, 907, + -1, 1130, + 263, 1107, + 268, 1107, -2, 420, - -1, 2318, - 230, 1634, - -2, 1628, - -1, 2319, - 230, 1630, - -2, 1626, - -1, 2422, - 143, 165, - 185, 165, - 355, 165, + -1, 1215, + 1, 581, + 750, 581, + -2, 165, + -1, 1524, + 235, 1641, + -2, 1481, + -1, 1737, + 65, 895, + -2, 911, + -1, 1738, + 65, 896, + -2, 912, + -1, 1798, + 148, 165, + 190, 165, + 362, 165, -2, 459, - -1, 2429, - 27, 186, + -1, 1880, + 149, 409, + 258, 409, + -2, 513, + -1, 1889, + 263, 1108, + 268, 1108, + -2, 421, + -1, 2338, + 235, 1645, + -2, 1639, + -1, 2339, + 235, 1641, + -2, 1637, + -1, 2442, + 148, 165, + 190, 165, + 362, 165, + -2, 460, + -1, 2449, + 28, 186, -2, 188, - -1, 2888, - 82, 96, - 92, 96, - -2, 963, - -1, 2957, - 717, 700, - -2, 674, - -1, 3181, - 54, 1573, - -2, 1567, - -1, 4019, - 717, 700, - -2, 688, - -1, 4111, - 94, 632, - 99, 632, - 109, 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, - 227, 632, - 228, 632, - -2, 2002, + -1, 2912, + 86, 96, + 96, 96, + -2, 974, + -1, 2981, + 725, 702, + -2, 676, + -1, 3205, + 55, 1584, + -2, 1578, + -1, 4043, + 725, 702, + -2, 690, + -1, 4135, + 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, 2016, } const yyPrivate = 57344 -const yyLast = 56576 +const yyLast = 57755 var yyAct = [...]int{ - 966, 3669, 4109, 87, 4186, 3670, 4199, 3671, 4090, 4153, - 1277, 961, 4154, 953, 4000, 3333, 2111, 4078, 2419, 3233, - 3240, 2347, 3905, 3469, 3982, 2123, 3282, 3194, 3291, 1275, - 3296, 3980, 3047, 1786, 3293, 3292, 3290, 3295, 3294, 1993, - 3619, 3606, 4051, 3311, 2349, 3132, 2049, 3248, 2493, 5, - 3310, 745, 3198, 3195, 3515, 3509, 3712, 3021, 954, 3046, - 3182, 739, 2848, 740, 2374, 2922, 915, 773, 914, 2456, - 3313, 3003, 2923, 2390, 1742, 919, 3340, 2954, 42, 2481, - 2461, 3499, 2924, 2524, 2393, 163, 1034, 2407, 87, 1054, - 1842, 2873, 1086, 2394, 1061, 43, 1031, 2840, 2824, 2107, - 2271, 3537, 41, 2995, 1132, 2502, 2480, 1034, 2854, 2303, - 2270, 2395, 149, 2463, 2541, 2915, 2145, 3192, 2057, 1871, - 2382, 1114, 1096, 1119, 1775, 2890, 2397, 1755, 100, 1707, - 1889, 1526, 104, 2151, 1156, 2082, 2071, 1451, 1989, 105, - 1436, 1093, 1878, 1970, 1125, 3197, 1090, 755, 1094, 2478, - 2452, 1120, 2861, 1774, 750, 2453, 1071, 1121, 1073, 1760, - 2375, 1033, 1729, 1037, 1043, 99, 3707, 2159, 2178, 2822, - 1053, 107, 1485, 1040, 2048, 1265, 85, 2001, 3470, 1863, - 132, 133, 1056, 1039, 1066, 3526, 1509, 84, 3699, 1122, - 1038, 1205, 732, 106, 1041, 742, 1029, 749, 1530, 98, - 4187, 93, 167, 3607, 127, 916, 1273, 1065, 1251, 125, - 126, 2495, 2496, 2497, 2495, 3279, 4035, 1535, 2977, 2976, - 2539, 2945, 677, 3599, 4136, 1028, 3011, 743, 1046, 3562, - 3012, 1452, 4031, 134, 2344, 2345, 2064, 2063, 2062, 2061, - 1161, 1136, 4036, 1087, 2060, 2059, 2032, 4030, 3674, 1221, - 674, 2820, 675, 2589, 3178, 128, 4157, 1746, 4130, 4209, - 1468, 1744, 3136, 1169, 4152, 733, 1047, 4177, 3473, 4192, - 4140, 1080, 3472, 1032, 1447, 3983, 2850, 1081, 1030, 2371, - 2370, 2526, 3301, 2970, 1098, 95, 1158, 1747, 2146, 1111, - 95, 1745, 2785, 1955, 4191, 4139, 1103, 2528, 2069, 1175, - 1176, 1177, 3359, 1180, 1181, 1182, 1183, 2, 1055, 1186, - 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, - 1197, 1198, 1199, 1200, 1201, 1202, 1135, 128, 1178, 1110, - 3301, 2368, 4009, 717, 1109, 1108, 2947, 4105, 3299, 1462, - 3673, 2527, 1222, 3298, 4138, 1162, 1165, 1166, 4031, 920, - 1027, 3901, 111, 112, 113, 3900, 116, 711, 717, 122, - 3674, 3612, 191, 735, 3613, 669, 1160, 3305, 1159, 4137, - 4167, 3911, 95, 4134, 3631, 1438, 3620, 730, 731, 190, - 4079, 711, 86, 969, 970, 971, 3299, 1022, 1023, 1024, - 1025, 2967, 95, 86, 1036, 128, 4087, 2116, 2521, 1112, - 86, 3910, 129, 1465, 4114, 1466, 1467, 1709, 1079, 1083, - 918, 2085, 3385, 1852, 2821, 3305, 2864, 1776, 172, 1777, - 1736, 3229, 1068, 1069, 708, 3010, 2899, 2593, 1102, 2898, - 2413, 1104, 2900, 3726, 3230, 3231, 4091, 969, 970, 971, - 2414, 2415, 2041, 2042, 2865, 2994, 1241, 1020, 1458, 1270, - 2596, 1450, 3673, 1019, 3630, 2948, 711, 1107, 1229, 1214, - 1215, 2904, 95, 1230, 4001, 2911, 671, 86, 1486, 1242, - 88, 711, 693, 95, 169, 1235, 4014, 170, 1997, 1448, - 95, 3302, 1464, 711, 3367, 691, 1021, 2187, 1204, 1452, - 3356, 1217, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1495, - 1494, 1496, 1497, 189, 2432, 2431, 711, 2346, 1229, 3337, - 4158, 3365, 4095, 1230, 2472, 1105, 1258, 2594, 1260, 1246, - 1247, 1228, 4119, 1227, 3068, 688, 2378, 2587, 1092, 3302, - 1107, 4159, 1099, 2040, 703, 725, 3335, 2466, 1437, 1101, - 1100, 2044, 4117, 3022, 2857, 2858, 729, 95, 1179, 698, - 3341, 723, 4123, 4124, 1711, 2996, 1257, 1259, 2955, 1269, - 701, 3250, 3251, 2503, 1243, 1268, 4095, 2542, 4118, 712, - 1236, 2980, 3328, 3953, 1945, 3954, 4189, 2590, 1971, 2591, - 3329, 2984, 2985, 1244, 1245, 2179, 1262, 2565, 1105, 2566, - 2181, 2567, 2548, 712, 2186, 2182, 1267, 1462, 2183, 2184, - 2185, 1250, 3338, 2180, 2188, 2189, 2190, 2191, 2192, 2193, - 2194, 2195, 2196, 3601, 1210, 2998, 1998, 173, 1946, 3885, - 1947, 3600, 2568, 1185, 1248, 1184, 179, 3024, 678, 3336, - 680, 694, 2546, 714, 1249, 713, 684, 2544, 682, 686, - 695, 687, 2506, 681, 1106, 692, 1714, 2549, 683, 696, - 697, 700, 704, 705, 706, 702, 699, 4131, 690, 715, - 1115, 3512, 3678, 1255, 1116, 1856, 2391, 1256, 712, 1116, - 3249, 1154, 1155, 3135, 2545, 1153, 1152, 1261, 1151, 1150, - 1149, 1148, 3252, 712, 1147, 1142, 3252, 2547, 1772, 2465, - 3069, 1079, 1083, 918, 4210, 712, 1091, 4164, 3034, 3033, - 3032, 1128, 1254, 3026, 1091, 3030, 1458, 3025, 1274, 3023, - 1274, 1274, 1091, 1127, 3028, 1990, 1089, 1106, 712, 2376, - 2377, 2479, 1067, 3027, 2555, 2551, 2553, 2554, 2552, 2556, - 2557, 2558, 1082, 1076, 1074, 2999, 2532, 1850, 2531, 711, - 1986, 3029, 3031, 1439, 1457, 1454, 1455, 1456, 1461, 1463, - 1460, 164, 1459, 1172, 3272, 2949, 2979, 2525, 1034, 1510, - 1515, 1516, 1453, 1519, 1521, 1522, 1523, 1524, 1525, 1849, - 1528, 1529, 1531, 1531, 1848, 1531, 1531, 1536, 1536, 1536, - 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, 1657, 1658, - 1659, 1660, 1661, 1662, 967, 1507, 1263, 3357, 1663, 967, - 1665, 1666, 1667, 1668, 1669, 3672, 1430, 1431, 1773, 3560, - 3561, 1072, 1536, 1536, 1536, 1536, 1536, 1536, 4008, 1446, - 1113, 2982, 2946, 89, 716, 2913, 3457, 1676, 1677, 1678, - 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, - 1689, 712, 3303, 3304, 1213, 709, 1226, 3597, 94, 1520, - 4093, 3629, 1429, 3513, 1511, 3307, 1216, 1500, 1704, 94, - 710, 1532, 1134, 1533, 1534, 1145, 94, 4054, 1500, 1503, - 1504, 1505, 1506, 1957, 1956, 1958, 1959, 1960, 1239, 1517, - 165, 1134, 4092, 2969, 1877, 1537, 1538, 177, 1143, 2594, - 3303, 3304, 1457, 1454, 1455, 1456, 1461, 1463, 1460, 1075, - 1459, 967, 2595, 3307, 4093, 1082, 1076, 1074, 1134, 2469, - 1453, 1225, 1710, 1231, 1232, 1233, 1234, 3672, 711, 2825, - 2827, 1034, 1735, 3002, 1164, 1034, 2965, 2968, 185, 4203, - 1127, 1034, 1701, 94, 1163, 1208, 4092, 1271, 1272, 1987, - 1846, 1220, 4122, 3015, 1134, 668, 2993, 3144, 2523, 2992, - 2470, 1501, 1502, 4132, 2611, 3996, 3551, 2468, 3533, 1702, - 1976, 2378, 3596, 2895, 2860, 1133, 1212, 2797, 1218, 2119, - 2143, 166, 171, 168, 174, 175, 176, 178, 180, 181, - 182, 183, 1764, 1664, 1133, 1219, 4121, 184, 186, 187, - 188, 2471, 2855, 1876, 3143, 3236, 1718, 124, 676, 2420, - 1722, 2467, 1500, 1497, 3228, 2622, 1033, 1480, 1050, 1266, - 4022, 1133, 1157, 1720, 1146, 1171, 1736, 104, 2160, 3592, - 1721, 1224, 3525, 1252, 105, 3163, 119, 1702, 1441, 1670, - 1671, 1672, 1673, 1674, 1675, 2161, 1708, 1144, 2543, 2002, - 2053, 1983, 1778, 3237, 3042, 2152, 2152, 1133, 2631, 1695, - 2938, 4168, 3161, 1127, 1130, 1131, 107, 1091, 3005, 1466, - 1467, 1124, 1128, 3004, 3721, 1467, 3567, 3239, 2135, 2124, - 2125, 2126, 2127, 2137, 2128, 2129, 2130, 2142, 2138, 2131, - 2132, 2139, 2140, 2141, 2133, 2134, 2136, 3234, 1134, 1238, - 1716, 2826, 3005, 1975, 1738, 1107, 1203, 3004, 2622, 1134, - 1240, 1705, 120, 3566, 2510, 1869, 3250, 3251, 1886, 1885, - 1875, 1134, 2520, 3235, 2518, 2515, 1030, 1145, 1032, 1719, - 1995, 1862, 1717, 1940, 2515, 1879, 1879, 1741, 1143, 4055, - 712, 1045, 4160, 1134, 3552, 4205, 1853, 1854, 1855, 3626, - 4211, 3627, 1881, 1769, 1770, 1703, 3988, 3241, 2308, 1922, - 2522, 3893, 1274, 3892, 2376, 2377, 4201, 2519, 1837, 4202, - 1207, 4200, 3883, 1891, 1880, 1892, 2517, 1894, 1896, 2158, - 1223, 1900, 1902, 1904, 1906, 1908, 1253, 4056, 1979, 1845, - 1977, 1978, 1075, 1980, 1981, 1982, 3643, 1859, 1860, 1858, - 1209, 1133, 2003, 1872, 3989, 1965, 3642, 1127, 1130, 1131, - 1468, 1091, 1133, 1930, 1931, 1124, 1128, 1137, 1127, 1936, - 1937, 3574, 1139, 3573, 1133, 3249, 1140, 1138, 1736, 1137, - 1127, 3563, 3280, 1926, 1139, 2157, 1123, 3252, 1140, 1138, - 3268, 1883, 4212, 1723, 1468, 2920, 1133, 1141, 1170, 969, - 970, 971, 1167, 2919, 1963, 1991, 1972, 1486, 1973, 3014, - 2918, 1974, 1492, 1493, 1495, 1494, 1496, 1497, 1918, 2475, - 1966, 1921, 1964, 1923, 1952, 1950, 1206, 1949, 1948, 2087, - 1938, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1495, 1494, - 1496, 1497, 1106, 2088, 1498, 1499, 2086, 1932, 4173, 1736, - 190, 1488, 1489, 1490, 1491, 1492, 1493, 1495, 1494, 1496, - 1497, 1851, 128, 1929, 1110, 2008, 1928, 1927, 1898, 1109, - 1108, 1962, 1715, 129, 2075, 2076, 2601, 2602, 3332, 1274, - 1274, 3557, 717, 717, 1468, 1433, 2004, 2005, 2030, 172, - 1772, 1951, 101, 87, 2902, 717, 87, 2668, 2491, 2490, - 2009, 1486, 102, 1465, 3238, 1466, 1467, 2016, 2017, 2018, - 1490, 1491, 1492, 1493, 1495, 1494, 1496, 1497, 2029, 2489, - 2488, 2487, 2486, 2672, 1768, 1487, 1488, 1489, 1490, 1491, - 1492, 1493, 1495, 1494, 1496, 1497, 1749, 1465, 4161, 1466, - 1467, 2846, 4188, 1785, 4017, 169, 3044, 4016, 170, 1487, - 1488, 1489, 1490, 1491, 1492, 1493, 1495, 1494, 1496, 1497, - 1736, 4148, 1736, 2114, 2114, 2112, 2112, 1486, 42, 2115, - 1482, 42, 1483, 1736, 189, 3992, 1468, 3991, 1486, 3990, - 2610, 1468, 1750, 2846, 1736, 2077, 1484, 1498, 1499, 1481, - 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1495, 1494, - 1496, 1497, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1495, - 1494, 1496, 1497, 3888, 1487, 1488, 1489, 1490, 1491, 1492, - 1493, 1495, 1494, 1496, 1497, 3872, 1924, 1465, 2006, 1466, - 1467, 2670, 1464, 1736, 2198, 2010, 3871, 2012, 2013, 2014, - 2015, 1464, 1736, 1736, 2019, 2846, 4086, 1701, 1474, 1475, - 1476, 1477, 1478, 1479, 1473, 1470, 2031, 2075, 2076, 2073, - 2074, 1969, 3720, 2308, 4171, 1736, 85, 2305, 3718, 85, - 2054, 2846, 4065, 4010, 1702, 3639, 2307, 1700, 1996, 2084, - 1699, 1468, 110, 2072, 1698, 2037, 2038, 3571, 173, 3556, - 2147, 3342, 965, 109, 2007, 108, 110, 179, 2846, 4061, - 1468, 2011, 3339, 103, 1468, 2089, 3271, 109, 3270, 108, - 3973, 1736, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 1465, - 2929, 1466, 1467, 2916, 1465, 2318, 1466, 1467, 1697, 2090, - 1468, 2092, 2093, 2094, 2095, 2096, 2097, 2099, 2101, 2102, - 2103, 2104, 2105, 2106, 2316, 2222, 3242, 2118, 1468, 1690, - 3246, 3610, 4007, 1468, 2317, 3896, 1736, 3245, 2162, 2163, - 2164, 2165, 2091, 2846, 3884, 1736, 1511, 2578, 2306, 4101, - 1736, 3920, 2176, 2304, 3374, 2577, 2197, 1468, 2537, 1736, - 3919, 1486, 2536, 1468, 2153, 3610, 1736, 3876, 4099, 1736, - 3875, 3247, 4097, 1736, 2846, 3608, 3243, 2515, 1736, 103, - 1468, 3244, 3531, 1736, 3618, 1487, 1488, 1489, 1490, 1491, - 1492, 1493, 1495, 1494, 1496, 1497, 2214, 1468, 3966, 1736, - 2399, 2373, 164, 2352, 1465, 2318, 1466, 1467, 2752, 1736, - 2315, 3261, 3260, 2321, 2322, 2033, 3964, 1736, 3258, 3259, - 2956, 104, 1736, 1465, 2316, 1466, 1467, 1465, 105, 1466, - 1467, 3256, 3257, 101, 2388, 2429, 1999, 1468, 1961, 103, - 1703, 1736, 104, 102, 1953, 3961, 1736, 3256, 3255, 105, - 2363, 3943, 1736, 1465, 1468, 1466, 1467, 2351, 1468, 2870, - 1736, 2083, 2383, 2384, 1468, 2594, 2978, 2862, 3498, 1736, - 2843, 1465, 1096, 1466, 1467, 2401, 1465, 2658, 1466, 1467, - 1841, 2959, 2952, 2953, 103, 3491, 1736, 2212, 2058, 1468, - 2891, 1943, 2438, 2439, 2440, 2441, 1939, 1046, 2339, 2423, - 1465, 1736, 1466, 1467, 1935, 1096, 1465, 2424, 1466, 1467, - 2891, 1934, 2433, 1933, 2434, 2435, 2436, 2437, 1751, 2405, - 2357, 2364, 2358, 1465, 1264, 1466, 1467, 2846, 2845, 2934, - 2444, 2445, 2446, 2447, 2862, 2366, 2458, 2516, 2427, 1468, - 1465, 2870, 1466, 1467, 2504, 2841, 3488, 1736, 1468, 2428, - 2464, 2386, 3486, 1736, 3524, 2892, 1080, 2411, 2410, 1753, - 2409, 3528, 1081, 3193, 2143, 2894, 2426, 2295, 2296, 2297, - 2298, 2299, 2425, 1468, 3524, 2892, 3223, 3449, 1736, 1464, - 1465, 109, 1466, 1467, 2320, 2594, 2594, 2323, 2324, 2117, - 1736, 2501, 4049, 2474, 1841, 1840, 2618, 1465, 2515, 1466, - 1467, 1465, 1136, 1466, 1467, 1784, 1783, 1465, 3524, 1466, - 1467, 4021, 1879, 2846, 2459, 2455, 2448, 2450, 2451, 2477, - 2473, 2870, 3477, 2341, 1468, 2509, 3527, 1752, 2512, 3258, - 2513, 2485, 1465, 3166, 1466, 1467, 3447, 1736, 1468, 2412, - 2869, 165, 2752, 2655, 2529, 2654, 2508, 2507, 177, 2459, - 2511, 3575, 1464, 2515, 2498, 1468, 2533, 2381, 2530, 1740, - 2534, 2535, 2135, 2124, 2125, 2126, 2127, 2137, 2128, 2129, - 2130, 2142, 2138, 2131, 2132, 2139, 2140, 2141, 2133, 2134, - 2136, 2342, 1465, 1468, 1466, 1467, 2117, 1135, 1468, 185, - 2055, 1465, 1468, 1466, 1467, 2039, 2627, 1468, 2870, 1985, - 2599, 1737, 1739, 1468, 1771, 3576, 3577, 3578, 1468, 1034, - 1034, 1034, 3443, 1736, 1035, 1118, 1465, 2540, 1466, 1467, - 1117, 95, 4127, 4068, 3907, 3334, 3440, 1736, 1743, 1521, - 3873, 1521, 166, 171, 168, 174, 175, 176, 178, 180, - 181, 182, 183, 3438, 1736, 3733, 3591, 2614, 184, 186, - 187, 188, 3588, 3569, 3390, 3389, 2571, 1914, 1843, 2457, - 2318, 3330, 3285, 3281, 2960, 2454, 2620, 1465, 2449, 1466, - 1467, 2626, 1016, 1468, 2308, 3283, 2619, 1017, 2443, 2617, - 3915, 1465, 2442, 1466, 1467, 3436, 1736, 2113, 1968, 2317, - 4183, 3434, 1736, 1874, 95, 2385, 3432, 1736, 1465, 1870, - 1466, 1467, 1839, 2389, 121, 2392, 2926, 1208, 2058, 3908, - 2586, 1915, 1916, 1917, 2472, 2875, 2878, 2879, 2880, 2876, - 1468, 2877, 2881, 2592, 3538, 3539, 1465, 2355, 1466, 1467, - 4181, 1465, 4155, 1466, 1467, 1465, 4029, 1466, 1467, 2600, - 1465, 1468, 1466, 1467, 3948, 3541, 1465, 1468, 1466, 1467, - 3544, 1465, 2606, 1466, 1467, 3277, 2603, 2604, 2605, 2035, - 3579, 3430, 1736, 3276, 2084, 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, 1012, 1013, 1014, 1015, 1910, 3428, 1736, - 3580, 3581, 3582, 2607, 2630, 2609, 1465, 2925, 1466, 1467, - 3275, 3193, 2939, 2036, 2612, 2572, 2613, 3215, 1468, 3426, - 1736, 673, 3216, 3213, 3543, 3424, 1736, 3212, 3214, 3217, - 1468, 2879, 2880, 3211, 1468, 4025, 2608, 2796, 1468, 3698, - 3909, 3697, 2372, 2615, 1748, 1468, 1048, 1911, 1912, 1913, - 2361, 1468, 3532, 1465, 2784, 1466, 1467, 1468, 2926, 2666, - 3171, 3170, 1468, 3987, 3183, 3185, 3711, 2580, 2581, 2828, - 3713, 1468, 2583, 3186, 1465, 3520, 1466, 1467, 1468, 3180, - 1465, 2584, 1466, 1467, 3517, 2114, 1051, 2112, 1034, 1984, - 2831, 3696, 3516, 1468, 1052, 734, 2058, 1049, 2875, 2878, - 2879, 2880, 2876, 2550, 2877, 2881, 3422, 1736, 3538, 3539, - 1018, 2867, 2868, 2569, 2570, 2829, 3254, 2574, 3420, 1736, - 2399, 1468, 3546, 1034, 2887, 2909, 3418, 1736, 2930, 2579, - 2160, 2564, 2563, 3416, 1736, 2832, 2582, 2834, 2562, 3414, - 1736, 2561, 1468, 2560, 1174, 3412, 1736, 2161, 2559, 1173, - 3410, 1736, 1468, 2080, 2078, 2079, 2083, 2866, 2847, 3396, - 1736, 1465, 2585, 1466, 1467, 3350, 3372, 1736, 2637, 2925, - 1468, 3008, 2966, 1465, 1432, 1466, 1467, 1465, 129, 1466, - 1467, 1465, 1736, 1466, 1467, 2652, 42, 1468, 1465, 1708, - 1466, 1467, 2819, 1468, 1465, 2884, 1466, 1467, 2886, 1060, - 1465, 1468, 1466, 1467, 2885, 1465, 2856, 1466, 1467, 2817, - 1736, 2839, 3522, 1059, 1465, 101, 1466, 1467, 1468, 2912, - 2914, 1465, 1702, 1466, 1467, 102, 1468, 103, 2905, 2859, - 2815, 1736, 4197, 1468, 110, 2844, 1465, 2964, 1466, 1467, - 2790, 1736, 4104, 2889, 101, 109, 1468, 108, 3273, 2575, - 103, 3500, 2893, 1468, 102, 103, 2598, 2896, 2767, 1736, - 1468, 4006, 2464, 2903, 1465, 3903, 1466, 1467, 2906, 2383, - 2384, 3253, 2975, 2883, 2367, 2759, 1736, 108, 3169, 2917, - 3972, 2750, 1736, 109, 2155, 1465, 3168, 1466, 1467, 2156, - 4162, 3971, 110, 1468, 3951, 1465, 2927, 1466, 1467, 3719, - 3717, 3716, 3709, 109, 1468, 108, 2748, 1736, 3589, 2940, - 2941, 2942, 2936, 1465, 3493, 1466, 1467, 2935, 3521, 3519, - 2928, 2735, 1736, 1468, 3286, 2931, 2932, 2218, 2972, 1468, - 1465, 1862, 1466, 1467, 2733, 1736, 1465, 2499, 1466, 1467, - 1857, 2731, 1736, 110, 1465, 1058, 1466, 1467, 2729, 1736, - 2961, 2962, 1468, 3510, 109, 2971, 1468, 3708, 3018, 3019, - 2862, 1465, 3682, 1466, 1467, 4185, 4184, 3, 2843, 1465, - 1468, 1466, 1467, 3072, 1468, 2656, 1465, 2353, 1466, 1467, - 1765, 2727, 1736, 1468, 1757, 4184, 2997, 4185, 1468, 1465, - 3993, 1466, 1467, 4005, 3016, 3555, 1465, 3035, 1466, 1467, - 1468, 114, 115, 1465, 97, 1466, 1467, 2301, 1, 1026, - 3000, 2725, 1736, 2052, 1435, 1468, 10, 2723, 1736, 1434, - 3559, 4116, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, - 3061, 3062, 2050, 1468, 689, 9, 1465, 2333, 1466, 1467, - 3036, 3880, 3070, 2051, 2721, 1736, 8, 1465, 2343, 1466, - 1467, 1706, 4156, 4112, 4113, 1737, 2340, 2973, 2719, 1736, - 1954, 1944, 2717, 1736, 3621, 2269, 1465, 3904, 1466, 1467, - 3289, 3489, 1465, 2505, 1466, 1467, 2715, 1736, 1468, 3587, - 2462, 1126, 154, 2421, 2422, 4081, 118, 1084, 2713, 1736, - 3074, 2365, 1468, 1730, 117, 1465, 1129, 1466, 1467, 1465, - 1237, 1466, 1467, 2711, 1736, 2500, 3130, 1734, 3006, 3611, - 1731, 3007, 2910, 1465, 2430, 1466, 1467, 1465, 1790, 1466, - 1467, 2709, 1736, 1788, 1789, 1787, 1465, 1792, 1466, 1467, - 3020, 1465, 2888, 1466, 1467, 2359, 2360, 1733, 3037, 1732, - 3137, 1791, 4053, 1465, 3358, 1466, 1467, 3148, 2657, 3456, - 2043, 2951, 724, 2882, 718, 3139, 192, 1779, 1465, 3017, - 1466, 1467, 1758, 1168, 2399, 679, 2707, 1736, 3262, 3063, - 2306, 2538, 2306, 3110, 685, 2304, 1465, 2304, 1466, 1467, - 2705, 1736, 1518, 2034, 3167, 2897, 3200, 1078, 87, 1070, - 2354, 2399, 2399, 2399, 2399, 2399, 2833, 2476, 1077, 3120, - 3121, 3122, 3123, 3124, 3881, 3201, 2937, 3514, 3179, 3181, - 3148, 2399, 2849, 3184, 2399, 3177, 3986, 3205, 3138, 3710, - 3140, 1465, 4066, 1466, 1467, 2907, 1995, 1468, 1754, 3476, - 3222, 1468, 3038, 3147, 2629, 1465, 2150, 1466, 1467, 2401, - 1508, 2398, 3159, 1468, 3677, 2070, 747, 746, 3175, 744, - 3160, 3162, 3164, 2835, 1468, 2863, 3174, 3172, 1468, 1472, - 1471, 955, 1468, 1037, 2823, 1766, 2401, 2401, 2401, 2401, - 2401, 2874, 2986, 2987, 2988, 2989, 2990, 2991, 3306, 3165, - 3187, 3188, 2872, 1039, 3206, 2871, 2401, 3209, 3314, 2401, - 1038, 2573, 2406, 3218, 104, 3224, 3540, 3536, 3225, 2058, - 3001, 105, 3226, 3207, 3208, 1468, 3210, 4108, 2400, 2396, - 3232, 2842, 906, 3173, 1468, 2703, 1736, 3265, 1468, 3204, - 3593, 905, 3009, 756, 1468, 3263, 3264, 748, 738, 968, - 904, 2701, 1736, 1468, 903, 3316, 3317, 2981, 3331, 2983, - 2908, 3327, 2696, 1736, 1449, 1725, 2692, 1736, 1468, 1728, - 2690, 1736, 3190, 2362, 3318, 3315, 3319, 1097, 1468, 2464, - 3308, 3355, 4012, 2597, 3112, 3287, 3114, 3384, 1724, 3325, - 1465, 4019, 1466, 1467, 1465, 3297, 1466, 1467, 3605, 3278, - 3266, 3267, 3125, 3126, 3127, 3128, 1465, 3346, 1466, 1467, - 3196, 2957, 3345, 3455, 3343, 3196, 2492, 1465, 3353, 1466, - 1467, 1465, 3451, 1466, 1467, 1465, 3387, 1466, 1467, 69, - 1730, 46, 2683, 1736, 3981, 4050, 3363, 898, 895, 3679, - 3680, 2681, 1736, 3681, 1734, 3133, 3134, 1731, 3379, 3380, - 3381, 3382, 3383, 3360, 3361, 4032, 3362, 2921, 4033, 3364, - 894, 3366, 4034, 3368, 2207, 1445, 3386, 1442, 1465, 4129, - 1466, 1467, 1726, 1727, 1733, 2045, 1732, 1465, 96, 1466, - 1467, 1465, 1521, 1466, 1467, 36, 1521, 1465, 35, 1466, - 1467, 2616, 34, 33, 32, 2621, 1465, 26, 1466, 1467, - 25, 3288, 3501, 24, 3503, 3471, 23, 22, 29, 19, - 21, 1465, 3475, 1466, 1467, 20, 18, 3300, 2624, 4151, - 2625, 1465, 4196, 1466, 1467, 123, 2633, 55, 52, 50, - 2635, 2636, 131, 130, 53, 49, 1211, 47, 31, 2642, - 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 30, - 2653, 17, 16, 15, 14, 3199, 13, 12, 11, 7, - 6, 39, 38, 37, 2399, 28, 27, 40, 3506, 4, - 2944, 2494, 0, 2659, 2660, 2661, 2662, 3553, 2664, 2665, - 3511, 2667, 3518, 3354, 3502, 2669, 3504, 0, 0, 2674, - 2675, 0, 2676, 0, 1468, 2679, 2680, 2682, 2684, 2685, - 2686, 2687, 2688, 2689, 2691, 2693, 2694, 2695, 2697, 0, - 2699, 2700, 2702, 2704, 2706, 2708, 2710, 2712, 2714, 2716, - 2718, 2720, 2722, 2724, 2726, 2728, 2730, 2732, 2734, 2736, - 2737, 2738, 3309, 2740, 3545, 2742, 3547, 2744, 2745, 2401, - 2747, 2749, 2751, 3318, 3315, 3319, 2754, 3554, 3548, 736, - 2758, 3542, 3523, 0, 2763, 2764, 2765, 2766, 1468, 0, - 3570, 0, 3572, 1468, 0, 3508, 0, 2777, 2778, 2779, - 2780, 2781, 2782, 0, 0, 2786, 2787, 3478, 0, 3480, - 3481, 3482, 3378, 2789, 0, 1468, 0, 3274, 2795, 3348, - 3349, 0, 0, 2798, 2799, 2800, 2801, 2802, 3535, 0, - 0, 0, 0, 0, 2809, 2810, 1468, 2811, 0, 0, - 2814, 2816, 2365, 3312, 2818, 0, 0, 3549, 3550, 3615, - 3616, 3564, 3565, 0, 2830, 0, 0, 3326, 0, 1468, - 0, 0, 0, 1468, 0, 0, 0, 1465, 1468, 1466, - 1467, 3617, 0, 0, 1468, 0, 3376, 3344, 1468, 0, - 3347, 2813, 0, 0, 0, 0, 0, 0, 1057, 0, - 0, 1063, 1063, 0, 0, 0, 3633, 0, 0, 0, - 0, 0, 0, 2812, 3598, 0, 1468, 0, 3602, 3603, - 3604, 1468, 0, 0, 0, 0, 0, 0, 0, 1468, - 0, 3644, 0, 0, 2808, 0, 0, 1468, 0, 0, - 0, 1465, 0, 1466, 1467, 0, 1465, 0, 1466, 1467, - 0, 0, 0, 0, 0, 0, 0, 2807, 1468, 0, - 0, 2806, 0, 1468, 0, 0, 2805, 0, 1465, 1703, - 1466, 1467, 2804, 0, 0, 0, 2803, 1468, 0, 0, - 3695, 1468, 0, 3702, 3685, 3704, 3686, 3687, 3688, 1465, - 0, 1466, 1467, 0, 0, 3675, 1468, 0, 0, 0, - 1468, 0, 0, 0, 2794, 0, 0, 3705, 3200, 2793, - 0, 87, 1465, 3200, 1466, 1467, 1465, 2792, 1466, 1467, - 0, 1465, 0, 1466, 1467, 2791, 0, 1465, 0, 1466, - 1467, 1465, 0, 1466, 1467, 3638, 0, 0, 2114, 0, - 2112, 0, 0, 3735, 3706, 1468, 2788, 0, 0, 3715, - 3714, 2783, 0, 3725, 0, 3507, 1468, 3727, 3722, 1465, - 3724, 1466, 1467, 0, 1465, 2776, 1466, 1467, 0, 2775, - 0, 0, 1465, 0, 1466, 1467, 0, 0, 3887, 0, - 1465, 0, 1466, 1467, 2774, 0, 42, 3739, 2773, 0, - 0, 0, 0, 0, 0, 0, 0, 3594, 3595, 0, - 0, 1465, 0, 1466, 1467, 0, 1465, 0, 1466, 1467, - 0, 0, 0, 0, 0, 0, 0, 0, 3879, 3878, - 1465, 0, 1466, 1467, 1465, 0, 1466, 1467, 0, 3894, - 3906, 0, 0, 2772, 3899, 0, 3898, 0, 3877, 1465, - 3568, 1466, 1467, 1465, 2771, 1466, 1467, 0, 0, 0, - 3048, 3049, 3050, 3051, 3052, 3945, 0, 3946, 3729, 0, - 3583, 0, 0, 3584, 3585, 3586, 2114, 0, 2112, 0, - 3067, 3949, 3703, 0, 0, 0, 0, 0, 0, 0, - 3736, 3737, 0, 0, 0, 0, 0, 0, 1465, 0, - 1466, 1467, 0, 0, 0, 0, 0, 0, 0, 1465, - 0, 1466, 1467, 0, 0, 3952, 3994, 3200, 0, 3955, - 3196, 0, 3731, 0, 3889, 3890, 3891, 0, 0, 0, - 3666, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, - 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, - 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, 1638, 1639, - 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, - 1650, 1651, 1652, 1653, 1659, 1660, 1661, 1662, 1676, 1677, - 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, - 1688, 1689, 3995, 3979, 3950, 3978, 0, 3199, 0, 1468, - 0, 0, 3199, 1468, 3969, 0, 4013, 1468, 0, 0, - 0, 3975, 1468, 3977, 0, 0, 1468, 0, 0, 0, - 3202, 0, 3998, 0, 87, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3997, 1468, 0, 3220, 0, - 0, 1468, 0, 3882, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4002, 4015, 0, 0, 0, 4018, 0, - 0, 0, 0, 0, 0, 0, 1468, 3886, 0, 0, - 4020, 0, 1468, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2770, 0, 0, - 0, 2769, 0, 0, 0, 2768, 0, 0, 0, 42, - 2762, 0, 0, 0, 2761, 4038, 0, 0, 4039, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3985, 0, - 0, 0, 4063, 0, 2760, 0, 0, 87, 0, 2757, - 0, 4048, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4057, 1465, 0, 1466, 1467, 1465, 0, 1466, 1467, - 1465, 0, 1466, 1467, 2756, 1465, 4069, 1466, 1467, 1465, - 2755, 1466, 1467, 0, 4080, 0, 3352, 1469, 4072, 0, - 4077, 3906, 4083, 4067, 4074, 4073, 4071, 4076, 4075, 1465, - 0, 1466, 1467, 0, 1465, 3999, 1466, 1467, 3369, 3370, - 0, 3371, 3373, 3375, 4102, 0, 3199, 0, 1527, 0, - 0, 0, 42, 0, 4107, 4125, 4115, 4120, 0, 1465, - 0, 1466, 1467, 4094, 0, 1465, 0, 1466, 1467, 3388, - 4135, 0, 4133, 0, 3391, 4146, 3393, 3394, 3395, 3397, - 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, - 3408, 3409, 3411, 3413, 3415, 3417, 3419, 3421, 3423, 3425, - 3427, 3429, 3431, 3433, 3435, 3437, 3439, 3441, 3442, 3444, - 3445, 3446, 3448, 1995, 4150, 3450, 4145, 3452, 3453, 3454, - 4094, 4176, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, - 3466, 3467, 3468, 2114, 4182, 2112, 4180, 4169, 4179, 4178, - 4175, 3474, 4165, 4064, 4166, 3479, 1703, 4190, 1468, 3483, - 3484, 4059, 3485, 3487, 1468, 3490, 3492, 0, 3494, 3495, - 3496, 3497, 4204, 4206, 4198, 1468, 0, 0, 3505, 3196, - 0, 1468, 0, 0, 0, 4004, 1468, 0, 0, 0, - 1468, 0, 0, 0, 0, 4214, 1468, 0, 0, 4215, - 4216, 2114, 3946, 2112, 1468, 0, 4213, 4094, 0, 1468, - 0, 0, 4027, 3529, 3530, 4011, 0, 3534, 0, 4023, - 4037, 0, 0, 0, 1468, 0, 0, 0, 0, 1468, - 0, 0, 0, 0, 1468, 0, 0, 0, 0, 0, - 0, 0, 1468, 0, 0, 0, 2753, 0, 0, 1468, - 0, 0, 2746, 0, 0, 0, 4149, 0, 0, 0, - 0, 0, 0, 2743, 0, 1807, 0, 0, 0, 2741, - 0, 4141, 0, 0, 2739, 0, 0, 0, 2698, 0, - 0, 0, 1703, 0, 2678, 0, 0, 0, 0, 0, - 0, 0, 2677, 0, 0, 0, 4024, 2673, 0, 0, - 0, 1465, 0, 1466, 1467, 0, 4058, 1465, 0, 1466, - 1467, 0, 2671, 0, 0, 0, 0, 2663, 1465, 0, - 1466, 1467, 2634, 3609, 1465, 0, 1466, 1467, 0, 1465, - 2628, 1466, 1467, 1465, 0, 1466, 1467, 2623, 0, 1465, - 0, 1466, 1467, 0, 0, 0, 0, 1465, 1756, 1466, - 1467, 0, 1465, 0, 1466, 1467, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1465, 3628, 1466, - 1467, 3632, 1465, 0, 1466, 1467, 0, 1465, 0, 1466, - 1467, 0, 0, 0, 0, 1465, 1844, 1466, 1467, 0, - 0, 0, 1465, 0, 1466, 1467, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3645, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1795, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4163, - 0, 951, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3668, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3676, 0, 0, 0, 0, 0, 0, 3683, - 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, - 195, 1808, 0, 0, 722, 0, 0, 0, 0, 728, - 0, 0, 0, 0, 2000, 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, 728, 195, 728, 1821, 1824, 1825, 1826, 1827, 1828, - 1829, 0, 1830, 1831, 1833, 1834, 1832, 1835, 1836, 1809, - 1810, 1811, 1812, 1793, 1794, 1822, 0, 1796, 0, 1797, - 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 0, 0, - 1806, 1813, 1814, 1815, 1816, 0, 1817, 1818, 1819, 1820, - 0, 0, 0, 0, 0, 0, 0, 0, 3895, 0, - 0, 0, 0, 0, 0, 0, 0, 3902, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3912, 3913, 3914, - 0, 3916, 0, 3917, 3918, 0, 0, 0, 0, 3921, - 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, - 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, - 3942, 0, 3944, 3947, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3956, 3957, - 3958, 3959, 3960, 3962, 3963, 3965, 3967, 3968, 3970, 0, - 0, 0, 3974, 0, 0, 0, 3976, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4003, 0, 0, 2065, 2066, 2067, 2068, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2081, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2120, 2121, 0, 0, 0, - 0, 2144, 0, 0, 2148, 2149, 1823, 0, 0, 2154, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2166, 2167, 2168, 2169, 2170, 2171, - 2172, 2173, 2174, 2175, 0, 2177, 0, 0, 0, 2199, - 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2208, 0, 2213, - 0, 2215, 2216, 2217, 0, 2219, 2220, 2221, 0, 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, 2272, 2273, 2274, 2275, 2276, - 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, - 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 0, 0, - 0, 0, 0, 2300, 0, 2302, 0, 2309, 2310, 2311, - 2312, 2313, 2314, 0, 0, 0, 0, 0, 4028, 0, - 0, 0, 0, 0, 0, 0, 2325, 2326, 2327, 2328, - 2329, 2330, 2331, 2332, 0, 2334, 2335, 2336, 2337, 2338, - 0, 0, 4043, 0, 0, 0, 0, 0, 4046, 0, - 4047, 0, 0, 86, 44, 45, 88, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 190, 0, 92, 4062, 0, 1063, 48, 76, 77, 0, - 74, 78, 0, 0, 1807, 0, 0, 0, 0, 0, - 0, 0, 75, 129, 0, 151, 0, 0, 0, 4088, - 4089, 0, 2379, 2380, 0, 0, 0, 0, 0, 172, - 0, 0, 0, 4096, 4098, 4100, 0, 0, 0, 0, - 0, 62, 0, 0, 0, 0, 0, 0, 2418, 0, - 0, 4106, 0, 95, 0, 0, 0, 0, 0, 0, - 162, 0, 0, 4128, 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, - 195, 0, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 4147, 83, 0, 0, 0, 0, 0, 0, 2460, - 138, 139, 161, 160, 189, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 728, - 0, 728, 728, 0, 0, 4170, 4172, 4174, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 728, 195, 0, 0, 0, 1795, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4195, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1513, 0, 0, 0, 0, 0, 4207, 4208, 0, 0, - 0, 0, 0, 0, 0, 0, 51, 54, 57, 56, - 59, 0, 73, 0, 0, 82, 79, 0, 0, 0, - 0, 0, 0, 0, 0, 155, 136, 158, 143, 135, - 0, 156, 157, 0, 0, 0, 0, 0, 173, 61, - 91, 90, 0, 0, 71, 72, 58, 179, 144, 0, - 1808, 0, 80, 81, 0, 0, 0, 0, 0, 0, + 972, 3694, 967, 87, 3695, 4210, 3693, 4024, 960, 4114, + 2439, 4223, 3357, 3493, 2143, 4006, 3929, 4102, 3306, 3643, + 4177, 959, 2131, 3257, 3264, 4178, 2367, 4133, 1281, 3315, + 3218, 4004, 3320, 925, 3317, 3316, 42, 3314, 3319, 3318, + 2069, 3071, 3630, 5, 3156, 2369, 3335, 1283, 2514, 2010, + 3272, 3334, 751, 3219, 3533, 3539, 3222, 3045, 3736, 3070, + 2872, 2394, 745, 921, 3216, 779, 3206, 3523, 920, 2477, + 746, 1858, 1801, 3337, 2946, 3364, 2947, 3027, 1757, 2978, + 4075, 2482, 2502, 2948, 1092, 2427, 1040, 2545, 87, 163, + 1060, 1037, 2897, 1905, 2413, 41, 43, 2415, 2878, 2864, + 1067, 2410, 2848, 2291, 2323, 2127, 2077, 1040, 2414, 3019, + 2523, 2290, 2165, 149, 2501, 3561, 1887, 2402, 2562, 1039, + 2484, 1043, 1102, 2939, 1790, 1125, 1138, 1120, 2914, 2417, + 1718, 1770, 1537, 104, 105, 100, 2171, 2102, 2091, 1462, + 1062, 1447, 2006, 1894, 1099, 1096, 3221, 1131, 2499, 761, + 1986, 1100, 2473, 2474, 1128, 1126, 1127, 2395, 2885, 1789, + 1077, 1775, 756, 1079, 1049, 1740, 749, 3731, 2198, 748, + 2846, 99, 1520, 1046, 2179, 2068, 85, 1271, 107, 2018, + 3494, 132, 127, 1044, 1045, 3723, 1496, 1211, 1059, 133, + 167, 125, 126, 1879, 1035, 1072, 1279, 106, 84, 1047, + 738, 755, 93, 1541, 98, 4211, 3550, 3631, 3303, 1546, + 1257, 4059, 922, 1071, 2516, 2517, 2518, 2516, 2969, 681, + 3001, 3000, 2560, 3623, 1034, 4160, 3035, 3036, 4055, 2364, + 2365, 2084, 2083, 4054, 2082, 1052, 2081, 4060, 2080, 2079, + 3586, 2049, 1227, 128, 1167, 1093, 4154, 134, 2, 678, + 2844, 679, 2613, 3202, 2549, 4181, 3160, 1479, 2874, 1761, + 1759, 3698, 4216, 1142, 4233, 4176, 4201, 3497, 3496, 2391, + 1971, 4164, 1053, 739, 1087, 2390, 2994, 1162, 1458, 1086, + 4162, 4007, 1036, 3325, 1038, 1175, 1117, 4215, 3325, 1762, + 1760, 1141, 95, 111, 112, 113, 4163, 116, 2548, 2809, + 122, 3322, 3698, 191, 2089, 4161, 673, 1116, 3383, 1061, + 1168, 1171, 1172, 4129, 2388, 128, 1115, 1114, 736, 737, + 3925, 1104, 4033, 2971, 1751, 1184, 3924, 1166, 1028, 1029, + 1030, 1031, 723, 95, 4055, 1042, 95, 1165, 3636, 1228, + 95, 3637, 1109, 3323, 4191, 3935, 4158, 717, 3323, 1033, + 3655, 723, 1449, 3644, 4103, 4111, 2105, 3697, 2542, 926, + 3934, 2136, 4138, 1074, 1075, 3409, 1868, 3254, 3255, 3008, + 2845, 3009, 3329, 190, 2434, 2435, 2433, 3329, 2991, 3253, + 717, 2061, 2062, 128, 975, 976, 977, 2923, 3034, 1118, + 2922, 2617, 1791, 2924, 1792, 3018, 129, 1276, 3697, 975, + 976, 977, 1247, 1252, 1253, 1476, 86, 1477, 1478, 1235, + 1026, 2620, 172, 1025, 1236, 1235, 2972, 4025, 2935, 1248, + 1236, 1241, 1234, 712, 1233, 86, 1085, 1089, 924, 1164, + 717, 2014, 1085, 1089, 924, 3361, 1113, 4115, 1220, 1221, + 2452, 2451, 1181, 1182, 1183, 3359, 1186, 1187, 1188, 1189, + 2881, 2882, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, + 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 86, + 1223, 697, 169, 2398, 717, 170, 3750, 3654, 717, 3391, + 717, 2618, 1475, 1463, 695, 3389, 3326, 1459, 1442, 95, + 2611, 3326, 2888, 717, 1111, 3092, 2547, 2060, 731, 2064, + 735, 189, 2366, 3365, 729, 3020, 1722, 717, 95, 4182, + 1275, 1254, 2979, 4119, 2524, 1448, 1274, 1249, 3352, 1242, + 2889, 1255, 4213, 3977, 692, 3978, 3353, 1787, 4119, 3004, + 4183, 3362, 4038, 707, 1210, 1185, 4143, 86, 1463, 2563, + 88, 3360, 1987, 1961, 1268, 1264, 1441, 1266, 702, 2587, + 2398, 2588, 95, 2589, 1250, 1251, 4141, 2493, 1273, 705, + 1256, 718, 715, 1216, 2569, 3625, 4147, 4148, 2527, 3022, + 716, 1497, 2015, 3624, 2567, 3274, 3275, 2614, 2565, 2615, + 1140, 2487, 4142, 2590, 1140, 1263, 1265, 1962, 3909, 1963, + 3621, 1473, 1191, 3380, 718, 1498, 1499, 1500, 1501, 1502, + 1503, 1504, 1506, 1505, 1507, 1508, 2576, 2572, 2574, 2575, + 2573, 2577, 2578, 2579, 1190, 173, 2566, 1121, 2207, 2570, + 95, 1122, 3702, 2411, 179, 1122, 1112, 1160, 1725, 2568, + 682, 1151, 684, 698, 1159, 720, 1158, 719, 688, 1157, + 686, 690, 699, 691, 718, 685, 1473, 696, 4155, 1156, + 687, 700, 701, 704, 708, 709, 710, 706, 703, 1155, + 694, 721, 1078, 3093, 1154, 1153, 1148, 1872, 2396, 2397, + 3159, 1161, 3276, 4234, 1097, 1170, 1511, 1511, 3536, 1134, + 4188, 1133, 1097, 1139, 3273, 1169, 1095, 1139, 718, 2007, + 1133, 1097, 718, 2500, 718, 1261, 3276, 1073, 3023, 1262, + 2553, 2552, 2003, 1469, 1450, 3620, 1461, 718, 1178, 1267, + 3296, 1866, 1280, 3003, 1280, 1280, 1865, 2199, 1864, 2989, + 2973, 718, 2201, 3006, 3187, 2004, 2206, 2202, 3185, 1862, + 2203, 2204, 2205, 2486, 1260, 2200, 2208, 2209, 2210, 2211, + 2212, 2213, 2214, 2215, 2216, 2396, 2397, 1226, 672, 1512, + 1513, 4156, 164, 1088, 1082, 1080, 4020, 1788, 1469, 1088, + 1082, 1080, 3039, 2635, 1040, 1521, 1526, 1527, 3575, 1530, + 1532, 1533, 1534, 1535, 1536, 3557, 1539, 1540, 1542, 1542, + 1152, 1542, 1542, 1547, 1547, 1547, 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, 1670, 1671, 1672, 1673, + 1439, 1440, 1269, 1518, 1674, 973, 1676, 1677, 1678, 1679, + 1680, 4032, 2970, 1119, 1514, 1515, 1516, 1517, 1547, 1547, + 1547, 1547, 1547, 1547, 1528, 3696, 722, 3584, 3585, 1531, + 1457, 3481, 1232, 1687, 1688, 1689, 1690, 1691, 1692, 1693, + 1694, 1695, 1696, 1697, 1698, 1699, 1700, 713, 1438, 973, + 3327, 3328, 2937, 973, 4117, 3327, 3328, 1973, 1972, 1974, + 1975, 1976, 714, 3331, 1715, 2546, 3696, 1522, 3331, 4117, + 2619, 4078, 1543, 1214, 1544, 1545, 3537, 2993, 3653, 94, + 2919, 165, 4227, 1548, 1549, 1219, 4116, 1149, 177, 1468, + 1465, 1466, 1467, 1472, 1474, 1471, 1712, 1470, 94, 1893, + 89, 4116, 2618, 3381, 3026, 1108, 1222, 1464, 1110, 2849, + 2851, 1140, 1231, 3168, 1237, 1238, 1239, 1240, 1721, 3017, + 1081, 2992, 3016, 2884, 1245, 2544, 1081, 1040, 2821, 185, + 2139, 1040, 1750, 1779, 1675, 1225, 3167, 1040, 1277, 1278, + 1140, 2440, 94, 2879, 1468, 1465, 1466, 1467, 1472, 1474, + 1471, 1177, 1470, 124, 680, 1511, 2490, 1508, 1713, 4146, + 1729, 3252, 1464, 1258, 1733, 1991, 1992, 1140, 2646, 1751, + 1039, 1491, 166, 171, 168, 174, 175, 176, 178, 180, + 181, 182, 183, 1140, 1056, 1272, 4046, 1163, 184, 186, + 187, 188, 3616, 3549, 2564, 3260, 1230, 2491, 2019, 2073, + 2000, 2180, 1793, 4145, 2489, 3066, 119, 1113, 1892, 1105, + 94, 3046, 2172, 2172, 1139, 2655, 1107, 1106, 2181, 2962, + 1731, 1732, 4192, 3745, 104, 105, 1713, 1681, 1682, 1683, + 1684, 1685, 1686, 1478, 1113, 1209, 1150, 3591, 2492, 1477, + 1478, 3590, 2531, 1139, 1902, 1719, 3261, 2107, 2488, 1133, + 1136, 1137, 2646, 1097, 1901, 1891, 2541, 1130, 1134, 1706, + 2539, 2108, 1509, 1510, 2106, 1111, 2536, 1151, 1149, 107, + 1139, 3263, 3029, 1140, 3029, 1143, 1133, 3028, 1129, 3028, + 1145, 4184, 2850, 120, 1146, 1144, 1139, 2095, 2096, 2625, + 2626, 3258, 1133, 1136, 1137, 3048, 1097, 1140, 4235, 1213, + 1130, 1134, 3576, 1885, 1051, 1147, 1753, 4229, 4079, 2540, + 3274, 3275, 1981, 4225, 1727, 1716, 4226, 3259, 4224, 1988, + 1259, 1989, 1479, 1730, 1990, 4012, 1036, 1979, 1878, 1728, + 1956, 2543, 1907, 1479, 1908, 1038, 1910, 1912, 1756, 1244, + 1916, 1918, 1920, 1922, 1924, 1897, 1215, 1938, 3917, 1229, + 1246, 3265, 3916, 1895, 1895, 2020, 2178, 4080, 1280, 2536, + 1784, 1785, 3650, 2012, 3651, 1968, 1853, 3907, 3058, 3057, + 3056, 1896, 3667, 3050, 4013, 3054, 1139, 3049, 1176, 3047, + 1734, 1861, 1173, 1980, 3052, 1996, 3666, 1994, 1995, 1993, + 1997, 1998, 1999, 3051, 4236, 1876, 1751, 1112, 1978, 3598, + 1139, 1888, 2538, 1874, 2177, 1143, 1133, 1875, 1212, 3597, + 1145, 3587, 3053, 3055, 1146, 1144, 975, 976, 977, 3273, + 2095, 2096, 2093, 2094, 1112, 3939, 1942, 2328, 3304, 3292, + 2944, 3276, 1497, 2943, 3356, 1493, 1967, 1494, 1503, 1504, + 1506, 1505, 1507, 1508, 1899, 2942, 2092, 2496, 1867, 1982, + 1966, 1495, 1509, 1510, 1492, 2008, 1498, 1499, 1500, 1501, + 1502, 1503, 1504, 1506, 1505, 1507, 1508, 1965, 1964, 1954, + 1476, 1934, 1477, 1478, 1937, 1497, 1939, 3038, 1948, 3068, + 1945, 1476, 2163, 1477, 1478, 1869, 1870, 1871, 1116, 1944, + 1497, 1943, 1914, 1726, 1444, 723, 128, 1115, 1114, 1498, + 1499, 1500, 1501, 1502, 1503, 1504, 1506, 1505, 1507, 1508, + 1479, 1787, 2696, 2025, 1498, 1499, 1500, 1501, 1502, 1503, + 1504, 1506, 1505, 1507, 1508, 1479, 4185, 4041, 1280, 1280, + 3581, 2926, 723, 723, 2021, 2022, 2047, 190, 1497, 2692, + 2634, 2512, 4040, 2511, 87, 2870, 4212, 87, 2026, 4172, + 1751, 3262, 1946, 1947, 2046, 2033, 2034, 2035, 1952, 1953, + 129, 4016, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1506, + 1505, 1507, 1508, 2510, 1764, 2509, 172, 42, 1479, 4015, + 42, 2155, 2144, 2145, 2146, 2147, 2157, 2148, 2149, 2150, + 2162, 2158, 2151, 2152, 2159, 2160, 2161, 2153, 2154, 2156, + 2870, 1751, 4197, 1751, 1751, 2134, 2134, 1498, 1499, 1500, + 1501, 1502, 1503, 1504, 1506, 1505, 1507, 1508, 1751, 1475, + 1751, 1479, 2928, 1765, 2132, 2132, 2135, 1501, 1502, 1503, + 1504, 1506, 1505, 1507, 1508, 2508, 169, 2507, 4014, 170, + 2870, 4110, 4034, 2097, 1485, 1486, 1487, 1488, 1489, 1490, + 1484, 1481, 2166, 2870, 4089, 1479, 1712, 3912, 1476, 3896, + 1477, 1478, 101, 3895, 1497, 189, 3744, 101, 103, 3742, + 3570, 2023, 102, 1476, 2218, 1477, 1478, 102, 2027, 3663, + 2029, 2030, 2031, 2032, 1479, 2870, 4085, 2036, 1498, 1499, + 1500, 1501, 1502, 1503, 1504, 1506, 1505, 1507, 1508, 2048, + 1499, 1500, 1501, 1502, 1503, 1504, 1506, 1505, 1507, 1508, + 1479, 3997, 1751, 4195, 1751, 1479, 1711, 85, 1713, 1479, + 85, 1710, 2074, 1709, 2054, 2055, 1476, 741, 1477, 1478, + 2694, 3595, 2104, 1751, 2682, 3580, 1479, 2167, 1751, 3944, + 1475, 1751, 3634, 4031, 3920, 1751, 3943, 4125, 1751, 2870, + 3908, 3900, 2111, 1479, 2110, 3366, 2112, 2113, 2114, 2115, + 2116, 2117, 2119, 2121, 2122, 2123, 2124, 2125, 2126, 1476, + 2109, 1477, 1478, 3634, 1751, 1479, 4123, 1751, 3899, 173, + 1479, 2870, 3632, 3642, 2138, 2328, 1479, 3363, 179, 2325, + 1479, 3295, 2242, 3266, 2336, 3294, 1479, 3270, 2327, 2536, + 1751, 2403, 2404, 1476, 3269, 1477, 1478, 4121, 1751, 3555, + 1751, 3990, 1751, 2338, 971, 2337, 2182, 2183, 2184, 2185, + 2326, 2324, 2776, 1751, 1522, 2953, 110, 2217, 3988, 1751, + 2196, 2940, 1476, 1708, 1477, 1478, 1701, 109, 3271, 108, + 2608, 2234, 2173, 3267, 2600, 3985, 1751, 103, 3268, 3285, + 3284, 3282, 3283, 3280, 3281, 3280, 3279, 1479, 1476, 2599, + 1477, 1478, 2558, 1476, 2557, 1477, 1478, 1476, 1479, 1477, + 1478, 2393, 3967, 1751, 103, 2419, 2372, 2335, 3522, 1751, + 2341, 2342, 3515, 1751, 1476, 1479, 1477, 1478, 3512, 1751, + 2894, 1751, 2980, 104, 105, 2618, 3002, 2958, 2336, 1479, + 110, 1476, 2449, 1477, 1478, 1479, 1768, 2050, 2421, 2016, + 1479, 109, 1751, 108, 104, 105, 164, 2338, 2867, 2408, + 1977, 1479, 1969, 1476, 2371, 1477, 1478, 2383, 1476, 1479, + 1477, 1478, 103, 1479, 1476, 1959, 1477, 1478, 1476, 1751, + 1477, 1478, 2103, 1955, 1476, 1951, 1477, 1478, 1102, 3510, + 1751, 1857, 2983, 2976, 2977, 2870, 2869, 1479, 2137, 1751, + 3473, 1751, 3552, 2915, 2458, 2459, 2460, 2461, 2453, 1950, + 2454, 2455, 2456, 2457, 2444, 2359, 1949, 1767, 2443, 1052, + 1766, 1102, 2425, 1479, 2463, 1270, 1751, 2465, 2466, 2467, + 2468, 3471, 1751, 1857, 1856, 2384, 2865, 3467, 1751, 1799, + 1798, 2893, 3464, 1751, 2448, 1476, 3548, 1477, 1478, 2377, + 2386, 2378, 2479, 3462, 1751, 2447, 1476, 2915, 1477, 1478, + 2886, 3460, 1751, 2525, 1479, 3458, 1751, 2886, 2406, 2485, + 3551, 2916, 3217, 1476, 1087, 1477, 1478, 2430, 2431, 1086, + 2429, 2918, 3247, 3548, 1479, 2446, 2445, 1476, 1479, 1477, + 1478, 2537, 2618, 1476, 1479, 1477, 1478, 1475, 1476, 2522, + 1477, 1478, 2894, 4073, 1479, 4045, 2495, 2870, 1479, 1476, + 109, 1477, 1478, 1479, 2894, 3456, 1751, 1476, 1479, 1477, + 1478, 1476, 3501, 1477, 1478, 2916, 3282, 3190, 2432, 2480, + 2469, 2471, 2472, 2476, 1479, 2618, 2776, 2894, 2530, 2494, + 1142, 2533, 2498, 2534, 3548, 1476, 2506, 1477, 1478, 2679, + 1895, 2678, 2550, 2536, 2519, 2536, 3454, 1751, 2401, 1755, + 2362, 2137, 2075, 2059, 2480, 2529, 2528, 2532, 1141, 2002, + 1786, 1476, 1479, 1477, 1478, 1124, 3452, 1751, 2554, 2551, + 3450, 1751, 2555, 2556, 1475, 1123, 3448, 1751, 1479, 95, + 1041, 4151, 4092, 3931, 3398, 165, 3446, 1751, 1758, 4049, + 3444, 1751, 177, 3897, 3358, 3442, 1751, 1479, 3757, 3307, + 3440, 1751, 1476, 3599, 1477, 1478, 1479, 1752, 1754, 3615, + 2623, 2561, 1479, 3612, 3593, 2949, 3438, 1751, 3414, 1040, + 1040, 1040, 1476, 1479, 1477, 1478, 1476, 1479, 1477, 1478, + 3413, 1479, 1476, 185, 1477, 1478, 1859, 2478, 1479, 1532, + 3354, 1532, 1476, 3309, 1477, 1478, 1476, 3305, 1477, 1478, + 1479, 1476, 2984, 1477, 1478, 1751, 1476, 2638, 1477, 1478, + 3600, 3601, 3602, 95, 3932, 2475, 1479, 2593, 2470, 2950, + 3436, 1751, 1476, 1479, 1477, 1478, 166, 171, 168, 174, + 175, 176, 178, 180, 181, 182, 183, 2464, 2641, 3434, + 1751, 1479, 184, 186, 187, 188, 2462, 4207, 3420, 1751, + 1479, 1984, 1890, 2493, 3396, 1751, 1886, 2338, 1855, 2337, + 1476, 1479, 1477, 1478, 2950, 2841, 1751, 121, 1479, 2839, + 1751, 2610, 1214, 2814, 1751, 2375, 1476, 1479, 1477, 1478, + 2791, 1751, 3562, 3563, 4205, 2616, 4179, 1479, 2052, 4053, + 3972, 3565, 2783, 1751, 3301, 1476, 3300, 1477, 1478, 3299, + 3217, 2624, 1479, 2963, 1476, 2594, 1477, 1478, 2774, 1751, + 1476, 1479, 1477, 1478, 2630, 2772, 1751, 3568, 2627, 2628, + 2629, 1476, 1479, 1477, 1478, 1476, 2104, 1477, 1478, 1476, + 3603, 1477, 1478, 2759, 1751, 3239, 1476, 3567, 1477, 1478, + 3240, 3237, 2757, 1751, 3236, 2632, 3238, 2631, 1476, 2633, + 1477, 1478, 3235, 2755, 1751, 2053, 3933, 2392, 2636, 1763, + 2637, 1751, 1479, 3556, 1476, 1930, 1477, 1478, 1479, 2753, + 1751, 1476, 3195, 1477, 1478, 1054, 2381, 2654, 3194, 2751, + 1751, 4011, 1479, 3604, 3605, 3606, 3735, 1479, 1926, 1476, + 677, 1477, 1478, 3737, 2749, 1751, 1479, 3544, 1476, 3204, + 1477, 1478, 2001, 2747, 1751, 1479, 1024, 2820, 3278, 1476, + 1479, 1477, 1478, 3541, 2745, 1751, 1476, 2933, 1477, 1478, + 2639, 3540, 1931, 1932, 1933, 1476, 1055, 1477, 1478, 2954, + 2690, 2602, 2603, 2808, 2586, 1476, 2605, 1477, 1478, 2852, + 2180, 1927, 1928, 1929, 2585, 2606, 2134, 1479, 1057, 3722, + 1476, 3721, 1477, 1478, 2743, 1751, 1058, 2181, 1040, 1476, + 3517, 1477, 1478, 1066, 740, 2132, 2855, 3207, 3209, 2584, + 1476, 2583, 1477, 1478, 2741, 1751, 3210, 1065, 2582, 2739, + 1751, 2891, 2892, 2100, 2098, 2099, 2853, 2581, 2737, 1751, + 2419, 2580, 1180, 1040, 2911, 1179, 3374, 2735, 1751, 1479, + 2949, 101, 2733, 1751, 3720, 101, 2856, 103, 2858, 1443, + 1476, 102, 1477, 1478, 42, 102, 1476, 1479, 1477, 1478, + 3032, 2890, 1479, 2908, 2990, 2871, 2910, 1479, 129, 3546, + 1476, 1479, 1477, 1478, 103, 1476, 2103, 1477, 1478, 2731, + 1751, 2403, 2404, 1497, 1476, 1479, 1477, 1478, 3241, 1479, + 2903, 2904, 4128, 1476, 4221, 1477, 1478, 3297, 1476, 1479, + 1477, 1478, 1719, 2843, 1479, 2597, 2880, 1498, 1499, 1500, + 1501, 1502, 1503, 1504, 1506, 1505, 1507, 1508, 2651, 1479, + 4030, 3927, 3277, 3524, 2909, 1713, 2936, 2938, 2863, 2907, + 1479, 2729, 1751, 2387, 1479, 1476, 3193, 1477, 1478, 1479, + 2622, 2913, 2929, 2883, 3192, 1714, 1479, 2868, 2988, 2727, + 1751, 1479, 108, 2058, 2725, 1751, 3996, 2057, 1479, 2720, + 1751, 110, 3995, 2716, 1751, 2917, 3975, 2920, 3743, 3741, + 2642, 1479, 109, 110, 108, 2999, 2485, 2714, 1751, 2927, + 2930, 2707, 1751, 1479, 109, 109, 108, 1476, 3740, 1477, + 1478, 2705, 1751, 3733, 103, 2175, 2650, 3613, 2941, 1479, + 2176, 2644, 3534, 1479, 3545, 1476, 3543, 1477, 1478, 3310, + 1476, 2643, 1477, 1478, 2951, 1476, 2520, 1477, 1478, 1476, + 1479, 1477, 1478, 4186, 1873, 2959, 3513, 2960, 2964, 2965, + 2966, 110, 4029, 1476, 1479, 1477, 1478, 1476, 2238, 1477, + 1478, 2996, 109, 1878, 3904, 1064, 3732, 1476, 2886, 1477, + 1478, 3617, 1476, 3706, 1477, 1478, 4209, 4208, 2985, 2986, + 2867, 3042, 3043, 3479, 3096, 1479, 2680, 1476, 2373, 1477, + 1478, 2995, 1780, 1479, 1772, 3475, 114, 115, 1476, 4208, + 1477, 1478, 1476, 4209, 1477, 1478, 1479, 1476, 2163, 1477, + 1478, 3411, 4017, 3579, 1476, 3410, 1477, 1478, 3, 1476, + 2072, 1477, 1478, 10, 3021, 97, 1476, 1, 1477, 1478, + 3024, 3059, 3402, 1032, 2070, 3040, 1479, 9, 2321, 1476, + 2071, 1477, 1478, 8, 1446, 1479, 3400, 1445, 3583, 4140, + 693, 1476, 2363, 1477, 1478, 1717, 3077, 3078, 3079, 3080, + 3081, 3082, 3083, 3084, 3085, 3086, 1479, 1476, 2353, 1477, + 1478, 1476, 4180, 1477, 1478, 4136, 3094, 4137, 2945, 1970, + 3060, 1960, 3645, 2289, 3928, 2837, 1752, 2360, 1476, 3313, + 1477, 1478, 2526, 3611, 2952, 2997, 2483, 1132, 2836, 2955, + 2956, 154, 1476, 2441, 1477, 1478, 2442, 2155, 2144, 2145, + 2146, 2147, 2157, 2148, 2149, 2150, 2162, 2158, 2151, 2152, + 2159, 2160, 2161, 2153, 2154, 2156, 2385, 4105, 2832, 118, + 3098, 1090, 3041, 1476, 117, 1477, 1478, 2831, 3044, 1135, + 3154, 1476, 3030, 1477, 1478, 3031, 3061, 1243, 2521, 3635, + 1479, 2934, 2450, 1805, 1476, 1803, 1477, 1478, 2830, 1804, + 2899, 2902, 2903, 2904, 2900, 2975, 2901, 2905, 1802, 1807, + 3562, 3563, 2899, 2902, 2903, 2904, 2900, 1806, 2901, 2905, + 3172, 4077, 3382, 3161, 1476, 2681, 1477, 1478, 3163, 3480, + 1479, 2063, 730, 1476, 2906, 1477, 1478, 724, 2419, 1479, + 192, 3087, 1794, 1773, 2056, 2326, 2324, 2326, 2324, 1174, + 3134, 683, 3286, 2559, 1476, 689, 1477, 1478, 1479, 1529, + 3224, 2051, 87, 1479, 3191, 2419, 2419, 2419, 2419, 2419, + 2921, 2421, 1084, 2497, 3144, 3145, 3146, 3147, 3148, 1076, + 2374, 2857, 2829, 3172, 1083, 2419, 3905, 3162, 2419, 3164, + 3225, 1479, 3538, 3203, 3229, 1043, 3205, 2873, 2421, 2421, + 2421, 2421, 2421, 3171, 1479, 3208, 3201, 4010, 1479, 3246, + 3734, 4090, 1479, 2931, 1769, 3500, 3189, 2653, 2421, 2170, + 3183, 2421, 2828, 1519, 2418, 3701, 2090, 1479, 753, 752, + 750, 2827, 3199, 3196, 1479, 2859, 3198, 2012, 1476, 2887, + 1477, 1478, 1483, 1482, 3211, 3212, 3184, 3186, 3188, 961, + 2818, 2847, 3330, 1781, 2898, 2817, 3228, 1044, 1045, 1479, + 2896, 2895, 3338, 3231, 3232, 1479, 3234, 2595, 3242, 104, + 105, 2426, 1479, 3230, 3250, 3564, 3233, 1479, 1476, 3248, + 1477, 1478, 3249, 2816, 3560, 4132, 2420, 1476, 3256, 1477, + 1478, 1479, 2416, 3197, 2866, 3289, 2815, 912, 911, 762, + 2812, 3288, 754, 3287, 2807, 744, 1476, 974, 1477, 1478, + 910, 1476, 909, 1477, 1478, 3340, 1479, 3341, 3005, 2800, + 3355, 3007, 1479, 2932, 3351, 3342, 2799, 3339, 1460, 1736, + 3343, 3311, 1739, 2382, 1479, 3332, 2485, 1103, 3379, 1476, + 4036, 1477, 1478, 2621, 3214, 3349, 3408, 1735, 4043, 3321, + 3629, 2798, 1476, 3302, 1477, 1478, 1476, 2797, 1477, 1478, + 1476, 2981, 1477, 1478, 2796, 1714, 2513, 3367, 69, 2795, + 3370, 3220, 3369, 46, 4005, 1476, 3220, 1477, 1478, 3377, + 4074, 904, 1476, 2794, 1477, 1478, 901, 3703, 3384, 3385, + 3387, 3386, 3704, 3705, 3388, 3157, 3390, 3158, 3392, 4056, + 4057, 900, 3403, 3404, 3405, 3406, 3407, 1476, 2793, 1477, + 1478, 4058, 2232, 1476, 2792, 1477, 1478, 2227, 1456, 1453, + 1476, 4153, 1477, 1478, 2065, 1476, 2786, 1477, 1478, 96, + 36, 35, 34, 33, 32, 26, 1532, 25, 24, 1476, + 1532, 1477, 1478, 23, 22, 29, 19, 21, 20, 18, + 3324, 2640, 4175, 4220, 123, 2645, 3525, 55, 3527, 52, + 50, 131, 3312, 130, 1476, 53, 1477, 1478, 3495, 49, + 1476, 1217, 1477, 1478, 47, 3499, 3378, 31, 2648, 30, + 2649, 17, 1476, 16, 1477, 1478, 2657, 15, 14, 13, + 2659, 2660, 2315, 2316, 2317, 2318, 2319, 3290, 3291, 2666, + 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2340, + 2677, 12, 2343, 2344, 11, 7, 6, 39, 2419, 3223, + 38, 37, 28, 3530, 3526, 27, 3528, 40, 4, 2968, + 2515, 3577, 3535, 2683, 2684, 2685, 2686, 0, 2688, 2689, + 0, 2691, 3542, 0, 0, 2693, 1479, 0, 2361, 2698, + 2699, 2421, 2700, 3547, 1479, 2703, 2704, 2706, 2708, 2709, + 2710, 2711, 2712, 2713, 2715, 2717, 2718, 2719, 2721, 3333, + 2723, 2724, 2726, 2728, 2730, 2732, 2734, 2736, 2738, 2740, + 2742, 2744, 2746, 2748, 2750, 2752, 2754, 2756, 2758, 2760, + 2761, 2762, 3569, 2764, 3342, 2766, 3339, 2768, 2769, 3343, + 2771, 2773, 2775, 742, 3578, 3502, 2778, 3504, 3505, 3506, + 2782, 3594, 3572, 3596, 2787, 2788, 2789, 2790, 3571, 3566, + 0, 0, 1479, 3639, 3640, 3532, 1479, 2801, 2802, 2803, + 2804, 2805, 2806, 1479, 0, 2810, 2811, 0, 2785, 0, + 3372, 3373, 0, 2813, 0, 1479, 2784, 0, 2819, 0, + 1720, 0, 1479, 2822, 2823, 2824, 2825, 2826, 3559, 0, + 1479, 0, 0, 0, 2833, 2834, 1479, 2835, 0, 0, + 2838, 2840, 2385, 1479, 2842, 0, 0, 3573, 3574, 0, + 0, 0, 0, 1479, 2854, 0, 0, 1479, 0, 0, + 0, 0, 0, 0, 1476, 0, 1477, 1478, 0, 3641, + 1479, 0, 1476, 0, 1477, 1478, 0, 0, 0, 675, + 0, 0, 1063, 0, 2781, 1069, 1069, 3657, 2780, 0, + 0, 0, 0, 0, 0, 2779, 0, 0, 0, 1027, + 0, 0, 0, 0, 0, 0, 1479, 2777, 0, 0, + 1479, 0, 0, 0, 2770, 3668, 0, 0, 1479, 0, + 0, 0, 2767, 1479, 0, 0, 0, 1479, 2765, 0, + 0, 1479, 0, 0, 0, 2763, 0, 0, 0, 0, + 1476, 1098, 1477, 1478, 1476, 2722, 1477, 1478, 0, 2702, + 0, 1476, 0, 1477, 1478, 0, 0, 3709, 0, 3710, + 3711, 3712, 2701, 1476, 3719, 1477, 1478, 3726, 0, 3728, + 1476, 0, 1477, 1478, 0, 0, 0, 0, 1476, 3699, + 1477, 1478, 0, 0, 1476, 0, 1477, 1478, 3588, 3589, + 0, 1476, 3224, 1477, 1478, 87, 3729, 3224, 2697, 0, + 0, 1476, 2695, 1477, 1478, 1476, 0, 1477, 1478, 0, + 2687, 0, 0, 2134, 0, 2658, 0, 0, 1476, 2652, + 1477, 1478, 0, 2647, 0, 0, 0, 3730, 42, 0, + 0, 0, 2132, 3759, 3739, 3751, 3738, 3662, 3749, 0, + 0, 3622, 3746, 0, 0, 3626, 3627, 3628, 3748, 0, + 0, 0, 0, 0, 1476, 0, 1477, 1478, 1476, 0, + 1477, 1478, 3911, 0, 3618, 3619, 1476, 0, 1477, 1478, + 0, 1476, 3763, 1477, 1478, 1476, 0, 1477, 1478, 1476, + 0, 1477, 1478, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3903, 0, 3902, 0, 0, 0, 0, 0, + 0, 0, 0, 3930, 3918, 0, 0, 0, 0, 0, + 0, 3923, 0, 3922, 0, 0, 3901, 0, 0, 0, + 0, 0, 0, 0, 0, 3969, 0, 0, 3970, 0, + 0, 2134, 0, 3753, 3072, 3073, 3074, 3075, 3076, 0, + 0, 0, 0, 3727, 0, 0, 0, 0, 0, 0, + 2132, 3973, 0, 0, 3091, 0, 0, 0, 0, 0, + 3760, 3761, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2661, 0, 0, 0, 0, 0, 3976, 0, + 4018, 3224, 3979, 0, 3755, 0, 0, 0, 0, 2676, + 0, 3220, 0, 0, 0, 1550, 1551, 1552, 1553, 1554, + 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, + 1565, 1566, 1567, 1568, 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, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, + 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1670, 1671, + 1672, 1673, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, + 1695, 1696, 1697, 1698, 1699, 1700, 3974, 4019, 4003, 0, + 4002, 3913, 3914, 3915, 1741, 3993, 0, 0, 0, 0, + 4037, 3223, 3999, 0, 4001, 0, 3223, 0, 1749, 0, + 0, 1742, 0, 0, 0, 0, 0, 0, 87, 0, + 3906, 0, 0, 0, 3226, 0, 0, 0, 0, 0, + 1741, 0, 0, 0, 4022, 0, 2379, 2380, 1748, 1746, + 1747, 1743, 3244, 1744, 1749, 4026, 0, 1742, 0, 4039, + 4021, 42, 0, 4042, 0, 0, 0, 0, 4044, 0, + 0, 0, 0, 0, 0, 0, 1745, 0, 0, 0, + 0, 3910, 1737, 1738, 1748, 1746, 1747, 1743, 0, 1744, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1745, 0, 0, 0, 0, 0, 4062, 0, + 0, 4063, 0, 0, 0, 0, 4087, 0, 0, 0, + 0, 87, 0, 0, 0, 4072, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4081, 0, + 0, 0, 4093, 1218, 0, 1224, 0, 0, 0, 0, + 0, 0, 4104, 0, 42, 0, 0, 4118, 0, 0, + 0, 4091, 4023, 4096, 3930, 4107, 4101, 1480, 4098, 4097, + 3376, 4095, 4100, 4099, 0, 0, 0, 0, 0, 4126, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3393, 3394, 0, 3395, 3397, 3399, 1538, 4149, + 3223, 0, 0, 4131, 4139, 4144, 0, 1452, 0, 0, + 0, 0, 0, 4157, 4118, 4159, 0, 0, 0, 4170, + 0, 0, 0, 3412, 0, 0, 0, 0, 3415, 0, + 3417, 3418, 3419, 3421, 3422, 3423, 3424, 3425, 3426, 3427, + 3428, 3429, 3430, 3431, 3432, 3433, 3435, 3437, 3439, 3441, + 3443, 3445, 3447, 3449, 3451, 3453, 3455, 3457, 3459, 3461, + 3463, 3465, 3466, 3468, 3469, 3470, 3472, 4190, 2134, 3474, + 4193, 3476, 3477, 3478, 4199, 4202, 3482, 3483, 3484, 3485, + 3486, 3487, 3488, 3489, 3490, 3491, 3492, 2132, 4203, 4206, + 4200, 4118, 4214, 4204, 2012, 3498, 4189, 4174, 4169, 3503, + 3062, 4222, 4028, 3507, 3508, 4088, 3509, 3511, 4230, 3514, + 3516, 4228, 3518, 3519, 3520, 3521, 4083, 0, 0, 0, + 3220, 0, 3529, 0, 0, 0, 2134, 0, 0, 4239, + 4240, 0, 0, 3970, 4238, 0, 4047, 0, 0, 0, + 0, 0, 4173, 0, 0, 2132, 4237, 0, 0, 0, + 0, 1823, 0, 0, 0, 0, 0, 3553, 3554, 4035, + 0, 3558, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4165, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4082, 0, 0, 0, 0, 0, 0, + 0, 0, 3136, 0, 3138, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3149, 3150, 3151, 3152, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3633, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1771, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1810, 0, 0, + 0, 0, 3652, 0, 0, 3656, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1860, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1783, 0, 0, 0, 0, 0, 3669, + 0, 0, 0, 0, 0, 0, 4187, 0, 0, 0, + 0, 0, 1800, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1824, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3692, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3700, 0, 0, 0, + 0, 0, 0, 3707, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1940, 0, 0, 0, 0, + 0, 0, 0, 0, 2017, 0, 1837, 1840, 1841, 1842, + 1843, 1844, 1845, 0, 1846, 1847, 1849, 1850, 1848, 1851, + 1852, 1825, 1826, 1827, 1828, 1808, 1809, 1838, 0, 1811, + 1985, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, + 0, 0, 1821, 1829, 1830, 1831, 1832, 2013, 1833, 1834, + 1835, 1836, 0, 0, 1822, 0, 0, 0, 0, 0, + 0, 0, 0, 2024, 0, 0, 0, 0, 0, 0, + 2028, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3919, 0, 0, 0, 0, 0, 0, 0, + 0, 3926, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3936, 3937, 3938, 0, 3940, 0, 3941, 3942, 0, + 0, 0, 0, 3945, 3946, 3947, 3948, 3949, 3950, 3951, + 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, + 3962, 3963, 3964, 3965, 3966, 0, 3968, 3971, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3980, 3981, 3982, 3983, 3984, 3986, 3987, 3989, + 3991, 3992, 3994, 0, 0, 0, 3998, 0, 0, 0, + 4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1714, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4027, 0, 0, 0, 2085, + 2086, 2087, 2088, 0, 0, 0, 0, 0, 0, 1839, + 0, 0, 0, 0, 0, 2101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2078, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2140, 2141, 0, 0, 0, 0, 2164, 0, 0, 2168, + 2169, 0, 0, 0, 2174, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2186, + 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 0, + 2197, 0, 0, 0, 2219, 2220, 2221, 2222, 2223, 2224, + 2225, 2226, 2228, 0, 2233, 0, 2235, 2236, 2237, 0, + 2239, 2240, 2241, 0, 2243, 2244, 2245, 2246, 2247, 2248, + 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, + 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, + 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, + 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, + 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, + 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, + 2312, 2313, 2314, 0, 0, 0, 0, 0, 2320, 0, + 2322, 0, 2329, 2330, 2331, 2332, 2333, 2334, 0, 0, + 0, 0, 4052, 0, 0, 0, 0, 0, 0, 0, + 0, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 0, + 2354, 2355, 2356, 2357, 2358, 0, 4067, 0, 3690, 0, + 0, 0, 4070, 0, 4071, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4086, 0, 0, + 1069, 0, 0, 0, 0, 0, 0, 0, 0, 129, + 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4112, 4113, 172, 0, 0, 0, 0, + 0, 2399, 2400, 0, 0, 0, 0, 4120, 4122, 4124, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4130, 0, 2438, 0, 162, + 0, 0, 0, 0, 0, 150, 0, 4152, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, + 44, 45, 88, 2405, 0, 169, 957, 0, 170, 0, + 0, 2409, 0, 2412, 0, 0, 2078, 0, 92, 0, + 0, 0, 48, 76, 77, 4171, 74, 78, 0, 0, + 138, 139, 161, 160, 189, 0, 0, 0, 75, 2481, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4194, + 4196, 4198, 195, 0, 0, 195, 0, 0, 0, 728, + 62, 0, 0, 0, 734, 0, 0, 0, 0, 0, + 0, 0, 95, 0, 0, 195, 0, 0, 0, 0, + 0, 0, 4219, 0, 0, 0, 0, 0, 0, 1823, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 4231, 4232, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 734, 195, 734, 0, + 0, 0, 83, 0, 0, 155, 136, 158, 143, 135, + 0, 156, 157, 0, 0, 0, 4009, 0, 173, 0, + 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2078, 0, 0, 0, 0, + 0, 0, 2571, 0, 0, 0, 51, 54, 57, 56, + 59, 0, 73, 2591, 2592, 82, 79, 2596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2601, + 0, 0, 0, 0, 0, 1810, 2604, 0, 0, 61, + 91, 90, 0, 0, 71, 72, 58, 0, 0, 0, + 0, 0, 80, 81, 0, 0, 0, 0, 0, 0, + 0, 0, 2607, 0, 0, 164, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1821, 1824, 1825, 1826, 1827, 1828, 1829, - 0, 1830, 1831, 1833, 1834, 1832, 1835, 1836, 1809, 1810, - 1811, 1812, 1793, 1794, 1822, 0, 1796, 0, 1797, 1798, - 1799, 1800, 1801, 1802, 1803, 1804, 1805, 0, 0, 1806, - 1813, 1814, 1815, 1816, 0, 1817, 1818, 1819, 1820, 60, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1513, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2632, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2638, 2639, 2640, 2641, 0, 0, 0, 89, - 0, 195, 0, 0, 0, 728, 728, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 159, 0, - 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1527, 0, 0, - 0, 0, 0, 0, 0, 728, 0, 0, 195, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 728, 0, 0, 0, 0, 0, 0, 195, 0, 0, - 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 728, 0, 728, 0, 0, 94, - 0, 0, 0, 0, 728, 1823, 0, 1513, 728, 0, - 0, 728, 728, 728, 728, 0, 728, 152, 728, 728, - 153, 728, 728, 728, 728, 728, 728, 0, 0, 0, - 0, 0, 0, 0, 1513, 728, 728, 1513, 728, 1513, - 195, 728, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 165, 0, 0, 0, 0, 0, 0, 177, 0, - 195, 0, 0, 0, 0, 0, 0, 0, 0, 1016, - 0, 0, 0, 728, 1017, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 2113, 0, 728, 0, 0, 728, - 0, 195, 195, 0, 0, 0, 0, 0, 0, 185, - 0, 1756, 0, 0, 0, 0, 70, 0, 195, 0, - 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 728, 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, 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, - 1012, 1013, 1014, 1015, 0, 0, 0, 0, 0, 0, + 67, 68, 0, 0, 1714, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2656, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2662, 2663, 2664, 2665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4051, 159, 60, 0, 0, 0, 0, 0, 4061, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1837, 1840, 1841, 1842, 1843, 1844, + 1845, 1538, 1846, 1847, 1849, 1850, 1848, 1851, 1852, 1825, + 1826, 1827, 1828, 1808, 1809, 1838, 0, 1811, 0, 1812, + 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 0, 0, + 1821, 1829, 1830, 1831, 1832, 0, 1833, 1834, 1835, 1836, + 1714, 0, 1822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 89, 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, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 728, 728, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 728, 0, 0, 0, 0, 0, 3013, - 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, 3039, 3040, 3041, 0, - 0, 3043, 0, 0, 3045, 0, 0, 0, 0, 0, + 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 94, 0, 0, 1771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 728, 0, 3064, 3065, 3066, 0, 0, 0, - 0, 0, 1513, 3071, 0, 0, 0, 0, 3073, 0, - 0, 3075, 3076, 3077, 0, 0, 0, 3078, 3079, 0, - 1513, 3080, 0, 3081, 0, 0, 0, 0, 0, 0, - 3082, 0, 3083, 0, 0, 0, 3084, 0, 3085, 0, - 0, 3086, 0, 3087, 0, 3088, 0, 3089, 0, 3090, - 0, 3091, 0, 3092, 0, 3093, 0, 3094, 0, 3095, - 0, 3096, 0, 3097, 0, 3098, 0, 3099, 0, 3100, - 0, 3101, 0, 3102, 0, 3103, 0, 0, 0, 3104, - 0, 3105, 0, 3106, 0, 0, 3107, 0, 3108, 0, - 3109, 0, 2272, 3111, 0, 0, 3113, 0, 0, 3115, - 3116, 3117, 3118, 0, 0, 0, 0, 3119, 2272, 2272, - 2272, 2272, 2272, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3129, 0, 0, 0, 0, 0, 0, - 0, 3142, 0, 0, 3146, 0, 0, 0, 0, 0, - 0, 0, 0, 3149, 3150, 3151, 3152, 3153, 3154, 0, - 0, 0, 3155, 3156, 0, 3157, 2319, 3158, 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, 1063, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2912, 0, 1839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 195, 3191, 0, 0, 0, 728, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 70, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 734, 0, + 734, 734, 0, 0, 0, 0, 0, 0, 0, 0, + 2961, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 734, 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, + 0, 1524, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3010, 3011, 3012, 3013, + 3014, 3015, 0, 0, 0, 0, 0, 3037, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2078, 3025, 0, 0, 0, 0, + 0, 0, 0, 0, 3063, 3064, 3065, 0, 0, 3067, + 0, 0, 3069, 0, 0, 0, 0, 0, 0, 3033, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3088, 3089, 3090, 0, 0, 0, 0, 0, + 0, 3095, 0, 0, 0, 0, 3097, 0, 0, 3099, + 3100, 3101, 0, 0, 0, 3102, 3103, 0, 0, 3104, + 0, 3105, 0, 0, 0, 0, 0, 0, 3106, 0, + 3107, 0, 0, 0, 3108, 0, 3109, 0, 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, 3122, 0, 3123, 0, 3124, 0, 3125, + 0, 3126, 0, 3127, 0, 0, 0, 3128, 0, 3129, + 0, 3130, 0, 0, 3131, 0, 3132, 0, 3133, 0, + 2292, 3135, 0, 0, 3137, 0, 0, 3139, 3140, 3141, + 3142, 0, 0, 0, 1524, 3143, 2292, 2292, 2292, 2292, + 2292, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3153, 0, 0, 0, 0, 0, 0, 0, 3166, + 0, 0, 3170, 0, 0, 0, 0, 0, 0, 0, + 0, 3173, 3174, 3175, 3176, 3177, 3178, 0, 0, 0, + 3179, 3180, 0, 3181, 0, 3182, 0, 0, 0, 0, + 0, 0, 195, 0, 0, 0, 734, 734, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1069, + 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, 190, 0, 3221, 0, 0, - 0, 0, 195, 0, 0, 728, 2950, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 129, 195, - 151, 0, 0, 728, 0, 0, 2319, 195, 0, 195, - 0, 195, 195, 0, 172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 728, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3284, 0, - 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, - 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, + 3215, 0, 0, 0, 0, 0, 734, 0, 0, 195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 734, 0, 0, 0, 3245, 0, 0, 195, 0, + 0, 0, 734, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 734, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 734, 0, 734, 0, 0, + 0, 0, 0, 0, 0, 734, 0, 0, 1524, 734, + 0, 0, 734, 734, 734, 734, 3308, 734, 0, 734, + 734, 0, 734, 734, 734, 734, 734, 734, 0, 0, + 0, 0, 0, 0, 0, 1524, 734, 734, 1524, 734, + 1524, 195, 734, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3298, 0, 0, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 734, 0, 195, 0, 0, 0, + 3336, 0, 1022, 0, 0, 2328, 0, 734, 1023, 0, + 734, 0, 195, 195, 3350, 0, 0, 0, 2133, 0, + 0, 0, 0, 0, 0, 0, 0, 956, 0, 195, + 0, 0, 3401, 0, 3368, 0, 195, 3371, 0, 0, + 0, 0, 0, 0, 0, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 734, 0, 1022, 0, 0, 0, + 3416, 0, 1023, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2133, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 711, + 0, 0, 0, 0, 0, 733, 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, 1019, 1020, 1021, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 733, 0, 733, + 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, 1019, + 1020, 1021, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3531, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 734, 734, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 734, + 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, 3614, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3592, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 734, 0, + 0, 0, 3638, 0, 0, 0, 0, 3607, 1524, 0, + 3608, 3609, 3610, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1524, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3658, 0, 3659, 0, 3660, 0, 3661, 0, 0, 0, + 0, 0, 0, 0, 3664, 3665, 0, 0, 0, 0, + 0, 0, 0, 0, 3670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3671, 0, + 3672, 0, 3673, 0, 3674, 0, 3675, 0, 3676, 0, + 3677, 0, 3678, 0, 3679, 0, 3680, 0, 3681, 0, + 3682, 0, 3683, 0, 3684, 190, 3685, 0, 3686, 0, + 0, 3687, 0, 0, 0, 3688, 2974, 3689, 0, 0, + 0, 0, 0, 3691, 0, 0, 0, 0, 129, 0, + 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2339, 0, 172, 3708, 0, 0, 0, 0, + 0, 0, 0, 0, 3713, 0, 3714, 3715, 0, 3716, + 0, 3717, 0, 0, 0, 0, 3718, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, + 0, 0, 0, 0, 150, 0, 0, 195, 0, 0, + 0, 0, 734, 3747, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 0, 3756, 170, 0, 3758, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3762, 195, 0, 0, 734, 0, 0, 0, 1881, + 1882, 161, 160, 189, 0, 0, 0, 3898, 0, 195, + 0, 0, 0, 734, 0, 0, 2339, 195, 0, 195, + 0, 195, 195, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 734, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 0, 0, + 0, 734, 734, 734, 155, 1883, 158, 0, 1880, 0, + 156, 157, 0, 0, 0, 0, 0, 173, 0, 0, + 0, 734, 0, 0, 0, 0, 179, 734, 734, 0, + 0, 734, 0, 734, 0, 0, 0, 0, 0, 734, + 0, 0, 0, 0, 0, 0, 4008, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 0, 734, + 0, 0, 0, 734, 734, 0, 0, 0, 0, 733, + 1437, 733, 733, 0, 0, 190, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1877, 0, 0, 0, + 0, 0, 0, 733, 0, 0, 0, 0, 129, 0, + 151, 195, 0, 0, 0, 0, 0, 0, 195, 0, + 0, 0, 0, 0, 172, 0, 0, 0, 0, 195, + 195, 0, 1523, 195, 0, 195, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 195, 0, 0, 0, 0, + 0, 0, 195, 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, 195, 0, + 0, 0, 0, 0, 169, 195, 0, 170, 0, 0, + 734, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1881, + 1882, 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, 0, 913, 0, + 159, 0, 0, 4050, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1524, 0, 2339, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4048, 0, 0, 0, 0, 0, 4064, + 0, 0, 4065, 0, 4066, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 732, 0, 0, 0, + 0, 0, 0, 0, 155, 1883, 158, 0, 1880, 0, + 156, 157, 0, 0, 0, 0, 0, 173, 0, 0, + 0, 0, 0, 0, 0, 1523, 179, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, + 0, 0, 153, 0, 0, 0, 0, 0, 1094, 0, + 1101, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 0, 0, 0, 4150, 733, 733, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4166, 0, 4167, 0, 4168, + 0, 185, 0, 0, 0, 0, 0, 733, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 733, 164, 0, 0, 0, 0, 0, + 0, 0, 0, 733, 166, 171, 168, 174, 175, 176, + 178, 180, 181, 182, 183, 0, 0, 0, 0, 195, + 184, 186, 187, 188, 0, 0, 733, 195, 733, 4217, + 0, 4218, 0, 0, 0, 0, 733, 0, 734, 1523, + 733, 0, 0, 733, 733, 733, 733, 0, 733, 0, + 733, 733, 734, 733, 733, 733, 733, 733, 733, 0, + 0, 0, 0, 0, 0, 0, 1523, 733, 733, 1523, + 733, 1523, 0, 733, 0, 0, 195, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, + 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 734, 0, 0, 0, 0, 0, 195, 0, 0, 0, + 0, 0, 0, 195, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 734, 0, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 734, 734, + 0, 0, 0, 734, 0, 0, 0, 0, 0, 152, + 0, 0, 153, 0, 0, 0, 0, 0, 0, 1524, + 734, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 195, 195, 195, 195, 195, 195, 0, 0, + 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 195, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 95, 0, 0, 1022, 0, 0, 0, 0, 962, + 1023, 975, 976, 977, 963, 195, 0, 964, 965, 0, + 966, 185, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 971, 0, 978, 979, + 0, 734, 0, 0, 0, 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, 733, 733, 0, 0, 0, + 184, 186, 187, 188, 0, 0, 3344, 3345, 0, 0, + 733, 734, 0, 0, 0, 0, 0, 0, 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, 1019, 1020, 1021, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 733, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1523, + 0, 0, 0, 0, 0, 0, 0, 0, 2142, 0, + 0, 0, 0, 0, 0, 0, 0, 1523, 0, 0, + 0, 3346, 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, 728, 0, 0, 0, 0, 0, 0, - 728, 728, 728, 0, 0, 1865, 1866, 161, 160, 189, + 0, 0, 0, 0, 0, 0, 734, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 734, 0, + 1282, 0, 1282, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 728, 0, 0, 0, 0, 0, 728, 728, 0, 0, - 728, 0, 728, 0, 0, 0, 0, 0, 728, 950, - 0, 0, 0, 0, 3377, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1451, 0, 0, 0, 0, 734, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3347, 3348, 0, 195, 0, 0, 734, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3392, 728, 0, 0, 0, 0, 728, 0, - 0, 0, 728, 728, 0, 0, 0, 0, 0, 0, + 0, 734, 0, 0, 0, 1524, 0, 0, 734, 734, + 1524, 195, 195, 195, 195, 195, 0, 0, 0, 0, + 0, 0, 0, 195, 0, 0, 0, 0, 0, 195, + 0, 195, 0, 733, 195, 195, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 707, 0, 0, 0, 0, 0, 727, 190, 0, - 155, 1867, 158, 0, 1864, 0, 156, 157, 0, 1861, - 195, 0, 0, 173, 0, 0, 0, 195, 0, 0, - 0, 129, 179, 151, 0, 0, 0, 195, 195, 0, - 0, 195, 0, 195, 0, 0, 0, 172, 0, 0, - 0, 0, 0, 195, 0, 0, 0, 0, 0, 727, - 195, 727, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, - 0, 0, 0, 0, 150, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 728, 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, 0, 0, 1865, 1866, - 161, 160, 189, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 927, 0, 0, 0, + 0, 0, 931, 0, 0, 0, 928, 929, 0, 0, + 195, 930, 932, 733, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 734, 0, 0, 1524, 0, 0, 0, + 0, 734, 0, 0, 0, 0, 195, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, + 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 733, 0, 0, 733, 0, 0, + 195, 0, 0, 195, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1513, - 0, 2319, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3590, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 155, 1867, 158, 0, 1864, 0, 156, - 157, 0, 0, 0, 0, 0, 173, 0, 0, 0, - 0, 0, 0, 159, 0, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3634, 0, 3635, 0, 3636, 0, 3637, 0, - 0, 0, 0, 0, 0, 0, 3640, 3641, 0, 0, - 0, 0, 0, 0, 0, 0, 3646, 0, 0, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, + 0, 0, 733, 733, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3647, 0, 3648, 0, 3649, 0, 3650, 0, 3651, 0, - 3652, 0, 3653, 0, 3654, 0, 3655, 0, 3656, 0, - 3657, 0, 3658, 0, 3659, 0, 3660, 0, 3661, 0, - 3662, 0, 0, 3663, 0, 0, 0, 3664, 0, 3665, - 0, 0, 0, 0, 0, 3667, 0, 0, 0, 0, - 0, 0, 152, 0, 0, 153, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3684, 0, 0, - 164, 0, 0, 0, 0, 0, 3689, 0, 3690, 3691, - 0, 3692, 0, 3693, 195, 0, 165, 0, 3694, 0, - 0, 0, 195, 177, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 728, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3723, 0, 728, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3732, 0, - 0, 3734, 0, 0, 185, 0, 0, 0, 0, 0, - 0, 195, 0, 3738, 0, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3874, - 0, 0, 0, 0, 0, 0, 159, 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, 733, 0, 0, 0, 0, 0, 733, 733, + 0, 0, 733, 0, 733, 0, 0, 0, 1723, 1724, + 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 734, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 728, 0, 0, 0, 0, 0, - 195, 0, 0, 0, 0, 0, 0, 195, 0, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 1777, 0, + 733, 0, 0, 0, 733, 733, 0, 0, 195, 0, + 0, 0, 0, 1795, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1854, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 728, 0, 0, 0, 0, 0, 0, 728, 0, - 0, 0, 728, 728, 0, 0, 0, 728, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1094, 0, 1889, + 0, 0, 0, 0, 195, 0, 0, 1898, 0, 0, + 0, 1900, 0, 0, 1903, 1904, 1906, 1906, 0, 1906, + 0, 1906, 1906, 0, 1915, 1906, 1906, 1906, 1906, 1906, + 0, 0, 0, 195, 0, 0, 0, 0, 1935, 1936, + 0, 1094, 0, 0, 1941, 0, 0, 0, 0, 0, + 0, 0, 0, 195, 0, 0, 195, 195, 195, 0, + 0, 733, 0, 0, 0, 0, 734, 734, 0, 0, + 0, 914, 0, 0, 0, 0, 1983, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2005, + 0, 0, 2009, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1513, 728, 152, 0, 0, 153, 0, - 0, 0, 0, 0, 0, 0, 195, 195, 195, 195, - 195, 195, 0, 0, 0, 0, 0, 0, 3984, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, - 0, 0, 0, 195, 195, 0, 177, 0, 0, 0, + 0, 0, 0, 0, 0, 734, 734, 734, 734, 0, + 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, + 676, 0, 0, 0, 0, 1523, 1282, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 195, 727, 1428, 727, - 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 185, 0, 727, - 0, 0, 728, 0, 0, 0, 0, 0, 0, 0, + 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1050, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1512, 0, + 0, 0, 0, 1070, 1070, 0, 0, 0, 0, 0, + 0, 0, 676, 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, 728, 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, @@ -2400,342 +2563,316 @@ 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, 734, 0, 734, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4026, 0, 0, 0, 0, - 0, 907, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 728, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 728, + 0, 0, 0, 0, 0, 1524, 1282, 1282, 0, 195, + 0, 0, 734, 0, 734, 0, 0, 0, 0, 0, + 0, 2066, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4040, 0, 0, 4041, 0, 4042, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 728, 0, 0, 0, 0, 0, 0, 0, 0, 726, - 0, 0, 0, 0, 0, 195, 0, 0, 728, 0, - 0, 1512, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 728, 0, 0, 0, 1513, 0, 0, 728, - 728, 1513, 195, 195, 195, 195, 195, 0, 0, 0, - 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, - 195, 1088, 195, 1095, 0, 195, 195, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 727, 0, 0, 0, 4126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 734, 0, 0, 0, 0, 0, 0, 733, + 2128, 0, 0, 0, 0, 195, 0, 0, 734, 0, + 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, + 0, 734, 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, 4142, 0, 4143, - 0, 4144, 0, 727, 728, 0, 0, 1513, 0, 0, - 0, 0, 728, 0, 0, 0, 0, 195, 727, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 727, - 0, 195, 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 195, 0, 0, 195, 0, 0, 0, 0, 0, - 0, 0, 727, 0, 727, 0, 0, 0, 0, 0, - 0, 4193, 727, 4194, 0, 1512, 727, 0, 0, 727, - 727, 727, 727, 0, 727, 0, 727, 727, 0, 727, - 727, 727, 727, 727, 727, 0, 0, 0, 0, 0, - 0, 0, 1512, 727, 727, 1512, 727, 1512, 0, 727, + 0, 0, 0, 0, 0, 0, 0, 0, 2925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 727, 0, 0, 727, 0, 0, + 0, 0, 0, 0, 0, 0, 734, 0, 0, 0, + 0, 0, 0, 734, 0, 734, 0, 0, 0, 0, + 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 733, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 733, + 733, 0, 0, 0, 733, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1282, 0, 0, 0, 0, 0, + 1523, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 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, 2376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 733, 0, 0, 1777, 0, 0, 1282, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1094, 0, + 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 734, 195, + 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1101, 0, 0, 0, + 0, 0, 0, 2503, 2504, 2505, 0, 0, 0, 0, + 0, 0, 0, 0, 676, 0, 676, 0, 0, 0, + 0, 0, 0, 1094, 734, 0, 0, 0, 0, 1101, + 1898, 0, 0, 1898, 734, 1898, 0, 0, 0, 0, + 0, 2535, 0, 0, 1524, 734, 0, 734, 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, 728, 728, 0, + 0, 0, 734, 2339, 0, 0, 1094, 733, 676, 0, + 0, 2128, 0, 0, 0, 2128, 2128, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1525, 0, 0, 0, + 0, 0, 0, 195, 734, 0, 0, 0, 0, 0, + 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 727, 727, + 0, 0, 733, 0, 734, 0, 1523, 0, 0, 733, + 733, 1523, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 734, 0, + 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 734, 0, 734, + 0, 0, 2612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 0, 0, 728, 728, 728, 728, - 0, 0, 0, 908, 0, 0, 0, 0, 0, 0, + 0, 0, 3293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 733, 0, 0, 1523, 0, 0, + 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 727, 0, 0, 0, 0, 0, 0, 0, 0, 193, - 1512, 0, 672, 0, 0, 0, 0, 0, 0, 2122, - 0, 0, 0, 0, 0, 0, 0, 0, 1512, 0, - 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1044, 0, + 0, 0, 0, 0, 3375, 0, 0, 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1064, 1064, 0, 0, 0, - 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1276, - 0, 1276, 1276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1440, 0, 728, 0, 728, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1513, 0, 0, 0, - 195, 0, 0, 728, 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 728, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 727, 0, 195, 0, 0, 728, + 1050, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 728, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, + 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 728, 0, 0, - 0, 0, 0, 0, 728, 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 0, 728, 0, 0, 727, 727, - 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 727, 0, - 0, 0, 0, 0, 727, 727, 0, 0, 727, 0, - 727, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1712, 1713, 0, 0, 0, + 1525, 0, 0, 1525, 0, 1525, 676, 0, 0, 0, + 2860, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3582, 2875, 0, 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 0, 0, 727, 0, 0, 0, - 727, 727, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1762, 0, 0, 0, 0, + 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2011, 676, 0, + 0, 0, 0, 0, 0, 0, 0, 733, 733, 0, + 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, + 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, + 2037, 2038, 676, 676, 676, 676, 676, 676, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1780, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1838, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1847, 0, 0, 0, 728, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 733, 733, 733, 733, + 0, 0, 2957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 195, 0, 0, 1088, 0, 1873, 0, 0, 0, - 0, 0, 0, 0, 1882, 0, 0, 0, 1884, 728, - 195, 1887, 1888, 1890, 1890, 0, 1890, 0, 1890, 1890, - 0, 1899, 1890, 1890, 1890, 1890, 1890, 0, 0, 0, - 0, 0, 0, 727, 0, 1919, 1920, 0, 1088, 0, - 0, 1925, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2389, + 0, 0, 0, 0, 0, 0, 2982, 0, 0, 0, + 1898, 1898, 0, 0, 0, 2987, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2998, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1967, 0, 728, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 728, 1988, 0, 0, 1992, - 0, 0, 0, 0, 0, 1513, 728, 0, 728, 0, - 0, 0, 0, 0, 0, 0, 0, 1512, 0, 727, - 0, 0, 672, 0, 672, 0, 0, 0, 0, 0, - 0, 0, 0, 728, 2319, 0, 0, 0, 0, 0, - 0, 0, 0, 1276, 0, 0, 0, 0, 0, 0, 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, 728, 0, 0, 0, 0, - 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1514, 0, 0, 728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 728, - 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 728, 0, - 728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 733, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1523, 0, 0, 0, + 0, 0, 0, 733, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 2128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1276, 1276, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2046, 0, 0, 0, 0, 95, 0, - 0, 1016, 0, 0, 0, 956, 1017, 969, 970, 971, - 957, 0, 0, 958, 959, 0, 960, 0, 0, 0, + 0, 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 965, 0, 972, 973, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, - 0, 0, 2108, 0, 0, 0, 0, 0, 0, 0, + 0, 1525, 0, 733, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3320, 3321, 0, 1514, 0, 0, 0, 0, - 2901, 0, 0, 0, 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, 1012, 1013, 1014, 1015, 0, 0, 0, 0, - 0, 0, 727, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1044, 0, 0, 727, - 0, 0, 0, 0, 0, 0, 727, 3322, 0, 0, - 727, 727, 0, 0, 0, 727, 0, 0, 0, 0, - 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1512, 727, 0, 0, 0, 0, 0, 0, 672, - 0, 0, 0, 0, 0, 0, 1276, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, + 0, 1906, 0, 0, 733, 0, 733, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3200, + 0, 0, 0, 0, 0, 0, 0, 2011, 0, 0, + 0, 0, 0, 1282, 0, 733, 0, 0, 0, 0, + 3227, 1906, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3323, 3324, 0, 0, 1514, - 0, 0, 0, 0, 0, 0, 2356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1514, 0, 0, 1514, - 727, 1514, 672, 0, 0, 2369, 0, 0, 0, 0, + 0, 0, 1957, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1070, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1941, 1762, 0, 0, 1276, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 672, 0, 0, - 0, 0, 0, 0, 0, 0, 1088, 0, 0, 921, - 727, 0, 0, 1994, 672, 925, 0, 0, 0, 922, - 923, 0, 0, 0, 924, 926, 0, 0, 0, 0, - 672, 0, 0, 0, 0, 0, 0, 672, 0, 0, - 0, 0, 0, 0, 0, 0, 2020, 2021, 672, 672, - 672, 672, 672, 672, 672, 0, 0, 0, 0, 0, - 0, 0, 0, 1095, 0, 0, 0, 0, 0, 0, - 2482, 2483, 2484, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1050, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1088, 0, 0, 0, 0, 0, 1095, 1882, 0, 0, - 1882, 0, 1882, 0, 0, 0, 0, 0, 2514, 0, + 0, 0, 0, 0, 676, 1094, 0, 0, 0, 0, + 0, 2011, 676, 2389, 676, 0, 676, 2428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, - 0, 0, 0, 1088, 0, 0, 0, 0, 2108, 0, - 0, 0, 2108, 2108, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 727, 0, 0, 0, 1512, 0, 0, 727, 727, 1512, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2588, 0, 0, 0, 0, - 3269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 727, 0, 0, 1512, 0, 0, 0, 0, - 727, 0, 0, 0, 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1276, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1523, 733, 0, 733, 0, + 0, 0, 0, 1854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 733, 733, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 676, 0, 0, 0, + 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 676, 676, 0, 0, 676, 0, + 2598, 0, 0, 0, 0, 733, 0, 0, 0, 0, + 676, 0, 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 676, 0, 733, 0, 0, 0, 0, + 2609, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, + 733, 0, 0, 0, 0, 0, 0, 0, 2389, 2389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1525, + 0, 2011, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3646, 3647, 3648, + 3649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1941, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1064, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1044, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 672, 0, 0, 0, 0, 0, 0, 1994, 672, - 0, 672, 0, 672, 2408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3558, 0, 2836, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2851, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 727, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 727, 727, 727, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2933, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3724, 0, 3724, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2369, 0, 0, 0, 0, 0, 0, 2958, 0, - 0, 0, 1882, 1882, 0, 0, 0, 2963, 0, 0, + 0, 0, 0, 0, 3752, 0, 3754, 0, 0, 0, + 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, + 0, 0, 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2974, 0, 0, 0, 0, 0, - 0, 0, 672, 0, 0, 0, 0, 0, 0, 672, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 672, - 672, 0, 0, 672, 0, 2576, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, - 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 2108, 727, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2389, 0, 0, 0, 0, 0, + 0, 676, 0, 0, 0, 0, 676, 0, 0, 0, + 3921, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1512, 0, 0, 0, 0, 0, - 0, 727, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1514, 0, 1994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 676, 0, 0, 0, 0, 0, 0, 2967, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3724, 0, + 0, 0, 0, 0, 0, 3724, 0, 3724, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1525, 0, 2389, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 676, 676, 676, + 676, 676, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3131, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1276, + 0, 0, 0, 0, 0, 676, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, - 0, 0, 727, 0, 727, 0, 0, 0, 0, 0, - 1890, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3176, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, - 0, 0, 1276, 0, 0, 0, 0, 0, 0, 3203, - 1890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 672, 0, 0, 0, - 0, 0, 0, 0, 1941, 0, 0, 0, 0, 0, 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, 2369, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 672, 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, + 0, 3784, 3786, 3785, 3851, 3852, 3853, 3854, 3855, 3856, + 3857, 3787, 3788, 804, 0, 0, 2389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 672, 0, 0, 0, 0, 0, 0, 2943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 1514, 0, 0, 0, 0, - 0, 0, 0, 1512, 727, 0, 727, 0, 672, 672, - 672, 672, 672, 672, 0, 0, 0, 0, 0, 0, - 0, 0, 1838, 0, 0, 0, 0, 0, 0, 0, - 0, 727, 727, 0, 0, 672, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 672, 0, + 0, 0, 0, 0, 0, 0, 4068, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4076, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2389, 0, 4084, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1282, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1070, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4134, 0, 0, 0, + 1525, 0, 0, 0, 0, 1525, 676, 676, 676, 676, + 676, 0, 0, 0, 0, 0, 0, 0, 3243, 0, + 0, 0, 0, 0, 1957, 0, 676, 0, 0, 676, + 3251, 2011, 0, 3792, 0, 0, 4076, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3800, 3801, + 0, 0, 3876, 3875, 3874, 0, 0, 3872, 3873, 3871, + 2389, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 676, 0, 0, 0, 1854, + 0, 4134, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1525, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3877, 927, 676, 780, 781, 3878, 3879, + 931, 3880, 783, 784, 928, 929, 0, 778, 782, 930, + 932, 0, 0, 0, 0, 676, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 727, 0, 727, 0, + 0, 0, 0, 0, 0, 0, 3781, 3782, 3783, 3789, + 3790, 3791, 3802, 3849, 3850, 3858, 3860, 883, 3859, 3861, + 3862, 3863, 3866, 3867, 3868, 3869, 3864, 3865, 3870, 3764, + 3768, 3765, 3766, 3767, 3779, 3769, 3770, 3771, 3772, 3773, + 3774, 3775, 3776, 3777, 3778, 3780, 3881, 3882, 3883, 3884, + 3885, 3886, 3795, 3799, 3798, 3796, 3797, 3793, 3794, 3821, + 3820, 3822, 3823, 3824, 3825, 3826, 3827, 3829, 3828, 3830, + 3831, 3832, 3833, 3834, 3835, 3803, 3804, 3807, 3808, 3806, + 3805, 3809, 3818, 3819, 3810, 3811, 3812, 3813, 3814, 3815, + 3817, 3816, 3836, 3837, 3838, 3839, 3840, 3842, 3841, 3845, + 3846, 3844, 3843, 3848, 3847, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 933, 0, + 934, 0, 0, 938, 0, 0, 0, 940, 939, 0, + 941, 903, 902, 0, 0, 935, 936, 0, 937, 0, + 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2369, 2369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 676, + 0, 0, 0, 3887, 3888, 3889, 3890, 3891, 3892, 3893, + 3894, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3622, 3623, 3624, 3625, + 0, 0, 0, 0, 0, 0, 0, 0, 676, 0, + 0, 676, 676, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2743,104 +2880,52 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1064, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1514, 0, - 0, 0, 0, 1514, 672, 672, 672, 672, 672, 0, - 0, 0, 0, 0, 0, 0, 3219, 0, 0, 0, - 0, 0, 1941, 0, 672, 0, 0, 672, 3227, 1994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3700, 0, 3700, 0, 0, 0, 0, - 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1514, - 0, 0, 0, 3728, 0, 3730, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 672, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2369, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3700, 0, 0, - 0, 0, 0, 0, 3700, 0, 3700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2369, 0, 0, 0, 0, - 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, + 1525, 0, 0, 0, 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 672, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3760, 3762, - 3761, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3763, 3764, - 798, 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 672, 0, 0, 672, - 672, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4044, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4052, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2369, 0, 4060, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1276, 1276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3776, 3777, 4110, 0, 3852, 3851, 3850, - 0, 0, 3848, 3849, 3847, 0, 0, 0, 0, 1941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1514, 0, - 0, 0, 1941, 0, 0, 4052, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3853, 921, 2369, - 774, 775, 3854, 3855, 925, 3856, 777, 778, 922, 923, - 0, 772, 776, 924, 926, 0, 0, 0, 1838, 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, 0, 0, 0, 1941, 0, - 3757, 3758, 3759, 3765, 3766, 3767, 3778, 3825, 3826, 3834, - 3836, 877, 3835, 3837, 3838, 3839, 3842, 3843, 3844, 3845, - 3840, 3841, 3846, 3740, 3744, 3741, 3742, 3743, 3755, 3745, - 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3756, - 3857, 3858, 3859, 3860, 3861, 3862, 3771, 3775, 3774, 3772, - 3773, 3769, 3770, 3797, 3796, 3798, 3799, 3800, 3801, 3802, - 3803, 3805, 3804, 3806, 3807, 3808, 3809, 3810, 3811, 3779, - 3780, 3783, 3784, 3782, 3781, 3785, 3794, 3795, 3786, 3787, - 3788, 3789, 3790, 3791, 3793, 3792, 3812, 3813, 3814, 3815, - 3816, 3818, 3817, 3821, 3822, 3820, 3819, 3824, 3823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 927, 0, 928, 0, 0, 932, 0, 0, - 0, 934, 933, 0, 935, 897, 896, 0, 0, 929, - 930, 0, 931, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3863, 3864, 3865, - 3866, 3867, 3868, 3869, 3870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2848,9 +2933,9 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1941, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2858,1718 +2943,1515 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1514, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4082, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1941, 0, 0, 0, - 396, 0, 0, 0, 0, 0, 1411, 1397, 527, 0, - 1339, 1414, 1308, 1327, 1424, 1330, 1333, 1376, 1286, 1354, - 416, 1324, 1312, 1281, 1319, 1282, 1310, 1341, 270, 1307, - 1399, 1358, 1413, 366, 267, 1288, 1279, 204, 505, 1313, - 430, 1329, 203, 1378, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 1420, 370, - 1364, 0, 497, 401, 0, 0, 1994, 1343, 1403, 1352, - 1390, 1338, 1377, 1296, 1363, 1415, 1325, 1373, 1416, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 4084, 952, 0, 0, 0, 0, 4085, 0, 0, 0, - 0, 238, 0, 0, 245, 0, 0, 0, 351, 360, - 359, 339, 340, 342, 344, 350, 357, 363, 336, 345, - 1321, 1370, 606, 1410, 1322, 1372, 265, 321, 272, 264, - 579, 1421, 1402, 1285, 1351, 1409, 1346, 0, 0, 229, - 1412, 1345, 0, 1375, 0, 1427, 1280, 1366, 0, 1283, - 1287, 1423, 1407, 1316, 275, 0, 0, 0, 0, 0, - 0, 0, 1342, 1353, 1387, 1391, 1336, 0, 0, 0, - 0, 0, 0, 0, 0, 1314, 0, 1362, 0, 0, - 0, 1292, 1284, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1340, 0, 0, 0, 0, - 1295, 0, 1315, 1388, 0, 1278, 297, 1289, 402, 257, - 0, 453, 1395, 1406, 1337, 624, 1408, 1335, 1334, 1382, - 1293, 1401, 1328, 365, 1291, 330, 197, 225, 0, 1326, - 412, 461, 473, 1400, 1311, 1320, 253, 1318, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 1361, 1380, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 1290, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 1306, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 1396, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 1385, 1426, 425, 472, 240, 603, 496, 199, 1300, 1305, - 1298, 0, 254, 255, 1367, 574, 1301, 1299, 1356, 1357, - 1302, 1417, 1418, 1419, 1404, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 1389, 1294, 0, 1303, 1304, 398, 1398, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 1360, - 196, 221, 368, 1422, 454, 288, 645, 614, 484, 609, - 206, 223, 1297, 262, 1309, 1317, 0, 1323, 1331, 1332, - 1344, 1347, 1348, 1349, 1350, 1368, 1369, 1371, 1379, 1381, - 1384, 1386, 1393, 1405, 1425, 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 1359, 1365, 381, 281, 305, 320, 1374, - 613, 502, 227, 466, 290, 251, 1392, 1394, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 1355, 1383, 376, 575, 576, 316, 396, 0, - 0, 0, 0, 0, 1411, 1397, 527, 0, 1339, 1414, - 1308, 1327, 1424, 1330, 1333, 1376, 1286, 1354, 416, 1324, - 1312, 1281, 1319, 1282, 1310, 1341, 270, 1307, 1399, 1358, - 1413, 366, 267, 1288, 1279, 204, 505, 1313, 430, 1329, - 203, 1378, 487, 252, 377, 374, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 1420, 370, 1364, 0, - 497, 401, 0, 0, 0, 1343, 1403, 1352, 1390, 1338, - 1377, 1296, 1363, 1415, 1325, 1373, 1416, 323, 248, 325, - 202, 413, 498, 286, 0, 0, 0, 0, 0, 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, 1321, 1370, - 606, 1410, 1322, 1372, 265, 321, 272, 264, 579, 1421, - 1402, 1285, 1351, 1409, 1346, 0, 0, 229, 1412, 1345, - 0, 1375, 0, 1427, 1280, 1366, 0, 1283, 1287, 1423, - 1407, 1316, 275, 0, 0, 0, 0, 0, 0, 0, - 1342, 1353, 1387, 1391, 1336, 0, 0, 0, 0, 0, - 0, 3228, 0, 1314, 0, 1362, 0, 0, 0, 1292, - 1284, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1340, 0, 0, 0, 0, 1295, 0, - 1315, 1388, 0, 1278, 297, 1289, 402, 257, 0, 453, - 1395, 1406, 1337, 624, 1408, 1335, 1334, 1382, 1293, 1401, - 1328, 365, 1291, 330, 197, 225, 0, 1326, 412, 461, - 473, 1400, 1311, 1320, 253, 1318, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 1361, 1380, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, + 0, 0, 0, 0, 0, 0, 0, 0, 1957, 0, + 0, 396, 0, 0, 0, 0, 0, 0, 1420, 1404, + 528, 0, 1346, 1423, 1314, 1333, 1433, 1336, 1339, 1383, + 1292, 1361, 416, 1330, 1318, 1287, 1325, 1288, 1316, 1348, + 270, 1313, 1406, 1365, 1422, 366, 267, 1294, 1285, 204, + 505, 1319, 430, 1335, 203, 1385, 487, 252, 377, 374, + 583, 282, 273, 269, 250, 317, 385, 428, 518, 422, + 1429, 370, 1371, 0, 497, 401, 0, 0, 2011, 1410, + 1409, 1340, 1350, 1412, 1359, 1397, 1345, 1384, 1302, 1370, + 1424, 1331, 1380, 1425, 323, 248, 325, 202, 413, 498, + 286, 0, 0, 0, 0, 4108, 507, 958, 0, 0, + 0, 0, 4109, 0, 0, 0, 0, 238, 0, 0, + 245, 0, 0, 0, 351, 360, 359, 339, 340, 342, + 344, 350, 357, 363, 336, 345, 1327, 1377, 608, 1419, + 1328, 1379, 265, 321, 272, 264, 580, 1430, 1411, 1291, + 1358, 1418, 1353, 0, 0, 229, 1421, 1352, 0, 1382, + 0, 1436, 1286, 1373, 0, 1289, 1293, 1432, 1416, 1322, + 275, 0, 0, 0, 0, 0, 0, 0, 1349, 1360, + 1394, 1398, 1343, 0, 0, 0, 0, 0, 0, 0, + 0, 1320, 0, 1369, 0, 0, 0, 1298, 1290, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1347, 0, 0, 0, 0, 1301, 0, 1321, 1395, + 0, 1284, 297, 1295, 402, 257, 0, 453, 1402, 1415, + 1344, 628, 1417, 1342, 1341, 1389, 1299, 1408, 1334, 365, + 1297, 330, 197, 225, 0, 1332, 412, 461, 473, 1407, + 1317, 1326, 253, 1324, 471, 426, 603, 233, 284, 458, + 432, 469, 440, 287, 1368, 1387, 470, 372, 585, 450, + 600, 629, 630, 263, 406, 614, 522, 622, 647, 226, + 260, 420, 506, 606, 494, 397, 581, 582, 329, 493, + 295, 201, 369, 635, 224, 479, 371, 242, 231, 587, + 611, 299, 289, 456, 642, 213, 517, 597, 239, 483, + 0, 0, 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 1290, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, + 258, 415, 589, 590, 256, 651, 228, 621, 220, 1296, + 620, 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 1306, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 1396, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 1385, 1426, - 425, 472, 240, 603, 496, 199, 1300, 1305, 1298, 0, - 254, 255, 1367, 574, 1301, 1299, 1356, 1357, 1302, 1417, - 1418, 1419, 1404, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 1389, 1294, 0, 1303, 1304, 398, 1398, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 1360, 196, 221, - 368, 1422, 454, 288, 645, 614, 484, 609, 206, 223, - 1297, 262, 1309, 1317, 0, 1323, 1331, 1332, 1344, 1347, - 1348, 1349, 1350, 1368, 1369, 1371, 1379, 1381, 1384, 1386, - 1393, 1405, 1425, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 1359, 1365, 381, 281, 305, 320, 1374, 613, 502, - 227, 466, 290, 251, 1392, 1394, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 1355, 1383, 376, 575, 576, 316, 396, 0, 0, 0, - 0, 0, 1411, 1397, 527, 0, 1339, 1414, 1308, 1327, - 1424, 1330, 1333, 1376, 1286, 1354, 416, 1324, 1312, 1281, - 1319, 1282, 1310, 1341, 270, 1307, 1399, 1358, 1413, 366, - 267, 1288, 1279, 204, 505, 1313, 430, 1329, 203, 1378, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 1420, 370, 1364, 0, 497, 401, - 0, 0, 0, 1343, 1403, 1352, 1390, 1338, 1377, 1296, - 1363, 1415, 1325, 1373, 1416, 323, 248, 325, 202, 413, - 498, 286, 0, 0, 0, 0, 0, 717, 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, 1321, 1370, 606, 1410, - 1322, 1372, 265, 321, 272, 264, 579, 1421, 1402, 1285, - 1351, 1409, 1346, 0, 0, 229, 1412, 1345, 0, 1375, - 0, 1427, 1280, 1366, 0, 1283, 1287, 1423, 1407, 1316, - 275, 0, 0, 0, 0, 0, 0, 0, 1342, 1353, - 1387, 1391, 1336, 0, 0, 0, 0, 0, 0, 3189, - 0, 1314, 0, 1362, 0, 0, 0, 1292, 1284, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1340, 0, 0, 0, 0, 1295, 0, 1315, 1388, - 0, 1278, 297, 1289, 402, 257, 0, 453, 1395, 1406, - 1337, 624, 1408, 1335, 1334, 1382, 1293, 1401, 1328, 365, - 1291, 330, 197, 225, 0, 1326, 412, 461, 473, 1400, - 1311, 1320, 253, 1318, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 1361, 1380, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, - 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 1290, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, - 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 1306, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 1396, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 1385, 1426, 425, 472, - 240, 603, 496, 199, 1300, 1305, 1298, 0, 254, 255, - 1367, 574, 1301, 1299, 1356, 1357, 1302, 1417, 1418, 1419, - 1404, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 1389, - 1294, 0, 1303, 1304, 398, 1398, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 1360, 196, 221, 368, 1422, - 454, 288, 645, 614, 484, 609, 206, 223, 1297, 262, - 1309, 1317, 0, 1323, 1331, 1332, 1344, 1347, 1348, 1349, - 1350, 1368, 1369, 1371, 1379, 1381, 1384, 1386, 1393, 1405, - 1425, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 1359, - 1365, 381, 281, 305, 320, 1374, 613, 502, 227, 466, - 290, 251, 1392, 1394, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 1355, 1383, - 376, 575, 576, 316, 396, 0, 0, 0, 0, 0, - 1411, 1397, 527, 0, 1339, 1414, 1308, 1327, 1424, 1330, - 1333, 1376, 1286, 1354, 416, 1324, 1312, 1281, 1319, 1282, - 1310, 1341, 270, 1307, 1399, 1358, 1413, 366, 267, 1288, - 1279, 204, 505, 1313, 430, 1329, 203, 1378, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 1420, 370, 1364, 0, 497, 401, 0, 0, - 0, 1343, 1403, 1352, 1390, 1338, 1377, 1296, 1363, 1415, - 1325, 1373, 1416, 323, 248, 325, 202, 413, 498, 286, - 0, 0, 0, 0, 0, 952, 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, 1321, 1370, 606, 1410, 1322, 1372, - 265, 321, 272, 264, 579, 1421, 1402, 1285, 1351, 1409, - 1346, 0, 0, 229, 1412, 1345, 0, 1375, 0, 1427, - 1280, 1366, 0, 1283, 1287, 1423, 1407, 1316, 275, 0, - 0, 0, 0, 0, 0, 0, 1342, 1353, 1387, 1391, - 1336, 0, 0, 0, 0, 0, 0, 2387, 0, 1314, - 0, 1362, 0, 0, 0, 1292, 1284, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1340, - 0, 0, 0, 0, 1295, 0, 1315, 1388, 0, 1278, - 297, 1289, 402, 257, 0, 453, 1395, 1406, 1337, 624, - 1408, 1335, 1334, 1382, 1293, 1401, 1328, 365, 1291, 330, - 197, 225, 0, 1326, 412, 461, 473, 1400, 1311, 1320, - 253, 1318, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 1361, 1380, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 1290, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 1306, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 1396, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 1385, 1426, 425, 472, 240, 603, - 496, 199, 1300, 1305, 1298, 0, 254, 255, 1367, 574, - 1301, 1299, 1356, 1357, 1302, 1417, 1418, 1419, 1404, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 1389, 1294, 0, - 1303, 1304, 398, 1398, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 1360, 196, 221, 368, 1422, 454, 288, - 645, 614, 484, 609, 206, 223, 1297, 262, 1309, 1317, - 0, 1323, 1331, 1332, 1344, 1347, 1348, 1349, 1350, 1368, - 1369, 1371, 1379, 1381, 1384, 1386, 1393, 1405, 1425, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 1359, 1365, 381, - 281, 305, 320, 1374, 613, 502, 227, 466, 290, 251, - 1392, 1394, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 1355, 1383, 376, 575, - 576, 316, 396, 0, 0, 0, 0, 0, 1411, 1397, - 527, 0, 1339, 1414, 1308, 1327, 1424, 1330, 1333, 1376, - 1286, 1354, 416, 1324, 1312, 1281, 1319, 1282, 1310, 1341, - 270, 1307, 1399, 1358, 1413, 366, 267, 1288, 1279, 204, - 505, 1313, 430, 1329, 203, 1378, 487, 252, 377, 374, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 1420, 370, 1364, 0, 497, 401, 0, 0, 0, 1343, - 1403, 1352, 1390, 1338, 1377, 1296, 1363, 1415, 1325, 1373, - 1416, 323, 248, 325, 202, 413, 498, 286, 0, 95, - 0, 0, 0, 717, 0, 0, 0, 0, 0, 0, + 404, 403, 405, 207, 607, 625, 0, 208, 0, 499, + 610, 652, 452, 212, 234, 235, 237, 1312, 279, 283, + 291, 294, 303, 304, 313, 367, 419, 446, 442, 451, + 1403, 579, 601, 615, 627, 633, 634, 636, 637, 638, + 639, 640, 643, 641, 407, 311, 495, 333, 373, 1392, + 1435, 425, 472, 240, 605, 496, 199, 1306, 1311, 1304, + 0, 254, 255, 1374, 575, 1307, 1305, 1363, 1364, 1308, + 1426, 1427, 1428, 1413, 653, 654, 655, 656, 657, 658, + 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 648, 508, 514, 509, 510, 511, 512, 513, + 0, 515, 1396, 1300, 0, 1309, 1310, 398, 1405, 591, + 592, 671, 384, 486, 602, 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, 618, 619, 623, 205, 462, + 463, 464, 465, 292, 613, 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, 1367, 196, + 221, 368, 1431, 454, 288, 649, 617, 484, 612, 206, + 223, 1303, 262, 1315, 1323, 0, 1329, 1337, 1338, 1351, + 1354, 1355, 1356, 1357, 1375, 1376, 1378, 1386, 1388, 1391, + 1393, 1400, 1414, 1434, 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, 604, 624, 631, 480, 301, 302, 444, 445, + 314, 315, 645, 646, 300, 599, 632, 596, 644, 626, + 438, 378, 1366, 1372, 381, 281, 305, 320, 1381, 616, + 502, 227, 466, 290, 251, 1399, 1401, 211, 246, 230, + 259, 274, 277, 324, 391, 400, 429, 434, 296, 271, + 244, 459, 241, 485, 519, 520, 521, 523, 395, 266, + 433, 1362, 1390, 376, 576, 577, 316, 396, 0, 0, + 0, 0, 0, 0, 1420, 1404, 528, 0, 1346, 1423, + 1314, 1333, 1433, 1336, 1339, 1383, 1292, 1361, 416, 1330, + 1318, 1287, 1325, 1288, 1316, 1348, 270, 1313, 1406, 1365, + 1422, 366, 267, 1294, 1285, 204, 505, 1319, 430, 1335, + 203, 1385, 487, 252, 377, 374, 583, 282, 273, 269, + 250, 317, 385, 428, 518, 422, 1429, 370, 1371, 0, + 497, 401, 0, 0, 0, 1410, 1409, 1340, 1350, 1412, + 1359, 1397, 1345, 1384, 1302, 1370, 1424, 1331, 1380, 1425, + 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, 1321, 1370, 606, 1410, 1322, 1372, 265, 321, - 272, 264, 579, 1421, 1402, 1285, 1351, 1409, 1346, 0, - 0, 229, 1412, 1345, 0, 1375, 0, 1427, 1280, 1366, - 0, 1283, 1287, 1423, 1407, 1316, 275, 0, 0, 0, - 0, 0, 0, 0, 1342, 1353, 1387, 1391, 1336, 0, - 0, 0, 0, 0, 0, 0, 0, 1314, 0, 1362, - 0, 0, 0, 1292, 1284, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1340, 0, 0, - 0, 0, 1295, 0, 1315, 1388, 0, 1278, 297, 1289, - 402, 257, 0, 453, 1395, 1406, 1337, 624, 1408, 1335, - 1334, 1382, 1293, 1401, 1328, 365, 1291, 330, 197, 225, - 0, 1326, 412, 461, 473, 1400, 1311, 1320, 253, 1318, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 1361, 1380, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 1290, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 1306, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 1396, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 1385, 1426, 425, 472, 240, 603, 496, 199, - 1300, 1305, 1298, 0, 254, 255, 1367, 574, 1301, 1299, - 1356, 1357, 1302, 1417, 1418, 1419, 1404, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 1389, 1294, 0, 1303, 1304, - 398, 1398, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 1360, 196, 221, 368, 1422, 454, 288, 645, 614, - 484, 609, 206, 223, 1297, 262, 1309, 1317, 0, 1323, - 1331, 1332, 1344, 1347, 1348, 1349, 1350, 1368, 1369, 1371, - 1379, 1381, 1384, 1386, 1393, 1405, 1425, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 1359, 1365, 381, 281, 305, - 320, 1374, 613, 502, 227, 466, 290, 251, 1392, 1394, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 1355, 1383, 376, 575, 576, 316, - 396, 0, 0, 0, 0, 0, 1411, 1397, 527, 0, - 1339, 1414, 1308, 1327, 1424, 1330, 1333, 1376, 1286, 1354, - 416, 1324, 1312, 1281, 1319, 1282, 1310, 1341, 270, 1307, - 1399, 1358, 1413, 366, 267, 1288, 1279, 204, 505, 1313, - 430, 1329, 203, 1378, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 1420, 370, - 1364, 0, 497, 401, 0, 0, 0, 1343, 1403, 1352, - 1390, 1338, 1377, 1296, 1363, 1415, 1325, 1373, 1416, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 0, 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, - 1321, 1370, 606, 1410, 1322, 1372, 265, 321, 272, 264, - 579, 1421, 1402, 1285, 1351, 1409, 1346, 0, 0, 229, - 1412, 1345, 0, 1375, 0, 1427, 1280, 1366, 0, 1283, - 1287, 1423, 1407, 1316, 275, 0, 0, 0, 0, 0, - 0, 0, 1342, 1353, 1387, 1391, 1336, 0, 0, 0, - 0, 0, 0, 0, 0, 1314, 0, 1362, 0, 0, - 0, 1292, 1284, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1340, 0, 0, 0, 0, - 1295, 0, 1315, 1388, 0, 1278, 297, 1289, 402, 257, - 0, 453, 1395, 1406, 1337, 624, 1408, 1335, 1334, 1382, - 1293, 1401, 1328, 365, 1291, 330, 197, 225, 0, 1326, - 412, 461, 473, 1400, 1311, 1320, 253, 1318, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 1361, 1380, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 1290, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 1306, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 1396, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 1385, 1426, 425, 472, 240, 603, 496, 199, 1300, 1305, - 1298, 0, 254, 255, 1367, 574, 1301, 1299, 1356, 1357, - 1302, 1417, 1418, 1419, 1404, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 1389, 1294, 0, 1303, 1304, 398, 1398, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 1360, - 196, 221, 368, 1422, 454, 288, 645, 614, 484, 609, - 206, 223, 1297, 262, 1309, 1317, 0, 1323, 1331, 1332, - 1344, 1347, 1348, 1349, 1350, 1368, 1369, 1371, 1379, 1381, - 1384, 1386, 1393, 1405, 1425, 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 1359, 1365, 381, 281, 305, 320, 1374, - 613, 502, 227, 466, 290, 251, 1392, 1394, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 1355, 1383, 376, 575, 576, 316, 396, 0, - 0, 0, 0, 0, 1411, 1397, 527, 0, 1339, 1414, - 1308, 1327, 1424, 1330, 1333, 1376, 1286, 1354, 416, 1324, - 1312, 1281, 1319, 1282, 1310, 1341, 270, 1307, 1399, 1358, - 1413, 366, 267, 1288, 1279, 204, 505, 1313, 430, 1329, - 203, 1378, 487, 252, 377, 374, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 1420, 370, 1364, 0, - 497, 401, 0, 0, 0, 1343, 1403, 1352, 1390, 1338, - 1377, 1296, 1363, 1415, 1325, 1373, 1416, 323, 248, 325, - 202, 413, 498, 286, 0, 0, 0, 0, 0, 717, + 336, 345, 1327, 1377, 608, 1419, 1328, 1379, 265, 321, + 272, 264, 580, 1430, 1411, 1291, 1358, 1418, 1353, 0, + 0, 229, 1421, 1352, 0, 1382, 0, 1436, 1286, 1373, + 0, 1289, 1293, 1432, 1416, 1322, 275, 0, 0, 0, + 0, 0, 0, 0, 1349, 1360, 1394, 1398, 1343, 0, + 0, 0, 0, 0, 0, 3252, 0, 1320, 0, 1369, + 0, 0, 0, 1298, 1290, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1347, 0, 0, + 0, 0, 1301, 0, 1321, 1395, 0, 1284, 297, 1295, + 402, 257, 0, 453, 1402, 1415, 1344, 628, 1417, 1342, + 1341, 1389, 1299, 1408, 1334, 365, 1297, 330, 197, 225, + 0, 1332, 412, 461, 473, 1407, 1317, 1326, 253, 1324, + 471, 426, 603, 233, 284, 458, 432, 469, 440, 287, + 1368, 1387, 470, 372, 585, 450, 600, 629, 630, 263, + 406, 614, 522, 622, 647, 226, 260, 420, 506, 606, + 494, 397, 581, 582, 329, 493, 295, 201, 369, 635, + 224, 479, 371, 242, 231, 587, 611, 299, 289, 456, + 642, 213, 517, 597, 239, 483, 0, 0, 650, 247, + 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, + 0, 457, 268, 293, 0, 0, 258, 415, 589, 590, + 256, 651, 228, 621, 220, 1296, 620, 408, 584, 595, + 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, + 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, + 607, 625, 0, 208, 0, 499, 610, 652, 452, 212, + 234, 235, 237, 1312, 279, 283, 291, 294, 303, 304, + 313, 367, 419, 446, 442, 451, 1403, 579, 601, 615, + 627, 633, 634, 636, 637, 638, 639, 640, 643, 641, + 407, 311, 495, 333, 373, 1392, 1435, 425, 472, 240, + 605, 496, 199, 1306, 1311, 1304, 0, 254, 255, 1374, + 575, 1307, 1305, 1363, 1364, 1308, 1426, 1427, 1428, 1413, + 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 648, 508, + 514, 509, 510, 511, 512, 513, 0, 515, 1396, 1300, + 0, 1309, 1310, 398, 1405, 591, 592, 671, 384, 486, + 602, 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, 618, 619, 623, 205, 462, 463, 464, 465, 292, + 613, 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, 1367, 196, 221, 368, 1431, 454, + 288, 649, 617, 484, 612, 206, 223, 1303, 262, 1315, + 1323, 0, 1329, 1337, 1338, 1351, 1354, 1355, 1356, 1357, + 1375, 1376, 1378, 1386, 1388, 1391, 1393, 1400, 1414, 1434, + 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, 604, 624, + 631, 480, 301, 302, 444, 445, 314, 315, 645, 646, + 300, 599, 632, 596, 644, 626, 438, 378, 1366, 1372, + 381, 281, 305, 320, 1381, 616, 502, 227, 466, 290, + 251, 1399, 1401, 211, 246, 230, 259, 274, 277, 324, + 391, 400, 429, 434, 296, 271, 244, 459, 241, 485, + 519, 520, 521, 523, 395, 266, 433, 1362, 1390, 376, + 576, 577, 316, 396, 0, 0, 0, 0, 0, 0, + 1420, 1404, 528, 0, 1346, 1423, 1314, 1333, 1433, 1336, + 1339, 1383, 1292, 1361, 416, 1330, 1318, 1287, 1325, 1288, + 1316, 1348, 270, 1313, 1406, 1365, 1422, 366, 267, 1294, + 1285, 204, 505, 1319, 430, 1335, 203, 1385, 487, 252, + 377, 374, 583, 282, 273, 269, 250, 317, 385, 428, + 518, 422, 1429, 370, 1371, 0, 497, 401, 0, 0, + 0, 1410, 1409, 1340, 1350, 1412, 1359, 1397, 1345, 1384, + 1302, 1370, 1424, 1331, 1380, 1425, 323, 248, 325, 202, + 413, 498, 286, 0, 0, 0, 0, 0, 507, 723, 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, 1321, 1370, - 606, 1410, 1322, 1372, 265, 321, 272, 264, 579, 1421, - 1402, 1285, 1351, 1409, 1346, 0, 0, 229, 1412, 1345, - 0, 1375, 0, 1427, 1280, 1366, 0, 1283, 1287, 1423, - 1407, 1316, 275, 0, 0, 0, 0, 0, 0, 0, - 1342, 1353, 1387, 1391, 1336, 0, 0, 0, 0, 0, - 0, 0, 0, 1314, 0, 1362, 0, 0, 0, 1292, - 1284, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1340, 0, 0, 0, 0, 1295, 0, - 1315, 1388, 0, 1278, 297, 1289, 402, 257, 0, 453, - 1395, 1406, 1337, 624, 1408, 1335, 1334, 1382, 1293, 1401, - 1328, 365, 1291, 330, 197, 225, 0, 1326, 412, 461, - 473, 1400, 1311, 1320, 253, 1318, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 1361, 1380, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 1290, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 1306, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 1396, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 1385, 1426, - 425, 472, 240, 603, 496, 199, 1300, 1305, 1298, 0, - 254, 255, 1367, 574, 1301, 1299, 1356, 1357, 1302, 1417, - 1418, 1419, 1404, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 1389, 1294, 0, 1303, 1304, 398, 1398, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 1360, 196, 221, - 368, 1422, 454, 288, 645, 614, 484, 609, 206, 223, - 1297, 262, 1309, 1317, 0, 1323, 1331, 1332, 1344, 1347, - 1348, 1349, 1350, 1368, 1369, 1371, 1379, 1381, 1384, 1386, - 1393, 1405, 1425, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 1359, 1365, 381, 281, 305, 320, 1374, 613, 502, - 227, 466, 290, 251, 1392, 1394, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 1355, 1383, 376, 575, 576, 316, 396, 0, 0, 0, - 0, 0, 1411, 1397, 527, 0, 1339, 1414, 1308, 1327, - 1424, 1330, 1333, 1376, 1286, 1354, 416, 1324, 1312, 1281, - 1319, 1282, 1310, 1341, 270, 1307, 1399, 1358, 1413, 366, - 267, 1288, 1279, 204, 505, 1313, 430, 1329, 203, 1378, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 1420, 370, 1364, 0, 497, 401, - 0, 0, 0, 1343, 1403, 1352, 1390, 1338, 1377, 1296, - 1363, 1415, 1325, 1373, 1416, 323, 248, 325, 202, 413, - 498, 286, 0, 0, 0, 0, 0, 952, 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, 1321, 1370, 606, 1410, - 1322, 1372, 265, 321, 272, 264, 579, 1421, 1402, 1285, - 1351, 1409, 1346, 0, 0, 229, 1412, 1345, 0, 1375, - 0, 1427, 1280, 1366, 0, 1283, 1287, 1423, 1407, 1316, - 275, 0, 0, 0, 0, 0, 0, 0, 1342, 1353, - 1387, 1391, 1336, 0, 0, 0, 0, 0, 0, 0, - 0, 1314, 0, 1362, 0, 0, 0, 1292, 1284, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1340, 0, 0, 0, 0, 1295, 0, 1315, 1388, - 0, 1278, 297, 1289, 402, 257, 0, 453, 1395, 1406, - 1337, 624, 1408, 1335, 1334, 1382, 1293, 1401, 1328, 365, - 1291, 330, 197, 225, 0, 1326, 412, 461, 473, 1400, - 1311, 1320, 253, 1318, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 1361, 1380, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 340, 342, 344, 350, 357, 363, 336, 345, 1327, 1377, + 608, 1419, 1328, 1379, 265, 321, 272, 264, 580, 1430, + 1411, 1291, 1358, 1418, 1353, 0, 0, 229, 1421, 1352, + 0, 1382, 0, 1436, 1286, 1373, 0, 1289, 1293, 1432, + 1416, 1322, 275, 0, 0, 0, 0, 0, 0, 0, + 1349, 1360, 1394, 1398, 1343, 0, 0, 0, 0, 0, + 0, 3213, 0, 1320, 0, 1369, 0, 0, 0, 1298, + 1290, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1347, 0, 0, 0, 0, 1301, 0, + 1321, 1395, 0, 1284, 297, 1295, 402, 257, 0, 453, + 1402, 1415, 1344, 628, 1417, 1342, 1341, 1389, 1299, 1408, + 1334, 365, 1297, 330, 197, 225, 0, 1332, 412, 461, + 473, 1407, 1317, 1326, 253, 1324, 471, 426, 603, 233, + 284, 458, 432, 469, 440, 287, 1368, 1387, 470, 372, + 585, 450, 600, 629, 630, 263, 406, 614, 522, 622, + 647, 226, 260, 420, 506, 606, 494, 397, 581, 582, + 329, 493, 295, 201, 369, 635, 224, 479, 371, 242, + 231, 587, 611, 299, 289, 456, 642, 213, 517, 597, + 239, 483, 0, 0, 650, 247, 504, 609, 598, 215, + 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, + 0, 0, 258, 415, 589, 590, 256, 651, 228, 621, + 220, 1296, 620, 408, 584, 595, 394, 383, 219, 593, + 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, + 306, 308, 404, 403, 405, 207, 607, 625, 0, 208, + 0, 499, 610, 652, 452, 212, 234, 235, 237, 1312, + 279, 283, 291, 294, 303, 304, 313, 367, 419, 446, + 442, 451, 1403, 579, 601, 615, 627, 633, 634, 636, + 637, 638, 639, 640, 643, 641, 407, 311, 495, 333, + 373, 1392, 1435, 425, 472, 240, 605, 496, 199, 1306, + 1311, 1304, 0, 254, 255, 1374, 575, 1307, 1305, 1363, + 1364, 1308, 1426, 1427, 1428, 1413, 653, 654, 655, 656, + 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 648, 508, 514, 509, 510, 511, + 512, 513, 0, 515, 1396, 1300, 0, 1309, 1310, 398, + 1405, 591, 592, 671, 384, 486, 602, 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, 618, 619, 623, + 205, 462, 463, 464, 465, 292, 613, 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, + 1367, 196, 221, 368, 1431, 454, 288, 649, 617, 484, + 612, 206, 223, 1303, 262, 1315, 1323, 0, 1329, 1337, + 1338, 1351, 1354, 1355, 1356, 1357, 1375, 1376, 1378, 1386, + 1388, 1391, 1393, 1400, 1414, 1434, 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, 604, 624, 631, 480, 301, 302, + 444, 445, 314, 315, 645, 646, 300, 599, 632, 596, + 644, 626, 438, 378, 1366, 1372, 381, 281, 305, 320, + 1381, 616, 502, 227, 466, 290, 251, 1399, 1401, 211, + 246, 230, 259, 274, 277, 324, 391, 400, 429, 434, + 296, 271, 244, 459, 241, 485, 519, 520, 521, 523, + 395, 266, 433, 1362, 1390, 376, 576, 577, 316, 396, + 0, 0, 0, 0, 0, 0, 1420, 1404, 528, 0, + 1346, 1423, 1314, 1333, 1433, 1336, 1339, 1383, 1292, 1361, + 416, 1330, 1318, 1287, 1325, 1288, 1316, 1348, 270, 1313, + 1406, 1365, 1422, 366, 267, 1294, 1285, 204, 505, 1319, + 430, 1335, 203, 1385, 487, 252, 377, 374, 583, 282, + 273, 269, 250, 317, 385, 428, 518, 422, 1429, 370, + 1371, 0, 497, 401, 0, 0, 0, 1410, 1409, 1340, + 1350, 1412, 1359, 1397, 1345, 1384, 1302, 1370, 1424, 1331, + 1380, 1425, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 958, 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, 1327, 1377, 608, 1419, 1328, 1379, + 265, 321, 272, 264, 580, 1430, 1411, 1291, 1358, 1418, + 1353, 0, 0, 229, 1421, 1352, 0, 1382, 0, 1436, + 1286, 1373, 0, 1289, 1293, 1432, 1416, 1322, 275, 0, + 0, 0, 0, 0, 0, 0, 1349, 1360, 1394, 1398, + 1343, 0, 0, 0, 0, 0, 0, 2407, 0, 1320, + 0, 1369, 0, 0, 0, 1298, 1290, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1347, + 0, 0, 0, 0, 1301, 0, 1321, 1395, 0, 1284, + 297, 1295, 402, 257, 0, 453, 1402, 1415, 1344, 628, + 1417, 1342, 1341, 1389, 1299, 1408, 1334, 365, 1297, 330, + 197, 225, 0, 1332, 412, 461, 473, 1407, 1317, 1326, + 253, 1324, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 1368, 1387, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 1290, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 1296, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 1306, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 1396, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 1385, 1426, 425, 472, - 240, 603, 496, 199, 1300, 1305, 1298, 0, 254, 255, - 1367, 574, 1301, 1299, 1356, 1357, 1302, 1417, 1418, 1419, - 1404, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 1389, - 1294, 0, 1303, 1304, 398, 1398, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 1360, 196, 221, 368, 1422, - 454, 288, 645, 614, 484, 609, 206, 223, 1297, 262, - 1309, 1317, 0, 1323, 1331, 1332, 1344, 1347, 1348, 1349, - 1350, 1368, 1369, 1371, 1379, 1381, 1384, 1386, 1393, 1405, - 1425, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 1359, - 1365, 381, 281, 305, 320, 1374, 613, 502, 227, 466, - 290, 251, 1392, 1394, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 1355, 1383, - 376, 575, 576, 316, 396, 0, 0, 0, 0, 0, - 0, 0, 527, 0, 770, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 757, 0, - 0, 0, 270, 762, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 769, 370, 0, 0, 497, 401, 0, 0, - 0, 0, 0, 764, 765, 0, 0, 0, 0, 0, - 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, - 0, 95, 0, 0, 1016, 952, 741, 918, 956, 1017, - 969, 970, 971, 957, 0, 238, 958, 959, 245, 960, - 0, 917, 800, 802, 801, 867, 868, 869, 870, 871, - 872, 873, 803, 804, 798, 965, 606, 972, 973, 0, - 265, 321, 272, 264, 579, 0, 0, 2209, 2210, 2211, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 1312, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 1403, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 1392, 1435, 425, + 472, 240, 605, 496, 199, 1306, 1311, 1304, 0, 254, + 255, 1374, 575, 1307, 1305, 1363, 1364, 1308, 1426, 1427, + 1428, 1413, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 1396, 1300, 0, 1309, 1310, 398, 1405, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 1367, 196, 221, 368, + 1431, 454, 288, 649, 617, 484, 612, 206, 223, 1303, + 262, 1315, 1323, 0, 1329, 1337, 1338, 1351, 1354, 1355, + 1356, 1357, 1375, 1376, 1378, 1386, 1388, 1391, 1393, 1400, + 1414, 1434, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 1366, 1372, 381, 281, 305, 320, 1381, 616, 502, 227, + 466, 290, 251, 1399, 1401, 211, 246, 230, 259, 274, + 277, 324, 391, 400, 429, 434, 296, 271, 244, 459, + 241, 485, 519, 520, 521, 523, 395, 266, 433, 1362, + 1390, 376, 576, 577, 316, 396, 0, 0, 0, 0, + 0, 0, 1420, 1404, 528, 0, 1346, 1423, 1314, 1333, + 1433, 1336, 1339, 1383, 1292, 1361, 416, 1330, 1318, 1287, + 1325, 1288, 1316, 1348, 270, 1313, 1406, 1365, 1422, 366, + 267, 1294, 1285, 204, 505, 1319, 430, 1335, 203, 1385, + 487, 252, 377, 374, 583, 282, 273, 269, 250, 317, + 385, 428, 518, 422, 1429, 370, 1371, 0, 497, 401, + 0, 0, 0, 1410, 1409, 1340, 1350, 1412, 1359, 1397, + 1345, 1384, 1302, 1370, 1424, 1331, 1380, 1425, 323, 248, + 325, 202, 413, 498, 286, 0, 95, 0, 0, 0, + 507, 723, 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, + 1327, 1377, 608, 1419, 1328, 1379, 265, 321, 272, 264, + 580, 1430, 1411, 1291, 1358, 1418, 1353, 0, 0, 229, + 1421, 1352, 0, 1382, 0, 1436, 1286, 1373, 0, 1289, + 1293, 1432, 1416, 1322, 275, 0, 0, 0, 0, 0, + 0, 0, 1349, 1360, 1394, 1398, 1343, 0, 0, 0, + 0, 0, 0, 0, 0, 1320, 0, 1369, 0, 0, + 0, 1298, 1290, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1347, 0, 0, 0, 0, + 1301, 0, 1321, 1395, 0, 1284, 297, 1295, 402, 257, + 0, 453, 1402, 1415, 1344, 628, 1417, 1342, 1341, 1389, + 1299, 1408, 1334, 365, 1297, 330, 197, 225, 0, 1332, + 412, 461, 473, 1407, 1317, 1326, 253, 1324, 471, 426, + 603, 233, 284, 458, 432, 469, 440, 287, 1368, 1387, + 470, 372, 585, 450, 600, 629, 630, 263, 406, 614, + 522, 622, 647, 226, 260, 420, 506, 606, 494, 397, + 581, 582, 329, 493, 295, 201, 369, 635, 224, 479, + 371, 242, 231, 587, 611, 299, 289, 456, 642, 213, + 517, 597, 239, 483, 0, 0, 650, 247, 504, 609, + 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, + 268, 293, 0, 0, 258, 415, 589, 590, 256, 651, + 228, 621, 220, 1296, 620, 408, 584, 595, 394, 383, + 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, + 375, 448, 306, 308, 404, 403, 405, 207, 607, 625, + 0, 208, 0, 499, 610, 652, 452, 212, 234, 235, + 237, 1312, 279, 283, 291, 294, 303, 304, 313, 367, + 419, 446, 442, 451, 1403, 579, 601, 615, 627, 633, + 634, 636, 637, 638, 639, 640, 643, 641, 407, 311, + 495, 333, 373, 1392, 1435, 425, 472, 240, 605, 496, + 199, 1306, 1311, 1304, 0, 254, 255, 1374, 575, 1307, + 1305, 1363, 1364, 1308, 1426, 1427, 1428, 1413, 653, 654, + 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 648, 508, 514, 509, + 510, 511, 512, 513, 0, 515, 1396, 1300, 0, 1309, + 1310, 398, 1405, 591, 592, 671, 384, 486, 602, 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, 618, + 619, 623, 205, 462, 463, 464, 465, 292, 613, 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, 1367, 196, 221, 368, 1431, 454, 288, 649, + 617, 484, 612, 206, 223, 1303, 262, 1315, 1323, 0, + 1329, 1337, 1338, 1351, 1354, 1355, 1356, 1357, 1375, 1376, + 1378, 1386, 1388, 1391, 1393, 1400, 1414, 1434, 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, 604, 624, 631, 480, + 301, 302, 444, 445, 314, 315, 645, 646, 300, 599, + 632, 596, 644, 626, 438, 378, 1366, 1372, 381, 281, + 305, 320, 1381, 616, 502, 227, 466, 290, 251, 1399, + 1401, 211, 246, 230, 259, 274, 277, 324, 391, 400, + 429, 434, 296, 271, 244, 459, 241, 485, 519, 520, + 521, 523, 395, 266, 433, 1362, 1390, 376, 576, 577, + 316, 396, 0, 0, 0, 0, 0, 0, 1420, 1404, + 528, 0, 1346, 1423, 1314, 1333, 1433, 1336, 1339, 1383, + 1292, 1361, 416, 1330, 1318, 1287, 1325, 1288, 1316, 1348, + 270, 1313, 1406, 1365, 1422, 366, 267, 1294, 1285, 204, + 505, 1319, 430, 1335, 203, 1385, 487, 252, 377, 374, + 583, 282, 273, 269, 250, 317, 385, 428, 518, 422, + 1429, 370, 1371, 0, 497, 401, 0, 0, 0, 1410, + 1409, 1340, 1350, 1412, 1359, 1397, 1345, 1384, 1302, 1370, + 1424, 1331, 1380, 1425, 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, 1327, 1377, 608, 1419, + 1328, 1379, 265, 321, 272, 264, 580, 1430, 1411, 1291, + 1358, 1418, 1353, 0, 0, 229, 1421, 1352, 0, 1382, + 0, 1436, 1286, 1373, 0, 1289, 1293, 1432, 1416, 1322, + 275, 0, 0, 0, 0, 0, 0, 0, 1349, 1360, + 1394, 1398, 1343, 0, 0, 0, 0, 0, 0, 0, + 0, 1320, 0, 1369, 0, 0, 0, 1298, 1290, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1347, 0, 0, 0, 0, 1301, 0, 1321, 1395, + 0, 1284, 297, 1295, 402, 257, 0, 453, 1402, 1415, + 1344, 628, 1417, 1342, 1341, 1389, 1299, 1408, 1334, 365, + 1297, 330, 197, 225, 0, 1332, 412, 461, 473, 1407, + 1317, 1326, 253, 1324, 471, 426, 603, 233, 284, 458, + 432, 469, 440, 287, 1368, 1387, 470, 372, 585, 450, + 600, 629, 630, 263, 406, 614, 522, 622, 647, 226, + 260, 420, 506, 606, 494, 397, 581, 582, 329, 493, + 295, 201, 369, 635, 224, 479, 371, 242, 231, 587, + 611, 299, 289, 456, 642, 213, 517, 597, 239, 483, + 0, 0, 650, 247, 504, 609, 598, 215, 594, 503, + 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, + 258, 415, 589, 590, 256, 651, 228, 621, 220, 1296, + 620, 408, 584, 595, 394, 383, 219, 593, 392, 382, + 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, + 404, 403, 405, 207, 607, 625, 0, 208, 0, 499, + 610, 652, 452, 212, 234, 235, 237, 1312, 279, 283, + 291, 294, 303, 304, 313, 367, 419, 446, 442, 451, + 1403, 579, 601, 615, 627, 633, 634, 636, 637, 638, + 639, 640, 643, 641, 407, 311, 495, 333, 373, 1392, + 1435, 425, 472, 240, 605, 496, 199, 1306, 1311, 1304, + 0, 254, 255, 1374, 575, 1307, 1305, 1363, 1364, 1308, + 1426, 1427, 1428, 1413, 653, 654, 655, 656, 657, 658, + 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 648, 508, 514, 509, 510, 511, 512, 513, + 0, 515, 1396, 1300, 0, 1309, 1310, 398, 1405, 591, + 592, 671, 384, 486, 602, 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, 618, 619, 623, 205, 462, + 463, 464, 465, 292, 613, 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, 1367, 196, + 221, 368, 1431, 454, 288, 649, 617, 484, 612, 206, + 223, 1303, 262, 1315, 1323, 0, 1329, 1337, 1338, 1351, + 1354, 1355, 1356, 1357, 1375, 1376, 1378, 1386, 1388, 1391, + 1393, 1400, 1414, 1434, 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, 604, 624, 631, 480, 301, 302, 444, 445, + 314, 315, 645, 646, 300, 599, 632, 596, 644, 626, + 438, 378, 1366, 1372, 381, 281, 305, 320, 1381, 616, + 502, 227, 466, 290, 251, 1399, 1401, 211, 246, 230, + 259, 274, 277, 324, 391, 400, 429, 434, 296, 271, + 244, 459, 241, 485, 519, 520, 521, 523, 395, 266, + 433, 1362, 1390, 376, 576, 577, 316, 396, 0, 0, + 0, 0, 0, 0, 1420, 1404, 528, 0, 1346, 1423, + 1314, 1333, 1433, 1336, 1339, 1383, 1292, 1361, 416, 1330, + 1318, 1287, 1325, 1288, 1316, 1348, 270, 1313, 1406, 1365, + 1422, 366, 267, 1294, 1285, 204, 505, 1319, 430, 1335, + 203, 1385, 487, 252, 377, 374, 583, 282, 273, 269, + 250, 317, 385, 428, 518, 422, 1429, 370, 1371, 0, + 497, 401, 0, 0, 0, 1410, 1409, 1340, 1350, 1412, + 1359, 1397, 1345, 1384, 1302, 1370, 1424, 1331, 1380, 1425, + 323, 248, 325, 202, 413, 498, 286, 0, 0, 0, + 0, 0, 507, 723, 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, 1327, 1377, 608, 1419, 1328, 1379, 265, 321, + 272, 264, 580, 1430, 1411, 1291, 1358, 1418, 1353, 0, + 0, 229, 1421, 1352, 0, 1382, 0, 1436, 1286, 1373, + 0, 1289, 1293, 1432, 1416, 1322, 275, 0, 0, 0, + 0, 0, 0, 0, 1349, 1360, 1394, 1398, 1343, 0, + 0, 0, 0, 0, 0, 0, 0, 1320, 0, 1369, + 0, 0, 0, 1298, 1290, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1347, 0, 0, + 0, 0, 1301, 0, 1321, 1395, 0, 1284, 297, 1295, + 402, 257, 0, 453, 1402, 1415, 1344, 628, 1417, 1342, + 1341, 1389, 1299, 1408, 1334, 365, 1297, 330, 197, 225, + 0, 1332, 412, 461, 473, 1407, 1317, 1326, 253, 1324, + 471, 426, 603, 233, 284, 458, 432, 469, 440, 287, + 1368, 1387, 470, 372, 585, 450, 600, 629, 630, 263, + 406, 614, 522, 622, 647, 226, 260, 420, 506, 606, + 494, 397, 581, 582, 329, 493, 295, 201, 369, 635, + 224, 479, 371, 242, 231, 587, 611, 299, 289, 456, + 642, 213, 517, 597, 239, 483, 0, 0, 650, 247, + 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, + 0, 457, 268, 293, 0, 0, 258, 415, 589, 590, + 256, 651, 228, 621, 220, 1296, 620, 408, 584, 595, + 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, + 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, + 607, 625, 0, 208, 0, 499, 610, 652, 452, 212, + 234, 235, 237, 1312, 279, 283, 291, 294, 303, 304, + 313, 367, 419, 446, 442, 451, 1403, 579, 601, 615, + 627, 633, 634, 636, 637, 638, 639, 640, 643, 641, + 407, 311, 495, 333, 373, 1392, 1435, 425, 472, 240, + 605, 496, 199, 1306, 1311, 1304, 0, 254, 255, 1374, + 575, 1307, 1305, 1363, 1364, 1308, 1426, 1427, 1428, 1413, + 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 648, 508, + 514, 509, 510, 511, 512, 513, 0, 515, 1396, 1300, + 0, 1309, 1310, 398, 1405, 591, 592, 671, 384, 486, + 602, 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, 618, 619, 623, 205, 462, 463, 464, 465, 292, + 613, 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, 1367, 196, 221, 368, 1431, 454, + 288, 649, 617, 484, 612, 206, 223, 1303, 262, 1315, + 1323, 0, 1329, 1337, 1338, 1351, 1354, 1355, 1356, 1357, + 1375, 1376, 1378, 1386, 1388, 1391, 1393, 1400, 1414, 1434, + 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, 604, 624, + 631, 480, 301, 302, 444, 445, 314, 315, 645, 646, + 300, 599, 632, 596, 644, 626, 438, 378, 1366, 1372, + 381, 281, 305, 320, 1381, 616, 502, 227, 466, 290, + 251, 1399, 1401, 211, 246, 230, 259, 274, 277, 324, + 391, 400, 429, 434, 296, 271, 244, 459, 241, 485, + 519, 520, 521, 523, 395, 266, 433, 1362, 1390, 376, + 576, 577, 316, 396, 0, 0, 0, 0, 0, 0, + 1420, 1404, 528, 0, 1346, 1423, 1314, 1333, 1433, 1336, + 1339, 1383, 1292, 1361, 416, 1330, 1318, 1287, 1325, 1288, + 1316, 1348, 270, 1313, 1406, 1365, 1422, 366, 267, 1294, + 1285, 204, 505, 1319, 430, 1335, 203, 1385, 487, 252, + 377, 374, 583, 282, 273, 269, 250, 317, 385, 428, + 518, 422, 1429, 370, 1371, 0, 497, 401, 0, 0, + 0, 1410, 1409, 1340, 1350, 1412, 1359, 1397, 1345, 1384, + 1302, 1370, 1424, 1331, 1380, 1425, 323, 248, 325, 202, + 413, 498, 286, 0, 0, 0, 0, 0, 507, 958, + 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, 1327, 1377, + 608, 1419, 1328, 1379, 265, 321, 272, 264, 580, 1430, + 1411, 1291, 1358, 1418, 1353, 0, 0, 229, 1421, 1352, + 0, 1382, 0, 1436, 1286, 1373, 0, 1289, 1293, 1432, + 1416, 1322, 275, 0, 0, 0, 0, 0, 0, 0, + 1349, 1360, 1394, 1398, 1343, 0, 0, 0, 0, 0, + 0, 0, 0, 1320, 0, 1369, 0, 0, 0, 1298, + 1290, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1347, 0, 0, 0, 0, 1301, 0, + 1321, 1395, 0, 1284, 297, 1295, 402, 257, 0, 453, + 1402, 1415, 1344, 628, 1417, 1342, 1341, 1389, 1299, 1408, + 1334, 365, 1297, 330, 197, 225, 0, 1332, 412, 461, + 473, 1407, 1317, 1326, 253, 1324, 471, 426, 603, 233, + 284, 458, 432, 469, 440, 287, 1368, 1387, 470, 372, + 585, 450, 600, 629, 630, 263, 406, 614, 522, 622, + 647, 226, 260, 420, 506, 606, 494, 397, 581, 582, + 329, 493, 295, 201, 369, 635, 224, 479, 371, 242, + 231, 587, 611, 299, 289, 456, 642, 213, 517, 597, + 239, 483, 0, 0, 650, 247, 504, 609, 598, 215, + 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, + 0, 0, 258, 415, 589, 590, 256, 651, 228, 621, + 220, 1296, 620, 408, 584, 595, 394, 383, 219, 593, + 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, + 306, 308, 404, 403, 405, 207, 607, 625, 0, 208, + 0, 499, 610, 652, 452, 212, 234, 235, 237, 1312, + 279, 283, 291, 294, 303, 304, 313, 367, 419, 446, + 442, 451, 1403, 579, 601, 615, 627, 633, 634, 636, + 637, 638, 639, 640, 643, 641, 407, 311, 495, 333, + 373, 1392, 1435, 425, 472, 240, 605, 496, 199, 1306, + 1311, 1304, 0, 254, 255, 1374, 575, 1307, 1305, 1363, + 1364, 1308, 1426, 1427, 1428, 1413, 653, 654, 655, 656, + 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 648, 508, 514, 509, 510, 511, + 512, 513, 0, 515, 1396, 1300, 0, 1309, 1310, 398, + 1405, 591, 592, 671, 384, 486, 602, 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, 618, 619, 623, + 205, 462, 463, 464, 465, 292, 613, 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, + 1367, 196, 221, 368, 1431, 454, 288, 649, 617, 484, + 612, 206, 223, 1303, 262, 1315, 1323, 0, 1329, 1337, + 1338, 1351, 1354, 1355, 1356, 1357, 1375, 1376, 1378, 1386, + 1388, 1391, 1393, 1400, 1414, 1434, 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, 604, 624, 631, 480, 301, 302, + 444, 445, 314, 315, 645, 646, 300, 599, 632, 596, + 644, 626, 438, 378, 1366, 1372, 381, 281, 305, 320, + 1381, 616, 502, 227, 466, 290, 251, 1399, 1401, 211, + 246, 230, 259, 274, 277, 324, 391, 400, 429, 434, + 296, 271, 244, 459, 241, 485, 519, 520, 521, 523, + 395, 266, 433, 1362, 1390, 376, 576, 577, 316, 396, + 0, 0, 0, 0, 0, 0, 0, 0, 528, 0, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 2229, 2230, 2231, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, - 0, 737, 754, 0, 768, 0, 0, 0, 275, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 751, 752, 0, 0, 0, - 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, 1015, 763, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 297, 0, 402, 257, 0, 453, 911, 0, 0, 624, - 0, 0, 909, 0, 0, 0, 0, 365, 0, 330, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 962, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 963, 964, - 256, 647, 808, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 816, 817, 280, - 307, 893, 892, 891, 306, 308, 889, 890, 888, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 899, 921, 910, 774, 775, 900, 901, 925, 902, - 777, 778, 922, 923, 771, 772, 776, 924, 926, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 913, 760, 759, - 0, 766, 767, 0, 796, 797, 799, 805, 806, 807, - 818, 865, 866, 874, 876, 877, 875, 878, 879, 880, - 883, 884, 885, 886, 881, 882, 887, 779, 783, 780, - 781, 782, 794, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 795, 936, 937, 938, 939, 940, 941, - 811, 815, 814, 812, 813, 809, 810, 837, 836, 838, - 839, 840, 841, 842, 843, 845, 844, 846, 847, 848, - 849, 850, 851, 819, 820, 823, 824, 822, 821, 825, - 834, 835, 826, 827, 828, 829, 830, 831, 833, 832, - 852, 853, 854, 855, 856, 858, 857, 861, 862, 860, - 859, 864, 863, 758, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 206, 223, 927, 262, 928, 0, - 0, 932, 0, 0, 0, 934, 933, 0, 935, 897, - 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, 621, 627, - 480, 942, 943, 944, 945, 946, 947, 948, 949, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 967, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 0, 770, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, - 757, 0, 0, 0, 270, 762, 0, 0, 0, 366, - 267, 0, 0, 204, 505, 0, 430, 0, 203, 0, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 769, 370, 0, 0, 497, 401, - 0, 0, 0, 0, 0, 764, 765, 0, 0, 0, - 0, 0, 0, 2416, 0, 323, 248, 325, 202, 413, - 498, 286, 0, 95, 0, 0, 1016, 952, 741, 918, - 956, 1017, 969, 970, 971, 957, 0, 238, 958, 959, - 245, 960, 0, 917, 800, 802, 801, 867, 868, 869, - 870, 871, 872, 873, 803, 804, 798, 965, 606, 972, - 973, 2417, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, - 0, 0, 0, 737, 754, 0, 768, 0, 0, 0, - 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 751, 752, 0, - 0, 0, 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, - 1015, 763, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 297, 0, 402, 257, 0, 453, 911, 0, - 0, 624, 0, 0, 909, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 962, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 963, 964, 256, 647, 808, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 816, - 817, 280, 307, 893, 892, 891, 306, 308, 889, 890, - 888, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 899, 921, 910, 774, 775, 900, 901, - 925, 902, 777, 778, 922, 923, 771, 772, 776, 924, - 926, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 913, - 760, 759, 0, 766, 767, 0, 796, 797, 799, 805, - 806, 807, 818, 865, 866, 874, 876, 877, 875, 878, - 879, 880, 883, 884, 885, 886, 881, 882, 887, 779, - 783, 780, 781, 782, 794, 784, 785, 786, 787, 788, - 789, 790, 791, 792, 793, 795, 936, 937, 938, 939, - 940, 941, 811, 815, 814, 812, 813, 809, 810, 837, - 836, 838, 839, 840, 841, 842, 843, 845, 844, 846, - 847, 848, 849, 850, 851, 819, 820, 823, 824, 822, - 821, 825, 834, 835, 826, 827, 828, 829, 830, 831, - 833, 832, 852, 853, 854, 855, 856, 858, 857, 861, - 862, 860, 859, 864, 863, 758, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 206, 223, 927, 262, - 928, 0, 0, 932, 0, 0, 0, 934, 933, 0, - 935, 897, 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, - 621, 627, 480, 942, 943, 944, 945, 946, 947, 948, - 949, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 967, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 86, 527, 0, 770, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, - 0, 0, 757, 0, 0, 0, 270, 762, 0, 0, - 0, 366, 267, 0, 0, 204, 505, 0, 430, 0, - 203, 0, 487, 252, 377, 374, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 769, 370, 0, 0, - 497, 401, 0, 0, 0, 0, 0, 764, 765, 0, - 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, - 202, 413, 498, 286, 0, 95, 0, 0, 1016, 952, - 741, 918, 956, 1017, 969, 970, 971, 957, 0, 238, - 958, 959, 245, 960, 0, 917, 800, 802, 801, 867, - 868, 869, 870, 871, 872, 873, 803, 804, 798, 965, - 606, 972, 973, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, - 0, 0, 0, 0, 0, 737, 754, 0, 768, 0, - 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 751, - 752, 0, 0, 0, 0, 912, 0, 753, 0, 0, - 761, 974, 975, 976, 977, 978, 979, 980, 981, 982, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 2436, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 2437, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 763, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 911, 0, 0, 624, 0, 0, 909, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 962, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 963, 964, 256, 647, 808, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 816, 817, 280, 307, 893, 892, 891, 306, 308, - 889, 890, 888, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 899, 921, 910, 774, 775, - 900, 901, 925, 902, 777, 778, 922, 923, 771, 772, - 776, 924, 926, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 913, 760, 759, 0, 766, 767, 0, 796, 797, - 799, 805, 806, 807, 818, 865, 866, 874, 876, 877, - 875, 878, 879, 880, 883, 884, 885, 886, 881, 882, - 887, 779, 783, 780, 781, 782, 794, 784, 785, 786, - 787, 788, 789, 790, 791, 792, 793, 795, 936, 937, - 938, 939, 940, 941, 811, 815, 814, 812, 813, 809, - 810, 837, 836, 838, 839, 840, 841, 842, 843, 845, - 844, 846, 847, 848, 849, 850, 851, 819, 820, 823, - 824, 822, 821, 825, 834, 835, 826, 827, 828, 829, - 830, 831, 833, 832, 852, 853, 854, 855, 856, 858, - 857, 861, 862, 860, 859, 864, 863, 758, 196, 221, - 368, 94, 454, 288, 645, 614, 484, 609, 206, 223, - 927, 262, 928, 0, 0, 932, 0, 0, 0, 934, - 933, 0, 935, 897, 896, 0, 0, 929, 930, 0, - 931, 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, 515, 585, - 587, 602, 621, 627, 480, 942, 943, 944, 945, 946, - 947, 948, 949, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 967, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, - 770, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 757, 0, 0, 0, 270, 762, + 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 769, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, 0, 0, 0, 366, 267, 0, 0, 204, 505, 0, - 430, 0, 203, 0, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 769, 370, - 0, 0, 497, 401, 0, 0, 0, 0, 0, 764, - 765, 0, 0, 0, 0, 0, 0, 0, 0, 323, - 248, 325, 202, 413, 498, 286, 0, 95, 0, 0, - 1016, 952, 741, 918, 956, 1017, 969, 970, 971, 957, - 0, 238, 958, 959, 245, 960, 0, 917, 800, 802, - 801, 867, 868, 869, 870, 871, 872, 873, 803, 804, - 798, 965, 606, 972, 973, 0, 265, 321, 272, 264, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 229, - 0, 0, 0, 0, 0, 0, 0, 737, 754, 0, - 768, 0, 0, 0, 275, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 751, 752, 0, 0, 0, 0, 912, 0, 753, - 0, 0, 761, 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, 1012, 1013, 1014, 1015, 763, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 911, 0, 0, 624, 0, 0, 909, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 962, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 4070, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 963, 964, 256, 647, 808, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 816, 817, 280, 307, 893, 892, 891, - 306, 308, 889, 890, 888, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 899, 921, 910, - 774, 775, 900, 901, 925, 902, 777, 778, 922, 923, - 771, 772, 776, 924, 926, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 913, 760, 759, 0, 766, 767, 0, - 796, 797, 799, 805, 806, 807, 818, 865, 866, 874, - 876, 877, 875, 878, 879, 880, 883, 884, 885, 886, - 881, 882, 887, 779, 783, 780, 781, 782, 794, 784, - 785, 786, 787, 788, 789, 790, 791, 792, 793, 795, - 936, 937, 938, 939, 940, 941, 811, 815, 814, 812, - 813, 809, 810, 837, 836, 838, 839, 840, 841, 842, - 843, 845, 844, 846, 847, 848, 849, 850, 851, 819, - 820, 823, 824, 822, 821, 825, 834, 835, 826, 827, - 828, 829, 830, 831, 833, 832, 852, 853, 854, 855, - 856, 858, 857, 861, 862, 860, 859, 864, 863, 758, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 206, 223, 927, 262, 928, 0, 0, 932, 0, 0, - 0, 934, 933, 0, 935, 897, 896, 0, 0, 929, - 930, 0, 931, 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, - 515, 585, 587, 602, 621, 627, 480, 942, 943, 944, - 945, 946, 947, 948, 949, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 967, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 0, 770, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 0, 0, 757, 0, 0, 0, - 270, 762, 0, 0, 0, 366, 267, 0, 0, 204, - 505, 0, 430, 0, 203, 0, 487, 252, 377, 374, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 769, 370, 0, 0, 497, 401, 0, 0, 0, 0, - 0, 764, 765, 0, 0, 0, 0, 0, 0, 0, - 0, 323, 248, 325, 202, 413, 498, 286, 0, 95, - 0, 1736, 1016, 952, 741, 918, 956, 1017, 969, 970, - 971, 957, 0, 238, 958, 959, 245, 960, 0, 917, - 800, 802, 801, 867, 868, 869, 870, 871, 872, 873, - 803, 804, 798, 965, 606, 972, 973, 0, 265, 321, - 272, 264, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 229, 0, 0, 0, 0, 0, 0, 0, 737, - 754, 0, 768, 0, 0, 0, 275, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 751, 752, 0, 0, 0, 0, 912, - 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, 1015, 763, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 297, 0, - 402, 257, 0, 453, 911, 0, 0, 624, 0, 0, - 909, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 962, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 963, 964, 256, 647, - 808, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 816, 817, 280, 307, 893, - 892, 891, 306, 308, 889, 890, 888, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 899, - 921, 910, 774, 775, 900, 901, 925, 902, 777, 778, - 922, 923, 771, 772, 776, 924, 926, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 913, 760, 759, 0, 766, - 767, 0, 796, 797, 799, 805, 806, 807, 818, 865, - 866, 874, 876, 877, 875, 878, 879, 880, 883, 884, - 885, 886, 881, 882, 887, 779, 783, 780, 781, 782, - 794, 784, 785, 786, 787, 788, 789, 790, 791, 792, - 793, 795, 936, 937, 938, 939, 940, 941, 811, 815, - 814, 812, 813, 809, 810, 837, 836, 838, 839, 840, - 841, 842, 843, 845, 844, 846, 847, 848, 849, 850, - 851, 819, 820, 823, 824, 822, 821, 825, 834, 835, - 826, 827, 828, 829, 830, 831, 833, 832, 852, 853, - 854, 855, 856, 858, 857, 861, 862, 860, 859, 864, - 863, 758, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 206, 223, 927, 262, 928, 0, 0, 932, - 0, 0, 0, 934, 933, 0, 935, 897, 896, 0, - 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, 621, 627, 480, 942, - 943, 944, 945, 946, 947, 948, 949, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 967, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 0, 770, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 757, 0, - 0, 0, 270, 762, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 769, 370, 0, 0, 497, 401, 0, 0, - 0, 0, 0, 764, 765, 0, 0, 0, 0, 0, - 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, - 0, 95, 0, 0, 1016, 952, 741, 918, 956, 1017, - 969, 970, 971, 957, 0, 238, 958, 959, 245, 960, - 0, 917, 800, 802, 801, 867, 868, 869, 870, 871, - 872, 873, 803, 804, 798, 965, 606, 972, 973, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 430, 0, 203, 0, 487, 252, 377, 374, 583, 282, + 273, 269, 250, 317, 385, 428, 518, 422, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, - 0, 737, 754, 0, 768, 0, 0, 0, 275, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 751, 752, 1062, 0, 0, - 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, 1015, 763, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 297, 0, 402, 257, 0, 453, 911, 0, 0, 624, - 0, 0, 909, 0, 0, 0, 0, 365, 0, 330, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 962, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 963, 964, - 256, 647, 808, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 816, 817, 280, - 307, 893, 892, 891, 306, 308, 889, 890, 888, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 899, 921, 910, 774, 775, 900, 901, 925, 902, - 777, 778, 922, 923, 771, 772, 776, 924, 926, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 913, 760, 759, - 0, 766, 767, 0, 796, 797, 799, 805, 806, 807, - 818, 865, 866, 874, 876, 877, 875, 878, 879, 880, - 883, 884, 885, 886, 881, 882, 887, 779, 783, 780, - 781, 782, 794, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 795, 936, 937, 938, 939, 940, 941, - 811, 815, 814, 812, 813, 809, 810, 837, 836, 838, - 839, 840, 841, 842, 843, 845, 844, 846, 847, 848, - 849, 850, 851, 819, 820, 823, 824, 822, 821, 825, - 834, 835, 826, 827, 828, 829, 830, 831, 833, 832, - 852, 853, 854, 855, 856, 858, 857, 861, 862, 860, - 859, 864, 863, 758, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 206, 223, 927, 262, 928, 0, - 0, 932, 0, 0, 0, 934, 933, 0, 935, 897, - 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, 621, 627, - 480, 942, 943, 944, 945, 946, 947, 948, 949, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 967, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 0, 770, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, - 757, 0, 0, 0, 270, 762, 0, 0, 0, 366, - 267, 0, 0, 204, 505, 0, 430, 0, 203, 0, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 769, 370, 0, 0, 497, 401, - 0, 0, 0, 0, 0, 764, 765, 0, 0, 0, - 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, - 498, 286, 0, 95, 0, 0, 1016, 952, 741, 918, - 956, 1017, 969, 970, 971, 957, 0, 238, 958, 959, - 245, 960, 0, 917, 800, 802, 801, 867, 868, 869, - 870, 871, 872, 873, 803, 804, 798, 965, 606, 972, - 973, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, - 0, 0, 0, 737, 754, 0, 768, 0, 0, 0, - 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 751, 752, 0, - 0, 0, 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, - 1015, 763, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 297, 0, 402, 257, 0, 453, 911, 0, - 0, 624, 0, 0, 909, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 962, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 963, 964, 256, 647, 808, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 816, - 817, 280, 307, 893, 892, 891, 306, 308, 889, 890, - 888, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 899, 921, 910, 774, 775, 900, 901, - 925, 902, 777, 778, 922, 923, 771, 772, 776, 924, - 926, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 913, - 760, 759, 0, 766, 767, 0, 796, 797, 799, 805, - 806, 807, 818, 865, 866, 874, 876, 877, 875, 878, - 879, 880, 883, 884, 885, 886, 881, 882, 887, 779, - 783, 780, 781, 782, 794, 784, 785, 786, 787, 788, - 789, 790, 791, 792, 793, 795, 936, 937, 938, 939, - 940, 941, 811, 815, 814, 812, 813, 809, 810, 837, - 836, 838, 839, 840, 841, 842, 843, 845, 844, 846, - 847, 848, 849, 850, 851, 819, 820, 823, 824, 822, - 821, 825, 834, 835, 826, 827, 828, 829, 830, 831, - 833, 832, 852, 853, 854, 855, 856, 858, 857, 861, - 862, 860, 859, 864, 863, 758, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 206, 223, 927, 262, - 928, 0, 0, 932, 0, 0, 0, 934, 933, 0, - 935, 897, 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, - 621, 627, 480, 942, 943, 944, 945, 946, 947, 948, - 949, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 967, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 0, 770, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, - 0, 0, 757, 0, 0, 0, 270, 762, 0, 0, - 0, 366, 267, 0, 0, 204, 505, 0, 430, 0, - 203, 0, 487, 252, 377, 374, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 769, 370, 0, 0, - 497, 401, 0, 0, 0, 0, 0, 764, 765, 0, - 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, - 202, 413, 498, 286, 0, 95, 0, 0, 1016, 952, - 741, 918, 956, 1017, 969, 970, 971, 957, 0, 238, - 958, 959, 245, 960, 0, 917, 800, 802, 801, 867, - 868, 869, 870, 871, 872, 873, 803, 804, 798, 965, - 606, 972, 973, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, - 0, 0, 0, 0, 0, 737, 754, 0, 768, 0, - 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 751, - 752, 0, 0, 0, 0, 912, 0, 753, 0, 0, - 761, 974, 975, 976, 977, 978, 979, 980, 981, 982, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 94, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 3145, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 911, 0, 0, 624, 0, 0, 909, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 962, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 963, 964, 256, 647, 808, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 816, 817, 280, 307, 893, 892, 891, 306, 308, - 889, 890, 888, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 899, 921, 910, 774, 775, - 900, 901, 925, 902, 777, 778, 922, 923, 771, 772, - 776, 924, 926, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 913, 760, 759, 0, 766, 767, 0, 796, 797, - 799, 805, 806, 807, 818, 865, 866, 874, 876, 877, - 875, 878, 879, 880, 883, 884, 885, 886, 881, 882, - 887, 779, 783, 780, 781, 782, 794, 784, 785, 786, - 787, 788, 789, 790, 791, 792, 793, 795, 936, 937, - 938, 939, 940, 941, 811, 815, 814, 812, 813, 809, - 810, 837, 836, 838, 839, 840, 841, 842, 843, 845, - 844, 846, 847, 848, 849, 850, 851, 819, 820, 823, - 824, 822, 821, 825, 834, 835, 826, 827, 828, 829, - 830, 831, 833, 832, 852, 853, 854, 855, 856, 858, - 857, 861, 862, 860, 859, 864, 863, 758, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 206, 223, - 927, 262, 928, 0, 0, 932, 0, 0, 0, 934, - 933, 0, 935, 897, 896, 0, 0, 929, 930, 0, - 931, 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, 515, 585, - 587, 602, 621, 627, 480, 942, 943, 944, 945, 946, - 947, 948, 949, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 967, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, - 770, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 757, 0, 0, 0, 270, 762, + 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 769, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 4094, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, 0, 0, 0, 366, 267, 0, 0, 204, 505, 0, - 430, 0, 203, 0, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 769, 370, - 0, 0, 497, 401, 0, 0, 0, 0, 0, 764, - 765, 0, 0, 0, 0, 0, 0, 0, 0, 323, - 248, 325, 202, 413, 498, 286, 0, 95, 0, 0, - 1016, 952, 741, 918, 956, 1017, 969, 970, 971, 957, - 0, 238, 958, 959, 245, 960, 0, 917, 800, 802, - 801, 867, 868, 869, 870, 871, 872, 873, 803, 804, - 798, 965, 606, 972, 973, 0, 265, 321, 272, 264, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 229, - 0, 0, 0, 0, 0, 0, 0, 737, 754, 0, - 768, 0, 0, 0, 275, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 751, 752, 0, 0, 0, 0, 912, 0, 753, - 0, 0, 761, 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, 1012, 1013, 1014, 1015, 3141, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 911, 0, 0, 624, 0, 0, 909, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 962, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 963, 964, 256, 647, 808, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 816, 817, 280, 307, 893, 892, 891, - 306, 308, 889, 890, 888, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 899, 921, 910, - 774, 775, 900, 901, 925, 902, 777, 778, 922, 923, - 771, 772, 776, 924, 926, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 913, 760, 759, 0, 766, 767, 0, - 796, 797, 799, 805, 806, 807, 818, 865, 866, 874, - 876, 877, 875, 878, 879, 880, 883, 884, 885, 886, - 881, 882, 887, 779, 783, 780, 781, 782, 794, 784, - 785, 786, 787, 788, 789, 790, 791, 792, 793, 795, - 936, 937, 938, 939, 940, 941, 811, 815, 814, 812, - 813, 809, 810, 837, 836, 838, 839, 840, 841, 842, - 843, 845, 844, 846, 847, 848, 849, 850, 851, 819, - 820, 823, 824, 822, 821, 825, 834, 835, 826, 827, - 828, 829, 830, 831, 833, 832, 852, 853, 854, 855, - 856, 858, 857, 861, 862, 860, 859, 864, 863, 758, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 206, 223, 927, 262, 928, 0, 0, 932, 0, 0, - 0, 934, 933, 0, 935, 897, 896, 0, 0, 929, - 930, 0, 931, 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, - 515, 585, 587, 602, 621, 627, 480, 942, 943, 944, - 945, 946, 947, 948, 949, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 967, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 0, 770, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 0, 0, 757, 0, 0, 0, - 270, 762, 0, 0, 0, 366, 267, 0, 0, 204, - 505, 0, 430, 0, 203, 0, 487, 252, 377, 374, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 769, 370, 0, 0, 497, 401, 0, 0, 0, 0, - 0, 764, 765, 0, 0, 0, 0, 0, 0, 0, - 0, 323, 248, 325, 202, 413, 498, 286, 0, 95, - 0, 0, 1016, 952, 1083, 918, 956, 1017, 969, 970, - 971, 957, 0, 238, 958, 959, 245, 960, 0, 917, - 800, 802, 801, 867, 868, 869, 870, 871, 872, 873, - 803, 804, 798, 965, 606, 972, 973, 0, 265, 321, - 272, 264, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, - 754, 0, 768, 0, 0, 0, 275, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 751, 752, 0, 0, 0, 0, 912, - 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, 1015, 763, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 297, 0, - 402, 257, 0, 453, 911, 0, 0, 624, 0, 0, - 909, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 962, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 963, 964, 256, 647, - 808, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 816, 817, 280, 307, 893, - 892, 891, 306, 308, 889, 890, 888, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 899, - 921, 910, 774, 775, 900, 901, 925, 902, 777, 778, - 922, 923, 771, 772, 776, 924, 926, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 913, 760, 759, 0, 766, - 767, 0, 796, 797, 799, 805, 806, 807, 818, 865, - 866, 874, 876, 877, 875, 878, 879, 880, 883, 884, - 885, 886, 881, 882, 887, 779, 783, 780, 781, 782, - 794, 784, 785, 786, 787, 788, 789, 790, 791, 792, - 793, 795, 936, 937, 938, 939, 940, 941, 811, 815, - 814, 812, 813, 809, 810, 837, 836, 838, 839, 840, - 841, 842, 843, 845, 844, 846, 847, 848, 849, 850, - 851, 819, 820, 823, 824, 822, 821, 825, 834, 835, - 826, 827, 828, 829, 830, 831, 833, 832, 852, 853, - 854, 855, 856, 858, 857, 861, 862, 860, 859, 864, - 863, 758, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 206, 223, 927, 262, 928, 0, 0, 932, - 0, 0, 0, 934, 933, 0, 935, 897, 896, 0, - 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, 621, 627, 480, 942, - 943, 944, 945, 946, 947, 948, 949, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 967, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 0, 770, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 757, 0, - 0, 0, 270, 762, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 769, 370, 0, 0, 497, 401, 0, 0, - 0, 0, 0, 764, 765, 0, 0, 0, 0, 0, - 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, - 0, 95, 0, 0, 1016, 952, 1083, 918, 956, 1017, - 969, 970, 971, 957, 0, 238, 958, 959, 245, 960, - 0, 917, 800, 802, 801, 867, 868, 869, 870, 871, - 872, 873, 803, 804, 798, 965, 606, 972, 973, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 430, 0, 203, 0, 487, 252, 377, 374, 583, 282, + 273, 269, 250, 317, 385, 428, 518, 422, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 1751, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, - 0, 0, 754, 0, 768, 0, 0, 0, 275, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 751, 752, 0, 0, 0, - 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, 1015, 2100, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 297, 0, 402, 257, 0, 453, 911, 0, 0, 624, - 0, 0, 909, 0, 0, 0, 0, 365, 0, 330, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 962, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 963, 964, - 256, 647, 808, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 816, 817, 280, - 307, 893, 892, 891, 306, 308, 889, 890, 888, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 899, 921, 910, 774, 775, 900, 901, 925, 902, - 777, 778, 922, 923, 771, 772, 776, 924, 926, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 913, 760, 759, - 0, 766, 767, 0, 796, 797, 799, 805, 806, 807, - 818, 865, 866, 874, 876, 877, 875, 878, 879, 880, - 883, 884, 885, 886, 881, 882, 887, 779, 783, 780, - 781, 782, 794, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 795, 936, 937, 938, 939, 940, 941, - 811, 815, 814, 812, 813, 809, 810, 837, 836, 838, - 839, 840, 841, 842, 843, 845, 844, 846, 847, 848, - 849, 850, 851, 819, 820, 823, 824, 822, 821, 825, - 834, 835, 826, 827, 828, 829, 830, 831, 833, 832, - 852, 853, 854, 855, 856, 858, 857, 861, 862, 860, - 859, 864, 863, 758, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 206, 223, 927, 262, 928, 0, - 0, 932, 0, 0, 0, 934, 933, 0, 935, 897, - 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, 621, 627, - 480, 942, 943, 944, 945, 946, 947, 948, 949, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 967, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 0, 770, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, - 757, 0, 0, 0, 270, 762, 0, 0, 0, 366, - 267, 0, 0, 204, 505, 0, 430, 0, 203, 0, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 769, 370, 0, 0, 497, 401, - 0, 0, 0, 0, 0, 764, 765, 0, 0, 0, - 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, - 498, 286, 0, 95, 0, 0, 1016, 952, 1083, 918, - 956, 1017, 969, 970, 971, 957, 0, 238, 958, 959, - 245, 960, 0, 917, 800, 802, 801, 867, 868, 869, - 870, 871, 872, 873, 803, 804, 798, 965, 606, 972, - 973, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, - 0, 0, 0, 0, 754, 0, 768, 0, 0, 0, - 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 751, 752, 0, - 0, 0, 0, 912, 0, 753, 0, 0, 761, 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, 1012, 1013, 1014, - 1015, 2098, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 297, 0, 402, 257, 0, 453, 911, 0, - 0, 624, 0, 0, 909, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 962, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 963, 964, 256, 647, 808, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 816, - 817, 280, 307, 893, 892, 891, 306, 308, 889, 890, - 888, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 899, 921, 910, 774, 775, 900, 901, - 925, 902, 777, 778, 922, 923, 771, 772, 776, 924, - 926, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 913, - 760, 759, 0, 766, 767, 0, 796, 797, 799, 805, - 806, 807, 818, 865, 866, 874, 876, 877, 875, 878, - 879, 880, 883, 884, 885, 886, 881, 882, 887, 779, - 783, 780, 781, 782, 794, 784, 785, 786, 787, 788, - 789, 790, 791, 792, 793, 795, 936, 937, 938, 939, - 940, 941, 811, 815, 814, 812, 813, 809, 810, 837, - 836, 838, 839, 840, 841, 842, 843, 845, 844, 846, - 847, 848, 849, 850, 851, 819, 820, 823, 824, 822, - 821, 825, 834, 835, 826, 827, 828, 829, 830, 831, - 833, 832, 852, 853, 854, 855, 856, 858, 857, 861, - 862, 860, 859, 864, 863, 758, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 206, 223, 927, 262, - 928, 0, 0, 932, 0, 0, 0, 934, 933, 0, - 935, 897, 896, 0, 0, 929, 930, 0, 931, 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, 515, 585, 587, 602, - 621, 627, 480, 942, 943, 944, 945, 946, 947, 948, - 949, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 967, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 1134, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 1068, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 3169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 747, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 743, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 1133, 624, 0, 0, 0, 0, 0, 1130, - 1131, 365, 1091, 330, 197, 225, 1124, 1128, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 3165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, 0, 0, 0, 366, 267, 0, 0, 204, 505, 0, - 430, 0, 203, 0, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 430, 0, 203, 0, 487, 252, 377, 374, 583, 282, + 273, 269, 250, 317, 385, 428, 518, 422, 775, 370, 0, 0, 497, 401, 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, - 1697, 952, 0, 0, 1694, 0, 0, 0, 0, 1692, - 0, 238, 1693, 1691, 245, 1696, 0, 917, 351, 360, - 359, 339, 340, 342, 344, 350, 357, 363, 336, 345, - 0, 0, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 229, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 1089, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 760, 0, 774, 0, 0, 0, 275, 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, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 1089, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 2120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 0, 763, 0, 0, 0, 270, 768, + 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, 775, 370, + 0, 0, 497, 401, 0, 0, 0, 0, 0, 0, + 0, 0, 770, 771, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 1022, 507, 958, 1089, 924, 962, 1023, + 975, 976, 977, 963, 0, 238, 964, 965, 245, 966, + 0, 923, 806, 808, 807, 873, 874, 875, 876, 877, + 878, 879, 809, 810, 804, 971, 608, 978, 979, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 760, 0, 774, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 758, 0, 0, 0, + 0, 918, 0, 759, 0, 0, 767, 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, 1019, 1020, 1021, 2118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 917, 0, 0, 628, + 0, 0, 915, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 968, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 969, 970, 256, 651, 814, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 822, + 823, 280, 307, 899, 898, 897, 306, 308, 895, 896, + 894, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 905, 927, 916, 780, 781, 906, + 907, 931, 908, 783, 784, 928, 929, 777, 778, 782, + 930, 932, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 919, 766, 765, 0, 772, 773, 0, 802, 803, 805, + 811, 812, 813, 824, 871, 872, 880, 882, 883, 881, + 884, 885, 886, 889, 890, 891, 892, 887, 888, 893, + 785, 789, 786, 787, 788, 800, 790, 791, 792, 793, + 794, 795, 796, 797, 798, 799, 801, 942, 943, 944, + 945, 946, 947, 817, 821, 820, 818, 819, 815, 816, + 843, 842, 844, 845, 846, 847, 848, 849, 851, 850, + 852, 853, 854, 855, 856, 857, 825, 826, 829, 830, + 828, 827, 831, 840, 841, 832, 833, 834, 835, 836, + 837, 839, 838, 858, 859, 860, 861, 862, 864, 863, + 867, 868, 866, 865, 870, 869, 764, 196, 221, 368, + 0, 454, 288, 649, 617, 484, 612, 206, 223, 933, + 262, 934, 0, 0, 938, 0, 0, 0, 940, 939, + 0, 941, 903, 902, 0, 0, 935, 936, 0, 937, + 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, + 604, 624, 631, 480, 948, 949, 950, 951, 952, 953, + 954, 955, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 502, 227, + 466, 290, 251, 973, 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, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 86, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 94, 454, 288, 645, 614, - 484, 609, 206, 223, 0, 262, 0, 0, 0, 0, - 0, 0, 2403, 0, 0, 2402, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 1759, 0, 376, 575, 576, 316, - 0, 0, 527, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 1761, 0, 0, - 0, 0, 270, 0, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 1763, 717, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, - 0, 0, 0, 229, 0, 0, 0, 1465, 0, 1466, - 1467, 0, 0, 0, 0, 0, 0, 0, 275, 0, + 357, 363, 336, 345, 0, 0, 608, 0, 0, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 1140, 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, @@ -4578,72 +4460,72 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, - 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, - 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 86, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 1736, 0, 717, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 1139, 628, + 0, 0, 0, 0, 0, 1136, 1137, 365, 1097, 330, + 197, 225, 1130, 1134, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, - 275, 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, 1708, 507, 958, 0, 0, 1705, 0, + 0, 0, 0, 1703, 0, 238, 1704, 1702, 245, 1707, + 0, 923, 351, 360, 359, 339, 340, 342, 344, 350, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -4651,72 +4533,74 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 94, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 608, 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, 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, @@ -4724,72 +4608,72 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 206, 223, - 0, 262, 0, 0, 0, 0, 0, 0, 2403, 0, - 0, 2402, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 2350, 0, 0, 0, 0, 270, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 206, 223, 0, + 262, 0, 0, 0, 0, 0, 0, 2423, 0, 0, + 2422, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1774, + 0, 376, 576, 577, 316, 0, 0, 0, 528, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 416, 0, 0, 1776, 0, 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, 0, - 430, 0, 203, 0, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 1942, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 1778, 507, 723, 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, 608, 0, 0, 0, + 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 0, 0, 0, 1476, 0, 1477, + 1478, 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, @@ -4797,143 +4681,71 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 2348, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 717, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 1085, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 1091, 330, 197, 225, - 1089, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 2350, 0, 0, - 0, 0, 270, 0, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 1942, 194, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1751, 0, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -4944,72 +4756,73 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 1736, 0, 717, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 608, 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, - 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, @@ -5017,291 +4830,147 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 3701, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 2109, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 206, 223, 0, + 262, 0, 0, 0, 0, 0, 0, 2423, 0, 0, + 2422, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 2370, 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, 1958, 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, 608, 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, 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, - 2110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 2368, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 2852, 717, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 2853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 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, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 717, 0, 0, 0, 0, 2837, 0, - 0, 0, 0, 238, 0, 0, 245, 2838, 0, 0, - 351, 360, 359, 339, 340, 342, 344, 350, 357, 363, - 336, 345, 0, 0, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 270, 1782, 0, 0, 0, 366, 267, 0, - 0, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 1781, 717, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, 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, 0, 0, @@ -5309,73 +4978,73 @@ 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, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 1097, 330, + 197, 225, 1095, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 2370, 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, 1958, 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, 608, 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, - 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, - 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 719, 720, 721, - 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 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, @@ -5383,72 +5052,72 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, - 0, 0, 275, 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, 1751, 0, 507, 723, 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, 608, 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, @@ -5456,292 +5125,296 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 4045, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 3725, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 1942, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 2129, 507, 723, 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, 608, 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, 2130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 717, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 3701, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 717, 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, 2876, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, 2877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 0, 0, 0, 0, + 2861, 0, 0, 0, 0, 238, 0, 0, 245, 2862, + 0, 0, 351, 360, 359, 339, 340, 342, 344, 350, + 357, 363, 336, 345, 0, 0, 608, 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, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 0, 0, 0, 0, 2404, - 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1797, + 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, 1796, 507, 723, 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, 608, 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, - 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, @@ -5749,72 +5422,73 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 1763, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 725, 726, 727, 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, 608, 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, 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, @@ -5822,72 +5496,72 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 0, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 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, 608, 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, @@ -5895,143 +5569,959 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 2056, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 2047, 717, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 717, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 4069, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1958, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 3725, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 2424, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1778, 507, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, + 2076, 454, 288, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 2067, 507, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1925, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1923, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -6042,362 +6532,218 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 717, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 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, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1911, 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, 723, 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, 608, 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, - 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, - 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 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, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 723, 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, 608, 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, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 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, 1903, 204, 505, 0, - 430, 0, 203, 0, 487, 252, 377, 374, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, - 0, 0, 497, 401, 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, 717, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, 1901, 204, - 505, 0, 430, 0, 203, 0, 487, 252, 377, 374, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 717, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 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, - 1897, 204, 505, 0, 430, 0, 203, 0, 487, 252, - 377, 374, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 717, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 1884, 0, 0, 0, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -6408,72 +6754,73 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 1895, 204, 505, 0, 430, 0, 203, 0, - 487, 252, 377, 374, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 717, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 1782, 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, 608, 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, - 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, @@ -6481,72 +6828,72 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 1893, 204, 505, 0, 430, 0, - 203, 0, 487, 252, 377, 374, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 717, - 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 275, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 95, 0, 0, 0, 507, 958, 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, 608, 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, @@ -6554,216 +6901,145 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 1868, 0, 0, - 0, 717, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 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, 608, 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, 1455, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 1454, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, - 0, 0, 0, 0, 0, 0, 297, 0, 402, 257, - 0, 453, 0, 0, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 1767, - 270, 0, 0, 0, 0, 366, 267, 0, 0, 204, - 505, 0, 430, 0, 203, 0, 487, 252, 377, 374, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 952, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -6774,72 +7050,73 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 206, 223, 0, + 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1048, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 608, 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, - 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, @@ -6847,72 +7124,72 @@ 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, - 1444, 0, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 674, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 1443, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 275, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 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, 608, 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, @@ -6920,216 +7197,71 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 206, 223, - 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1042, - 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 396, 0, 376, 575, 576, 316, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, 4135, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 582, 282, - 273, 269, 250, 317, 385, 428, 517, 422, 0, 370, + 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, 323, - 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, - 0, 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, 606, 0, 0, 0, 265, 321, 272, 264, - 579, 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, 670, 0, 624, 0, 0, 0, 0, - 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, - 412, 461, 473, 0, 0, 0, 253, 0, 471, 426, - 601, 233, 284, 458, 432, 469, 440, 287, 0, 0, - 470, 372, 584, 450, 598, 625, 626, 263, 406, 611, - 521, 619, 643, 226, 260, 420, 506, 604, 494, 397, - 580, 581, 329, 493, 295, 201, 369, 631, 224, 479, - 371, 242, 231, 586, 608, 299, 289, 456, 638, 213, - 516, 596, 239, 483, 0, 0, 646, 247, 504, 215, - 593, 503, 393, 326, 327, 214, 0, 457, 268, 293, - 0, 0, 258, 415, 588, 589, 256, 647, 228, 618, - 220, 0, 617, 408, 583, 594, 394, 383, 219, 592, - 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, - 306, 308, 404, 403, 405, 207, 605, 0, 208, 0, - 499, 607, 648, 452, 212, 234, 235, 237, 0, 279, - 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, - 451, 0, 578, 599, 612, 623, 629, 630, 632, 633, - 634, 635, 636, 639, 637, 407, 311, 495, 333, 373, - 0, 0, 425, 472, 240, 603, 496, 199, 0, 0, - 0, 0, 254, 255, 0, 574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 644, 507, 513, 508, 509, 510, 511, - 512, 0, 514, 0, 0, 0, 0, 0, 398, 0, - 590, 591, 667, 384, 486, 600, 335, 349, 352, 341, - 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, - 354, 358, 364, 249, 210, 390, 399, 577, 312, 216, - 217, 218, 523, 524, 525, 526, 615, 616, 620, 205, - 462, 463, 464, 465, 292, 610, 309, 468, 467, 331, - 332, 379, 449, 539, 541, 552, 556, 558, 560, 566, - 569, 540, 542, 553, 557, 559, 561, 567, 570, 529, - 531, 533, 535, 548, 547, 544, 572, 573, 550, 555, - 534, 546, 551, 564, 571, 568, 528, 532, 536, 545, - 563, 562, 543, 554, 565, 549, 537, 530, 538, 0, - 196, 221, 368, 0, 454, 288, 645, 614, 484, 609, - 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, - 515, 585, 587, 602, 621, 627, 480, 301, 302, 444, - 445, 314, 315, 641, 642, 300, 597, 628, 595, 640, - 622, 438, 378, 0, 0, 381, 281, 305, 320, 0, - 613, 502, 227, 466, 290, 251, 0, 0, 211, 246, - 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, - 271, 244, 459, 241, 485, 518, 519, 520, 522, 395, - 266, 433, 396, 0, 376, 575, 576, 316, 0, 0, - 527, 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, - 582, 282, 273, 269, 250, 317, 385, 428, 517, 422, - 0, 370, 0, 0, 497, 401, 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, 717, 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, 606, 0, 0, 0, 265, 321, - 272, 264, 579, 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, 624, 0, 0, - 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, - 0, 0, 412, 461, 473, 0, 0, 0, 253, 0, - 471, 426, 601, 233, 284, 458, 432, 469, 440, 287, - 0, 0, 470, 372, 584, 450, 598, 625, 626, 263, - 406, 611, 521, 619, 643, 226, 260, 420, 506, 604, - 494, 397, 580, 581, 329, 493, 295, 201, 369, 631, - 224, 479, 371, 242, 231, 586, 608, 299, 289, 456, - 638, 213, 516, 596, 239, 483, 0, 0, 646, 247, - 504, 215, 593, 503, 393, 326, 327, 214, 0, 457, - 268, 293, 0, 0, 258, 415, 588, 589, 256, 647, - 228, 618, 220, 0, 617, 408, 583, 594, 394, 383, - 219, 592, 392, 382, 334, 355, 356, 280, 307, 447, - 375, 448, 306, 308, 404, 403, 405, 207, 605, 0, - 208, 0, 499, 607, 648, 452, 212, 234, 235, 237, - 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, - 446, 442, 451, 0, 578, 599, 612, 623, 629, 630, - 632, 633, 634, 635, 636, 639, 637, 407, 311, 495, - 333, 373, 0, 0, 425, 472, 240, 603, 496, 199, - 0, 0, 0, 0, 254, 255, 0, 574, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 644, 507, 513, 508, 509, - 510, 511, 512, 0, 514, 0, 0, 0, 0, 0, - 398, 0, 590, 591, 667, 384, 486, 600, 335, 349, - 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, - 348, 353, 354, 358, 364, 249, 210, 390, 399, 577, - 312, 216, 217, 218, 523, 524, 525, 526, 615, 616, - 620, 205, 462, 463, 464, 465, 292, 610, 309, 468, - 467, 331, 332, 379, 449, 539, 541, 552, 556, 558, - 560, 566, 569, 540, 542, 553, 557, 559, 561, 567, - 570, 529, 531, 533, 535, 548, 547, 544, 572, 573, - 550, 555, 534, 546, 551, 564, 571, 568, 528, 532, - 536, 545, 563, 562, 543, 554, 565, 549, 537, 530, - 538, 0, 196, 221, 368, 0, 454, 288, 645, 614, - 484, 609, 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, 4111, - 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, 515, 585, 587, 602, 621, 627, 480, 301, - 302, 444, 445, 314, 315, 641, 642, 300, 597, 628, - 595, 640, 622, 438, 378, 0, 0, 381, 281, 305, - 320, 0, 613, 502, 227, 466, 290, 251, 0, 0, - 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, - 434, 296, 271, 244, 459, 241, 485, 518, 519, 520, - 522, 395, 266, 433, 396, 0, 376, 575, 576, 316, - 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, 385, 428, - 517, 422, 0, 370, 0, 0, 497, 401, 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, 717, 0, 0, 0, 0, + 0, 0, 323, 248, 325, 202, 413, 498, 286, 0, + 0, 0, 0, 0, 507, 723, 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, 606, 0, 0, 0, - 265, 321, 272, 264, 579, 0, 0, 0, 0, 0, + 357, 363, 336, 345, 0, 0, 608, 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, @@ -7140,72 +7272,73 @@ 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, - 297, 0, 402, 257, 0, 453, 0, 0, 0, 624, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, - 253, 0, 471, 426, 601, 233, 284, 458, 432, 469, - 440, 287, 0, 0, 470, 372, 584, 450, 598, 625, - 626, 263, 406, 611, 521, 619, 643, 226, 260, 420, - 506, 604, 494, 397, 580, 581, 329, 493, 295, 201, - 369, 631, 224, 479, 371, 242, 231, 586, 608, 299, - 289, 456, 638, 213, 516, 596, 239, 483, 0, 0, - 646, 247, 504, 215, 593, 503, 393, 326, 327, 214, - 0, 457, 268, 293, 0, 0, 258, 415, 588, 589, - 256, 647, 228, 618, 220, 0, 617, 408, 583, 594, - 394, 383, 219, 592, 392, 382, 334, 355, 356, 280, - 307, 447, 375, 448, 306, 308, 404, 403, 405, 207, - 605, 0, 208, 0, 499, 607, 648, 452, 212, 234, - 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, - 367, 419, 446, 442, 451, 0, 578, 599, 612, 623, - 629, 630, 632, 633, 634, 635, 636, 639, 637, 407, - 311, 495, 333, 373, 0, 0, 425, 472, 240, 603, - 496, 199, 0, 0, 0, 0, 254, 255, 0, 574, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 644, 507, 513, - 508, 509, 510, 511, 512, 0, 514, 0, 0, 0, - 0, 0, 398, 0, 590, 591, 667, 384, 486, 600, - 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, - 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, - 399, 577, 312, 216, 217, 218, 523, 524, 525, 526, - 615, 616, 620, 205, 462, 463, 464, 465, 292, 610, - 309, 468, 467, 331, 332, 379, 449, 539, 541, 552, - 556, 558, 560, 566, 569, 540, 542, 553, 557, 559, - 561, 567, 570, 529, 531, 533, 535, 548, 547, 544, - 572, 573, 550, 555, 534, 546, 551, 564, 571, 568, - 528, 532, 536, 545, 563, 562, 543, 554, 565, 549, - 537, 530, 538, 0, 196, 221, 368, 0, 454, 288, - 645, 614, 484, 609, 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, 515, 585, 587, 602, 621, 627, - 480, 301, 302, 444, 445, 314, 315, 641, 642, 300, - 597, 628, 595, 640, 622, 438, 378, 0, 0, 381, - 281, 305, 320, 0, 613, 502, 227, 466, 290, 251, - 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, - 400, 429, 434, 296, 271, 244, 459, 241, 485, 518, - 519, 520, 522, 395, 266, 433, 396, 0, 376, 575, - 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, 250, 317, - 385, 428, 517, 422, 0, 370, 0, 0, 497, 401, - 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, 952, 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, 606, 0, - 0, 0, 265, 321, 272, 264, 579, 0, 0, 0, - 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 958, 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, 608, 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, - 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, @@ -7213,72 +7346,72 @@ 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, 297, 0, 402, 257, 0, 453, 0, 0, - 0, 624, 0, 0, 0, 0, 0, 0, 0, 365, - 0, 330, 197, 225, 0, 0, 412, 461, 473, 0, - 0, 0, 253, 0, 471, 426, 601, 233, 284, 458, - 432, 469, 440, 287, 0, 0, 470, 372, 584, 450, - 598, 625, 626, 263, 406, 611, 521, 619, 643, 226, - 260, 420, 506, 604, 494, 397, 580, 581, 329, 493, - 295, 201, 369, 631, 224, 479, 371, 242, 231, 586, - 608, 299, 289, 456, 638, 213, 516, 596, 239, 483, - 0, 0, 646, 247, 504, 215, 593, 503, 393, 326, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, - 588, 589, 256, 647, 228, 618, 220, 0, 617, 408, - 583, 594, 394, 383, 219, 592, 392, 382, 334, 355, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, - 405, 207, 605, 0, 208, 0, 499, 607, 648, 452, - 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, - 304, 313, 367, 419, 446, 442, 451, 0, 578, 599, - 612, 623, 629, 630, 632, 633, 634, 635, 636, 639, - 637, 407, 311, 495, 333, 373, 0, 0, 425, 472, - 240, 603, 496, 199, 0, 0, 0, 0, 254, 255, - 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 644, - 507, 513, 508, 509, 510, 511, 512, 0, 514, 0, - 0, 0, 0, 0, 398, 0, 590, 591, 667, 384, - 486, 600, 335, 349, 352, 341, 361, 0, 362, 337, - 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, - 210, 390, 399, 577, 312, 216, 217, 218, 523, 524, - 525, 526, 615, 616, 620, 205, 462, 463, 464, 465, - 292, 610, 309, 468, 467, 331, 332, 379, 449, 539, - 541, 552, 556, 558, 560, 566, 569, 540, 542, 553, - 557, 559, 561, 567, 570, 529, 531, 533, 535, 548, - 547, 544, 572, 573, 550, 555, 534, 546, 551, 564, - 571, 568, 528, 532, 536, 545, 563, 562, 543, 554, - 565, 549, 537, 530, 538, 0, 196, 221, 368, 0, - 454, 288, 645, 614, 484, 609, 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, 515, 585, 587, 602, - 621, 627, 480, 301, 302, 444, 445, 314, 315, 641, - 642, 300, 597, 628, 595, 640, 622, 438, 378, 0, - 0, 381, 281, 305, 320, 0, 613, 502, 227, 466, - 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, - 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, - 485, 518, 519, 520, 522, 395, 266, 433, 396, 0, - 376, 575, 576, 316, 0, 0, 527, 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, 582, 282, 273, 269, - 250, 317, 385, 428, 517, 422, 0, 370, 0, 0, - 497, 401, 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, 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, - 606, 0, 0, 0, 265, 321, 272, 264, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 275, 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, 608, 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, @@ -7286,80 +7419,82 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 0, 402, 257, 0, 453, - 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, - 0, 365, 0, 330, 197, 225, 0, 0, 412, 461, - 473, 0, 0, 0, 253, 0, 471, 426, 601, 233, - 284, 458, 432, 469, 440, 287, 0, 0, 470, 372, - 584, 450, 598, 625, 626, 263, 406, 611, 521, 619, - 643, 226, 260, 420, 506, 604, 494, 397, 580, 581, - 329, 493, 295, 201, 369, 631, 224, 479, 371, 242, - 231, 586, 608, 299, 289, 456, 638, 213, 516, 596, - 239, 483, 0, 0, 646, 247, 504, 215, 593, 503, - 393, 326, 327, 214, 0, 457, 268, 293, 0, 0, - 258, 415, 588, 589, 256, 647, 228, 618, 220, 0, - 617, 408, 583, 594, 394, 383, 219, 592, 392, 382, - 334, 355, 356, 280, 307, 447, 375, 448, 306, 308, - 404, 403, 405, 207, 605, 0, 208, 0, 499, 607, - 648, 452, 212, 234, 235, 237, 0, 279, 283, 291, - 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, - 578, 599, 612, 623, 629, 630, 632, 633, 634, 635, - 636, 639, 637, 407, 311, 495, 333, 373, 0, 0, - 425, 472, 240, 603, 496, 199, 0, 0, 0, 0, - 254, 255, 0, 574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 644, 507, 513, 508, 509, 510, 511, 512, 0, - 514, 0, 0, 0, 0, 0, 398, 0, 590, 591, - 667, 384, 486, 600, 335, 349, 352, 341, 361, 0, - 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, - 364, 249, 210, 390, 399, 577, 312, 216, 217, 218, - 523, 524, 525, 526, 615, 616, 620, 205, 462, 463, - 464, 465, 292, 610, 309, 468, 467, 331, 332, 379, - 449, 539, 541, 552, 556, 558, 560, 566, 569, 540, - 542, 553, 557, 559, 561, 567, 570, 529, 531, 533, - 535, 548, 547, 544, 572, 573, 550, 555, 534, 546, - 551, 564, 571, 568, 528, 532, 536, 545, 563, 562, - 543, 554, 565, 549, 537, 530, 538, 0, 196, 221, - 368, 0, 454, 288, 645, 614, 484, 609, 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, 515, 585, - 587, 602, 621, 627, 480, 301, 302, 444, 445, 314, - 315, 641, 642, 300, 597, 628, 595, 640, 622, 438, - 378, 0, 0, 381, 281, 305, 320, 0, 613, 502, - 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, - 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, - 459, 241, 485, 518, 519, 520, 522, 395, 266, 433, - 0, 0, 376, 575, 576, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 297, 0, 402, 257, 0, 453, 0, 0, 0, 628, + 0, 0, 0, 0, 0, 0, 0, 365, 0, 330, + 197, 225, 0, 0, 412, 461, 473, 0, 0, 0, + 253, 0, 471, 426, 603, 233, 284, 458, 432, 469, + 440, 287, 0, 0, 470, 372, 585, 450, 600, 629, + 630, 263, 406, 614, 522, 622, 647, 226, 260, 420, + 506, 606, 494, 397, 581, 582, 329, 493, 295, 201, + 369, 635, 224, 479, 371, 242, 231, 587, 611, 299, + 289, 456, 642, 213, 517, 597, 239, 483, 0, 0, + 650, 247, 504, 609, 598, 215, 594, 503, 393, 326, + 327, 214, 0, 457, 268, 293, 0, 0, 258, 415, + 589, 590, 256, 651, 228, 621, 220, 0, 620, 408, + 584, 595, 394, 383, 219, 593, 392, 382, 334, 355, + 356, 280, 307, 447, 375, 448, 306, 308, 404, 403, + 405, 207, 607, 625, 0, 208, 0, 499, 610, 652, + 452, 212, 234, 235, 237, 0, 279, 283, 291, 294, + 303, 304, 313, 367, 419, 446, 442, 451, 0, 579, + 601, 615, 627, 633, 634, 636, 637, 638, 639, 640, + 643, 641, 407, 311, 495, 333, 373, 0, 0, 425, + 472, 240, 605, 496, 199, 0, 0, 0, 0, 254, + 255, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 648, 508, 514, 509, 510, 511, 512, 513, 0, 515, + 0, 0, 0, 0, 0, 398, 0, 591, 592, 671, + 384, 486, 602, 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, 618, 619, 623, 205, 462, 463, 464, + 465, 292, 613, 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, 649, 617, 484, 612, 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, + 604, 624, 631, 480, 301, 302, 444, 445, 314, 315, + 645, 646, 300, 599, 632, 596, 644, 626, 438, 378, + 0, 0, 381, 281, 305, 320, 0, 616, 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, 5002, -1000, -543, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 5137, -1000, -546, -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, 2405, 2552, -1000, -1000, -1000, -1000, 2650, -1000, 1021, + 2102, -1000, 2424, 5045, -1000, 57005, 496, -1000, 54045, -455, + 873, 232, 37765, -1000, 174, -1000, 163, 55525, 167, -1000, + -1000, -1000, -1000, -455, 22965, 2286, -1, -4, 57005, -1000, + -1000, -1000, -1000, -372, 2610, 2048, -1000, 394, -1000, -1000, + -1000, -1000, -1000, -1000, 53305, -1000, 1105, -1000, -1000, 2432, + 2409, 2289, 919, 2330, -1000, 2518, 2048, -1000, 22965, 2612, + 2366, 22225, 22225, 441, -1000, -1000, 332, -1000, -1000, 32585, + 57005, 40725, 866, -1000, 2424, -1000, -1000, -1000, 199, -1000, + 333, 1959, -1000, 1949, -1000, 900, 927, 378, 858, 492, + 377, 376, 371, 361, 351, 348, 346, 339, 388, -1000, + 933, 933, -262, -272, 362, 422, 431, 431, 1033, 453, + 2387, 2384, -1000, -1000, 933, 933, 933, 345, 933, 933, + 933, 933, 318, 296, 933, 933, 933, 933, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, + 933, 893, 2424, 265, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2499, 2504, -1000, -1000, -1000, -1000, 2666, -1000, 1045, - 2083, -1000, 2425, 5020, -1000, 55834, 808, -1000, 52906, -446, - 922, 238, 36802, -1000, 226, -1000, 205, 54370, 218, -1000, - -1000, -1000, -1000, -446, 22162, 2341, 47, 41, 55834, -1000, - -1000, -1000, -1000, -363, 2613, 2073, -1000, 389, -1000, -1000, - -1000, -1000, -1000, -1000, 52174, -1000, 1137, -1000, -1000, 2476, - 2470, 2311, 948, 2319, -1000, 2534, 2073, -1000, 22162, 2603, - 2453, 21430, 21430, 471, -1000, -1000, 596, -1000, -1000, 31678, - 55834, 39730, 284, -1000, 2425, -1000, -1000, -1000, 214, -1000, - 381, 1998, -1000, 1993, -1000, 1053, 1064, 402, 864, 841, - 401, 398, 397, 396, 395, 393, 392, 388, 394, -1000, - 963, 963, -223, -225, 1390, 786, 459, 459, 1098, 503, - 2392, 2387, -1000, -1000, 963, 963, 963, 363, 963, 963, - 963, 963, 334, 332, 963, 963, 963, 963, 963, 963, - 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, - 963, 959, 2425, 321, -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, @@ -7406,68 +7541,67 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55834, 211, - 55834, -1000, 865, 804, -1000, -1000, -450, 1113, 1113, 117, - 1113, 1113, 1113, 1113, 181, 951, 40, -1000, 175, 289, - 225, 307, 1116, 269, -1000, -1000, 291, 1116, 1800, -1000, - 952, 302, 159, -1000, 1113, 1113, -1000, 14818, 263, 14818, - 14818, -1000, 2420, -1000, -1000, -1000, -1000, -1000, 1339, -1000, - -1000, -1000, -1000, -49, 493, -1000, -1000, -1000, -1000, 54370, - 51442, 234, -1000, -1000, 45, 1857, 1527, 22162, 1439, 946, - -1000, -1000, 1369, 927, -1000, -1000, -1000, -1000, -1000, 829, - -1000, 24358, 24358, 24358, 24358, -1000, -1000, 2000, 50710, 2000, - 2000, 24358, 2000, 24358, 2000, 2000, 2000, 2000, 22162, 2000, - 2000, 2000, 2000, -1000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, -1000, -1000, -1000, -1000, 2000, 863, 2000, - 2000, 2000, 2000, 2000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2000, 2000, 2000, 2000, 2000, 2000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - -1000, -1000, -1000, 1605, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 27286, 1540, 1536, 1533, -1000, 19234, 2000, -1000, -1000, + -1000, -1000, 57005, 185, 57005, -1000, 810, 495, -1000, -1000, + -465, 1087, 1087, 10, 1087, 1087, 1087, 1087, 122, 996, + -12, -1000, 120, 255, 104, 261, 1055, 293, -1000, -1000, + 244, 1055, 1797, -1000, 923, 259, 102, -1000, 1087, 1087, + -1000, 15541, 251, 15541, 15541, 247, 149, -1000, 2404, -1000, + -1000, -1000, -1000, -1000, 1303, -1000, -1000, -1000, -1000, -80, + 449, -1000, -1000, -1000, -1000, 55525, 52565, 237, -1000, -1000, + 292, 1871, 1863, 22965, 1390, 905, -1000, -1000, 1189, 875, + -1000, -1000, -1000, -1000, -1000, 512, -1000, 25185, 25185, 25185, + 25185, -1000, -1000, 1964, 51825, 1964, 1964, 25185, 1964, 25185, + 1964, 1964, 1964, 1964, 22965, 1964, 1964, 1964, 1964, -1000, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, -1000, + -1000, -1000, -1000, 1964, 809, 1964, 1964, 1964, 1964, 1964, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1964, 1964, 1964, + 1964, 1964, 1964, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, -1000, -1000, -1000, 1648, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 28145, 1535, 1533, + 1528, -1000, 20005, 1964, -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, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55834, - -1000, 2000, 243, 54370, 54370, 366, 1322, -1000, -1000, 2534, - 2073, -1000, 2613, 2562, 389, -1000, 3064, 1622, 1778, 1500, - 2073, 1937, 55834, -1000, 2007, -1000, -1000, -1000, -382, -386, - 2258, 1438, 1794, -1000, -1000, -1000, -1000, 1905, 22162, -1000, - -1000, 2647, -1000, 28750, 862, 2643, 49978, -1000, 471, 471, - 1982, 593, -5, -1000, -1000, -1000, -1000, 993, 36070, -1000, - -1000, -1000, -1000, -1000, 1883, 55834, -1000, -1000, 5010, 54370, - -1000, 2081, -1000, 1872, -1000, 2037, 22162, 2091, 803, 54370, - 526, 521, 489, -1000, -64, -1000, -1000, -1000, -1000, -1000, - -1000, 963, 963, 963, -1000, 387, 2598, 5020, 6408, -1000, - -1000, -1000, 49246, 2078, 54370, -1000, 2072, -1000, 1075, 850, - 827, 827, 54370, -1000, -1000, 55102, 54370, 1074, 1073, 54370, - 54370, 54370, 54370, -1000, 48514, -1000, 47782, 47050, 1318, 54370, - 46318, 45586, 44854, 44122, 43390, -1000, 2244, -1000, 2094, -1000, - -1000, -1000, 55102, 54370, 54370, 55102, 54370, 55102, 55834, 54370, - -1000, -1000, 328, -1000, -1000, 1317, 1316, 1313, 963, 963, - 1297, 1789, 1787, 1780, 963, 963, 1280, 1772, 38266, 1767, - 310, 1278, 1277, 1275, 1341, 1720, 260, 1714, 1321, 1272, - 1270, 54370, 2067, 55834, -1000, 280, 1122, 976, 992, 2425, - 2320, 1977, 490, 802, 54370, 463, 463, 54370, -1000, 15556, - 55834, 228, -1000, 1712, 22162, -1000, 1132, 1116, 1116, -1000, - -1000, -1000, -1000, -1000, -1000, 1113, 55834, 1132, -1000, -1000, - -1000, 1116, 1113, 55834, 1113, 1113, 1113, 1113, 1116, 1116, - 1116, 1113, 55834, 55834, 55834, 55834, 55834, 55834, 55834, 55834, - 55834, 14818, 952, 1113, -453, -1000, 1691, -1000, -1000, -1000, - 2212, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 57005, -1000, 1964, 190, 55525, + 55525, 343, 1298, -1000, -1000, 2518, 2048, -1000, 2610, 2540, + 394, -1000, 3913, 1725, 1546, 1417, 2048, 1933, 57005, -1000, + 1973, -1000, -1000, -1000, -391, -392, 2222, 1435, 1792, -1000, + -1000, -1000, -1000, 1791, 22965, -1000, -1000, 2646, -1000, 29625, + 808, 2644, 51085, -1000, 441, 441, 1944, 427, -38, -1000, + -1000, -1000, -1000, 948, 37025, -1000, -1000, -1000, -1000, -1000, + 1813, 57005, -1000, -1000, 5214, 55525, -1000, 2093, -1000, 1807, + -1000, 2021, 22965, 2112, 477, 55525, 465, 463, 458, -1000, + -119, -1000, -1000, -1000, -1000, -1000, -1000, 933, 933, 933, + -1000, 384, 2591, 5045, 7104, -1000, -1000, -1000, 50345, 2091, + 55525, -1000, 2087, -1000, 1015, 860, 871, 871, 55525, -1000, + -1000, 56265, 55525, 1014, 1004, 55525, 55525, 55525, 55525, -1000, + 49605, -1000, 48865, 48125, 1297, 55525, 47385, 46645, 45905, 45165, + 44425, -1000, 2284, -1000, 2261, -1000, -1000, -1000, 56265, 55525, + 55525, 56265, 55525, 56265, 57005, 55525, -1000, -1000, 330, -1000, + -1000, 1296, 1294, 1285, 933, 933, 1283, 1788, 1781, 1757, + 933, 933, 1274, 1755, 39245, 1747, 274, 1273, 1272, 1255, + 1241, 1734, 236, 1732, 1203, 1188, 1254, 55525, 2086, 57005, + -1000, 239, 990, 978, 946, 2424, 2282, 1943, 447, 473, + 55525, 432, 432, 55525, -1000, 16287, 57005, 176, -1000, 1721, + 22965, -1000, 1090, 1055, 1055, -1000, -1000, -1000, -1000, -1000, + -1000, 1087, 57005, 1090, -1000, -1000, -1000, 1055, 1087, 57005, + 1087, 1087, 1087, 1087, 1055, 1055, 1055, 1087, 57005, 57005, + 57005, 57005, 57005, 57005, 57005, 57005, 57005, 15541, 923, 1087, + -466, -1000, 1719, -1000, -1000, -1000, 2200, -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, @@ -7482,335 +7616,338 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 14818, 14818, - -1000, -1000, -1000, -1000, -1000, 1973, -1000, 202, 17, 213, - -1000, 42658, 456, 991, -1000, 456, -1000, -1000, -1000, 1968, - 41926, -1000, -454, -455, -460, -461, -1000, -1000, -1000, -462, - -463, -1000, -1000, -1000, 22162, 22162, 22162, 22162, -313, -1000, - 1482, 24358, 2393, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 22162, 301, 1226, 24358, 24358, 24358, 24358, 24358, 24358, 24358, - 25822, 25090, 24358, 24358, 24358, 24358, 24358, 24358, -1000, -1000, - 33874, 5565, 5565, 927, 927, 927, 927, -1000, -187, 1964, - 55102, -1000, -1000, -1000, 849, 22162, 22162, 927, -1000, 1338, - 1583, 19234, 22162, 22162, 22162, 22162, 1000, 1527, 55102, 22162, - -1000, 1500, -1000, -1000, -1000, -1000, 1235, -1000, -1000, 1102, - 2384, 2384, 2384, 2384, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 2384, 22162, 136, 136, 729, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 17770, 22162, 22162, - 24358, 22162, 22162, 22162, 1500, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 1500, 22162, 1517, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 17032, 22162, 22162, 22162, 22162, 22162, - -1000, -1000, -1000, -1000, -1000, -1000, 22162, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 1500, 22162, 22162, 22162, 22162, 22162, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 1636, 1417, 1490, 22162, -1000, 1959, -1000, -190, 30946, - 22162, 1679, 2640, 2115, 54370, -1000, -1000, -1000, -1000, 2534, - -1000, 2534, 1636, 2747, 2266, 21430, -1000, -1000, 2747, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1718, -1000, - 55834, 1937, 2527, 54370, -1000, -356, -1000, -357, 2255, 1677, - 885, -1000, 22162, 22162, 1935, -1000, 1803, 55834, -1000, -313, - -1000, 41194, -1000, -1000, 14080, 55834, 383, 55834, -1000, 30214, - 40462, 313, -1000, -5, 1917, -1000, 7, 15, 18502, 924, - -1000, -1000, -1000, 1390, 26554, 1826, 924, 120, -1000, -1000, - -1000, 2037, -1000, 2037, 2037, 2037, 2037, 885, 885, 885, - 885, -1000, -1000, -1000, -1000, -1000, 2061, 2057, -1000, 2037, - 2037, 2037, 2037, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 15541, 15541, -1000, + -1000, 2521, 2517, -1000, -1000, -1000, 1937, -1000, 161, -52, + 166, -1000, 43685, 525, 945, -1000, 525, -1000, -1000, -1000, + 1936, 42945, -1000, -468, -469, -471, -473, -1000, -1000, -1000, + -475, -476, -1000, -1000, -1000, 22965, 22965, 22965, 22965, -315, + -1000, 1200, 25185, 2372, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 22965, 241, 999, 25185, 25185, 25185, 25185, 25185, 25185, + 25185, 26665, 25925, 25185, 25185, 25185, 25185, 25185, 25185, -1000, + -1000, 34805, 6328, 6328, 875, 875, 875, 875, -1000, -231, + 1935, 56265, -1000, -1000, -1000, 805, 22965, 22965, 875, -1000, + 1305, 2320, 20005, 22965, 22965, 22965, 22965, 962, 1863, 56265, + 22965, -1000, 1417, -1000, -1000, -1000, -1000, 1209, -1000, -1000, + 1084, 2343, 2343, 2343, 2343, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 2343, 22965, 260, 260, 1034, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 18525, 22965, + 22965, 25185, 22965, 22965, 22965, 1417, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 1417, 22965, 1594, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 17779, 22965, 22965, 22965, 22965, + 22965, -1000, -1000, -1000, -1000, -1000, -1000, 22965, 22965, 22965, + 22965, 22965, 22965, 22965, 22965, 1417, 22965, 22965, 22965, 22965, + 22965, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1799, 1551, 1433, 22965, -1000, 1934, -1000, -203, + 31845, 22965, 1688, 2640, 2119, 55525, -1000, -1000, -1000, -1000, + 2518, -1000, 2518, 1799, 3877, 2241, 22225, -1000, -1000, 3877, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2047, 2047, 2047, 2044, 2044, 2038, 2038, 446, -1000, 22162, - 432, 39730, 2520, 1269, 2369, 280, 469, 2102, 54370, 54370, - 54370, 469, -1000, 1377, 1375, 1354, -1000, -525, 1932, -1000, - -1000, 2595, -1000, -1000, 909, 1104, 1093, 1076, 54370, 255, - 359, -1000, 438, -1000, 39730, 54370, 1069, 827, 54370, -1000, - 54370, -1000, -1000, -1000, -1000, -1000, 54370, -1000, -1000, 1931, - -1000, 1876, 1142, 1090, 1133, 1088, 1931, -1000, -1000, -189, - 1931, -1000, 1931, -1000, 1931, -1000, 1931, -1000, 1931, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1024, 130, - -338, 54370, 255, 488, -1000, 486, 33874, -1000, -1000, -1000, - 33874, 33874, -1000, -1000, -1000, -1000, 1638, 1634, -1000, -1000, + -1000, -1000, -1000, 1752, -1000, 57005, 1933, 2495, 55525, -1000, + -369, -1000, -375, 2219, 1683, 282, -1000, 22965, 22965, 1932, + -1000, 1681, 57005, -1000, -315, -1000, 42205, -1000, -1000, 14795, + 57005, 335, 57005, -1000, 31105, 41465, 326, -1000, -38, 1902, + -1000, -55, -59, 19265, 861, -1000, -1000, -1000, 362, 27405, + 1817, 861, 48, -1000, -1000, -1000, 2021, -1000, 2021, 2021, + 2021, 2021, 282, 282, 282, 282, -1000, -1000, -1000, -1000, + -1000, 2081, 2021, 2072, -1000, 2021, 2021, 2021, 2021, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 2053, 2053, 2053, 2050, + 2050, 2022, 2022, 428, -1000, 22965, 471, 40725, 2441, 1252, + 2194, 239, 436, 2097, 55525, 55525, 55525, 436, -1000, 1447, + 1385, 1353, -1000, -530, 1928, -1000, -1000, 2583, -1000, -1000, + 943, 1039, 1038, 1057, 55525, 201, 280, -1000, 411, -1000, + 40725, 55525, 1002, 871, 55525, -1000, 55525, -1000, -1000, -1000, + -1000, -1000, 55525, -1000, -1000, 1927, -1000, 1929, 1173, 1031, + 1080, 1027, 1927, -1000, -1000, -237, 1927, -1000, 1927, -1000, + 1927, -1000, 1927, -1000, 1927, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1000, 340, -389, 55525, 201, 446, + -1000, 445, 34805, -1000, -1000, -1000, 34805, 34805, -1000, -1000, + -1000, -1000, 1676, 1674, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -512, 55834, -1000, - 267, 989, 348, 385, 345, 55834, 412, 2388, 2383, 2381, - 2378, 2372, 2371, 286, 331, 55834, 55834, 463, 2214, 55834, - 2501, 55834, -1000, -1000, -1000, -1000, -1000, 1631, 1623, -1000, - 1527, 55834, -1000, -1000, 1113, 1113, -1000, -1000, 55834, 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, 55834, -1000, -1000, -1000, -1000, -49, - 195, -1000, -1000, 54370, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -113, -1000, 303, 3, 425, -1000, -1000, - -1000, -1000, -1000, 2511, -1000, 1527, 1020, 1025, -1000, 2000, - -1000, -1000, 1299, -1000, -1000, -1000, -1000, -1000, 2000, 2000, - 2000, -1000, -1000, -1000, -1000, -1000, 301, 24358, 24358, 24358, - 1380, 793, 1392, 1327, 1228, 1285, 1285, 1185, 24358, 1185, - 24358, 931, 931, 931, 931, 931, -1000, -1000, -1000, -1000, - -1000, -1000, 1605, -1000, 1584, -1000, 2000, 55102, 1867, 17032, - 1939, 2054, 1500, 940, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -518, 57005, -1000, 234, 940, 284, 322, + 312, 57005, 289, 2380, 2376, 2367, 2360, 2358, 2333, 2323, + 243, 287, 57005, 57005, 432, 2150, 57005, 2466, 57005, -1000, + -1000, -1000, -1000, -1000, 1671, 1656, -1000, 1863, 57005, -1000, + -1000, 1087, 1087, -1000, -1000, 57005, 1087, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1087, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 4265, 1500, 1857, 1500, 2049, 4258, - 1001, -1000, 22162, 1500, 4250, -1000, -1000, 1500, 1500, 22162, - -1000, -1000, 22162, 22162, 22162, 22162, 2369, 2369, 2369, 2369, - 2369, 2369, 2369, 2369, 2369, 2369, 22162, 2369, 1923, -1000, + -1000, 57005, -1000, -1000, -1000, -1000, 1652, -1000, 57005, -80, + 153, -1000, -1000, 55525, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -121, -1000, 347, -41, 385, -1000, -1000, + -1000, -1000, -1000, 2504, -1000, 1863, 995, 988, -1000, 1964, + -1000, -1000, 1067, -1000, -1000, -1000, -1000, -1000, 1964, 1964, + 1964, -1000, -1000, -1000, -1000, -1000, 241, 25185, 25185, 25185, + 1295, 487, 1421, 1340, 1432, 1357, 1357, 1166, 25185, 1166, + 25185, 880, 880, 880, 880, 880, -1000, -1000, -1000, -1000, + -1000, -1000, 1648, -1000, 1645, -1000, 1964, 56265, 1772, 17779, + 2532, 2505, 1417, 898, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1921, 2638, 1820, - 2369, 2369, 2369, 2369, 4245, 2369, 2369, 22162, 1430, -1000, - -1000, -1000, 1499, 4240, 1303, 4225, 2369, 2369, -1000, 2369, - 4220, 4212, 1500, 3009, 3000, 2369, 2369, 2369, 2369, 2369, - 2938, 2934, 2369, 2369, 2930, 2369, 4206, 2369, 2919, 2903, - 2768, 2754, 2709, 2691, 2676, 2664, 2650, 2646, 2632, 2605, - 2599, 2569, 2536, 2529, 2522, 2509, 2369, 2369, 2369, 4202, - 2369, 4197, 2369, 4191, 2369, 2369, 4180, 2494, 2469, 1500, - 1920, -1000, 4174, 2369, 3948, 3942, 3917, 2463, 3912, 3892, - 3888, 2369, 2369, 2369, 2446, 3883, 3879, 3875, 3572, 3561, - 3516, 3512, 3497, 3493, 2369, 1490, 1490, 1490, 1490, 1490, - 3479, -320, 2369, 1500, -1000, -1000, -1000, -1000, -1000, 3474, - 2428, 3453, 3445, 3437, 3432, 1500, 2000, 847, -1000, -1000, - 1490, 1500, 1500, 1490, 1490, 3404, 3400, 3394, 3389, 3385, - 3362, 2369, 2369, -1000, 2369, 3341, 3319, 2418, 2397, 1500, - -1000, 1490, 55834, -1000, -445, -1000, -11, 950, 2000, -1000, - 38266, 1500, -1000, 2048, -1000, 1162, -1000, -1000, -1000, -1000, - -1000, 35338, 1823, -1000, -1000, -1000, -1000, 2000, 1805, -1000, - -1000, -1000, -1000, 885, 67, 34606, 916, 916, 165, 1527, - 1527, 22162, -1000, -1000, -1000, -1000, -1000, -1000, 844, 2622, - 382, 2000, -1000, 1976, 2114, -1000, -1000, -1000, 2526, 28018, - -1000, -1000, 2000, 2000, 55834, 1863, 1843, -1000, 843, -1000, - 1345, 1917, -5, 2, -1000, -1000, -1000, -1000, 1527, -1000, - 1350, 386, 369, -1000, 454, -1000, -1000, -1000, -1000, 2360, - 79, -1000, -1000, -1000, 340, 885, -1000, -1000, -1000, -1000, - -1000, -1000, 1579, 1579, -1000, -1000, -1000, -1000, -1000, 1260, - -1000, -1000, -1000, -1000, 1253, -1000, -1000, 1245, -1000, -1000, - 3024, 2252, 432, -1000, -1000, 963, 1576, -1000, -1000, 2364, - 963, 963, 54370, -1000, -1000, 1806, 2520, 267, 55834, 1009, - 2211, -1000, 2102, 2102, 2102, 55834, -1000, -1000, -1000, -1000, - -1000, -1000, -514, 191, 364, -1000, -1000, -1000, 6185, 54370, - 1760, -1000, 249, -1000, 1697, -1000, 54370, -1000, 1758, 2043, - 54370, 54370, -1000, -1000, -1000, 54370, 2000, -1000, -1000, -1000, - -1000, 789, 2419, 358, -1000, -1000, -344, -1000, -1000, 255, - 249, 55102, 54370, 924, -1000, -1000, -1000, -1000, -1000, -515, - 1743, 507, 264, 487, 55834, 55834, 55834, 55834, 55834, 55834, - 820, -1000, -1000, 31, -1000, -1000, 235, -1000, -1000, -1000, - -1000, -1000, 235, -1000, -1000, -1000, -1000, -1000, 323, 485, - -1000, 55834, 55834, 941, -1000, -1000, -1000, -1000, -1000, 1116, - -1000, -1000, 1116, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 2416, 55834, 1, -482, -1000, -476, 22162, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1209, 782, 1392, - 24358, 24358, 1583, 1583, 24358, -1000, -1000, -1000, 357, 357, - 33874, -1000, 24358, 22162, -1000, -1000, 22162, 22162, 22162, 996, - -1000, 22162, 1340, -1000, 22162, -1000, -320, 1490, 2369, 2369, - 2369, 2369, -320, -320, -320, -320, -320, -320, -320, -320, - -320, -320, 1930, -1000, 22162, 22162, 22162, 1500, 338, -1000, - -1000, -1000, -320, 22162, -1000, -1000, 2636, -1000, 22162, -1000, - 33874, 22162, 22162, 22162, -1000, -1000, -1000, 22162, 22162, -1000, - -1000, 22162, -1000, 22162, -1000, -1000, -1000, -1000, -1000, -1000, - 22162, -1000, 22162, -1000, -1000, -1000, 22162, -1000, 22162, -1000, - -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, - -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, - -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, - -1000, 22162, -1000, 22162, -1000, 22162, -1000, -1000, -1000, 22162, - -1000, 22162, -1000, 22162, -1000, -1000, 22162, -1000, 22162, -1000, - 22162, -1000, 22162, 22162, -1000, 22162, 22162, 22162, -1000, 22162, - 22162, 22162, 22162, -1000, -1000, -1000, -1000, 22162, 22162, 22162, - 22162, 22162, 22162, 22162, 22162, 22162, 22162, -1000, -1000, -1000, - -1000, -1000, -1000, 22162, -1000, 39730, 11, -320, 1517, 11, - 1517, 23626, 875, 828, 22894, -1000, 22162, 16294, -1000, -1000, - -1000, -1000, -1000, 22162, 22162, 22162, 22162, 22162, 22162, -1000, - -1000, -1000, 22162, 22162, -1000, 22162, -1000, 22162, -1000, -1000, - -1000, -1000, -1000, 950, -1000, 873, 846, 827, 54370, -1000, - -1000, -1000, -1000, 1911, -1000, 2541, -1000, 2279, 2278, 2631, - 2622, 21430, -1000, 30214, -1000, -1000, 54370, -435, -1000, 2308, - 2292, 916, 916, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 13342, 2534, 22162, 2210, 55102, 199, -1000, 29482, 54370, 55102, - 30214, 30214, 30214, 30214, 30214, -1000, 2242, 2236, -1000, 2232, - 2226, 2238, 55834, -1000, 1636, 1737, -1000, 22162, 32410, 1864, - 30214, -1000, -1000, 30214, 55834, 12604, -1000, -1000, -3, 6, - -1000, -1000, -1000, -1000, 1390, -1000, -1000, 1072, 2524, 2350, - -1000, -1000, -1000, -1000, -1000, 1725, -1000, 1709, 1907, 1696, - 1689, 130, -1000, 2090, 2414, 963, 963, -1000, 1240, -1000, - 1338, 1564, 1562, -1000, -1000, -1000, 505, -1000, 2500, 55834, - 2209, 2152, 2144, -1000, -524, 1232, 2042, 2059, 22162, 2041, - 2582, 1891, 54370, -1000, -1000, 55102, -1000, 281, -1000, 432, - 54370, -1000, -1000, -1000, 359, 55834, -1000, 8587, -1000, -1000, - -1000, 249, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55834, - 274, -1000, 2040, 1332, -1000, -1000, 2013, -1000, -1000, -1000, - -1000, -1000, 247, 220, 1558, 229, 1547, 229, -1000, 55834, - 907, 2252, 55834, -1000, -1000, -1000, 1113, 1113, -1000, -1000, - 2410, -1000, 1338, 2369, 24358, 24358, -1000, 927, -1000, -1000, - 320, -292, 2037, 2037, -1000, 2037, 2038, -1000, 2037, 173, - 2037, 146, 2037, -1000, -1000, 1500, 1500, -1000, 1490, 2354, - 1699, 3314, -1000, 1527, 22162, 3250, -1000, -1000, -320, -320, - -320, -320, -320, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -71, 3034, 2994, 2369, -1000, 2034, 2033, - -1000, 2369, 22162, 2369, 1500, 2347, 2369, 2369, 2369, 2369, - 2369, 2369, 2369, 2369, 2369, 2369, 2369, 2369, 2338, 2333, - 2327, 2321, 2314, 2306, 2294, 2213, 2207, 2186, 2139, 2074, - 2069, 2063, 2021, 2004, 2369, 2369, 1990, 2369, 1914, 1855, - -1000, 1527, 1490, 2990, 1490, 2369, 2369, 2981, 256, 2369, - 1686, 1686, 1686, 1686, 1686, 1490, 1490, 1490, 1490, 2369, - 54370, -1000, -320, -1000, -1000, -372, -376, -1000, 1500, -320, - 1900, 24358, 2369, 24358, 24358, 24358, 2369, 1500, -1000, 1830, - 1824, 2659, 1763, 2369, 2502, 2369, 2369, 2369, 1746, -1000, - 2506, 2000, 2506, 2000, 2506, 1655, 1162, 55834, -1000, -1000, - -1000, -1000, 2622, 2614, -1000, 1899, -1000, 67, 605, -1000, - 2312, 2292, -1000, 2577, 2301, 2576, -1000, -1000, -1000, -1000, - -1000, 1527, -1000, 2460, 1852, -1000, 973, 1904, -1000, -1000, - 20698, 1660, 2270, 838, 1655, 1886, 2114, 2113, 2134, 2307, - -1000, -1000, -1000, -1000, 2233, -1000, 2149, -1000, -1000, 2007, - -1000, 2310, 383, 30214, 1819, 1819, -1000, 836, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1119, 8587, 2660, -1000, 1545, - -1000, 1337, 196, 1231, -1000, -1000, 963, 963, -1000, 1068, - 1031, -1000, 55834, 2032, -1000, 885, 1543, 885, 1223, -1000, - -1000, 1221, -1000, -1000, -1000, -1000, 1988, 2197, -1000, -1000, - -1000, -1000, 55834, -1000, -1000, 55834, 55834, 55834, 2031, 2566, - -1000, 22162, 2025, 970, 2907, 54370, 54370, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 787, 963, - -494, 330, 322, 963, 963, 963, -536, -1000, -1000, 1652, - 1643, -1000, -226, -1000, 22162, -1000, -1000, -1000, -1000, -1000, - 1249, 1249, 1540, 1536, 1533, -1000, 2007, -1000, -1000, -1000, - 1661, -1000, -1000, -211, 54370, 54370, 54370, 54370, -1000, -1000, - -1000, 1149, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 927, 1500, 376, -214, 1500, -1000, - -1000, 885, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 22162, -1000, 22162, -1000, 22162, 1527, 22162, -1000, - -1000, -1000, -1000, -1000, 2534, 1531, 22162, 22162, -1000, 1206, - 1196, -320, 2369, -1000, -1000, -1000, 22162, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 3487, 1417, 1871, 1417, 2490, 3483, + 963, -1000, 22965, 1417, 3479, -1000, -1000, 1417, 1417, 22965, + -1000, -1000, 22965, 22965, 22965, 22965, 2194, 2194, 2194, 2194, + 2194, 2194, 2194, 2194, 2194, 2194, 22965, 2194, 1925, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, - 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, - 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, 22162, -1000, - 22162, -1000, -1000, 22162, -1000, -1000, -1000, 22162, -1000, 22162, - -1000, 22162, -1000, -1000, -1000, 22162, 327, 357, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1500, - 379, -1000, -1000, -1000, 2625, -1000, 1500, 22162, 1583, -1000, - 1583, 1583, 1583, -1000, -1000, -1000, 22162, -1000, 22162, 22162, - -1000, 22162, -1000, 22162, -1000, -1000, -1000, -1000, 22162, 2000, - 2300, 38998, 2000, 38998, 2000, 32410, -1000, -1000, 2614, 2617, - 2560, 2288, 2293, 2293, 2312, -1000, 2559, 2558, -1000, 1524, - 2557, 1518, 1029, -1000, 55102, 22162, -1000, 199, 38266, -1000, - 371, 54370, 199, 54370, -1000, 2542, -1000, -1000, 22162, 2024, - -1000, 22162, -1000, -1000, -1000, -1000, 5565, 2622, 1819, -1000, - -1000, 937, -1000, 22162, -1000, 10926, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1492, 1481, -1000, -1000, 2009, 22162, - -1000, -1000, -1000, 1647, 1644, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 2007, -1000, -1000, -1000, -1000, 359, -522, - 2628, 54370, 1172, -1000, 1621, 1891, 333, 199, 1469, 963, - 963, 963, 1163, 1161, 38266, 1613, -1000, 54370, 421, -1000, - 359, -1000, -236, -240, 2369, -1000, -1000, 2518, -1000, -1000, - 16294, -1000, -1000, 2003, 2097, -1000, -1000, -1000, -1000, 2253, - -185, -218, -1000, -1000, 2369, 2369, 2369, 2058, 1500, -1000, - 2369, 2369, 1637, 1628, -1000, -1000, 2369, 2369, 2369, 2369, - 2369, 2369, 2369, 2369, 2369, 2369, 2369, 2369, 2369, 2369, - 2369, 2369, 2369, 2369, 2369, 2369, 1490, 1729, -1000, 327, - 1500, 2133, -1000, -1000, 5565, -1000, -1000, 2542, 2552, 11, - -1000, -1000, 265, 11, 1527, 1033, 1500, 1500, 1033, 1723, - 2369, 1694, 1676, 2369, 2369, 33142, -1000, 2549, 2538, 1568, - -1000, -1000, 38998, 1568, 38998, 950, 2617, -343, 22162, 22162, - 2284, 1175, -1000, -1000, -1000, -1000, 1435, 1433, -1000, 1431, - -1000, 2655, -1000, 1527, -1000, 2000, 199, -1000, 835, 1904, - -1000, 2534, 1527, 54370, 1527, 73, 2542, -1000, 2369, -1000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, - 2000, -1000, -1000, 54370, 2580, -1000, -1000, 2514, 1609, 187, - -1000, 1530, 1891, -1000, -1000, 194, -1000, 22162, -1000, 38266, - 1403, 1400, -1000, -1000, -1000, -1000, -536, -1000, -1000, -1000, - -1000, -1000, -1000, 389, 1889, -1000, 961, 54370, 55834, -1000, - 2248, -1000, -1000, -1000, -1000, 22162, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1923, 2638, 1616, + 2194, 2194, 2194, 2194, 3474, 2194, 2194, 22965, 1431, -1000, + -1000, -1000, 1554, 3466, 1247, 3462, 2194, 2194, -1000, 2194, + 3426, 3413, 1417, 2485, 2475, 2194, 2194, 2194, 2194, 2194, + 2471, 2457, 2194, 2194, 2453, 2194, 3409, 2194, 2448, 2443, + 2425, 2373, 2336, 2331, 2322, 2313, 2308, 2288, 2248, 2237, + 2228, 2213, 2203, 2187, 2176, 2167, 2194, 2194, 2194, 3399, + 2194, 3392, 2194, 3386, 2194, 2194, 3378, 2149, 2142, 1417, + 1910, -1000, 3371, 2194, 3359, 3352, 3348, 2126, 3280, 3272, + 3060, 2194, 2194, 2194, 2114, 3048, 3042, 3017, 3003, 2998, + 2991, 2985, 2960, 2953, 2194, 1433, 1433, 1433, 1433, 1433, + 2938, -321, 2194, 1417, -1000, -1000, -1000, -1000, -1000, 2934, + 2107, 2930, 2917, 2889, 2884, 1417, 1964, 803, -1000, -1000, + 1433, 1417, 1417, 1433, 1433, 2865, 2856, 2816, 2732, 2711, + 2702, 2194, 2194, -1000, 2194, 2672, 2659, 2103, 2099, 1417, + -1000, 1433, 57005, -1000, -454, -1000, -63, 936, 1964, -1000, + 39245, 1417, -1000, 6274, -1000, 1236, -1000, -1000, -1000, -1000, + -1000, 36285, 1810, -1000, -1000, -1000, -1000, 1964, 1769, -1000, + -1000, -1000, -1000, 282, 16, 35545, 862, 862, 64, 1863, + 1863, 22965, -1000, -1000, -1000, -1000, -1000, -1000, 798, 2619, + 457, 1964, -1000, 1876, 2767, -1000, -1000, -1000, 2491, 28885, + -1000, -1000, 1964, 1964, 57005, 1909, 1855, -1000, 755, -1000, + 1321, 1902, -38, -45, -1000, -1000, -1000, -1000, 1863, -1000, + 1343, 337, 1436, -1000, 419, -1000, -1000, -1000, -1000, 2301, + 24, -1000, -1000, -1000, 359, 282, -1000, -1000, -1000, -1000, + -1000, -1000, 1643, -1000, 1643, -1000, -1000, -1000, -1000, -1000, + 1250, -1000, -1000, -1000, -1000, 1238, -1000, -1000, 1235, -1000, + -1000, 2651, 2059, 471, -1000, -1000, 933, 1637, -1000, -1000, + 2314, 933, 933, 55525, -1000, -1000, 1710, 2441, 234, 57005, + 973, 2148, -1000, 2097, 2097, 2097, 57005, -1000, -1000, -1000, + -1000, -1000, -1000, -525, 173, 321, -1000, -1000, -1000, 6784, + 55525, 1767, -1000, 198, -1000, 1705, -1000, 55525, -1000, 1765, + 2037, 55525, 55525, -1000, -1000, -1000, 55525, 1964, -1000, -1000, + -1000, -1000, 467, 2420, 344, -1000, -1000, -359, -1000, -1000, + 201, 198, 56265, 55525, 861, -1000, -1000, -1000, -1000, -1000, + -521, 1709, 459, 217, 271, 57005, 57005, 57005, 57005, 57005, + 57005, 788, -1000, -1000, -27, -1000, -1000, 180, -1000, -1000, + -1000, -1000, -1000, -1000, 180, -1000, -1000, -1000, -1000, -1000, + 272, 443, -1000, 57005, 57005, 918, -1000, -1000, -1000, -1000, + -1000, 1055, -1000, -1000, 1055, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2414, 57005, -44, + -490, -1000, -487, 22965, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 1232, 486, 1421, 25185, 25185, 2320, 2320, 25185, -1000, + -1000, -1000, 930, 930, 34805, -1000, 25185, 22965, -1000, -1000, + 22965, 22965, 22965, 952, -1000, 22965, 1228, -1000, 22965, -1000, + -321, 1433, 2194, 2194, 2194, 2194, -321, -321, -321, -321, + -321, -321, -321, -321, -321, -321, 1958, -1000, 22965, 22965, + 22965, 1417, 304, -1000, -1000, -1000, -321, 22965, -1000, -1000, + 2636, -1000, 22965, -1000, 34805, 22965, 22965, 22965, -1000, -1000, + -1000, 22965, 22965, -1000, -1000, 22965, -1000, 22965, -1000, -1000, + -1000, -1000, -1000, -1000, 22965, -1000, 22965, -1000, -1000, -1000, + 22965, -1000, 22965, -1000, -1000, 22965, -1000, 22965, -1000, 22965, + -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, + -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, + -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, + -1000, -1000, -1000, 22965, -1000, 22965, -1000, 22965, -1000, -1000, + 22965, -1000, 22965, -1000, 22965, -1000, 22965, 22965, -1000, 22965, + 22965, 22965, -1000, 22965, 22965, 22965, 22965, -1000, -1000, -1000, + -1000, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, 22965, + 22965, -1000, -1000, -1000, -1000, -1000, -1000, 22965, -1000, 40725, + 0, -321, 1594, 0, 1594, 24445, 812, 789, 23705, -1000, + 22965, 17033, -1000, -1000, -1000, -1000, -1000, 22965, 22965, 22965, + 22965, 22965, 22965, -1000, -1000, -1000, 22965, 22965, -1000, 22965, + -1000, 22965, -1000, -1000, -1000, -1000, -1000, 936, -1000, 434, + 430, 871, 55525, -1000, -1000, -1000, -1000, 1901, -1000, 2508, + -1000, 2245, 2239, 2632, 2619, 22225, -1000, 31105, -1000, -1000, + 55525, -444, -1000, 2277, 2344, 862, 862, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 14049, 2518, 22965, 2145, 56265, 197, + -1000, 30365, 55525, 56265, 31105, 31105, 31105, 31105, 31105, -1000, + 2207, 2199, -1000, 2196, 2190, 2403, 57005, -1000, 1799, 1704, + -1000, 22965, 33325, 1866, 31105, -1000, -1000, 31105, 57005, 13303, + -1000, -1000, -53, -69, -1000, -1000, -1000, -1000, 362, -1000, + -1000, 1071, 2484, 2291, -1000, -1000, -1000, -1000, -1000, 1669, + -1000, 1667, 1900, 1665, 1663, 340, -1000, 2104, 2394, 933, + 933, -1000, 1234, -1000, 1305, 1607, 1603, -1000, -1000, -1000, + 456, -1000, 2458, 57005, 2144, 2141, 2139, -1000, -539, 1233, + 2032, 1989, 22965, 2028, 2576, 1881, 55525, -1000, -1000, 56265, + -1000, 238, -1000, 471, 55525, -1000, -1000, -1000, 280, 57005, + -1000, 7666, -1000, -1000, -1000, 198, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 57005, 215, -1000, 2025, 1243, -1000, -1000, + 1988, -1000, -1000, -1000, -1000, -1000, 151, 141, 1599, 177, + 1567, 177, -1000, 57005, 916, 2059, 57005, -1000, -1000, -1000, + 1087, 1087, -1000, -1000, 2390, -1000, 1305, 2194, 25185, 25185, + -1000, 875, -1000, -1000, 418, -294, 2021, 2021, -1000, 2021, + 2022, -1000, 2021, 140, 2021, 134, 2021, -1000, -1000, 1417, + 1417, -1000, 1433, 2088, 2038, 2620, -1000, 1863, 22965, 2606, + -1000, -1000, -321, -321, -321, -321, -321, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -126, 2589, 2585, + 2194, -1000, 2015, 2003, -1000, 2194, 22965, 2194, 1417, 2082, + 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, + 2194, 2194, 2073, 2054, 2000, 1984, 1979, 1974, 1970, 1960, + 1954, 1950, 1930, 1889, 1839, 1835, 1827, 1816, 2194, 2194, + 1811, 2194, 1805, 1774, -1000, 1863, 1433, 2569, 1433, 2194, + 2194, 2557, 253, 2194, 1636, 1636, 1636, 1636, 1636, 1433, + 1433, 1433, 1433, 2194, 55525, -1000, -321, -1000, -1000, -384, + -385, -1000, 1417, -321, 1896, 25185, 2194, 25185, 25185, 25185, + 2194, 1417, -1000, 1763, 1702, 2520, 1696, 2194, 2294, 2194, + 2194, 2194, 1692, -1000, 2487, 1964, 2487, 1964, 2487, 1613, + 1236, 57005, -1000, -1000, -1000, -1000, 2619, 2572, -1000, 1888, + -1000, 16, 621, -1000, 2290, 2344, -1000, 2573, 2272, 2571, + -1000, -1000, -1000, -1000, -1000, 1863, -1000, 2426, 1857, -1000, + 939, 1844, -1000, -1000, 21485, 1623, 2230, 540, 1613, 1918, + 2767, 2127, 2136, 2755, -1000, -1000, -1000, -1000, 2192, -1000, + 2172, -1000, -1000, 1973, -1000, 1484, 335, 31105, 1911, 1911, + -1000, 533, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1082, + 7666, 2667, -1000, 1547, -1000, 1342, 206, 1216, -1000, -1000, + 933, 933, -1000, 1001, 997, -1000, 57005, 1999, -1000, 282, + 1543, 282, 1214, -1000, -1000, 1204, -1000, -1000, -1000, -1000, + 2049, 2226, -1000, -1000, -1000, -1000, 57005, -1000, -1000, 57005, + 57005, 57005, 1998, 2564, -1000, 22965, 1994, 938, 2544, 55525, + 55525, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 415, 933, -502, 277, 269, 933, 933, 933, + -540, -1000, -1000, 1595, 1587, -1000, -257, -1000, 22965, -1000, + -1000, -1000, -1000, -1000, 1221, 1221, 1535, 1533, 1528, -1000, + 1973, -1000, -1000, -1000, 1596, -1000, -1000, -242, 55525, 55525, + 55525, 55525, -1000, -1000, -1000, 1167, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 875, 1417, + 395, -246, 1417, -1000, -1000, 282, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 22965, -1000, 22965, -1000, + 22965, 1863, 22965, -1000, -1000, -1000, -1000, -1000, 2518, 1491, + 22965, 22965, -1000, 1191, 1177, -321, 2194, -1000, -1000, -1000, + 22965, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 22965, -1000, 22965, -1000, 22965, -1000, + 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, + 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, 22965, -1000, + 22965, -1000, 22965, -1000, 22965, -1000, -1000, 22965, -1000, -1000, + -1000, 22965, -1000, 22965, -1000, 22965, -1000, -1000, -1000, 22965, + 227, 930, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1417, 334, -1000, -1000, -1000, 2625, -1000, + 1417, 22965, 2320, -1000, 2320, 2320, 2320, -1000, -1000, -1000, + 22965, -1000, 22965, 22965, -1000, 22965, -1000, 22965, -1000, -1000, + -1000, -1000, 22965, 1964, 2359, 39985, 1964, 39985, 1964, 33325, + -1000, -1000, 2572, 2615, 2560, 2257, 2265, 2265, 2290, -1000, + 2555, 2536, -1000, 1481, 2535, 1478, 983, -1000, 56265, 22965, + -1000, 197, 39245, -1000, 413, 55525, 197, 55525, -1000, 2553, + -1000, -1000, 22965, 1983, -1000, 22965, -1000, -1000, -1000, -1000, + 6328, 2619, 1911, -1000, -1000, 889, -1000, 22965, -1000, 11034, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1475, 1471, + -1000, -1000, 1978, 22965, -1000, -1000, -1000, 1591, 1564, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1973, -1000, -1000, + -1000, -1000, 280, -527, 2537, 55525, 1172, -1000, 1563, 1881, + 297, 197, 1469, 933, 933, 933, 1157, 1153, 39245, 1558, + -1000, 55525, 402, -1000, 280, -1000, -273, -279, 2194, -1000, + -1000, 2483, -1000, -1000, 17033, -1000, -1000, 1968, 2058, -1000, + -1000, -1000, -1000, 2218, -234, -252, -1000, -1000, 2194, 2194, + 2194, 1239, 1417, -1000, 2194, 2194, 1559, 1552, -1000, -1000, + 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, + 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, + 1433, 1686, -1000, 227, 1417, 2135, -1000, -1000, 6328, -1000, + -1000, 2553, 2533, 0, -1000, -1000, 210, 0, 1863, 982, + 1417, 1417, 982, 1659, 2194, 1642, 1625, 2194, 2194, 34065, + -1000, 2529, 2523, 1525, -1000, -1000, 39985, 1525, 39985, 936, + 2615, -345, 22965, 22965, 2251, 1150, -1000, -1000, -1000, -1000, + 1450, 1391, -1000, 1373, -1000, 2666, -1000, 1863, -1000, 1964, + 197, -1000, 521, 1844, -1000, 2518, 1863, 55525, 1863, 18, + 2553, -1000, 2194, -1000, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, -1000, -1000, 55525, 2525, -1000, + -1000, 2482, 1556, 172, -1000, 1455, 1881, -1000, -1000, 245, + -1000, 22965, -1000, 39245, 1354, 1339, -1000, -1000, -1000, -1000, + -540, -1000, -1000, -1000, -1000, -1000, -1000, 394, 1879, -1000, + 932, 55525, 57005, -1000, 2001, -1000, -1000, -1000, -1000, 22965, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 22162, -1000, 1500, 2125, -1000, -352, -1000, - -495, 22162, -320, -1000, -1000, -320, -1000, -1000, -1000, -1000, - -1000, 22162, -1000, -1000, 22162, -1000, 22162, -1000, -1000, 1568, - -1000, -1000, -1000, 37534, -1000, 1568, -1000, 1568, -1000, -343, - -1000, 1870, -1000, 54370, 1527, 390, -1000, 1158, -1000, -1000, - -1000, -1000, -1000, 55102, 54370, 1904, 54370, -1000, -1000, 1556, - 1500, 2000, 2534, -1000, 1529, -1000, 389, -1000, 2002, 2059, - -1000, -1000, -1000, 19966, -1000, -1000, -1000, -1000, -1000, 233, - -207, 16294, 11866, 1503, -1000, -191, 2369, 1490, -1000, -468, - -1000, -1000, -1000, -1000, 283, -1000, -1000, 1857, -1000, -1000, - 1650, 1646, 1627, -1000, -1000, -1000, -1000, -1000, -1000, -343, - -1000, -1000, 2495, -1000, -255, -1000, -1000, 1832, 1441, -1000, - -1000, -1000, 32410, 53638, -1000, -179, 417, -207, 22162, 2001, - 1500, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -39, - -1000, -1000, 833, -1000, -1000, -1000, 2013, -215, -1000, -1000, - -1000, 337, -486, -286, -360, 24358, -1000, 22162, -1000, 22162, - -1000, 22162, -1000, 54370, 2000, -1000, -1000, -1000, 1419, -1000, - 4251, -388, 2121, -1000, -141, -1000, -1000, -1000, 1117, 1394, - -1000, -1000, -1000, -1000, -1000, -1000, 2477, 54370, -1000, 439, - -1000, -1000, 15556, -211, -219, 1011, -1000, -1000, -1000, -1000, - -1000, 1583, 1522, 1306, 2369, -1000, 54370, -1000, 53638, -381, - 924, 5565, -1000, 2119, 2079, 2630, -1000, -1000, -1000, -1000, - -1000, -1000, -540, 1399, 277, -1000, -1000, -1000, 337, -361, - -1000, 22162, -1000, 22162, -1000, 1500, -1000, -1000, 2484, 73, - -1000, 2652, -1000, 2649, 1005, 1005, -1000, 1145, -540, -1000, - -1000, -1000, -1000, 2369, 2369, -1000, -393, -1000, -1000, -1000, - -1000, -1000, 434, 1217, -1000, -1000, -1000, -1000, -1000, 5565, - -1000, -1000, -1000, 215, 215, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 22965, -1000, 1417, + 2134, -1000, -374, -1000, -508, 22965, -321, -1000, -1000, -321, + -1000, -1000, -1000, -1000, -1000, 22965, -1000, -1000, 22965, -1000, + 22965, -1000, -1000, 1525, -1000, -1000, -1000, 38505, -1000, 1525, + -1000, 1525, -1000, -345, -1000, 1877, -1000, 55525, 1863, 386, + -1000, 1133, -1000, -1000, -1000, -1000, -1000, 56265, 55525, 1844, + 55525, -1000, -1000, 1499, 1417, 1964, 2518, -1000, 1467, -1000, + 394, -1000, 1967, 1989, -1000, -1000, -1000, 20745, -1000, -1000, + -1000, -1000, -1000, 233, -241, 17033, 12557, 1454, -1000, -240, + 2194, 1433, -1000, -480, -1000, -1000, -1000, -1000, 279, -1000, + -1000, 1871, -1000, -1000, 1621, 1590, 1561, -1000, -1000, -1000, + -1000, -1000, -1000, -345, -1000, -1000, 2454, -1000, -287, -1000, + -1000, 1820, 1414, -1000, -1000, -1000, 33325, 54785, -1000, -229, + 426, -241, 22965, 1966, 1417, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -56, -1000, -1000, 516, -1000, -1000, -1000, + 1988, -250, -1000, -1000, -1000, 294, -493, -358, -367, 25185, + -1000, 22965, -1000, 22965, -1000, 22965, -1000, 55525, 1964, -1000, + -1000, -1000, 1363, -1000, 4226, -395, 2131, -1000, -150, -1000, + -1000, -1000, 1061, 1338, -1000, -1000, -1000, -1000, -1000, -1000, + 2516, 55525, -1000, 417, -1000, -1000, 16287, -242, -253, 977, + -1000, -1000, -1000, -1000, -1000, 2320, 1527, 1416, 2194, -1000, + 55525, -1000, 54785, -390, 861, 6328, -1000, 2129, 2092, 2630, + -1000, -1000, -1000, -1000, -1000, -1000, -543, 1359, 218, -1000, + -1000, -1000, 294, -376, -1000, 22965, -1000, 22965, -1000, 1417, + -1000, -1000, 2455, 18, -1000, 2657, -1000, 2652, 957, 957, + -1000, 1112, -543, -1000, -1000, -1000, -1000, 2194, 2194, -1000, + -396, -1000, -1000, -1000, -1000, -1000, 408, 1174, -1000, -1000, + -1000, -1000, -1000, 6328, -1000, -1000, -1000, 268, 268, -1000, + -1000, } var yyPgo = [...]int{ - 0, 3231, 3230, 26, 4, 38, 37, 3229, 3227, 3226, - 174, 3225, 3223, 3222, 3221, 3220, 3219, 2723, 2712, 2693, - 3218, 3217, 3216, 3214, 3213, 3212, 3211, 3209, 3198, 46, - 95, 75, 102, 187, 201, 3197, 173, 164, 194, 3196, - 3195, 3194, 112, 179, 72, 82, 181, 3193, 3192, 65, - 3189, 3188, 3187, 210, 209, 204, 1107, 3185, 202, 105, - 48, 3182, 3179, 3177, 3176, 3175, 3170, 3169, 3168, 3167, - 3166, 3163, 3160, 3157, 3154, 3153, 3152, 3148, 3145, 307, - 3138, 3135, 17, 3129, 71, 3127, 3125, 3124, 3122, 3120, - 8, 3118, 3115, 23, 32, 59, 3106, 3105, 45, 3103, - 3100, 3099, 3098, 3097, 42, 3095, 24, 3094, 31, 3091, - 3089, 121, 3076, 3071, 3059, 41, 3058, 3055, 3051, 25, - 168, 3048, 3047, 137, 3043, 3042, 3041, 167, 193, 3037, - 2301, 3033, 94, 3029, 3025, 3024, 162, 191, 3021, 114, - 3020, 3019, 3018, 143, 3017, 3309, 3016, 3015, 66, 70, - 195, 3014, 3010, 227, 68, 58, 3009, 13, 16, 3008, - 3007, 67, 63, 3003, 109, 3001, 2992, 97, 84, 2991, - 93, 111, 2989, 2988, 2, 14, 2987, 5, 1, 7, - 101, 2977, 2976, 118, 2972, 2971, 2965, 91, 2962, 2951, - 407, 2945, 87, 126, 98, 81, 2944, 169, 152, 2941, - 2940, 2939, 2935, 2933, 2929, 51, 2927, 2926, 2925, 135, - 288, 116, 2924, 145, 349, 52, 147, 2921, 205, 77, - 197, 186, 2920, 2916, 133, 131, 2914, 2909, 55, 166, - 196, 2908, 96, 127, 120, 170, 89, 128, 2905, 2902, - 56, 62, 2899, 2896, 2895, 2893, 172, 2892, 2889, 60, - 2888, 54, 2887, 165, 2885, 331, 74, 2884, 188, 154, - 2878, 61, 2876, 2870, 73, 130, 117, 27, 2869, 153, - 158, 124, 160, 2867, 2865, 53, 2864, 2863, 2862, 184, - 276, 2854, 2851, 342, 175, 138, 149, 83, 2848, 284, - 2845, 2843, 10, 4461, 7231, 178, 29, 159, 2842, 2837, - 7803, 39, 44, 21, 2836, 208, 2834, 185, 2833, 2832, - 2830, 192, 206, 99, 156, 57, 2829, 2828, 2824, 2822, - 33, 2821, 2807, 2805, 2804, 2803, 2798, 36, 35, 34, - 90, 217, 64, 18, 108, 155, 150, 69, 2794, 2792, - 2789, 115, 92, 2785, 157, 151, 123, 104, 2780, 177, - 142, 119, 2776, 134, 30, 2774, 2767, 2766, 2765, 85, - 2764, 2763, 2762, 2761, 148, 141, 113, 79, 2760, 80, - 106, 144, 146, 50, 2759, 43, 2753, 2750, 28, 180, - 22, 2747, 40, 100, 110, 2745, 6349, 2744, 15, 296, - 189, 2741, 2740, 6, 9, 12, 2734, 2733, 2732, 2731, - 129, 2728, 2714, 2701, 2700, 20, 47, 19, 11, 103, - 136, 76, 2699, 2694, 140, 2689, 2688, 2684, 0, 1032, - 125, 2647, 198, + 0, 3260, 3259, 18, 5, 39, 38, 3258, 3257, 3255, + 175, 3252, 3251, 3250, 3247, 3246, 3245, 2710, 2704, 2690, + 3244, 3241, 3219, 3218, 3217, 3213, 3211, 3209, 3207, 40, + 96, 33, 95, 198, 202, 3204, 173, 164, 199, 3201, + 3199, 3195, 113, 193, 76, 83, 189, 3193, 3191, 74, + 3190, 3189, 3187, 192, 191, 182, 1063, 3184, 190, 110, + 48, 3183, 3182, 3180, 3179, 3178, 3177, 3176, 3175, 3174, + 3173, 3168, 3167, 3165, 3164, 3163, 3162, 3161, 3160, 248, + 3159, 3154, 17, 3151, 77, 3149, 3148, 3147, 3141, 3131, + 9, 3130, 3129, 13, 41, 59, 3127, 3125, 44, 3123, + 3122, 3117, 3116, 3111, 80, 3110, 15, 3104, 31, 3103, + 3098, 127, 3096, 3091, 3083, 42, 3080, 3079, 3078, 14, + 168, 3077, 3076, 139, 3073, 3070, 3068, 174, 197, 3067, + 2320, 3063, 100, 3062, 3059, 3058, 165, 187, 3054, 118, + 3053, 3051, 3050, 150, 3048, 3333, 3047, 3045, 63, 73, + 169, 3042, 3040, 166, 68, 8, 3037, 21, 22, 3035, + 3032, 65, 70, 3029, 104, 3028, 3027, 99, 94, 3024, + 108, 97, 3022, 3016, 27, 7, 3015, 1, 6, 4, + 115, 3014, 3005, 106, 3001, 2997, 2991, 92, 2990, 2984, + 3380, 2983, 85, 129, 102, 67, 2981, 170, 158, 2979, + 2973, 2972, 2969, 2965, 2960, 52, 2959, 2958, 2956, 137, + 1562, 112, 2955, 146, 359, 56, 149, 2954, 212, 79, + 201, 172, 2953, 2949, 136, 132, 2947, 2945, 54, 167, + 194, 2944, 91, 131, 117, 188, 90, 135, 2943, 2941, + 58, 60, 2940, 2937, 2936, 2935, 186, 2927, 2926, 66, + 2923, 55, 2922, 171, 2920, 314, 78, 2916, 185, 162, + 2914, 62, 2911, 2910, 101, 93, 64, 30, 2909, 159, + 163, 124, 157, 2902, 2900, 53, 2894, 2891, 2889, 195, + 258, 2885, 2883, 339, 177, 142, 148, 87, 2882, 321, + 2881, 2879, 2874, 47, 5156, 7268, 180, 28, 161, 2873, + 2872, 8471, 49, 45, 26, 2870, 210, 2867, 206, 2864, + 2862, 2861, 200, 196, 105, 160, 57, 2859, 2855, 2852, + 2851, 72, 2847, 2839, 2838, 2829, 2825, 2823, 37, 35, + 34, 71, 209, 61, 10, 98, 153, 152, 69, 2822, + 2821, 2819, 123, 84, 2818, 156, 155, 125, 126, 2817, + 179, 143, 116, 2809, 277, 32, 2804, 2801, 2799, 2797, + 89, 2776, 2773, 2771, 2767, 151, 144, 120, 82, 2766, + 81, 114, 147, 145, 51, 2763, 46, 2762, 2759, 29, + 181, 16, 2754, 19, 103, 111, 2753, 6397, 2752, 12, + 342, 154, 2751, 2749, 11, 20, 25, 2747, 2745, 2742, + 2725, 130, 2722, 2720, 2719, 2718, 24, 50, 23, 2, + 109, 138, 75, 2717, 2714, 141, 2703, 2697, 2695, 0, + 1042, 128, 2688, 203, } -//line sql.y:8691 +//line sql.y:8750 type yySymType struct { union any empty struct{} @@ -8510,122 +8647,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, + 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, 153, 153, 153, 153, 153, 153, + 150, 150, 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, 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, + 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, @@ -8644,69 +8782,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, 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, + 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, 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, + 119, 119, 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, + 120, 120, 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, @@ -8722,21 +8827,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, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 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, 293, 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, 294, 294, 419, + 420, 312, 313, 313, 313, } var yyR2 = [...]int{ @@ -8774,136 +8913,138 @@ 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, + 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, 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, + 1, 1, 3, 4, 6, 4, 4, 8, 8, 6, + 8, 6, 5, 4, 10, 2, 2, 1, 2, 2, + 2, 2, 2, 5, 6, 6, 6, 6, 6, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, + 4, 8, 8, 6, 5, 4, 4, 4, 5, 7, + 4, 4, 7, 4, 4, 6, 6, 6, 8, 6, + 6, 4, 4, 3, 4, 6, 6, 4, 4, 6, + 4, 6, 4, 4, 4, 4, 4, 4, 6, 4, + 6, 4, 4, 4, 6, 4, 6, 4, 4, 6, + 4, 6, 4, 6, 8, 4, 6, 8, 4, 6, + 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 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, + 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, 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, 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, @@ -8966,657 +9107,662 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 1, 1, + 1, 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, 234, -51, -41, 235, -52, 237, 236, 274, 238, - 387, 267, 79, 323, 324, 326, 327, 328, 329, -110, - 694, 272, 273, 240, 38, 50, 35, 36, 39, 244, - 280, 281, 243, 140, -33, -36, 11, -418, 14, 477, - 269, 268, 30, -34, 587, 91, -80, -417, 742, -253, - -237, 25, 35, 31, -236, -232, -128, -237, 23, 21, - 10, -79, -79, -79, 15, 16, -79, -355, -357, 91, - 167, 91, -79, -57, -56, -54, -53, -55, -58, 33, - -47, -48, -379, -46, -43, 239, 236, 284, 130, 131, - 274, 275, 276, 238, 258, 273, 277, 272, 293, -42, - 86, 35, 587, 590, -362, 235, 241, 242, 237, 478, - 133, 132, 80, -359, 382, 621, 712, -58, 714, 105, - 108, 713, 49, 248, 715, 716, 717, 628, 718, 257, - 719, 720, 721, 722, 728, 669, 729, 730, 731, 134, - 10, -79, -304, -300, 95, -293, 584, 260, 619, 431, - 620, 309, 86, 46, 41, 523, 594, 379, 382, 621, - 508, 712, 388, 323, 339, 333, 513, 514, 515, 362, - 354, 585, 622, 595, 312, 261, 297, 706, 352, 143, - 714, 316, 623, 275, 389, 390, 624, 391, 105, 326, - 428, 727, 315, 625, 725, 108, 713, 331, 84, 507, - 56, 709, 49, 270, 436, 437, 350, 243, 346, 715, - 298, 626, 597, 291, 133, 130, 734, 38, 342, 55, - 32, 724, 132, 54, 716, 158, 627, 717, 628, 393, - 369, 700, 53, 394, 276, 629, 89, 281, 589, 320, - 708, 395, 528, 343, 396, 308, 723, 240, 630, 319, - 689, 681, 682, 397, 398, 701, 374, 370, 375, 530, - 631, 420, 512, 399, 685, 686, 741, 57, 632, 633, - 702, 131, 634, 83, 718, 85, 337, 338, 635, 306, - 259, 533, 534, 422, 366, 490, 122, 497, 498, 115, - 116, 493, 117, 499, 118, 123, 500, 501, 502, 491, - 119, 112, 492, 503, 504, 367, 368, 120, 505, 114, - 113, 494, 496, 121, 506, 257, 37, 400, 586, 310, - 63, 314, 285, 423, 51, 372, 738, 50, 696, 535, - 636, 699, 365, 361, 487, 58, 637, 638, 639, 640, - 509, 719, 364, 336, 360, 733, 4, 303, 482, 510, - 720, 67, 242, 377, 376, 378, 292, 419, 357, 641, - 642, 643, 264, 87, 644, 347, 24, 645, 646, 401, - 299, 647, 61, 648, 649, 426, 273, 650, 59, 721, - 44, 651, 278, 735, 722, 652, 653, 654, 695, 655, - 280, 656, 403, 657, 683, 684, 402, 371, 373, 536, - 287, 404, 387, 245, 588, 658, 321, 341, 277, 726, - 659, 265, 524, 525, 526, 527, 707, 532, 531, 279, - 284, 272, 427, 266, 660, 661, 662, 663, 664, 313, - 680, 665, 666, 327, 592, 728, 488, 48, 667, 668, - 669, 670, 671, 307, 302, 421, 430, 66, 88, 384, - 672, 673, 705, 335, 332, 42, 300, 468, 470, 471, - 472, 473, 474, 469, 476, 674, 324, 60, 729, 730, - 731, 294, 732, 516, 517, 518, 519, 12, 570, 553, - 581, 554, 571, 555, 564, 556, 572, 580, 582, 537, - 545, 538, 546, 576, 559, 573, 565, 558, 557, 579, - 562, 566, 539, 547, 577, 563, 540, 548, 541, 549, - 542, 550, 575, 574, 567, 578, 543, 551, 569, 544, - 552, 568, 560, 561, 439, 739, 740, 511, 406, 134, - 304, 305, 52, 358, 286, 675, 317, 676, 348, 349, - 484, 485, 363, 334, 359, 692, 325, 690, 288, 407, - 489, 274, 677, 429, 301, 380, 126, 385, 318, 593, - 529, 293, 408, 704, 591, 520, 521, 356, 353, 295, - 522, 678, 694, 409, 249, 289, 290, 679, 691, 410, - 411, 311, 412, 413, 414, 415, 416, 418, 322, 417, - 693, 687, 688, 296, 467, 590, 330, 351, 386, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 486, 247, -79, - 247, -190, -300, -130, 696, 698, 186, -272, 390, -290, - 392, 405, 400, 410, 398, -281, 401, 403, 287, -402, - 420, 247, 407, 234, 393, 402, 411, 412, 311, 418, - 413, 322, 417, 296, 414, 415, 416, -386, 186, 717, - 732, 143, 355, 397, 395, 421, 696, 95, -306, 95, - 96, 97, -293, 325, -309, 330, -294, -386, -293, 328, - -79, -79, -311, -311, -130, -210, -145, 151, -159, -261, - -162, 96, -150, -153, -204, -205, -206, -207, -160, -220, - -259, 175, 176, 183, 152, -216, -163, 28, 583, 479, - 478, 186, 33, 229, 73, 74, 481, 482, 154, 62, - 14, 444, 445, -161, 434, 435, 446, 440, 441, 507, - 509, 510, 511, 508, 513, 514, 515, 516, 517, 518, - 519, 520, 521, 522, 512, 523, 484, 485, 124, 486, - 112, 114, 113, 122, 123, 487, 488, 489, 352, 535, - 536, 530, 533, 534, 532, 531, 367, 368, 490, 553, - 554, 558, 557, 555, 556, 559, 562, 563, 564, 565, - 566, 567, 569, 568, 560, 561, 538, 537, 539, 540, - 541, 542, 543, 544, 546, 545, 547, 548, 549, 550, - 551, 552, 570, 571, 572, 573, 574, 576, 575, 580, - 579, 577, 578, 582, 581, 491, 492, 115, 116, 117, - 118, 119, 120, 121, 493, 496, 494, 495, 497, 498, - 499, 504, 505, 500, 501, 502, 503, 506, 378, 376, - 377, 373, 372, 371, -89, -102, 610, 609, -103, 431, - 436, 437, 439, -151, -152, -165, -166, -294, -300, 252, - 433, 246, 181, 477, -154, -148, -218, 111, 97, -31, - -214, 432, 442, 443, 447, 438, 448, 596, 598, 613, - 614, 616, 601, 606, 605, 608, 524, 525, 526, 527, - 528, 529, 681, 682, 683, 684, 685, 686, 687, 688, - -386, -293, 95, -157, -155, -199, 98, 103, 106, 107, - 109, -408, 270, 348, 349, 125, -418, 710, -156, 100, - 101, 102, 127, 128, 187, 188, 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, 228, 94, 99, 49, 406, - 406, -190, -79, -79, -79, -79, -415, 713, 588, -230, - -128, -232, -33, -31, -418, 11, -79, -31, -32, -30, - -36, -38, 615, -37, -300, 104, -237, -253, 15, 66, - 170, 47, 55, -235, -236, -34, -31, -145, 22, 40, - 26, -132, 177, -145, -300, -132, -279, 251, -79, -79, - -268, -314, 325, -270, 421, 696, 420, -260, -273, 95, - -259, -272, 419, 96, -356, 167, -342, -346, -294, 262, - -372, 258, -190, -365, -364, -294, -418, -129, -289, 248, - 256, 255, 144, -389, 147, 304, 433, 246, -53, -54, - -55, -272, 185, 716, -111, 279, 283, 92, 92, -346, - -345, -344, -390, 283, 262, -371, -363, 254, 263, -352, - 255, 256, -347, 248, 145, -390, -347, 253, 263, 258, - 262, 283, 283, 134, 283, 134, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 278, -353, 159, -353, 591, - 591, -359, -390, 258, 248, -390, -390, 254, -291, -347, - 250, 27, 250, 37, 37, -353, -353, -353, -272, 185, - -353, -353, -353, -353, 291, 291, -353, -353, -353, -353, - -353, -353, -353, -353, -353, -353, -353, -353, -353, -353, - -353, -353, -353, 247, -389, -137, 417, 311, 86, -56, - 293, -39, -190, -289, 248, 249, -389, 280, -190, 230, - 247, 699, -283, 167, 18, -283, -280, 406, 404, 391, - 396, -283, -283, -283, -283, 294, 389, -348, 248, 37, - 259, 406, 294, 389, 294, 295, 294, 295, 399, 409, - 294, -305, 17, 170, 433, 394, 398, 287, 247, 288, - 249, 408, 295, -305, 94, -284, 167, 294, 406, 400, - 290, -283, -283, -312, -418, -296, -294, -292, 239, 40, - 150, 27, 29, 153, 186, 137, 22, 154, 39, 241, - 355, 258, 185, 254, 478, 234, 77, 596, 434, 441, - 432, 440, 444, 480, 481, 433, 392, 33, 16, 598, - 30, 268, 26, 43, 179, 236, 157, 599, 271, 28, - 269, 124, 128, 601, 25, 80, 263, 17, 256, 45, - 19, 602, 603, 20, 252, 251, 170, 248, 75, 14, - 229, 31, 166, 71, 604, 145, 140, 605, 606, 607, - 608, 138, 73, 167, 23, 736, 442, 443, 35, 697, - 583, 282, 181, 78, 64, 698, 151, 438, 609, 610, - 125, 611, 129, 81, 703, 147, 21, 76, 47, 612, - 283, 613, 253, 737, 614, 424, 615, 168, 237, 477, - 74, 169, 710, 616, 711, 246, 405, 11, 483, 34, - 267, 255, 136, 72, 448, 617, 247, 156, 250, 139, - 127, 10, 144, 36, 15, 79, 82, 445, 446, 447, - 62, 135, 587, 155, 18, 618, 425, 149, -386, 699, - -312, -312, 34, 96, -412, -413, -414, 587, 424, 250, - -294, -190, -85, 689, 238, -86, 695, 40, 245, -135, - 406, -123, 186, 717, 700, 701, 702, 699, 403, 707, - 705, 703, 294, 704, 92, 147, 149, 150, 4, -145, - 166, -200, -201, 165, 159, 160, 161, 162, 163, 164, - 171, 170, 151, 153, 167, -246, 148, 172, 173, 174, - 175, 176, 177, 178, 180, 179, 181, 182, 168, 169, - 185, 232, 233, -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, -418, -418, 230, -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, 311, -294, -294, 280, 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, 643, 673, 643, 673, 66, 48, - 94, 94, 92, 24, -231, -233, -145, 17, -298, 4, - -297, 27, -294, 94, 230, 17, -191, 31, -190, -279, - -279, 92, 95, 325, -269, -271, 422, 424, 159, -299, - -294, 94, 33, 93, 92, -190, -320, -323, -325, -324, - -326, -321, -322, 352, 353, 186, 356, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 369, 34, 270, 348, - 349, 350, 351, 370, 371, 372, 373, 375, 376, 377, - 378, 333, 354, 585, 334, 335, 336, 337, 338, 339, - 341, 342, 345, 343, 344, 346, 347, -295, -294, 91, - 93, 92, -330, 91, -145, -137, 247, -294, 248, 248, - 248, -79, 477, -353, -353, -353, 278, 22, -46, -43, - -379, 21, -42, -43, 239, 130, 131, 236, 91, -342, - 91, -351, -295, -294, 91, 145, 253, 144, -350, -347, - -350, -351, -294, -218, -294, 145, 145, -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, 264, 308, 310, 100, 100, - 100, 100, 33, 94, -392, 33, 724, 723, 725, 726, - 727, 94, 100, 33, 100, 33, 100, -294, 91, -190, - -143, 298, 234, 236, 239, 81, 94, 314, 315, 312, - 317, 318, 319, 159, 49, 92, 250, 247, -294, -285, - 252, -285, -294, -301, -300, -292, -190, 250, 388, 94, - -145, -349, 17, 170, -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, 699, 94, -277, 17, 81, -312, -312, 92, - 331, 425, 426, -310, 328, -81, -294, 94, -10, -29, - -18, -17, -19, 159, -10, 92, 587, -183, -190, 699, - 699, 699, 699, 699, 699, -145, -145, -145, -145, 611, - -208, -410, 151, 127, 128, 125, 126, -162, 41, 42, - 40, -145, -209, -214, -216, 110, 170, 153, 167, -246, - -150, -153, -150, -150, -150, -150, -150, -150, 229, -150, - 229, -150, -150, -150, -150, -150, -150, -313, -294, 94, - 186, -158, -157, 109, -408, -158, 584, 92, -221, 230, - -145, -145, -386, -119, 450, 451, 452, 453, 455, 456, - 457, 460, 461, 465, 466, 449, 467, 454, 459, 462, - 463, 464, 458, 351, -145, -211, -210, -211, -145, -145, - -223, -224, 155, -218, -145, -419, -419, 100, 177, -127, - 26, 43, -127, -127, -127, -127, -145, -145, -145, -145, - -145, -145, -145, -145, -145, -145, -127, -145, -120, 449, - 467, 454, 459, 462, 463, 464, 458, 351, 468, 469, - 470, 471, 472, 473, 474, 475, 476, -120, -119, -145, - -145, -145, -145, -145, -145, -145, -145, -87, -145, 137, - 138, 139, -210, -145, -150, -145, -145, -145, -419, -145, + -8, -32, -31, -30, 13, 14, -109, -35, 35, -40, + -50, 239, -51, -41, 240, -52, 242, 241, 279, 243, + 395, 272, 83, 328, 329, 331, 332, 333, 334, -110, + 702, 277, 278, 245, 39, 51, 36, 37, 40, 249, + 285, 286, 248, 145, -33, -36, 12, -419, 15, 485, + 274, 273, 31, -34, 595, 95, -80, -418, 750, -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, 595, 598, -363, 240, 246, 247, 242, 486, + 138, 137, 84, -360, 390, 629, 720, -58, 722, 110, + 113, 721, 50, 253, 723, 724, 725, 636, 726, 262, + 727, 728, 729, 730, 736, 677, 737, 738, 739, 139, + 11, -79, -305, -301, 100, -294, 592, 265, 627, 439, + 628, 314, 90, 47, 42, 531, 602, 386, 390, 629, + 516, 720, 396, 328, 346, 340, 521, 522, 523, 369, + 361, 593, 630, 603, 317, 266, 302, 714, 359, 148, + 722, 321, 631, 280, 397, 398, 632, 399, 110, 331, + 436, 735, 320, 633, 733, 113, 721, 336, 88, 515, + 57, 717, 50, 275, 444, 445, 357, 248, 353, 723, + 303, 634, 605, 296, 138, 135, 742, 39, 349, 56, + 33, 732, 137, 55, 724, 163, 635, 725, 636, 401, + 376, 708, 54, 402, 281, 637, 93, 286, 597, 325, + 716, 403, 536, 350, 404, 313, 731, 245, 638, 324, + 697, 689, 690, 405, 406, 709, 381, 377, 382, 538, + 639, 428, 520, 407, 693, 694, 749, 58, 640, 641, + 710, 136, 642, 87, 726, 89, 344, 345, 643, 311, + 264, 541, 542, 430, 373, 498, 127, 505, 506, 120, + 121, 501, 122, 507, 123, 128, 508, 509, 510, 499, + 124, 117, 500, 511, 512, 374, 375, 125, 513, 119, + 118, 502, 504, 126, 514, 262, 38, 408, 594, 315, + 64, 319, 290, 431, 52, 379, 746, 51, 704, 543, + 644, 707, 372, 368, 495, 59, 645, 646, 647, 648, + 517, 727, 371, 343, 367, 741, 4, 308, 490, 518, + 728, 68, 247, 384, 383, 385, 297, 427, 364, 649, + 650, 651, 269, 91, 652, 354, 25, 653, 654, 409, + 304, 655, 62, 656, 657, 434, 278, 658, 60, 729, + 45, 659, 283, 743, 730, 660, 661, 662, 703, 663, + 285, 664, 411, 665, 691, 692, 410, 378, 380, 544, + 292, 412, 395, 250, 596, 666, 326, 348, 282, 734, + 667, 270, 532, 533, 534, 535, 715, 540, 539, 284, + 289, 277, 435, 271, 668, 669, 670, 671, 672, 318, + 688, 673, 674, 332, 600, 736, 496, 49, 675, 676, + 677, 678, 679, 312, 307, 429, 438, 67, 92, 392, + 680, 681, 713, 342, 337, 43, 305, 99, 476, 478, + 479, 480, 481, 482, 477, 484, 682, 329, 61, 737, + 738, 739, 299, 740, 524, 525, 526, 527, 13, 578, + 561, 589, 562, 579, 563, 572, 564, 580, 588, 590, + 545, 553, 546, 554, 584, 567, 581, 573, 566, 565, + 587, 570, 574, 547, 555, 585, 571, 548, 556, 549, + 557, 550, 558, 583, 582, 575, 586, 551, 559, 577, + 552, 560, 576, 568, 569, 447, 747, 748, 519, 414, + 139, 309, 310, 53, 365, 291, 683, 322, 684, 355, + 356, 492, 493, 370, 341, 366, 700, 330, 339, 698, + 293, 415, 497, 279, 685, 437, 306, 387, 131, 338, + 393, 323, 601, 537, 298, 416, 712, 599, 528, 529, + 363, 360, 300, 530, 686, 388, 702, 417, 254, 294, + 295, 687, 699, 418, 419, 316, 420, 421, 422, 423, + 424, 426, 327, 425, 701, 695, 696, 301, 475, 598, + 335, 358, 394, 457, 458, 459, 460, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 494, 252, -79, 252, -190, -301, -130, 704, 706, + 191, -272, 398, -290, 400, 413, 408, 418, 406, -281, + 409, 411, 292, -403, 428, 252, 415, 239, 401, 410, + 419, 420, 316, 426, 421, 327, 425, 301, 422, 423, + 424, -387, 191, 725, 740, 330, 338, 148, 362, 405, + 403, 429, 704, 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, 591, 487, 486, 191, 34, 234, + 77, 78, 489, 490, 159, 63, 15, 452, 453, -161, + 442, 443, 454, 448, 449, 515, 517, 518, 519, 516, + 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, + 520, 531, 492, 493, 129, 494, 117, 119, 118, 127, + 128, 495, 496, 497, 359, 543, 544, 538, 541, 542, + 540, 539, 374, 375, 498, 561, 562, 566, 565, 563, + 564, 567, 570, 571, 572, 573, 574, 575, 577, 576, + 568, 569, 546, 545, 547, 548, 549, 550, 551, 552, + 554, 553, 555, 556, 557, 558, 559, 560, 578, 579, + 580, 581, 582, 584, 583, 588, 587, 585, 586, 590, + 589, 499, 500, 120, 121, 122, 123, 124, 125, 126, + 501, 504, 502, 503, 505, 506, 507, 512, 513, 508, + 509, 510, 511, 514, 385, 383, 384, 380, 379, 378, + -89, -102, 618, 617, -103, 439, 444, 445, 447, -151, + -152, -165, -166, -295, -301, 257, 441, 251, 186, 485, + -154, -148, -218, 116, 102, -31, -214, 440, 450, 451, + 455, 446, 456, 604, 606, 621, 622, 624, 609, 614, + 613, 616, 532, 533, 534, 535, 536, 537, 689, 690, + 691, 692, 693, 694, 695, 696, -387, -294, 100, -157, + -155, -199, 103, 108, 111, 112, 114, -409, 275, 355, + 356, 130, -419, 718, -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, 227, 228, 229, 230, 231, + 232, 233, 98, 104, 50, 414, 414, -190, -79, -79, + -79, -79, -416, 721, 596, -230, -128, -232, -33, -31, + -419, 12, -79, -31, -32, -30, -36, -38, 623, -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, + 429, 704, 428, -260, -273, 100, -259, -272, 427, 101, + -357, 172, -343, -347, -295, 267, -373, 263, -190, -366, + -365, -295, -419, -129, -289, 253, 261, 260, 149, -390, + 152, 309, 441, 251, -53, -54, -55, -272, 190, 724, + -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, 599, 599, -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, 425, 316, 90, -56, 298, -39, -190, -289, + 253, 254, -390, 285, -190, 235, 252, 707, -283, 172, + 19, -283, -280, 414, 412, 399, 404, -283, -283, -283, + -283, 299, 397, -349, 253, 38, 264, 414, 299, 397, + 299, 300, 299, 300, 407, 417, 299, -306, 18, 175, + 441, 402, 406, 292, 252, 293, 254, 416, 300, -306, + 98, -284, 172, 299, 414, 408, 295, -283, -283, -313, + -419, -297, -295, -293, 244, 41, 155, 28, 30, 158, + 191, 142, 23, 159, 40, 246, 362, 263, 190, 259, + 486, 239, 81, 604, 442, 449, 440, 448, 452, 488, + 489, 441, 400, 34, 17, 606, 31, 273, 27, 44, + 184, 241, 162, 607, 276, 29, 274, 129, 133, 609, + 26, 84, 268, 18, 261, 46, 20, 610, 611, 21, + 74, 257, 256, 175, 253, 79, 15, 234, 32, 171, + 75, 612, 150, 145, 613, 614, 615, 616, 143, 77, + 172, 24, 744, 450, 451, 36, 705, 591, 287, 186, + 82, 65, 706, 156, 446, 617, 618, 130, 619, 134, + 85, 711, 152, 22, 80, 48, 620, 288, 621, 258, + 745, 622, 432, 623, 173, 242, 485, 78, 174, 718, + 624, 719, 251, 413, 12, 491, 35, 272, 260, 73, + 72, 141, 76, 456, 625, 252, 161, 255, 144, 132, + 11, 149, 37, 16, 83, 86, 453, 454, 455, 63, + 140, 595, 160, 19, 626, 433, 154, -387, 707, -313, + -313, 299, 339, 35, 101, -413, -414, -415, 595, 432, + 255, -295, -190, -85, 697, 243, -86, 703, 41, 250, + -135, 414, -123, 191, 725, 708, 709, 710, 707, 411, + 715, 713, 711, 299, 712, 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, 651, + 681, 651, 681, 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, 430, 432, 164, -300, -295, 98, 34, 97, 96, + -190, -321, -324, -326, -325, -327, -322, -323, 359, 360, + 191, 363, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 376, 388, 35, 275, 355, 356, 357, 358, 377, + 378, 379, 380, 382, 383, 384, 385, 340, 361, 593, + 341, 342, 343, 344, 345, 346, 348, 349, 352, 350, + 351, 353, 354, -296, -295, 95, 97, 96, -331, 95, + -145, -137, 252, -295, 253, 253, 253, -79, 485, -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, 732, 731, 733, 734, 735, 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, 396, 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, 707, + 98, -277, 18, 85, -313, -313, -292, 26, 26, 96, + 336, 433, 434, -311, 333, -81, -295, 98, -10, -29, + -18, -17, -19, 164, -10, 96, 595, -183, -190, 707, + 707, 707, 707, 707, 707, -145, -145, -145, -145, 619, + -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, 592, 96, -221, 235, + -145, -145, -387, -119, 458, 459, 460, 461, 463, 464, + 465, 468, 469, 473, 474, 457, 475, 462, 467, 470, + 471, 472, 466, 358, -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, 457, + 475, 462, 467, 470, 471, 472, 466, 358, 476, 477, + 478, 479, 480, 481, 482, 483, 484, -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, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -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, -386, + -385, -384, -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, + -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, -419, -145, -145, -145, -145, -145, -253, - -419, -210, 92, -401, 424, 425, 697, -303, 283, -302, - 27, -211, 94, 17, -263, 82, -294, -235, -235, 68, - 69, 64, -131, -132, -136, -419, -37, 27, -255, -294, - 636, 636, 67, 94, -332, -272, 379, 380, 186, -145, - -145, 92, -234, 29, 30, -190, -297, 177, -301, -190, - -264, 283, -190, -168, -170, -171, -172, -193, -217, -418, - -173, -31, 607, 604, 17, -183, -184, -192, -300, -270, - -314, -269, 92, 423, 425, 426, 81, 129, -145, -333, - 185, -361, -360, -359, -342, -344, -345, -346, 93, -333, - -338, 385, 384, -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, 257, 105, 679, 635, 587, - 628, 669, 82, -364, -234, 100, -419, -143, -286, 252, - -370, -367, -294, -294, -294, -286, 95, 94, 95, 94, - 95, 94, -112, -60, -1, 736, 737, 738, 92, 22, - -343, -342, -59, 308, -375, -376, 283, -371, -365, -351, - 145, -350, -351, -351, -294, 92, 31, 134, 134, 134, - 134, 587, 236, 34, -287, 627, 151, 679, 635, -342, - -59, 250, 250, -313, -313, -313, 94, 94, -282, 732, - -183, -139, 300, 159, 289, 289, 247, 302, 247, 302, - -190, 313, 316, 314, 315, 312, 317, 318, 319, 40, - 40, 40, 40, 40, 40, 301, 303, 305, 291, -190, - -190, -285, 81, -185, -190, 28, -300, 94, 94, -190, - -283, -283, -190, -283, -283, -190, -414, 332, -294, 366, - 690, 692, -123, 424, 92, 587, 25, -124, 25, -418, - -410, 127, 128, -216, -216, -216, -209, -150, -153, -150, - 150, 271, -150, -150, -418, -218, -419, -296, 27, 92, - 82, -419, 175, 92, -419, -419, 92, 17, 92, -226, - -224, 157, -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, 92, -419, -419, -225, -419, 17, -419, - 82, 92, 170, 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, 612, -419, -419, 92, -419, - 92, 92, 92, 92, 92, -419, -418, 230, -419, -419, - -419, -419, -419, 92, 92, 92, 92, 92, 92, -419, - -419, -419, 92, 92, -419, 92, -419, 92, -419, -400, - 696, 425, -197, -196, -194, 79, 251, 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, 186, -334, 186, -334, 379, 380, -233, - 230, -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, 230, -271, -274, 427, 424, - 430, -386, 94, -111, 92, -359, -346, -238, -140, 45, - -339, 386, -332, 595, -332, -341, 94, -341, 100, 100, - 100, 93, -49, -44, -45, 35, 86, -366, -353, 94, - 44, -353, -353, -294, 93, -234, -139, -190, 151, 81, - -370, -370, -370, -300, -2, 735, 741, 145, 91, 391, - 21, -255, 92, 93, -219, 309, 93, -113, -294, 93, - 91, -351, -351, -294, -418, 247, 33, 33, 679, 635, - 627, -59, -219, -218, -294, -333, 734, 733, 93, 249, - 307, -144, 444, -141, 94, 95, -190, -190, -190, -190, - -190, -190, 239, 236, 414, -409, 320, -409, 292, 250, - -183, -190, 92, -84, 266, 261, -305, -305, 35, -190, - 424, 708, 706, -145, 150, 271, -162, -153, -119, -119, - -150, -315, 186, 352, 270, 350, 346, 366, 357, 384, - 348, 385, 343, 342, 341, -315, -313, -150, -210, -145, - -145, -145, 158, -145, 156, -145, -95, -94, -419, -419, - -419, -419, -419, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -230, -145, -145, -145, -419, 186, 352, - -95, -145, 17, -145, -313, -145, -145, -145, -145, -145, + -145, -145, -145, -420, -145, -145, -145, -145, -145, -253, + -420, -210, 96, -402, 432, 433, 705, -304, 288, -303, + 28, -211, 98, 18, -263, 86, -295, -235, -235, 69, + 70, 65, -131, -132, -136, -420, -37, 28, -255, -295, + 644, 644, 68, 98, -333, -272, 386, 387, 191, -145, + -145, 96, -234, 30, 31, -190, -298, 182, -302, -190, + -264, 288, -190, -168, -170, -171, -172, -193, -217, -419, + -173, -31, 615, 612, 18, -183, -184, -192, -301, -270, + -315, -269, 96, 431, 433, 434, 85, 134, -145, -334, + 190, -362, -361, -360, -343, -345, -346, -347, 97, -334, + -339, 393, 392, -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, 687, 643, + 595, 636, 677, 86, -365, -234, 105, -420, -143, -286, + 257, -371, -368, -295, -295, -295, -286, 100, 98, 100, + 98, 100, 98, -112, -60, -1, 744, 745, 746, 96, + 23, -344, -343, -59, 313, -376, -377, 288, -372, -366, + -352, 150, -351, -352, -352, -295, 96, 32, 139, 139, + 139, 139, 595, 241, 35, -287, 635, 156, 687, 643, + -343, -59, 255, 255, -314, -314, -314, 98, 98, -282, + 740, -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, -301, + -415, 337, -295, 373, 698, 700, -123, 432, 96, 595, + 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, 620, + -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, 704, 433, -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, 386, 387, -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, 435, 432, 438, -387, 98, -111, 96, -360, + -347, -238, -140, 46, -340, 394, -333, 603, -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, 743, + 749, 150, 95, 399, 22, -255, 96, 97, -219, 314, + 97, -113, -295, 97, 95, -352, -352, -295, -419, 252, + 34, 34, 687, 643, 635, -59, -219, -218, -295, -334, + 742, 741, 97, 254, 312, -144, 452, -141, 98, 100, + -190, -190, -190, -190, -190, -190, 244, 241, 422, -410, + 325, -410, 297, 255, -183, -190, 96, -84, 271, 266, + -306, -306, 36, -190, 432, 716, 714, -145, 155, 276, + -162, -153, -119, -119, -150, -316, 191, 359, 275, 357, + 353, 373, 364, 392, 355, 393, 350, 349, 348, -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, 359, -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, - -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, 662, 251, -94, -164, -98, - -164, 229, -145, 229, 229, 229, -145, -211, -296, -145, - -145, -145, -145, -145, -145, -145, -145, -145, -145, -194, - -347, 289, -347, 289, -347, -265, 92, -276, 25, 17, - 62, 62, -167, -198, -132, -168, -294, -244, 689, -250, - 51, -248, -249, 52, -245, 53, 61, -334, -334, 177, - -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, 177, 424, - 428, 429, -359, -407, 125, 151, 33, 81, 382, 105, - -405, 185, 624, 674, 679, 635, 628, 669, -406, 253, - 144, 145, 265, 27, 46, 93, 92, 93, 92, 93, - 93, 92, -288, -287, -45, -44, -353, -353, 100, -386, - 94, 94, 249, 28, -190, 81, 81, 81, -114, 739, - 100, 91, -3, 86, -145, 91, 22, -342, -218, -377, - -327, -378, -328, -329, -5, -6, -354, -117, 62, 105, - -63, 49, 248, 719, 720, 134, -418, 732, -369, -255, - -373, -375, -190, -149, -418, -161, -147, -146, -148, -154, - 175, 176, 270, 348, 349, -219, -190, -138, 298, 306, - 91, -142, 96, -388, 82, 289, 382, 289, 382, 94, - -411, 321, 94, -411, -190, -84, -49, -190, -283, -283, - 35, -386, -419, -162, -153, -126, 170, 587, -318, 594, - -330, -330, -330, -337, -330, 338, -330, 338, -330, -419, - -419, -419, 92, -419, 25, -419, 92, -145, 92, -95, - -95, -95, -95, -95, -122, 483, 92, 92, -419, 91, - 91, -419, -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, 680, -419, -419, - -419, -419, -419, -419, -419, -419, -419, -419, -419, -93, - -295, -94, 644, 644, -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, 358, -252, -251, 60, 52, -249, 22, - 54, 22, 32, -266, 92, 159, -307, 92, 27, -419, - -419, 92, 62, 230, -419, -198, -181, -180, 81, 82, - -182, 81, -180, 71, 71, -256, 92, -264, -168, -198, - -198, 230, 125, -418, -149, 15, 94, 94, -386, -404, - 723, 724, 33, 100, -353, -353, 145, 145, -190, 91, - -332, 94, -332, 100, 100, 33, 87, 88, 89, 33, - 83, 84, 85, -190, -190, -190, -190, -374, 91, 22, - -145, 91, 159, 93, -255, -255, 285, 170, -353, 717, - 291, 291, -353, -353, -353, -116, -115, 739, 93, -419, - 92, -340, 587, 590, -145, -155, -155, -256, 93, -382, - 587, -387, -294, -294, -294, -294, 100, 102, -419, 585, - 78, 588, -419, -332, -145, -145, -145, -145, -235, 94, - -145, -145, 100, 100, -95, -419, -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, 670, + 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, 697, -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, 432, 436, 437, -360, -408, 130, 156, + 34, 85, 390, 110, -406, 190, 632, 682, 687, 643, + 636, 677, -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, 747, 105, 95, -3, 90, -145, 95, + 23, -343, -218, -378, -328, -379, -329, -330, -5, -6, + -355, -117, 63, 110, -63, 50, 253, 727, 728, 139, + -419, 740, -370, -255, -374, -376, -190, -149, -419, -161, + -147, -146, -148, -154, 180, 181, 275, 355, 356, -219, + -190, -138, 303, 311, 95, -142, 101, -389, 86, 294, + 390, 294, 390, 98, -412, 326, 98, -412, -190, -84, + -49, -190, -283, -283, 36, -387, -420, -162, -153, -126, + 175, 595, -319, 602, -331, -331, -331, -338, -331, 345, + -331, 345, -331, -420, -420, -420, 96, -420, 26, -420, + 96, -145, 96, -95, -95, -95, -95, -95, -122, 491, + 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, 688, -420, -420, -420, -420, -420, -420, -420, -420, + -420, -420, -420, -93, -296, -94, 652, 652, -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, 365, -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, 731, 732, 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, 725, 296, 296, -354, -354, -354, -116, + -115, 747, 97, -420, 96, -341, 595, 598, -145, -155, + -155, -256, 97, -383, 595, -388, -295, -295, -295, -295, + 105, 107, -420, 593, 82, 596, -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, -210, -145, -419, -178, - -177, -179, 700, 125, 33, -315, -419, -212, 283, -101, - -100, -99, 17, -419, -145, -119, -119, -119, -119, -145, - -145, -145, -145, -145, -145, -418, 71, 21, 19, -258, - -294, 253, -418, -258, -418, -303, -228, -229, 20, 22, - -242, 58, -240, 57, -240, -251, 22, 22, 94, 22, - 94, 145, -275, -145, -215, -302, 62, -29, -294, -213, - -294, -230, -145, 91, -145, -158, -198, -198, -145, -205, - 507, 509, 510, 511, 508, 513, 514, 515, 516, 517, - 518, 519, 520, 521, 522, 512, 523, 484, 485, 486, - 112, 114, 113, 122, 123, 487, 488, 489, 352, 535, - 536, 530, 533, 534, 532, 531, 367, 368, 490, 553, - 554, 558, 557, 555, 556, 559, 562, 563, 564, 565, - 566, 567, 569, 568, 560, 561, 538, 537, 539, 540, - 541, 542, 543, 544, 546, 545, 547, 548, 549, 550, - 551, 552, 570, 571, 572, 573, 574, 576, 575, 580, - 579, 577, 578, 582, 581, 491, 492, 115, 116, 117, - 118, 119, 120, 121, 493, 496, 494, 497, 498, 499, - 504, 505, 500, 501, 502, 503, 506, 378, 376, 377, - 373, 372, 371, 431, 436, 437, 439, 524, 525, 526, - 527, 528, 529, 681, 682, 683, 684, 685, 686, 687, - 688, 94, 94, 91, -145, 93, 93, -256, -373, -60, - 93, -257, -255, 100, 93, 286, -214, -418, 94, -353, - -353, -353, 100, 100, -302, -419, 92, -294, -406, -375, - 591, 591, -419, 27, -381, -380, -296, 91, 82, 67, - 586, 589, -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, 308, 310, -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, 618, -145, -210, -243, 59, 81, 129, - 94, 94, 94, 15, -418, -213, 230, -307, -235, -255, - -175, 391, -230, -419, -255, 93, 27, 93, 741, 145, - 93, -214, -125, -418, 282, -302, 94, 94, -115, -118, - -29, 92, 159, -255, -190, 67, -145, -210, -419, 81, - 599, 700, -92, -91, -88, 711, 737, -210, -94, -94, - -145, -145, -145, -419, -294, 253, -419, -419, -108, 92, - -105, -104, -294, -319, 587, 81, 129, -267, -255, -307, - -294, 93, -419, -418, -235, 93, -239, -29, 91, -3, - 282, -327, -378, -328, -329, -5, -6, -354, -82, 587, - -380, -358, -300, -296, 94, 100, 93, 587, -419, -419, - -90, 153, 709, 677, -155, 229, -419, 92, -419, 92, - -419, 92, -106, 92, 27, 592, -419, -303, -176, -174, - -294, 641, -397, -396, 583, -407, -403, 125, 151, 105, - -405, 679, 635, 135, 136, -82, -145, 91, -419, -83, - 297, 696, 230, -388, 588, -90, 710, 655, 630, 655, - 630, -150, -145, -145, -145, -104, -418, -419, 92, 25, - -320, -62, 652, -394, -395, 81, -398, 397, 651, 672, - 125, 94, 93, -255, 258, -301, -382, 589, 150, -119, - -419, 92, -419, 92, -419, -93, -174, 648, -333, -158, - -395, 81, -394, 81, 16, 15, -4, 740, 93, 299, - -90, 655, 630, -145, -145, -419, -61, 28, -175, -393, - 266, 261, 264, 34, -393, 100, -4, -419, -419, 652, - 260, 33, 125, -158, -178, -177, -177, + -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, + -210, -145, -420, -178, -177, -179, 708, 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, 515, 517, 518, 519, 516, 521, + 522, 523, 524, 525, 526, 527, 528, 529, 530, 520, + 531, 492, 493, 494, 117, 119, 118, 127, 128, 495, + 496, 497, 359, 543, 544, 538, 541, 542, 540, 539, + 374, 375, 498, 561, 562, 566, 565, 563, 564, 567, + 570, 571, 572, 573, 574, 575, 577, 576, 568, 569, + 546, 545, 547, 548, 549, 550, 551, 552, 554, 553, + 555, 556, 557, 558, 559, 560, 578, 579, 580, 581, + 582, 584, 583, 588, 587, 585, 586, 590, 589, 499, + 500, 120, 121, 122, 123, 124, 125, 126, 501, 504, + 502, 505, 506, 507, 512, 513, 508, 509, 510, 511, + 514, 385, 383, 384, 380, 379, 378, 439, 444, 445, + 447, 532, 533, 534, 535, 536, 537, 689, 690, 691, + 692, 693, 694, 695, 696, 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, 599, 599, -420, 28, -382, -381, + -297, 95, 86, 68, 594, 597, -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, 626, -145, -210, + -243, 60, 85, 134, 98, 98, 98, 16, -419, -213, + 235, -308, -235, -255, -175, 399, -230, -420, -255, 97, + 28, 97, 749, 150, 97, -214, -125, -419, 287, -303, + 98, 98, -115, -118, -29, 96, 164, -255, -190, 68, + -145, -210, -420, 85, 607, 708, -92, -91, -88, 719, + 745, -210, -94, -94, -145, -145, -145, -420, -295, 258, + -420, -420, -108, 96, -105, -104, -295, -320, 595, 85, + 134, -267, -255, -308, -295, 97, -420, -419, -235, 97, + -239, -29, 95, -3, 287, -328, -379, -329, -330, -5, + -6, -355, -82, 595, -381, -359, -301, -297, 98, 105, + 97, 595, -420, -420, -90, 158, 717, 685, -155, 234, + -420, 96, -420, 96, -420, 96, -106, 96, 28, 600, + -420, -304, -176, -174, -295, 649, -398, -397, 591, -408, + -404, 130, 156, 110, -406, 687, 643, 140, 141, -82, + -145, 95, -420, -83, 302, 704, 235, -389, 596, -90, + 718, 663, 638, 663, 638, -150, -145, -145, -145, -104, + -419, -420, 96, 26, -321, -62, 660, -395, -396, 85, + -399, 405, 659, 680, 130, 98, 97, -255, 263, -302, + -383, 597, 155, -119, -420, 96, -420, 96, -420, -93, + -174, 656, -334, -158, -396, 85, -395, 85, 17, 16, + -4, 748, 97, 304, -90, 663, 638, -145, -145, -420, + -61, 29, -175, -394, 271, 266, 269, 35, -394, 105, + -4, -420, -420, 660, 265, 34, 130, -158, -178, -177, + -177, } var yyDef = [...]int{ - 880, -2, -2, 882, 2, 4, 5, 6, 7, 8, + 887, -2, -2, 889, 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, 1631, 0, 880, 0, 875, - 0, -2, 797, 803, 0, 812, -2, 0, 0, 880, - 880, 2263, 2263, 875, 0, 0, 0, 0, 0, 880, - 880, 880, 880, 1636, 1489, 50, 880, 0, 85, 86, - 830, 831, 832, 65, 0, 2261, 881, 1, 3, 71, - 75, 0, 0, 0, 58, 1498, 0, 78, 0, 0, - 884, 0, 0, 1614, 880, 880, 0, 126, 127, 0, + 39, 70, 72, 73, 887, 887, 887, 0, 887, 0, + 0, 887, -2, -2, 887, 1642, 0, 887, 0, 882, + 0, -2, 804, 810, 0, 819, -2, 0, 0, 887, + 887, 2281, 2281, 882, 0, 0, 0, 0, 0, 887, + 887, 887, 887, 1647, 1500, 50, 887, 0, 85, 86, + 837, 838, 839, 65, 0, 2279, 888, 1, 3, 71, + 75, 0, 0, 0, 58, 1509, 0, 78, 0, 0, + 891, 0, 0, 1625, 887, 887, 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, 1616, 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, 1516, 165, 1632, 1629, 1630, 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, 2257, 2258, 2259, 2260, 0, 1608, - 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, 2264, 0, 2264, - 2264, 1599, 0, 780, 778, 792, 793, 42, 796, 799, - 800, 801, 802, 805, 0, 816, 819, 1625, 1626, 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, 1991, 1460, 0, - 0, 1422, 1422, 1156, 1422, 1422, 1424, 1424, 1424, 1842, - 1983, 1992, 2170, 1803, 1809, 1810, 1811, 2116, 2117, 2118, - 2119, 2208, 2209, 2213, 1905, 1798, 2183, 2184, 0, 2260, - 1944, 1952, 1953, 1929, 1938, 1977, 2079, 2193, 1821, 1972, - 2042, 1902, 1924, 1925, 2060, 2061, 1948, 1949, 1928, 2122, - 2124, 2140, 2141, 2126, 2128, 2137, 2143, 2148, 2127, 2139, - 2144, 2157, 2161, 2164, 2165, 2166, 2134, 2132, 2145, 2149, - 2151, 2153, 2159, 2162, 2135, 2133, 2146, 2150, 2152, 2154, - 2160, 2163, 2121, 2125, 2129, 2138, 2156, 2136, 2155, 2130, - 2142, 2147, 2158, 2131, 2123, 1942, 1945, 1932, 1933, 1935, - 1937, 1943, 1950, 1956, 1934, 1955, 1954, 0, 1930, 1931, - 1936, 1947, 1951, 1939, 1940, 1941, 1946, 1957, 1998, 1997, - 1996, 2041, 1968, 2040, 0, 0, 0, 0, 0, 1792, - 1847, 1848, 2167, 1344, 1345, 1346, 1347, 0, 0, 0, - 0, 0, 0, 0, 291, 292, 1473, 1474, 44, 1139, - 1595, 1424, 1424, 1424, 1424, 1424, 1424, 1078, 1079, 1080, - 1081, 1082, 1108, 1109, 1115, 1116, 2055, 2056, 2057, 2058, - 1885, 2203, 1894, 1895, 2037, 2038, 1907, 1908, 2234, 2235, - -2, -2, -2, 232, 233, 234, 235, 236, 237, 238, - 239, 0, 1846, 2181, 2182, 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, 2263, 0, - 853, 0, 0, 0, 0, 0, 0, 1637, 1638, 1498, - 0, 1490, 1489, 63, 0, 880, -2, 0, 0, 0, - 0, 47, 0, 52, 937, 883, 77, 76, 1538, 1541, - 0, 0, 0, 59, 1499, 67, 69, 1500, 0, 885, - 886, 0, 913, 917, 0, 0, 0, 1615, 1614, 1614, - 102, 0, 0, 103, 123, 124, 125, 0, 0, 109, - 110, 1601, 1602, 43, 0, 0, 177, 178, 0, 1096, - 428, 0, 173, 0, 421, 360, 0, 1516, 0, 0, - 0, 0, 0, 880, 0, 1609, 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, - 1617, 1618, 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, 1529, 0, 0, 0, -2, - 0, 712, 0, 0, 0, 1610, 1610, 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, 2264, 789, 786, 0, 758, 0, 759, 760, 761, - 762, 765, 766, 768, 2265, 2266, 1627, 1628, 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, 1787, 1788, 2264, 2264, - 772, 776, 1600, 798, 804, 806, 807, 0, 0, 817, - 820, 837, 49, 1893, 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, 1469, -2, 0, 0, 0, 1063, 1064, 0, - 0, 0, 1620, 1620, 0, 0, 0, 1461, 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, 0, 0, 1620, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 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, 1620, 0, 0, 1620, 1620, 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, - 1620, 0, 0, 896, 0, 1635, 57, 66, 68, 1498, - 61, 1498, 0, 900, 0, 0, -2, -2, 901, 902, - 906, 907, 908, 909, 910, 54, 2262, 55, 0, 74, - 0, 48, 0, 0, 1539, 0, 1542, 0, 0, 0, - 374, 1546, 0, 0, 1491, 1492, 1495, 0, 914, 1989, - 918, 0, 920, 921, 0, 0, 100, 0, 979, 0, - 0, 0, 111, 0, 113, 114, 0, 0, 0, 385, - 1603, 1604, 1605, -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, 1495, 0, 0, 1529, 1612, 1622, 0, 0, - 0, 1612, 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, - 1520, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1610, 0, 0, - 0, 0, 899, 981, 1633, 1634, 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, 1437, 1438, - 1439, 1067, 301, 302, 0, 1068, 0, 0, 0, 0, - 0, 0, 0, 0, 1384, 1385, 1386, 1387, 1388, 1389, - 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, - 1400, 1401, 1402, 1403, 1140, 0, 1621, 0, 0, 0, - 1467, 1464, 0, 0, 0, 1423, 1425, 0, 0, 0, - 891, 892, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1404, - 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, - 1415, 1416, 1417, 1418, 1419, 1420, 1421, 0, 0, 1440, - 0, 0, 0, 0, 0, 0, 0, 1460, 0, 1073, - 1074, 1075, 0, 0, 0, 0, 0, 0, 1202, 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, 1627, 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, 1527, 165, 1643, 1640, 1641, 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, 2275, 2276, + 2277, 2278, 0, 1619, 0, 722, 991, 0, 883, 884, + 0, 793, 793, 0, 793, 793, 793, 793, 0, 0, + 0, 736, 0, 0, 0, 0, 790, 0, 752, 753, + 0, 790, 0, 759, 796, 0, 0, 766, 793, 793, + 769, 2282, 0, 2282, 2282, 0, 0, 1610, 0, 787, + 785, 799, 800, 42, 803, 806, 807, 808, 809, 812, + 0, 823, 826, 1636, 1637, 0, 828, 833, 850, 851, + 0, 45, 1151, 0, 1015, 0, 1026, -2, 1037, 1054, + 1055, 1056, 1057, 1058, 1060, 1061, 1062, 0, 0, 0, + 0, 1067, 1068, 0, 0, 0, 0, 0, 1131, 0, + 0, 0, 0, 2005, 1471, 0, 0, 1433, 1433, 1167, + 1433, 1433, 1435, 1435, 1435, 1856, 1997, 2006, 2185, 1817, + 1823, 1824, 1825, 2131, 2132, 2133, 2134, 2225, 2226, 2230, + 1919, 1812, 2198, 2199, 0, 2278, 1958, 1966, 1967, 1943, + 1952, 1991, 2093, 2209, 1835, 1986, 2056, 1916, 1938, 1939, + 2074, 2075, 1962, 1963, 1942, 2137, 2139, 2155, 2156, 2141, + 2143, 2152, 2158, 2163, 2142, 2154, 2159, 2172, 2176, 2179, + 2180, 2181, 2149, 2147, 2160, 2164, 2166, 2168, 2174, 2177, + 2150, 2148, 2161, 2165, 2167, 2169, 2175, 2178, 2136, 2140, + 2144, 2153, 2171, 2151, 2170, 2145, 2157, 2162, 2173, 2146, + 2138, 1956, 1959, 1946, 1947, 1949, 1951, 1957, 1964, 1970, + 1948, 1969, 1968, 0, 1944, 1945, 1950, 1961, 1965, 1953, + 1954, 1955, 1960, 1971, 2012, 2011, 2010, 2055, 1982, 2054, + 0, 0, 0, 0, 0, 1806, 1861, 1862, 2182, 1355, + 1356, 1357, 1358, 0, 0, 0, 0, 0, 0, 0, + 291, 292, 1484, 1485, 44, 1150, 1606, 1435, 1435, 1435, + 1435, 1435, 1435, 1089, 1090, 1091, 1092, 1093, 1119, 1120, + 1126, 1127, 2069, 2070, 2071, 2072, 1899, 2220, 1908, 1909, + 2051, 2052, 1921, 1922, 2252, 2253, -2, -2, -2, 232, + 233, 234, 235, 236, 237, 238, 239, 0, 1860, 2196, + 2197, 228, 0, 0, 296, 293, 294, 295, 1133, 1134, + 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, 2281, 0, 860, 0, 0, 0, + 0, 0, 0, 1648, 1649, 1509, 0, 1501, 1500, 63, + 0, 887, -2, 0, 0, 0, 0, 47, 0, 52, + 948, 890, 77, 76, 1549, 1552, 0, 0, 0, 59, + 1510, 67, 69, 1511, 0, 892, 893, 0, 924, 928, + 0, 0, 0, 1626, 1625, 1625, 102, 0, 0, 103, + 123, 124, 125, 0, 0, 109, 110, 1612, 1613, 43, + 0, 0, 177, 178, 0, 1107, 429, 0, 173, 0, + 422, 361, 0, 1527, 0, 0, 0, 0, 0, 887, + 0, 1620, 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, 1628, 1629, 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, 1540, 0, 0, 0, -2, 0, 714, 0, 0, + 0, 1621, 1621, 0, 721, 0, 0, 0, 726, 0, + 0, 727, 0, 790, 790, 788, 789, 729, 730, 731, + 732, 793, 0, 0, 411, 412, 413, 790, 793, 0, + 793, 793, 793, 793, 790, 790, 790, 793, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2282, 796, 793, + 0, 760, 0, 761, 762, 763, 764, 767, 768, 770, + 2283, 2284, 1638, 1639, 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, 1801, 1802, 2282, 2282, 774, + 778, 782, 780, 1611, 805, 811, 813, 814, 0, 0, + 824, 827, 844, 49, 1907, 832, 49, 834, 835, 836, + 862, 863, 868, 0, 0, 0, 0, 874, 875, 876, + 0, 0, 879, 880, 881, 0, 0, 0, 0, 0, + 1013, 0, 0, 1139, 1140, 1141, 1142, 1143, 1144, 1145, + 1146, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1038, + 1039, 0, 0, 0, 1063, 1064, 1065, 1066, 1069, 0, + 1080, 0, 1082, 1480, -2, 0, 0, 0, 1074, 1075, + 0, 0, 0, 1631, 1631, 0, 0, 0, 1472, 0, + 0, 1165, 0, 1166, 1168, 1169, 1170, 0, 1171, 1172, + 897, 897, 897, 897, 897, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 897, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 1631, 0, 0, 1631, 1631, 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, 1150, 0, 0, 0, 46, 852, 853, 0, + 974, 1631, 0, 0, 903, 0, 1646, 57, 66, 68, + 1509, 61, 1509, 0, 907, 0, 0, -2, -2, 908, + 909, 913, 914, 915, 916, 917, 918, 919, 920, 921, + 54, 2280, 55, 0, 74, 0, 48, 0, 0, 1550, + 0, 1553, 0, 0, 0, 375, 1557, 0, 0, 1502, + 1503, 1506, 0, 925, 2003, 929, 0, 931, 932, 0, + 0, 100, 0, 990, 0, 0, 0, 111, 0, 113, + 114, 0, 0, 0, 386, 1614, 1615, 1616, -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, 1108, 0, 390, 0, 1506, 0, + 0, 1540, 1623, 1633, 0, 0, 0, 1623, 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, 960, 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, 977, 978, 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, 1531, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1621, 0, 0, 0, 0, 906, + 992, 1644, 1645, 723, 0, 0, 794, 795, 0, 414, + 415, 793, 793, 733, 775, 0, 793, 737, 776, 738, + 740, 739, 741, 754, 755, 793, 744, 791, 792, 745, + 746, 747, 748, 749, 750, 751, 771, 756, 757, 758, + 797, 0, 801, 802, 772, 773, 0, 783, 0, 0, + 0, 817, 818, 0, 825, 847, 845, 846, 848, 840, + 841, 842, 843, 0, 849, 0, 0, 865, 96, 870, + 871, 872, 873, 885, 878, 1152, 1010, 1011, 1012, 0, + 1014, 1020, 0, 1135, 1137, 1018, 1019, 1022, 0, 0, + 0, 1016, 1027, 1147, 1148, 1149, 0, 0, 0, 0, + 0, 1031, 1035, 1040, 1041, 1042, 1043, 1044, 0, 1045, + 0, 1048, 1049, 1050, 1051, 1052, 1053, 1059, 1448, 1449, + 1450, 1078, 301, 302, 0, 1079, 0, 0, 0, 0, + 0, 0, 0, 0, 1395, 1396, 1397, 1398, 1399, 1400, + 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, + 1411, 1412, 1413, 1414, 1151, 0, 1632, 0, 0, 0, + 1478, 1475, 0, 0, 0, 1434, 1436, 0, 0, 0, + 898, 899, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1415, + 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, + 1426, 1427, 1428, 1429, 1430, 1431, 1432, 0, 0, 1451, + 0, 0, 0, 0, 0, 0, 0, 1471, 0, 1084, + 1085, 1086, 0, 0, 0, 0, 0, 0, 1213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -9625,214 +9771,215 @@ var yyDef = [...]int{ 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, 1348, 1349, 1350, 1351, 41, 0, - 0, 0, 0, 0, 0, 0, 1471, 0, -2, -2, + 0, 0, 0, 0, 1359, 1360, 1361, 1362, 41, 0, + 0, 0, 0, 0, 0, 0, 1482, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1373, 0, 0, 0, 0, 0, 0, - 1593, 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, - 1540, 1543, 1544, 374, 1566, 0, 383, 383, 380, 1501, - 1502, 0, 1494, 1496, 1497, 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, 0, 0, 1384, 0, 0, 0, 0, 0, 0, + 1604, 0, 0, 855, 856, 858, 0, 994, 0, 975, + 0, 0, 861, 0, 902, 0, 905, 60, 62, 911, + 912, 0, 933, 922, 910, 56, 51, 0, 0, 952, + 1551, 1554, 1555, 375, 1577, 0, 384, 384, 381, 1512, + 1513, 0, 1505, 1507, 1508, 79, 930, 926, 0, 1008, + 0, 0, 989, 0, 936, 938, 939, 940, 972, 0, + 943, 944, 0, 0, 0, 0, 0, 98, 991, 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, 1503, 390, 391, 393, 401, 0, 396, 397, 0, - 401, 401, 0, 422, 423, 0, 1495, 1520, 0, 0, - 0, 1623, 1622, 1622, 1622, 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, 1517, 1518, 1519, 0, 0, - 713, 0, 0, 451, 94, 1611, 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, 1471, 0, 0, - 0, 1121, 0, 0, 1144, 1145, 0, 0, 0, 0, - 1465, 0, 0, 1152, 0, 1426, 1102, 0, 0, 0, - 0, 0, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, - 1102, 1102, 1489, 1179, 0, 0, 0, 0, 0, 1184, - 1185, 1186, 1102, 0, 1189, 1190, 0, 1192, 0, 1193, - 0, 0, 0, 0, 1200, 1201, 1203, 0, 0, 1206, - 1207, 0, 1209, 0, 1211, 1212, 1213, 1214, 1215, 1216, - 0, 1218, 0, 1220, 1221, 1222, 0, 1224, 0, 1226, - 1227, 0, 1229, 0, 1231, 0, 1234, 0, 1237, 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, 1280, 1281, 0, - 1283, 0, 1285, 0, 1288, 1289, 0, 1291, 0, 1294, - 0, 1297, 0, 0, 1298, 0, 0, 0, 1302, 0, - 0, 0, 0, 1311, 1312, 1313, 1314, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1325, 1326, 1327, - 1328, 1329, 1330, 0, 1332, 0, 1103, 0, 0, 1103, - 0, 0, 0, 0, 0, 1142, 1620, 0, 1427, 1428, - 1429, 1430, 1431, 0, 0, 0, 0, 0, 0, 1371, - 1372, 1374, 0, 0, 1377, 0, 1379, 0, 1594, 847, - 850, 852, 935, 984, 985, 0, 0, 0, 0, 965, - 1619, 893, 894, 897, 943, 0, 1475, 0, 0, 922, - 997, 0, 923, 0, 53, 938, 0, 1548, 1547, 1560, - 1573, 383, 383, 377, 378, 384, 379, 381, 382, 1493, - 0, 1498, 0, 1587, 0, 0, 1576, 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, 1507, 1506, 401, 401, 392, 0, 395, - 0, 0, 0, 1624, 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, 1530, 1531, 1536, 1534, 1535, 133, 583, 585, 589, - 584, 588, 0, 0, 0, 520, 0, 520, 581, 0, - 451, 1503, 0, 717, 452, 453, 786, 786, 857, 97, - 0, 860, 0, 0, 0, 0, 1018, 1022, 1035, 1036, - 1432, 1458, 360, 360, 1445, 360, 366, 1448, 360, 1450, - 360, 1453, 360, 1456, 1457, 0, 0, 1065, 0, 0, - 0, 0, 1151, 1468, 0, 0, 1162, 1101, 1102, 1102, - 1102, 1102, 1102, 1168, 1169, 1170, 1171, 1172, 1173, 1174, - 1175, 1176, 1177, 1462, 0, 0, 0, 1183, 0, 0, - 1187, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 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, 1382, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1096, 1100, 0, 1104, 1105, 0, 0, 1334, 0, 0, - 1352, 0, 0, 0, 0, 0, 0, 0, 1472, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 986, - 993, 0, 993, 0, 993, 0, 0, 0, 1606, 1607, - 1476, 1477, 997, 1478, 912, 924, 942, 1566, 0, 1559, - 0, -2, 1568, 0, 0, 0, 1574, 375, 376, 916, - 80, 998, 83, 0, 1587, 1596, 0, 1584, 1589, 1591, - 0, 0, 0, 1580, 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, 1504, 1505, 0, 0, 394, 398, - 399, 400, 0, 1613, 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, 1521, 1522, 1523, - 0, 1533, 1537, 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, 1459, - 1443, 374, 1446, 1447, 1449, 1451, 1452, 1454, 1455, 1061, - 1062, 1066, 0, 1148, 0, 1150, 0, 1466, 0, 1163, - 1164, 1165, 1166, 1167, 1498, 0, 0, 0, 1182, 0, - 0, 1102, 0, 1195, 1194, 1196, 0, 1198, 1199, 1204, - 1205, 1208, 1210, 1217, 1219, 1223, 1225, 1228, 1230, 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, - 0, 1282, 1284, 0, 1287, 1290, 1292, 0, 1295, 0, - 1299, 0, 1301, 1303, 1304, 0, 0, 0, 1315, 1316, - 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1331, 0, - 1094, 1333, 1106, 1107, 1112, 1336, 0, 0, 0, 1339, - 0, 0, 0, 1343, 1143, 1354, 0, 1359, 0, 0, - 1365, 0, 1369, 0, 1375, 1376, 1378, 1380, 0, 0, - 0, 0, 0, 0, 0, 963, 944, 64, 1478, 1482, - 0, 1553, 1551, 1551, 1561, 1562, 0, 0, 1569, 0, - 0, 0, 0, 84, 0, 0, 1575, 0, 0, 1592, - 0, 0, 0, 0, 101, 1489, 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, 1508, 1509, 1510, 1511, 1512, - 1513, 1514, 1515, 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, 1532, 582, - 0, 134, 135, 0, 0, 587, 521, 522, 1059, 0, - 0, 0, 1060, 1444, 0, 0, 0, 0, 0, 1463, - 0, 0, 0, 0, 1188, 1191, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1307, 0, - 0, 0, 638, 639, 0, 1383, 1099, 1489, 0, 1103, - 1113, 1114, 0, 1103, 1353, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 994, 0, 0, 0, - 945, 946, 0, 0, 0, 983, 1482, 1487, 0, 0, - 1556, 0, 1549, 1552, 1550, 1563, 0, 0, 1570, 0, - 1572, 0, 1597, 1598, 1590, 1585, 0, 1579, 1582, 1584, - 1581, 1498, 955, 0, 960, 0, 1489, 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, 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, 1433, - 0, 1436, 1146, 1149, 1147, 0, 1178, 1180, 1181, 1441, - 1442, 1197, 1233, 1236, 1239, 1242, 1245, 1248, 1251, 1254, - 1257, 1260, 1263, 1266, 1269, 1272, 1275, 1278, 1286, 1293, - 1296, 1300, 1305, 0, 1308, 0, 0, 1309, 0, 640, - 1090, 0, 0, 1110, 1111, 0, 1338, 1340, 1341, 1342, - 1355, 0, 1360, 1361, 0, 1366, 0, 1370, 1381, 0, - 988, 995, 996, 0, 991, 0, 992, 0, 936, 1487, - 82, 1488, 1485, 0, 1483, 1480, 1545, 0, 1554, 1555, - 1564, 1565, 1571, 0, 0, 1584, 0, 1578, 87, 0, - 0, 0, 1498, 191, 0, 210, 0, 617, 0, 620, - 610, 697, 698, 0, 710, 702, 704, 705, 687, -2, - 1524, 0, 0, 0, 590, 1434, 0, 0, 1310, 0, - 636, 637, 1098, 1091, 0, 1076, 1077, 1095, 1335, 1337, - 0, 0, 0, 987, 947, 948, 989, 990, 81, 0, - 1484, 1118, 0, 1479, 0, 1557, 1558, 1588, 0, 1577, - 1583, 956, 963, 0, 88, 442, 435, 1524, 0, 0, - 0, 690, 691, 692, 693, 694, 695, 696, 579, 1526, - 139, 140, 0, 509, 510, 511, 133, 0, 1153, 1306, - 1092, 0, 0, 0, 0, 0, 1356, 0, 1362, 0, - 1367, 0, 1486, 0, 0, 1481, 1586, 622, 0, 624, - 0, -2, 430, 443, 0, 185, 211, 212, 0, 0, - 215, 216, 217, 208, 209, 129, 0, 0, 711, 0, - 1527, 1528, 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, 1435, 0, 0, - 1357, 0, 1363, 0, 1368, 0, 625, 626, 634, 0, - 433, 0, 434, 0, 0, 0, 614, 0, 645, 1525, - 1093, 1087, 1089, 0, 0, 1117, 0, 635, 631, 444, - 446, 447, 0, 0, 445, 646, 615, 1358, 1364, 0, - 448, 449, 450, 627, 628, 629, 630, + 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, 1514, 391, 392, 394, 402, 0, 397, 398, + 0, 402, 402, 0, 423, 424, 0, 1506, 1531, 0, + 0, 0, 1634, 1633, 1633, 1633, 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, 1528, 1529, 1530, + 0, 0, 715, 0, 0, 452, 94, 1622, 720, 724, + 725, 790, 743, 777, 790, 735, 742, 765, 779, 781, + 815, 816, 821, 829, 830, 831, 869, 0, 0, 0, + 0, 877, 0, 0, 1021, 1136, 1138, 1023, 1024, 1025, + 1028, 0, 1032, 1036, 0, 0, 0, 0, 0, 1083, + 1081, 1482, 0, 0, 0, 1132, 0, 0, 1155, 1156, + 0, 0, 0, 0, 1476, 0, 0, 1163, 0, 1437, + 1113, 0, 0, 0, 0, 0, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, 1113, 1500, 1190, 0, 0, + 0, 0, 0, 1195, 1196, 1197, 1113, 0, 1200, 1201, + 0, 1203, 0, 1204, 0, 0, 0, 0, 1211, 1212, + 1214, 0, 0, 1217, 1218, 0, 1220, 0, 1222, 1223, + 1224, 1225, 1226, 1227, 0, 1229, 0, 1231, 1232, 1233, + 0, 1235, 0, 1237, 1238, 0, 1240, 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, 1278, 0, 1281, 0, 1284, 0, 1287, 0, + 1290, 1291, 1292, 0, 1294, 0, 1296, 0, 1299, 1300, + 0, 1302, 0, 1305, 0, 1308, 0, 0, 1309, 0, + 0, 0, 1313, 0, 0, 0, 0, 1322, 1323, 1324, + 1325, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1336, 1337, 1338, 1339, 1340, 1341, 0, 1343, 0, + 1114, 0, 0, 1114, 0, 0, 0, 0, 0, 1153, + 1631, 0, 1438, 1439, 1440, 1441, 1442, 0, 0, 0, + 0, 0, 0, 1382, 1383, 1385, 0, 0, 1388, 0, + 1390, 0, 1605, 854, 857, 859, 946, 995, 996, 0, + 0, 0, 0, 976, 1630, 900, 901, 904, 954, 0, + 1486, 0, 0, 933, 1008, 0, 934, 0, 53, 949, + 0, 1559, 1558, 1571, 1584, 384, 384, 378, 379, 385, + 380, 382, 383, 1504, 0, 1509, 0, 1598, 0, 0, + 1587, 0, 0, 0, 0, 0, 0, 0, 0, 979, + 0, 0, 982, 0, 0, 0, 0, 973, 944, 0, + 945, 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, 1518, 1517, 402, + 402, 393, 0, 396, 0, 0, 0, 1635, 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, 961, 0, 0, + 539, 0, 542, 543, 456, 517, 548, 549, 563, 550, + 498, 499, 496, 0, 0, 1541, 1542, 1547, 1545, 1546, + 133, 584, 586, 590, 585, 589, 0, 0, 0, 521, + 0, 521, 582, 0, 452, 1514, 0, 719, 453, 454, + 793, 793, 864, 97, 0, 867, 0, 0, 0, 0, + 1029, 1033, 1046, 1047, 1443, 1469, 361, 361, 1456, 361, + 367, 1459, 361, 1461, 361, 1464, 361, 1467, 1468, 0, + 0, 1076, 0, 0, 0, 0, 1162, 1479, 0, 0, + 1173, 1112, 1113, 1113, 1113, 1113, 1113, 1179, 1180, 1181, + 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1473, 0, 0, + 0, 1194, 0, 0, 1198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1393, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1107, 1111, 0, 1115, 1116, 0, + 0, 1345, 0, 0, 1363, 0, 0, 0, 0, 0, + 0, 0, 1483, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 997, 1004, 0, 1004, 0, 1004, 0, + 0, 0, 1617, 1618, 1487, 1488, 1008, 1489, 923, 935, + 953, 1577, 0, 1570, 0, -2, 1579, 0, 0, 0, + 1585, 376, 377, 927, 80, 1009, 83, 0, 1598, 1607, + 0, 1595, 1600, 1602, 0, 0, 0, 1591, 0, 1008, + 937, 968, 970, 0, 965, 980, 981, 983, 0, 985, + 0, 987, 988, 948, 942, 0, 100, 0, 1008, 1008, + 99, 0, 993, 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, 1515, 1516, + 0, 0, 395, 399, 400, 401, 0, 1624, 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, + 948, 1532, 1533, 1534, 0, 1544, 1548, 136, 0, 0, + 0, 0, 592, 597, 603, 0, 520, 604, 716, 717, + 718, 95, 728, 734, 866, 886, 1017, 1030, 1034, 0, + 0, 0, 0, 1470, 1454, 375, 1457, 1458, 1460, 1462, + 1463, 1465, 1466, 1072, 1073, 1077, 0, 1159, 0, 1161, + 0, 1477, 0, 1174, 1175, 1176, 1177, 1178, 1509, 0, + 0, 0, 1193, 0, 0, 1113, 0, 1206, 1205, 1207, + 0, 1209, 1210, 1215, 1216, 1219, 1221, 1228, 1230, 1234, + 1236, 1239, 1241, 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, 0, 1293, 1295, 0, 1298, 1301, + 1303, 0, 1306, 0, 1310, 0, 1312, 1314, 1315, 0, + 0, 0, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, + 1334, 1335, 1342, 0, 1105, 1344, 1117, 1118, 1123, 1347, + 0, 0, 0, 1350, 0, 0, 0, 1354, 1154, 1365, + 0, 1370, 0, 0, 1376, 0, 1380, 0, 1386, 1387, + 1389, 1391, 0, 0, 0, 0, 0, 0, 0, 974, + 955, 64, 1489, 1493, 0, 1564, 1562, 1562, 1572, 1573, + 0, 0, 1580, 0, 0, 0, 0, 84, 0, 0, + 1586, 0, 0, 1603, 0, 0, 0, 0, 101, 1500, + 962, 969, 0, 0, 963, 0, 964, 984, 986, 941, + 0, 1008, 1008, 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, 1519, + 1520, 1521, 1522, 1523, 1524, 1525, 1526, 948, 149, 150, + 151, 610, 0, 620, 0, 950, 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, 1543, 583, 0, 134, 135, 0, 0, 588, + 522, 523, 1070, 0, 0, 0, 1071, 1455, 0, 0, + 0, 0, 0, 1474, 0, 0, 0, 0, 1199, 1202, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1318, 0, 0, 0, 640, 641, 0, 1394, + 1110, 1500, 0, 1114, 1124, 1125, 0, 1114, 1364, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1005, 0, 0, 0, 956, 957, 0, 0, 0, 994, + 1493, 1498, 0, 0, 1567, 0, 1560, 1563, 1561, 1574, + 0, 0, 1581, 0, 1583, 0, 1608, 1609, 1601, 1596, + 0, 1590, 1593, 1595, 1592, 1509, 966, 0, 971, 0, + 1500, 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, 951, 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, 1444, 0, 1447, 1157, 1160, 1158, 0, + 1189, 1191, 1192, 1452, 1453, 1208, 1244, 1247, 1250, 1253, + 1256, 1259, 1262, 1265, 1268, 1271, 1274, 1277, 1280, 1283, + 1286, 1289, 1297, 1304, 1307, 1311, 1316, 0, 1319, 0, + 0, 1320, 0, 642, 1101, 0, 0, 1121, 1122, 0, + 1349, 1351, 1352, 1353, 1366, 0, 1371, 1372, 0, 1377, + 0, 1381, 1392, 0, 999, 1006, 1007, 0, 1002, 0, + 1003, 0, 947, 1498, 82, 1499, 1496, 0, 1494, 1491, + 1556, 0, 1565, 1566, 1575, 1576, 1582, 0, 0, 1595, + 0, 1589, 87, 0, 0, 0, 1509, 191, 0, 210, + 0, 619, 0, 622, 612, 699, 700, 0, 712, 704, + 706, 707, 689, -2, 1535, 0, 0, 0, 591, 1445, + 0, 0, 1321, 0, 638, 639, 1109, 1102, 0, 1087, + 1088, 1106, 1346, 1348, 0, 0, 0, 998, 958, 959, + 1000, 1001, 81, 0, 1495, 1129, 0, 1490, 0, 1568, + 1569, 1599, 0, 1588, 1594, 967, 974, 0, 88, 443, + 436, 1535, 0, 0, 0, 692, 693, 694, 695, 696, + 697, 698, 580, 1537, 139, 140, 0, 510, 511, 512, + 133, 0, 1164, 1317, 1103, 0, 0, 0, 0, 0, + 1367, 0, 1373, 0, 1378, 0, 1497, 0, 0, 1492, + 1597, 624, 0, 626, 0, -2, 431, 444, 0, 185, + 211, 212, 0, 0, 215, 216, 217, 208, 209, 129, + 0, 0, 713, 0, 1538, 1539, 0, 136, 0, 0, + 1094, 1095, 1096, 1097, 1099, 0, 0, 0, 0, 1130, + 1107, 625, 0, 0, 386, 0, 635, 432, 433, 0, + 439, 440, 441, 442, 213, 214, 647, 0, 0, 509, + 587, 1446, 0, 0, 1368, 0, 1374, 0, 1379, 0, + 627, 628, 636, 0, 434, 0, 435, 0, 0, 0, + 616, 0, 647, 1536, 1104, 1098, 1100, 0, 0, 1128, + 0, 637, 633, 445, 447, 448, 0, 0, 446, 648, + 617, 1369, 1375, 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, 152, 3, 3, 3, 180, 172, 3, - 91, 93, 177, 175, 92, 176, 230, 178, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 742, - 160, 159, 161, 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, 750, + 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, 182, 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, 148, 3, 183, + 3, 3, 3, 3, 153, 3, 188, } var yyTok2 = [...]int{ @@ -9844,20 +9991,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, 146, 147, 149, 150, 151, 153, 154, 155, 156, - 157, 158, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 173, 174, 179, 181, 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, - 228, 229, 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, @@ -9958,7 +10105,9 @@ 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, - 58065, 740, 58066, 741, 0, + 58065, 740, 58066, 741, 58067, 742, 58068, 743, 58069, 744, + 58070, 745, 58071, 746, 58072, 747, 58073, 748, 58074, 749, + 0, } var yyErrorMessages = [...]struct { @@ -10308,7 +10457,7 @@ yydefault: case 1: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:622 +//line sql.y:631 { stmt := yyDollar[2].statementUnion() // If the statement is empty and we have comments @@ -10322,46 +10471,46 @@ yydefault: } case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:635 +//line sql.y:644 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:636 +//line sql.y:645 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:640 +//line sql.y:649 { yyLOCAL = yyDollar[1].selStmtUnion() } yyVAL.union = yyLOCAL case 40: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:679 +//line sql.y:688 { setParseTree(yylex, nil) } case 41: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:685 +//line sql.y:694 { yyLOCAL = NewVariableExpression(yyDollar[1].str, SingleAt) } yyVAL.union = yyLOCAL case 42: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:691 +//line sql.y:700 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } case 43: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:697 +//line sql.y:706 { yyLOCAL = NewVariableExpression(string(yyDollar[1].str), SingleAt) } @@ -10369,7 +10518,7 @@ yydefault: case 44: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:701 +//line sql.y:710 { yyLOCAL = NewVariableExpression(string(yyDollar[1].str), DoubleAt) } @@ -10377,7 +10526,7 @@ yydefault: case 45: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:707 +//line sql.y:716 { yyLOCAL = &OtherAdmin{} } @@ -10385,7 +10534,7 @@ yydefault: case 46: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:713 +//line sql.y:722 { yyLOCAL = &Load{} } @@ -10393,7 +10542,7 @@ yydefault: case 47: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *With -//line sql.y:719 +//line sql.y:728 { yyLOCAL = &With{CTEs: yyDollar[2].ctesUnion(), Recursive: false} } @@ -10401,7 +10550,7 @@ yydefault: case 48: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *With -//line sql.y:723 +//line sql.y:732 { yyLOCAL = &With{CTEs: yyDollar[3].ctesUnion(), Recursive: true} } @@ -10409,7 +10558,7 @@ yydefault: case 49: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *With -//line sql.y:728 +//line sql.y:737 { yyLOCAL = nil } @@ -10417,14 +10566,14 @@ yydefault: case 50: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *With -//line sql.y:732 +//line sql.y:741 { yyLOCAL = yyDollar[1].withUnion() } yyVAL.union = yyLOCAL case 51: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:738 +//line sql.y:747 { yySLICE := (*[]*CommonTableExpr)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].cteUnion()) @@ -10432,7 +10581,7 @@ yydefault: case 52: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*CommonTableExpr -//line sql.y:742 +//line sql.y:751 { yyLOCAL = []*CommonTableExpr{yyDollar[1].cteUnion()} } @@ -10440,15 +10589,15 @@ yydefault: case 53: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *CommonTableExpr -//line sql.y:748 +//line sql.y:757 { - yyLOCAL = &CommonTableExpr{ID: yyDollar[1].identifierCS, Columns: yyDollar[2].columnsUnion(), Subquery: yyDollar[4].subqueryUnion()} + yyLOCAL = &CommonTableExpr{ID: yyDollar[1].identifierCS, Columns: yyDollar[2].columnsUnion(), Subquery: yyDollar[4].subqueryUnion().Select} } yyVAL.union = yyLOCAL case 54: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:754 +//line sql.y:763 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10456,7 +10605,7 @@ yydefault: case 55: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:758 +//line sql.y:767 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10464,7 +10613,7 @@ yydefault: case 56: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:762 +//line sql.y:771 { setLockInSelect(yyDollar[2].selStmtUnion(), yyDollar[3].lockUnion()) yyLOCAL = yyDollar[2].selStmtUnion() @@ -10473,7 +10622,7 @@ yydefault: case 57: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:785 +//line sql.y:794 { yyDollar[1].selStmtUnion().SetOrderBy(yyDollar[2].orderByUnion()) yyDollar[1].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10483,7 +10632,7 @@ yydefault: case 58: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:791 +//line sql.y:800 { yyDollar[1].selStmtUnion().SetLimit(yyDollar[2].limitUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10492,7 +10641,7 @@ yydefault: case 59: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:796 +//line sql.y:805 { yyDollar[1].selStmtUnion().SetOrderBy(yyDollar[2].orderByUnion()) yyDollar[1].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10502,7 +10651,7 @@ yydefault: case 60: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:802 +//line sql.y:811 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetOrderBy(yyDollar[3].orderByUnion()) @@ -10513,7 +10662,7 @@ yydefault: case 61: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:809 +//line sql.y:818 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10523,7 +10672,7 @@ yydefault: case 62: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:815 +//line sql.y:824 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetOrderBy(yyDollar[3].orderByUnion()) @@ -10533,14 +10682,14 @@ yydefault: yyVAL.union = yyLOCAL case 63: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:822 +//line sql.y:831 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) } case 64: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:826 +//line sql.y:835 { 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) } @@ -10548,7 +10697,7 @@ yydefault: case 65: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:832 +//line sql.y:841 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10556,7 +10705,7 @@ yydefault: case 66: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:836 +//line sql.y:845 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10564,7 +10713,7 @@ yydefault: case 67: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:840 +//line sql.y:849 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10572,7 +10721,7 @@ yydefault: case 68: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:844 +//line sql.y:853 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10580,7 +10729,7 @@ yydefault: case 69: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:848 +//line sql.y:857 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10588,7 +10737,7 @@ yydefault: case 70: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:854 +//line sql.y:863 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10596,7 +10745,7 @@ yydefault: case 71: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:858 +//line sql.y:867 { setLockInSelect(yyDollar[1].selStmtUnion(), yyDollar[2].lockUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10605,7 +10754,7 @@ yydefault: case 72: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:863 +//line sql.y:872 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10613,7 +10762,7 @@ yydefault: case 73: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:867 +//line sql.y:876 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10621,7 +10770,7 @@ yydefault: case 74: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:873 +//line sql.y:882 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10629,7 +10778,7 @@ yydefault: case 75: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:877 +//line sql.y:886 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10638,7 +10787,7 @@ yydefault: case 76: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:882 +//line sql.y:891 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyDollar[1].selStmtUnion().SetLock(yyDollar[3].lockUnion()) @@ -10648,7 +10797,7 @@ yydefault: case 77: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:888 +//line sql.y:897 { yyDollar[1].selStmtUnion().SetInto(yyDollar[3].selectIntoUnion()) yyDollar[1].selStmtUnion().SetLock(yyDollar[2].lockUnion()) @@ -10658,7 +10807,7 @@ yydefault: case 78: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:894 +//line sql.y:903 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10667,7 +10816,7 @@ yydefault: case 79: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:901 +//line sql.y:910 { yyLOCAL = &Stream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: yyDollar[3].selectExprUnion(), Table: yyDollar[5].tableName} } @@ -10675,7 +10824,7 @@ yydefault: case 80: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:907 +//line sql.y:916 { 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()} } @@ -10683,7 +10832,7 @@ yydefault: case 81: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:915 +//line sql.y:924 { 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()) } @@ -10691,7 +10840,7 @@ yydefault: case 82: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:919 +//line sql.y:928 { 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()) } @@ -10699,7 +10848,7 @@ yydefault: case 83: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:925 +//line sql.y:934 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].insUnion() @@ -10715,7 +10864,7 @@ yydefault: case 84: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:937 +//line sql.y:946 { cols := make(Columns, 0, len(yyDollar[7].updateExprsUnion())) vals := make(ValTuple, 0, len(yyDollar[8].updateExprsUnion())) @@ -10729,7 +10878,7 @@ yydefault: case 85: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:949 +//line sql.y:958 { yyLOCAL = InsertAct } @@ -10737,7 +10886,7 @@ yydefault: case 86: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:953 +//line sql.y:962 { yyLOCAL = ReplaceAct } @@ -10745,7 +10894,7 @@ yydefault: case 87: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Statement -//line sql.y:959 +//line sql.y:968 { 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()} } @@ -10753,7 +10902,7 @@ yydefault: case 88: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL Statement -//line sql.y:965 +//line sql.y:974 { 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()} } @@ -10761,7 +10910,7 @@ yydefault: case 89: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Statement -//line sql.y:969 +//line sql.y:978 { 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())} } @@ -10769,7 +10918,7 @@ yydefault: case 90: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:973 +//line sql.y:982 { 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())} } @@ -10777,32 +10926,32 @@ yydefault: case 91: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:977 +//line sql.y:986 { 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:982 +//line sql.y:991 { } case 93: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:983 +//line sql.y:992 { } case 94: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:987 +//line sql.y:996 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 95: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:991 +//line sql.y:1000 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10810,14 +10959,14 @@ yydefault: case 96: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:997 +//line sql.y:1006 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 97: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1001 +//line sql.y:1010 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10825,14 +10974,14 @@ yydefault: case 98: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:1007 +//line sql.y:1016 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 99: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1011 +//line sql.y:1020 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10840,7 +10989,7 @@ yydefault: case 100: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Partitions -//line sql.y:1016 +//line sql.y:1025 { yyLOCAL = nil } @@ -10848,7 +10997,7 @@ yydefault: case 101: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Partitions -//line sql.y:1020 +//line sql.y:1029 { yyLOCAL = yyDollar[3].partitionsUnion() } @@ -10856,7 +11005,7 @@ yydefault: case 102: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:1026 +//line sql.y:1035 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[3].setExprsUnion()) } @@ -10864,14 +11013,14 @@ yydefault: case 103: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1032 +//line sql.y:1041 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL case 104: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1036 +//line sql.y:1045 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) @@ -10879,7 +11028,7 @@ yydefault: case 105: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1042 +//line sql.y:1051 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("on")} } @@ -10887,7 +11036,7 @@ yydefault: case 106: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1046 +//line sql.y:1055 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("off")} } @@ -10895,7 +11044,7 @@ yydefault: case 107: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1050 +//line sql.y:1059 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: yyDollar[3].exprUnion()} } @@ -10903,7 +11052,7 @@ yydefault: case 108: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1054 +//line sql.y:1063 { yyLOCAL = &SetExpr{Var: NewSetVariable(string(yyDollar[1].str), SessionScope), Expr: yyDollar[2].exprUnion()} } @@ -10911,7 +11060,7 @@ yydefault: case 109: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1060 +//line sql.y:1069 { yyLOCAL = NewSetVariable(string(yyDollar[1].str), SessionScope) } @@ -10919,7 +11068,7 @@ yydefault: case 110: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1064 +//line sql.y:1073 { yyLOCAL = yyDollar[1].variableUnion() } @@ -10927,7 +11076,7 @@ yydefault: case 111: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Variable -//line sql.y:1068 +//line sql.y:1077 { yyLOCAL = NewSetVariable(string(yyDollar[2].str), yyDollar[1].scopeUnion()) } @@ -10935,7 +11084,7 @@ yydefault: case 112: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:1074 +//line sql.y:1083 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), UpdateSetExprsScope(yyDollar[5].setExprsUnion(), yyDollar[3].scopeUnion())) } @@ -10943,7 +11092,7 @@ yydefault: case 113: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:1078 +//line sql.y:1087 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[4].setExprsUnion()) } @@ -10951,14 +11100,14 @@ yydefault: case 114: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1084 +//line sql.y:1093 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL case 115: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1088 +//line sql.y:1097 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) @@ -10966,7 +11115,7 @@ yydefault: case 116: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1094 +//line sql.y:1103 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionIsolationStr, NextTxScope), Expr: NewStrLiteral(yyDollar[3].str)} } @@ -10974,7 +11123,7 @@ yydefault: case 117: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1098 +//line sql.y:1107 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("off")} } @@ -10982,39 +11131,39 @@ yydefault: case 118: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1102 +//line sql.y:1111 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("on")} } yyVAL.union = yyLOCAL case 119: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1108 +//line sql.y:1117 { yyVAL.str = RepeatableReadStr } case 120: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1112 +//line sql.y:1121 { yyVAL.str = ReadCommittedStr } case 121: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1116 +//line sql.y:1125 { yyVAL.str = ReadUncommittedStr } case 122: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1120 +//line sql.y:1129 { yyVAL.str = SerializableStr } case 123: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1126 +//line sql.y:1135 { yyLOCAL = SessionScope } @@ -11022,7 +11171,7 @@ yydefault: case 124: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1130 +//line sql.y:1139 { yyLOCAL = SessionScope } @@ -11030,7 +11179,7 @@ yydefault: case 125: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1134 +//line sql.y:1143 { yyLOCAL = GlobalScope } @@ -11038,7 +11187,7 @@ yydefault: case 126: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1140 +//line sql.y:1149 { yyDollar[1].createTableUnion().TableSpec = yyDollar[2].tableSpecUnion() yyDollar[1].createTableUnion().FullyParsed = true @@ -11048,7 +11197,7 @@ yydefault: case 127: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1146 +//line sql.y:1155 { // Create table [name] like [name] yyDollar[1].createTableUnion().OptLike = yyDollar[2].optLikeUnion() @@ -11059,7 +11208,7 @@ yydefault: case 128: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:1153 +//line sql.y:1162 { indexDef := yyDollar[1].alterTableUnion().AlterOptions[0].(*AddIndexDefinition).IndexDefinition indexDef.Columns = yyDollar[3].indexColumnsUnion() @@ -11072,7 +11221,7 @@ yydefault: case 129: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Statement -//line sql.y:1162 +//line sql.y:1171 { 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} } @@ -11080,7 +11229,7 @@ yydefault: case 130: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1166 +//line sql.y:1175 { yyDollar[1].createDatabaseUnion().FullyParsed = true yyDollar[1].createDatabaseUnion().CreateOptions = yyDollar[2].databaseOptionsUnion() @@ -11090,7 +11239,7 @@ yydefault: case 131: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:1173 +//line sql.y:1182 { yyLOCAL = false } @@ -11098,33 +11247,33 @@ yydefault: case 132: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:1177 +//line sql.y:1186 { yyLOCAL = true } yyVAL.union = yyLOCAL case 133: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1182 +//line sql.y:1191 { yyVAL.identifierCI = NewIdentifierCI("") } case 134: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1186 +//line sql.y:1195 { yyVAL.identifierCI = yyDollar[2].identifierCI } case 135: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1192 +//line sql.y:1201 { yyVAL.identifierCI = yyDollar[1].identifierCI } case 136: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1197 +//line sql.y:1206 { var v []VindexParam yyLOCAL = v @@ -11133,7 +11282,7 @@ yydefault: case 137: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1202 +//line sql.y:1211 { yyLOCAL = yyDollar[2].vindexParamsUnion() } @@ -11141,7 +11290,7 @@ yydefault: case 138: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1208 +//line sql.y:1217 { yyLOCAL = make([]VindexParam, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].vindexParam) @@ -11149,21 +11298,21 @@ yydefault: yyVAL.union = yyLOCAL case 139: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1213 +//line sql.y:1222 { yySLICE := (*[]VindexParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].vindexParam) } case 140: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1219 +//line sql.y:1228 { 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:1224 +//line sql.y:1233 { yyLOCAL = nil } @@ -11171,7 +11320,7 @@ yydefault: case 142: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1228 +//line sql.y:1237 { yyLOCAL = yyDollar[1].jsonObjectParamsUnion() } @@ -11179,28 +11328,28 @@ yydefault: case 143: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1234 +//line sql.y:1243 { yyLOCAL = []*JSONObjectParam{yyDollar[1].jsonObjectParam} } yyVAL.union = yyLOCAL case 144: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1238 +//line sql.y:1247 { yySLICE := (*[]*JSONObjectParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].jsonObjectParam) } case 145: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1244 +//line sql.y:1253 { 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:1250 +//line sql.y:1259 { yyLOCAL = &CreateTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[6].tableName, IfNotExists: yyDollar[5].booleanUnion(), Temp: yyDollar[3].booleanUnion()} setDDL(yylex, yyLOCAL) @@ -11209,7 +11358,7 @@ yydefault: case 147: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1257 +//line sql.y:1266 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[4].tableName} setDDL(yylex, yyLOCAL) @@ -11218,7 +11367,7 @@ yydefault: case 148: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1264 +//line sql.y:1273 { yyLOCAL = &AlterTable{Table: yyDollar[7].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[4].identifierCI}, Options: yyDollar[5].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) @@ -11227,7 +11376,7 @@ yydefault: case 149: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1269 +//line sql.y:1278 { 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) @@ -11236,7 +11385,7 @@ yydefault: case 150: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1274 +//line sql.y:1283 { 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) @@ -11245,7 +11394,7 @@ yydefault: case 151: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1279 +//line sql.y:1288 { 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) @@ -11254,7 +11403,7 @@ yydefault: case 152: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *CreateDatabase -//line sql.y:1286 +//line sql.y:1295 { yyLOCAL = &CreateDatabase{Comments: Comments(yyDollar[4].strs).Parsed(), DBName: yyDollar[6].identifierCS, IfNotExists: yyDollar[5].booleanUnion()} setDDL(yylex, yyLOCAL) @@ -11263,7 +11412,7 @@ yydefault: case 153: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AlterDatabase -//line sql.y:1293 +//line sql.y:1302 { yyLOCAL = &AlterDatabase{} setDDL(yylex, yyLOCAL) @@ -11272,7 +11421,7 @@ yydefault: case 156: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1304 +//line sql.y:1313 { yyLOCAL = yyDollar[2].tableSpecUnion() yyLOCAL.Options = yyDollar[4].tableOptionsUnion() @@ -11282,7 +11431,7 @@ yydefault: case 157: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1311 +//line sql.y:1320 { yyLOCAL = nil } @@ -11290,7 +11439,7 @@ yydefault: case 158: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1315 +//line sql.y:1324 { yyLOCAL = yyDollar[1].databaseOptionsUnion() } @@ -11298,7 +11447,7 @@ yydefault: case 159: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1321 +//line sql.y:1330 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } @@ -11306,7 +11455,7 @@ yydefault: case 160: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1325 +//line sql.y:1334 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } @@ -11314,28 +11463,28 @@ yydefault: case 161: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1329 +//line sql.y:1338 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } yyVAL.union = yyLOCAL case 162: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1333 +//line sql.y:1342 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } case 163: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1337 +//line sql.y:1346 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } case 164: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1341 +//line sql.y:1350 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) @@ -11343,7 +11492,7 @@ yydefault: case 165: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:1347 +//line sql.y:1356 { yyLOCAL = false } @@ -11351,51 +11500,51 @@ yydefault: case 166: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:1351 +//line sql.y:1360 { yyLOCAL = true } yyVAL.union = yyLOCAL case 167: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1357 +//line sql.y:1366 { 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:1361 +//line sql.y:1370 { 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:1367 +//line sql.y:1376 { 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:1371 +//line sql.y:1380 { 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:1377 +//line sql.y:1386 { 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:1381 +//line sql.y:1390 { 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:1387 +//line sql.y:1396 { yyLOCAL = &OptLike{LikeTable: yyDollar[2].tableName} } @@ -11403,7 +11552,7 @@ yydefault: case 174: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OptLike -//line sql.y:1391 +//line sql.y:1400 { yyLOCAL = &OptLike{LikeTable: yyDollar[3].tableName} } @@ -11411,14 +11560,14 @@ yydefault: case 175: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColumnDefinition -//line sql.y:1397 +//line sql.y:1406 { yyLOCAL = []*ColumnDefinition{yyDollar[1].columnDefinitionUnion()} } yyVAL.union = yyLOCAL case 176: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1401 +//line sql.y:1410 { yySLICE := (*[]*ColumnDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].columnDefinitionUnion()) @@ -11426,7 +11575,7 @@ yydefault: case 177: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1407 +//line sql.y:1416 { yyLOCAL = &TableSpec{} yyLOCAL.AddColumn(yyDollar[1].columnDefinitionUnion()) @@ -11435,7 +11584,7 @@ yydefault: case 178: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1412 +//line sql.y:1421 { yyLOCAL = &TableSpec{} yyLOCAL.AddConstraint(yyDollar[1].constraintDefinitionUnion()) @@ -11443,39 +11592,39 @@ yydefault: yyVAL.union = yyLOCAL case 179: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1417 +//line sql.y:1426 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) } case 180: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1421 +//line sql.y:1430 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) yyVAL.tableSpecUnion().AddConstraint(yyDollar[4].constraintDefinitionUnion()) } case 181: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1426 +//line sql.y:1435 { yyVAL.tableSpecUnion().AddIndex(yyDollar[3].indexDefinitionUnion()) } case 182: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1430 +//line sql.y:1439 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } case 183: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1434 +//line sql.y:1443 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } case 184: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1445 +//line sql.y:1454 { yyDollar[2].columnType.Options = yyDollar[4].columnTypeOptionsUnion() if yyDollar[2].columnType.Options.Collate == "" { @@ -11488,7 +11637,7 @@ yydefault: case 185: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1454 +//line sql.y:1463 { yyDollar[2].columnType.Options = yyDollar[9].columnTypeOptionsUnion() yyDollar[2].columnType.Options.As = yyDollar[7].exprUnion() @@ -11499,20 +11648,20 @@ yydefault: yyVAL.union = yyLOCAL case 186: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1463 +//line sql.y:1472 { yyVAL.str = "" } case 187: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1467 +//line sql.y:1476 { yyVAL.str = "" } case 188: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1476 +//line sql.y:1485 { yyLOCAL = &ColumnTypeOptions{Null: nil, Default: nil, OnUpdate: nil, Autoincrement: false, KeyOpt: ColKeyNone, Comment: nil, As: nil, Invisible: nil, Format: UnspecifiedFormat, EngineAttribute: nil, SecondaryEngineAttribute: nil} } @@ -11520,7 +11669,7 @@ yydefault: case 189: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1480 +//line sql.y:1489 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11529,7 +11678,7 @@ yydefault: case 190: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1485 +//line sql.y:1494 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11538,7 +11687,7 @@ yydefault: case 191: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1490 +//line sql.y:1499 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11547,7 +11696,7 @@ yydefault: case 192: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1495 +//line sql.y:1504 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[3].exprUnion() yyDollar[1].columnTypeOptionsUnion().DefaultLiteral = true @@ -11557,7 +11706,7 @@ yydefault: case 193: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1501 +//line sql.y:1510 { yyDollar[1].columnTypeOptionsUnion().OnUpdate = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11566,7 +11715,7 @@ yydefault: case 194: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1506 +//line sql.y:1515 { yyDollar[1].columnTypeOptionsUnion().Autoincrement = true yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11575,7 +11724,7 @@ yydefault: case 195: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1511 +//line sql.y:1520 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11584,7 +11733,7 @@ yydefault: case 196: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1516 +//line sql.y:1525 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11592,14 +11741,14 @@ yydefault: yyVAL.union = yyLOCAL case 197: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1521 +//line sql.y:1530 { yyDollar[1].columnTypeOptionsUnion().Collate = encodeSQLString(yyDollar[3].str) } case 198: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1525 +//line sql.y:1534 { yyDollar[1].columnTypeOptionsUnion().Collate = string(yyDollar[3].identifierCI.String()) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11607,14 +11756,14 @@ yydefault: yyVAL.union = yyLOCAL case 199: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1530 +//line sql.y:1539 { yyDollar[1].columnTypeOptionsUnion().Format = yyDollar[3].columnFormatUnion() } case 200: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1534 +//line sql.y:1543 { yyDollar[1].columnTypeOptionsUnion().SRID = NewIntLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11623,7 +11772,7 @@ yydefault: case 201: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1539 +//line sql.y:1548 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11632,7 +11781,7 @@ yydefault: case 202: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1544 +//line sql.y:1553 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11640,20 +11789,20 @@ yydefault: yyVAL.union = yyLOCAL case 203: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1549 +//line sql.y:1558 { yyDollar[1].columnTypeOptionsUnion().EngineAttribute = NewStrLiteral(yyDollar[4].str) } case 204: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1553 +//line sql.y:1562 { yyDollar[1].columnTypeOptionsUnion().SecondaryEngineAttribute = NewStrLiteral(yyDollar[4].str) } case 205: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1559 +//line sql.y:1568 { yyLOCAL = FixedFormat } @@ -11661,7 +11810,7 @@ yydefault: case 206: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1563 +//line sql.y:1572 { yyLOCAL = DynamicFormat } @@ -11669,7 +11818,7 @@ yydefault: case 207: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1567 +//line sql.y:1576 { yyLOCAL = DefaultFormat } @@ -11677,7 +11826,7 @@ yydefault: case 208: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1573 +//line sql.y:1582 { yyLOCAL = VirtualStorage } @@ -11685,7 +11834,7 @@ yydefault: case 209: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1577 +//line sql.y:1586 { yyLOCAL = StoredStorage } @@ -11693,7 +11842,7 @@ yydefault: case 210: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1582 +//line sql.y:1591 { yyLOCAL = &ColumnTypeOptions{} } @@ -11701,7 +11850,7 @@ yydefault: case 211: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1586 +//line sql.y:1595 { yyDollar[1].columnTypeOptionsUnion().Storage = yyDollar[2].columnStorageUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11710,7 +11859,7 @@ yydefault: case 212: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1591 +//line sql.y:1600 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11719,7 +11868,7 @@ yydefault: case 213: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1596 +//line sql.y:1605 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11728,7 +11877,7 @@ yydefault: case 214: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1601 +//line sql.y:1610 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11737,7 +11886,7 @@ yydefault: case 215: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1606 +//line sql.y:1615 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11746,7 +11895,7 @@ yydefault: case 216: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1611 +//line sql.y:1620 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11755,7 +11904,7 @@ yydefault: case 217: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1616 +//line sql.y:1625 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11764,7 +11913,7 @@ yydefault: case 218: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1623 +//line sql.y:1632 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11772,7 +11921,7 @@ yydefault: case 220: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1630 +//line sql.y:1639 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_timestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11780,7 +11929,7 @@ yydefault: case 221: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1634 +//line sql.y:1643 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtime"), Fsp: yyDollar[2].integerUnion()} } @@ -11788,7 +11937,7 @@ yydefault: case 222: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1638 +//line sql.y:1647 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtimestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11796,7 +11945,7 @@ yydefault: case 223: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1642 +//line sql.y:1651 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_timestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11804,7 +11953,7 @@ yydefault: case 224: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1646 +//line sql.y:1655 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("now"), Fsp: yyDollar[2].integerUnion()} } @@ -11812,7 +11961,7 @@ yydefault: case 225: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1650 +//line sql.y:1659 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("sysdate"), Fsp: yyDollar[2].integerUnion()} } @@ -11820,7 +11969,7 @@ yydefault: case 228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1660 +//line sql.y:1669 { yyLOCAL = &NullVal{} } @@ -11828,7 +11977,7 @@ yydefault: case 230: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1667 +//line sql.y:1676 { yyLOCAL = yyDollar[2].exprUnion() } @@ -11836,7 +11985,7 @@ yydefault: case 231: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1671 +//line sql.y:1680 { yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } @@ -11844,7 +11993,7 @@ yydefault: case 232: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1677 +//line sql.y:1686 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11852,7 +12001,7 @@ yydefault: case 233: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1681 +//line sql.y:1690 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11860,7 +12009,7 @@ yydefault: case 234: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1685 +//line sql.y:1694 { yyLOCAL = yyDollar[1].boolValUnion() } @@ -11868,7 +12017,7 @@ yydefault: case 235: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1689 +//line sql.y:1698 { yyLOCAL = NewHexLiteral(yyDollar[1].str) } @@ -11876,7 +12025,7 @@ yydefault: case 236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1693 +//line sql.y:1702 { yyLOCAL = NewHexNumLiteral(yyDollar[1].str) } @@ -11884,7 +12033,7 @@ yydefault: case 237: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1697 +//line sql.y:1706 { yyLOCAL = NewBitLiteral(yyDollar[1].str) } @@ -11892,7 +12041,7 @@ yydefault: case 238: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1701 +//line sql.y:1710 { yyLOCAL = NewBitLiteral("0b" + yyDollar[1].str) } @@ -11900,7 +12049,7 @@ yydefault: case 239: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1705 +//line sql.y:1714 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } @@ -11908,7 +12057,7 @@ yydefault: case 240: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1709 +//line sql.y:1718 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral("0b" + yyDollar[2].str)} } @@ -11916,7 +12065,7 @@ yydefault: case 241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1713 +//line sql.y:1722 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexNumLiteral(yyDollar[2].str)} } @@ -11924,7 +12073,7 @@ yydefault: case 242: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1717 +//line sql.y:1726 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral(yyDollar[2].str)} } @@ -11932,7 +12081,7 @@ yydefault: case 243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1721 +//line sql.y:1730 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexLiteral(yyDollar[2].str)} } @@ -11940,7 +12089,7 @@ yydefault: case 244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1725 +//line sql.y:1734 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: yyDollar[2].exprUnion()} } @@ -11948,7 +12097,7 @@ yydefault: case 245: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1729 +//line sql.y:1738 { arg := parseBindVariable(yylex, yyDollar[2].str[1:]) yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: arg} @@ -11957,7 +12106,7 @@ yydefault: case 246: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1734 +//line sql.y:1743 { yyLOCAL = NewDateLiteral(yyDollar[2].str) } @@ -11965,7 +12114,7 @@ yydefault: case 247: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1738 +//line sql.y:1747 { yyLOCAL = NewTimeLiteral(yyDollar[2].str) } @@ -11973,267 +12122,267 @@ yydefault: case 248: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1742 +//line sql.y:1751 { yyLOCAL = NewTimestampLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL case 249: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1748 +//line sql.y:1757 { yyVAL.str = Armscii8Str } case 250: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1752 +//line sql.y:1761 { yyVAL.str = ASCIIStr } case 251: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1756 +//line sql.y:1765 { yyVAL.str = Big5Str } case 252: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1760 +//line sql.y:1769 { yyVAL.str = UBinaryStr } case 253: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1764 +//line sql.y:1773 { yyVAL.str = Cp1250Str } case 254: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1768 +//line sql.y:1777 { yyVAL.str = Cp1251Str } case 255: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1772 +//line sql.y:1781 { yyVAL.str = Cp1256Str } case 256: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1776 +//line sql.y:1785 { yyVAL.str = Cp1257Str } case 257: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1780 +//line sql.y:1789 { yyVAL.str = Cp850Str } case 258: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1784 +//line sql.y:1793 { yyVAL.str = Cp852Str } case 259: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1788 +//line sql.y:1797 { yyVAL.str = Cp866Str } case 260: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1792 +//line sql.y:1801 { yyVAL.str = Cp932Str } case 261: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1796 +//line sql.y:1805 { yyVAL.str = Dec8Str } case 262: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1800 +//line sql.y:1809 { yyVAL.str = EucjpmsStr } case 263: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1804 +//line sql.y:1813 { yyVAL.str = EuckrStr } case 264: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1808 +//line sql.y:1817 { yyVAL.str = Gb18030Str } case 265: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1812 +//line sql.y:1821 { yyVAL.str = Gb2312Str } case 266: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1816 +//line sql.y:1825 { yyVAL.str = GbkStr } case 267: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1820 +//line sql.y:1829 { yyVAL.str = Geostd8Str } case 268: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1824 +//line sql.y:1833 { yyVAL.str = GreekStr } case 269: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1828 +//line sql.y:1837 { yyVAL.str = HebrewStr } case 270: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1832 +//line sql.y:1841 { yyVAL.str = Hp8Str } case 271: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1836 +//line sql.y:1845 { yyVAL.str = Keybcs2Str } case 272: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1840 +//line sql.y:1849 { yyVAL.str = Koi8rStr } case 273: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1844 +//line sql.y:1853 { yyVAL.str = Koi8uStr } case 274: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1848 +//line sql.y:1857 { yyVAL.str = Latin1Str } case 275: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1852 +//line sql.y:1861 { yyVAL.str = Latin2Str } case 276: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1856 +//line sql.y:1865 { yyVAL.str = Latin5Str } case 277: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1860 +//line sql.y:1869 { yyVAL.str = Latin7Str } case 278: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1864 +//line sql.y:1873 { yyVAL.str = MacceStr } case 279: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1868 +//line sql.y:1877 { yyVAL.str = MacromanStr } case 280: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1872 +//line sql.y:1881 { yyVAL.str = SjisStr } case 281: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1876 +//line sql.y:1885 { yyVAL.str = Swe7Str } case 282: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1880 +//line sql.y:1889 { yyVAL.str = Tis620Str } case 283: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1884 +//line sql.y:1893 { yyVAL.str = Ucs2Str } case 284: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1888 +//line sql.y:1897 { yyVAL.str = UjisStr } case 285: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1892 +//line sql.y:1901 { yyVAL.str = Utf16Str } case 286: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1896 +//line sql.y:1905 { yyVAL.str = Utf16leStr } case 287: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1900 +//line sql.y:1909 { yyVAL.str = Utf32Str } case 288: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1904 +//line sql.y:1913 { yyVAL.str = Utf8mb3Str } case 289: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1908 +//line sql.y:1917 { yyVAL.str = Utf8mb4Str } case 290: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1912 +//line sql.y:1921 { yyVAL.str = Utf8mb3Str } case 293: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1922 +//line sql.y:1931 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } @@ -12241,7 +12390,7 @@ yydefault: case 294: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1926 +//line sql.y:1935 { yyLOCAL = NewFloatLiteral(yyDollar[1].str) } @@ -12249,7 +12398,7 @@ yydefault: case 295: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1930 +//line sql.y:1939 { yyLOCAL = NewDecimalLiteral(yyDollar[1].str) } @@ -12257,7 +12406,7 @@ yydefault: case 296: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1936 +//line sql.y:1945 { yyLOCAL = yyDollar[1].exprUnion() } @@ -12265,7 +12414,7 @@ yydefault: case 297: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1940 +//line sql.y:1949 { yyLOCAL = AppendString(yyDollar[1].exprUnion(), yyDollar[2].str) } @@ -12273,7 +12422,7 @@ yydefault: case 298: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1946 +//line sql.y:1955 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } @@ -12281,7 +12430,7 @@ yydefault: case 299: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1950 +//line sql.y:1959 { yyLOCAL = &UnaryExpr{Operator: NStringOp, Expr: NewStrLiteral(yyDollar[1].str)} } @@ -12289,7 +12438,7 @@ yydefault: case 300: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1954 +//line sql.y:1963 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewStrLiteral(yyDollar[2].str)} } @@ -12297,7 +12446,7 @@ yydefault: case 301: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1960 +//line sql.y:1969 { yyLOCAL = yyDollar[1].exprUnion() } @@ -12305,7 +12454,7 @@ yydefault: case 302: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1964 +//line sql.y:1973 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } @@ -12313,7 +12462,7 @@ yydefault: case 303: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1970 +//line sql.y:1979 { yyLOCAL = ColKeyPrimary } @@ -12321,7 +12470,7 @@ yydefault: case 304: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1974 +//line sql.y:1983 { yyLOCAL = ColKeyUnique } @@ -12329,7 +12478,7 @@ yydefault: case 305: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1978 +//line sql.y:1987 { yyLOCAL = ColKeyUniqueKey } @@ -12337,14 +12486,14 @@ yydefault: case 306: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1982 +//line sql.y:1991 { yyLOCAL = ColKey } yyVAL.union = yyLOCAL case 307: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1988 +//line sql.y:1997 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].booleanUnion() @@ -12352,74 +12501,74 @@ yydefault: } case 311: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1999 +//line sql.y:2008 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].intPtrUnion() } case 312: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2004 +//line sql.y:2013 { yyVAL.columnType = yyDollar[1].columnType } case 313: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2010 +//line sql.y:2019 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 314: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2014 +//line sql.y:2023 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 315: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2018 +//line sql.y:2027 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 316: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2022 +//line sql.y:2031 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 317: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2026 +//line sql.y:2035 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 318: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2030 +//line sql.y:2039 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 319: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2034 +//line sql.y:2043 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 320: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2038 +//line sql.y:2047 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 321: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2042 +//line sql.y:2051 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2048 +//line sql.y:2057 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12427,7 +12576,7 @@ yydefault: } case 323: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2054 +//line sql.y:2063 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12435,7 +12584,7 @@ yydefault: } case 324: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2060 +//line sql.y:2069 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12443,7 +12592,7 @@ yydefault: } case 325: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2066 +//line sql.y:2075 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12451,7 +12600,7 @@ yydefault: } case 326: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2072 +//line sql.y:2081 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12459,7 +12608,7 @@ yydefault: } case 327: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2078 +//line sql.y:2087 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12467,7 +12616,7 @@ yydefault: } case 328: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2084 +//line sql.y:2093 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12475,43 +12624,43 @@ yydefault: } case 329: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2092 +//line sql.y:2101 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 330: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2096 +//line sql.y:2105 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 331: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2100 +//line sql.y:2109 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 332: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2104 +//line sql.y:2113 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 333: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2108 +//line sql.y:2117 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 334: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2114 +//line sql.y:2123 { 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:2118 +//line sql.y:2127 { // CHAR BYTE is an alias for binary. See also: // https://dev.mysql.com/doc/refman/8.0/en/string-type-syntax.html @@ -12519,1633 +12668,1631 @@ yydefault: } case 336: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2124 +//line sql.y:2133 { 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:2128 +//line sql.y:2137 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 338: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2132 +//line sql.y:2141 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 339: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2136 +//line sql.y:2145 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 340: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2140 +//line sql.y:2149 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 341: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2144 +//line sql.y:2153 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 342: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2148 +//line sql.y:2157 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2152 +//line sql.y:2161 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 344: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2156 +//line sql.y:2165 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 345: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2160 +//line sql.y:2169 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 346: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2164 +//line sql.y:2173 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 347: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2168 +//line sql.y:2177 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 348: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2172 +//line sql.y:2181 { 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:2177 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2185 { - 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:2183 + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:2190 { - 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:2187 +//line sql.y:2196 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 352: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2191 +//line sql.y:2200 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 353: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2195 +//line sql.y:2204 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 354: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2199 +//line sql.y:2208 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 355: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2203 +//line sql.y:2212 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 356: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2207 +//line sql.y:2216 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 357: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2211 +//line sql.y:2220 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 358: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2217 +//line sql.y:2224 + { + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + } + case 359: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2230 { 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:2222 +//line sql.y:2235 { 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:2227 +//line sql.y:2240 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 361: + case 362: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *int -//line sql.y:2231 +//line sql.y:2244 { yyLOCAL = ptr.Of(convertStringToInt(yyDollar[2].str)) } yyVAL.union = yyLOCAL - case 362: + case 363: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2236 +//line sql.y:2249 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 363: + case 364: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2240 +//line sql.y:2253 { 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:2249 +//line sql.y:2262 { yyVAL.LengthScaleOption = yyDollar[1].LengthScaleOption } - case 365: + case 366: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2253 +//line sql.y:2266 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 366: + case 367: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2260 +//line sql.y:2273 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 367: + case 368: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2264 +//line sql.y:2277 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 368: + case 369: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2270 +//line sql.y:2283 { 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:2278 +//line sql.y:2291 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 370: + case 371: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2282 +//line sql.y:2295 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 371: + case 372: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2286 +//line sql.y:2299 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 372: + case 373: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2291 +//line sql.y:2304 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 373: + case 374: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2295 +//line sql.y:2308 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 374: + case 375: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2300 +//line sql.y:2313 { yyVAL.columnCharset = ColumnCharset{} } - case 375: + case 376: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2304 +//line sql.y:2317 { 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:2308 +//line sql.y:2321 { 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:2312 +//line sql.y:2325 { yyVAL.columnCharset = ColumnCharset{Name: string(yyDollar[2].str)} } - case 378: + case 379: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2316 +//line sql.y:2329 { // 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:2321 +//line sql.y:2334 { // 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:2326 +//line sql.y:2339 { // 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:2331 +//line sql.y:2344 { // 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:2336 +//line sql.y:2349 { // 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:2342 +//line sql.y:2355 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 384: + case 385: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2346 +//line sql.y:2359 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 385: + case 386: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2351 +//line sql.y:2364 { yyVAL.str = "" } - case 386: + case 387: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2355 +//line sql.y:2368 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 387: + case 388: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2359 +//line sql.y:2372 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 388: + case 389: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexDefinition -//line sql.y:2365 +//line sql.y:2378 { 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:2370 +//line sql.y:2383 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 390: + case 391: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2374 +//line sql.y:2387 { yyLOCAL = yyDollar[1].indexOptionsUnion() } yyVAL.union = yyLOCAL - case 391: + case 392: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2380 +//line sql.y:2393 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 392: + case 393: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2384 +//line sql.y:2397 { 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:2390 +//line sql.y:2403 { yyLOCAL = yyDollar[1].indexOptionUnion() } yyVAL.union = yyLOCAL - case 394: + case 395: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2394 +//line sql.y:2407 { // 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:2399 +//line sql.y:2412 { 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:2403 +//line sql.y:2416 { 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:2407 +//line sql.y:2420 { 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:2411 +//line sql.y:2424 { 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:2415 +//line sql.y:2428 { 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:2419 +//line sql.y:2432 { 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:2425 +//line sql.y:2438 { yyVAL.str = "" } - case 402: + case 403: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2429 +//line sql.y:2442 { yyVAL.str = string(yyDollar[1].str) } - case 403: + case 404: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2435 +//line sql.y:2448 { 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:2439 +//line sql.y:2452 { 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:2443 +//line sql.y:2456 { 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:2447 +//line sql.y:2460 { 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:2451 +//line sql.y:2464 { 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:2456 +//line sql.y:2469 { yyVAL.str = "" } - case 409: + case 410: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2460 +//line sql.y:2473 { yyVAL.str = yyDollar[2].str } - case 410: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2466 - { - yyVAL.str = string(yyDollar[1].str) - } case 411: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2470 +//line sql.y:2479 { yyVAL.str = string(yyDollar[1].str) } case 412: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2474 +//line sql.y:2483 { yyVAL.str = string(yyDollar[1].str) } case 413: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2480 +//line sql.y:2487 { yyVAL.str = string(yyDollar[1].str) } case 414: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2484 +//line sql.y:2493 { yyVAL.str = string(yyDollar[1].str) } case 415: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2497 + { + yyVAL.str = string(yyDollar[1].str) + } + case 416: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2489 +//line sql.y:2502 { yyVAL.str = "" } - case 416: + case 417: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2493 +//line sql.y:2506 { yyVAL.str = yyDollar[1].str } - case 417: + case 418: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2499 +//line sql.y:2512 { yyVAL.str = string(yyDollar[1].str) } - case 418: + case 419: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2503 +//line sql.y:2516 { yyVAL.str = string(yyDollar[1].str) } - case 419: + case 420: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2508 +//line sql.y:2521 { yyVAL.str = "" } - case 420: + case 421: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2512 +//line sql.y:2525 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 421: + case 422: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexColumn -//line sql.y:2518 +//line sql.y:2531 { yyLOCAL = []*IndexColumn{yyDollar[1].indexColumnUnion()} } yyVAL.union = yyLOCAL - case 422: + case 423: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2522 +//line sql.y:2535 { 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:2528 +//line sql.y:2541 { 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:2532 +//line sql.y:2545 { 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:2538 +//line sql.y:2551 { 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:2542 +//line sql.y:2555 { 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:2548 +//line sql.y:2561 { 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:2552 +//line sql.y:2565 { 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:2558 +//line sql.y:2571 { 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:2564 +//line sql.y:2577 { 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:2568 +//line sql.y:2581 { 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:2572 +//line sql.y:2585 { 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:2576 +//line sql.y:2589 { 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:2580 +//line sql.y:2593 { 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:2585 +//line sql.y:2598 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 436: + case 437: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2589 +//line sql.y:2602 { yyLOCAL = yyDollar[1].referenceDefinitionUnion() } yyVAL.union = yyLOCAL - case 437: + case 438: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL ConstraintInfo -//line sql.y:2595 +//line sql.y:2608 { 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:2601 +//line sql.y:2614 { yyLOCAL = yyDollar[2].matchActionUnion() } yyVAL.union = yyLOCAL - case 439: + case 440: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2607 +//line sql.y:2620 { yyLOCAL = Full } yyVAL.union = yyLOCAL - case 440: + case 441: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2611 +//line sql.y:2624 { yyLOCAL = Partial } yyVAL.union = yyLOCAL - case 441: + case 442: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2615 +//line sql.y:2628 { yyLOCAL = Simple } yyVAL.union = yyLOCAL - case 442: + case 443: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2620 +//line sql.y:2633 { yyLOCAL = DefaultMatch } yyVAL.union = yyLOCAL - case 443: + case 444: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2624 +//line sql.y:2637 { yyLOCAL = yyDollar[1].matchActionUnion() } yyVAL.union = yyLOCAL - case 444: + case 445: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2630 +//line sql.y:2643 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 445: + case 446: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2636 +//line sql.y:2649 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 446: + case 447: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2642 +//line sql.y:2655 { yyLOCAL = Restrict } yyVAL.union = yyLOCAL - case 447: + case 448: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2646 +//line sql.y:2659 { yyLOCAL = Cascade } yyVAL.union = yyLOCAL - case 448: + case 449: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2650 +//line sql.y:2663 { yyLOCAL = NoAction } yyVAL.union = yyLOCAL - case 449: + case 450: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2654 +//line sql.y:2667 { yyLOCAL = SetDefault } yyVAL.union = yyLOCAL - case 450: + case 451: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2658 +//line sql.y:2671 { yyLOCAL = SetNull } yyVAL.union = yyLOCAL - case 451: + case 452: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2663 +//line sql.y:2676 { yyVAL.str = "" } - case 452: + case 453: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2667 +//line sql.y:2680 { yyVAL.str = string(yyDollar[1].str) } - case 453: + case 454: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2671 +//line sql.y:2684 { yyVAL.str = string(yyDollar[1].str) } - case 454: + case 455: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2677 +//line sql.y:2690 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 455: + case 456: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:2681 +//line sql.y:2694 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 456: + case 457: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2686 +//line sql.y:2699 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 457: + case 458: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2690 +//line sql.y:2703 { yyLOCAL = yyDollar[1].booleanUnion() } yyVAL.union = yyLOCAL - case 458: + case 459: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2695 +//line sql.y:2708 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 459: + case 460: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2699 +//line sql.y:2712 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 460: + case 461: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2705 +//line sql.y:2718 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 461: + case 462: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2709 +//line sql.y:2722 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableOptionUnion()) } - case 462: + case 463: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2713 +//line sql.y:2726 { 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:2719 +//line sql.y:2732 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 464: + case 465: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2723 +//line sql.y:2736 { 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:2729 +//line sql.y:2742 { 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:2733 +//line sql.y:2746 { 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:2737 +//line sql.y:2750 { 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:2741 +//line sql.y:2754 { 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:2745 +//line sql.y:2758 { 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:2749 +//line sql.y:2762 { 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:2753 +//line sql.y:2766 { 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:2757 +//line sql.y:2770 { 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:2761 +//line sql.y:2774 { 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:2765 +//line sql.y:2778 { 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:2769 +//line sql.y:2782 { 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:2773 +//line sql.y:2786 { 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:2777 +//line sql.y:2790 { 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:2781 +//line sql.y:2794 { 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:2785 +//line sql.y:2798 { 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:2789 +//line sql.y:2802 { 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:2793 +//line sql.y:2806 { 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:2797 +//line sql.y:2810 { 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:2801 +//line sql.y:2814 { 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:2805 +//line sql.y:2818 { 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:2809 +//line sql.y:2822 { 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:2813 +//line sql.y:2826 { 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:2817 +//line sql.y:2830 { 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:2821 +//line sql.y:2834 { 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:2825 +//line sql.y:2838 { 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:2829 +//line sql.y:2842 { 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:2833 +//line sql.y:2846 { 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:2837 +//line sql.y:2850 { 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:2841 +//line sql.y:2854 { 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:2845 +//line sql.y:2858 { 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:2849 +//line sql.y:2862 { 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:2854 +//line sql.y:2867 { yyVAL.str = "" } - case 497: + case 498: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2858 +//line sql.y:2871 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 498: + case 499: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2862 +//line sql.y:2875 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 508: + case 509: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2881 +//line sql.y:2894 { 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:2885 +//line sql.y:2898 { yyVAL.str = yyDollar[1].identifierCI.String() } - case 510: + case 511: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2889 +//line sql.y:2902 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 511: + case 512: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2893 +//line sql.y:2906 { yyVAL.str = string(yyDollar[1].str) } - case 512: + case 513: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2898 +//line sql.y:2911 { yyVAL.str = "" } - case 514: + case 515: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2904 +//line sql.y:2917 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 515: + case 516: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2908 +//line sql.y:2921 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 516: + case 517: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColName -//line sql.y:2913 +//line sql.y:2926 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 517: + case 518: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColName -//line sql.y:2917 +//line sql.y:2930 { yyLOCAL = yyDollar[2].colNameUnion() } yyVAL.union = yyLOCAL - case 518: + case 519: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2922 +//line sql.y:2935 { yyVAL.str = "" } - case 519: + case 520: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2926 +//line sql.y:2939 { yyVAL.str = string(yyDollar[2].str) } - case 520: + case 521: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Literal -//line sql.y:2931 +//line sql.y:2944 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 521: + case 522: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:2935 +//line sql.y:2948 { yyLOCAL = NewIntLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 522: + case 523: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:2939 +//line sql.y:2952 { yyLOCAL = NewDecimalLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 523: + case 524: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2944 +//line sql.y:2957 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 524: + case 525: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2948 +//line sql.y:2961 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 525: + case 526: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2952 +//line sql.y:2965 { 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:2956 +//line sql.y:2969 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 527: + case 528: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2960 +//line sql.y:2973 { 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:2964 +//line sql.y:2977 { 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:2970 +//line sql.y:2983 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 530: + case 531: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2974 +//line sql.y:2987 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 531: + case 532: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2978 +//line sql.y:2991 { 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:2984 +//line sql.y:2997 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 533: + case 534: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2988 +//line sql.y:3001 { 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:2992 +//line sql.y:3005 { 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:2996 +//line sql.y:3009 { 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:3000 +//line sql.y:3013 { 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:3004 +//line sql.y:3017 { 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:3008 +//line sql.y:3021 { 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:3012 +//line sql.y:3025 { 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:3016 +//line sql.y:3029 { 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:3020 +//line sql.y:3033 { 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:3024 +//line sql.y:3037 { 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:3028 +//line sql.y:3041 { 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:3032 +//line sql.y:3045 { 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:3036 +//line sql.y:3049 { 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:3040 +//line sql.y:3053 { 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:3044 +//line sql.y:3057 { 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:3048 +//line sql.y:3061 { 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:3052 +//line sql.y:3065 { 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:3056 +//line sql.y:3069 { yyLOCAL = &KeyState{Enable: false} } yyVAL.union = yyLOCAL - case 551: + case 552: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3060 +//line sql.y:3073 { yyLOCAL = &KeyState{Enable: true} } yyVAL.union = yyLOCAL - case 552: + case 553: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3064 +//line sql.y:3077 { yyLOCAL = &TablespaceOperation{Import: false} } yyVAL.union = yyLOCAL - case 553: + case 554: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3068 +//line sql.y:3081 { yyLOCAL = &TablespaceOperation{Import: true} } yyVAL.union = yyLOCAL - case 554: + case 555: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3072 +//line sql.y:3085 { 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:3076 +//line sql.y:3089 { 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:3080 +//line sql.y:3093 { yyLOCAL = &DropKey{Type: PrimaryKeyType} } yyVAL.union = yyLOCAL - case 557: + case 558: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3084 +//line sql.y:3097 { 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:3088 +//line sql.y:3101 { 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:3092 +//line sql.y:3105 { 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:3096 +//line sql.y:3109 { yyLOCAL = &Force{} } yyVAL.union = yyLOCAL - case 561: + case 562: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3100 +//line sql.y:3113 { 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:3104 +//line sql.y:3117 { 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:3110 +//line sql.y:3123 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 564: + case 565: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3114 +//line sql.y:3127 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 565: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL AlterOption -//line sql.y:3120 - { - yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) - } - yyVAL.union = yyLOCAL case 566: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3124 +//line sql.y:3133 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } @@ -14153,7 +14300,7 @@ yydefault: case 567: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3128 +//line sql.y:3137 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } @@ -14161,7 +14308,7 @@ yydefault: case 568: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3132 +//line sql.y:3141 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } @@ -14169,55 +14316,63 @@ yydefault: case 569: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3136 +//line sql.y:3145 { - yyLOCAL = &LockOption{Type: DefaultType} + yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL case 570: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3140 +//line sql.y:3149 { - yyLOCAL = &LockOption{Type: NoneType} + yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL case 571: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3144 +//line sql.y:3153 { - yyLOCAL = &LockOption{Type: SharedType} + yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL case 572: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3148 +//line sql.y:3157 { - yyLOCAL = &LockOption{Type: ExclusiveType} + yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL case 573: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL AlterOption +//line sql.y:3161 + { + yyLOCAL = &LockOption{Type: ExclusiveType} + } + yyVAL.union = yyLOCAL + case 574: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3152 +//line sql.y:3165 { yyLOCAL = &Validation{With: true} } yyVAL.union = yyLOCAL - case 574: + case 575: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3156 +//line sql.y:3169 { yyLOCAL = &Validation{With: false} } yyVAL.union = yyLOCAL - case 575: + case 576: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3162 +//line sql.y:3175 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14225,10 +14380,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:3169 +//line sql.y:3182 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14236,10 +14391,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:3176 +//line sql.y:3189 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14247,28 +14402,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:3183 +//line sql.y:3196 { 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:3189 +//line sql.y:3202 { 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:3199 +//line sql.y:3212 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -14276,10 +14431,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:3206 +//line sql.y:3219 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -14287,10 +14442,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:3213 +//line sql.y:3226 { yyLOCAL = &AlterVschema{ Action: CreateVindexDDLAction, @@ -14303,10 +14458,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 583: + case 584: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3225 +//line sql.y:3238 { yyLOCAL = &AlterVschema{ Action: DropVindexDDLAction, @@ -14317,26 +14472,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 584: + case 585: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3235 +//line sql.y:3248 { 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:3239 +//line sql.y:3252 { 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:3243 +//line sql.y:3256 { yyLOCAL = &AlterVschema{ Action: AddColVindexDDLAction, @@ -14350,10 +14505,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 587: + case 588: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:3256 +//line sql.y:3269 { yyLOCAL = &AlterVschema{ Action: DropColVindexDDLAction, @@ -14364,26 +14519,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 588: + case 589: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3266 +//line sql.y:3279 { 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:3270 +//line sql.y:3283 { 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:3274 +//line sql.y:3287 { yyLOCAL = &AlterVschema{ Action: AddAutoIncDDLAction, @@ -14395,10 +14550,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 591: + case 592: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3285 +//line sql.y:3298 { yyLOCAL = &AlterVschema{ Action: DropAutoIncDDLAction, @@ -14406,10 +14561,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 592: + case 593: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3292 +//line sql.y:3305 { yyLOCAL = &AlterMigration{ Type: RetryMigrationType, @@ -14417,10 +14572,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 593: + case 594: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3299 +//line sql.y:3312 { yyLOCAL = &AlterMigration{ Type: CleanupMigrationType, @@ -14428,10 +14583,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 594: + case 595: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:3319 + { + yyLOCAL = &AlterMigration{ + Type: CleanupAllMigrationType, + } + } + yyVAL.union = yyLOCAL + case 596: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3306 +//line sql.y:3325 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -14439,10 +14604,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 595: + case 597: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3313 +//line sql.y:3332 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -14451,20 +14616,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 596: + case 598: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3321 +//line sql.y:3340 { yyLOCAL = &AlterMigration{ Type: LaunchAllMigrationType, } } yyVAL.union = yyLOCAL - case 597: + case 599: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3327 +//line sql.y:3346 { yyLOCAL = &AlterMigration{ Type: CompleteMigrationType, @@ -14472,20 +14637,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 598: + case 600: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3334 +//line sql.y:3353 { yyLOCAL = &AlterMigration{ Type: CompleteAllMigrationType, } } yyVAL.union = yyLOCAL - case 599: + case 601: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3340 +//line sql.y:3359 { yyLOCAL = &AlterMigration{ Type: CancelMigrationType, @@ -14493,20 +14658,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 600: + case 602: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3347 +//line sql.y:3366 { yyLOCAL = &AlterMigration{ Type: CancelAllMigrationType, } } yyVAL.union = yyLOCAL - case 601: + case 603: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3353 +//line sql.y:3372 { yyLOCAL = &AlterMigration{ Type: ThrottleMigrationType, @@ -14516,10 +14681,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 602: + case 604: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3362 +//line sql.y:3381 { yyLOCAL = &AlterMigration{ Type: ThrottleAllMigrationType, @@ -14528,10 +14693,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 603: + case 605: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3370 +//line sql.y:3389 { yyLOCAL = &AlterMigration{ Type: UnthrottleMigrationType, @@ -14539,20 +14704,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 604: + case 606: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3377 +//line sql.y:3396 { yyLOCAL = &AlterMigration{ Type: UnthrottleAllMigrationType, } } yyVAL.union = yyLOCAL - case 605: + case 607: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3383 +//line sql.y:3402 { yyLOCAL = &AlterMigration{ Type: ForceCutOverMigrationType, @@ -14560,28 +14725,28 @@ yydefault: } } yyVAL.union = yyLOCAL - case 606: + case 608: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3390 +//line sql.y:3409 { yyLOCAL = &AlterMigration{ Type: ForceCutOverAllMigrationType, } } yyVAL.union = yyLOCAL - case 607: + case 609: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3397 +//line sql.y:3416 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 608: + case 610: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3401 +//line sql.y:3420 { yyDollar[3].partitionOptionUnion().Partitions = yyDollar[4].integerUnion() yyDollar[3].partitionOptionUnion().SubPartition = yyDollar[5].subPartitionUnion() @@ -14589,10 +14754,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:3410 +//line sql.y:3429 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -14601,10 +14766,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 610: + case 612: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3418 +//line sql.y:3437 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -14614,10 +14779,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 611: + case 613: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3427 +//line sql.y:3446 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -14625,10 +14790,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 612: + case 614: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3434 +//line sql.y:3453 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -14636,18 +14801,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 613: + case 615: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3442 +//line sql.y:3461 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 614: + case 616: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3446 +//line sql.y:3465 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -14657,10 +14822,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 615: + case 617: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3455 +//line sql.y:3474 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -14671,678 +14836,678 @@ yydefault: } } yyVAL.union = yyLOCAL - case 616: + case 618: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3466 +//line sql.y:3485 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 617: + case 619: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3470 +//line sql.y:3489 { yyLOCAL = yyDollar[2].partDefsUnion() } yyVAL.union = yyLOCAL - case 618: + case 620: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3475 +//line sql.y:3494 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 619: + case 621: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3479 +//line sql.y:3498 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 620: + case 622: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3484 +//line sql.y:3503 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 621: + case 623: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3488 +//line sql.y:3507 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 622: + case 624: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL TableExpr -//line sql.y:3494 +//line sql.y:3513 { 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:3500 +//line sql.y:3519 { yyLOCAL = yyDollar[3].jtColumnListUnion() } yyVAL.union = yyLOCAL - case 624: + case 626: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JtColumnDefinition -//line sql.y:3506 +//line sql.y:3525 { yyLOCAL = []*JtColumnDefinition{yyDollar[1].jtColumnDefinitionUnion()} } yyVAL.union = yyLOCAL - case 625: + case 627: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3510 +//line sql.y:3529 { 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:3516 +//line sql.y:3535 { 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:3520 +//line sql.y:3539 { 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:3526 +//line sql.y:3545 { 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:3532 +//line sql.y:3551 { 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:3538 +//line sql.y:3557 { 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:3544 +//line sql.y:3563 { 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:3550 +//line sql.y:3569 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 633: + case 635: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3554 +//line sql.y:3573 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 634: + case 636: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3558 +//line sql.y:3577 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 635: + case 637: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3562 +//line sql.y:3581 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 636: + case 638: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3568 +//line sql.y:3587 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 637: + case 639: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3574 +//line sql.y:3593 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 638: + case 640: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3580 +//line sql.y:3599 { yyLOCAL = &JtOnResponse{ResponseType: ErrorJSONType} } yyVAL.union = yyLOCAL - case 639: + case 641: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3584 +//line sql.y:3603 { yyLOCAL = &JtOnResponse{ResponseType: NullJSONType} } yyVAL.union = yyLOCAL - case 640: + case 642: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3588 +//line sql.y:3607 { 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:3594 +//line sql.y:3613 { yyLOCAL = RangeType } yyVAL.union = yyLOCAL - case 642: + case 644: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL PartitionByType -//line sql.y:3598 +//line sql.y:3617 { yyLOCAL = ListType } yyVAL.union = yyLOCAL - case 643: + case 645: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3603 +//line sql.y:3622 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 644: + case 646: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:3607 +//line sql.y:3626 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 645: + case 647: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3612 +//line sql.y:3631 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 646: + case 648: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:3616 +//line sql.y:3635 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 647: + case 649: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3622 +//line sql.y:3641 { 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:3626 +//line sql.y:3645 { 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:3630 +//line sql.y:3649 { 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:3634 +//line sql.y:3653 { 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:3638 +//line sql.y:3657 { 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:3642 +//line sql.y:3661 { 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:3646 +//line sql.y:3665 { 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:3650 +//line sql.y:3669 { 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:3654 +//line sql.y:3673 { 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:3658 +//line sql.y:3677 { 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:3662 +//line sql.y:3681 { 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:3666 +//line sql.y:3685 { 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:3670 +//line sql.y:3689 { 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:3674 +//line sql.y:3693 { 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:3678 +//line sql.y:3697 { 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:3682 +//line sql.y:3701 { 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:3686 +//line sql.y:3705 { 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:3690 +//line sql.y:3709 { 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:3694 +//line sql.y:3713 { 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:3698 +//line sql.y:3717 { 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:3702 +//line sql.y:3721 { 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:3706 +//line sql.y:3725 { yyLOCAL = &PartitionSpec{Action: UpgradeAction} } yyVAL.union = yyLOCAL - case 669: + case 671: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3711 +//line sql.y:3730 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 670: + case 672: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:3715 +//line sql.y:3734 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 671: + case 673: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:3719 +//line sql.y:3738 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 672: + case 674: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3725 +//line sql.y:3744 { yyLOCAL = []*PartitionDefinition{yyDollar[1].partDefUnion()} } yyVAL.union = yyLOCAL - case 673: + case 675: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3729 +//line sql.y:3748 { yySLICE := (*[]*PartitionDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].partDefUnion()) } - case 674: + case 676: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3735 +//line sql.y:3754 { yyVAL.partDefUnion().Options = yyDollar[2].partitionDefinitionOptionsUnion() } - case 675: + case 677: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3740 +//line sql.y:3759 { yyLOCAL = &PartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 676: + case 678: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3744 +//line sql.y:3763 { 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:3749 +//line sql.y:3768 { 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:3754 +//line sql.y:3773 { 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:3759 +//line sql.y:3778 { 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:3764 +//line sql.y:3783 { 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:3769 +//line sql.y:3788 { 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:3774 +//line sql.y:3793 { 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:3779 +//line sql.y:3798 { 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:3784 +//line sql.y:3803 { 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:3790 +//line sql.y:3809 { yyLOCAL = yyDollar[2].subPartitionDefinitionsUnion() } yyVAL.union = yyLOCAL - case 686: + case 688: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SubPartitionDefinitions -//line sql.y:3796 +//line sql.y:3815 { yyLOCAL = SubPartitionDefinitions{yyDollar[1].subPartitionDefinitionUnion()} } yyVAL.union = yyLOCAL - case 687: + case 689: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3800 +//line sql.y:3819 { 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:3806 +//line sql.y:3825 { 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:3811 +//line sql.y:3830 { yyLOCAL = &SubPartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 690: + case 692: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3815 +//line sql.y:3834 { 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:3820 +//line sql.y:3839 { 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:3825 +//line sql.y:3844 { 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:3830 +//line sql.y:3849 { 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:3835 +//line sql.y:3854 { 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:3840 +//line sql.y:3859 { 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:3845 +//line sql.y:3864 { 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:3852 +//line sql.y:3871 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -15350,10 +15515,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 698: + case 700: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:3859 +//line sql.y:3878 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -15361,10 +15526,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 699: + case 701: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:3866 +//line sql.y:3885 { yyLOCAL = &PartitionValueRange{ Type: InType, @@ -15372,131 +15537,131 @@ yydefault: } } yyVAL.union = yyLOCAL - case 700: + case 702: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3874 +//line sql.y:3893 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 701: + case 703: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3878 +//line sql.y:3897 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 702: + case 704: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionEngine -//line sql.y:3884 +//line sql.y:3903 { 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:3890 +//line sql.y:3909 { yyLOCAL = NewStrLiteral(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 704: + case 706: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:3896 +//line sql.y:3915 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 705: + case 707: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:3902 +//line sql.y:3921 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 706: + case 708: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3908 +//line sql.y:3927 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 707: + case 709: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3914 +//line sql.y:3933 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 708: + case 710: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3920 +//line sql.y:3939 { yyVAL.str = yyDollar[3].identifierCS.String() } - case 709: + case 711: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinition -//line sql.y:3926 +//line sql.y:3945 { yyLOCAL = &PartitionDefinition{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 710: + case 712: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3932 +//line sql.y:3951 { yyVAL.str = "" } - case 711: + case 713: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3936 +//line sql.y:3955 { yyVAL.str = "" } - case 712: + case 714: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3942 +//line sql.y:3961 { 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:3948 +//line sql.y:3967 { 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:3952 +//line sql.y:3971 { 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:3958 +//line sql.y:3977 { 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:3962 +//line sql.y:3981 { // Change this to an alter statement if yyDollar[4].identifierCI.Lowered() == "primary" { @@ -15506,1327 +15671,1361 @@ yydefault: } } yyVAL.union = yyLOCAL - case 717: + case 719: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3971 +//line sql.y:3990 { 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:3975 +//line sql.y:3994 { 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:3981 +//line sql.y:4000 { 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:3985 +//line sql.y:4004 { 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:3991 +//line sql.y:4010 { 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:3997 +//line sql.y:4016 { 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:4001 +//line sql.y:4020 { 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:4007 +//line sql.y:4026 { 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:4011 +//line sql.y:4030 { 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:4015 +//line sql.y:4034 { 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:4019 +//line sql.y:4038 { 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:4023 +//line sql.y:4042 { 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:4027 +//line sql.y:4046 { 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:4031 +//line sql.y:4050 { 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:4035 +//line sql.y:4054 { 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:4039 +//line sql.y:4058 { 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:4043 +//line sql.y:4062 { 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:4047 +//line sql.y:4066 { yyLOCAL = &Show{&ShowBasic{Command: Privilege}} } yyVAL.union = yyLOCAL - case 735: + case 737: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4051 +//line sql.y:4070 { 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:4055 +//line sql.y:4074 { 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:4059 +//line sql.y:4078 { 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:4063 +//line sql.y:4082 { 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:4067 +//line sql.y:4086 { 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:4071 +//line sql.y:4090 { 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:4075 +//line sql.y:4094 { 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:4079 +//line sql.y:4098 { 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:4083 +//line sql.y:4102 { 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:4087 +//line sql.y:4106 { 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:4091 +//line sql.y:4110 { 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:4095 +//line sql.y:4114 { 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:4099 +//line sql.y:4118 { 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:4103 +//line sql.y:4122 { 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:4107 +//line sql.y:4126 { 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:4111 +//line sql.y:4130 { yyLOCAL = &Show{&ShowBasic{Command: Engines}} } yyVAL.union = yyLOCAL - case 751: + case 753: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4115 +//line sql.y:4134 { yyLOCAL = &Show{&ShowBasic{Command: Plugins}} } yyVAL.union = yyLOCAL - case 752: + case 754: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4119 +//line sql.y:4138 { 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:4123 +//line sql.y:4142 { 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:4127 +//line sql.y:4146 { 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:4131 +//line sql.y:4150 { 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:4135 +//line sql.y:4154 { 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:4139 +//line sql.y:4158 { yyLOCAL = &ShowThrottledApps{} } yyVAL.union = yyLOCAL - case 758: + case 760: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4143 +//line sql.y:4162 { 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:4147 +//line sql.y:4166 { yyLOCAL = &ShowThrottlerStatus{} } yyVAL.union = yyLOCAL - case 760: + case 762: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4151 +//line sql.y:4170 { yyLOCAL = &Show{&ShowBasic{Command: VschemaTables}} } yyVAL.union = yyLOCAL - case 761: + case 763: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4155 +//line sql.y:4174 { yyLOCAL = &Show{&ShowBasic{Command: VschemaKeyspaces}} } yyVAL.union = yyLOCAL - case 762: + case 764: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4159 +//line sql.y:4178 { yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes}} } yyVAL.union = yyLOCAL - case 763: + case 765: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4163 +//line sql.y:4182 { 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:4167 +//line sql.y:4186 { yyLOCAL = &Show{&ShowBasic{Command: Warnings}} } yyVAL.union = yyLOCAL - case 765: + case 767: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4171 +//line sql.y:4190 { 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:4175 +//line sql.y:4194 { 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:4179 +//line sql.y:4198 { yyLOCAL = &Show{&ShowBasic{Command: VitessTarget}} } yyVAL.union = yyLOCAL - case 768: + case 770: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4186 +//line sql.y:4205 { 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:4190 +//line sql.y:4209 { 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:4194 +//line sql.y:4213 { 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:4198 +//line sql.y:4217 { 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:4202 +//line sql.y:4221 { 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:4206 +//line sql.y:4225 { 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:4210 +//line sql.y:4229 { 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:4214 +//line sql.y:4233 { 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:4218 +//line sql.y:4237 { 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:4241 + { + yyLOCAL = &Show{&ShowTransactionStatus{TransactionID: string(yyDollar[5].str)}} + } + yyVAL.union = yyLOCAL + case 780: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL Statement +//line sql.y:4245 + { + yyLOCAL = &Show{&ShowTransactionStatus{}} + } + yyVAL.union = yyLOCAL + case 781: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:4249 + { + yyLOCAL = &Show{&ShowTransactionStatus{Keyspace: yyDollar[5].identifierCS.String()}} + } + yyVAL.union = yyLOCAL + case 782: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:4254 + { + } + case 783: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4256 + { + } + case 784: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4224 +//line sql.y:4260 { yyVAL.str = "" } - case 778: + case 785: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4228 +//line sql.y:4264 { yyVAL.str = "extended " } - case 779: + case 786: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4234 +//line sql.y:4270 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 780: + case 787: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4238 +//line sql.y:4274 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 781: + case 788: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4244 +//line sql.y:4280 { yyVAL.str = string(yyDollar[1].str) } - case 782: + case 789: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4248 +//line sql.y:4284 { yyVAL.str = string(yyDollar[1].str) } - case 783: + case 790: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4254 +//line sql.y:4290 { yyVAL.identifierCS = NewIdentifierCS("") } - case 784: + case 791: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4258 +//line sql.y:4294 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 785: + case 792: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4262 +//line sql.y:4298 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 786: + case 793: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4268 +//line sql.y:4304 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 787: + case 794: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4272 +//line sql.y:4308 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 788: + case 795: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4276 +//line sql.y:4312 { yyLOCAL = &ShowFilter{Filter: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 789: + case 796: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4282 +//line sql.y:4318 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 790: + case 797: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4286 +//line sql.y:4322 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 791: + case 798: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4292 +//line sql.y:4328 { yyVAL.empty = struct{}{} } - case 792: + case 799: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4296 +//line sql.y:4332 { yyVAL.empty = struct{}{} } - case 793: + case 800: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4300 +//line sql.y:4336 { yyVAL.empty = struct{}{} } - case 794: + case 801: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4306 +//line sql.y:4342 { yyVAL.str = string(yyDollar[1].str) } - case 795: + case 802: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4310 +//line sql.y:4346 { yyVAL.str = string(yyDollar[1].str) } - case 796: + case 803: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4316 +//line sql.y:4352 { yyLOCAL = &Use{DBName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 797: + case 804: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4320 +//line sql.y:4356 { yyLOCAL = &Use{DBName: IdentifierCS{v: ""}} } yyVAL.union = yyLOCAL - case 798: + case 805: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4324 +//line sql.y:4360 { yyLOCAL = &Use{DBName: NewIdentifierCS(yyDollar[2].identifierCS.String() + "@" + string(yyDollar[3].str))} } yyVAL.union = yyLOCAL - case 799: + case 806: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4331 +//line sql.y:4367 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 800: + case 807: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4335 +//line sql.y:4371 { yyVAL.identifierCS = NewIdentifierCS("@" + string(yyDollar[1].str)) } - case 801: + case 808: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4339 +//line sql.y:4375 { yyVAL.identifierCS = NewIdentifierCS("@@" + string(yyDollar[1].str)) } - case 802: + case 809: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4343 +//line sql.y:4379 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 803: + case 810: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4350 +//line sql.y:4386 { yyLOCAL = &Begin{} } yyVAL.union = yyLOCAL - case 804: + case 811: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4354 +//line sql.y:4390 { yyLOCAL = &Begin{TxAccessModes: yyDollar[3].txAccessModesUnion()} } yyVAL.union = yyLOCAL - case 805: + case 812: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4359 +//line sql.y:4395 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 806: + case 813: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4363 +//line sql.y:4399 { yyLOCAL = yyDollar[1].txAccessModesUnion() } yyVAL.union = yyLOCAL - case 807: + case 814: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4369 +//line sql.y:4405 { yyLOCAL = []TxAccessMode{yyDollar[1].txAccessModeUnion()} } yyVAL.union = yyLOCAL - case 808: + case 815: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4373 +//line sql.y:4409 { yySLICE := (*[]TxAccessMode)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].txAccessModeUnion()) } - case 809: + case 816: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4379 +//line sql.y:4415 { yyLOCAL = WithConsistentSnapshot } yyVAL.union = yyLOCAL - case 810: + case 817: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4383 +//line sql.y:4419 { yyLOCAL = ReadWrite } yyVAL.union = yyLOCAL - case 811: + case 818: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4387 +//line sql.y:4423 { yyLOCAL = ReadOnly } yyVAL.union = yyLOCAL - case 812: + case 819: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4394 +//line sql.y:4430 { yyLOCAL = &Commit{} } yyVAL.union = yyLOCAL - case 813: + case 820: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4400 +//line sql.y:4436 { yyLOCAL = &Rollback{} } yyVAL.union = yyLOCAL - case 814: + case 821: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4404 +//line sql.y:4440 { yyLOCAL = &SRollback{Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 815: + case 822: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4409 +//line sql.y:4445 { yyVAL.empty = struct{}{} } - case 816: + case 823: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4411 +//line sql.y:4447 { yyVAL.empty = struct{}{} } - case 817: + case 824: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4414 +//line sql.y:4450 { yyVAL.empty = struct{}{} } - case 818: + case 825: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4416 +//line sql.y:4452 { yyVAL.empty = struct{}{} } - case 819: + case 826: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4420 +//line sql.y:4456 { yyLOCAL = &Savepoint{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 820: + case 827: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4426 +//line sql.y:4462 { yyLOCAL = &Release{Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 821: + case 828: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4431 +//line sql.y:4467 { yyLOCAL = EmptyType } yyVAL.union = yyLOCAL - case 822: + case 829: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4435 +//line sql.y:4471 { yyLOCAL = JSONType } yyVAL.union = yyLOCAL - case 823: + case 830: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4439 +//line sql.y:4475 { yyLOCAL = TreeType } yyVAL.union = yyLOCAL - case 824: + case 831: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4443 +//line sql.y:4479 { yyLOCAL = TraditionalType } yyVAL.union = yyLOCAL - case 825: + case 832: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4447 +//line sql.y:4483 { yyLOCAL = AnalyzeType } yyVAL.union = yyLOCAL - case 826: + case 833: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4452 +//line sql.y:4488 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 827: + case 834: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4456 +//line sql.y:4492 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 828: + case 835: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4460 +//line sql.y:4496 { yyLOCAL = AllVExplainType } yyVAL.union = yyLOCAL - case 829: + case 836: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4464 +//line sql.y:4500 { yyLOCAL = QueriesVExplainType } yyVAL.union = yyLOCAL - case 830: + case 837: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4470 +//line sql.y:4506 { yyVAL.str = yyDollar[1].str } - case 831: + case 838: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4474 +//line sql.y:4510 { yyVAL.str = yyDollar[1].str } - case 832: + case 839: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4478 +//line sql.y:4514 { yyVAL.str = yyDollar[1].str } - case 833: + case 840: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4484 +//line sql.y:4520 { yyLOCAL = yyDollar[1].selStmtUnion() } yyVAL.union = yyLOCAL - case 834: + case 841: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4488 +//line sql.y:4524 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 835: + case 842: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4492 +//line sql.y:4528 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 836: + case 843: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4496 +//line sql.y:4532 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 837: + case 844: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4501 +//line sql.y:4537 { yyVAL.str = "" } - case 838: + case 845: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4505 +//line sql.y:4541 { yyVAL.str = yyDollar[1].identifierCI.val } - case 839: + case 846: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4509 +//line sql.y:4545 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 840: + case 847: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4515 +//line sql.y:4551 { yyLOCAL = &ExplainTab{Table: yyDollar[3].tableName, Wild: yyDollar[4].str} } yyVAL.union = yyLOCAL - case 841: + case 848: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4519 +//line sql.y:4555 { yyLOCAL = &ExplainStmt{Type: yyDollar[3].explainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 842: + case 849: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4525 +//line sql.y:4561 { yyLOCAL = &VExplainStmt{Type: yyDollar[3].vexplainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 843: + case 850: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4531 +//line sql.y:4567 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 844: + case 851: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4535 +//line sql.y:4571 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 845: + case 852: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4541 +//line sql.y:4577 { yyLOCAL = &LockTables{Tables: yyDollar[3].tableAndLockTypesUnion()} } yyVAL.union = yyLOCAL - case 846: + case 853: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableAndLockTypes -//line sql.y:4547 +//line sql.y:4583 { yyLOCAL = TableAndLockTypes{yyDollar[1].tableAndLockTypeUnion()} } yyVAL.union = yyLOCAL - case 847: + case 854: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4551 +//line sql.y:4587 { yySLICE := (*TableAndLockTypes)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableAndLockTypeUnion()) } - case 848: + case 855: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *TableAndLockType -//line sql.y:4557 +//line sql.y:4593 { yyLOCAL = &TableAndLockType{Table: yyDollar[1].aliasedTableNameUnion(), Lock: yyDollar[2].lockTypeUnion()} } yyVAL.union = yyLOCAL - case 849: + case 856: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4563 +//line sql.y:4599 { yyLOCAL = Read } yyVAL.union = yyLOCAL - case 850: + case 857: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:4567 +//line sql.y:4603 { yyLOCAL = ReadLocal } yyVAL.union = yyLOCAL - case 851: + case 858: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4571 +//line sql.y:4607 { yyLOCAL = Write } yyVAL.union = yyLOCAL - case 852: + case 859: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:4575 +//line sql.y:4611 { yyLOCAL = LowPriorityWrite } yyVAL.union = yyLOCAL - case 853: + case 860: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4581 +//line sql.y:4617 { yyLOCAL = &UnlockTables{} } yyVAL.union = yyLOCAL - case 854: + case 861: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4587 +//line sql.y:4623 { yyLOCAL = &RevertMigration{Comments: Comments(yyDollar[2].strs).Parsed(), UUID: string(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 855: + case 862: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4593 +//line sql.y:4629 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), FlushOptions: yyDollar[3].strs} } yyVAL.union = yyLOCAL - case 856: + case 863: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4597 +//line sql.y:4633 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion()} } yyVAL.union = yyLOCAL - case 857: + case 864: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:4601 +//line sql.y:4637 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 858: + case 865: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4605 +//line sql.y:4641 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion()} } yyVAL.union = yyLOCAL - case 859: + case 866: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4609 +//line sql.y:4645 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 860: + case 867: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:4613 +//line sql.y:4649 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), ForExport: true} } yyVAL.union = yyLOCAL - case 861: + case 868: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4619 +//line sql.y:4655 { yyVAL.strs = []string{yyDollar[1].str} } - case 862: + case 869: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4623 +//line sql.y:4659 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[3].str) } - case 863: + case 870: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4629 +//line sql.y:4665 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 864: + case 871: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4633 +//line sql.y:4669 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 865: + case 872: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4637 +//line sql.y:4673 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 866: + case 873: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4641 +//line sql.y:4677 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 867: + case 874: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4645 +//line sql.y:4681 { yyVAL.str = string(yyDollar[1].str) } - case 868: + case 875: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4649 +//line sql.y:4685 { yyVAL.str = string(yyDollar[1].str) } - case 869: + case 876: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4653 +//line sql.y:4689 { yyVAL.str = string(yyDollar[1].str) } - case 870: + case 877: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4657 +//line sql.y:4693 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) + yyDollar[3].str } - case 871: + case 878: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4661 +//line sql.y:4697 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 872: + case 879: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4665 +//line sql.y:4701 { yyVAL.str = string(yyDollar[1].str) } - case 873: + case 880: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4669 +//line sql.y:4705 { yyVAL.str = string(yyDollar[1].str) } - case 874: + case 881: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4673 +//line sql.y:4709 { yyVAL.str = string(yyDollar[1].str) } - case 875: + case 882: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4678 +//line sql.y:4714 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 876: + case 883: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4682 +//line sql.y:4718 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 877: + case 884: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4686 +//line sql.y:4722 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 878: + case 885: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4691 +//line sql.y:4727 { yyVAL.str = "" } - case 879: + case 886: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4695 +//line sql.y:4731 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String() } - case 880: + case 887: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4700 +//line sql.y:4736 { setAllowComments(yylex, true) } - case 881: + case 888: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4704 +//line sql.y:4740 { yyVAL.strs = yyDollar[2].strs setAllowComments(yylex, false) } - case 882: + case 889: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4710 +//line sql.y:4746 { yyVAL.strs = nil } - case 883: + case 890: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4714 +//line sql.y:4750 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 884: + case 891: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4720 +//line sql.y:4756 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 885: + case 892: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4724 +//line sql.y:4760 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 886: + case 893: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4728 +//line sql.y:4764 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 887: + case 894: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4733 +//line sql.y:4769 { yyVAL.str = "" } - case 888: + case 895: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4737 +//line sql.y:4773 { yyVAL.str = SQLNoCacheStr } - case 889: + case 896: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4741 +//line sql.y:4777 { yyVAL.str = SQLCacheStr } - case 890: + case 897: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4746 +//line sql.y:4782 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 891: + case 898: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4750 +//line sql.y:4786 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 892: + case 899: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4754 +//line sql.y:4790 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 893: + case 900: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4760 +//line sql.y:4796 { yyLOCAL = &PrepareStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Statement: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 894: + case 901: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4764 +//line sql.y:4800 { yyLOCAL = &PrepareStmt{ Name: yyDollar[3].identifierCI, @@ -16835,573 +17034,597 @@ yydefault: } } yyVAL.union = yyLOCAL - case 895: + case 902: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4774 +//line sql.y:4810 { yyLOCAL = &ExecuteStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Arguments: yyDollar[4].variablesUnion()} } yyVAL.union = yyLOCAL - case 896: + case 903: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4779 +//line sql.y:4815 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 897: + case 904: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4783 +//line sql.y:4819 { yyLOCAL = yyDollar[2].variablesUnion() } yyVAL.union = yyLOCAL - case 898: + case 905: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4789 +//line sql.y:4825 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 899: + case 906: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4793 +//line sql.y:4829 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 900: + case 907: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4798 +//line sql.y:4834 { yyVAL.strs = nil } - case 901: + case 908: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4802 +//line sql.y:4838 { yyVAL.strs = yyDollar[1].strs } - case 902: + case 909: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4808 +//line sql.y:4844 { yyVAL.strs = []string{yyDollar[1].str} } - case 903: + case 910: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4812 +//line sql.y:4848 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 904: + case 911: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4818 +//line sql.y:4854 { yyVAL.str = SQLNoCacheStr } - case 905: + case 912: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4822 +//line sql.y:4858 { yyVAL.str = SQLCacheStr } - case 906: + case 913: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4826 +//line sql.y:4862 { yyVAL.str = DistinctStr } - case 907: + case 914: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4830 +//line sql.y:4866 { yyVAL.str = DistinctStr } - case 908: + case 915: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4834 +//line sql.y:4870 + { + yyVAL.str = HighPriorityStr + } + case 916: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4874 { yyVAL.str = StraightJoinHint } - case 909: + case 917: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4838 +//line sql.y:4878 + { + yyVAL.str = SQLBufferResultStr + } + case 918: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4882 + { + yyVAL.str = SQLSmallResultStr + } + case 919: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4886 + { + yyVAL.str = SQLBigResultStr + } + case 920: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4890 { yyVAL.str = SQLCalcFoundRowsStr } - case 910: + case 921: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4842 +//line sql.y:4894 { 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 922: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectExprs -//line sql.y:4848 +//line sql.y:4900 { yyLOCAL = SelectExprs{yyDollar[1].selectExprUnion()} } yyVAL.union = yyLOCAL - case 912: + case 923: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4852 +//line sql.y:4904 { yySLICE := (*SelectExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].selectExprUnion()) } - case 913: + case 924: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4858 +//line sql.y:4910 { yyLOCAL = &StarExpr{} } yyVAL.union = yyLOCAL - case 914: + case 925: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4862 +//line sql.y:4914 { yyLOCAL = &AliasedExpr{Expr: yyDollar[1].exprUnion(), As: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 915: + case 926: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4866 +//line sql.y:4918 { yyLOCAL = &StarExpr{TableName: TableName{Name: yyDollar[1].identifierCS}} } yyVAL.union = yyLOCAL - case 916: + case 927: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4870 +//line sql.y:4922 { yyLOCAL = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}} } yyVAL.union = yyLOCAL - case 917: + case 928: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4875 +//line sql.y:4927 { yyVAL.identifierCI = IdentifierCI{} } - case 918: + case 929: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4879 +//line sql.y:4931 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 919: + case 930: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4883 +//line sql.y:4935 { yyVAL.identifierCI = yyDollar[2].identifierCI } - case 921: + case 932: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4890 +//line sql.y:4942 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 922: + case 933: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4895 +//line sql.y:4947 { yyLOCAL = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewIdentifierCS("dual")}}} } yyVAL.union = yyLOCAL - case 923: + case 934: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4899 +//line sql.y:4951 { yyLOCAL = yyDollar[1].tableExprsUnion() } yyVAL.union = yyLOCAL - case 924: + case 935: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4905 +//line sql.y:4957 { yyLOCAL = yyDollar[2].tableExprsUnion() } yyVAL.union = yyLOCAL - case 925: + case 936: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4911 +//line sql.y:4963 { yyLOCAL = TableExprs{yyDollar[1].tableExprUnion()} } yyVAL.union = yyLOCAL - case 926: + case 937: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4915 +//line sql.y:4967 { yySLICE := (*TableExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableExprUnion()) } - case 929: + case 940: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4925 +//line sql.y:4977 { yyLOCAL = yyDollar[1].aliasedTableNameUnion() } yyVAL.union = yyLOCAL - case 930: + case 941: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4929 +//line sql.y:4981 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].derivedTableUnion(), As: yyDollar[3].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 931: + case 942: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4933 +//line sql.y:4985 { yyLOCAL = &ParenTableExpr{Exprs: yyDollar[2].tableExprsUnion()} } yyVAL.union = yyLOCAL - case 932: + case 943: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4937 +//line sql.y:4989 { yyLOCAL = yyDollar[1].tableExprUnion() } yyVAL.union = yyLOCAL - case 933: + case 944: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:4943 +//line sql.y:4995 { yyLOCAL = &DerivedTable{Lateral: false, Select: yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 934: + case 945: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:4947 +//line sql.y:4999 { yyLOCAL = &DerivedTable{Lateral: true, Select: yyDollar[2].selStmtUnion()} } yyVAL.union = yyLOCAL - case 935: + case 946: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:4953 +//line sql.y:5005 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].identifierCS, Hints: yyDollar[3].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 936: + case 947: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:4957 +//line sql.y:5009 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitionsUnion(), As: yyDollar[6].identifierCS, Hints: yyDollar[7].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 937: + case 948: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:4962 +//line sql.y:5014 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 938: + case 949: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:4966 +//line sql.y:5018 { yyLOCAL = yyDollar[2].columnsUnion() } yyVAL.union = yyLOCAL - case 939: + case 950: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:4971 +//line sql.y:5023 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 940: + case 951: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:4975 +//line sql.y:5027 { yyLOCAL = yyDollar[1].columnsUnion() } yyVAL.union = yyLOCAL - case 941: + case 952: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:4981 +//line sql.y:5033 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 942: + case 953: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4985 +//line sql.y:5037 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 943: + case 954: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4991 +//line sql.y:5043 { yyLOCAL = []*Variable{yyDollar[1].variableUnion()} } yyVAL.union = yyLOCAL - case 944: + case 955: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4995 +//line sql.y:5047 { yySLICE := (*[]*Variable)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].variableUnion()) } - case 945: + case 956: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5001 +//line sql.y:5053 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 946: + case 957: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5005 +//line sql.y:5057 { yyLOCAL = Columns{NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 947: + case 958: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5009 +//line sql.y:5061 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 948: + case 959: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5013 +//line sql.y:5065 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, NewIdentifierCI(string(yyDollar[3].str))) } - case 949: + case 960: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Partitions -//line sql.y:5019 +//line sql.y:5071 { yyLOCAL = Partitions{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 950: + case 961: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5023 +//line sql.y:5075 { yySLICE := (*Partitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 951: + case 962: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5036 +//line sql.y:5088 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 952: + case 963: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5040 +//line sql.y:5092 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 953: + case 964: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5044 +//line sql.y:5096 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 954: + case 965: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5048 +//line sql.y:5100 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion()} } yyVAL.union = yyLOCAL - case 955: + case 966: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5054 +//line sql.y:5106 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 956: + case 967: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:5056 +//line sql.y:5108 { yyVAL.joinCondition = &JoinCondition{Using: yyDollar[3].columnsUnion()} } - case 957: + case 968: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5060 +//line sql.y:5112 { yyVAL.joinCondition = &JoinCondition{} } - case 958: + case 969: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5062 +//line sql.y:5114 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 959: + case 970: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5066 +//line sql.y:5118 { yyVAL.joinCondition = &JoinCondition{} } - case 960: + case 971: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5068 +//line sql.y:5120 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 961: + case 972: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5071 +//line sql.y:5123 { yyVAL.empty = struct{}{} } - case 962: + case 973: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5073 +//line sql.y:5125 { yyVAL.empty = struct{}{} } - case 963: + case 974: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5076 +//line sql.y:5128 { yyVAL.identifierCS = NewIdentifierCS("") } - case 964: + case 975: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5080 +//line sql.y:5132 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 965: + case 976: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5084 +//line sql.y:5136 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 967: + case 978: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5091 +//line sql.y:5143 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 968: + case 979: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5097 +//line sql.y:5149 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 969: + case 980: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5101 +//line sql.y:5153 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 970: + case 981: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5105 +//line sql.y:5157 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 971: + case 982: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5111 +//line sql.y:5163 { yyLOCAL = StraightJoinType } yyVAL.union = yyLOCAL - case 972: + case 983: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5117 +//line sql.y:5169 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 973: + case 984: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5121 +//line sql.y:5173 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 974: + case 985: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5125 +//line sql.y:5177 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 975: + case 986: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5129 +//line sql.y:5181 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 976: + case 987: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5135 +//line sql.y:5187 { yyLOCAL = NaturalJoinType } yyVAL.union = yyLOCAL - case 977: + case 988: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5139 +//line sql.y:5191 { if yyDollar[2].joinTypeUnion() == LeftJoinType { yyLOCAL = NaturalLeftJoinType @@ -17410,667 +17633,667 @@ yydefault: } } yyVAL.union = yyLOCAL - case 978: + case 989: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5149 +//line sql.y:5201 { yyVAL.tableName = yyDollar[2].tableName } - case 979: + case 990: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5153 +//line sql.y:5205 { yyVAL.tableName = yyDollar[1].tableName } - case 980: + case 991: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5159 +//line sql.y:5211 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 981: + case 992: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5163 +//line sql.y:5215 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS} } - case 982: + case 993: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5169 +//line sql.y:5221 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 983: + case 994: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5174 +//line sql.y:5226 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 984: + case 995: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5178 +//line sql.y:5230 { yyLOCAL = yyDollar[1].indexHintsUnion() } yyVAL.union = yyLOCAL - case 985: + case 996: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5184 +//line sql.y:5236 { yyLOCAL = IndexHints{yyDollar[1].indexHintUnion()} } yyVAL.union = yyLOCAL - case 986: + case 997: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5188 +//line sql.y:5240 { yySLICE := (*IndexHints)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].indexHintUnion()) } - case 987: + case 998: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5194 +//line sql.y:5246 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 988: + case 999: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5198 +//line sql.y:5250 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion()} } yyVAL.union = yyLOCAL - case 989: + case 1000: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5202 +//line sql.y:5254 { yyLOCAL = &IndexHint{Type: IgnoreOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 990: + case 1001: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5206 +//line sql.y:5258 { yyLOCAL = &IndexHint{Type: ForceOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 991: + case 1002: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5210 +//line sql.y:5262 { yyLOCAL = &IndexHint{Type: UseVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 992: + case 1003: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5214 +//line sql.y:5266 { yyLOCAL = &IndexHint{Type: IgnoreVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 993: + case 1004: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5219 +//line sql.y:5271 { yyLOCAL = NoForType } yyVAL.union = yyLOCAL - case 994: + case 1005: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5223 +//line sql.y:5275 { yyLOCAL = JoinForType } yyVAL.union = yyLOCAL - case 995: + case 1006: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5227 +//line sql.y:5279 { yyLOCAL = OrderByForType } yyVAL.union = yyLOCAL - case 996: + case 1007: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5231 +//line sql.y:5283 { yyLOCAL = GroupByForType } yyVAL.union = yyLOCAL - case 997: + case 1008: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:5237 +//line sql.y:5289 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 998: + case 1009: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5241 +//line sql.y:5293 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 999: + case 1010: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5248 +//line sql.y:5300 { yyLOCAL = &OrExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1000: + case 1011: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5252 +//line sql.y:5304 { yyLOCAL = &XorExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1001: + case 1012: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5256 +//line sql.y:5308 { yyLOCAL = &AndExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1002: + case 1013: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5260 +//line sql.y:5312 { yyLOCAL = &NotExpr{Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1003: + case 1014: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5264 +//line sql.y:5316 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].isExprOperatorUnion()} } yyVAL.union = yyLOCAL - case 1004: + case 1015: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5268 +//line sql.y:5320 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1005: + case 1016: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5272 +//line sql.y:5324 { yyLOCAL = &AssignmentExpr{Left: yyDollar[1].variableUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1006: + case 1017: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5276 +//line sql.y:5328 { yyLOCAL = &MemberOfExpr{Value: yyDollar[1].exprUnion(), JSONArr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1007: + case 1018: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5282 +//line sql.y:5334 { } - case 1008: + case 1019: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5285 +//line sql.y:5337 { } - case 1009: + case 1020: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5290 +//line sql.y:5342 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNullOp} } yyVAL.union = yyLOCAL - case 1010: + case 1021: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5294 +//line sql.y:5346 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNotNullOp} } yyVAL.union = yyLOCAL - case 1011: + case 1022: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5298 +//line sql.y:5350 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1012: + case 1023: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5302 +//line sql.y:5354 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1013: + case 1024: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5306 +//line sql.y:5358 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1014: + case 1025: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5310 +//line sql.y:5362 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: All, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1015: + case 1026: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5314 +//line sql.y:5366 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1016: + case 1027: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5320 +//line sql.y:5372 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: InOp, Right: yyDollar[3].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1017: + case 1028: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5324 +//line sql.y:5376 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotInOp, Right: yyDollar[4].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1018: + case 1029: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5328 +//line sql.y:5380 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: true, From: yyDollar[3].exprUnion(), To: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1019: + case 1030: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5332 +//line sql.y:5384 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: false, From: yyDollar[4].exprUnion(), To: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1020: + case 1031: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5336 +//line sql.y:5388 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1021: + case 1032: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5340 +//line sql.y:5392 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1022: + case 1033: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5344 +//line sql.y:5396 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion(), Escape: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1023: + case 1034: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5348 +//line sql.y:5400 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion(), Escape: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1024: + case 1035: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5352 +//line sql.y:5404 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: RegexpOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1025: + case 1036: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5356 +//line sql.y:5408 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotRegexpOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1026: + case 1037: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5360 +//line sql.y:5412 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1027: + case 1038: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5366 +//line sql.y:5418 { } - case 1028: + case 1039: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5369 +//line sql.y:5421 { } - case 1029: + case 1040: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5375 +//line sql.y:5427 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitOrOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1030: + case 1041: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5379 +//line sql.y:5431 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitAndOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1031: + case 1042: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5383 +//line sql.y:5435 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftLeftOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1032: + case 1043: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5387 +//line sql.y:5439 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftRightOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1033: + case 1044: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5391 +//line sql.y:5443 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: PlusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1034: + case 1045: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5395 +//line sql.y:5447 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MinusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1035: + case 1046: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5399 +//line sql.y:5451 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAdd, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1036: + case 1047: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5403 +//line sql.y:5455 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinarySub, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1037: + case 1048: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5407 +//line sql.y:5459 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MultOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1038: + case 1049: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5411 +//line sql.y:5463 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: DivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1039: + case 1050: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5415 +//line sql.y:5467 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1040: + case 1051: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5419 +//line sql.y:5471 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: IntDivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1041: + case 1052: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5423 +//line sql.y:5475 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1042: + case 1053: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5427 +//line sql.y:5479 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitXorOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1043: + case 1054: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5431 +//line sql.y:5483 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1044: + case 1055: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5437 +//line sql.y:5489 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1045: + case 1056: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5441 +//line sql.y:5493 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1046: + case 1057: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5445 +//line sql.y:5497 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1047: + case 1058: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5449 +//line sql.y:5501 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1048: + case 1059: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5453 +//line sql.y:5505 { yyLOCAL = &CollateExpr{Expr: yyDollar[1].exprUnion(), Collation: yyDollar[3].str} } yyVAL.union = yyLOCAL - case 1049: + case 1060: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5457 +//line sql.y:5509 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1050: + case 1061: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5461 +//line sql.y:5513 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1051: + case 1062: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5465 +//line sql.y:5517 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1052: + case 1063: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5469 +//line sql.y:5521 { yyLOCAL = yyDollar[2].exprUnion() // TODO: do we really want to ignore unary '+' before any kind of literals? } yyVAL.union = yyLOCAL - case 1053: + case 1064: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5473 +//line sql.y:5525 { yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1054: + case 1065: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5477 +//line sql.y:5529 { yyLOCAL = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1055: + case 1066: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5481 +//line sql.y:5533 { yyLOCAL = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1056: + case 1067: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5485 +//line sql.y:5537 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1057: + case 1068: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5489 +//line sql.y:5541 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1058: + case 1069: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5493 +//line sql.y:5545 { yyLOCAL = &ExistsExpr{Subquery: yyDollar[2].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1059: + case 1070: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:5497 +//line sql.y:5549 { yyLOCAL = &MatchExpr{Columns: yyDollar[2].colNamesUnion(), Expr: yyDollar[5].exprUnion(), Option: yyDollar[6].matchExprOptionUnion()} } yyVAL.union = yyLOCAL - case 1060: + case 1071: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:5501 +//line sql.y:5553 { yyLOCAL = &CastExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion(), Array: yyDollar[6].booleanUnion()} } yyVAL.union = yyLOCAL - case 1061: + case 1072: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5505 +//line sql.y:5557 { yyLOCAL = &ConvertExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1062: + case 1073: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5509 +//line sql.y:5561 { yyLOCAL = &ConvertUsingExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 1063: + case 1074: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5513 +//line sql.y:5565 { // 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: @@ -18079,3218 +18302,3218 @@ yydefault: yyLOCAL = &ConvertExpr{Expr: yyDollar[2].exprUnion(), Type: &ConvertType{Type: yyDollar[1].str}} } yyVAL.union = yyLOCAL - case 1064: + case 1075: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5521 +//line sql.y:5573 { yyLOCAL = &Default{ColName: yyDollar[2].str} } yyVAL.union = yyLOCAL - case 1065: + case 1076: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5525 +//line sql.y:5577 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAddLeft, Date: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion(), Interval: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1066: + case 1077: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5529 +//line sql.y:5581 { yyLOCAL = &IntervalFuncExpr{Expr: yyDollar[3].exprUnion(), Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1067: + case 1078: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5533 +//line sql.y:5585 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: JSONExtractOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1068: + case 1079: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5537 +//line sql.y:5589 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: JSONUnquoteExtractOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1069: + case 1080: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5543 +//line sql.y:5595 { yyLOCAL = yyDollar[1].colNamesUnion() } yyVAL.union = yyLOCAL - case 1070: + case 1081: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5547 +//line sql.y:5599 { yyLOCAL = yyDollar[2].colNamesUnion() } yyVAL.union = yyLOCAL - case 1071: + case 1082: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5553 +//line sql.y:5605 { yyLOCAL = []*ColName{yyDollar[1].colNameUnion()} } yyVAL.union = yyLOCAL - case 1072: + case 1083: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5557 +//line sql.y:5609 { yySLICE := (*[]*ColName)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].colNameUnion()) } - case 1073: + case 1084: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5563 +//line sql.y:5615 { yyLOCAL = BothTrimType } yyVAL.union = yyLOCAL - case 1074: + case 1085: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5567 +//line sql.y:5619 { yyLOCAL = LeadingTrimType } yyVAL.union = yyLOCAL - case 1075: + case 1086: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5571 +//line sql.y:5623 { yyLOCAL = TrailingTrimType } yyVAL.union = yyLOCAL - case 1076: + case 1087: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:5577 +//line sql.y:5629 { yyLOCAL = FrameRowsType } yyVAL.union = yyLOCAL - case 1077: + case 1088: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:5581 +//line sql.y:5633 { yyLOCAL = FrameRangeType } yyVAL.union = yyLOCAL - case 1078: + case 1089: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5588 +//line sql.y:5640 { yyLOCAL = CumeDistExprType } yyVAL.union = yyLOCAL - case 1079: + case 1090: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5592 +//line sql.y:5644 { yyLOCAL = DenseRankExprType } yyVAL.union = yyLOCAL - case 1080: + case 1091: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5596 +//line sql.y:5648 { yyLOCAL = PercentRankExprType } yyVAL.union = yyLOCAL - case 1081: + case 1092: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5600 +//line sql.y:5652 { yyLOCAL = RankExprType } yyVAL.union = yyLOCAL - case 1082: + case 1093: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5604 +//line sql.y:5656 { yyLOCAL = RowNumberExprType } yyVAL.union = yyLOCAL - case 1083: + case 1094: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5610 +//line sql.y:5662 { yyLOCAL = &FramePoint{Type: CurrentRowType} } yyVAL.union = yyLOCAL - case 1084: + case 1095: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5614 +//line sql.y:5666 { yyLOCAL = &FramePoint{Type: UnboundedPrecedingType} } yyVAL.union = yyLOCAL - case 1085: + case 1096: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5618 +//line sql.y:5670 { yyLOCAL = &FramePoint{Type: UnboundedFollowingType} } yyVAL.union = yyLOCAL - case 1086: + case 1097: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5622 +//line sql.y:5674 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1087: + case 1098: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5626 +//line sql.y:5678 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1088: + case 1099: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5630 +//line sql.y:5682 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1089: + case 1100: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5634 +//line sql.y:5686 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1090: + case 1101: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5639 +//line sql.y:5691 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1091: + case 1102: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5643 +//line sql.y:5695 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1092: + case 1103: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5649 +//line sql.y:5701 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[2].framePointUnion()} } yyVAL.union = yyLOCAL - case 1093: + case 1104: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5653 +//line sql.y:5705 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[3].framePointUnion(), End: yyDollar[5].framePointUnion()} } yyVAL.union = yyLOCAL - case 1094: + case 1105: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Exprs -//line sql.y:5658 +//line sql.y:5710 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1095: + case 1106: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Exprs -//line sql.y:5662 +//line sql.y:5714 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1096: + case 1107: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5667 +//line sql.y:5719 { yyVAL.identifierCI = IdentifierCI{} } - case 1097: + case 1108: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5671 +//line sql.y:5723 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1098: + case 1109: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *WindowSpecification -//line sql.y:5677 +//line sql.y:5729 { yyLOCAL = &WindowSpecification{Name: yyDollar[1].identifierCI, PartitionClause: yyDollar[2].exprsUnion(), OrderClause: yyDollar[3].orderByUnion(), FrameClause: yyDollar[4].frameClauseUnion()} } yyVAL.union = yyLOCAL - case 1099: + case 1110: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5683 +//line sql.y:5735 { yyLOCAL = &OverClause{WindowSpec: yyDollar[3].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1100: + case 1111: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5687 +//line sql.y:5739 { yyLOCAL = &OverClause{WindowName: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 1101: + case 1112: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5693 +//line sql.y:5745 { yyLOCAL = yyDollar[1].overClauseUnion() } yyVAL.union = yyLOCAL - case 1102: + case 1113: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5697 +//line sql.y:5749 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1103: + case 1114: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:5702 +//line sql.y:5754 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1105: + case 1116: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:5709 +//line sql.y:5761 { yyLOCAL = &NullTreatmentClause{yyDollar[1].nullTreatmentTypeUnion()} } yyVAL.union = yyLOCAL - case 1106: + case 1117: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:5715 +//line sql.y:5767 { yyLOCAL = RespectNullsType } yyVAL.union = yyLOCAL - case 1107: + case 1118: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:5719 +//line sql.y:5771 { yyLOCAL = IgnoreNullsType } yyVAL.union = yyLOCAL - case 1108: + case 1119: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:5725 +//line sql.y:5777 { yyLOCAL = FirstValueExprType } yyVAL.union = yyLOCAL - case 1109: + case 1120: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:5729 +//line sql.y:5781 { yyLOCAL = LastValueExprType } yyVAL.union = yyLOCAL - case 1110: + case 1121: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:5735 +//line sql.y:5787 { yyLOCAL = FromFirstType } yyVAL.union = yyLOCAL - case 1111: + case 1122: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:5739 +//line sql.y:5791 { yyLOCAL = FromLastType } yyVAL.union = yyLOCAL - case 1112: + case 1123: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:5744 +//line sql.y:5796 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1114: + case 1125: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:5751 +//line sql.y:5803 { yyLOCAL = &FromFirstLastClause{yyDollar[1].fromFirstLastTypeUnion()} } yyVAL.union = yyLOCAL - case 1115: + case 1126: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:5757 +//line sql.y:5809 { yyLOCAL = LagExprType } yyVAL.union = yyLOCAL - case 1116: + case 1127: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:5761 +//line sql.y:5813 { yyLOCAL = LeadExprType } yyVAL.union = yyLOCAL - case 1117: + case 1128: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *WindowDefinition -//line sql.y:5767 +//line sql.y:5819 { yyLOCAL = &WindowDefinition{Name: yyDollar[1].identifierCI, WindowSpec: yyDollar[4].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1118: + case 1129: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL WindowDefinitions -//line sql.y:5773 +//line sql.y:5825 { yyLOCAL = WindowDefinitions{yyDollar[1].windowDefinitionUnion()} } yyVAL.union = yyLOCAL - case 1119: + case 1130: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5777 +//line sql.y:5829 { yySLICE := (*WindowDefinitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].windowDefinitionUnion()) } - case 1120: + case 1131: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5783 +//line sql.y:5835 { yyVAL.str = "" } - case 1121: + case 1132: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5787 +//line sql.y:5839 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 1122: + case 1133: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:5793 +//line sql.y:5845 { yyLOCAL = BoolVal(true) } yyVAL.union = yyLOCAL - case 1123: + case 1134: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:5797 +//line sql.y:5849 { yyLOCAL = BoolVal(false) } yyVAL.union = yyLOCAL - case 1124: + case 1135: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5804 +//line sql.y:5856 { yyLOCAL = IsTrueOp } yyVAL.union = yyLOCAL - case 1125: + case 1136: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5808 +//line sql.y:5860 { yyLOCAL = IsNotTrueOp } yyVAL.union = yyLOCAL - case 1126: + case 1137: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5812 +//line sql.y:5864 { yyLOCAL = IsFalseOp } yyVAL.union = yyLOCAL - case 1127: + case 1138: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5816 +//line sql.y:5868 { yyLOCAL = IsNotFalseOp } yyVAL.union = yyLOCAL - case 1128: + case 1139: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5822 +//line sql.y:5874 { yyLOCAL = yyDollar[1].comparisonExprOperatorUnion() } yyVAL.union = yyLOCAL - case 1129: + case 1140: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5826 +//line sql.y:5878 { yyLOCAL = NullSafeEqualOp } yyVAL.union = yyLOCAL - case 1130: + case 1141: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5832 +//line sql.y:5884 { yyLOCAL = EqualOp } yyVAL.union = yyLOCAL - case 1131: + case 1142: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5836 +//line sql.y:5888 { yyLOCAL = LessThanOp } yyVAL.union = yyLOCAL - case 1132: + case 1143: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5840 +//line sql.y:5892 { yyLOCAL = GreaterThanOp } yyVAL.union = yyLOCAL - case 1133: + case 1144: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5844 +//line sql.y:5896 { yyLOCAL = LessEqualOp } yyVAL.union = yyLOCAL - case 1134: + case 1145: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5848 +//line sql.y:5900 { yyLOCAL = GreaterEqualOp } yyVAL.union = yyLOCAL - case 1135: + case 1146: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5852 +//line sql.y:5904 { yyLOCAL = NotEqualOp } yyVAL.union = yyLOCAL - case 1136: + case 1147: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5858 +//line sql.y:5910 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1137: + case 1148: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5862 +//line sql.y:5914 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1138: + case 1149: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5866 +//line sql.y:5918 { yyLOCAL = ListArg(yyDollar[1].str[2:]) markBindVariable(yylex, yyDollar[1].str[2:]) } yyVAL.union = yyLOCAL - case 1139: + case 1150: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Subquery -//line sql.y:5873 +//line sql.y:5925 { yyLOCAL = &Subquery{yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1140: + case 1151: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Exprs -//line sql.y:5879 +//line sql.y:5931 { yyLOCAL = Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1141: + case 1152: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5883 +//line sql.y:5935 { yySLICE := (*Exprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].exprUnion()) } - case 1142: + case 1153: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5893 +//line sql.y:5945 { yyLOCAL = &FuncExpr{Name: yyDollar[1].identifierCI, Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1143: + case 1154: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5897 +//line sql.y:5949 { yyLOCAL = &FuncExpr{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCI, Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1144: + case 1155: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5907 +//line sql.y:5959 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("left"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1145: + case 1156: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5911 +//line sql.y:5963 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("right"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1146: + case 1157: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5915 +//line sql.y:5967 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1147: + case 1158: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5919 +//line sql.y:5971 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1148: + case 1159: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5923 +//line sql.y:5975 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1149: + case 1160: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5927 +//line sql.y:5979 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1150: + case 1161: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5931 +//line sql.y:5983 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1151: + case 1162: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5935 +//line sql.y:5987 { yyLOCAL = &CaseExpr{Expr: yyDollar[2].exprUnion(), Whens: yyDollar[3].whensUnion(), Else: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1152: + case 1163: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5939 +//line sql.y:5991 { yyLOCAL = &ValuesFuncExpr{Name: yyDollar[3].colNameUnion()} } yyVAL.union = yyLOCAL - case 1153: + case 1164: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:5943 +//line sql.y:5995 { yyLOCAL = &InsertExpr{Str: yyDollar[3].exprUnion(), Pos: yyDollar[5].exprUnion(), Len: yyDollar[7].exprUnion(), NewStr: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1154: + case 1165: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5947 +//line sql.y:5999 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1155: + case 1166: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5958 +//line sql.y:6010 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("utc_date")} } yyVAL.union = yyLOCAL - case 1156: + case 1167: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5962 +//line sql.y:6014 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1157: + case 1168: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5968 +//line sql.y:6020 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("current_date")} } yyVAL.union = yyLOCAL - case 1158: + case 1169: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5972 +//line sql.y:6024 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("curdate")} } yyVAL.union = yyLOCAL - case 1159: + case 1170: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5976 +//line sql.y:6028 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1160: + case 1171: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5981 +//line sql.y:6033 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("curtime"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1161: + case 1172: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5986 +//line sql.y:6038 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1162: + case 1173: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5990 +//line sql.y:6042 { yyLOCAL = &CountStar{OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1163: + case 1174: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5994 +//line sql.y:6046 { yyLOCAL = &Count{Distinct: yyDollar[3].booleanUnion(), Args: yyDollar[4].exprsUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1164: + case 1175: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5998 +//line sql.y:6050 { yyLOCAL = &Max{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1165: + case 1176: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6002 +//line sql.y:6054 { yyLOCAL = &Min{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1166: + case 1177: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6006 +//line sql.y:6058 { yyLOCAL = &Sum{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1167: + case 1178: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6010 +//line sql.y:6062 { yyLOCAL = &Avg{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1168: + case 1179: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6014 +//line sql.y:6066 { yyLOCAL = &BitAnd{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1169: + case 1180: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6018 +//line sql.y:6070 { yyLOCAL = &BitOr{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1170: + case 1181: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6022 +//line sql.y:6074 { yyLOCAL = &BitXor{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1171: + case 1182: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6026 +//line sql.y:6078 { yyLOCAL = &Std{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1172: + case 1183: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6030 +//line sql.y:6082 { yyLOCAL = &StdDev{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1173: + case 1184: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6034 +//line sql.y:6086 { yyLOCAL = &StdPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1174: + case 1185: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6038 +//line sql.y:6090 { yyLOCAL = &StdSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1175: + case 1186: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6042 +//line sql.y:6094 { yyLOCAL = &VarPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1176: + case 1187: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6046 +//line sql.y:6098 { yyLOCAL = &VarSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1177: + case 1188: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6050 +//line sql.y:6102 { yyLOCAL = &Variance{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1178: + case 1189: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6054 +//line sql.y:6106 { 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 1190: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6058 +//line sql.y:6110 { yyLOCAL = &AnyValue{Arg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1180: + case 1191: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6062 +//line sql.y:6114 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprTimestampadd, Date: yyDollar[7].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1181: + case 1192: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6066 +//line sql.y:6118 { yyLOCAL = &TimestampDiffExpr{Unit: yyDollar[3].intervalTypeUnion(), Expr1: yyDollar[5].exprUnion(), Expr2: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1182: + case 1193: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6070 +//line sql.y:6122 { yyLOCAL = &ExtractFuncExpr{IntervalType: yyDollar[3].intervalTypeUnion(), Expr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1183: + case 1194: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6074 +//line sql.y:6126 { yyLOCAL = &WeightStringFuncExpr{Expr: yyDollar[3].exprUnion(), As: yyDollar[4].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1184: + case 1195: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6078 +//line sql.y:6130 { yyLOCAL = &JSONPrettyExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1185: + case 1196: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6082 +//line sql.y:6134 { yyLOCAL = &JSONStorageFreeExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1186: + case 1197: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6086 +//line sql.y:6138 { yyLOCAL = &JSONStorageSizeExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1187: + case 1198: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6090 +//line sql.y:6142 { yyLOCAL = &JSONArrayAgg{Expr: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1188: + case 1199: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:6094 +//line sql.y:6146 { yyLOCAL = &JSONObjectAgg{Key: yyDollar[3].exprUnion(), Value: yyDollar[5].exprUnion(), OverClause: yyDollar[7].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1189: + case 1200: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6098 +//line sql.y:6150 { yyLOCAL = &TrimFuncExpr{TrimFuncType: LTrimType, Type: LeadingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1190: + case 1201: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6102 +//line sql.y:6154 { yyLOCAL = &TrimFuncExpr{TrimFuncType: RTrimType, Type: TrailingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1191: + case 1202: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:6106 +//line sql.y:6158 { yyLOCAL = &TrimFuncExpr{Type: yyDollar[3].trimTypeUnion(), TrimArg: yyDollar[4].exprUnion(), StringArg: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1192: + case 1203: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6110 +//line sql.y:6162 { yyLOCAL = &TrimFuncExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1193: + case 1204: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6114 +//line sql.y:6166 { yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1194: + case 1205: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6118 +//line sql.y:6170 { yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion(), Charset: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 1195: + case 1206: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6122 +//line sql.y:6174 { yyLOCAL = &TrimFuncExpr{TrimArg: yyDollar[3].exprUnion(), StringArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1196: + case 1207: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6126 +//line sql.y:6178 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1197: + case 1208: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6130 +//line sql.y:6182 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion(), Pos: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1198: + case 1209: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6134 +//line sql.y:6186 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1199: + case 1210: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6138 +//line sql.y:6190 { yyLOCAL = &LockingFunc{Type: GetLock, Name: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1200: + case 1211: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6142 +//line sql.y:6194 { yyLOCAL = &LockingFunc{Type: IsFreeLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1201: + case 1212: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6146 +//line sql.y:6198 { yyLOCAL = &LockingFunc{Type: IsUsedLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1202: + case 1213: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:6150 +//line sql.y:6202 { yyLOCAL = &LockingFunc{Type: ReleaseAllLocks} } yyVAL.union = yyLOCAL - case 1203: + case 1214: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6154 +//line sql.y:6206 { yyLOCAL = &LockingFunc{Type: ReleaseLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1204: + case 1215: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6158 +//line sql.y:6210 { yyLOCAL = &JSONSchemaValidFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1205: + case 1216: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6162 +//line sql.y:6214 { yyLOCAL = &JSONSchemaValidationReportFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1206: + case 1217: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6166 +//line sql.y:6218 { yyLOCAL = &JSONArrayExpr{Params: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1207: + case 1218: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6170 +//line sql.y:6222 { yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1208: + case 1219: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6174 +//line sql.y:6226 { yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, 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:6178 +//line sql.y:6230 { yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1210: + case 1221: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6182 +//line sql.y:6234 { yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1211: + case 1222: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6186 +//line sql.y:6238 { yyLOCAL = &GeomPropertyFuncExpr{Property: IsEmpty, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1212: + case 1223: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6190 +//line sql.y:6242 { yyLOCAL = &GeomPropertyFuncExpr{Property: IsSimple, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1213: + case 1224: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6194 +//line sql.y:6246 { yyLOCAL = &GeomPropertyFuncExpr{Property: Dimension, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1214: + case 1225: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6198 +//line sql.y:6250 { yyLOCAL = &GeomPropertyFuncExpr{Property: Envelope, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1215: + case 1226: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6202 +//line sql.y:6254 { yyLOCAL = &GeomPropertyFuncExpr{Property: GeometryType, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1216: + case 1227: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6206 +//line sql.y:6258 { yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1217: + case 1228: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6210 +//line sql.y:6262 { yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, 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:6214 +//line sql.y:6266 { yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1219: + case 1230: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6218 +//line sql.y:6270 { yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1220: + case 1231: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6222 +//line sql.y:6274 { yyLOCAL = &LinestrPropertyFuncExpr{Property: EndPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1221: + case 1232: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6226 +//line sql.y:6278 { yyLOCAL = &LinestrPropertyFuncExpr{Property: IsClosed, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1222: + case 1233: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6230 +//line sql.y:6282 { yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1223: + case 1234: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6234 +//line sql.y:6286 { yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, 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:6238 +//line sql.y:6290 { yyLOCAL = &LinestrPropertyFuncExpr{Property: NumPoints, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1225: + case 1236: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6242 +//line sql.y:6294 { yyLOCAL = &LinestrPropertyFuncExpr{Property: PointN, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1226: + case 1237: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6246 +//line sql.y:6298 { yyLOCAL = &LinestrPropertyFuncExpr{Property: StartPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1227: + case 1238: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6250 +//line sql.y:6302 { yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1228: + case 1239: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6254 +//line sql.y:6306 { yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, 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:6258 +//line sql.y:6310 { yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1230: + case 1241: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6262 +//line sql.y:6314 { yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1231: + case 1242: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6266 +//line sql.y:6318 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1232: + case 1243: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6270 +//line sql.y:6322 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1233: + case 1244: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6274 +//line sql.y:6326 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1234: + case 1245: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6278 +//line sql.y:6330 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1235: + case 1246: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6282 +//line sql.y:6334 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1236: + case 1247: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6286 +//line sql.y:6338 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1237: + case 1248: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6290 +//line sql.y:6342 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1238: + case 1249: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6294 +//line sql.y:6346 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1239: + case 1250: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6298 +//line sql.y:6350 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1240: + case 1251: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6302 +//line sql.y:6354 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1241: + case 1252: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6306 +//line sql.y:6358 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1242: + case 1253: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6310 +//line sql.y:6362 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1243: + case 1254: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6314 +//line sql.y:6366 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1244: + case 1255: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6318 +//line sql.y:6370 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1245: + case 1256: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6322 +//line sql.y:6374 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1246: + case 1257: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6326 +//line sql.y:6378 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1247: + case 1258: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6330 +//line sql.y:6382 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1248: + case 1259: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6334 +//line sql.y:6386 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1249: + case 1260: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6338 +//line sql.y:6390 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1250: + case 1261: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6342 +//line sql.y:6394 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1251: + case 1262: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6346 +//line sql.y:6398 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1252: + case 1263: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6350 +//line sql.y:6402 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1253: + case 1264: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6354 +//line sql.y:6406 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1254: + case 1265: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6358 +//line sql.y:6410 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1255: + case 1266: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6362 +//line sql.y:6414 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1256: + case 1267: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6366 +//line sql.y:6418 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1257: + case 1268: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6370 +//line sql.y:6422 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1258: + case 1269: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6374 +//line sql.y:6426 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1259: + case 1270: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6378 +//line sql.y:6430 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1260: + case 1271: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6382 +//line sql.y:6434 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1261: + case 1272: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6386 +//line sql.y:6438 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1262: + case 1273: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6390 +//line sql.y:6442 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1263: + case 1274: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6394 +//line sql.y:6446 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1264: + case 1275: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6398 +//line sql.y:6450 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1265: + case 1276: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6402 +//line sql.y:6454 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1266: + case 1277: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6406 +//line sql.y:6458 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1267: + case 1278: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6410 +//line sql.y:6462 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1268: + case 1279: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6414 +//line sql.y:6466 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1269: + case 1280: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6418 +//line sql.y:6470 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1270: + case 1281: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6422 +//line sql.y:6474 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1271: + case 1282: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6426 +//line sql.y:6478 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1272: + case 1283: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6430 +//line sql.y:6482 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1273: + case 1284: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6434 +//line sql.y:6486 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1274: + case 1285: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6438 +//line sql.y:6490 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1275: + case 1286: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6442 +//line sql.y:6494 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1276: + case 1287: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6446 +//line sql.y:6498 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1277: + case 1288: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6450 +//line sql.y:6502 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1278: + case 1289: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6454 +//line sql.y:6506 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1279: + case 1290: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6458 +//line sql.y:6510 { yyLOCAL = &PolygonPropertyFuncExpr{Property: Area, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1280: + case 1291: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6462 +//line sql.y:6514 { yyLOCAL = &PolygonPropertyFuncExpr{Property: Centroid, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1281: + case 1292: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6466 +//line sql.y:6518 { yyLOCAL = &PolygonPropertyFuncExpr{Property: ExteriorRing, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1282: + case 1293: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6470 +//line sql.y:6522 { yyLOCAL = &PolygonPropertyFuncExpr{Property: InteriorRingN, Polygon: 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:6474 +//line sql.y:6526 { yyLOCAL = &PolygonPropertyFuncExpr{Property: NumInteriorRings, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1284: + case 1295: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6478 +//line sql.y:6530 { yyLOCAL = &GeomCollPropertyFuncExpr{Property: GeometryN, GeomColl: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1285: + case 1296: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6482 +//line sql.y:6534 { yyLOCAL = &GeomCollPropertyFuncExpr{Property: NumGeometries, GeomColl: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1286: + case 1297: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6486 +//line sql.y:6538 { yyLOCAL = &GeoHashFromLatLongExpr{Longitude: yyDollar[3].exprUnion(), Latitude: yyDollar[5].exprUnion(), MaxLength: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1287: + case 1298: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6490 +//line sql.y:6542 { yyLOCAL = &GeoHashFromPointExpr{Point: yyDollar[3].exprUnion(), MaxLength: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1288: + case 1299: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6494 +//line sql.y:6546 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: LatitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1289: + case 1300: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6498 +//line sql.y:6550 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: LongitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1290: + case 1301: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6502 +//line sql.y:6554 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: PointFromHash, GeoHash: yyDollar[3].exprUnion(), SridOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1291: + case 1302: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6506 +//line sql.y:6558 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1292: + case 1303: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6510 +//line sql.y:6562 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1293: + case 1304: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6514 +//line sql.y:6566 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion(), Srid: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1294: + case 1305: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6518 +//line sql.y:6570 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1295: + case 1306: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6522 +//line sql.y:6574 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1296: + case 1307: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6526 +//line sql.y:6578 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion(), Bitmask: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1297: + case 1308: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6530 +//line sql.y:6582 { yyLOCAL = &JSONObjectExpr{Params: yyDollar[3].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1298: + case 1309: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6534 +//line sql.y:6586 { yyLOCAL = &JSONQuoteExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1299: + case 1310: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6538 +//line sql.y:6590 { yyLOCAL = &JSONContainsExpr{Target: yyDollar[3].exprUnion(), Candidate: yyDollar[5].exprsUnion()[0], PathList: yyDollar[5].exprsUnion()[1:]} } yyVAL.union = yyLOCAL - case 1300: + case 1311: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6542 +//line sql.y:6594 { yyLOCAL = &JSONContainsPathExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), PathList: yyDollar[7].exprsUnion()} } yyVAL.union = yyLOCAL - case 1301: + case 1312: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6546 +//line sql.y:6598 { yyLOCAL = &JSONExtractExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1302: + case 1313: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6550 +//line sql.y:6602 { yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1303: + case 1314: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6554 +//line sql.y:6606 { yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1304: + case 1315: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6558 +//line sql.y:6610 { yyLOCAL = &JSONOverlapsExpr{JSONDoc1: yyDollar[3].exprUnion(), JSONDoc2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1305: + case 1316: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6562 +//line sql.y:6614 { yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1306: + case 1317: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6566 +//line sql.y:6618 { 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 1307: + case 1318: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:6570 +//line sql.y:6622 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1308: + case 1319: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6574 +//line sql.y:6626 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL - case 1309: + case 1320: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6578 +//line sql.y:6630 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), ErrorOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL - case 1310: + case 1321: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6582 +//line sql.y:6634 { 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 1311: + case 1322: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6586 +//line sql.y:6638 { yyLOCAL = &JSONAttributesExpr{Type: DepthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1312: + case 1323: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6590 +//line sql.y:6642 { yyLOCAL = &JSONAttributesExpr{Type: ValidAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1313: + case 1324: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6594 +//line sql.y:6646 { yyLOCAL = &JSONAttributesExpr{Type: TypeAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1314: + case 1325: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6598 +//line sql.y:6650 { yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1315: + case 1326: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6602 +//line sql.y:6654 { yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1316: + case 1327: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6606 +//line sql.y:6658 { yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayAppendType, 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:6610 +//line sql.y:6662 { yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayInsertType, 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:6614 +//line sql.y:6666 { yyLOCAL = &JSONValueModifierExpr{Type: JSONInsertType, 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:6618 +//line sql.y:6670 { yyLOCAL = &JSONValueModifierExpr{Type: JSONReplaceType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1320: + case 1331: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6622 +//line sql.y:6674 { yyLOCAL = &JSONValueModifierExpr{Type: JSONSetType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1321: + case 1332: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6626 +//line sql.y:6678 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergeType, 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:6630 +//line sql.y:6682 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePatchType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1323: + case 1334: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6634 +//line sql.y:6686 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePreserveType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1324: + case 1335: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6638 +//line sql.y:6690 { yyLOCAL = &JSONRemoveExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1325: + case 1336: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6642 +//line sql.y:6694 { yyLOCAL = &JSONUnquoteExpr{JSONValue: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1326: + case 1337: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6646 +//line sql.y:6698 { yyLOCAL = &MultiPolygonExpr{PolygonParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1327: + case 1338: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6650 +//line sql.y:6702 { yyLOCAL = &MultiPointExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1328: + case 1339: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6654 +//line sql.y:6706 { yyLOCAL = &MultiLinestringExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1329: + case 1340: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6658 +//line sql.y:6710 { yyLOCAL = &PolygonExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1330: + case 1341: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6662 +//line sql.y:6714 { yyLOCAL = &LineStringExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1331: + case 1342: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6666 +//line sql.y:6718 { yyLOCAL = &PointExpr{XCordinate: yyDollar[3].exprUnion(), YCordinate: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1332: + case 1343: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6670 +//line sql.y:6722 { yyLOCAL = &ArgumentLessWindowExpr{Type: yyDollar[1].argumentLessWindowExprTypeUnion(), OverClause: yyDollar[4].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1333: + case 1344: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6674 +//line sql.y:6726 { yyLOCAL = &FirstOrLastValueExpr{Type: yyDollar[1].firstOrLastValueExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1334: + case 1345: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6678 +//line sql.y:6730 { yyLOCAL = &NtileExpr{N: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1335: + case 1346: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6682 +//line sql.y:6734 { 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 1336: + case 1347: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6686 +//line sql.y:6738 { yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1337: + case 1348: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6690 +//line sql.y:6742 { 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 1338: + case 1349: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6694 +//line sql.y:6746 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1339: + case 1350: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6698 +//line sql.y:6750 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1340: + case 1351: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6702 +//line sql.y:6754 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateAdd, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1341: + case 1352: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6706 +//line sql.y:6758 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateSub, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1342: + case 1353: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6710 +//line sql.y:6762 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1343: + case 1354: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6714 +//line sql.y:6766 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1348: + case 1359: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6724 +//line sql.y:6776 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1349: + case 1360: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6728 +//line sql.y:6780 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1350: + case 1361: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6732 +//line sql.y:6784 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1351: + case 1362: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6736 +//line sql.y:6788 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1352: + case 1363: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:6741 +//line sql.y:6793 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1353: + case 1364: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6745 +//line sql.y:6797 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1354: + case 1365: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6751 +//line sql.y:6803 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1355: + case 1366: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6755 +//line sql.y:6807 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1356: + case 1367: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6759 +//line sql.y:6811 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1357: + case 1368: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6763 +//line sql.y:6815 { 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 1358: + case 1369: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:6767 +//line sql.y:6819 { // 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 1359: + case 1370: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6772 +//line sql.y:6824 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1360: + case 1371: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6776 +//line sql.y:6828 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), MatchType: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1361: + case 1372: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6780 +//line sql.y:6832 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1362: + case 1373: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6784 +//line sql.y:6836 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion(), Position: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1363: + case 1374: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6788 +//line sql.y:6840 { 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 1364: + case 1375: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:6792 +//line sql.y:6844 { // 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 1365: + case 1376: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6797 +//line sql.y:6849 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1366: + case 1377: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6801 +//line sql.y:6853 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1367: + case 1378: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6805 +//line sql.y:6857 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1368: + case 1379: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6809 +//line sql.y:6861 { // 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 1369: + case 1380: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6816 +//line sql.y:6868 { yyLOCAL = &ExtractValueExpr{Fragment: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1370: + case 1381: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6820 +//line sql.y:6872 { yyLOCAL = &UpdateXMLExpr{Target: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion(), NewXML: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1371: + case 1382: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6826 +//line sql.y:6878 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatBytesType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1372: + case 1383: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6830 +//line sql.y:6882 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatPicoTimeType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1373: + case 1384: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:6834 +//line sql.y:6886 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsCurrentThreadIDType} } yyVAL.union = yyLOCAL - case 1374: + case 1385: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6838 +//line sql.y:6890 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsThreadIDType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1375: + case 1386: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6844 +//line sql.y:6896 { yyLOCAL = >IDFuncExpr{Type: GTIDSubsetType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1376: + case 1387: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6848 +//line sql.y:6900 { yyLOCAL = >IDFuncExpr{Type: GTIDSubtractType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1377: + case 1388: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6852 +//line sql.y:6904 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1378: + case 1389: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6856 +//line sql.y:6908 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1379: + case 1390: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6860 +//line sql.y:6912 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1380: + case 1391: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6864 +//line sql.y:6916 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1381: + case 1392: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6868 +//line sql.y:6920 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion(), Channel: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1382: + case 1393: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:6873 +//line sql.y:6925 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1383: + case 1394: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:6877 +//line sql.y:6929 { yyLOCAL = yyDollar[2].convertTypeUnion() } yyVAL.union = yyLOCAL - case 1384: + case 1395: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6883 +//line sql.y:6935 { yyLOCAL = IntervalDayHour } yyVAL.union = yyLOCAL - case 1385: + case 1396: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6887 +//line sql.y:6939 { yyLOCAL = IntervalDayMicrosecond } yyVAL.union = yyLOCAL - case 1386: + case 1397: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6891 +//line sql.y:6943 { yyLOCAL = IntervalDayMinute } yyVAL.union = yyLOCAL - case 1387: + case 1398: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6895 +//line sql.y:6947 { yyLOCAL = IntervalDaySecond } yyVAL.union = yyLOCAL - case 1388: + case 1399: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6899 +//line sql.y:6951 { yyLOCAL = IntervalHourMicrosecond } yyVAL.union = yyLOCAL - case 1389: + case 1400: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6903 +//line sql.y:6955 { yyLOCAL = IntervalHourMinute } yyVAL.union = yyLOCAL - case 1390: + case 1401: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6907 +//line sql.y:6959 { yyLOCAL = IntervalHourSecond } yyVAL.union = yyLOCAL - case 1391: + case 1402: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6911 +//line sql.y:6963 { yyLOCAL = IntervalMinuteMicrosecond } yyVAL.union = yyLOCAL - case 1392: + case 1403: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6915 +//line sql.y:6967 { yyLOCAL = IntervalMinuteSecond } yyVAL.union = yyLOCAL - case 1393: + case 1404: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6919 +//line sql.y:6971 { yyLOCAL = IntervalSecondMicrosecond } yyVAL.union = yyLOCAL - case 1394: + case 1405: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6923 +//line sql.y:6975 { yyLOCAL = IntervalYearMonth } yyVAL.union = yyLOCAL - case 1395: + case 1406: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6927 +//line sql.y:6979 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1396: + case 1407: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6931 +//line sql.y:6983 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1397: + case 1408: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6935 +//line sql.y:6987 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1398: + case 1409: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6939 +//line sql.y:6991 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1399: + case 1410: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6943 +//line sql.y:6995 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1400: + case 1411: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6947 +//line sql.y:6999 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1401: + case 1412: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6951 +//line sql.y:7003 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1402: + case 1413: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6955 +//line sql.y:7007 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1403: + case 1414: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6959 +//line sql.y:7011 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1404: + case 1415: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6965 +//line sql.y:7017 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1405: + case 1416: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6969 +//line sql.y:7021 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1406: + case 1417: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6973 +//line sql.y:7025 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1407: + case 1418: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6977 +//line sql.y:7029 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1408: + case 1419: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6981 +//line sql.y:7033 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1409: + case 1420: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6985 +//line sql.y:7037 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1410: + case 1421: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6989 +//line sql.y:7041 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1411: + case 1422: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6993 +//line sql.y:7045 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1412: + case 1423: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6997 +//line sql.y:7049 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1413: + case 1424: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7001 +//line sql.y:7053 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1414: + case 1425: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7005 +//line sql.y:7057 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1415: + case 1426: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7009 +//line sql.y:7061 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1416: + case 1427: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7013 +//line sql.y:7065 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1417: + case 1428: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7017 +//line sql.y:7069 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1418: + case 1429: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7021 +//line sql.y:7073 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1419: + case 1430: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7025 +//line sql.y:7077 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1420: + case 1431: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7029 +//line sql.y:7081 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1421: + case 1432: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7033 +//line sql.y:7085 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1424: + case 1435: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:7043 +//line sql.y:7095 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1425: + case 1436: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:7047 +//line sql.y:7099 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1426: + case 1437: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:7051 +//line sql.y:7103 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1427: + case 1438: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7061 +//line sql.y:7113 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("if"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1428: + case 1439: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7065 +//line sql.y:7117 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("database"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1429: + case 1440: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7069 +//line sql.y:7121 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("schema"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1430: + case 1441: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7073 +//line sql.y:7125 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("mod"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1431: + case 1442: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7077 +//line sql.y:7129 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("replace"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1432: + case 1443: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7083 +//line sql.y:7135 { yyLOCAL = NoOption } yyVAL.union = yyLOCAL - case 1433: + case 1444: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7087 +//line sql.y:7139 { yyLOCAL = BooleanModeOpt } yyVAL.union = yyLOCAL - case 1434: + case 1445: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7091 +//line sql.y:7143 { yyLOCAL = NaturalLanguageModeOpt } yyVAL.union = yyLOCAL - case 1435: + case 1446: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7095 +//line sql.y:7147 { yyLOCAL = NaturalLanguageModeWithQueryExpansionOpt } yyVAL.union = yyLOCAL - case 1436: + case 1447: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7099 +//line sql.y:7151 { yyLOCAL = QueryExpansionOpt } yyVAL.union = yyLOCAL - case 1437: + case 1448: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7105 +//line sql.y:7157 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 1438: + case 1449: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7109 +//line sql.y:7161 { yyVAL.str = string(yyDollar[1].str) } - case 1439: + case 1450: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7113 +//line sql.y:7165 { yyVAL.str = string(yyDollar[1].str) } - case 1440: + case 1451: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7119 +//line sql.y:7171 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1441: + case 1452: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7123 +//line sql.y:7175 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1442: + case 1453: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7127 +//line sql.y:7179 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1443: + case 1454: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7133 +//line sql.y:7185 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1444: + case 1455: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7137 +//line sql.y:7189 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } yyVAL.union = yyLOCAL - case 1445: + case 1456: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7141 +//line sql.y:7193 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1446: + case 1457: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7145 +//line sql.y:7197 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1447: + case 1458: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7149 +//line sql.y:7201 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} yyLOCAL.Length = yyDollar[2].LengthScaleOption.Length yyLOCAL.Scale = yyDollar[2].LengthScaleOption.Scale } yyVAL.union = yyLOCAL - case 1448: + case 1459: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7155 +//line sql.y:7207 { 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:7159 +//line sql.y:7211 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1450: + case 1461: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7163 +//line sql.y:7215 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1451: + case 1462: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7167 +//line sql.y:7219 { 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:7171 +//line sql.y:7223 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1453: + case 1464: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7175 +//line sql.y:7227 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1454: + case 1465: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7179 +//line sql.y:7231 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1455: + case 1466: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7183 +//line sql.y:7235 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1456: + case 1467: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7187 +//line sql.y:7239 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1457: + case 1468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7191 +//line sql.y:7243 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1458: + case 1469: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7197 +//line sql.y:7249 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1459: + case 1470: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:7201 +//line sql.y:7253 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1460: + case 1471: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7206 +//line sql.y:7258 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1461: + case 1472: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7210 +//line sql.y:7262 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1462: + case 1473: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7215 +//line sql.y:7267 { yyVAL.str = string("") } - case 1463: + case 1474: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7219 +//line sql.y:7271 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 1464: + case 1475: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*When -//line sql.y:7225 +//line sql.y:7277 { yyLOCAL = []*When{yyDollar[1].whenUnion()} } yyVAL.union = yyLOCAL - case 1465: + case 1476: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7229 +//line sql.y:7281 { yySLICE := (*[]*When)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].whenUnion()) } - case 1466: + case 1477: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *When -//line sql.y:7235 +//line sql.y:7287 { yyLOCAL = &When{Cond: yyDollar[2].exprUnion(), Val: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1467: + case 1478: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7240 +//line sql.y:7292 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1468: + case 1479: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7244 +//line sql.y:7296 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1469: + case 1480: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7250 +//line sql.y:7302 { yyLOCAL = &ColName{Name: yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1470: + case 1481: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7254 +//line sql.y:7306 { yyLOCAL = &ColName{Name: NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 1471: + case 1482: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColName -//line sql.y:7258 +//line sql.y:7310 { yyLOCAL = &ColName{Qualifier: TableName{Name: yyDollar[1].identifierCS}, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1472: + case 1483: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColName -//line sql.y:7262 +//line sql.y:7314 { yyLOCAL = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}, Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 1473: + case 1484: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7268 +//line sql.y:7320 { yyLOCAL = yyDollar[1].colNameUnion() } yyVAL.union = yyLOCAL - case 1474: + case 1485: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7272 +//line sql.y:7324 { yyLOCAL = &Offset{V: convertStringToInt(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1475: + case 1486: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7278 +//line sql.y:7330 { // TODO(sougou): Deprecate this construct. if yyDollar[1].identifierCI.Lowered() != "value" { @@ -21300,442 +21523,442 @@ yydefault: yyLOCAL = NewIntLiteral("1") } yyVAL.union = yyLOCAL - case 1476: + case 1487: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7287 +//line sql.y:7339 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1477: + case 1488: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7291 +//line sql.y:7343 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1478: + case 1489: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7296 +//line sql.y:7348 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1479: + case 1490: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7300 +//line sql.y:7352 { yyLOCAL = &GroupBy{Exprs: yyDollar[3].exprsUnion(), WithRollup: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 1480: + case 1491: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7305 +//line sql.y:7357 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1481: + case 1492: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:7309 +//line sql.y:7361 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1482: + case 1493: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7315 +//line sql.y:7367 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1483: + case 1494: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7319 +//line sql.y:7371 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1484: + case 1495: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *NamedWindow -//line sql.y:7325 +//line sql.y:7377 { yyLOCAL = &NamedWindow{yyDollar[2].windowDefinitionsUnion()} } yyVAL.union = yyLOCAL - case 1485: + case 1496: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7331 +//line sql.y:7383 { yyLOCAL = NamedWindows{yyDollar[1].namedWindowUnion()} } yyVAL.union = yyLOCAL - case 1486: + case 1497: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7335 +//line sql.y:7387 { yySLICE := (*NamedWindows)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].namedWindowUnion()) } - case 1487: + case 1498: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL NamedWindows -//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 NamedWindows -//line sql.y:7344 +//line sql.y:7396 { yyLOCAL = yyDollar[1].namedWindowsUnion() } yyVAL.union = yyLOCAL - case 1489: + case 1500: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7349 +//line sql.y:7401 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1490: + case 1501: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7353 +//line sql.y:7405 { yyLOCAL = yyDollar[1].orderByUnion() } yyVAL.union = yyLOCAL - case 1491: + case 1502: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7359 +//line sql.y:7411 { yyLOCAL = yyDollar[3].orderByUnion() } yyVAL.union = yyLOCAL - case 1492: + case 1503: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7365 +//line sql.y:7417 { yyLOCAL = OrderBy{yyDollar[1].orderUnion()} } yyVAL.union = yyLOCAL - case 1493: + case 1504: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7369 +//line sql.y:7421 { yySLICE := (*OrderBy)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].orderUnion()) } - case 1494: + case 1505: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Order -//line sql.y:7375 +//line sql.y:7427 { yyLOCAL = &Order{Expr: yyDollar[1].exprUnion(), Direction: yyDollar[2].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 1495: + case 1506: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7380 +//line sql.y:7432 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1496: + case 1507: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7384 +//line sql.y:7436 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1497: + case 1508: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7388 +//line sql.y:7440 { yyLOCAL = DescOrder } yyVAL.union = yyLOCAL - case 1498: + case 1509: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Limit -//line sql.y:7393 +//line sql.y:7445 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1499: + case 1510: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Limit -//line sql.y:7397 +//line sql.y:7449 { yyLOCAL = yyDollar[1].limitUnion() } yyVAL.union = yyLOCAL - case 1500: + case 1511: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Limit -//line sql.y:7403 +//line sql.y:7455 { yyLOCAL = &Limit{Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1501: + case 1512: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7407 +//line sql.y:7459 { yyLOCAL = &Limit{Offset: yyDollar[2].exprUnion(), Rowcount: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1502: + case 1513: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7411 +//line sql.y:7463 { yyLOCAL = &Limit{Offset: yyDollar[4].exprUnion(), Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1503: + case 1514: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7416 +//line sql.y:7468 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1504: + case 1515: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7420 +//line sql.y:7472 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1505: + case 1516: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7424 +//line sql.y:7476 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1506: + case 1517: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7428 +//line sql.y:7480 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1507: + case 1518: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7432 +//line sql.y:7484 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1508: + case 1519: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7439 +//line sql.y:7491 { yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL - case 1509: + case 1520: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7443 +//line sql.y:7495 { yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL - case 1510: + case 1521: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7447 +//line sql.y:7499 { yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL - case 1511: + case 1522: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7451 +//line sql.y:7503 { yyLOCAL = &LockOption{Type: ExclusiveType} } yyVAL.union = yyLOCAL - case 1512: + case 1523: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7457 +//line sql.y:7509 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1513: + case 1524: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7461 +//line sql.y:7513 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1514: + case 1525: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7465 +//line sql.y:7517 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1515: + case 1526: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7469 +//line sql.y:7521 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1516: + case 1527: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7474 +//line sql.y:7526 { yyVAL.str = "" } - case 1517: + case 1528: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7478 +//line sql.y:7530 { yyVAL.str = string(yyDollar[3].str) } - case 1518: + case 1529: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7482 +//line sql.y:7534 { yyVAL.str = string(yyDollar[3].str) } - case 1519: + case 1530: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7486 +//line sql.y:7538 { yyVAL.str = string(yyDollar[3].str) } - case 1520: + case 1531: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7491 +//line sql.y:7543 { yyVAL.str = "" } - case 1521: + case 1532: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7495 +//line sql.y:7547 { yyVAL.str = yyDollar[3].str } - case 1522: + case 1533: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7501 +//line sql.y:7553 { yyVAL.str = string(yyDollar[1].str) } - case 1523: + case 1534: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7505 +//line sql.y:7557 { yyVAL.str = string(yyDollar[1].str) } - case 1524: + case 1535: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7510 +//line sql.y:7562 { yyVAL.str = "" } - case 1525: + case 1536: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:7514 +//line sql.y:7566 { yyVAL.str = yyDollar[2].str } - case 1526: + case 1537: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7519 +//line sql.y:7571 { yyVAL.str = "cascaded" } - case 1527: + case 1538: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7523 +//line sql.y:7575 { yyVAL.str = string(yyDollar[1].str) } - case 1528: + case 1539: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7527 +//line sql.y:7579 { yyVAL.str = string(yyDollar[1].str) } - case 1529: + case 1540: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Definer -//line sql.y:7532 +//line sql.y:7584 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1530: + case 1541: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:7536 +//line sql.y:7588 { yyLOCAL = yyDollar[3].definerUnion() } yyVAL.union = yyLOCAL - case 1531: + case 1542: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Definer -//line sql.y:7542 +//line sql.y:7594 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1532: + case 1543: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:7548 +//line sql.y:7600 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1533: + case 1544: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Definer -//line sql.y:7554 +//line sql.y:7606 { yyLOCAL = &Definer{ Name: yyDollar[1].str, @@ -21743,433 +21966,433 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1534: + case 1545: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7563 +//line sql.y:7615 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 1535: + case 1546: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7567 +//line sql.y:7619 { yyVAL.str = formatIdentifier(yyDollar[1].str) } - case 1536: + case 1547: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7572 +//line sql.y:7624 { yyVAL.str = "" } - case 1537: + case 1548: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7576 +//line sql.y:7628 { yyVAL.str = formatAddress(yyDollar[1].str) } - case 1538: + case 1549: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:7582 +//line sql.y:7634 { yyLOCAL = ForUpdateLock } yyVAL.union = yyLOCAL - case 1539: + case 1550: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:7586 +//line sql.y:7638 { yyLOCAL = ForUpdateLockNoWait } yyVAL.union = yyLOCAL - case 1540: + case 1551: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7590 +//line sql.y:7642 { yyLOCAL = ForUpdateLockSkipLocked } yyVAL.union = yyLOCAL - case 1541: + case 1552: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:7594 +//line sql.y:7646 { yyLOCAL = ForShareLock } yyVAL.union = yyLOCAL - case 1542: + case 1553: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:7598 +//line sql.y:7650 { yyLOCAL = ForShareLockNoWait } yyVAL.union = yyLOCAL - case 1543: + case 1554: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7602 +//line sql.y:7654 { yyLOCAL = ForShareLockSkipLocked } yyVAL.union = yyLOCAL - case 1544: + case 1555: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7606 +//line sql.y:7658 { yyLOCAL = ShareModeLock } yyVAL.union = yyLOCAL - case 1545: + case 1556: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7612 +//line sql.y:7664 { 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 1546: + case 1557: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7616 +//line sql.y:7668 { yyLOCAL = &SelectInto{Type: IntoDumpfile, FileName: encodeSQLString(yyDollar[3].str), Charset: ColumnCharset{}, FormatOption: "", ExportOption: "", Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1547: + case 1558: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7620 +//line sql.y:7672 { yyLOCAL = &SelectInto{Type: IntoOutfile, FileName: encodeSQLString(yyDollar[3].str), Charset: yyDollar[4].columnCharset, FormatOption: "", ExportOption: yyDollar[5].str, Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1548: + case 1559: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7625 +//line sql.y:7677 { yyVAL.str = "" } - case 1549: + case 1560: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7629 +//line sql.y:7681 { yyVAL.str = " format csv" + yyDollar[3].str } - case 1550: + case 1561: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7633 +//line sql.y:7685 { yyVAL.str = " format text" + yyDollar[3].str } - 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-1 : yypt+1] -//line sql.y:7642 +//line sql.y:7694 { yyVAL.str = " header" } - case 1553: + case 1564: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7647 +//line sql.y:7699 { yyVAL.str = "" } - case 1554: + case 1565: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7651 +//line sql.y:7703 { yyVAL.str = " manifest on" } - case 1555: + case 1566: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7655 +//line sql.y:7707 { yyVAL.str = " manifest off" } - case 1556: + case 1567: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7660 +//line sql.y:7712 { yyVAL.str = "" } - case 1557: + case 1568: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7664 +//line sql.y:7716 { yyVAL.str = " overwrite on" } - case 1558: + case 1569: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7668 +//line sql.y:7720 { yyVAL.str = " overwrite off" } - case 1559: + case 1570: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7674 +//line sql.y:7726 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1560: + case 1571: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7679 +//line sql.y:7731 { yyVAL.str = "" } - case 1561: + case 1572: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7683 +//line sql.y:7735 { yyVAL.str = " lines" + yyDollar[2].str } - case 1562: + case 1573: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7689 +//line sql.y:7741 { yyVAL.str = yyDollar[1].str } - case 1563: + case 1574: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7693 +//line sql.y:7745 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1564: + case 1575: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7699 +//line sql.y:7751 { yyVAL.str = " starting by " + encodeSQLString(yyDollar[3].str) } - case 1565: + case 1576: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7703 +//line sql.y:7755 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1566: + case 1577: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7708 +//line sql.y:7760 { yyVAL.str = "" } - case 1567: + case 1578: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7712 +//line sql.y:7764 { yyVAL.str = " " + yyDollar[1].str + yyDollar[2].str } - case 1568: + case 1579: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7718 +//line sql.y:7770 { yyVAL.str = yyDollar[1].str } - case 1569: + case 1580: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7722 +//line sql.y:7774 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1570: + case 1581: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7728 +//line sql.y:7780 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1571: + case 1582: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:7732 +//line sql.y:7784 { yyVAL.str = yyDollar[1].str + " enclosed by " + encodeSQLString(yyDollar[4].str) } - case 1572: + case 1583: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7736 +//line sql.y:7788 { yyVAL.str = " escaped by " + encodeSQLString(yyDollar[3].str) } - case 1573: + case 1584: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7741 +//line sql.y:7793 { yyVAL.str = "" } - case 1574: + case 1585: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7745 +//line sql.y:7797 { yyVAL.str = " optionally" } - case 1575: + case 1586: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Insert -//line sql.y:7758 +//line sql.y:7810 { yyLOCAL = &Insert{Rows: yyDollar[2].valuesUnion(), RowAlias: yyDollar[3].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1576: + case 1587: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Insert -//line sql.y:7762 +//line sql.y:7814 { yyLOCAL = &Insert{Rows: yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1577: + case 1588: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *Insert -//line sql.y:7766 +//line sql.y:7818 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[5].valuesUnion(), RowAlias: yyDollar[6].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1578: + case 1589: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *Insert -//line sql.y:7770 +//line sql.y:7822 { yyLOCAL = &Insert{Columns: []IdentifierCI{}, Rows: yyDollar[4].valuesUnion(), RowAlias: yyDollar[5].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1579: + case 1590: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Insert -//line sql.y:7774 +//line sql.y:7826 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[4].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1580: + case 1591: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:7780 +//line sql.y:7832 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1581: + case 1592: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:7784 +//line sql.y:7836 { yyLOCAL = Columns{yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1582: + case 1593: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7788 +//line sql.y:7840 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1583: + case 1594: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:7792 +//line sql.y:7844 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[5].identifierCI) } - case 1584: + case 1595: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7797 +//line sql.y:7849 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1585: + case 1596: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7801 +//line sql.y:7853 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 1586: + case 1597: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7805 +//line sql.y:7857 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1587: + case 1598: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7810 +//line sql.y:7862 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1588: + case 1599: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7814 +//line sql.y:7866 { yyLOCAL = yyDollar[5].updateExprsUnion() } yyVAL.union = yyLOCAL - case 1589: + case 1600: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Values -//line sql.y:7820 +//line sql.y:7872 { yyLOCAL = Values{yyDollar[1].valTupleUnion()} } yyVAL.union = yyLOCAL - case 1590: + case 1601: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7824 +//line sql.y:7876 { yySLICE := (*Values)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].valTupleUnion()) } - case 1591: + case 1602: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7830 +//line sql.y:7882 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1592: + case 1603: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7834 +//line sql.y:7886 { yyLOCAL = ValTuple{} } yyVAL.union = yyLOCAL - case 1593: + case 1604: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7840 +//line sql.y:7892 { yyLOCAL = ValTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 1594: + case 1605: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7844 +//line sql.y:7896 { yyLOCAL = ValTuple(yyDollar[3].exprsUnion()) } yyVAL.union = yyLOCAL - case 1595: + case 1606: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7849 +//line sql.y:7901 { if len(yyDollar[1].valTupleUnion()) == 1 { yyLOCAL = yyDollar[1].valTupleUnion()[0] @@ -22178,300 +22401,300 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1596: + case 1607: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7859 +//line sql.y:7911 { yyLOCAL = UpdateExprs{yyDollar[1].updateExprUnion()} } yyVAL.union = yyLOCAL - case 1597: + case 1608: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7863 +//line sql.y:7915 { yySLICE := (*UpdateExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].updateExprUnion()) } - case 1598: + case 1609: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *UpdateExpr -//line sql.y:7869 +//line sql.y:7921 { yyLOCAL = &UpdateExpr{Name: yyDollar[1].colNameUnion(), Expr: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1600: + case 1611: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7876 +//line sql.y:7928 { yyVAL.str = "charset" } - case 1603: + case 1614: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7886 +//line sql.y:7938 { yyLOCAL = NewStrLiteral(yyDollar[1].identifierCI.String()) } yyVAL.union = yyLOCAL - case 1604: + case 1615: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7890 +//line sql.y:7942 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1605: + case 1616: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7894 +//line sql.y:7946 { yyLOCAL = &Default{} } yyVAL.union = yyLOCAL - case 1608: + case 1619: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7903 +//line sql.y:7955 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1609: + case 1620: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:7905 +//line sql.y:7957 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1610: + case 1621: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7908 +//line sql.y:7960 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1611: + case 1622: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:7910 +//line sql.y:7962 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1612: + case 1623: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7913 +//line sql.y:7965 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1613: + case 1624: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line sql.y:7915 +//line sql.y:7967 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1614: + case 1625: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Ignore -//line sql.y:7918 +//line sql.y:7970 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1615: + case 1626: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Ignore -//line sql.y:7920 +//line sql.y:7972 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1616: + case 1627: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7923 +//line sql.y:7975 { yyVAL.empty = struct{}{} } - case 1617: + case 1628: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7925 +//line sql.y:7977 { yyVAL.empty = struct{}{} } - case 1618: + case 1629: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7927 +//line sql.y:7979 { yyVAL.empty = struct{}{} } - case 1619: + case 1630: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:7931 +//line sql.y:7983 { yyLOCAL = &CallProc{Name: yyDollar[2].tableName, Params: yyDollar[4].exprsUnion()} } yyVAL.union = yyLOCAL - case 1620: + case 1631: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Exprs -//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 Exprs -//line sql.y:7940 +//line sql.y:7992 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1622: + case 1633: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:7945 +//line sql.y:7997 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1623: + case 1634: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:7947 +//line sql.y:7999 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 1624: + case 1635: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:7951 +//line sql.y:8003 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), String: string(yyDollar[2].identifierCI.String())} } yyVAL.union = yyLOCAL - case 1625: + case 1636: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7957 +//line sql.y:8009 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1626: + case 1637: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7961 +//line sql.y:8013 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1628: + case 1639: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7968 +//line sql.y:8020 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1629: + case 1640: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7974 +//line sql.y:8026 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1630: + case 1641: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7978 +//line sql.y:8030 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1631: + case 1642: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7984 +//line sql.y:8036 { yyVAL.identifierCS = NewIdentifierCS("") } - case 1632: + case 1643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7988 +//line sql.y:8040 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 1634: + case 1645: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7995 +//line sql.y:8047 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1635: + case 1646: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:8001 +//line sql.y:8053 { yyLOCAL = &Kill{Type: yyDollar[2].killTypeUnion(), ProcesslistID: convertStringToUInt64(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 1636: + case 1647: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL KillType -//line sql.y:8007 +//line sql.y:8059 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1637: + case 1648: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8011 +//line sql.y:8063 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1638: + case 1649: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8015 +//line sql.y:8067 { yyLOCAL = QueryType } yyVAL.union = yyLOCAL - case 2261: + case 2279: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8666 +//line sql.y:8725 { } - case 2262: + case 2280: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8671 +//line sql.y:8730 { } - case 2263: + case 2281: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8675 +//line sql.y:8734 { skipToEnd(yylex) } - case 2264: + case 2282: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8680 +//line sql.y:8739 { skipToEnd(yylex) } - case 2265: + case 2283: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8684 +//line sql.y:8743 { skipToEnd(yylex) } - case 2266: + case 2284: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8688 +//line sql.y:8747 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 7686aeaa726..64ce957d2dd 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,12 +259,12 @@ 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 @@ -330,6 +336,7 @@ func markBindVariable(yylex yyLexer, bvar string) { // Transaction Tokens %token BEGIN START TRANSACTION COMMIT ROLLBACK SAVEPOINT RELEASE WORK %token CONSISTENT SNAPSHOT +%token UNRESOLVED TRANSACTIONS // Type Tokens %token BIT TINYINT SMALLINT MEDIUMINT INT INTEGER BIGINT INTNUM @@ -341,6 +348,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 @@ -545,7 +554,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 @@ -746,7 +755,7 @@ with_list: common_table_expr: table_id column_list_opt AS subquery { - $$ = &CommonTableExpr{ID: $1, Columns: $2, Subquery: $4} + $$ = &CommonTableExpr{ID: $1, Columns: $2, Subquery: $4.Select} } query_expression_parens: @@ -2172,6 +2181,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 { @@ -3302,6 +3315,12 @@ alter_statement: UUID: string($4), } } +| ALTER comment_opt VITESS_MIGRATION CLEANUP ALL + { + $$ = &AlterMigration{ + Type: CleanupAllMigrationType, + } + } | ALTER comment_opt VITESS_MIGRATION STRING LAUNCH { $$ = &AlterMigration{ @@ -4218,6 +4237,23 @@ show_statement: { $$ = &Show{&ShowOther{Command: string($2)}} } +| SHOW TRANSACTION STATUS for_opt STRING + { + $$ = &Show{&ShowTransactionStatus{TransactionID: string($5)}} + } +| SHOW UNRESOLVED TRANSACTIONS + { + $$ = &Show{&ShowTransactionStatus{}} + } +| SHOW UNRESOLVED TRANSACTIONS FOR table_id + { + $$ = &Show{&ShowTransactionStatus{Keyspace: $5.String()}} + } + +for_opt: + {} +| FOR + {} extended_opt: /* empty */ @@ -4795,10 +4831,10 @@ deallocate_statement: } select_options_opt: - { + %prec SELECT_OPTIONS { $$ = nil } -| select_options +| select_options %prec SELECT_OPTIONS { $$ = $1 } @@ -4830,10 +4866,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 @@ -8083,6 +8135,7 @@ reserved_keyword: | GROUPING | GROUPS | HAVING +| HIGH_PRIORITY | IF | IGNORE | IN @@ -8151,6 +8204,8 @@ reserved_keyword: | SET | SHOW | SPATIAL +| SQL_BIG_RESULT +| SQL_SMALL_RESULT | STORED | STRAIGHT_JOIN | SYSDATE @@ -8497,6 +8552,7 @@ non_reserved_keyword: | SNAPSHOT | SOME %prec ANY_SOME | SQL +| SQL_BUFFER_RESULT | SQL_TSI_DAY | SQL_TSI_HOUR | SQL_TSI_MINUTE @@ -8587,6 +8643,7 @@ non_reserved_keyword: | TINYTEXT | TRADITIONAL | TRANSACTION +| TRANSACTIONS | TREE | TRIGGER | TRIGGERS @@ -8597,6 +8654,7 @@ non_reserved_keyword: | UNDEFINED | UNICODE | UNKNOWN +| UNRESOLVED | UNSIGNED | UNTHROTTLE | UNUSED @@ -8612,6 +8670,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 6fedca5ddfd..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)); @@ -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")); @@ -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); @@ -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); @@ -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)); @@ -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; diff --git a/go/vt/sysvars/sysvars.go b/go/vt/sysvars/sysvars.go index c8037563ca1..297ed956bf8 100644 --- a/go/vt/sysvars/sysvars.go +++ b/go/vt/sysvars/sysvars.go @@ -191,6 +191,7 @@ var ( {Name: ForeignKeyChecks, IsBoolean: true, SupportSetVar: true}, {Name: "group_concat_max_len", SupportSetVar: true}, {Name: "information_schema_stats_expiry"}, + {Name: "innodb_lock_wait_timeout"}, {Name: "max_heap_table_size", SupportSetVar: true}, {Name: "max_seeks_for_key", SupportSetVar: true}, {Name: "max_tmp_tables"}, @@ -246,7 +247,6 @@ var ( {Name: "collation_server"}, {Name: "completion_type"}, {Name: "div_precision_increment", SupportSetVar: true}, - {Name: "innodb_lock_wait_timeout"}, {Name: "interactive_timeout"}, {Name: "lc_time_names"}, {Name: "lock_wait_timeout", SupportSetVar: true}, 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 f2a3e8774e7..23b7be6cfa1 100644 --- a/go/vt/topo/server.go +++ b/go/vt/topo/server.go @@ -95,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.go b/go/vt/topo/shard.go index 77983f20d2d..ba3a02a68ca 100644 --- a/go/vt/topo/shard.go +++ b/go/vt/topo/shard.go @@ -19,6 +19,7 @@ package topo import ( "context" "encoding/hex" + "errors" "fmt" "path" "slices" @@ -393,7 +394,7 @@ func (si *ShardInfo) UpdateDeniedTables(ctx context.Context, tabletType topodata return err } if tabletType == topodatapb.TabletType_PRIMARY && len(cells) > 0 { - return fmt.Errorf(dlNoCellsForPrimary) + return errors.New(dlNoCellsForPrimary) } tc := si.GetTabletControl(tabletType) if tc == nil { 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/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/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/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/vtadmin/api.go b/go/vt/vtadmin/api.go index 1e83875de35..530b57ccdee 100644 --- a/go/vt/vtadmin/api.go +++ b/go/vt/vtadmin/api.go @@ -32,7 +32,9 @@ import ( "github.com/gorilla/mux" "github.com/patrickmn/go-cache" + vreplcommon "vitess.io/vitess/go/cmd/vtctldclient/command/vreplication/common" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/textutil" "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/sets" @@ -56,6 +58,8 @@ import ( "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtexplain" + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtadminpb "vitess.io/vitess/go/vt/proto/vtadmin" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" @@ -417,6 +421,9 @@ func (api *API) Handler() http.Handler { router.HandleFunc("/vtexplain", httpAPI.Adapt(vtadminhttp.VTExplain)).Name("API.VTExplain") router.HandleFunc("/workflow/{cluster_id}/{keyspace}/{name}", httpAPI.Adapt(vtadminhttp.GetWorkflow)).Name("API.GetWorkflow") router.HandleFunc("/workflows", httpAPI.Adapt(vtadminhttp.GetWorkflows)).Name("API.GetWorkflows") + router.HandleFunc("/workflow/{cluster_id}/{keyspace}/{name}/status", httpAPI.Adapt(vtadminhttp.GetWorkflowStatus)).Name("API.GetWorkflowStatus") + router.HandleFunc("/workflow/{cluster_id}/{keyspace}/{name}/start", httpAPI.Adapt(vtadminhttp.StartWorkflow)).Name("API.StartWorkflow") + router.HandleFunc("/workflow/{cluster_id}/{keyspace}/{name}/stop", httpAPI.Adapt(vtadminhttp.StopWorkflow)).Name("API.StopWorkflow") experimentalRouter := router.PathPrefix("/experimental").Subrouter() experimentalRouter.HandleFunc("/tablet/{tablet}/debug/vars", httpAPI.Adapt(experimental.TabletDebugVarsPassthrough)).Name("API.TabletDebugVarsPassthrough") @@ -1662,6 +1669,97 @@ func (api *API) GetWorkflow(ctx context.Context, req *vtadminpb.GetWorkflowReque }) } +// GetWorkflowStatus is part of the vtadminpb.VTAdminServer interface. +func (api *API) GetWorkflowStatus(ctx context.Context, req *vtadminpb.GetWorkflowStatusRequest) (*vtctldatapb.WorkflowStatusResponse, error) { + span, ctx := trace.NewSpan(ctx, "API.GetWorkflowStatus") + defer span.Finish() + + c, err := api.getClusterForRequest(req.ClusterId) + if err != nil { + return nil, err + } + + cluster.AnnotateSpan(c, span) + span.Annotate("keyspace", req.Keyspace) + span.Annotate("workflow_name", req.Name) + + if !api.authz.IsAuthorized(ctx, c.ID, rbac.WorkflowResource, rbac.GetAction) { + return nil, nil + } + + return c.Vtctld.WorkflowStatus(ctx, &vtctldatapb.WorkflowStatusRequest{ + Keyspace: req.Keyspace, + Workflow: req.Name, + }) +} + +// StartWorkflow is part of the vtadminpb.VTAdminServer interface. +func (api *API) StartWorkflow(ctx context.Context, req *vtadminpb.StartWorkflowRequest) (*vtctldatapb.WorkflowUpdateResponse, error) { + span, ctx := trace.NewSpan(ctx, "API.StartWorkflow") + defer span.Finish() + + c, err := api.getClusterForRequest(req.ClusterId) + if err != nil { + return nil, err + } + + cluster.AnnotateSpan(c, span) + span.Annotate("keyspace", req.Keyspace) + span.Annotate("workflow_name", req.Workflow) + + if !api.authz.IsAuthorized(ctx, c.ID, rbac.WorkflowResource, rbac.PutAction) { + return nil, nil + } + + vreplcommon.SetClient(c.Vtctld) + vreplcommon.SetCommandCtx(ctx) + + if err := vreplcommon.CanRestartWorkflow(req.Keyspace, req.Workflow); err != nil { + return nil, err + } + + return c.Vtctld.WorkflowUpdate(ctx, &vtctldatapb.WorkflowUpdateRequest{ + Keyspace: req.Keyspace, + TabletRequest: &tabletmanagerdatapb.UpdateVReplicationWorkflowRequest{ + Workflow: req.Workflow, + Cells: textutil.SimulatedNullStringSlice, + TabletTypes: []topodatapb.TabletType{topodatapb.TabletType(textutil.SimulatedNullInt)}, + OnDdl: binlogdatapb.OnDDLAction(textutil.SimulatedNullInt), + State: binlogdatapb.VReplicationWorkflowState_Running, + }, + }) +} + +// StopWorkflow is part of the vtadminpb.VTAdminServer interface. +func (api *API) StopWorkflow(ctx context.Context, req *vtadminpb.StopWorkflowRequest) (*vtctldatapb.WorkflowUpdateResponse, error) { + span, ctx := trace.NewSpan(ctx, "API.StopWorkflow") + defer span.Finish() + + c, err := api.getClusterForRequest(req.ClusterId) + if err != nil { + return nil, err + } + + cluster.AnnotateSpan(c, span) + span.Annotate("keyspace", req.Keyspace) + span.Annotate("workflow_name", req.Workflow) + + if !api.authz.IsAuthorized(ctx, c.ID, rbac.WorkflowResource, rbac.PutAction) { + return nil, nil + } + + return c.Vtctld.WorkflowUpdate(ctx, &vtctldatapb.WorkflowUpdateRequest{ + Keyspace: req.Keyspace, + TabletRequest: &tabletmanagerdatapb.UpdateVReplicationWorkflowRequest{ + Workflow: req.Workflow, + Cells: textutil.SimulatedNullStringSlice, + TabletTypes: []topodatapb.TabletType{topodatapb.TabletType(textutil.SimulatedNullInt)}, + OnDdl: binlogdatapb.OnDDLAction(textutil.SimulatedNullInt), + State: binlogdatapb.VReplicationWorkflowState_Stopped, + }, + }) +} + // GetWorkflows is part of the vtadminpb.VTAdminServer interface. func (api *API) GetWorkflows(ctx context.Context, req *vtadminpb.GetWorkflowsRequest) (*vtadminpb.GetWorkflowsResponse, error) { span, ctx := trace.NewSpan(ctx, "API.GetWorkflows") diff --git a/go/vt/vtadmin/http/workflows.go b/go/vt/vtadmin/http/workflows.go index 80c6dff775b..d0846844f9d 100644 --- a/go/vt/vtadmin/http/workflows.go +++ b/go/vt/vtadmin/http/workflows.go @@ -69,3 +69,51 @@ func GetWorkflows(ctx context.Context, r Request, api *API) *JSONResponse { return NewJSONResponse(workflows, err) } + +// GetWorkflowStatus implements the http wrapper for the VTAdminServer.GetWorkflowStatus +// method. +// +// Its route is /workflow/{cluster_id}/{keyspace}/{name}/status +func GetWorkflowStatus(ctx context.Context, r Request, api *API) *JSONResponse { + vars := r.Vars() + + workflowStatus, err := api.server.GetWorkflowStatus(ctx, &vtadminpb.GetWorkflowStatusRequest{ + ClusterId: vars["cluster_id"], + Keyspace: vars["keyspace"], + Name: vars["name"], + }) + + return NewJSONResponse(workflowStatus, err) +} + +// StartWorkflow implements the http wrapper for the VTAdminServer.StartWorkflow +// method. +// +// Its route is /workflow/{cluster_id}/{keyspace}/{name}/start +func StartWorkflow(ctx context.Context, r Request, api *API) *JSONResponse { + vars := r.Vars() + + res, err := api.server.StartWorkflow(ctx, &vtadminpb.StartWorkflowRequest{ + ClusterId: vars["cluster_id"], + Keyspace: vars["keyspace"], + Workflow: vars["name"], + }) + + return NewJSONResponse(res, err) +} + +// StopWorkflow implements the http wrapper for the VTAdminServer.StopWorkflow +// method. +// +// Its route is /workflow/{cluster_id}/{keyspace}/{name}/stop +func StopWorkflow(ctx context.Context, r Request, api *API) *JSONResponse { + vars := r.Vars() + + res, err := api.server.StopWorkflow(ctx, &vtadminpb.StopWorkflowRequest{ + ClusterId: vars["cluster_id"], + Keyspace: vars["keyspace"], + Workflow: vars["name"], + }) + + return NewJSONResponse(res, err) +} diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index 77db2d0afef..88b09846edd 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -254,7 +254,11 @@ func DeleteKs( tablet.tm.Stop() tablet.tm.Close() tablet.qsc.SchemaEngine().Close() - err := ts.DeleteTablet(ctx, tablet.alias) + err := tablet.qsc.QueryService().Close(ctx) + if err != nil { + return err + } + err = ts.DeleteTablet(ctx, tablet.alias) if err != nil { return err } @@ -322,6 +326,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 @@ -553,6 +562,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, @@ -975,6 +990,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/grpcvtctldserver/server.go b/go/vt/vtctl/grpcvtctldserver/server.go index 65f99c43694..d036cb0e8dd 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" @@ -680,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") @@ -1929,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{} @@ -1936,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 { @@ -1959,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 } @@ -2869,10 +2976,11 @@ func (s *VtctldServer) PlannedReparentShard(ctx context.Context, req *vtctldatap req.Keyspace, req.Shard, reparentutil.PlannedReparentOptions{ - AvoidPrimaryAlias: req.AvoidPrimary, - NewPrimaryAlias: req.NewPrimary, - WaitReplicasTimeout: waitReplicasTimeout, - TolerableReplLag: tolerableReplLag, + AvoidPrimaryAlias: req.AvoidPrimary, + NewPrimaryAlias: req.NewPrimary, + WaitReplicasTimeout: waitReplicasTimeout, + TolerableReplLag: tolerableReplLag, + AllowCrossCellPromotion: req.AllowCrossCellPromotion, }, ) 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 1b641488e1a..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" @@ -8296,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 { @@ -8425,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", + }, }, }, }, @@ -8451,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/reparent.go b/go/vt/vtctl/reparent.go index 4498228d9c7..192d19ed7ee 100644 --- a/go/vt/vtctl/reparent.go +++ b/go/vt/vtctl/reparent.go @@ -119,6 +119,7 @@ func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, sub keyspaceShard := subFlags.String("keyspace_shard", "", "keyspace/shard of the shard that needs to be reparented") newPrimary := subFlags.String("new_primary", "", "alias of a tablet that should be the new primary") avoidTablet := subFlags.String("avoid_tablet", "", "alias of a tablet that should not be the primary, i.e. reparent to any other tablet if this one is the primary") + allowCrossCellPromotion := subFlags.Bool("allow-cross-cell-promotion", false, "allow cross cell promotions") if err := subFlags.Parse(args); err != nil { return err @@ -153,10 +154,11 @@ func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, sub } return wr.PlannedReparentShard(ctx, keyspace, shard, reparentutil.PlannedReparentOptions{ - NewPrimaryAlias: newPrimaryAlias, - AvoidPrimaryAlias: avoidTabletAlias, - WaitReplicasTimeout: *waitReplicasTimeout, - TolerableReplLag: *tolerableReplicationLag, + NewPrimaryAlias: newPrimaryAlias, + AvoidPrimaryAlias: avoidTabletAlias, + WaitReplicasTimeout: *waitReplicasTimeout, + TolerableReplLag: *tolerableReplicationLag, + AllowCrossCellPromotion: *allowCrossCellPromotion, }) } 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..0852583bec9 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. @@ -57,10 +59,11 @@ type PlannedReparenter struct { // operations. Options are passed by value, so it is safe for callers to mutate // resue options structs for multiple calls. type PlannedReparentOptions struct { - NewPrimaryAlias *topodatapb.TabletAlias - AvoidPrimaryAlias *topodatapb.TabletAlias - WaitReplicasTimeout time.Duration - TolerableReplLag time.Duration + NewPrimaryAlias *topodatapb.TabletAlias + AvoidPrimaryAlias *topodatapb.TabletAlias + WaitReplicasTimeout time.Duration + TolerableReplLag time.Duration + AllowCrossCellPromotion bool // Private options managed internally. We use value-passing semantics to // set these options inside a PlannedReparent without leaking these details @@ -157,9 +160,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 +182,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, pr.logger) if err != nil { return true, err } @@ -220,7 +222,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 +261,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 +376,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 +490,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 +527,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 +599,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 +609,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 +619,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 +734,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..fd701f8c69b 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,11 +68,8 @@ func ElectNewPrimary( tmc tmclient.TabletManagerClient, shardInfo *topo.ShardInfo, tabletMap map[string]*topo.TabletInfo, - newPrimaryAlias *topodatapb.TabletAlias, - avoidPrimaryAlias *topodatapb.TabletAlias, - waitReplicasTimeout time.Duration, - tolerableReplLag time.Duration, - durability Durabler, + innodbBufferPoolData map[string]int, + opts *PlannedReparentOptions, // (TODO:@ajm188) it's a little gross we need to pass this, maybe embed in the context? logger logutil.Logger, ) (*topodatapb.TabletAlias, error) { @@ -84,6 +85,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) ) @@ -92,16 +94,16 @@ func ElectNewPrimary( reasonsToInvalidate := strings.Builder{} for _, tablet := range tabletMap { switch { - case newPrimaryAlias != nil: + case opts.NewPrimaryAlias != nil: // If newPrimaryAlias is provided, then that is the only valid tablet, even if it is not of type replica or in a different cell. - if !topoproto.TabletAliasEqual(tablet.Alias, newPrimaryAlias) { + if !topoproto.TabletAliasEqual(tablet.Alias, opts.NewPrimaryAlias) { reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v does not match the new primary alias provided", topoproto.TabletAliasString(tablet.Alias))) continue } - case primaryCell != "" && tablet.Alias.Cell != primaryCell: + case !opts.AllowCrossCellPromotion && primaryCell != "" && tablet.Alias.Cell != primaryCell: reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v is not in the same cell as the previous primary", topoproto.TabletAliasString(tablet.Alias))) continue - case avoidPrimaryAlias != nil && topoproto.TabletAliasEqual(tablet.Alias, avoidPrimaryAlias): + case opts.AvoidPrimaryAlias != nil && topoproto.TabletAliasEqual(tablet.Alias, opts.AvoidPrimaryAlias): reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v matches the primary alias to avoid", topoproto.TabletAliasString(tablet.Alias))) continue case tablet.Tablet.Type != topodatapb.TabletType_REPLICA: @@ -116,7 +118,7 @@ func ElectNewPrimary( // then we don't need to find the position of the said tablet for sorting. // We can just return the tablet quickly. // This check isn't required, but it saves us an RPC call that is otherwise unnecessary. - if len(candidates) == 1 && tolerableReplLag == 0 { + if len(candidates) == 1 && opts.TolerableReplLag == 0 { return candidates[0].Alias, nil } @@ -124,12 +126,13 @@ func ElectNewPrimary( tb := tablet errorGroup.Go(func() error { // find and store the positions for the tablet - pos, replLag, err := findPositionAndLagForTablet(groupCtx, tb, logger, tmc, waitReplicasTimeout) + pos, replLag, err := findPositionAndLagForTablet(groupCtx, tb, logger, tmc, opts.WaitReplicasTimeout) mu.Lock() defer mu.Unlock() - if err == nil && (tolerableReplLag == 0 || tolerableReplLag >= replLag) { + if err == nil && (opts.TolerableReplLag == 0 || opts.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 +151,7 @@ func ElectNewPrimary( } // sort the tablets for finding the best primary - err = sortTabletsForReparent(validTablets, tabletPositions, durability) + err = sortTabletsForReparent(validTablets, tabletPositions, innodbBufferPool, opts.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..f4e9092fc3f 100644 --- a/go/vt/vtctl/reparentutil/util_test.go +++ b/go/vt/vtctl/reparentutil/util_test.go @@ -67,15 +67,17 @@ 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 + allowCrossCellPromotion bool + expected *topodatapb.TabletAlias + errContains []string }{ { name: "found a replica", @@ -472,6 +474,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{ @@ -653,6 +717,64 @@ func TestElectNewPrimary(t *testing.T) { `zone1-0000000102 is not in the same cell as the previous primary`, }, }, + { + name: "no replicas in primary cell but cross cell allowed", + tmc: &chooseNewPrimaryTestTMClient{ + // zone1-101 is behind zone1-102 + replicationStatuses: map[string]*replicationdatapb.Status{ + "zone1-0000000101": { + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1", + }, + "zone1-0000000102": { + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5", + }, + }, + }, + allowCrossCellPromotion: true, + shardInfo: topo.NewShardInfo("testkeyspace", "-", &topodatapb.Shard{ + PrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone2", + Uid: 200, + }, + }, nil), + tabletMap: map[string]*topo.TabletInfo{ + "primary": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone2", + Uid: 200, + }, + 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: 102, + }, + }, { name: "only available tablet is AvoidPrimary", tmc: &chooseNewPrimaryTestTMClient{ @@ -731,7 +853,15 @@ 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) + options := &PlannedReparentOptions{ + NewPrimaryAlias: tt.newPrimaryAlias, + AvoidPrimaryAlias: tt.avoidPrimaryAlias, + TolerableReplLag: tt.tolerableReplLag, + durability: durability, + AllowCrossCellPromotion: tt.allowCrossCellPromotion, + WaitReplicasTimeout: time.Millisecond * 50, + } + actual, err := ElectNewPrimary(ctx, tt.tmc, tt.shardInfo, tt.tabletMap, tt.innodbBufferPoolData, options, 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 7d0a053f477..1f07dce40ff 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -2242,24 +2242,24 @@ func commandVReplicationWorkflow(ctx context.Context, wr *wrangler.Wrangler, sub } if *atomicCopy { - var errors []string + var errs []string if !*allTables { - errors = append(errors, "atomic copy requires --all.") + errs = append(errs, "atomic copy requires --all.") } if *tables != "" { - errors = append(errors, "atomic copy does not support specifying tables.") + errs = append(errs, "atomic copy does not support specifying tables.") } if *excludes != "" { - errors = append(errors, "atomic copy does not support specifying excludes.") + errs = append(errs, "atomic copy does not support specifying excludes.") } - if len(errors) > 0 { - errors = append(errors, "Found options incompatible with atomic copy:") - return fmt.Errorf(strings.Join(errors, " ")) + if len(errs) > 0 { + errs = append(errs, "Found options incompatible with atomic copy:") + return errors.New(strings.Join(errs, " ")) } } if !*allTables && *tables == "" { - return fmt.Errorf("no tables specified to move") + return errors.New("no tables specified to move") } vrwp.SourceKeyspace = *sourceKeyspace vrwp.Tables = *tables @@ -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) @@ -3740,7 +3740,7 @@ func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag return err } if subFlags.NArg() < 2 { - return fmt.Errorf(usage) + return errors.New(usage) } if len(*shards) > 0 { log.Infof("Subset of shards specified: %d, %v", len(*shards), strings.Join(*shards, ",")) @@ -3775,7 +3775,7 @@ func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag } } else { if subFlags.NArg() != 2 { - return fmt.Errorf(usage) + return errors.New(usage) } var rpcReq any = nil if action == "update" { @@ -3817,7 +3817,7 @@ func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag onddl = ival } if !changes { - return fmt.Errorf(errWorkflowUpdateWithoutChanges) + return errors.New(errWorkflowUpdateWithoutChanges) } tsp := tabletmanagerdatapb.TabletSelectionPreference_UNKNOWN if inorder { diff --git a/go/vt/vtctl/workflow/framework_test.go b/go/vt/vtctl/workflow/framework_test.go index e2ccde0a0e7..b5d0a308261 100644 --- a/go/vt/vtctl/workflow/framework_test.go +++ b/go/vt/vtctl/workflow/framework_test.go @@ -66,6 +66,7 @@ type testKeyspace struct { type queryResult struct { query string result *querypb.QueryResult + err error } func TestMain(m *testing.M) { @@ -228,6 +229,23 @@ func (env *testEnv) deleteTablet(tablet *topodatapb.Tablet) { delete(env.tablets[tablet.Keyspace], int(tablet.Alias.Uid)) } +func (env *testEnv) confirmRoutingAllTablesToTarget(t *testing.T) { + t.Helper() + env.tmc.mu.Lock() + defer env.tmc.mu.Unlock() + wantRR := make(map[string][]string) + for _, sd := range env.tmc.schema { + for _, td := range sd.TableDefinitions { + for _, tt := range []string{"", "@rdonly", "@replica"} { + wantRR[td.Name+tt] = []string{fmt.Sprintf("%s.%s", env.targetKeyspace.KeyspaceName, td.Name)} + wantRR[fmt.Sprintf("%s.%s", env.sourceKeyspace.KeyspaceName, td.Name+tt)] = []string{fmt.Sprintf("%s.%s", env.targetKeyspace.KeyspaceName, td.Name)} + wantRR[fmt.Sprintf("%s.%s", env.targetKeyspace.KeyspaceName, td.Name+tt)] = []string{fmt.Sprintf("%s.%s", env.targetKeyspace.KeyspaceName, td.Name)} + } + } + } + checkRouting(t, env.ws, wantRR) +} + type testTMClient struct { tmclient.TabletManagerClient schema map[string]*tabletmanagerdatapb.SchemaDefinition @@ -236,9 +254,14 @@ type testTMClient struct { vrQueries map[int][]*queryResult createVReplicationWorkflowRequests map[uint32]*tabletmanagerdatapb.CreateVReplicationWorkflowRequest readVReplicationWorkflowRequests map[uint32]*tabletmanagerdatapb.ReadVReplicationWorkflowRequest + primaryPositions map[uint32]string + + // Stack of ReadVReplicationWorkflowsResponse to return, in order, for each shard + readVReplicationWorkflowsResponses map[string][]*tabletmanagerdatapb.ReadVReplicationWorkflowsResponse env *testEnv // For access to the env config from tmc methods. reverse atomic.Bool // Are we reversing traffic? + frozen atomic.Bool // Are the workflows frozen? } func newTestTMClient(env *testEnv) *testTMClient { @@ -247,6 +270,8 @@ func newTestTMClient(env *testEnv) *testTMClient { vrQueries: make(map[int][]*queryResult), createVReplicationWorkflowRequests: make(map[uint32]*tabletmanagerdatapb.CreateVReplicationWorkflowRequest), readVReplicationWorkflowRequests: make(map[uint32]*tabletmanagerdatapb.ReadVReplicationWorkflowRequest), + readVReplicationWorkflowsResponses: make(map[string][]*tabletmanagerdatapb.ReadVReplicationWorkflowsResponse), + primaryPositions: make(map[uint32]string), env: env, } } @@ -264,6 +289,10 @@ func (tmc *testTMClient) CreateVReplicationWorkflow(ctx context.Context, tablet return &tabletmanagerdatapb.CreateVReplicationWorkflowResponse{Result: sqltypes.ResultToProto3(res)}, nil } +func (tmc *testTMClient) GetWorkflowKey(keyspace, shard string) string { + return fmt.Sprintf("%s/%s", keyspace, shard) +} + func (tmc *testTMClient) ReadVReplicationWorkflow(ctx context.Context, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { tmc.mu.Lock() defer tmc.mu.Unlock() @@ -305,6 +334,9 @@ func (tmc *testTMClient) ReadVReplicationWorkflow(ctx context.Context, tablet *t }, }, } + if tmc.frozen.Load() { + stream.Message = Frozen + } res.Streams = append(res.Streams, stream) } @@ -389,7 +421,7 @@ func (tmc *testTMClient) VReplicationExec(ctx context.Context, tablet *topodatap return nil, fmt.Errorf("tablet %v:\nunexpected query\n%s\nwant:\n%s", tablet, query, qrs[0].query) } tmc.vrQueries[int(tablet.Alias.Uid)] = qrs[1:] - return qrs[0].result, nil + return qrs[0].result, qrs[0].err } func (tmc *testTMClient) ExecuteFetchAsDba(ctx context.Context, tablet *topodatapb.Tablet, usePool bool, req *tabletmanagerdatapb.ExecuteFetchAsDbaRequest) (*querypb.QueryResult, error) { @@ -439,6 +471,10 @@ func (tmc *testTMClient) ReadVReplicationWorkflows(ctx context.Context, tablet * tmc.mu.Lock() defer tmc.mu.Unlock() + workflowKey := tmc.GetWorkflowKey(tablet.Keyspace, tablet.Shard) + if resp := tmc.getVReplicationWorkflowsResponse(workflowKey); resp != nil { + return resp, nil + } workflowType := binlogdatapb.VReplicationWorkflowType_MoveTables if len(req.IncludeWorkflows) > 0 { for _, wf := range req.IncludeWorkflows { @@ -470,7 +506,7 @@ func (tmc *testTMClient) ReadVReplicationWorkflows(ctx context.Context, tablet * }, }, }, - Pos: "MySQL56/" + position, + Pos: position, TimeUpdated: protoutil.TimeToProto(time.Now()), TimeHeartbeat: protoutil.TimeToProto(time.Now()), }, @@ -491,7 +527,21 @@ func (tmc *testTMClient) UpdateVReplicationWorkflow(ctx context.Context, tablet }, nil } +func (tmc *testTMClient) setPrimaryPosition(tablet *topodatapb.Tablet, position string) { + tmc.mu.Lock() + defer tmc.mu.Unlock() + if tmc.primaryPositions == nil { + tmc.primaryPositions = make(map[uint32]string) + } + tmc.primaryPositions[tablet.Alias.Uid] = position +} + func (tmc *testTMClient) PrimaryPosition(ctx context.Context, tablet *topodatapb.Tablet) (string, error) { + tmc.mu.Lock() + defer tmc.mu.Unlock() + if tmc.primaryPositions != nil && tmc.primaryPositions[tablet.Alias.Uid] != "" { + return tmc.primaryPositions[tablet.Alias.Uid], nil + } return position, nil } @@ -502,3 +552,109 @@ func (tmc *testTMClient) WaitForPosition(ctx context.Context, tablet *topodatapb func (tmc *testTMClient) VReplicationWaitForPos(ctx context.Context, tablet *topodatapb.Tablet, id int32, pos string) error { return nil } + +func (tmc *testTMClient) AddVReplicationWorkflowsResponse(key string, resp *tabletmanagerdatapb.ReadVReplicationWorkflowsResponse) { + tmc.mu.Lock() + defer tmc.mu.Unlock() + tmc.readVReplicationWorkflowsResponses[key] = append(tmc.readVReplicationWorkflowsResponses[key], resp) +} + +func (tmc *testTMClient) getVReplicationWorkflowsResponse(key string) *tabletmanagerdatapb.ReadVReplicationWorkflowsResponse { + if len(tmc.readVReplicationWorkflowsResponses) == 0 { + return nil + } + responses, ok := tmc.readVReplicationWorkflowsResponses[key] + if !ok || len(responses) == 0 { + return nil + } + resp := tmc.readVReplicationWorkflowsResponses[key][0] + tmc.readVReplicationWorkflowsResponses[key] = tmc.readVReplicationWorkflowsResponses[key][1:] + return resp +} + +// +// Utility / helper functions. +// + +func checkRouting(t *testing.T, ws *Server, want map[string][]string) { + t.Helper() + ctx := context.Background() + got, err := topotools.GetRoutingRules(ctx, ws.ts) + require.NoError(t, err) + require.EqualValues(t, got, want, "routing rules don't match: got: %v, want: %v", got, want) + cells, err := ws.ts.GetCellInfoNames(ctx) + require.NoError(t, err) + for _, cell := range cells { + checkCellRouting(t, ws, cell, want) + } +} + +func checkCellRouting(t *testing.T, ws *Server, cell string, want map[string][]string) { + t.Helper() + ctx := context.Background() + svs, err := ws.ts.GetSrvVSchema(ctx, cell) + require.NoError(t, err) + got := make(map[string][]string, len(svs.RoutingRules.Rules)) + for _, rr := range svs.RoutingRules.Rules { + got[rr.FromTable] = append(got[rr.FromTable], rr.ToTables...) + } + require.EqualValues(t, got, want, "routing rules don't match for cell %s: got: %v, want: %v", cell, got, want) +} + +func checkDenyList(t *testing.T, ts *topo.Server, keyspace, shard string, want []string) { + t.Helper() + ctx := context.Background() + si, err := ts.GetShard(ctx, keyspace, shard) + require.NoError(t, err) + tc := si.GetTabletControl(topodatapb.TabletType_PRIMARY) + var got []string + if tc != nil { + got = tc.DeniedTables + } + require.EqualValues(t, got, want, "denied tables for %s/%s: got: %v, want: %v", keyspace, shard, got, want) +} + +func checkServedTypes(t *testing.T, ts *topo.Server, keyspace, shard string, want int) { + t.Helper() + ctx := context.Background() + si, err := ts.GetShard(ctx, keyspace, shard) + require.NoError(t, err) + servedTypes, err := ts.GetShardServingTypes(ctx, si) + require.NoError(t, err) + require.Equal(t, want, len(servedTypes), "shard %s/%s has wrong served types: got: %v, want: %v", + keyspace, shard, len(servedTypes), want) +} + +func checkCellServedTypes(t *testing.T, ts *topo.Server, keyspace, shard, cell string, want int) { + t.Helper() + ctx := context.Background() + srvKeyspace, err := ts.GetSrvKeyspace(ctx, cell, keyspace) + require.NoError(t, err) + count := 0 +outer: + for _, partition := range srvKeyspace.GetPartitions() { + for _, ref := range partition.ShardReferences { + if ref.Name == shard { + count++ + continue outer + } + } + } + require.Equal(t, want, count, "serving types for %s/%s in cell %s: got: %d, want: %d", keyspace, shard, cell, count, want) +} + +func checkIfPrimaryServing(t *testing.T, ts *topo.Server, keyspace, shard string, want bool) { + t.Helper() + ctx := context.Background() + si, err := ts.GetShard(ctx, keyspace, shard) + require.NoError(t, err) + require.Equal(t, want, si.IsPrimaryServing, "primary serving for %s/%s: got: %v, want: %v", keyspace, shard, si.IsPrimaryServing, want) +} + +func checkIfTableExistInVSchema(ctx context.Context, t *testing.T, ts *topo.Server, keyspace, table string) bool { + vschema, err := ts.GetVSchema(ctx, keyspace) + require.NoError(t, err) + require.NotNil(t, vschema) + _, ok := vschema.Tables[table] + return ok +} diff --git a/go/vt/vtctl/workflow/materializer_env_test.go b/go/vt/vtctl/workflow/materializer_env_test.go index 569651f85ca..aada59c244d 100644 --- a/go/vt/vtctl/workflow/materializer_env_test.go +++ b/go/vt/vtctl/workflow/materializer_env_test.go @@ -61,7 +61,7 @@ type testMaterializerEnv struct { venv *vtenv.Environment } -//---------------------------------------------- +// ---------------------------------------------- // testMaterializerEnv func newTestMaterializerEnv(t *testing.T, ctx context.Context, ms *vtctldatapb.MaterializeSettings, sourceShards, targetShards []string) *testMaterializerEnv { @@ -426,7 +426,7 @@ func (tmc *testMaterializerTMClient) ReadVReplicationWorkflows(ctx context.Conte }, }, }, - Pos: "MySQL56/" + position, + Pos: position, TimeUpdated: protoutil.TimeToProto(time.Now()), TimeHeartbeat: protoutil.TimeToProto(time.Now()), } diff --git a/go/vt/vtctl/workflow/materializer_test.go b/go/vt/vtctl/workflow/materializer_test.go index 51a7d22d5eb..763dd7c04d3 100644 --- a/go/vt/vtctl/workflow/materializer_test.go +++ b/go/vt/vtctl/workflow/materializer_test.go @@ -44,7 +44,7 @@ import ( ) const ( - position = "9d10e6ec-07a0-11ee-ae73-8e53f4cf3083:1-97" + position = "MySQL56/9d10e6ec-07a0-11ee-ae73-8e53f4cf3083:1-97" mzSelectFrozenQuery = "select 1 from _vt.vreplication where db_name='vt_targetks' and message='FROZEN' and workflow_sub_type != 1" mzCheckJournal = "/select val from _vt.resharding_journal where id=" mzGetCopyState = "select distinct table_name from _vt.copy_state cs, _vt.vreplication vr where vr.id = cs.vrepl_id and vr.id = 1" @@ -56,6 +56,14 @@ var ( defaultOnDDL = binlogdatapb.OnDDLAction_IGNORE.String() ) +func gtid(position string) string { + arr := strings.Split(position, "/") + if len(arr) != 2 { + return "" + } + return arr[1] +} + func TestStripForeignKeys(t *testing.T) { tcs := []struct { desc string @@ -577,7 +585,7 @@ func TestMoveTablesDDLFlag(t *testing.T) { sourceShard, err := env.topoServ.GetShardNames(ctx, ms.SourceKeyspace) require.NoError(t, err) want := fmt.Sprintf("shard_streams:{key:\"%s/%s\" value:{streams:{id:1 tablet:{cell:\"%s\" uid:200} source_shard:\"%s/%s\" position:\"%s\" status:\"Running\" info:\"VStream Lag: 0s\"}}} traffic_state:\"Reads Not Switched. Writes Not Switched\"", - ms.TargetKeyspace, targetShard[0], env.cell, ms.SourceKeyspace, sourceShard[0], position) + ms.TargetKeyspace, targetShard[0], env.cell, ms.SourceKeyspace, sourceShard[0], gtid(position)) res, err := env.ws.MoveTablesCreate(ctx, &vtctldatapb.MoveTablesCreateRequest{ Workflow: ms.Workflow, @@ -636,7 +644,7 @@ func TestMoveTablesNoRoutingRules(t *testing.T) { Uid: 200, }, SourceShard: fmt.Sprintf("%s/%s", ms.SourceKeyspace, sourceShard[0]), - Position: position, + Position: gtid(position), Status: binlogdatapb.VReplicationWorkflowState_Running.String(), Info: "VStream Lag: 0s", }, diff --git a/go/vt/vtctl/workflow/mount_test.go b/go/vt/vtctl/workflow/mount_test.go new file mode 100644 index 00000000000..2fec275e4cb --- /dev/null +++ b/go/vt/vtctl/workflow/mount_test.go @@ -0,0 +1,77 @@ +/* +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" + "testing" + + "github.com/stretchr/testify/require" + + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" + "vitess.io/vitess/go/vt/topo/memorytopo" + "vitess.io/vitess/go/vt/vtenv" +) + +// TestMount tests various Mount-related methods. +func TestMount(t *testing.T) { + const ( + extCluster = "extcluster" + topoType = "etcd2" + topoServer = "localhost:2379" + topoRoot = "/vitess/global" + ) + ctx := context.Background() + ts := memorytopo.NewServer(ctx, "cell") + tmc := &fakeTMC{} + s := NewServer(vtenv.NewTestEnv(), ts, tmc) + + resp, err := s.MountRegister(ctx, &vtctldatapb.MountRegisterRequest{ + Name: extCluster, + TopoType: topoType, + TopoServer: topoServer, + TopoRoot: topoRoot, + }) + require.NoError(t, err) + require.NotNil(t, resp) + + respList, err := s.MountList(ctx, &vtctldatapb.MountListRequest{}) + require.NoError(t, err) + require.NotNil(t, respList) + require.Equal(t, []string{extCluster}, respList.Names) + + respShow, err := s.MountShow(ctx, &vtctldatapb.MountShowRequest{ + Name: extCluster, + }) + require.NoError(t, err) + require.NotNil(t, respShow) + require.Equal(t, extCluster, respShow.Name) + require.Equal(t, topoType, respShow.TopoType) + require.Equal(t, topoServer, respShow.TopoServer) + require.Equal(t, topoRoot, respShow.TopoRoot) + + respUnregister, err := s.MountUnregister(ctx, &vtctldatapb.MountUnregisterRequest{ + Name: extCluster, + }) + require.NoError(t, err) + require.NotNil(t, respUnregister) + + respList, err = s.MountList(ctx, &vtctldatapb.MountListRequest{}) + require.NoError(t, err) + require.NotNil(t, respList) + require.Nil(t, respList.Names) +} diff --git a/go/vt/vtctl/workflow/resharder_test.go b/go/vt/vtctl/workflow/resharder_test.go index 1bb2f065e0f..6353f36db9f 100644 --- a/go/vt/vtctl/workflow/resharder_test.go +++ b/go/vt/vtctl/workflow/resharder_test.go @@ -84,7 +84,7 @@ func TestReshardCreate(t *testing.T) { { Id: 1, Tablet: &topodatapb.TabletAlias{Cell: defaultCellName, Uid: startingTargetTabletUID}, - SourceShard: "targetks/0", Position: position, Status: "Running", Info: "VStream Lag: 0s", + SourceShard: "targetks/0", Position: gtid(position), Status: "Running", Info: "VStream Lag: 0s", }, }, }, @@ -93,7 +93,7 @@ func TestReshardCreate(t *testing.T) { { Id: 1, Tablet: &topodatapb.TabletAlias{Cell: defaultCellName, Uid: startingTargetTabletUID + tabletUIDStep}, - SourceShard: "targetks/0", Position: position, Status: "Running", Info: "VStream Lag: 0s", + SourceShard: "targetks/0", Position: gtid(position), Status: "Running", Info: "VStream Lag: 0s", }, }, }, diff --git a/go/vt/vtctl/workflow/server.go b/go/vt/vtctl/workflow/server.go index 86a3a6c6ead..c14d39d7256 100644 --- a/go/vt/vtctl/workflow/server.go +++ b/go/vt/vtctl/workflow/server.go @@ -35,7 +35,6 @@ import ( "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" - "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sets" "vitess.io/vitess/go/sqlescape" @@ -45,7 +44,6 @@ import ( "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/key" - "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/mysqlctl/tmutils" "vitess.io/vitess/go/vt/schema" @@ -66,7 +64,6 @@ 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" @@ -81,6 +78,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} @@ -130,9 +129,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 ( @@ -157,18 +153,26 @@ type Server struct { ts *topo.Server tmc tmclient.TabletManagerClient // Limit the number of concurrent background goroutines if needed. - sem *semaphore.Weighted - env *vtenv.Environment + sem *semaphore.Weighted + env *vtenv.Environment + options serverOptions } // NewServer returns a new server instance with the given topo.Server and // TabletManagerClient. -func NewServer(env *vtenv.Environment, ts *topo.Server, tmc tmclient.TabletManagerClient) *Server { - return &Server{ +func NewServer(env *vtenv.Environment, ts *topo.Server, tmc tmclient.TabletManagerClient, opts ...ServerOption) *Server { + s := &Server{ ts: ts, tmc: tmc, env: env, } + for _, o := range opts { + o.apply(&s.options) + } + if s.options.logger == nil { + s.options.logger = logutil.NewConsoleLogger() // Use the default system logger + } + return s } func (s *Server) SQLParser() *sqlparser.Parser { @@ -332,7 +336,7 @@ func (s *Server) GetCellsWithTableReadsSwitched( for _, to := range rule.ToTables { ks, err := getKeyspace(to) if err != nil { - log.Errorf(err.Error()) + s.Logger().Errorf(err.Error()) return nil, nil, err } @@ -853,7 +857,7 @@ ORDER BY } if stream.Id > streamLog.StreamId { - log.Warningf("Found stream log for nonexistent stream: %+v", streamLog) + s.Logger().Warningf("Found stream log for nonexistent stream: %+v", streamLog) // This can happen on manual/failed workflow cleanup so keep going. continue } @@ -943,7 +947,7 @@ ORDER BY func (s *Server) getWorkflowState(ctx context.Context, targetKeyspace, workflowName string) (*trafficSwitcher, *State, error) { ts, err := s.buildTrafficSwitcher(ctx, targetKeyspace, workflowName) if err != nil { - log.Errorf("buildTrafficSwitcher failed: %v", err) + s.Logger().Errorf("buildTrafficSwitcher failed: %v", err) return nil, nil, err } @@ -1325,7 +1329,7 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl return nil, err } sourceTopo = externalTopo - log.Infof("Successfully opened external topo: %+v", externalTopo) + s.Logger().Infof("Successfully opened external topo: %+v", externalTopo) } var vschema *vschemapb.Keyspace @@ -1382,7 +1386,7 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl if len(tables) == 0 { return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "no tables to move") } - log.Infof("Found tables to move: %s", strings.Join(tables, ",")) + s.Logger().Infof("Found tables to move: %s", strings.Join(tables, ",")) if !vschema.Sharded { // Save the original in case we need to restore it for a late failure @@ -1458,13 +1462,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. @@ -1530,12 +1542,12 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl return nil, err } if exists { - log.Errorf("Found a previous journal entry for %d", migrationID) + s.Logger().Errorf("Found a previous journal entry for %d", migrationID) msg := fmt.Sprintf("found an entry from a previous run for migration id %d in _vt.resharding_journal on tablets %s, ", migrationID, strings.Join(tablets, ",")) msg += fmt.Sprintf("please review and delete it before proceeding and then start the workflow using: MoveTables --workflow %s --target-keyspace %s start", req.Workflow, req.TargetKeyspace) - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, msg) + return nil, vterrors.New(vtrpcpb.Code_INTERNAL, msg) } } @@ -1593,7 +1605,7 @@ func (s *Server) setupInitialRoutingRules(ctx context.Context, req *vtctldatapb. targetKeyspace := req.TargetKeyspace if req.NoRoutingRules { - log.Warningf("Found --no-routing-rules flag, not creating routing rules for workflow %s.%s", targetKeyspace, req.Workflow) + s.Logger().Warningf("Found --no-routing-rules flag, not creating routing rules for workflow %s.%s", targetKeyspace, req.Workflow) return nil } @@ -1606,7 +1618,7 @@ func (s *Server) setupInitialRoutingRules(ctx context.Context, req *vtctldatapb. } if mz.IsMultiTenantMigration() { - log.Infof("Setting up keyspace routing rules for workflow %s.%s", targetKeyspace, req.Workflow) + s.Logger().Infof("Setting up keyspace routing rules for workflow %s.%s", targetKeyspace, req.Workflow) // Note that you can never point the target keyspace to the source keyspace in a multi-tenant migration // since the target takes write traffic for all tenants! routes := make(map[string]string) @@ -1723,7 +1735,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("%v", err2) + s.Logger().Errorf("%v", err2) return nil, err } tabletTypesStr := discovery.BuildTabletTypesString(req.TabletTypes, req.TabletSelectionPreference) @@ -1748,7 +1760,7 @@ func (s *Server) ReshardCreate(ctx context.Context, req *vtctldatapb.ReshardCrea return nil, vterrors.Wrap(err, "startStreams") } } else { - log.Warningf("Streams will not be started since --auto-start is set to false") + s.Logger().Warningf("Streams will not be started since --auto-start is set to false") } return s.WorkflowStatus(ctx, &vtctldatapb.WorkflowStatusRequest{ Keyspace: req.Keyspace, @@ -1807,9 +1819,10 @@ func (s *Server) VDiffCreate(ctx context.Context, req *vtctldatapb.VDiffCreateRe MaxDiffSeconds: req.MaxDiffDuration.Seconds, }, ReportOptions: &tabletmanagerdatapb.VDiffReportOptions{ - OnlyPks: req.OnlyPKs, - DebugQuery: req.DebugQuery, - MaxSampleRows: req.MaxReportSampleRows, + OnlyPks: req.OnlyPKs, + DebugQuery: req.DebugQuery, + MaxSampleRows: req.MaxReportSampleRows, + RowDiffColumnTruncateAt: req.RowDiffColumnTruncateAt, }, } @@ -1835,7 +1848,7 @@ func (s *Server) VDiffCreate(ctx context.Context, req *vtctldatapb.VDiffCreateRe return nil, err } if workflowStatus != binlogdatapb.VReplicationWorkflowState_Running { - log.Infof("Workflow %s.%s is not running, cannot start VDiff in state %s", req.TargetKeyspace, req.Workflow, workflowStatus) + s.Logger().Infof("Workflow %s.%s is not running, cannot start VDiff in state %s", req.TargetKeyspace, req.Workflow, workflowStatus) return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "not all streams are running in workflow %s.%s", req.TargetKeyspace, req.Workflow) } @@ -1845,7 +1858,7 @@ func (s *Server) VDiffCreate(ctx context.Context, req *vtctldatapb.VDiffCreateRe return err }) if err != nil { - log.Errorf("Error executing vdiff create action: %v", err) + s.Logger().Errorf("Error executing vdiff create action: %v", err) return nil, err } @@ -1880,7 +1893,7 @@ func (s *Server) VDiffDelete(ctx context.Context, req *vtctldatapb.VDiffDeleteRe return err }) if err != nil { - log.Errorf("Error executing vdiff delete action: %v", err) + s.Logger().Errorf("Error executing vdiff delete action: %v", err) return nil, err } @@ -1913,7 +1926,7 @@ func (s *Server) VDiffResume(ctx context.Context, req *vtctldatapb.VDiffResumeRe return err }) if err != nil { - log.Errorf("Error executing vdiff resume action: %v", err) + s.Logger().Errorf("Error executing vdiff resume action: %v", err) return nil, err } @@ -1953,7 +1966,7 @@ func (s *Server) VDiffShow(ctx context.Context, req *vtctldatapb.VDiffShowReques return err }) if output.err != nil { - log.Errorf("Error executing vdiff show action: %v", output.err) + s.Logger().Errorf("Error executing vdiff show action: %v", output.err) return nil, output.err } return &vtctldatapb.VDiffShowResponse{ @@ -1987,7 +2000,7 @@ func (s *Server) VDiffStop(ctx context.Context, req *vtctldatapb.VDiffStopReques return err }) if err != nil { - log.Errorf("Error executing vdiff stop action: %v", err) + s.Logger().Errorf("Error executing vdiff stop action: %v", err) return nil, err } @@ -2009,7 +2022,7 @@ func (s *Server) WorkflowDelete(ctx context.Context, req *vtctldatapb.WorkflowDe ts, state, err := s.getWorkflowState(ctx, req.GetKeyspace(), req.GetWorkflow()) if err != nil { - log.Errorf("failed to get VReplication workflow state for %s.%s: %v", req.GetKeyspace(), req.GetWorkflow(), err) + s.Logger().Errorf("failed to get VReplication workflow state for %s.%s: %v", req.GetKeyspace(), req.GetWorkflow(), err) return nil, err } @@ -2503,7 +2516,7 @@ func (s *Server) deleteWorkflowVDiffData(ctx context.Context, tablet *topodatapb Action: string(vdiff.DeleteAction), ActionArg: vdiff.AllActionArg, }); err != nil { - log.Errorf("Error deleting vdiff data for %s.%s workflow: %v", tablet.Keyspace, workflow, err) + s.Logger().Errorf("Error deleting vdiff data for %s.%s workflow: %v", tablet.Keyspace, workflow, err) } } @@ -2523,7 +2536,7 @@ func (s *Server) deleteWorkflowVDiffData(ctx context.Context, tablet *topodatapb func (s *Server) optimizeCopyStateTable(tablet *topodatapb.Tablet) { if s.sem != nil { if !s.sem.TryAcquire(1) { - log.Warningf("Deferring work to optimize the copy_state table on %q due to hitting the maximum concurrent background job limit.", + s.Logger().Warningf("Deferring work to optimize the copy_state table on %q due to hitting the maximum concurrent background job limit.", tablet.Alias.String()) return } @@ -2534,17 +2547,17 @@ 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{ Query: []byte(sqlOptimizeTable), MaxRows: uint64(100), // always produces 1+rows with notes and status }); err != nil { - if sqlErr, ok := err.(*sqlerror.SQLError); ok && sqlErr.Num == sqlerror.ERNoSuchTable { // the table may not exist + if IsTableDidNotExistError(err) { return } - log.Warningf("Failed to optimize the copy_state table on %q: %v", tablet.Alias.String(), err) + s.Logger().Warningf("Failed to optimize the copy_state table on %q: %v", tablet.Alias.String(), err) } // This will automatically set the value to 1 or the current max value in the // table, whichever is greater. @@ -2553,7 +2566,7 @@ func (s *Server) optimizeCopyStateTable(tablet *topodatapb.Tablet) { Query: []byte(sqlResetAutoInc), MaxRows: uint64(0), }); err != nil { - log.Warningf("Failed to reset the auto_increment value for the copy_state table on %q: %v", + s.Logger().Warningf("Failed to reset the auto_increment value for the copy_state table on %q: %v", tablet.Alias.String(), err) } }() @@ -2570,24 +2583,28 @@ 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 { + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s workflow", 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 + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s keyspace", ts.SourceKeyspaceName()), 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 + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s keyspace", ts.TargetKeyspaceName()), lockErr) } defer targetUnlock(&err) - ctx = tctx + ctx = lockCtx } + if !keepData { switch ts.MigrationType() { case binlogdatapb.MigrationType_TABLES: @@ -2618,14 +2635,14 @@ func (s *Server) DropTargets(ctx context.Context, ts *trafficSwitcher, keepData, func (s *Server) buildTrafficSwitcher(ctx context.Context, targetKeyspace, workflowName string) (*trafficSwitcher, error) { tgtInfo, err := BuildTargets(ctx, s.ts, s.tmc, targetKeyspace, workflowName) if err != nil { - log.Infof("Error building targets: %s", err) + s.Logger().Infof("Error building targets: %s", err) return nil, err } targets, frozen, optCells, optTabletTypes := tgtInfo.Targets, tgtInfo.Frozen, tgtInfo.OptCells, tgtInfo.OptTabletTypes ts := &trafficSwitcher{ ws: s, - logger: logutil.NewConsoleLogger(), + logger: s.Logger(), workflow: workflowName, reverseWorkflow: ReverseWorkflowName(workflowName), id: HashStreams(targetKeyspace, targets), @@ -2639,7 +2656,7 @@ func (s *Server) buildTrafficSwitcher(ctx context.Context, targetKeyspace, workf workflowSubType: tgtInfo.WorkflowSubType, options: tgtInfo.Options, } - log.Infof("Migration ID for workflow %s: %d", workflowName, ts.id) + s.Logger().Infof("Migration ID for workflow %s: %d", workflowName, ts.id) sourceTopo := s.ts // Build the sources. @@ -2726,7 +2743,7 @@ func (s *Server) buildTrafficSwitcher(ctx context.Context, targetKeyspace, workf return nil, err } if ts.isPartialMigration { - log.Infof("Migration is partial, for shards %+v", sourceShards) + s.Logger().Infof("Migration is partial, for shards %+v", sourceShards) } return ts, nil } @@ -2762,23 +2779,28 @@ 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("Source LockKeyspace failed: %v", lockErr) - return nil, lockErr + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s workflow", lockName), lockErr) + } + defer workflowUnlock(&err) + ctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "DropSources") + if lockErr != nil { + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s keyspace", ts.SourceKeyspaceName()), 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 + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s keyspace", ts.TargetKeyspaceName()), 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) @@ -2788,7 +2810,7 @@ func (s *Server) dropSources(ctx context.Context, ts *trafficSwitcher, removalTy if !keepData { switch ts.MigrationType() { case binlogdatapb.MigrationType_TABLES: - log.Infof("Deleting tables") + s.Logger().Infof("Deleting tables") if err := sw.removeSourceTables(ctx, removalType); err != nil { return nil, err } @@ -2800,7 +2822,7 @@ func (s *Server) dropSources(ctx context.Context, ts *trafficSwitcher, removalTy } case binlogdatapb.MigrationType_SHARDS: - log.Infof("Removing shards") + s.Logger().Infof("Removing shards") if err := sw.dropSourceShards(ctx); err != nil { return nil, err } @@ -2847,7 +2869,7 @@ func (s *Server) DeleteShard(ctx context.Context, keyspace, shard string, recurs shardInfo, err := s.ts.GetShard(ctx, keyspace, shard) if err != nil { if topo.IsErrType(err, topo.NoNode) { - log.Warningf("Shard %v/%v did not exist when attempting to remove it", keyspace, shard) + s.Logger().Warningf("Shard %v/%v did not exist when attempting to remove it", keyspace, shard) return nil } return err @@ -2920,11 +2942,11 @@ func (s *Server) DeleteShard(ctx context.Context, keyspace, shard string, recurs return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "shard %v/%v still has %v tablets in cell %v; use --recursive or remove them manually", keyspace, shard, len(tabletMap), cell) } - log.Infof("Deleting all tablets in shard %v/%v cell %v", keyspace, shard, cell) + s.Logger().Infof("Deleting all tablets in shard %v/%v cell %v", keyspace, shard, cell) for tabletAlias, tabletInfo := range tabletMap { // We don't care about scrapping or updating the replication graph, // because we're about to delete the entire replication graph. - log.Infof("Deleting tablet %v", tabletAlias) + s.Logger().Infof("Deleting tablet %v", tabletAlias) if err := s.ts.DeleteTablet(ctx, tabletInfo.Alias); err != nil && !topo.IsErrType(err, topo.NoNode) { // We don't want to continue if a DeleteTablet fails for // any good reason (other than missing tablet, in which @@ -2945,7 +2967,7 @@ func (s *Server) DeleteShard(ctx context.Context, keyspace, shard string, recurs // regardless of its existence. for _, cell := range cells { if err := s.ts.DeleteShardReplication(ctx, cell, keyspace, shard); err != nil && !topo.IsErrType(err, topo.NoNode) { - log.Warningf("Cannot delete ShardReplication in cell %v for %v/%v: %v", cell, keyspace, shard, err) + s.Logger().Warningf("Cannot delete ShardReplication in cell %v for %v/%v: %v", cell, keyspace, shard, err) } } @@ -2976,7 +2998,7 @@ func (s *Server) refreshPrimaryTablets(ctx context.Context, shards []*topo.Shard if err := s.tmc.RefreshState(ctx, ti.Tablet); err != nil { rec.RecordError(err) } else { - log.Infof("%v responded", topoproto.TabletAliasString(si.PrimaryAlias)) + s.Logger().Infof("%v responded", topoproto.TabletAliasString(si.PrimaryAlias)) } }(si) } @@ -2996,14 +3018,20 @@ 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("Target LockKeyspace failed: %v", lockErr) - return nil, lockErr + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s workflow", lockName), lockErr) + } + defer workflowUnlock(&err) + ctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "completeMigrateWorkflow") + if lockErr != nil { + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to lock the %s keyspace", ts.TargetKeyspaceName()), lockErr) } defer targetUnlock(&err) - ctx = tctx + if err := sw.dropTargetVReplicationStreams(ctx); err != nil { return nil, err } @@ -3015,7 +3043,7 @@ func (s *Server) finalizeMigrateWorkflow(ctx context.Context, ts *trafficSwitche return nil, err } } - log.Infof("cancel is %t, keepData %t", cancel, keepData) + s.Logger().Infof("cancel is %t, keepData %t", cancel, keepData) if cancel && !keepData { if err := sw.removeTargetTables(ctx); err != nil { return nil, err @@ -3031,13 +3059,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 { @@ -3054,7 +3088,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 { @@ -3086,7 +3120,7 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor if rdDryRunResults, err = s.switchReads(ctx, req, ts, startState, !hasPrimary /* rebuildSrvVSchema */, direction); err != nil { return nil, err } - log.Infof("Switch Reads done for workflow %s.%s", req.Keyspace, req.Workflow) + s.Logger().Infof("Switch Reads done for workflow %s.%s", req.Keyspace, req.Workflow) } if rdDryRunResults != nil { dryRunResults = append(dryRunResults, *rdDryRunResults...) @@ -3095,7 +3129,7 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor if _, wrDryRunResults, err = s.switchWrites(ctx, req, ts, timeout, false); err != nil { return nil, err } - log.Infof("Switch Writes done for workflow %s.%s", req.Keyspace, req.Workflow) + s.Logger().Infof("Switch Writes done for workflow %s.%s", req.Keyspace, req.Workflow) } if wrDryRunResults != nil { @@ -3108,13 +3142,13 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor if direction == DirectionBackward { cmd = "ReverseTraffic" } - log.Infof("%s done for workflow %s.%s", cmd, req.Keyspace, req.Workflow) + s.Logger().Infof("%s done for workflow %s.%s", cmd, req.Keyspace, req.Workflow) resp := &vtctldatapb.WorkflowSwitchTrafficResponse{} if req.DryRun { resp.Summary = fmt.Sprintf("%s dry run results for workflow %s.%s at %v", cmd, req.Keyspace, req.Workflow, time.Now().UTC().Format(time.RFC822)) resp.DryRunResults = dryRunResults } else { - log.Infof("%s done for workflow %s.%s", cmd, req.Keyspace, req.Workflow) + s.Logger().Infof("%s done for workflow %s.%s", cmd, 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 SwitchTraffic operation // and return that as a string. @@ -3125,14 +3159,14 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor workflow = ts.reverseWorkflow } resp.StartState = startState.String() - log.Infof("Before reloading workflow state after switching traffic: %+v\n", resp.StartState) + s.Logger().Infof("Before reloading workflow state after switching traffic: %+v\n", resp.StartState) _, currentState, err := s.getWorkflowState(ctx, keyspace, workflow) if err != nil { resp.CurrentState = fmt.Sprintf("Error reloading workflow state after switching traffic: %v", err) } else { resp.CurrentState = currentState.String() } - log.Infof("%s done for workflow %s.%s, returning response %v", cmd, req.Keyspace, req.Workflow, resp) + s.Logger().Infof("%s done for workflow %s.%s, returning response %v", cmd, req.Keyspace, req.Workflow, resp) } return resp, nil } @@ -3161,16 +3195,10 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc cellsStr := strings.Join(req.Cells, ",") - // Consistently handle errors by logging and returning them. - handleError := func(message string, err error) (*[]string, error) { - werr := vterrors.Wrapf(err, message) - ts.Logger().Error(werr) - return nil, werr - } - - log.Infof("Switching reads: %s.%s tablet types: %s, cells: %s, workflow state: %s", ts.targetKeyspace, ts.workflow, roTypesToSwitchStr, cellsStr, state.String()) + s.Logger().Infof("Switching reads: %s.%s tablet types: %s, cells: %s, workflow state: %s", ts.targetKeyspace, ts.workflow, roTypesToSwitchStr, cellsStr, state.String()) if !switchReplica && !switchRdonly { - return handleError("invalid tablet types", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "tablet types must be REPLICA or RDONLY: %s", roTypesToSwitchStr)) + return defaultErrorHandler(ts.Logger(), "invalid tablet types", + vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "tablet types must be REPLICA or RDONLY: %s", roTypesToSwitchStr)) } // For partial (shard-by-shard migrations) or multi-tenant migrations, traffic for all tablet types // is expected to be switched at once. For other MoveTables migrations where we use table routing rules @@ -3182,7 +3210,8 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc trafficSwitchingIsAllOrNothing = true case ts.MigrationType() == binlogdatapb.MigrationType_TABLES && ts.IsMultiTenantMigration(): if direction == DirectionBackward { - return handleError("invalid request", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "requesting reversal of read traffic for multi-tenant migrations is not supported")) + return defaultErrorHandler(ts.Logger(), "invalid request", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, + "requesting reversal of read traffic for multi-tenant migrations is not supported")) } // For multi-tenant migrations, we only support switching traffic to all cells at once allCells, err := ts.TopoServer().GetCellInfoNames(ctx) @@ -3190,16 +3219,19 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc return nil, err } if len(req.GetCells()) != 0 && len(req.GetCells()) != len(allCells) { - return handleError("invalid request", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "requesting read traffic for multi-tenant migrations must include all cells")) + return defaultErrorHandler(ts.Logger(), "invalid request", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, + "requesting read traffic for multi-tenant migrations must include all cells")) } } if !trafficSwitchingIsAllOrNothing { if direction == DirectionBackward && switchReplica && len(state.ReplicaCellsSwitched) == 0 { - return handleError("invalid request", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "requesting reversal of read traffic for REPLICAs but REPLICA reads have not been switched")) + return defaultErrorHandler(ts.Logger(), "invalid request", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, + "requesting reversal of read traffic for REPLICAs but REPLICA reads have not been switched")) } if direction == DirectionBackward && switchRdonly && len(state.RdonlyCellsSwitched) == 0 { - return handleError("invalid request", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "requesting reversal of SwitchReads for RDONLYs but RDONLY reads have not been switched")) + return defaultErrorHandler(ts.Logger(), "invalid request", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, + "requesting reversal of SwitchReads for RDONLYs but RDONLY reads have not been switched")) } } @@ -3221,10 +3253,10 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc // If journals exist notify user and fail. journalsExist, _, err := ts.checkJournals(ctx) if err != nil { - return handleError(fmt.Sprintf("failed to read journal in the %s keyspace", ts.SourceKeyspaceName()), err) + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to read journal in the %s keyspace", ts.SourceKeyspaceName()), err) } if journalsExist { - log.Infof("Found a previous journal entry for %d", ts.id) + s.Logger().Infof("Found a previous journal entry for %d", ts.id) } var sw iswitcher if req.DryRun { @@ -3234,28 +3266,47 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc } if err := ts.validate(ctx); err != nil { - return handleError("workflow validation failed", err) + return defaultErrorHandler(ts.Logger(), "workflow validation failed", err) } - // 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) + // 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) + return defaultErrorHandler(ts.Logger(), 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 defaultErrorHandler(ts.Logger(), 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 { case ts.IsMultiTenantMigration(): err := sw.switchKeyspaceReads(ctx, roTabletTypes) if err != nil { - return handleError(fmt.Sprintf("failed to switch read traffic, from source keyspace %s to target keyspace %s, workflow %s", + return defaultErrorHandler(ts.Logger(), fmt.Sprintf("failed to switch read traffic, from source keyspace %s to target keyspace %s, workflow %s", ts.SourceKeyspaceName(), ts.TargetKeyspaceName(), ts.WorkflowName()), err) } case ts.isPartialMigration: @@ -3263,27 +3314,34 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc default: err := sw.switchTableReads(ctx, req.Cells, roTabletTypes, rebuildSrvVSchema, direction) if err != nil { - return handleError("failed to switch read traffic for the tables", err) + return defaultErrorHandler(ts.Logger(), "failed to switch read traffic for the tables", err) } } return sw.logs(), nil } + + if err := confirmKeyspaceLocksHeld(); err != nil { + return defaultErrorHandler(ts.Logger(), "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) + return defaultErrorHandler(ts.Logger(), "failed to switch read traffic for the shards", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return defaultErrorHandler(ts.Logger(), "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", ts.targetKeyspace, cellsStr) - return handleError("failed to validate SrvKeyspace record", err2) + return defaultErrorHandler(ts.Logger(), "failed to validate SrvKeyspace record", err2) } return sw.logs(), nil } // 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 @@ -3295,7 +3353,7 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit // Consistently handle errors by logging and returning them. handleError := func(message string, err error) (int64, *[]string, error) { - werr := vterrors.Wrapf(err, message) + werr := vterrors.Wrap(err, message) ts.Logger().Error(werr) return 0, nil, werr } @@ -3315,27 +3373,53 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit } } - // 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) + // 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, []topodatapb.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 @@ -3386,7 +3470,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 { @@ -3414,37 +3498,58 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit } } + // Get the source positions now that writes are stopped, the streams were stopped (e.g. + // intra-keyspace materializations that write on the source), and we know for certain + // that any in progress writes are done. + if err := ts.gatherSourcePositions(ctx); err != nil { + return handleError("failed to gather replication positions on migration sources", err) + } + + 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) @@ -3464,6 +3569,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) } @@ -3493,7 +3601,7 @@ func (s *Server) canSwitch(ctx context.Context, ts *trafficSwitcher, state *Stat maxAllowedReplLagSecs int64, shards []string) (reason string, err error) { if direction == DirectionForward && state.WritesSwitched || direction == DirectionBackward && !state.WritesSwitched { - log.Infof("writes already switched no need to check lag") + s.Logger().Infof("writes already switched no need to check lag") return "", nil } wf, err := s.GetWorkflow(ctx, state.TargetKeyspace, state.Workflow, false, shards) @@ -3625,9 +3733,9 @@ func (s *Server) CopySchemaShard(ctx context.Context, sourceTabletAlias *topodat // Notify Replicas to reload schema. This is best-effort. reloadCtx, cancel := context.WithTimeout(ctx, waitReplicasTimeout) defer cancel() - _, ok := schematools.ReloadShard(reloadCtx, s.ts, s.tmc, logutil.NewMemoryLogger(), destKeyspace, destShard, destPrimaryPos, nil, true) + _, ok := schematools.ReloadShard(reloadCtx, s.ts, s.tmc, s.Logger(), destKeyspace, destShard, destPrimaryPos, nil, true) if !ok { - log.Error(vterrors.Errorf(vtrpcpb.Code_INTERNAL, "CopySchemaShard: failed to reload schema on all replicas")) + s.Logger().Error(vterrors.Errorf(vtrpcpb.Code_INTERNAL, "CopySchemaShard: failed to reload schema on all replicas")) } return err @@ -3645,7 +3753,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. @@ -4130,14 +4238,14 @@ func (s *Server) WorkflowMirrorTraffic(ctx context.Context, req *vtctldatapb.Wor cmd := "MirrorTraffic" resp := &vtctldatapb.WorkflowMirrorTrafficResponse{} - log.Infof("Mirror Traffic done for workflow %s.%s", req.Keyspace, req.Workflow) + s.Logger().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) + s.Logger().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) @@ -4155,7 +4263,7 @@ func (s *Server) mirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMir return err } - log.Infof("Mirroring traffic: %s.%s, workflow state: %s", ts.targetKeyspace, ts.workflow, state.String()) + s.Logger().Infof("Mirroring traffic: %s.%s, workflow state: %s", ts.targetKeyspace, ts.workflow, state.String()) sw := &switcher{ts: ts, s: s} @@ -4169,3 +4277,10 @@ func (s *Server) mirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMir return nil } + +func (s *Server) Logger() logutil.Logger { + if s.options.logger == nil { + s.options.logger = logutil.NewConsoleLogger() // Use default system logger + } + return s.options.logger +} diff --git a/go/vt/vtctl/workflow/server_options.go b/go/vt/vtctl/workflow/server_options.go new file mode 100644 index 00000000000..ed6fdf284a9 --- /dev/null +++ b/go/vt/vtctl/workflow/server_options.go @@ -0,0 +1,56 @@ +/* +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 ( + "vitess.io/vitess/go/vt/logutil" +) + +// serverOptions configure a Workflow Server. serverOptions are set by +// the ServerOption values passed to the server functions. +type serverOptions struct { + logger logutil.Logger +} + +// ServerOption configures how we perform the certain operations. +type ServerOption interface { + apply(*serverOptions) +} + +// funcServerOption wraps a function that modifies serverOptions into +// an implementation of the ServerOption interface. +type funcServerOption struct { + f func(*serverOptions) +} + +func (fso *funcServerOption) apply(so *serverOptions) { + fso.f(so) +} + +func newFuncServerOption(f func(*serverOptions)) *funcServerOption { + return &funcServerOption{ + f: f, + } +} + +// WithLogger determines the customer logger to use. If this option +// is not provided then the default system logger will be used. +func WithLogger(l logutil.Logger) ServerOption { + return newFuncServerOption(func(o *serverOptions) { + o.logger = l + }) +} diff --git a/go/vt/vtctl/workflow/server_test.go b/go/vt/vtctl/workflow/server_test.go index f2b9f6b2496..1653f5001ce 100644 --- a/go/vt/vtctl/workflow/server_test.go +++ b/go/vt/vtctl/workflow/server_test.go @@ -32,6 +32,7 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/utils" + "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/topo/topoproto" @@ -208,20 +209,303 @@ func TestVDiffCreate(t *testing.T) { } } +func TestMoveTablesComplete(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + table1Name := "t1" + table2Name := "t1_2" + table3Name := "t1_3" + tableTemplate := "CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))" + sourceKeyspaceName := "sourceks" + targetKeyspaceName := "targetks" + tabletTypes := []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + } + lockName := fmt.Sprintf("%s/%s", targetKeyspaceName, workflowName) + schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ + table1Name: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: table1Name, + Schema: fmt.Sprintf(tableTemplate, table1Name), + }, + }, + }, + table2Name: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: table2Name, + Schema: fmt.Sprintf(tableTemplate, table2Name), + }, + }, + }, + table3Name: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: table3Name, + Schema: fmt.Sprintf(tableTemplate, table3Name), + }, + }, + }, + } + + testcases := []struct { + name string + sourceKeyspace, targetKeyspace *testKeyspace + preFunc func(t *testing.T, env *testEnv) + req *vtctldatapb.MoveTablesCompleteRequest + expectedSourceQueries []*queryResult + expectedTargetQueries []*queryResult + want *vtctldatapb.MoveTablesCompleteResponse + wantErr string + postFunc func(t *testing.T, env *testEnv) + }{ + { + name: "basic", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + req: &vtctldatapb.MoveTablesCompleteRequest{ + TargetKeyspace: targetKeyspaceName, + Workflow: workflowName, + }, + expectedSourceQueries: []*queryResult{ + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", sourceKeyspaceName, table1Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", sourceKeyspaceName, table2Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", sourceKeyspaceName, table3Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + sourceKeyspaceName, ReverseWorkflowName(workflowName)), + result: &querypb.QueryResult{}, + }, + }, + expectedTargetQueries: []*queryResult{ + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + targetKeyspaceName, workflowName), + result: &querypb.QueryResult{}, + }, + }, + want: &vtctldatapb.MoveTablesCompleteResponse{ + Summary: fmt.Sprintf("Successfully completed the %s workflow in the %s keyspace", + workflowName, targetKeyspaceName), + }, + }, + { + name: "keep routing rules and data", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + req: &vtctldatapb.MoveTablesCompleteRequest{ + TargetKeyspace: targetKeyspaceName, + Workflow: workflowName, + KeepRoutingRules: true, + KeepData: true, + }, + expectedSourceQueries: []*queryResult{ + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + sourceKeyspaceName, ReverseWorkflowName(workflowName)), + result: &querypb.QueryResult{}, + }, + }, + expectedTargetQueries: []*queryResult{ + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + targetKeyspaceName, workflowName), + result: &querypb.QueryResult{}, + }, + }, + postFunc: func(t *testing.T, env *testEnv) { + env.confirmRoutingAllTablesToTarget(t) + }, + want: &vtctldatapb.MoveTablesCompleteResponse{ + Summary: fmt.Sprintf("Successfully completed the %s workflow in the %s keyspace", + workflowName, targetKeyspaceName), + }, + }, + { + name: "rename tables", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + req: &vtctldatapb.MoveTablesCompleteRequest{ + TargetKeyspace: targetKeyspaceName, + Workflow: workflowName, + RenameTables: true, + }, + expectedSourceQueries: []*queryResult{ + { + query: fmt.Sprintf("rename table `vt_%s`.`%s` TO `vt_%s`.`_%s_old`", sourceKeyspaceName, table1Name, sourceKeyspaceName, table1Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("rename table `vt_%s`.`%s` TO `vt_%s`.`_%s_old`", sourceKeyspaceName, table2Name, sourceKeyspaceName, table2Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("rename table `vt_%s`.`%s` TO `vt_%s`.`_%s_old`", sourceKeyspaceName, table3Name, sourceKeyspaceName, table3Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + sourceKeyspaceName, ReverseWorkflowName(workflowName)), + result: &querypb.QueryResult{}, + }, + }, + expectedTargetQueries: []*queryResult{ + { + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", + targetKeyspaceName, workflowName), + result: &querypb.QueryResult{}, + }, + }, + want: &vtctldatapb.MoveTablesCompleteResponse{ + Summary: fmt.Sprintf("Successfully completed the %s workflow in the %s keyspace", + workflowName, targetKeyspaceName), + }, + }, + { + name: "named lock held", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + req: &vtctldatapb.MoveTablesCompleteRequest{ + TargetKeyspace: targetKeyspaceName, + Workflow: workflowName, + KeepRoutingRules: true, + }, + preFunc: func(t *testing.T, env *testEnv) { + _, _, err := env.ts.LockName(ctx, lockName, "test") + require.NoError(t, err) + topo.LockTimeout = 500 * time.Millisecond + }, + postFunc: func(t *testing.T, env *testEnv) { + topo.LockTimeout = 45 * time.Second // reset it to the default + }, + wantErr: fmt.Sprintf("failed to lock the %s workflow: deadline exceeded: internal/named_locks/%s", lockName, lockName), + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.NotNil(t, tc.sourceKeyspace) + require.NotNil(t, tc.targetKeyspace) + require.NotNil(t, tc.req) + env := newTestEnv(t, ctx, defaultCellName, tc.sourceKeyspace, tc.targetKeyspace) + defer env.close() + env.tmc.schema = schema + env.tmc.frozen.Store(true) + if tc.expectedSourceQueries != nil { + require.NotNil(t, env.tablets[tc.sourceKeyspace.KeyspaceName]) + for _, eq := range tc.expectedSourceQueries { + env.tmc.expectVRQueryResultOnKeyspaceTablets(tc.sourceKeyspace.KeyspaceName, eq) + } + } + if tc.expectedTargetQueries != nil { + require.NotNil(t, env.tablets[tc.targetKeyspace.KeyspaceName]) + for _, eq := range tc.expectedTargetQueries { + env.tmc.expectVRQueryResultOnKeyspaceTablets(tc.targetKeyspace.KeyspaceName, eq) + } + } + if tc.preFunc != nil { + tc.preFunc(t, env) + } + // Setup the routing rules as they would be after having previously done SwitchTraffic. + env.addTableRoutingRules(t, ctx, tabletTypes, []string{table1Name, table2Name, table3Name}) + got, err := env.ws.MoveTablesComplete(ctx, tc.req) + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + require.EqualValues(t, got, tc.want, "Server.MoveTablesComplete() = %v, want %v", got, tc.want) + } + if tc.postFunc != nil { + tc.postFunc(t, env) + } else { // Default post checks + // Confirm that we have no routing rules. + rr, err := env.ts.GetRoutingRules(ctx) + require.NoError(t, err) + require.Zero(t, rr.Rules) + + // Confirm that we have no shard tablet controls, which is where + // DeniedTables live. + for _, keyspace := range []*testKeyspace{tc.sourceKeyspace, tc.targetKeyspace} { + for _, shardName := range keyspace.ShardNames { + checkDenyList(t, env.ts, keyspace.KeyspaceName, shardName, nil) + } + } + } + }) + } +} + func TestWorkflowDelete(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() workflowName := "wf1" - tableName := "t1" + table1Name := "t1" + table2Name := "t1_2" + table3Name := "t1_3" + tableTemplate := "CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))" sourceKeyspaceName := "sourceks" targetKeyspaceName := "targetks" + lockName := fmt.Sprintf("%s/%s", targetKeyspaceName, workflowName) schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ - "t1": { + table1Name: { TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ { - Name: tableName, - Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + Name: table1Name, + Schema: fmt.Sprintf(tableTemplate, table1Name), + }, + }, + }, + table2Name: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: table2Name, + Schema: fmt.Sprintf(tableTemplate, table2Name), + }, + }, + }, + table3Name: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: table3Name, + Schema: fmt.Sprintf(tableTemplate, table3Name), }, }, }, @@ -235,11 +519,12 @@ func TestWorkflowDelete(t *testing.T) { expectedSourceQueries []*queryResult expectedTargetQueries []*queryResult want *vtctldatapb.WorkflowDeleteResponse - wantErr bool + wantErr string postFunc func(t *testing.T, env *testEnv) + expectedLogs []string }{ { - name: "basic", + name: "missing table", sourceKeyspace: &testKeyspace{ KeyspaceName: sourceKeyspaceName, ShardNames: []string{"0"}, @@ -261,9 +546,26 @@ func TestWorkflowDelete(t *testing.T) { }, expectedTargetQueries: []*queryResult{ { - query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, tableName), + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table1Name), result: &querypb.QueryResult{}, }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table2Name), + result: &querypb.QueryResult{}, + // We don't care that the cell and tablet info is off in the error message, only that + // it contains the expected SQL error we'd encounter when attempting to drop a table + // that doesn't exist. That will then cause this error to be non-fatal and the workflow + // delete work will continue. + err: fmt.Errorf("rpc error: code = Unknown desc = TabletManager.ExecuteFetchAsDba on cell-01: rpc error: code = Unknown desc = Unknown table 'vt_%s.%s' (errno 1051) (sqlstate 42S02) during query: drop table `vt_%s`.`%s`", + targetKeyspaceName, table2Name, targetKeyspaceName, table2Name), + }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table3Name), + result: &querypb.QueryResult{}, + }, + }, + expectedLogs: []string{ // Confirm that the custom logger is working as expected + fmt.Sprintf("Table `%s` did not exist when attempting to remove it", table2Name), }, want: &vtctldatapb.WorkflowDeleteResponse{ Summary: fmt.Sprintf("Successfully cancelled the %s workflow in the %s keyspace", @@ -281,7 +583,7 @@ func TestWorkflowDelete(t *testing.T) { }, }, { - name: "basic with existing denied table entries", + name: "missing denied table entries", sourceKeyspace: &testKeyspace{ KeyspaceName: sourceKeyspaceName, ShardNames: []string{"0"}, @@ -298,7 +600,9 @@ func TestWorkflowDelete(t *testing.T) { defer targetUnlock(&err) for _, shard := range env.targetKeyspace.ShardNames { _, err := env.ts.UpdateShardFields(lockCtx, targetKeyspaceName, shard, func(si *topo.ShardInfo) error { - err := si.UpdateDeniedTables(lockCtx, topodatapb.TabletType_PRIMARY, nil, false, []string{tableName, "t2", "t3"}) + // So t1_2 and t1_3 do not exist in the denied table list when we go + // to remove t1, t1_2, and t1_3. + err := si.UpdateDeniedTables(lockCtx, topodatapb.TabletType_PRIMARY, nil, false, []string{table1Name, "t2", "t3"}) return err }) require.NoError(t, err) @@ -317,7 +621,15 @@ func TestWorkflowDelete(t *testing.T) { }, expectedTargetQueries: []*queryResult{ { - query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, tableName), + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table1Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table2Name), + result: &querypb.QueryResult{}, + }, + { + query: fmt.Sprintf("drop table `vt_%s`.`%s`", targetKeyspaceName, table3Name), result: &querypb.QueryResult{}, }, }, @@ -346,6 +658,30 @@ func TestWorkflowDelete(t *testing.T) { } }, }, + { + name: "named lock held", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + req: &vtctldatapb.WorkflowDeleteRequest{ + Keyspace: targetKeyspaceName, + Workflow: workflowName, + }, + preFunc: func(t *testing.T, env *testEnv) { + _, _, err := env.ts.LockName(ctx, lockName, "test") + require.NoError(t, err) + topo.LockTimeout = 500 * time.Millisecond + }, + postFunc: func(t *testing.T, env *testEnv) { + topo.LockTimeout = 45 * time.Second // reset it to the default + }, + wantErr: fmt.Sprintf("failed to lock the %s workflow: deadline exceeded: internal/named_locks/%s", lockName, lockName), + }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { @@ -354,6 +690,9 @@ func TestWorkflowDelete(t *testing.T) { require.NotNil(t, tc.req) env := newTestEnv(t, ctx, defaultCellName, tc.sourceKeyspace, tc.targetKeyspace) defer env.close() + memlogger := logutil.NewMemoryLogger() + defer memlogger.Clear() + env.ws.options.logger = memlogger env.tmc.schema = schema if tc.expectedSourceQueries != nil { require.NotNil(t, env.tablets[tc.sourceKeyspace.KeyspaceName]) @@ -371,11 +710,12 @@ func TestWorkflowDelete(t *testing.T) { tc.preFunc(t, env) } got, err := env.ws.WorkflowDelete(ctx, tc.req) - if (err != nil) != tc.wantErr { - require.Fail(t, "unexpected error value", "Server.WorkflowDelete() error = %v, wantErr %v", err, tc.wantErr) - return + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + require.EqualValues(t, got, tc.want, "Server.WorkflowDelete() = %v, want %v", got, tc.want) } - require.EqualValues(t, got, tc.want, "Server.WorkflowDelete() = %v, want %v", got, tc.want) if tc.postFunc != nil { tc.postFunc(t, env) } else { // Default post checks @@ -388,12 +728,20 @@ func TestWorkflowDelete(t *testing.T) { // DeniedTables live. for _, keyspace := range []*testKeyspace{tc.sourceKeyspace, tc.targetKeyspace} { for _, shardName := range keyspace.ShardNames { - si, err := env.ts.GetShard(ctx, keyspace.KeyspaceName, shardName) - require.NoError(t, err) - require.Zero(t, si.Shard.TabletControls) + checkDenyList(t, env.ts, keyspace.KeyspaceName, shardName, nil) } } } + logs := memlogger.String() + // Confirm that the custom logger was passed on to the trafficSwitcher + // if we didn't expect/want an error as otherwise we may not have made + // it into the trafficSwitcher. + if tc.wantErr == "" { + require.Contains(t, logs, "traffic_switcher.go") + } + for _, expectedLog := range tc.expectedLogs { + require.Contains(t, logs, expectedLog) + } }) } } @@ -689,14 +1037,14 @@ func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { DryRun: true, }, want: []string{ - fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [REPLICA,RDONLY]", sourceKeyspaceName, targetKeyspaceName), 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("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [PRIMARY]", sourceKeyspaceName, targetKeyspaceName), 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", @@ -730,14 +1078,14 @@ func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { DryRun: true, }, want: []string{ - fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [REPLICA,RDONLY]", targetKeyspaceName, sourceKeyspaceName), 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("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [PRIMARY]", targetKeyspaceName, sourceKeyspaceName), 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", diff --git a/go/vt/vtctl/workflow/stream_migrator_test.go b/go/vt/vtctl/workflow/stream_migrator_test.go index 38ae10280f7..5e9c2a79038 100644 --- a/go/vt/vtctl/workflow/stream_migrator_test.go +++ b/go/vt/vtctl/workflow/stream_migrator_test.go @@ -19,17 +19,22 @@ package workflow import ( "context" "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/proto/tabletmanagerdata" "vitess.io/vitess/go/vt/sqlparser" - + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vtgate/vindexes" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" ) @@ -347,3 +352,271 @@ func stringifyVRS(streams []*VReplicationStream) string { b, _ := json.Marshal(converted) return string(b) } + +var testVSchema = &vschemapb.Keyspace{ + Sharded: true, + Vindexes: map[string]*vschemapb.Vindex{ + "xxhash": { + Type: "xxhash", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Columns: []string{"c1"}, + Name: "xxhash", + }}, + }, + "t2": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Columns: []string{"c1"}, + Name: "xxhash", + }}, + }, + "ref": { + Type: vindexes.TypeReference, + }, + }, +} + +var ( + commerceKeyspace = &testKeyspace{ + KeyspaceName: "commerce", + ShardNames: []string{"0"}, + } + customerUnshardedKeyspace = &testKeyspace{ + KeyspaceName: "customer", + ShardNames: []string{"0"}, + } + customerShardedKeyspace = &testKeyspace{ + KeyspaceName: "customer", + ShardNames: []string{"-80", "80-"}, + } +) + +type streamMigratorEnv struct { + tenv *testEnv + ts *testTrafficSwitcher + sourceTabletIds []int + targetTabletIds []int +} + +func (env *streamMigratorEnv) close() { + env.tenv.close() +} + +func (env *streamMigratorEnv) addSourceQueries(queries []string) { + for _, id := range env.sourceTabletIds { + for _, q := range queries { + env.tenv.tmc.expectVRQuery(id, q, &sqltypes.Result{}) + } + } +} + +func (env *streamMigratorEnv) addTargetQueries(queries []string) { + for _, id := range env.targetTabletIds { + for _, q := range queries { + env.tenv.tmc.expectVRQuery(id, q, &sqltypes.Result{}) + } + } +} + +func newStreamMigratorEnv(ctx context.Context, t *testing.T, sourceKeyspace, targetKeyspace *testKeyspace) *streamMigratorEnv { + tenv := newTestEnv(t, ctx, "cell1", sourceKeyspace, targetKeyspace) + env := &streamMigratorEnv{tenv: tenv} + + ksschema, err := vindexes.BuildKeyspaceSchema(testVSchema, "ks", sqlparser.NewTestParser()) + require.NoError(t, err, "could not create test keyspace %+v", testVSchema) + sources := make(map[string]*MigrationSource, len(sourceKeyspace.ShardNames)) + targets := make(map[string]*MigrationTarget, len(targetKeyspace.ShardNames)) + for i, shard := range sourceKeyspace.ShardNames { + tablet := tenv.tablets[sourceKeyspace.KeyspaceName][startingSourceTabletUID+(i*tabletUIDStep)] + kr, _ := key.ParseShardingSpec(shard) + sources[shard] = &MigrationSource{ + si: topo.NewShardInfo(sourceKeyspace.KeyspaceName, shard, &topodatapb.Shard{KeyRange: kr[0]}, nil), + primary: &topo.TabletInfo{ + Tablet: tablet, + }, + } + env.sourceTabletIds = append(env.sourceTabletIds, int(tablet.Alias.Uid)) + } + for i, shard := range targetKeyspace.ShardNames { + tablet := tenv.tablets[targetKeyspace.KeyspaceName][startingTargetTabletUID+(i*tabletUIDStep)] + kr, _ := key.ParseShardingSpec(shard) + targets[shard] = &MigrationTarget{ + si: topo.NewShardInfo(targetKeyspace.KeyspaceName, shard, &topodatapb.Shard{KeyRange: kr[0]}, nil), + primary: &topo.TabletInfo{ + Tablet: tablet, + }, + } + env.targetTabletIds = append(env.targetTabletIds, int(tablet.Alias.Uid)) + } + ts := &testTrafficSwitcher{ + trafficSwitcher: trafficSwitcher{ + migrationType: binlogdatapb.MigrationType_SHARDS, + workflow: "wf1", + id: 1, + sources: sources, + targets: targets, + sourceKeyspace: sourceKeyspace.KeyspaceName, + targetKeyspace: targetKeyspace.KeyspaceName, + sourceKSSchema: ksschema, + workflowType: binlogdatapb.VReplicationWorkflowType_Reshard, + ws: tenv.ws, + }, + sourceKeyspaceSchema: ksschema, + } + env.ts = ts + + return env +} + +func addMaterializeWorkflow(t *testing.T, env *streamMigratorEnv, id int32, sourceShard string) { + var wfs tabletmanagerdata.ReadVReplicationWorkflowsResponse + wfName := "wfMat1" + wfs.Workflows = append(wfs.Workflows, &tabletmanagerdata.ReadVReplicationWorkflowResponse{ + Workflow: wfName, + WorkflowType: binlogdatapb.VReplicationWorkflowType_Materialize, + }) + wfs.Workflows[0].Streams = append(wfs.Workflows[0].Streams, &tabletmanagerdata.ReadVReplicationWorkflowResponse_Stream{ + Id: id, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: env.tenv.sourceKeyspace.KeyspaceName, + Shard: sourceShard, + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{ + {Match: "t1", Filter: "select * from t1"}, + }, + }, + }, + Pos: position, + State: binlogdatapb.VReplicationWorkflowState_Running, + }) + workflowKey := env.tenv.tmc.GetWorkflowKey(env.tenv.sourceKeyspace.KeyspaceName, sourceShard) + workflowResponses := []*tabletmanagerdata.ReadVReplicationWorkflowsResponse{ + nil, // this is the response for getting stopped workflows + &wfs, &wfs, &wfs, // return the full list for subsequent GetWorkflows calls + } + for _, resp := range workflowResponses { + env.tenv.tmc.AddVReplicationWorkflowsResponse(workflowKey, resp) + } + queries := []string{ + fmt.Sprintf("select distinct vrepl_id from _vt.copy_state where vrepl_id in (%d)", id), + fmt.Sprintf("update _vt.vreplication set state='Stopped', message='for cutover' where id in (%d)", id), + fmt.Sprintf("delete from _vt.vreplication where db_name='vt_%s' and workflow in ('%s')", + env.tenv.sourceKeyspace.KeyspaceName, wfName), + } + env.addSourceQueries(queries) + queries = []string{ + fmt.Sprintf("delete from _vt.vreplication where db_name='vt_%s' and workflow in ('%s')", + env.tenv.sourceKeyspace.KeyspaceName, wfName), + } + env.addTargetQueries(queries) + +} + +func addReferenceWorkflow(t *testing.T, env *streamMigratorEnv, id int32, sourceShard string) { + var wfs tabletmanagerdata.ReadVReplicationWorkflowsResponse + wfName := "wfRef1" + wfs.Workflows = append(wfs.Workflows, &tabletmanagerdata.ReadVReplicationWorkflowResponse{ + Workflow: wfName, + WorkflowType: binlogdatapb.VReplicationWorkflowType_Materialize, + }) + wfs.Workflows[0].Streams = append(wfs.Workflows[0].Streams, &tabletmanagerdata.ReadVReplicationWorkflowResponse_Stream{ + Id: id, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: env.tenv.sourceKeyspace.KeyspaceName, + Shard: sourceShard, + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{ + {Match: "ref", Filter: "select * from ref"}, + }, + }, + }, + Pos: position, + State: binlogdatapb.VReplicationWorkflowState_Running, + }) + workflowKey := env.tenv.tmc.GetWorkflowKey(env.tenv.sourceKeyspace.KeyspaceName, sourceShard) + workflowResponses := []*tabletmanagerdata.ReadVReplicationWorkflowsResponse{ + nil, // this is the response for getting stopped workflows + &wfs, &wfs, &wfs, // return the full list for subsequent GetWorkflows calls + } + for _, resp := range workflowResponses { + env.tenv.tmc.AddVReplicationWorkflowsResponse(workflowKey, resp) + } +} + +func TestBuildStreamMigratorOneMaterialize(t *testing.T) { + ctx := context.Background() + env := newStreamMigratorEnv(ctx, t, customerUnshardedKeyspace, customerShardedKeyspace) + defer env.close() + tmc := env.tenv.tmc + + addMaterializeWorkflow(t, env, 100, "0") + + // FIXME: Note: currently it is not optimal: we create two streams for each shard from all the + // shards even if the key ranges don't intersect. TBD + getInsert := func(shard string) string { + s := "/insert into _vt.vreplication.*" + s += fmt.Sprintf("shard:\"-80\".*in_keyrange.*c1.*%s.*", shard) + s += fmt.Sprintf("shard:\"80-\".*in_keyrange.*c1.*%s.*", shard) + return s + } + tmc.expectVRQuery(200, getInsert("-80"), &sqltypes.Result{}) + tmc.expectVRQuery(210, getInsert("80-"), &sqltypes.Result{}) + + sm, err := BuildStreamMigrator(ctx, env.ts, false, sqlparser.NewTestParser()) + require.NoError(t, err) + require.NotNil(t, sm) + require.NotNil(t, sm.streams) + require.Equal(t, 1, len(sm.streams)) + + workflows, err := sm.StopStreams(ctx) + require.NoError(t, err) + require.Equal(t, 1, len(workflows)) + require.NoError(t, sm.MigrateStreams(ctx)) + require.Len(t, sm.templates, 1) + env.addTargetQueries([]string{ + fmt.Sprintf("update _vt.vreplication set state='Running' where db_name='vt_%s' and workflow in ('%s')", + env.tenv.sourceKeyspace.KeyspaceName, "wfMat1"), + }) + require.NoError(t, StreamMigratorFinalize(ctx, env.ts, []string{"wfMat1"})) +} + +func TestBuildStreamMigratorNoStreams(t *testing.T) { + ctx := context.Background() + env := newStreamMigratorEnv(ctx, t, customerUnshardedKeyspace, customerShardedKeyspace) + defer env.close() + + sm, err := BuildStreamMigrator(ctx, env.ts, false, sqlparser.NewTestParser()) + require.NoError(t, err) + require.NotNil(t, sm) + require.NotNil(t, sm.streams) + require.Equal(t, 0, len(sm.streams)) + + workflows, err := sm.StopStreams(ctx) + require.NoError(t, err) + require.Equal(t, 0, len(workflows)) + require.NoError(t, sm.MigrateStreams(ctx)) + require.Len(t, sm.templates, 0) +} + +func TestBuildStreamMigratorRefStream(t *testing.T) { + ctx := context.Background() + env := newStreamMigratorEnv(ctx, t, customerUnshardedKeyspace, customerShardedKeyspace) + defer env.close() + + addReferenceWorkflow(t, env, 100, "0") + + sm, err := BuildStreamMigrator(ctx, env.ts, false, sqlparser.NewTestParser()) + require.NoError(t, err) + require.NotNil(t, sm) + require.NotNil(t, sm.streams) + require.Equal(t, 0, len(sm.streams)) + + workflows, err := sm.StopStreams(ctx) + require.NoError(t, err) + require.Equal(t, 0, len(workflows)) + require.NoError(t, sm.MigrateStreams(ctx)) + require.Len(t, sm.templates, 0) +} diff --git a/go/vt/vtctl/workflow/switcher.go b/go/vt/vtctl/workflow/switcher.go index 3fbd1c507e2..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 { diff --git a/go/vt/vtctl/workflow/switcher_dry_run.go b/go/vt/vtctl/workflow/switcher_dry_run.go index 55c843b07cb..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" @@ -304,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 9dea0af30a1..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 diff --git a/go/vt/vtctl/workflow/traffic_switcher.go b/go/vt/vtctl/workflow/traffic_switcher.go index 35930bc3e97..34e1e4e4329 100644 --- a/go/vt/vtctl/workflow/traffic_switcher.go +++ b/go/vt/vtctl/workflow/traffic_switcher.go @@ -30,13 +30,11 @@ import ( "golang.org/x/sync/errgroup" "vitess.io/vitess/go/json2" - "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sqlescape" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/key" - "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" @@ -252,7 +250,7 @@ func (ts *trafficSwitcher) TopoServer() *topo.Server { func (ts *trafficSwitcher) TabletManagerClient() tmclient.TabletManagerClient { return ts.ws.tmc } func (ts *trafficSwitcher) Logger() logutil.Logger { if ts.logger == nil { - ts.logger = logutil.NewConsoleLogger() + ts.logger = logutil.NewConsoleLogger() // Use the default system logger } return ts.logger } @@ -436,7 +434,7 @@ func (ts *trafficSwitcher) deleteShardRoutingRules(ctx context.Context) error { srr, err := topotools.GetShardRoutingRules(ctx, ts.TopoServer()) if err != nil { if topo.IsErrType(err, topo.NoNode) { - log.Warningf("No shard routing rules found when attempting to delete the ones for the %s keyspace", ts.targetKeyspace) + ts.Logger().Warningf("No shard routing rules found when attempting to delete the ones for the %s keyspace", ts.targetKeyspace) return nil } return err @@ -454,7 +452,7 @@ func (ts *trafficSwitcher) deleteKeyspaceRoutingRules(ctx context.Context) error if !ts.IsMultiTenantMigration() { return nil } - log.Infof("deleteKeyspaceRoutingRules: workflow %s.%s", ts.targetKeyspace, ts.workflow) + ts.Logger().Infof("deleteKeyspaceRoutingRules: workflow %s.%s", ts.targetKeyspace, ts.workflow) reason := fmt.Sprintf("Deleting rules for %s", ts.SourceKeyspaceName()) return topotools.UpdateKeyspaceRoutingRules(ctx, ts.TopoServer(), reason, func(ctx context.Context, rules *map[string]string) error { @@ -548,12 +546,12 @@ func (ts *trafficSwitcher) removeSourceTables(ctx context.Context, removalType T DisableForeignKeyChecks: true, }) if err != nil { - if mysqlErr, ok := err.(*sqlerror.SQLError); ok && mysqlErr.Num == sqlerror.ERNoSuchTable { + if IsTableDidNotExistError(err) { ts.Logger().Warningf("%s: Table %s did not exist when attempting to remove it", topoproto.TabletAliasString(source.GetPrimary().GetAlias()), tableName) - return nil + } else { + ts.Logger().Errorf("%s: Error removing table %s: %v", topoproto.TabletAliasString(source.GetPrimary().GetAlias()), tableName, err) + return err } - ts.Logger().Errorf("%s: Error removing table %s: %v", topoproto.TabletAliasString(source.GetPrimary().GetAlias()), tableName, err) - return err } ts.Logger().Infof("%s: Removed table %s.%s\n", topoproto.TabletAliasString(source.GetPrimary().GetAlias()), source.GetPrimary().DbName(), tableName) @@ -583,19 +581,19 @@ func (ts *trafficSwitcher) dropSourceShards(ctx context.Context) error { func (ts *trafficSwitcher) switchShardReads(ctx context.Context, cells []string, servedTypes []topodatapb.TabletType, direction TrafficSwitchDirection) error { cellsStr := strings.Join(cells, ",") - log.Infof("switchShardReads: cells: %s, tablet types: %+v, direction %d", cellsStr, servedTypes, direction) + ts.Logger().Infof("switchShardReads: cells: %s, tablet types: %+v, direction %d", cellsStr, servedTypes, direction) fromShards, toShards := ts.SourceShards(), ts.TargetShards() if err := ts.TopoServer().ValidateSrvKeyspace(ctx, ts.TargetKeyspaceName(), cellsStr); err != nil { err2 := vterrors.Wrapf(err, "Before switching shard reads, found SrvKeyspace for %s is corrupt in cell %s", ts.TargetKeyspaceName(), cellsStr) - log.Errorf("%w", err2) + ts.Logger().Errorf("%w", err2) return err2 } for _, servedType := range servedTypes { - if err := ts.ws.updateShardRecords(ctx, ts.SourceKeyspaceName(), fromShards, cells, servedType, true /* isFrom */, false /* clearSourceShards */, ts.logger); err != nil { + if err := ts.ws.updateShardRecords(ctx, ts.SourceKeyspaceName(), fromShards, cells, servedType, true /* isFrom */, false /* clearSourceShards */, ts.Logger()); err != nil { return err } - if err := ts.ws.updateShardRecords(ctx, ts.SourceKeyspaceName(), toShards, cells, servedType, false, false, ts.logger); err != nil { + if err := ts.ws.updateShardRecords(ctx, ts.SourceKeyspaceName(), toShards, cells, servedType, false, false, ts.Logger()); err != nil { return err } err := ts.TopoServer().MigrateServedType(ctx, ts.SourceKeyspaceName(), toShards, fromShards, servedType, cells) @@ -606,14 +604,14 @@ func (ts *trafficSwitcher) switchShardReads(ctx context.Context, cells []string, if err := ts.TopoServer().ValidateSrvKeyspace(ctx, ts.TargetKeyspaceName(), cellsStr); err != nil { err2 := vterrors.Wrapf(err, "after switching shard reads, found SrvKeyspace for %s is corrupt in cell %s", ts.TargetKeyspaceName(), cellsStr) - log.Errorf("%w", err2) + ts.Logger().Errorf("%w", err2) return err2 } return nil } func (ts *trafficSwitcher) switchTableReads(ctx context.Context, cells []string, servedTypes []topodatapb.TabletType, rebuildSrvVSchema bool, direction TrafficSwitchDirection) error { - log.Infof("switchTableReads: cells: %s, tablet types: %+v, direction: %s", strings.Join(cells, ","), servedTypes, direction) + ts.Logger().Infof("switchTableReads: cells: %s, tablet types: %+v, direction: %s", strings.Join(cells, ","), servedTypes, direction) rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer()) if err != nil { return err @@ -655,7 +653,7 @@ func (ts *trafficSwitcher) startReverseVReplication(ctx context.Context) error { } func (ts *trafficSwitcher) createJournals(ctx context.Context, sourceWorkflows []string) error { - log.Infof("In createJournals for source workflows %+v", sourceWorkflows) + ts.Logger().Infof("In createJournals for source workflows %+v", sourceWorkflows) return ts.ForAllSources(func(source *MigrationSource) error { if source.Journaled { return nil @@ -692,7 +690,7 @@ func (ts *trafficSwitcher) createJournals(ctx context.Context, sourceWorkflows [ }) } - log.Infof("Creating journal %v", journal) + ts.Logger().Infof("Creating journal %v", journal) ts.Logger().Infof("Creating journal: %v", journal) statement := fmt.Sprintf("insert into _vt.resharding_journal "+ "(id, db_name, val) "+ @@ -773,7 +771,7 @@ func (ts *trafficSwitcher) changeWriteRoute(ctx context.Context) error { func (ts *trafficSwitcher) changeShardRouting(ctx context.Context) error { if err := ts.TopoServer().ValidateSrvKeyspace(ctx, ts.TargetKeyspaceName(), ""); err != nil { err2 := vterrors.Wrapf(err, "Before changing shard routes, found SrvKeyspace for %s is corrupt", ts.TargetKeyspaceName()) - log.Errorf("%w", err2) + ts.Logger().Errorf("%w", err2) return err2 } err := ts.ForAllSources(func(source *MigrationSource) error { @@ -802,7 +800,7 @@ func (ts *trafficSwitcher) changeShardRouting(ctx context.Context) error { } if err := ts.TopoServer().ValidateSrvKeyspace(ctx, ts.TargetKeyspaceName(), ""); err != nil { err2 := vterrors.Wrapf(err, "after changing shard routes, found SrvKeyspace for %s is corrupt", ts.TargetKeyspaceName()) - log.Errorf("%w", err2) + ts.Logger().Errorf("%w", err2) return err2 } return nil @@ -922,7 +920,7 @@ func (ts *trafficSwitcher) createReverseVReplication(ctx context.Context) error Filter: filter, }) } - log.Infof("Creating reverse workflow vreplication stream on tablet %s: workflow %s, startPos %s", + ts.Logger().Infof("Creating reverse workflow vreplication stream on tablet %s: workflow %s, startPos %s", source.GetPrimary().GetAlias(), ts.ReverseWorkflowName(), target.Position) _, err = ts.VReplicationExec(ctx, source.GetPrimary().GetAlias(), binlogplayer.CreateVReplicationState(ts.ReverseWorkflowName(), reverseBls, target.Position, @@ -939,7 +937,7 @@ func (ts *trafficSwitcher) createReverseVReplication(ctx context.Context) error updateQuery := ts.getReverseVReplicationUpdateQuery(target.GetPrimary().GetAlias().GetCell(), source.GetPrimary().GetAlias().GetCell(), source.GetPrimary().DbName(), string(optionsJSON)) if updateQuery != "" { - log.Infof("Updating vreplication stream entry on %s with: %s", source.GetPrimary().GetAlias(), updateQuery) + ts.Logger().Infof("Updating vreplication stream entry on %s with: %s", source.GetPrimary().GetAlias(), updateQuery) _, err = ts.VReplicationExec(ctx, source.GetPrimary().GetAlias(), updateQuery) return err } @@ -989,12 +987,12 @@ func (ts *trafficSwitcher) waitForCatchup(ctx context.Context, filteredReplicati if err := ts.TabletManagerClient().VReplicationWaitForPos(ctx, target.GetPrimary().Tablet, uid, source.Position); err != nil { return err } - log.Infof("After catchup: target keyspace:shard: %v:%v, source position %v, uid %d", + ts.Logger().Infof("After catchup: target keyspace:shard: %v:%v, source position %v, uid %d", ts.TargetKeyspaceName(), target.GetShard().ShardName(), source.Position, uid) ts.Logger().Infof("After catchup: position for keyspace:shard: %v:%v reached, uid %d", ts.TargetKeyspaceName(), target.GetShard().ShardName(), uid) if _, err := ts.TabletManagerClient().VReplicationExec(ctx, target.GetPrimary().Tablet, binlogplayer.StopVReplication(uid, "stopped for cutover")); err != nil { - log.Infof("Error marking stopped for cutover on %s, uid %d", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), uid) + ts.Logger().Infof("Error marking stopped for cutover on %s, uid %d", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), uid) return err } return nil @@ -1018,19 +1016,10 @@ func (ts *trafficSwitcher) stopSourceWrites(ctx context.Context) error { err = ts.changeShardsAccess(ctx, ts.SourceKeyspaceName(), ts.SourceShards(), disallowWrites) } if err != nil { - log.Warningf("Error: %s", err) + ts.Logger().Warningf("Error stopping writes on migration sources: %v", err) return err } - return ts.ForAllSources(func(source *MigrationSource) error { - var err error - source.Position, err = ts.TabletManagerClient().PrimaryPosition(ctx, source.GetPrimary().Tablet) - log.Infof("Stopped Source Writes. Position for source %v:%v: %v", - ts.SourceKeyspaceName(), source.GetShard().ShardName(), source.Position) - if err != nil { - log.Warningf("Error: %s", err) - } - return err - }) + return nil } // switchDeniedTables switches the denied tables rules for the traffic switch. @@ -1076,7 +1065,7 @@ func (ts *trafficSwitcher) switchDeniedTables(ctx context.Context) error { }) }) if err := egrp.Wait(); err != nil { - log.Warningf("Error in switchDeniedTables: %s", err) + ts.Logger().Warningf("Error in switchDeniedTables: %s", err) return err } @@ -1158,7 +1147,7 @@ func (ts *trafficSwitcher) dropSourceReverseVReplicationStreams(ctx context.Cont func (ts *trafficSwitcher) removeTargetTables(ctx context.Context) error { err := ts.ForAllTargets(func(target *MigrationTarget) error { - log.Infof("ForAllTargets: %+v", target) + ts.Logger().Infof("ForAllTargets: %+v", target) for _, tableName := range ts.Tables() { primaryDbName, err := sqlescape.EnsureEscaped(target.GetPrimary().DbName()) if err != nil { @@ -1177,15 +1166,15 @@ func (ts *trafficSwitcher) removeTargetTables(ctx context.Context) error { ReloadSchema: true, DisableForeignKeyChecks: true, }) - log.Infof("Removed target table with result: %+v", res) + ts.Logger().Infof("Removed target table with result: %+v", res) if err != nil { - if mysqlErr, ok := err.(*sqlerror.SQLError); ok && mysqlErr.Num == sqlerror.ERNoSuchTable { + if IsTableDidNotExistError(err) { // The table was already gone, so we can ignore the error. ts.Logger().Warningf("%s: Table %s did not exist when attempting to remove it", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), tableName) - return nil + } else { + ts.Logger().Errorf("%s: Error removing table %s: %v", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), tableName, err) + return err } - ts.Logger().Errorf("%s: Error removing table %s: %v", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), tableName, err) - return err } ts.Logger().Infof("%s: Removed table %s.%s\n", topoproto.TabletAliasString(target.GetPrimary().GetAlias()), target.GetPrimary().DbName(), tableName) @@ -1320,6 +1309,24 @@ func (ts *trafficSwitcher) gatherPositions(ctx context.Context) error { }) } +// gatherSourcePositions will get the current replication position for all +// migration sources. +func (ts *trafficSwitcher) gatherSourcePositions(ctx context.Context) error { + return ts.ForAllSources(func(source *MigrationSource) error { + var err error + tablet := source.GetPrimary().Tablet + tabletAlias := topoproto.TabletAliasString(tablet.Alias) + source.Position, err = ts.TabletManagerClient().PrimaryPosition(ctx, tablet) + if err != nil { + ts.Logger().Errorf("Error getting migration source position on %s: %s", tabletAlias, err) + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "failed to get position on migration source %s: %v", + tabletAlias, err) + } + ts.Logger().Infof("Position on migration source %s after having stopped writes: %s", tabletAlias, source.Position) + return nil + }) +} + func (ts *trafficSwitcher) isSequenceParticipating(ctx context.Context) (bool, error) { vschema, err := ts.TopoServer().GetVSchema(ctx, ts.targetKeyspace) if err != nil { @@ -1747,8 +1754,6 @@ func (ts *trafficSwitcher) IsMultiTenantMigration() bool { } func (ts *trafficSwitcher) mirrorTableTraffic(ctx context.Context, types []topodatapb.TabletType, percent float32) error { - log.Infof("mirrorTableTraffic") - mrs, err := topotools.GetMirrorRules(ctx, ts.TopoServer()) if err != nil { return err diff --git a/go/vt/vtctl/workflow/traffic_switcher_test.go b/go/vt/vtctl/workflow/traffic_switcher_test.go index 5c0b2aba682..dfe394b2608 100644 --- a/go/vt/vtctl/workflow/traffic_switcher_test.go +++ b/go/vt/vtctl/workflow/traffic_switcher_test.go @@ -20,12 +20,15 @@ import ( "context" "fmt" "reflect" + "strconv" + "strings" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" "vitess.io/vitess/go/vt/proto/vschema" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vtgate/vindexes" @@ -361,3 +364,72 @@ func TestGetTargetSequenceMetadata(t *testing.T) { }) } } + +// TestSwitchTrafficPositionHandling confirms that if any writes are somehow +// executed against the source between the stop source writes and wait for +// catchup steps, that we have the correct position and do not lose the write(s). +func TestTrafficSwitchPositionHandling(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + tableName := "t1" + sourceKeyspaceName := "sourceks" + targetKeyspaceName := "targetks" + + 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), + }, + }, + }, + } + + sourceKeyspace := &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + } + targetKeyspace := &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + } + + env := newTestEnv(t, ctx, defaultCellName, sourceKeyspace, targetKeyspace) + defer env.close() + env.tmc.schema = schema + + ts, _, err := env.ws.getWorkflowState(ctx, targetKeyspaceName, workflowName) + require.NoError(t, err) + sw := &switcher{ts: ts, s: env.ws} + + lockCtx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "test") + require.NoError(t, lockErr) + ctx = lockCtx + defer sourceUnlock(&err) + lockCtx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "test") + require.NoError(t, lockErr) + ctx = lockCtx + defer targetUnlock(&err) + + err = ts.stopSourceWrites(ctx) + require.NoError(t, err) + + // Now we simulate a write on the source. + newPosition := position[:strings.LastIndex(position, "-")+1] + oldSeqNo, err := strconv.Atoi(position[strings.LastIndex(position, "-")+1:]) + require.NoError(t, err) + newPosition = fmt.Sprintf("%s%d", newPosition, oldSeqNo+1) + env.tmc.setPrimaryPosition(env.tablets[sourceKeyspaceName][startingSourceTabletUID], newPosition) + + // And confirm that we picked up the new position. + err = ts.gatherSourcePositions(ctx) + require.NoError(t, err) + err = ts.ForAllSources(func(ms *MigrationSource) error { + require.Equal(t, newPosition, ms.Position) + return nil + }) + require.NoError(t, err) +} diff --git a/go/vt/vtctl/workflow/utils.go b/go/vt/vtctl/workflow/utils.go index d4e8d7b4ec0..374d96396f2 100644 --- a/go/vt/vtctl/workflow/utils.go +++ b/go/vt/vtctl/workflow/utils.go @@ -28,27 +28,27 @@ import ( "strings" "sync" - querypb "vitess.io/vitess/go/vt/proto/query" - - "vitess.io/vitess/go/vt/vtgate/vindexes" - "google.golang.org/protobuf/encoding/prototext" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sets" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/vindexes" "vitess.io/vitess/go/vt/vttablet/tmclient" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + querypb "vitess.io/vitess/go/vt/proto/query" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" @@ -398,8 +398,7 @@ func BuildTargets(ctx context.Context, ts *topo.Server, tmc tmclient.TabletManag optionsJSON := wf.GetOptions() if optionsJSON != "" { if err := json.Unmarshal([]byte(optionsJSON), &options); err != nil { - log.Errorf("failed to unmarshal options: %v %s", err, optionsJSON) - return nil, err + return nil, vterrors.Wrapf(err, "failed to unmarshal options: %s", optionsJSON) } } @@ -545,7 +544,7 @@ func doValidateWorkflowHasCompleted(ctx context.Context, ts *trafficSwitcher) er _ = ts.ForAllSources(func(source *MigrationSource) error { wg.Add(1) if source.GetShard().IsPrimaryServing { - rec.RecordError(fmt.Errorf(fmt.Sprintf("Shard %s is still serving", source.GetShard().ShardName()))) + rec.RecordError(fmt.Errorf("shard %s is still serving", source.GetShard().ShardName())) } wg.Done() return nil @@ -671,7 +670,7 @@ func areTabletsAvailableToStreamFrom(ctx context.Context, req *vtctldatapb.Workf wg.Wait() if allErrors.HasErrors() { - log.Errorf("%s", allErrors.Error()) + ts.Logger().Errorf("%s", allErrors.Error()) return allErrors.Error() } return nil @@ -949,3 +948,22 @@ func getTabletTypeSuffix(tabletType topodatapb.TabletType) string { } return "" } + +// IsTableDidNotExistError will convert the given error to an sqlerror.SQLError and if +// the error code is ERNoSuchTable or ERBadTable, it will return true. This is helpful +// when e.g. processing a gRPC error which will be a status.Error that needs to be +// converted to an sqlerror.SQLError before we can examine the error code. +func IsTableDidNotExistError(err error) bool { + if sqlErr, ok := sqlerror.NewSQLErrorFromError(err).(*sqlerror.SQLError); ok { + return sqlErr.Num == sqlerror.ERNoSuchTable || sqlErr.Num == sqlerror.ERBadTable + } + return false +} + +// defaultErrorHandler provides a way to consistently handle errors by logging and +// returning them. +func defaultErrorHandler(logger logutil.Logger, message string, err error) (*[]string, error) { + werr := vterrors.Wrap(err, message) + logger.Error(werr) + return nil, werr +} diff --git a/go/vt/vtctl/workflow/utils_test.go b/go/vt/vtctl/workflow/utils_test.go index d79c4710b77..b315e1aa991 100644 --- a/go/vt/vtctl/workflow/utils_test.go +++ b/go/vt/vtctl/workflow/utils_test.go @@ -16,12 +16,85 @@ import ( "vitess.io/vitess/go/testfiles" "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/proto/vtctldata" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/etcd2topo" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/topotools" ) +// TestCreateDefaultShardRoutingRules confirms that the default shard routing rules are created correctly for sharded +// and unsharded keyspaces. +func TestCreateDefaultShardRoutingRules(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ks1 := &testKeyspace{ + KeyspaceName: "sourceks", + } + ks2 := &testKeyspace{ + KeyspaceName: "targetks", + } + + type testCase struct { + name string + sourceKeyspace *testKeyspace + targetKeyspace *testKeyspace + shards []string + want map[string]string + } + getExpectedRules := func(sourceKeyspace, targetKeyspace *testKeyspace) map[string]string { + rules := make(map[string]string) + for _, targetShard := range targetKeyspace.ShardNames { + rules[fmt.Sprintf("%s.%s", targetKeyspace.KeyspaceName, targetShard)] = sourceKeyspace.KeyspaceName + } + return rules + + } + testCases := []testCase{ + { + name: "unsharded", + sourceKeyspace: ks1, + targetKeyspace: ks2, + shards: []string{"0"}, + }, + { + name: "sharded", + sourceKeyspace: ks2, + targetKeyspace: ks1, + shards: []string{"-80", "80-"}, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tc.sourceKeyspace.ShardNames = tc.shards + tc.targetKeyspace.ShardNames = tc.shards + env := newTestEnv(t, ctx, defaultCellName, tc.sourceKeyspace, tc.targetKeyspace) + defer env.close() + ms := &vtctldata.MaterializeSettings{ + Workflow: "wf1", + SourceKeyspace: tc.sourceKeyspace.KeyspaceName, + TargetKeyspace: tc.targetKeyspace.KeyspaceName, + TableSettings: []*vtctldata.TableMaterializeSettings{ + { + TargetTable: "t1", + SourceExpression: "select * from t1", + }, + }, + Cell: "zone1", + SourceShards: tc.sourceKeyspace.ShardNames, + } + err := createDefaultShardRoutingRules(ctx, ms, env.ts) + require.NoError(t, err) + rules, err := topotools.GetShardRoutingRules(ctx, env.ts) + require.NoError(t, err) + require.Len(t, rules, len(tc.shards)) + want := getExpectedRules(tc.sourceKeyspace, tc.targetKeyspace) + require.EqualValues(t, want, rules) + }) + } +} + // TestUpdateKeyspaceRoutingRule confirms that the keyspace routing rules are updated correctly. func TestUpdateKeyspaceRoutingRule(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) diff --git a/go/vt/vtctl/workflow/vreplication_stream_test.go b/go/vt/vtctl/workflow/vreplication_stream_test.go new file mode 100644 index 00000000000..6269cfa978e --- /dev/null +++ b/go/vt/vtctl/workflow/vreplication_stream_test.go @@ -0,0 +1,52 @@ +/* +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 ( + "fmt" + "reflect" + "testing" +) + +// TestVReplicationStreams tests various methods of VReplicationStreams. +func TestVReplicationStreams(t *testing.T) { + var streams VReplicationStreams + for i := 1; i <= 3; i++ { + streams = append(streams, &VReplicationStream{ID: int32(i), Workflow: fmt.Sprintf("workflow%d", i)}) + } + + tests := []struct { + name string + funcUnderTest func(VReplicationStreams) interface{} + expectedResult interface{} + }{ + {"Test IDs", func(s VReplicationStreams) interface{} { return s.IDs() }, []int32{1, 2, 3}}, + {"Test Values", func(s VReplicationStreams) interface{} { return s.Values() }, "(1, 2, 3)"}, + {"Test Workflows", func(s VReplicationStreams) interface{} { return s.Workflows() }, []string{"workflow1", "workflow2", "workflow3"}}, + {"Test Copy", func(s VReplicationStreams) interface{} { return s.Copy() }, streams.Copy()}, + {"Test ToSlice", func(s VReplicationStreams) interface{} { return s.ToSlice() }, []*VReplicationStream{streams[0], streams[1], streams[2]}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.funcUnderTest(streams) + if !reflect.DeepEqual(result, tt.expectedResult) { + t.Errorf("Failed %s: expected %v, got %v", tt.name, tt.expectedResult, result) + } + }) + } +} diff --git a/go/vt/vterrors/code.go b/go/vt/vterrors/code.go index d485c930b77..31c98cef280 100644 --- a/go/vt/vterrors/code.go +++ b/go/vt/vterrors/code.go @@ -96,8 +96,15 @@ var ( VT09022 = errorWithoutState("VT09022", vtrpcpb.Code_FAILED_PRECONDITION, "Destination does not have exactly one shard: %v", "Cannot send query to multiple shards.") VT09023 = errorWithoutState("VT09023", vtrpcpb.Code_FAILED_PRECONDITION, "could not map %v to a keyspace id", "Unable to determine the shard for the given row.") VT09024 = errorWithoutState("VT09024", vtrpcpb.Code_FAILED_PRECONDITION, "could not map %v to a unique keyspace id: %v", "Unable to determine the shard for the given row.") + VT09025 = errorWithoutState("VT09025", vtrpcpb.Code_FAILED_PRECONDITION, "atomic transaction error: %v", "Error in atomic transactions") + VT09026 = errorWithState("VT09026", vtrpcpb.Code_FAILED_PRECONDITION, CTERecursiveRequiresUnion, "Recursive Common Table Expression '%s' should contain a UNION", "") + VT09027 = errorWithState("VT09027", vtrpcpb.Code_FAILED_PRECONDITION, CTERecursiveForbidsAggregation, "Recursive Common Table Expression '%s' can contain neither aggregation nor window functions in recursive query block", "") + VT09028 = errorWithState("VT09028", vtrpcpb.Code_FAILED_PRECONDITION, CTERecursiveForbiddenJoinOrder, "In recursive query block of Recursive Common Table Expression '%s', the recursive table must neither be in the right argument of a LEFT JOIN, nor be forced to be non-first with join order hints", "") + VT09029 = errorWithState("VT09029", vtrpcpb.Code_FAILED_PRECONDITION, CTERecursiveRequiresSingleReference, "In recursive query block of Recursive Common Table Expression %s, the recursive table must be referenced only once, and not in any subquery", "") + VT09030 = errorWithState("VT09030", vtrpcpb.Code_FAILED_PRECONDITION, CTEMaxRecursionDepth, "Recursive query aborted after 1000 iterations.", "") VT10001 = errorWithoutState("VT10001", vtrpcpb.Code_ABORTED, "foreign key constraints are not allowed", "Foreign key constraints are not allowed, see https://vitess.io/blog/2021-06-15-online-ddl-why-no-fk/.") + VT10002 = errorWithoutState("VT10002", vtrpcpb.Code_ABORTED, "atomic distributed transaction not allowed: %s", "The distributed transaction cannot be committed. A rollback decision is taken.") VT12001 = errorWithoutState("VT12001", vtrpcpb.Code_UNIMPLEMENTED, "unsupported: %s", "This statement is unsupported by Vitess. Please rewrite your query to use supported syntax.") VT12002 = errorWithoutState("VT12002", vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cross-shard foreign keys", "Vitess does not support cross shard foreign keys.") @@ -181,7 +188,12 @@ var ( VT09022, VT09023, VT09024, + VT09026, + VT09027, + VT09028, + VT09029, VT10001, + VT10002, VT12001, VT12002, VT13001, diff --git a/go/vt/vterrors/errors_test.go b/go/vt/vterrors/errors_test.go index 49b77ee0385..3444b0986c4 100644 --- a/go/vt/vterrors/errors_test.go +++ b/go/vt/vterrors/errors_test.go @@ -213,7 +213,7 @@ func TestWrapf(t *testing.T) { } for _, tt := range tests { - got := Wrapf(tt.err, tt.message).Error() + got := Wrap(tt.err, tt.message).Error() if got != tt.want { t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) } diff --git a/go/vt/vterrors/state.go b/go/vt/vterrors/state.go index 8223405fc92..528000e9e41 100644 --- a/go/vt/vterrors/state.go +++ b/go/vt/vterrors/state.go @@ -62,6 +62,11 @@ const ( NoReferencedRow2 UnknownStmtHandler KeyDoesNotExist + CTERecursiveRequiresSingleReference + CTERecursiveRequiresUnion + CTERecursiveForbidsAggregation + CTERecursiveForbiddenJoinOrder + CTEMaxRecursionDepth // not found BadDb @@ -120,6 +125,8 @@ const ( CharacterSetMismatch WrongParametersToNativeFct + VectorConversion + // No state should be added below NumOfStates NumOfStates ) diff --git a/go/vt/vterrors/vterrors.go b/go/vt/vterrors/vterrors.go index 6a322837de9..c97a7c8e45f 100644 --- a/go/vt/vterrors/vterrors.go +++ b/go/vt/vterrors/vterrors.go @@ -150,10 +150,14 @@ func Errorf(code vtrpcpb.Code, format string, args ...any) error { // NewErrorf also records the stack trace at the point it was called. // Use this for errors in Vitess that we eventually want to mimic as a MySQL error func NewErrorf(code vtrpcpb.Code, state State, format string, args ...any) error { - msg := format - if len(args) != 0 { - msg = fmt.Sprintf(format, args...) - } + return NewError(code, state, fmt.Sprintf(format, args...)) +} + +// NewErrorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// NewErrorf also records the stack trace at the point it was called. +// Use this for errors in Vitess that we eventually want to mimic as a MySQL error +func NewError(code vtrpcpb.Code, state State, msg string) error { return &fundamental{ msg: msg, code: code, @@ -251,14 +255,7 @@ func Wrap(err error, message string) error { // at the point Wrapf is call, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...any) error { - if err == nil { - return nil - } - return &wrapping{ - cause: err, - msg: fmt.Sprintf(format, args...), - stack: callers(), - } + return Wrap(err, fmt.Sprintf(format, args...)) } // Unwrap attempts to return the Cause of the given error, if it is indeed the result of a vterrors.Wrapf() diff --git a/go/vt/vtexplain/vtexplain_test.go b/go/vt/vtexplain/vtexplain_test.go index ed32d0698db..e9420b043c7 100644 --- a/go/vt/vtexplain/vtexplain_test.go +++ b/go/vt/vtexplain/vtexplain_test.go @@ -296,7 +296,7 @@ func TestJSONOutput(t *testing.T) { }` diff := cmp.Diff(wantJSON, string(actionsJSON)) if diff != "" { - t.Errorf(diff) + t.Error(diff) } } 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..dc052df33d6 --- /dev/null +++ b/go/vt/vtgate/debug_2pc.go @@ -0,0 +1,69 @@ +//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 + +import ( + "context" + + "vitess.io/vitess/go/vt/callerid" + "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" +) + +const DebugTwoPc = true + +// checkTestFailure is used to simulate failures in 2PC flow for testing when DebugTwoPc is true. +func checkTestFailure(ctx context.Context, expectCaller string, target *querypb.Target) error { + callerID := callerid.EffectiveCallerIDFromContext(ctx) + if callerID == nil || callerID.GetPrincipal() != expectCaller { + return 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 vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail After TR created") + case "RMPrepare_-40_FailNow": + if target.Shard != "-40" { + return nil + } + log.Errorf("Fail During RM prepare") + // no commit decision is made. Transaction should be a rolled back. + return 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 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 vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail After MM commit") + case "RMCommit_-40_FailNow": + if target.Shard != "-40" { + return nil + } + log.Errorf("Fail During RM commit") + // commit decision is made. Transaction should be a committed. + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail During RM commit") + default: + return nil + } +} diff --git a/go/vt/vtgate/endtoend/aggr_test.go b/go/vt/vtgate/endtoend/aggr_test.go index b37697a72f4..402cecc0c6d 100644 --- a/go/vt/vtgate/endtoend/aggr_test.go +++ b/go/vt/vtgate/endtoend/aggr_test.go @@ -21,37 +21,35 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/test/utils" + "vitess.io/vitess/go/mysql" ) func TestAggregateTypes(t *testing.T) { ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer conn.Close() exec(t, conn, "insert into aggr_test(id, val1, val2) values(1,'a',1), (2,'A',1), (3,'b',1), (4,'c',3), (5,'c',4)") exec(t, conn, "insert into aggr_test(id, val1, val2) values(6,'d',null), (7,'e',null), (8,'E',1)") qr := exec(t, conn, "select val1, count(distinct val2), count(*) from aggr_test group by val1") - if got, want := fmt.Sprintf("%v", qr.Rows), `[[VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("d") INT64(0) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)]]`; got != want { - t.Errorf("select:\n%v want\n%v", got, want) - } + want := `[[VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("d") INT64(0) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)]]` + utils.MustMatch(t, want, fmt.Sprintf("%v", qr.Rows)) qr = exec(t, conn, "select val1, sum(distinct val2), sum(val2) from aggr_test group by val1") - if got, want := fmt.Sprintf("%v", qr.Rows), `[[VARCHAR("a") DECIMAL(1) DECIMAL(2)] [VARCHAR("b") DECIMAL(1) DECIMAL(1)] [VARCHAR("c") DECIMAL(7) DECIMAL(7)] [VARCHAR("d") NULL NULL] [VARCHAR("e") DECIMAL(1) DECIMAL(1)]]`; got != want { - t.Errorf("select:\n%v want\n%v", got, want) - } + want = `[[VARCHAR("a") DECIMAL(1) DECIMAL(2)] [VARCHAR("b") DECIMAL(1) DECIMAL(1)] [VARCHAR("c") DECIMAL(7) DECIMAL(7)] [VARCHAR("d") NULL NULL] [VARCHAR("e") DECIMAL(1) DECIMAL(1)]]` + utils.MustMatch(t, want, fmt.Sprintf("%v", qr.Rows)) qr = exec(t, conn, "select val1, count(distinct val2) k, count(*) from aggr_test group by val1 order by k desc, val1") - if got, want := fmt.Sprintf("%v", qr.Rows), `[[VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)] [VARCHAR("d") INT64(0) INT64(1)]]`; got != want { - t.Errorf("select:\n%v want\n%v", got, want) - } + want = `[[VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)] [VARCHAR("d") INT64(0) INT64(1)]]` + utils.MustMatch(t, want, fmt.Sprintf("%v", qr.Rows)) qr = exec(t, conn, "select val1, count(distinct val2) k, count(*) from aggr_test group by val1 order by k desc, val1 limit 4") - if got, want := fmt.Sprintf("%v", qr.Rows), `[[VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)]]`; got != want { - t.Errorf("select:\n%v want\n%v", got, want) - } + want = `[[VARCHAR("c") INT64(2) INT64(2)] [VARCHAR("a") INT64(1) INT64(2)] [VARCHAR("b") INT64(1) INT64(1)] [VARCHAR("e") INT64(1) INT64(2)]]` + utils.MustMatch(t, want, fmt.Sprintf("%v", qr.Rows)) } diff --git a/go/vt/vtgate/endtoend/vstream_test.go b/go/vt/vtgate/endtoend/vstream_test.go index 246d17f88b5..8fed95f5d51 100644 --- a/go/vt/vtgate/endtoend/vstream_test.go +++ b/go/vt/vtgate/endtoend/vstream_test.go @@ -60,6 +60,7 @@ func initialize(ctx context.Context, t *testing.T) (*vtgateconn.VTGateConn, *mys } return gconn, conn, mconn, close } + func TestVStream(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -186,7 +187,7 @@ func TestVStreamCopyBasic(t *testing.T) { Lastpk: qr, }} var shardGtids []*binlogdatapb.ShardGtid - var vgtid = &binlogdatapb.VGtid{} + vgtid := &binlogdatapb.VGtid{} shardGtids = append(shardGtids, &binlogdatapb.ShardGtid{ Keyspace: "ks", Shard: "-80", @@ -264,20 +265,14 @@ func TestVStreamCopyUnspecifiedShardGtid(t *testing.T) { defer cancel() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) defer conn.Close() _, err = conn.ExecuteFetch("insert into t1_copy_all(id1,id2) values(1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8)", 1, false) - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) _, err = conn.ExecuteFetch("insert into t1_copy_all_ks2(id1,id2) values(10,10), (20,20)", 1, false) - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) filter := &binlogdatapb.Filter{ Rules: []*binlogdatapb.Rule{{ @@ -343,13 +338,11 @@ func TestVStreamCopyUnspecifiedShardGtid(t *testing.T) { gconn, conn, mconn, closeConnections := initialize(ctx, t) defer closeConnections() - var vgtid = &binlogdatapb.VGtid{} + vgtid := &binlogdatapb.VGtid{} vgtid.ShardGtids = []*binlogdatapb.ShardGtid{c.shardGtid} reader, err := gconn.VStream(ctx, topodatapb.TabletType_PRIMARY, vgtid, filter, flags) _, _ = conn, mconn - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) require.NotNil(t, reader) var evs []*binlogdatapb.VEvent var completedEvs []*binlogdatapb.VEvent @@ -426,7 +419,7 @@ func TestVStreamCopyResume(t *testing.T) { } var shardGtids []*binlogdatapb.ShardGtid - var vgtid = &binlogdatapb.VGtid{} + vgtid := &binlogdatapb.VGtid{} shardGtids = append(shardGtids, &binlogdatapb.ShardGtid{ Keyspace: "ks", Shard: "-80", @@ -526,7 +519,7 @@ func TestVStreamCurrent(t *testing.T) { defer closeConnections() var shardGtids []*binlogdatapb.ShardGtid - var vgtid = &binlogdatapb.VGtid{} + vgtid := &binlogdatapb.VGtid{} shardGtids = append(shardGtids, &binlogdatapb.ShardGtid{ Keyspace: "ks", Shard: "-80", @@ -580,7 +573,7 @@ func TestVStreamSharded(t *testing.T) { defer closeConnections() var shardGtids []*binlogdatapb.ShardGtid - var vgtid = &binlogdatapb.VGtid{} + vgtid := &binlogdatapb.VGtid{} shardGtids = append(shardGtids, &binlogdatapb.ShardGtid{ Keyspace: "ks", Shard: "-80", @@ -665,7 +658,6 @@ func TestVStreamSharded(t *testing.T) { t.Fatalf("remote error: %v\n", err) } } - } // TestVStreamCopyTransactions tests that we are properly wrapping @@ -822,9 +814,11 @@ type VEventSorter []*binlogdatapb.VEvent func (v VEventSorter) Len() int { return len(v) } + func (v VEventSorter) Swap(i, j int) { v[i], v[j] = v[j], v[i] } + func (v VEventSorter) Less(i, j int) bool { valsI := v[i].GetRowEvent().RowChanges[0].After if valsI == nil { diff --git a/go/vt/vtgate/engine/aggregations.go b/go/vt/vtgate/engine/aggregations.go index d3f2b7a1c82..769df332b73 100644 --- a/go/vt/vtgate/engine/aggregations.go +++ b/go/vt/vtgate/engine/aggregations.go @@ -42,7 +42,7 @@ type AggregateParams struct { WCol int Type evalengine.Type - Alias string `json:",omitempty"` + Alias string Func sqlparser.AggrFunc Original *sqlparser.AliasedExpr @@ -347,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 diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index df23f14f6f5..4c0d1009bd1 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -857,6 +857,40 @@ func (cached *Projection) CachedSize(alloc bool) int64 { } return size } + +//go:nocheckptr +func (cached *RecurseCTE) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field Seed vitess.io/vitess/go/vt/vtgate/engine.Primitive + if cc, ok := cached.Seed.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field Term vitess.io/vitess/go/vt/vtgate/engine.Primitive + if cc, ok := cached.Term.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field Vars map[string]int + if cached.Vars != nil { + size += int64(48) + hmap := reflect.ValueOf(cached.Vars) + numBuckets := int(math.Pow(2, float64((*(*uint8)(unsafe.Pointer(hmap.Pointer() + uintptr(9))))))) + numOldBuckets := (*(*uint16)(unsafe.Pointer(hmap.Pointer() + uintptr(10)))) + size += hack.RuntimeAllocSize(int64(numOldBuckets * 208)) + if len(cached.Vars) > 0 || numBuckets > 1 { + size += hack.RuntimeAllocSize(int64(numBuckets * 208)) + } + for k := range cached.Vars { + size += hack.RuntimeAllocSize(int64(len(k))) + } + } + return size +} func (cached *RenameFields) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -1293,6 +1327,20 @@ 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(32) + } + // field Keyspace string + size += hack.RuntimeAllocSize(int64(len(cached.Keyspace))) + // 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) @@ -1549,6 +1597,24 @@ func (cached *VitessMetadata) CachedSize(alloc bool) int64 { size += hack.RuntimeAllocSize(int64(len(cached.Value))) return size } +func (cached *percentBasedMirror) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field primitive vitess.io/vitess/go/vt/vtgate/engine.Primitive + if cc, ok := cached.primitive.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field target vitess.io/vitess/go/vt/vtgate/engine.Primitive + if cc, ok := cached.target.(cachedObject); ok { + size += cc.CachedSize(true) + } + return size +} //go:nocheckptr func (cached *shardRoute) CachedSize(alloc bool) int64 { diff --git a/go/vt/vtgate/engine/concatenate.go b/go/vt/vtgate/engine/concatenate.go index 13727124e78..eb93711eed2 100644 --- a/go/vt/vtgate/engine/concatenate.go +++ b/go/vt/vtgate/engine/concatenate.go @@ -102,12 +102,14 @@ func (c *Concatenate) TryExecute(ctx context.Context, vcursor VCursor, bindVars } var rows [][]sqltypes.Value - err = c.coerceAndVisitResults(res, fieldTypes, func(result *sqltypes.Result) error { + callback := func(result *sqltypes.Result) error { rows = append(rows, result.Rows...) return nil - }, evalengine.ParseSQLMode(vcursor.SQLMode())) - if err != nil { - return nil, err + } + for _, r := range res { + if err = c.coerceAndVisitResultsForOneSource([]*sqltypes.Result{r}, fields, fieldTypes, callback, evalengine.ParseSQLMode(vcursor.SQLMode())); err != nil { + return nil, err + } } return &sqltypes.Result{ @@ -245,12 +247,14 @@ func (c *Concatenate) parallelStreamExec(inCtx context.Context, vcursor VCursor, // Mutexes for dealing with concurrent access to shared state. var ( - muCallback sync.Mutex // Protects callback - muFields sync.Mutex // Protects field state - condFields = sync.NewCond(&muFields) // Condition var for field arrival - wg errgroup.Group // Wait group for all streaming goroutines - rest = make([]*sqltypes.Result, len(c.Sources)) // Collects first result from each source to derive fields - fieldTypes []evalengine.Type // Cached final field types + muCallback sync.Mutex // Protects callback + muFields sync.Mutex // Protects field state + condFields = sync.NewCond(&muFields) // Condition var for field arrival + wg errgroup.Group // Wait group for all streaming goroutines + rest = make([]*sqltypes.Result, len(c.Sources)) // Collects first result from each source to derive fields + fieldTypes []evalengine.Type // Cached final field types + resultFields []*querypb.Field // Final fields that need to be set for the first result. + needsCoercion = make([]bool, len(c.Sources)) // Tracks if coercion is needed for each individual source ) // Process each result chunk, considering type coercion. @@ -258,19 +262,8 @@ func (c *Concatenate) parallelStreamExec(inCtx context.Context, vcursor VCursor, muCallback.Lock() defer muCallback.Unlock() - // Check if type coercion needed for this source. - // We only need to check if fields are not in NoNeedToTypeCheck set. - needsCoercion := false - for idx, field := range rest[srcIdx].Fields { - _, skip := c.NoNeedToTypeCheck[idx] - if !skip && fieldTypes[idx].Type() != field.Type { - needsCoercion = true - break - } - } - // Apply type coercion if needed. - if needsCoercion { + if needsCoercion[srcIdx] { for _, row := range res.Rows { if err := c.coerceValuesTo(row, fieldTypes, sqlmode); err != nil { return err @@ -296,12 +289,29 @@ func (c *Concatenate) parallelStreamExec(inCtx context.Context, vcursor VCursor, if !slices.Contains(rest, nil) { // We have received fields from all sources. We can now calculate the output types var err error - resultChunk.Fields, fieldTypes, err = c.getFieldTypes(vcursor, rest) + resultFields, fieldTypes, err = c.getFieldTypes(vcursor, rest) if err != nil { muFields.Unlock() return err } + // Check if we need coercion for each source. + for srcIdx, result := range rest { + srcNeedsCoercion := false + for idx, field := range result.Fields { + _, skip := c.NoNeedToTypeCheck[idx] + // We only need to check if fields are not in NoNeedToTypeCheck set. + if !skip && fieldTypes[idx].Type() != field.Type { + srcNeedsCoercion = true + break + } + } + needsCoercion[srcIdx] = srcNeedsCoercion + } + + // We only need to send the fields in the first result. + // We set this field after the coercion check to avoid calculating incorrect needs coercion value. + resultChunk.Fields = resultFields muFields.Unlock() defer condFields.Broadcast() return callback(resultChunk, currIndex) @@ -310,8 +320,11 @@ func (c *Concatenate) parallelStreamExec(inCtx context.Context, vcursor VCursor, // Wait for fields from all sources. for slices.Contains(rest, nil) { + // This wait call lets go of the muFields lock and acquires it again later after waiting. condFields.Wait() } + // We only need to send fields in the first result. + resultChunk.Fields = nil muFields.Unlock() // Context check to avoid extra work. @@ -368,12 +381,12 @@ func (c *Concatenate) sequentialStreamExec(ctx context.Context, vcursor VCursor, firsts[i] = result[0] } - _, fieldTypes, err := c.getFieldTypes(vcursor, firsts) + fields, fieldTypes, err := c.getFieldTypes(vcursor, firsts) if err != nil { return err } for _, res := range results { - if err = c.coerceAndVisitResults(res, fieldTypes, callback, sqlmode); err != nil { + if err = c.coerceAndVisitResultsForOneSource(res, fields, fieldTypes, callback, sqlmode); err != nil { return err } } @@ -381,25 +394,33 @@ func (c *Concatenate) sequentialStreamExec(ctx context.Context, vcursor VCursor, return nil } -func (c *Concatenate) coerceAndVisitResults( +func (c *Concatenate) coerceAndVisitResultsForOneSource( res []*sqltypes.Result, + fields []*querypb.Field, fieldTypes []evalengine.Type, callback func(*sqltypes.Result) error, sqlmode evalengine.SQLMode, ) error { + if len(res) == 0 { + return nil + } + needsCoercion := false + for idx, field := range res[0].Fields { + if fieldTypes[idx].Type() != field.Type { + needsCoercion = true + break + } + } + if res[0].Fields != nil { + res[0].Fields = fields + } + for _, r := range res { if len(r.Rows) > 0 && len(fieldTypes) != len(r.Rows[0]) { return errWrongNumberOfColumnsInSelect } - needsCoercion := false - for idx, field := range r.Fields { - if fieldTypes[idx].Type() != field.Type { - needsCoercion = true - break - } - } if needsCoercion { for _, row := range r.Rows { err := c.coerceValuesTo(row, fieldTypes, sqlmode) diff --git a/go/vt/vtgate/engine/concatenate_test.go b/go/vt/vtgate/engine/concatenate_test.go index dd2b1300e9b..39b9ed961b3 100644 --- a/go/vt/vtgate/engine/concatenate_test.go +++ b/go/vt/vtgate/engine/concatenate_test.go @@ -124,27 +124,24 @@ func TestConcatenate_NoErrors(t *testing.T) { if !tx { txStr = "NotInTx" } - t.Run(fmt.Sprintf("%s-%s-Exec", txStr, tc.testName), func(t *testing.T) { - qr, err := concatenate.TryExecute(context.Background(), vcursor, nil, true) + checkResult := func(t *testing.T, qr *sqltypes.Result, err error) { if tc.expectedError == "" { require.NoError(t, err) utils.MustMatch(t, tc.expectedResult.Fields, qr.Fields, "fields") - utils.MustMatch(t, tc.expectedResult.Rows, qr.Rows) + require.NoError(t, sqltypes.RowsEquals(tc.expectedResult.Rows, qr.Rows)) } else { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError) } + } + t.Run(fmt.Sprintf("%s-%s-Exec", txStr, tc.testName), func(t *testing.T) { + qr, err := concatenate.TryExecute(context.Background(), vcursor, nil, true) + checkResult(t, qr, err) }) t.Run(fmt.Sprintf("%s-%s-StreamExec", txStr, tc.testName), func(t *testing.T) { qr, err := wrapStreamExecute(concatenate, vcursor, nil, true) - if tc.expectedError == "" { - require.NoError(t, err) - require.NoError(t, sqltypes.RowsEquals(tc.expectedResult.Rows, qr.Rows)) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expectedError) - } + checkResult(t, qr, err) }) } } diff --git a/go/vt/vtgate/engine/fake_primitive_test.go b/go/vt/vtgate/engine/fake_primitive_test.go index e992c2a4623..b878c1931c0 100644 --- a/go/vt/vtgate/engine/fake_primitive_test.go +++ b/go/vt/vtgate/engine/fake_primitive_test.go @@ -24,6 +24,7 @@ import ( "testing" "golang.org/x/sync/errgroup" + "google.golang.org/protobuf/proto" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" @@ -80,7 +81,7 @@ func (f *fakePrimitive) TryExecute(ctx context.Context, vcursor VCursor, bindVar if r == nil { return nil, f.sendErr } - return r, nil + return r.Copy(), nil } func (f *fakePrimitive) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { @@ -111,7 +112,7 @@ func (f *fakePrimitive) syncCall(wantfields bool, callback func(*sqltypes.Result } result := &sqltypes.Result{} for i := 0; i < len(r.Rows); i++ { - result.Rows = append(result.Rows, r.Rows[i]) + result.Rows = append(result.Rows, sqltypes.CopyRow(r.Rows[i])) // Send only two rows at a time. if i%2 == 1 { if err := callback(result); err != nil { @@ -188,6 +189,15 @@ func wrapStreamExecute(prim Primitive, vcursor VCursor, bindVars map[string]*que if result == nil { result = r } else { + if r.Fields != nil { + for i, field := range r.Fields { + aField := field + bField := result.Fields[i] + if !proto.Equal(aField, bField) { + return fmt.Errorf("fields differ: %s <> %s", aField.String(), bField.String()) + } + } + } result.Rows = append(result.Rows, r.Rows...) } return nil diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index 1ba0abfa2ef..498c26db877 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -46,11 +46,15 @@ import ( vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" ) -var testMaxMemoryRows = 100 -var testIgnoreMaxMemoryRows = false +var ( + testMaxMemoryRows = 100 + testIgnoreMaxMemoryRows = false +) -var _ VCursor = (*noopVCursor)(nil) -var _ SessionActions = (*noopVCursor)(nil) +var ( + _ VCursor = (*noopVCursor)(nil) + _ SessionActions = (*noopVCursor)(nil) +) // noopVCursor is used to build other vcursors. type noopVCursor struct { @@ -112,6 +116,18 @@ func (t *noopVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { panic("implement me") } +func (t *noopVCursor) CloneForMirroring(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) UnresolvedTransactions(ctx context.Context, keyspace string) ([]*querypb.TransactionMetadata, error) { + panic("implement me") +} + func (t *noopVCursor) SetExec(ctx context.Context, name string, value string) error { panic("implement me") } @@ -338,7 +354,7 @@ func (t *noopVCursor) ExceedsMaxMemoryRows(numRows int) bool { } func (t *noopVCursor) GetKeyspace() string { - return "" + return "test_ks" } func (t *noopVCursor) RecordWarning(warning *querypb.QueryWarning) { @@ -380,8 +396,10 @@ func (t *noopVCursor) GetDBDDLPluginName() string { panic("unimplemented") } -var _ VCursor = (*loggingVCursor)(nil) -var _ SessionActions = (*loggingVCursor)(nil) +var ( + _ VCursor = (*loggingVCursor)(nil) + _ SessionActions = (*loggingVCursor)(nil) +) // loggingVCursor logs requests and allows you to verify // that the correct requests were made. @@ -397,7 +415,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 @@ -421,6 +440,10 @@ type loggingVCursor struct { shardSession []*srvtopo.ResolvedShard parser *sqlparser.Parser + + handleMirrorClonesFn func(context.Context) VCursor + onExecuteMultiShardFn func(context.Context, Primitive, []*srvtopo.ResolvedShard, []*querypb.BoundQuery, bool, bool) + onStreamExecuteMultiFn func(context.Context, Primitive, string, []*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, bool, bool, func(*sqltypes.Result) error) } func (f *loggingVCursor) HasCreatedTempTable() { @@ -536,6 +559,13 @@ func (f *loggingVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { return f } +func (f *loggingVCursor) CloneForMirroring(ctx context.Context) VCursor { + if f.handleMirrorClonesFn != nil { + return f.handleMirrorClonesFn(ctx) + } + panic("no mirror clones available") +} + func (f *loggingVCursor) Execute(ctx context.Context, method string, query string, bindvars map[string]*querypb.BindVariable, rollbackOnError bool, co vtgatepb.CommitOrder) (*sqltypes.Result, error) { name := "Unknown" switch co { @@ -553,7 +583,12 @@ func (f *loggingVCursor) Execute(ctx context.Context, method string, query strin } func (f *loggingVCursor) ExecuteMultiShard(ctx context.Context, primitive Primitive, rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, rollbackOnError, canAutocommit bool) (*sqltypes.Result, []error) { + f.mu.Lock() + defer f.mu.Unlock() f.log = append(f.log, fmt.Sprintf("ExecuteMultiShard %v%v %v", printResolvedShardQueries(rss, queries), rollbackOnError, canAutocommit)) + if f.onExecuteMultiShardFn != nil { + f.onExecuteMultiShardFn(ctx, primitive, rss, queries, rollbackOnError, canAutocommit) + } res, err := f.nextResult() if err != nil { return nil, []error{err} @@ -574,6 +609,9 @@ func (f *loggingVCursor) ExecuteStandalone(ctx context.Context, primitive Primit func (f *loggingVCursor) StreamExecuteMulti(ctx context.Context, primitive Primitive, query string, rss []*srvtopo.ResolvedShard, bindVars []map[string]*querypb.BindVariable, rollbackOnError bool, autocommit bool, callback func(reply *sqltypes.Result) error) []error { f.mu.Lock() f.log = append(f.log, fmt.Sprintf("StreamExecuteMulti %s %s", query, printResolvedShardsBindVars(rss, bindVars))) + if f.onStreamExecuteMultiFn != nil { + f.onStreamExecuteMultiFn(ctx, primitive, query, rss, bindVars, rollbackOnError, autocommit, callback) + } r, err := f.nextResult() f.mu.Unlock() if err != nil { @@ -725,6 +763,8 @@ func (f *loggingVCursor) ResolveDestinationsMultiCol(ctx context.Context, keyspa func (f *loggingVCursor) ExpectLog(t *testing.T, want []string) { t.Helper() + f.mu.Lock() + defer f.mu.Unlock() if len(f.log) == 0 && len(want) == 0 { return } @@ -742,6 +782,8 @@ func (f *loggingVCursor) ExpectWarnings(t *testing.T, want []*querypb.QueryWarni } func (f *loggingVCursor) Rewind() { + f.mu.Lock() + defer f.mu.Unlock() f.curShardForKsid = 0 f.curResult = 0 f.log = nil @@ -814,6 +856,24 @@ 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 + } + var out *querypb.TransactionMetadata + if len(f.transactionStatusOutput) > 0 { + out = f.transactionStatusOutput[0] + } + return out, nil +} + +func (f *loggingVCursor) UnresolvedTransactions(_ 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 { @@ -827,6 +887,7 @@ func (t *noopVCursor) DisableLogging() {} func (t *noopVCursor) GetVExplainLogs() []ExecuteEntry { return nil } + func (t *noopVCursor) GetLogs() ([]ExecuteEntry, error) { return nil, 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/mirror.go b/go/vt/vtgate/engine/mirror.go new file mode 100644 index 00000000000..bfab4cee91d --- /dev/null +++ b/go/vt/vtgate/engine/mirror.go @@ -0,0 +1,152 @@ +/* +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" + "math/rand/v2" + "time" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +type ( + // percentBasedMirror represents the instructions to execute an + // authoritative primitive and, based on whether a die-roll exceeds a + // percentage, to also execute a target Primitive. + percentBasedMirror struct { + percent float32 + primitive Primitive + target Primitive + } +) + +const ( + // maxMirrorTargetLag limits how long a mirror target may continue + // executing after the main primitive has finished. + maxMirrorTargetLag = 100 * time.Millisecond +) + +var _ Primitive = (*percentBasedMirror)(nil) + +// NewPercentBasedMirror creates a Mirror. +func NewPercentBasedMirror(percentage float32, primitive Primitive, target Primitive) Primitive { + return &percentBasedMirror{percentage, primitive, target} +} + +func (m *percentBasedMirror) RouteType() string { + return "Mirror" +} + +func (m *percentBasedMirror) GetKeyspaceName() string { + return m.primitive.GetKeyspaceName() +} + +func (m *percentBasedMirror) GetTableName() string { + return m.primitive.GetTableName() +} + +func (m *percentBasedMirror) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { + return m.primitive.GetFields(ctx, vcursor, bindVars) +} + +func (m *percentBasedMirror) NeedsTransaction() bool { + return m.primitive.NeedsTransaction() +} + +func (m *percentBasedMirror) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { + if !m.percentAtLeastDieRoll() { + return vcursor.ExecutePrimitive(ctx, m.primitive, bindVars, wantfields) + } + + mirrorCh := make(chan any) + mirrorCtx, mirrorCtxCancel := context.WithTimeout(ctx, maxMirrorTargetLag) + defer mirrorCtxCancel() + + go func() { + defer close(mirrorCh) + mirrorVCursor := vcursor.CloneForMirroring(mirrorCtx) + // TODO(maxeng) handle error. + _, _ = mirrorVCursor.ExecutePrimitive(mirrorCtx, m.target, bindVars, wantfields) + }() + + r, err := vcursor.ExecutePrimitive(ctx, m.primitive, bindVars, wantfields) + + select { + case <-mirrorCh: + // Mirroring completed within the allowed time. + case <-mirrorCtx.Done(): + // Mirroring took too long and was canceled. + } + + return r, err +} + +func (m *percentBasedMirror) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { + if !m.percentAtLeastDieRoll() { + return vcursor.StreamExecutePrimitive(ctx, m.primitive, bindVars, wantfields, callback) + } + + mirrorCh := make(chan any) + mirrorCtx, mirrorCtxCancel := context.WithTimeout(ctx, maxMirrorTargetLag) + defer mirrorCtxCancel() + + go func() { + defer close(mirrorCh) + mirrorVCursor := vcursor.CloneForMirroring(mirrorCtx) + // TODO(maxeng) handle error. + _ = mirrorVCursor.StreamExecutePrimitive( + mirrorCtx, m.target, bindVars, wantfields, func(_ *sqltypes.Result, + ) error { + return nil + }) + }() + + err := vcursor.StreamExecutePrimitive(ctx, m.primitive, bindVars, wantfields, callback) + + select { + case <-mirrorCh: + // Mirroring completed within the allowed time. + case <-mirrorCtx.Done(): + // Mirroring took too long and was canceled. + } + + return err +} + +// Inputs is a slice containing the inputs to this Primitive. +// The returned map has additional information about the inputs, that is used in the description. +func (m *percentBasedMirror) Inputs() ([]Primitive, []map[string]any) { + return []Primitive{m.primitive, m.target}, nil +} + +// description is the description, sans the inputs, of this Primitive. +// to get the plan description with all children, use PrimitiveToPlanDescription() +func (m *percentBasedMirror) description() PrimitiveDescription { + return PrimitiveDescription{ + OperatorType: "Mirror", + Variant: "PercentBased", + Other: map[string]any{ + "Percent": m.percent, + }, + } +} + +func (m *percentBasedMirror) percentAtLeastDieRoll() bool { + return m.percent >= (rand.Float32() * 100.0) +} diff --git a/go/vt/vtgate/engine/mirror_test.go b/go/vt/vtgate/engine/mirror_test.go new file mode 100644 index 00000000000..b9e442df32d --- /dev/null +++ b/go/vt/vtgate/engine/mirror_test.go @@ -0,0 +1,376 @@ +/* +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" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/srvtopo" + "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/vt/vtgate/vindexes" +) + +func TestMirror(t *testing.T) { + vindex, _ := vindexes.CreateVindex("xxhash", "xxhash_vdx", nil) + + primitive := NewRoute( + Unsharded, + &vindexes.Keyspace{ + Name: "ks1", + }, + "select f.bar from foo f where f.id = 1", + "select 1 from foo f where f.id = 1 and 1 != 1", + ) + + mirrorPrimitive1 := NewRoute( + EqualUnique, + &vindexes.Keyspace{ + Name: "ks2", + Sharded: true, + }, + "select f.bar from foo f where f.id = 1", + "select 1 from foo f where f.id = 1 and 1 != 1", + ) + mirrorPrimitive1.Vindex = vindex.(vindexes.SingleColumn) + mirrorPrimitive1.Values = []evalengine.Expr{ + evalengine.NewLiteralInt(1), + } + + mirror := NewPercentBasedMirror(100, primitive, mirrorPrimitive1) + + mirrorVC := &loggingVCursor{ + shards: []string{"-20", "20-"}, + ksShardMap: map[string][]string{ + "ks2": {"-20", "20-"}, + }, + results: []*sqltypes.Result{ + sqltypes.MakeTestResult( + sqltypes.MakeTestFields( + "bar", + "varchar", + ), + "hello", + ), + }, + } + + vc := &loggingVCursor{ + shards: []string{"0"}, + ksShardMap: map[string][]string{ + "ks1": {"0"}, + }, + results: []*sqltypes.Result{ + sqltypes.MakeTestResult( + sqltypes.MakeTestFields( + "bar", + "varchar", + ), + "hello", + ), + }, + handleMirrorClonesFn: func(ctx context.Context) VCursor { + return mirrorVC + }, + } + + t.Run("TryExecute success", func(t *testing.T) { + defer func() { + vc.Rewind() + mirrorVC.Rewind() + }() + + want := vc.results[0] + res, err := mirror.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, true) + require.Equal(t, want, res) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "ExecuteMultiShard ks1.0: select f.bar from foo f where f.id = 1 {} false false", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "ExecuteMultiShard ks2.-20: select f.bar from foo f where f.id = 1 {} false false", + }) + }) + + t.Run("TryExecute return primitive error", func(t *testing.T) { + results := vc.results + + defer func() { + vc.Rewind() + vc.results = results + vc.resultErr = nil + mirrorVC.Rewind() + }() + + vc.results = nil + vc.resultErr = fmt.Errorf("return me") + + ctx := context.Background() + res, err := mirror.TryExecute(ctx, vc, map[string]*querypb.BindVariable{}, true) + require.Nil(t, res) + require.Error(t, err) + require.Equal(t, vc.resultErr, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "ExecuteMultiShard ks1.0: select f.bar from foo f where f.id = 1 {} false false", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "ExecuteMultiShard ks2.-20: select f.bar from foo f where f.id = 1 {} false false", + }) + }) + + t.Run("TryExecute ignore mirror target error", func(t *testing.T) { + results := mirrorVC.results + + defer func() { + vc.Rewind() + mirrorVC.Rewind() + mirrorVC.results = results + mirrorVC.resultErr = nil + }() + + mirrorVC.results = nil + mirrorVC.resultErr = fmt.Errorf("ignore me") + + want := vc.results[0] + res, err := mirror.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, true) + require.Equal(t, res, want) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "ExecuteMultiShard ks1.0: select f.bar from foo f where f.id = 1 {} false false", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "ExecuteMultiShard ks2.-20: select f.bar from foo f where f.id = 1 {} false false", + }) + }) + + t.Run("TryExecute slow mirror target", func(t *testing.T) { + defer func() { + vc.Rewind() + vc.onExecuteMultiShardFn = nil + mirrorVC.Rewind() + mirrorVC.onExecuteMultiShardFn = nil + }() + + primitiveLatency := maxMirrorTargetLag * 2 + vc.onExecuteMultiShardFn = func(ctx context.Context, _ Primitive, _ []*srvtopo.ResolvedShard, _ []*querypb.BoundQuery, _ bool, _ bool) { + time.Sleep(primitiveLatency) + select { + case <-ctx.Done(): + require.Fail(t, "primitive context done") + default: + } + } + + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(1) + mirrorVC.onExecuteMultiShardFn = func(ctx context.Context, _ Primitive, _ []*srvtopo.ResolvedShard, _ []*querypb.BoundQuery, _ bool, _ bool) { + defer wg.Done() + time.Sleep(primitiveLatency + (2 * maxMirrorTargetLag)) + select { + case <-ctx.Done(): + default: + require.Fail(t, "mirror target context not done") + } + } + + want := vc.results[0] + res, err := mirror.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, true) + require.Equal(t, res, want) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "ExecuteMultiShard ks1.0: select f.bar from foo f where f.id = 1 {} false false", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "ExecuteMultiShard ks2.-20: select f.bar from foo f where f.id = 1 {} false false", + }) + }) + + t.Run("TryStreamExecute success", func(t *testing.T) { + defer func() { + vc.Rewind() + mirrorVC.Rewind() + }() + + want := vc.results[0] + err := mirror.TryStreamExecute( + context.Background(), + vc, + map[string]*querypb.BindVariable{}, + true, + func(result *sqltypes.Result) error { + require.Equal(t, want, result) + return nil + }, + ) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks1.0: {} ", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks2.-20: {} ", + }) + }) + + t.Run("TryStreamExecute return primitive error", func(t *testing.T) { + results := vc.results + + defer func() { + vc.Rewind() + vc.results = results + vc.resultErr = nil + mirrorVC.Rewind() + }() + + vc.results = nil + vc.resultErr = fmt.Errorf("return me") + + err := mirror.TryStreamExecute( + context.Background(), + vc, + map[string]*querypb.BindVariable{}, + true, + func(result *sqltypes.Result) error { + require.Nil(t, result) + return nil + }, + ) + require.Error(t, err) + require.Equal(t, vc.resultErr, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks1.0: {} ", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks2.-20: {} ", + }) + }) + + t.Run("TryStreamExecute ignore mirror target error", func(t *testing.T) { + results := mirrorVC.results + + defer func() { + vc.Rewind() + mirrorVC.Rewind() + mirrorVC.results = results + mirrorVC.resultErr = nil + }() + + mirrorVC.results = nil + mirrorVC.resultErr = fmt.Errorf("ignore me") + + want := vc.results[0] + err := mirror.TryStreamExecute( + context.Background(), + vc, + map[string]*querypb.BindVariable{}, + true, + func(result *sqltypes.Result) error { + require.Equal(t, want, result) + return nil + }, + ) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks1.0: {} ", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks2.-20: {} ", + }) + }) + + t.Run("TryStreamExecute slow mirror target", func(t *testing.T) { + defer func() { + vc.Rewind() + vc.onStreamExecuteMultiFn = nil + mirrorVC.Rewind() + mirrorVC.onStreamExecuteMultiFn = nil + }() + + primitiveLatency := maxMirrorTargetLag * 2 + vc.onStreamExecuteMultiFn = func(ctx context.Context, _ Primitive, _ string, _ []*srvtopo.ResolvedShard, _ []map[string]*querypb.BindVariable, _ bool, _ bool, _ func(*sqltypes.Result) error) { + time.Sleep(primitiveLatency) + select { + case <-ctx.Done(): + require.Fail(t, "primitive context done") + default: + } + } + + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(1) + mirrorVC.onStreamExecuteMultiFn = func(ctx context.Context, _ Primitive, _ string, _ []*srvtopo.ResolvedShard, _ []map[string]*querypb.BindVariable, _ bool, _ bool, _ func(*sqltypes.Result) error) { + defer wg.Done() + time.Sleep(primitiveLatency + (2 * maxMirrorTargetLag)) + select { + case <-ctx.Done(): + default: + require.Fail(t, "mirror target context not done") + } + } + + want := vc.results[0] + err := mirror.TryStreamExecute( + context.Background(), + vc, + map[string]*querypb.BindVariable{}, + true, + func(result *sqltypes.Result) error { + require.Equal(t, want, result) + return nil + }, + ) + require.NoError(t, err) + + vc.ExpectLog(t, []string{ + "ResolveDestinations ks1 [] Destinations:DestinationAllShards()", + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks1.0: {} ", + }) + mirrorVC.ExpectLog(t, []string{ + `ResolveDestinations ks2 [type:INT64 value:"1"] Destinations:DestinationKeyspaceID(d46405367612b4b7)`, + "StreamExecuteMulti select f.bar from foo f where f.id = 1 ks2.-20: {} ", + }) + }) +} 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/primitive.go b/go/vt/vtgate/engine/primitive.go index 1c0e7de7a19..30894b99ab8 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -131,6 +131,15 @@ type ( // CloneForReplicaWarming clones the VCursor for re-use in warming queries to replicas CloneForReplicaWarming(ctx context.Context) VCursor + + // CloneForMirroring clones the VCursor for re-use in mirroring queries to other keyspaces + CloneForMirroring(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) + + // UnresolvedTransactions reads the state of all the unresolved atomic transactions in the given keyspace. + UnresolvedTransactions(ctx context.Context, keyspace string) ([]*querypb.TransactionMetadata, error) } // SessionActions gives primitives ability to interact with the session state diff --git a/go/vt/vtgate/engine/recurse_cte.go b/go/vt/vtgate/engine/recurse_cte.go new file mode 100644 index 00000000000..f523883d280 --- /dev/null +++ b/go/vt/vtgate/engine/recurse_cte.go @@ -0,0 +1,155 @@ +/* +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" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/vterrors" +) + +// RecurseCTE is used to represent recursive CTEs +// Seed is used to represent the non-recursive part that initializes the result set. +// It's result are then used to start the recursion on the Term side +// The values being sent to the Term side are stored in the Vars map - +// the key is the bindvar name and the value is the index of the column in the recursive result +type RecurseCTE struct { + Seed, Term Primitive + + Vars map[string]int +} + +var _ Primitive = (*RecurseCTE)(nil) + +func (r *RecurseCTE) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { + res, err := vcursor.ExecutePrimitive(ctx, r.Seed, bindVars, wantfields) + if err != nil { + return nil, err + } + + // recurseRows contains the rows used in the next recursion + recurseRows := res.Rows + joinVars := make(map[string]*querypb.BindVariable) + loops := 0 + for len(recurseRows) > 0 { + // copy over the results from the previous recursion + theseRows := recurseRows + recurseRows = nil + for _, row := range theseRows { + for k, col := range r.Vars { + joinVars[k] = sqltypes.ValueBindVariable(row[col]) + } + // check if the context is done - we might be in a long running recursion + if err := ctx.Err(); err != nil { + return nil, err + } + rresult, err := vcursor.ExecutePrimitive(ctx, r.Term, combineVars(bindVars, joinVars), false) + if err != nil { + return nil, err + } + recurseRows = append(recurseRows, rresult.Rows...) + res.Rows = append(res.Rows, rresult.Rows...) + loops++ + if loops > 1000 { // TODO: This should be controlled with a system variable setting + return nil, vterrors.VT09030("") + } + } + } + return res, nil +} + +func (r *RecurseCTE) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { + if vcursor.Session().InTransaction() { + res, err := r.TryExecute(ctx, vcursor, bindVars, wantfields) + if err != nil { + return err + } + return callback(res) + } + return vcursor.StreamExecutePrimitive(ctx, r.Seed, bindVars, wantfields, func(result *sqltypes.Result) error { + err := callback(result) + if err != nil { + return err + } + return r.recurse(ctx, vcursor, bindVars, result, callback) + }) +} + +func (r *RecurseCTE) recurse(ctx context.Context, vcursor VCursor, bindvars map[string]*querypb.BindVariable, result *sqltypes.Result, callback func(*sqltypes.Result) error) error { + if len(result.Rows) == 0 { + return nil + } + joinVars := make(map[string]*querypb.BindVariable) + for _, row := range result.Rows { + for k, col := range r.Vars { + joinVars[k] = sqltypes.ValueBindVariable(row[col]) + } + + err := vcursor.StreamExecutePrimitive(ctx, r.Term, combineVars(bindvars, joinVars), false, func(result *sqltypes.Result) error { + err := callback(result) + if err != nil { + return err + } + return r.recurse(ctx, vcursor, bindvars, result, callback) + }) + if err != nil { + return err + } + } + return nil +} + +func (r *RecurseCTE) RouteType() string { + return "RecurseCTE" +} + +func (r *RecurseCTE) GetKeyspaceName() string { + if r.Seed.GetKeyspaceName() == r.Term.GetKeyspaceName() { + return r.Seed.GetKeyspaceName() + } + return r.Seed.GetKeyspaceName() + "_" + r.Term.GetKeyspaceName() +} + +func (r *RecurseCTE) GetTableName() string { + return r.Seed.GetTableName() +} + +func (r *RecurseCTE) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { + return r.Seed.GetFields(ctx, vcursor, bindVars) +} + +func (r *RecurseCTE) NeedsTransaction() bool { + return r.Seed.NeedsTransaction() || r.Term.NeedsTransaction() +} + +func (r *RecurseCTE) Inputs() ([]Primitive, []map[string]any) { + return []Primitive{r.Seed, r.Term}, nil +} + +func (r *RecurseCTE) description() PrimitiveDescription { + other := map[string]interface{}{ + "JoinVars": orderedStringIntMap(r.Vars), + } + + return PrimitiveDescription{ + OperatorType: "RecurseCTE", + Other: other, + Inputs: nil, + } +} diff --git a/go/vt/vtgate/engine/recurse_cte_test.go b/go/vt/vtgate/engine/recurse_cte_test.go new file mode 100644 index 00000000000..d6826284d21 --- /dev/null +++ b/go/vt/vtgate/engine/recurse_cte_test.go @@ -0,0 +1,129 @@ +/* +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" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +func TestRecurseDualQuery(t *testing.T) { + // Test that the RecurseCTE primitive works as expected. + // The test is testing something like this: + // WITH RECURSIVE cte AS (SELECT 1 as col1 UNION SELECT col1+1 FROM cte WHERE col1 < 5) SELECT * FROM cte; + leftPrim := &fakePrimitive{ + results: []*sqltypes.Result{ + sqltypes.MakeTestResult( + sqltypes.MakeTestFields( + "col1", + "int64", + ), + "1", + ), + }, + } + rightFields := sqltypes.MakeTestFields( + "col4", + "int64", + ) + + rightPrim := &fakePrimitive{ + results: []*sqltypes.Result{ + sqltypes.MakeTestResult( + rightFields, + "2", + ), + sqltypes.MakeTestResult( + rightFields, + "3", + ), + sqltypes.MakeTestResult( + rightFields, + "4", + ), sqltypes.MakeTestResult( + rightFields, + ), + }, + } + bv := map[string]*querypb.BindVariable{} + + cte := &RecurseCTE{ + Seed: leftPrim, + Term: rightPrim, + Vars: map[string]int{"col1": 0}, + } + + r, err := cte.TryExecute(context.Background(), &noopVCursor{}, bv, true) + require.NoError(t, err) + + rightPrim.ExpectLog(t, []string{ + `Execute col1: type:INT64 value:"1" false`, + `Execute col1: type:INT64 value:"2" false`, + `Execute col1: type:INT64 value:"3" false`, + `Execute col1: type:INT64 value:"4" false`, + }) + + wantRes := sqltypes.MakeTestResult( + sqltypes.MakeTestFields( + "col1", + "int64", + ), + "1", + "2", + "3", + "4", + ) + expectResult(t, r, wantRes) + + // testing the streaming mode. + + leftPrim.rewind() + rightPrim.rewind() + + r, err = wrapStreamExecute(cte, &noopVCursor{}, bv, true) + require.NoError(t, err) + + rightPrim.ExpectLog(t, []string{ + `StreamExecute col1: type:INT64 value:"1" false`, + `StreamExecute col1: type:INT64 value:"2" false`, + `StreamExecute col1: type:INT64 value:"3" false`, + `StreamExecute col1: type:INT64 value:"4" false`, + }) + expectResult(t, r, wantRes) + + // testing the streaming mode with transaction + + leftPrim.rewind() + rightPrim.rewind() + + r, err = wrapStreamExecute(cte, &noopVCursor{inTx: true}, bv, true) + require.NoError(t, err) + + rightPrim.ExpectLog(t, []string{ + `Execute col1: type:INT64 value:"1" false`, + `Execute col1: type:INT64 value:"2" false`, + `Execute col1: type:INT64 value:"3" false`, + `Execute col1: type:INT64 value:"4" false`, + }) + expectResult(t, r, wantRes) + +} 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/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..9914031009f --- /dev/null +++ b/go/vt/vtgate/engine/transaction_status.go @@ -0,0 +1,134 @@ +/* +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 + + Keyspace string + 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) { + var transactionStatuses []*querypb.TransactionMetadata + var err error + if t.TransactionID != "" { + var transactionState *querypb.TransactionMetadata + transactionState, err = vcursor.ReadTransaction(ctx, t.TransactionID) + transactionStatuses = append(transactionStatuses, transactionState) + } else { + transactionStatuses, err = vcursor.UnresolvedTransactions(ctx, t.Keyspace) + } + if err != nil { + return nil, err + } + + res := &sqltypes.Result{} + if wantfields { + res.Fields = t.getFields() + } + + for _, transactionState := range transactionStatuses { + if transactionState != nil && transactionState.Dtid != "" { + 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 { + otherMap := map[string]any{} + if t.TransactionID == "" { + otherMap["Keyspace"] = t.Keyspace + } else { + otherMap["TransactionID"] = t.TransactionID + } + return PrimitiveDescription{ + OperatorType: "TransactionStatus", + Other: otherMap, + } +} 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..739a1d32cce --- /dev/null +++ b/go/vt/vtgate/engine/transaction_status_test.go @@ -0,0 +1,146 @@ +/* +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 + primitive *TransactionStatus + }{ + { + name: "Empty Transaction Status", + transactionStatusOutput: nil, + expectedRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|state|record_time|participants", "varchar|varchar|datetime|varchar")), + primitive: &TransactionStatus{}, + }, { + name: "Valid Transaction Status for a transaction ID", + primitive: &TransactionStatus{ + TransactionID: "ks:-80:v24s7843sf78934l3", + }, + 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", + primitive: &TransactionStatus{ + TransactionID: "ks:-80:v24s7843sf78934l3", + }, + resultErr: fmt.Errorf("failed reading transaction state"), + }, { + name: "Valid Transaction Statuses for a keyspace", + primitive: &TransactionStatus{ + Keyspace: "ks", + }, + 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, + }, + }, + }, + { + Dtid: "ks:-80:v34afdfdsfdfd", + State: querypb.TransactionState_PREPARE, + TimeCreated: 1259894000000000000, + Participants: []*querypb.Target{ + { + Keyspace: "ks", + Shard: "-80", + TabletType: topodatapb.TabletType_PRIMARY, + }, { + Keyspace: "ks", + Shard: "80-", + 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-", + "ks:-80:v34afdfdsfdfd|PREPARE|2009-12-04 02:33:20 +0000 UTC|ks:-80,ks:80-", + ), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := test.primitive.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/engine/vindex_func.go b/go/vt/vtgate/engine/vindex_func.go index ecd83baeaad..13507631716 100644 --- a/go/vt/vtgate/engine/vindex_func.go +++ b/go/vt/vtgate/engine/vindex_func.go @@ -153,6 +153,9 @@ func (vf *VindexFunc) mapVindex(ctx context.Context, vcursor VCursor, bindVars m case key.DestinationKeyspaceID: if len(d) > 0 { if vcursor != nil { + if vcursor.GetKeyspace() == "" { + return nil, vterrors.VT09005() + } resolvedShards, _, err := vcursor.ResolveDestinations(ctx, vcursor.GetKeyspace(), nil, []key.Destination{d}) if err != nil { return nil, err 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..c1ed1f9475c 100644 --- a/go/vt/vtgate/evalengine/cached_size.go +++ b/go/vt/vtgate/evalengine/cached_size.go @@ -1397,6 +1397,30 @@ func (cached *builtinPad) CachedSize(alloc bool) int64 { size += cached.CallExpr.CachedSize(false) return size } +func (cached *builtinPeriodAdd) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field CallExpr vitess.io/vitess/go/vt/vtgate/evalengine.CallExpr + size += cached.CallExpr.CachedSize(false) + return size +} +func (cached *builtinPeriodDiff) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field CallExpr vitess.io/vitess/go/vt/vtgate/evalengine.CallExpr + size += cached.CallExpr.CachedSize(false) + return size +} func (cached *builtinPi) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -2068,6 +2092,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_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index 6c8896bb1f4..dfb1a30bffc 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() { @@ -4277,6 +4299,46 @@ func (asm *assembler) Fn_YEARWEEK() { }, "FN YEARWEEK DATE(SP-1)") } +func (asm *assembler) Fn_PERIOD_ADD() { + asm.adjustStack(-1) + asm.emit(func(env *ExpressionEnv) int { + if env.vm.stack[env.vm.sp-2] == nil { + env.vm.sp-- + return 1 + } + period := env.vm.stack[env.vm.sp-2].(*evalInt64).i + months := env.vm.stack[env.vm.sp-1].(*evalInt64).i + res, err := periodAdd(period, months) + if err != nil { + env.vm.err = err + return 0 + } + env.vm.stack[env.vm.sp-2] = res + env.vm.sp-- + return 1 + }, "FN PERIOD_ADD INT64(SP-2) INT64(SP-1)") +} + +func (asm *assembler) Fn_PERIOD_DIFF() { + asm.adjustStack(-1) + asm.emit(func(env *ExpressionEnv) int { + if env.vm.stack[env.vm.sp-2] == nil { + env.vm.sp-- + return 1 + } + period1 := env.vm.stack[env.vm.sp-2].(*evalInt64).i + period2 := env.vm.stack[env.vm.sp-1].(*evalInt64).i + res, err := periodDiff(period1, period2) + if err != nil { + env.vm.err = err + return 0 + } + env.vm.stack[env.vm.sp-2] = res + env.vm.sp-- + return 1 + }, "FN PERIOD_DIFF INT64(SP-2) INT64(SP-1)") +} + func (asm *assembler) Interval(l int) { asm.adjustStack(-l) asm.emit(func(env *ExpressionEnv) int { 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 daf64296e98..50f231dbe9c 100644 --- a/go/vt/vtgate/evalengine/expr_bvar.go +++ b/go/vt/vtgate/evalengine/expr_bvar.go @@ -160,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_regexp.go b/go/vt/vtgate/evalengine/fn_regexp.go index a94b9a83aee..10aa3f6b6c6 100644 --- a/go/vt/vtgate/evalengine/fn_regexp.go +++ b/go/vt/vtgate/evalengine/fn_regexp.go @@ -167,43 +167,43 @@ func compileRegex(pat eval, c colldata.Charset, flags icuregex.RegexpFlag) (*icu var compileErr *icuregex.CompileError if errors.Is(err, icuerrors.ErrUnsupported) { - err = vterrors.NewErrorf(vtrpcpb.Code_UNIMPLEMENTED, vterrors.RegexpUnimplemented, err.Error()) + err = vterrors.NewError(vtrpcpb.Code_UNIMPLEMENTED, vterrors.RegexpUnimplemented, err.Error()) } else if errors.Is(err, icuerrors.ErrIllegalArgument) { - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpIllegalArgument, err.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpIllegalArgument, err.Error()) } else if errors.As(err, &compileErr) { switch compileErr.Code { case icuregex.InternalError: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInternal, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInternal, compileErr.Error()) case icuregex.RuleSyntax: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpRuleSyntax, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpRuleSyntax, compileErr.Error()) case icuregex.BadEscapeSequence: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpBadEscapeSequence, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpBadEscapeSequence, compileErr.Error()) case icuregex.PropertySyntax: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpRuleSyntax, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpRuleSyntax, compileErr.Error()) case icuregex.Unimplemented: - err = vterrors.NewErrorf(vtrpcpb.Code_UNIMPLEMENTED, vterrors.RegexpUnimplemented, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_UNIMPLEMENTED, vterrors.RegexpUnimplemented, compileErr.Error()) case icuregex.MismatchedParen: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMismatchParen, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMismatchParen, compileErr.Error()) case icuregex.BadInterval: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpBadInterval, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpBadInterval, compileErr.Error()) case icuregex.MaxLtMin: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMaxLtMin, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMaxLtMin, compileErr.Error()) case icuregex.InvalidBackRef: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidBackRef, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidBackRef, compileErr.Error()) case icuregex.InvalidFlag: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidFlag, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidFlag, compileErr.Error()) case icuregex.LookBehindLimit: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpLookBehindLimit, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpLookBehindLimit, compileErr.Error()) case icuregex.MissingCloseBracket: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMissingCloseBracket, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMissingCloseBracket, compileErr.Error()) case icuregex.InvalidRange: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidRange, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidRange, compileErr.Error()) case icuregex.PatternTooBig: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpPatternTooBig, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpPatternTooBig, compileErr.Error()) case icuregex.InvalidCaptureGroupName: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidCaptureGroup, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidCaptureGroup, compileErr.Error()) default: - err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInternal, compileErr.Error()) + err = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInternal, compileErr.Error()) } } 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..2d5e12f518d 100644 --- a/go/vt/vtgate/evalengine/fn_time.go +++ b/go/vt/vtgate/evalengine/fn_time.go @@ -21,10 +21,14 @@ 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" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/vterrors" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) var SystemTime = time.Now @@ -173,6 +177,14 @@ type ( CallExpr } + builtinPeriodAdd struct { + CallExpr + } + + builtinPeriodDiff struct { + CallExpr + } + builtinDateMath struct { CallExpr sub bool @@ -213,6 +225,8 @@ var _ IR = (*builtinWeekDay)(nil) var _ IR = (*builtinWeekOfYear)(nil) var _ IR = (*builtinYear)(nil) var _ IR = (*builtinYearWeek)(nil) +var _ IR = (*builtinPeriodAdd)(nil) +var _ IR = (*builtinPeriodDiff)(nil) func (call *builtinNow) eval(env *ExpressionEnv) (eval, error) { now := env.time(call.utc) @@ -1859,6 +1873,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 +1891,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 +1911,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 } @@ -1955,6 +1977,105 @@ func (call *builtinYearWeek) compile(c *compiler) (ctype, error) { return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil } +func periodAdd(period, months int64) (*evalInt64, error) { + if !datetime.ValidatePeriod(period) { + return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongArguments, "Incorrect arguments to period_add") + } + return newEvalInt64(datetime.MonthsToPeriod(datetime.PeriodToMonths(period) + months)), nil +} + +func (b *builtinPeriodAdd) eval(env *ExpressionEnv) (eval, error) { + p, m, err := b.arg2(env) + if err != nil { + return nil, err + } + if p == nil || m == nil { + return nil, nil + } + period := evalToInt64(p) + months := evalToInt64(m) + return periodAdd(period.i, months.i) +} + +func (call *builtinPeriodAdd) compile(c *compiler) (ctype, error) { + period, err := call.Arguments[0].compile(c) + if err != nil { + return ctype{}, err + } + months, err := call.Arguments[1].compile(c) + if err != nil { + return ctype{}, err + } + + skip := c.compileNullCheck2(period, months) + + switch period.Type { + case sqltypes.Int64: + default: + c.asm.Convert_xi(2) + } + + switch months.Type { + case sqltypes.Int64: + default: + c.asm.Convert_xi(1) + } + + c.asm.Fn_PERIOD_ADD() + c.asm.jumpDestination(skip) + return ctype{Type: sqltypes.Int64, Flag: period.Flag | months.Flag | flagNullable}, nil +} + +func periodDiff(period1, period2 int64) (*evalInt64, error) { + if !datetime.ValidatePeriod(period1) || !datetime.ValidatePeriod(period2) { + return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongArguments, "Incorrect arguments to period_diff") + } + res := datetime.PeriodToMonths(period1) - datetime.PeriodToMonths(period2) + return newEvalInt64(res), nil +} + +func (b *builtinPeriodDiff) eval(env *ExpressionEnv) (eval, error) { + p1, p2, err := b.arg2(env) + if err != nil { + return nil, err + } + if p1 == nil || p2 == nil { + return nil, nil + } + period1 := evalToInt64(p1) + period2 := evalToInt64(p2) + return periodDiff(period1.i, period2.i) +} + +func (call *builtinPeriodDiff) compile(c *compiler) (ctype, error) { + period1, err := call.Arguments[0].compile(c) + if err != nil { + return ctype{}, err + } + period2, err := call.Arguments[1].compile(c) + if err != nil { + return ctype{}, err + } + + skip := c.compileNullCheck2(period1, period2) + + switch period1.Type { + case sqltypes.Int64: + default: + c.asm.Convert_xi(2) + } + + switch period2.Type { + case sqltypes.Int64: + default: + c.asm.Convert_xi(1) + } + + c.asm.Fn_PERIOD_DIFF() + c.asm.jumpDestination(skip) + return ctype{Type: sqltypes.Int64, Flag: period1.Flag | period2.Flag | flagNullable}, nil +} + func evalToInterval(itv eval, unit datetime.IntervalType, negate bool) *datetime.Interval { switch itv := itv.(type) { case *evalBytes: diff --git a/go/vt/vtgate/evalengine/integration/fuzz_test.go b/go/vt/vtgate/evalengine/integration/fuzz_test.go index 17a721edde9..7372d6fd731 100644 --- a/go/vt/vtgate/evalengine/integration/fuzz_test.go +++ b/go/vt/vtgate/evalengine/integration/fuzz_test.go @@ -20,6 +20,7 @@ package integration import ( "encoding/json" + "errors" "fmt" "math/rand/v2" "os" @@ -205,11 +206,11 @@ func TestGenerateFuzzCases(t *testing.T) { remote, remoteErr := conn.ExecuteFetch(query, 1, false) if localErr != nil && strings.Contains(localErr.Error(), "syntax error at position") { - localErr = fmt.Errorf(localSyntaxErr) + localErr = errors.New(localSyntaxErr) } if remoteErr != nil && strings.Contains(remoteErr.Error(), "You have an error in your SQL syntax") { - remoteErr = fmt.Errorf(syntaxErr) + remoteErr = errors.New(syntaxErr) } res := mismatch{ diff --git a/go/vt/vtgate/evalengine/testcases/cases.go b/go/vt/vtgate/evalengine/testcases/cases.go index c937e7dbbc0..ed1c5ed1f76 100644 --- a/go/vt/vtgate/evalengine/testcases/cases.go +++ b/go/vt/vtgate/evalengine/testcases/cases.go @@ -155,6 +155,8 @@ var Cases = []TestCase{ {Run: FnWeekOfYear}, {Run: FnYear}, {Run: FnYearWeek}, + {Run: FnPeriodAdd}, + {Run: FnPeriodDiff}, {Run: FnInetAton}, {Run: FnInetNtoa}, {Run: FnInet6Aton}, @@ -1960,6 +1962,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) @@ -2220,6 +2225,48 @@ func FnYearWeek(yield Query) { } } +func FnPeriodAdd(yield Query) { + for _, p := range inputBitwise { + for _, m := range inputBitwise { + yield(fmt.Sprintf("PERIOD_ADD(%s, %s)", p, m), nil) + } + } + for _, p := range inputPeriods { + for _, m := range inputBitwise { + yield(fmt.Sprintf("PERIOD_ADD(%s, %s)", p, m), nil) + } + } + + mysqlDocSamples := []string{ + `PERIOD_ADD(200801,2)`, + } + + for _, q := range mysqlDocSamples { + yield(q, nil) + } +} + +func FnPeriodDiff(yield Query) { + for _, p1 := range inputBitwise { + for _, p2 := range inputBitwise { + yield(fmt.Sprintf("PERIOD_DIFF(%s, %s)", p1, p2), nil) + } + } + for _, p1 := range inputPeriods { + for _, p2 := range inputPeriods { + yield(fmt.Sprintf("PERIOD_DIFF(%s, %s)", p1, p2), nil) + } + } + + mysqlDocSamples := []string{ + `PERIOD_DIFF(200802,200703)`, + } + + for _, q := range mysqlDocSamples { + yield(q, nil) + } +} + func FnInetAton(yield Query) { for _, d := range ipInputs { yield(fmt.Sprintf("INET_ATON(%s)", d), 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/evalengine/testcases/inputs.go b/go/vt/vtgate/evalengine/testcases/inputs.go index eb94235d9b4..ac23281fd54 100644 --- a/go/vt/vtgate/evalengine/testcases/inputs.go +++ b/go/vt/vtgate/evalengine/testcases/inputs.go @@ -59,6 +59,11 @@ var inputBitwise = []string{ "64", "'64'", "_binary '64'", "X'40'", "_binary X'40'", } +var inputPeriods = []string{ + "110192", "'119812'", "2703", "7111", "200103", "200309", "0309", "-110102", "0", + "'032'", "223", "'-119812'", "-2703", "99999999999999999999999911", "'-0309'", +} + var radianInputs = []string{ "0", "1", diff --git a/go/vt/vtgate/evalengine/translate.go b/go/vt/vtgate/evalengine/translate.go index 0091f06a633..99e1508cc04 100644 --- a/go/vt/vtgate/evalengine/translate.go +++ b/go/vt/vtgate/evalengine/translate.go @@ -87,7 +87,7 @@ func (ast *astCompiler) translateComparisonExpr2(op sqlparser.ComparisonExprOper Negate: op == sqlparser.NotRegexpOp, }, nil default: - return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, op.ToString()) + return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, op.ToString()) } } diff --git a/go/vt/vtgate/evalengine/translate_builtin.go b/go/vt/vtgate/evalengine/translate_builtin.go index d4c6bcdae5a..476ee32483b 100644 --- a/go/vt/vtgate/evalengine/translate_builtin.go +++ b/go/vt/vtgate/evalengine/translate_builtin.go @@ -528,6 +528,20 @@ func (ast *astCompiler) translateFuncExpr(fn *sqlparser.FuncExpr) (IR, error) { default: return nil, argError(method) } + case "period_add": + switch len(args) { + case 2: + return &builtinPeriodAdd{CallExpr: call}, nil + default: + return nil, argError(method) + } + case "period_diff": + switch len(args) { + case 2: + return &builtinPeriodDiff{CallExpr: call}, nil + default: + return nil, argError(method) + } case "inet_aton": if len(args) != 1 { return nil, argError(method) diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index cec0dba8274..093246c71c5 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -208,7 +208,7 @@ func NewExecutor( return e.plans.Metrics.Hits() }) stats.NewCounterFunc("QueryPlanCacheMisses", "Query plan cache misses", func() int64 { - return e.plans.Metrics.Hits() + return e.plans.Metrics.Misses() }) servenv.HTTPHandle(pathQueryPlans, e) servenv.HTTPHandle(pathScatterStats, e) @@ -1619,6 +1619,14 @@ 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) +} + +func (e *Executor) UnresolvedTransactions(ctx context.Context, targets []*querypb.Target) ([]*querypb.TransactionMetadata, error) { + return e.txConn.UnresolvedTransactions(ctx, targets) +} + type ( errorTransformer interface { TransformError(err error) error diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index bd24907af9b..2e95e438c22 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -121,11 +121,13 @@ func TestSelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select count(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname /* VARCHAR */ and ist.table_name = :ist_table_name /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select count(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname /* VARCHAR */ and ist.table_name = :ist_table_name /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "__vtschemaname": sqltypes.StringBindVariable("performance_schema"), "ist_table_name": sqltypes.StringBindVariable("foo"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil @@ -135,11 +137,13 @@ func TestSelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */ and table_name = :table_name /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */ and table_name = :table_name /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), "table_name": sqltypes.StringBindVariable("user"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil @@ -149,10 +153,12 @@ func TestSelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) } @@ -427,6 +433,19 @@ func TestSetSystemVariablesWithReservedConnection(t *testing.T) { sbc1.Queries = nil } +func TestSelectVindexFunc(t *testing.T) { + executor, _, _, _, _ := createExecutorEnv(t) + + query := "select * from hash_index where id = 1" + session := NewAutocommitSession(&vtgatepb.Session{}) + _, err := executor.Execute(context.Background(), nil, "TestSelectVindexFunc", session, query, nil) + require.ErrorContains(t, err, "VT09005: no database selected") + + session.TargetString = KsTestSharded + _, err = executor.Execute(context.Background(), nil, "TestSelectVindexFunc", session, query, nil) + require.NoError(t, err) +} + func TestCreateTableValidTimestamp(t *testing.T) { executor, sbc1, _, _, _ := createExecutorEnv(t) executor.normalize = true @@ -468,13 +487,15 @@ func TestGen4SelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select count(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname /* VARCHAR */ and ist.table_name = :ist_table_name1 /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select count(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname /* VARCHAR */ and ist.table_name = :ist_table_name1 /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "ist_table_schema": sqltypes.StringBindVariable("performance_schema"), "__vtschemaname": sqltypes.StringBindVariable("performance_schema"), "ist_table_name": sqltypes.StringBindVariable("foo"), "ist_table_name1": sqltypes.StringBindVariable("foo"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil @@ -484,26 +505,30 @@ func TestGen4SelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select :vtg1 /* INT64 */ from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select :vtg1 /* INT64 */ from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "vtg1": sqltypes.Int64BindVariable(1), "constraint_schema": sqltypes.StringBindVariable("vt_ks"), "table_name": sqltypes.StringBindVariable("user"), "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), "table_name1": sqltypes.StringBindVariable("user"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks'" _, err = executor.Execute(context.Background(), nil, "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), query, map[string]*querypb.BindVariable{}) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select :vtg1 /* INT64 */ from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select :vtg1 /* INT64 */ from information_schema.table_constraints where constraint_schema = :__vtschemaname /* VARCHAR */", BindVariables: map[string]*querypb.BindVariable{ "vtg1": sqltypes.Int64BindVariable(1), "constraint_schema": sqltypes.StringBindVariable("vt_ks"), "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil @@ -513,11 +538,13 @@ func TestGen4SelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname /* VARCHAR */ and c.table_schema = :__vtschemaname /* VARCHAR */ and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", + wantQueries = []*querypb.BoundQuery{{ + Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname /* VARCHAR */ and c.table_schema = :__vtschemaname /* VARCHAR */ and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", BindVariables: map[string]*querypb.BindVariable{ "t_table_schema": sqltypes.StringBindVariable("TestExecutor"), "__replacevtschemaname": sqltypes.Int64BindVariable(1), - }}} + }, + }} utils.MustMatch(t, wantQueries, sbc1.Queries) } @@ -1075,7 +1102,6 @@ func TestSelectDatabase(t *testing.T) { } require.NoError(t, err) utils.MustMatch(t, wantResult, result, "Mismatch") - } func TestSelectBindvars(t *testing.T) { @@ -3192,7 +3218,6 @@ func TestLockReserve(t *testing.T) { _, err := exec(executor, session, "select get_lock('lock name', 10) from dual") require.NoError(t, err) require.NotNil(t, session.LockSession) - } func TestSelectFromInformationSchema(t *testing.T) { @@ -3900,15 +3925,15 @@ func TestSelectAggregationNoData(t *testing.T) { { sql: `select count(*) from (select col1, col2 from user limit 2) x`, sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1", "int64|int64|int64")), - expSandboxQ: "select x.col1, x.col2, 1 from (select col1, col2 from `user`) as x limit 2", - expField: `[name:"count(*)" type:INT64]`, + expSandboxQ: "select 1 from (select col1, col2 from `user`) as x limit 2", + expField: `[name:"count(*)" type:INT64 charset:63 flags:32769]`, expRow: `[[INT64(0)]]`, }, { sql: `select col2, count(*) from (select col1, col2 from user limit 2) x group by col2`, sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1|weight_string(col2)", "int64|int64|int64|varbinary")), - expSandboxQ: "select x.col1, x.col2, 1, weight_string(x.col2) from (select col1, col2 from `user`) as x limit 2", - expField: `[name:"col2" type:INT64 name:"count(*)" type:INT64]`, + expSandboxQ: "select x.col1, x.col2, weight_string(x.col2) from (select col1, col2 from `user`) as x limit 2", + expField: `[name:"col2" type:INT64 charset:63 flags:32768 name:"count(*)" type:INT64 charset:63 flags:32769]`, expRow: `[]`, }, } @@ -3992,15 +4017,15 @@ func TestSelectAggregationData(t *testing.T) { { sql: `select count(*) from (select col1, col2 from user limit 2) x`, sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1", "int64|int64|int64"), "100|200|1", "200|300|1"), - expSandboxQ: "select x.col1, x.col2, 1 from (select col1, col2 from `user`) as x limit 2", - expField: `[name:"count(*)" type:INT64]`, + expSandboxQ: "select 1 from (select col1, col2 from `user`) as x limit 2", + expField: `[name:"count(*)" type:INT64 charset:63 flags:32769]`, expRow: `[[INT64(2)]]`, }, { sql: `select col2, count(*) from (select col1, col2 from user limit 9) x group by col2`, sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1|weight_string(col2)", "int64|int64|int64|varbinary"), "100|3|1|NULL", "200|2|1|NULL"), - expSandboxQ: "select x.col1, x.col2, 1, weight_string(x.col2) from (select col1, col2 from `user`) as x limit 9", - expField: `[name:"col2" type:INT64 name:"count(*)" type:INT64]`, + expSandboxQ: "select x.col1, x.col2, weight_string(x.col2) from (select col1, col2 from `user`) as x limit 9", + expField: `[name:"col2" type:INT64 charset:63 flags:32768 name:"count(*)" type:INT64 charset:63 flags:32769]`, expRow: `[[INT64(2) INT64(4)] [INT64(3) INT64(5)]]`, }, { @@ -4335,3 +4360,107 @@ func TestStreamJoinQuery(t *testing.T) { utils.MustMatch(t, wantResult.Rows[idx], result.Rows[idx], "mismatched on: ", strconv.Itoa(idx)) } } + +// TestSysVarGlobalAndSession tests that global and session variables are set correctly. +// It also tests that setting a global variable does not affect the session variable and vice versa. +// Also, test what happens on running select @@global and select @@session for a system variable. +func TestSysVarGlobalAndSession(t *testing.T) { + executor, sbc1, _, _, _ := createExecutorEnv(t) + executor.normalize = true + session := NewAutocommitSession(&vtgatepb.Session{EnableSystemSettings: true, SystemVariables: map[string]string{}}) + + sbc1.SetResults([]*sqltypes.Result{ + sqltypes.MakeTestResult(sqltypes.MakeTestFields("innodb_lock_wait_timeout", "uint64"), "20"), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("innodb_lock_wait_timeout", "uint64"), "20"), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("1", "int64")), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("new", "uint64"), "40"), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("reserve_execute", "uint64")), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("@@global.innodb_lock_wait_timeout", "uint64"), "20"), + }) + qr, err := executor.Execute(context.Background(), nil, "TestSetStmt", session, + "select @@innodb_lock_wait_timeout", nil) + require.NoError(t, err) + require.Equal(t, `[[UINT64(20)]]`, fmt.Sprintf("%v", qr.Rows)) + + qr, err = executor.Execute(context.Background(), nil, "TestSetStmt", session, + "select @@global.innodb_lock_wait_timeout", nil) + require.NoError(t, err) + require.Equal(t, `[[UINT64(20)]]`, fmt.Sprintf("%v", qr.Rows)) + + _, err = executor.Execute(context.Background(), nil, "TestSetStmt", session, + "set @@global.innodb_lock_wait_timeout = 120", nil) + require.NoError(t, err) + require.Empty(t, session.SystemVariables["innodb_lock_wait_timeout"]) + + _, err = executor.Execute(context.Background(), nil, "TestSetStmt", session, + "set @@innodb_lock_wait_timeout = 40", nil) + require.NoError(t, err) + require.EqualValues(t, "40", session.SystemVariables["innodb_lock_wait_timeout"]) + + qr, err = executor.Execute(context.Background(), nil, "TestSetStmt", session, + "select @@innodb_lock_wait_timeout", nil) + require.NoError(t, err) + require.Equal(t, `[[INT64(40)]]`, fmt.Sprintf("%v", qr.Rows)) + + qr, err = executor.Execute(context.Background(), nil, "TestSetStmt", session, + "select @@global.innodb_lock_wait_timeout", nil) + require.NoError(t, err) + require.Equal(t, `[[UINT64(20)]]`, fmt.Sprintf("%v", qr.Rows)) +} + +func BenchmarkSelectMirror(b *testing.B) { + ctx := context.Background() + cell := "aa" + sql := fmt.Sprintf("select id from %s.user where id = 1", KsTestUnsharded) + + currentSandboxMirrorRules := sandboxMirrorRules + b.Cleanup(func() { + setSandboxMirrorRules(currentSandboxMirrorRules) + }) + + // Don't use createExecutorEnv. Doesn't work with benchmarks because of + // utils.EnsureNoLeak. + createBenchmarkExecutor := func(b *testing.B) (context.Context, *Executor) { + ctx, cancel := context.WithCancel(ctx) + b.Cleanup(cancel) + hc := discovery.NewFakeHealthCheck(nil) + u := createSandbox(KsTestUnsharded) + s := createSandbox(KsTestSharded) + s.VSchema = executorVSchema + u.VSchema = unshardedVSchema + serv := newSandboxForCells(ctx, []string{cell}) + resolver := newTestResolver(ctx, hc, serv, cell) + shards := []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"} + for _, shard := range shards { + hc.AddTestTablet(cell, shard, 1, KsTestSharded, shard, topodatapb.TabletType_PRIMARY, true, 1, nil) + } + hc.AddTestTablet(cell, "0", 1, KsTestUnsharded, "0", topodatapb.TabletType_PRIMARY, true, 1, nil) + return ctx, createExecutor(ctx, serv, cell, resolver) + } + + for _, percent := range []float32{0, 1, 5, 10, 25, 50, 100} { + b.Run(fmt.Sprintf("mirror %.2f%%", percent), func(b *testing.B) { + setSandboxMirrorRules(fmt.Sprintf(`{ + "rules": [ + { + "from_table": "%s.user", + "to_table": "%s.user", + "percent": %.2f + } + ] + }`, KsTestUnsharded, KsTestSharded, percent)) + + ctx, executor := createBenchmarkExecutor(b) + session := &vtgatepb.Session{ + TargetString: "@primary", + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + executorExec(ctx, executor, session, sql, nil) + } + b.StopTimer() + }) + } +} diff --git a/go/vt/vtgate/executor_set_test.go b/go/vt/vtgate/executor_set_test.go index 5e66899db44..2792c957edd 100644 --- a/go/vt/vtgate/executor_set_test.go +++ b/go/vt/vtgate/executor_set_test.go @@ -364,6 +364,13 @@ func TestExecutorSetOp(t *testing.T) { in: "set tx_isolation = 'read-committed'", sysVars: map[string]string{"tx_isolation": "'read-committed'"}, result: returnResult("tx_isolation", "varchar", "read-committed"), + }, { + in: "set @@innodb_lock_wait_timeout=120", + sysVars: map[string]string{"innodb_lock_wait_timeout": "120"}, + result: returnResult("innodb_lock_wait_timeout", "int64", "120"), + }, { + in: "set @@global.innodb_lock_wait_timeout=120", + result: returnResult("innodb_lock_wait_timeout", "int64", "120"), }} for _, tcase := range testcases { t.Run(tcase.in, func(t *testing.T) { diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index cce717674d6..b8e2b996780 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -1105,6 +1105,15 @@ func TestExecutorShowTargeted(t *testing.T) { } } +func TestExecutorShowFromSystemSchema(t *testing.T) { + executor, _, _, _, ctx := createExecutorEnv(t) + + session := NewSafeSession(&vtgatepb.Session{TargetString: "mysql"}) + + _, err := executor.Execute(ctx, nil, "TestExecutorShowFromSystemSchema", session, "show tables", nil) + require.NoError(t, err) +} + func TestExecutorUse(t *testing.T) { executor, _, _, _, ctx := createExecutorEnv(t) 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/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 546a9854f26..458c8c5e1c3 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -77,11 +77,31 @@ func transformToPrimitive(ctx *plancontext.PlanningContext, op operators.Operato return transformSequential(ctx, op) case *operators.DMLWithInput: return transformDMLWithInput(ctx, op) + case *operators.RecurseCTE: + return transformRecurseCTE(ctx, op) + case *operators.PercentBasedMirror: + return transformPercentBasedMirror(ctx, op) } return nil, vterrors.VT13001(fmt.Sprintf("unknown type encountered: %T (transformToPrimitive)", op)) } +func transformPercentBasedMirror(ctx *plancontext.PlanningContext, op *operators.PercentBasedMirror) (engine.Primitive, error) { + primitive, err := transformToPrimitive(ctx, op.Operator) + if err != nil { + return nil, err + } + + target, err := transformToPrimitive(ctx.UseMirror(), op.Target) + // Mirroring is best-effort. If we encounter an error while building the + // mirror target primitive, proceed without mirroring. + if err != nil { + return primitive, nil + } + + return engine.NewPercentBasedMirror(op.Percent, primitive, target), nil +} + func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWithInput) (engine.Primitive, error) { input, err := transformToPrimitive(ctx, op.Source) if err != nil { @@ -288,7 +308,6 @@ func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify Verify: verify, Exec: inputLP, }, nil - } func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggregator) (engine.Primitive, error) { @@ -451,7 +470,6 @@ func getEvalEngineExpr(ctx *plancontext.PlanningContext, pe *operators.ProjExpr) default: return nil, vterrors.VT13001("project not planned for: %s", pe.String()) } - } // newSimpleProjection creates a simple projections @@ -981,6 +999,22 @@ func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) return prim, nil } +func transformRecurseCTE(ctx *plancontext.PlanningContext, op *operators.RecurseCTE) (engine.Primitive, error) { + seed, err := transformToPrimitive(ctx, op.Seed) + if err != nil { + return nil, err + } + term, err := transformToPrimitive(ctx, op.Term) + if err != nil { + return nil, err + } + return &engine.RecurseCTE{ + Seed: seed, + Term: term, + Vars: op.Vars, + }, nil +} + func generateQuery(statement sqlparser.Statement) string { buf := sqlparser.NewTrackedBuffer(dmlFormatter) statement.Format(buf) diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index fef4ae2aee4..3972ac8290a 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -55,7 +55,36 @@ func ToSQL(ctx *plancontext.PlanningContext, op Operator) (_ sqlparser.Statement return q.stmt, q.dmlOperator, nil } +// includeTable will return false if the table is a CTE, and it is not merged +// it will return true if the table is not a CTE or if it is a CTE and it is merged +func (qb *queryBuilder) includeTable(op *Table) bool { + if qb.ctx.SemTable == nil { + return true + } + tbl, err := qb.ctx.SemTable.TableInfoFor(op.QTable.ID) + if err != nil { + panic(err) + } + cteTbl, isCTE := tbl.(*semantics.CTETable) + if !isCTE { + return true + } + + return cteTbl.Merged +} + func (qb *queryBuilder) addTable(db, tableName, alias string, tableID semantics.TableSet, hints sqlparser.IndexHints) { + if tableID.NumberOfTables() == 1 && qb.ctx.SemTable != nil { + tblInfo, err := qb.ctx.SemTable.TableInfoFor(tableID) + if err != nil { + panic(err) + } + cte, isCTE := tblInfo.(*semantics.CTETable) + if isCTE { + tableName = cte.TableName + db = "" + } + } tableExpr := sqlparser.TableName{ Name: sqlparser.NewIdentifierCS(tableName), Qualifier: sqlparser.NewIdentifierCS(db), @@ -105,6 +134,12 @@ func (qb *queryBuilder) addPredicate(expr sqlparser.Expr) { addPred = stmt.AddWhere case *sqlparser.Delete: addPred = stmt.AddWhere + case nil: + // this would happen if we are adding a predicate on a dual query. + // we use this when building recursive CTE queries + sel := &sqlparser.Select{} + addPred = sel.AddWhere + qb.stmt = sel default: panic(fmt.Sprintf("cant add WHERE to %T", qb.stmt)) } @@ -207,6 +242,27 @@ func (qb *queryBuilder) unionWith(other *queryBuilder, distinct bool) { } } +func (qb *queryBuilder) recursiveCteWith(other *queryBuilder, name, alias string, distinct bool) { + cteUnion := &sqlparser.Union{ + Left: qb.stmt.(sqlparser.SelectStatement), + Right: other.stmt.(sqlparser.SelectStatement), + Distinct: distinct, + } + + qb.stmt = &sqlparser.Select{ + With: &sqlparser.With{ + Recursive: true, + CTEs: []*sqlparser.CommonTableExpr{{ + ID: sqlparser.NewIdentifierCS(name), + Columns: nil, + Subquery: cteUnion, + }}, + }, + } + + qb.addTable("", name, alias, "", nil) +} + type FromStatement interface { GetFrom() []sqlparser.TableExpr SetFrom([]sqlparser.TableExpr) @@ -233,7 +289,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)} } @@ -399,6 +457,8 @@ func buildQuery(op Operator, qb *queryBuilder) { buildDelete(op, qb) case *Insert: buildDML(op, qb) + case *RecurseCTE: + buildRecursiveCTE(op, qb) default: panic(vterrors.VT13001(fmt.Sprintf("unknown operator to convert to SQL: %T", op))) } @@ -466,6 +526,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) { @@ -482,6 +550,10 @@ func buildLimit(op *Limit, qb *queryBuilder) { } func buildTable(op *Table, qb *queryBuilder) { + if !qb.includeTable(op) { + return + } + dbName := "" if op.QTable.IsInfSchema { @@ -541,7 +613,16 @@ func buildApplyJoin(op *ApplyJoin, qb *queryBuilder) { qbR := &queryBuilder{ctx: qb.ctx} buildQuery(op.RHS, qbR) - qb.joinWith(qbR, pred, op.JoinType) + + switch { + // if we have a recursive cte, we might be missing a statement from one of the sides + case qbR.stmt == nil: + // do nothing + case qb.stmt == nil: + qb.stmt = qbR.stmt + default: + qb.joinWith(qbR, pred, op.JoinType) + } } func buildUnion(op *Union, qb *queryBuilder) { @@ -626,6 +707,28 @@ func buildHorizon(op *Horizon, qb *queryBuilder) { sqlparser.RemoveKeyspaceInCol(qb.stmt) } +func buildRecursiveCTE(op *RecurseCTE, qb *queryBuilder) { + predicates := slice.Map(op.Predicates, func(jc *plancontext.RecurseExpression) sqlparser.Expr { + // since we are adding these join predicates, we need to mark to broken up version (RHSExpr) of it as done + err := qb.ctx.SkipJoinPredicates(jc.Original) + if err != nil { + panic(err) + } + return jc.Original + }) + pred := sqlparser.AndExpressions(predicates...) + buildQuery(op.Seed, qb) + qbR := &queryBuilder{ctx: qb.ctx} + buildQuery(op.Term, qbR) + qbR.addPredicate(pred) + infoFor, err := qb.ctx.SemTable.TableInfoFor(op.OuterID) + if err != nil { + panic(err) + } + + qb.recursiveCteWith(qbR, op.Def.Name, infoFor.GetAliasedTableExpr().As.String(), op.Distinct) +} + func mergeHaving(h1, h2 *sqlparser.Where) *sqlparser.Where { switch { case h1 == nil && h2 == nil: diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index fd9fca30110..63c21ba2bce 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -57,6 +57,9 @@ type ( // This is used to truncate the columns in the final result ResultColumns int + // Truncate is set to true if the columns produced by this operator should be truncated if we added any additional columns + Truncate bool + QP *QueryProjection DT *DerivedTable @@ -77,9 +80,6 @@ func (a *Aggregator) Inputs() []Operator { } func (a *Aggregator) SetInputs(operators []Operator) { - if len(operators) != 1 { - panic(fmt.Sprintf("unexpected number of operators as input in aggregator: %d", len(operators))) - } a.Source = operators[0] } @@ -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 } @@ -159,6 +151,8 @@ func (a *Aggregator) checkOffset(offset int) { } func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, reuse bool, groupBy bool, ae *sqlparser.AliasedExpr) (offset int) { + a.planOffsets(ctx) + defer func() { a.checkOffset(offset) }() @@ -207,6 +201,10 @@ func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, reuse bool, gro } func (a *Aggregator) AddWSColumn(ctx *plancontext.PlanningContext, offset int, underRoute bool) int { + if !underRoute { + a.planOffsets(ctx) + } + if len(a.Columns) <= offset { panic(vterrors.VT13001("offset out of range")) } @@ -229,7 +227,7 @@ func (a *Aggregator) AddWSColumn(ctx *plancontext.PlanningContext, offset int, u } if expr == nil { - for _, aggr := range a.Aggregations { + for i, aggr := range a.Aggregations { if aggr.ColOffset != offset { continue } @@ -238,9 +236,13 @@ func (a *Aggregator) AddWSColumn(ctx *plancontext.PlanningContext, offset int, u return aggr.WSOffset } - panic(vterrors.VT13001("expected to find a weight string for aggregation")) + a.Aggregations[i].WSOffset = len(a.Columns) + expr = a.Columns[offset].Expr + break } + } + if expr == nil { panic(vterrors.VT13001("could not find expression at offset")) } @@ -446,6 +448,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() } @@ -520,7 +525,7 @@ func (a *Aggregator) pushRemainingGroupingColumnsAndWeightStrings(ctx *planconte continue } - offset := a.internalAddColumn(ctx, aeWrap(weightStringFor(gb.Inner)), false) + offset := a.internalAddWSColumn(ctx, a.Grouping[idx].ColOffset, aeWrap(weightStringFor(gb.Inner))) a.Grouping[idx].WSOffset = offset } for idx, aggr := range a.Aggregations { @@ -529,11 +534,28 @@ func (a *Aggregator) pushRemainingGroupingColumnsAndWeightStrings(ctx *planconte } arg := aggr.getPushColumn() - offset := a.internalAddColumn(ctx, aeWrap(weightStringFor(arg)), false) + offset := a.internalAddWSColumn(ctx, aggr.ColOffset, aeWrap(weightStringFor(arg))) + a.Aggregations[idx].WSOffset = offset } } +func (a *Aggregator) internalAddWSColumn(ctx *plancontext.PlanningContext, inOffset int, aliasedExpr *sqlparser.AliasedExpr) int { + if a.ResultColumns == 0 && a.Truncate { + // if we need to use `internalAddColumn`, it means we are adding columns that are not part of the original list, + // so we need to set the ResultColumns to the current length of the columns list + a.ResultColumns = len(a.Columns) + } + + offset := a.Source.AddWSColumn(ctx, inOffset, false) + + if offset == len(a.Columns) { + // if we get an offset at the end of our current column list, it means we added a new column + a.Columns = append(a.Columns, aliasedExpr) + } + return offset +} + func (a *Aggregator) setTruncateColumnCount(offset int) { a.ResultColumns = offset } @@ -543,7 +565,7 @@ func (a *Aggregator) getTruncateColumnCount() int { } func (a *Aggregator) internalAddColumn(ctx *plancontext.PlanningContext, aliasedExpr *sqlparser.AliasedExpr, addToGroupBy bool) int { - if a.ResultColumns == 0 { + if a.ResultColumns == 0 && a.Truncate { // if we need to use `internalAddColumn`, it means we are adding columns that are not part of the original list, // so we need to set the ResultColumns to the current length of the columns list a.ResultColumns = len(a.Columns) diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index cd8f7b94dd5..4c6baab3729 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -37,8 +37,6 @@ type ( // JoinType is permitted to store only 3 of the possible values // NormalJoinType, StraightJoinType and LeftJoinType. JoinType sqlparser.JoinType - // LeftJoin will be true in the case of an outer join - LeftJoin bool // JoinColumns keeps track of what AST expression is represented in the Columns array JoinColumns *applyJoinColumns @@ -71,11 +69,10 @@ type ( // so they can be used for the result of this expression that is using data from both sides. // All fields will be used for these applyJoinColumn struct { - Original sqlparser.Expr // this is the original expression being passed through - LHSExprs []BindVarExpr // These are the expressions we are pushing to the left hand side which we'll receive as bind variables - RHSExpr sqlparser.Expr // This the expression that we'll evaluate on the right hand side. This is nil, if the right hand side has nothing. - DTColName *sqlparser.ColName // This is the output column name that the parent of JOIN will be seeing. If this is unset, then the colname is the String(Original). We set this when we push Projections with derived tables underneath a Join. - GroupBy bool // if this is true, we need to push this down to our inputs with addToGroupBy set to true + Original sqlparser.Expr // this is the original expression being passed through + LHSExprs []BindVarExpr // These are the expressions we are pushing to the left hand side which we'll receive as bind variables + RHSExpr sqlparser.Expr // This the expression that we'll evaluate on the right hand side. This is nil, if the right hand side has nothing. + GroupBy bool // if this is true, we need to push this down to our inputs with addToGroupBy set to true } // BindVarExpr is an expression needed from one side of a join/subquery, and the argument name for it. @@ -207,7 +204,6 @@ func (aj *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, orig *sq rhs := TableID(aj.RHS) both := lhs.Merge(rhs) deps := ctx.SemTable.RecursiveDeps(e) - switch { case deps.IsSolvedBy(lhs): col.LHSExprs = []BindVarExpr{{Expr: e}} @@ -227,8 +223,7 @@ func (aj *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, orig *sq func applyJoinCompare(ctx *plancontext.PlanningContext, expr sqlparser.Expr) func(e applyJoinColumn) bool { return func(e applyJoinColumn) bool { - // e.DTColName is how the outside world will be using this expression. So we should check for an equality with that too. - return ctx.SemTable.EqualsExprWithDeps(e.Original, expr) || ctx.SemTable.EqualsExprWithDeps(e.DTColName, expr) + return ctx.SemTable.EqualsExprWithDeps(e.Original, expr) } } @@ -295,7 +290,7 @@ func (aj *ApplyJoin) AddWSColumn(ctx *plancontext.PlanningContext, offset int, u func (aj *ApplyJoin) planOffsets(ctx *plancontext.PlanningContext) Operator { if len(aj.Columns) > 0 { // we've already done offset planning - return aj + return nil } for _, col := range aj.JoinColumns.columns { // Read the type description for applyJoinColumn to understand the following code @@ -304,12 +299,18 @@ func (aj *ApplyJoin) planOffsets(ctx *plancontext.PlanningContext) Operator { for _, col := range aj.JoinPredicates.columns { for _, lhsExpr := range col.LHSExprs { + if _, found := aj.Vars[lhsExpr.Name]; found { + continue + } offset := aj.LHS.AddColumn(ctx, true, false, aeWrap(lhsExpr.Expr)) aj.Vars[lhsExpr.Name] = offset } } for _, lhsExpr := range aj.ExtraLHSVars { + if _, found := aj.Vars[lhsExpr.Name]; found { + continue + } offset := aj.LHS.AddColumn(ctx, true, false, aeWrap(lhsExpr.Expr)) aj.Vars[lhsExpr.Name] = offset } @@ -344,6 +345,10 @@ func (aj *ApplyJoin) ShortDescription() string { } firstPart := fmt.Sprintf("on %s columns: %s", fn(aj.JoinPredicates), fn(aj.JoinColumns)) + if aj.JoinType == sqlparser.LeftJoinType { + firstPart = "LEFT JOIN " + firstPart + } + if len(aj.ExtraLHSVars) == 0 { return firstPart } @@ -439,11 +444,8 @@ func (jc applyJoinColumn) String() string { lhs := slice.Map(jc.LHSExprs, func(e BindVarExpr) string { return sqlparser.String(e.Expr) }) - 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)) + return fmt.Sprintf("[%s | %s | %s]", strings.Join(lhs, ", "), rhs, sqlparser.String(jc.Original)) } func (jc applyJoinColumn) IsPureLeft() bool { @@ -459,16 +461,10 @@ func (jc applyJoinColumn) IsMixedLeftAndRight() bool { } 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 } diff --git a/go/vt/vtgate/planbuilder/operators/ast_to_op.go b/go/vt/vtgate/planbuilder/operators/ast_to_op.go index 0d838610866..86d1c6197d4 100644 --- a/go/vt/vtgate/planbuilder/operators/ast_to_op.go +++ b/go/vt/vtgate/planbuilder/operators/ast_to_op.go @@ -26,8 +26,10 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -const foreignKeyConstraintValues = "fkc_vals" -const foreignKeyUpdateExpr = "fkc_upd" +const ( + foreignKeyConstraintValues = "fkc_vals" + foreignKeyUpdateExpr = "fkc_upd" +) // translateQueryToOp creates an operator tree that represents the input SELECT or UNION query func translateQueryToOp(ctx *plancontext.PlanningContext, selStmt sqlparser.Statement) Operator { @@ -47,6 +49,19 @@ func translateQueryToOp(ctx *plancontext.PlanningContext, selStmt sqlparser.Stat } } +func translateQueryToOpWithMirroring(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) Operator { + op := translateQueryToOp(ctx, stmt) + + if selStmt, ok := stmt.(sqlparser.SelectStatement); ok { + if mi := ctx.SemTable.GetMirrorInfo(); mi.Percent > 0 { + mirrorOp := translateQueryToOp(ctx.UseMirror(), selStmt) + op = NewPercentBasedMirror(mi.Percent, op, mirrorOp) + } + } + + return op +} + func createOperatorFromSelect(ctx *plancontext.PlanningContext, sel *sqlparser.Select) Operator { op := crossJoin(ctx, sel.From) @@ -148,8 +163,8 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U if isRHSUnion { panic(vterrors.VT12001("nesting of UNIONs on the right-hand side")) } - opLHS := translateQueryToOp(ctx, node.Left) - opRHS := translateQueryToOp(ctx, node.Right) + opLHS := translateQueryToOpForUnion(ctx, node.Left) + opRHS := translateQueryToOpForUnion(ctx, node.Right) lexprs := ctx.SemTable.SelectExprs(node.Left) rexprs := ctx.SemTable.SelectExprs(node.Right) @@ -158,6 +173,14 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U return newHorizon(union, node) } +func translateQueryToOpForUnion(ctx *plancontext.PlanningContext, node sqlparser.SelectStatement) Operator { + op := translateQueryToOp(ctx, node) + if hz, ok := op.(*Horizon); ok { + hz.Truncate = true + } + return op +} + // createOpFromStmt creates an operator from the given statement. It takes in two additional arguments— // 1. verifyAllFKs: For this given statement, do we need to verify validity of all the foreign keys on the vtgate level. // 2. fkToIgnore: The foreign key constraint to specifically ignore while planning the statement. This field is used in UPDATE CASCADE planning, wherein while planning the child update @@ -246,24 +269,47 @@ func getOperatorFromAliasedTableExpr(ctx *plancontext.PlanningContext, tableExpr panic(err) } - if vt, isVindex := tableInfo.(*semantics.VindexTable); isVindex { - solves := tableID + switch tableInfo := tableInfo.(type) { + case *semantics.VindexTable: return &Vindex{ Table: VindexTable{ TableID: tableID, Alias: tableExpr, Table: tbl, - VTable: vt.Table.GetVindexTable(), + VTable: tableInfo.Table.GetVindexTable(), }, - Vindex: vt.Vindex, - Solved: solves, + Vindex: tableInfo.Vindex, + Solved: tableID, + } + case *semantics.CTETable: + return createDualCTETable(ctx, tableID, tableInfo) + case *semantics.RealTable: + if tableInfo.CTE != nil { + return createRecursiveCTE(ctx, tableInfo.CTE, tableID) + } + + qg := newQueryGraph() + isInfSchema := tableInfo.IsInfSchema() + if ctx.IsMirrored() { + if mr := tableInfo.GetMirrorRule(); mr != nil { + newTbl := sqlparser.Clone(tbl) + newTbl.Qualifier = sqlparser.NewIdentifierCS(mr.Table.Keyspace.Name) + newTbl.Name = mr.Table.Name + if newTbl.Name.String() != tbl.Name.String() { + tableExpr = sqlparser.Clone(tableExpr) + tableExpr.As = tbl.Name + } + tbl = newTbl + } else { + panic(vterrors.VT13001(fmt.Sprintf("unable to find mirror rule for table: %T", tbl))) + } } + qt := &QueryTable{Alias: tableExpr, Table: tbl, ID: tableID, IsInfSchema: isInfSchema} + qg.Tables = append(qg.Tables, qt) + return qg + default: + panic(vterrors.VT13001(fmt.Sprintf("unknown table type %T", tableInfo))) } - qg := newQueryGraph() - isInfSchema := tableInfo.IsInfSchema() - qt := &QueryTable{Alias: tableExpr, Table: tbl, ID: tableID, IsInfSchema: isInfSchema} - qg.Tables = append(qg.Tables, qt) - return qg case *sqlparser.DerivedTable: if onlyTable && tbl.Select.GetLimit() == nil { tbl.Select.SetOrderBy(nil) @@ -284,6 +330,56 @@ func getOperatorFromAliasedTableExpr(ctx *plancontext.PlanningContext, tableExpr } } +func createDualCTETable(ctx *plancontext.PlanningContext, tableID semantics.TableSet, tableInfo *semantics.CTETable) Operator { + vschemaTable, _, _, _, _, err := ctx.VSchema.FindTableOrVindex(sqlparser.NewTableName("dual")) + if err != nil { + panic(err) + } + qtbl := &QueryTable{ + ID: tableID, + Alias: tableInfo.ASTNode, + Table: sqlparser.NewTableName("dual"), + } + return createRouteFromVSchemaTable(ctx, qtbl, vschemaTable, false, nil) +} + +func createRecursiveCTE(ctx *plancontext.PlanningContext, def *semantics.CTE, outerID semantics.TableSet) Operator { + union, ok := def.Query.(*sqlparser.Union) + if !ok { + panic(vterrors.VT13001("expected UNION in recursive CTE")) + } + + seed := translateQueryToOp(ctx, union.Left) + + // Push the CTE definition to the stack so that it can be used in the recursive part of the query + ctx.PushCTE(def, *def.IDForRecurse) + + term := translateQueryToOp(ctx, union.Right) + horizon, ok := term.(*Horizon) + if !ok { + panic(vterrors.VT09027(def.Name)) + } + term = horizon.Source + horizon.Source = nil // not sure about this + activeCTE, err := ctx.PopCTE() + if err != nil { + panic(err) + } + + return newRecurse(ctx, def, seed, term, activeCTE.Predicates, horizon, idForRecursiveTable(ctx, def), outerID, union.Distinct) +} + +func idForRecursiveTable(ctx *plancontext.PlanningContext, def *semantics.CTE) semantics.TableSet { + for i, table := range ctx.SemTable.Tables { + tbl, ok := table.(*semantics.CTETable) + if !ok || tbl.CTE.Name != def.Name { + continue + } + return semantics.SingleTableSet(i) + } + panic(vterrors.VT13001("recursive table not found")) +} + func crossJoin(ctx *plancontext.PlanningContext, exprs sqlparser.TableExprs) Operator { var output Operator for _, tableExpr := range exprs { diff --git a/go/vt/vtgate/planbuilder/operators/cte_merging.go b/go/vt/vtgate/planbuilder/operators/cte_merging.go new file mode 100644 index 00000000000..a6830cbe12b --- /dev/null +++ b/go/vt/vtgate/planbuilder/operators/cte_merging.go @@ -0,0 +1,95 @@ +/* +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 operators + +import ( + "vitess.io/vitess/go/vt/vtgate/engine" + "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" +) + +func tryMergeRecurse(ctx *plancontext.PlanningContext, in *RecurseCTE) (Operator, *ApplyResult) { + op := tryMergeCTE(ctx, in.Seed, in.Term, in) + if op == nil { + return in, NoRewrite + } + + return op, Rewrote("Merged CTE") +} + +func tryMergeCTE(ctx *plancontext.PlanningContext, seed, term Operator, in *RecurseCTE) *Route { + seedRoute, termRoute, routingA, routingB, a, b, sameKeyspace := prepareInputRoutes(seed, term) + if seedRoute == nil { + return nil + } + + switch { + case a == dual: + return mergeCTE(ctx, seedRoute, termRoute, routingB, in) + case b == dual: + return mergeCTE(ctx, seedRoute, termRoute, routingA, in) + case !sameKeyspace: + return nil + case a == anyShard: + return mergeCTE(ctx, seedRoute, termRoute, routingB, in) + case b == anyShard: + return mergeCTE(ctx, seedRoute, termRoute, routingA, in) + case a == sharded && b == sharded: + return tryMergeCTESharded(ctx, seedRoute, termRoute, in) + default: + return nil + } +} + +func tryMergeCTESharded(ctx *plancontext.PlanningContext, seed, term *Route, in *RecurseCTE) *Route { + tblA := seed.Routing.(*ShardedRouting) + tblB := term.Routing.(*ShardedRouting) + switch tblA.RouteOpCode { + case engine.EqualUnique: + // If the two routes fully match, they can be merged together. + if tblB.RouteOpCode == engine.EqualUnique { + aVdx := tblA.SelectedVindex() + bVdx := tblB.SelectedVindex() + aExpr := tblA.VindexExpressions() + bExpr := tblB.VindexExpressions() + if aVdx == bVdx && gen4ValuesEqual(ctx, aExpr, bExpr) { + return mergeCTE(ctx, seed, term, tblA, in) + } + } + } + + return nil +} + +func mergeCTE(ctx *plancontext.PlanningContext, seed, term *Route, r Routing, in *RecurseCTE) *Route { + in.Def.Merged = true + hz := in.Horizon + hz.Source = term.Source + newTerm, _ := expandHorizon(ctx, hz) + return &Route{ + Routing: r, + Source: &RecurseCTE{ + Predicates: in.Predicates, + Def: in.Def, + Seed: seed.Source, + Term: newTerm, + LeftID: in.LeftID, + OuterID: in.OuterID, + Distinct: in.Distinct, + }, + MergedWith: []*Route{term}, + } +} diff --git a/go/vt/vtgate/planbuilder/operators/delete.go b/go/vt/vtgate/planbuilder/operators/delete.go index 5bbf5218bd7..ef8403e5603 100644 --- a/go/vt/vtgate/planbuilder/operators/delete.go +++ b/go/vt/vtgate/planbuilder/operators/delete.go @@ -45,9 +45,6 @@ func (d *Delete) Inputs() []Operator { } func (d *Delete) SetInputs(inputs []Operator) { - if len(inputs) != 1 { - panic(vterrors.VT13001("unexpected number of inputs for Delete operator")) - } d.Source = inputs[0] } @@ -260,16 +257,16 @@ func createDeleteOperator(ctx *plancontext.PlanningContext, del *sqlparser.Delet Ignore: del.Ignore, Target: targetTbl, OwnedVindexQuery: ovq, - Source: op, }, } if del.Limit != nil { - addOrdering(ctx, del.OrderBy, delOp) delOp.Source = &Limit{ - Source: delOp.Source, + Source: addOrdering(ctx, op, del.OrderBy), AST: del.Limit, } + } else { + delOp.Source = op } return sqc.getRootOperator(delOp, nil), vTbl @@ -302,26 +299,24 @@ func makeColName(col sqlparser.IdentifierCI, table TargetTable, isMultiTbl bool) return sqlparser.NewColName(col.String()) } -func addOrdering(ctx *plancontext.PlanningContext, orderBy sqlparser.OrderBy, op Operator) { +func addOrdering(ctx *plancontext.PlanningContext, op Operator, orderBy sqlparser.OrderBy) Operator { es := &expressionSet{} - ordering := &Ordering{} - ordering.SetInputs(op.Inputs()) - for _, order := range orderBy { - if sqlparser.IsNull(order.Expr) { - // ORDER BY null can safely be ignored - continue - } - if !es.add(ctx, order.Expr) { + var order []OrderBy + for _, ord := range orderBy { + if sqlparser.IsNull(ord.Expr) || !es.add(ctx, ord.Expr) { + // ORDER BY null, or expression repeated can safely be ignored continue } - ordering.Order = append(ordering.Order, OrderBy{ - Inner: sqlparser.Clone(order), - SimplifiedExpr: order.Expr, + + order = append(order, OrderBy{ + Inner: sqlparser.Clone(ord), + SimplifiedExpr: ord.Expr, }) } - if len(ordering.Order) > 0 { - op.SetInputs([]Operator{ordering}) + if len(order) == 0 { + return op } + return &Ordering{Source: op, Order: order} } func updateQueryGraphWithSource(ctx *plancontext.PlanningContext, input Operator, tblID semantics.TableSet, vTbl *vindexes.Table) *vindexes.Table { diff --git a/go/vt/vtgate/planbuilder/operators/dml_with_input.go b/go/vt/vtgate/planbuilder/operators/dml_with_input.go index 09859b90bac..720056f1964 100644 --- a/go/vt/vtgate/planbuilder/operators/dml_with_input.go +++ b/go/vt/vtgate/planbuilder/operators/dml_with_input.go @@ -50,9 +50,6 @@ func (d *DMLWithInput) Inputs() []Operator { } func (d *DMLWithInput) SetInputs(inputs []Operator) { - if len(inputs) < 2 { - panic("unexpected number of inputs for DMLWithInput operator") - } d.Source = inputs[0] d.DML = inputs[1:] } @@ -114,7 +111,7 @@ func (d *DMLWithInput) planOffsets(ctx *plancontext.PlanningContext) Operator { } } d.BvList = bvList - return d + return nil } var _ Operator = (*DMLWithInput)(nil) diff --git a/go/vt/vtgate/planbuilder/operators/expressions.go b/go/vt/vtgate/planbuilder/operators/expressions.go index 17b4bc7c3f1..4e920d4312c 100644 --- a/go/vt/vtgate/planbuilder/operators/expressions.go +++ b/go/vt/vtgate/planbuilder/operators/expressions.go @@ -59,3 +59,15 @@ func breakExpressionInLHSandRHS( col.Original = expr return } + +// nothingNeedsFetching will return true if all the nodes in the expression are constant +func nothingNeedsFetching(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (constant bool) { + constant = true + _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + if mustFetchFromInput(ctx, node) { + constant = false + } + return true, nil + }, expr) + return +} diff --git a/go/vt/vtgate/planbuilder/operators/fk_cascade.go b/go/vt/vtgate/planbuilder/operators/fk_cascade.go index f24b59ca5ab..0aff5b3bea2 100644 --- a/go/vt/vtgate/planbuilder/operators/fk_cascade.go +++ b/go/vt/vtgate/planbuilder/operators/fk_cascade.go @@ -61,9 +61,6 @@ func (fkc *FkCascade) Inputs() []Operator { // SetInputs implements the Operator interface func (fkc *FkCascade) SetInputs(operators []Operator) { - if len(operators) < 2 { - panic("incorrect count of inputs for FkCascade") - } fkc.Parent = operators[0] fkc.Selection = operators[1] for idx, operator := range operators { diff --git a/go/vt/vtgate/planbuilder/operators/fk_verify.go b/go/vt/vtgate/planbuilder/operators/fk_verify.go index 8275a8d462f..a27f88f3335 100644 --- a/go/vt/vtgate/planbuilder/operators/fk_verify.go +++ b/go/vt/vtgate/planbuilder/operators/fk_verify.go @@ -52,9 +52,6 @@ func (fkv *FkVerify) Inputs() []Operator { // SetInputs implements the Operator interface func (fkv *FkVerify) SetInputs(operators []Operator) { fkv.Input = operators[0] - if len(fkv.Verify) != len(operators)-1 { - panic("mismatched number of verify inputs") - } for i := 1; i < len(operators); i++ { fkv.Verify[i-1].Op = operators[i] } diff --git a/go/vt/vtgate/planbuilder/operators/hash_join.go b/go/vt/vtgate/planbuilder/operators/hash_join.go index 1928f4dda9e..23d0d061e21 100644 --- a/go/vt/vtgate/planbuilder/operators/hash_join.go +++ b/go/vt/vtgate/planbuilder/operators/hash_join.go @@ -326,20 +326,9 @@ func (hj *HashJoin) addColumn(ctx *plancontext.PlanningContext, in sqlparser.Exp inOffset = op.AddColumn(ctx, false, false, aeWrap(expr)) } - // we turn the + // we have to turn the incoming offset to an outgoing offset of the columns this operator is exposing internalOffset := offsetter(inOffset) - - // ok, we have an offset from the input operator. Let's check if we already have it - // in our list of incoming columns - - for idx, offset := range hj.ColumnOffsets { - if internalOffset == offset { - return idx - } - } - hj.ColumnOffsets = append(hj.ColumnOffsets, internalOffset) - return len(hj.ColumnOffsets) - 1 } @@ -434,17 +423,7 @@ func (hj *HashJoin) addSingleSidedColumn( // we have to turn the incoming offset to an outgoing offset of the columns this operator is exposing internalOffset := offsetter(inOffset) - - // ok, we have an offset from the input operator. Let's check if we already have it - // in our list of incoming columns - for idx, offset := range hj.ColumnOffsets { - if internalOffset == offset { - return idx - } - } - hj.ColumnOffsets = append(hj.ColumnOffsets, internalOffset) - return len(hj.ColumnOffsets) - 1 } diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index 7539704c2a9..3fb72df91b4 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -18,6 +18,7 @@ package operators import ( "errors" + "fmt" "slices" "vitess.io/vitess/go/vt/sqlparser" @@ -49,6 +50,8 @@ type Horizon struct { // Columns needed to feed other plans Columns []*sqlparser.ColName ColumnsOffset []int + + Truncate bool } func newHorizon(src Operator, query sqlparser.SelectStatement) *Horizon { @@ -205,7 +208,7 @@ func (h *Horizon) getQP(ctx *plancontext.PlanningContext) *QueryProjection { } func (h *Horizon) ShortDescription() string { - return h.Alias + return fmt.Sprintf("Horizon (Alias: %s)", h.Alias) } func (h *Horizon) introducesTableID() semantics.TableSet { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 3f7700eed9d..29c1b1033f1 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) @@ -172,7 +208,7 @@ func createProjectionFromSelect(ctx *plancontext.PlanningContext, horizon *Horiz } if qp.NeedsAggregation() { - return createProjectionWithAggr(ctx, qp, dt, horizon.src()) + return createProjectionWithAggr(ctx, qp, dt, horizon) } projX := createProjectionWithoutAggr(ctx, qp, horizon.src()) @@ -180,8 +216,9 @@ func createProjectionFromSelect(ctx *plancontext.PlanningContext, horizon *Horiz return projX } -func createProjectionWithAggr(ctx *plancontext.PlanningContext, qp *QueryProjection, dt *DerivedTable, src Operator) Operator { +func createProjectionWithAggr(ctx *plancontext.PlanningContext, qp *QueryProjection, dt *DerivedTable, horizon *Horizon) Operator { aggregations, complexAggr := qp.AggregationExpressions(ctx, true) + src := horizon.Source aggrOp := &Aggregator{ Source: src, Original: true, @@ -203,7 +240,11 @@ func createProjectionWithAggr(ctx *plancontext.PlanningContext, qp *QueryProject if complexAggr { return createProjectionForComplexAggregation(aggrOp, qp) } - return createProjectionForSimpleAggregation(ctx, aggrOp, qp) + + addAllColumnsToAggregator(ctx, aggrOp, qp) + aggrOp.Truncate = horizon.Truncate + + return aggrOp } func pullOutValueSubqueries(ctx *plancontext.PlanningContext, aggr Aggr, sqc *SubQueryBuilder, outerID semantics.TableSet) Aggr { @@ -225,7 +266,7 @@ func pullOutValueSubqueries(ctx *plancontext.PlanningContext, aggr Aggr, sqc *Su return aggr } -func createProjectionForSimpleAggregation(ctx *plancontext.PlanningContext, a *Aggregator, qp *QueryProjection) Operator { +func addAllColumnsToAggregator(ctx *plancontext.PlanningContext, a *Aggregator, qp *QueryProjection) { outer: for colIdx, expr := range qp.SelectExprs { ae, err := expr.GetAliasedExpr() @@ -256,7 +297,6 @@ outer: } panic(vterrors.VT13001(fmt.Sprintf("Could not find the %s in aggregation in the original query", sqlparser.String(ae)))) } - return a } func createProjectionForComplexAggregation(a *Aggregator, qp *QueryProjection) Operator { diff --git a/go/vt/vtgate/planbuilder/operators/join.go b/go/vt/vtgate/planbuilder/operators/join.go index 71d2e5a8048..35760bceafb 100644 --- a/go/vt/vtgate/planbuilder/operators/join.go +++ b/go/vt/vtgate/planbuilder/operators/join.go @@ -17,9 +17,11 @@ limitations under the License. package operators import ( + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "vitess.io/vitess/go/vt/vtgate/semantics" ) // Join represents a join. If we have a predicate, this is an inner join. If no predicate exists, it is a cross join @@ -141,11 +143,49 @@ func addJoinPredicates( if subq != nil { continue } + + // if we are inside a CTE, we need to check if we depend on the recursion table + if cte := ctx.ActiveCTE(); cte != nil && ctx.SemTable.DirectDeps(pred).IsOverlapping(cte.Id) { + original := pred + pred = addCTEPredicate(ctx, pred, cte) + ctx.AddJoinPredicates(original, pred) + } op = op.AddPredicate(ctx, pred) } return sqc.getRootOperator(op, nil) } +// addCTEPredicate breaks the expression into LHS and RHS +func addCTEPredicate( + ctx *plancontext.PlanningContext, + pred sqlparser.Expr, + cte *plancontext.ContextCTE, +) sqlparser.Expr { + expr := breakCTEExpressionInLhsAndRhs(ctx, pred, cte.Id) + cte.Predicates = append(cte.Predicates, expr) + return expr.RightExpr +} + +func breakCTEExpressionInLhsAndRhs(ctx *plancontext.PlanningContext, pred sqlparser.Expr, lhsID semantics.TableSet) *plancontext.RecurseExpression { + col := breakExpressionInLHSandRHS(ctx, pred, lhsID) + + lhsExprs := slice.Map(col.LHSExprs, func(bve BindVarExpr) plancontext.BindVarExpr { + col, ok := bve.Expr.(*sqlparser.ColName) + if !ok { + panic(vterrors.VT13001("expected column name")) + } + return plancontext.BindVarExpr{ + Name: bve.Name, + Expr: col, + } + }) + return &plancontext.RecurseExpression{ + Original: col.Original, + RightExpr: col.RHSExpr, + LeftExprs: lhsExprs, + } +} + func createJoin(ctx *plancontext.PlanningContext, LHS, RHS Operator) Operator { lqg, lok := LHS.(*QueryGraph) rqg, rok := RHS.(*QueryGraph) diff --git a/go/vt/vtgate/planbuilder/operators/join_merging.go b/go/vt/vtgate/planbuilder/operators/join_merging.go index 8bba8ba57d9..672da551fa6 100644 --- a/go/vt/vtgate/planbuilder/operators/join_merging.go +++ b/go/vt/vtgate/planbuilder/operators/join_merging.go @@ -18,64 +18,90 @@ package operators import ( "fmt" - "reflect" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "vitess.io/vitess/go/vt/vtgate/vindexes" ) // mergeJoinInputs checks whether two operators can be merged into a single one. // If they can be merged, a new operator with the merged routing is returned // If they cannot be merged, nil is returned. -func mergeJoinInputs(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPredicates []sqlparser.Expr, m *joinMerger) *Route { +func (jm *joinMerger) mergeJoinInputs(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPredicates []sqlparser.Expr) *Route { lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace := prepareInputRoutes(lhs, rhs) if lhsRoute == nil { return nil } switch { + // We clone the right hand side and try and push all the join predicates that are solved entirely by that side. + // If a dual is on the left side, and it is a left join (all right joins are changed to left joins), then we can only merge if the right side is a single sharded routing. case a == dual: - // We clone the right hand side and try and push all the join predicates that are solved entirely by that side. - // If a dual is on the left side and it is a left join (all right joins are changed to left joins), then we can only merge if the right side is a single sharded routing. rhsClone := Clone(rhs).(*Route) for _, predicate := range joinPredicates { if ctx.SemTable.DirectDeps(predicate).IsSolvedBy(TableID(rhsClone)) { rhsClone.AddPredicate(ctx, predicate) } } - if !m.joinType.IsInner() && !rhsClone.Routing.OpCode().IsSingleShard() { + if !jm.joinType.IsInner() && !rhsClone.Routing.OpCode().IsSingleShard() { return nil } - return m.merge(ctx, lhsRoute, rhsClone, rhsClone.Routing) + return jm.merge(ctx, lhsRoute, rhsClone, rhsClone.Routing) + + // If a dual is on the right side. case b == dual: - // If a dual is on the right side. - return m.merge(ctx, lhsRoute, rhsRoute, routingA) + return jm.merge(ctx, lhsRoute, rhsRoute, routingA) + + // As both are reference route. We need to merge the alternates as well. + case a == anyShard && b == anyShard && sameKeyspace: + newrouting := mergeAnyShardRoutings(ctx, routingA.(*AnyShardRouting), routingB.(*AnyShardRouting), joinPredicates, jm.joinType) + return jm.merge(ctx, lhsRoute, rhsRoute, newrouting) // an unsharded/reference route can be merged with anything going to that keyspace case a == anyShard && sameKeyspace: - return m.merge(ctx, lhsRoute, rhsRoute, routingB) + return jm.merge(ctx, lhsRoute, rhsRoute, routingB) case b == anyShard && sameKeyspace: - return m.merge(ctx, lhsRoute, rhsRoute, routingA) + return jm.merge(ctx, lhsRoute, rhsRoute, routingA) // None routing can always be merged, as long as we are aiming for the same keyspace case a == none && sameKeyspace: - return m.merge(ctx, lhsRoute, rhsRoute, routingA) + return jm.merge(ctx, lhsRoute, rhsRoute, routingA) case b == none && sameKeyspace: - return m.merge(ctx, lhsRoute, rhsRoute, routingB) + return jm.merge(ctx, lhsRoute, rhsRoute, routingB) // infoSchema routing is complex, so we handle it in a separate method case a == infoSchema && b == infoSchema: - return tryMergeInfoSchemaRoutings(ctx, routingA, routingB, m, lhsRoute, rhsRoute) + return tryMergeInfoSchemaRoutings(ctx, routingA, routingB, jm, lhsRoute, rhsRoute) // sharded routing is complex, so we handle it in a separate method case a == sharded && b == sharded: - return tryMergeJoinShardedRouting(ctx, lhsRoute, rhsRoute, m, joinPredicates) + return tryMergeShardedRouting(ctx, lhsRoute, rhsRoute, jm, joinPredicates) default: return nil } } +func mergeAnyShardRoutings(ctx *plancontext.PlanningContext, a, b *AnyShardRouting, joinPredicates []sqlparser.Expr, joinType sqlparser.JoinType) *AnyShardRouting { + alternates := make(map[*vindexes.Keyspace]*Route) + for ak, av := range a.Alternates { + for bk, bv := range b.Alternates { + // only same keyspace alternates can be merged. + if ak != bk { + continue + } + op, _ := mergeOrJoin(ctx, av, bv, joinPredicates, joinType) + if r, ok := op.(*Route); ok { + alternates[ak] = r + } + } + } + return &AnyShardRouting{ + keyspace: a.keyspace, + Alternates: alternates, + } +} + func prepareInputRoutes(lhs Operator, rhs Operator) (*Route, *Route, Routing, Routing, routingType, routingType, bool) { lhsRoute, rhsRoute := operatorsToRoutes(lhs, rhs) if lhsRoute == nil || rhsRoute == nil { @@ -85,7 +111,6 @@ func prepareInputRoutes(lhs Operator, rhs Operator) (*Route, *Route, Routing, Ro lhsRoute, rhsRoute, routingA, routingB, sameKeyspace := getRoutesOrAlternates(lhsRoute, rhsRoute) a, b := getRoutingType(routingA), getRoutingType(routingB) - return lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace } @@ -161,10 +186,6 @@ func getRoutesOrAlternates(lhsRoute, rhsRoute *Route) (*Route, *Route, Routing, return lhsRoute, rhsRoute, routingA, routingB, sameKeyspace } -func getTypeName(myvar interface{}) string { - return reflect.TypeOf(myvar).String() -} - func getRoutingType(r Routing) routingType { switch r.(type) { case *InfoSchemaRouting: diff --git a/go/vt/vtgate/planbuilder/operators/joins.go b/go/vt/vtgate/planbuilder/operators/joins.go index 86cdf06fe7e..fb740fd1920 100644 --- a/go/vt/vtgate/planbuilder/operators/joins.go +++ b/go/vt/vtgate/planbuilder/operators/joins.go @@ -17,7 +17,10 @@ limitations under the License. package operators import ( + "fmt" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" "vitess.io/vitess/go/vt/vtgate/semantics" ) @@ -86,7 +89,7 @@ func AddPredicate( return join } - return nil + panic(vterrors.VT13001(fmt.Sprintf("pushed wrong predicate to the join: %s", sqlparser.String(expr)))) } // we are looking for predicates like `tbl.col = <>` or `<> = tbl.col`, diff --git a/go/vt/vtgate/planbuilder/operators/mirror.go b/go/vt/vtgate/planbuilder/operators/mirror.go new file mode 100644 index 00000000000..3ab1d66e70d --- /dev/null +++ b/go/vt/vtgate/planbuilder/operators/mirror.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 operators + +import ( + "fmt" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" +) + +type ( + PercentBasedMirror struct { + Percent float32 + Operator Operator + Target Operator + } +) + +var _ Operator = (*PercentBasedMirror)(nil) + +func NewPercentBasedMirror(percent float32, operator, target Operator) *PercentBasedMirror { + return &PercentBasedMirror{ + percent, + operator, + target, + } +} + +// Clone will return a copy of this operator, protected so changed to the original will not impact the clone +func (m *PercentBasedMirror) Clone(inputs []Operator) Operator { + cloneMirror := *m + cloneMirror.SetInputs(inputs) + return &cloneMirror +} + +// Inputs returns the inputs for this operator +func (m *PercentBasedMirror) Inputs() []Operator { + return []Operator{ + m.Operator, + m.Target, + } +} + +// SetInputs changes the inputs for this op +func (m *PercentBasedMirror) SetInputs(inputs []Operator) { + if len(inputs) < 2 { + panic(vterrors.VT13001("unexpected number of inputs for PercentBasedMirror operator")) + } + m.Operator = inputs[0] + m.Target = inputs[1] +} + +// AddPredicate is used to push predicates. It pushed it as far down as is possible in the tree. +// If we encounter a join and the predicate depends on both sides of the join, the predicate will be split into two parts, +// where data is fetched from the LHS of the join to be used in the evaluation on the RHS +// TODO: we should remove this and replace it with rewriters +func (m *PercentBasedMirror) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) Operator { + panic(vterrors.VT13001("not supported")) +} + +func (m *PercentBasedMirror) AddColumn(ctx *plancontext.PlanningContext, reuseExisting bool, addToGroupBy bool, expr *sqlparser.AliasedExpr) int { + panic(vterrors.VT13001("not supported")) +} + +func (m *PercentBasedMirror) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) int { + return m.Operator.FindCol(ctx, expr, underRoute) +} + +func (m *PercentBasedMirror) GetColumns(ctx *plancontext.PlanningContext) []*sqlparser.AliasedExpr { + return m.Operator.GetColumns(ctx) +} + +func (m *PercentBasedMirror) GetSelectExprs(ctx *plancontext.PlanningContext) sqlparser.SelectExprs { + return m.Operator.GetSelectExprs(ctx) +} + +func (m *PercentBasedMirror) ShortDescription() string { + return fmt.Sprintf("PercentBasedMirror (%.02f%%)", m.Percent) +} + +func (m *PercentBasedMirror) GetOrdering(ctx *plancontext.PlanningContext) []OrderBy { + return m.Operator.GetOrdering(ctx) +} + +// AddWSColumn implements Operator. +func (m *PercentBasedMirror) AddWSColumn(ctx *plancontext.PlanningContext, offset int, underRoute bool) int { + panic(vterrors.VT13001("not supported")) +} diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index 7a9cedccb89..adf71a47f24 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -25,20 +25,19 @@ import ( "vitess.io/vitess/go/vt/vtgate/semantics" ) +type offsettable interface { + Operator + planOffsets(ctx *plancontext.PlanningContext) Operator +} + // planOffsets will walk the tree top down, adding offset information to columns in the tree for use in further optimization, func planOffsets(ctx *plancontext.PlanningContext, root Operator) Operator { - type offsettable interface { - Operator - planOffsets(ctx *plancontext.PlanningContext) Operator - } - visitor := func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { switch op := in.(type) { case *Horizon: panic(vterrors.VT13001(fmt.Sprintf("should not see %T here", in))) case offsettable: newOp := op.planOffsets(ctx) - if newOp == nil { newOp = op } @@ -47,7 +46,13 @@ func planOffsets(ctx *plancontext.PlanningContext, root Operator) Operator { fmt.Println("Planned offsets for:") fmt.Println(ToTree(newOp)) } - return newOp, nil + + if newOp == op { + return newOp, nil + } else { + // We got a new operator from plan offsets. We should return that something has changed. + return newOp, Rewrote("planning offsets introduced a new operator") + } } return in, NoRewrite } @@ -115,50 +120,6 @@ func findAggregatorInSource(op Operator) *Aggregator { } } -// 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 { - - addColumnsNeededByFilter := func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { - addedCols := false - filter, ok := in.(*Filter) - if !ok { - return in, NoRewrite - } - - var neededAggrs []sqlparser.Expr - extractAggrs := func(cursor *sqlparser.CopyOnWriteCursor) { - node := cursor.Node() - if ctx.IsAggr(node) { - neededAggrs = append(neededAggrs, node.(sqlparser.Expr)) - } - } - - for _, expr := range filter.Predicates { - _ = sqlparser.CopyOnRewrite(expr, dontEnterSubqueries, extractAggrs, nil) - } - - if neededAggrs == nil { - return in, NoRewrite - } - - aggregator := findAggregatorInSource(filter.Source) - for _, aggr := range neededAggrs { - if aggregator.FindCol(ctx, aggr, false) == -1 { - aggregator.addColumnWithoutPushing(ctx, aeWrap(aggr), false) - addedCols = true - } - } - - if addedCols { - return in, Rewrote("added columns because filter needs it") - } - return in, NoRewrite - } - - return TopDown(root, TableID, addColumnsNeededByFilter, stopAtRoute) -} - // isolateDistinctFromUnion will pull out the distinct from a union operator func isolateDistinctFromUnion(_ *plancontext.PlanningContext, root Operator) Operator { visitor := func(in Operator, _ semantics.TableSet, isRoot bool) (Operator, *ApplyResult) { diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index f1a38974c93..76797aee906 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -54,7 +54,8 @@ type ( // Inputs returns the inputs for this operator Inputs() []Operator - // SetInputs changes the inputs for this op + // SetInputs changes the inputs for this op. + // We don't need to check the size of the inputs, as the planner will ensure that the inputs are correct SetInputs([]Operator) // AddPredicate is used to push predicates. It pushed it as far down as is possible in the tree. diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index 94c4f3dd846..c8f4ccdf853 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -82,17 +82,25 @@ func (o *Ordering) GetOrdering(*plancontext.PlanningContext) []OrderBy { } func (o *Ordering) planOffsets(ctx *plancontext.PlanningContext) Operator { + var weightStrings []*OrderBy + for _, order := range o.Order { offset := o.Source.AddColumn(ctx, true, false, aeWrap(order.SimplifiedExpr)) o.Offset = append(o.Offset, offset) if !ctx.NeedsWeightString(order.SimplifiedExpr) { - o.WOffset = append(o.WOffset, -1) + weightStrings = append(weightStrings, nil) continue } + weightStrings = append(weightStrings, &order) + } - wsExpr := &sqlparser.WeightStringFuncExpr{Expr: order.SimplifiedExpr} - offset = o.Source.AddColumn(ctx, true, false, aeWrap(wsExpr)) + for i, order := range weightStrings { + if order == nil { + o.WOffset = append(o.WOffset, -1) + continue + } + offset := o.Source.AddWSColumn(ctx, o.Offset[i], false) o.WOffset = append(o.WOffset, offset) } return nil diff --git a/go/vt/vtgate/planbuilder/operators/phases.go b/go/vt/vtgate/planbuilder/operators/phases.go index 9f2178bae05..d5354e9548f 100644 --- a/go/vt/vtgate/planbuilder/operators/phases.go +++ b/go/vt/vtgate/planbuilder/operators/phases.go @@ -36,6 +36,7 @@ const ( initialPlanning pullDistinctFromUnion delegateAggregation + recursiveCTEHorizons addAggrOrdering cleanOutPerfDistinct dmlWithInput @@ -53,6 +54,8 @@ func (p Phase) String() string { return "pull distinct from UNION" case delegateAggregation: return "split aggregation between vtgate and mysql" + case recursiveCTEHorizons: + return "expand recursive CTE horizons" case addAggrOrdering: return "optimize aggregations with ORDER BY" case cleanOutPerfDistinct: @@ -72,6 +75,8 @@ func (p Phase) shouldRun(s semantics.QuerySignature) bool { return s.Union case delegateAggregation: return s.Aggregation + case recursiveCTEHorizons: + return s.RecursiveCTE case addAggrOrdering: return s.Aggregation case cleanOutPerfDistinct: @@ -93,6 +98,8 @@ func (p Phase) act(ctx *plancontext.PlanningContext, op Operator) Operator { return enableDelegateAggregation(ctx, op) case addAggrOrdering: return addOrderingForAllAggregations(ctx, op) + case recursiveCTEHorizons: + return planRecursiveCTEHorizons(ctx, op) case cleanOutPerfDistinct: return removePerformanceDistinctAboveRoute(ctx, op) case subquerySettling: @@ -207,7 +214,7 @@ func removePerformanceDistinctAboveRoute(_ *plancontext.PlanningContext, op Oper } func enableDelegateAggregation(ctx *plancontext.PlanningContext, op Operator) Operator { - return addColumnsToInput(ctx, op) + return prepareForAggregationPushing(ctx, op) } // addOrderingForAllAggregations is run we have pushed down Aggregators as far down as possible. @@ -290,10 +297,101 @@ func addLiteralGroupingToRHS(in *ApplyJoin) (Operator, *ApplyResult) { return nil } if len(aggr.Grouping) == 0 { - gb := sqlparser.NewIntLiteral(".0") + gb := sqlparser.NewFloatLiteral(".0") aggr.Grouping = append(aggr.Grouping, NewGroupBy(gb)) } return nil }) return in, NoRewrite } + +// prepareForAggregationPushing 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 prepareForAggregationPushing(ctx *plancontext.PlanningContext, root Operator) Operator { + return TopDown(root, TableID, func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { + filter, ok := in.(*Filter) + if !ok { + return in, NoRewrite + } + + var neededAggrs []sqlparser.Expr + extractAggrs := func(cursor *sqlparser.CopyOnWriteCursor) { + node := cursor.Node() + if ctx.IsAggr(node) { + neededAggrs = append(neededAggrs, node.(sqlparser.Expr)) + } + } + + for _, expr := range filter.Predicates { + _ = sqlparser.CopyOnRewrite(expr, dontEnterSubqueries, extractAggrs, nil) + } + + if neededAggrs == nil { + return in, NoRewrite + } + + addedCols := false + aggregator := findAggregatorInSource(filter.Source) + for _, aggr := range neededAggrs { + if aggregator.FindCol(ctx, aggr, false) == -1 { + aggregator.addColumnWithoutPushing(ctx, aeWrap(aggr), false) + addedCols = true + } + } + + if addedCols { + return in, Rewrote("added columns because filter needs it") + } + return in, NoRewrite + }, stopAtRoute) +} + +// prepareForAggregationPushing 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 planRecursiveCTEHorizons(ctx *plancontext.PlanningContext, root Operator) Operator { + return TopDown(root, TableID, func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { + // These recursive CTEs have not been pushed under a route, so we will have to evaluate it one the vtgate + // That means that we need to turn anything that is coming from the recursion into arguments + rcte, ok := in.(*RecurseCTE) + if !ok { + return in, NoRewrite + } + hz := rcte.Horizon + hz.Source = rcte.Term + newTerm, _ := expandHorizon(ctx, hz) + pr := findProjection(newTerm) + ap, err := pr.GetAliasedProjections() + if err != nil { + panic(vterrors.VT09015()) + } + + // We need to break the expressions into LHS and RHS, and store them in the CTE for later use + projections := slice.Map(ap, func(p *ProjExpr) *plancontext.RecurseExpression { + recurseExpression := breakCTEExpressionInLhsAndRhs(ctx, p.EvalExpr, rcte.LeftID) + p.EvalExpr = recurseExpression.RightExpr + return recurseExpression + }) + rcte.Projections = projections + rcte.Term = newTerm + return rcte, Rewrote("expanded horizon on term side of recursive CTE") + }, stopAtRoute) +} + +func findProjection(op Operator) *Projection { + for { + proj, ok := op.(*Projection) + if ok { + return proj + } + 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 projection")) + } + op = src + } +} diff --git a/go/vt/vtgate/planbuilder/operators/plan_query.go b/go/vt/vtgate/planbuilder/operators/plan_query.go index 4d371942c26..40c27d03126 100644 --- a/go/vt/vtgate/planbuilder/operators/plan_query.go +++ b/go/vt/vtgate/planbuilder/operators/plan_query.go @@ -60,7 +60,7 @@ type ( func PlanQuery(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (result Operator, err error) { defer PanicHandler(&err) - op := translateQueryToOp(ctx, stmt) + op := translateQueryToOpWithMirroring(ctx, stmt) if DebugOperatorTree { fmt.Println("Initial tree:") diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 527991cba26..95ebeadaeb7 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -87,7 +87,7 @@ type ( ProjExpr struct { Original *sqlparser.AliasedExpr // this is the expression the user asked for. should only be used to decide on the column alias - EvalExpr sqlparser.Expr // EvalExpr is the expression that will be evaluated at runtime + EvalExpr sqlparser.Expr // EvalExpr represents the expression evaluated at runtime or used when the ProjExpr is pushed under a route ColExpr sqlparser.Expr // ColExpr is used during planning to figure out which column this ProjExpr is representing Info ExprInfo // Here we store information about evalengine, offsets or subqueries } @@ -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 { @@ -392,8 +383,18 @@ func (p *Projection) addColumn( return p.addProjExpr(pe) } - // we need to push down this column to our input - inputOffset := p.Source.AddColumn(ctx, true, addToGroupBy, ae) + var inputOffset int + if nothingNeedsFetching(ctx, expr) { + // if we don't need to fetch anything, we could just evaluate it in the projection + // we still check if it's there - if it is, we can, we should use it + inputOffset = p.Source.FindCol(ctx, expr, false) + if inputOffset < 0 { + return p.addProjExpr(pe) + } + } else { + // we need to push down this column to our input + inputOffset = p.Source.AddColumn(ctx, true, addToGroupBy, ae) + } pe.Info = Offset(inputOffset) // since we already know the offset, let's save the information return p.addProjExpr(pe) diff --git a/go/vt/vtgate/planbuilder/operators/projection_pushing.go b/go/vt/vtgate/planbuilder/operators/projection_pushing.go index b5c6a10bb78..1d1a5a04501 100644 --- a/go/vt/vtgate/planbuilder/operators/projection_pushing.go +++ b/go/vt/vtgate/planbuilder/operators/projection_pushing.go @@ -320,7 +320,7 @@ func splitSubqueryExpression( alias string, ) applyJoinColumn { col := join.getJoinColumnFor(ctx, pe.Original, pe.ColExpr, false) - return pushDownSplitJoinCol(col, lhs, pe, alias, rhs) + return pushDownSplitJoinCol(col, lhs, rhs, pe, alias) } func splitUnexploredExpression( @@ -334,23 +334,49 @@ func splitUnexploredExpression( original := sqlparser.Clone(pe.Original) expr := pe.ColExpr - var colName *sqlparser.ColName - if dt != nil { - if !pe.isSameInAndOut(ctx) { - panic(vterrors.VT13001("derived table columns must be the same in and out")) - } - colName = sqlparser.NewColNameWithQualifier(pe.Original.ColumnName(), sqlparser.NewTableName(dt.Alias)) - ctx.SemTable.CopySemanticInfo(expr, colName) - } - // Get a applyJoinColumn for the current expression. col := join.getJoinColumnFor(ctx, original, expr, false) - col.DTColName = colName - return pushDownSplitJoinCol(col, lhs, pe, alias, rhs) + if dt == nil { + return pushDownSplitJoinCol(col, lhs, rhs, pe, alias) + } + + if !pe.isSameInAndOut(ctx) { + panic(vterrors.VT13001("derived table columns must be the same in and out")) + } + // we are pushing a derived projection through a join. that means that after this rewrite, we are on top of the + // derived table divider, and can only see the projected columns, not the underlying expressions + colName := sqlparser.NewColNameWithQualifier(pe.Original.ColumnName(), sqlparser.NewTableName(dt.Alias)) + ctx.SemTable.CopySemanticInfo(expr, colName) + col.Original = colName + if alias == "" { + alias = pe.Original.ColumnName() + } + + // Update the left and right child columns and names based on the applyJoinColumn type. + switch { + case col.IsPureLeft(): + lhs.add(pe, alias) + col.LHSExprs[0].Expr = colName + case col.IsPureRight(): + rhs.add(pe, alias) + col.RHSExpr = colName + default: + for _, lhsExpr := range col.LHSExprs { + ae := aeWrap(lhsExpr.Expr) + columnName := ae.ColumnName() + lhs.add(newProjExpr(ae), columnName) + } + innerPE := newProjExprWithInner(pe.Original, col.RHSExpr) + innerPE.ColExpr = col.RHSExpr + col.RHSExpr = colName + innerPE.Info = pe.Info + rhs.add(innerPE, alias) + } + return col } -func pushDownSplitJoinCol(col applyJoinColumn, lhs *projector, pe *ProjExpr, alias string, rhs *projector) applyJoinColumn { +func pushDownSplitJoinCol(col applyJoinColumn, lhs, rhs *projector, pe *ProjExpr, alias string) applyJoinColumn { // Update the left and right child columns and names based on the applyJoinColumn type. switch { case col.IsPureLeft(): diff --git a/go/vt/vtgate/planbuilder/operators/query_planning.go b/go/vt/vtgate/planbuilder/operators/query_planning.go index e88fb53edb3..f930a7f4f76 100644 --- a/go/vt/vtgate/planbuilder/operators/query_planning.go +++ b/go/vt/vtgate/planbuilder/operators/query_planning.go @@ -102,11 +102,21 @@ func runRewriters(ctx *plancontext.PlanningContext, root Operator) Operator { return tryPushDelete(in) case *Update: return tryPushUpdate(in) + case *RecurseCTE: + return tryMergeRecurse(ctx, in) + default: return in, NoRewrite } } + if pbm, ok := root.(*PercentBasedMirror); ok { + pbm.SetInputs([]Operator{ + runRewriters(ctx, pbm.Operator), + runRewriters(ctx.UseMirror(), pbm.Target), + }) + } + return FixedPointBottomUp(root, TableID, visitor, stopAtRoute) } @@ -733,7 +743,6 @@ func pushFilterUnderProjection(ctx *plancontext.PlanningContext, filter *Filter, } } return Swap(filter, projection, "push filter under projection") - } func tryPushDistinct(in *Distinct) (Operator, *ApplyResult) { diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index 8ad8a6efe1e..a245831ca13 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -68,7 +68,7 @@ type ( // Aggr encodes all information needed for aggregation functions Aggr struct { 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 is used + 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 the opcode while pushing them down @@ -664,6 +664,24 @@ 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 ctx.IsAggr(node) { diff --git a/go/vt/vtgate/planbuilder/operators/recurse_cte.go b/go/vt/vtgate/planbuilder/operators/recurse_cte.go new file mode 100644 index 00000000000..ebb7dc54765 --- /dev/null +++ b/go/vt/vtgate/planbuilder/operators/recurse_cte.go @@ -0,0 +1,214 @@ +/* +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 operators + +import ( + "fmt" + "slices" + "strings" + + "golang.org/x/exp/maps" + + "vitess.io/vitess/go/slice" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "vitess.io/vitess/go/vt/vtgate/semantics" +) + +// RecurseCTE is used to represent a recursive CTE +type RecurseCTE struct { + Seed, // used to describe the non-recursive part that initializes the result set + Term Operator // the part that repeatedly applies the recursion, processing the result set + + // Def is the CTE definition according to the semantics + Def *semantics.CTE + + // Expressions are the predicates that are needed on the recurse side of the CTE + Predicates []*plancontext.RecurseExpression + Projections []*plancontext.RecurseExpression + + // Vars is the map of variables that are sent between the two parts of the recursive CTE + // It's filled in at offset planning time + Vars map[string]int + + // MyTableID is the id of the CTE + MyTableInfo *semantics.CTETable + + // Horizon is stored here until we either expand it or push it under a route + Horizon *Horizon + + // The LeftID is the id of the left side of the CTE + LeftID, + + // The OuterID is the id for this use of the CTE + OuterID semantics.TableSet + + // Distinct is used to determine if the result set should be distinct + Distinct bool +} + +var _ Operator = (*RecurseCTE)(nil) + +func newRecurse( + ctx *plancontext.PlanningContext, + def *semantics.CTE, + seed, term Operator, + predicates []*plancontext.RecurseExpression, + horizon *Horizon, + leftID, outerID semantics.TableSet, + distinct bool, +) *RecurseCTE { + for _, pred := range predicates { + ctx.AddJoinPredicates(pred.Original, pred.RightExpr) + } + return &RecurseCTE{ + Def: def, + Seed: seed, + Term: term, + Predicates: predicates, + Horizon: horizon, + LeftID: leftID, + OuterID: outerID, + Distinct: distinct, + } +} + +func (r *RecurseCTE) Clone(inputs []Operator) Operator { + klone := *r + klone.Seed = inputs[0] + klone.Term = inputs[1] + klone.Vars = maps.Clone(r.Vars) + klone.Predicates = slices.Clone(r.Predicates) + klone.Projections = slices.Clone(r.Projections) + return &klone +} + +func (r *RecurseCTE) Inputs() []Operator { + return []Operator{r.Seed, r.Term} +} + +func (r *RecurseCTE) SetInputs(operators []Operator) { + r.Seed = operators[0] + r.Term = operators[1] +} + +func (r *RecurseCTE) AddPredicate(_ *plancontext.PlanningContext, e sqlparser.Expr) Operator { + return newFilter(r, e) +} + +func (r *RecurseCTE) AddColumn(ctx *plancontext.PlanningContext, _, _ bool, expr *sqlparser.AliasedExpr) int { + r.makeSureWeHaveTableInfo(ctx) + e := semantics.RewriteDerivedTableExpression(expr.Expr, r.MyTableInfo) + offset := r.Seed.FindCol(ctx, e, false) + if offset == -1 { + panic(vterrors.VT13001("CTE column not found")) + } + return offset +} + +func (r *RecurseCTE) makeSureWeHaveTableInfo(ctx *plancontext.PlanningContext) { + if r.MyTableInfo == nil { + for _, table := range ctx.SemTable.Tables { + cte, ok := table.(*semantics.CTETable) + if !ok { + continue + } + if cte.CTE == r.Def { + r.MyTableInfo = cte + break + } + } + if r.MyTableInfo == nil { + panic(vterrors.VT13001("CTE not found")) + } + } +} + +func (r *RecurseCTE) AddWSColumn(ctx *plancontext.PlanningContext, offset int, underRoute bool) int { + seed := r.Seed.AddWSColumn(ctx, offset, underRoute) + term := r.Term.AddWSColumn(ctx, offset, underRoute) + if seed != term { + panic(vterrors.VT13001("CTE columns don't match")) + } + return seed +} + +func (r *RecurseCTE) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) int { + r.makeSureWeHaveTableInfo(ctx) + expr = semantics.RewriteDerivedTableExpression(expr, r.MyTableInfo) + return r.Seed.FindCol(ctx, expr, underRoute) +} + +func (r *RecurseCTE) GetColumns(ctx *plancontext.PlanningContext) []*sqlparser.AliasedExpr { + return r.Seed.GetColumns(ctx) +} + +func (r *RecurseCTE) GetSelectExprs(ctx *plancontext.PlanningContext) sqlparser.SelectExprs { + return r.Seed.GetSelectExprs(ctx) +} + +func (r *RecurseCTE) ShortDescription() string { + distinct := "" + if r.Distinct { + distinct = "distinct " + } + if len(r.Vars) > 0 { + return fmt.Sprintf("%s%v", distinct, r.Vars) + } + expressions := slice.Map(r.expressions(), func(expr *plancontext.RecurseExpression) string { + return sqlparser.String(expr.Original) + }) + return fmt.Sprintf("%s%v %v", distinct, r.Def.Name, strings.Join(expressions, ", ")) +} + +func (r *RecurseCTE) GetOrdering(*plancontext.PlanningContext) []OrderBy { + // RecurseCTE is a special case. It never guarantees any ordering. + return nil +} + +func (r *RecurseCTE) expressions() []*plancontext.RecurseExpression { + return append(r.Predicates, r.Projections...) +} + +func (r *RecurseCTE) planOffsets(ctx *plancontext.PlanningContext) Operator { + r.Vars = make(map[string]int) + columns := r.Seed.GetColumns(ctx) + for _, expr := range r.expressions() { + outer: + for _, lhsExpr := range expr.LeftExprs { + _, found := r.Vars[lhsExpr.Name] + if found { + continue + } + + for offset, column := range columns { + if lhsExpr.Expr.Name.EqualString(column.ColumnName()) { + r.Vars[lhsExpr.Name] = offset + continue outer + } + } + + panic(vterrors.VT13001("couldn't find column")) + } + } + return r +} + +func (r *RecurseCTE) introducesTableID() semantics.TableSet { + return r.OuterID +} diff --git a/go/vt/vtgate/planbuilder/operators/rewriters.go b/go/vt/vtgate/planbuilder/operators/rewriters.go index ab9fe66e368..a5743e001e1 100644 --- a/go/vt/vtgate/planbuilder/operators/rewriters.go +++ b/go/vt/vtgate/planbuilder/operators/rewriters.go @@ -227,7 +227,7 @@ func bottomUp( } if anythingChanged.Changed() { - root = root.Clone(newInputs) + root.SetInputs(newInputs) } newOp, treeIdentity := rewriter(root, rootID, isRoot) @@ -257,11 +257,7 @@ func breakableTopDown( } } - if anythingChanged.Changed() { - return newOp, NoRewrite, nil - } - - return newOp.Clone(newInputs), anythingChanged, nil + return newOp, anythingChanged, nil } // topDown is a helper function that recursively traverses the operator tree from the @@ -301,7 +297,8 @@ func topDown( } if anythingChanged != NoRewrite { - return root.Clone(newInputs), anythingChanged + root.SetInputs(newInputs) + return root, anythingChanged } return root, NoRewrite diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index 62d6aad6a97..25e3f610a04 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -19,12 +19,10 @@ package operators import ( "fmt" - "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/key" topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/evalengine" @@ -121,7 +119,7 @@ func UpdateRoutingLogic(ctx *plancontext.PlanningContext, expr sqlparser.Expr, r } nr := &NoneRouting{keyspace: ks} - if isConstantFalse(ctx.VSchema.Environment(), expr, ctx.VSchema.ConnCollation()) { + if isConstantFalse(ctx, expr) { return nr } @@ -165,11 +163,19 @@ func UpdateRoutingLogic(ctx *plancontext.PlanningContext, expr sqlparser.Expr, r // isConstantFalse checks whether this predicate can be evaluated at plan-time. If it returns `false` or `null`, // we know that the query will not return anything, and this can be used to produce better plans -func isConstantFalse(env *vtenv.Environment, expr sqlparser.Expr, collation collations.ID) bool { +func isConstantFalse(ctx *plancontext.PlanningContext, expr sqlparser.Expr) bool { + if !ctx.SemTable.RecursiveDeps(expr).IsEmpty() { + // we have column dependencies, so we can be pretty sure + // we won't be able to use the evalengine to check if this is constant false + return false + } + env := ctx.VSchema.Environment() + collation := ctx.VSchema.ConnCollation() eenv := evalengine.EmptyExpressionEnv(env) eexpr, err := evalengine.Translate(expr, &evalengine.Config{ - Collation: collation, - Environment: env, + Collation: collation, + Environment: env, + NoCompilation: true, }) if err != nil { return false @@ -587,96 +593,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 +688,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 +711,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) { diff --git a/go/vt/vtgate/planbuilder/operators/route_planning.go b/go/vt/vtgate/planbuilder/operators/route_planning.go index 47405e3b935..6a242649725 100644 --- a/go/vt/vtgate/planbuilder/operators/route_planning.go +++ b/go/vt/vtgate/planbuilder/operators/route_planning.go @@ -288,7 +288,8 @@ func requiresSwitchingSides(ctx *plancontext.PlanningContext, op Operator) (requ } func mergeOrJoin(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPredicates []sqlparser.Expr, joinType sqlparser.JoinType) (Operator, *ApplyResult) { - newPlan := mergeJoinInputs(ctx, lhs, rhs, joinPredicates, newJoinMerge(joinPredicates, joinType)) + jm := newJoinMerge(joinPredicates, joinType) + newPlan := jm.mergeJoinInputs(ctx, lhs, rhs, joinPredicates) if newPlan != nil { return newPlan, Rewrote("merge routes into single operator") } @@ -305,13 +306,18 @@ func mergeOrJoin(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPredic } join := NewApplyJoin(ctx, Clone(rhs), Clone(lhs), nil, joinType) - newOp := pushJoinPredicates(ctx, joinPredicates, join) - return newOp, Rewrote("logical join to applyJoin, switching side because LIMIT") + for _, pred := range joinPredicates { + join.AddJoinPredicate(ctx, pred) + } + return join, Rewrote("logical join to applyJoin, switching side because LIMIT") } join := NewApplyJoin(ctx, Clone(lhs), Clone(rhs), nil, joinType) - newOp := pushJoinPredicates(ctx, joinPredicates, join) - return newOp, Rewrote("logical join to applyJoin ") + for _, pred := range joinPredicates { + join.AddJoinPredicate(ctx, pred) + } + + return join, Rewrote("logical join to applyJoin ") } func operatorsToRoutes(a, b Operator) (*Route, *Route) { @@ -530,15 +536,3 @@ func hexEqual(a, b *sqlparser.Literal) bool { } return false } - -func pushJoinPredicates(ctx *plancontext.PlanningContext, exprs []sqlparser.Expr, op *ApplyJoin) Operator { - if len(exprs) == 0 { - return op - } - - for _, expr := range exprs { - AddPredicate(ctx, op, expr, true, newFilterSinglePredicate) - } - - return op -} diff --git a/go/vt/vtgate/planbuilder/operators/sharded_routing.go b/go/vt/vtgate/planbuilder/operators/sharded_routing.go index 1319b76f040..066cb47d9a9 100644 --- a/go/vt/vtgate/planbuilder/operators/sharded_routing.go +++ b/go/vt/vtgate/planbuilder/operators/sharded_routing.go @@ -23,7 +23,6 @@ import ( "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/evalengine" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" @@ -634,13 +633,15 @@ func (tr *ShardedRouting) extraInfo() string { ) } -func tryMergeJoinShardedRouting( +func tryMergeShardedRouting( ctx *plancontext.PlanningContext, routeA, routeB *Route, m merger, joinPredicates []sqlparser.Expr, ) *Route { - sameKeyspace := routeA.Routing.Keyspace() == routeB.Routing.Keyspace() + if routeA.Routing.Keyspace() != routeB.Routing.Keyspace() { + return nil + } tblA := routeA.Routing.(*ShardedRouting) tblB := routeB.Routing.(*ShardedRouting) @@ -669,10 +670,6 @@ func tryMergeJoinShardedRouting( return nil } - if !sameKeyspace { - panic(vterrors.VT12001("cross-shard correlated subquery")) - } - canMerge := canMergeOnFilters(ctx, routeA, routeB, joinPredicates) if !canMerge { return nil diff --git a/go/vt/vtgate/planbuilder/operators/subquery.go b/go/vt/vtgate/planbuilder/operators/subquery.go index 5ae0fb52e7f..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) diff --git a/go/vt/vtgate/planbuilder/operators/subquery_planning.go b/go/vt/vtgate/planbuilder/operators/subquery_planning.go index aef54bd8c41..0893afbeead 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_planning.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_planning.go @@ -758,7 +758,7 @@ func mergeSubqueryInputs(ctx *plancontext.PlanningContext, in, out Operator, joi // sharded routing is complex, so we handle it in a separate method case inner == sharded && outer == sharded: - return tryMergeJoinShardedRouting(ctx, inRoute, outRoute, m, joinPredicates) + return tryMergeShardedRouting(ctx, inRoute, outRoute, m, joinPredicates) default: return nil diff --git a/go/vt/vtgate/planbuilder/operators/update.go b/go/vt/vtgate/planbuilder/operators/update.go index e843155246c..b4f0a37914e 100644 --- a/go/vt/vtgate/planbuilder/operators/update.go +++ b/go/vt/vtgate/planbuilder/operators/update.go @@ -66,9 +66,6 @@ func (u *Update) Inputs() []Operator { } func (u *Update) SetInputs(inputs []Operator) { - if len(inputs) != 1 { - panic(vterrors.VT13001("unexpected number of inputs for Update operator")) - } u.Source = inputs[0] } @@ -388,7 +385,6 @@ func createUpdateOperator(ctx *plancontext.PlanningContext, updStmt *sqlparser.U Ignore: updStmt.Ignore, Target: targetTbl, OwnedVindexQuery: ovq, - Source: op, }, Assignments: assignments, ChangedVindexValues: cvv, @@ -397,7 +393,9 @@ func createUpdateOperator(ctx *plancontext.PlanningContext, updStmt *sqlparser.U } if len(updStmt.OrderBy) > 0 { - addOrdering(ctx, updStmt.OrderBy, updOp) + updOp.Source = addOrdering(ctx, op, updStmt.OrderBy) + } else { + updOp.Source = op } if updStmt.Limit != nil { diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index f49994d37b2..79536483970 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -591,6 +591,32 @@ func (s *planTestSuite) TestOtherPlanningFromFile() { s.testFile("other_admin_cases.json", vschema, false) } +func (s *planTestSuite) TestMirrorPlanning() { + vschema := &vschemawrapper.VSchemaWrapper{ + V: loadSchema(s.T(), "vschemas/mirror_schema.json", true), + TabletType_: topodatapb.TabletType_PRIMARY, + SysVarEnabled: true, + TestBuilder: TestBuilder, + Env: vtenv.NewTestEnv(), + } + + s.testFile("mirror_cases.json", vschema, false) +} + +func (s *planTestSuite) TestOneMirror() { + reset := operators.EnableDebugPrinting() + defer reset() + vschema := &vschemawrapper.VSchemaWrapper{ + V: loadSchema(s.T(), "vschemas/mirror_schema.json", true), + TabletType_: topodatapb.TabletType_PRIMARY, + SysVarEnabled: true, + TestBuilder: TestBuilder, + Env: vtenv.NewTestEnv(), + } + + s.testFile("onecase.json", vschema, false) +} + func loadSchema(t testing.TB, filename string, setCollation bool) *vindexes.VSchema { formal, err := vindexes.LoadFormal(locateFile(filename)) require.NoError(t, err) @@ -683,7 +709,7 @@ func (s *planTestSuite) testFile(filename string, vschema *vschemawrapper.VSchem if tcase.Skip { t.Skip(message) } else { - t.Errorf(message) + t.Error(message) } } else if tcase.Skip { t.Errorf("query is correct even though it is skipped:\n %s", tcase.Query) @@ -839,6 +865,35 @@ func BenchmarkSelectVsDML(b *testing.B) { }) } +func BenchmarkBaselineVsMirrored(b *testing.B) { + baseline := loadSchema(b, "vschemas/mirror_schema.json", true) + baseline.MirrorRules = map[string]*vindexes.MirrorRule{} + baselineVschema := &vschemawrapper.VSchemaWrapper{ + V: baseline, + SysVarEnabled: true, + Version: Gen4, + Env: vtenv.NewTestEnv(), + } + + mirroredSchema := loadSchema(b, "vschemas/mirror_schema.json", true) + mirroredVschema := &vschemawrapper.VSchemaWrapper{ + V: mirroredSchema, + SysVarEnabled: true, + Version: Gen4, + Env: vtenv.NewTestEnv(), + } + + cases := readJSONTests("mirror_cases.json") + + b.Run("Baseline", func(b *testing.B) { + benchmarkPlanner(b, Gen4, cases, baselineVschema) + }) + + b.Run("Mirrored", func(b *testing.B) { + benchmarkPlanner(b, Gen4, cases, mirroredVschema) + }) +} + func benchmarkPlanner(b *testing.B, version plancontext.PlannerVersion, testCases []planTest, vschema *vschemawrapper.VSchemaWrapper) { b.ReportAllocs() for n := 0; n < b.N; n++ { diff --git a/go/vt/vtgate/planbuilder/plancontext/planning_context.go b/go/vt/vtgate/planbuilder/plancontext/planning_context.go index 58be17febab..66be6a4c71d 100644 --- a/go/vt/vtgate/planbuilder/plancontext/planning_context.go +++ b/go/vt/vtgate/planbuilder/plancontext/planning_context.go @@ -66,6 +66,16 @@ type PlanningContext struct { // OuterTables contains the tables that are outer to the current query // Used to set the nullable flag on the columns OuterTables semantics.TableSet + + // This is a stack of CTEs being built. It's used when we have CTEs inside CTEs, + // to remember which is the CTE currently being assembled + CurrentCTE []*ContextCTE + + // mirror contains a mirrored clone of this planning context. + mirror *PlanningContext + + // isMirrored indicates that mirrored tables should be used. + isMirrored bool } // CreatePlanningContext initializes a new PlanningContext with the given parameters. @@ -376,3 +386,74 @@ func (ctx *PlanningContext) ContainsAggr(e sqlparser.SQLNode) (hasAggr bool) { }, e) return } + +func (ctx *PlanningContext) IsMirrored() bool { + return ctx.isMirrored +} + +type ContextCTE struct { + *semantics.CTE + Id semantics.TableSet + Predicates []*RecurseExpression +} + +type RecurseExpression struct { + Original sqlparser.Expr + RightExpr sqlparser.Expr + LeftExprs []BindVarExpr +} + +type BindVarExpr struct { + Name string + Expr *sqlparser.ColName +} + +func (ctx *PlanningContext) PushCTE(def *semantics.CTE, id semantics.TableSet) { + ctx.CurrentCTE = append(ctx.CurrentCTE, &ContextCTE{ + CTE: def, + Id: id, + }) +} + +func (ctx *PlanningContext) PopCTE() (*ContextCTE, error) { + if len(ctx.CurrentCTE) == 0 { + return nil, vterrors.VT13001("no CTE to pop") + } + activeCTE := ctx.CurrentCTE[len(ctx.CurrentCTE)-1] + ctx.CurrentCTE = ctx.CurrentCTE[:len(ctx.CurrentCTE)-1] + return activeCTE, nil +} + +func (ctx *PlanningContext) ActiveCTE() *ContextCTE { + if len(ctx.CurrentCTE) == 0 { + return nil + } + return ctx.CurrentCTE[len(ctx.CurrentCTE)-1] +} + +func (ctx *PlanningContext) UseMirror() *PlanningContext { + if ctx.isMirrored { + panic(vterrors.VT13001("cannot mirror already mirrored planning context")) + } + if ctx.mirror != nil { + return ctx.mirror + } + ctx.mirror = &PlanningContext{ + ctx.ReservedVars, + ctx.SemTable, + ctx.VSchema, + map[sqlparser.Expr][]sqlparser.Expr{}, + map[sqlparser.Expr]any{}, + ctx.PlannerVersion, + map[sqlparser.Expr]string{}, + ctx.VerifyAllFKs, + ctx.MergedSubqueries, + ctx.CurrentPhase, + ctx.Statement, + ctx.OuterTables, + ctx.CurrentCTE, + nil, + true, + } + return ctx.mirror +} diff --git a/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go b/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go index 3ab58cba724..d7315f376b6 100644 --- a/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go +++ b/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go @@ -365,4 +365,9 @@ func (v *vschema) GetAggregateUDFs() []string { panic("implement me") } +// FindMirrorRule implements VSchema. +func (v *vschema) FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) { + panic("unimplemented") +} + var _ VSchema = (*vschema)(nil) diff --git a/go/vt/vtgate/planbuilder/plancontext/vschema.go b/go/vt/vtgate/planbuilder/plancontext/vschema.go index 8ac4c57bfd7..6e92ad0d83b 100644 --- a/go/vt/vtgate/planbuilder/plancontext/vschema.go +++ b/go/vt/vtgate/planbuilder/plancontext/vschema.go @@ -96,6 +96,10 @@ type VSchema interface { // GetAggregateUDFs returns the list of aggregate UDFs. GetAggregateUDFs() []string + + // FindMirrorRule finds the mirror rule for the requested keyspace, table + // name, and the tablet type in the VSchema. + FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) } // PlannerNameToVersion returns the numerical representation of the planner diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 01dfd8aa387..9cc1c8efe06 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -205,7 +205,7 @@ func newBuildSelectPlan( return nil, nil, err } - if ks, _ := ctx.SemTable.SingleUnshardedKeyspace(); ks != nil { + if ks, ok := ctx.SemTable.CanTakeSelectUnshardedShortcut(); ok { plan, tablesUsed, err = selectUnshardedShortcut(ctx, selStmt, ks) if err != nil { return nil, nil, err @@ -214,7 +214,6 @@ func newBuildSelectPlan( return plan, tablesUsed, err } - // From this point on, we know it is not an unsharded query and return the NotUnshardedErr if there is any if ctx.SemTable.NotUnshardedErr != nil { return nil, nil, ctx.SemTable.NotUnshardedErr } @@ -242,11 +241,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..f5a5282ceab 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) case *sqlparser.ShowBasic: prim, err = buildShowBasicPlan(show, vschema) case *sqlparser.ShowCreate: @@ -67,6 +69,14 @@ func buildShowPlan(sql string, stmt *sqlparser.Show, _ *sqlparser.ReservedVars, return newPlanResult(prim), nil } +// buildShowTransactionStatusPlan builds the transaction status plan +func buildShowTransactionStatusPlan(show *sqlparser.ShowTransactionStatus) (engine.Primitive, error) { + return &engine.TransactionStatus{ + Keyspace: show.Keyspace, + 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 b124e8f2b50..343159bccaa 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -689,13 +689,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "1 ASC", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "count_distinct(1|3) AS k", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -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", @@ -2097,13 +2149,13 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) <= 10", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS a", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -2135,13 +2187,13 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 1.00", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(0) AS a", "GroupBy": "(1|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -2164,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", @@ -2818,16 +2918,16 @@ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2", + "JoinColumnIndexes": "L:0,L:1,L:3", "JoinVars": { - "u2_val2": 3 + "u2_val2": 2 }, "TableName": "`user`_`user`_music", "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,R:0", + "JoinColumnIndexes": "L:0,L:1,R:0,L:2", "JoinVars": { "u_val2": 1 }, @@ -2997,13 +3097,13 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 3", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS count(*)", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -3035,13 +3135,13 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "sum(foo) + sum(bar) = 42", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum(1) AS sum(foo), sum(2) AS sum(bar)", "GroupBy": "(0|3)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", @@ -3073,13 +3173,13 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "sum(`user`.foo) + sum(bar) = 42", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum(1) AS fooSum, sum(2) AS barSum", "GroupBy": "(0|3)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", @@ -3118,7 +3218,6 @@ "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS count(*)", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -3157,7 +3256,6 @@ "Variant": "Ordered", "Aggregates": "sum_count(1) AS count(u.`name`)", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Projection", @@ -3262,7 +3360,6 @@ "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS count(*)", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Projection", @@ -3521,8 +3618,10 @@ "Aggregates": "count_star(0) AS count(*)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "3", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Limit", @@ -3535,8 +3634,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select x.phone, x.id, x.city, 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", - "Query": "select x.phone, x.id, x.city, 1 from (select phone, id, city from `user` where id > 12) as x limit 10", + "FieldQuery": "select 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", + "Query": "select 1 from (select phone, id, city from `user` where id > 12) as x limit 10", "Table": "`user`" } ] @@ -3634,8 +3733,12 @@ "ResultColumns": 2, "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,2,3", + "OperatorType": "Projection", + "Expressions": [ + ":1 as val1", + "1 as 1", + ":2 as weight_string(val1)" + ], "Inputs": [ { "OperatorType": "Limit", @@ -3648,9 +3751,9 @@ "Name": "user", "Sharded": true }, - "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", + "FieldQuery": "select x.id, x.val1, weight_string(x.val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", + "OrderBy": "(1|2) ASC", + "Query": "select x.id, x.val1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by x.val1 asc limit 2", "Table": "`user`" } ] @@ -4012,7 +4115,6 @@ "Variant": "Ordered", "Aggregates": "max(1|3) AS bazo", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -4051,7 +4153,6 @@ "Variant": "Ordered", "Aggregates": "sum_count(1) AS bazo", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -4899,13 +5000,13 @@ "Collations": [ "0" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(0) AS count(*)", "GroupBy": "1", - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -5581,7 +5682,6 @@ "OperatorType": "Aggregate", "Variant": "Ordered", "GroupBy": "0, (1|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "SimpleProjection", @@ -5590,7 +5690,7 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "any_value(0) AS id, sum_count_star(1) AS a, any_value(2)", + "Aggregates": "any_value(0|2) AS id, sum_count_star(1) AS a", "Inputs": [ { "OperatorType": "Route", @@ -5599,9 +5699,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, count(*) as a, weight_string(id) from `user` where 1 != 1", - "OrderBy": "1 ASC, (0|2) ASC", - "Query": "select id, count(*) as a, weight_string(id) from `user` order by count(*) asc, id asc", + "FieldQuery": "select dt.c0 as id, dt.c1 as a, weight_string(dt.c0), weight_string(dt.c0) from (select id, count(*) as a from `user` where 1 != 1) as dt(c0, c1) where 1 != 1", + "OrderBy": "1 ASC, (0|3) ASC", + "Query": "select dt.c0 as id, dt.c1 as a, weight_string(dt.c0), weight_string(dt.c0) from (select id, count(*) as a from `user` order by count(*) asc, id asc) as dt(c0, c1)", "Table": "`user`" } ] @@ -5746,16 +5846,15 @@ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "group_concat(1) AS group_concat(u.bar), any_value(2) AS baz, any_value(4)", + "Aggregates": "group_concat(1) AS group_concat(u.bar), any_value(2|4) AS baz", "GroupBy": "(0|3)", - "ResultColumns": 5, "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,L:3,L:4", + "JoinColumnIndexes": "L:0,L:1,L:2,L:4,L:5", "JoinVars": { - "u_col": 5 + "u_col": 3 }, "TableName": "`user`_music", "Inputs": [ @@ -5766,9 +5865,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select u.foo, u.bar, u.baz, weight_string(u.foo), weight_string(u.baz), u.col from `user` as u where 1 != 1", - "OrderBy": "(0|3) ASC", - "Query": "select u.foo, u.bar, u.baz, weight_string(u.foo), weight_string(u.baz), u.col from `user` as u order by u.foo asc", + "FieldQuery": "select u.foo, u.bar, u.baz, u.col, weight_string(u.foo), weight_string(u.baz) from `user` as u where 1 != 1", + "OrderBy": "(0|4) ASC", + "Query": "select u.foo, u.bar, u.baz, u.col, weight_string(u.foo), weight_string(u.baz) from `user` as u order by u.foo asc", "Table": "`user`" }, { @@ -6004,18 +6103,19 @@ "Variant": "Ordered", "Aggregates": "count_star(0)", "GroupBy": "1", - "ResultColumns": 1, "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "2,1", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1", + "0 as .0" + ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "sum_count_star(0) AS count(*), any_value(2)", + "Aggregates": "sum_count_star(0) AS count(*)", "GroupBy": "1", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", @@ -6024,8 +6124,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*), .0, 1 from `user` where 1 != 1 group by .0", - "Query": "select count(*), .0, 1 from `user` group by .0", + "FieldQuery": "select count(*), .0 from `user` where 1 != 1 group by .0", + "Query": "select count(*), .0 from `user` group by .0", "Table": "`user`" } ] @@ -6189,7 +6289,6 @@ "Variant": "Ordered", "Aggregates": "sum(1) AS avg(id), sum_count(2) AS count(foo), sum_count(3) AS count(id)", "GroupBy": "(0|4)", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Route", @@ -6239,7 +6338,6 @@ "Variant": "Ordered", "Aggregates": "sum(1) AS avg(id), sum_count(2) AS count(foo), sum_count(3) AS count(id)", "GroupBy": "(0|4)", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Route", @@ -6423,7 +6521,6 @@ "OperatorType": "Aggregate", "Variant": "Scalar", "Aggregates": "min(0|2) AS min_id, max(1|3) AS max_id", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -6567,7 +6664,7 @@ "Variant": "HashLeftJoin", "Collation": "binary", "ComparisonType": "INT16", - "JoinColumnIndexes": "-1,1,-2,2,-3,3", + "JoinColumnIndexes": "-1,1,-2,2,-3,3,-3,4", "Predicate": "`user`.col = ue.col", "TableName": "`user`_user_extra", "Inputs": [ @@ -6587,16 +6684,20 @@ "Variant": "Ordered", "Aggregates": "count_star(0)", "GroupBy": "1, (2|3)", - "ResultColumns": 3, "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "2,0,1,3", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1", + ":0 as col", + ":1 as bar", + ":2 as weight_string(ue.bar)" + ], "Inputs": [ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "0 ASC, (1|3) ASC", + "OrderBy": "0 ASC, (1|2) ASC", "Inputs": [ { "OperatorType": "Limit", @@ -6609,8 +6710,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select ue.col, ue.bar, 1, weight_string(ue.bar) from (select col, bar from user_extra where 1 != 1) as ue where 1 != 1", - "Query": "select ue.col, ue.bar, 1, weight_string(ue.bar) from (select col, bar from user_extra) as ue limit 10", + "FieldQuery": "select ue.col, ue.bar, weight_string(ue.bar) from (select col, bar from user_extra where 1 != 1) as ue where 1 != 1", + "Query": "select ue.col, ue.bar, weight_string(ue.bar) from (select col, bar from user_extra) as ue limit 10", "Table": "user_extra" } ] @@ -7144,6 +7245,51 @@ ] } }, + { + "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": "Projection", + "Expressions": [ + "1 as 1" + ], + "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, 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|2) DESC", + "Query": "select subquery_for_count.one, subquery_for_count.id, 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", diff --git a/go/vt/vtgate/planbuilder/testdata/cte_cases.json b/go/vt/vtgate/planbuilder/testdata/cte_cases.json index 7b54bcb5a4a..b00dc0a060f 100644 --- a/go/vt/vtgate/planbuilder/testdata/cte_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/cte_cases.json @@ -223,8 +223,10 @@ "Aggregates": "count_star(0) AS count(*)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "3", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Limit", @@ -237,8 +239,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select x.phone, x.id, x.city, 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", - "Query": "select x.phone, x.id, x.city, 1 from (select phone, id, city from `user` where id > 12) as x limit 10", + "FieldQuery": "select 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", + "Query": "select 1 from (select phone, id, city from `user` where id > 12) as x limit 10", "Table": "`user`" } ] @@ -336,8 +338,12 @@ "ResultColumns": 2, "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,2,3", + "OperatorType": "Projection", + "Expressions": [ + ":1 as val1", + "1 as 1", + ":2 as weight_string(val1)" + ], "Inputs": [ { "OperatorType": "Limit", @@ -350,9 +356,9 @@ "Name": "user", "Sharded": true }, - "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", + "FieldQuery": "select x.id, x.val1, weight_string(x.val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", + "OrderBy": "(1|2) ASC", + "Query": "select x.id, x.val1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by x.val1 asc limit 2", "Table": "`user`" } ] @@ -479,7 +485,6 @@ "Variant": "Ordered", "Aggregates": "max(1|3) AS bazo", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -518,7 +523,6 @@ "Variant": "Ordered", "Aggregates": "sum_count(1) AS bazo", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -565,7 +569,6 @@ "OperatorType": "Aggregate", "Variant": "Ordered", "GroupBy": "0, (1|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "SimpleProjection", @@ -574,7 +577,7 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "any_value(0) AS id, sum_count_star(1) AS a, any_value(2)", + "Aggregates": "any_value(0|2) AS id, sum_count_star(1) AS a", "Inputs": [ { "OperatorType": "Route", @@ -583,9 +586,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, count(*) as a, weight_string(id) from `user` where 1 != 1", - "OrderBy": "1 ASC, (0|2) ASC", - "Query": "select id, count(*) as a, weight_string(id) from `user` order by count(*) asc, id asc", + "FieldQuery": "select dt.c0 as id, dt.c1 as a, weight_string(dt.c0), weight_string(dt.c0) from (select id, count(*) as a from `user` where 1 != 1) as dt(c0, c1) where 1 != 1", + "OrderBy": "1 ASC, (0|3) ASC", + "Query": "select dt.c0 as id, dt.c1 as a, weight_string(dt.c0), weight_string(dt.c0) from (select id, count(*) as a from `user` order by count(*) asc, id asc) as dt(c0, c1)", "Table": "`user`" } ] @@ -718,13 +721,15 @@ "Aggregates": "count_star(0) AS count(*)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS count(*), any_value(1)", + "Aggregates": "sum_count_star(0) AS count(*)", "Inputs": [ { "OperatorType": "Route", @@ -733,8 +738,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*), 1 from `user` where 1 != 1", - "Query": "select count(*), 1 from `user`", + "FieldQuery": "select count(*) from `user` where 1 != 1", + "Query": "select count(*) from `user`", "Table": "`user`" } ] @@ -1999,8 +2004,11 @@ "Aggregates": "any_value(0), sum(1) AS sum(num)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,0", + "OperatorType": "Projection", + "Expressions": [ + "1000 as 1000", + ":0 as num" + ], "Inputs": [ { "OperatorType": "Concatenate", @@ -2012,11 +2020,13 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "count_star(0) AS num, any_value(1)", + "Aggregates": "count_star(0) AS num", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,2", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Limit", @@ -2029,8 +2039,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t.id, 1, 1000 from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", - "Query": "select t.id, 1, 1000 from (select `user`.id from `user` where `user`.textcol1 = 'open' and `user`.intcol = 1) as t limit :__upper_limit", + "FieldQuery": "select 1 from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", + "Query": "select 1 from (select `user`.id from `user` where `user`.textcol1 = 'open' and `user`.intcol = 1) as t limit :__upper_limit", "Table": "`user`" } ] @@ -2048,11 +2058,13 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "count_star(0) AS num, any_value(1)", + "Aggregates": "count_star(0) AS num", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,2", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Limit", @@ -2065,8 +2077,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t.id, 1, 1000 from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", - "Query": "select t.id, 1, 1000 from (select `user`.id from `user` where `user`.textcol1 = 'closed' and `user`.intcol = 1) as t limit :__upper_limit", + "FieldQuery": "select 1 from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", + "Query": "select 1 from (select `user`.id from `user` where `user`.textcol1 = 'closed' and `user`.intcol = 1) as t limit :__upper_limit", "Table": "`user`" } ] @@ -2093,5 +2105,461 @@ "user.user" ] } + }, + { + "comment": "Recursive CTE that cannot be merged", + "query": "with recursive cte as (select name, id from user where manager_id is null union all select e.name, e.id from user e inner join cte on e.manager_id = cte.id) select name from cte", + "plan": { + "QueryType": "SELECT", + "Original": "with recursive cte as (select name, id from user where manager_id is null union all select e.name, e.id from user e inner join cte on e.manager_id = cte.id) select name from cte", + "Instructions": { + "OperatorType": "SimpleProjection", + "ColumnNames": [ + "0:name" + ], + "Columns": "0", + "Inputs": [ + { + "OperatorType": "RecurseCTE", + "JoinVars": { + "cte_id": 1 + }, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `name`, id from `user` where 1 != 1", + "Query": "select `name`, id from `user` where manager_id is null", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select e.`name`, e.id from `user` as e where 1 != 1", + "Query": "select e.`name`, e.id from `user` as e where e.manager_id = :cte_id", + "Table": "`user`, dual" + } + ] + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Recursive CTE that cannot be merged 2", + "query": "with recursive cte as (select name, id from user where manager_id is null union all select e.name, e.id from cte join user e on e.manager_id = cte.id) select name from cte", + "plan": { + "QueryType": "SELECT", + "Original": "with recursive cte as (select name, id from user where manager_id is null union all select e.name, e.id from cte join user e on e.manager_id = cte.id) select name from cte", + "Instructions": { + "OperatorType": "SimpleProjection", + "ColumnNames": [ + "0:name" + ], + "Columns": "0", + "Inputs": [ + { + "OperatorType": "RecurseCTE", + "JoinVars": { + "cte_id": 1 + }, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `name`, id from `user` where 1 != 1", + "Query": "select `name`, id from `user` where manager_id is null", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select e.`name`, e.id from `user` as e where 1 != 1", + "Query": "select e.`name`, e.id from `user` as e where e.manager_id = :cte_id", + "Table": "`user`, dual" + } + ] + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Merge into a single dual route", + "query": "WITH RECURSIVE cte AS (SELECT 1 as n UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT n FROM cte", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE cte AS (SELECT 1 as n UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT n FROM cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "with recursive cte as (select 1 as n from dual where 1 != 1 union all select n + 1 from cte where 1 != 1) select n from cte where 1 != 1", + "Query": "with recursive cte as (select 1 as n from dual union all select n + 1 from cte where n < 5) select n from cte", + "Table": "dual" + }, + "TablesUsed": [ + "main.dual" + ] + } + }, + { + "comment": "Recursive CTE with star projection", + "query": "WITH RECURSIVE cte (n) AS (SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT * FROM cte", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE cte (n) AS (SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT * FROM cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "with recursive cte as (select 1 from dual where 1 != 1 union all select n + 1 from cte where 1 != 1) select n from cte where 1 != 1", + "Query": "with recursive cte as (select 1 from dual union all select n + 1 from cte where n < 5) select n from cte", + "Table": "dual" + }, + "TablesUsed": [ + "main.dual" + ] + } + }, + { + "comment": "Recursive CTE calculations on the term side - merged", + "query": "WITH RECURSIVE emp_cte AS (SELECT id, 1 AS level FROM user WHERE manager_id IS NULL and id = 6 UNION ALL SELECT e.id, cte.level + 1 FROM user e JOIN emp_cte cte ON e.manager_id = cte.id and e.id = 6) SELECT * FROM emp_cte", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE emp_cte AS (SELECT id, 1 AS level FROM user WHERE manager_id IS NULL and id = 6 UNION ALL SELECT e.id, cte.level + 1 FROM user e JOIN emp_cte cte ON e.manager_id = cte.id and e.id = 6) SELECT * FROM emp_cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "with recursive emp_cte as (select id, 1 as `level` from `user` where 1 != 1 union all select e.id, cte.`level` + 1 from cte as cte, `user` as e where 1 != 1) select id, `level` from emp_cte where 1 != 1", + "Query": "with recursive emp_cte as (select id, 1 as `level` from `user` where manager_id is null and id = 6 union all select e.id, cte.`level` + 1 from cte as cte, `user` as e where e.id = 6 and e.manager_id = cte.id) select id, `level` from emp_cte", + "Table": "`user`, dual", + "Values": [ + "6" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Recursive CTE calculations on the term side - unmerged", + "query": "WITH RECURSIVE emp_cte AS (SELECT id, 1 AS level FROM user WHERE manager_id IS NULL UNION ALL SELECT e.id, cte.level + 1 FROM user e JOIN emp_cte cte ON e.manager_id = cte.id) SELECT * FROM emp_cte", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE emp_cte AS (SELECT id, 1 AS level FROM user WHERE manager_id IS NULL UNION ALL SELECT e.id, cte.level + 1 FROM user e JOIN emp_cte cte ON e.manager_id = cte.id) SELECT * FROM emp_cte", + "Instructions": { + "OperatorType": "RecurseCTE", + "JoinVars": { + "cte_id": 0, + "cte_level": 1 + }, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, 1 as `level` from `user` where 1 != 1", + "Query": "select id, 1 as `level` from `user` where manager_id is null", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select e.id, :cte_level + 1 as `cte.``level`` + 1` from `user` as e where 1 != 1", + "Query": "select e.id, :cte_level + 1 as `cte.``level`` + 1` from `user` as e where e.manager_id = :cte_id", + "Table": "`user`, dual" + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Outer join with recursive CTE", + "query": "WITH RECURSIVE literal_cte AS (SELECT 1 AS id, 100 AS value, 1 AS manager_id UNION ALL SELECT id + 1, value * 2, id FROM literal_cte WHERE id < 5) SELECT l.id, l.value, l.manager_id, e.name AS employee_name FROM literal_cte l LEFT JOIN user e ON l.id = e.id", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE literal_cte AS (SELECT 1 AS id, 100 AS value, 1 AS manager_id UNION ALL SELECT id + 1, value * 2, id FROM literal_cte WHERE id < 5) SELECT l.id, l.value, l.manager_id, e.name AS employee_name FROM literal_cte l LEFT JOIN user e ON l.id = e.id", + "Instructions": { + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinColumnIndexes": "L:0,L:1,L:2,R:0", + "JoinVars": { + "l_id": 0 + }, + "TableName": "dual_`user`", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "with recursive literal_cte as (select 1 as id, 100 as value, 1 as manager_id from dual where 1 != 1 union all select id + 1, value * 2, id from literal_cte where 1 != 1) select l.id, l.value, l.manager_id from literal_cte as l where 1 != 1", + "Query": "with recursive literal_cte as (select 1 as id, 100 as value, 1 as manager_id from dual union all select id + 1, value * 2, id from literal_cte where id < 5) select l.id, l.value, l.manager_id from literal_cte as l", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select e.`name` as employee_name from `user` as e where 1 != 1", + "Query": "select e.`name` as employee_name from `user` as e where e.id = :l_id", + "Table": "`user`", + "Values": [ + ":l_id" + ], + "Vindex": "user_index" + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Aggregation on the output of a recursive CTE", + "query": "WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id FROM user WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id FROM user e INNER JOIN emp_cte cte ON e.manager_id = cte.id) SELECT manager_id, COUNT(*) AS employee_count FROM emp_cte GROUP BY manager_id", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE emp_cte AS (SELECT id, name, manager_id FROM user WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id FROM user e INNER JOIN emp_cte cte ON e.manager_id = cte.id) SELECT manager_id, COUNT(*) AS employee_count FROM emp_cte GROUP BY manager_id", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "count_star(1) AS employee_count", + "GroupBy": "(0|2)", + "ResultColumns": 2, + "Inputs": [ + { + "OperatorType": "Projection", + "Expressions": [ + ":2 as manager_id", + "1 as 1", + "weight_string(:2) as weight_string(manager_id)" + ], + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|3) ASC", + "Inputs": [ + { + "OperatorType": "RecurseCTE", + "JoinVars": { + "cte_id": 0 + }, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select dt.c0 as id, dt.c1 as `name`, dt.c2 as manager_id, weight_string(dt.c2) from (select id, `name`, manager_id from `user` where 1 != 1) as dt(c0, c1, c2) where 1 != 1", + "Query": "select dt.c0 as id, dt.c1 as `name`, dt.c2 as manager_id, weight_string(dt.c2) from (select id, `name`, manager_id from `user` where manager_id is null) as dt(c0, c1, c2)", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select e.id, e.`name`, e.manager_id, weight_string(e.manager_id) from `user` as e where 1 != 1", + "Query": "select e.id, e.`name`, e.manager_id, weight_string(e.manager_id) from `user` as e where e.manager_id = :cte_id", + "Table": "`user`, dual" + } + ] + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Query that can be merged, dual on the RHS of the UNION", + "query": "with recursive cte as (select id from user where id = 72 union all select id+1 from cte where id < 100) select * from cte", + "plan": { + "QueryType": "SELECT", + "Original": "with recursive cte as (select id from user where id = 72 union all select id+1 from cte where id < 100) select * from cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "with recursive cte as (select id from `user` where 1 != 1 union all select id + 1 from cte where 1 != 1) select id from cte where 1 != 1", + "Query": "with recursive cte as (select id from `user` where id = 72 union all select id + 1 from cte where id < 100) select id from cte", + "Table": "`user`, dual", + "Values": [ + "72" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Merge CTE with reference tables", + "query": "with recursive cte as (select ue.id, ue.foo from user u join user_extra ue on u.id = ue.user_id union all select sr.id, sr.foo from cte join main.source_of_ref sr on sr.foo = cte.foo join main.rerouted_ref rr on rr.bar = sr.bar) select * from cte", + "plan": { + "QueryType": "SELECT", + "Original": "with recursive cte as (select ue.id, ue.foo from user u join user_extra ue on u.id = ue.user_id union all select sr.id, sr.foo from cte join main.source_of_ref sr on sr.foo = cte.foo join main.rerouted_ref rr on rr.bar = sr.bar) select * from cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "with recursive cte as (select ue.id, ue.foo from `user` as u, user_extra as ue where 1 != 1 union all select sr.id, sr.foo from ref_with_source as sr, ref as rr where 1 != 1) select id, foo from cte where 1 != 1", + "Query": "with recursive cte as (select ue.id, ue.foo from `user` as u, user_extra as ue where u.id = ue.user_id union all select sr.id, sr.foo from ref_with_source as sr, ref as rr where rr.bar = sr.bar and sr.foo = cte.foo) select id, foo from cte", + "Table": "`user`, ref, ref_with_source, user_extra" + }, + "TablesUsed": [ + "user.ref", + "user.ref_with_source", + "user.user", + "user.user_extra" + ] + } + }, + { + "comment": "Merge CTE with reference tables 2", + "query": "with recursive cte as (select sr.id, sr.foo from main.source_of_ref sr join main.rerouted_ref rr on rr.bar = sr.bar union all select ue.id, ue.foo from cte join user_extra ue on cte.foo = ue.foo join user u on ue.user_id = u.id) select * from cte", + "plan": { + "QueryType": "SELECT", + "Original": "with recursive cte as (select sr.id, sr.foo from main.source_of_ref sr join main.rerouted_ref rr on rr.bar = sr.bar union all select ue.id, ue.foo from cte join user_extra ue on cte.foo = ue.foo join user u on ue.user_id = u.id) select * from cte", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "with recursive cte as (select 1 from ref_with_source as sr, ref as rr where 1 != 1 union all select ue.id, ue.foo from cte, user_extra as ue, `user` as u where 1 != 1) select id, foo from cte where 1 != 1", + "Query": "with recursive cte as (select 1 from ref_with_source as sr, ref as rr where rr.bar = sr.bar union all select ue.id, ue.foo from cte, user_extra as ue, `user` as u where ue.user_id = u.id and cte.foo = ue.foo) select id, foo from cte", + "Table": "`user`, dual, ref, ref_with_source, user_extra" + }, + "TablesUsed": [ + "main.dual", + "user.ref", + "user.ref_with_source", + "user.user", + "user.user_extra" + ] + } + }, + { + "comment": "Merged recursive CTE with DISTINCT", + "query": "WITH RECURSIVE hierarchy AS (SELECT id, name, manager_id FROM user UNION ALL SELECT id, name, manager_id FROM user UNION DISTINCT SELECT id*2, name, manager_id from hierarchy WHERE id < 10 ) SELECT * FROM hierarchy", + "plan": { + "QueryType": "SELECT", + "Original": "WITH RECURSIVE hierarchy AS (SELECT id, name, manager_id FROM user UNION ALL SELECT id, name, manager_id FROM user UNION DISTINCT SELECT id*2, name, manager_id from hierarchy WHERE id < 10 ) SELECT * FROM hierarchy", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "with recursive hierarchy as (select id, `name`, manager_id from `user` where 1 != 1 union all select id, `name`, manager_id from `user` where 1 != 1 union select id * 2, `name`, manager_id from hierarchy where 1 != 1) select id, `name`, manager_id from hierarchy where 1 != 1", + "Query": "with recursive hierarchy as (select id, `name`, manager_id from `user` union all select id, `name`, manager_id from `user` union select id * 2, `name`, manager_id from hierarchy where id < 10) select id, `name`, manager_id from hierarchy", + "Table": "`user`, dual" + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } + }, + { + "comment": "Query that caused planner to stack overflow", + "query": "SELECT * FROM (SELECT 1 UNION ALL SELECT 2) AS dt(a) WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a * 0 AS b UNION ALL SELECT b + 1 FROM qn WHERE b = 0) SELECT * FROM qn WHERE b = a)", + "plan": { + "QueryType": "SELECT", + "Original": "SELECT * FROM (SELECT 1 UNION ALL SELECT 2) AS dt(a) WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a * 0 AS b UNION ALL SELECT b + 1 FROM qn WHERE b = 0) SELECT * FROM qn WHERE b = a)", + "Instructions": { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select a from (select 1 from dual where 1 != 1 union all select 2 from dual where 1 != 1) as dt(a) where 1 != 1", + "Query": "select a from (select 1 from dual union all select 2 from dual) as dt(a) where exists (with recursive qn as (select a * 0 as b from dual union all select b + 1 from qn where b = 0) select 1 from qn where b = a)", + "Table": "dual" + }, + "TablesUsed": [ + "main.dual" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 0e540e88b27..2e0fe429c1f 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -720,6 +720,117 @@ ] } }, + { + "comment": "Complex query that has hash left join underneath a memory sort and ordered aggregation", + "query": "select 1 from user join user_extra on user.id = user_extra.user_id join music on music.intcol = user_extra.col left join (select user_metadata.col, count(*) as count from user_metadata group by user_metadata.col) um on um.col = user_extra.col where user.id IN (103) group by user_extra.col, music.intcol", + "plan": { + "QueryType": "SELECT", + "Original": "select 1 from user join user_extra on user.id = user_extra.user_id join music on music.intcol = user_extra.col left join (select user_metadata.col, count(*) as count from user_metadata group by user_metadata.col) um on um.col = user_extra.col where user.id IN (103) group by user_extra.col, music.intcol", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "any_value(0) AS 1", + "GroupBy": "1, 4", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "1 ASC, 4 ASC", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "HashLeftJoin", + "Collation": "binary", + "ComparisonType": "FLOAT64", + "JoinColumnIndexes": "-1,-2,1,-2,-4,-1", + "Predicate": "user_extra.col = um.col", + "TableName": "music_`user`, user_extra_user_metadata", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:0,L:1", + "JoinVars": { + "music_intcol": 1 + }, + "TableName": "music_`user`, user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1, music.intcol from music where 1 != 1 group by music.intcol", + "Query": "select 1, music.intcol from music group by music.intcol", + "Table": "music" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col, user_extra.col from `user`, user_extra where 1 != 1 group by user_extra.col", + "Query": "select user_extra.col, user_extra.col from `user`, user_extra where `user`.id in (103) and user_extra.col = :music_intcol /* INT16 */ and `user`.id = user_extra.user_id group by user_extra.col", + "Table": "`user`, user_extra", + "Values": [ + "103" + ], + "Vindex": "user_index" + } + ] + }, + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "SimpleProjection", + "Columns": "0,2", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(1) AS count", + "GroupBy": "(0|2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_metadata.col, count(*) as `count`, weight_string(user_metadata.col) from user_metadata where 1 != 1 group by user_metadata.col, weight_string(user_metadata.col)", + "OrderBy": "(0|2) ASC", + "Query": "select user_metadata.col, count(*) as `count`, weight_string(user_metadata.col) from user_metadata group by user_metadata.col, weight_string(user_metadata.col) order by user_metadata.col asc", + "Table": "user_metadata" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user", + "user.user_extra", + "user.user_metadata" + ] + } + }, { "comment": "Straight-join (ignores the straight_join hint)", "query": "select m1.col from unsharded as m1 straight_join unsharded as m2", @@ -784,6 +895,59 @@ ] } }, + { + "comment": "Outer join with join predicates that only depend on the inner side", + "query": "select 1 from user left join user_extra on user.foo = 42 and user.bar = user_extra.bar", + "plan": { + "QueryType": "SELECT", + "Original": "select 1 from user left join user_extra on user.foo = 42 and user.bar = user_extra.bar", + "Instructions": { + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinVars": { + "user_bar": 1, + "user_foo": 0 + }, + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.foo, `user`.bar from `user` where 1 != 1", + "Query": "select `user`.foo, `user`.bar from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra where user_extra.bar = :user_bar and :user_foo = 42", + "Table": "user_extra" + } + ] + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "Parenthesized, single chunk", "query": "select user.col from user join (unsharded as m1 join unsharded as m2)", @@ -1742,6 +1906,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 +1988,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", @@ -4363,20 +4592,21 @@ "Aggregates": "count_star(0) AS count(*)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1", + "OperatorType": "Projection", + "Expressions": [ + "1 as 1" + ], "Inputs": [ { "OperatorType": "Distinct", "Collations": [ - "(0:2)", - "1" + "(0:1)" ], "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,L:1,R:1", + "JoinColumnIndexes": "R:0,R:1", "JoinVars": { "m_id": 0 }, @@ -4389,8 +4619,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select subquery_for_count.`m.id`, 1 from (select m.id as `m.id` from music as m where 1 != 1) as subquery_for_count where 1 != 1", - "Query": "select distinct subquery_for_count.`m.id`, 1 from (select m.id as `m.id` from music as m) as subquery_for_count", + "FieldQuery": "select subquery_for_count.`m.id` from (select m.id as `m.id` from music as m where 1 != 1) as subquery_for_count where 1 != 1", + "Query": "select distinct subquery_for_count.`m.id` from (select m.id as `m.id` from music as m) as subquery_for_count", "Table": "music" }, { @@ -4501,6 +4731,55 @@ ] } }, + { + "comment": "Cross keyspace join", + "query": "select 1 from user join t1 on user.id = t1.id", + "plan": { + "QueryType": "SELECT", + "Original": "select 1 from user join t1 on user.id = t1.id", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0", + "JoinVars": { + "t1_id": 1 + }, + "TableName": "t1_`user`", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "zlookup_unique", + "Sharded": true + }, + "FieldQuery": "select 1, t1.id from t1 where 1 != 1", + "Query": "select 1, t1.id from t1", + "Table": "t1" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from `user` where 1 != 1", + "Query": "select 1 from `user` where `user`.id = :t1_id", + "Table": "`user`", + "Values": [ + ":t1_id" + ], + "Vindex": "user_index" + } + ] + }, + "TablesUsed": [ + "user.user", + "zlookup_unique.t1" + ] + } + }, { "comment": "Select everything from a derived table having a cross-shard join", "query": "select * from (select u.foo * ue.bar from user u join user_extra ue) as dt", diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json index f26b160ef69..060f073a366 100644 --- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json @@ -14,9 +14,8 @@ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "any_value(1) AS b, sum_count_star(2) AS count(*), any_value(4)", + "Aggregates": "any_value(1|4) AS b, sum_count_star(2) AS count(*)", "GroupBy": "(0|3)", - "ResultColumns": 5, "Inputs": [ { "OperatorType": "Route", @@ -25,9 +24,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b, count(*), weight_string(a), weight_string(`user`.b) from `user` where 1 != 1 group by a, weight_string(a)", + "FieldQuery": "select dt.c0 as a, dt.c1 as b, dt.c2 as `count(*)`, dt.c3 as `weight_string(a)`, weight_string(dt.c1) from (select a, b, count(*), weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)) as dt(c0, c1, c2, c3) where 1 != 1", "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*), weight_string(a), weight_string(`user`.b) from `user` group by a, weight_string(a) order by a asc", + "Query": "select dt.c0 as a, dt.c1 as b, dt.c2 as `count(*)`, dt.c3 as `weight_string(a)`, weight_string(dt.c1) from (select a, b, count(*), weight_string(a) from `user` group by a, weight_string(a) order by a asc) as dt(c0, c1, c2, c3)", "Table": "`user`" } ] @@ -49,13 +48,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "2 ASC", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "any_value(1) AS b, sum_count_star(2) AS k", "GroupBy": "(0|3)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", @@ -93,9 +92,8 @@ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "any_value(1) AS b, sum_count_star(2) AS k, any_value(4)", + "Aggregates": "any_value(1|4) AS b, sum_count_star(2) AS k", "GroupBy": "(0|3)", - "ResultColumns": 5, "Inputs": [ { "OperatorType": "Route", @@ -104,9 +102,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b, count(*) as k, weight_string(a), weight_string(`user`.b) from `user` where 1 != 1 group by a, weight_string(a)", + "FieldQuery": "select dt.c0 as a, dt.c1 as b, dt.c2 as k, dt.c3 as `weight_string(a)`, weight_string(dt.c1) from (select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)) as dt(c0, c1, c2, c3) where 1 != 1", "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a), weight_string(`user`.b) from `user` group by a, weight_string(a) order by a asc", + "Query": "select dt.c0 as a, dt.c1 as b, dt.c2 as k, dt.c3 as `weight_string(a)`, weight_string(dt.c1) from (select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc) as dt(c0, c1, c2, c3)", "Table": "`user`" } ] @@ -132,13 +130,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "2 DESC", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "any_value(1) AS b, sum_count_star(2) AS k", "GroupBy": "(0|3)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", @@ -180,7 +178,6 @@ "Variant": "Ordered", "Aggregates": "any_value(1) AS b, sum_count_star(2) AS k", "GroupBy": "(0|3)", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Route", @@ -360,9 +357,9 @@ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,R:0,L:2,R:1,L:3", + "JoinColumnIndexes": "L:0,L:1,R:0,L:3,R:1,L:4", "JoinVars": { - "user_id": 4 + "user_id": 2 }, "TableName": "`user`_music", "Inputs": [ @@ -373,8 +370,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2), `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2), `user`.id from `user` where `user`.id = 1", + "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id, weight_string(`user`.col1), weight_string(`user`.col2) from `user` where 1 != 1", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id, weight_string(`user`.col1), weight_string(`user`.col2) from `user` where `user`.id = 1", "Table": "`user`", "Values": [ "1" diff --git a/go/vt/vtgate/planbuilder/testdata/mirror_cases.json b/go/vt/vtgate/planbuilder/testdata/mirror_cases.json new file mode 100644 index 00000000000..2466b3dca12 --- /dev/null +++ b/go/vt/vtgate/planbuilder/testdata/mirror_cases.json @@ -0,0 +1,397 @@ +[ + { + "comment": "select unsharded, qualified, table mirrored to unsharded table", + "query": "select t1.id from unsharded_src1.t1 where t1.id = 1", + "plan": { + "QueryType": "SELECT", + "Original": "select t1.id from unsharded_src1.t1 where t1.id = 1", + "Instructions": { + "OperatorType": "Mirror", + "Variant": "PercentBased", + "Percent": 1, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1", + "Query": "select t1.id from t1 where t1.id = 1", + "Table": "t1" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_dst1", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1", + "Query": "select t1.id from t1 where t1.id = 1", + "Table": "t1" + } + ] + }, + "TablesUsed": [ + "unsharded_dst1.t1", + "unsharded_src1.t1" + ] + } + }, + { + "comment": "select unsharded, qualified, table mirrored to unsharded table with zero percentage", + "query": "select t3.id from unsharded_src1.t3 where t3.id = 1", + "plan": { + "QueryType": "SELECT", + "Original": "select t3.id from unsharded_src1.t3 where t3.id = 1", + "Instructions": { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "FieldQuery": "select t3.id from t3 where 1 != 1", + "Query": "select t3.id from t3 where t3.id = 1", + "Table": "t3" + }, + "TablesUsed": [ + "unsharded_src1.t3" + ] + } + }, + { + "comment": "select unsharded, qualified, table mirrored to sharded table", + "query": "select t2.id from unsharded_src1.t2 where t2.id = 1", + "plan": { + "QueryType": "SELECT", + "Original": "select t2.id from unsharded_src1.t2 where t2.id = 1", + "Instructions": { + "OperatorType": "Mirror", + "Variant": "PercentBased", + "Percent": 2, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "FieldQuery": "select t2.id from t2 where 1 != 1", + "Query": "select t2.id from t2 where t2.id = 1", + "Table": "t2" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "sharded_dst1", + "Sharded": true + }, + "FieldQuery": "select t2.id from t1 as t2 where 1 != 1", + "Query": "select t2.id from t1 as t2 where t2.id = 1", + "Table": "t1", + "Values": [ + "1" + ], + "Vindex": "xxhash" + } + ] + }, + "TablesUsed": [ + "sharded_dst1.t1", + "unsharded_src1.t2" + ] + } + }, + { + "comment": "select two unsharded, qualified, tables, one mirrored to unsharded table, other to sharded table", + "query": "select t1.id, t2.id from unsharded_src1.t1, unsharded_src1.t2 where t1.id = t2.id", + "plan": { + "QueryType": "SELECT", + "Original": "select t1.id, t2.id from unsharded_src1.t1, unsharded_src1.t2 where t1.id = t2.id", + "Instructions": { + "OperatorType": "Mirror", + "Variant": "PercentBased", + "Percent": 1, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "FieldQuery": "select t1.id, t2.id from t1, t2 where 1 != 1", + "Query": "select t1.id, t2.id from t1, t2 where t1.id = t2.id", + "Table": "t1, t2" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0", + "JoinVars": { + "t1_id1": 0 + }, + "TableName": "t1_t1", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_dst1", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1", + "Query": "select t1.id from t1", + "Table": "t1" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "sharded_dst1", + "Sharded": true + }, + "FieldQuery": "select t2.id from t1 as t2 where 1 != 1", + "Query": "select t2.id from t1 as t2 where t2.id = :t1_id1", + "Table": "t1", + "Values": [ + ":t1_id1" + ], + "Vindex": "xxhash" + } + ] + } + ] + }, + "TablesUsed": [ + "sharded_dst1.t1", + "unsharded_dst1.t1", + "unsharded_src1.t1", + "unsharded_src1.t2" + ] + } + }, + { + "comment": "union of selects from unsharded, qualified, tables, one mirrored to unsharded table, other to sharded table", + "query": "select t1.id from unsharded_src1.t1 union select t2.id from unsharded_src1.t2", + "plan": { + "QueryType": "SELECT", + "Original": "select t1.id from unsharded_src1.t1 union select t2.id from unsharded_src1.t2", + "Instructions": { + "OperatorType": "Mirror", + "Variant": "PercentBased", + "Percent": 1, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1 union select t2.id from t2 where 1 != 1", + "Query": "select t1.id from t1 union select t2.id from t2", + "Table": "t1, t2" + }, + { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_dst1", + "Sharded": false + }, + "FieldQuery": "select dt.c0 as id, weight_string(dt.c0) from (select t1.id from t1 where 1 != 1) as dt(c0) where 1 != 1", + "Query": "select dt.c0 as id, weight_string(dt.c0) from (select distinct t1.id from t1) as dt(c0)", + "Table": "t1" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "sharded_dst1", + "Sharded": true + }, + "FieldQuery": "select dt.c0 as id, weight_string(dt.c0) from (select t2.id from t1 as t2 where 1 != 1) as dt(c0) where 1 != 1", + "Query": "select dt.c0 as id, weight_string(dt.c0) from (select distinct t2.id from t1 as t2) as dt(c0)", + "Table": "t1" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "sharded_dst1.t1", + "unsharded_dst1.t1", + "unsharded_src1.t1", + "unsharded_src1.t2" + ] + } + }, + { + "comment": "inserts are not mirrored", + "query": "insert into unsharded_src1.t1 (id) values(1)", + "plan": { + "QueryType": "INSERT", + "Original": "insert into unsharded_src1.t1 (id) values(1)", + "Instructions": { + "OperatorType": "Insert", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "TargetTabletType": "PRIMARY", + "Query": "insert into t1(id) values (1)", + "TableName": "t1" + }, + "TablesUsed": [ + "unsharded_src1.t1" + ] + } + }, + { + "comment": "updates are not mirrored", + "query": "update unsharded_src1.t1 set data = 'a' where id = 1", + "plan": { + "QueryType": "UPDATE", + "Original": "update unsharded_src1.t1 set data = 'a' where id = 1", + "Instructions": { + "OperatorType": "Update", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "TargetTabletType": "PRIMARY", + "Query": "update t1 set `data` = 'a' where id = 1", + "Table": "t1" + }, + "TablesUsed": [ + "unsharded_src1.t1" + ] + } + }, + { + "comment": "deletes are not mirrored", + "query": "delete from unsharded_src1.t1 where id = 1", + "plan": { + "QueryType": "DELETE", + "Original": "delete from unsharded_src1.t1 where id = 1", + "Instructions": { + "OperatorType": "Delete", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src1", + "Sharded": false + }, + "TargetTabletType": "PRIMARY", + "Query": "delete from t1 where id = 1", + "Table": "t1" + }, + "TablesUsed": [ + "unsharded_src1.t1" + ] + } + }, + { + "comment": "self-mirror is not allowed", + "query": "select t1.id from unsharded_src2.t1", + "plan": { + "QueryType": "SELECT", + "Original": "select t1.id from unsharded_src2.t1", + "Instructions": { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src2", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1", + "Query": "select t1.id from t1", + "Table": "t1" + }, + "TablesUsed": [ + "unsharded_src2.t1" + ] + } + }, + { + "comment": "chained mirror is not allowed", + "query": "select t2.id from unsharded_src2.t2", + "plan": { + "QueryType": "SELECT", + "Original": "select t2.id from unsharded_src2.t2", + "Instructions": { + "OperatorType": "Mirror", + "Variant": "PercentBased", + "Percent": 4, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src2", + "Sharded": false + }, + "FieldQuery": "select t2.id from t2 where 1 != 1", + "Query": "select t2.id from t2", + "Table": "t2" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_dst2", + "Sharded": false + }, + "FieldQuery": "select t2.id from t2 where 1 != 1", + "Query": "select t2.id from t2", + "Table": "t2" + } + ] + }, + "TablesUsed": [ + "unsharded_dst2.t2", + "unsharded_src2.t2" + ] + } + }, + { + "comment": "circular mirror is not allowed", + "query": "select t1.id from unsharded_src3.t1", + "plan": { + "QueryType": "SELECT", + "Original": "select t1.id from unsharded_src3.t1", + "Instructions": { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "unsharded_src3", + "Sharded": false + }, + "FieldQuery": "select t1.id from t1 where 1 != 1", + "Query": "select t1.id from t1", + "Table": "t1" + }, + "TablesUsed": [ + "unsharded_src3.t1" + ] + } + } +] diff --git a/go/vt/vtgate/planbuilder/testdata/onecase.json b/go/vt/vtgate/planbuilder/testdata/onecase.json index da7543f706a..9d653b2f6e9 100644 --- a/go/vt/vtgate/planbuilder/testdata/onecase.json +++ b/go/vt/vtgate/planbuilder/testdata/onecase.json @@ -3,7 +3,6 @@ "comment": "Add your test case here for debugging and run go test -run=One.", "query": "", "plan": { - } } ] \ No newline at end of file diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 74e5229016a..36f1472007d 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -1554,7 +1554,7 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "sum_count(0) AS count(id), any_value(1) AS num, any_value(2)", + "Aggregates": "sum_count(0) AS count(id), any_value(1|2) AS num", "Inputs": [ { "OperatorType": "Route", @@ -1618,13 +1618,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "0 ASC", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count(0) AS count(id)", "GroupBy": "(1|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Route", @@ -1729,7 +1729,7 @@ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "sum_count_star(1) AS count(*), any_value(2) AS c1, any_value(3)", + "Aggregates": "sum_count_star(1) AS count(*), any_value(2|3) AS c1", "GroupBy": "0", "Inputs": [ { @@ -1739,9 +1739,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col, count(*), c1, weight_string(c1) from `user` where 1 != 1 group by col", + "FieldQuery": "select dt.c0 as col, dt.c1 as `count(*)`, dt.c2 as c1, weight_string(dt.c2) from (select col, count(*), c1 from `user` where 1 != 1 group by col) as dt(c0, c1, c2) where 1 != 1", "OrderBy": "0 ASC", - "Query": "select col, count(*), c1, weight_string(c1) from `user` group by col order by col asc", + "Query": "select dt.c0 as col, dt.c1 as `count(*)`, dt.c2 as c1, weight_string(dt.c2) from (select col, count(*), c1 from `user` group by col order by col asc) as dt(c0, c1, c2)", "Table": "`user`" } ] @@ -2090,7 +2090,6 @@ "Variant": "Ordered", "Aggregates": "min(1|3) AS min(a.id)", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Join", diff --git a/go/vt/vtgate/planbuilder/testdata/reference_cases.json b/go/vt/vtgate/planbuilder/testdata/reference_cases.json index a89fa103923..6aa01355934 100644 --- a/go/vt/vtgate/planbuilder/testdata/reference_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/reference_cases.json @@ -746,5 +746,30 @@ "user.user" ] } + }, + { + "comment": "two sharded and two unsharded reference table join - all should be merged into one route", + "query": "select 1 from user u join user_extra ue on u.id = ue.user_id join main.source_of_ref sr on sr.foo = ue.foo join main.rerouted_ref rr on rr.bar = sr.bar", + "plan": { + "QueryType": "SELECT", + "Original": "select 1 from user u join user_extra ue on u.id = ue.user_id join main.source_of_ref sr on sr.foo = ue.foo join main.rerouted_ref rr on rr.bar = sr.bar", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from `user` as u, user_extra as ue, ref_with_source as sr, ref as rr where 1 != 1", + "Query": "select 1 from `user` as u, user_extra as ue, ref_with_source as sr, ref as rr where rr.bar = sr.bar and u.id = ue.user_id and sr.foo = ue.foo", + "Table": "`user`, ref, ref_with_source, user_extra" + }, + "TablesUsed": [ + "user.ref", + "user.ref_with_source", + "user.user", + "user.user_extra" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 98d0f9d0cbd..f06a6a50d45 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -793,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", @@ -1809,7 +1836,6 @@ "Variant": "Ordered", "Aggregates": "sum(0) AS avg_col, sum_count(3) AS count(intcol)", "GroupBy": "1 COLLATE latin1_swedish_ci, (2|4) COLLATE ", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Route", @@ -1856,6 +1882,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", @@ -2717,6 +2849,28 @@ ] } }, + { + "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", @@ -4175,7 +4329,6 @@ "Variant": "Ordered", "Aggregates": "any_value(0) AS id", "GroupBy": "(1|2)", - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -4341,7 +4494,6 @@ "OperatorType": "Aggregate", "Variant": "Scalar", "Aggregates": "max(0|1) AS max(music.id)", - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -4878,7 +5030,6 @@ "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS b", "GroupBy": "(2|3), (0|4)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Route", diff --git a/go/vt/vtgate/planbuilder/testdata/show_cases.json b/go/vt/vtgate/planbuilder/testdata/show_cases.json index 45ad277677c..00bd37fe8f2 100644 --- a/go/vt/vtgate/planbuilder/testdata/show_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/show_cases.json @@ -838,5 +838,40 @@ "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" + } + } + }, + { + "comment": "show unresolved transactions for default keyspace", + "query": "show unresolved transactions", + "plan": { + "QueryType": "SHOW", + "Original": "show unresolved transactions", + "Instructions": { + "OperatorType": "TransactionStatus" + } + } + }, + { + "comment": "show unresolved transactions for explicitly provided keyspace", + "query": "show unresolved transactions for ks", + "plan": { + "QueryType": "SHOW", + "Original": "show unresolved transactions for ks", + "Instructions": { + "OperatorType": "TransactionStatus", + "Keyspace": "ks" + } + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json index 442f4d6b8b6..6b3f84d01d6 100644 --- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json @@ -25,7 +25,6 @@ "Variant": "Ordered", "Aggregates": "sum(2) AS sum_qty, sum(3) AS sum_base_price, sum(4) AS sum_disc_price, sum(5) AS sum_charge, sum(6) AS avg_qty, sum(7) AS avg_price, sum(8) AS avg_disc, sum_count_star(9) AS count_order, sum_count(10) AS count(l_quantity), sum_count(11) AS count(l_extendedprice), sum_count(12) AS count(l_discount)", "GroupBy": "(0|13), (1|14)", - "ResultColumns": 13, "Inputs": [ { "OperatorType": "Route", @@ -74,7 +73,6 @@ "Variant": "Ordered", "Aggregates": "sum(1) AS revenue", "GroupBy": "(0|4), (2|5), (3|6)", - "ResultColumns": 6, "Inputs": [ { "OperatorType": "Projection", @@ -279,13 +277,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "1 DESC COLLATE utf8mb4_0900_ai_ci", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum(1) AS revenue", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Projection", @@ -802,7 +800,6 @@ "Variant": "Ordered", "Aggregates": "sum(1) AS sum(case when nation = 'BRAZIL' then volume else 0 end), sum(2) AS sum(volume)", "GroupBy": "(0|3)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Projection", @@ -832,7 +829,6 @@ "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", @@ -1112,12 +1108,11 @@ "Variant": "Ordered", "Aggregates": "sum(0) AS sum_profit", "GroupBy": "(1|3), (2|4)", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,L:4,L:6,L:7", + "JoinColumnIndexes": "R:0,L:0,L:4,L:6,L:8", "JoinVars": { "l_discount": 2, "l_extendedprice": 1, @@ -1130,7 +1125,7 @@ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(0|6) ASC, (4|7) ASC", + "OrderBy": "(0|6) ASC, (4|8) ASC", "Inputs": [ { "OperatorType": "Join", @@ -1349,13 +1344,13 @@ "OperatorType": "Sort", "Variant": "Memory", "OrderBy": "2 DESC COLLATE utf8mb4_0900_ai_ci", + "ResultColumns": 8, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum(2) AS revenue", "GroupBy": "(0|8), (1|9), (3|10), (6|11), (4|12), (5|13), (7|14)", - "ResultColumns": 8, "Inputs": [ { "OperatorType": "Projection", @@ -1660,6 +1655,7 @@ "InputName": "Outer", "OperatorType": "Filter", "Predicate": "sum(ps_supplycost * ps_availqty) > :__sq1", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Sort", @@ -1671,7 +1667,6 @@ "Variant": "Ordered", "Aggregates": "sum(1) AS value", "GroupBy": "(0|2)", - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Projection", @@ -1892,23 +1887,24 @@ "GroupBy": "0", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "1,3", + "OperatorType": "Projection", + "Expressions": [ + ":1 as c_count", + "1 as 1" + ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "sum_count(1) AS count(o_orderkey), any_value(3)", + "Aggregates": "sum_count(1) AS count(o_orderkey)", "GroupBy": "(0|2)", - "ResultColumns": 4, "Inputs": [ { "OperatorType": "Projection", "Expressions": [ ":2 as c_custkey", "count(*) * count(o_orderkey) as count(o_orderkey)", - ":3 as weight_string(c_custkey)", - ":4 as 1" + ":3 as weight_string(c_custkey)" ], "Inputs": [ { @@ -1919,7 +1915,7 @@ { "OperatorType": "Join", "Variant": "LeftJoin", - "JoinColumnIndexes": "R:0,L:0,L:1,L:2,L:3", + "JoinColumnIndexes": "R:0,L:0,L:1,L:2", "JoinVars": { "c_custkey": 1 }, @@ -1932,9 +1928,9 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select count(*), c_custkey, weight_string(c_custkey), 1 from customer where 1 != 1 group by c_custkey, weight_string(c_custkey)", + "FieldQuery": "select count(*), c_custkey, weight_string(c_custkey) from customer where 1 != 1 group by c_custkey, weight_string(c_custkey)", "OrderBy": "(1|2) ASC", - "Query": "select count(*), c_custkey, weight_string(c_custkey), 1 from customer group by c_custkey, weight_string(c_custkey) order by c_custkey asc", + "Query": "select count(*), c_custkey, weight_string(c_custkey) from customer group by c_custkey, weight_string(c_custkey) order by c_custkey asc", "Table": "customer" }, { @@ -1986,41 +1982,51 @@ "Aggregates": "any_value(0), sum(1) AS sum(case when p_type like 'PROMO%' then l_extendedprice * (1 - l_discount) else 0 end), sum(2) AS sum(l_extendedprice * (1 - l_discount))", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:3", - "JoinVars": { - "l_discount": 2, - "l_extendedprice": 1, - "l_partkey": 4 - }, - "TableName": "lineitem_part", + "OperatorType": "Projection", + "Expressions": [ + "100.00 as 100.00", + ":0 as case when p_type like 'PROMO%' then l_extendedprice * (1 - l_discount) else 0 end", + ":1 as l_extendedprice * (1 - l_discount)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select 100.00, l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where 1 != 1", - "Query": "select 100.00, l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where l_shipdate >= date('1995-09-01') and l_shipdate < date('1995-09-01') + interval '1' month", - "Table": "lineitem" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "R:0,L:2", + "JoinVars": { + "l_discount": 1, + "l_extendedprice": 0, + "l_partkey": 3 }, - "FieldQuery": "select case when p_type like 'PROMO%' then :l_extendedprice * (1 - :l_discount) else 0 end from part where 1 != 1", - "Query": "select case when p_type like 'PROMO%' then :l_extendedprice * (1 - :l_discount) else 0 end from part where p_partkey = :l_partkey", - "Table": "part", - "Values": [ - ":l_partkey" - ], - "Vindex": "hash" + "TableName": "lineitem_part", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where 1 != 1", + "Query": "select l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where l_shipdate >= date('1995-09-01') and l_shipdate < date('1995-09-01') + interval '1' month", + "Table": "lineitem" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select case when p_type like 'PROMO%' then :l_extendedprice * (1 - :l_discount) else 0 end from part where 1 != 1", + "Query": "select case when p_type like 'PROMO%' then :l_extendedprice * (1 - :l_discount) else 0 end from part where p_partkey = :l_partkey", + "Table": "part", + "Values": [ + ":l_partkey" + ], + "Vindex": "hash" + } + ] } ] } @@ -2052,7 +2058,6 @@ "OperatorType": "Aggregate", "Variant": "Scalar", "Aggregates": "max(0|1) AS max(total_revenue)", - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -2106,7 +2111,6 @@ "Variant": "Ordered", "Aggregates": "count_distinct(3|7) AS supplier_cnt", "GroupBy": "(0|4), (1|5), (2|6)", - "ResultColumns": 7, "Inputs": [ { "OperatorType": "Sort", @@ -2116,9 +2120,9 @@ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1,R:2,L:0,R:3,R:4,R:5,L:1", + "JoinColumnIndexes": "R:0,R:1,R:2,L:0,R:3,R:4,R:5,L:2", "JoinVars": { - "ps_partkey": 2, + "ps_partkey": 1, "ps_suppkey": 0 }, "TableName": "partsupp_part", @@ -2151,8 +2155,8 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select ps_suppkey, weight_string(ps_suppkey), ps_partkey from partsupp where 1 != 1", - "Query": "select ps_suppkey, weight_string(ps_suppkey), ps_partkey from partsupp where not :__sq_has_values or ps_suppkey not in ::__sq1", + "FieldQuery": "select ps_suppkey, ps_partkey, weight_string(ps_suppkey) from partsupp where 1 != 1", + "Query": "select ps_suppkey, ps_partkey, weight_string(ps_suppkey) from partsupp where not :__sq_has_values or ps_suppkey not in ::__sq1", "Table": "partsupp" } ] @@ -2444,7 +2448,6 @@ "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS numwait", "GroupBy": "(0|2)", - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Projection", diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index 6f3148e602b..9241cec595c 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", @@ -284,6 +294,11 @@ "query": "select 1 from music union (select id from user union all select name from unsharded)", "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" }, + { + "comment": "Cross keyspace query with subquery", + "query": "select 1 from user where id = (select id from t1 where user.foo = t1.bar)", + "plan": "VT12001: unsupported: correlated subquery is only supported for EXISTS" + }, { "comment": "multi-shard union", "query": "select 1 from music union (select id from user union select name from unsharded)", @@ -314,11 +329,6 @@ "query": "with user as (select aa from user where user.id=1) select ref.col from ref join user", "plan": "VT12001: unsupported: do not support CTE that use the CTE alias inside the CTE query" }, - { - "comment": "Recursive WITH", - "query": "WITH RECURSIVE cte (n) AS (SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT * FROM cte", - "plan": "VT12001: unsupported: recursive common table expression" - }, { "comment": "Alias cannot clash with base tables", "query": "WITH user AS (SELECT col FROM user) SELECT * FROM user", diff --git a/go/vt/vtgate/planbuilder/testdata/vschemas/mirror_schema.json b/go/vt/vtgate/planbuilder/testdata/vschemas/mirror_schema.json new file mode 100644 index 00000000000..4feaa09c126 --- /dev/null +++ b/go/vt/vtgate/planbuilder/testdata/vschemas/mirror_schema.json @@ -0,0 +1,103 @@ +{ + "mirror_rules": { + "rules": [ + { + "from_table": "unsharded_src1.t1", + "to_table": "unsharded_dst1.t1", + "percent": 1 + }, + { + "from_table": "unsharded_src1.t2", + "to_table": "sharded_dst1.t1", + "percent": 2 + }, + { + "from_table": "unsharded_src2.t1", + "to_table": "unsharded_src2.t1", + "percent": 3 + }, + { + "from_table": "unsharded_src2.t2", + "to_table": "unsharded_dst2.t2", + "percent": 4 + }, + { + "from_table": "unsharded_dst2.t2", + "to_table": "unsharded_dst3.t2", + "percent": 5 + }, + { + "from_table": "unsharded_src3.t1", + "to_table": "unsharded_dst4.t1", + "percent": 6 + }, + { + "from_table": "unsharded_dst4.t2", + "to_table": "unsharded_src3.t2", + "percent": 7 + }, + { + "from_table": "sharded_src1.t1", + "to_table": "sharded_dst1.t1", + "percent": 8 + }, + { + "from_table": "unsharded_src1.t3", + "to_table": "unsharded_dst1.t2", + "percent": 0 + } + ] + }, + "keyspaces": { + "main": { + "sharded": false, + "tables": {} + }, + "unsharded_src1": { + "sharded": false, + "tables": {} + }, + "unsharded_src2": { + "sharded": false, + "tables": {} + }, + "unsharded_src3": { + "sharded": false, + "tables": {} + }, + "unsharded_dst1": { + "sharded": false, + "tables": {} + }, + "unsharded_dst2": { + "sharded": false, + "tables": {} + }, + "unsharded_dst3": { + "sharded": false, + "tables": {} + }, + "unsharded_dst4": { + "sharded": false, + "tables": {} + }, + "sharded_dst1": { + "sharded": true, + "vindexes": { + "xxhash": { + "type": "xxhash" + } + }, + "tables": { + "t1": { + "columnVindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] + } + } + } + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json b/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json index a8fe91e5d49..4fe275f2398 100644 --- a/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json +++ b/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json @@ -282,6 +282,12 @@ "column": "id", "name": "music_user_map" } + ], + "columns": [ + { + "name": "intcol", + "type": "INT16" + } ] }, "authoritative": { diff --git a/go/vt/vtgate/plugin_mysql_server.go b/go/vt/vtgate/plugin_mysql_server.go index 55954013862..dec7794c9bd 100644 --- a/go/vt/vtgate/plugin_mysql_server.go +++ b/go/vt/vtgate/plugin_mysql_server.go @@ -103,7 +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 connected clients to drain") + 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. @@ -399,7 +399,7 @@ func (vh *vtgateHandler) KillConnection(ctx context.Context, connectionID uint32 c, exists := vh.connections[connectionID] if !exists { - return sqlerror.NewSQLError(sqlerror.ERNoSuchThread, sqlerror.SSUnknownSQLState, "Unknown thread id: %d", connectionID) + return sqlerror.NewSQLErrorf(sqlerror.ERNoSuchThread, sqlerror.SSUnknownSQLState, "Unknown thread id: %d", connectionID) } // First, we mark the connection for close, so that even when the context is cancelled, while returning the response back to client, @@ -417,7 +417,7 @@ func (vh *vtgateHandler) KillQuery(connectionID uint32) error { defer vh.mu.Unlock() c, exists := vh.connections[connectionID] if !exists { - return sqlerror.NewSQLError(sqlerror.ERNoSuchThread, sqlerror.SSUnknownSQLState, "Unknown thread id: %d", connectionID) + return sqlerror.NewSQLErrorf(sqlerror.ERNoSuchThread, sqlerror.SSUnknownSQLState, "Unknown thread id: %d", connectionID) } c.CancelCtx() return nil diff --git a/go/vt/vtgate/production.go b/go/vt/vtgate/production.go new file mode 100644 index 00000000000..d3b0ff4fe7e --- /dev/null +++ b/go/vt/vtgate/production.go @@ -0,0 +1,38 @@ +//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 + +import ( + "context" + + querypb "vitess.io/vitess/go/vt/proto/query" +) + +// 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 + +func checkTestFailure(_ context.Context, _ string, _ *querypb.Target) error { + return nil +} diff --git a/go/vt/vtgate/sandbox_test.go b/go/vt/vtgate/sandbox_test.go index 70b96a63126..fa5ffbbffd8 100644 --- a/go/vt/vtgate/sandbox_test.go +++ b/go/vt/vtgate/sandbox_test.go @@ -48,6 +48,7 @@ const ( func init() { ksToSandbox = make(map[string]*sandbox) + sandboxMirrorRules = `{"rules":[]}` createSandbox(KsTestSharded) createSandbox(KsTestUnsharded) createSandbox(KsTestBadVSchema) @@ -57,6 +58,7 @@ func init() { var sandboxMu sync.Mutex var ksToSandbox map[string]*sandbox +var sandboxMirrorRules string func createSandbox(keyspace string) *sandbox { sandboxMu.Lock() @@ -86,9 +88,20 @@ func getSandboxSrvVSchema() *vschemapb.SrvVSchema { } result.Keyspaces[keyspace] = &vs } + var mrs vschemapb.MirrorRules + if err := json2.Unmarshal([]byte(sandboxMirrorRules), &mrs); err != nil { + panic(err) + } + result.MirrorRules = &mrs return result } +func setSandboxMirrorRules(mirrorRules string) { + sandboxMu.Lock() + defer sandboxMu.Unlock() + sandboxMirrorRules = mirrorRules +} + type sandbox struct { // Use sandmu to access the variables below sandmu sync.Mutex diff --git a/go/vt/vtgate/semantics/FakeSI.go b/go/vt/vtgate/semantics/FakeSI.go index 1ca6718f1a8..cb1b9cec094 100644 --- a/go/vt/vtgate/semantics/FakeSI.go +++ b/go/vt/vtgate/semantics/FakeSI.go @@ -85,3 +85,8 @@ func (s *FakeSI) KeyspaceError(keyspace string) error { func (s *FakeSI) GetAggregateUDFs() []string { return s.UDFs } + +// FindMirrorRule implements SchemaInformation. +func (s *FakeSI) FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) { + return nil, nil +} diff --git a/go/vt/vtgate/semantics/analyzer.go b/go/vt/vtgate/semantics/analyzer.go index 8bb7cc393fc..0a9d2480d9b 100644 --- a/go/vt/vtgate/semantics/analyzer.go +++ b/go/vt/vtgate/semantics/analyzer.go @@ -357,7 +357,7 @@ func (a *analyzer) collationEnv() *collations.Environment { } func (a *analyzer) analyze(statement sqlparser.Statement) error { - _ = sqlparser.Rewrite(statement, nil, a.earlyUp) + _ = sqlparser.Rewrite(statement, a.earlyTables.down, a.earlyTables.up) if a.err != nil { return a.err } @@ -387,7 +387,14 @@ func (a *analyzer) reAnalyze(statement sqlparser.SQLNode) error { // canShortCut checks if we are dealing with a single unsharded keyspace and no tables that have managed foreign keys // if so, we can stop the analyzer early func (a *analyzer) canShortCut(statement sqlparser.Statement) (canShortCut bool) { - ks, _ := singleUnshardedKeyspace(a.earlyTables.Tables) + var ks *vindexes.Keyspace + switch statement.(type) { + case sqlparser.SelectStatement: + ks, canShortCut = canTakeSelectUnshardedShortcut(a.earlyTables.Tables) + default: + ks, canShortCut = canTakeUnshardedShortcut(a.earlyTables.Tables) + } + a.singleUnshardedKeyspace = ks != nil if !a.singleUnshardedKeyspace { return false @@ -424,13 +431,6 @@ func (a *analyzer) canShortCut(statement sqlparser.Statement) (canShortCut bool) return true } -// earlyUp collects tables in the query, so we can check -// if this a single unsharded query we are dealing with -func (a *analyzer) earlyUp(cursor *sqlparser.Cursor) bool { - a.earlyTables.up(cursor) - return true -} - func (a *analyzer) shouldContinue() bool { return a.err == nil } @@ -455,6 +455,10 @@ func (a *analyzer) noteQuerySignature(node sqlparser.SQLNode) { if node.GroupBy != nil { a.sig.Aggregation = true } + case *sqlparser.With: + if node.Recursive { + a.sig.RecursiveCTE = true + } case sqlparser.AggrFunc: a.sig.Aggregation = true case *sqlparser.Delete, *sqlparser.Update, *sqlparser.Insert: diff --git a/go/vt/vtgate/semantics/analyzer_test.go b/go/vt/vtgate/semantics/analyzer_test.go index 0fbf0911f3a..0c42456b0ab 100644 --- a/go/vt/vtgate/semantics/analyzer_test.go +++ b/go/vt/vtgate/semantics/analyzer_test.go @@ -195,6 +195,59 @@ func TestBindingMultiTablePositive(t *testing.T) { } } +func TestBindingRecursiveCTEs(t *testing.T) { + type testCase struct { + query string + rdeps TableSet + ddeps TableSet + } + queries := []testCase{{ + query: "with recursive x as (select id from user union select x.id + 1 from x where x.id < 15) select t.id from x join x t;", + rdeps: TS3, + ddeps: TS3, + }, { + query: "WITH RECURSIVE user_cte AS (SELECT id, name FROM user WHERE id = 42 UNION ALL SELECT u.id, u.name FROM user u JOIN user_cte cte ON u.id = cte.id + 1 WHERE u.id = 42) SELECT id FROM user_cte", + rdeps: TS3, + ddeps: TS3, + }} + for _, query := range queries { + t.Run(query.query, func(t *testing.T) { + stmt, semTable := parseAndAnalyzeStrict(t, query.query, "user") + sel := stmt.(*sqlparser.Select) + assert.Equal(t, query.rdeps, semTable.RecursiveDeps(extract(sel, 0)), "recursive") + assert.Equal(t, query.ddeps, semTable.DirectDeps(extract(sel, 0)), "direct") + }) + } +} + +func TestRecursiveCTEChecking(t *testing.T) { + type testCase struct { + name, query, err string + } + queries := []testCase{{ + name: "recursive CTE using aggregation", + query: "with recursive x as (select id from user union select count(*) from x) select t.id from x join x t", + err: "VT09027: Recursive Common Table Expression 'x' can contain neither aggregation nor window functions in recursive query block", + }, { + name: "recursive CTE using grouping", + query: "with recursive x as (select id from user union select id+1 from x where id < 10 group by 1) select t.id from x join x t", + err: "VT09027: Recursive Common Table Expression 'x' can contain neither aggregation nor window functions in recursive query block", + }, { + name: "use the same recursive cte twice in definition", + query: "with recursive x as (select 1 union select id+1 from x where id < 10 union select id+2 from x where id < 20) select t.id from x", + err: "VT09029: In recursive query block of Recursive Common Table Expression x, the recursive table must be referenced only once, and not in any subquery", + }} + for _, tc := range queries { + t.Run(tc.query, func(t *testing.T) { + parse, err := sqlparser.NewTestParser().Parse(tc.query) + require.NoError(t, err) + + _, err = AnalyzeStrict(parse, "user", fakeSchemaInfo()) + require.EqualError(t, err, tc.err) + }) + } +} + func TestBindingMultiAliasedTablePositive(t *testing.T) { type testCase struct { query string @@ -887,9 +940,6 @@ func TestInvalidQueries(t *testing.T) { }, { sql: "select 1 from t1 where (id, id) in (select 1, 2, 3)", serr: "Operand should contain 2 column(s)", - }, { - sql: "WITH RECURSIVE cte (n) AS (SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5) SELECT * FROM cte", - serr: "VT12001: unsupported: recursive common table expression", }, { sql: "with x as (select 1), x as (select 1) select * from x", serr: "VT03013: not unique table/alias: 'x'", @@ -956,7 +1006,7 @@ func TestScopingWithWITH(t *testing.T) { }, { query: "with c as (select x as foo from user), t as (select foo as id from c) select id from t", recursive: TS0, - direct: TS3, + direct: TS2, }, { query: "with t as (select foo as id from user) select t.id from t", recursive: TS0, diff --git a/go/vt/vtgate/semantics/check_invalid.go b/go/vt/vtgate/semantics/check_invalid.go index a739e857c00..6509f5f5ee8 100644 --- a/go/vt/vtgate/semantics/check_invalid.go +++ b/go/vt/vtgate/semantics/check_invalid.go @@ -48,10 +48,6 @@ func (a *analyzer) checkForInvalidConstructs(cursor *sqlparser.Cursor) error { } case *sqlparser.Subquery: return a.checkSubqueryColumns(cursor.Parent(), node) - case *sqlparser.With: - if node.Recursive { - return vterrors.VT12001("recursive common table expression") - } case *sqlparser.Insert: if !a.singleUnshardedKeyspace && node.Action == sqlparser.ReplaceAct { return ShardedError{Inner: &UnsupportedConstruct{errString: "REPLACE INTO with sharded keyspace"}} diff --git a/go/vt/vtgate/semantics/cte_table.go b/go/vt/vtgate/semantics/cte_table.go new file mode 100644 index 00000000000..498fc5076c1 --- /dev/null +++ b/go/vt/vtgate/semantics/cte_table.go @@ -0,0 +1,182 @@ +/* +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 semantics + +import ( + "strings" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/vt/vtgate/vindexes" +) + +// CTETable contains the information about the CTE table. +// This is a special TableInfo that is used to represent the recursive table inside a CTE. For the query: +// WITH RECURSIVE cte AS (SELECT 1 UNION ALL SELECT * FROM cte as C1) SELECT * FROM cte as C2 +// The CTE table C1 is represented by a CTETable. +type CTETable struct { + TableName string + ASTNode *sqlparser.AliasedTableExpr + *CTE +} + +var _ TableInfo = (*CTETable)(nil) + +func newCTETable(node *sqlparser.AliasedTableExpr, t sqlparser.TableName, cteDef *CTE) *CTETable { + var name string + if node.As.IsEmpty() { + name = t.Name.String() + } else { + name = node.As.String() + } + + authoritative := true + for _, expr := range cteDef.Query.GetColumns() { + _, isStar := expr.(*sqlparser.StarExpr) + if isStar { + authoritative = false + break + } + } + cteDef.isAuthoritative = authoritative + + return &CTETable{ + TableName: name, + ASTNode: node, + CTE: cteDef, + } +} + +func (cte *CTETable) Name() (sqlparser.TableName, error) { + return sqlparser.NewTableName(cte.TableName), nil +} + +func (cte *CTETable) GetVindexTable() *vindexes.Table { + return nil +} + +func (cte *CTETable) IsInfSchema() bool { + return false +} + +func (cte *CTETable) matches(name sqlparser.TableName) bool { + return cte.TableName == name.Name.String() && name.Qualifier.IsEmpty() +} + +func (cte *CTETable) authoritative() bool { + return cte.isAuthoritative +} + +func (cte *CTETable) GetAliasedTableExpr() *sqlparser.AliasedTableExpr { + return cte.ASTNode +} + +func (cte *CTETable) canShortCut() shortCut { + return canShortCut +} + +func (cte *CTETable) getColumns(bool) []ColumnInfo { + selExprs := cte.Query.GetColumns() + cols := make([]ColumnInfo, 0, len(selExprs)) + for i, selExpr := range selExprs { + ae, isAe := selExpr.(*sqlparser.AliasedExpr) + if !isAe { + panic(vterrors.VT12001("should not be called")) + } + if len(cte.Columns) == 0 { + cols = append(cols, ColumnInfo{Name: ae.ColumnName()}) + continue + } + + // We have column aliases defined on the CTE + cols = append(cols, ColumnInfo{Name: cte.Columns[i].String()}) + } + return cols +} + +func (cte *CTETable) dependencies(colName string, org originable) (dependencies, error) { + directDeps := org.tableSetFor(cte.ASTNode) + columns := cte.getColumns(false) + for _, columnInfo := range columns { + if strings.EqualFold(columnInfo.Name, colName) { + return createCertain(directDeps, directDeps, evalengine.NewUnknownType()), nil + } + } + + if cte.authoritative() { + return ¬hing{}, nil + } + + return createUncertain(directDeps, directDeps), nil +} + +func (cte *CTETable) getExprFor(s string) (sqlparser.Expr, error) { + for _, se := range cte.Query.GetColumns() { + ae, ok := se.(*sqlparser.AliasedExpr) + if !ok { + return nil, vterrors.VT09015() + } + if ae.ColumnName() == s { + return ae.Expr, nil + } + } + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Unknown column '%s' in 'field list'", s) +} + +func (cte *CTETable) getTableSet(org originable) TableSet { + return org.tableSetFor(cte.ASTNode) +} + +// GetMirrorRule implements TableInfo. +func (cte *CTETable) GetMirrorRule() *vindexes.MirrorRule { + return nil +} + +type CTE struct { + Name string + Query sqlparser.SelectStatement + isAuthoritative bool + recursiveDeps *TableSet + Columns sqlparser.Columns + IDForRecurse *TableSet + + // Was this CTE marked for being recursive? + Recursive bool + + // The CTE had the seed and term parts merged + Merged bool +} + +func (cte *CTE) recursive(org originable) (id TableSet) { + if cte.recursiveDeps != nil { + return *cte.recursiveDeps + } + + // We need to find the recursive dependencies of the CTE + // We'll do this by walking the inner query and finding all the tables + _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + ate, ok := node.(*sqlparser.AliasedTableExpr) + if !ok { + return true, nil + } + id = id.Merge(org.tableSetFor(ate)) + return true, nil + }, cte.Query) + return +} diff --git a/go/vt/vtgate/semantics/dependencies.go b/go/vt/vtgate/semantics/dependencies.go index 70167ff02fc..42b7a918384 100644 --- a/go/vt/vtgate/semantics/dependencies.go +++ b/go/vt/vtgate/semantics/dependencies.go @@ -17,6 +17,8 @@ limitations under the License. package semantics import ( + "fmt" + querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/evalengine" @@ -29,6 +31,7 @@ type ( empty() bool get(col *sqlparser.ColName) (dependency, error) merge(other dependencies, allowMulti bool) dependencies + debugString() string } dependency struct { certain bool @@ -100,6 +103,10 @@ func (u *uncertain) merge(d dependencies, _ bool) dependencies { } } +func (u *uncertain) debugString() string { + return fmt.Sprintf("uncertain: %v %v %s", u.direct, u.recursive, u.typ.Type().String()) +} + func (c *certain) empty() bool { return false } @@ -117,26 +124,34 @@ func (c *certain) merge(d dependencies, allowMulti bool) dependencies { if d.recursive == c.recursive { return c } - c.direct = c.direct.Merge(d.direct) - c.recursive = c.recursive.Merge(d.recursive) + + res := createCertain(c.direct.Merge(d.direct), c.recursive.Merge(d.recursive), c.typ) if !allowMulti { - c.err = true + res.err = true } - return c + return res } return c } -func (n *nothing) empty() bool { +func (c *certain) debugString() string { + return fmt.Sprintf("certain: %v %v %s", c.direct, c.recursive, c.typ.Type().String()) +} + +func (*nothing) empty() bool { return true } -func (n *nothing) get(*sqlparser.ColName) (dependency, error) { +func (*nothing) get(*sqlparser.ColName) (dependency, error) { return dependency{certain: true}, nil } -func (n *nothing) merge(d dependencies, _ bool) dependencies { +func (*nothing) merge(d dependencies, _ bool) dependencies { return d } + +func (*nothing) debugString() string { + return "nothing" +} diff --git a/go/vt/vtgate/semantics/derived_table.go b/go/vt/vtgate/semantics/derived_table.go index aabbe9f0b22..fc7e1cb391c 100644 --- a/go/vt/vtgate/semantics/derived_table.go +++ b/go/vt/vtgate/semantics/derived_table.go @@ -146,7 +146,7 @@ func (dt *DerivedTable) GetAliasedTableExpr() *sqlparser.AliasedTableExpr { } func (dt *DerivedTable) canShortCut() shortCut { - panic(vterrors.VT12001("should not be called")) + return canShortCut } // GetVindexTable implements the TableInfo interface @@ -195,3 +195,8 @@ func (dt *DerivedTable) checkForDuplicates() error { } return nil } + +// GetMirrorRule implements TableInfo. +func (dt *DerivedTable) GetMirrorRule() *vindexes.MirrorRule { + return nil +} diff --git a/go/vt/vtgate/semantics/early_rewriter.go b/go/vt/vtgate/semantics/early_rewriter.go index 568e1900d44..ee12765e984 100644 --- a/go/vt/vtgate/semantics/early_rewriter.go +++ b/go/vt/vtgate/semantics/early_rewriter.go @@ -57,11 +57,27 @@ func (r *earlyRewriter) down(cursor *sqlparser.Cursor) error { case *sqlparser.ComparisonExpr: return handleComparisonExpr(cursor, node) case *sqlparser.With: - return r.handleWith(node) + if !node.Recursive { + return r.handleWith(node) + } case *sqlparser.AliasedTableExpr: 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 } @@ -130,7 +146,7 @@ func (r *earlyRewriter) handleAliasedTable(node *sqlparser.AliasedTableExpr) err node.As = tbl.Name } node.Expr = &sqlparser.DerivedTable{ - Select: cte.Subquery.Select, + Select: cte.Subquery, } if len(cte.Columns) > 0 { node.Columns = cte.Columns diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index 81d3ed8c450..fab8211f74e 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -184,6 +184,9 @@ func TestExpandStar(t *testing.T) { // if we are only star-expanding authoritative tables, we don't need to stop the expansion sql: "SELECT * FROM (SELECT t2.*, 12 AS foo FROM t3, t2) as results", expSQL: "select c1, c2, foo from (select t2.c1, t2.c2, 12 as foo from t3, t2) as results", + }, { + sql: "with recursive hierarchy as (select t1.a, t1.b from t1 where t1.a is null union select t1.a, t1.b from t1 join hierarchy on t1.a = hierarchy.b) select * from hierarchy", + expSQL: "with recursive hierarchy as (select t1.a, t1.b from t1 where t1.a is null union select t1.a, t1.b from t1 join hierarchy on t1.a = hierarchy.b) select a, b from hierarchy", }} for _, tcase := range tcases { t.Run(tcase.sql, func(t *testing.T) { @@ -854,6 +857,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/foreign_keys_test.go b/go/vt/vtgate/semantics/foreign_keys_test.go index e1c26ecf569..a46c67c9710 100644 --- a/go/vt/vtgate/semantics/foreign_keys_test.go +++ b/go/vt/vtgate/semantics/foreign_keys_test.go @@ -141,13 +141,10 @@ func TestGetAllManagedForeignKeys(t *testing.T) { { name: "Collect all foreign key constraints", fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t0"], - tbl["t1"], - &DerivedTable{}, - }, - }, + tables: makeTableCollector(nil, + tbl["t0"], + tbl["t1"], + &DerivedTable{}), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -171,12 +168,10 @@ func TestGetAllManagedForeignKeys(t *testing.T) { { name: "keyspace not found in schema information", fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t2"], - tbl["t3"], - }, - }, + tables: makeTableCollector(nil, + tbl["t2"], + tbl["t3"], + ), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -188,12 +183,9 @@ func TestGetAllManagedForeignKeys(t *testing.T) { { name: "Cyclic fk constraints error", fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t0"], tbl["t1"], - &DerivedTable{}, - }, - }, + tables: makeTableCollector(nil, + tbl["t0"], tbl["t1"], + &DerivedTable{}), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -236,17 +228,11 @@ func TestFilterForeignKeysUsingUpdateExpressions(t *testing.T) { }, }, getError: func() error { return fmt.Errorf("ambiguous test error") }, - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t4"], - tbl["t5"], - }, - si: &FakeSI{ - KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ - "ks": vschemapb.Keyspace_managed, - }, - }, - }, + tables: makeTableCollector(&FakeSI{ + KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ + "ks": vschemapb.Keyspace_managed, + }}, tbl["t4"], + tbl["t5"]), } updateExprs := sqlparser.UpdateExprs{ &sqlparser.UpdateExpr{Name: cola, Expr: sqlparser.NewIntLiteral("1")}, @@ -350,12 +336,10 @@ func TestGetInvolvedForeignKeys(t *testing.T) { name: "Delete Query", stmt: &sqlparser.Delete{}, fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t0"], - tbl["t1"], - }, - }, + tables: makeTableCollector(nil, + tbl["t0"], + tbl["t1"], + ), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -389,12 +373,10 @@ func TestGetInvolvedForeignKeys(t *testing.T) { cold: SingleTableSet(1), }, }, - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t4"], - tbl["t5"], - }, - }, + tables: makeTableCollector(nil, + tbl["t4"], + tbl["t5"], + ), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -433,12 +415,10 @@ func TestGetInvolvedForeignKeys(t *testing.T) { Action: sqlparser.ReplaceAct, }, fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t0"], - tbl["t1"], - }, - }, + tables: makeTableCollector(nil, + tbl["t0"], + tbl["t1"], + ), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -465,12 +445,9 @@ func TestGetInvolvedForeignKeys(t *testing.T) { Action: sqlparser.InsertAct, }, fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t0"], - tbl["t1"], - }, - }, + tables: makeTableCollector(nil, + tbl["t0"], + tbl["t1"]), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -502,12 +479,9 @@ func TestGetInvolvedForeignKeys(t *testing.T) { colb: SingleTableSet(0), }, }, - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t6"], - tbl["t1"], - }, - }, + tables: makeTableCollector(nil, + tbl["t6"], + tbl["t1"]), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -536,12 +510,9 @@ func TestGetInvolvedForeignKeys(t *testing.T) { name: "Insert error", stmt: &sqlparser.Insert{}, fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t2"], - tbl["t3"], - }, - }, + tables: makeTableCollector(nil, + tbl["t2"], + tbl["t3"]), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -554,12 +525,9 @@ func TestGetInvolvedForeignKeys(t *testing.T) { name: "Update error", stmt: &sqlparser.Update{}, fkManager: &fkManager{ - tables: &tableCollector{ - Tables: []TableInfo{ - tbl["t2"], - tbl["t3"], - }, - }, + tables: makeTableCollector(nil, + tbl["t2"], + tbl["t3"]), si: &FakeSI{ KsForeignKeyMode: map[string]vschemapb.Keyspace_ForeignKeyMode{ "ks": vschemapb.Keyspace_managed, @@ -600,3 +568,12 @@ func pkInfo(parentTable *vindexes.Table, pCols []string, cCols []string) vindexe ChildColumns: sqlparser.MakeColumns(cCols...), } } + +func makeTableCollector(si SchemaInformation, tables ...TableInfo) *tableCollector { + return &tableCollector{ + earlyTableCollector: earlyTableCollector{ + Tables: tables, + si: si, + }, + } +} diff --git a/go/vt/vtgate/semantics/info_schema.go b/go/vt/vtgate/semantics/info_schema.go index 11e577f3fa7..127f4a00960 100644 --- a/go/vt/vtgate/semantics/info_schema.go +++ b/go/vt/vtgate/semantics/info_schema.go @@ -1603,11 +1603,15 @@ type infoSchemaWithColumns struct { infoSchemaData map[string][]vindexes.Column } +var _ SchemaInformation = (*infoSchemaWithColumns)(nil) + // MySQLVersion implements SchemaInformation. // We cache this information, since these are maps that are not changed -var infoSchema57 = getInfoSchema57() -var infoSchema80 = getInfoSchema80() +var ( + infoSchema57 = getInfoSchema57() + infoSchema80 = getInfoSchema80() +) // newSchemaInfo returns a SchemaInformation that has the column information for all info_schema tables func newSchemaInfo(inner SchemaInformation) SchemaInformation { @@ -1665,3 +1669,8 @@ func (i *infoSchemaWithColumns) KeyspaceError(keyspace string) error { func (i *infoSchemaWithColumns) GetAggregateUDFs() []string { return i.inner.GetAggregateUDFs() } + +// FindMirrorRule implements SchemaInformation. +func (i *infoSchemaWithColumns) FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) { + return i.inner.FindMirrorRule(tablename) +} diff --git a/go/vt/vtgate/semantics/real_table.go b/go/vt/vtgate/semantics/real_table.go index 4f1639d0897..64f3ac5f3f0 100644 --- a/go/vt/vtgate/semantics/real_table.go +++ b/go/vt/vtgate/semantics/real_table.go @@ -20,9 +20,11 @@ import ( "strings" "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/slice" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/evalengine" "vitess.io/vitess/go/vt/vtgate/vindexes" ) @@ -31,26 +33,41 @@ type RealTable struct { dbName, tableName string ASTNode *sqlparser.AliasedTableExpr Table *vindexes.Table + CTE *CTE VindexHint *sqlparser.IndexHint + MirrorRule *vindexes.MirrorRule isInfSchema bool collationEnv *collations.Environment + cache map[string]dependencies } var _ TableInfo = (*RealTable)(nil) // dependencies implements the TableInfo interface -func (r *RealTable) dependencies(colName string, org originable) (dependencies, error) { - ts := org.tableSetFor(r.ASTNode) - for _, info := range r.getColumns(false /* ignoreInvisbleCol */) { - if strings.EqualFold(info.Name, colName) { - return createCertain(ts, ts, info.Type), nil +func (r *RealTable) dependencies(colName string, org originable) (deps dependencies, err error) { + var myID *TableSet + if r.cache == nil { + r.cache = make(map[string]dependencies) + ts := org.tableSetFor(r.ASTNode) + myID = &ts + for _, info := range r.getColumns(false /* ignoreInvisbleCol */) { + r.cache[strings.ToLower(info.Name)] = createCertain(ts, ts, info.Type) } } + if deps, ok := r.cache[strings.ToLower(colName)]; ok { + return deps, nil + } + if r.authoritative() { return ¬hing{}, nil } - return createUncertain(ts, ts), nil + + if myID == nil { + ts := org.tableSetFor(r.ASTNode) + myID = &ts + } + return createUncertain(*myID, *myID), nil } // GetTables implements the TableInfo interface @@ -70,9 +87,17 @@ func (r *RealTable) IsInfSchema() bool { // GetColumns implements the TableInfo interface func (r *RealTable) getColumns(ignoreInvisbleCol bool) []ColumnInfo { - if r.Table == nil { + switch { + case r.CTE != nil: + return r.getCTEColumns() + case r.Table == nil: return nil + default: + return r.getVindexTableColumns(ignoreInvisbleCol) } +} + +func (r *RealTable) getVindexTableColumns(ignoreInvisbleCol bool) []ColumnInfo { nameMap := map[string]any{} cols := make([]ColumnInfo, 0, len(r.Table.Columns)) for _, col := range r.Table.Columns { @@ -105,6 +130,57 @@ func (r *RealTable) getColumns(ignoreInvisbleCol bool) []ColumnInfo { return cols } +func (r *RealTable) getCTEColumns() []ColumnInfo { + selectExprs := r.CTE.Query.GetColumns() + ci := extractColumnsFromCTE(r.CTE.Columns, selectExprs) + if ci != nil { + return ci + } + return extractSelectExprsFromCTE(selectExprs) +} + +// Authoritative implements the TableInfo interface +func (r *RealTable) authoritative() bool { + switch { + case r.Table != nil: + return r.Table.ColumnListAuthoritative + case r.CTE != nil: + return r.CTE.isAuthoritative + default: + return false + } +} + +func extractSelectExprsFromCTE(selectExprs sqlparser.SelectExprs) []ColumnInfo { + var ci []ColumnInfo + for _, expr := range selectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + return nil + } + ci = append(ci, ColumnInfo{ + Name: ae.ColumnName(), + Type: evalengine.NewUnknownType(), // TODO: set the proper type + }) + } + return ci +} + +func extractColumnsFromCTE(columns sqlparser.Columns, selectExprs sqlparser.SelectExprs) []ColumnInfo { + if len(columns) == 0 { + return nil + } + if len(selectExprs) != len(columns) { + panic("mismatch of columns") + } + return slice.Map(columns, func(from sqlparser.IdentifierCI) ColumnInfo { + return ColumnInfo{ + Name: from.String(), + Type: evalengine.NewUnknownType(), + } + }) +} + // GetExpr implements the TableInfo interface func (r *RealTable) GetAliasedTableExpr() *sqlparser.AliasedTableExpr { return r.ASTNode @@ -145,12 +221,12 @@ func (r *RealTable) Name() (sqlparser.TableName, error) { return r.ASTNode.TableName() } -// Authoritative implements the TableInfo interface -func (r *RealTable) authoritative() bool { - return r.Table != nil && r.Table.ColumnListAuthoritative -} - // Matches implements the TableInfo interface func (r *RealTable) matches(name sqlparser.TableName) bool { return (name.Qualifier.IsEmpty() || name.Qualifier.String() == r.dbName) && r.tableName == name.Name.String() } + +// GetMirrorRule implements TableInfo. +func (r *RealTable) GetMirrorRule() *vindexes.MirrorRule { + return r.MirrorRule +} diff --git a/go/vt/vtgate/semantics/scoper.go b/go/vt/vtgate/semantics/scoper.go index ae3e5b7e88d..9d596d9ecd1 100644 --- a/go/vt/vtgate/semantics/scoper.go +++ b/go/vt/vtgate/semantics/scoper.go @@ -35,9 +35,10 @@ type ( binder *binder // These scopes are only used for rewriting ORDER BY 1 and GROUP BY 1 - specialExprScopes map[*sqlparser.Literal]*scope - statementIDs map[sqlparser.Statement]TableSet - si SchemaInformation + specialExprScopes map[*sqlparser.Literal]*scope + statementIDs map[sqlparser.Statement]TableSet + commonTableExprScopes []*sqlparser.CommonTableExpr + si SchemaInformation } scope struct { @@ -105,6 +106,8 @@ func (s *scoper) down(cursor *sqlparser.Cursor) error { s.currentScope().inHaving = true return nil } + case *sqlparser.CommonTableExpr: + s.commonTableExprScopes = append(s.commonTableExprScopes, node) } return nil } @@ -240,6 +243,9 @@ func (s *scoper) up(cursor *sqlparser.Cursor) error { case sqlparser.AggrFunc: s.currentScope().inHavingAggr = false case sqlparser.TableExpr: + // inside joins and derived tables, we can only see the tables in the table/join. + // we also want the tables available in the outer query, for SELECT expressions and the WHERE clause, + // so we copy the tables from the current scope to the parent scope if isParentSelect(cursor) { curScope := s.currentScope() s.popScope() @@ -258,6 +264,8 @@ func (s *scoper) up(cursor *sqlparser.Cursor) error { s.binder.usingJoinInfo[ts] = m } } + case *sqlparser.CommonTableExpr: + s.commonTableExprScopes = s.commonTableExprScopes[:len(s.commonTableExprScopes)-1] } return nil } @@ -367,7 +375,7 @@ func checkForInvalidAliasUse(cte *sqlparser.CommonTableExpr, name string) (err e } return err == nil } - _ = sqlparser.CopyOnRewrite(cte.Subquery.Select, down, nil, nil) + _ = sqlparser.CopyOnRewrite(cte.Subquery, down, nil, nil) return err } diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_table.go similarity index 94% rename from go/vt/vtgate/semantics/semantic_state.go rename to go/vt/vtgate/semantics/semantic_table.go index ac2fd9c1604..f9856a901a6 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_table.go @@ -63,6 +63,9 @@ type ( dependencies(colName string, org originable) (dependencies, error) getExprFor(s string) (sqlparser.Expr, error) getTableSet(org originable) TableSet + + // GetMirrorRule returns the vschema mirror rule for this TableInfo + GetMirrorRule() *vindexes.MirrorRule } // ColumnInfo contains information about columns @@ -77,12 +80,19 @@ type ( // QuerySignature is used to identify shortcuts in the planning process QuerySignature struct { - Aggregation bool - DML bool - Distinct bool - HashJoin bool - SubQueries bool - Union bool + Aggregation bool + DML bool + Distinct bool + HashJoin bool + SubQueries bool + Union bool + RecursiveCTE bool + } + + // MirrorInfo stores information used to produce mirror + // operators. + MirrorInfo struct { + Percent float32 } // SemTable contains semantic analysis information about the query. @@ -162,6 +172,7 @@ type ( GetForeignKeyChecksState() *bool KeyspaceError(keyspace string) error GetAggregateUDFs() []string + FindMirrorRule(tablename sqlparser.TableName) (*vindexes.MirrorRule, error) } shortCut = int @@ -173,10 +184,8 @@ const ( dependsOnKeyspace ) -var ( - // ErrNotSingleTable refers to an error happening when something should be used only for single tables - ErrNotSingleTable = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] should only be used for single tables") -) +// ErrNotSingleTable refers to an error happening when something should be used only for single tables +var ErrNotSingleTable = vterrors.VT13001("should only be used for single tables") // CopyDependencies copies the dependencies from one expression into the other func (st *SemTable) CopyDependencies(from, to sqlparser.Expr) { @@ -733,7 +742,6 @@ func RewriteDerivedTableExpression(expr sqlparser.Expr, vt TableInfo) sqlparser. col := *node col.Qualifier = sqlparser.TableName{} cursor.Replace(&col) - }, nil).(sqlparser.Expr) } @@ -773,10 +781,6 @@ func singleUnshardedKeyspace(tableInfos []TableInfo) (ks *vindexes.Keyspace, tab } for _, table := range tableInfos { - if _, isDT := table.(*DerivedTable); isDT { - continue - } - sc := table.canShortCut() var vtbl *vindexes.Table @@ -800,6 +804,7 @@ func singleUnshardedKeyspace(tableInfos []TableInfo) (ks *vindexes.Keyspace, tab tables = append(tables, vtbl) } + return ks, tables } @@ -983,3 +988,45 @@ func (st *SemTable) NewTableId() TableSet { st.Tables = append(st.Tables, nil) return tableID } + +func (st *SemTable) CanTakeSelectUnshardedShortcut() (*vindexes.Keyspace, bool) { + return canTakeSelectUnshardedShortcut(st.Tables) +} + +func (st *SemTable) CanTakeUnshardedShortcut() (*vindexes.Keyspace, bool) { + return canTakeUnshardedShortcut(st.Tables) +} + +func canTakeUnshardedShortcut(tableInfos []TableInfo) (*vindexes.Keyspace, bool) { + uks, _ := singleUnshardedKeyspace(tableInfos) + return uks, uks != nil +} + +func canTakeSelectUnshardedShortcut(tableInfos []TableInfo) (*vindexes.Keyspace, bool) { + if mi := mirrorInfo(tableInfos); mi.Percent > 0 { + return nil, false + } + return canTakeUnshardedShortcut(tableInfos) +} + +func (st *SemTable) GetMirrorInfo() MirrorInfo { + return mirrorInfo(st.Tables) +} + +// mirrorInfo looks through all tables with mirror rules defined, and returns a +// MirrorInfo containing the lowest mirror percentage found across all rules. +// +// The idea here is that if you have two tables with mirror rules both involved +// in a query, and one of those rules is 1% while the other is 100%, to mirror +// the query with 1% chance. +func mirrorInfo(tableInfos []TableInfo) MirrorInfo { + mi := MirrorInfo{} + for _, t := range tableInfos { + if mr := t.GetMirrorRule(); mr != nil { + if mi.Percent == 0 || mr.Percent < mi.Percent { + mi.Percent = mr.Percent + } + } + } + return mi +} diff --git a/go/vt/vtgate/semantics/semantic_state_test.go b/go/vt/vtgate/semantics/semantic_table_test.go similarity index 99% rename from go/vt/vtgate/semantics/semantic_state_test.go rename to go/vt/vtgate/semantics/semantic_table_test.go index 84f8cec6cf9..1f324215326 100644 --- a/go/vt/vtgate/semantics/semantic_state_test.go +++ b/go/vt/vtgate/semantics/semantic_table_test.go @@ -464,7 +464,7 @@ func TestRemoveParentForeignKey(t *testing.T) { }, }, }, - expectedErr: "[BUG] should only be used for single tables", + expectedErr: "VT13001: [BUG] should only be used for single tables", }, } for _, tt := range tests { @@ -716,7 +716,7 @@ func TestRemoveNonRequiredForeignKeys(t *testing.T) { SingleTableSet(0).Merge(SingleTableSet(1)): {}, }, }, - expectedErr: "[BUG] should only be used for single tables", + expectedErr: "VT13001: [BUG] should only be used for single tables", }, { name: "Error - Reading table info for child foreign keys", @@ -734,7 +734,7 @@ func TestRemoveNonRequiredForeignKeys(t *testing.T) { }, parentForeignKeysInvolved: map[TableSet][]vindexes.ParentFKInfo{}, }, - expectedErr: "[BUG] should only be used for single tables", + expectedErr: "VT13001: [BUG] should only be used for single tables", }, } for _, tt := range tests { diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index 948edb37d47..191d9c3b38e 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -28,45 +28,59 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -// tableCollector is responsible for gathering information about the tables listed in the FROM clause, -// and adding them to the current scope, plus keeping the global list of tables used in the query -type tableCollector struct { - Tables []TableInfo - scoper *scoper - si SchemaInformation - currentDb string - org originable - unionInfo map[*sqlparser.Union]unionInfo - done map[*sqlparser.AliasedTableExpr]TableInfo -} +type ( + // tableCollector is responsible for gathering information about the tables listed in the FROM clause, + // and adding them to the current scope, plus keeping the global list of tables used in the query + tableCollector struct { + earlyTableCollector + scoper *scoper + org originable + unionInfo map[*sqlparser.Union]unionInfo + } -type earlyTableCollector struct { - si SchemaInformation - currentDb string - Tables []TableInfo - done map[*sqlparser.AliasedTableExpr]TableInfo - withTables map[sqlparser.IdentifierCS]any -} + earlyTableCollector struct { + si SchemaInformation + currentDb string + Tables []TableInfo + done map[*sqlparser.AliasedTableExpr]TableInfo + + // cte is a map of CTE definitions that are used in the query + cte map[string]*CTE + } +) func newEarlyTableCollector(si SchemaInformation, currentDb string) *earlyTableCollector { return &earlyTableCollector{ - si: si, - currentDb: currentDb, - done: map[*sqlparser.AliasedTableExpr]TableInfo{}, - withTables: map[sqlparser.IdentifierCS]any{}, + si: si, + currentDb: currentDb, + done: map[*sqlparser.AliasedTableExpr]TableInfo{}, + cte: map[string]*CTE{}, } } -func (etc *earlyTableCollector) up(cursor *sqlparser.Cursor) { - switch node := cursor.Node().(type) { - case *sqlparser.AliasedTableExpr: - etc.visitAliasedTableExpr(node) - case *sqlparser.With: - for _, cte := range node.CTEs { - etc.withTables[cte.ID] = nil +func (etc *earlyTableCollector) down(cursor *sqlparser.Cursor) bool { + with, ok := cursor.Node().(*sqlparser.With) + if !ok { + return true + } + for _, cte := range with.CTEs { + etc.cte[cte.ID.String()] = &CTE{ + Name: cte.ID.String(), + Query: cte.Subquery, + Columns: cte.Columns, + Recursive: with.Recursive, } } + return true +} +func (etc *earlyTableCollector) up(cursor *sqlparser.Cursor) bool { + ate, ok := cursor.Node().(*sqlparser.AliasedTableExpr) + if !ok { + return true + } + etc.visitAliasedTableExpr(ate) + return true } func (etc *earlyTableCollector) visitAliasedTableExpr(aet *sqlparser.AliasedTableExpr) { @@ -79,25 +93,22 @@ func (etc *earlyTableCollector) visitAliasedTableExpr(aet *sqlparser.AliasedTabl func (etc *earlyTableCollector) newTableCollector(scoper *scoper, org originable) *tableCollector { return &tableCollector{ - Tables: etc.Tables, - scoper: scoper, - si: etc.si, - currentDb: etc.currentDb, - unionInfo: map[*sqlparser.Union]unionInfo{}, - done: etc.done, - org: org, + earlyTableCollector: *etc, + scoper: scoper, + unionInfo: map[*sqlparser.Union]unionInfo{}, + org: org, } } func (etc *earlyTableCollector) handleTableName(tbl sqlparser.TableName, aet *sqlparser.AliasedTableExpr) { if tbl.Qualifier.IsEmpty() { - _, isCTE := etc.withTables[tbl.Name] + _, isCTE := etc.cte[tbl.Name.String()] if isCTE { // no need to handle these tables here, we wait for the late phase instead return } } - tableInfo, err := getTableInfo(aet, tbl, etc.si, etc.currentDb) + tableInfo, err := etc.getTableInfo(aet, tbl, nil) if err != nil { // this could just be a CTE that we haven't processed, so we'll give it the benefit of the doubt for now return @@ -304,7 +315,7 @@ func (tc *tableCollector) handleTableName(node *sqlparser.AliasedTableExpr, t sq tableInfo, found = tc.done[node] if !found { - tableInfo, err = getTableInfo(node, t, tc.si, tc.currentDb) + tableInfo, err = tc.earlyTableCollector.getTableInfo(node, t, tc.scoper) if err != nil { return err } @@ -315,12 +326,32 @@ func (tc *tableCollector) handleTableName(node *sqlparser.AliasedTableExpr, t sq return scope.addTable(tableInfo) } -func getTableInfo(node *sqlparser.AliasedTableExpr, t sqlparser.TableName, si SchemaInformation, currentDb string) (TableInfo, error) { +func (etc *earlyTableCollector) getCTE(t sqlparser.TableName) *CTE { + if t.Qualifier.NotEmpty() { + return nil + } + + return etc.cte[t.Name.String()] +} + +func (etc *earlyTableCollector) getTableInfo(node *sqlparser.AliasedTableExpr, t sqlparser.TableName, sc *scoper) (TableInfo, error) { var tbl *vindexes.Table var vindex vindexes.Vindex + if cteDef := etc.getCTE(t); cteDef != nil { + cte, err := etc.buildRecursiveCTE(node, t, sc, cteDef) + if err != nil { + return nil, err + } + if cte != nil { + // if we didn't get a table, it means we can't build a recursive CTE, + // so we need to look for a regular table instead + return cte, nil + } + } + isInfSchema := sqlparser.SystemSchema(t.Qualifier.String()) var err error - tbl, vindex, _, _, _, err = si.FindTableOrVindex(t) + tbl, vindex, _, _, _, err = etc.si.FindTableOrVindex(t) if err != nil && !isInfSchema { // if we are dealing with a system table, it might not be available in the vschema, but that is OK return nil, err @@ -329,13 +360,64 @@ func getTableInfo(node *sqlparser.AliasedTableExpr, t sqlparser.TableName, si Sc tbl = newVindexTable(t.Name) } - tableInfo, err := createTable(t, node, tbl, isInfSchema, vindex, si, currentDb) + tableInfo, err := etc.createTable(t, node, tbl, isInfSchema, vindex) if err != nil { return nil, err } return tableInfo, nil } +func (etc *earlyTableCollector) buildRecursiveCTE(node *sqlparser.AliasedTableExpr, t sqlparser.TableName, sc *scoper, cteDef *CTE) (TableInfo, error) { + // If sc is nil, then we are in the early table collector. + // In early table collector, we don't go over the CTE definitions, so we must be seeing a usage of the CTE. + if sc != nil && len(sc.commonTableExprScopes) > 0 { + cte := sc.commonTableExprScopes[len(sc.commonTableExprScopes)-1] + if cte.ID.String() == t.Name.String() { + + if err := checkValidRecursiveCTE(cteDef); err != nil { + return nil, err + } + + cteTable := newCTETable(node, t, cteDef) + cteTableSet := SingleTableSet(len(etc.Tables)) + cteDef.IDForRecurse = &cteTableSet + if !cteDef.Recursive { + return nil, nil + } + return cteTable, nil + } + } + return &RealTable{ + tableName: node.TableNameString(), + ASTNode: node, + CTE: cteDef, + collationEnv: etc.si.Environment().CollationEnv(), + }, nil +} + +func checkValidRecursiveCTE(cteDef *CTE) error { + if cteDef.IDForRecurse != nil { + return vterrors.VT09029(cteDef.Name) + } + + union, isUnion := cteDef.Query.(*sqlparser.Union) + if !isUnion { + return vterrors.VT09026(cteDef.Name) + } + + firstSelect := sqlparser.GetFirstSelect(union.Right) + if firstSelect.GroupBy != nil { + return vterrors.VT09027(cteDef.Name) + } + + for _, expr := range firstSelect.GetColumns() { + if sqlparser.ContainsAggregation(expr) { + return vterrors.VT09027(cteDef.Name) + } + } + return nil +} + func (tc *tableCollector) handleDerivedTable(node *sqlparser.AliasedTableExpr, t *sqlparser.DerivedTable) error { switch sel := t.Select.(type) { case *sqlparser.Select: @@ -437,14 +519,12 @@ func (tc *tableCollector) tableInfoFor(id TableSet) (TableInfo, error) { return tc.Tables[offset], nil } -func createTable( +func (etc *earlyTableCollector) createTable( t sqlparser.TableName, alias *sqlparser.AliasedTableExpr, tbl *vindexes.Table, isInfSchema bool, vindex vindexes.Vindex, - si SchemaInformation, - currentDb string, ) (TableInfo, error) { hint := getVindexHint(alias.Hints) @@ -452,19 +532,28 @@ func createTable( return nil, err } + mr, err := etc.si.FindMirrorRule(t) + if err != nil { + // Mirroring is best effort. If we get an error while mirroring, keep going + // as if mirroring was disabled. We don't want to interrupt production work + // because of an issue with mirroring. + mr = nil + } + table := &RealTable{ tableName: alias.As.String(), ASTNode: alias, Table: tbl, VindexHint: hint, + MirrorRule: mr, isInfSchema: isInfSchema, - collationEnv: si.Environment().CollationEnv(), + collationEnv: etc.si.Environment().CollationEnv(), } if alias.As.IsEmpty() { dbName := t.Qualifier.String() if dbName == "" { - dbName = currentDb + dbName = etc.currentDb } table.dbName = dbName diff --git a/go/vt/vtgate/semantics/vindex_table.go b/go/vt/vtgate/semantics/vindex_table.go index b598c93f36a..c8ef271af5d 100644 --- a/go/vt/vtgate/semantics/vindex_table.go +++ b/go/vt/vtgate/semantics/vindex_table.go @@ -84,3 +84,8 @@ func (v *VindexTable) getColumns(ignoreInvisbleCol bool) []ColumnInfo { func (v *VindexTable) IsInfSchema() bool { return v.Table.IsInfSchema() } + +// GetMirrorRule implements TableInfo. +func (v *VindexTable) GetMirrorRule() *vindexes.MirrorRule { + return nil +} diff --git a/go/vt/vtgate/semantics/vtable.go b/go/vt/vtgate/semantics/vtable.go index 14519a7e938..6cd7e34aecc 100644 --- a/go/vt/vtgate/semantics/vtable.go +++ b/go/vt/vtgate/semantics/vtable.go @@ -175,3 +175,8 @@ func selectExprsToInfos( } return } + +// GetMirrorRule implements TableInfo. +func (v *vTableInfo) GetMirrorRule() *vindexes.MirrorRule { + return nil +} diff --git a/go/vt/vtgate/tx_conn.go b/go/vt/vtgate/tx_conn.go index 2eccdc54992..714644967cb 100644 --- a/go/vt/vtgate/tx_conn.go +++ b/go/vt/vtgate/tx_conn.go @@ -26,14 +26,13 @@ import ( "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 @@ -60,6 +59,16 @@ var txAccessModeToEOTxAccessMode = map[sqlparser.TxAccessMode]querypb.ExecuteOpt sqlparser.ReadOnly: querypb.ExecuteOptions_READ_ONLY, } +type commitPhase int + +const ( + Commit2pcCreateTransaction commitPhase = iota + Commit2pcPrepare + Commit2pcStartCommit + Commit2pcPrepareCommit + Commit2pcConclude +) + // Begin begins a new transaction. If one is already in progress, it commits it // and starts a new one. func (txc *TxConn) Begin(ctx context.Context, session *SafeSession, txAccessModes []sqlparser.TxAccessMode) error { @@ -177,7 +186,7 @@ func (txc *TxConn) commitNormal(ctx context.Context, session *SafeSession) error } // commit2PC will not used the pinned tablets - to make sure we use the current source, we need to use the gateway's queryservice -func (txc *TxConn) commit2PC(ctx context.Context, session *SafeSession) error { +func (txc *TxConn) commit2PC(ctx context.Context, session *SafeSession) (err error) { if len(session.PreSessions) != 0 || len(session.PostSessions) != 0 { _ = txc.Rollback(ctx, session) return vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "pre or post actions not allowed for 2PC commits") @@ -188,45 +197,118 @@ func (txc *TxConn) commit2PC(ctx context.Context, session *SafeSession) error { return txc.commitNormal(ctx, session) } - participants := make([]*querypb.Target, 0, len(session.ShardSessions)-1) - for _, s := range session.ShardSessions[1:] { - participants = append(participants, s.Target) - } mmShard := session.ShardSessions[0] + rmShards := session.ShardSessions[1:] dtid := dtids.New(mmShard) - err := txc.tabletGateway.CreateTransaction(ctx, mmShard.Target, dtid, participants) - if err != nil { - // Normal rollback is safe because nothing was prepared yet. - _ = txc.Rollback(ctx, session) + participants := make([]*querypb.Target, len(rmShards)) + for i, s := range rmShards { + participants[i] = s.Target + } + + var txPhase commitPhase + defer func() { + if err == nil { + return + } + txc.errActionAndLogWarn(ctx, session, txPhase, dtid, mmShard, rmShards) + }() + + txPhase = Commit2pcCreateTransaction + if err = txc.tabletGateway.CreateTransaction(ctx, mmShard.Target, dtid, participants); err != nil { return err } - err = txc.runSessions(ctx, session.ShardSessions[1:], session.logging, func(ctx context.Context, s *vtgatepb.Session_ShardSession, logging *executeLogger) error { - 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 { - log.Warningf("Rollback failed after Prepare failure: %v", resumeErr) + if DebugTwoPc { // Test code to simulate a failure after RM prepare + if terr := checkTestFailure(ctx, "TRCreated_FailNow", nil); terr != nil { + return terr } - // Return the original error even if the previous operation fails. + } + + txPhase = Commit2pcPrepare + prepareAction := func(ctx context.Context, s *vtgatepb.Session_ShardSession, logging *executeLogger) error { + if DebugTwoPc { // Test code to simulate a failure during RM prepare + if terr := checkTestFailure(ctx, "RMPrepare_-40_FailNow", s.Target); terr != nil { + return terr + } + } + return txc.tabletGateway.Prepare(ctx, s.Target, s.TransactionId, dtid) + } + if err = txc.runSessions(ctx, rmShards, session.logging, prepareAction); err != nil { return err } + if DebugTwoPc { // Test code to simulate a failure after RM prepare + if terr := checkTestFailure(ctx, "RMPrepared_FailNow", nil); terr != nil { + return terr + } + } + + txPhase = Commit2pcStartCommit err = txc.tabletGateway.StartCommit(ctx, mmShard.Target, mmShard.TransactionId, dtid) if err != nil { 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 after MM commit + if terr := checkTestFailure(ctx, "MMCommitted_FailNow", nil); terr != nil { + return terr + } + } + + txPhase = Commit2pcPrepareCommit + prepareCommitAction := func(ctx context.Context, s *vtgatepb.Session_ShardSession, logging *executeLogger) error { + if DebugTwoPc { // Test code to simulate a failure during RM prepare + if terr := checkTestFailure(ctx, "RMCommit_-40_FailNow", s.Target); terr != nil { + return terr + } + } return txc.tabletGateway.CommitPrepared(ctx, s.Target, dtid) - }) - if err != nil { + } + if err = txc.runSessions(ctx, rmShards, session.logging, prepareCommitAction); err != nil { return err } - return txc.tabletGateway.ConcludeTransaction(ctx, mmShard.Target, dtid) + // At this point, application can continue forward. + // The transaction is already committed. + // This step is to clean up the transaction metadata. + txPhase = Commit2pcConclude + _ = txc.tabletGateway.ConcludeTransaction(ctx, mmShard.Target, dtid) + return nil +} + +func (txc *TxConn) errActionAndLogWarn(ctx context.Context, session *SafeSession, txPhase commitPhase, dtid string, mmShard *vtgatepb.Session_ShardSession, rmShards []*vtgatepb.Session_ShardSession) { + switch txPhase { + case Commit2pcCreateTransaction: + // Normal rollback is safe because nothing was prepared yet. + if rollbackErr := txc.Rollback(ctx, session); rollbackErr != nil { + log.Warningf("Rollback failed after Create Transaction failure: %v", rollbackErr) + } + case Commit2pcPrepare: + // Rollback the prepared and unprepared transactions. + if resumeErr := txc.rollbackTx(ctx, dtid, mmShard, rmShards, session.logging); resumeErr != nil { + log.Warningf("Rollback failed after Prepare failure: %v", resumeErr) + } + } + session.RecordWarning(&querypb.QueryWarning{ + Code: uint32(sqlerror.ERInAtomicRecovery), + Message: createWarningMessage(dtid, txPhase)}) +} + +func createWarningMessage(dtid string, txPhase commitPhase) string { + warningMsg := fmt.Sprintf("%s distributed transaction ID failed during", dtid) + switch txPhase { + case Commit2pcCreateTransaction: + warningMsg += " transaction record creation; rollback attempted; conclude on recovery" + case Commit2pcPrepare: + warningMsg += " transaction prepare phase; prepare transaction rollback attempted; conclude on recovery" + case Commit2pcStartCommit: + warningMsg += " metadata manager commit; transaction will be committed/rollbacked based on the state on recovery" + case Commit2pcPrepareCommit: + warningMsg += " resource manager commit; transaction will be committed on recovery" + case Commit2pcConclude: + warningMsg += " transaction conclusion" + } + return warningMsg } // Rollback rolls back the current transaction. There are no retries on this operation. @@ -343,48 +425,85 @@ 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: // Should never happen. - return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "invalid state: %v", transaction.State) + return vterrors.VT13001(fmt.Sprintf("invalid state: %v", transaction.State)) } return nil } +// rollbackTx rollbacks the specified distributed transaction. +// Rollbacks happens on the metadata manager and all participants irrespective of the failure. +func (txc *TxConn) rollbackTx(ctx context.Context, dtid string, mmShard *vtgatepb.Session_ShardSession, participants []*vtgatepb.Session_ShardSession, logging *executeLogger) error { + var errs []error + if mmErr := txc.rollbackMM(ctx, dtid, mmShard); mmErr != nil { + errs = append(errs, mmErr) + } + if rmErr := 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) + }); rmErr != nil { + errs = append(errs, rmErr) + } + if err := vterrors.Aggregate(errs); err != nil { + return err + } + return txc.tabletGateway.ConcludeTransaction(ctx, mmShard.Target, dtid) + +} + +func (txc *TxConn) rollbackMM(ctx context.Context, dtid string, mmShard *vtgatepb.Session_ShardSession) error { + qs, err := txc.queryService(ctx, mmShard.TabletAlias) + if err != nil { + return err + } + return qs.SetRollback(ctx, mmShard.Target, dtid, mmShard.TransactionId) +} + 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 +566,27 @@ 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) +} + +func (txc *TxConn) UnresolvedTransactions(ctx context.Context, targets []*querypb.Target) ([]*querypb.TransactionMetadata, error) { + var tmList []*querypb.TransactionMetadata + var mu sync.Mutex + err := txc.runTargets(targets, func(target *querypb.Target) error { + res, err := txc.tabletGateway.UnresolvedTransactions(ctx, target) + if err != nil { + return err + } + mu.Lock() + defer mu.Unlock() + tmList = append(tmList, res...) + return nil + }) + return tmList, err +} diff --git a/go/vt/vtgate/tx_conn_test.go b/go/vt/vtgate/tx_conn_test.go index 4d77ea16c92..ed977b75051 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) { @@ -1085,9 +1090,7 @@ func TestTxConnCommit2PCConcludeTransactionFail(t *testing.T) { sbc0.MustFailConcludeTransaction = 1 session.TransactionMode = vtgatepb.TransactionMode_TWOPC err := sc.txConn.Commit(ctx, session) - want := "error: err" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Commit") + require.NoError(t, err) // ConcludeTransaction is best-effort as it does not impact the outcome. assert.EqualValues(t, 1, sbc0.CreateTransactionCount.Load(), "sbc0.CreateTransactionCount") assert.EqualValues(t, 1, sbc1.PrepareCount.Load(), "sbc1.PrepareCount") assert.EqualValues(t, 1, sbc0.StartCommitCount.Load(), "sbc0.StartCommitCount") @@ -1179,14 +1182,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 +1204,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 +1218,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 +1227,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 +1241,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 +1250,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 +1296,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 +1308,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 +1318,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 +1331,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 +1347,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 +1360,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 +1375,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 +1388,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 +1402,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 +1415,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..d7a426e41d4 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -58,10 +58,12 @@ import ( "vitess.io/vitess/go/vt/vtgate/vtgateservice" ) -var _ engine.VCursor = (*vcursorImpl)(nil) -var _ plancontext.VSchema = (*vcursorImpl)(nil) -var _ iExecute = (*Executor)(nil) -var _ vindexes.VCursor = (*vcursorImpl)(nil) +var ( + _ engine.VCursor = (*vcursorImpl)(nil) + _ plancontext.VSchema = (*vcursorImpl)(nil) + _ iExecute = (*Executor)(nil) + _ vindexes.VCursor = (*vcursorImpl)(nil) +) // vcursor_impl needs these facilities to be able to be able to execute queries for vindexes type iExecute interface { @@ -86,6 +88,8 @@ 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) + UnresolvedTransactions(ctx context.Context, targets []*querypb.Target) ([]*querypb.TransactionMetadata, error) } // VSchemaOperator is an interface to Vschema Operations @@ -250,6 +254,27 @@ 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) +} + +// UnresolvedTransactions gets the unresolved transactions for the given keyspace. If the keyspace is not given, +// then we use the default keyspace. +func (vc *vcursorImpl) UnresolvedTransactions(ctx context.Context, keyspace string) ([]*querypb.TransactionMetadata, error) { + if keyspace == "" { + keyspace = vc.GetKeyspace() + } + rss, _, err := vc.ResolveDestinations(ctx, keyspace, nil, []key.Destination{key.DestinationAllShards{}}) + if err != nil { + return nil, err + } + var targets []*querypb.Target + for _, rs := range rss { + targets = append(targets, rs.Target) + } + return vc.executor.UnresolvedTransactions(ctx, targets) +} + // 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) { @@ -814,7 +839,7 @@ func commentedShardQueries(shardQueries []*querypb.BoundQuery, marginComments sq // TargetDestination implements the ContextVSchema interface func (vc *vcursorImpl) TargetDestination(qualifier string) (key.Destination, *vindexes.Keyspace, topodatapb.TabletType, error) { - keyspaceName := vc.keyspace + keyspaceName := vc.getActualKeyspace() if vc.destination == nil && qualifier != "" { keyspaceName = qualifier } @@ -899,7 +924,6 @@ func (vc *vcursorImpl) SetPriority(priority string) { } else if vc.safeSession.Options != nil && vc.safeSession.Options.Priority != "" { vc.safeSession.Options.Priority = "" } - } // SetConsolidator implements the SessionActions interface @@ -1079,6 +1103,23 @@ func (vc *vcursorImpl) GetAggregateUDFs() []string { return vc.vschema.GetAggregateUDFs() } +// FindMirrorRule finds the mirror rule for the requested table name and +// VSchema tablet type. +func (vc *vcursorImpl) FindMirrorRule(name sqlparser.TableName) (*vindexes.MirrorRule, error) { + destKeyspace, destTabletType, _, err := vc.executor.ParseDestinationTarget(name.Qualifier.String()) + if err != nil { + return nil, err + } + if destKeyspace == "" { + destKeyspace = vc.keyspace + } + mirrorRule, err := vc.vschema.FindMirrorRule(destKeyspace, name.Name.String(), destTabletType) + if err != nil { + return nil, err + } + return mirrorRule, err +} + // ParseDestinationTarget parses destination target string and sets default keyspace if possible. func parseDestinationTarget(targetString string, vschema *vindexes.VSchema) (string, topodatapb.TabletType, key.Destination, error) { destKeyspace, destTabletType, dest, err := topoprotopb.ParseDestination(targetString, defaultTabletType) @@ -1139,7 +1180,6 @@ func (vc *vcursorImpl) ExecuteVSchema(ctx context.Context, keyspace string, vsch allowed := vschemaacl.Authorized(user) if !allowed { return vterrors.NewErrorf(vtrpcpb.Code_PERMISSION_DENIED, vterrors.AccessDeniedError, "User '%s' is not authorized to perform vschema operations", user.GetUsername()) - } // Resolve the keyspace either from the table qualifier or the target keyspace @@ -1156,7 +1196,6 @@ func (vc *vcursorImpl) ExecuteVSchema(ctx context.Context, keyspace string, vsch ks := srvVschema.Keyspaces[ksName] ks, err := topotools.ApplyVSchemaDDL(ksName, ks, vschemaDDL) - if err != nil { return err } @@ -1164,7 +1203,6 @@ func (vc *vcursorImpl) ExecuteVSchema(ctx context.Context, keyspace string, vsch srvVschema.Keyspaces[ksName] = ks return vc.vm.UpdateVSchema(ctx, ksName, srvVschema) - } func (vc *vcursorImpl) MessageStream(ctx context.Context, rss []*srvtopo.ResolvedShard, tableName string, callback func(*sqltypes.Result) error) error { @@ -1225,7 +1263,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 } @@ -1288,6 +1335,7 @@ func (vc *vcursorImpl) VExplainLogging() { func (vc *vcursorImpl) GetVExplainLogs() []engine.ExecuteEntry { return vc.safeSession.logging.GetLogs() } + func (vc *vcursorImpl) FindRoutedShard(keyspace, shard string) (keyspaceName string, err error) { return vc.vschema.FindRoutedShard(keyspace, shard) } @@ -1356,6 +1404,37 @@ func (vc *vcursorImpl) CloneForReplicaWarming(ctx context.Context) engine.VCurso return v } +func (vc *vcursorImpl) CloneForMirroring(ctx context.Context) engine.VCursor { + callerId := callerid.EffectiveCallerIDFromContext(ctx) + immediateCallerId := callerid.ImmediateCallerIDFromContext(ctx) + + clonedCtx := callerid.NewContext(ctx, callerId, immediateCallerId) + + v := &vcursorImpl{ + safeSession: NewAutocommitSession(vc.safeSession.Session), + keyspace: vc.keyspace, + tabletType: vc.tabletType, + destination: vc.destination, + marginComments: vc.marginComments, + executor: vc.executor, + resolver: vc.resolver, + topoServer: vc.topoServer, + logStats: &logstats.LogStats{Ctx: clonedCtx}, + collation: vc.collation, + ignoreMaxMemoryRows: vc.ignoreMaxMemoryRows, + vschema: vc.vschema, + vm: vc.vm, + semTable: vc.semTable, + warnShardedOnly: vc.warnShardedOnly, + warnings: vc.warnings, + pv: vc.pv, + } + + v.marginComments.Trailing += "/* mirror query */" + + return v +} + // UpdateForeignKeyChecksState updates the foreign key checks state of the vcursor. func (vc *vcursorImpl) UpdateForeignKeyChecksState(fkStateFromQuery *bool) { // Initialize the state to unspecified. 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/region_experimental.go b/go/vt/vtgate/vindexes/region_experimental.go index c116e9bd84d..c6b867647aa 100644 --- a/go/vt/vtgate/vindexes/region_experimental.go +++ b/go/vt/vtgate/vindexes/region_experimental.go @@ -20,7 +20,6 @@ import ( "bytes" "context" "encoding/binary" - "fmt" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" @@ -61,7 +60,7 @@ type RegionExperimental struct { func newRegionExperimental(name string, m map[string]string) (Vindex, error) { rbs, ok := m[regionExperimentalParamRegionBytes] if !ok { - return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, fmt.Sprintf("region_experimental missing %s param", regionExperimentalParamRegionBytes)) + return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "region_experimental missing %s param", regionExperimentalParamRegionBytes) } var rb int switch rbs { diff --git a/go/vt/vtgate/vindexes/vschema.go b/go/vt/vtgate/vindexes/vschema.go index eba3ac49969..3852bbfcde3 100644 --- a/go/vt/vtgate/vindexes/vschema.go +++ b/go/vt/vtgate/vindexes/vschema.go @@ -63,6 +63,7 @@ const ( // VSchema represents the denormalized version of SrvVSchema, // used for building routing plans. type VSchema struct { + MirrorRules map[string]*MirrorRule `json:"mirror_rules"` RoutingRules map[string]*RoutingRule `json:"routing_rules"` // globalTables contains the name of all tables in all keyspaces. If the @@ -79,13 +80,34 @@ type VSchema struct { created time.Time } +// MirrorRule represents one mirror rule. +type MirrorRule struct { + Error error + Percent float32 `json:"percent,omitempty"` + Table *Table `json:"table,omitempty"` +} + +// MarshalJSON returns a JSON representation of MirrorRule. +func (mr *MirrorRule) MarshalJSON() ([]byte, error) { + if mr.Error != nil { + return json.Marshal(mr.Error.Error()) + } + return json.Marshal(struct { + Percent float32 + Table *Table + }{ + Percent: mr.Percent, + Table: mr.Table, + }) +} + // RoutingRule represents one routing rule. type RoutingRule struct { Tables []*Table Error error } -// MarshalJSON returns a JSON representation of Column. +// MarshalJSON returns a JSON representation of RoutingRule. func (rr *RoutingRule) MarshalJSON() ([]byte, error) { if rr.Error != nil { return json.Marshal(rr.Error.Error()) @@ -324,6 +346,7 @@ func (source *Source) String() string { // BuildVSchema builds a VSchema from a SrvVSchema. func BuildVSchema(source *vschemapb.SrvVSchema, parser *sqlparser.Parser) (vschema *VSchema) { vschema = &VSchema{ + MirrorRules: make(map[string]*MirrorRule), RoutingRules: make(map[string]*RoutingRule), globalTables: make(map[string]*Table), uniqueVindexes: make(map[string]Vindex), @@ -338,6 +361,7 @@ func BuildVSchema(source *vschemapb.SrvVSchema, parser *sqlparser.Parser) (vsche buildRoutingRule(source, vschema, parser) buildShardRoutingRule(source, vschema) buildKeyspaceRoutingRule(source, vschema) + buildMirrorRule(source, vschema, parser) // Resolve auto-increments after routing rules are built since sequence tables also obey routing rules. resolveAutoIncrement(source, vschema, parser) return vschema @@ -895,7 +919,7 @@ func escapeQualifiedTable(qualifiedTableName string) (string, error) { } func extractTableParts(tableName string, allowUnqualified bool) (string, string, error) { - errMsgFormat := "invalid table name: %s, it must be of the " + errMsgFormat := "invalid table name: '%s', it must be of the " if allowUnqualified { errMsgFormat = errMsgFormat + "unqualified form or the " } @@ -914,7 +938,6 @@ func extractTableParts(tableName string, allowUnqualified bool) (string, string, } // Using fmt.Errorf instead of vterrors here because this error is always wrapped in vterrors. return "", "", fmt.Errorf(errMsgFormat, tableName) - } func parseTable(tableName string) (sqlparser.TableName, error) { @@ -963,7 +986,7 @@ outer: toTable, err = escapeQualifiedTable(toTable) if err != nil { vschema.RoutingRules[rule.FromTable] = &RoutingRule{ - Error: vterrors.Errorf( + Error: vterrors.New( vtrpcpb.Code_INVALID_ARGUMENT, err.Error(), ), @@ -972,7 +995,6 @@ outer: } toKeyspace, toTableName, err := parser.ParseTable(toTable) - if err != nil { vschema.RoutingRules[rule.FromTable] = &RoutingRule{ Error: err, @@ -1025,6 +1047,216 @@ func buildKeyspaceRoutingRule(source *vschemapb.SrvVSchema, vschema *VSchema) { vschema.KeyspaceRoutingRules = rulesMap } +func buildMirrorRule(source *vschemapb.SrvVSchema, vschema *VSchema, parser *sqlparser.Parser) { + if source.MirrorRules == nil { + return + } + + // Used to validate no mirror chains exist. + fromTableKeyspaces := make(map[string]string) + toKeyspaces := make(map[string]struct{}) + + for _, rule := range source.MirrorRules.Rules { + toTable := rule.ToTable + + // + // Forbid duplicate FromTables expressions. + // + + if _, ok := vschema.MirrorRules[rule.FromTable]; ok { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_ALREADY_EXISTS, + "from table: duplicate rule for entry '%s'", + rule.FromTable, + ), + } + continue + } + + // + // Parse and validate FromTable. + // + + // Separate tablet-type from rest of FromTable. + fromTableParts := strings.Split(rule.FromTable, "@") + if len(fromTableParts) == 0 { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "from table: invalid table name: '%s'", + rule.FromTable, + ), + } + } + + // Escape and parse the FromTable, without table-type specifier. + fromTable, err := escapeQualifiedTable(fromTableParts[0]) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "from table: %s", + err.Error(), + ), + } + continue + } + fromKeyspace, fromTableName, err := parser.ParseTable(fromTable) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "from table: invalid table name: '%s'", + err.Error(), + ), + } + continue + } + + // Find the from table. + _, err = vschema.FindTable(fromKeyspace, fromTableName) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "from table: %s", + err.Error(), + ), + } + continue + } + + // Validate the table-type, if specified. + if len(fromTableParts) > 1 { + fromTabletTypeSuffix := "@" + strings.Join(fromTableParts[1:], "") + var ok bool + for _, tabletTypeSuffix := range TabletTypeSuffix { + if tabletTypeSuffix == fromTabletTypeSuffix { + ok = true + break + } + } + if !ok { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "from table: invalid tablet type: '%s'", + rule.FromTable, + ), + } + continue + } + } + + // + // Parse and validate ToTable. + // + + // Forbid tablet-type specifier. + toTableParts := strings.Split(toTable, "@") + if len(toTableParts) != 1 || toTableParts[0] == "@" { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "to table: tablet type may not be specified: '%s'", + rule.ToTable, + ), + } + continue + } + + // Escape and parse the table. + toTable, err = escapeQualifiedTable(toTable) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "to table: %s", + err.Error(), + ), + } + continue + } + toKeyspace, toTableName, err := parser.ParseTable(toTable) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "to table: invalid table name: '%s'", + rule.ToTable, + ), + } + continue + } + + // Forbid self-mirroring. + if fromKeyspace == toKeyspace { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "to table: cannot reside in same keyspace as from table", + ), + } + continue + } + + // + // Find table in VSchema. + // + + t, err := vschema.FindTable(toKeyspace, toTableName) + if err != nil { + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Error: vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "to table: %s", + err.Error(), + ), + } + continue + } + + // + // Return non-error mirror rule. + // + + vschema.MirrorRules[rule.FromTable] = &MirrorRule{ + Table: t, + Percent: rule.Percent, + } + + // + // Save some info for validating no mirror chains exist + // + + fromTableKeyspaces[rule.FromTable] = fromKeyspace + toKeyspaces[toKeyspace] = struct{}{} + } + + // Forbid mirror chains. Keyspaces which are the target of a mirror rule + // may not be the source of another. + for fromTable, rule := range vschema.MirrorRules { + if rule.Error != nil { + continue + } + fromKeyspace, ok := fromTableKeyspaces[fromTable] + if !ok { + rule.Error = vterrors.Errorf( + vtrpcpb.Code_INTERNAL, + "[BUG] from table: failed to determine keyspace", + ) + continue + } + if _, ok := toKeyspaces[fromKeyspace]; ok { + rule.Error = vterrors.Errorf( + vtrpcpb.Code_INVALID_ARGUMENT, + "mirror chaining is not allowed", + ) + } + } +} + // FindTable returns a pointer to the Table. If a keyspace is specified, only tables // from that keyspace are searched. If the specified keyspace is unsharded // and no tables matched, it's considered valid: FindTable will construct a table @@ -1325,6 +1557,28 @@ func (vschema *VSchema) GetAggregateUDFs() (udfs []string) { return } +// FindMirrorRule finds a mirror rule from the keyspace, table name and +// tablet type. +func (vschema *VSchema) FindMirrorRule(keyspace, tablename string, tabletType topodatapb.TabletType) (*MirrorRule, error) { + qualified := tablename + if keyspace != "" { + qualified = keyspace + "." + tablename + } + fqtn := qualified + TabletTypeSuffix[tabletType] + // First look for a fully qualified table name: keyspace.table@tablet_type. + // Then look for one without tablet type: keyspace.table. + for _, name := range []string{fqtn, qualified} { + mr, ok := vschema.MirrorRules[name] + if ok { + if mr.Error != nil { + return nil, mr.Error + } + return mr, nil + } + } + return nil, nil +} + // ByCost provides the interface needed for ColumnVindexes to // be sorted by cost order. type ByCost []*ColumnVindex @@ -1392,7 +1646,7 @@ func ChooseVindexForType(typ querypb.Type) (string, error) { // FindBestColVindex finds the best ColumnVindex for VReplication. func FindBestColVindex(table *Table) (*ColumnVindex, error) { - if table.ColumnVindexes == nil || len(table.ColumnVindexes) == 0 { + if len(table.ColumnVindexes) == 0 { return nil, vterrors.Errorf( vtrpcpb.Code_INVALID_ARGUMENT, "table %s has no vindex", diff --git a/go/vt/vtgate/vindexes/vschema_test.go b/go/vt/vtgate/vindexes/vschema_test.go index 7761b6ae8ab..25f8e135698 100644 --- a/go/vt/vtgate/vindexes/vschema_test.go +++ b/go/vt/vtgate/vindexes/vschema_test.go @@ -838,6 +838,7 @@ func TestVSchemaRoutingRules(t *testing.T) { Keyspace: ks2, } want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{ "rt1": { Error: errors.New("table rt1 has more than one target: [ks1.t1 ks2.t2]"), @@ -852,10 +853,10 @@ func TestVSchemaRoutingRules(t *testing.T) { Error: errors.New("duplicate rule for entry dup"), }, "badname": { - Error: errors.New("invalid table name: t1.t2.t3, it must be of the qualified form . (dots are not allowed in either name)"), + Error: errors.New("invalid table name: 't1.t2.t3', it must be of the qualified form . (dots are not allowed in either name)"), }, "unqualified": { - Error: errors.New("invalid table name: t1, it must be of the qualified form . (dots are not allowed in either name)"), + Error: errors.New("invalid table name: 't1', it must be of the qualified form . (dots are not allowed in either name)"), }, "badkeyspace": { Error: errors.New("VT05003: unknown database 'ks3' in vschema"), @@ -897,6 +898,282 @@ func TestVSchemaRoutingRules(t *testing.T) { assert.Equal(t, string(wantb), string(gotb), string(gotb)) } +func TestVSchemaMirrorRules(t *testing.T) { + input := vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{ + Rules: []*vschemapb.MirrorRule{ + // Empty FromTable not allowed. + { + FromTable: "", + ToTable: "ks2.ks2t1", + }, + // Invalid FromTable, needs to be .[@]. + { + FromTable: "ks1", + ToTable: "ks2.ks2t1", + }, + // Invalid ToTable, needs to be .
. + { + FromTable: "ks1.ks1t1", + ToTable: "ks2", + }, + // Invalid ToTable, needs to be .
. + { + FromTable: "ks1.ks1t2", + ToTable: "ks2.ks2t2.c", + }, + // OK, unsharded => unsharded. + { + FromTable: "ks1.ks1t3", + ToTable: "ks2.ks2t3", + Percent: 50, + }, + // Invalid ToTable, needs to be .
. + { + FromTable: "ks1.ks1t4", + ToTable: "ks2.ks2t4@replica", + }, + // OK, unsharded@tablet-type => unsharded. + { + FromTable: "ks1.ks1t5@replica", + ToTable: "ks2.ks2t5", + }, + // Invalid FromTable tablet type.. + { + FromTable: "ks1.ks1t6@stone", + ToTable: "ks2.ks2t6", + }, + // OK, sharded => sharded. + { + FromTable: "ks3.ks3t1", + ToTable: "ks4.ks4t1", + Percent: 50, + }, + // OK, unsharded => sharded. + { + FromTable: "ks1.ks1t7", + ToTable: "ks4.ks4t1", + Percent: 50, + }, + // Destination sharded table must be defined in VSchema. + { + FromTable: "ks1.ks1t8", + ToTable: "ks4.ks4t2", + Percent: 50, + }, + // Source sharded table must be defined in VSchema. + { + FromTable: "ks3.ks3t2", + ToTable: "ks4.ks4t1", + Percent: 50, + }, + // Keyspaces that are the target of a rule may not be the + // source of another. + { + FromTable: "ks2.ks2t9", + ToTable: "ks4.ks4t1", + Percent: 50, + }, + }, + }, + RoutingRules: &vschemapb.RoutingRules{}, + Keyspaces: map[string]*vschemapb.Keyspace{ + "ks1": { + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Tables: map[string]*vschemapb.Table{}, + }, + "ks2": { + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Tables: map[string]*vschemapb.Table{}, + }, + "ks3": { + Sharded: true, + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Vindexes: map[string]*vschemapb.Vindex{ + "stfu1": { + Type: "stfu", + }, + }, + Tables: map[string]*vschemapb.Table{ + "ks3t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{ + { + Column: "id", + Name: "stfu1", + }, + }, + }, + }, + }, + "ks4": { + Sharded: true, + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Vindexes: map[string]*vschemapb.Vindex{ + "stfu1": { + Type: "stfu", + }, + }, + Tables: map[string]*vschemapb.Table{ + "ks4t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{ + { + Column: "id", + Name: "stfu1", + }, + }, + }, + }, + }, + }, + } + got := BuildVSchema(&input, sqlparser.NewTestParser()) + + ks1 := &Keyspace{ + Name: "ks1", + Sharded: false, + } + ks2 := &Keyspace{ + Name: "ks2", + Sharded: false, + } + ks3 := &Keyspace{ + Name: "ks3", + Sharded: true, + } + ks4 := &Keyspace{ + Name: "ks4", + Sharded: true, + } + + vindex1 := &stFU{ + name: "stfu1", + } + + ks3t1 := &Table{ + Name: sqlparser.NewIdentifierCS("ks3t1"), + Keyspace: ks3, + ColumnVindexes: []*ColumnVindex{{ + Columns: []sqlparser.IdentifierCI{sqlparser.NewIdentifierCI("id")}, + Type: "stfu", + Name: "stfu1", + Vindex: vindex1, + isUnique: vindex1.IsUnique(), + cost: vindex1.Cost(), + }}, + } + ks3t1.Ordered = []*ColumnVindex{ + ks3t1.ColumnVindexes[0], + } + + ks4t1 := &Table{ + Name: sqlparser.NewIdentifierCS("ks4t1"), + Keyspace: ks4, + ColumnVindexes: []*ColumnVindex{{ + Columns: []sqlparser.IdentifierCI{sqlparser.NewIdentifierCI("id")}, + Type: "stfu", + Name: "stfu1", + Vindex: vindex1, + isUnique: vindex1.IsUnique(), + cost: vindex1.Cost(), + }}, + } + ks4t1.Ordered = []*ColumnVindex{ + ks4t1.ColumnVindexes[0], + } + + want := &VSchema{ + MirrorRules: map[string]*MirrorRule{ + "": { + Error: errors.New("from table: invalid table name: '', it must be of the qualified form . (dots are not allowed in either name)"), + }, + "ks1": { + Error: errors.New("from table: invalid table name: 'ks1', it must be of the qualified form . (dots are not allowed in either name)"), + }, + "ks1.ks1t1": { + Error: errors.New("to table: invalid table name: 'ks2', it must be of the qualified form . (dots are not allowed in either name)"), + }, + "ks1.ks1t2": { + Error: errors.New("to table: invalid table name: 'ks2.ks2t2.c', it must be of the qualified form . (dots are not allowed in either name)"), + }, + "ks1.ks1t3": { + Table: &Table{ + Name: sqlparser.NewIdentifierCS("ks2t3"), + }, + Percent: 50, + }, + "ks1.ks1t4": { + Error: errors.New("to table: tablet type may not be specified: 'ks2.ks2t4@replica'"), + }, + "ks1.ks1t5@replica": { + Table: &Table{ + Name: sqlparser.NewIdentifierCS("ks2t5"), + }, + }, + "ks1.ks1t6@stone": { + Error: errors.New("from table: invalid tablet type: 'ks1.ks1t6@stone'"), + }, + "ks3.ks3t1": { + Table: ks4t1, + Percent: 50, + }, + "ks1.ks1t7": { + Table: ks4t1, + Percent: 50, + }, + "ks1.ks1t8": { + Error: errors.New("to table: table ks4t2 not found"), + }, + "ks3.ks3t2": { + Error: errors.New("from table: table ks3t2 not found"), + }, + "ks2.ks2t9": { + Error: errors.New("mirror chaining is not allowed"), + }, + }, + RoutingRules: map[string]*RoutingRule{}, + Keyspaces: map[string]*KeyspaceSchema{ + "ks1": { + Keyspace: ks1, + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Tables: map[string]*Table{}, + Vindexes: map[string]Vindex{}, + }, + "ks2": { + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Keyspace: ks2, + Tables: map[string]*Table{}, + Vindexes: map[string]Vindex{}, + }, + "ks3": { + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Keyspace: ks3, + Tables: map[string]*Table{ + "ks3t1": ks3t1, + }, + Vindexes: map[string]Vindex{ + "stfu1": vindex1, + }, + }, + "ks4": { + ForeignKeyMode: vschemapb.Keyspace_unmanaged, + Keyspace: ks4, + Tables: map[string]*Table{ + "ks4t1": ks4t1, + }, + Vindexes: map[string]Vindex{ + "stfu1": vindex1, + }, + }, + }, + } + + gotb, err := json.MarshalIndent(got, "", " ") + assert.NoError(t, err) + wantb, err := json.MarshalIndent(want, "", " ") + assert.NoError(t, err) + assert.Equal(t, string(wantb), string(gotb), string(gotb)) +} + func TestChooseVindexForType(t *testing.T) { testcases := []struct { in querypb.Type @@ -1247,6 +1524,7 @@ func TestShardedVSchemaMultiColumnVindex(t *testing.T) { t1.ColumnVindexes[0], } want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "t1": t1, @@ -1323,6 +1601,7 @@ func TestShardedVSchemaNotOwned(t *testing.T) { t1.ColumnVindexes[1], t1.ColumnVindexes[0]} want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "t1": t1, @@ -1430,6 +1709,7 @@ func TestBuildVSchemaDupSeq(t *testing.T) { Keyspace: ksb, Type: "sequence"} want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "t1": nil, @@ -1491,6 +1771,7 @@ func TestBuildVSchemaDupTable(t *testing.T) { Keyspace: ksb, } want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "t1": nil, @@ -1620,6 +1901,7 @@ func TestBuildVSchemaDupVindex(t *testing.T) { t2.ColumnVindexes[0], } want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "t1": nil, @@ -2206,6 +2488,7 @@ func TestSequence(t *testing.T) { t2.ColumnVindexes[0], } want := &VSchema{ + MirrorRules: map[string]*MirrorRule{}, RoutingRules: map[string]*RoutingRule{}, globalTables: map[string]*Table{ "seq": seq, 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..8db0c2df05b 100644 --- a/go/vt/vtgate/vschema_manager_test.go +++ b/go/vt/vtgate/vschema_manager_test.go @@ -234,6 +234,7 @@ func TestVSchemaUpdate(t *testing.T) { }, }, expected: &vindexes.VSchema{ + MirrorRules: map[string]*vindexes.MirrorRule{}, RoutingRules: map[string]*vindexes.RoutingRule{}, Keyspaces: map[string]*vindexes.KeyspaceSchema{ "ks": { @@ -336,6 +337,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"), @@ -456,6 +500,7 @@ func TestVSchemaUDFsUpdate(t *testing.T) { }, nil) utils.MustMatchFn(".globalTables", ".uniqueVindexes")(t, &vindexes.VSchema{ + MirrorRules: map[string]*vindexes.MirrorRule{}, RoutingRules: map[string]*vindexes.RoutingRule{}, Keyspaces: map[string]*vindexes.KeyspaceSchema{ "ks": { @@ -778,6 +823,7 @@ func TestVSchemaUpdateWithFKReferenceToInternalTables(t *testing.T) { }, nil) utils.MustMatchFn(".globalTables", ".uniqueVindexes")(t, &vindexes.VSchema{ + MirrorRules: map[string]*vindexes.MirrorRule{}, RoutingRules: map[string]*vindexes.RoutingRule{}, Keyspaces: map[string]*vindexes.KeyspaceSchema{ "ks": { @@ -827,6 +873,7 @@ func makeTestVSchema(ks string, sharded bool, tbls map[string]*vindexes.Table) * func makeTestEmptyVSchema() *vindexes.VSchema { return &vindexes.VSchema{ + MirrorRules: map[string]*vindexes.MirrorRule{}, RoutingRules: map[string]*vindexes.RoutingRule{}, Keyspaces: map[string]*vindexes.KeyspaceSchema{}, } diff --git a/go/vt/vtgate/vstream_manager.go b/go/vt/vtgate/vstream_manager.go index e0d195853cf..84ad5552c13 100644 --- a/go/vt/vtgate/vstream_manager.go +++ b/go/vt/vtgate/vstream_manager.go @@ -122,6 +122,8 @@ type vstream struct { ts *topo.Server tabletPickerOptions discovery.TabletPickerOptions + + flags *vtgatepb.VStreamFlags } type journalEvent struct { @@ -183,6 +185,7 @@ func (vsm *vstreamManager) VStream(ctx context.Context, tabletType topodatapb.Ta CellPreference: flags.GetCellPreference(), TabletOrder: flags.GetTabletOrder(), }, + flags: flags, } return vs.stream(ctx) } @@ -269,7 +272,7 @@ func (vsm *vstreamManager) resolveParams(ctx context.Context, tabletType topodat } } - //TODO add tablepk validations + // TODO add tablepk validations return newvgtid, filter, flags, nil } @@ -575,15 +578,24 @@ func (vs *vstream) streamFromTablet(ctx context.Context, sgtid *binlogdatapb.Sha }) }() - log.Infof("Starting to vstream from %s", tablet.Alias.String()) + var options *binlogdatapb.VStreamOptions + const SidecarDBHeartbeatTableName = "heartbeat" + if vs.flags.GetStreamKeyspaceHeartbeats() { + options = &binlogdatapb.VStreamOptions{ + InternalTables: []string{SidecarDBHeartbeatTableName}, + } + } + // Safe to access sgtid.Gtid here (because it can't change until streaming begins). req := &binlogdatapb.VStreamRequest{ Target: target, Position: sgtid.Gtid, Filter: vs.filter, TableLastPKs: sgtid.TablePKs, + Options: options, } var vstreamCreatedOnce sync.Once + log.Infof("Starting to vstream from %s, with req %+v", topoproto.TabletAliasString(tablet.Alias), req) err = tabletConn.VStream(ctx, req, func(events []*binlogdatapb.VEvent) error { // We received a valid event. Reset error count. errCount = 0 diff --git a/go/vt/vtgate/vstream_manager_test.go b/go/vt/vtgate/vstream_manager_test.go index e51bd2785dd..4e10e60c758 100644 --- a/go/vt/vtgate/vstream_manager_test.go +++ b/go/vt/vtgate/vstream_manager_test.go @@ -458,7 +458,7 @@ func TestVStreamRetriableErrors(t *testing.T) { // Always have the local cell tablet error so it's ignored on retry and we pick the other one // if the error requires ignoring the tablet on retry. - sbc0.AddVStreamEvents(nil, vterrors.Errorf(tcase.code, tcase.msg)) + sbc0.AddVStreamEvents(nil, vterrors.New(tcase.code, tcase.msg)) if tcase.ignoreTablet { sbc1.AddVStreamEvents(commit, nil) diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index e23e313108c..e9e7cd65011 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() @@ -559,11 +563,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/vtorc/inst/instance_dao.go b/go/vt/vtorc/inst/instance_dao.go index 0615cbc0cde..4e401606a95 100644 --- a/go/vt/vtorc/inst/instance_dao.go +++ b/go/vt/vtorc/inst/instance_dao.go @@ -141,8 +141,8 @@ func logReadTopologyInstanceError(tabletAlias string, hint string, err error) er strings.Replace(hint, "%", "%%", -1), // escape % err) } - log.Errorf(msg) - return fmt.Errorf(msg) + log.Error(msg) + return errors.New(msg) } // RegisterStats registers stats from the inst package @@ -933,7 +933,7 @@ func mkInsertOdkuForInstances(instances []*Instance, instanceWasActuallyFound bo if err != nil { errMsg := fmt.Sprintf("Failed to build query: %v", err) log.Errorf(errMsg) - return sql, args, fmt.Errorf(errMsg) + return sql, args, errors.New(errMsg) } return sql, args, nil @@ -1031,7 +1031,7 @@ func ForgetInstance(tabletAlias string) error { if tabletAlias == "" { errMsg := "ForgetInstance(): empty tabletAlias" log.Errorf(errMsg) - return fmt.Errorf(errMsg) + return errors.New(errMsg) } forgetAliases.Set(tabletAlias, true, cache.DefaultExpiration) log.Infof("Forgetting: %v", tabletAlias) @@ -1069,8 +1069,8 @@ func ForgetInstance(tabletAlias string) error { } if rows == 0 { errMsg := fmt.Sprintf("ForgetInstance(): tablet %+v not found", tabletAlias) - log.Errorf(errMsg) - return fmt.Errorf(errMsg) + log.Error(errMsg) + return errors.New(errMsg) } _ = AuditOperation("forget", tabletAlias, "") return nil diff --git a/go/vt/vtorc/logic/disable_recovery.go b/go/vt/vtorc/logic/disable_recovery.go index 4a3766055d2..74aa291e17a 100644 --- a/go/vt/vtorc/logic/disable_recovery.go +++ b/go/vt/vtorc/logic/disable_recovery.go @@ -30,6 +30,7 @@ package logic // go to the database each time. import ( + "errors" "fmt" "vitess.io/vitess/go/vt/external/golib/sqlutils" @@ -55,7 +56,7 @@ func IsRecoveryDisabled() (disabled bool, err error) { if err != nil { errMsg := fmt.Sprintf("recovery.IsRecoveryDisabled(): %v", err) log.Errorf(errMsg) - err = fmt.Errorf(errMsg) + err = errors.New(errMsg) } return disabled, err } diff --git a/go/vt/vtorc/logic/topology_recovery_dao.go b/go/vt/vtorc/logic/topology_recovery_dao.go index e8af34bdad4..1920da4dcd8 100644 --- a/go/vt/vtorc/logic/topology_recovery_dao.go +++ b/go/vt/vtorc/logic/topology_recovery_dao.go @@ -17,6 +17,7 @@ package logic import ( + "errors" "fmt" "strings" @@ -121,7 +122,7 @@ func AttemptRecoveryRegistration(analysisEntry *inst.ReplicationAnalysis) (*Topo if len(recoveries) > 0 { errMsg := fmt.Sprintf("AttemptRecoveryRegistration: Active recovery (id:%v) in the cluster %s:%s for %s", recoveries[0].ID, analysisEntry.ClusterDetails.Keyspace, analysisEntry.ClusterDetails.Shard, recoveries[0].AnalysisEntry.Analysis) log.Errorf(errMsg) - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } topologyRecovery := NewTopologyRecovery(*analysisEntry) 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/connecttcp/main_test.go b/go/vt/vttablet/endtoend/connecttcp/main_test.go new file mode 100644 index 00000000000..9d52b1287a1 --- /dev/null +++ b/go/vt/vttablet/endtoend/connecttcp/main_test.go @@ -0,0 +1,119 @@ +/* +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 connecttcp + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + + "vitess.io/vitess/go/mysql" + vttestpb "vitess.io/vitess/go/vt/proto/vttest" + "vitess.io/vitess/go/vt/vttablet/endtoend/framework" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" + "vitess.io/vitess/go/vt/vttest" +) + +var ( + connParams mysql.ConnParams + connAppDebugParams mysql.ConnParams +) + +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", + } + if err := cfg.InitSchemas("vttest", testSchema, nil); err != nil { + fmt.Fprintf(os.Stderr, "InitSchemas failed: %v\n", err) + return 1 + } + defer os.RemoveAll(cfg.SchemaDir) + cluster := vttest.LocalCluster{ + Config: cfg, + } + if err := cluster.Setup(); err != nil { + fmt.Fprintf(os.Stderr, "could not launch mysql: %v\n", err) + return 1 + } + defer cluster.TearDown() + + if err := allowConnectOnTCP(cluster); err != nil { + fmt.Fprintf(os.Stderr, "failed to allow tcp priviliges: %v", err) + return 1 + } + + connParams = cluster.MySQLTCPConnParams() + connAppDebugParams = cluster.MySQLAppDebugConnParams() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + config := tabletenv.NewDefaultConfig() + config.TwoPCEnable = true + config.TwoPCAbandonAge = 1 + + if err := framework.StartCustomServer(ctx, connParams, connAppDebugParams, cluster.DbName(), config); err != nil { + fmt.Fprintf(os.Stderr, "%v", err) + return 1 + } + defer framework.StopServer() + + return m.Run() + }() + os.Exit(exitCode) +} + +func allowConnectOnTCP(cluster vttest.LocalCluster) error { + connParams = cluster.MySQLConnParams() + conn, err := mysql.Connect(context.Background(), &connParams) + if err != nil { + return err + } + if _, err = conn.ExecuteFetch("UPDATE mysql.user SET Host = '%' WHERE User = 'vt_dba';", 0, false); err != nil { + return err + } + if _, err = conn.ExecuteFetch("FLUSH PRIVILEGES;", 0, false); err != nil { + return err + } + conn.Close() + return nil +} + +var testSchema = `create table vitess_test(intval int primary key);` diff --git a/go/vt/vttablet/endtoend/connecttcp/prepare_test.go b/go/vt/vttablet/endtoend/connecttcp/prepare_test.go new file mode 100644 index 00000000000..524b4a3dcc8 --- /dev/null +++ b/go/vt/vttablet/endtoend/connecttcp/prepare_test.go @@ -0,0 +1,41 @@ +/* +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 connecttcp + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/vttablet/endtoend/framework" +) + +// TestPrepareOnTCP tests that a prepare statement is not allowed on a network connection. +func TestPrepareOnTCP(t *testing.T) { + client := framework.NewClient() + + query := "insert into vitess_test (intval) values(4)" + + err := client.Begin(false) + require.NoError(t, err) + + _, err = client.Execute(query, nil) + require.NoError(t, err) + + err = client.Prepare("aa") + require.ErrorContains(t, err, "VT10002: atomic distributed transaction not allowed: cannot prepare the transaction on a network connection") +} diff --git a/go/vt/vttablet/endtoend/framework/client.go b/go/vt/vttablet/endtoend/framework/client.go index dc4b7f9f339..e4c2aa66066 100644 --- a/go/vt/vttablet/endtoend/framework/client.go +++ b/go/vt/vttablet/endtoend/framework/client.go @@ -178,12 +178,15 @@ 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 { err := client.server.SetServingType(tabletType, time.Time{}, true /* serving */, "" /* reason */) - // Wait for TwoPC transition, if necessary - client.server.TwoPCEngineWait() return err } 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/transaction_test.go b/go/vt/vttablet/endtoend/transaction_test.go index b15e73585ba..2bc7a1b39d4 100644 --- a/go/vt/vttablet/endtoend/transaction_test.go +++ b/go/vt/vttablet/endtoend/transaction_test.go @@ -256,7 +256,7 @@ func TestPrepareRollback(t *testing.T) { err = client.Prepare("aa") if err != nil { client.RollbackPrepared("aa", 0) - t.Fatalf(err.Error()) + t.Fatal(err.Error()) } err = client.RollbackPrepared("aa", 0) require.NoError(t, err) @@ -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..a8bf7187bcc 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() @@ -671,6 +691,7 @@ func (conn *gRPCQueryClient) VStream(ctx context.Context, request *binlogdatapb. Position: request.Position, Filter: request.Filter, TableLastPKs: request.TableLastPKs, + Options: request.Options, } stream, err := conn.c.VStream(ctx, req) if err != nil { 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..f693dfe135c 100644 --- a/go/vt/vttablet/onlineddl/executor.go +++ b/go/vt/vttablet/onlineddl/executor.go @@ -178,6 +178,7 @@ type Executor struct { ts *topo.Server lagThrottler *throttle.Throttler toggleBufferTableFunc func(cancelCtx context.Context, tableName string, timeout time.Duration, bufferQueries bool) + isPreparedPoolEmpty func(tableName string) bool requestGCChecksFunc func() tabletAlias *topodatapb.TabletAlias @@ -238,6 +239,7 @@ func NewExecutor(env tabletenv.Env, tabletAlias *topodatapb.TabletAlias, ts *top tabletTypeFunc func() topodatapb.TabletType, toggleBufferTableFunc func(cancelCtx context.Context, tableName string, timeout time.Duration, bufferQueries bool), requestGCChecksFunc func(), + isPreparedPoolEmpty func(tableName string) bool, ) *Executor { // sanitize flags if maxConcurrentOnlineDDLs < 1 { @@ -255,6 +257,7 @@ func NewExecutor(env tabletenv.Env, tabletAlias *topodatapb.TabletAlias, ts *top ts: ts, lagThrottler: lagThrottler, toggleBufferTableFunc: toggleBufferTableFunc, + isPreparedPoolEmpty: isPreparedPoolEmpty, requestGCChecksFunc: requestGCChecksFunc, ticks: timer.NewTimer(migrationCheckInterval), // Gracefully return an error if any caller tries to execute @@ -616,7 +619,7 @@ func (e *Executor) getCreateTableStatement(ctx context.Context, tableName string } createTable, ok := stmt.(*sqlparser.CreateTable) if !ok { - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "expected CREATE TABLE. Got %v", sqlparser.CanonicalString(stmt)) + return nil, schemadiff.ErrExpectedCreateTable } return createTable, nil } @@ -870,7 +873,10 @@ func (e *Executor) killTableLockHoldersAndAccessors(ctx context.Context, tableNa threadId := row.AsInt64("trx_mysql_thread_id", 0) log.Infof("killTableLockHoldersAndAccessors: killing connection %v with transaction on table", threadId) killConnection := fmt.Sprintf("KILL %d", threadId) - _, _ = conn.Conn.ExecuteFetch(killConnection, 1, false) + _, err = conn.Conn.ExecuteFetch(killConnection, 1, false) + if err != nil { + log.Errorf("Unable to kill the connection %d: %v", threadId, err) + } } } } @@ -979,7 +985,14 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh if err != nil { return err } + // Set large enough `@@lock_wait_timeout` so that it does not interfere with the cut-over operation. + // The code will ensure everything that needs to be terminated by `migrationCutOverThreshold` will be terminated. + lockConnRestoreLockWaitTimeout, err := e.initConnectionLockWaitTimeout(ctx, lockConn.Conn, 5*migrationCutOverThreshold) + if err != nil { + return err + } defer lockConn.Recycle() + defer lockConnRestoreLockWaitTimeout() defer lockConn.Conn.Exec(ctx, sqlUnlockTables, 1, false) renameCompleteChan := make(chan error) @@ -988,6 +1001,12 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh if err != nil { return err } + // Set large enough `@@lock_wait_timeout` so that it does not interfere with the cut-over operation. + // The code will ensure everything that needs to be terminated by `migrationCutOverThreshold` will be terminated. + renameConnRestoreLockWaitTimeout, err := e.initConnectionLockWaitTimeout(ctx, renameConn.Conn, 5*migrationCutOverThreshold*4) + if err != nil { + return err + } defer renameConn.Recycle() defer func() { if !renameWasSuccessful { @@ -997,6 +1016,8 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh } } }() + defer renameConnRestoreLockWaitTimeout() + // See if backend MySQL server supports 'rename_table_preserve_foreign_key' variable preserveFKSupported, err := e.isPreserveForeignKeySupported(ctx) if err != nil { @@ -1087,6 +1108,11 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh time.Sleep(100 * time.Millisecond) if shouldForceCutOver { + // We should only proceed with forceful cut over if there is no pending atomic transaction for the table. + // This will help in keeping the atomicity guarantee of a prepared transaction. + if err := e.checkOnPreparedPool(ctx, onlineDDL.Table, 100*time.Millisecond); err != nil { + return err + } if err := e.killTableLockHoldersAndAccessors(ctx, onlineDDL.Table); err != nil { return err } @@ -1260,6 +1286,24 @@ func (e *Executor) initMigrationSQLMode(ctx context.Context, onlineDDL *schema.O return deferFunc, nil } +// initConnectionLockWaitTimeout sets the given lock_wait_timeout for the given connection, with a deferred value restoration function +func (e *Executor) initConnectionLockWaitTimeout(ctx context.Context, conn *connpool.Conn, lockWaitTimeout time.Duration) (deferFunc func(), err error) { + deferFunc = func() {} + + if _, err := conn.Exec(ctx, `set @lock_wait_timeout=@@session.lock_wait_timeout`, 0, false); err != nil { + return deferFunc, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "could not read lock_wait_timeout: %v", err) + } + timeoutSeconds := int64(lockWaitTimeout.Seconds()) + setQuery := fmt.Sprintf("set @@session.lock_wait_timeout=%d", timeoutSeconds) + if _, err := conn.Exec(ctx, setQuery, 0, false); err != nil { + return deferFunc, err + } + deferFunc = func() { + conn.Exec(ctx, "set @@session.lock_wait_timeout=@lock_wait_timeout", 0, false) + } + return deferFunc, nil +} + // newConstraintName generates a new, unique name for a constraint. Our problem is that a MySQL // constraint's name is unique in the schema (!). And so as we duplicate the original table, we must // create completely new names for all constraints. @@ -1518,7 +1562,10 @@ func (e *Executor) initVreplicationOriginalMigration(ctx context.Context, online return v, err } - v = NewVRepl(e.env.Environment(), onlineDDL.UUID, e.keyspace, e.shard, e.dbName, onlineDDL.Table, vreplTableName, originalCreateTable, vreplCreateTable, alterTable, onlineDDL.StrategySetting().IsAnalyzeTableFlag()) + v, err = NewVRepl(e.env.Environment(), onlineDDL.UUID, e.keyspace, e.shard, e.dbName, originalCreateTable, vreplCreateTable, alterTable, onlineDDL.StrategySetting().IsAnalyzeTableFlag()) + if err != nil { + return v, err + } return v, nil } @@ -1526,7 +1573,7 @@ func (e *Executor) initVreplicationOriginalMigration(ctx context.Context, online // This function is called after both source and target tables have been analyzed, so there's more information // about the two, and about the transition between the two. func (e *Executor) postInitVreplicationOriginalMigration(ctx context.Context, onlineDDL *schema.OnlineDDL, v *VRepl, conn *dbconnpool.DBConnection) (err error) { - if v.sourceAutoIncrement > 0 && !v.parser.IsAutoIncrementDefined() { + if v.analysis.SourceAutoIncrement > 0 && !v.alterTableAnalysis.IsAutoIncrementChangeRequested { restoreSQLModeFunc, err := e.initMigrationSQLMode(ctx, onlineDDL, conn) defer restoreSQLModeFunc() if err != nil { @@ -1534,9 +1581,9 @@ func (e *Executor) postInitVreplicationOriginalMigration(ctx context.Context, on } // Apply ALTER TABLE AUTO_INCREMENT=? - parsed := sqlparser.BuildParsedQuery(sqlAlterTableAutoIncrement, v.targetTable, ":auto_increment") + parsed := sqlparser.BuildParsedQuery(sqlAlterTableAutoIncrement, v.targetTableName(), ":auto_increment") bindVars := map[string]*querypb.BindVariable{ - "auto_increment": sqltypes.Uint64BindVariable(v.sourceAutoIncrement), + "auto_increment": sqltypes.Uint64BindVariable(v.analysis.SourceAutoIncrement), } bound, err := parsed.GenerateQuery(bindVars, nil) if err != nil { @@ -1572,7 +1619,18 @@ func (e *Executor) initVreplicationRevertMigration(ctx context.Context, onlineDD if err := e.updateArtifacts(ctx, onlineDDL.UUID, vreplTableName); err != nil { return v, err } - v = NewVRepl(e.env.Environment(), onlineDDL.UUID, e.keyspace, e.shard, e.dbName, onlineDDL.Table, vreplTableName, nil, nil, nil, false) + originalCreateTable, err := e.getCreateTableStatement(ctx, onlineDDL.Table) + if err != nil { + return v, err + } + vreplCreateTable, err := e.getCreateTableStatement(ctx, vreplTableName) + if err != nil { + return v, err + } + v, err = NewVRepl(e.env.Environment(), onlineDDL.UUID, e.keyspace, e.shard, e.dbName, originalCreateTable, vreplCreateTable, nil, false) + if err != nil { + return v, err + } v.pos = revertStream.pos return v, nil } @@ -1614,19 +1672,15 @@ func (e *Executor) ExecuteWithVReplication(ctx context.Context, onlineDDL *schem if err := e.updateMigrationTableRows(ctx, onlineDDL.UUID, v.tableRows); err != nil { return err } - removedUniqueKeyNames := []string{} - for _, uniqueKey := range v.removedUniqueKeys { - removedUniqueKeyNames = append(removedUniqueKeyNames, uniqueKey.Name) - } if err := e.updateSchemaAnalysis(ctx, onlineDDL.UUID, - len(v.addedUniqueKeys), - len(v.removedUniqueKeys), - strings.Join(sqlescape.EscapeIDs(removedUniqueKeyNames), ","), - strings.Join(sqlescape.EscapeIDs(v.removedForeignKeyNames), ","), - strings.Join(sqlescape.EscapeIDs(v.droppedNoDefaultColumnNames), ","), - strings.Join(sqlescape.EscapeIDs(v.expandedColumnNames), ","), - v.revertibleNotes, + v.analysis.AddedUniqueKeys.Len(), + v.analysis.RemovedUniqueKeys.Len(), + strings.Join(sqlescape.EscapeIDs(v.analysis.RemovedUniqueKeys.Names()), ","), + strings.Join(sqlescape.EscapeIDs(v.analysis.RemovedForeignKeyNames), ","), + strings.Join(sqlescape.EscapeIDs(v.analysis.DroppedNoDefaultColumns.Names()), ","), + strings.Join(sqlescape.EscapeIDs(v.analysis.ExpandedColumns.Names()), ","), + v.analysis.RevertibleNotes, ); err != nil { return err } @@ -1654,7 +1708,7 @@ func (e *Executor) ExecuteWithVReplication(ctx context.Context, onlineDDL *schem } // create vreplication entry - insertVReplicationQuery, err := v.generateInsertStatement(ctx) + insertVReplicationQuery, err := v.generateInsertStatement() if err != nil { return err } @@ -1671,7 +1725,7 @@ func (e *Executor) ExecuteWithVReplication(ctx context.Context, onlineDDL *schem } } // start stream! - startVReplicationQuery, err := v.generateStartStatement(ctx) + startVReplicationQuery, err := v.generateStartStatement() if err != nil { return err } @@ -2967,7 +3021,7 @@ func (e *Executor) analyzeDropDDLActionMigration(ctx context.Context, onlineDDL // Write analysis: } if err := e.updateSchemaAnalysis(ctx, onlineDDL.UUID, - 0, 0, "", strings.Join(sqlescape.EscapeIDs(removedForeignKeyNames), ","), "", "", "", + 0, 0, "", strings.Join(sqlescape.EscapeIDs(removedForeignKeyNames), ","), "", "", nil, ); err != nil { return err } @@ -3640,6 +3694,7 @@ func (e *Executor) readVReplStream(ctx context.Context, uuid string, okIfMissing timeHeartbeat: row.AsInt64("time_heartbeat", 0), timeThrottled: row.AsInt64("time_throttled", 0), componentThrottled: row.AsString("component_throttled", ""), + reasonThrottled: row.AsString("reason_throttled", ""), transactionTimestamp: row.AsInt64("transaction_timestamp", 0), state: binlogdatapb.VReplicationWorkflowState(binlogdatapb.VReplicationWorkflowState_value[row.AsString("state", "")]), message: row.AsString("message", ""), @@ -3801,7 +3856,7 @@ func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning i uuid := row["migration_uuid"].ToString() cutoverAttempts := row.AsInt64("cutover_attempts", 0) sinceLastCutoverAttempt := time.Second * time.Duration(row.AsInt64("seconds_since_last_cutover_attempt", 0)) - sinceReadyToComplete := time.Second * time.Duration(row.AsInt64("seconds_since_ready_to_complete", 0)) + sinceReadyToComplete := time.Microsecond * time.Duration(row.AsInt64("microseconds_since_ready_to_complete", 0)) onlineDDL, migrationRow, err := e.readMigration(ctx, uuid) if err != nil { return countRunnning, cancellable, err @@ -3870,8 +3925,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, s.reasonThrottled) + } if onlineDDL.StrategySetting().IsInOrderCompletion() { // We will fail an in-order migration if there's _prior_ migrations within the same migration-context // which have failed. @@ -4489,7 +4546,8 @@ func (e *Executor) updateSchemaAnalysis(ctx context.Context, uuid string, addedUniqueKeys, removedUniqueKeys int, removedUniqueKeyNames string, removedForeignKeyNames string, droppedNoDefaultColumnNames string, expandedColumnNames string, - revertibleNotes string) error { + revertibleNotes []string) error { + notes := strings.Join(revertibleNotes, "\n") query, err := sqlparser.ParseAndBind(sqlUpdateSchemaAnalysis, sqltypes.Int64BindVariable(int64(addedUniqueKeys)), sqltypes.Int64BindVariable(int64(removedUniqueKeys)), @@ -4497,7 +4555,7 @@ func (e *Executor) updateSchemaAnalysis(ctx context.Context, uuid string, sqltypes.StringBindVariable(removedForeignKeyNames), sqltypes.StringBindVariable(droppedNoDefaultColumnNames), sqltypes.StringBindVariable(expandedColumnNames), - sqltypes.StringBindVariable(revertibleNotes), + sqltypes.StringBindVariable(notes), sqltypes.StringBindVariable(uuid), ) if err != nil { @@ -4573,10 +4631,17 @@ func (e *Executor) updateMigrationETASecondsByProgress(ctx context.Context, uuid return err } -func (e *Executor) updateMigrationLastThrottled(ctx context.Context, uuid string, lastThrottledTime time.Time, throttledCompnent string) error { +func (e *Executor) updateMigrationLastThrottled( + ctx context.Context, + uuid string, + lastThrottledTime time.Time, + throttledCompnent string, + reasonThrottled string, +) error { query, err := sqlparser.ParseAndBind(sqlUpdateLastThrottled, sqltypes.StringBindVariable(lastThrottledTime.Format(sqltypes.TimestampFormat)), sqltypes.StringBindVariable(throttledCompnent), + sqltypes.StringBindVariable(reasonThrottled), sqltypes.StringBindVariable(uuid), ) if err != nil { @@ -4758,6 +4823,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). @@ -5270,3 +5355,20 @@ func (e *Executor) OnSchemaMigrationStatus(ctx context.Context, return e.onSchemaMigrationStatus(ctx, uuidParam, status, dryRun, progressPct, etaSeconds, rowsCopied, hint) } + +func (e *Executor) checkOnPreparedPool(ctx context.Context, table string, waitTime time.Duration) error { + if e.isPreparedPoolEmpty(table) { + return nil + } + + select { + case <-ctx.Done(): + // Return context error if context is done + return ctx.Err() + case <-time.After(waitTime): + if e.isPreparedPoolEmpty(table) { + return nil + } + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot force cut-over on non-empty prepared pool for table: %s", table) + } +} diff --git a/go/vt/vttablet/onlineddl/executor_test.go b/go/vt/vttablet/onlineddl/executor_test.go index 1dc5447bbb9..d5e7f635a19 100644 --- a/go/vt/vttablet/onlineddl/executor_test.go +++ b/go/vt/vttablet/onlineddl/executor_test.go @@ -481,6 +481,38 @@ func TestShouldCutOverAccordingToBackoff(t *testing.T) { expectShouldCutOver: false, expectShouldForceCutOver: false, }, + { + name: "zero since ready", + cutoverAttempts: 3, + forceCutOverAfter: time.Second, + sinceReadyToComplete: 0, + expectShouldCutOver: false, + expectShouldForceCutOver: false, + }, + { + name: "zero since read, zero cut-over-after", + cutoverAttempts: 3, + forceCutOverAfter: 0, + sinceReadyToComplete: 0, + expectShouldCutOver: false, + expectShouldForceCutOver: false, + }, + { + name: "microsecond", + cutoverAttempts: 3, + forceCutOverAfter: time.Microsecond, + sinceReadyToComplete: time.Millisecond, + expectShouldCutOver: true, + expectShouldForceCutOver: true, + }, + { + name: "microsecond, not ready", + cutoverAttempts: 3, + forceCutOverAfter: time.Millisecond, + sinceReadyToComplete: time.Microsecond, + expectShouldCutOver: false, + expectShouldForceCutOver: false, + }, { name: "cutover-after overrides backoff", cutoverAttempts: 3, diff --git a/go/vt/vttablet/onlineddl/schema.go b/go/vt/vttablet/onlineddl/schema.go index 30f132bd0e3..9023639fd00 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 @@ -202,7 +209,9 @@ const ( migration_uuid=%a ` sqlUpdateMessage = `UPDATE _vt.schema_migrations - SET message=%a + SET + message=%a, + message_timestamp=NOW(6) WHERE migration_uuid=%a ` @@ -242,7 +251,7 @@ const ( migration_uuid=%a ` sqlUpdateLastThrottled = `UPDATE _vt.schema_migrations - SET last_throttled_timestamp=%a, component_throttled=%a + SET last_throttled_timestamp=%a, component_throttled=%a, reason_throttled=%a WHERE migration_uuid=%a ` @@ -297,7 +306,7 @@ const ( postpone_completion, force_cutover, cutover_attempts, - ifnull(timestampdiff(second, ready_to_complete_timestamp, now()), 0) as seconds_since_ready_to_complete, + ifnull(timestampdiff(microsecond, ready_to_complete_timestamp, now(6)), 0) as microseconds_since_ready_to_complete, ifnull(timestampdiff(second, last_cutover_attempt_timestamp, now()), 0) as seconds_since_last_cutover_attempt, timestampdiff(second, started_timestamp, now()) as elapsed_seconds FROM _vt.schema_migrations @@ -428,6 +437,7 @@ const ( last_throttled_timestamp, cancelled_timestamp, component_throttled, + reason_throttled, postpone_launch, postpone_completion, is_immediate_operation, @@ -453,16 +463,6 @@ const ( AND ACTION_TIMING='AFTER' AND LEFT(TRIGGER_NAME, 7)='pt_osc_' ` - sqlSelectColumnTypes = ` - select - *, - COLUMN_DEFAULT IS NULL AS is_default_null - from - information_schema.columns - where - table_schema=%a - and table_name=%a - ` selSelectCountFKParentConstraints = ` SELECT COUNT(*) as num_fk_constraints @@ -479,75 +479,10 @@ const ( TABLE_SCHEMA=%a AND TABLE_NAME=%a AND REFERENCED_TABLE_NAME IS NOT NULL ` - sqlSelectUniqueKeys = ` - SELECT - COLUMNS.TABLE_SCHEMA as table_schema, - COLUMNS.TABLE_NAME as table_name, - COLUMNS.COLUMN_NAME as column_name, - UNIQUES.INDEX_NAME as index_name, - UNIQUES.COLUMN_NAMES as column_names, - UNIQUES.COUNT_COLUMN_IN_INDEX as count_column_in_index, - COLUMNS.DATA_TYPE as data_type, - COLUMNS.CHARACTER_SET_NAME as character_set_name, - LOCATE('auto_increment', EXTRA) > 0 as is_auto_increment, - (DATA_TYPE='float' OR DATA_TYPE='double') AS is_float, - has_subpart, - has_nullable - FROM INFORMATION_SCHEMA.COLUMNS INNER JOIN ( - SELECT - TABLE_SCHEMA, - TABLE_NAME, - INDEX_NAME, - COUNT(*) AS COUNT_COLUMN_IN_INDEX, - GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC) AS COLUMN_NAMES, - SUBSTRING_INDEX(GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC), ',', 1) AS FIRST_COLUMN_NAME, - SUM(SUB_PART IS NOT NULL) > 0 AS has_subpart, - SUM(NULLABLE='YES') > 0 AS has_nullable - FROM INFORMATION_SCHEMA.STATISTICS - WHERE - NON_UNIQUE=0 - AND TABLE_SCHEMA=%a - AND TABLE_NAME=%a - GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME - ) AS UNIQUES - ON ( - COLUMNS.COLUMN_NAME = UNIQUES.FIRST_COLUMN_NAME - ) - WHERE - COLUMNS.TABLE_SCHEMA=%a - AND COLUMNS.TABLE_NAME=%a - ORDER BY - COLUMNS.TABLE_SCHEMA, COLUMNS.TABLE_NAME, - CASE UNIQUES.INDEX_NAME - WHEN 'PRIMARY' THEN 0 - ELSE 1 - END, - CASE has_nullable - WHEN 0 THEN 0 - ELSE 1 - END, - CASE has_subpart - WHEN 0 THEN 0 - ELSE 1 - END, - CASE IFNULL(CHARACTER_SET_NAME, '') - WHEN '' THEN 0 - ELSE 1 - END, - CASE DATA_TYPE - WHEN 'tinyint' THEN 0 - WHEN 'smallint' THEN 1 - WHEN 'int' THEN 2 - WHEN 'bigint' THEN 3 - ELSE 100 - END, - COUNT_COLUMN_IN_INDEX - ` sqlDropTrigger = "DROP TRIGGER IF EXISTS `%a`.`%a`" sqlShowTablesLike = "SHOW TABLES LIKE '%a'" sqlDropTable = "DROP TABLE `%a`" sqlDropTableIfExists = "DROP TABLE IF EXISTS `%a`" - sqlShowColumnsFrom = "SHOW COLUMNS FROM `%a`" sqlShowTableStatus = "SHOW TABLE STATUS LIKE '%a'" sqlAnalyzeTable = "ANALYZE NO_WRITE_TO_BINLOG TABLE `%a`" sqlShowCreateTable = "SHOW CREATE TABLE `%a`" @@ -555,23 +490,14 @@ const ( sqlShowVariablesLikeFastAnalyzeTable = "show global variables like 'fast_analyze_table'" sqlEnableFastAnalyzeTable = "set @@fast_analyze_table = 1" sqlDisableFastAnalyzeTable = "set @@fast_analyze_table = 0" - sqlGetAutoIncrement = ` - SELECT - AUTO_INCREMENT - FROM INFORMATION_SCHEMA.TABLES - WHERE - TABLES.TABLE_SCHEMA=%a - AND TABLES.TABLE_NAME=%a - AND AUTO_INCREMENT IS NOT NULL - ` - sqlAlterTableAutoIncrement = "ALTER TABLE `%s` AUTO_INCREMENT=%a" - sqlAlterTableExchangePartition = "ALTER TABLE `%a` EXCHANGE PARTITION `%a` WITH TABLE `%a`" - sqlAlterTableRemovePartitioning = "ALTER TABLE `%a` REMOVE PARTITIONING" - sqlAlterTableDropPartition = "ALTER TABLE `%a` DROP PARTITION `%a`" - sqlStartVReplStream = "UPDATE _vt.vreplication set state='Running' where db_name=%a and workflow=%a" - sqlStopVReplStream = "UPDATE _vt.vreplication set state='Stopped' where db_name=%a and workflow=%a" - sqlDeleteVReplStream = "DELETE FROM _vt.vreplication where db_name=%a and workflow=%a" - sqlReadVReplStream = `SELECT + sqlAlterTableAutoIncrement = "ALTER TABLE `%s` AUTO_INCREMENT=%a" + sqlAlterTableExchangePartition = "ALTER TABLE `%a` EXCHANGE PARTITION `%a` WITH TABLE `%a`" + sqlAlterTableRemovePartitioning = "ALTER TABLE `%a` REMOVE PARTITIONING" + sqlAlterTableDropPartition = "ALTER TABLE `%a` DROP PARTITION `%a`" + sqlStartVReplStream = "UPDATE _vt.vreplication set state='Running' where db_name=%a and workflow=%a" + sqlStopVReplStream = "UPDATE _vt.vreplication set state='Stopped' where db_name=%a and workflow=%a" + sqlDeleteVReplStream = "DELETE FROM _vt.vreplication where db_name=%a and workflow=%a" + sqlReadVReplStream = `SELECT id, workflow, source, @@ -581,6 +507,7 @@ const ( time_heartbeat, time_throttled, component_throttled, + reason_throttled, state, message, rows_copied diff --git a/go/vt/vttablet/onlineddl/vrepl.go b/go/vt/vttablet/onlineddl/vrepl.go index cde2f276563..58e6a2c8b3a 100644 --- a/go/vt/vttablet/onlineddl/vrepl.go +++ b/go/vt/vttablet/onlineddl/vrepl.go @@ -38,11 +38,10 @@ import ( "vitess.io/vitess/go/textutil" "vitess.io/vitess/go/vt/dbconnpool" "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/schemadiff" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/onlineddl/vrepl" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" @@ -59,6 +58,7 @@ type VReplStream struct { timeHeartbeat int64 timeThrottled int64 componentThrottled string + reasonThrottled string transactionTimestamp int64 state binlogdatapb.VReplicationWorkflowState message string @@ -98,43 +98,23 @@ func (v *VReplStream) hasError() (isTerminal bool, vreplError error) { // VRepl is an online DDL helper for VReplication based migrations (ddl_strategy="online") type VRepl struct { - workflow string - keyspace string - shard string - dbName string - sourceTable string - targetTable string - pos string - alterQuery *sqlparser.AlterTable - tableRows int64 - - originalCreateTable *sqlparser.CreateTable - vreplCreateTable *sqlparser.CreateTable + workflow string + keyspace string + shard string + dbName string + pos string + tableRows int64 - analyzeTable bool - - sourceSharedColumns *vrepl.ColumnList - targetSharedColumns *vrepl.ColumnList - droppedSourceNonGeneratedColumns *vrepl.ColumnList - droppedNoDefaultColumnNames []string - expandedColumnNames []string - sharedColumnsMap map[string]string - sourceAutoIncrement uint64 + sourceCreateTableEntity *schemadiff.CreateTableEntity + targetCreateTableEntity *schemadiff.CreateTableEntity + analysis *schemadiff.MigrationTablesAnalysis - chosenSourceUniqueKey *vrepl.UniqueKey - chosenTargetUniqueKey *vrepl.UniqueKey - - addedUniqueKeys []*vrepl.UniqueKey - removedUniqueKeys []*vrepl.UniqueKey - removedForeignKeyNames []string + analyzeTable bool - revertibleNotes string - filterQuery string - enumToTextMap map[string]string - intToEnumMap map[string]bool - bls *binlogdatapb.BinlogSource + filterQuery string + bls *binlogdatapb.BinlogSource - parser *vrepl.AlterTableParser + alterTableAnalysis *schemadiff.AlterTableAnalysis convertCharset map[string](*binlogdatapb.CharsetConversion) @@ -148,110 +128,40 @@ func NewVRepl( keyspace string, shard string, dbName string, - sourceTable string, - targetTable string, - originalCreateTable *sqlparser.CreateTable, - vreplCreateTable *sqlparser.CreateTable, + sourceCreateTable *sqlparser.CreateTable, + targetCreateTable *sqlparser.CreateTable, alterQuery *sqlparser.AlterTable, analyzeTable bool, -) *VRepl { - return &VRepl{ - env: env, - workflow: workflow, - keyspace: keyspace, - shard: shard, - dbName: dbName, - sourceTable: sourceTable, - targetTable: targetTable, - originalCreateTable: originalCreateTable, - vreplCreateTable: vreplCreateTable, - alterQuery: alterQuery, - analyzeTable: analyzeTable, - parser: vrepl.NewAlterTableParser(), - enumToTextMap: map[string]string{}, - intToEnumMap: map[string]bool{}, - convertCharset: map[string](*binlogdatapb.CharsetConversion){}, - } -} - -// readAutoIncrement reads the AUTO_INCREMENT value, if any, for a give ntable -func (v *VRepl) readAutoIncrement(ctx context.Context, conn *dbconnpool.DBConnection, tableName string) (autoIncrement uint64, err error) { - query, err := sqlparser.ParseAndBind(sqlGetAutoIncrement, - sqltypes.StringBindVariable(v.dbName), - sqltypes.StringBindVariable(tableName), - ) +) (*VRepl, error) { + v := &VRepl{ + env: env, + workflow: workflow, + keyspace: keyspace, + shard: shard, + dbName: dbName, + alterTableAnalysis: schemadiff.OnlineDDLAlterTableAnalysis(alterQuery), + analyzeTable: analyzeTable, + convertCharset: map[string](*binlogdatapb.CharsetConversion){}, + } + senv := schemadiff.NewEnv(v.env, v.env.CollationEnv().DefaultConnectionCharset()) + var err error + v.sourceCreateTableEntity, err = schemadiff.NewCreateTableEntity(senv, sourceCreateTable) if err != nil { - return 0, err + return nil, err } - - rs, err := conn.ExecuteFetch(query, -1, true) + v.targetCreateTableEntity, err = schemadiff.NewCreateTableEntity(senv, targetCreateTable) if err != nil { - return 0, err - } - for _, row := range rs.Named().Rows { - autoIncrement = row.AsUint64("AUTO_INCREMENT", 0) + return nil, err } - - return autoIncrement, nil + return v, nil } -// readTableColumns reads column list from given table -func (v *VRepl) readTableColumns(ctx context.Context, conn *dbconnpool.DBConnection, tableName string) (columns *vrepl.ColumnList, virtualColumns *vrepl.ColumnList, pkColumns *vrepl.ColumnList, err error) { - parsed := sqlparser.BuildParsedQuery(sqlShowColumnsFrom, tableName) - rs, err := conn.ExecuteFetch(parsed.Query, -1, true) - if err != nil { - return nil, nil, nil, err - } - columnNames := []string{} - virtualColumnNames := []string{} - pkColumnNames := []string{} - for _, row := range rs.Named().Rows { - columnName := row.AsString("Field", "") - columnNames = append(columnNames, columnName) - - extra := row.AsString("Extra", "") - if strings.Contains(extra, "STORED GENERATED") || strings.Contains(extra, "VIRTUAL GENERATED") { - virtualColumnNames = append(virtualColumnNames, columnName) - } - - key := row.AsString("Key", "") - if key == "PRI" { - pkColumnNames = append(pkColumnNames, columnName) - } - } - if len(columnNames) == 0 { - return nil, nil, nil, fmt.Errorf("Found 0 columns on `%s`", tableName) - } - return vrepl.NewColumnList(columnNames), vrepl.NewColumnList(virtualColumnNames), vrepl.NewColumnList(pkColumnNames), nil +func (v *VRepl) sourceTableName() string { + return v.sourceCreateTableEntity.Name() } -// readTableUniqueKeys reads all unique keys from a given table, by order of usefulness/performance: PRIMARY first, integers are better, non-null are better -func (v *VRepl) readTableUniqueKeys(ctx context.Context, conn *dbconnpool.DBConnection, tableName string) (uniqueKeys []*vrepl.UniqueKey, err error) { - query, err := sqlparser.ParseAndBind(sqlSelectUniqueKeys, - sqltypes.StringBindVariable(v.dbName), - sqltypes.StringBindVariable(tableName), - sqltypes.StringBindVariable(v.dbName), - sqltypes.StringBindVariable(tableName), - ) - if err != nil { - return nil, err - } - rs, err := conn.ExecuteFetch(query, -1, true) - if err != nil { - return nil, err - } - for _, row := range rs.Named().Rows { - uniqueKey := &vrepl.UniqueKey{ - Name: row.AsString("index_name", ""), - Columns: *vrepl.ParseColumnList(row.AsString("column_names", "")), - HasNullable: row.AsBool("has_nullable", false), - HasSubpart: row.AsBool("has_subpart", false), - HasFloat: row.AsBool("is_float", false), - IsAutoIncrement: row.AsBool("is_auto_increment", false), - } - uniqueKeys = append(uniqueKeys, uniqueKey) - } - return uniqueKeys, nil +func (v *VRepl) targetTableName() string { + return v.targetCreateTableEntity.Name() } // isFastAnalyzeTableSupported checks if the underlying MySQL server supports 'fast_analyze_table', @@ -306,255 +216,64 @@ func (v *VRepl) readTableStatus(ctx context.Context, conn *dbconnpool.DBConnecti return tableRows, err } -// applyColumnTypes -func (v *VRepl) applyColumnTypes(ctx context.Context, conn *dbconnpool.DBConnection, tableName string, columnsLists ...*vrepl.ColumnList) error { - query, err := sqlparser.ParseAndBind(sqlSelectColumnTypes, - sqltypes.StringBindVariable(v.dbName), - sqltypes.StringBindVariable(tableName), - ) - if err != nil { - return err - } - rs, err := conn.ExecuteFetch(query, -1, true) - if err != nil { - return err - } - for _, row := range rs.Named().Rows { - columnName := row["COLUMN_NAME"].ToString() - columnType := row["COLUMN_TYPE"].ToString() - columnOctetLength := row.AsUint64("CHARACTER_OCTET_LENGTH", 0) - - for _, columnsList := range columnsLists { - column := columnsList.GetColumn(columnName) - if column == nil { - continue - } - - column.DataType = row.AsString("DATA_TYPE", "") // a more canonical form of column_type - column.IsNullable = (row.AsString("IS_NULLABLE", "") == "YES") - column.IsDefaultNull = row.AsBool("is_default_null", false) - - column.CharacterMaximumLength = row.AsInt64("CHARACTER_MAXIMUM_LENGTH", 0) - column.NumericPrecision = row.AsInt64("NUMERIC_PRECISION", 0) - column.NumericScale = row.AsInt64("NUMERIC_SCALE", 0) - column.DateTimePrecision = row.AsInt64("DATETIME_PRECISION", -1) - - column.Type = vrepl.UnknownColumnType - if strings.Contains(columnType, "unsigned") { - column.IsUnsigned = true - } - if strings.Contains(columnType, "mediumint") { - column.SetTypeIfUnknown(vrepl.MediumIntColumnType) - } - if strings.Contains(columnType, "timestamp") { - column.SetTypeIfUnknown(vrepl.TimestampColumnType) - } - if strings.Contains(columnType, "datetime") { - column.SetTypeIfUnknown(vrepl.DateTimeColumnType) - } - if strings.Contains(columnType, "json") { - column.SetTypeIfUnknown(vrepl.JSONColumnType) - } - if strings.Contains(columnType, "float") { - column.SetTypeIfUnknown(vrepl.FloatColumnType) - } - if strings.Contains(columnType, "double") { - column.SetTypeIfUnknown(vrepl.DoubleColumnType) - } - if strings.HasPrefix(columnType, "enum") { - column.SetTypeIfUnknown(vrepl.EnumColumnType) - column.EnumValues = schema.ParseEnumValues(columnType) - } - if strings.HasPrefix(columnType, "set(") { - column.SetTypeIfUnknown(vrepl.SetColumnType) - column.EnumValues = schema.ParseSetValues(columnType) - } - if strings.HasPrefix(columnType, "binary") { - column.SetTypeIfUnknown(vrepl.BinaryColumnType) - column.BinaryOctetLength = columnOctetLength - } - if charset := row.AsString("CHARACTER_SET_NAME", ""); charset != "" { - column.Charset = charset - } - if collation := row.AsString("COLLATION_NAME", ""); collation != "" { - column.SetTypeIfUnknown(vrepl.StringColumnType) - column.Collation = collation +// formalizeColumns +func formalizeColumns(columnsLists ...*schemadiff.ColumnDefinitionEntityList) error { + for _, colList := range columnsLists { + for _, col := range colList.Entities { + col.SetExplicitDefaultAndNull() + if err := col.SetExplicitCharsetCollate(); err != nil { + return err } } } return nil } -func (v *VRepl) analyzeAlter(ctx context.Context) error { - if v.alterQuery == nil { - // Happens for REVERT - return nil - } - v.parser.AnalyzeAlter(v.alterQuery) - if v.parser.IsRenameTable() { - return fmt.Errorf("Renaming the table is not supported in ALTER TABLE: %s", sqlparser.CanonicalString(v.alterQuery)) +func (v *VRepl) analyzeAlter() error { + if v.alterTableAnalysis.IsRenameTable { + return fmt.Errorf("renaming the table is not supported in ALTER TABLE") } return nil } -func (v *VRepl) analyzeTables(ctx context.Context, conn *dbconnpool.DBConnection) (err error) { - if v.analyzeTable { - if err := v.executeAnalyzeTable(ctx, conn, v.sourceTable); err != nil { - return err - } - } - v.tableRows, err = v.readTableStatus(ctx, conn, v.sourceTable) - if err != nil { - return err - } - // columns: - sourceColumns, sourceVirtualColumns, sourcePKColumns, err := v.readTableColumns(ctx, conn, v.sourceTable) - if err != nil { - return err - } - targetColumns, targetVirtualColumns, targetPKColumns, err := v.readTableColumns(ctx, conn, v.targetTable) - if err != nil { - return err - } - v.sourceSharedColumns, v.targetSharedColumns, v.droppedSourceNonGeneratedColumns, v.sharedColumnsMap = vrepl.GetSharedColumns(sourceColumns, targetColumns, sourceVirtualColumns, targetVirtualColumns, v.parser) - - // unique keys - sourceUniqueKeys, err := v.readTableUniqueKeys(ctx, conn, v.sourceTable) - if err != nil { - return err - } - if len(sourceUniqueKeys) == 0 { - return fmt.Errorf("Found no possible unique key on `%s`", v.sourceTable) - } - targetUniqueKeys, err := v.readTableUniqueKeys(ctx, conn, v.targetTable) +func (v *VRepl) analyzeTables() (err error) { + analysis, err := schemadiff.OnlineDDLMigrationTablesAnalysis(v.sourceCreateTableEntity, v.targetCreateTableEntity, v.alterTableAnalysis) if err != nil { return err } - if len(targetUniqueKeys) == 0 { - return fmt.Errorf("Found no possible unique key on `%s`", v.targetTable) - } - v.chosenSourceUniqueKey, v.chosenTargetUniqueKey = vrepl.GetSharedUniqueKeys(sourceUniqueKeys, targetUniqueKeys, v.parser.ColumnRenameMap()) - if v.chosenSourceUniqueKey == nil { - // VReplication supports completely different unique keys on source and target, covering - // some/completely different columns. The condition is that the key on source - // must use columns which all exist on target table. - v.chosenSourceUniqueKey = vrepl.GetUniqueKeyCoveredByColumns(sourceUniqueKeys, v.sourceSharedColumns) - if v.chosenSourceUniqueKey == nil { - // Still no luck. - return fmt.Errorf("Found no possible unique key on `%s` whose columns are in target table `%s`", v.sourceTable, v.targetTable) - } - } - if v.chosenTargetUniqueKey == nil { - // VReplication supports completely different unique keys on source and target, covering - // some/completely different columns. The condition is that the key on target - // must use columns which all exist on source table. - v.chosenTargetUniqueKey = vrepl.GetUniqueKeyCoveredByColumns(targetUniqueKeys, v.targetSharedColumns) - if v.chosenTargetUniqueKey == nil { - // Still no luck. - return fmt.Errorf("Found no possible unique key on `%s` whose columns are in source table `%s`", v.targetTable, v.sourceTable) - } - } - if v.chosenSourceUniqueKey == nil || v.chosenTargetUniqueKey == nil { - return fmt.Errorf("Found no shared, not nullable, unique keys between `%s` and `%s`", v.sourceTable, v.targetTable) - } - v.addedUniqueKeys = vrepl.AddedUniqueKeys(sourceUniqueKeys, targetUniqueKeys, v.parser.ColumnRenameMap()) - v.removedUniqueKeys = vrepl.RemovedUniqueKeys(sourceUniqueKeys, targetUniqueKeys, v.parser.ColumnRenameMap()) - v.removedForeignKeyNames, err = vrepl.RemovedForeignKeyNames(v.env, v.originalCreateTable, v.vreplCreateTable) - if err != nil { - return err - } - - // chosen source & target unique keys have exact columns in same order - sharedPKColumns := &v.chosenSourceUniqueKey.Columns + v.analysis = analysis - if err := v.applyColumnTypes(ctx, conn, v.sourceTable, sourceColumns, sourceVirtualColumns, sourcePKColumns, v.sourceSharedColumns, sharedPKColumns, v.droppedSourceNonGeneratedColumns); err != nil { - return err - } - if err := v.applyColumnTypes(ctx, conn, v.targetTable, targetColumns, targetVirtualColumns, targetPKColumns, v.targetSharedColumns); err != nil { - return err - } - - for _, sourcePKColumn := range sharedPKColumns.Columns() { - mappedColumn := v.targetSharedColumns.GetColumn(sourcePKColumn.Name) - if sourcePKColumn.Type == vrepl.EnumColumnType && mappedColumn.Type == vrepl.EnumColumnType { - // An ENUM as part of PRIMARY KEY. We must convert it to text because OMG that's complicated. - // There's a scenario where a query may modify the enum value (and it's bad practice, seeing - // that it's part of the PK, but it's still valid), and in that case we must have the string value - // to be able to DELETE the old row - v.targetSharedColumns.SetEnumToTextConversion(mappedColumn.Name, sourcePKColumn.EnumValues) - v.enumToTextMap[sourcePKColumn.Name] = sourcePKColumn.EnumValues - } - } - - for i := range v.sourceSharedColumns.Columns() { - sourceColumn := v.sourceSharedColumns.Columns()[i] - mappedColumn := v.targetSharedColumns.Columns()[i] - if sourceColumn.Type == vrepl.EnumColumnType { - switch { - // Either this is an ENUM column that stays an ENUM, or it is converted to a textual type. - // We take note of the enum values, and make it available in vreplication's Filter.Rule.ConvertEnumToText. - // This, in turn, will be used by vplayer (in TablePlan) like so: - // - In the binary log, enum values are integers. - // - Upon seeing this map, PlanBuilder will convert said int to the enum's logical string value. - // - And will apply the value as a string (`StringBindVariable`) in the query. - // What this allows is for enum values to have different ordering in the before/after table schema, - // so that for example you could modify an enum column: - // - from `('red', 'green', 'blue')` to `('red', 'blue')` - // - from `('red', 'green', 'blue')` to `('blue', 'red', 'green')` - case mappedColumn.Type == vrepl.EnumColumnType: - v.enumToTextMap[sourceColumn.Name] = sourceColumn.EnumValues - case mappedColumn.Charset != "": - v.enumToTextMap[sourceColumn.Name] = sourceColumn.EnumValues - v.targetSharedColumns.SetEnumToTextConversion(mappedColumn.Name, sourceColumn.EnumValues) - } - } + return nil +} - if sourceColumn.IsIntegralType() && mappedColumn.Type == vrepl.EnumColumnType { - v.intToEnumMap[sourceColumn.Name] = true +// analyzeTableStatus reads information from SHOW TABLE STATUS +func (v *VRepl) analyzeTableStatus(ctx context.Context, conn *dbconnpool.DBConnection) (err error) { + if v.analyzeTable { + if err := v.executeAnalyzeTable(ctx, conn, v.sourceTableName()); err != nil { + return err } } - - v.droppedNoDefaultColumnNames = vrepl.GetNoDefaultColumnNames(v.droppedSourceNonGeneratedColumns) - var expandedDescriptions map[string]string - v.expandedColumnNames, expandedDescriptions = vrepl.GetExpandedColumnNames(v.sourceSharedColumns, v.targetSharedColumns) - - v.sourceAutoIncrement, err = v.readAutoIncrement(ctx, conn, v.sourceTable) - - notes := []string{} - for _, uk := range v.removedUniqueKeys { - notes = append(notes, fmt.Sprintf("unique constraint removed: %s", uk.Name)) - } - for _, name := range v.droppedNoDefaultColumnNames { - notes = append(notes, fmt.Sprintf("column %s dropped, and had no default value", name)) - } - for _, name := range v.expandedColumnNames { - notes = append(notes, fmt.Sprintf("column %s: %s", name, expandedDescriptions[name])) - } - for _, name := range v.removedForeignKeyNames { - notes = append(notes, fmt.Sprintf("foreign key %s dropped", name)) - } - v.revertibleNotes = strings.Join(notes, "\n") + v.tableRows, err = v.readTableStatus(ctx, conn, v.sourceTableName()) if err != nil { return err } - return nil } // generateFilterQuery creates a SELECT query used by vreplication as a filter. It SELECTs all // non-generated columns between source & target tables, and takes care of column renames. -func (v *VRepl) generateFilterQuery(ctx context.Context) error { - if v.sourceSharedColumns.Len() == 0 { - return fmt.Errorf("Empty column list") +func (v *VRepl) generateFilterQuery() error { + if v.analysis.SourceSharedColumns.Len() == 0 { + return fmt.Errorf("empty column list") } var sb strings.Builder sb.WriteString("select ") - for i, sourceCol := range v.sourceSharedColumns.Columns() { - name := sourceCol.Name - targetName := v.sharedColumnsMap[name] + for i, sourceCol := range v.analysis.SourceSharedColumns.Entities { + name := sourceCol.Name() + targetName := v.analysis.SharedColumnsMap[name] - targetCol := v.targetSharedColumns.GetColumn(targetName) + targetCol := v.analysis.TargetSharedColumns.GetColumn(targetName) if targetCol == nil { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Cannot find target column %s", targetName) } @@ -563,37 +282,41 @@ func (v *VRepl) generateFilterQuery(ctx context.Context) error { sb.WriteString(", ") } switch { - case sourceCol.EnumToTextConversion: + case sourceCol.HasEnumValues(): + // Source is `enum` or `set`. We always take the textual represenation rather than the numeric one. sb.WriteString(fmt.Sprintf("CONCAT(%s)", escapeName(name))) - case v.intToEnumMap[name]: + case v.analysis.IntToEnumMap[name]: sb.WriteString(fmt.Sprintf("CONCAT(%s)", escapeName(name))) - case sourceCol.Type == vrepl.JSONColumnType: + case sourceCol.Type() == "json": sb.WriteString(fmt.Sprintf("convert(%s using utf8mb4)", escapeName(name))) - case sourceCol.Type == vrepl.StringColumnType: + case targetCol.Type() == "json": // we already know the source col is not JSON, per the above `case` condition + // Convert any type to JSON: encode the type as utf8mb4 text + sb.WriteString(fmt.Sprintf("convert(%s using utf8mb4)", escapeName(name))) + case sourceCol.IsTextual(): // Check source and target charset/encoding. If needed, create // a binlogdatapb.CharsetConversion entry (later written to vreplication) - fromCollation := v.env.CollationEnv().DefaultCollationForCharset(sourceCol.Charset) + fromCollation := v.env.CollationEnv().DefaultCollationForCharset(sourceCol.Charset()) if fromCollation == collations.Unknown { - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Character set %s not supported for column %s", sourceCol.Charset, sourceCol.Name) + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Character set %s not supported for column %s", sourceCol.Charset(), sourceCol.Name()) } - toCollation := v.env.CollationEnv().DefaultCollationForCharset(targetCol.Charset) + toCollation := v.env.CollationEnv().DefaultCollationForCharset(targetCol.Charset()) // Let's see if target col is at all textual - if targetCol.Type == vrepl.StringColumnType && toCollation == collations.Unknown { - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Character set %s not supported for column %s", targetCol.Charset, targetCol.Name) + if targetCol.IsTextual() && toCollation == collations.Unknown { + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Character set %s not supported for column %s", targetCol.Charset(), targetCol.Name()) } - - if trivialCharset(fromCollation) && trivialCharset(toCollation) && targetCol.Type != vrepl.JSONColumnType { + if trivialCharset(fromCollation) && trivialCharset(toCollation) { + sb.WriteString(escapeName(name)) + } else if fromCollation == toCollation { + // No need for charset conversions as both have the same collation. sb.WriteString(escapeName(name)) } else { + // Charset conversion required: v.convertCharset[targetName] = &binlogdatapb.CharsetConversion{ - FromCharset: sourceCol.Charset, - ToCharset: targetCol.Charset, + FromCharset: sourceCol.Charset(), + ToCharset: targetCol.Charset(), } - sb.WriteString(fmt.Sprintf("convert(%s using utf8mb4)", escapeName(name))) + sb.WriteString(escapeName(name)) } - case targetCol.Type == vrepl.JSONColumnType && sourceCol.Type != vrepl.JSONColumnType: - // Convert any type to JSON: encode the type as utf8mb4 text - sb.WriteString(fmt.Sprintf("convert(%s using utf8mb4)", escapeName(name))) default: sb.WriteString(escapeName(name)) } @@ -601,7 +324,7 @@ func (v *VRepl) generateFilterQuery(ctx context.Context) error { sb.WriteString(escapeName(targetName)) } sb.WriteString(" from ") - sb.WriteString(escapeName(v.sourceTable)) + sb.WriteString(escapeName(v.sourceTableName())) v.filterQuery = sb.String() return nil @@ -623,25 +346,22 @@ func (v *VRepl) analyzeBinlogSource(ctx context.Context) { StopAfterCopy: false, } - encodeColumns := func(columns *vrepl.ColumnList) string { - return textutil.EscapeJoin(columns.Names(), ",") + encodeColumns := func(names []string) string { + return textutil.EscapeJoin(names, ",") } rule := &binlogdatapb.Rule{ - Match: v.targetTable, + Match: v.targetTableName(), Filter: v.filterQuery, - SourceUniqueKeyColumns: encodeColumns(&v.chosenSourceUniqueKey.Columns), - TargetUniqueKeyColumns: encodeColumns(&v.chosenTargetUniqueKey.Columns), - SourceUniqueKeyTargetColumns: encodeColumns(v.chosenSourceUniqueKey.Columns.MappedNamesColumnList(v.sharedColumnsMap)), - ForceUniqueKey: url.QueryEscape(v.chosenSourceUniqueKey.Name), + SourceUniqueKeyColumns: encodeColumns(v.analysis.ChosenSourceUniqueKey.ColumnList.Names()), + TargetUniqueKeyColumns: encodeColumns(v.analysis.ChosenTargetUniqueKey.ColumnList.Names()), + SourceUniqueKeyTargetColumns: encodeColumns(schemadiff.MappedColumnNames(v.analysis.ChosenSourceUniqueKey.ColumnList, v.analysis.SharedColumnsMap)), + ForceUniqueKey: url.QueryEscape(v.analysis.ChosenSourceUniqueKey.Name()), } if len(v.convertCharset) > 0 { rule.ConvertCharset = v.convertCharset } - if len(v.enumToTextMap) > 0 { - rule.ConvertEnumToText = v.enumToTextMap - } - if len(v.intToEnumMap) > 0 { - rule.ConvertIntToEnum = v.intToEnumMap + if len(v.analysis.IntToEnumMap) > 0 { + rule.ConvertIntToEnum = v.analysis.IntToEnumMap } bls.Filter.Rules = append(bls.Filter.Rules, rule) @@ -649,13 +369,16 @@ func (v *VRepl) analyzeBinlogSource(ctx context.Context) { } func (v *VRepl) analyze(ctx context.Context, conn *dbconnpool.DBConnection) error { - if err := v.analyzeAlter(ctx); err != nil { + if err := v.analyzeAlter(); err != nil { + return err + } + if err := v.analyzeTables(); err != nil { return err } - if err := v.analyzeTables(ctx, conn); err != nil { + if err := v.generateFilterQuery(); err != nil { return err } - if err := v.generateFilterQuery(ctx); err != nil { + if err := v.analyzeTableStatus(ctx, conn); err != nil { return err } v.analyzeBinlogSource(ctx) @@ -663,7 +386,7 @@ func (v *VRepl) analyze(ctx context.Context, conn *dbconnpool.DBConnection) erro } // generateInsertStatement generates the INSERT INTO _vt.replication statement that creates the vreplication workflow -func (v *VRepl) generateInsertStatement(ctx context.Context) (string, error) { +func (v *VRepl) generateInsertStatement() (string, error) { ig := vreplication.NewInsertGenerator(binlogdatapb.VReplicationWorkflowState_Stopped, v.dbName) ig.AddRow(v.workflow, v.bls, v.pos, "", "in_order:REPLICA,PRIMARY", binlogdatapb.VReplicationWorkflowType_OnlineDDL, binlogdatapb.VReplicationWorkflowSubType_None, false) @@ -672,7 +395,7 @@ func (v *VRepl) generateInsertStatement(ctx context.Context) (string, error) { } // generateStartStatement Generates the statement to start VReplication running on the workflow -func (v *VRepl) generateStartStatement(ctx context.Context) (string, error) { +func (v *VRepl) generateStartStatement() (string, error) { return sqlparser.ParseAndBind(sqlStartVReplStream, sqltypes.StringBindVariable(v.dbName), sqltypes.StringBindVariable(v.workflow), diff --git a/go/vt/vttablet/onlineddl/vrepl/columns.go b/go/vt/vttablet/onlineddl/vrepl/columns.go deleted file mode 100644 index f2bb8f6d3f2..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/columns.go +++ /dev/null @@ -1,208 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "fmt" - "strings" - - "vitess.io/vitess/go/vt/schema" -) - -// expandedDataTypes maps some known and difficult-to-compute by INFORMATION_SCHEMA data types which expand other data types. -// For example, in "date:datetime", datetime expands date because it has more precision. In "timestamp:date" date expands timestamp -// because it can contain years not covered by timestamp. -var expandedDataTypes = map[string]bool{ - "time:datetime": true, - "date:datetime": true, - "timestamp:datetime": true, - "time:timestamp": true, - "date:timestamp": true, - "timestamp:date": true, -} - -// GetSharedColumns returns the intersection of two lists of columns in same order as the first list -func GetSharedColumns( - sourceColumns, targetColumns *ColumnList, - sourceVirtualColumns, targetVirtualColumns *ColumnList, - parser *AlterTableParser, -) ( - sourceSharedColumns *ColumnList, - targetSharedColumns *ColumnList, - droppedSourceNonGeneratedColumns *ColumnList, - sharedColumnsMap map[string]string, -) { - sharedColumnNames := []string{} - droppedSourceNonGeneratedColumnsNames := []string{} - for _, sourceColumn := range sourceColumns.Names() { - isSharedColumn := false - isVirtualColumnOnSource := false - for _, targetColumn := range targetColumns.Names() { - if strings.EqualFold(sourceColumn, targetColumn) { - // both tables have this column. Good start. - isSharedColumn = true - break - } - if strings.EqualFold(parser.columnRenameMap[sourceColumn], targetColumn) { - // column in source is renamed in target - isSharedColumn = true - break - } - } - for droppedColumn := range parser.DroppedColumnsMap() { - if strings.EqualFold(sourceColumn, droppedColumn) { - isSharedColumn = false - break - } - } - for _, virtualColumn := range sourceVirtualColumns.Names() { - // virtual/generated columns on source are silently skipped - if strings.EqualFold(sourceColumn, virtualColumn) { - isSharedColumn = false - isVirtualColumnOnSource = true - } - } - for _, virtualColumn := range targetVirtualColumns.Names() { - // virtual/generated columns on target are silently skipped - if strings.EqualFold(sourceColumn, virtualColumn) { - isSharedColumn = false - } - } - if isSharedColumn { - sharedColumnNames = append(sharedColumnNames, sourceColumn) - } else if !isVirtualColumnOnSource { - droppedSourceNonGeneratedColumnsNames = append(droppedSourceNonGeneratedColumnsNames, sourceColumn) - } - } - sharedColumnsMap = map[string]string{} - for _, columnName := range sharedColumnNames { - if mapped, ok := parser.columnRenameMap[columnName]; ok { - sharedColumnsMap[columnName] = mapped - } else { - sharedColumnsMap[columnName] = columnName - } - } - mappedSharedColumnNames := []string{} - for _, columnName := range sharedColumnNames { - mappedSharedColumnNames = append(mappedSharedColumnNames, sharedColumnsMap[columnName]) - } - return NewColumnList(sharedColumnNames), NewColumnList(mappedSharedColumnNames), NewColumnList(droppedSourceNonGeneratedColumnsNames), sharedColumnsMap -} - -// isExpandedColumn sees if target column has any value set/range that is impossible in source column. See GetExpandedColumns comment for examples -func isExpandedColumn(sourceColumn *Column, targetColumn *Column) (bool, string) { - if targetColumn.IsNullable && !sourceColumn.IsNullable { - return true, "target is NULL-able, source is not" - } - if targetColumn.CharacterMaximumLength > sourceColumn.CharacterMaximumLength { - return true, "increased CHARACTER_MAXIMUM_LENGTH" - } - if targetColumn.NumericPrecision > sourceColumn.NumericPrecision { - return true, "increased NUMERIC_PRECISION" - } - if targetColumn.NumericScale > sourceColumn.NumericScale { - return true, "increased NUMERIC_SCALE" - } - if targetColumn.DateTimePrecision > sourceColumn.DateTimePrecision { - return true, "increased DATETIME_PRECISION" - } - if sourceColumn.IsNumeric() && targetColumn.IsNumeric() { - if sourceColumn.IsUnsigned && !targetColumn.IsUnsigned { - return true, "source is unsigned, target is signed" - } - if sourceColumn.NumericPrecision <= targetColumn.NumericPrecision && !sourceColumn.IsUnsigned && targetColumn.IsUnsigned { - // e.g. INT SIGNED => INT UNSIGNED, INT SIGNED => BIGINT UNSIGNED - return true, "target unsigned value exceeds source unsigned value" - } - if targetColumn.IsFloatingPoint() && !sourceColumn.IsFloatingPoint() { - return true, "target is floating point, source is not" - } - } - if expandedDataTypes[fmt.Sprintf("%s:%s", sourceColumn.DataType, targetColumn.DataType)] { - return true, "target is expanded data type of source" - } - if sourceColumn.Charset != targetColumn.Charset { - if targetColumn.Charset == "utf8mb4" { - return true, "expand character set to utf8mb4" - } - if strings.HasPrefix(targetColumn.Charset, "utf8") && !strings.HasPrefix(sourceColumn.Charset, "utf8") { - // not utf to utf - return true, "expand character set to utf8" - } - } - for _, colType := range []ColumnType{EnumColumnType, SetColumnType} { - // enums and sets have very similar properties, and are practically identical in our analysis - if sourceColumn.Type == colType { - // this is an enum or a set - if targetColumn.Type != colType { - return true, "conversion from enum/set to non-enum/set adds potential values" - } - // target is an enum or a set. See if all values on target exist in source - sourceEnumTokensMap := schema.ParseEnumOrSetTokensMap(sourceColumn.EnumValues) - targetEnumTokensMap := schema.ParseEnumOrSetTokensMap(targetColumn.EnumValues) - for k, v := range targetEnumTokensMap { - if sourceEnumTokensMap[k] != v { - return true, "target enum/set expands source enum/set" - } - } - } - } - return false, "" -} - -// GetExpandedColumnNames is given source and target shared columns, and returns the list of columns whose data type is expanded. -// An expanded data type is one where the target can have a value which the source does not. Examples: -// - any NOT NULL to NULLable (a NULL in the target cannot appear on source) -// - INT -> BIGINT (obvious) -// - BIGINT UNSIGNED -> INT SIGNED (negative values) -// - TIMESTAMP -> TIMESTAMP(3) -// etc. -func GetExpandedColumnNames( - sourceSharedColumns *ColumnList, - targetSharedColumns *ColumnList, -) ( - expandedColumnNames []string, - expandedDescriptions map[string]string, -) { - expandedDescriptions = map[string]string{} - for i := range sourceSharedColumns.Columns() { - // source and target columns assumed to be mapped 1:1, same length - sourceColumn := sourceSharedColumns.Columns()[i] - targetColumn := targetSharedColumns.Columns()[i] - - if isExpanded, description := isExpandedColumn(&sourceColumn, &targetColumn); isExpanded { - expandedColumnNames = append(expandedColumnNames, sourceColumn.Name) - expandedDescriptions[sourceColumn.Name] = description - } - } - return expandedColumnNames, expandedDescriptions -} - -// GetNoDefaultColumnNames returns names of columns which have no default value, out of given list of columns -func GetNoDefaultColumnNames(columns *ColumnList) (names []string) { - names = []string{} - for _, col := range columns.Columns() { - if !col.HasDefault() { - names = append(names, col.Name) - } - } - return names -} diff --git a/go/vt/vttablet/onlineddl/vrepl/columns_test.go b/go/vt/vttablet/onlineddl/vrepl/columns_test.go deleted file mode 100644 index 32efd104cc1..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/columns_test.go +++ /dev/null @@ -1,380 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - columnsA = &ColumnList{ - columns: []Column{ - { - Name: "id", - }, - { - Name: "cint", - }, - { - Name: "cgen1", - }, - { - Name: "cgen2", - }, - { - Name: "cchar", - }, - { - Name: "cremoved", - }, - { - Name: "cnullable", - IsNullable: true, - }, - { - Name: "cnodefault", - IsNullable: false, - IsDefaultNull: true, - }, - }, - Ordinals: ColumnsMap{}, - } - columnsB = &ColumnList{ - columns: []Column{ - { - Name: "id", - }, - { - Name: "cint", - }, - { - Name: "cgen1", - }, - { - Name: "cchar_alternate", - }, - { - Name: "cnullable", - IsNullable: true, - }, - { - Name: "cnodefault", - IsNullable: false, - IsDefaultNull: true, - }, - }, - Ordinals: ColumnsMap{}, - } - columnsVirtual = ParseColumnList("cgen1,cgen2") -) - -func TestGetSharedColumns(t *testing.T) { - tt := []struct { - name string - sourceCols *ColumnList - targetCols *ColumnList - renameMap map[string]string - expectSourceSharedColNames []string - expectTargetSharedColNames []string - expectDroppedSourceNonGeneratedColNames []string - }{ - { - name: "rename map empty", - sourceCols: columnsA, - targetCols: columnsB, - renameMap: map[string]string{}, - expectSourceSharedColNames: []string{"id", "cint", "cnullable", "cnodefault"}, - expectTargetSharedColNames: []string{"id", "cint", "cnullable", "cnodefault"}, - expectDroppedSourceNonGeneratedColNames: []string{"cchar", "cremoved"}, - }, - { - name: "renamed column", - sourceCols: columnsA, - targetCols: columnsB, - renameMap: map[string]string{"cchar": "cchar_alternate"}, - expectSourceSharedColNames: []string{"id", "cint", "cchar", "cnullable", "cnodefault"}, - expectTargetSharedColNames: []string{"id", "cint", "cchar_alternate", "cnullable", "cnodefault"}, - expectDroppedSourceNonGeneratedColNames: []string{"cremoved"}, - }, - } - - parser := NewAlterTableParser() - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - parser.columnRenameMap = tc.renameMap - sourceSharedCols, targetSharedCols, droppedNonGeneratedCols, _ := GetSharedColumns( - tc.sourceCols, tc.targetCols, - columnsVirtual, columnsVirtual, - parser, - ) - assert.Equal(t, tc.expectSourceSharedColNames, sourceSharedCols.Names()) - assert.Equal(t, tc.expectTargetSharedColNames, targetSharedCols.Names()) - assert.Equal(t, tc.expectDroppedSourceNonGeneratedColNames, droppedNonGeneratedCols.Names()) - }) - } -} - -func TestGetExpandedColumnNames(t *testing.T) { - var ( - columnsA = &ColumnList{ - columns: []Column{ - { - Name: "c1", - IsNullable: true, - }, - { - Name: "c2", - IsNullable: true, - }, - { - Name: "c3", - IsNullable: false, - }, - }, - Ordinals: ColumnsMap{}, - } - columnsB = &ColumnList{ - columns: []Column{ - { - Name: "c1", - IsNullable: true, - }, - { - Name: "c2", - IsNullable: false, - }, - { - Name: "c3", - IsNullable: true, - }, - }, - Ordinals: ColumnsMap{}, - } - ) - tcases := []struct { - name string - sourceCol Column - targetCol Column - expanded bool - }{ - { - "both nullable", - Column{ - IsNullable: true, - }, - Column{ - IsNullable: true, - }, - false, - }, - { - "nullable to non nullable", - Column{ - IsNullable: true, - }, - Column{ - IsNullable: false, - }, - false, - }, - { - "non nullable to nullable", - Column{ - IsNullable: false, - }, - Column{ - IsNullable: true, - }, - true, - }, - { - "signed to unsigned", - Column{ - Type: IntegerColumnType, - NumericPrecision: 4, - IsUnsigned: false, - }, - Column{ - Type: IntegerColumnType, - NumericPrecision: 4, - IsUnsigned: true, - }, - true, - }, - { - "unsigned to signed", - Column{ - Type: IntegerColumnType, - NumericPrecision: 4, - IsUnsigned: true, - }, - Column{ - Type: IntegerColumnType, - NumericPrecision: 4, - IsUnsigned: false, - }, - true, - }, - { - "signed to smaller unsigned", - Column{ - Type: IntegerColumnType, - NumericPrecision: 8, - IsUnsigned: false, - }, - Column{ - Type: IntegerColumnType, - NumericPrecision: 4, - IsUnsigned: true, - }, - false, - }, - { - "same char length", - Column{ - CharacterMaximumLength: 20, - }, - Column{ - CharacterMaximumLength: 20, - }, - false, - }, - { - "reduced char length", - Column{ - CharacterMaximumLength: 20, - }, - Column{ - CharacterMaximumLength: 19, - }, - false, - }, - { - "increased char length", - Column{ - CharacterMaximumLength: 20, - }, - Column{ - CharacterMaximumLength: 21, - }, - true, - }, - { - "expand temporal", - Column{ - DataType: "time", - }, - Column{ - DataType: "timestamp", - }, - true, - }, - { - "expand temporal", - Column{ - DataType: "date", - }, - Column{ - DataType: "timestamp", - }, - true, - }, - { - "expand temporal", - Column{ - DataType: "date", - }, - Column{ - DataType: "datetime", - }, - true, - }, - { - "non expand temporal", - Column{ - DataType: "datetime", - }, - Column{ - DataType: "timestamp", - }, - false, - }, - { - "expand temporal", - Column{ - DataType: "timestamp", - }, - Column{ - DataType: "datetime", - }, - true, - }, - { - "expand enum", - Column{ - Type: EnumColumnType, - EnumValues: "'a','b'", - }, - Column{ - Type: EnumColumnType, - EnumValues: "'a','x'", - }, - true, - }, - { - "expand enum", - Column{ - Type: EnumColumnType, - EnumValues: "'a','b'", - }, - Column{ - Type: EnumColumnType, - EnumValues: "'a','b','c'", - }, - true, - }, - { - "reduce enum", - Column{ - Type: EnumColumnType, - EnumValues: "'a','b','c'", - }, - Column{ - Type: EnumColumnType, - EnumValues: "'a','b'", - }, - false, - }, - } - - expectedExpandedColumnNames := []string{"c3"} - expandedColumnNames, _ := GetExpandedColumnNames(columnsA, columnsB) - assert.Equal(t, expectedExpandedColumnNames, expandedColumnNames) - - for _, tcase := range tcases { - t.Run(tcase.name, func(t *testing.T) { - expanded, _ := isExpandedColumn(&tcase.sourceCol, &tcase.targetCol) - assert.Equal(t, tcase.expanded, expanded) - }) - } -} diff --git a/go/vt/vttablet/onlineddl/vrepl/foreign_key.go b/go/vt/vttablet/onlineddl/vrepl/foreign_key.go deleted file mode 100644 index 006beb7345c..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/foreign_key.go +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "vitess.io/vitess/go/vt/schemadiff" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtenv" -) - -// RemovedForeignKeyNames returns the names of removed foreign keys, ignoring mere name changes -func RemovedForeignKeyNames( - venv *vtenv.Environment, - originalCreateTable *sqlparser.CreateTable, - vreplCreateTable *sqlparser.CreateTable, -) (names []string, err error) { - if originalCreateTable == nil || vreplCreateTable == nil { - return nil, nil - } - env := schemadiff.NewEnv(venv, venv.CollationEnv().DefaultConnectionCharset()) - diffHints := schemadiff.DiffHints{ - ConstraintNamesStrategy: schemadiff.ConstraintNamesIgnoreAll, - } - diff, err := schemadiff.DiffTables(env, originalCreateTable, vreplCreateTable, &diffHints) - if err != nil { - return nil, err - } - - validateWalk := func(node sqlparser.SQLNode) (kontinue bool, err error) { - switch node := node.(type) { - case *sqlparser.DropKey: - if node.Type == sqlparser.ForeignKeyType { - names = append(names, node.Name.String()) - } - } - return true, nil - } - _ = sqlparser.Walk(validateWalk, diff.Statement()) // We never return an error - return names, nil -} diff --git a/go/vt/vttablet/onlineddl/vrepl/foreign_key_test.go b/go/vt/vttablet/onlineddl/vrepl/foreign_key_test.go deleted file mode 100644 index 66775092dcb..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/foreign_key_test.go +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtenv" -) - -func TestRemovedForeignKeyNames(t *testing.T) { - - tcases := []struct { - before string - after string - names []string - }{ - { - before: "create table t (id int primary key)", - after: "create table t (id2 int primary key, i int)", - }, - { - before: "create table t (id int primary key)", - after: "create table t2 (id2 int primary key, i int)", - }, - { - before: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", - after: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", - }, - { - before: "create table t (id int primary key, i int, constraint f1 foreign key (i) references parent (id) on delete cascade)", - after: "create table t (id int primary key, i int, constraint f2 foreign key (i) references parent (id) on delete cascade)", - }, - { - before: "create table t (id int primary key, i int, constraint f foreign key (i) references parent (id) on delete cascade)", - after: "create table t (id int primary key, i int)", - names: []string{"f"}, - }, - { - before: "create table t (id int primary key, i int, i2 int, constraint f1 foreign key (i) references parent (id) on delete cascade, constraint fi2 foreign key (i2) references parent (id) on delete cascade)", - after: "create table t (id int primary key, i int, i2 int, constraint f2 foreign key (i) references parent (id) on delete cascade)", - names: []string{"fi2"}, - }, - { - before: "create table t1 (id int primary key, i int, constraint `check1` CHECK ((`i` < 5)))", - after: "create table t2 (id int primary key, i int)", - }, - } - for _, tcase := range tcases { - t.Run(tcase.before, func(t *testing.T) { - env := vtenv.NewTestEnv() - beforeStmt, err := env.Parser().ParseStrictDDL(tcase.before) - require.NoError(t, err) - beforeCreateTable, ok := beforeStmt.(*sqlparser.CreateTable) - require.True(t, ok) - require.NotNil(t, beforeCreateTable) - - afterStmt, err := env.Parser().ParseStrictDDL(tcase.after) - require.NoError(t, err) - afterCreateTable, ok := afterStmt.(*sqlparser.CreateTable) - require.True(t, ok) - require.NotNil(t, afterCreateTable) - - names, err := RemovedForeignKeyNames(env, beforeCreateTable, afterCreateTable) - assert.NoError(t, err) - assert.Equal(t, tcase.names, names) - }) - } -} diff --git a/go/vt/vttablet/onlineddl/vrepl/parser.go b/go/vt/vttablet/onlineddl/vrepl/parser.go deleted file mode 100644 index f76f8735016..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/parser.go +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "strings" - - "vitess.io/vitess/go/vt/sqlparser" -) - -// AlterTableParser is a parser tool for ALTER TABLE statements -// This is imported from gh-ost. In the future, we should replace that with Vitess parsing. -type AlterTableParser struct { - columnRenameMap map[string]string - droppedColumns map[string]bool - isRenameTable bool - isAutoIncrementDefined bool -} - -// NewAlterTableParser creates a new parser -func NewAlterTableParser() *AlterTableParser { - return &AlterTableParser{ - columnRenameMap: make(map[string]string), - droppedColumns: make(map[string]bool), - } -} - -// NewParserFromAlterStatement creates a new parser with a ALTER TABLE statement -func NewParserFromAlterStatement(alterTable *sqlparser.AlterTable) *AlterTableParser { - parser := NewAlterTableParser() - parser.AnalyzeAlter(alterTable) - return parser -} - -// AnalyzeAlter looks for specific changes in the AlterTable statement, that are relevant -// to OnlineDDL/VReplication -func (p *AlterTableParser) AnalyzeAlter(alterTable *sqlparser.AlterTable) { - for _, opt := range alterTable.AlterOptions { - switch opt := opt.(type) { - case *sqlparser.RenameTableName: - p.isRenameTable = true - case *sqlparser.DropColumn: - p.droppedColumns[opt.Name.Name.String()] = true - case *sqlparser.ChangeColumn: - if opt.OldColumn != nil && opt.NewColDefinition != nil { - oldName := opt.OldColumn.Name.String() - newName := opt.NewColDefinition.Name.String() - p.columnRenameMap[oldName] = newName - } - case sqlparser.TableOptions: - for _, tableOption := range opt { - if strings.ToUpper(tableOption.Name) == "AUTO_INCREMENT" { - p.isAutoIncrementDefined = true - } - } - } - } -} - -// GetNonTrivialRenames gets a list of renamed column -func (p *AlterTableParser) GetNonTrivialRenames() map[string]string { - result := make(map[string]string) - for column, renamed := range p.columnRenameMap { - if column != renamed { - result[column] = renamed - } - } - return result -} - -// HasNonTrivialRenames is true when columns have been renamed -func (p *AlterTableParser) HasNonTrivialRenames() bool { - return len(p.GetNonTrivialRenames()) > 0 -} - -// DroppedColumnsMap returns list of dropped columns -func (p *AlterTableParser) DroppedColumnsMap() map[string]bool { - return p.droppedColumns -} - -// IsRenameTable returns true when the ALTER TABLE statement includes renaming the table -func (p *AlterTableParser) IsRenameTable() bool { - return p.isRenameTable -} - -// IsAutoIncrementDefined returns true when alter options include an explicit AUTO_INCREMENT value -func (p *AlterTableParser) IsAutoIncrementDefined() bool { - return p.isAutoIncrementDefined -} - -// ColumnRenameMap returns the renamed column mapping -func (p *AlterTableParser) ColumnRenameMap() map[string]string { - return p.columnRenameMap -} diff --git a/go/vt/vttablet/onlineddl/vrepl/parser_test.go b/go/vt/vttablet/onlineddl/vrepl/parser_test.go deleted file mode 100644 index 93e2ef25a15..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/parser_test.go +++ /dev/null @@ -1,190 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "vitess.io/vitess/go/vt/sqlparser" -) - -func alterTableStatement(t *testing.T, sql string) *sqlparser.AlterTable { - stmt, err := sqlparser.NewTestParser().ParseStrictDDL(sql) - require.NoError(t, err) - alter, ok := stmt.(*sqlparser.AlterTable) - require.True(t, ok) - return alter -} - -func TestParseAlterStatement(t *testing.T) { - statement := "alter table t add column t int, engine=innodb" - alterStatement := alterTableStatement(t, statement) - parser := NewAlterTableParser() - parser.AnalyzeAlter(alterStatement) - assert.False(t, parser.HasNonTrivialRenames()) - assert.False(t, parser.IsAutoIncrementDefined()) -} - -func TestParseAlterStatementTrivialRename(t *testing.T) { - statement := "alter table t add column t int, change ts ts timestamp, engine=innodb" - alterStatement := alterTableStatement(t, statement) - parser := NewAlterTableParser() - parser.AnalyzeAlter(alterStatement) - assert.False(t, parser.HasNonTrivialRenames()) - assert.False(t, parser.IsAutoIncrementDefined()) - assert.Equal(t, len(parser.columnRenameMap), 1) - assert.Equal(t, parser.columnRenameMap["ts"], "ts") -} - -func TestParseAlterStatementWithAutoIncrement(t *testing.T) { - - statements := []string{ - "auto_increment=7", - "auto_increment = 7", - "AUTO_INCREMENT = 71", - "AUTO_INCREMENT 23", - "AUTO_INCREMENT 23", - "add column t int, change ts ts timestamp, auto_increment=7 engine=innodb", - "add column t int, change ts ts timestamp, auto_increment =7 engine=innodb", - "add column t int, change ts ts timestamp, AUTO_INCREMENT = 7 engine=innodb", - "add column t int, change ts ts timestamp, engine=innodb auto_increment=73425", - "add column t int, change ts ts timestamp, engine=innodb, auto_increment=73425", - "add column t int, change ts ts timestamp, engine=innodb, auto_increment 73425", - "add column t int, change ts ts timestamp, engine innodb, auto_increment 73425", - "add column t int, change ts ts timestamp, engine innodb auto_increment 73425", - } - for _, statement := range statements { - parser := NewAlterTableParser() - statement := "alter table t " + statement - alterStatement := alterTableStatement(t, statement) - parser.AnalyzeAlter(alterStatement) - assert.True(t, parser.IsAutoIncrementDefined()) - } -} - -func TestParseAlterStatementTrivialRenames(t *testing.T) { - statement := "alter table t add column t int, change ts ts timestamp, CHANGE f `f` float, engine=innodb" - alterStatement := alterTableStatement(t, statement) - parser := NewAlterTableParser() - parser.AnalyzeAlter(alterStatement) - assert.False(t, parser.HasNonTrivialRenames()) - assert.False(t, parser.IsAutoIncrementDefined()) - assert.Equal(t, len(parser.columnRenameMap), 2) - assert.Equal(t, parser.columnRenameMap["ts"], "ts") - assert.Equal(t, parser.columnRenameMap["f"], "f") -} - -func TestParseAlterStatementNonTrivial(t *testing.T) { - statements := []string{ - `add column b bigint, change f fl float, change i count int, engine=innodb`, - "add column b bigint, change column `f` fl float, change `i` `count` int, engine=innodb", - "add column b bigint, change column `f` fl float, change `i` `count` int, change ts ts timestamp, engine=innodb", - `change - f fl float, - CHANGE COLUMN i - count int, engine=innodb`, - } - - for _, statement := range statements { - statement := "alter table t " + statement - alterStatement := alterTableStatement(t, statement) - parser := NewAlterTableParser() - parser.AnalyzeAlter(alterStatement) - assert.False(t, parser.IsAutoIncrementDefined()) - renames := parser.GetNonTrivialRenames() - assert.Equal(t, len(renames), 2) - assert.Equal(t, renames["i"], "count") - assert.Equal(t, renames["f"], "fl") - } -} - -func TestParseAlterStatementDroppedColumns(t *testing.T) { - - { - parser := NewAlterTableParser() - statement := "alter table t drop column b" - alterStatement := alterTableStatement(t, statement) - parser.AnalyzeAlter(alterStatement) - assert.Equal(t, len(parser.droppedColumns), 1) - assert.True(t, parser.droppedColumns["b"]) - } - { - parser := NewAlterTableParser() - statement := "alter table t drop column b, drop key c_idx, drop column `d`" - alterStatement := alterTableStatement(t, statement) - parser.AnalyzeAlter(alterStatement) - assert.Equal(t, len(parser.droppedColumns), 2) - assert.True(t, parser.droppedColumns["b"]) - assert.True(t, parser.droppedColumns["d"]) - } - { - parser := NewAlterTableParser() - statement := "alter table t drop column b, drop key c_idx, drop column `d`, drop `e`, drop primary key, drop foreign key fk_1" - alterStatement := alterTableStatement(t, statement) - parser.AnalyzeAlter(alterStatement) - assert.Equal(t, len(parser.droppedColumns), 3) - assert.True(t, parser.droppedColumns["b"]) - assert.True(t, parser.droppedColumns["d"]) - assert.True(t, parser.droppedColumns["e"]) - } -} - -func TestParseAlterStatementRenameTable(t *testing.T) { - tt := []struct { - alter string - isRename bool - }{ - { - alter: "alter table t drop column b", - }, - { - alter: "alter table t rename as something_else", - isRename: true, - }, - { - alter: "alter table t rename to something_else", - isRename: true, - }, - { - alter: "alter table t drop column b, rename as something_else", - isRename: true, - }, - { - alter: "alter table t engine=innodb, rename as something_else", - isRename: true, - }, - { - alter: "alter table t rename as something_else, engine=innodb", - isRename: true, - }, - } - for _, tc := range tt { - t.Run(tc.alter, func(t *testing.T) { - parser := NewAlterTableParser() - alterStatement := alterTableStatement(t, tc.alter) - parser.AnalyzeAlter(alterStatement) - assert.Equal(t, tc.isRename, parser.isRenameTable) - }) - } -} diff --git a/go/vt/vttablet/onlineddl/vrepl/types.go b/go/vt/vttablet/onlineddl/vrepl/types.go deleted file mode 100644 index 0ca834ffdf0..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/types.go +++ /dev/null @@ -1,293 +0,0 @@ -/* - Original copyright by GitHub as follows. Additions by the Vitess authors as follows. -*/ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "fmt" - "reflect" - "strings" - - "vitess.io/vitess/go/vt/schemadiff" -) - -// ColumnType indicated some MySQL data types -type ColumnType int - -const ( - UnknownColumnType ColumnType = iota - TimestampColumnType - DateTimeColumnType - EnumColumnType - SetColumnType - MediumIntColumnType - JSONColumnType - FloatColumnType - DoubleColumnType - BinaryColumnType - StringColumnType - IntegerColumnType -) - -// Column represents a table column -type Column struct { - Name string - IsUnsigned bool - Charset string - Collation string - Type ColumnType - EnumValues string - EnumToTextConversion bool - DataType string // from COLUMN_TYPE column - - IsNullable bool - IsDefaultNull bool - - CharacterMaximumLength int64 - NumericPrecision int64 - NumericScale int64 - DateTimePrecision int64 - - // add Octet length for binary type, fix bytes with suffix "00" get clipped in mysql binlog. - // https://github.com/github/gh-ost/issues/909 - BinaryOctetLength uint64 -} - -// SetTypeIfUnknown will set a new column type only if the current type is unknown, otherwise silently skip -func (c *Column) SetTypeIfUnknown(t ColumnType) { - if c.Type == UnknownColumnType { - c.Type = t - } -} - -// HasDefault returns true if the column at all has a default value (possibly NULL) -func (c *Column) HasDefault() bool { - if c.IsDefaultNull && !c.IsNullable { - // based on INFORMATION_SCHEMA.COLUMNS, this is the indicator for a 'NOT NULL' column with no default value. - return false - } - return true -} - -// IsNumeric returns true if the column is of a numeric type -func (c *Column) IsNumeric() bool { - return c.NumericPrecision > 0 -} - -// IsIntegralType returns true if the column is some form of an integer -func (c *Column) IsIntegralType() bool { - return schemadiff.IsIntegralType(c.DataType) -} - -// IsFloatingPoint returns true if the column is of a floating point numeric type -func (c *Column) IsFloatingPoint() bool { - return c.Type == FloatColumnType || c.Type == DoubleColumnType -} - -// IsFloatingPoint returns true if the column is of a temporal type -func (c *Column) IsTemporal() bool { - return c.DateTimePrecision >= 0 -} - -// NewColumns creates a new column array from non empty names -func NewColumns(names []string) []Column { - result := []Column{} - for _, name := range names { - if name == "" { - continue - } - result = append(result, Column{Name: name}) - } - return result -} - -// ParseColumns creates a new column array fby parsing comma delimited names list -func ParseColumns(names string) []Column { - namesArray := strings.Split(names, ",") - return NewColumns(namesArray) -} - -// ColumnsMap maps a column name onto its ordinal position -type ColumnsMap map[string]int - -// NewEmptyColumnsMap creates an empty map -func NewEmptyColumnsMap() ColumnsMap { - columnsMap := make(map[string]int) - return ColumnsMap(columnsMap) -} - -// NewColumnsMap creates a column map based on ordered list of columns -func NewColumnsMap(orderedColumns []Column) ColumnsMap { - columnsMap := NewEmptyColumnsMap() - for i, column := range orderedColumns { - columnsMap[column.Name] = i - } - return columnsMap -} - -// ColumnList makes for a named list of columns -type ColumnList struct { - columns []Column - Ordinals ColumnsMap -} - -// NewColumnList creates an object given ordered list of column names -func NewColumnList(names []string) *ColumnList { - result := &ColumnList{ - columns: NewColumns(names), - } - result.Ordinals = NewColumnsMap(result.columns) - return result -} - -// ParseColumnList parses a comma delimited list of column names -func ParseColumnList(names string) *ColumnList { - result := &ColumnList{ - columns: ParseColumns(names), - } - result.Ordinals = NewColumnsMap(result.columns) - return result -} - -// Columns returns the list of columns -func (l *ColumnList) Columns() []Column { - return l.columns -} - -// Names returns list of column names -func (l *ColumnList) Names() []string { - names := make([]string, len(l.columns)) - for i := range l.columns { - names[i] = l.columns[i].Name - } - return names -} - -// GetColumn gets a column by name -func (l *ColumnList) GetColumn(columnName string) *Column { - if ordinal, ok := l.Ordinals[columnName]; ok { - return &l.columns[ordinal] - } - return nil -} - -// ColumnExists returns true if this column list has a column by a given name -func (l *ColumnList) ColumnExists(columnName string) bool { - _, ok := l.Ordinals[columnName] - return ok -} - -// String returns a comma separated list of column names -func (l *ColumnList) String() string { - return strings.Join(l.Names(), ",") -} - -// Equals checks for complete (deep) identities of columns, in order. -func (l *ColumnList) Equals(other *ColumnList) bool { - return reflect.DeepEqual(l.Columns, other.Columns) -} - -// EqualsByNames checks if the names in this list equals the names of another list, in order. Type is ignored. -func (l *ColumnList) EqualsByNames(other *ColumnList) bool { - return reflect.DeepEqual(l.Names(), other.Names()) -} - -// IsSubsetOf returns 'true' when column names of this list are a subset of -// another list, in arbitrary order (order agnostic) -func (l *ColumnList) IsSubsetOf(other *ColumnList) bool { - for _, column := range l.columns { - if _, exists := other.Ordinals[column.Name]; !exists { - return false - } - } - return true -} - -// Difference returns a (new copy) subset of this column list, consisting of all -// column NOT in given list. -// The result is never nil, even if the difference is empty -func (l *ColumnList) Difference(other *ColumnList) (diff *ColumnList) { - names := []string{} - for _, column := range l.columns { - if !other.ColumnExists(column.Name) { - names = append(names, column.Name) - } - } - return NewColumnList(names) -} - -// Len returns the length of this list -func (l *ColumnList) Len() int { - return len(l.columns) -} - -// MappedNamesColumnList returns a column list based on this list, with names possibly mapped by given map -func (l *ColumnList) MappedNamesColumnList(columnNamesMap map[string]string) *ColumnList { - names := l.Names() - for i := range names { - if mappedName, ok := columnNamesMap[names[i]]; ok { - names[i] = mappedName - } - } - return NewColumnList(names) -} - -// SetEnumToTextConversion tells this column list that an enum is converted to text -func (l *ColumnList) SetEnumToTextConversion(columnName string, enumValues string) { - l.GetColumn(columnName).EnumToTextConversion = true - l.GetColumn(columnName).EnumValues = enumValues -} - -// IsEnumToTextConversion tells whether an enum was converted to text -func (l *ColumnList) IsEnumToTextConversion(columnName string) bool { - return l.GetColumn(columnName).EnumToTextConversion -} - -// UniqueKey is the combination of a key's name and columns -type UniqueKey struct { - Name string - Columns ColumnList - HasNullable bool - HasSubpart bool - HasFloat bool - IsAutoIncrement bool -} - -// IsPrimary checks if this unique key is primary -func (k *UniqueKey) IsPrimary() bool { - return k.Name == "PRIMARY" -} - -// Len returns the length of this list -func (k *UniqueKey) Len() int { - return k.Columns.Len() -} - -// String returns a visual representation of this key -func (k *UniqueKey) String() string { - description := k.Name - if k.IsAutoIncrement { - description = fmt.Sprintf("%s (auto_increment)", description) - } - return fmt.Sprintf("%s: %s; has nullable: %+v", description, k.Columns.Names(), k.HasNullable) -} diff --git a/go/vt/vttablet/onlineddl/vrepl/types_test.go b/go/vt/vttablet/onlineddl/vrepl/types_test.go deleted file mode 100644 index d146d286d3a..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/types_test.go +++ /dev/null @@ -1,214 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestParseColumnList(t *testing.T) { - names := "id,category,max_len" - - columnList := ParseColumnList(names) - assert.Equal(t, columnList.Len(), 3) - assert.Equal(t, columnList.Names(), []string{"id", "category", "max_len"}) - assert.Equal(t, columnList.Ordinals["id"], 0) - assert.Equal(t, columnList.Ordinals["category"], 1) - assert.Equal(t, columnList.Ordinals["max_len"], 2) -} - -func TestGetColumn(t *testing.T) { - names := "id,category,max_len" - columnList := ParseColumnList(names) - { - column := columnList.GetColumn("category") - assert.NotNil(t, column) - assert.Equal(t, column.Name, "category") - } - { - column := columnList.GetColumn("no_such_column") - assert.True(t, column == nil) - } -} - -func TestIsSubsetOf(t *testing.T) { - tt := []struct { - columns1 *ColumnList - columns2 *ColumnList - expectSubset bool - }{ - { - columns1: ParseColumnList(""), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList("a,c"), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList("b,c"), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList("b"), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList(""), - columns2: ParseColumnList("a,b,c"), - expectSubset: true, - }, - { - columns1: ParseColumnList("a,d"), - columns2: ParseColumnList("a,b,c"), - expectSubset: false, - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList("a,b"), - expectSubset: false, - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList(""), - expectSubset: false, - }, - } - for _, tc := range tt { - name := fmt.Sprintf("%v:%v", tc.columns1.Names(), tc.columns2.Names()) - t.Run(name, func(t *testing.T) { - isSubset := tc.columns1.IsSubsetOf(tc.columns2) - assert.Equal(t, tc.expectSubset, isSubset) - }, - ) - } -} - -func TestDifference(t *testing.T) { - tt := []struct { - columns1 *ColumnList - columns2 *ColumnList - expect *ColumnList - }{ - { - columns1: ParseColumnList(""), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList("a,c"), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList("b,c"), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList("b"), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList(""), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList(""), - }, - { - columns1: ParseColumnList("a,d"), - columns2: ParseColumnList("a,b,c"), - expect: ParseColumnList("d"), - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList("a,b"), - expect: ParseColumnList("c"), - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList(""), - expect: ParseColumnList("a,b,c"), - }, - { - columns1: ParseColumnList("a,b,c"), - columns2: ParseColumnList("b,d,e"), - expect: ParseColumnList("a,c"), - }, - } - for _, tc := range tt { - name := fmt.Sprintf("%v:%v", tc.columns1.Names(), tc.columns2.Names()) - t.Run(name, func(t *testing.T) { - diff := tc.columns1.Difference(tc.columns2) - assert.Equal(t, tc.expect, diff) - }, - ) - } -} - -func TestMappedNamesColumnList(t *testing.T) { - tt := []struct { - columns *ColumnList - namesMap map[string]string - expected *ColumnList - }{ - { - columns: ParseColumnList("a,b,c"), - namesMap: map[string]string{}, - expected: ParseColumnList("a,b,c"), - }, - { - columns: ParseColumnList("a,b,c"), - namesMap: map[string]string{"x": "y"}, - expected: ParseColumnList("a,b,c"), - }, - { - columns: ParseColumnList("a,b,c"), - namesMap: map[string]string{"a": "x", "c": "y"}, - expected: ParseColumnList("x,b,y"), - }, - } - for _, tc := range tt { - name := fmt.Sprintf("%v:%v", tc.columns.Names(), tc.namesMap) - t.Run(name, func(t *testing.T) { - mappedNames := tc.columns.MappedNamesColumnList(tc.namesMap) - assert.Equal(t, tc.expected, mappedNames) - }, - ) - } -} diff --git a/go/vt/vttablet/onlineddl/vrepl/unique_key.go b/go/vt/vttablet/onlineddl/vrepl/unique_key.go deleted file mode 100644 index cc649b4ea37..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/unique_key.go +++ /dev/null @@ -1,184 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "strings" -) - -// UniqueKeyValidForIteration returns 'false' if we should not use this unique key as the main -// iteration key in vreplication. -func UniqueKeyValidForIteration(uniqueKey *UniqueKey) bool { - if uniqueKey.HasNullable { - // NULLable columns in a unique key means the set of values is not really unique (two identical rows with NULLs are allowed). - // Thus, we cannot use this unique key for iteration. - return false - } - if uniqueKey.HasSubpart { - // vreplication does not fully support indexes on column prefixes such as: - // UNIQUE KEY `name_idx` (`name`(15)) - // "HasSubpart" means some column covered by the index has a key length spec. - return false - } - if uniqueKey.HasFloat { - // float & double data types are imprecise and we cannot use them while iterating unique keys - return false - } - return true // good to go! -} - -// GetSharedUniqueKeys returns the unique keys shared between the source & target tables -func GetSharedUniqueKeys(sourceUniqueKeys, targetUniqueKeys [](*UniqueKey), columnRenameMap map[string]string) (chosenSourceUniqueKey, chosenTargetUniqueKey *UniqueKey) { - type ukPair struct{ source, target *UniqueKey } - var sharedUKPairs []*ukPair - - for _, sourceUniqueKey := range sourceUniqueKeys { - if !UniqueKeyValidForIteration(sourceUniqueKey) { - continue - } - for _, targetUniqueKey := range targetUniqueKeys { - if !UniqueKeyValidForIteration(targetUniqueKey) { - continue - } - uniqueKeyMatches := func() bool { - // Compare two unique keys - if sourceUniqueKey.Columns.Len() != targetUniqueKey.Columns.Len() { - return false - } - // Expect same columns, same order, potentially column name mapping - sourceUniqueKeyNames := sourceUniqueKey.Columns.Names() - targetUniqueKeyNames := targetUniqueKey.Columns.Names() - for i := range sourceUniqueKeyNames { - sourceColumnName := sourceUniqueKeyNames[i] - targetColumnName := targetUniqueKeyNames[i] - mappedSourceColumnName := sourceColumnName - if mapped, ok := columnRenameMap[sourceColumnName]; ok { - mappedSourceColumnName = mapped - } - if !strings.EqualFold(mappedSourceColumnName, targetColumnName) { - return false - } - } - return true - } - if uniqueKeyMatches() { - sharedUKPairs = append(sharedUKPairs, &ukPair{source: sourceUniqueKey, target: targetUniqueKey}) - } - } - } - // Now that we know what the shared unique keys are, let's find the "best" shared one. - // Source and target unique keys can have different name, even though they cover the exact same - // columns and in same order. - for _, pair := range sharedUKPairs { - if pair.source.HasNullable { - continue - } - if pair.target.HasNullable { - continue - } - return pair.source, pair.target - } - return nil, nil -} - -// SourceUniqueKeyAsOrMoreConstrainedThanTarget returns 'true' when sourceUniqueKey is at least as constrained as targetUniqueKey. -// "More constrained" means the uniqueness constraint is "stronger". Thus, if sourceUniqueKey is as-or-more constrained than targetUniqueKey, then -// rows valid under sourceUniqueKey must also be valid in targetUniqueKey. The opposite is not necessarily so: rows that are valid in targetUniqueKey -// may cause a unique key violation under sourceUniqueKey -func SourceUniqueKeyAsOrMoreConstrainedThanTarget(sourceUniqueKey, targetUniqueKey *UniqueKey, columnRenameMap map[string]string) bool { - // Compare two unique keys - if sourceUniqueKey.Columns.Len() > targetUniqueKey.Columns.Len() { - // source can't be more constrained if it covers *more* columns - return false - } - // we know that len(sourceUniqueKeyNames) <= len(targetUniqueKeyNames) - sourceUniqueKeyNames := sourceUniqueKey.Columns.Names() - targetUniqueKeyNames := targetUniqueKey.Columns.Names() - // source is more constrained than target if every column in source is also in target, order is immaterial - for i := range sourceUniqueKeyNames { - sourceColumnName := sourceUniqueKeyNames[i] - mappedSourceColumnName := sourceColumnName - if mapped, ok := columnRenameMap[sourceColumnName]; ok { - mappedSourceColumnName = mapped - } - columnFoundInTarget := func() bool { - for _, targetColumnName := range targetUniqueKeyNames { - if strings.EqualFold(mappedSourceColumnName, targetColumnName) { - return true - } - } - return false - } - if !columnFoundInTarget() { - return false - } - } - return true -} - -// AddedUniqueKeys returns the unique key constraints added in target. This does not necessarily mean that the unique key itself is new, -// rather that there's a new, stricter constraint on a set of columns, that didn't exist before. Example: -// -// before: unique key `my_key`(c1, c2, c3); after: unique key `my_key`(c1, c2) -// The constraint on (c1, c2) is new; and `my_key` in target table ("after") is considered a new key -// -// Order of columns is immaterial to uniqueness of column combination. -func AddedUniqueKeys(sourceUniqueKeys, targetUniqueKeys [](*UniqueKey), columnRenameMap map[string]string) (addedUKs [](*UniqueKey)) { - addedUKs = [](*UniqueKey){} - for _, targetUniqueKey := range targetUniqueKeys { - foundAsOrMoreConstrainingSourceKey := func() bool { - for _, sourceUniqueKey := range sourceUniqueKeys { - if SourceUniqueKeyAsOrMoreConstrainedThanTarget(sourceUniqueKey, targetUniqueKey, columnRenameMap) { - // target key does not add a new constraint - return true - } - } - return false - } - if !foundAsOrMoreConstrainingSourceKey() { - addedUKs = append(addedUKs, targetUniqueKey) - } - } - return addedUKs -} - -// RemovedUniqueKeys returns the list of unique key constraints _removed_ going from source to target. -func RemovedUniqueKeys(sourceUniqueKeys, targetUniqueKeys [](*UniqueKey), columnRenameMap map[string]string) (removedUKs [](*UniqueKey)) { - reverseColumnRenameMap := map[string]string{} - for k, v := range columnRenameMap { - reverseColumnRenameMap[v] = k - } - return AddedUniqueKeys(targetUniqueKeys, sourceUniqueKeys, reverseColumnRenameMap) -} - -// GetUniqueKeyCoveredByColumns returns the first unique key from given list, whose columns all appear -// in given column list. -func GetUniqueKeyCoveredByColumns(uniqueKeys [](*UniqueKey), columns *ColumnList) (chosenUniqueKey *UniqueKey) { - for _, uniqueKey := range uniqueKeys { - if !UniqueKeyValidForIteration(uniqueKey) { - continue - } - if uniqueKey.Columns.IsSubsetOf(columns) { - return uniqueKey - } - } - return nil -} diff --git a/go/vt/vttablet/onlineddl/vrepl/unique_key_test.go b/go/vt/vttablet/onlineddl/vrepl/unique_key_test.go deleted file mode 100644 index 3364c55a308..00000000000 --- a/go/vt/vttablet/onlineddl/vrepl/unique_key_test.go +++ /dev/null @@ -1,666 +0,0 @@ -/* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE -*/ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vrepl - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - columns1 = ParseColumnList("c1") - columns12 = ParseColumnList("c1,c2") - columns123 = ParseColumnList("c1,c2,c3") - columns2 = ParseColumnList("c2") - columns21 = ParseColumnList("c2,c1") - columns12A = ParseColumnList("c1,c2,ca") -) - -func TestGetSharedUniqueKeys(t *testing.T) { - tt := []struct { - name string - sourceUKs, targetUKs [](*UniqueKey) - renameMap map[string]string - expectSourceUK, expectTargetUK *UniqueKey - }{ - { - name: "empty", - sourceUKs: []*UniqueKey{}, - targetUKs: []*UniqueKey{}, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "half empty", - sourceUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{}, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "single identical", - sourceUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "PRIMARY", Columns: *columns1}, - expectTargetUK: &UniqueKey{Name: "PRIMARY", Columns: *columns1}, - }, - { - name: "single identical non pk", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx", Columns: *columns1}, - expectTargetUK: &UniqueKey{Name: "uidx", Columns: *columns1}, - }, - { - name: "single identical, source is nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1, HasNullable: true}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "single identical, target is nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1, HasNullable: true}, - }, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "single no shared", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "single no shared different order", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns21}, - }, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "single identical, source has FLOAT", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1, HasFloat: true}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "exact match", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - expectTargetUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - }, - { - name: "exact match from multiple options", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - expectTargetUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - }, - { - name: "exact match from multiple options reorder", - sourceUKs: []*UniqueKey{ - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx12", Columns: *columns12}, - expectTargetUK: &UniqueKey{Name: "uidx12", Columns: *columns12}, - }, - { - name: "match different names", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidxother", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx12", Columns: *columns12}, - expectTargetUK: &UniqueKey{Name: "uidxother", Columns: *columns12}, - }, - { - name: "match different names, nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123other", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12, HasNullable: true}, - }, - renameMap: map[string]string{}, - expectSourceUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - expectTargetUK: &UniqueKey{Name: "uidx123other", Columns: *columns123}, - }, - { - name: "match different column names", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "ca"}, - expectSourceUK: &UniqueKey{Name: "uidx123", Columns: *columns123}, - expectTargetUK: &UniqueKey{Name: "uidx12A", Columns: *columns12A}, - }, - { - // enforce mapping from c3 to ca; will not match c3<->c3 - name: "no match identical column names", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{"c3": "ca"}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - { - name: "no match different column names", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "cx"}, - expectSourceUK: nil, - expectTargetUK: nil, - }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - sourceUK, targetUK := GetSharedUniqueKeys(tc.sourceUKs, tc.targetUKs, tc.renameMap) - assert.Equal(t, tc.expectSourceUK, sourceUK) - assert.Equal(t, tc.expectTargetUK, targetUK) - }) - } -} - -func TestAddedUniqueKeys(t *testing.T) { - emptyUniqueKeys := []*UniqueKey{} - tt := []struct { - name string - sourceUKs, targetUKs [](*UniqueKey) - renameMap map[string]string - expectAddedUKs [](*UniqueKey) - expectRemovedUKs [](*UniqueKey) - }{ - { - name: "empty", - sourceUKs: emptyUniqueKeys, - targetUKs: emptyUniqueKeys, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "UK removed", - sourceUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - targetUKs: emptyUniqueKeys, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - }, - { - name: "NULLable UK removed", - sourceUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1, HasNullable: true}, - }, - targetUKs: emptyUniqueKeys, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1, HasNullable: true}, - }, - }, - { - name: "UK added", - sourceUKs: emptyUniqueKeys, - targetUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "single identical", - sourceUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "PRIMARY", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "single identical non pk", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "single identical, source is nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1, HasNullable: true}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "single identical, target is nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1, HasNullable: true}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "expand columns: not considered added", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - }, - { - name: "expand columns, different order: not considered added", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns21}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - }, - { - name: "reduced columns: considered added", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "reduced columns, multiple: considered added", - sourceUKs: []*UniqueKey{ - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidx2", Columns: *columns2}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - renameMap: map[string]string{}, - expectAddedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx2", Columns: *columns2}, - }, - }, - { - name: "different order: not considered added", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns21}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "no match, different columns", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx2", Columns: *columns2}, - }, - renameMap: map[string]string{}, - expectAddedUKs: []*UniqueKey{ - {Name: "uidx2", Columns: *columns2}, - }, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - name: "one match, one expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - }, - { - name: "exact match from multiple options", - sourceUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - }, - { - name: "exact match from multiple options reorder", - sourceUKs: []*UniqueKey{ - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx", Columns: *columns1}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx", Columns: *columns1}, - }, - }, - { - name: "match different names", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - {Name: "uidxother", Columns: *columns12}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - name: "match different names, nullable", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123other", Columns: *columns123}, - {Name: "uidx12", Columns: *columns12, HasNullable: true}, - }, - renameMap: map[string]string{}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - name: "match different column names, expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "ca"}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - name: "match different column names, no expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "ca"}, - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: emptyUniqueKeys, - }, - { - // enforce mapping from c3 to ca; will not match c3<->c3 - name: "no match identical column names, expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{"c3": "ca"}, - // 123 expands 12, so even though 3 is mapped to A, 123 is still not more constrained. - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - // enforce mapping from c3 to ca; will not match c3<->c3 - name: "no match identical column names, no expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - renameMap: map[string]string{"c3": "ca"}, - expectAddedUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - expectRemovedUKs: emptyUniqueKeys, - }, - { - name: "no match for different column names, expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - {Name: "uidx12", Columns: *columns12}, - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx21", Columns: *columns21}, - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "cx"}, - // 123 expands 12, so even though 3 is mapped to x, 123 is still not more constrained. - expectAddedUKs: emptyUniqueKeys, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx1", Columns: *columns1}, - }, - }, - { - name: "no match for different column names, no expand", - sourceUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - targetUKs: []*UniqueKey{ - {Name: "uidx12A", Columns: *columns12A}, - }, - renameMap: map[string]string{"c3": "cx"}, - expectAddedUKs: []*UniqueKey{ - {Name: "uidx12A", Columns: *columns12A}, - }, - expectRemovedUKs: []*UniqueKey{ - {Name: "uidx123", Columns: *columns123}, - }, - }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - addedUKs := AddedUniqueKeys(tc.sourceUKs, tc.targetUKs, tc.renameMap) - assert.Equal(t, tc.expectAddedUKs, addedUKs) - removedUKs := RemovedUniqueKeys(tc.sourceUKs, tc.targetUKs, tc.renameMap) - assert.Equal(t, tc.expectRemovedUKs, removedUKs) - }) - } -} diff --git a/go/vt/vttablet/onlineddl/vrepl_test.go b/go/vt/vttablet/onlineddl/vrepl_test.go index ddb723ed7b7..b9875c3f6d2 100644 --- a/go/vt/vttablet/onlineddl/vrepl_test.go +++ b/go/vt/vttablet/onlineddl/vrepl_test.go @@ -1,6 +1,238 @@ /* - Copyright 2016 GitHub Inc. - See https://github.com/github/gh-ost/blob/master/LICENSE +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 onlineddl + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/schemadiff" + "vitess.io/vitess/go/vt/vtenv" +) + +func TestRevertible(t *testing.T) { + + type revertibleTestCase struct { + name string + fromSchema string + toSchema string + // expectProblems bool + removedForeignKeyNames string + removedUniqueKeyNames string + droppedNoDefaultColumnNames string + expandedColumnNames string + } + + var testCases = []revertibleTestCase{ + { + name: "identical schemas", + fromSchema: `id int primary key, i1 int not null default 0`, + toSchema: `id int primary key, i2 int not null default 0`, + }, + { + name: "different schemas, nothing to note", + fromSchema: `id int primary key, i1 int not null default 0, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i1 int not null default 0, i2 int not null default 0, unique key i1_uidx(i1)`, + }, + { + name: "removed non-nullable unique key", + fromSchema: `id int primary key, i1 int not null default 0, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i2 int not null default 0`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "removed nullable unique key", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i2 int default null`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "expanding unique key removes unique constraint", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + toSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1, id)`, + removedUniqueKeyNames: `i1_uidx`, + }, + { + name: "expanding unique key prefix removes unique constraint", + fromSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(20))`, + toSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(21))`, + removedUniqueKeyNames: `v_uidx`, + }, + { + name: "reducing unique key does not remove unique constraint", + fromSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1, id)`, + toSchema: `id int primary key, i1 int default null, unique key i1_uidx(i1)`, + removedUniqueKeyNames: ``, + }, + { + name: "reducing unique key does not remove unique constraint", + fromSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(21))`, + toSchema: `id int primary key, v varchar(100) default null, unique key v_uidx(v(20))`, + }, + { + name: "removed foreign key", + fromSchema: "id int primary key, i int, constraint some_fk_1 foreign key (i) references parent (id) on delete cascade", + toSchema: "id int primary key, i int", + removedForeignKeyNames: "some_fk_1", + }, + + { + name: "renamed foreign key", + fromSchema: "id int primary key, i int, constraint f1 foreign key (i) references parent (id) on delete cascade", + toSchema: "id int primary key, i int, constraint f2 foreign key (i) references parent (id) on delete cascade", + }, + { + name: "remove column without default", + fromSchema: `id int primary key, i1 int not null, i2 int not null default 0, i3 int default null`, + toSchema: `id int primary key, i4 int not null default 0`, + droppedNoDefaultColumnNames: `i1`, + }, + { + name: "expanded: nullable", + fromSchema: `id int primary key, i1 int not null, i2 int default null`, + toSchema: `id int primary key, i1 int default null, i2 int not null`, + expandedColumnNames: `i1`, + }, + { + name: "expanded: longer text", + fromSchema: `id int primary key, i1 int default null, v1 varchar(40) not null, v2 varchar(5), v3 varchar(3)`, + toSchema: `id int primary key, i1 int not null, v1 varchar(100) not null, v2 char(3), v3 char(5)`, + expandedColumnNames: `v1,v3`, + }, + { + name: "expanded: int numeric precision and scale", + fromSchema: `id int primary key, i1 int, i2 tinyint, i3 mediumint, i4 bigint`, + toSchema: `id int primary key, i1 int, i2 mediumint, i3 int, i4 tinyint`, + expandedColumnNames: `i2,i3`, + }, + { + name: "expanded: floating point", + fromSchema: `id int primary key, i1 int, n2 bigint, n3 bigint, n4 float, n5 double`, + toSchema: `id int primary key, i1 int, n2 float, n3 double, n4 double, n5 float`, + expandedColumnNames: `n2,n3,n4`, + }, + { + name: "expanded: decimal numeric precision and scale", + fromSchema: `id int primary key, i1 int, d1 decimal(10,2), d2 decimal (10,2), d3 decimal (10,2)`, + toSchema: `id int primary key, i1 int, d1 decimal(11,2), d2 decimal (9,1), d3 decimal (10,3)`, + expandedColumnNames: `d1,d3`, + }, + { + name: "expanded: signed, unsigned", + fromSchema: `id int primary key, i1 bigint signed, i2 int unsigned, i3 bigint unsigned`, + toSchema: `id int primary key, i1 int signed, i2 int signed, i3 int signed`, + expandedColumnNames: `i2,i3`, + }, + { + name: "expanded: signed, unsigned: range", + fromSchema: `id int primary key, i1 int signed, i2 bigint signed, i3 int signed`, + toSchema: `id int primary key, i1 int unsigned, i2 int unsigned, i3 bigint unsigned`, + expandedColumnNames: `i1,i3`, + }, + { + name: "expanded: datetime precision", + fromSchema: `id int primary key, dt1 datetime, ts1 timestamp, ti1 time, dt2 datetime(3), dt3 datetime(6), ts2 timestamp(3)`, + toSchema: `id int primary key, dt1 datetime(3), ts1 timestamp(6), ti1 time(3), dt2 datetime(6), dt3 datetime(3), ts2 timestamp`, + expandedColumnNames: `dt1,ts1,ti1,dt2`, + }, + { + name: "expanded: strange data type changes", + fromSchema: `id int primary key, dt1 datetime, ts1 timestamp, i1 int, d1 date, e1 enum('a', 'b')`, + toSchema: `id int primary key, dt1 char(32), ts1 varchar(32), i1 tinytext, d1 char(2), e1 varchar(2)`, + expandedColumnNames: `dt1,ts1,i1,d1,e1`, + }, + { + name: "expanded: temporal types", + fromSchema: `id int primary key, t1 time, t2 timestamp, t3 date, t4 datetime, t5 time, t6 date`, + toSchema: `id int primary key, t1 datetime, t2 datetime, t3 timestamp, t4 timestamp, t5 timestamp, t6 datetime`, + expandedColumnNames: `t1,t2,t3,t5,t6`, + }, + { + name: "expanded: character sets", + fromSchema: `id int primary key, c1 char(3) charset utf8, c2 char(3) charset utf8mb4, c3 char(3) charset ascii, c4 char(3) charset utf8mb4, c5 char(3) charset utf8, c6 char(3) charset latin1`, + toSchema: `id int primary key, c1 char(3) charset utf8mb4, c2 char(3) charset utf8, c3 char(3) charset utf8, c4 char(3) charset ascii, c5 char(3) charset utf8, c6 char(3) charset utf8mb4`, + expandedColumnNames: `c1,c3,c6`, + }, + { + name: "expanded: enum", + fromSchema: `id int primary key, e1 enum('a', 'b'), e2 enum('a', 'b'), e3 enum('a', 'b'), e4 enum('a', 'b'), e5 enum('a', 'b'), e6 enum('a', 'b'), e7 enum('a', 'b'), e8 enum('a', 'b')`, + toSchema: `id int primary key, e1 enum('a', 'b'), e2 enum('a'), e3 enum('a', 'b', 'c'), e4 enum('a', 'x'), e5 enum('a', 'x', 'b'), e6 enum('b'), e7 varchar(1), e8 tinyint`, + expandedColumnNames: `e3,e4,e5,e6,e7,e8`, + }, + { + name: "expanded: set", + fromSchema: `id int primary key, e1 set('a', 'b'), e2 set('a', 'b'), e3 set('a', 'b'), e4 set('a', 'b'), e5 set('a', 'b'), e6 set('a', 'b'), e7 set('a', 'b'), e8 set('a', 'b')`, + toSchema: `id int primary key, e1 set('a', 'b'), e2 set('a'), e3 set('a', 'b', 'c'), e4 set('a', 'x'), e5 set('a', 'x', 'b'), e6 set('b'), e7 varchar(1), e8 tinyint`, + expandedColumnNames: `e3,e4,e5,e6,e7,e8`, + }, + } + + var ( + createTableWrapper = `CREATE TABLE t (%s)` + ) + + senv := schemadiff.NewTestEnv() + venv := vtenv.NewTestEnv() + diffHints := &schemadiff.DiffHints{} + for _, tcase := range testCases { + t.Run(tcase.name, func(t *testing.T) { + tcase.fromSchema = fmt.Sprintf(createTableWrapper, tcase.fromSchema) + sourceTableEntity, err := schemadiff.NewCreateTableEntityFromSQL(senv, tcase.fromSchema) + require.NoError(t, err) + + tcase.toSchema = fmt.Sprintf(createTableWrapper, tcase.toSchema) + targetTableEntity, err := schemadiff.NewCreateTableEntityFromSQL(senv, tcase.toSchema) + require.NoError(t, err) + + diff, err := sourceTableEntity.TableDiff(targetTableEntity, diffHints) + require.NoError(t, err) + + v, err := NewVRepl( + venv, + "7cee19dd_354b_11eb_82cd_f875a4d24e90", + "ks", + "0", + "mydb", + sourceTableEntity.CreateTable, + targetTableEntity.CreateTable, + diff.AlterTable(), + false, + ) + require.NoError(t, err) + + err = v.analyzeAlter() + require.NoError(t, err) + err = v.analyzeTables() + require.NoError(t, err) + + toStringSlice := func(s string) []string { + if s == "" { + return []string{} + } + return strings.Split(s, ",") + } + assert.Equal(t, toStringSlice(tcase.removedForeignKeyNames), v.analysis.RemovedForeignKeyNames) + assert.Equal(t, toStringSlice(tcase.removedUniqueKeyNames), v.analysis.RemovedUniqueKeys.Names()) + assert.Equal(t, toStringSlice(tcase.droppedNoDefaultColumnNames), v.analysis.DroppedNoDefaultColumns.Names()) + assert.Equal(t, toStringSlice(tcase.expandedColumnNames), v.analysis.ExpandedColumns.Names()) + }) + } +} 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_actions.go b/go/vt/vttablet/tabletmanager/rpc_actions.go index 45dd51670ba..21560f9d34b 100644 --- a/go/vt/vttablet/tabletmanager/rpc_actions.go +++ b/go/vt/vttablet/tabletmanager/rpc_actions.go @@ -78,7 +78,20 @@ func (tm *TabletManager) SetReadOnly(ctx context.Context, rdonly bool) error { return err } defer tm.unlock() + superRo, err := tm.MysqlDaemon.IsSuperReadOnly(ctx) + if err != nil { + return err + } + if !rdonly && superRo { + // If super read only is set, then we need to prepare the transactions before setting read_only OFF. + // We need to redo the prepared transactions in read only mode using the dba user to ensure we don't lose them. + // setting read_only OFF will also set super_read_only OFF if it was set. + // If super read only is already off, then we probably called this function from PRS or some other place + // because it is idempotent. We only need to redo prepared transactions the first time we transition from super read only + // to read write. + return tm.redoPreparedTransactionsAndSetReadWrite(ctx) + } return tm.MysqlDaemon.SetReadOnly(ctx, rdonly) } 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_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 3e745222092..1bd05493a59 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -22,11 +22,10 @@ import ( "strings" "time" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/protoutil" - - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/proto/vtrpc" @@ -348,6 +347,15 @@ func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string } defer tm.unlock() + semiSyncAction, err := tm.convertBoolToSemiSyncAction(ctx, semiSync) + if err != nil { + return "", err + } + + // If semi-sync is enabled, we need to set two pc to be allowed. + // Otherwise, we block all Prepared calls because atomic transactions require semi-sync for correctness.. + tm.QueryServiceControl.SetTwoPCAllowed(semiSyncAction == SemiSyncActionSet) + // Setting super_read_only `OFF` so that we can run the DDL commands if _, err := tm.MysqlDaemon.SetSuperReadOnly(ctx, false); err != nil { if sqlErr, ok := err.(*sqlerror.SQLError); ok && sqlErr.Number() == sqlerror.ERUnknownSystemVariable { @@ -369,11 +377,6 @@ func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string return "", err } - semiSyncAction, err := tm.convertBoolToSemiSyncAction(ctx, semiSync) - if err != nil { - return "", err - } - // Set the server read-write, from now on we can accept real // client writes. Note that if semi-sync replication is enabled, // we'll still need some replicas to be able to commit transactions. @@ -544,9 +547,10 @@ func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure defer func() { if finalErr != nil && revertPartialFailure && !wasReadOnly { + // We need to redo the prepared transactions in read only mode using the dba user to ensure we don't lose them. // setting read_only OFF will also set super_read_only OFF if it was set - if err := tm.MysqlDaemon.SetReadOnly(ctx, false); err != nil { - log.Warningf("SetReadOnly(false) failed during revert: %v", err) + if err = tm.redoPreparedTransactionsAndSetReadWrite(ctx); err != nil { + log.Warningf("RedoPreparedTransactionsAndSetReadWrite failed during revert: %v", err) } } }() @@ -594,13 +598,17 @@ func (tm *TabletManager) UndoDemotePrimary(ctx context.Context, semiSync bool) e return err } + // If semi-sync is enabled, we need to set two pc to be allowed. + // Otherwise, we block all Prepared calls because atomic transactions require semi-sync for correctness.. + tm.QueryServiceControl.SetTwoPCAllowed(semiSyncAction == SemiSyncActionSet) + // If using semi-sync, we need to enable source-side. if err := tm.fixSemiSync(ctx, topodatapb.TabletType_PRIMARY, semiSyncAction); err != nil { return err } - // Now, set the server read-only false. - if err := tm.MysqlDaemon.SetReadOnly(ctx, false); err != nil { + // We need to redo the prepared transactions in read only mode using the dba user to ensure we don't lose them. + if err = tm.redoPreparedTransactionsAndSetReadWrite(ctx); err != nil { return err } @@ -910,12 +918,16 @@ func (tm *TabletManager) PromoteReplica(ctx context.Context, semiSync bool) (str } defer tm.unlock() - pos, err := tm.MysqlDaemon.Promote(ctx, tm.hookExtraEnv()) + semiSyncAction, err := tm.convertBoolToSemiSyncAction(ctx, semiSync) if err != nil { return "", err } - semiSyncAction, err := tm.convertBoolToSemiSyncAction(ctx, semiSync) + // If semi-sync is enabled, we need to set two pc to be allowed. + // Otherwise, we block all Prepared calls because atomic transactions require semi-sync for correctness.. + tm.QueryServiceControl.SetTwoPCAllowed(semiSyncAction == SemiSyncActionSet) + + pos, err := tm.MysqlDaemon.Promote(ctx, tm.hookExtraEnv()) if err != nil { return "", err } diff --git a/go/vt/vttablet/tabletmanager/rpc_throttler.go b/go/vt/vttablet/tabletmanager/rpc_throttler.go index ab153b3ef43..ec75db6da43 100644 --- a/go/vt/vttablet/tabletmanager/rpc_throttler.go +++ b/go/vt/vttablet/tabletmanager/rpc_throttler.go @@ -19,36 +19,134 @@ 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 { return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "nil checkResult") } resp := &tabletmanagerdatapb.CheckThrottlerResponse{ + ResponseCode: throttle.ResponseCodeFromStatus(checkResult.ResponseCode, checkResult.StatusCode), StatusCode: int32(checkResult.StatusCode), Value: checkResult.Value, Threshold: checkResult.Threshold, Message: checkResult.Message, RecentlyChecked: checkResult.RecentlyChecked, + AppName: checkResult.AppName, + Summary: checkResult.Summary(), + 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), + ResponseCode: throttle.ResponseCodeFromStatus(metric.ResponseCode, 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), + ResponseCode: throttle.ResponseCodeFromStatus(checkResult.ResponseCode, 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), + ResponseCode: recentApp.ResponseCode, + } + } + return resp, nil +} diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 6046ed99727..2e70596b686 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -50,6 +50,7 @@ import ( "vitess.io/vitess/go/constants/sidecar" "vitess.io/vitess/go/flagutil" "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sets" @@ -751,6 +752,24 @@ func (tm *TabletManager) findMysqlPort(retryInterval time.Duration) { } } +// redoPreparedTransactionsAndSetReadWrite redoes prepared transactions in read-only mode. +// We turn off super read only mode, and then redo the transactions. Finally, we turn off read-only mode to allow for further traffic. +func (tm *TabletManager) redoPreparedTransactionsAndSetReadWrite(ctx context.Context) error { + _, err := tm.MysqlDaemon.SetSuperReadOnly(ctx, false) + if err != nil { + // Ignore the error if the sever doesn't support super read only variable. + // We should just redo the preapred transactions before we set it to read-write. + if sqlErr, ok := err.(*sqlerror.SQLError); ok && sqlErr.Number() == sqlerror.ERUnknownSystemVariable { + log.Warningf("server does not know about super_read_only, continuing anyway...") + } else { + return err + } + } + tm.QueryServiceControl.RedoPreparedTransactions() + err = tm.MysqlDaemon.SetReadOnly(ctx, false) + return err +} + func (tm *TabletManager) initTablet(ctx context.Context) error { tablet := tm.Tablet() err := tm.TopoServer.CreateTablet(ctx, tablet) diff --git a/go/vt/vttablet/tabletmanager/tm_state.go b/go/vt/vttablet/tabletmanager/tm_state.go index 312c675fce7..cf56c515cfc 100644 --- a/go/vt/vttablet/tabletmanager/tm_state.go +++ b/go/vt/vttablet/tabletmanager/tm_state.go @@ -214,9 +214,10 @@ func (ts *tmState) ChangeTabletType(ctx context.Context, tabletType topodatapb.T } if action == DBActionSetReadWrite { + // We need to redo the prepared transactions in read only mode using the dba user to ensure we don't lose them. // We call SetReadOnly only after the topo has been updated to avoid // situations where two tablets are primary at the DB level but not at the vitess level - if err := ts.tm.MysqlDaemon.SetReadOnly(ctx, false); err != nil { + if err = ts.tm.redoPreparedTransactionsAndSetReadWrite(ctx); err != nil { return err } } @@ -281,7 +282,7 @@ func (ts *tmState) updateLocked(ctx context.Context) error { errStr := fmt.Sprintf("SetServingType(serving=false) failed: %v", err) log.Errorf(errStr) // No need to short circuit. Apply all steps and return error in the end. - returnErr = vterrors.Wrapf(err, errStr) + returnErr = vterrors.Wrap(err, errStr) } } @@ -289,7 +290,7 @@ func (ts *tmState) updateLocked(ctx context.Context) error { errStr := fmt.Sprintf("Cannot update denied tables rule: %v", err) log.Errorf(errStr) // No need to short circuit. Apply all steps and return error in the end. - returnErr = vterrors.Wrapf(err, errStr) + returnErr = vterrors.Wrap(err, errStr) } if ts.tm.UpdateStream != nil { @@ -329,7 +330,7 @@ func (ts *tmState) updateLocked(ctx context.Context) error { if err := ts.tm.QueryServiceControl.SetServingType(ts.tablet.Type, ptsTime, true, ""); err != nil { errStr := fmt.Sprintf("Cannot start query service: %v", err) log.Errorf(errStr) - returnErr = vterrors.Wrapf(err, errStr) + returnErr = vterrors.Wrap(err, errStr) } } diff --git a/go/vt/vttablet/tabletmanager/vdiff/action.go b/go/vt/vttablet/tabletmanager/vdiff/action.go index 0b9dd6f45ed..f81fe3205eb 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/action.go +++ b/go/vt/vttablet/tabletmanager/vdiff/action.go @@ -37,7 +37,7 @@ import ( vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) -type VDiffAction string //nolint +type VDiffAction string // nolint const ( CreateAction VDiffAction = "create" @@ -238,9 +238,8 @@ func (vde *Engine) handleCreateResumeAction(ctx context.Context, dbClient binlog return err } if qr.RowsAffected == 0 { - msg := fmt.Sprintf("no completed or stopped vdiff found for UUID %s on tablet %v", + return fmt.Errorf("no completed or stopped vdiff found for UUID %s on tablet %v", req.VdiffUuid, vde.thisTablet.Alias) - return fmt.Errorf(msg) } } diff --git a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go index 43aa76894d4..ec42fab38a7 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go @@ -26,10 +26,12 @@ import ( "sync" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "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" @@ -212,7 +214,7 @@ func shortCircuitTestAfterQuery(query string, dbClient *binlogplayer.MockDBClien dbClient.ExpectRequest("insert into _vt.vdiff_log(vdiff_id, message) values (1, 'Error: Short circuiting test')", singleRowAffected, nil) } -//-------------------------------------- +// -------------------------------------- // Topos and tablets // fakeTabletConn implement TabletConn interface. We only care about the @@ -248,7 +250,7 @@ func (ftc *fakeTabletConn) VStream(ctx context.Context, request *binlogdatapb.VS if vstreamHook != nil { vstreamHook(ctx) } - return vdiffenv.vse.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send) + return vdiffenv.vse.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send, nil) } // vstreamRowsHook allows you to do work just before calling VStreamRows. @@ -282,7 +284,7 @@ func (ftc *fakeTabletConn) Close(ctx context.Context) error { return nil } -//-------------------------------------- +// -------------------------------------- // Binlog Client to TabletManager // fakeBinlogClient satisfies binlogplayer.Client. @@ -343,7 +345,7 @@ func (bts *btStream) Recv() (*binlogdatapb.BinlogTransaction, error) { return nil, bts.ctx.Err() } -//-------------------------------------- +// -------------------------------------- // DBCLient wrapper func realDBClientFactory() binlogplayer.DBClient { @@ -422,7 +424,11 @@ 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 type fakeTMClient struct { @@ -510,6 +516,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 @@ -613,10 +623,10 @@ func (tvde *testVDiffEnv) close() { tstenv.SchemaEngine.Reload(context.Background()) } tvde.tablets = nil - vdiffenv.vse.Close() - vdiffenv.vre.Close() - vdiffenv.vde.Close() - vdiffenv.dbClient.Close() + tvde.vse.Close() + tvde.vre.Close() + tvde.vde.Close() + tvde.dbClient.Close() } func (tvde *testVDiffEnv) addTablet(id int, keyspace, shard string, tabletType topodatapb.TabletType) *fakeTabletConn { @@ -651,3 +661,16 @@ func (tvde *testVDiffEnv) addTablet(id int, keyspace, shard string, tabletType t tstenv.SchemaEngine.Reload(context.Background()) return tvde.tablets[id] } + +func (tvde *testVDiffEnv) createController(t *testing.T, id int) *controller { + controllerQR := sqltypes.MakeTestResult(sqltypes.MakeTestFields( + vdiffTestCols, + vdiffTestColTypes, + ), + fmt.Sprintf("%d|%s|%s|%s|%s|%s|%s|%s|", id, uuid.New(), tvde.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), + ) + tvde.dbClient.ExpectRequest(fmt.Sprintf("select * from _vt.vdiff where id = %d", id), noResults, nil) + ct, err := newController(context.Background(), controllerQR.Named().Row(), tvde.dbClientFactory, tstenv.TopoServ, tvde.vde, tvde.opts) + require.NoError(t, err) + return ct +} diff --git a/go/vt/vttablet/tabletmanager/vdiff/report.go b/go/vt/vttablet/tabletmanager/vdiff/report.go index 62ce6d24585..b53288b3019 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/report.go +++ b/go/vt/vttablet/tabletmanager/vdiff/report.go @@ -18,11 +18,11 @@ package vdiff import ( "fmt" - "sort" - "strings" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" ) const ( @@ -63,9 +63,9 @@ type RowDiff struct { Query string `json:"Query,omitempty"` } -func (td *tableDiffer) genRowDiff(queryStmt string, row []sqltypes.Value, debug, onlyPks bool) (*RowDiff, error) { - drp := &RowDiff{} - drp.Row = make(map[string]string) +func (td *tableDiffer) genRowDiff(queryStmt string, row []sqltypes.Value, opts *tabletmanagerdatapb.VDiffReportOptions) (*RowDiff, error) { + rd := &RowDiff{} + rd.Row = make(map[string]string) statement, err := td.wd.ct.vde.parser.Parse(queryStmt) if err != nil { return nil, err @@ -75,30 +75,44 @@ func (td *tableDiffer) genRowDiff(queryStmt string, row []sqltypes.Value, debug, return nil, fmt.Errorf("unexpected: %+v", sqlparser.String(statement)) } - if debug { - drp.Query = td.genDebugQueryDiff(sel, row, onlyPks) + if opts.GetDebugQuery() { + rd.Query = td.genDebugQueryDiff(sel, row, opts.GetOnlyPks()) } - setVal := func(index int) { + addVal := func(index int, truncateAt int) { buf := sqlparser.NewTrackedBuffer(nil) sel.SelectExprs[index].Format(buf) col := buf.String() - drp.Row[col] = row[index].ToString() + // Let's truncate if it's really worth it to avoid losing + // value for a few chars. + if truncateAt > 0 && row[index].Len() >= truncateAt+len(truncatedNotation)+20 { + rd.Row[col] = row[index].ToString()[:truncateAt] + truncatedNotation + } else { + rd.Row[col] = row[index].ToString() + } } - if onlyPks { - for _, pkI := range td.tablePlan.selectPks { - setVal(pkI) - } - return drp, nil + // Include PK columns first and do not truncate them so that + // the user can always at a minimum identify the row for + // further investigation. + pks := make(map[int]struct{}, len(td.tablePlan.selectPks)) + for _, pkI := range td.tablePlan.selectPks { + addVal(pkI, 0) + pks[pkI] = struct{}{} } + if opts.GetOnlyPks() { + return rd, nil + } + + truncateAt := int(opts.GetRowDiffColumnTruncateAt()) for i := range sel.SelectExprs { - setVal(i) + if _, pk := pks[i]; !pk { + addVal(i, truncateAt) + } } - formatSampleRow(drp) - return drp, nil + return rd, nil } func (td *tableDiffer) genDebugQueryDiff(sel *sqlparser.Select, row []sqltypes.Value, onlyPks bool) string { @@ -130,22 +144,3 @@ func (td *tableDiffer) genDebugQueryDiff(sel *sqlparser.Select, row []sqltypes.V buf.Myprintf(";") return buf.String() } - -// formatSampleRow returns a formatted string representing a sample -// extra/mismatched row -func formatSampleRow(rd *RowDiff) { - keys := make([]string, 0, len(rd.Row)) - rowString := strings.Builder{} - for k := range rd.Row { - keys = append(keys, k) - } - - sort.Strings(keys) - for _, k := range keys { - // Let's truncate if it's really worth it to avoid losing value for a few chars - if len(rd.Row[k]) >= 30+len(truncatedNotation)+20 { - rd.Row[k] = rd.Row[k][:30] + truncatedNotation - } - rowString.WriteString(fmt.Sprintf("%s: %s\n", k, rd.Row[k])) - } -} diff --git a/go/vt/vttablet/tabletmanager/vdiff/report_test.go b/go/vt/vttablet/tabletmanager/vdiff/report_test.go new file mode 100644 index 00000000000..9b6d840f751 --- /dev/null +++ b/go/vt/vttablet/tabletmanager/vdiff/report_test.go @@ -0,0 +1,186 @@ +/* +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 vdiff + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/sqltypes" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" +) + +func TestGenRowDiff(t *testing.T) { + vdenv := newTestVDiffEnv(t) + defer vdenv.close() + + testCases := []struct { + name string + schema *tabletmanagerdatapb.SchemaDefinition + query string + tablePlan *tablePlan + row []sqltypes.Value + reportOptions *tabletmanagerdatapb.VDiffReportOptions + want *RowDiff + }{ + { + name: "defaults", + schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "t1", + Columns: []string{"c1", "c2", "c3", "c4", "c5"}, + PrimaryKeyColumns: []string{"c1", "c5"}, + Fields: sqltypes.MakeTestFields("c1|c2|c3|c4|c5", "int64|int64|varchar|varchar|int64"), + }, + }, + }, + query: "select c1,c2,c3,c4,c5 from t1", + tablePlan: &tablePlan{ + selectPks: []int{0, 4}, + }, + row: []sqltypes.Value{ + sqltypes.NewInt64(1), + sqltypes.NewInt64(2), + sqltypes.NewVarChar("hi3"), + sqltypes.NewVarChar("hi4"), + sqltypes.NewInt64(5), + }, + reportOptions: &tabletmanagerdatapb.VDiffReportOptions{}, + want: &RowDiff{ + Row: map[string]string{ // The two PK cols should be first + "c1": "1", "c5": "5", "c2": "2", "c3": "hi3", "c4": "hi4", + }, + }, + }, + { + name: "only PKs", + schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "t1", + Columns: []string{"c1", "c2"}, + PrimaryKeyColumns: []string{"c1"}, + Fields: sqltypes.MakeTestFields("c1|c2", "int64|int64"), + }, + }, + }, + query: "select c1,c2 from t1", + tablePlan: &tablePlan{ + selectPks: []int{0}, + }, + row: []sqltypes.Value{ + sqltypes.NewInt64(1), + sqltypes.NewInt64(2), + }, + reportOptions: &tabletmanagerdatapb.VDiffReportOptions{ + OnlyPks: true, + }, + want: &RowDiff{ + Row: map[string]string{ + "c1": "1", + }, + }, + }, + { + name: "debug query", + schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "t1", + Columns: []string{"c1", "c2"}, + PrimaryKeyColumns: []string{"c1"}, + Fields: sqltypes.MakeTestFields("c1|c2", "int64|int64"), + }, + }, + }, + query: "select c1,c2 from t1", + tablePlan: &tablePlan{ + selectPks: []int{0}, + }, + row: []sqltypes.Value{ + sqltypes.NewInt64(1), + sqltypes.NewInt64(2), + }, + reportOptions: &tabletmanagerdatapb.VDiffReportOptions{ + DebugQuery: true, + }, + want: &RowDiff{ + Row: map[string]string{ + "c1": "1", + "c2": "2", + }, + Query: "select c1, c2 from t1 where c1=1;", + }, + }, + { + name: "column truncation", + schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "t1", + Columns: []string{"c1", "c2"}, + PrimaryKeyColumns: []string{"c1"}, + Fields: sqltypes.MakeTestFields("c1|c2", "varchar|varchar"), + }, + }, + }, + query: "select c1,c2 from t1", + tablePlan: &tablePlan{ + selectPks: []int{0}, + }, + row: []sqltypes.Value{ + sqltypes.NewVarChar(strings.Repeat("a", 100)), + sqltypes.NewVarChar(strings.Repeat("b", 100)), + }, + reportOptions: &tabletmanagerdatapb.VDiffReportOptions{ + RowDiffColumnTruncateAt: 5, + }, + want: &RowDiff{ + Row: map[string]string{ + "c1": strings.Repeat("a", 100), // PK fields are not truncated + "c2": strings.Repeat("b", 5) + truncatedNotation, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + require.NotNil(t, tc.tablePlan) + require.NotNil(t, tc.row) + require.NotNil(t, tc.reportOptions) + + vdenv.tmc.schema = tc.schema + ct := vdenv.createController(t, 1) + wd, err := newWorkflowDiffer(ct, vdenv.opts, collations.MySQL8()) + require.NoError(t, err) + td := &tableDiffer{ + wd: wd, + sourceQuery: tc.query, + tablePlan: tc.tablePlan, + } + + got, err := td.genRowDiff(tc.query, tc.row, tc.reportOptions) + require.NoError(t, err) + require.EqualValues(t, tc.want, got) + }) + } +} diff --git a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go index a98a3ce90f9..102d7535af9 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) } }() @@ -485,7 +486,7 @@ func (td *tableDiffer) setupRowSorters() { } } -func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onlyPks bool, maxExtraRowsToCompare int64, maxReportSampleRows int64, stop <-chan time.Time) (*DiffReport, error) { +func (td *tableDiffer) diff(ctx context.Context, coreOpts *tabletmanagerdatapb.VDiffCoreOptions, reportOpts *tabletmanagerdatapb.VDiffReportOptions, stop <-chan time.Time) (*DiffReport, error) { defer td.wd.ct.TableDiffPhaseTimings.Record(fmt.Sprintf("%s.%s", td.table.Name, diffingTable), time.Now()) dbClient := td.wd.ct.dbClientFactory() if err := dbClient.Connect(); err != nil { @@ -538,6 +539,10 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl globalStats.RowsDiffedCount.Add(dr.ProcessedRows) }() + rowsToCompare := coreOpts.GetMaxRows() + maxExtraRowsToCompare := coreOpts.GetMaxExtraRowsToCompare() + maxReportSampleRows := reportOpts.GetMaxSampleRows() + for { lastProcessedRow = sourceRow @@ -559,6 +564,7 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl return nil, err } } + rowsToCompare-- if rowsToCompare < 0 { log.Infof("Stopping vdiff, specified row limit reached") @@ -586,7 +592,7 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl advanceSource = true advanceTarget = true if sourceRow == nil { - diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, targetRow, debug, onlyPks) + diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, targetRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } @@ -604,7 +610,7 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl if targetRow == nil { // No more rows from the target but we know we have more rows from // source, so drain them and update the counts. - diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, sourceRow, debug, onlyPks) + diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, sourceRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } @@ -627,7 +633,7 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl return nil, err case c < 0: if dr.ExtraRowsSource < maxExtraRowsToCompare { - diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, sourceRow, debug, onlyPks) + diffRow, err := td.genRowDiff(td.tablePlan.sourceQuery, sourceRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } @@ -638,7 +644,7 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl continue case c > 0: if dr.ExtraRowsTarget < maxExtraRowsToCompare { - diffRow, err := td.genRowDiff(td.tablePlan.targetQuery, targetRow, debug, onlyPks) + diffRow, err := td.genRowDiff(td.tablePlan.targetQuery, targetRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } @@ -658,11 +664,11 @@ func (td *tableDiffer) diff(ctx context.Context, rowsToCompare int64, debug, onl case c != 0: // We don't do a second pass to compare mismatched rows so we can cap the slice here. if maxReportSampleRows == 0 || dr.MismatchedRows < maxReportSampleRows { - sourceDiffRow, err := td.genRowDiff(td.tablePlan.targetQuery, sourceRow, debug, onlyPks) + sourceDiffRow, err := td.genRowDiff(td.tablePlan.targetQuery, sourceRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } - targetDiffRow, err := td.genRowDiff(td.tablePlan.targetQuery, targetRow, debug, onlyPks) + targetDiffRow, err := td.genRowDiff(td.tablePlan.targetQuery, targetRow, reportOpts) if err != nil { return nil, vterrors.Wrap(err, "unexpected error generating diff") } diff --git a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go index 8c00b61b784..e891b693423 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go +++ b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go @@ -205,7 +205,7 @@ func (wd *workflowDiffer) diffTable(ctx context.Context, dbClient binlogplayer.D } log.Infof("Table initialization done on table %s for vdiff %s", td.table.Name, wd.ct.uuid) diffTimer = time.NewTimer(maxDiffRuntime) - diffReport, diffErr = td.diff(ctx, wd.opts.CoreOptions.MaxRows, wd.opts.ReportOptions.DebugQuery, wd.opts.ReportOptions.OnlyPks, wd.opts.CoreOptions.MaxExtraRowsToCompare, wd.opts.ReportOptions.MaxSampleRows, diffTimer.C) + diffReport, diffErr = td.diff(ctx, wd.opts.CoreOptions, wd.opts.ReportOptions, diffTimer.C) if diffErr == nil { // We finished the diff successfully break } diff --git a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go index d4f9ddb001d..0054c37faf7 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go @@ -588,15 +588,7 @@ func TestBuildPlanInclude(t *testing.T) { vdenv := newTestVDiffEnv(t) defer vdenv.close() - controllerQR := sqltypes.MakeTestResult(sqltypes.MakeTestFields( - vdiffTestCols, - vdiffTestColTypes, - ), - fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", uuid.New(), vdiffenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), - ) - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", noResults, nil) - ct, err := newController(context.Background(), controllerQR.Named().Row(), vdiffenv.dbClientFactory, tstenv.TopoServ, vdiffenv.vde, vdiffenv.opts) - require.NoError(t, err) + ct := vdenv.createController(t, 1) schm := &tabletmanagerdatapb.SchemaDefinition{ TableDefinitions: []*tabletmanagerdatapb.TableDefinition{{ 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/external_connector.go b/go/vt/vttablet/tabletmanager/vreplication/external_connector.go index c53bfd2a584..f98e7d73c79 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/external_connector.go +++ b/go/vt/vttablet/tabletmanager/vreplication/external_connector.go @@ -48,7 +48,8 @@ type VStreamerClient interface { Close(context.Context) error // VStream streams VReplication events based on the specified filter. - VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error) error + VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, + send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error // VStreamRows streams rows of a table from the specified starting point. VStreamRows(ctx context.Context, query string, lastpk *querypb.QueryResult, send func(*binlogdatapb.VStreamRowsResponse) error) error @@ -110,7 +111,7 @@ func (ec *externalConnector) Get(name string) (*mysqlConnector, error) { return c, nil } -//----------------------------------------------------------- +// ----------------------------------------------------------- type mysqlConnector struct { env tabletenv.Env @@ -131,8 +132,9 @@ func (c *mysqlConnector) Close(ctx context.Context) error { return nil } -func (c *mysqlConnector) VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error) error { - return c.vstreamer.Stream(ctx, startPos, tablePKs, filter, throttlerapp.ExternalConnectorName, send) +func (c *mysqlConnector) VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error { + return c.vstreamer.Stream(ctx, startPos, tablePKs, filter, throttlerapp.ExternalConnectorName, send, nil) } func (c *mysqlConnector) VStreamRows(ctx context.Context, query string, lastpk *querypb.QueryResult, send func(*binlogdatapb.VStreamRowsResponse) error) error { @@ -151,7 +153,7 @@ func (c *mysqlConnector) VStreamTables(ctx context.Context, send func(response * return c.vstreamer.StreamTables(ctx, send) } -//----------------------------------------------------------- +// ----------------------------------------------------------- type tabletConnector struct { tablet *topodatapb.Tablet @@ -180,8 +182,9 @@ func (tc *tabletConnector) Close(ctx context.Context) error { return tc.qs.Close(ctx) } -func (tc *tabletConnector) VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error) error { - req := &binlogdatapb.VStreamRequest{Target: tc.target, Position: startPos, TableLastPKs: tablePKs, Filter: filter} +func (tc *tabletConnector) VStream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error { + req := &binlogdatapb.VStreamRequest{Target: tc.target, Position: startPos, TableLastPKs: tablePKs, Filter: filter, Options: options} return tc.qs.VStream(ctx, req, send) } diff --git a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go index d4253de27e7..8b5dd6d9416 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" @@ -236,7 +237,7 @@ func execConnStatements(t *testing.T, conn *dbconnpool.DBConnection, queries []s } } -//-------------------------------------- +// -------------------------------------- // Topos and tablets func addTablet(id int) *topodatapb.Tablet { @@ -318,7 +319,7 @@ func (ftc *fakeTabletConn) VStream(ctx context.Context, request *binlogdatapb.VS if vstreamHook != nil { vstreamHook(ctx) } - return streamerEngine.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send) + return streamerEngine.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send, nil) } // vstreamRowsHook allows you to do work just before calling VStreamRows. @@ -348,7 +349,7 @@ func (ftc *fakeTabletConn) VStreamRows(ctx context.Context, request *binlogdatap }) } -//-------------------------------------- +// -------------------------------------- // Binlog Client to TabletManager // fakeBinlogClient satisfies binlogplayer.Client. @@ -425,7 +426,7 @@ func expectFBCRequest(t *testing.T, tablet *topodatapb.Tablet, pos string, table } } -//-------------------------------------- +// -------------------------------------- // DBCLient wrapper func realDBClientFactory() binlogplayer.DBClient { @@ -486,7 +487,7 @@ func (dbc *realDBClient) ExecuteFetch(query string, maxrows int) (*sqltypes.Resu globalDBQueries <- query } else if testSetForeignKeyQueries && strings.Contains(query, "set foreign_key_checks") { globalDBQueries <- query - } else if testForeignKeyQueries && strings.Contains(query, "foreign_key_checks") { //allow select/set for foreign_key_checks + } else if testForeignKeyQueries && strings.Contains(query, "foreign_key_checks") { // allow select/set for foreign_key_checks globalDBQueries <- query } return qr, err @@ -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/replica_connector.go b/go/vt/vttablet/tabletmanager/vreplication/replica_connector.go index c3cd073f0bf..f26b5054d01 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/replica_connector.go +++ b/go/vt/vttablet/tabletmanager/vreplication/replica_connector.go @@ -58,7 +58,7 @@ func NewReplicaConnector(venv *vtenv.Environment, connParams *mysql.ConnParams) return c } -//----------------------------------------------------------- +// ----------------------------------------------------------- type ReplicaConnector struct { conn *mysql.ConnParams @@ -73,5 +73,5 @@ func (c *ReplicaConnector) Close() error { } func (c *ReplicaConnector) VStream(ctx context.Context, startPos string, filter *binlogdatapb.Filter, send func([]*binlogdatapb.VEvent) error) error { - return c.vstreamer.Stream(ctx, startPos, nil, filter, throttlerapp.ReplicaConnectorName, send) + return c.vstreamer.Stream(ctx, startPos, nil, filter, throttlerapp.ReplicaConnectorName, send, nil) } diff --git a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan.go b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan.go index 3bef997d0be..bd41fd76419 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan.go +++ b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan.go @@ -27,6 +27,7 @@ import ( "vitess.io/vitess/go/mysql/collations/charset" "vitess.io/vitess/go/mysql/collations/colldata" vjson "vitess.io/vitess/go/mysql/json" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/sqlparser" @@ -88,7 +89,7 @@ func (rp *ReplicatorPlan) buildExecutionPlan(fieldEvent *binlogdatapb.FieldEvent // select * construct was used. We need to use the field names. tplan, err := rp.buildFromFields(prelim.TargetName, prelim.Lastpk, fieldEvent.Fields) if err != nil { - return nil, err + return nil, vterrors.Wrapf(err, "failed to build replication plan for %s table", fieldEvent.TableName) } tplan.Fields = fieldEvent.Fields return tplan, nil @@ -257,7 +258,7 @@ func (tp *TablePlan) applyBulkInsert(sqlbuffer *bytes2.Buffer, rows []*querypb.R if i > 0 { sqlbuffer.WriteString(", ") } - if err := appendFromRow(tp.BulkInsertValues, sqlbuffer, tp.Fields, row, tp.FieldsToSkip); err != nil { + if err := tp.appendFromRow(sqlbuffer, row); err != nil { return nil, err } } @@ -296,7 +297,7 @@ func (tp *TablePlan) isOutsidePKRange(bindvars map[string]*querypb.BindVariable, case !before && after: bindvar = bindvars["a_"+tp.PKReferences[0]] } - if bindvar == nil { //should never happen + if bindvar == nil { // should never happen return false } @@ -312,6 +313,30 @@ func (tp *TablePlan) isOutsidePKRange(bindvars map[string]*querypb.BindVariable, return false } +// convertStringCharset does a charset conversion given raw data and an applicable conversion rule. +// In case of a conversion error, it returns an equivalent of MySQL error 1366, which is what you'd +// get in a failed `CONVERT()` function, e.g.: +// +// > create table tascii(v varchar(100) charset ascii); +// > insert into tascii values ('€'); +// ERROR 1366 (HY000): Incorrect string value: '\xE2\x82\xAC' for column 'v' at row 1 +func (tp *TablePlan) convertStringCharset(raw []byte, conversion *binlogdatapb.CharsetConversion, fieldName string) ([]byte, error) { + fromCollation := tp.CollationEnv.DefaultCollationForCharset(conversion.FromCharset) + if fromCollation == collations.Unknown { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "character set %s not supported for column %s", conversion.FromCharset, fieldName) + } + toCollation := tp.CollationEnv.DefaultCollationForCharset(conversion.ToCharset) + if toCollation == collations.Unknown { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "character set %s not supported for column %s", conversion.ToCharset, fieldName) + } + + out, err := charset.Convert(nil, colldata.Lookup(toCollation).Charset(), raw, colldata.Lookup(fromCollation).Charset()) + if err != nil { + return nil, sqlerror.NewSQLErrorf(sqlerror.ERTruncatedWrongValueForField, sqlerror.SSUnknownSQLState, "Incorrect string value: %s", err.Error()) + } + return out, nil +} + // bindFieldVal returns a bind variable based on given field and value. // Most values will just bind directly. But some values may need manipulation: // - text values with charset conversion @@ -320,11 +345,7 @@ func (tp *TablePlan) isOutsidePKRange(bindvars map[string]*querypb.BindVariable, func (tp *TablePlan) bindFieldVal(field *querypb.Field, val *sqltypes.Value) (*querypb.BindVariable, error) { if conversion, ok := tp.ConvertCharset[field.Name]; ok && !val.IsNull() { // Non-null string value, for which we have a charset conversion instruction - fromCollation := tp.CollationEnv.DefaultCollationForCharset(conversion.FromCharset) - if fromCollation == collations.Unknown { - return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Character set %s not supported for column %s", conversion.FromCharset, field.Name) - } - out, err := charset.Convert(nil, charset.Charset_utf8mb4{}, val.Raw(), colldata.Lookup(fromCollation).Charset()) + out, err := tp.convertStringCharset(val.Raw(), conversion, field.Name) if err != nil { return nil, err } @@ -590,28 +611,30 @@ func valsEqual(v1, v2 sqltypes.Value) bool { // note: there can be more fields than bind locations since extra columns might be requested from the source if not all // primary keys columns are present in the target table, for example. Also some values in the row may not correspond for // values from the database on the source: sum/count for aggregation queries, for example -func appendFromRow(pq *sqlparser.ParsedQuery, buf *bytes2.Buffer, fields []*querypb.Field, row *querypb.Row, skipFields map[string]bool) error { - bindLocations := pq.BindLocations() - if len(fields) < len(bindLocations) { +func (tp *TablePlan) appendFromRow(buf *bytes2.Buffer, row *querypb.Row) error { + bindLocations := tp.BulkInsertValues.BindLocations() + if len(tp.Fields) < len(bindLocations) { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "wrong number of fields: got %d fields for %d bind locations ", - len(fields), len(bindLocations)) + len(tp.Fields), len(bindLocations)) } type colInfo struct { typ querypb.Type length int64 offset int64 + field *querypb.Field } rowInfo := make([]*colInfo, 0) offset := int64(0) - for i, field := range fields { // collect info required for fields to be bound + for i, field := range tp.Fields { // collect info required for fields to be bound length := row.Lengths[i] - if !skipFields[strings.ToLower(field.Name)] { + if !tp.FieldsToSkip[strings.ToLower(field.Name)] { rowInfo = append(rowInfo, &colInfo{ typ: field.Type, length: length, offset: offset, + field: field, }) } if length > 0 { @@ -623,7 +646,7 @@ func appendFromRow(pq *sqlparser.ParsedQuery, buf *bytes2.Buffer, fields []*quer var offsetQuery int for i, loc := range bindLocations { col := rowInfo[i] - buf.WriteString(pq.Query[offsetQuery:loc.Offset]) + buf.WriteString(tp.BulkInsertValues.Query[offsetQuery:loc.Offset]) typ := col.typ switch typ { @@ -645,12 +668,25 @@ func appendFromRow(pq *sqlparser.ParsedQuery, buf *bytes2.Buffer, fields []*quer // -1 means a null variable; serialize it directly buf.WriteString(sqltypes.NullStr) } else { - vv := sqltypes.MakeTrusted(typ, row.Values[col.offset:col.offset+col.length]) + raw := row.Values[col.offset : col.offset+col.length] + var vv sqltypes.Value + + if conversion, ok := tp.ConvertCharset[col.field.Name]; ok && col.length > 0 { + // Non-null string value, for which we have a charset conversion instruction + out, err := tp.convertStringCharset(raw, conversion, col.field.Name) + if err != nil { + return err + } + vv = sqltypes.MakeTrusted(typ, out) + } else { + vv = sqltypes.MakeTrusted(typ, raw) + } + vv.EncodeSQLBytes2(buf) } } offsetQuery = loc.Offset + loc.Length } - buf.WriteString(pq.Query[offsetQuery:]) + buf.WriteString(tp.BulkInsertValues.Query[offsetQuery:]) return nil } diff --git a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go index 6c9f92128ac..d3971c3a397 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go @@ -574,7 +574,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "bad query", }}, }, - err: "syntax error at position 4 near 'bad' in query: bad query", + err: "failed to build table replication plan for t1 table: syntax error at position 4 near 'bad' in query: bad query", }, { // not a select input: &binlogdatapb.Filter{ @@ -583,7 +583,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "update t1 set val = 1", }}, }, - err: "unsupported non-select statement in query: update t1 set val = 1", + err: "failed to build table replication plan for t1 table: unsupported non-select statement in query: update t1 set val = 1", }, { // no distinct input: &binlogdatapb.Filter{ @@ -592,7 +592,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select distinct c1 from t1", }}, }, - err: "unsupported distinct clause in query: select distinct c1 from t1", + err: "failed to build table replication plan for t1 table: unsupported distinct clause in query: select distinct c1 from t1", }, { // no ',' join input: &binlogdatapb.Filter{ @@ -601,7 +601,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select * from t1, t2", }}, }, - err: "unsupported multi-table usage in query: select * from t1, t2", + err: "failed to build table replication plan for t1 table: unsupported multi-table usage in query: select * from t1, t2", }, { // no join input: &binlogdatapb.Filter{ @@ -610,7 +610,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select * from t1 join t2", }}, }, - err: "unsupported from expression (*sqlparser.JoinTableExpr) in query: select * from t1 join t2", + err: "failed to build table replication plan for t1 table: unsupported from expression (*sqlparser.JoinTableExpr) in query: select * from t1 join t2", }, { // no subqueries input: &binlogdatapb.Filter{ @@ -619,7 +619,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select * from (select * from t2) as a", }}, }, - err: "unsupported from source (*sqlparser.DerivedTable) in query: select * from (select * from t2) as a", + err: "failed to build table replication plan for t1 table: unsupported from source (*sqlparser.DerivedTable) in query: select * from (select * from t2) as a", }, { // cannot combine '*' with other input: &binlogdatapb.Filter{ @@ -628,7 +628,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select *, c1 from t1", }}, }, - err: "unsupported mix of '*' and columns in query: select *, c1 from t1", + err: "failed to build table replication plan for t1 table: unsupported mix of '*' and columns in query: select *, c1 from t1", }, { // cannot combine '*' with other (different code path) input: &binlogdatapb.Filter{ @@ -637,7 +637,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select c1, * from t1", }}, }, - err: "invalid expression: * in query: select c1, * from t1", + err: "failed to build table replication plan for t1 table: invalid expression: * in query: select c1, * from t1", }, { // no distinct in func input: &binlogdatapb.Filter{ @@ -646,7 +646,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select hour(distinct c1) as a from t1", }}, }, - err: "syntax error at position 21 near 'distinct' in query: select hour(distinct c1) as a from t1", + err: "failed to build table replication plan for t1 table: syntax error at position 21 near 'distinct' in query: select hour(distinct c1) as a from t1", }, { // funcs need alias input: &binlogdatapb.Filter{ @@ -655,7 +655,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select hour(c1) from t1", }}, }, - err: "expression needs an alias: hour(c1) in query: select hour(c1) from t1", + err: "failed to build table replication plan for t1 table: expression needs an alias: hour(c1) in query: select hour(c1) from t1", }, { // only count(*) input: &binlogdatapb.Filter{ @@ -664,7 +664,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select count(c1) as c from t1", }}, }, - err: "only count(*) is supported: count(c1) in query: select count(c1) as c from t1", + err: "failed to build table replication plan for t1 table: only count(*) is supported: count(c1) in query: select count(c1) as c from t1", }, { // no sum(*) input: &binlogdatapb.Filter{ @@ -673,7 +673,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select sum(*) as c from t1", }}, }, - err: "syntax error at position 13 in query: select sum(*) as c from t1", + err: "failed to build table replication plan for t1 table: syntax error at position 13 in query: select sum(*) as c from t1", }, { // sum should have only one argument input: &binlogdatapb.Filter{ @@ -682,7 +682,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select sum(a, b) as c from t1", }}, }, - err: "syntax error at position 14 in query: select sum(a, b) as c from t1", + err: "failed to build table replication plan for t1 table: syntax error at position 14 in query: select sum(a, b) as c from t1", }, { // no complex expr in sum input: &binlogdatapb.Filter{ @@ -691,7 +691,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select sum(a + b) as c from t1", }}, }, - err: "unsupported non-column name in sum clause: sum(a + b) in query: select sum(a + b) as c from t1", + err: "failed to build table replication plan for t1 table: unsupported non-column name in sum clause: sum(a + b) in query: select sum(a + b) as c from t1", }, { // no complex expr in group by input: &binlogdatapb.Filter{ @@ -700,7 +700,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select a from t1 group by a + 1", }}, }, - err: "unsupported non-column name or alias in group by clause: a + 1 in query: select a from t1 group by a + 1", + err: "failed to build table replication plan for t1 table: unsupported non-column name or alias in group by clause: a + 1 in query: select a from t1 group by a + 1", }, { // group by does not reference alias input: &binlogdatapb.Filter{ @@ -709,7 +709,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select a as b from t1 group by a", }}, }, - err: "group by expression does not reference an alias in the select list: a in query: select a as b from t1 group by a", + err: "failed to build table replication plan for t1 table: group by expression does not reference an alias in the select list: a in query: select a as b from t1 group by a", }, { // cannot group by aggr input: &binlogdatapb.Filter{ @@ -718,7 +718,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select count(*) as a from t1 group by a", }}, }, - err: "group by expression is not allowed to reference an aggregate expression: a in query: select count(*) as a from t1 group by a", + err: "failed to build table replication plan for t1 table: group by expression is not allowed to reference an aggregate expression: a in query: select count(*) as a from t1 group by a", }} PrimaryKeyInfos := map[string][]*ColumnInfo{ diff --git a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go index 2e44fd49e9b..db774af1861 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go +++ b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go @@ -161,7 +161,7 @@ func buildReplicatorPlan(source *binlogdatapb.BinlogSource, colInfoMap map[strin } tablePlan, err := buildTablePlan(tableName, rule, colInfos, lastpk, stats, source, collationEnv, parser) if err != nil { - return nil, err + return nil, vterrors.Wrapf(err, "failed to build table replication plan for %s table", tableName) } if tablePlan == nil { // Table was excluded. @@ -598,7 +598,7 @@ func (tpb *tablePlanBuilder) analyzePK(cols []*ColumnInfo) error { // TODO(shlomi): at some point in the futue we want to make this check stricter. // We could be reading a generated column c1 which in turn selects some other column c2. // We will want t oensure that `c2` is found in select list... - return fmt.Errorf("primary key column %v not found in select list", col) + return fmt.Errorf("primary key column %v not found in table's select filter or the TableMap event within the GTID", col) } if cexpr.operation != opExpr { return fmt.Errorf("primary key column %v is not allowed to reference an aggregate expression", col) diff --git a/go/vt/vttablet/tabletmanager/vreplication/utils.go b/go/vt/vttablet/tabletmanager/vreplication/utils.go index 2b80bfb62a2..230fe6a249c 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/utils.go +++ b/go/vt/vttablet/tabletmanager/vreplication/utils.go @@ -134,7 +134,12 @@ func isUnrecoverableError(err error) bool { if err == nil { return false } - if vterrors.Code(err) == vtrpcpb.Code_FAILED_PRECONDITION { + switch vterrors.Code(err) { + case vtrpcpb.Code_FAILED_PRECONDITION: + if vterrors.RxWrongTablet.MatchString(err.Error()) { + // If the chosen tablet type picked changes, say due to PRS/ERS, we should retry. + return false + } return true } sqlErr, isSQLErr := sqlerror.NewSQLErrorFromError(err).(*sqlerror.SQLError) @@ -222,6 +227,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/utils_test.go b/go/vt/vttablet/tabletmanager/vreplication/utils_test.go index bfe79036f3c..eb2b128f90e 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/utils_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/utils_test.go @@ -17,17 +17,21 @@ limitations under the License. package vreplication import ( + "errors" "fmt" "strings" "testing" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/textutil" "vitess.io/vitess/go/vt/binlog/binlogplayer" + "vitess.io/vitess/go/vt/vterrors" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) func TestInsertLogTruncation(t *testing.T) { @@ -97,3 +101,60 @@ func TestInsertLogTruncation(t *testing.T) { }) } } + +// TestIsUnrecoverableError tests the different error cases for isUnrecoverableError(). +func TestIsUnrecoverableError(t *testing.T) { + if runNoBlobTest { + t.Skip() + } + + type testCase struct { + name string + err error + expected bool + } + + testCases := []testCase{ + { + name: "Nil error", + err: nil, + expected: false, + }, + { + name: "vterrors.Code_FAILED_PRECONDITION", + err: vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "test error"), + expected: true, + }, + { + name: "vterrors.Code_FAILED_PRECONDITION, WrongTablet", + err: vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s: %v, want: %v or %v", vterrors.WrongTablet, "PRIMARY", "REPLICA", nil), + expected: false, + }, + { + name: "Non-SQL error", + err: errors.New("non-SQL error"), + expected: false, + }, + { + name: "SQL error with ERUnknownError", + err: sqlerror.NewSQLError(sqlerror.ERUnknownError, "test SQL error", "test"), + expected: false, + }, + { + name: "SQL error with ERAccessDeniedError", + err: sqlerror.NewSQLError(sqlerror.ERAccessDeniedError, "access denied", "test"), + expected: true, + }, + { + name: "SQL error with ERDataOutOfRange", + err: sqlerror.NewSQLError(sqlerror.ERDataOutOfRange, "data out of range", "test"), + expected: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := isUnrecoverableError(tc.err) + require.Equal(t, tc.expected, result) + }) + } +} diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier.go index 9057a55707f..47e3798acd0 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vcopier.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vcopier.go @@ -456,7 +456,7 @@ func (vc *vcopier) copyTable(ctx context.Context, tableName string, copyState ma default: } if rows.Throttled { - _ = vc.vr.updateTimeThrottled(throttlerapp.RowStreamerName) + _ = vc.vr.updateTimeThrottled(throttlerapp.RowStreamerName, rows.ThrottledReason) return nil } if rows.Heartbeat { @@ -464,10 +464,10 @@ func (vc *vcopier) copyTable(ctx context.Context, tableName string, copyState ma return nil } // verify throttler is happy, otherwise keep looping - if vc.vr.vre.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, throttlerapp.Name(vc.throttlerAppName)) { + if checkResult, ok := vc.vr.vre.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, throttlerapp.Name(vc.throttlerAppName)); ok { break // out of 'for' loop } else { // we're throttled - _ = vc.vr.updateTimeThrottled(throttlerapp.VCopierName) + _ = vc.vr.updateTimeThrottled(throttlerapp.VCopierName, checkResult.Summary()) } } if !copyWorkQueue.isOpen { diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer.go index c2eba565524..31558102a5e 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vplayer.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer.go @@ -176,7 +176,7 @@ func newVPlayer(vr *vreplicator, settings binlogplayer.VRSettings, copyState map timeLastSaved: time.Now(), tablePlans: make(map[string]*TablePlan), phase: phase, - throttlerAppName: throttlerapp.VCopierName.ConcatenateString(vr.throttlerAppName()), + throttlerAppName: throttlerapp.VPlayerName.ConcatenateString(vr.throttlerAppName()), query: queryFunc, commit: commitFunc, batchMode: batchMode, @@ -273,9 +273,10 @@ func (vp *vplayer) fetchAndApply(ctx context.Context) (err error) { streamErr := make(chan error, 1) go func() { - streamErr <- vp.vr.sourceVStreamer.VStream(ctx, replication.EncodePosition(vp.startPos), nil, vp.replicatorPlan.VStreamFilter, func(events []*binlogdatapb.VEvent) error { - return relay.Send(events) - }) + streamErr <- vp.vr.sourceVStreamer.VStream(ctx, replication.EncodePosition(vp.startPos), nil, + vp.replicatorPlan.VStreamFilter, func(events []*binlogdatapb.VEvent) error { + return relay.Send(events) + }, nil) }() applyErr := make(chan error, 1) @@ -414,7 +415,7 @@ func (vp *vplayer) recordHeartbeat() error { return nil } if err := vp.vr.updateHeartbeatTime(tm); err != nil { - return vterrors.Wrapf(errVPlayerStalled, fmt.Sprintf("%s: %v", failedToRecordHeartbeatMsg, err)) + return vterrors.Wrapf(errVPlayerStalled, "%s: %v", failedToRecordHeartbeatMsg, err) } // Only reset the pending heartbeat count if the update was successful. // Otherwise the vplayer may not actually be making progress and nobody @@ -476,19 +477,26 @@ func (vp *vplayer) recordHeartbeat() error { func (vp *vplayer) applyEvents(ctx context.Context, relay *relayLog) error { defer vp.vr.dbClient.Rollback() + estimateLag := func() { + behind := time.Now().UnixNano() - vp.lastTimestampNs - vp.timeOffsetNs + vp.vr.stats.ReplicationLagSeconds.Store(behind / 1e9) + vp.vr.stats.VReplicationLags.Add(strconv.Itoa(int(vp.vr.id)), time.Duration(behind/1e9)*time.Second) + } + // If we're not running, set ReplicationLagSeconds to be very high. // TODO(sougou): if we also stored the time of the last event, we // can estimate this value more accurately. defer vp.vr.stats.ReplicationLagSeconds.Store(math.MaxInt64) defer vp.vr.stats.VReplicationLags.Add(strconv.Itoa(int(vp.vr.id)), math.MaxInt64) - var sbm int64 = -1 + var lagSecs int64 for { if ctx.Err() != nil { return ctx.Err() } // Check throttler. - if !vp.vr.vre.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, throttlerapp.Name(vp.throttlerAppName)) { - _ = vp.vr.updateTimeThrottled(throttlerapp.VPlayerName) + if checkResult, ok := vp.vr.vre.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, throttlerapp.Name(vp.throttlerAppName)); !ok { + _ = vp.vr.updateTimeThrottled(throttlerapp.VPlayerName, checkResult.Summary()) + estimateLag() continue } @@ -496,13 +504,7 @@ func (vp *vplayer) applyEvents(ctx context.Context, relay *relayLog) error { if err != nil { return err } - // No events were received. This likely means that there's a network partition. - // So, we should assume we're falling behind. - if len(items) == 0 { - behind := time.Now().UnixNano() - vp.lastTimestampNs - vp.timeOffsetNs - vp.vr.stats.ReplicationLagSeconds.Store(behind / 1e9) - vp.vr.stats.VReplicationLags.Add(strconv.Itoa(int(vp.vr.id)), time.Duration(behind/1e9)*time.Second) - } + // Empty transactions are saved at most once every idleTimeout. // This covers two situations: // 1. Fetch was idle for idleTimeout. @@ -520,12 +522,20 @@ func (vp *vplayer) applyEvents(ctx context.Context, relay *relayLog) error { } } + lagSecs = -1 for i, events := range items { for j, event := range events { if event.Timestamp != 0 { - vp.lastTimestampNs = event.Timestamp * 1e9 - vp.timeOffsetNs = time.Now().UnixNano() - event.CurrentTime - sbm = event.CurrentTime/1e9 - event.Timestamp + // If the event is a heartbeat sent while throttled then do not update + // the lag based on it. + // If the batch consists only of throttled heartbeat events then we cannot + // determine the actual lag, as the vstreamer is fully throttled, and we + // will estimate it after processing the batch. + if !(event.Type == binlogdatapb.VEventType_HEARTBEAT && event.Throttled) { + vp.lastTimestampNs = event.Timestamp * 1e9 + vp.timeOffsetNs = time.Now().UnixNano() - event.CurrentTime + lagSecs = event.CurrentTime/1e9 - event.Timestamp + } } mustSave := false switch event.Type { @@ -549,7 +559,7 @@ func (vp *vplayer) applyEvents(ctx context.Context, relay *relayLog) error { if err := vp.applyEvent(ctx, event, mustSave); err != nil { if err != io.EOF { vp.vr.stats.ErrorCounts.Add([]string{"Apply"}, 1) - var table, tableLogMsg string + var table, tableLogMsg, gtidLogMsg string switch { case event.GetFieldEvent() != nil: table = event.GetFieldEvent().TableName @@ -559,18 +569,24 @@ func (vp *vplayer) applyEvents(ctx context.Context, relay *relayLog) error { if table != "" { tableLogMsg = fmt.Sprintf(" for table %s", table) } - log.Errorf("Error applying event%s: %s", tableLogMsg, err.Error()) + pos := getNextPosition(items, i, j+1) + if pos != "" { + gtidLogMsg = fmt.Sprintf(" while processing position %s", pos) + } + log.Errorf("Error applying event%s%s: %s", tableLogMsg, gtidLogMsg, err.Error()) + err = vterrors.Wrapf(err, "error applying event%s%s", tableLogMsg, gtidLogMsg) } return err } } } - if sbm >= 0 { - vp.vr.stats.ReplicationLagSeconds.Store(sbm) - vp.vr.stats.VReplicationLags.Add(strconv.Itoa(int(vp.vr.id)), time.Duration(sbm)*time.Second) + if lagSecs >= 0 { + vp.vr.stats.ReplicationLagSeconds.Store(lagSecs) + vp.vr.stats.VReplicationLags.Add(strconv.Itoa(int(vp.vr.id)), time.Duration(lagSecs)*time.Second) + } else { // We couldn't determine the lag, so we need to estimate it + estimateLag() } - } } @@ -592,6 +608,34 @@ func hasAnotherCommit(items [][]*binlogdatapb.VEvent, i, j int) bool { return false } +// getNextPosition returns the GTID set/position we would be at if the current +// transaction was committed. This is useful for error handling as we can then +// determine which GTID we're failing to process from the source and examine the +// binlog events for that GTID directly on the source to debug the issue. +// This is needed as it's not as simple as the user incrementing the current +// position in the stream by 1 as we may be skipping N intermediate GTIDs in the +// stream due to filtering. For GTIDs that we filter out we still replicate the +// GTID event itself, just without any internal events and a COMMIT event (see +// the unsavedEvent handling). +func getNextPosition(items [][]*binlogdatapb.VEvent, i, j int) string { + for i < len(items) { + for j < len(items[i]) { + switch items[i][j].Type { + case binlogdatapb.VEventType_GTID: + pos, err := binlogplayer.DecodePosition(items[i][j].Gtid) + if err != nil { + return "" + } + return pos.String() + } + j++ + } + j = 0 + i++ + } + return "" +} + func (vp *vplayer) applyEvent(ctx context.Context, event *binlogdatapb.VEvent, mustSave bool) error { stats := NewVrLogStats(event.Type.String()) switch event.Type { @@ -794,7 +838,7 @@ func (vp *vplayer) applyEvent(ctx context.Context, event *binlogdatapb.VEvent, m return io.EOF case binlogdatapb.VEventType_HEARTBEAT: if event.Throttled { - if err := vp.vr.updateTimeThrottled(throttlerapp.VStreamerName); err != nil { + if err := vp.vr.updateTimeThrottled(throttlerapp.VStreamerName, event.ThrottledReason); err != nil { return err } } diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go index b1925c3c64f..0641a111199 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go @@ -575,9 +575,20 @@ func TestPlayerForeignKeyCheck(t *testing.T) { cancel() } -func TestPlayerStatementModeWithFilter(t *testing.T) { +// TestPlayerStatementModeWithFilterAndErrorHandling confirms that we get the +// expected error when using a filter with statement mode. It also tests the +// general vplayer applyEvent error and log message handling. +func TestPlayerStatementModeWithFilterAndErrorHandling(t *testing.T) { defer deleteTablet(addTablet(100)) + // We want to check for the expected log message. + ole := log.Errorf + logger := logutil.NewMemoryLogger() + log.Errorf = logger.Errorf + defer func() { + log.Errorf = ole + }() + execStatements(t, []string{ "create table src1(id int, val varbinary(128), primary key(id))", }) @@ -600,21 +611,29 @@ func TestPlayerStatementModeWithFilter(t *testing.T) { cancel, _ := startVReplication(t, bls, "") defer cancel() + const gtid = "37f16b4c-5a74-11ef-87de-56bfd605e62e:100" input := []string{ "set @@session.binlog_format='STATEMENT'", + fmt.Sprintf("set @@session.gtid_next='%s'", gtid), "insert into src1 values(1, 'aaa')", + "set @@session.gtid_next='AUTOMATIC'", "set @@session.binlog_format='ROW'", } + expectedMsg := fmt.Sprintf("[Ee]rror applying event while processing position .*%s.* filter rules are not supported for SBR.*", gtid) + // It does not work when filter is enabled output := qh.Expect( "begin", "rollback", - "/update _vt.vreplication set message='filter rules are not supported for SBR", + fmt.Sprintf("/update _vt.vreplication set message='%s", expectedMsg), ) execStatements(t, input) expectDBClientQueries(t, output) + + logs := logger.String() + require.Regexp(t, expectedMsg, logs) } func TestPlayerStatementMode(t *testing.T) { @@ -1758,8 +1777,8 @@ func TestPlayerDDL(t *testing.T) { execStatements(t, []string{"alter table t1 add column val2 varchar(128)"}) expectDBClientQueries(t, qh.Expect( "alter table t1 add column val2 varchar(128)", - "/update _vt.vreplication set message='Duplicate", - "/update _vt.vreplication set state='Error', message='Duplicate", + "/update _vt.vreplication set message='error applying event: Duplicate", + "/update _vt.vreplication set state='Error', message='error applying event: Duplicate", )) cancel() diff --git a/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go b/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go index 8a01cf7c8ed..2a4d598c960 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 @@ -582,13 +630,13 @@ func (vr *vreplicator) throttlerAppName() string { // tablet throttler over time. It also increments the global throttled count to keep // track of how many times in total vreplication has been throttled across all workflows // (both ones that currently exist and ones that no longer do). -func (vr *vreplicator) updateTimeThrottled(appThrottled throttlerapp.Name) error { +func (vr *vreplicator) updateTimeThrottled(appThrottled throttlerapp.Name, reasonThrottled string) error { appName := appThrottled.String() vr.stats.ThrottledCounts.Add([]string{"tablet", appName}, 1) globalStats.ThrottledCount.Add(1) err := vr.throttleUpdatesRateLimiter.Do(func() error { tm := time.Now().Unix() - update, err := binlogplayer.GenerateUpdateTimeThrottled(vr.id, tm, appName) + update, err := binlogplayer.GenerateUpdateTimeThrottled(vr.id, tm, appName, reasonThrottled) if err != nil { return err } @@ -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..20a5450741d 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go @@ -31,6 +31,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/mysqlctl" @@ -481,7 +482,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) @@ -807,3 +816,59 @@ func waitForQueryResult(t *testing.T, dbc binlogplayer.DBClient, query, val stri } } } + +func TestThrottlerAppNames(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + tablet := addTablet(100) + defer deleteTablet(tablet) + filter := &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "t1", + }}, + } + bls := &binlogdatapb.BinlogSource{ + Keyspace: env.KeyspaceName, + Shard: env.ShardName, + Filter: filter, + } + id := int32(1) + vsclient := newTabletConnector(tablet) + stats := binlogplayer.NewStats() + defer stats.Stop() + dbClient := playerEngine.dbClientFactoryFiltered() + err := dbClient.Connect() + require.NoError(t, err) + defer dbClient.Close() + dbName := dbClient.DBName() + // Ensure there's a dummy vreplication workflow record + _, err = dbClient.ExecuteFetch(fmt.Sprintf("insert into _vt.vreplication (id, workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state, db_name, options) values (%d, 'test_workflow', '', '', 99999, 99999, 0, 0, 'Running', '%s', '{}') on duplicate key update workflow='test', source='', pos='', max_tps=99999, max_replication_lag=99999, time_updated=0, transaction_timestamp=0, state='Running', db_name='%s'", + id, dbName, dbName), 1) + require.NoError(t, err) + defer func() { + _, err = dbClient.ExecuteFetch(fmt.Sprintf("delete from _vt.vreplication where id = %d", id), 1) + require.NoError(t, err) + }() + vr := newVReplicator(id, bls, vsclient, stats, dbClient, env.Mysqld, playerEngine) + settings, _, err := vr.loadSettings(ctx, newVDBClient(dbClient, stats)) + require.NoError(t, err) + + throttlerAppName := vr.throttlerAppName() + assert.Contains(t, throttlerAppName, "test_workflow") + assert.Contains(t, throttlerAppName, "vreplication") + assert.NotContains(t, throttlerAppName, "vcopier") + assert.NotContains(t, throttlerAppName, "vplayer") + + vp := newVPlayer(vr, settings, nil, replication.Position{}, "") + assert.Contains(t, vp.throttlerAppName, "test_workflow") + assert.Contains(t, vp.throttlerAppName, "vreplication") + assert.Contains(t, vp.throttlerAppName, "vplayer") + assert.NotContains(t, vp.throttlerAppName, "vcopier") + + vc := newVCopier(vr) + assert.Contains(t, vc.throttlerAppName, "test_workflow") + assert.Contains(t, vc.throttlerAppName, "vreplication") + assert.Contains(t, vc.throttlerAppName, "vcopier") + assert.NotContains(t, vc.throttlerAppName, "vplayer") +} diff --git a/go/vt/vttablet/tabletmanager/vreplication/vrlog_test.go b/go/vt/vttablet/tabletmanager/vreplication/vrlog_test.go index 3bd0dcf3217..48fe7fa983e 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vrlog_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vrlog_test.go @@ -23,6 +23,8 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestVrLog(t *testing.T) { @@ -49,9 +51,7 @@ func TestVrLog(t *testing.T) { } want := fmt.Sprintf("%s Event %s", eventType, detail) - if !strings.Contains(s, want) { - t.Fatalf(fmt.Sprintf("want %s, got %s", want, s)) - } + require.Contains(t, s, want) if strings.HasSuffix(s, "\\n") { t.Fatalf("does not end in a newline: %s", s) } @@ -65,9 +65,7 @@ func TestVrLog(t *testing.T) { if err != nil { t.Fatalf("Duration is not an integer: %s", err) } - if lastColValue == 0 { - t.Fatalf("Duration should not be zero") - } + require.NotZero(t, lastColValue, "duration") stats = &VrLogStats{} stats.Send("detail123") diff --git a/go/vt/vttablet/tabletserver/binlog_watcher.go b/go/vt/vttablet/tabletserver/binlog_watcher.go index cff7697c18a..80ac1194c7e 100644 --- a/go/vt/vttablet/tabletserver/binlog_watcher.go +++ b/go/vt/vttablet/tabletserver/binlog_watcher.go @@ -31,7 +31,9 @@ import ( // VStreamer defines the functions of VStreamer // that the BinlogWatcher needs. type VStreamer interface { - Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error + Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, + options *binlogdatapb.VStreamOptions) error } // BinlogWatcher is a tabletserver service that watches the @@ -93,7 +95,7 @@ func (blw *BinlogWatcher) process(ctx context.Context) { // VStreamer will reload the schema when it encounters a DDL. err := blw.vs.Stream(ctx, "current", nil, filter, throttlerapp.BinlogWatcherName, func(events []*binlogdatapb.VEvent) error { return nil - }) + }, nil) log.Infof("ReplicationWatcher VStream ended: %v, retrying in 5 seconds", err) select { case <-ctx.Done(): diff --git a/go/vt/vttablet/tabletserver/connpool/dbconn.go b/go/vt/vttablet/tabletserver/connpool/dbconn.go index af8c5fbc78e..61816b16d08 100644 --- a/go/vt/vttablet/tabletserver/connpool/dbconn.go +++ b/go/vt/vttablet/tabletserver/connpool/dbconn.go @@ -598,3 +598,7 @@ func (dbc *Conn) applySameSetting(ctx context.Context) error { _, err := dbc.execOnce(ctx, dbc.setting.ApplyQuery(), 1, false, false) return err } + +func (dbc *Conn) IsUnixSocket() bool { + return dbc.conn.IsClientUnixSocket() +} diff --git a/go/vt/vttablet/tabletserver/controller.go b/go/vt/vttablet/tabletserver/controller.go index 4d7e35862de..aae07fb96f6 100644 --- a/go/vt/vttablet/tabletserver/controller.go +++ b/go/vt/vttablet/tabletserver/controller.go @@ -92,6 +92,12 @@ type Controller interface { // CheckThrottler CheckThrottler(ctx context.Context, appName string, flags *throttle.CheckFlags) *throttle.CheckResult + GetThrottlerStatus(ctx context.Context) *throttle.ThrottlerStatus + + RedoPreparedTransactions() + + // SetTwoPCAllowed sets whether TwoPC is allowed or not. + SetTwoPCAllowed(bool) } // Ensure TabletServer satisfies Controller interface. diff --git a/go/vt/vttablet/tabletserver/debug_2pc.go b/go/vt/vttablet/tabletserver/debug_2pc.go new file mode 100644 index 00000000000..a0de20104db --- /dev/null +++ b/go/vt/vttablet/tabletserver/debug_2pc.go @@ -0,0 +1,48 @@ +//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 tabletserver + +import ( + "os" + "path" + "strconv" + "time" + + "vitess.io/vitess/go/vt/log" +) + +const DebugTwoPc = true + +// readFileForTestSynchronization is a test-only function that reads a file +// that we use for synchronizing some of the tests. +func readFileForTestSynchronization(fileName string) string { + res, _ := os.ReadFile(path.Join(os.Getenv("VTDATAROOT"), fileName)) + return string(res) +} + +// commitPreparedDelayForTest is a test-only function that delays the commit that have already been prepared. +func commitPreparedDelayForTest(tsv *TabletServer) { + sh := readFileForTestSynchronization("VT_DELAY_COMMIT_SHARD") + if tsv.sm.target.Shard == sh { + delay := readFileForTestSynchronization("VT_DELAY_COMMIT_TIME") + delVal, _ := strconv.Atoi(delay) + log.Infof("Delaying commit for shard %v for %d seconds", sh, delVal) + time.Sleep(time.Duration(delVal) * time.Second) + } +} 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/dt_executor.go b/go/vt/vttablet/tabletserver/dt_executor.go index baaa8b43a4e..52e9366f322 100644 --- a/go/vt/vttablet/tabletserver/dt_executor.go +++ b/go/vt/vttablet/tabletserver/dt_executor.go @@ -20,15 +20,15 @@ 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/sqlparser" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/tabletserver/rules" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" ) // DTExecutor is used for executing a distributed transactional request. @@ -36,13 +36,15 @@ type DTExecutor struct { ctx context.Context logStats *tabletenv.LogStats te *TxEngine + qe *QueryEngine } // NewDTExecutor creates a new distributed transaction executor. -func NewDTExecutor(ctx context.Context, te *TxEngine, logStats *tabletenv.LogStats) *DTExecutor { +func NewDTExecutor(ctx context.Context, te *TxEngine, qe *QueryEngine, logStats *tabletenv.LogStats) *DTExecutor { return &DTExecutor{ ctx: ctx, te: te, + qe: qe, logStats: logStats, } } @@ -55,6 +57,9 @@ func (dte *DTExecutor) Prepare(transactionID int64, dtid string) error { if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } + if !dte.te.twopcAllowed { + return vterrors.VT10002("two-pc is enabled, but semi-sync is not") + } defer dte.te.env.Stats().QueryTimings.Record("PREPARE", time.Now()) dte.logStats.TransactionID = transactionID @@ -65,14 +70,35 @@ func (dte *DTExecutor) Prepare(transactionID int64, dtid string) error { // If no queries were executed, we just rollback. if len(conn.TxProperties().Queries) == 0 { - conn.Release(tx.TxRollback) + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) return nil } + // We can only prepare on a Unix socket connection. + // Unix socket are reliable and we can be sure that the connection is not lost with the server after prepare. + if !conn.IsUnixSocket() { + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) + return vterrors.VT10002("cannot prepare the transaction on a network connection") + } + // 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") + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) + return vterrors.VT10002("cannot prepare the transaction on a reserved connection") + } + + // Fail Prepare if any query rule disallows it. + // This could be due to ongoing cutover happening in vreplication workflow + // regarding OnlineDDL or MoveTables. + for _, query := range conn.TxProperties().Queries { + qr := dte.qe.queryRuleSources.FilterByPlan(query.Sql, 0, query.Tables...) + if qr != nil { + act, _, _, _ := qr.GetAction("", "", nil, sqlparser.MarginComments{}) + if act != rules.QRContinue { + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) + return vterrors.VT10002("cannot prepare the transaction due to query rule") + } + } } err = dte.te.preparedPool.Put(conn, dtid) @@ -81,6 +107,28 @@ func (dte *DTExecutor) Prepare(transactionID int64, dtid string) error { return vterrors.Errorf(vtrpcpb.Code_RESOURCE_EXHAUSTED, "prepare failed for transaction %d: %v", transactionID, err) } + // Recheck the rules. As some prepare transaction could have passed the first check. + // If they are put in the prepared pool, then vreplication workflow waits. + // This check helps reject the prepare that came later. + for _, query := range conn.TxProperties().Queries { + qr := dte.qe.queryRuleSources.FilterByPlan(query.Sql, 0, query.Tables...) + if qr != nil { + act, _, _, _ := qr.GetAction("", "", nil, sqlparser.MarginComments{}) + if act != rules.QRContinue { + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) + dte.te.preparedPool.FetchForRollback(dtid) + return vterrors.VT10002("cannot prepare the transaction due to query rule") + } + } + } + + // If OnlineDDL killed the connection. We should avoid the prepare for it. + if conn.IsClosed() { + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) + dte.te.preparedPool.FetchForRollback(dtid) + return vterrors.VT10002("cannot prepare the transaction on a closed connection") + } + return dte.inTransaction(func(localConn *StatefulConnection) error { return dte.te.twoPC.SaveRedo(dte.ctx, localConn, dtid, conn.TxProperties().Queries) }) @@ -90,30 +138,34 @@ func (dte *DTExecutor) 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 (dte *DTExecutor) CommitPrepared(dtid string) error { +func (dte *DTExecutor) CommitPrepared(dtid string) (err error) { if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } defer dte.te.env.Stats().QueryTimings.Record("COMMIT_PREPARED", time.Now()) - conn, err := dte.te.preparedPool.FetchForCommit(dtid) + var conn *StatefulConnection + 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) + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "cannot commit dtid %s, err: %v", dtid, err) } + // No connection means the transaction was already committed. if conn == nil { return nil } // We have to use a context that will never give up, // even if the original context expires. 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 { - dte.markFailed(ctx, dtid) + defer func() { + if err != nil { + dte.markFailed(ctx, dtid) + log.Warningf("failed to commit the prepared transaction '%s' with error: %v", dtid, err) + } + dte.te.txPool.RollbackAndRelease(ctx, conn) + }() + if err = dte.te.twoPC.DeleteRedo(ctx, conn, dtid); err != nil { return err } - _, err = dte.te.txPool.Commit(ctx, conn) - if err != nil { - dte.markFailed(ctx, dtid) + if _, err = dte.te.txPool.Commit(ctx, conn); err != nil { return err } dte.te.preparedPool.Forget(dtid) @@ -209,7 +261,16 @@ func (dte *DTExecutor) StartCommit(transactionID int64, dtid string) error { } defer dte.te.txPool.RollbackAndRelease(dte.ctx, conn) - err = dte.te.twoPC.Transition(dte.ctx, conn, dtid, querypb.TransactionState_COMMIT) + // If the connection is tainted, we cannot take a commit decision on it. + if conn.IsTainted() { + dte.inTransaction(func(conn *StatefulConnection) error { + return dte.te.twoPC.Transition(dte.ctx, conn, dtid, DTStateRollback) + }) + // return the error, defer call above will roll back the transaction. + return vterrors.VT10002("cannot commit the transaction on a reserved connection") + } + + err = dte.te.twoPC.Transition(dte.ctx, conn, dtid, DTStateCommit) if err != nil { return err } @@ -227,11 +288,16 @@ func (dte *DTExecutor) SetRollback(dtid string, transactionID int64) error { dte.logStats.TransactionID = transactionID if transactionID != 0 { + // 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) + } else { + // This is a warning because it should not happen in normal operation. + log.Warningf("SetRollback called with no transactionID for dtid %s", dtid) } return dte.inTransaction(func(conn *StatefulConnection) error { - return dte.te.twoPC.Transition(dte.ctx, conn, dtid, querypb.TransactionState_ROLLBACK) + return dte.te.twoPC.Transition(dte.ctx, conn, dtid, DTStateRollback) }) } @@ -290,3 +356,8 @@ func (dte *DTExecutor) inTransaction(f func(*StatefulConnection) error) error { } 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/dt_executor_test.go b/go/vt/vttablet/tabletserver/dt_executor_test.go index 6637cc83841..f6369cfb978 100644 --- a/go/vt/vttablet/tabletserver/dt_executor_test.go +++ b/go/vt/vttablet/tabletserver/dt_executor_test.go @@ -21,9 +21,14 @@ import ( "errors" "fmt" "reflect" + "strings" "testing" "time" + "vitess.io/vitess/go/event/syslogger" + "vitess.io/vitess/go/vt/vtenv" + "vitess.io/vitess/go/vt/vttablet/tabletserver/rules" + "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" "github.com/stretchr/testify/require" @@ -31,8 +36,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" @@ -45,11 +48,42 @@ func TestTxExecutorEmptyPrepare(t *testing.T) { txe, tsv, db := newTestTxExecutor(t, ctx) defer db.Close() defer tsv.StopService() + + // start a transaction. txid := newTransaction(tsv, nil) - err := txe.Prepare(txid, "aa") + + // taint the connection. + sc, err := tsv.te.txPool.GetAndLock(txid, "taint") + require.NoError(t, err) + sc.Taint(ctx, nil) + sc.Unlock() + + err = txe.Prepare(txid, "aa") require.NoError(t, err) // Nothing should be prepared. require.Empty(t, txe.te.preparedPool.conns, "txe.te.preparedPool.conns") + require.False(t, sc.IsInTransaction(), "transaction should be roll back before returning the connection to the pool") +} + +func TestExecutorPrepareFailure(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + txe, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + + // start a transaction + txid := newTxForPrep(ctx, tsv) + + // taint the connection. + sc, err := tsv.te.txPool.GetAndLock(txid, "taint") + require.NoError(t, err) + sc.Taint(ctx, nil) + sc.Unlock() + + // try 2pc commit of Metadata Manager. + err = txe.Prepare(txid, "aa") + require.EqualError(t, err, "VT10002: atomic distributed transaction not allowed: cannot prepare the transaction on a reserved connection") } func TestTxExecutorPrepare(t *testing.T) { @@ -84,7 +118,7 @@ func TestDTExecutorPrepareResevedConn(t *testing.T) { 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") + require.ErrorContains(t, err, "VT10002: atomic distributed transaction not allowed: cannot prepare the transaction on a reserved connection") } func TestTxExecutorPrepareNotInTx(t *testing.T) { @@ -154,6 +188,60 @@ func TestTxExecutorPrepareRedoCommitFail(t *testing.T) { require.Contains(t, err.Error(), "commit fail") } +func TestExecutorPrepareRuleFailure(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + txe, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + + alterRule := rules.NewQueryRule("disable update", "disable update", rules.QRBuffer) + alterRule.AddTableCond("test_table") + + r := rules.New() + r.Add(alterRule) + txe.qe.queryRuleSources.RegisterSource("bufferQuery") + err := txe.qe.queryRuleSources.SetRules("bufferQuery", r) + require.NoError(t, err) + + // start a transaction + txid := newTxForPrep(ctx, tsv) + + // taint the connection. + sc, err := tsv.te.txPool.GetAndLock(txid, "adding query property") + require.NoError(t, err) + sc.txProps.Queries = append(sc.txProps.Queries, tx.Query{ + Sql: "update test_table set col = 5", + Tables: []string{"test_table"}, + }) + sc.Unlock() + + // try 2pc commit of Metadata Manager. + err = txe.Prepare(txid, "aa") + require.EqualError(t, err, "VT10002: atomic distributed transaction not allowed: cannot prepare the transaction due to query rule") +} + +func TestExecutorPrepareConnFailure(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + txe, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + + // start a transaction + txid := newTxForPrep(ctx, tsv) + + // taint the connection. + sc, err := tsv.te.txPool.GetAndLock(txid, "adding query property") + require.NoError(t, err) + sc.Unlock() + sc.dbConn.Close() + + // try 2pc commit of Metadata Manager. + err = txe.Prepare(txid, "aa") + require.EqualError(t, err, "VT10002: atomic distributed transaction not allowed: cannot prepare the transaction on a closed connection") +} + func TestTxExecutorCommit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -176,20 +264,31 @@ func TestTxExecutorCommitRedoFail(t *testing.T) { txe, tsv, db := newTestTxExecutor(t, ctx) defer db.Close() defer tsv.StopService() + + tl := syslogger.NewTestLogger() + defer tl.Close() + + // start a transaction. txid := newTxForPrep(ctx, tsv) - // Allow all additions to redo logs to succeed + + // prepare the transaction db.AddQueryPattern("insert into _vt\\.redo_state.*", &sqltypes.Result{}) err := txe.Prepare(txid, "bb") require.NoError(t, err) - defer txe.RollbackPrepared("bb", 0) - db.AddQuery("update _vt.redo_state set state = 'Failed' where dtid = 'bb'", &sqltypes.Result{}) + + // fail commit prepare as the delete redo query is in rejected query. + db.AddRejectedQuery("delete from _vt.redo_state where dtid = 'bb'", errors.New("delete redo log fail")) + db.AddQuery("update _vt.redo_state set state = 0 where dtid = 'bb'", sqltypes.MakeTestResult(nil)) err = txe.CommitPrepared("bb") - require.Error(t, err) - require.Contains(t, err.Error(), "is not supported") - // A retry should fail differently. + require.ErrorContains(t, err, "delete redo log fail") + + // A retry should fail differently as the prepared transaction is marked as failed. err = txe.CommitPrepared("bb") require.Error(t, err) - require.Contains(t, err.Error(), "cannot commit dtid bb, state: failed") + require.Contains(t, err.Error(), "cannot commit dtid bb, err: VT09025: atomic transaction error: failed to commit") + + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), + "failed to commit the prepared transaction 'bb' with error: unknown error: delete redo log fail") } func TestTxExecutorCommitRedoCommitFail(t *testing.T) { @@ -275,6 +374,31 @@ func TestExecutorStartCommit(t *testing.T) { require.Contains(t, err.Error(), "could not transition to COMMIT: aa") } +func TestExecutorStartCommitFailure(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + txe, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + + // start a transaction + txid := newTxForPrep(ctx, tsv) + + // taint the connection. + sc, err := tsv.te.txPool.GetAndLock(txid, "taint") + require.NoError(t, err) + sc.Taint(ctx, nil) + sc.Unlock() + + // add rollback state update expectation + rollbackTransition := fmt.Sprintf("update _vt.dt_state set state = %d where dtid = 'aa' and state = %d", int(querypb.TransactionState_ROLLBACK), int(querypb.TransactionState_PREPARE)) + db.AddQuery(rollbackTransition, sqltypes.MakeTestResult(nil)) + + // try 2pc commit of Metadata Manager. + err = txe.StartCommit(txid, "aa") + require.EqualError(t, err, "VT10002: atomic distributed transaction not allowed: cannot commit the transaction on a reserved connection") +} + func TestExecutorSetRollback(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -449,51 +573,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") } } @@ -553,6 +667,11 @@ func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *DTExecutor, tsv db = setUpQueryExecutorTest(t) logStats := tabletenv.NewLogStats(ctx, "TestTxExecutor") tsv = newTestTabletServer(ctx, smallTxPool, db) + cfg := tabletenv.NewDefaultConfig() + cfg.DB = newDBConfigs(db) + env := tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest") + se := schema.NewEngine(env) + qe := NewQueryEngine(env, se) db.AddQueryPattern("insert into _vt\\.redo_state\\(dtid, state, time_created\\) values \\('aa', 1,.*", &sqltypes.Result{}) db.AddQueryPattern("insert into _vt\\.redo_statement.*", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_state where dtid = 'aa'", &sqltypes.Result{}) @@ -562,6 +681,7 @@ func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *DTExecutor, tsv ctx: ctx, logStats: logStats, te: tsv.te, + qe: qe, }, tsv, db } diff --git a/go/vt/vttablet/tabletserver/gc/tablegc.go b/go/vt/vttablet/tabletserver/gc/tablegc.go index fced176b027..4d1714532a3 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, @@ -550,7 +551,7 @@ func (collector *TableGC) purge(ctx context.Context) (tableName string, err erro // cancelled return tableName, err } - if !collector.throttlerClient.ThrottleCheckOKOrWait(ctx) { + if _, ok := collector.throttlerClient.ThrottleCheckOKOrWait(ctx); !ok { continue } // OK, we're clear to go! diff --git a/go/vt/vttablet/tabletserver/health_streamer.go b/go/vt/vttablet/tabletserver/health_streamer.go index 269e3daefd6..cfc5ea5e974 100644 --- a/go/vt/vttablet/tabletserver/health_streamer.go +++ b/go/vt/vttablet/tabletserver/health_streamer.go @@ -346,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/messager/engine.go b/go/vt/vttablet/tabletserver/messager/engine.go index 612619f7ccc..2e526fcdc3d 100644 --- a/go/vt/vttablet/tabletserver/messager/engine.go +++ b/go/vt/vttablet/tabletserver/messager/engine.go @@ -45,7 +45,8 @@ type TabletService interface { // VStreamer defines the functions of VStreamer // that the messager needs. type VStreamer interface { - Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error + Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, + throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error StreamResults(ctx context.Context, query string, send func(*binlogdatapb.VStreamResultsResponse) error) error } diff --git a/go/vt/vttablet/tabletserver/messager/message_manager.go b/go/vt/vttablet/tabletserver/messager/message_manager.go index 2f4f8605870..a1fc27187a3 100644 --- a/go/vt/vttablet/tabletserver/messager/message_manager.go +++ b/go/vt/vttablet/tabletserver/messager/message_manager.go @@ -742,7 +742,7 @@ func (mm *messageManager) runOneVStream(ctx context.Context) error { } } return nil - }) + }, nil) return err } diff --git a/go/vt/vttablet/tabletserver/messager/message_manager_test.go b/go/vt/vttablet/tabletserver/messager/message_manager_test.go index fdf39556e5c..6c323d2d95b 100644 --- a/go/vt/vttablet/tabletserver/messager/message_manager_test.go +++ b/go/vt/vttablet/tabletserver/messager/message_manager_test.go @@ -889,7 +889,8 @@ func (fv *fakeVStreamer) setPollerResponse(pr []*binlogdatapb.VStreamResultsResp fv.pollerResponse = pr } -func (fv *fakeVStreamer) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error { +func (fv *fakeVStreamer) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error { fv.streamInvocations.Add(1) for { fv.mu.Lock() diff --git a/go/vt/vttablet/tabletserver/planbuilder/builder.go b/go/vt/vttablet/tabletserver/planbuilder/builder.go index 94f5fc1caa2..6df89f7caf8 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/builder.go +++ b/go/vt/vttablet/tabletserver/planbuilder/builder.go @@ -33,7 +33,7 @@ func analyzeSelect(env *vtenv.Environment, sel *sqlparser.Select, tables map[str PlanID: PlanSelect, FullQuery: GenerateLimitQuery(sel), } - plan.Table, plan.AllTables = lookupTables(sel.From, tables) + plan.Table = lookupTables(sel.From, tables) if sel.Where != nil { comp, ok := sel.Where.Expr.(*sqlparser.ComparisonExpr) @@ -72,7 +72,7 @@ func analyzeUpdate(upd *sqlparser.Update, tables map[string]*schema.Table) (plan plan = &Plan{ PlanID: PlanUpdate, } - plan.Table, plan.AllTables = lookupTables(upd.TableExprs, tables) + plan.Table = lookupTables(upd.TableExprs, tables) // Store the WHERE clause as string for the hot row protection (txserializer). if upd.Where != nil { @@ -102,7 +102,7 @@ func analyzeDelete(del *sqlparser.Delete, tables map[string]*schema.Table) (plan plan = &Plan{ PlanID: PlanDelete, } - plan.Table, plan.AllTables = lookupTables(del.TableExprs, tables) + plan.Table = lookupTables(del.TableExprs, tables) if del.Where != nil { buf := sqlparser.NewTrackedBuffer(nil) @@ -127,11 +127,7 @@ func analyzeInsert(ins *sqlparser.Insert, tables map[string]*schema.Table) (plan FullQuery: GenerateFullQuery(ins), } - tableName, err := ins.Table.TableName() - if err != nil { - return nil, err - } - plan.Table = tables[sqlparser.GetTableName(tableName).String()] + plan.Table = lookupTables(sqlparser.TableExprs{ins.Table}, tables) return plan, nil } @@ -188,16 +184,26 @@ func analyzeSet(set *sqlparser.Set) (plan *Plan) { } } -func lookupTables(tableExprs sqlparser.TableExprs, tables map[string]*schema.Table) (singleTable *schema.Table, allTables []*schema.Table) { +func lookupTables(tableExprs sqlparser.TableExprs, tables map[string]*schema.Table) (singleTable *schema.Table) { for _, tableExpr := range tableExprs { if t := lookupSingleTable(tableExpr, tables); t != nil { - allTables = append(allTables, t) + if singleTable != nil { + return nil + } + singleTable = t } } - if len(allTables) == 1 { - singleTable = allTables[0] + return singleTable +} + +func lookupAllTables(stmt sqlparser.Statement, tables map[string]*schema.Table) (allTables []*schema.Table) { + tablesUsed := sqlparser.ExtractAllTables(stmt) + for _, tbl := range tablesUsed { + if t := tables[tbl]; t != nil { + allTables = append(allTables, t) + } } - return singleTable, allTables + return allTables } func lookupSingleTable(tableExpr sqlparser.TableExpr, tables map[string]*schema.Table) *schema.Table { @@ -229,12 +235,14 @@ func analyzeFlush(stmt *sqlparser.Flush, tables map[string]*schema.Table) (*Plan for _, tbl := range stmt.TableNames { if schemaTbl, ok := tables[tbl.Name.String()]; ok { - plan.AllTables = append(plan.AllTables, schemaTbl) + if plan.Table != nil { + // If there are multiple tables, we empty out the table field. + plan.Table = nil + break + } + plan.Table = schemaTbl } } - if len(plan.AllTables) == 1 { - plan.Table = plan.AllTables[0] - } if stmt.WithLock { plan.NeedsReservedConn = true diff --git a/go/vt/vttablet/tabletserver/planbuilder/permission.go b/go/vt/vttablet/tabletserver/planbuilder/permission.go index 79b2f9eb430..dbc6cfccdad 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/permission.go +++ b/go/vt/vttablet/tabletserver/planbuilder/permission.go @@ -36,7 +36,13 @@ func BuildPermissions(stmt sqlparser.Statement) []Permission { var permissions []Permission // All Statement types myst be covered here. switch node := stmt.(type) { - case *sqlparser.Union, *sqlparser.Select: + case *sqlparser.Select: + role := tableacl.READER + if _, ok := node.SelectExprs[0].(*sqlparser.Nextval); ok { + role = tableacl.WRITER + } + permissions = buildSubqueryPermissions(node, role, permissions) + case *sqlparser.Union: permissions = buildSubqueryPermissions(node, tableacl.READER, permissions) case *sqlparser.Insert: permissions = buildTableExprPermissions(node.Table, tableacl.WRITER, permissions) diff --git a/go/vt/vttablet/tabletserver/planbuilder/permission_test.go b/go/vt/vttablet/tabletserver/planbuilder/permission_test.go index 6d42118cb0b..0ece6ed19b2 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/permission_test.go +++ b/go/vt/vttablet/tabletserver/planbuilder/permission_test.go @@ -174,6 +174,12 @@ func TestBuildPermissions(t *testing.T) { }, { TableName: "t1", // derived table in update or delete needs reader permission as they cannot be modified. }}, + }, { + input: "select next 10 values from seq", + output: []Permission{{ + TableName: "seq", + Role: tableacl.WRITER, + }}, }} for _, tcase := range tcases { diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index 7b1e57c2f90..f18ea59a714 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -157,7 +157,7 @@ type Plan struct { PlanID PlanType // When the query indicates a single table Table *schema.Table - // SELECT, UPDATE, DELETE statements may list multiple tables + // This indicates all the tables that are accessed in the query. AllTables []*schema.Table // Permissions stores the permissions for the tables accessed in the query. @@ -257,6 +257,7 @@ func Build(env *vtenv.Environment, statement sqlparser.Statement, tables map[str if err != nil { return nil, err } + plan.AllTables = lookupAllTables(statement, tables) plan.Permissions = BuildPermissions(statement) return plan, nil } @@ -274,14 +275,14 @@ func BuildStreaming(statement sqlparser.Statement, tables map[string]*schema.Tab if hasLockFunc(stmt) { plan.NeedsReservedConn = true } - plan.Table, plan.AllTables = lookupTables(stmt.From, tables) + plan.Table = lookupTables(stmt.From, tables) case *sqlparser.Show, *sqlparser.Union, *sqlparser.CallProc, sqlparser.Explain: case *sqlparser.Analyze: plan.PlanID = PlanOtherRead default: return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s not allowed for streaming", sqlparser.ASTToStatementType(statement)) } - + plan.AllTables = lookupAllTables(statement, tables) return plan, nil } diff --git a/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt b/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt index 977b3822050..cafbe43231d 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt +++ b/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt @@ -140,7 +140,7 @@ "Permissions": [ { "TableName": "seq", - "Role": 0 + "Role": 1 } ], "NextCount": "1" @@ -154,7 +154,7 @@ "Permissions": [ { "TableName": "seq", - "Role": 0 + "Role": 1 } ], "NextCount": "10" @@ -169,7 +169,7 @@ "Permissions": [ { "TableName": "seq", - "Role": 0 + "Role": 1 } ], "NextCount": ":a" @@ -183,7 +183,7 @@ "Permissions": [ { "TableName": "seq", - "Role": 0 + "Role": 1 } ], "NextCount": "12345667852342342342323423423" diff --git a/go/vt/vttablet/tabletserver/production.go b/go/vt/vttablet/tabletserver/production.go new file mode 100644 index 00000000000..70cb8b092fa --- /dev/null +++ b/go/vt/vttablet/tabletserver/production.go @@ -0,0 +1,30 @@ +//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 tabletserver + +// 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 + +func commitPreparedDelayForTest(tsv *TabletServer) {} diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index f8245ac8e2f..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 plan 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 plan 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 plan 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 plan 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 plan 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 plan 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..e89dee889dc 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()) } @@ -668,7 +670,6 @@ func (qre *QueryExecutor) execNextval() (*sqltypes.Result, error) { newLast += cache } query = fmt.Sprintf("update %s set next_id = %d where id = 0", sqlparser.String(tableName), newLast) - conn.TxProperties().RecordQuery(query) _, err = qre.execStatefulConn(conn, query, false) if err != nil { return nil, err @@ -805,7 +806,7 @@ func (qre *QueryExecutor) txFetch(conn *StatefulConnection, record bool) (*sqlty } // Only record successful queries. if record { - conn.TxProperties().RecordQuery(sql) + conn.TxProperties().RecordQueryDetail(sql, qre.plan.TableNames()) } return qr, nil } @@ -923,6 +924,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 +961,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..cc72c629ddb 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 { @@ -1533,9 +1532,6 @@ func newTestTabletServer(ctx context.Context, flags executorFlags, db *fakesqldb tsv := NewTabletServer(ctx, vtenv.NewTestEnv(), "TabletServerTest", cfg, memorytopo.NewServer(ctx, ""), &topodatapb.TabletAlias{}, srvTopoCounts) target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} err := tsv.StartService(target, dbconfigs, nil /* mysqld */) - if cfg.TwoPCEnable { - tsv.TwoPCEngineWait() - } if err != nil { panic(err) } @@ -1704,10 +1700,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/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index 5babed271ca..aadba5739c8 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -40,6 +40,7 @@ import ( "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/dbconnpool" "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/mysqlctl/tmutils" "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/servenv" @@ -85,9 +86,10 @@ type Engine struct { historian *historian - conns *connpool.Pool - ticks *timer.Timer - reloadTimeout time.Duration + conns *connpool.Pool + ticks *timer.Timer + reloadTimeout time.Duration + throttledLogger *logutil.ThrottledLogger // dbCreationFailed is for preventing log spam. dbCreationFailed bool @@ -109,7 +111,8 @@ func NewEngine(env tabletenv.Env) *Engine { Size: 3, IdleTimeout: env.Config().OltpReadPool.IdleTimeout, }), - ticks: timer.NewTimer(reloadTime), + ticks: timer.NewTimer(reloadTime), + throttledLogger: logutil.NewThrottledLogger("schema-tracker", 1*time.Minute), } se.schemaCopy = env.Config().SignalWhenSchemaChange _ = env.Exporter().NewGaugeDurationFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", se.ticks.Interval) @@ -448,7 +451,7 @@ func (se *Engine) reload(ctx context.Context, includeStats bool) error { udfsChanged, err := getChangedUserDefinedFunctions(ctx, conn.Conn, shouldUseDatabase) if err != nil { - return err + se.throttledLogger.Errorf("error in getting changed UDFs: %v", err) } rec := concurrency.AllErrorRecorder{} diff --git a/go/vt/vttablet/tabletserver/schema/engine_test.go b/go/vt/vttablet/tabletserver/schema/engine_test.go index d4271dee876..1fd6098b384 100644 --- a/go/vt/vttablet/tabletserver/schema/engine_test.go +++ b/go/vt/vttablet/tabletserver/schema/engine_test.go @@ -467,7 +467,7 @@ func TestOpenFailedDueToExecErr(t *testing.T) { defer db.Close() schematest.AddDefaultQueries(db) want := "injected error" - db.AddRejectedQuery(mysql.BaseShowTables, fmt.Errorf(want)) + db.AddRejectedQuery(mysql.BaseShowTables, errors.New(want)) se := newEngine(1*time.Second, 1*time.Second, 0, db) err := se.Open() if err == nil || !strings.Contains(err.Error(), want) { @@ -1331,7 +1331,8 @@ func TestEngineReload(t *testing.T) { } // adding query pattern for udfs - db.AddQueryPattern("SELECT name.*", &sqltypes.Result{}) + udfQueryPattern := "SELECT name.*" + db.AddQueryPattern(udfQueryPattern, &sqltypes.Result{}) // Verify the list of created, altered and dropped tables seen. se.RegisterNotifier("test", func(full map[string]*Table, created, altered, dropped []*Table, _ bool) { @@ -1344,6 +1345,16 @@ func TestEngineReload(t *testing.T) { err = se.reload(context.Background(), false) require.NoError(t, err) require.NoError(t, db.LastError()) + require.Zero(t, se.throttledLogger.GetLastLogTime()) + + // Now if we remove the query pattern for udfs, schema engine shouldn't fail. + // Instead we should see a log message with the error. + db.RemoveQueryPattern(udfQueryPattern) + se.UnregisterNotifier("test") + err = se.reload(context.Background(), false) + require.NoError(t, err) + // Check for the udf error being logged. The last log time should be less than a second. + require.Less(t, time.Since(se.throttledLogger.GetLastLogTime()), 1*time.Second) } // TestEngineReload tests the vreplication specific GetTableForPos function to ensure diff --git a/go/vt/vttablet/tabletserver/schema/tracker.go b/go/vt/vttablet/tabletserver/schema/tracker.go index 8db202efa13..252a81f3493 100644 --- a/go/vt/vttablet/tabletserver/schema/tracker.go +++ b/go/vt/vttablet/tabletserver/schema/tracker.go @@ -39,7 +39,8 @@ import ( // VStreamer defines the functions of VStreamer // that the replicationWatcher needs. type VStreamer interface { - Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error + Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, + throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error } // Tracker watches the replication and saves the latest schema into the schema_version table when a DDL is encountered. @@ -144,7 +145,7 @@ func (tr *Tracker) process(ctx context.Context) { } } return nil - }) + }, nil) select { case <-ctx.Done(): return diff --git a/go/vt/vttablet/tabletserver/schema/tracker_test.go b/go/vt/vttablet/tabletserver/schema/tracker_test.go index 32f68597779..0e7444b39b9 100644 --- a/go/vt/vttablet/tabletserver/schema/tracker_test.go +++ b/go/vt/vttablet/tabletserver/schema/tracker_test.go @@ -139,7 +139,8 @@ type fakeVstreamer struct { events [][]*binlogdatapb.VEvent } -func (f *fakeVstreamer) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error { +func (f *fakeVstreamer) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error { for _, events := range f.events { err := send(events) if err != nil { diff --git a/go/vt/vttablet/tabletserver/state_manager.go b/go/vt/vttablet/tabletserver/state_manager.go index 308f9165ba6..3fe78457b60 100644 --- a/go/vt/vttablet/tabletserver/state_manager.go +++ b/go/vt/vttablet/tabletserver/state_manager.go @@ -164,6 +164,7 @@ type ( AcceptReadWrite() AcceptReadOnly() Close() + RollbackPrepared() } subComponent interface { @@ -610,6 +611,12 @@ func (sm *stateManager) terminateAllQueries(wg *sync.WaitGroup) (cancel func()) log.Infof("Killed all stateless OLTP queries.") sm.statefulql.TerminateAll() log.Infof("Killed all OLTP queries.") + // We can rollback prepared transactions only after we have killed all the write queries in progress. + // This is essential because when we rollback a prepared transaction, it lets go of the locks it was holding. + // If there were some other conflicting write in progress that hadn't been killed, then it could potentially go through + // and cause data corruption since we won't be able to prepare the transaction again. + sm.te.RollbackPrepared() + log.Infof("Rollbacked all prepared transactions") }() return cancel } diff --git a/go/vt/vttablet/tabletserver/state_manager_test.go b/go/vt/vttablet/tabletserver/state_manager_test.go index 02896eeefe0..f70e77de710 100644 --- a/go/vt/vttablet/tabletserver/state_manager_test.go +++ b/go/vt/vttablet/tabletserver/state_manager_test.go @@ -379,6 +379,9 @@ func (te *delayedTxEngine) Close() { time.Sleep(50 * time.Millisecond) } +func (te *delayedTxEngine) RollbackPrepared() { +} + type killableConn struct { id int64 killed atomic.Bool @@ -903,6 +906,8 @@ func (te *testTxEngine) Close() { te.state = testStateClosed } +func (te *testTxEngine) RollbackPrepared() {} + type testSubcomponent struct { testOrderState } diff --git a/go/vt/vttablet/tabletserver/stateful_connection.go b/go/vt/vttablet/tabletserver/stateful_connection.go index 067f2194655..91d51677241 100644 --- a/go/vt/vttablet/tabletserver/stateful_connection.go +++ b/go/vt/vttablet/tabletserver/stateful_connection.go @@ -150,7 +150,7 @@ func (sc *StatefulConnection) unlock(updateTime bool) { return } if sc.dbConn.Conn.IsClosed() { - sc.Releasef("unlocked closed connection") + sc.ReleaseString("unlocked closed connection") } else { sc.pool.markAsNotInUse(sc, updateTime) } @@ -159,16 +159,24 @@ func (sc *StatefulConnection) unlock(updateTime bool) { // Release is used when the connection will not be used ever again. // The underlying dbConn is removed so that this connection cannot be used by mistake. func (sc *StatefulConnection) Release(reason tx.ReleaseReason) { - sc.Releasef(reason.String()) + sc.ReleaseString(reason.String()) } // Releasef is used when the connection will not be used ever again. // The underlying dbConn is removed so that this connection cannot be used by mistake. func (sc *StatefulConnection) Releasef(reasonFormat string, a ...any) { + sc.ReleaseString(fmt.Sprintf(reasonFormat, a...)) +} + +// ReleaseString is used when the connection will not be used ever again. +// The underlying dbConn is removed so that this connection cannot be used by mistake. +func (sc *StatefulConnection) ReleaseString(reason string) { if sc.dbConn == nil { return } - sc.pool.unregister(sc.ConnID, fmt.Sprintf(reasonFormat, a...)) + if sc.pool != nil { + sc.pool.unregister(sc.ConnID, reason) + } sc.dbConn.Recycle() sc.dbConn = nil sc.logReservedConn() @@ -264,7 +272,7 @@ func (sc *StatefulConnection) IsTainted() bool { // LogTransaction logs transaction related stats func (sc *StatefulConnection) LogTransaction(reason tx.ReleaseReason) { if sc.txProps == nil { - return //Nothing to log as no transaction exists on this connection. + return // Nothing to log as no transaction exists on this connection. } sc.txProps.Conclusion = reason.Name() sc.txProps.EndTime = time.Now() @@ -288,7 +296,7 @@ func (sc *StatefulConnection) SetTimeout(timeout time.Duration) { // logReservedConn logs reserved connection related stats. func (sc *StatefulConnection) logReservedConn() { if sc.reservedProps == nil { - return //Nothing to log as this connection is not reserved. + return // Nothing to log as this connection is not reserved. } duration := time.Since(sc.reservedProps.StartTime) username := sc.getUsername() @@ -315,3 +323,8 @@ func (sc *StatefulConnection) ApplySetting(ctx context.Context, setting *smartco func (sc *StatefulConnection) resetExpiryTime() { sc.expiryTime = time.Now().Add(sc.timeout) } + +// IsUnixSocket returns true if the connection is using a unix socket +func (sc *StatefulConnection) IsUnixSocket() bool { + return sc.dbConn.Conn.IsUnixSocket() +} diff --git a/go/vt/vttablet/tabletserver/stateful_connection_pool.go b/go/vt/vttablet/tabletserver/stateful_connection_pool.go index 64268825b70..88fbc56fd0c 100644 --- a/go/vt/vttablet/tabletserver/stateful_connection_pool.go +++ b/go/vt/vttablet/tabletserver/stateful_connection_pool.go @@ -96,7 +96,7 @@ func (sf *StatefulConnectionPool) Close() { log.Warningf("killing %s for shutdown: %s", thing, conn.String(sf.env.Config().SanitizeLogMessages, sf.env.Environment().Parser())) sf.env.Stats().InternalErrors.Add("StrayTransactions", 1) conn.Close() - conn.Releasef("pool closed") + conn.ReleaseString("pool closed") } sf.conns.Close() sf.foundRowsPool.Close() @@ -111,7 +111,7 @@ func (sf *StatefulConnectionPool) ShutdownNonTx() { return !sc.(*StatefulConnection).IsInTransaction() })) for _, sc := range conns { - sc.Releasef("kill non-tx") + sc.ReleaseString("kill non-tx") } } @@ -231,14 +231,14 @@ func (sf *StatefulConnectionPool) markAsNotInUse(sc *StatefulConnection, updateT switch sf.state.Load() { case scpKillingNonTx: if !sc.IsInTransaction() { - sc.Releasef("kill non-tx") + sc.ReleaseString("kill non-tx") return } case scpKillingAll: if sc.IsInTransaction() { sc.Close() } - sc.Releasef("kill all") + sc.ReleaseString("kill all") return } if updateTime { diff --git a/go/vt/vttablet/tabletserver/tabletenv/config.go b/go/vt/vttablet/tabletserver/tabletenv/config.go index 89f827fa1f3..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.") @@ -332,13 +331,12 @@ type TabletConfig struct { 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:"-"` @@ -406,8 +404,6 @@ func (cfg *TabletConfig) UnmarshalJSON(data []byte) (err error) { if err != nil { return err } - } else { - cfg.SchemaReloadInterval = 0 } if tmp.SchemaChangeReloadTimeout != "" { @@ -415,8 +411,6 @@ func (cfg *TabletConfig) UnmarshalJSON(data []byte) (err error) { if err != nil { return err } - } else { - cfg.SchemaChangeReloadTimeout = 0 } return nil 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 2238195c97d..840d5920a4d 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -44,6 +44,11 @@ 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" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + 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 +67,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,11 +182,11 @@ 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) - tsv.onlineDDLExecutor = onlineddl.NewExecutor(tsv, alias, topoServer, tsv.lagThrottler, tabletTypeFunc, tsv.onlineDDLExecutorToggleTableBuffer, tsv.tableGC.RequestChecks) + tsv.onlineDDLExecutor = onlineddl.NewExecutor(tsv, alias, topoServer, tsv.lagThrottler, tabletTypeFunc, tsv.onlineDDLExecutorToggleTableBuffer, tsv.tableGC.RequestChecks, tsv.te.preparedPool.IsEmpty) tsv.sm = &stateManager{ statelessql: tsv.statelessql, @@ -475,11 +476,6 @@ func (tsv *TabletServer) TableGC() *gc.TableGC { return tsv.tableGC } -// TwoPCEngineWait waits until the TwoPC engine has been opened, and the redo read -func (tsv *TabletServer) TwoPCEngineWait() { - tsv.te.twoPCReady.Wait() -} - // SchemaEngine returns the SchemaEngine part of TabletServer. func (tsv *TabletServer) SchemaEngine() *schema.Engine { return tsv.se @@ -645,7 +641,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.Prepare(transactionID, dtid) }, ) @@ -658,7 +654,10 @@ 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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) + if DebugTwoPc { + commitPreparedDelayForTest(tsv) + } return txe.CommitPrepared(dtid) }, ) @@ -671,7 +670,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.RollbackPrepared(dtid, originalID) }, ) @@ -684,7 +683,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.CreateTransaction(dtid, participants) }, ) @@ -698,7 +697,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.StartCommit(transactionID, dtid) }, ) @@ -712,7 +711,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.SetRollback(dtid, transactionID) }, ) @@ -726,7 +725,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) return txe.ConcludeTransaction(dtid) }, ) @@ -739,7 +738,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 := NewDTExecutor(ctx, tsv.te, logStats) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, logStats) metadata, err = txe.ReadTransaction(dtid) return err }, @@ -747,6 +746,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, tsv.qe, 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") @@ -1152,7 +1166,7 @@ func (tsv *TabletServer) VStream(ctx context.Context, request *binlogdatapb.VStr if err := tsv.sm.VerifyTarget(ctx, request.Target); err != nil { return err } - return tsv.vstreamer.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send) + return tsv.vstreamer.Stream(ctx, request.Position, request.TableLastPKs, request.Filter, throttlerapp.VStreamerName, send, request.Options) } // VStreamRows streams rows from the specified starting point. @@ -1663,10 +1677,26 @@ 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 +} + +// RedoPreparedTransactions redoes the prepared transactions. +func (tsv *TabletServer) RedoPreparedTransactions() { + tsv.te.RedoPreparedTransactions() +} + +// SetTwoPCAllowed sets whether TwoPC is allowed or not. +func (tsv *TabletServer) SetTwoPCAllowed(allowed bool) { + tsv.te.twopcAllowed = allowed +} + // HandlePanic is part of the queryservice.QueryService interface func (tsv *TabletServer) HandlePanic(err *error) { if x := recover(); x != nil { @@ -1746,7 +1776,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 := NewDTExecutor(ctx, tsv.te, tabletenv.NewLogStats(ctx, "twopcz")) + txe := NewDTExecutor(ctx, tsv.te, tsv.qe, tabletenv.NewLogStats(ctx, "twopcz")) twopczHandler(txe, w, r) }) } @@ -1765,24 +1795,23 @@ 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) - if checkResult.StatusCode == http.StatusNotFound && flags.OKIfNotExists { + metricNames := tsv.lagThrottler.MetricNames(r.URL.Query()["m"]) + checkResult := tsv.lagThrottler.Check(ctx, appName, metricNames, flags) + if checkResult.ResponseCode == tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC && flags.OKIfNotExists { checkResult.StatusCode = http.StatusOK // 200 + checkResult.ResponseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_OK } if r.Method == http.MethodGet { @@ -1794,8 +1823,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 563ab5e84b3..e70b575f464 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -36,6 +36,7 @@ import ( "vitess.io/vitess/go/vt/callerid" "vitess.io/vitess/go/vt/sidecardb" "vitess.io/vitess/go/vt/vtenv" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/test/utils" @@ -154,9 +155,10 @@ func TestTabletServerPrimaryToReplica(t *testing.T) { // Reuse code from tx_executor_test. _, tsv, db := newTestTxExecutor(t, ctx) // This is required because the test is verifying that we rollback transactions on changing serving type, - // but that only happens immediately if the shut down grace period is not specified. - tsv.te.shutdownGracePeriod = 0 - tsv.sm.shutdownGracePeriod = 0 + // but that only happens when we have a shutdown grace period, otherwise we wait for transactions to be resolved + // indefinitely. + tsv.te.shutdownGracePeriod = 1 + tsv.sm.shutdownGracePeriod = 1 defer tsv.StopService() defer db.Close() target := querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} @@ -200,14 +202,20 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { _, tsv, db := newTestTxExecutor(t, ctx) defer tsv.StopService() defer db.Close() - tsv.SetServingType(topodatapb.TabletType_REPLICA, time.Time{}, true, "") + // This is required because the test is verifying that we rollback transactions on changing serving type, + // but that only happens when we have a shutdown grace period, otherwise we wait for transactions to be resolved + // indefinitely. + tsv.te.shutdownGracePeriod = 1 + tsv.sm.shutdownGracePeriod = 1 + tsv.SetServingType(topodatapb.TabletType_PRIMARY, time.Time{}, false, "") turnOnTxEngine := func() { tsv.SetServingType(topodatapb.TabletType_PRIMARY, time.Time{}, true, "") - tsv.TwoPCEngineWait() } turnOffTxEngine := func() { - tsv.SetServingType(topodatapb.TabletType_REPLICA, time.Time{}, true, "") + // We can use a transition to PRIMARY non-serving or REPLICA serving to turn off the transaction engine. + // With primary serving, the shutdown of prepared transactions is synchronous, but for the latter its asynchronous. + tsv.SetServingType(topodatapb.TabletType_PRIMARY, time.Time{}, false, "") } tpc := tsv.te.twoPC @@ -234,7 +242,9 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { turnOnTxEngine() assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") got := tsv.te.preparedPool.conns["dtid0"].TxProperties().Queries - want := []string{"update test_table set `name` = 2 where pk = 1 limit 10001"} + want := []tx.Query{{ + Sql: "update test_table set `name` = 2 where pk = 1 limit 10001", + Tables: []string{"test_table"}}} utils.MustMatch(t, want, got, "Prepared queries") turnOffTxEngine() assert.Empty(t, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") @@ -268,7 +278,9 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { turnOnTxEngine() assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") got = tsv.te.preparedPool.conns["a:b:10"].TxProperties().Queries - want = []string{"update test_table set `name` = 2 where pk = 1 limit 10001"} + want = []tx.Query{{ + Sql: "update test_table set `name` = 2 where pk = 1 limit 10001", + Tables: []string{"test_table"}}} utils.MustMatch(t, want, got, "Prepared queries") wantFailed := map[string]error{"a:b:20": errPrepFailed} utils.MustMatch(t, tsv.te.preparedPool.reserved, wantFailed, fmt.Sprintf("Failed dtids: %v, want %v", tsv.te.preparedPool.reserved, wantFailed)) @@ -2745,10 +2757,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/base/throttle_metric_app.go b/go/vt/vttablet/tabletserver/throttle/base/inventory.go similarity index 81% rename from go/vt/vttablet/tabletserver/throttle/base/throttle_metric_app.go rename to go/vt/vttablet/tabletserver/throttle/base/inventory.go index 482f319365f..5294caf1115 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_app.go +++ b/go/vt/vttablet/tabletserver/throttle/base/inventory.go @@ -41,19 +41,18 @@ limitations under the License. package base -import ( - "errors" -) - -// ErrAppDenied is seen when an app is denied access -var ErrAppDenied = errors.New("App denied") - -type appDeniedMetric struct{} - -// Get implements MetricResult -func (metricResult *appDeniedMetric) Get() (float64, error) { - return 0, ErrAppDenied +// Inventory has the operational data about probes, their metrics, and relevant configuration +type Inventory struct { + ClustersProbes Probes + IgnoreHostsCount int + IgnoreHostsThreshold float64 + TabletMetrics TabletResultMap } -// AppDeniedMetric is a special metric indicating a "denied" situation -var AppDeniedMetric = &appDeniedMetric{} +// 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/mysql_throttle_metric.go b/go/vt/vttablet/tabletserver/throttle/base/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/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/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/metric_name.go b/go/vt/vttablet/tabletserver/throttle/base/metric_name.go new file mode 100644 index 00000000000..98e1288fb23 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/metric_name.go @@ -0,0 +1,128 @@ +/* +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 base + +import ( + "fmt" + "slices" + "strings" +) + +// 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 { + if selfMetric := RegisteredSelfMetrics[metric]; selfMetric != nil { + return selfMetric.DefaultScope() + } + 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()) +} + +type AggregatedMetricName struct { + Scope Scope + Metric MetricName +} + +var ( + KnownMetricNames = make(MetricNames, 0) + // 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 = make(map[string]AggregatedMetricName) +) + +// 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 +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/metric_name_test.go b/go/vt/vttablet/tabletserver/throttle/base/metric_name_test.go new file mode 100644 index 00000000000..9867ca18db3 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/metric_name_test.go @@ -0,0 +1,241 @@ +/* +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)) + }) + } +} + +func TestKnownMetricNames(t *testing.T) { + assert.NotEmpty(t, KnownMetricNames) + assert.Contains(t, KnownMetricNames, LagMetricName) + assert.Contains(t, KnownMetricNames, ThreadsRunningMetricName) + assert.Contains(t, KnownMetricNames, LoadAvgMetricName) + assert.Contains(t, KnownMetricNames, CustomMetricName) + assert.Contains(t, KnownMetricNames, DefaultMetricName) +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go b/go/vt/vttablet/tabletserver/throttle/base/metric_result.go similarity index 59% rename from go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go rename to go/vt/vttablet/tabletserver/throttle/base/metric_result.go index 3d4c4f95a2e..0fa48fe3240 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go +++ b/go/vt/vttablet/tabletserver/throttle/base/metric_result.go @@ -1,5 +1,5 @@ /* -Copyright 2023 The Vitess Authors. +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. @@ -14,36 +14,11 @@ 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" - "strings" + "net" ) // MetricResult is what we expect our probes to return. This can be a numeric result, or @@ -55,22 +30,39 @@ 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") + +// ErrAppDenied is seen when an app is denied access +var ErrAppDenied = errors.New("app denied") // 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 { - if e == nil { +func IsDialTCPError(err error) bool { + if err == nil { return false } - return strings.HasPrefix(e.Error(), "dial tcp") + switch err := err.(type) { + case *net.OpError: + return err.Op == "dial" && err.Net == "tcp" + } + return false } type noHostsMetricResult struct{} @@ -87,7 +79,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" @@ -117,3 +109,13 @@ func NewSimpleMetricResult(value float64) MetricResult { func (metricResult *simpleMetricResult) Get() (float64, error) { return metricResult.Value, nil } + +type appDeniedMetric struct{} + +// Get implements MetricResult +func (metricResult *appDeniedMetric) Get() (float64, error) { + return 0, ErrAppDenied +} + +// AppDeniedMetric is a special metric indicating a "denied" situation +var AppDeniedMetric = &appDeniedMetric{} diff --git a/go/vt/vttablet/tabletserver/throttle/base/metric_scope.go b/go/vt/vttablet/tabletserver/throttle/base/metric_scope.go new file mode 100644 index 00000000000..60d116861c3 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/metric_scope.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 +limitations under the License. +*/ + +package base + +import ( + "fmt" +) + +// 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) + } +} 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..7ae2bf789af 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/recent_app.go +++ b/go/vt/vttablet/tabletserver/throttle/base/recent_app.go @@ -42,19 +42,25 @@ package base import ( "time" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" ) // RecentApp indicates when an app was last checked type RecentApp struct { - CheckedAtEpoch int64 - MinutesSinceChecked int64 + AppName string + CheckedAt time.Time + StatusCode int + ResponseCode tabletmanagerdatapb.CheckThrottlerResponseCode } // NewRecentApp creates a RecentApp -func NewRecentApp(checkedAt time.Time) *RecentApp { +func NewRecentApp(appName string, statusCode int, responseCode tabletmanagerdatapb.CheckThrottlerResponseCode) *RecentApp { result := &RecentApp{ - CheckedAtEpoch: checkedAt.Unix(), - MinutesSinceChecked: int64(time.Since(checkedAt).Minutes()), + AppName: appName, + CheckedAt: time.Now(), + StatusCode: statusCode, + ResponseCode: responseCode, } return result } diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric.go new file mode 100644 index 00000000000..220dfa6bf60 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric.go @@ -0,0 +1,91 @@ +/* +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 ( + "context" + "fmt" + "strconv" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +type SelfMetric interface { + Name() MetricName + DefaultScope() Scope + DefaultThreshold() float64 + RequiresConn() bool + Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric +} + +var ( + RegisteredSelfMetrics = make(map[MetricName]SelfMetric) +) + +func registerSelfMetric(selfMetric SelfMetric) SelfMetric { + RegisteredSelfMetrics[selfMetric.Name()] = selfMetric + KnownMetricNames = append(KnownMetricNames, selfMetric.Name()) + aggregatedMetricNames[selfMetric.Name().String()] = AggregatedMetricName{ + Scope: selfMetric.DefaultScope(), + Metric: selfMetric.Name(), + } + for _, scope := range []Scope{ShardScope, SelfScope} { + aggregatedName := selfMetric.Name().AggregatedName(scope) + aggregatedMetricNames[aggregatedName] = AggregatedMetricName{ + Scope: scope, + Metric: selfMetric.Name(), + } + } + return selfMetric +} + +// ReadSelfMySQLThrottleMetric reads a metric using a given MySQL connection and a query. +func ReadSelfMySQLThrottleMetric(ctx context.Context, conn *connpool.Conn, query string) *ThrottleMetric { + metric := &ThrottleMetric{ + Scope: SelfScope, + } + if query == "" { + return metric + } + if conn == nil { + return metric.WithError(fmt.Errorf("conn is nil")) + } + + tm, err := conn.Exec(ctx, query, 1, true) + if err != nil { + return metric.WithError(err) + } + if len(tm.Rows) == 0 { + return metric.WithError(fmt.Errorf("no results in ReadSelfMySQLThrottleMetric for query %s", query)) + } + if len(tm.Rows) > 1 { + return metric.WithError(fmt.Errorf("expecting single row in ReadSelfMySQLThrottleMetric for query %s", query)) + } + + metricsQueryType := GetMetricsQueryType(query) + switch metricsQueryType { + case MetricsQueryTypeSelect: + metric.Value, metric.Err = tm.Rows[0][0].ToFloat64() + case MetricsQueryTypeShowGlobal: + // Columns are [Variable_name, Value] + metric.Value, metric.Err = strconv.ParseFloat(tm.Rows[0][1].ToString(), 64) + default: + metric.Err = fmt.Errorf("unsupported metrics query type for query: %s", query) + } + + return metric +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_custom_query.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_custom_query.go new file mode 100644 index 00000000000..585e63ea285 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_custom_query.go @@ -0,0 +1,48 @@ +/* +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 ( + "context" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +var _ SelfMetric = registerSelfMetric(&CustomQuerySelfMetric{}) + +type CustomQuerySelfMetric struct { +} + +func (m *CustomQuerySelfMetric) Name() MetricName { + return CustomMetricName +} + +func (m *CustomQuerySelfMetric) DefaultScope() Scope { + return SelfScope +} + +func (m *CustomQuerySelfMetric) DefaultThreshold() float64 { + return 0 +} + +func (m *CustomQuerySelfMetric) RequiresConn() bool { + return true +} + +func (m *CustomQuerySelfMetric) Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric { + return ReadSelfMySQLThrottleMetric(ctx, conn, throttler.GetCustomMetricsQuery()) +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_default.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_default.go new file mode 100644 index 00000000000..8bce295da7c --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_default.go @@ -0,0 +1,51 @@ +/* +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 ( + "context" + "fmt" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +var _ SelfMetric = registerSelfMetric(&DefaultSelfMetric{}) + +type DefaultSelfMetric struct { +} + +func (m *DefaultSelfMetric) Name() MetricName { + return DefaultMetricName +} + +func (m *DefaultSelfMetric) DefaultScope() Scope { + return SelfScope +} + +func (m *DefaultSelfMetric) DefaultThreshold() float64 { + return 0 +} + +func (m *DefaultSelfMetric) RequiresConn() bool { + return false +} + +func (m *DefaultSelfMetric) Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric { + return &ThrottleMetric{ + Err: fmt.Errorf("unexpected direct call to DefaultSelfMetric.Read"), + } +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_lag.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_lag.go new file mode 100644 index 00000000000..dc25ee5622a --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_lag.go @@ -0,0 +1,70 @@ +/* +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 ( + "context" + "sync/atomic" + "time" + + "vitess.io/vitess/go/constants/sidecar" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +var ( + lagSelfMetricQueryBase = "select unix_timestamp(now(6))-max(ts/1000000000) as replication_lag from %s.heartbeat" + lagSelfDefaultThreshold = 5 * time.Second +) + +var _ SelfMetric = registerSelfMetric(&LagSelfMetric{}) + +type LagSelfMetric struct { + lagSelfMetricQuery atomic.Value +} + +// SetQuery is only used by unit tests to override the query. +func (m *LagSelfMetric) SetQuery(query string) { + m.lagSelfMetricQuery.Store(query) +} + +func (m *LagSelfMetric) GetQuery() string { + if query := m.lagSelfMetricQuery.Load(); query == nil { + m.lagSelfMetricQuery.Store(sqlparser.BuildParsedQuery(lagSelfMetricQueryBase, sidecar.GetIdentifier()).Query) + } + return m.lagSelfMetricQuery.Load().(string) +} + +func (m *LagSelfMetric) Name() MetricName { + return LagMetricName +} + +func (m *LagSelfMetric) DefaultScope() Scope { + return ShardScope +} + +func (m *LagSelfMetric) DefaultThreshold() float64 { + return lagSelfDefaultThreshold.Seconds() +} + +func (m *LagSelfMetric) RequiresConn() bool { + return true +} + +func (m *LagSelfMetric) Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric { + return ReadSelfMySQLThrottleMetric(ctx, conn, m.GetQuery()) +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_loadavg.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_loadavg.go new file mode 100644 index 00000000000..40a2878421a --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_loadavg.go @@ -0,0 +1,81 @@ +/* +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 ( + "context" + "fmt" + "os" + "runtime" + "strconv" + "strings" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +var ( + loadavgOnlyAvailableOnLinuxMetric = &ThrottleMetric{ + Scope: SelfScope, + Err: fmt.Errorf("loadavg metric is only available on Linux"), + } +) + +var _ SelfMetric = registerSelfMetric(&LoadAvgSelfMetric{}) + +type LoadAvgSelfMetric struct { +} + +func (m *LoadAvgSelfMetric) Name() MetricName { + return LoadAvgMetricName +} + +func (m *LoadAvgSelfMetric) DefaultScope() Scope { + return SelfScope +} + +func (m *LoadAvgSelfMetric) DefaultThreshold() float64 { + return 1.0 +} + +func (m *LoadAvgSelfMetric) RequiresConn() bool { + return false +} + +func (m *LoadAvgSelfMetric) Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric { + if runtime.GOOS != "linux" { + return loadavgOnlyAvailableOnLinuxMetric + } + metric := &ThrottleMetric{ + Scope: SelfScope, + } + { + 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(runtime.NumCPU()) + } + return metric +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_threads_running.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_threads_running.go new file mode 100644 index 00000000000..08f7d408d1c --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_threads_running.go @@ -0,0 +1,52 @@ +/* +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 ( + "context" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" +) + +var ( + threadsRunningMetricQuery = "show global status like 'threads_running'" +) + +var _ SelfMetric = registerSelfMetric(&ThreadsRunningSelfMetric{}) + +type ThreadsRunningSelfMetric struct { +} + +func (m *ThreadsRunningSelfMetric) Name() MetricName { + return ThreadsRunningMetricName +} + +func (m *ThreadsRunningSelfMetric) DefaultScope() Scope { + return SelfScope +} + +func (m *ThreadsRunningSelfMetric) DefaultThreshold() float64 { + return 100 +} + +func (m *ThreadsRunningSelfMetric) RequiresConn() bool { + return true +} + +func (m *ThreadsRunningSelfMetric) Read(ctx context.Context, throttler ThrottlerMetricsPublisher, conn *connpool.Conn) *ThrottleMetric { + return ReadSelfMySQLThrottleMetric(ctx, conn, threadsRunningMetricQuery) +} 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/throttler_metrics_publisher.go b/go/vt/vttablet/tabletserver/throttle/base/throttler_metrics_publisher.go new file mode 100644 index 00000000000..1d2d4d0652c --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/throttler_metrics_publisher.go @@ -0,0 +1,23 @@ +/* +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 + +// ThrottlerMetricsPublisher is implemented by throttler.Throttler and is used by SelfMetric +// implementations to query the throttler. +type ThrottlerMetricsPublisher interface { + GetCustomMetricsQuery() string +} diff --git a/go/vt/vttablet/tabletserver/throttle/check.go b/go/vt/vttablet/tabletserver/throttle/check.go index c15d8963d05..ccdfcb2ce23 100644 --- a/go/vt/vttablet/tabletserver/throttle/check.go +++ b/go/vt/vttablet/tabletserver/throttle/check.go @@ -45,13 +45,14 @@ import ( "context" "fmt" "net/http" - "strings" "time" "vitess.io/vitess/go/stats" "vitess.io/vitess/go/textutil" "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" ) const ( @@ -65,14 +66,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,109 +92,176 @@ 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 // - metricResult, threshold := check.throttler.AppRequestMetricResult(ctx, appName, metricResultFunc, denyApp) + metricResult, threshold, matchedApp := check.throttler.AppRequestMetricResult(ctx, appName, metricResultFunc, denyApp) if flags.OverrideThreshold > 0 { threshold = flags.OverrideThreshold } value, err := metricResult.Get() if appName == "" { - return NewCheckResult(http.StatusExpectationFailed, value, threshold, fmt.Errorf("no app indicated")) + return NewCheckResult(tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED, http.StatusExpectationFailed, value, threshold, "", fmt.Errorf("no app indicated")) } var statusCode int + var responseCode tabletmanagerdatapb.CheckThrottlerResponseCode switch { case err == base.ErrAppDenied: // app specifically not allowed to get metrics statusCode = http.StatusExpectationFailed // 417 + responseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED case err == base.ErrNoSuchMetric: // not collected yet, or metric does not exist statusCode = http.StatusNotFound // 404 + responseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC case err != nil: // any error statusCode = http.StatusInternalServerError // 500 + responseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_INTERNAL_ERROR case value > threshold: // casual throttling statusCode = http.StatusTooManyRequests // 429 + responseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED err = base.ErrThresholdExceeded default: // all good! statusCode = http.StatusOK // 200 + responseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_OK } - return NewCheckResult(statusCode, value, threshold, err) + return NewCheckResult(responseCode, statusCode, value, threshold, matchedApp, err) } // 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, + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + 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(metricName base.MetricName, metric *MetricResult) { + checkResult.StatusCode = metric.StatusCode + checkResult.ResponseCode = metric.ResponseCode + checkResult.Value = metric.Value + checkResult.Threshold = metric.Threshold + checkResult.Error = metric.Error + checkResult.Message = metric.Message + checkResult.AppName = metric.AppName + checkResult.Scope = metric.Scope + checkResult.MetricName = metricName.String() } + 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(metricCheckResult *CheckResult) { + 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 !metricCheckResult.IsOK() { + stats.GetOrNewCounter(fmt.Sprintf("ThrottlerCheck%s%sError", textutil.SingleWordCamel(metricScope.String()), textutil.SingleWordCamel(metricName.String())), "").Add(1) + } + }(metricCheckResult) + } + if metricCheckResult.RecentlyChecked { + checkResult.RecentlyChecked = true + } + metric := &MetricResult{ + StatusCode: metricCheckResult.StatusCode, + ResponseCode: metricCheckResult.ResponseCode, + Value: metricCheckResult.Value, + Threshold: metricCheckResult.Threshold, + Error: metricCheckResult.Error, + Message: metricCheckResult.Message, + AppName: metricCheckResult.AppName, + 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(metricName, 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 + metricNameUsedAsDefault := check.throttler.metricNameUsedAsDefault() + if metric, ok := checkResult.Metrics[metricNameUsedAsDefault.String()]; ok && checkResult.IsOK() { + applyMetricToCheckResult(metricNameUsedAsDefault, 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(base.DefaultMetricName, metric) + } + go func(checkResult *CheckResult) { + statsThrottlerCheckAnyTotal.Add(1) + if !checkResult.IsOK() { + statsThrottlerCheckAnyError.Add(1) + } + }(checkResult) + go check.throttler.markRecentApp(appName, checkResult.StatusCode, checkResult.ResponseCode) + 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) + if checkResult.IsOK() { + 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 +270,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 +281,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..34532b7ce37 100644 --- a/go/vt/vttablet/tabletserver/throttle/check_result.go +++ b/go/vt/vttablet/tabletserver/throttle/check_result.go @@ -42,28 +42,78 @@ limitations under the License. package throttle import ( + "fmt" "net/http" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" ) +// ResponseCodeFromStatus returns a ResponseCode based on either given response code or HTTP status code. +// It is used to handle the transition period from v20 to v21 where v20 only returns HTTP status code. +// In v22 and beyond, the HTTP status code will be removed, and so will this function. +func ResponseCodeFromStatus(responseCode tabletmanagerdatapb.CheckThrottlerResponseCode, statusCode int) tabletmanagerdatapb.CheckThrottlerResponseCode { + if responseCode != tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED { + return responseCode + } + switch statusCode { + case http.StatusOK: + return tabletmanagerdatapb.CheckThrottlerResponseCode_OK + case http.StatusExpectationFailed: + return tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED + case http.StatusTooManyRequests: + return tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED + case http.StatusNotFound: + return tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC + case http.StatusInternalServerError: + return tabletmanagerdatapb.CheckThrottlerResponseCode_INTERNAL_ERROR + default: + return tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED + } +} + +type MetricResult struct { + ResponseCode tabletmanagerdatapb.CheckThrottlerResponseCode `json:"ResponseCode"` + StatusCode int `json:"StatusCode"` + Scope string `json:"Scope"` + Value float64 `json:"Value"` + Threshold float64 `json:"Threshold"` + Error error `json:"-"` + Message string `json:"Message"` + AppName string `json:"AppName"` +} + +func (m *MetricResult) IsOK() bool { + if m.ResponseCode != tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED { + return m.ResponseCode == tabletmanagerdatapb.CheckThrottlerResponseCode_OK + } + return m.StatusCode == http.StatusOK +} + // 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"` + ResponseCode tabletmanagerdatapb.CheckThrottlerResponseCode `json:"ResponseCode"` + StatusCode int `json:"StatusCode"` + Value float64 `json:"Value"` + Threshold float64 `json:"Threshold"` + Error error `json:"-"` + Message string `json:"Message"` + RecentlyChecked bool `json:"RecentlyChecked"` + AppName string `json:"AppName"` + MetricName string `json:"MetricName"` + Scope string `json:"Scope"` + Metrics map[string]*MetricResult `json:"Metrics"` // New in multi-metrics support. Will eventually replace the above fields. } // NewCheckResult returns a CheckResult -func NewCheckResult(statusCode int, value float64, threshold float64, err error) *CheckResult { +func NewCheckResult(responseCode tabletmanagerdatapb.CheckThrottlerResponseCode, statusCode int, value float64, threshold float64, appName string, err error) *CheckResult { result := &CheckResult{ - StatusCode: statusCode, - Value: value, - Threshold: threshold, - Error: err, + ResponseCode: responseCode, + StatusCode: statusCode, + Value: value, + Threshold: threshold, + AppName: appName, + Error: err, } if err != nil { result.Message = err.Error() @@ -71,14 +121,39 @@ func NewCheckResult(statusCode int, value float64, threshold float64, err error) return result } +func (c *CheckResult) IsOK() bool { + if c.ResponseCode != tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED { + return c.ResponseCode == tabletmanagerdatapb.CheckThrottlerResponseCode_OK + } + return c.StatusCode == http.StatusOK +} + +// Summary returns a human-readable summary of the check result +func (c *CheckResult) Summary() string { + switch ResponseCodeFromStatus(c.ResponseCode, c.StatusCode) { + case tabletmanagerdatapb.CheckThrottlerResponseCode_OK: + return fmt.Sprintf("%s is granted access", c.AppName) + case tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED: + return fmt.Sprintf("%s is explicitly denied access", c.AppName) + case tabletmanagerdatapb.CheckThrottlerResponseCode_INTERNAL_ERROR: + return fmt.Sprintf("%s is denied access due to unexpected error: %v", c.AppName, c.Error) + case tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED: + return fmt.Sprintf("%s is denied access due to %s/%s metric value %v exceeding threshold %v", c.AppName, c.Scope, c.MetricName, c.Value, c.Threshold) + case tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC: + return fmt.Sprintf("%s is denied access due to unknown or uncollected metric", c.AppName) + case tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED: + return "" + default: + return fmt.Sprintf("unknown response code: %v", c.ResponseCode) + } +} + // NewErrorCheckResult returns a check result that indicates an error -func NewErrorCheckResult(statusCode int, err error) *CheckResult { - return NewCheckResult(statusCode, 0, 0, err) +func NewErrorCheckResult(responseCode tabletmanagerdatapb.CheckThrottlerResponseCode, statusCode int, err error) *CheckResult { + return NewCheckResult(responseCode, statusCode, 0, 0, "", err) } // NoSuchMetricCheckResult is a result returns when a metric is unknown -var NoSuchMetricCheckResult = NewErrorCheckResult(http.StatusNotFound, base.ErrNoSuchMetric) - -var okMetricCheckResult = NewCheckResult(http.StatusOK, 0, 0, nil) +var NoSuchMetricCheckResult = NewErrorCheckResult(tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC, http.StatusNotFound, base.ErrNoSuchMetric) -var invalidCheckTypeCheckResult = NewErrorCheckResult(http.StatusInternalServerError, base.ErrInvalidCheckType) +var okMetricCheckResult = NewCheckResult(tabletmanagerdatapb.CheckThrottlerResponseCode_OK, http.StatusOK, 0, 0, "", nil) diff --git a/go/vt/vttablet/tabletserver/throttle/check_result_test.go b/go/vt/vttablet/tabletserver/throttle/check_result_test.go new file mode 100644 index 00000000000..fdb0ee600ba --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/check_result_test.go @@ -0,0 +1,143 @@ +/* +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 throttle + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" +) + +func TestReponseCodeFromStatus(t *testing.T) { + tcases := []struct { + responseCode tabletmanagerdatapb.CheckThrottlerResponseCode + statusCode int + expect tabletmanagerdatapb.CheckThrottlerResponseCode + }{ + { + tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED, + http.StatusOK, + tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED, + http.StatusExpectationFailed, + tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED, + http.StatusNotFound, + tabletmanagerdatapb.CheckThrottlerResponseCode_UNKNOWN_METRIC, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED, + http.StatusInternalServerError, + tabletmanagerdatapb.CheckThrottlerResponseCode_INTERNAL_ERROR, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_UNDEFINED, + http.StatusTooManyRequests, + tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + http.StatusTooManyRequests, + tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + }, + { + tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + http.StatusOK, + tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + }, + } + for _, tcase := range tcases { + t.Run("", func(t *testing.T) { + result := ResponseCodeFromStatus(tcase.responseCode, tcase.statusCode) + assert.Equal(t, tcase.expect, result) + }) + } +} + +func TestCheckResultSummary(t *testing.T) { + tcases := []struct { + checkResult *CheckResult + summary string + }{ + { + checkResult: &CheckResult{}, + summary: "", + }, + { + checkResult: &CheckResult{ + StatusCode: http.StatusOK, + AppName: "test", + }, + summary: "test is granted access", + }, + { + checkResult: &CheckResult{ + StatusCode: http.StatusTooManyRequests, + AppName: "test", + MetricName: "bugginess", + Threshold: 100, + Value: 200, + Scope: "self", + }, + summary: "test is denied access due to self/bugginess metric value 200 exceeding threshold 100", + }, + { + checkResult: &CheckResult{ + StatusCode: http.StatusExpectationFailed, + AppName: "test", + }, + summary: "test is explicitly denied access", + }, + { + checkResult: &CheckResult{ + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + AppName: "test", + }, + summary: "test is granted access", + }, + { + checkResult: &CheckResult{ + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_THRESHOLD_EXCEEDED, + AppName: "test", + MetricName: "bugginess", + Threshold: 100, + Value: 200, + Scope: "self", + }, + summary: "test is denied access due to self/bugginess metric value 200 exceeding threshold 100", + }, + { + checkResult: &CheckResult{ + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_APP_DENIED, + AppName: "test", + }, + summary: "test is explicitly denied access", + }, + } + for _, tcase := range tcases { + t.Run(tcase.summary, func(t *testing.T) { + assert.Equal(t, tcase.summary, tcase.checkResult.Summary()) + }) + } +} diff --git a/go/vt/vttablet/tabletserver/throttle/client.go b/go/vt/vttablet/tabletserver/throttle/client.go index 5194ba19f98..8549fb099b6 100644 --- a/go/vt/vttablet/tabletserver/throttle/client.go +++ b/go/vt/vttablet/tabletserver/throttle/client.go @@ -18,11 +18,11 @@ package throttle import ( "context" - "net/http" "sync" "sync/atomic" "time" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" ) @@ -30,11 +30,15 @@ const ( throttleCheckDuration = 250 * time.Millisecond ) -var throttleTicks int64 -var throttleInit sync.Once +var ( + throttleTicks int64 + throttleInit sync.Once + emptyCheckResult = &CheckResult{} +) 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,55 +53,73 @@ 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 // be called very frequently. // The function is not thread safe. -func (c *Client) ThrottleCheckOK(ctx context.Context, overrideAppName throttlerapp.Name) (throttleCheckOK bool) { +func (c *Client) ThrottleCheckOK(ctx context.Context, overrideAppName throttlerapp.Name) (checkResult *CheckResult, throttleCheckOK bool) { if c == nil { // no client - return true + return emptyCheckResult, true } if c.throttler == nil { // no throttler - return true + return emptyCheckResult, 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 + return emptyCheckResult, true } // It's time to run a throttler check - checkApp := c.appName - if overrideAppName != "" { - checkApp = overrideAppName + checkResult = c.throttler.Check(ctx, checkApp.String(), nil, &c.flags) + if !checkResult.IsOK() { + return checkResult, false } - checkResult := c.throttler.CheckByType(ctx, checkApp.String(), "", &c.flags, c.checkType) - if checkResult.StatusCode != http.StatusOK { - return false + for _, metricResult := range checkResult.Metrics { + if !metricResult.IsOK() { + return checkResult, false + } } - c.lastSuccessfulThrottle = atomic.LoadInt64(&throttleTicks) - return true + c.lastSuccessfulThrottle[checkApp.String()] = atomic.LoadInt64(&throttleTicks) + return checkResult, true } @@ -105,18 +127,23 @@ func (c *Client) ThrottleCheckOK(ctx context.Context, overrideAppName throttlera // otherwise it briefly sleeps and returns 'false'. // 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) +func (c *Client) ThrottleCheckOKOrWaitAppName(ctx context.Context, appName throttlerapp.Name) (checkResult *CheckResult, throttleCheckOK bool) { + checkResult, throttleCheckOK = c.ThrottleCheckOK(ctx, appName) + if throttleCheckOK { + return checkResult, true + } + if ctx.Err() != nil { + // context expired, skip sleeping + return checkResult, false } - return ok + time.Sleep(throttleCheckDuration) + return checkResult, false } // ThrottleCheckOKOrWait checks the throttler; if throttler is satisfied, the function returns 'true' immediately, // otherwise it briefly sleeps and returns 'false'. // The function is not thread safe. -func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) bool { +func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) (checkResult *CheckResult, throttleCheckOK bool) { return c.ThrottleCheckOKOrWaitAppName(ctx, "") } @@ -125,11 +152,9 @@ func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) bool { // The function is not thread safe. func (c *Client) Throttle(ctx context.Context) { for { - if ctx.Err() != nil { - return - } - if c.ThrottleCheckOKOrWait(ctx) { + if _, ok := c.ThrottleCheckOKOrWait(ctx); ok { return } + // 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..76d5f2dd298 100644 --- a/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go +++ b/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go @@ -41,40 +41,15 @@ limitations under the License. package config -import ( - "sync/atomic" -) - // // 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 -} - // 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 - 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 - IgnoreHostsThreshold float64 // Threshold beyond which IgnoreHostsCount applies (default: 0) - HTTPCheckPort int // port for HTTP check. -1 to disable. - 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 + 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 + IgnoreHosts []string // If non empty, substrings to indicate hosts to be ignored/skipped } diff --git a/go/vt/vttablet/tabletserver/throttle/config/store_config.go b/go/vt/vttablet/tabletserver/throttle/config/store_config.go deleted file mode 100644 index 7e5594050d9..00000000000 --- a/go/vt/vttablet/tabletserver/throttle/config/store_config.go +++ /dev/null @@ -1,53 +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 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 - - // Futuristic stores can come here. -} 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..5cd56460713 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttler.go +++ b/go/vt/vttablet/tabletserver/throttle/throttler.go @@ -48,7 +48,6 @@ import ( "math" "math/rand/v2" "net/http" - "strconv" "strings" "sync" "sync/atomic" @@ -57,17 +56,13 @@ import ( "github.com/patrickmn/go-cache" "github.com/spf13/pflag" - "vitess.io/vitess/go/constants/sidecar" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/stats" "vitess.io/vitess/go/textutil" "vitess.io/vitess/go/timer" "vitess.io/vitess/go/vt/log" - tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" - topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/srvtopo" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" @@ -76,42 +71,42 @@ 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" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) 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" ) var ( statsThrottlerHeartbeatRequests = stats.NewCounter("ThrottlerHeartbeatRequests", "heartbeat requests") - statsThrottlerRecentlyChecked = stats.NewCounter("ThrottlerRecentlyChecked", "recently checked") statsThrottlerProbeRecentlyChecked = stats.NewCounter("ThrottlerProbeRecentlyChecked", "probe recently checked") ) @@ -128,16 +123,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 +144,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 +159,7 @@ type Throttler struct { srvTopoServer srvtopo.Server heartbeatWriter heartbeat.HeartbeatWriter overrideTmClient tmclient.TabletManagerClient + tabletAlias string recentCheckRateLimiter *timer.RateLimiter recentCheckDormantDiff int64 @@ -181,22 +167,23 @@ 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 + 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 +191,7 @@ type Throttler struct { cancelEnableContext context.CancelFunc throttledAppsMutex sync.Mutex - readSelfThrottleMetric func(context.Context, *mysql.Probe) *mysql.MySQLThrottleMetric // overwritten by unit test - - httpClient *http.Client + readSelfThrottleMetrics func(context.Context) base.ThrottleMetrics // overwritten by unit test } // ThrottlerStatus published some status values from the throttler @@ -214,17 +199,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 +233,27 @@ 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.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,11 +262,10 @@ 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(base.RegisteredSelfMetrics[base.LagMetricName].DefaultThreshold()) + throttler.readSelfThrottleMetrics = func(ctx context.Context) base.ThrottleMetrics { + return throttler.readSelfThrottleMetricsInternal(ctx) } - return throttler } @@ -306,7 +296,22 @@ func (throttler *Throttler) InitDBConfig(keyspace, shard string) { } func (throttler *Throttler) GetMetricsQuery() string { - return throttler.metricsQuery.Load().(string) + if customQuery := throttler.GetCustomMetricsQuery(); customQuery != "" { + return customQuery + } + lagSelfMetric, ok := base.RegisteredSelfMetrics[base.LagMetricName].(*base.LagSelfMetric) + if !ok { + return "" + } + return lagSelfMetric.GetQuery() +} + +func (throttler *Throttler) GetCustomMetricsQuery() string { + val := throttler.customMetricsQuery.Load() + if val == nil { + return "" + } + return val.(string) } func (throttler *Throttler) GetMetricsThreshold() float64 { @@ -318,23 +323,10 @@ 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, - } } // readThrottlerConfig proactively reads the throttler's config from SrvKeyspace in local topo @@ -354,10 +346,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 = base.RegisteredSelfMetrics[base.LagMetricName].DefaultThreshold() } } return throttlerConfig @@ -388,20 +386,93 @@ 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. func (throttler *Throttler) applyThrottlerConfig(ctx context.Context, throttlerConfig *topodatapb.ThrottlerConfig) { log.Infof("Throttler: applying topo config: %+v", throttlerConfig) - if throttlerConfig.CustomQuery == "" { - throttler.metricsQuery.Store(sqlparser.BuildParsedQuery(defaultReplicationLagQuery, sidecar.GetIdentifier()).Query) - } else { - throttler.metricsQuery.Store(throttlerConfig.CustomQuery) + 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.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 +540,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 @@ -538,14 +608,11 @@ func (throttler *Throttler) Open() error { log.Infof("Throttler: opening") var ctx context.Context ctx, throttler.cancelOpenContext = context.WithCancel(context.Background()) - // The query needs to be dynamically built because the sidecar database name - // 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,56 +684,6 @@ 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) - } - return f -} - -// 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, - } - conn, err := throttler.pool.Get(ctx, nil) - if err != nil { - metric.Err = err - return metric - } - defer conn.Recycle() - - tm, err := conn.Conn.Exec(ctx, probe.MetricQuery, 1, true) - if err != nil { - metric.Err = err - return metric - } - row := tm.Named().Row() - if row == nil { - metric.Err = fmt.Errorf("no results for readSelfMySQLThrottleMetric") - return metric - } - - metricsQueryType := mysql.GetMetricsQueryType(throttler.GetMetricsQuery()) - switch metricsQueryType { - case mysql.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: - metric.Value, metric.Err = strconv.ParseFloat(row["Value"].ToString(), 64) - default: - metric.Err = fmt.Errorf("Unsupported metrics query type for query: %s", throttler.GetMetricsQuery()) - } - - return metric -} - // throttledAppsSnapshot returns a snapshot (a copy) of current throttled apps func (throttler *Throttler) throttledAppsSnapshot() map[string]cache.Item { return throttler.throttledApps.Items() @@ -709,22 +726,24 @@ 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() + clear(throttler.inventory.TabletMetrics) }() // 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 +789,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 +821,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(probes) + case <-metricsAggregateTicker.C: if throttler.IsOpen() { - throttler.aggregateMySQLMetrics(ctx) + throttler.aggregateMetrics() } case <-throttledAppsTicker.C: if throttler.IsOpen() { @@ -836,35 +854,54 @@ 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)) + } + throttleMetric.Value = resp.Value + if resp.ResponseCode == tabletmanagerdatapb.CheckThrottlerResponseCode_INTERNAL_ERROR { + throttleMetric.Err = fmt.Errorf("response code: %d", resp.ResponseCode) } - mySQLThrottleMetric.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 +909,311 @@ 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) { +// readSelfThrottleMetricsInternal rreads all registsred self metrics on this tablet (or backend MySQL server). +// This is the actual place where metrics are read, to be later aggregated and/or propagated to other tablets. +func (throttler *Throttler) readSelfThrottleMetricsInternal(ctx context.Context) base.ThrottleMetrics { + result := make(base.ThrottleMetrics, len(base.RegisteredSelfMetrics)) + writeMetric := func(metric *base.ThrottleMetric) { + select { + case <-ctx.Done(): + return + case throttler.throttleMetricChan <- metric: + } + } + readMetric := func(selfMetric base.SelfMetric) *base.ThrottleMetric { + if !selfMetric.RequiresConn() { + return selfMetric.Read(ctx, throttler, nil) + } + conn, err := throttler.pool.Get(ctx, nil) + if err != nil { + return &base.ThrottleMetric{Err: err} + } + defer conn.Recycle() + return selfMetric.Read(ctx, throttler, conn.Conn) + } + for metricName, selfMetric := range base.RegisteredSelfMetrics { + if metricName == base.DefaultMetricName { 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) + metric := readMetric(selfMetric) + metric.Name = metricName + metric.Alias = throttler.tabletAlias + + go writeMetric(metric) + result[metricName] = metric + } + return result +} + +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 + } + 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(), - } + metricNameUsedAsDefault := throttler.metricNameUsedAsDefault() + metricsThreshold := throttler.GetMetricsThreshold() + for metricName, selfMetric := range base.RegisteredSelfMetrics { + threshold := selfMetric.DefaultThreshold() + if (metricName == metricNameUsedAsDefault || metricName == base.DefaultMetricName) && metricsThreshold != 0 { + // backwards compatibility to v20: + threshold = metricsThreshold + } + throttler.metricThresholds.Set(inventoryPrefix+metricName.String(), threshold, cache.DefaultExpiration) + } + throttler.convergeMetricThresholds() - 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() + var clusterSettingsCopy config.MySQLConfigurationSettings = throttler.configSettings.MySQLStore + // 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(clusterProbes *base.ClusterProbes) error { + throttler.inventory.ClustersProbes = clusterProbes.TabletProbes + throttler.inventory.IgnoreHostsCount = clusterProbes.IgnoreHostsCount + throttler.inventory.IgnoreHostsThreshold = clusterProbes.IgnoreHostsThreshold + + for alias := range throttler.inventory.TabletMetrics { + if alias == "" { + // *this* tablet uses the empty alias to identify itself. + continue + } + if _, found := clusterProbes.TabletProbes[alias]; !found { + // There seems to be a metric stored for some alias, say zone1-0000000102, + // but there is no alias for this probe in the new clusterProbes. This + // suggests that the corresponding tablet has been removed, or its type was changed + // (e.g. from REPLICA to RDONLY). We should therefore remove this cached metric. + delete(throttler.inventory.TabletMetrics, alias) + } + } + 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 +} + +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 +} - return base.NoSuchMetric, 0 +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 +1229,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 +1259,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) @@ -1115,7 +1278,8 @@ func (throttler *Throttler) UnthrottleApp(appName string) (appThrottle *base.App // IsAppThrottled tells whether some app should be throttled. // 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 { +func (throttler *Throttler) IsAppThrottled(appName string) (bool, string) { + appFound := "" isSingleAppNameThrottled := func(singleAppName string) bool { object, found := throttler.throttledApps.Get(singleAppName) if !found { @@ -1123,9 +1287,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 = singleAppName if appThrottle.Exempt { return false } @@ -1136,21 +1303,32 @@ func (throttler *Throttler) IsAppThrottled(appName string) bool { return false } if isSingleAppNameThrottled(appName) { - return true + return true, appName } - for _, singleAppName := range strings.Split(appName, ":") { + for _, singleAppName := range throttlerapp.Name(appName).SplitStrings() { if singleAppName == "" { continue } if isSingleAppNameThrottled(singleAppName) { - return true + return true, singleAppName } } - return false + // If app was found then there was some explicit throttle instruction for the app, and the app + // passed the test. + if appFound != "" { + return false, appFound + } + // 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, throttlerapp.AllName.String() + } + return false, appName } // IsAppExempt -func (throttler *Throttler) IsAppExempted(appName string) bool { +func (throttler *Throttler) IsAppExempted(appName string) (bool, string) { isSingleAppNameExempted := func(singleAppName string) bool { if throttlerapp.ExemptFromChecks(appName) { // well known statically exempted apps return true @@ -1170,17 +1348,24 @@ func (throttler *Throttler) IsAppExempted(appName string) bool { return false } if isSingleAppNameExempted(appName) { - return true + return true, appName } - for _, singleAppName := range strings.Split(appName, ":") { + for _, singleAppName := range throttlerapp.Name(appName).SplitStrings() { if singleAppName == "" { continue } if isSingleAppNameExempted(singleAppName) { - return true + return true, singleAppName + } + } + + if isSingleAppNameExempted(throttlerapp.AllName.String()) { + if throttled, _ := throttler.IsAppThrottled(appName); !throttled { + return true, throttlerapp.AllName.String() } } - return false + + return false, appName } // ThrottledAppsMap returns a (copy) map of currently throttled apps @@ -1195,17 +1380,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, responseCode tabletmanagerdatapb.CheckThrottlerResponseCode) { + recentApp := base.NewRecentApp(appName, statusCode, responseCode) + 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 @@ -1234,28 +1419,73 @@ func (throttler *Throttler) metricsHealthSnapshot() base.MetricHealthMap { } // AppRequestMetricResult gets a metric result in the context of a specific app -func (throttler *Throttler) AppRequestMetricResult(ctx context.Context, appName string, metricResultFunc base.MetricResultFunc, denyApp bool) (metricResult base.MetricResult, threshold float64) { +func (throttler *Throttler) AppRequestMetricResult(ctx context.Context, appName string, metricResultFunc base.MetricResultFunc, denyApp bool) (metricResult base.MetricResult, threshold float64, matchedApp string) { if denyApp { - return base.AppDeniedMetric, 0 + return base.AppDeniedMetric, 0, appName } - if throttler.IsAppThrottled(appName) { - return base.AppDeniedMetric, 0 + throttled, matchedApp := throttler.IsAppThrottled(appName) + if throttled { + return base.AppDeniedMetric, 0, matchedApp } - return metricResultFunc() + metricResult, threshold = metricResultFunc() + return metricResult, threshold, matchedApp } -// 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 } - if throttler.IsAppExempted(appName) { + if exempted, matchedApp := throttler.IsAppExempted(appName); exempted { // Some apps are exempt from checks. They are always responded with OK. This is because those apps are // continuous and do not generate a substantial load. - return okMetricCheckResult + result := okMetricCheckResult + result.AppName = matchedApp + return result + } + + matchedApp := appName + 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...) + } + matchedApp = appToken + } + } } - - checkResult = throttler.check.Check(ctx, appName, "mysql", storeName, remoteAddr, flags) + 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 + } + matchedApp = throttlerapp.AllName.String() + } + } + if throttlerapp.VitessName.Equals(appName) { + // "vitess" always checks all metrics, irrespective of what is mapped. + metricNames = base.KnownMetricNames + matchedApp = appName + } + 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) + checkResult.AppName = matchedApp shouldRequestHeartbeats := !flags.SkipRequestHeartbeats if throttlerapp.VitessName.Equals(appName) { @@ -1274,7 +1504,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 +1512,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 +1548,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..41036620a60 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,67 @@ 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, + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + Value: 0.9, + }, + base.ThreadsRunningMetricName.String(): { + StatusCode: http.StatusOK, + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + Value: 13, + }, + base.CustomMetricName.String(): { + StatusCode: http.StatusOK, + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + Value: 14, + }, + base.LoadAvgMetricName.String(): { + StatusCode: http.StatusOK, + ResponseCode: tabletmanagerdatapb.CheckThrottlerResponseCode_OK, + Value: 5.1, + }, + } + nonPrimaryTabletType atomic.Int32 +) + 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 +116,24 @@ 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.ResponseCode = tabletmanagerdatapb.CheckThrottlerResponseCode_OK + 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), + ResponseCode: metric.ResponseCode, + Value: metric.Value, + Threshold: metric.Threshold, + Message: metric.Message, + } + } + } c.mu.Lock() defer c.mu.Unlock() c.appNames = append(c.appNames, request.AppName) @@ -81,7 +152,11 @@ type FakeTopoServer struct { func (ts *FakeTopoServer) GetTablet(ctx context.Context, alias *topodatapb.TabletAlias) (*topo.TabletInfo, error) { tabletType := topodatapb.TabletType_PRIMARY if alias.Uid != 100 { - tabletType = topodatapb.TabletType_REPLICA + val := topodatapb.TabletType(nonPrimaryTabletType.Load()) + if val == topodatapb.TabletType_UNKNOWN { + val = topodatapb.TabletType_REPLICA + } + tabletType = val } tablet := &topo.TabletInfo{ Tablet: &topodatapb.Tablet{ @@ -98,9 +173,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 +197,125 @@ 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) + lagSelfMetric := base.RegisteredSelfMetrics[base.LagMetricName].(*base.LagSelfMetric) + lagSelfMetric.SetQuery(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,160 +323,890 @@ 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to self/lag metric value") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to shard/lag metric value") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to self/loadavg metric value") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to shard/loadavg metric value") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to self/loadavg metric value") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to shard/loadavg metric value") + }) + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 1, len(checkResult.Metrics), "unexpected metrics: %+v", checkResult.Metrics) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), throttlerapp.AllName.String()+" is denied access due to self/loadavg metric value") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), throttlerapp.AllName.String()+" is denied access due to self/loadavg metric value") + }) + }) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), throttlerapp.AllName.String()+" is denied access due to self/loadavg metric value") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), throttlerapp.AllName.String()+" is granted access") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), throttlerapp.OnlineDDLName.String()+" is granted access") + }) + }) + + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Len(t, checkResult.Metrics, 1) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is granted access") + }) + }) + + 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) { + { + throttled, app := throttler.IsAppThrottled("app1") + assert.False(t, throttled) + assert.Equal(t, "app1", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.False(t, throttled) + assert.Equal(t, "app2", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.False(t, throttled) + assert.Equal(t, "app3", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.False(t, throttled) + assert.Equal(t, "app4", app) + } + + 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) + { + throttled, app := throttler.IsAppThrottled("app1") + assert.False(t, throttled) // exempted + assert.Equal(t, "app1", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.False(t, throttled) // expired + assert.Equal(t, "app2", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.True(t, throttled) + assert.Equal(t, "app3", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.False(t, throttled) // ratio is zero + assert.Equal(t, "app4", app) + } + { + throttled, app := throttler.IsAppThrottled("app_other") + assert.False(t, throttled) // not specified + assert.Equal(t, "app_other", app) + } + + 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()) + { + throttled, app := throttler.IsAppThrottled("all") + assert.True(t, throttled) // explicitly throttled + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app1") + assert.False(t, throttled) // exempted + assert.Equal(t, "app1", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.True(t, throttled) // expired, so falls under "all" + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.True(t, throttled) + assert.Equal(t, "app3", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.False(t, throttled) // ratio is zero, there is a specific instruction for this app, so it doesn't fall under "all" + assert.Equal(t, "app4", app) + } + { + throttled, app := throttler.IsAppThrottled("app_other") + assert.True(t, throttled) // falls under "all" + assert.Equal(t, "all", app) + } + + // 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") + + { + throttled, app := throttler.IsAppThrottled("app1") + assert.False(t, throttled) + assert.Equal(t, "app1", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.False(t, throttled) + assert.Equal(t, "app2", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.False(t, throttled) + assert.Equal(t, "app3", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.False(t, throttled) + assert.Equal(t, "app4", app) + } + + // 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()) + + { + throttled, app := throttler.IsAppThrottled("all") + assert.True(t, throttled) // explicitly throttled + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app1") + assert.True(t, throttled) + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.True(t, throttled) + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.True(t, throttled) + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.True(t, throttled) + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app_other") + assert.True(t, throttled) + assert.Equal(t, "all", app) + } + + // 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()) + + { + throttled, app := throttler.IsAppThrottled("all") + assert.False(t, throttled) // explicitly throttled + assert.Equal(t, "all", app) + } + { + throttled, app := throttler.IsAppThrottled("app1") + assert.False(t, throttled) + assert.Equal(t, "app1", app) + } + { + throttled, app := throttler.IsAppThrottled("app2") + assert.False(t, throttled) + assert.Equal(t, "app2", app) + } + { + throttled, app := throttler.IsAppThrottled("app3") + assert.True(t, throttled) // explicitly throttled + assert.Equal(t, "app3", app) + } + { + throttled, app := throttler.IsAppThrottled("app4") + assert.False(t, throttled) + assert.Equal(t, "app4", app) + } + { + throttled, app := throttler.IsAppThrottled("app_other") + assert.False(t, throttled) + assert.Equal(t, "app_other", app) + } + assert.Equal(t, 2, throttler.throttledApps.ItemCount()) + }) } func TestIsAppExempted(t *testing.T) { - + plusOneHour := time.Now().Add(time.Hour) throttler := Throttler{ throttledApps: cache.New(cache.NoExpiration, 0), heartbeatWriter: &FakeHeartbeatWriter{}, } - assert.False(t, throttler.IsAppExempted("app1")) - assert.False(t, throttler.IsAppExempted("app2")) - assert.False(t, throttler.IsAppExempted("app3")) - // - throttler.ThrottleApp("app1", time.Now().Add(time.Hour), DefaultThrottleRatio, true) - throttler.ThrottleApp("app2", time.Now(), DefaultThrottleRatio, true) // instantly expire - assert.True(t, throttler.IsAppExempted("app1")) - assert.True(t, throttler.IsAppExempted("app1:other-tag")) - assert.False(t, throttler.IsAppExempted("app2")) // expired - assert.False(t, throttler.IsAppExempted("app3")) - // - throttler.UnthrottleApp("app1") - throttler.ThrottleApp("app2", time.Now().Add(time.Hour), DefaultThrottleRatio, false) - assert.False(t, throttler.IsAppExempted("app1")) - assert.False(t, throttler.IsAppExempted("app2")) - assert.False(t, throttler.IsAppExempted("app3")) - // - assert.True(t, throttler.IsAppExempted("schema-tracker")) - throttler.UnthrottleApp("schema-tracker") // meaningless. App is statically exempted - assert.True(t, throttler.IsAppExempted("schema-tracker")) + t.Run("initial", func(t *testing.T) { + { + exempted, app := throttler.IsAppExempted("app1") + assert.False(t, exempted) + assert.Equal(t, "app1", app) + } + { + exempted, app := throttler.IsAppExempted("app2") + assert.False(t, exempted) + assert.Equal(t, "app2", app) + } + { + exempted, app := throttler.IsAppExempted("app3") + assert.False(t, exempted) + assert.Equal(t, "app3", app) + } + }) + t.Run("exempt", func(t *testing.T) { + throttler.ThrottleApp("app1", time.Now().Add(time.Hour), DefaultThrottleRatio, true) + throttler.ThrottleApp("app2", time.Now(), DefaultThrottleRatio, true) // instantly expire + { + exempted, app := throttler.IsAppExempted("app1") + assert.True(t, exempted) + assert.Equal(t, "app1", app) + } + { + exempted, app := throttler.IsAppExempted("app1:other-tag") + assert.True(t, exempted) + assert.Equal(t, "app1", app) + } + { + exempted, app := throttler.IsAppExempted("app2") + assert.False(t, exempted) + assert.Equal(t, "app2", app) + } + { + exempted, app := throttler.IsAppExempted("app3") + assert.False(t, exempted) + assert.Equal(t, "app3", app) + } + }) + t.Run("throttle", func(t *testing.T) { + throttler.UnthrottleApp("app1") + throttler.ThrottleApp("app2", time.Now().Add(time.Hour), DefaultThrottleRatio, false) + { + exempted, app := throttler.IsAppExempted("app1") + assert.False(t, exempted) + assert.Equal(t, "app1", app) + } + { + exempted, app := throttler.IsAppExempted("app2") + assert.False(t, exempted) + assert.Equal(t, "app2", app) + } + { + exempted, app := throttler.IsAppExempted("app3") + assert.False(t, exempted) + assert.Equal(t, "app3", app) + } + }) + t.Run("special", func(t *testing.T) { + { + exempted, app := throttler.IsAppExempted("schema-tracker") + assert.True(t, exempted) + assert.Equal(t, "schema-tracker", app) + } + throttler.ThrottleApp("schema-tracker", plusOneHour, 1.0, false) // meaningless. App is statically exempted + { + exempted, app := throttler.IsAppExempted("schema-tracker") + assert.True(t, exempted) + assert.Equal(t, "schema-tracker", app) + } + }) } -// 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(), } + lagSelfMetric := base.RegisteredSelfMetrics[base.LagMetricName].(*base.LagSelfMetric) + lagSelfMetric.SetQuery(metricsQuery) throttler.configSettings = configSettings - throttler.metricsQuery.Store(metricsQuery) + 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.Len(t, probes, 3) } else { - assert.Empty(t, probes) + assert.Len(t, probes, 1) } } 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(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 +1244,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 +1253,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 +1343,336 @@ 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) + }) + { + checkResult, checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // we expect threshold exceeded + assert.NotNil(t, checkResult) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to") + } + }) + + 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 + { + checkResult, checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + assert.NotNil(t, checkResult) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to") + } + }) + }) + }) + + 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) + }) + { + checkResult, checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // we expect threshold exceeded + assert.NotNil(t, checkResult) + } + }) + + 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) + } + }) + }) + }) + + t.Run("metrics", func(t *testing.T) { + var results base.TabletResultMap + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + results = maps.Clone(throttler.inventory.TabletMetrics) + }) + assert.Len(t, results, 3) // 1 self tablet + 2 shard tablets + assert.Contains(t, results, "", "TabletMetrics: %+v", results) // primary self identifies with empty alias + assert.Contains(t, results, "fakezone1-0000000101", "TabletMetrics: %+v", results) + assert.Contains(t, results, "fakezone2-0000000102", "TabletMetrics: %+v", results) + }) + + t.Run("no REPLICA probes", func(t *testing.T) { + nonPrimaryTabletType.Store(int32(topodatapb.TabletType_RDONLY)) + defer nonPrimaryTabletType.Store(int32(topodatapb.TabletType_REPLICA)) + + t.Run("waiting for inventory metrics", func(t *testing.T) { + ctx, cancel := context.WithTimeout(ctx, waitForProbesTimeout) + defer cancel() + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + for { + var results base.TabletResultMap + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + results = maps.Clone(throttler.inventory.TabletMetrics) + }) + if len(results) == 1 { + // That's what we were waiting for. Good. + assert.Contains(t, results, "", "TabletMetrics: %+v", results) // primary self identifies with empty alias + return + } + + select { + case <-ticker.C: + case <-ctx.Done(): + assert.FailNowf(t, ctx.Err().Error(), "waiting for inventory metrics") + } + } + }) + }) + t.Run("again with probes", func(t *testing.T) { + t.Run("waiting for inventory metrics", func(t *testing.T) { + ctx, cancel := context.WithTimeout(ctx, waitForProbesTimeout) + defer cancel() + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + for { + var results base.TabletResultMap + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + results = maps.Clone(throttler.inventory.TabletMetrics) + }) + if len(results) == 3 { + // That's what we were waiting for. Good. + return + } + + select { + case <-ticker.C: + case <-ctx.Done(): + assert.FailNowf(t, ctx.Err().Error(), "waiting for inventory metrics") + } + } + }) + }) + }) +} + +// 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) + + probes := throttler.inventory.ClustersProbes - 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 { + <-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.Empty(t, throttler.inventory.TabletMetrics) // map has been cleared }) t.Run("aggregated", func(t *testing.T) { @@ -496,7 +1683,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 +1696,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 +1711,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 +1719,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 +1735,266 @@ 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.Equal(t, testAppName.String(), checkResult.AppName) + 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) + } + } + if !assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "unexpected result: %+v", checkResult) { + for k, v := range checkResult.Metrics { + t.Logf("%s: %+v", k, v) + } + } + + assert.Equal(t, testAppName.String(), checkResult.AppName) + 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, throttlerapp.VitessName.String(), checkResult.AppName) + 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, throttlerapp.VitessName.String(), checkResult.AppName) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Equal(t, testAppName.String(), checkResult.AppName) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Equal(t, testAppName.String(), checkResult.AppName) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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 +2004,236 @@ 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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) + assert.EqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, recentApp.ResponseCode) + } + } + { + { + _, 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.NotEqualValues(t, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode, "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, tabletmanagerdatapb.CheckThrottlerResponseCode_OK, checkResult.ResponseCode) + 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.Len(t, checkResult.Metrics, 3) + }) + 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) + checkResult, checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + assert.NotNil(t, checkResult) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to") + }) + + 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) + checkResult, checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + assert.NotNil(t, checkResult) + assert.Contains(t, checkResult.Summary(), testAppName.String()+" is denied access due to") + }) }() }) } 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..ffb4bae39a5 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. @@ -157,7 +169,7 @@ func (tpc *TwoPC) Close() { } // SaveRedo saves the statements in the redo log using the supplied connection. -func (tpc *TwoPC) SaveRedo(ctx context.Context, conn *StatefulConnection, dtid string, queries []string) error { +func (tpc *TwoPC) SaveRedo(ctx context.Context, conn *StatefulConnection, dtid string, queries []tx.Query) error { bindVars := map[string]*querypb.BindVariable{ "dtid": sqltypes.StringBindVariable(dtid), "state": sqltypes.Int64BindVariable(RedoStatePrepared), @@ -173,7 +185,7 @@ func (tpc *TwoPC) SaveRedo(ctx context.Context, conn *StatefulConnection, dtid s rows[i] = []sqltypes.Value{ sqltypes.NewVarBinary(dtid), sqltypes.NewInt64(int64(i + 1)), - sqltypes.NewVarBinary(query), + sqltypes.NewVarBinary(query.Sql), } } extras := map[string]sqlparser.Encodable{ @@ -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 < DTStatePrepare || result.State > DTStateCommit { 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 < DTStatePrepare || protostate > DTStateCommit { 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/tx/api.go b/go/vt/vttablet/tabletserver/tx/api.go index a392e530ffa..48a1cc1107a 100644 --- a/go/vt/vttablet/tabletserver/tx/api.go +++ b/go/vt/vttablet/tabletserver/tx/api.go @@ -31,11 +31,11 @@ type ( // ConnID as type int64 ConnID = int64 - //DTID as type string + // DTID as type string DTID = string - //EngineStateMachine is used to control the state the transactional engine - - //whether new connections and/or transactions are allowed or not. + // EngineStateMachine is used to control the state the transactional engine - + // whether new connections and/or transactions are allowed or not. EngineStateMachine interface { Init() error AcceptReadWrite() error @@ -46,14 +46,14 @@ type ( // ReleaseReason as type int ReleaseReason int - //Properties contains all information that is related to the currently running - //transaction on the connection + // Properties contains all information that is related to the currently running + // transaction on the connection Properties struct { EffectiveCaller *vtrpcpb.CallerID ImmediateCaller *querypb.VTGateCallerID StartTime time.Time EndTime time.Time - Queries []string + Queries []Query Autocommit bool Conclusion string LogToFile bool @@ -62,6 +62,11 @@ type ( } ) +type Query struct { + Sql string + Tables []string +} + const ( // TxClose - connection released on close. TxClose ReleaseReason = iota @@ -114,12 +119,33 @@ var txNames = map[ReleaseReason]string{ ConnRenewFail: "renewFail", } -// RecordQuery records the query against this transaction. -func (p *Properties) RecordQuery(query string) { +// RecordQueryDetail records the query and tables against this transaction. +func (p *Properties) RecordQueryDetail(query string, tables []string) { if p == nil { return } - p.Queries = append(p.Queries, query) + p.Queries = append(p.Queries, Query{ + Sql: query, + Tables: tables, + }) +} + +// RecordQuery records the query and extract tables against this transaction. +func (p *Properties) RecordQuery(query string, parser *sqlparser.Parser) { + if p == nil { + return + } + stmt, err := parser.Parse(query) + if err != nil { + // This should neven happen, but if it does, + // we would not be able to block cut-overs on this query. + return + } + tables := sqlparser.ExtractAllTables(stmt) + p.Queries = append(p.Queries, Query{ + Sql: query, + Tables: tables, + }) } // InTransaction returns true as soon as this struct is not nil @@ -134,10 +160,11 @@ func (p *Properties) String(sanitize bool, parser *sqlparser.Parser) string { printQueries := func() string { sb := strings.Builder{} for _, query := range p.Queries { + sql := query.Sql if sanitize { - query, _ = parser.RedactSQLQuery(query) + sql, _ = parser.RedactSQLQuery(sql) } - sb.WriteString(query) + sb.WriteString(sql) sb.WriteString(";") } return sb.String() diff --git a/go/vt/vttablet/tabletserver/tx_engine.go b/go/vt/vttablet/tabletserver/tx_engine.go index 7e8ecc06a75..d7f2d55b18a 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 @@ -77,7 +75,11 @@ type TxEngine struct { // transition while creating new transactions beginRequests sync.WaitGroup - twopcEnabled bool + // twopcEnabled is the flag value of whether the user has enabled twopc or not. + twopcEnabled bool + // twopcAllowed is wether it is safe to allow two pc transactions or not. + // If the primary tablet doesn't run with semi-sync we set this to false, and disallow any prepared calls. + twopcAllowed bool shutdownGracePeriod time.Duration coordinatorAddress string abandonAge time.Duration @@ -89,11 +91,11 @@ type TxEngine struct { txPool *TxPool 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, @@ -102,18 +104,16 @@ func NewTxEngine(env tabletenv.Env) *TxEngine { } limiter := txlimiter.New(env) te.txPool = NewTxPool(env, limiter) + // We initially allow twoPC (handles vttablet restarts). + // We will disallow them, when a new tablet is promoted if semi-sync is turned off. + te.twopcAllowed = true 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) @@ -122,20 +122,18 @@ func NewTxEngine(env tabletenv.Env) *TxEngine { // perform metadata state change operations. Without this, // the system can deadlock if all connections get moved to // the TxPreparedPool. - te.preparedPool = NewTxPreparedPool(config.TxPool.Size - 2) + te.preparedPool = NewTxPreparedPool(config.TxPool.Size-2, te.twopcEnabled) readPool := connpool.NewPool(env, "TxReadPool", tabletenv.ConnPoolConfig{ Size: 3, IdleTimeout: env.Config().TxPool.IdleTimeout, }) te.twoPC = NewTwoPC(readPool) + te.dxNotify = dxNotifier te.state = NotServing return te } // AcceptReadWrite will start accepting all transactions. -// If transitioning from RO mode, transactions are rolled -// back before accepting new transactions. This is to allow -// for 2PC state to be correctly initialized. func (te *TxEngine) AcceptReadWrite() { te.transition(AcceptingReadAndWrite) } @@ -154,35 +152,70 @@ func (te *TxEngine) transition(state txEngineState) { } log.Infof("TxEngine transition: %v", state) - switch te.state { - case AcceptingReadOnly, AcceptingReadAndWrite: + + // When we are transitioning from read write state, we should close all transactions. + if te.state == AcceptingReadAndWrite { te.shutdownLocked() - case NotServing: - // No special action. } te.state = state + if te.twopcEnabled && te.state == AcceptingReadAndWrite { + // If the prepared pool is not open, then we need to redo the prepared transactions + // before we open the transaction engine to accept new writes. + // This check is required because during a Promotion, we would have already setup the prepared pool + // and redid the prepared transactions when we turn super_read_only off. So we don't need to do it again. + if !te.preparedPool.IsOpen() { + // We need to redo prepared transactions here to handle vttablet restarts. + // If MySQL continues to work fine, then we won't end up redoing the prepared transactions as part of any RPC call + // since VTOrc won't call `UndoDemotePrimary`. We need to do them as part of this transition. + te.redoPreparedTransactionsLocked() + } + te.startTransactionWatcher() + } te.txPool.Open(te.env.Config().DB.AppWithDB(), te.env.Config().DB.DbaWithDB(), te.env.Config().DB.AppDebugWithDB()) +} - if te.twopcEnabled && te.state == AcceptingReadAndWrite { - // If there are errors, we choose to raise an alert and - // continue anyway. Serving traffic is considered more important - // than blocking everything for the sake of a few transactions. - // We do this async; so we do not end up blocking writes on - // failover for our setup tasks if using semi-sync replication. - te.twoPCReady.Add(1) - go func() { - defer te.twoPCReady.Done() - if err := te.twoPC.Open(te.env.Config().DB); err != nil { - te.env.Stats().InternalErrors.Add("TwopcOpen", 1) - log.Errorf("Could not open TwoPC engine: %v", err) - } - if err := te.prepareFromRedo(); err != nil { - te.env.Stats().InternalErrors.Add("TwopcResurrection", 1) - log.Errorf("Could not prepare transactions: %v", err) - } - te.startWatchdog() - }() +// RedoPreparedTransactions acquires the state lock and calls redoPreparedTransactionsLocked. +func (te *TxEngine) RedoPreparedTransactions() { + if te.twopcEnabled { + te.stateLock.Lock() + defer te.stateLock.Unlock() + te.redoPreparedTransactionsLocked() + } +} + +// redoPreparedTransactionsLocked redoes the prepared transactions. +// If there are errors, we choose to raise an alert and +// continue anyway. Serving traffic is considered more important +// than blocking everything for the sake of a few transactions. +// We do this async; so we do not end up blocking writes on +// failover for our setup tasks if using semi-sync replication. +func (te *TxEngine) redoPreparedTransactionsLocked() { + oldState := te.state + // We shutdown to ensure no other writes are in progress. + te.shutdownLocked() + defer func() { + te.state = oldState + }() + + if err := te.twoPC.Open(te.env.Config().DB); err != nil { + te.env.Stats().InternalErrors.Add("TwopcOpen", 1) + log.Errorf("Could not open TwoPC engine: %v", err) + return + } + + // We should only open the prepared pool and the transaction pool if the opening of twoPC pool is successful. + // We use the prepared pool being open to know if we need to redo the prepared transactions. + // So if we open the prepared pool and then opening of twoPC fails, we will never end up opening the twoPC pool at all! + // This is why opening prepared pool after the twoPC pool is crucial for correctness. + te.preparedPool.Open() + // We have to defer opening the transaction pool because we call shutdown in the beginning that closes it. + // We want to open the transaction pool after the prepareFromRedo has run. Also, we want this to run even if that fails. + defer te.txPool.Open(te.env.Config().DB.AppWithDB(), te.env.Config().DB.DbaWithDB(), te.env.Config().DB.AppDebugWithDB()) + + if err := te.prepareFromRedo(); err != nil { + te.env.Stats().InternalErrors.Add("TwopcResurrection", 1) + log.Errorf("Could not prepare transactions: %v", err) } } @@ -309,11 +342,6 @@ func (te *TxEngine) shutdownLocked() { te.stateLock.Lock() log.Infof("TxEngine - state lock acquired again") - // Shut down functions are idempotent. - // No need to check if 2pc is enabled. - log.Infof("TxEngine - stop watchdog") - te.stopWatchdog() - poolEmpty := make(chan bool) rollbackDone := make(chan bool) // This goroutine decides if transactions have to be @@ -336,13 +364,6 @@ func (te *TxEngine) shutdownLocked() { // connections. te.txPool.scp.ShutdownNonTx() if te.shutdownGracePeriod <= 0 { - // No grace period was specified. Wait indefinitely for transactions to be concluded. - // TODO(sougou): invoking rollbackPrepared is incorrect here. Prepared statements should - // actually be rolled back last. But this will cause the shutdown to hang because the - // tx pool will never become empty, because the prepared pool is holding on to connections - // from the tx pool. But we plan to deprecate this approach to 2PC. So, this - // should eventually be deleted. - te.rollbackPrepared() log.Info("No grace period specified: performing normal wait.") return } @@ -357,6 +378,9 @@ func (te *TxEngine) shutdownLocked() { log.Info("Transactions completed before grace period: shutting down.") } }() + // It is important to note, that we aren't rolling back prepared transactions here. + // That is happneing in the same place where we are killing queries. This will block + // until either all prepared transactions get resolved or rollbacked. log.Infof("TxEngine - waiting for empty txPool") te.txPool.WaitForEmpty() // If the goroutine is still running, signal that it can exit. @@ -365,10 +389,19 @@ func (te *TxEngine) shutdownLocked() { log.Infof("TxEngine - making sure the goroutine has returned") <-rollbackDone + // We stop the transaction watcher so late, because if the user isn't running + // with any shutdown grace period, we still want the watcher to run while we are waiting + // for resolving transactions. + log.Infof("TxEngine - stop transaction watcher") + te.stopTransactionWatcher() + + // Mark the prepared pool closed. log.Infof("TxEngine - closing the txPool") te.txPool.Close() log.Infof("TxEngine - closing twoPC") te.twoPC.Close() + log.Infof("TxEngine - closing the prepared pool") + te.preparedPool.Close() log.Infof("TxEngine - finished shutdownLocked") } @@ -394,16 +427,17 @@ outer: if txid > maxid { maxid = txid } - conn, _, _, err := te.txPool.Begin(ctx, &querypb.ExecuteOptions{}, false, 0, nil, nil) + // We need to redo the prepared transactions using a dba user because MySQL might still be in read only mode. + conn, err := te.beginNewDbaConnection(ctx) if err != nil { - allErr.RecordError(err) + allErr.RecordError(vterrors.Wrapf(err, "dtid - %v", preparedTx.Dtid)) continue } for _, stmt := range preparedTx.Queries { - conn.TxProperties().RecordQuery(stmt) + conn.TxProperties().RecordQuery(stmt, te.env.Environment().Parser()) _, err := conn.Exec(ctx, stmt, 1, false) if err != nil { - allErr.RecordError(err) + allErr.RecordError(vterrors.Wrapf(err, "dtid - %v", preparedTx.Dtid)) te.txPool.RollbackAndRelease(ctx, conn) continue outer } @@ -412,7 +446,7 @@ outer: // we don't want to write again to the redo log. err = te.preparedPool.Put(conn, preparedTx.Dtid) if err != nil { - allErr.RecordError(err) + allErr.RecordError(vterrors.Wrapf(err, "dtid - %v", preparedTx.Dtid)) continue } } @@ -431,80 +465,59 @@ outer: return allErr.Error() } -// shutdownTransactions rolls back all open transactions -// including the prepared ones. -// This is used for transitioning from a primary to a non-primary -// serving type. +// shutdownTransactions rolls back all open transactions that are idol. +// These are transactions that are open but no write is executing on them right now. +// By definition, prepared transactions aren't part of them since these are transactions on which +// the user has issued a commit command. These transactions are rollbacked elsewhere when we kill all writes. +// This is used for transitioning from a primary to a non-primary serving type. func (te *TxEngine) shutdownTransactions() { - te.rollbackPrepared() ctx := tabletenv.LocalContext() - // The order of rollbacks is currently not material because - // we don't allow new statements or commits during - // this function. In case of any such change, this will - // have to be revisited. te.txPool.Shutdown(ctx) } -func (te *TxEngine) rollbackPrepared() { +// RollbackPrepared rollbacks all the prepared transactions. +// This should only be called after we are certain no other writes are in progress. +// If there were some other conflicting write in progress that hadn't been killed, then it could potentially go through +// and cause data corruption since we won't be able to prepare the transaction again. +func (te *TxEngine) RollbackPrepared() { ctx := tabletenv.LocalContext() - for _, conn := range te.preparedPool.FetchAll() { + for _, conn := range te.preparedPool.FetchAllForRollback() { te.txPool.Rollback(ctx, conn) conn.Release(tx.TxRollback) } } -// 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() } @@ -605,3 +618,22 @@ func (te *TxEngine) Release(connID int64) error { return nil } + +// beginNewDbaConnection gets a new dba connection and starts a transaction in it. +// This should only be used to redo prepared transactions. All the other writes should use the normal pool. +func (te *TxEngine) beginNewDbaConnection(ctx context.Context) (*StatefulConnection, error) { + dbConn, err := connpool.NewConn(ctx, te.env.Config().DB.DbaWithDB(), nil, nil, te.env) + if err != nil { + return nil, err + } + + sc := &StatefulConnection{ + dbConn: &connpool.PooledConn{ + Conn: dbConn, + }, + env: te.env, + } + + _, _, err = te.txPool.begin(ctx, nil, false, sc, nil) + return sc, err +} 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/tx_pool_test.go b/go/vt/vttablet/tabletserver/tx_pool_test.go index aa2d5b69e89..e80f1edb17f 100644 --- a/go/vt/vttablet/tabletserver/tx_pool_test.go +++ b/go/vt/vttablet/tabletserver/tx_pool_test.go @@ -365,7 +365,7 @@ func TestTxPoolGetConnRecentlyRemovedTransaction(t *testing.T) { assertErrorMatch := func(id int64, reason string) { conn, err := txPool.GetAndLock(id, "for query") if err == nil { // - conn.Releasef("fail") + conn.ReleaseString("fail") t.Errorf("expected to get an error") return } @@ -385,7 +385,7 @@ func TestTxPoolGetConnRecentlyRemovedTransaction(t *testing.T) { _, err := txPool.Commit(ctx, conn1) require.NoError(t, err) - conn1.Releasef("transaction committed") + conn1.ReleaseString("transaction committed") assertErrorMatch(id, "transaction committed") diff --git a/go/vt/vttablet/tabletserver/tx_prep_pool.go b/go/vt/vttablet/tabletserver/tx_prep_pool.go index 89547570cfc..468c160c002 100644 --- a/go/vt/vttablet/tabletserver/tx_prep_pool.go +++ b/go/vt/vttablet/tabletserver/tx_prep_pool.go @@ -17,14 +17,16 @@ limitations under the License. package tabletserver import ( - "errors" "fmt" "sync" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" ) var ( - errPrepCommitting = errors.New("committing") - errPrepFailed = errors.New("failed") + errPrepCommitting = vterrors.VT09025("locked for committing") + errPrepFailed = vterrors.VT09025("failed to commit") ) // TxPreparedPool manages connections for prepared transactions. @@ -34,35 +36,65 @@ type TxPreparedPool struct { mu sync.Mutex conns map[string]*StatefulConnection reserved map[string]error + // open tells if the prepared pool is open for accepting transactions. + open bool capacity int + // twoPCEnabled is set to true if 2PC is enabled. + twoPCEnabled bool } // NewTxPreparedPool creates a new TxPreparedPool. -func NewTxPreparedPool(capacity int) *TxPreparedPool { +func NewTxPreparedPool(capacity int, twoPCEnabled bool) *TxPreparedPool { if capacity < 0 { // If capacity is 0 all prepares will fail. capacity = 0 } return &TxPreparedPool{ - conns: make(map[string]*StatefulConnection, capacity), - reserved: make(map[string]error), - capacity: capacity, + conns: make(map[string]*StatefulConnection, capacity), + reserved: make(map[string]error), + capacity: capacity, + twoPCEnabled: twoPCEnabled, } } +// Open marks the prepared pool open for use. +func (pp *TxPreparedPool) Open() { + pp.mu.Lock() + defer pp.mu.Unlock() + pp.open = true +} + +// Close marks the prepared pool closed. +func (pp *TxPreparedPool) Close() { + pp.mu.Lock() + defer pp.mu.Unlock() + pp.open = false +} + +// IsOpen checks if the prepared pool is open for use. +func (pp *TxPreparedPool) IsOpen() bool { + pp.mu.Lock() + defer pp.mu.Unlock() + return pp.open +} + // Put adds the connection to the pool. It returns an error // if the pool is full or on duplicate key. func (pp *TxPreparedPool) Put(c *StatefulConnection, dtid string) error { pp.mu.Lock() defer pp.mu.Unlock() + // If the pool is shutdown, we don't accept new prepared transactions. + if !pp.open { + return vterrors.VT09025("pool is shutdown") + } if _, ok := pp.reserved[dtid]; ok { - return errors.New("duplicate DTID in Prepare: " + dtid) + return vterrors.VT09025("duplicate DTID in Prepare: " + dtid) } if _, ok := pp.conns[dtid]; ok { - return errors.New("duplicate DTID in Prepare: " + dtid) + return vterrors.VT09025("duplicate DTID in Prepare: " + dtid) } if len(pp.conns) >= pp.capacity { - return fmt.Errorf("prepared transactions exceeded limit: %d", pp.capacity) + return vterrors.New(vtrpcpb.Code_RESOURCE_EXHAUSTED, fmt.Sprintf("prepared transactions exceeded limit: %d", pp.capacity)) } pp.conns[dtid] = c return nil @@ -95,6 +127,11 @@ func (pp *TxPreparedPool) FetchForRollback(dtid string) *StatefulConnection { func (pp *TxPreparedPool) FetchForCommit(dtid string) (*StatefulConnection, error) { pp.mu.Lock() defer pp.mu.Unlock() + // If the pool is shutdown, we don't have any connections to return. + // That however doesn't mean this transaction was committed, it could very well have been rollbacked. + if !pp.open { + return nil, vterrors.VT09025("pool is shutdown") + } if err, ok := pp.reserved[dtid]; ok { return nil, err } @@ -121,11 +158,12 @@ func (pp *TxPreparedPool) Forget(dtid string) { delete(pp.reserved, dtid) } -// FetchAll removes all connections and returns them as a list. +// FetchAllForRollback removes all connections and returns them as a list. // It also forgets all reserved dtids. -func (pp *TxPreparedPool) FetchAll() []*StatefulConnection { +func (pp *TxPreparedPool) FetchAllForRollback() []*StatefulConnection { pp.mu.Lock() defer pp.mu.Unlock() + pp.open = false conns := make([]*StatefulConnection, 0, len(pp.conns)) for _, c := range pp.conns { conns = append(conns, c) @@ -134,3 +172,25 @@ func (pp *TxPreparedPool) FetchAll() []*StatefulConnection { pp.reserved = make(map[string]error) return conns } + +func (pp *TxPreparedPool) IsEmpty(tableName string) bool { + pp.mu.Lock() + defer pp.mu.Unlock() + if !pp.twoPCEnabled { + return true + } + // If the pool is shutdown, we do not know the correct state of prepared transactions. + if !pp.open { + return false + } + for _, connection := range pp.conns { + for _, query := range connection.txProps.Queries { + for _, table := range query.Tables { + if table == tableName { + return false + } + } + } + } + return true +} diff --git a/go/vt/vttablet/tabletserver/tx_prep_pool_test.go b/go/vt/vttablet/tabletserver/tx_prep_pool_test.go index a1cf50edb56..cf6d2b61093 100644 --- a/go/vt/vttablet/tabletserver/tx_prep_pool_test.go +++ b/go/vt/vttablet/tabletserver/tx_prep_pool_test.go @@ -19,48 +19,38 @@ package tabletserver import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestEmptyPrep(t *testing.T) { - pp := NewTxPreparedPool(0) - want := "prepared transactions exceeded limit: 0" + pp := createAndOpenPreparedPool(0) err := pp.Put(nil, "aa") - if err == nil || err.Error() != want { - t.Errorf("Put err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "prepared transactions exceeded limit: 0") } func TestPrepPut(t *testing.T) { - pp := NewTxPreparedPool(2) + pp := createAndOpenPreparedPool(2) err := pp.Put(nil, "aa") require.NoError(t, err) err = pp.Put(nil, "bb") require.NoError(t, err) - want := "prepared transactions exceeded limit: 2" err = pp.Put(nil, "cc") - if err == nil || err.Error() != want { - t.Errorf("Put err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "prepared transactions exceeded limit: 2") err = pp.Put(nil, "aa") - want = "duplicate DTID in Prepare: aa" - if err == nil || err.Error() != want { - t.Errorf("Put err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "duplicate DTID in Prepare: aa") + _, err = pp.FetchForCommit("aa") require.NoError(t, err) err = pp.Put(nil, "aa") - want = "duplicate DTID in Prepare: aa" - if err == nil || err.Error() != want { - t.Errorf("Put err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "duplicate DTID in Prepare: aa") pp.Forget("aa") err = pp.Put(nil, "aa") require.NoError(t, err) } func TestPrepFetchForRollback(t *testing.T) { - pp := NewTxPreparedPool(2) + pp := createAndOpenPreparedPool(2) conn := &StatefulConnection{} pp.Put(conn, "aa") got := pp.FetchForRollback("bb") @@ -78,55 +68,51 @@ func TestPrepFetchForRollback(t *testing.T) { } func TestPrepFetchForCommit(t *testing.T) { - pp := NewTxPreparedPool(2) + pp := createAndOpenPreparedPool(2) conn := &StatefulConnection{} got, err := pp.FetchForCommit("aa") require.NoError(t, err) - if got != nil { - t.Errorf("Get(aa): %v, want nil", got) - } + assert.Nil(t, got) + pp.Put(conn, "aa") got, err = pp.FetchForCommit("aa") require.NoError(t, err) - if got != conn { - t.Errorf("pp.Get(aa): %p, want %p", got, conn) - } + assert.Equal(t, conn, got) + _, err = pp.FetchForCommit("aa") - want := "committing" - if err == nil || err.Error() != want { - t.Errorf("FetchForCommit err: %v, want %s", err, want) - } + assert.ErrorContains(t, err, "locked for committing") + pp.SetFailed("aa") _, err = pp.FetchForCommit("aa") - want = "failed" - if err == nil || err.Error() != want { - t.Errorf("FetchForCommit err: %v, want %s", err, want) - } + assert.ErrorContains(t, err, "failed to commit") + pp.SetFailed("bb") _, err = pp.FetchForCommit("bb") - want = "failed" - if err == nil || err.Error() != want { - t.Errorf("FetchForCommit err: %v, want %s", err, want) - } + assert.ErrorContains(t, err, "failed to commit") + pp.Forget("aa") got, err = pp.FetchForCommit("aa") require.NoError(t, err) - if got != nil { - t.Errorf("Get(aa): %v, want nil", got) - } + assert.Nil(t, got) } func TestPrepFetchAll(t *testing.T) { - pp := NewTxPreparedPool(2) + pp := createAndOpenPreparedPool(2) conn1 := &StatefulConnection{} conn2 := &StatefulConnection{} pp.Put(conn1, "aa") pp.Put(conn2, "bb") - got := pp.FetchAll() - if len(got) != 2 { - t.Errorf("FetchAll len: %d, want 2", len(got)) - } - if len(pp.conns) != 0 { - t.Errorf("len(pp.conns): %d, want 0", len(pp.conns)) - } + got := pp.FetchAllForRollback() + require.Len(t, got, 2) + require.Len(t, pp.conns, 0) + _, err := pp.FetchForCommit("aa") + require.ErrorContains(t, err, "pool is shutdown") +} + +// createAndOpenPreparedPool creates a new transaction prepared pool and opens it. +// Used as a helper function for testing. +func createAndOpenPreparedPool(capacity int) *TxPreparedPool { + pp := NewTxPreparedPool(capacity, true) + pp.Open() + return pp } diff --git a/go/vt/vttablet/tabletserver/txlogz_test.go b/go/vt/vttablet/tabletserver/txlogz_test.go index 319669a0023..8faec74d07b 100644 --- a/go/vt/vttablet/tabletserver/txlogz_test.go +++ b/go/vt/vttablet/tabletserver/txlogz_test.go @@ -60,7 +60,7 @@ func testHandler(req *http.Request, t *testing.T) { ImmediateCaller: callerid.NewImmediateCallerID("immediate-caller"), StartTime: time.Now(), Conclusion: "unknown", - Queries: []string{"select * from test"}, + Queries: []tx.Query{{Sql: "select * from test"}}, }, } txConn.txProps.EndTime = txConn.txProps.StartTime 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 7cb774663a4..18fafa8eb96 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) } } @@ -70,21 +69,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" @@ -159,7 +143,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 stopHealthCheck context.CancelFunc healthCheck discovery.HealthCheck @@ -304,6 +288,7 @@ func newTxThrottlerState(txThrottler *txThrottler, config *tabletenv.TabletConfi ctx, cancel := context.WithCancel(context.Background()) state.stopHealthCheck = cancel state.initHealthCheckStream(txThrottler.topoServer, target) + state.healthCheck.RegisterStats() go state.healthChecksProcessor(ctx, txThrottler.topoServer, target) state.waitForTermination.Add(1) go state.updateMaxLag() @@ -314,7 +299,6 @@ func newTxThrottlerState(txThrottler *txThrottler, config *tabletenv.TabletConfi func (ts *txThrottlerStateImpl) initHealthCheckStream(topoServer *topo.Server, target *querypb.Target) { ts.healthCheck = healthCheckFactory(topoServer, target.Cell, ts.healthCheckCells) ts.healthCheckChan = ts.healthCheck.Subscribe() - } func (ts *txThrottlerStateImpl) closeHealthCheckStream() { @@ -330,7 +314,7 @@ func (ts *txThrottlerStateImpl) updateHealthCheckCells(ctx context.Context, topo defer cancel() knownCells := fetchKnownCells(fetchCtx, topoServer, 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.closeHealthCheckStream() diff --git a/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go b/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go index fe352cf96f4..25c855b898b 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" @@ -69,14 +69,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/copy.go b/go/vt/vttablet/tabletserver/vstreamer/copy.go index 2f54ea235fe..31a2f2efc6c 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/copy.go +++ b/go/vt/vttablet/tabletserver/vstreamer/copy.go @@ -74,7 +74,7 @@ func (uvs *uvstreamer) catchup(ctx context.Context) error { errch := make(chan error, 1) go func() { startPos := replication.EncodePosition(uvs.pos) - vs := newVStreamer(ctx, uvs.cp, uvs.se, startPos, "", uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send2, "catchup", uvs.vse) + vs := newVStreamer(ctx, uvs.cp, uvs.se, startPos, "", uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send2, "catchup", uvs.vse, nil) uvs.setVs(vs) errch <- vs.Stream() uvs.setVs(nil) @@ -333,7 +333,7 @@ func (uvs *uvstreamer) fastForward(stopPos string) error { }() log.Infof("starting fastForward from %s upto pos %s", replication.EncodePosition(uvs.pos), stopPos) uvs.stopPos, _ = replication.DecodePosition(stopPos) - vs := newVStreamer(uvs.ctx, uvs.cp, uvs.se, replication.EncodePosition(uvs.pos), "", uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send2, "fastforward", uvs.vse) + vs := newVStreamer(uvs.ctx, uvs.cp, uvs.se, replication.EncodePosition(uvs.pos), "", uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send2, "fastforward", uvs.vse, nil) uvs.setVs(vs) return vs.Stream() } diff --git a/go/vt/vttablet/tabletserver/vstreamer/engine.go b/go/vt/vttablet/tabletserver/vstreamer/engine.go index 501b3708eed..b391f5bac3d 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), @@ -232,7 +233,10 @@ func (vse *Engine) validateBinlogRowImage(ctx context.Context, db dbconfigs.Conn // Stream starts a new stream. // This streams events from the binary logs -func (vse *Engine) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) error { +func (vse *Engine) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK, + filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name, + send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) error { + if err := vse.validateBinlogRowImage(ctx, vse.se.GetDBConnector()); err != nil { return err } @@ -249,7 +253,8 @@ func (vse *Engine) Stream(ctx context.Context, startPos string, tablePKs []*binl } vse.mu.Lock() defer vse.mu.Unlock() - streamer := newUVStreamer(ctx, vse, vse.env.Config().DB.FilteredWithDB(), vse.se, startPos, tablePKs, filter, vse.lvschema, throttlerApp, send) + streamer := newUVStreamer(ctx, vse, vse.env.Config().DB.FilteredWithDB(), vse.se, startPos, tablePKs, + filter, vse.lvschema, throttlerApp, send, options) idx := vse.streamIdx vse.streamers[idx] = streamer vse.streamIdx++ diff --git a/go/vt/vttablet/tabletserver/vstreamer/engine_test.go b/go/vt/vttablet/tabletserver/vstreamer/engine_test.go index b0b31e256cc..7cafcc6d485 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/engine_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/engine_test.go @@ -96,7 +96,7 @@ func TestUpdateVSchema(t *testing.T) { // Stream should terminate immediately due to invalid pos. _ = engine.Stream(ctx, "invalid", nil, filter, throttlerapp.VStreamerName, func(_ []*binlogdatapb.VEvent) error { return nil - }) + }, nil) startCount := expectUpdateCount(t, 1) @@ -106,6 +106,7 @@ func TestUpdateVSchema(t *testing.T) { expectUpdateCount(t, startCount+1) want := `{ + "mirror_rules": {}, "routing_rules": {}, "keyspaces": { "vttest": { diff --git a/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go b/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go index 49dabae3973..c52e81564c0 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go @@ -158,10 +158,10 @@ func (s *TestRowEventSpec) String() string { TableName: s.table, } var rowChanges []*binlogdatapb.RowChange - if s.changes != nil && len(s.changes) > 0 { + if len(s.changes) > 0 { for _, c := range s.changes { rowChange := binlogdatapb.RowChange{} - if c.before != nil && len(c.before) > 0 { + if len(c.before) > 0 { rowChange.Before = &query.Row{} for _, val := range c.before { if val == sqltypes.NullStr { @@ -171,7 +171,7 @@ func (s *TestRowEventSpec) String() string { rowChange.Before.Values = append(rowChange.Before.Values, []byte(val)...) } } - if c.after != nil && len(c.after) > 0 { + if len(c.after) > 0 { rowChange.After = &query.Row{} for i, val := range c.after { if val == sqltypes.NullStr { @@ -318,7 +318,7 @@ func (ts *TestSpec) Init() { // Close() should be called (via defer) at the end of the test to clean up the tables created in the test. func (ts *TestSpec) Close() { - dropStatement := fmt.Sprintf("drop tables %s", strings.Join(ts.schema.TableNames(), ", ")) + dropStatement := fmt.Sprintf("drop table if exists %s", strings.Join(ts.schema.TableNames(), ", ")) execStatement(ts.t, dropStatement) } @@ -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/main_test.go b/go/vt/vttablet/tabletserver/vstreamer/main_test.go index aade1511060..7140f8140d9 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/main_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/main_test.go @@ -323,7 +323,7 @@ func vstream(ctx context.Context, t *testing.T, pos string, tablePKs []*binlogda return io.EOF } return nil - }) + }, nil) } func execStatement(t *testing.T, query string) { diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go index 2c768d7d3c6..9bbc98ca2bd 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go @@ -64,6 +64,9 @@ type Plan struct { EnumSetValuesMap map[int](map[int]string) env *vtenv.Environment + + // IsInternal is set to true if the plan is for a sidecar table. + IsInternal bool } // Opcode enumerates the operators supported in a where clause diff --git a/go/vt/vttablet/tabletserver/vstreamer/resultstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/resultstreamer.go index 4632bea672b..b6294cd1939 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/resultstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/resultstreamer.go @@ -109,7 +109,7 @@ func (rs *resultStreamer) Stream() error { } // check throttler. - if !rs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(rs.ctx, throttlerapp.ResultStreamerName) { + if _, ok := rs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(rs.ctx, throttlerapp.ResultStreamerName); !ok { logger.Infof("throttled.") continue } diff --git a/go/vt/vttablet/tabletserver/vstreamer/rowstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/rowstreamer.go index bb8ff7af85f..6015590dad7 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/rowstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/rowstreamer.go @@ -388,9 +388,9 @@ func (rs *rowStreamer) streamQuery(send func(*binlogdatapb.VStreamRowsResponse) } // check throttler. - if !rs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(rs.ctx, throttlerapp.RowStreamerName) { + if checkResult, ok := rs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(rs.ctx, throttlerapp.RowStreamerName); !ok { throttleResponseRateLimiter.Do(func() error { - return safeSend(&binlogdatapb.VStreamRowsResponse{Throttled: true}) + return safeSend(&binlogdatapb.VStreamRowsResponse{Throttled: true, ThrottledReason: checkResult.Summary()}) }) logger.Infof("throttled.") continue 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/uvstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/uvstreamer.go index 2b770c1d4f4..ea475d19676 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/uvstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/uvstreamer.go @@ -88,7 +88,8 @@ type uvstreamer struct { config *uvstreamerConfig - vs *vstreamer //last vstreamer created in uvstreamer + vs *vstreamer // last vstreamer created in uvstreamer + options *binlogdatapb.VStreamOptions } type uvstreamerConfig struct { @@ -96,7 +97,10 @@ type uvstreamerConfig struct { CatchupRetryTime time.Duration } -func newUVStreamer(ctx context.Context, vse *Engine, cp dbconfigs.Connector, se *schema.Engine, startPos string, tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, vschema *localVSchema, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error) *uvstreamer { +func newUVStreamer(ctx context.Context, vse *Engine, cp dbconfigs.Connector, se *schema.Engine, startPos string, + tablePKs []*binlogdatapb.TableLastPK, filter *binlogdatapb.Filter, vschema *localVSchema, + throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions) *uvstreamer { + ctx, cancel := context.WithCancel(ctx) config := &uvstreamerConfig{ MaxReplicationLag: 1 * time.Nanosecond, @@ -123,6 +127,7 @@ func newUVStreamer(ctx context.Context, vse *Engine, cp dbconfigs.Connector, se config: config, inTablePKs: tablePKs, throttlerApp: throttlerApp, + options: options, } return uvs @@ -138,6 +143,9 @@ func (uvs *uvstreamer) buildTablePlan() error { uvs.plans = make(map[string]*tablePlan) tableLastPKs := make(map[string]*binlogdatapb.TableLastPK) for _, tablePK := range uvs.inTablePKs { + if tablePK != nil && tablePK.Lastpk != nil && len(tablePK.Lastpk.Fields) == 0 { + return fmt.Errorf("lastpk for table %s has no fields defined", tablePK.TableName) + } tableLastPKs[tablePK.TableName] = tablePK } tables := uvs.se.GetSchema() @@ -313,7 +321,6 @@ func (uvs *uvstreamer) send2(evs []*binlogdatapb.VEvent) error { } behind := time.Now().UnixNano() - uvs.lastTimestampNs uvs.setReplicationLagSeconds(behind / 1e9) - //log.Infof("sbm set to %d", uvs.ReplicationLagSeconds) var evs2 []*binlogdatapb.VEvent if len(uvs.plans) > 0 { evs2 = uvs.filterEvents(evs) @@ -425,7 +432,7 @@ func (uvs *uvstreamer) Stream() error { } } vs := newVStreamer(uvs.ctx, uvs.cp, uvs.se, replication.EncodePosition(uvs.pos), replication.EncodePosition(uvs.stopPos), - uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send, "replicate", uvs.vse) + uvs.filter, uvs.getVSchema(), uvs.throttlerApp, uvs.send, "replicate", uvs.vse, uvs.options) uvs.setVs(vs) return vs.Stream() diff --git a/go/vt/vttablet/tabletserver/vstreamer/uvstreamer_flaky_test.go b/go/vt/vttablet/tabletserver/vstreamer/uvstreamer_flaky_test.go index 389c06a671e..e2972bb7071 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/uvstreamer_flaky_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/uvstreamer_flaky_test.go @@ -454,7 +454,7 @@ func startVStreamCopy(ctx context.Context, t *testing.T, filter *binlogdatapb.Fi pos := "" go func() { err := engine.Stream(ctx, pos, tablePKs, filter, throttlerapp.VStreamerName, func(evs []*binlogdatapb.VEvent) error { - //t.Logf("Received events: %v", evs) + // t.Logf("Received events: %v", evs) muAllEvents.Lock() defer muAllEvents.Unlock() for _, ev := range evs { @@ -474,7 +474,7 @@ func startVStreamCopy(ctx context.Context, t *testing.T, filter *binlogdatapb.Fi allEvents = append(allEvents, ev) } return nil - }) + }, nil) require.Nil(t, err) }() } @@ -503,7 +503,7 @@ var expectedEvents = []string{ "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"} enum_set_string_values:true}", "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"11110\"}}}", "type:GTID", - "type:COMMIT", //insert for t2 done along with t1 does not generate an event since t2 is not yet copied + "type:COMMIT", // insert for t2 done along with t1 does not generate an event since t2 is not yet copied fmt.Sprintf("type:OTHER gtid:\"%s t2\"", copyPhaseStart), "type:BEGIN", "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"} enum_set_string_values:true}", diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go index bf41111bbc8..00560a2526a 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go @@ -31,7 +31,6 @@ import ( "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/timer" "vitess.io/vitess/go/vt/binlog" "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" @@ -84,8 +83,9 @@ type vstreamer struct { pos replication.Position stopPos string - phase string - vse *Engine + phase string + vse *Engine + options *binlogdatapb.VStreamOptions } // streamerPlan extends the original plan to also include @@ -118,7 +118,9 @@ type streamerPlan struct { // // vschema: the current vschema. This value can later be changed through the SetVSchema method. // send: callback function to send events. -func newVStreamer(ctx context.Context, cp dbconfigs.Connector, se *schema.Engine, startPos string, stopPos string, filter *binlogdatapb.Filter, vschema *localVSchema, throttlerApp throttlerapp.Name, send func([]*binlogdatapb.VEvent) error, phase string, vse *Engine) *vstreamer { +func newVStreamer(ctx context.Context, cp dbconfigs.Connector, se *schema.Engine, startPos string, stopPos string, + filter *binlogdatapb.Filter, vschema *localVSchema, throttlerApp throttlerapp.Name, + send func([]*binlogdatapb.VEvent) error, phase string, vse *Engine, options *binlogdatapb.VStreamOptions) *vstreamer { ctx, cancel := context.WithCancel(ctx) return &vstreamer{ ctx: ctx, @@ -135,6 +137,7 @@ func newVStreamer(ctx context.Context, cp dbconfigs.Connector, se *schema.Engine plans: make(map[uint64]*streamerPlan), phase: phase, vse: vse, + options: options, } } @@ -287,41 +290,40 @@ func (vs *vstreamer) parseEvents(ctx context.Context, events <-chan mysql.Binlog hbTimer := time.NewTimer(HeartbeatTime) defer hbTimer.Stop() - injectHeartbeat := func(throttled bool) error { - now := time.Now().UnixNano() + injectHeartbeat := func(throttled bool, throttledReason string) error { select { case <-ctx.Done(): return vterrors.Errorf(vtrpcpb.Code_CANCELED, "context has expired") default: + now := time.Now().UnixNano() err := bufferAndTransmit(&binlogdatapb.VEvent{ - Type: binlogdatapb.VEventType_HEARTBEAT, - Timestamp: now / 1e9, - CurrentTime: now, - Throttled: throttled, + Type: binlogdatapb.VEventType_HEARTBEAT, + Timestamp: now / 1e9, + CurrentTime: now, + Throttled: throttled, + ThrottledReason: throttledReason, }) return err } } logger := logutil.NewThrottledLogger(vs.vse.GetTabletInfo(), throttledLoggerInterval) + wfNameLog := "" + if vs.filter != nil && vs.filter.WorkflowName != "" { + wfNameLog = fmt.Sprintf(" in workflow %s", vs.filter.WorkflowName) + } throttleEvents := func(throttledEvents chan mysql.BinlogEvent) { - throttledHeartbeatsRateLimiter := timer.NewRateLimiter(HeartbeatTime) - defer throttledHeartbeatsRateLimiter.Stop() for { - // check throttler. - if !vs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, vs.throttlerApp) { - // make sure to leave if context is cancelled + // Check throttler. + if checkResult, ok := vs.vse.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, vs.throttlerApp); !ok { + // Make sure to leave if context is cancelled. select { case <-ctx.Done(): return default: - // do nothing special + // Do nothing special. } - throttledHeartbeatsRateLimiter.Do(func() error { - return injectHeartbeat(true) - }) - // we won't process events, until we're no longer throttling - logger.Infof("throttled.") + logger.Infof("vstreamer throttled%s: %s.", wfNameLog, checkResult.Summary()) continue } select { @@ -393,7 +395,8 @@ func (vs *vstreamer) parseEvents(ctx context.Context, events <-chan mysql.Binlog case <-ctx.Done(): return nil case <-hbTimer.C: - if err := injectHeartbeat(false); err != nil { + checkResult, ok := vs.vse.throttlerClient.ThrottleCheckOK(ctx, vs.throttlerApp) + if err := injectHeartbeat(!ok, checkResult.Summary()); err != nil { if err == io.EOF { return nil } @@ -566,26 +569,28 @@ func (vs *vstreamer) parseEvent(ev mysql.BinlogEvent) ([]*binlogdatapb.VEvent, e if err != nil { return nil, err } - if plan, ok := vs.plans[id]; ok { // When the underlying mysql server restarts the table map can change. // Usually the vstreamer will also error out when this happens, and vstreamer re-initializes its table map. // But if the vstreamer is not aware of the restart, we could get an id that matches one in the cache, but // is for a different table. We then invalidate and recompute the plan for this id. - if plan == nil || plan.Table.Name == tm.Name { + isInternal := tm.Database == sidecar.GetName() + if plan == nil || + (plan.Table.Name == tm.Name && isInternal == plan.IsInternal) { return nil, nil } vs.plans[id] = nil log.Infof("table map changed: id %d for %s has changed to %s", id, plan.Table.Name, tm.Name) } - if tm.Database == sidecar.GetName() && tm.Name == "resharding_journal" { - // A journal is a special case that generates a JOURNAL event. - return nil, vs.buildJournalPlan(id, tm) - } else if tm.Database == sidecar.GetName() && tm.Name == "schema_version" && !vs.se.SkipMetaCheck { - // Generates a Version event when it detects that a schema is stored in the schema_version table. - return nil, vs.buildVersionPlan(id, tm) + // The database connector `vs.cp` points to the keyspace's database. + // If this is also setup as the sidecar database name, as is the case in the distributed transaction unit tests, + // for example, we stream all tables as usual. + // If not, we only stream the schema_version and journal tables and those specified in the internal_tables list. + if tm.Database == sidecar.GetName() && vs.cp.DBName() != sidecar.GetName() { + return vs.buildSidecarTablePlan(id, tm) } + if tm.Database != "" && tm.Database != vs.cp.DBName() { vs.plans[id] = nil return nil, nil @@ -642,15 +647,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") @@ -666,72 +679,84 @@ func (vs *vstreamer) parseEvent(ev mysql.BinlogEvent) ([]*binlogdatapb.VEvent, e return vevents, nil } -func (vs *vstreamer) buildJournalPlan(id uint64, tm *mysql.TableMap) error { - conn, err := vs.cp.Connect(vs.ctx) - if err != nil { - return err - } - defer conn.Close() - qr, err := conn.ExecuteFetch(sqlparser.BuildParsedQuery("select * from %s.resharding_journal where 1 != 1", - sidecar.GetIdentifier()).Query, 1, true) - if err != nil { - return err - } - fields := qr.Fields - if len(fields) < len(tm.Types) { - return fmt.Errorf("cannot determine table columns for %s: event has %v, schema has %v", tm.Name, tm.Types, fields) - } - table := &Table{ - Name: fmt.Sprintf("%s.resharding_journal", sidecar.GetIdentifier()), - Fields: fields[:len(tm.Types)], - } - // Build a normal table plan, which means, return all rows - // and columns as is. Special handling is done when we actually - // receive the row event. We'll build a JOURNAL event instead. - plan, err := buildREPlan(vs.se.Environment(), table, nil, "") - if err != nil { - return err - } - vs.plans[id] = &streamerPlan{ - Plan: plan, - TableMap: tm, +func (vs *vstreamer) buildSidecarTablePlan(id uint64, tm *mysql.TableMap) ([]*binlogdatapb.VEvent, error) { + tableName := tm.Name + switch tableName { + case "resharding_journal": + // A journal is a special case that generates a JOURNAL event. + case "schema_version": + // Generates a Version event when it detects that a schema is stored in the schema_version table. + + // SkipMetaCheck is set during PITR restore: some table metadata is not fetched in that case. + if vs.se.SkipMetaCheck { + return nil, nil + } + default: + if vs.options == nil { + return nil, nil + } + found := false + for _, table := range vs.options.InternalTables { + if table == tableName { + found = true + break + } + } + if !found { + return nil, nil + } } - vs.journalTableID = id - return nil -} -func (vs *vstreamer) buildVersionPlan(id uint64, tm *mysql.TableMap) error { conn, err := vs.cp.Connect(vs.ctx) if err != nil { - return err + return nil, err } defer conn.Close() - qr, err := conn.ExecuteFetch(sqlparser.BuildParsedQuery("select * from %s.schema_version where 1 != 1", - sidecar.GetIdentifier()).Query, 1, true) + qr, err := conn.ExecuteFetch(sqlparser.BuildParsedQuery("select * from %s.%s where 1 != 1", + sidecar.GetIdentifier(), tableName).Query, 1, true) if err != nil { - return err + return nil, err } fields := qr.Fields if len(fields) < len(tm.Types) { - return fmt.Errorf("cannot determine table columns for %s: event has %v, schema has %v", tm.Name, tm.Types, fields) + return nil, fmt.Errorf("cannot determine table columns for %s: event has %v, schema has %v", tm.Name, tm.Types, fields) } table := &Table{ - Name: fmt.Sprintf("%s.schema_version", sidecar.GetIdentifier()), + Name: tableName, Fields: fields[:len(tm.Types)], } + // Build a normal table plan, which means, return all rows - // and columns as is. Special handling is done when we actually - // receive the row event. We'll build a JOURNAL event instead. + // and columns as is. Special handling may be done when we actually + // receive the row event, example: we'll build a JOURNAL or VERSION event instead. plan, err := buildREPlan(vs.se.Environment(), table, nil, "") if err != nil { - return err + return nil, err } + plan.IsInternal = true vs.plans[id] = &streamerPlan{ Plan: plan, TableMap: tm, } - vs.versionTableID = id - return nil + + var vevents []*binlogdatapb.VEvent + switch tm.Name { + case "resharding_journal": + vs.journalTableID = id + case "schema_version": + vs.versionTableID = id + default: + vevents = append(vevents, &binlogdatapb.VEvent{ + Type: binlogdatapb.VEventType_FIELD, + FieldEvent: &binlogdatapb.FieldEvent{ + TableName: tableName, + Fields: plan.fields(), + Keyspace: vs.vse.keyspace, + Shard: vs.vse.shard, + IsInternalTable: plan.IsInternal, + }}) + } + return vevents, nil } func (vs *vstreamer) buildTablePlan(id uint64, tm *mysql.TableMap) (*binlogdatapb.VEvent, error) { @@ -986,11 +1011,12 @@ func (vs *vstreamer) processRowEvent(vevents []*binlogdatapb.VEvent, plan *strea vevents = append(vevents, &binlogdatapb.VEvent{ Type: binlogdatapb.VEventType_ROW, RowEvent: &binlogdatapb.RowEvent{ - TableName: plan.Table.Name, - RowChanges: rowChanges, - Keyspace: vs.vse.keyspace, - Shard: vs.vse.shard, - Flags: uint32(rows.Flags), + TableName: plan.Table.Name, + RowChanges: rowChanges, + Keyspace: vs.vse.keyspace, + Shard: vs.vse.shard, + Flags: uint32(rows.Flags), + IsInternalTable: plan.IsInternal, }, }) } diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go index 8d0d182790e..c265fb45b85 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "io" + "slices" "strconv" "strings" "sync" @@ -51,10 +52,7 @@ func checkIfOptionIsSupported(t *testing.T, variable string) bool { qr, err := env.Mysqld.FetchSuperQuery(context.Background(), fmt.Sprintf("show variables like '%s'", variable)) require.NoError(t, err) require.NotNil(t, qr) - if qr.Rows != nil && len(qr.Rows) == 1 { - return true - } - return false + return len(qr.Rows) == 1 } // TestPlayerNoBlob sets up a new environment with mysql running with @@ -398,6 +396,98 @@ func TestMissingTables(t *testing.T) { runCases(t, filter, testcases, startPos, nil) } +// TestSidecarDBTables tests streaming of sidecar db tables. +func TestSidecarDBTables(t *testing.T) { + ts := &TestSpec{ + t: t, + ddls: []string{ + "create table t1(id11 int, id12 int, primary key(id11))", + "create table _vt.internal1(id int, primary key(id))", + "create table _vt.internal2(id int, primary key(id))", + }, + } + ts.Init() + defer func() { + execStatements(t, []string{ + "drop table _vt.internal1", + "drop table _vt.internal2", + }) + }() + defer ts.Close() + position := primaryPosition(t) + filter := &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "t1", + Filter: "select * from t1", + }}, + } + execStatements(t, []string{ + "insert into t1 values (1, 1)", + "insert into t1 values (2, 2)", + "insert into _vt.internal1 values (1)", + "insert into _vt.internal2 values (1)", + "insert into _vt.internal2 values (2)", + }) + options := &binlogdatapb.VStreamOptions{ + InternalTables: []string{"internal1", "internal2"}, + } + ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second)) + defer cancel() + wantRowEvents := map[string]int{ + "t1": 2, + "internal1": 1, + "internal2": 2, + } + gotRowEvents := make(map[string]int) + gotFieldEvents := make(map[string]int) + err := engine.Stream(ctx, position, nil, filter, "", func(events []*binlogdatapb.VEvent) error { + for _, ev := range events { + if ev.Type == binlogdatapb.VEventType_ROW { + gotRowEvents[ev.RowEvent.TableName]++ + require.Equal(t, slices.Contains(options.InternalTables, ev.RowEvent.TableName), ev.RowEvent.IsInternalTable) + } + if ev.Type == binlogdatapb.VEventType_FIELD { + require.Equal(t, slices.Contains(options.InternalTables, ev.FieldEvent.TableName), ev.FieldEvent.IsInternalTable) + gotFieldEvents[ev.FieldEvent.TableName]++ + } + } + return nil + }, options) + require.NoError(t, err) + require.EqualValues(t, wantRowEvents, gotRowEvents) + for k, v := range gotFieldEvents { + require.Equal(t, 1, v, "gotFieldEvents[%s] = %d", k, v) + } +} + +// TestVStreamMissingFieldsInLastPK tests that we error out if the lastpk for a table is missing the fields spec. +func TestVStreamMissingFieldsInLastPK(t *testing.T) { + ts := &TestSpec{ + t: t, + ddls: []string{ + "create table t1(id11 int, id12 int, primary key(id11))", + }, + } + ts.Init() + defer ts.Close() + + filter := &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "t1", + Filter: "select * from t1", + }}, + } + var tablePKs []*binlogdatapb.TableLastPK + tablePKs = append(tablePKs, getTablePK("t1", 1)) + for _, tpk := range tablePKs { + tpk.Lastpk.Fields = nil + } + ctx := context.Background() + ch := make(chan []*binlogdatapb.VEvent) + err := vstream(ctx, t, "", tablePKs, filter, ch) + require.ErrorContains(t, err, "lastpk for table t1 has no fields defined") +} + func TestVStreamCopySimpleFlow(t *testing.T) { ts := &TestSpec{ t: t, @@ -408,7 +498,6 @@ func TestVStreamCopySimpleFlow(t *testing.T) { } ts.Init() defer ts.Close() - log.Infof("Pos before bulk insert: %s", primaryPosition(t)) insertSomeRows(t, 10) log.Infof("Pos after bulk insert: %s", primaryPosition(t)) @@ -636,11 +725,11 @@ func TestVStreamCopyWithDifferentFilters(t *testing.T) { return io.EOF } return nil - }) + }, nil) }() wg.Wait() if errGoroutine != nil { - t.Fatalf(errGoroutine.Error()) + t.Fatal(errGoroutine.Error()) } } @@ -1460,7 +1549,7 @@ func TestBestEffortNameInFieldEvent(t *testing.T) { // todo: migrate to new framework // test that vstreamer ignores tables created by OnlineDDL -func TestInternalTables(t *testing.T) { +func TestOnlineDDLTables(t *testing.T) { if version.GoOS == "darwin" { t.Skip("internal online ddl table matching doesn't work on Mac because it is case insensitive") } @@ -1736,7 +1825,7 @@ func TestMinimalMode(t *testing.T) { engine = oldEngine env = oldEnv }() - err := engine.Stream(context.Background(), "current", nil, nil, throttlerapp.VStreamerName, func(evs []*binlogdatapb.VEvent) error { return nil }) + err := engine.Stream(context.Background(), "current", nil, nil, throttlerapp.VStreamerName, func(evs []*binlogdatapb.VEvent) error { return nil }, nil) require.Error(t, err, "minimal binlog_row_image is not supported by Vitess VReplication") } diff --git a/go/vt/vttablet/tabletservermock/controller.go b/go/vt/vttablet/tabletservermock/controller.go index 33a6b94d327..1d9115392d2 100644 --- a/go/vt/vttablet/tabletservermock/controller.go +++ b/go/vt/vttablet/tabletservermock/controller.go @@ -221,6 +221,18 @@ 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 +} + +// RedoPreparedTransactions is part of the tabletserver.Controller interface +func (tqsc *Controller) RedoPreparedTransactions() {} + +// SetTwoPCAllowed sets whether TwoPC is allowed or not. +func (tqsc *Controller) SetTwoPCAllowed(bool) { +} + // 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..576a78bb761 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 @@ -292,6 +292,15 @@ func (db *LocalCluster) MySQLConnParams() mysql.ConnParams { return connParams } +func (db *LocalCluster) MySQLTCPConnParams() mysql.ConnParams { + connParams := db.mysql.Params(db.DbName()) + _, port := db.mysql.Address() + connParams.UnixSocket = "" + connParams.Host = "127.0.0.1" + connParams.Port = port + return connParams +} + // MySQLAppDebugConnParams returns a mysql.ConnParams struct that can be used // to connect directly to the mysqld service in the self-contained cluster, // using the appdebug user. It's valid only if you used MySQLOnly option. 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/keyspace.go b/go/vt/wrangler/keyspace.go index a5f7d6ae0bf..98551a084c9 100644 --- a/go/vt/wrangler/keyspace.go +++ b/go/vt/wrangler/keyspace.go @@ -19,6 +19,7 @@ package wrangler import ( "bytes" "context" + "errors" "fmt" "sync" "time" @@ -82,7 +83,7 @@ func (wr *Wrangler) validateNewWorkflow(ctx context.Context, keyspace, workflow return } if p3qr != nil && len(p3qr.Rows) != 0 { - allErrors.RecordError(vterrors.Wrap(fmt.Errorf(validation.msg), "validateWorkflowName.VReplicationExec")) + allErrors.RecordError(vterrors.Wrap(errors.New(validation.msg), "validateWorkflowName.VReplicationExec")) return } } diff --git a/go/vt/wrangler/materializer.go b/go/vt/wrangler/materializer.go index 9367c43c310..cc7ba3f1603 100644 --- a/go/vt/wrangler/materializer.go +++ b/go/vt/wrangler/materializer.go @@ -18,6 +18,7 @@ package wrangler import ( "context" + "errors" "fmt" "hash/fnv" "math" @@ -355,7 +356,7 @@ func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, ta migrationID, strings.Join(tablets, ",")) msg += fmt.Sprintf("please review and delete it before proceeding and restart the workflow using the Workflow %s.%s start", workflow, targetKeyspace) - return fmt.Errorf(msg) + return errors.New(msg) } } if autoStart { diff --git a/go/vt/wrangler/testlib/version_test.go b/go/vt/wrangler/testlib/version_test.go index cf5f3fd1487..552f7f29c04 100644 --- a/go/vt/wrangler/testlib/version_test.go +++ b/go/vt/wrangler/testlib/version_test.go @@ -56,7 +56,7 @@ func expvarHandler(gitRev *string) func(http.ResponseWriter, *http.Request) { http.Error(w, fmt.Sprintf("cannot marshal json: %s", err), http.StatusInternalServerError) return } - fmt.Fprintf(w, string(result)+"\n") + fmt.Fprint(w, string(result)+"\n") } } diff --git a/go/vt/wrangler/traffic_switcher.go b/go/vt/wrangler/traffic_switcher.go index 448f4f99734..6c6bbd933a7 100644 --- a/go/vt/wrangler/traffic_switcher.go +++ b/go/vt/wrangler/traffic_switcher.go @@ -335,7 +335,7 @@ func (wr *Wrangler) SwitchReads(ctx context.Context, targetKeyspace, workflowNam cells []string, direction workflow.TrafficSwitchDirection, dryRun bool) (*[]string, error) { // Consistently handle errors by logging and returning them. handleError := func(message string, err error) (*[]string, error) { - werr := vterrors.Errorf(vtrpcpb.Code_INTERNAL, fmt.Sprintf("%s: %v", message, err)) + werr := vterrors.Errorf(vtrpcpb.Code_INTERNAL, "%s: %v", message, err) wr.Logger().Error(werr) return nil, werr } @@ -346,7 +346,7 @@ func (wr *Wrangler) SwitchReads(ctx context.Context, targetKeyspace, workflowNam } if ts == nil { errorMsg := fmt.Sprintf("workflow %s not found in keyspace %s", workflowName, targetKeyspace) - return handleError("failed to get the current state of the workflow", fmt.Errorf(errorMsg)) + return handleError("failed to get the current state of the workflow", errors.New(errorMsg)) } log.Infof("Switching reads: %s.%s tt %+v, cells %+v, workflow state: %+v", targetKeyspace, workflowName, servedTypes, cells, ws) var switchReplicas, switchRdonly bool @@ -478,7 +478,7 @@ func (wr *Wrangler) SwitchWrites(ctx context.Context, targetKeyspace, workflowNa cancel, reverse, reverseReplication bool, dryRun, initializeTargetSequences bool) (journalID int64, dryRunResults *[]string, err error) { // Consistently handle errors by logging and returning them. handleError := func(message string, err error) (int64, *[]string, error) { - werr := vterrors.Errorf(vtrpcpb.Code_INTERNAL, fmt.Sprintf("%s: %v", message, err)) + werr := vterrors.Errorf(vtrpcpb.Code_INTERNAL, "%s: %v", message, err) wr.Logger().Error(werr) return 0, nil, werr } @@ -490,7 +490,7 @@ func (wr *Wrangler) SwitchWrites(ctx context.Context, targetKeyspace, workflowNa } if ts == nil { errorMsg := fmt.Sprintf("workflow %s not found in keyspace %s", workflowName, targetKeyspace) - return handleError("failed to get the current workflow state", fmt.Errorf(errorMsg)) + return handleError("failed to get the current workflow state", errors.New(errorMsg)) } var sw iswitcher @@ -1723,7 +1723,7 @@ func doValidateWorkflowHasCompleted(ctx context.Context, ts *trafficSwitcher) er _ = ts.ForAllSources(func(source *workflow.MigrationSource) error { wg.Add(1) if source.GetShard().IsPrimaryServing { - rec.RecordError(fmt.Errorf(fmt.Sprintf("Shard %s is still serving", source.GetShard().ShardName()))) + rec.RecordError(fmt.Errorf("Shard %s is still serving", source.GetShard().ShardName())) } wg.Done() return nil diff --git a/go/vt/wrangler/workflow.go b/go/vt/wrangler/workflow.go index 6862f5f4d3f..6e74e4c9ebd 100644 --- a/go/vt/wrangler/workflow.go +++ b/go/vt/wrangler/workflow.go @@ -2,6 +2,7 @@ package wrangler import ( "context" + "errors" "fmt" "sort" "strings" @@ -114,7 +115,7 @@ func (wr *Wrangler) NewVReplicationWorkflow(ctx context.Context, workflowType VR return nil, err } log.Infof("Workflow state is %+v", ws) - if ts != nil { //Other than on create we need to get SourceKeyspace from the workflow + if ts != nil { // Other than on create we need to get SourceKeyspace from the workflow vrw.params.TargetKeyspace = ts.targetKeyspace vrw.params.Workflow = ts.workflow vrw.params.SourceKeyspace = ts.sourceKeyspace @@ -379,7 +380,7 @@ func (vrw *VReplicationWorkflow) Complete() (*[]string, error) { } if !ws.WritesSwitched || len(ws.ReplicaCellsNotSwitched) > 0 || len(ws.RdonlyCellsNotSwitched) > 0 { - return nil, fmt.Errorf(ErrWorkflowNotFullySwitched) + return nil, errors.New(ErrWorkflowNotFullySwitched) } var renameTable workflow.TableRemovalType if vrw.params.RenameTables { @@ -404,7 +405,7 @@ func (vrw *VReplicationWorkflow) Cancel() error { } if ws.WritesSwitched || len(ws.ReplicaCellsSwitched) > 0 || len(ws.RdonlyCellsSwitched) > 0 { - return fmt.Errorf(ErrWorkflowPartiallySwitched) + return errors.New(ErrWorkflowPartiallySwitched) } if _, err := vrw.wr.DropTargets(vrw.ctx, vrw.ws.TargetKeyspace, vrw.ws.Workflow, vrw.params.KeepData, vrw.params.KeepRoutingRules, false); err != nil { return err 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/misc/errcheck_excludes.txt b/misc/errcheck_excludes.txt deleted file mode 100644 index fb689e26288..00000000000 --- a/misc/errcheck_excludes.txt +++ /dev/null @@ -1,49 +0,0 @@ -// This file contains one function signature per line, which errcheck should not warn about. -// -// The format for function signatures is `package.FunctionName`. -// The format for method signatures is `(package.Receiver).MethodName` for value receivers, -// and the format for pointer receivers is `(*package.Receiver).MethodName`. -// -// See https://github.com/kisielk/errcheck#excluding-functions for more details. - -flag.Set -(*flag.FlagSet).Parse -(flag.Value).Set - -fmt.Fprint -fmt.Fprintf - -io.WriteString(fmt.State) -io.WriteString(net/http.ResponseWriter) - -(net.Listener).Close -(net/http.ResponseWriter).Write - -(*os.File).Close -os.Remove -os.RemoveAll -os.Rename - -(*github.com/spf13/cobra.Command).Help -(*github.com/spf13/cobra.Command).MarkFlagRequired -(*github.com/spf13/cobra.Command).MarkPersistentFlagRequired -(*github.com/spf13/cobra.Command).MarkPersistentFlagFilename - -(*github.com/spf13/pflag.FlagSet).MarkDeprecated - -(*google.golang.org/grpc.ClientConn).Close -(*google.golang.org/grpc.Server).Serve - -(*vitess.io/vitess/go/bytes2.Buffer).Write -(*vitess.io/vitess/go/bytes2.Buffer).WriteByte -(*vitess.io/vitess/go/bytes2.Buffer).WriteString - -(vitess.io/vitess/go/sqltypes.BinWriter).Write - -vitess.io/vitess/go/vt/orchestrator/external/golib/log.Errore -vitess.io/vitess/go/vt/orchestrator/external/golib/log.Errorf -vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatal -vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatale -vitess.io/vitess/go/vt/orchestrator/external/golib/log.Fatalf - -(*vitess.io/vitess/go/vt/vttest.LocalCluster).TearDown diff --git a/misc/git/hooks/golangci-lint b/misc/git/hooks/golangci-lint index d152cb965a3..21313316a12 100755 --- a/misc/git/hooks/golangci-lint +++ b/misc/git/hooks/golangci-lint @@ -13,18 +13,58 @@ # See the License for the specific language governing permissions and # limitations under the License. -GOLANGCI_LINT=$(command -v golangci-lint >/dev/null 2>&1) -if [ $? -eq 1 ]; then - echo "Downloading golangci-lint..." - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.2 +# Required version of golangci-lint +REQUIRED_VERSION="v1.60.2" + +# Function to compare versions in pure Bash +version_greater_or_equal() { + local IFS=. + local i + local ver1=($1) + local ver2=($2) + + # Fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do + ver1[i]=0 + done + # Fill empty fields in ver2 with zeros + for ((i=${#ver2[@]}; i<${#ver1[@]}; i++)); do + ver2[i]=0 + done + + for ((i=0; i<${#ver1[@]}; i++)); do + if ((10#${ver1[i]} > 10#${ver2[i]})); then + return 0 + elif ((10#${ver1[i]} < 10#${ver2[i]})); then + return 1 + fi + done + return 0 +} + +# Check if golangci-lint is installed and capture the version +if ! command -v golangci-lint >/dev/null 2>&1; then + echo "golangci-lint not found. Installing version $REQUIRED_VERSION..." + go install github.com/golangci/golangci-lint/cmd/golangci-lint@$REQUIRED_VERSION +else + VERSION_OUTPUT=$(golangci-lint --version) + INSTALLED_VERSION=$(echo "$VERSION_OUTPUT" | sed -n 's/^golangci-lint has version v\([0-9.]*\).*/\1/p') + if ! version_greater_or_equal "$INSTALLED_VERSION" "${REQUIRED_VERSION#v}"; then + echo "golangci-lint version $INSTALLED_VERSION found, but $REQUIRED_VERSION or newer is required." + echo "Installing version $REQUIRED_VERSION..." + go install github.com/golangci/golangci-lint/cmd/golangci-lint@$REQUIRED_VERSION + fi fi +# Get list of Go files to lint gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '^go/.*\.go$') if [ -z "$gofiles" ]; then exit 0 fi +# Get unique directories of the Go files gopackages=$(echo "$gofiles" | xargs -n1 dirname | sort -u | paste -sd ' ' -) +# Lint the Go packages echo "Linting $gopackages" -golangci-lint run $gopackages +golangci-lint run $gopackages \ No newline at end of file diff --git a/proto/binlogdata.proto b/proto/binlogdata.proto index 1e70275e8b5..559bf8f847f 100644 --- a/proto/binlogdata.proto +++ b/proto/binlogdata.proto @@ -344,6 +344,7 @@ message RowEvent { string keyspace = 3; string shard = 4; uint32 flags = 5; // https://dev.mysql.com/doc/dev/mysql-server/latest/classbinary__log_1_1Rows__event.html + bool is_internal_table = 6; // set for sidecardb tables } // FieldEvent represents the field info for a table. @@ -360,6 +361,7 @@ message FieldEvent { // NOTE: because this is the use case, this is ONLY ever set today in // vstreams managed by the vstreamManager. bool enum_set_string_values = 25; + bool is_internal_table = 26; // set for sidecardb tables } // ShardGtid contains the GTID position for one shard. @@ -458,6 +460,8 @@ message VEvent { string shard = 23; // indicate that we are being throttled right now bool throttled = 24; + // ThrottledReason is a human readable string that explains why the stream is throttled + string throttled_reason = 25; } message MinimalTable { @@ -474,6 +478,10 @@ message MinimalSchema { repeated MinimalTable tables = 1; } +message VStreamOptions { + repeated string internal_tables = 1; +} + // VStreamRequest is the payload for VStreamer message VStreamRequest { vtrpc.CallerID effective_caller_id = 1; @@ -483,6 +491,8 @@ message VStreamRequest { string position = 4; Filter filter = 5; repeated TableLastPK table_last_p_ks = 6; + + VStreamOptions options = 7; } // VStreamResponse is the response from VStreamer @@ -511,6 +521,8 @@ message VStreamRowsResponse { bool throttled = 6; // Heartbeat indicates that this is a heartbeat message bool heartbeat = 7; + // ThrottledReason is a human readable string that explains why the stream is throttled + string throttled_reason = 8; } 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/tabletmanagerdata.proto b/proto/tabletmanagerdata.proto index ffe4aa29abf..24adde72098 100644 --- a/proto/tabletmanagerdata.proto +++ b/proto/tabletmanagerdata.proto @@ -657,6 +657,7 @@ message VDiffReportOptions { bool debug_query = 2; string format = 3; int64 max_sample_rows = 4; + int64 row_diff_column_truncate_at = 5; } message VDiffCoreOptions { @@ -736,6 +737,14 @@ message CheckThrottlerRequest { bool multi_metrics_enabled = 5; } +enum CheckThrottlerResponseCode { + UNDEFINED = 0; + OK = 1; + THRESHOLD_EXCEEDED = 2; + APP_DENIED = 3; + UNKNOWN_METRIC = 4; + INTERNAL_ERROR = 5; +} message CheckThrottlerResponse { // StatusCode is HTTP compliant response code (e.g. 200 for OK) @@ -767,10 +776,21 @@ message CheckThrottlerResponse { string message = 6; // Scope used in this check string scope = 7; + // ResponseCode is the enum representation of the response + CheckThrottlerResponseCode response_code = 8; } // 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; + + // AppName is the name of app that was matched by the throttler + string app_name = 8; + + // Summary is a human readable analysis of the result + string summary = 9; + + // ResponseCode is the enum representation of the response + CheckThrottlerResponseCode response_code = 10; } message GetThrottlerStatusRequest { @@ -829,6 +849,8 @@ message GetThrottlerStatusResponse { message RecentApp { vttime.Time checked_at = 1; int32 status_code = 2; + // ResponseCode is the enum representation of the response + CheckThrottlerResponseCode response_code = 3; } // RecentApps is a map of app names to their recent check status map recent_apps = 18; diff --git a/proto/vtadmin.proto b/proto/vtadmin.proto index d6f1047fc1e..310ae95bcba 100644 --- a/proto/vtadmin.proto +++ b/proto/vtadmin.proto @@ -126,6 +126,12 @@ service VTAdmin { rpc GetWorkflow(GetWorkflowRequest) returns (Workflow) {}; // GetWorkflows returns the Workflows for all specified clusters. rpc GetWorkflows(GetWorkflowsRequest) returns (GetWorkflowsResponse) {}; + // GetWorkflowStatus returns the status for a specific workflow. + rpc GetWorkflowStatus(GetWorkflowStatusRequest) returns (vtctldata.WorkflowStatusResponse) {}; + // StartWorkflow starts a vreplication workflow. + rpc StartWorkflow(StartWorkflowRequest) returns (vtctldata.WorkflowUpdateResponse) {}; + // StopWorkflow stops a vreplication workflow. + rpc StopWorkflow(StopWorkflowRequest) returns (vtctldata.WorkflowUpdateResponse) {}; // LaunchSchemaMigration launches one or all migrations in the given // cluster executed with --postpone-launch. rpc LaunchSchemaMigration(LaunchSchemaMigrationRequest) returns (vtctldata.LaunchSchemaMigrationResponse) {}; @@ -641,6 +647,24 @@ message GetWorkflowRequest { bool active_only = 4; } +message GetWorkflowStatusRequest { + string cluster_id = 1; + string keyspace = 2; + string name = 3; +} + +message StartWorkflowRequest { + string cluster_id = 1; + string keyspace = 2; + string workflow = 3; +} + +message StopWorkflowRequest { + string cluster_id = 1; + string keyspace = 2; + string workflow = 3; +} + message GetWorkflowsRequest { repeated string cluster_ids = 1; // ActiveOnly specifies whether to return workflows that are currently diff --git a/proto/vtctldata.proto b/proto/vtctldata.proto index 398357c0423..89af1958e0f 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 { @@ -1441,6 +1357,8 @@ message PlannedReparentShardRequest { // acceptable for a tablet to be eligible for promotion when Vitess makes the choice of a new primary. // A value of 0 indicates that Vitess shouldn't consider the replication lag at all. vttime.Duration tolerable_replication_lag = 6; + // AllowCrossCellPromotion allows cross cell promotion, + bool allow_cross_cell_promotion = 7; } message PlannedReparentShardResponse { @@ -1944,6 +1862,7 @@ message VDiffCreateRequest { bool verbose = 18; int64 max_report_sample_rows = 19; vttime.Duration max_diff_duration = 20; + int64 row_diff_column_truncate_at = 21; } message VDiffCreateResponse { diff --git a/proto/vtgate.proto b/proto/vtgate.proto index 0d8781bcd61..02268b9d7e8 100644 --- a/proto/vtgate.proto +++ b/proto/vtgate.proto @@ -302,6 +302,8 @@ message VStreamFlags { string cells = 4; string cell_preference = 5; string tablet_order = 6; + // When set, all new row events from the `heartbeat` table, for all shards, in the sidecardb will be streamed. + bool stream_keyspace_heartbeats = 7; } // VStreamRequest is the payload for VStream. 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/test.go b/test.go index 74438cbb504..30764662d33 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", "34", "the version identifier to use for the docker images") + bootstrapVersion = flag.String("bootstrap-version", "35", "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 ( @@ -111,7 +112,7 @@ const ( configFileName = "test/config.json" // List of flavors for which a bootstrap Docker image is available. - flavors = "mysql57,mysql80,percona,percona57,percona80" + flavors = "mysql80,percona80" ) // Config is the overall object serialized in test/config.json. @@ -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 8b48ccc3ec0..f1a8f1bcf74 100644 --- a/test/config.json +++ b/test/config.json @@ -799,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", @@ -808,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", @@ -817,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", @@ -826,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", @@ -835,7 +835,16 @@ }, "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", + "RetryMax": 1, + "Tags": [] + }, + "vtgate_transaction_twopc_stress": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc/stress"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", 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 46078cfcc0c..aa30cd6ee93 100644 --- a/test/templates/cluster_endtoend_test.tpl +++ b/test/templates/cluster_endtoend_test.tpl @@ -56,11 +56,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -85,13 +85,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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() @@ -222,7 +222,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/test/templates/cluster_endtoend_test_docker.tpl b/test/templates/cluster_endtoend_test_docker.tpl index 2b63e6d3516..0beeadb709b 100644 --- a/test/templates/cluster_endtoend_test_docker.tpl +++ b/test/templates/cluster_endtoend_test_docker.tpl @@ -28,11 +28,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -54,9 +54,9 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - 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 17d49c382e2..cc3f7ff7ffb 100644 --- a/test/templates/cluster_endtoend_test_mysql57.tpl +++ b/test/templates/cluster_endtoend_test_mysql57.tpl @@ -61,11 +61,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -90,13 +90,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -228,7 +228,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/test/templates/cluster_vitess_tester.tpl b/test/templates/cluster_vitess_tester.tpl index bd34c2de088..05ba2f015df 100644 --- a/test/templates/cluster_vitess_tester.tpl +++ b/test/templates/cluster_vitess_tester.tpl @@ -43,11 +43,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -55,7 +55,7 @@ jobs: end_to_end: - 'go/**/*.go' - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' + - 'go/test/endtoend/vtgate/vitess_tester/**' - 'test.go' - 'Makefile' - 'build.env' @@ -69,13 +69,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -110,7 +110,7 @@ jobs: go install github.com/vitessio/go-junit-report@HEAD # install vitess tester - go install github.com/vitessio/vitess-tester@eb953122baba163ed8ccaa6642458ee984f5d7e4 + go install github.com/vitessio/vitess-tester@89dd933a9ea0e15f69ca58b9c8ea09a358762cca - name: Setup launchable dependencies if: steps.skip-workflow.outputs.is_draft == 'false' && steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' @@ -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 @@ -141,9 +142,9 @@ jobs: # We go over all the directories in the given path. # If there is a vschema file there, we use it, otherwise we let vitess-tester autogenerate it. if [ -f $dir/vschema.json ]; then - vitess-tester --sharded --xunit --test-dir $dir --vschema "$dir"vschema.json + vitess-tester --xunit --vschema "$dir"vschema.json $dir/*.test else - vitess-tester --sharded --xunit --test-dir $dir + vitess-tester --sharded --xunit $dir/*.test fi # Number the reports by changing their file names. mv report.xml report"$i".xml @@ -163,7 +164,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report*.xml" show: "fail, skip" diff --git a/test/templates/dockerfile.tpl b/test/templates/dockerfile.tpl index 437971aa532..23d899441e4 100644 --- a/test/templates/dockerfile.tpl +++ b/test/templates/dockerfile.tpl @@ -1,4 +1,4 @@ -ARG bootstrap_version=34 +ARG bootstrap_version=35 ARG image="vitess/bootstrap:${bootstrap_version}-{{.Platform}}" FROM "${image}" diff --git a/test/templates/unit_test.tpl b/test/templates/unit_test.tpl index 7fd872bde1d..e7db651a5a0 100644 --- a/test/templates/unit_test.tpl +++ b/test/templates/unit_test.tpl @@ -43,11 +43,11 @@ jobs: - name: Check out code if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check for changes in relevant files if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: dorny/paths-filter@v3.0.1 + uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 id: changes with: token: '' @@ -67,13 +67,13 @@ jobs: - name: Set up Go if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.22.5 + go-version: 1.23.0 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@v5 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - name: Tune the OS 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 @@ -187,7 +186,7 @@ jobs: - name: Test Summary if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() - uses: test-summary/action@v2 + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 with: paths: "report.xml" show: "fail, skip" diff --git a/tools/check_go_versions.sh b/tools/check_go_versions.sh index 3549cdc10e9..f586cd245e0 100755 --- a/tools/check_go_versions.sh +++ b/tools/check_go_versions.sh @@ -14,8 +14,10 @@ if [ -z "${GO_MOD_VERSION}" ]; then exit 1 fi -# ci workflows -TPL_GO_VERSIONS="$(awk '/go-version: /{print $(NF-0)}' .github/workflows/*.yml test/templates/*.tpl | sort -u)" +# ci workflows excluding upgrade/downgrade tests +TPL_GO_VERSIONS="$(find .github/workflows test/templates -type f \( -name '*.yml' -o -name '*.tpl' \) \ + ! -name 'upgrade_downgrade_test*.yml' \ + -exec awk '/go-version: /{print $(NF-0)}' {} + | sort -u)" TPL_GO_VERSIONS_COUNT=$(echo "$TPL_GO_VERSIONS" | wc -l | tr -d [:space:]) if [ "${TPL_GO_VERSIONS_COUNT}" -gt 1 ]; then echo -e "expected a consistent 'go-version:' in CI workflow files/templates, found versions:\n${TPL_GO_VERSIONS}" @@ -35,4 +37,4 @@ if [[ ! "${BOOTSTRAP_GO_VERSION}" =~ "${GO_MOD_VERSION}" ]]; then elif [ "${TPL_GO_VERSION}" != "${BOOTSTRAP_GO_VERSION}" ]; then echo "expected equal go version in CI workflow files/templates and bootstrap Dockerfile: '${TPL_GO_VERSIONS}' != '${BOOTSTRAP_GO_VERSION}'" exit 1 -fi +fi \ No newline at end of file diff --git a/vitess-mixin/.env b/vitess-mixin/.env deleted file mode 100644 index 2dd23ee5572..00000000000 --- a/vitess-mixin/.env +++ /dev/null @@ -1,15 +0,0 @@ -TOPOLOGY_FLAGS=--topo_implementation consul --topo_global_server_address consul1:8500 --topo_global_root vitess/global -GRPC_PORT=15999 -WEB_PORT=8080 -MYSQL_PORT=15306 - -CELL=local -KEYSPACE=commerce -DB=commerce - -EXTERNAL_DB=0 -DB_HOST=external_db_host -DB_PORT=3306 -DB_USER=external_db_user -DB_PASS=external_db_password -DB_CHARSET=CHARACTER SET utf8 COLLATE utf8_general_ci \ No newline at end of file diff --git a/vitess-mixin/.gitignore b/vitess-mixin/.gitignore deleted file mode 100644 index eb410a1f9e8..00000000000 --- a/vitess-mixin/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -.DS_Store -*.yaml -dashboards_out -prometheus_alerts.yaml -prometheus_rules.yaml -jsonnetfile.lock.json -vendor -.vscode/ diff --git a/vitess-mixin/Makefile b/vitess-mixin/Makefile deleted file mode 100644 index 267bc569312..00000000000 --- a/vitess-mixin/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -.PHONY: dashboards_out prometheus_alerts.yaml prometheus_rules.yaml test tools all e2e e2e-dev e2e-compose-up e2e-compose-down lint fmt - -help: #: Show this message. - @echo "\nAvailable Targets:\n" - @sed -ne '/@sed/!s/#: //p' $(MAKEFILE_LIST) - -all: #: format all .jsonnet/.libsonnet files, generate all dashboards json, alerts and rules yaml - @make tools - @make clean > /dev/null - @make fmt > /dev/null - @make test - @make dashboards_out > /dev/null - @make prometheus_rules.yaml > /dev/null - -fmt: #: Usage make fmt - @echo "# Formatting all .libsonnet and .jsonnet files...\n" - @scripts/fmt.sh - @echo "\nDone!\n" - -a.yaml: #: Build prometheus alerts - @echo "# Building 'prometheus_alerts.yaml'...\n" - @jsonnet -S lib/alerts.jsonnet > $@ - @echo "\nDone!\n" - -prometheus_rules.yaml: #: Build prometheus rules - @echo "# Building 'prometheus_rules.yaml'...\n" - @jsonnet -S lib/rules.jsonnet > $@ - @echo "\nDone!\n" - -dashboards_out: #: Generate Grafana Dashboards Usage: `ENV='prod' make dashboards_out` - @echo "# Building Grafana dashboards...\n" - @make clean > /dev/null - @mkdir -p dashboards_out - @[ "${ENV}" = 'dev' ] || [ "${ENV}" = 'prod' ] || ( echo -e "##ERROR\nPlease specify ENV (prod or dev)"; exit 1) - @jsonnet -J vendor --ext-str env="${ENV}" -m dashboards_out lib/dashboards.jsonnet - @echo "\nDone!\n" - -lint: #: Usage: make lint - @echo "# Linting all .libsonnet and .jsonnet files...\n" - @scripts/fmt.sh --check - @echo "\nDone!\n" - @echo "# Linting 'prometheus_rules.yaml'...\n" - @make prometheus_rules.yaml > /dev/null - @promtool check rules prometheus_rules.yaml - @echo "Done!\n" - -clean: #: Delete generated dashboards (/dashboards_out) Usage: make clean - @echo "# Cleaning up all generated files...\n" - @rm -rf dashboards_out prometheus_alerts.yaml prometheus_rules.yaml > /dev/null - @echo "\nDone!\n" - -test: #: Compare your .json generated dashboards local version with the origin/main version. - @make clean > /dev/null - @ENV=${ENV} scripts/vitess-mixin-plan.sh - @make clean > /dev/null - -tools: tools.go - @# -mod='' tells go to ignore the vendor/ directory - @cat $^ | grep _ | awk -F'"' '{print $$2}' | xargs -I% go install -mod='' % - @jb install - @jb update https://github.com/grafana/grafonnet-lib/grafonnet > /dev/null 2>&1 - - -E2E_GRAFANA_VERSION ?= 7.3.6 - -e2e: #: Run all Grafana end-to-end tests. - GRAFANA_VERSION=${E2E_GRAFANA_VERSION} \ - docker-compose -f e2e/docker-compose.yml up \ - --abort-on-container-exit \ - --exit-code-from e2e \ - --remove-orphans - -e2e-dev: #: Run Grafana e2e tests in Cypress test runner. - GRAFANA_VERSION=${E2E_GRAFANA_VERSION} \ - DISPLAY=$$(ipconfig getifaddr en0):0 \ - docker-compose -f e2e/docker-compose.dev.yml up \ - --abort-on-container-exit \ - --exit-code-from e2e \ - --remove-orphans - -e2e-compose-up: #: Run Grafana e2e environment spining Prometheus and Vitess in the backend. - GRAFANA_VERSION=${E2E_GRAFANA_VERSION} \ - COMPOSE_HTTP_TIMEOUT=200 \ - DISPLAY=$$(ipconfig getifaddr en0):0 \ - docker-compose -f e2e/docker-compose.vt.yml up \ - --remove-orphans - -e2e-compose-down: #: Clean docker compose resources - @docker-compose -f e2e/docker-compose.vt.yml down -v --remove-orphans - @rm e2e/grafana/provisioning/dashboards/*.json - @rm e2e/prometheus/prometheus_rules.yaml diff --git a/vitess-mixin/README.md b/vitess-mixin/README.md deleted file mode 100644 index 695a943295c..00000000000 --- a/vitess-mixin/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# (Beta) Monitoring Mixin for Vitess - -A set of Grafana dashboards, Prometheus rules and alerts for Vitess, packaged together in a reusable and extensible bundle. - -## 🔁 Prerequisites - -1. Go (programming language) - - Install binaries using the official [installer](https://golang.org/dl/) - - Ensure `GOPATH` variable is set in your system. See instructions [here](https://golang.org/doc/install#install). Here below there's a sample config: - - ```shell - export GOPATH=$HOME/go - export PATH="$GOPATH/bin:/usr/local/go/bin:$PATH" - ``` - -1. Install the go tools: `make tools`, `jb`, `jsonnet`, `jsonnetfmt`, and `promtool` should now be in `$GOPATH/bin`. - -1. Install the dependencies by running: `jb install` - -## ℹ️ How-to - -Customize `config.libsonnet` based on your setup. Example: specify the `dataSource` name (default to `Prometheus_Vitess`). You can then generate: - -- Prometheus alerts: `$ make prometheus_alerts.yaml` -(Note: This files is empty because the current version of the mixin uses Grafana Alerts) - -- Prometheus rules: `$ make prometheus_rules.yaml` - -- Grafana dashboard: `$ ENV='prod' make dashboards_out` (Supported environments are `dev` and `prod`). - -The `prometheus_alerts.yaml` and `prometheus_rules.yaml` file then need to passed to your Prometheus server, and the files in `dashboards_out` need to be imported into you Grafana server. - -## 👩‍💻 Development - -If you want to contribute please read [Vitess mixin quickstart guide](vitess-mixin-quickstart.md) - -## 📚 Useful links & further learning - -- For more information about monitoring mixins, see this [design doc](https://docs.google.com/document/d/1A9xvzwqnFVSOZ5fD3blKODXfsat5fg6ZhnKu9LK3lB4/edit#). -- For more motivation, see -"[The RED Method: How to instrument your services](https://kccncna17.sched.com/event/CU8K/the-red-method-how-to-instrument-your-services-b-tom-wilkie-kausal?iframe=no&w=100%&sidebar=yes&bg=no)" talk from CloudNativeCon Austin. diff --git a/vitess-mixin/alerts/alerts.libsonnet b/vitess-mixin/alerts/alerts.libsonnet deleted file mode 100644 index 732a682f8b6..00000000000 --- a/vitess-mixin/alerts/alerts.libsonnet +++ /dev/null @@ -1,5 +0,0 @@ -{ - prometheusAlerts+:: { - - }, -} diff --git a/vitess-mixin/config.libsonnet b/vitess-mixin/config.libsonnet deleted file mode 100644 index 8c8f69ca0ee..00000000000 --- a/vitess-mixin/config.libsonnet +++ /dev/null @@ -1,74 +0,0 @@ -{ - _config+:: { - - // Selectors are inserted between {} in Prometheus queries. - vtctldSelector: 'job="vitess-vtctld"', - vtgateSelector: 'job="vitess-vtgate"', - vttabletSelector: 'job="vitess-vttablet"', - vtgateNodeSelector: 'job="node-exporter-vitess-vtgate"', - mysqlSelector: 'job="mysql"', - defaultTimeFrom: 'now-30m', - vttabletMountpoint: '/mnt', - - // Datasource to use - dataSource: 'Prometheus', - nodeDataSource: 'Prometheus', - - // Default config for the Grafana dashboards in the Vitess Mixin - grafanaDashboardMetadataDefault: { - dashboardNameSuffix: '(auto-generated)', - dashboardAlertPrefix: 'alerts', - dashboardTags: ['vitess-mixin'], - }, - - dashborardLinks: { - title: 'vitess-mixin', - tags: ['vitess-mixin'], - keepTime: true, - includeVars: false, - }, - - // Grafana dashboard IDs are necessary for stable links for dashboards - grafanaDashboardMetadata: { - - local defaultDashboard = { - environments: ['dev', 'prod'], - time_from: $._config.defaultTimeFrom, - }, - - // Overview - clusterOverview+: defaultDashboard { - uid: 'vitess-cluster-overview', - title: 'cluster - overview %(dashboardNameSuffix)s' % $._config.grafanaDashboardMetadataDefault, - description: 'General cluster overview', - dashboardTags: $._config.grafanaDashboardMetadataDefault.dashboardTags + ['overview', 'cluster'], - }, - vtgateOverview+: defaultDashboard { - uid: 'vitess-vtgate-overview', - title: 'vtgate - overview %(dashboardNameSuffix)s' % $._config.grafanaDashboardMetadataDefault, - description: 'General vtgate overview', - dashboardTags: $._config.grafanaDashboardMetadataDefault.dashboardTags + ['overview', 'vtgate'], - }, - - // Host View - vttabletHostView+: defaultDashboard { - uid: 'vitess-vttablet-host-view', - title: 'vttablet - host view %(dashboardNameSuffix)s' % $._config.grafanaDashboardMetadataDefault, - description: 'Detailed vttablet host view', - dashboardTags: $._config.grafanaDashboardMetadataDefault.dashboardTags + ['vttablet', 'host'], - }, - vtgateHostView+: defaultDashboard { - uid: 'vitess-vtgate-host-view', - title: 'vtgate - host view %(dashboardNameSuffix)s' % $._config.grafanaDashboardMetadataDefault, - description: 'Detailed vtgate view by host', - dashboardTags: $._config.grafanaDashboardMetadataDefault.dashboardTags + ['vtgate', 'host'], - }, - }, - }, - - os: import 'dashboards/resources/config/os_config.libsonnet', - vttablet: import 'dashboards/resources/config/vttablet_config.libsonnet', - vtgate: import 'dashboards/resources/config/vtgate_config.libsonnet', - mysql: import 'dashboards/resources/config/mysql_config.libsonnet', - row: import 'dashboards/resources/config/row_config.libsonnet', -} diff --git a/vitess-mixin/dashboards/dashboards.libsonnet b/vitess-mixin/dashboards/dashboards.libsonnet deleted file mode 100644 index 5840e4b5228..00000000000 --- a/vitess-mixin/dashboards/dashboards.libsonnet +++ /dev/null @@ -1,5 +0,0 @@ -(import 'layouts/cluster_overview.libsonnet') + -(import 'layouts/vtgate_host_view.libsonnet') + -(import 'layouts/vtgate_overview.libsonnet') + -(import 'layouts/vttablet_host_view.libsonnet') + -(import 'defaults.libsonnet') diff --git a/vitess-mixin/dashboards/defaults.libsonnet b/vitess-mixin/dashboards/defaults.libsonnet deleted file mode 100644 index d94de1fab09..00000000000 --- a/vitess-mixin/dashboards/defaults.libsonnet +++ /dev/null @@ -1,24 +0,0 @@ -{ - local grafanaDashboards = super.grafanaDashboards, - - grafanaDashboards:: { - [filename]: grafanaDashboards[filename] { - // Modify tooltip to only show a single value - rows: [ - row { - panels: [ - panel { - tooltip+: { - shared: false, - }, - } - for panel in super.panels - ], - } - for row in super.rows - ], - - } - for filename in std.objectFields(grafanaDashboards) - }, -} diff --git a/vitess-mixin/dashboards/layouts/cluster_overview.libsonnet b/vitess-mixin/dashboards/layouts/cluster_overview.libsonnet deleted file mode 100644 index 6db716c982c..00000000000 --- a/vitess-mixin/dashboards/layouts/cluster_overview.libsonnet +++ /dev/null @@ -1,56 +0,0 @@ -local helpers = import '../resources/grafonnet/helpers/helpers.libsonnet'; -local panels = import '../resources/grafonnet/panels.libsonnet'; -local rows = import '../resources/grafonnet/rows.libsonnet'; -local singlestats = import '../resources/grafonnet/singlestats.libsonnet'; -local templates = import '../resources/grafonnet/templates.libsonnet'; -local texts = import '../resources/grafonnet/texts.libsonnet'; - -local config = import '../../config.libsonnet'; - -{ - grafanaDashboards+:: { - 'cluster_overview.json': - - helpers.dashboard.getDashboard(config._config.grafanaDashboardMetadata.clusterOverview) - .addTemplates([ - templates.interval, - ]) - .addLink(helpers.default.getDashboardLink(config._config.dashborardLinks)) - .addPanels([ - texts.clusterOverview { gridPos: { h: 3, w: 24, x: 0, y: 0 } }, - singlestats.vtgateSuccessRate { gridPos: { h: 4, w: 4, x: 0, y: 3 } }, - singlestats.vttabletQuerySuccess { gridPos: { h: 4, w: 4, x: 4, y: 3 } }, - helpers.vtgate.getSingleStat(config.vtgate.singlestats.vtgateQueryLatencyP99) { gridPos: { h: 4, w: 4, x: 8, y: 3 } }, - helpers.vtgate.getSingleStat(config.vtgate.singlestats.vtgateQPS) { gridPos: { h: 2, w: 4, x: 12, y: 3 } }, - helpers.vttablet.getSingleStat(config.vttablet.singlestats.vttabletQPS) { gridPos: { h: 2, w: 4, x: 12, y: 5 } }, - singlestats.mysqlQPS { gridPos: { h: 2, w: 4, x: 16, y: 3 } }, - singlestats.keyspaceCount { gridPos: { h: 2, w: 2, x: 16, y: 3 } }, - singlestats.shardCount { gridPos: { h: 2, w: 2, x: 18, y: 3 } }, - singlestats.vtgateUp { gridPos: { h: 2, w: 2, x: 20, y: 3 } }, - singlestats.vtctldUp { gridPos: { h: 2, w: 2, x: 20, y: 5 } }, - singlestats.vttabletUp { gridPos: { h: 2, w: 2, x: 22, y: 3 } }, - - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequests) { gridPos: { h: 6, w: 8, x: 0, y: 7 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRate) { gridPos: { h: 6, w: 8, x: 8, y: 7 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99) { gridPos: { h: 6, w: 8, x: 16, y: 7 } }, - - rows.RED { gridPos: { h: 1, w: 24, x: 0, y: 13 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequestsByKeyspace) { gridPos: { h: 8, w: 8, x: 0, y: 14 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRateByKeyspace) { gridPos: { h: 8, w: 8, x: 8, y: 14 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99ByKeyspace) { gridPos: { h: 8, w: 8, x: 16, y: 14 } }, - - rows.tabletsQueries { gridPos: { h: 1, w: 24, x: 0, y: 22 } }, - helpers.vttablet.getPanel(config.vttablet.panels.countServingTablets) { gridPos: { h: 8, w: 8, x: 0, y: 23 } }, - helpers.mysql.getPanel(config.mysql.panels.mysqlSlowQueries) { gridPos: { h: 8, w: 8, x: 8, y: 23 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryTransactionKilled) { gridPos: { h: 8, w: 8, x: 16, y: 23 } }, - - rows.serviceRestart { gridPos: { h: 1, w: 24, x: 0, y: 31 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRestart) { gridPos: { h: 8, w: 8, x: 0, y: 32 } }, - panels.vtctldRestart { gridPos: { h: 8, w: 8, x: 8, y: 32 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRestart) { gridPos: { h: 8, w: 8, x: 16, y: 32 } }, - - helpers.mysql.getPanel(config.mysql.panels.mysqlRestart) { gridPos: { h: 8, w: 8, x: 16, y: 40 } }, - ]), - - }, -} diff --git a/vitess-mixin/dashboards/layouts/vtgate_host_view.libsonnet b/vitess-mixin/dashboards/layouts/vtgate_host_view.libsonnet deleted file mode 100644 index 139999e09fc..00000000000 --- a/vitess-mixin/dashboards/layouts/vtgate_host_view.libsonnet +++ /dev/null @@ -1,49 +0,0 @@ -local heatmaps = import '../resources/grafonnet/heatmaps.libsonnet'; -local helpers = import '../resources/grafonnet/helpers/helpers.libsonnet'; -local rows = import '../resources/grafonnet/rows.libsonnet'; -local singlestats = import '../resources/grafonnet/singlestats.libsonnet'; -local templates = import '../resources/grafonnet/templates.libsonnet'; -local texts = import '../resources/grafonnet/texts.libsonnet'; - -local config = import '../../config.libsonnet'; - -// TODO: add connections info - -{ - grafanaDashboards+:: { - 'vtgate_host_view.json': - - helpers.dashboard.getDashboard(config._config.grafanaDashboardMetadata.vtgateHostView) - .addTemplates([ - templates.hostVtgate, - ]) - .addLink(helpers.default.getDashboardLink(config._config.dashborardLinks)) - .addPanels([ - texts.vtgateHost { gridPos: { h: 3, w: 24, x: 0, y: 0 } }, - rows.RED { gridPos: { h: 1, w: 24, x: 0, y: 4 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequestsByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 5 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRateByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 5 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99ByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 5 } }, - rows.REDByTabletType.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequestsByInstanceDBType) { gridPos: { h: 7, w: 8, x: 0, y: 9 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRateByInstanceDBType) { gridPos: { h: 7, w: 8, x: 8, y: 9 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99ByInstanceDBType) { gridPos: { h: 7, w: 8, x: 16, y: 9 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 8 } }, - rows.errors.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorsByInstanceKeyspace) { gridPos: { h: 7, w: 8, x: 0, y: 17 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorsByInstanceCode) { gridPos: { h: 7, w: 8, x: 8, y: 17 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 16 } }, - rows.duration.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationAVGByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 25 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP50ByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 25 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP95ByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 25 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 24 } }, - rows.OS.addPanels([ - helpers.os.getPanel(config.os.panels.CPUUsageByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 33 } }, - helpers.os.getPanel(config.os.panels.MemoryUsageByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 33 } }, - helpers.os.getPanel(config.os.panels.NetworkUsageByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 33 } }, - helpers.os.getPanel(config.os.panels.TCPRetransmissionsByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 40 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 32 } }, - ]), - }, -} diff --git a/vitess-mixin/dashboards/layouts/vtgate_overview.libsonnet b/vitess-mixin/dashboards/layouts/vtgate_overview.libsonnet deleted file mode 100644 index b2c14eb8563..00000000000 --- a/vitess-mixin/dashboards/layouts/vtgate_overview.libsonnet +++ /dev/null @@ -1,58 +0,0 @@ -local heatmaps = import '../resources/grafonnet/heatmaps.libsonnet'; -local helpers = import '../resources/grafonnet/helpers/helpers.libsonnet'; -local rows = import '../resources/grafonnet/rows.libsonnet'; -local singlestats = import '../resources/grafonnet/singlestats.libsonnet'; -local templates = import '../resources/grafonnet/templates.libsonnet'; -local texts = import '../resources/grafonnet/texts.libsonnet'; - -local config = import '../../config.libsonnet'; - -// TODO: add connections info - -{ - grafanaDashboards+:: { - 'vtgate_overview.json': - - helpers.dashboard.getDashboard(config._config.grafanaDashboardMetadata.vtgateOverview) - .addLink(helpers.default.getDashboardLink(config._config.dashborardLinks)) - .addPanels([ - texts.vtgateOverview { gridPos: { h: 3, w: 24, x: 0, y: 0 } }, - - rows.RED { gridPos: { h: 1, w: 24, x: 0, y: 4 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequests) { gridPos: { h: 7, w: 8, x: 0, y: 5 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRate) { gridPos: { h: 7, w: 8, x: 8, y: 5 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99) { gridPos: { h: 7, w: 8, x: 16, y: 5 } }, - - rows.REDByKeyspace.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequestsByKeyspace) { gridPos: { h: 7, w: 8, x: 0, y: 13 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRateByKeyspace) { gridPos: { h: 7, w: 8, x: 8, y: 13 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99ByKeyspace) { gridPos: { h: 7, w: 8, x: 16, y: 13 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 12 } }, - - rows.REDByTabletType.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateRequestsByDBType) { gridPos: { h: 7, w: 8, x: 0, y: 21 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorRateByDBType) { gridPos: { h: 7, w: 8, x: 8, y: 21 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP99ByDBType) { gridPos: { h: 7, w: 8, x: 16, y: 21 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 20 } }, - - rows.errors.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorsByCode) { gridPos: { h: 7, w: 8, x: 0, y: 29 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorsByOperation) { gridPos: { h: 7, w: 8, x: 8, y: 29 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateErrorsByDbtype) { gridPos: { h: 7, w: 8, x: 16, y: 29 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 28 } }, - - rows.duration.addPanels([ - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationAVG) { gridPos: { h: 7, w: 8, x: 0, y: 37 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP50) { gridPos: { h: 7, w: 8, x: 8, y: 37 } }, - helpers.vtgate.getPanel(config.vtgate.panels.vtgateDurationP95) { gridPos: { h: 7, w: 8, x: 16, y: 37 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 36 } }, - - rows.OS.addPanels([ - helpers.os.getPanel(config.os.panels.CPUUsage) { gridPos: { h: 7, w: 8, x: 0, y: 45 } }, - helpers.os.getPanel(config.os.panels.MemoryUsage) { gridPos: { h: 7, w: 8, x: 8, y: 45 } }, - helpers.os.getPanel(config.os.panels.NetworkUsage) { gridPos: { h: 7, w: 8, x: 16, y: 45 } }, - helpers.os.getPanel(config.os.panels.TCPRetransmissions) { gridPos: { h: 7, w: 8, x: 16, y: 52 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 44 } }, - ]), - }, -} diff --git a/vitess-mixin/dashboards/layouts/vttablet_host_view.libsonnet b/vitess-mixin/dashboards/layouts/vttablet_host_view.libsonnet deleted file mode 100644 index 7148deb44ee..00000000000 --- a/vitess-mixin/dashboards/layouts/vttablet_host_view.libsonnet +++ /dev/null @@ -1,103 +0,0 @@ -local heatmaps = import '../resources/grafonnet/heatmaps.libsonnet'; -local helpers = import '../resources/grafonnet/helpers/helpers.libsonnet'; -local rows = import '../resources/grafonnet/rows.libsonnet'; -local templates = import '../resources/grafonnet/templates.libsonnet'; -local texts = import '../resources/grafonnet/texts.libsonnet'; - -local config = import '../../config.libsonnet'; -local rows_helper = helpers.default; - -{ - grafanaDashboards+:: { - 'vttablet_host_view.json': - - helpers.dashboard.getDashboard(config._config.grafanaDashboardMetadata.vttabletHostView) - .addTemplates( - [ - templates.hostVttablet, - ] - ).addLink(helpers.default.getDashboardLink(config._config.dashborardLinks)) - .addPanels( - [ - texts.vttabletHost { gridPos: { h: 3, w: 24, x: 0, y: 0 } }, - - rows.RED { gridPos: { h: 1, w: 24, x: 0, y: 4 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRequestsByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 5 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletErrorRateByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 5 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryDurationP99ByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 5 } }, - - rows.REDByPlanType.addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRequestsByPlanType) { gridPos: { h: 7, w: 8, x: 0, y: 13 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletErrorRateByPlanFilteredByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 13 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryDurationP99ByPlan) { gridPos: { h: 7, w: 8, x: 16, y: 13 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 12 } }, - - rows.REDByTable.addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRequestsByTableFilteredByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 29 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletErrorRateByTableFilteredByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 29 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 28 } }, - - rows.rowsReturned.addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRowsReturnedByTableFilteredByInstance) { gridPos: { h: 7, w: 12, x: 0, y: 37 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletRowsReturnedByPlansFilterByInstance) { gridPos: { h: 7, w: 12, x: 12, y: 37 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 36 } }, - - rows_helper.getRow(config.row.queryErrors).addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueriesKilled) { gridPos: { h: 7, w: 8, x: 0, y: 45 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryErrorsByType) { gridPos: { h: 7, w: 8, x: 8, y: 45 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 44 } }, - - rows.vitessQueryPool.addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryPoolAvailableConnections) { gridPos: { h: 7, w: 8, x: 0, y: 52 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryPoolActiveConnections) { gridPos: { h: 7, w: 8, x: 8, y: 52 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryPoolIddleClosedRate) { gridPos: { h: 7, w: 8, x: 16, y: 52 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryPoolWaitCount) { gridPos: { h: 7, w: 8, x: 0, y: 59 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryPoolAvgWaitTime) { gridPos: { h: 7, w: 8, x: 8, y: 59 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 51 } }, - - rows.vitessTransactionPool.addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionPoolAvailableConnections) { gridPos: { h: 7, w: 8, x: 0, y: 67 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionPoolActiveConnections) { gridPos: { h: 7, w: 8, x: 8, y: 67 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionPoolIddleClosedRate) { gridPos: { h: 7, w: 8, x: 16, y: 67 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionPoolWaitCount) { gridPos: { h: 7, w: 8, x: 0, y: 74 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionPoolAvgWaitTime) { gridPos: { h: 7, w: 8, x: 8, y: 74 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 66 } }, - - rows_helper.getRow(config.row.vitessTimings).addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryDurationAvgByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 82 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryDurationP50ByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 82 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletQueryDurationP95ByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 82 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionDurationAvgByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 89 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionDurationP50ByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 89 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletTransactionDurationP95ByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 89 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vtgateToVtTabletCallTimeAvgFilteredByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 86 } }, - heatmaps.vttabletQueryTimeDistribution { gridPos: { h: 7, w: 16, x: 8, y: 86 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 81 } }, - - rows.mysql.addPanels([ - helpers.mysql.getPanel(config.mysql.panels.mysqlSlowQueriesByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 94 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 93 } }, - - rows_helper.getRow(config.row.mysqlTimings).addPanels([ - helpers.vttablet.getPanel(config.vttablet.panels.vttabletMysqlTimeAvgFilteredByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 102 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletMysqlExecTimeP50FilterebyInstance) { gridPos: { h: 7, w: 8, x: 8, y: 102 } }, - helpers.vttablet.getPanel(config.vttablet.panels.vttabletMysqlExecTimeP95FilterebyInstance) { gridPos: { h: 7, w: 8, x: 16, y: 102 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 101 } }, - - rows.OS.addPanels([ - helpers.os.getPanel(config.os.panels.CPUUsageByInstance) { gridPos: { h: 7, w: 8, x: 0, y: 110 } }, - helpers.os.getPanel(config.os.panels.MemoryUsageByInstance) { gridPos: { h: 7, w: 8, x: 8, y: 110 } }, - helpers.os.getPanel(config.os.panels.DiskUsageByInstance) { gridPos: { h: 7, w: 8, x: 16, y: 110 } }, - helpers.os.getPanel(config.os.panels.NetworkTxByInstance) { gridPos: { h: 7, w: 12, x: 0, y: 117 } }, - helpers.os.getPanel(config.os.panels.NetworkRxByInstance) { gridPos: { h: 7, w: 12, x: 12, y: 117 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 109 } }, - - rows_helper.getRow(config.row.misc).addPanels([ - helpers.os.getPanel(config.vttablet.panels.vttabletGarbageCollectionCount) { gridPos: { h: 7, w: 8, x: 0, y: 125 } }, - helpers.os.getPanel(config.vttablet.panels.vttabletGarbageCollectionDuration) { gridPos: { h: 7, w: 8, x: 8, y: 125 } }, - helpers.os.getPanel(config.vttablet.panels.vttabletGarbageCollectionDurationQuantiles) { gridPos: { h: 7, w: 8, x: 16, y: 125 } }, - ]) { gridPos: { h: 1, w: 24, x: 0, y: 124 } }, - ], - ), - }, -} diff --git a/vitess-mixin/dashboards/resources/config/configuration_templates.libsonnet b/vitess-mixin/dashboards/resources/config/configuration_templates.libsonnet deleted file mode 100644 index 6f1f85da0a3..00000000000 --- a/vitess-mixin/dashboards/resources/config/configuration_templates.libsonnet +++ /dev/null @@ -1,125 +0,0 @@ -local config = import '../../../config.libsonnet'; - -{ - //Override default_panel values with custom configuration - prometheus_vitess: { - panel: { - - datasource: { - datasource: '%(dataSource)s' % config._config, - }, - - default+: self.datasource { - fill: 0, - legend_alignAsTable: true, - legend_values: true, - min: 0, - shared_tooltip: false, - }, - - legend_max+: self.default { - legend_max: true, - }, - - legend_min_max_avg+: self.default { - legend_max: true, - legend_min: true, - legend_avg: true, - }, - - legend_min_max_current+: self.default { - legend_max: true, - legend_min: true, - legend_current: true, - }, - - null_as_zeros+: self.default { - nullPointMode: 'null as zero', - }, - - mysql_default+: self.default { - legend_max: true, - legend_sort: 'max', - }, - - orc_default+: self.default { - legend_current: true, - legend_rightSide: true, - legend_sort: 'current', - legend_sortDesc: false, - pointradius: 5, - sort: 'none', - }, - - vitess_vttablet_host_view+: self.mysql_default { - legend_current: true, - legend_min: true, - legend_sort: 'current', - legend_sortDesc: true, - }, - - go_gc_seconds+: self.legend_max { - format: 's', - }, - - go_gc_ops+: self.legend_max { - format: 'ops', - }, - - mysql_timings+: self.legend_min_max_avg { - legend_sort: 'max', - legend_sortDesc: true, - format: 's', - }, - - vtgate_to_vttablet_calls: self.legend_min_max_avg + self.null_as_zeros { - format: 's', - legend_sortDesc: true, - legend_sort: 'max', - }, - - }, - }, - - prometheus_node: { - panel: { - default: { - datasource: '%(nodeDataSource)s' % config._config, - fill: 0, - legend_alignAsTable: true, - legend_current: true, - legend_sort: 'current', - legend_sortDesc: true, - legend_values: true, - min: 0, - sort: 'decreasing', - }, - - percent_panel: self.default { - format: 'percentunit', - legend_min: true, - legend_max: true, - }, - - null_as_zeros+: self.default { - nullPointMode: 'null as zero', - }, - - vttablet_host_view: self.percent_panel { - legend_avg: true, - legend_current: false, - legend_sort: 'max', - }, - - performance_analysis_short: self.percent_panel { - format: 'short', - legend_min: false, - legend_max: false, - }, - - performance_analysis_seconds+: self.performance_analysis_short { - format: 's', - }, - }, - }, -} diff --git a/vitess-mixin/dashboards/resources/config/mysql_config.libsonnet b/vitess-mixin/dashboards/resources/config/mysql_config.libsonnet deleted file mode 100644 index 543e3565902..00000000000 --- a/vitess-mixin/dashboards/resources/config/mysql_config.libsonnet +++ /dev/null @@ -1,87 +0,0 @@ -local config = import '../../../config.libsonnet'; -local configuration_templates = import './configuration_templates.libsonnet'; -local vitess_ct = configuration_templates.prometheus_vitess; - -// TODO: move local template variables and fields to ./configuration_templates.libsonnet. -{ - // TODO: add description for each panel. - panels: { - - local panel_template = vitess_ct.panel.mysql_default, - local vttablet_host_view_panel_template = vitess_ct.panel.vitess_vttablet_host_view, - - // TODO Create a recording rule for the prometheus target. - mysqlRestart: panel_template { - title: 'MySQL (by keyspace/shard)', - bars: true, - format: 'short', - legend_sort: 'max', - legend_sortDesc: false, - lines: false, - sort: 'increasing', - targets: [ - { - expr: ||| - count by (keyspace, shard) ( - idelta ( - mysql_global_status_uptime{ - %(mysqlSelector)s - }[5m] - ) < 0 - ) - ||| % config._config, - legendFormat: '{{keyspace}}/{{shard}}', - }, - ], - }, - - // TODO Create a recording rule for the prometheus target. - mysqlSlowQueries: panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Slow queries', - format: 'cps', - legend_min: true, - legend_current: true, - legend_sort: 'current', - legend_sortDesc: true, - sort: 'decreasing', - nullPointMode: 'null as zero', - targets: [ - { - expr: ||| - sum ( - rate( - mysql_global_status_slow_queries{ - %(mysqlSelector)s - }[$interval] - ) - ) - ||| % config._config, - legendFormat: 'Slow Queries', - }, - ], - }, - - // TODO Create a recording rule for the prometheus target. - mysqlSlowQueriesByInstance: vttablet_host_view_panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Slow Queries', - format: 'ops', - targets: [ - { - expr: ||| - sum by(instance)( - rate( - mysql_global_status_slow_queries{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - }, -} diff --git a/vitess-mixin/dashboards/resources/config/os_config.libsonnet b/vitess-mixin/dashboards/resources/config/os_config.libsonnet deleted file mode 100644 index 8451311cb1b..00000000000 --- a/vitess-mixin/dashboards/resources/config/os_config.libsonnet +++ /dev/null @@ -1,384 +0,0 @@ -/** This is a configuration file containing metadata for OS (Prometheus Node) grafana resources. */ - -local config = import '../../../config.libsonnet'; -local configuration_templates = import './configuration_templates.libsonnet'; -local node_ct = configuration_templates.prometheus_node; - -// TODO: move local template variables and fields to ./configuration_templates.libsonnet. -{ - // TODO: add description for each panel. - panels: { - - local vtgate_panel_template = node_ct.panel.percent_panel, - local vttablet_host_view_panel_template = node_ct.panel.vttablet_host_view, - - CPUUsage: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'CPU Usage', - targets: [ - { - expr: - ||| - 1 - - avg ( - rate( - node_cpu_seconds_total{ - %(vtgateNodeSelector)s, - mode="idle" - }[1m] - ) - ) - ||| % config._config, - legendFormat: 'cpu usage', - }, - ], - }, - - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - CPUUsageByInstance: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'CPU Usage', - targets: [ - { - expr: - ||| - 1 - - avg by (instance)( - rate( - node_cpu_seconds_total{ - instance=~"$host", - mode="idle" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - MemoryUsage: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'Memory Usage', - targets: [ - { - expr: - ||| - 1 - - sum ( - node_memory_MemAvailable_bytes{ - %(vtgateNodeSelector)s - } - ) - / - sum ( - node_memory_MemTotal_bytes{ - %(vtgateNodeSelector)s - } - ) - ||| % config._config, - legendFormat: 'Memory Usage', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - MemoryUsageByInstance: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'Memory Usage', - targets: [ - { - expr: - ||| - 1 - - sum by (instance)( - node_memory_MemAvailable_bytes{ - instance=~"$host" - } - ) - / - sum by (instance)( - node_memory_MemTotal_bytes{ - instance=~"$host" - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - TCPRetransmissions: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'TCP Retransmissions', - targets: [ - { - expr: - ||| - sum ( - rate( - node_netstat_Tcp_RetransSegs{ - %(vtgateNodeSelector)s - }[1m] - ) - ) - / - sum ( - rate( - node_netstat_Tcp_OutSegs{ - %(vtgateNodeSelector)s - }[1m] - ) - ) - ||| % config._config, - legendFormat: 'TCP retransmissions', - }, - ], - }, - - TCPRetransmissionsByInstance: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'TCP Retransmissions', - targets: [ - { - expr: - ||| - sum by (instance) ( - rate( - node_netstat_Tcp_RetransSegs{ - instance=~"$host" - }[1m] - ) - ) - / - sum by (instance) ( - rate( - node_netstat_Tcp_OutSegs{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - NetworkUsage: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'Network Usage', - format: 'bps', - min: null, - seriesOverrides: [ - { - alias: '/egress .*/', - transform: 'negative-Y', - }, - ], - targets: [ - { - expr: - ||| - sum ( - rate( - node_network_receive_bytes_total{ - %(vtgateNodeSelector)s - }[5m] - ) - ) - * 8 - ||| % config._config, - legendFormat: 'ingress', - }, - { - expr: - ||| - sum ( - rate( - node_network_transmit_bytes_total{ - %(vtgateNodeSelector)s - }[5m] - ) - ) - * 8 - ||| % config._config, - legendFormat: 'egress', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - NetworkUsageByInstance: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: 'Network Usage', - format: 'Bps', - min: null, - seriesOverrides: [ - { - alias: '/egress .*/', - transform: 'negative-Y', - }, - ], - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - node_network_receive_bytes_total{ - instance=~"$host" - }[5m] - ) - ) - ||| % config._config, - legendFormat: 'ingress - {{instance}}', - }, - { - expr: - ||| - sum by (instance)( - rate( - node_network_transmit_bytes_total{ - instance=~"$host" - }[5m] - ) - ) - ||| % config._config, - legendFormat: 'egress - {{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - NetworkUsageByInstanceFilteredByShardKeyspace: - vttablet_host_view_panel_template - + node_ct.panel.null_as_zeros { - title: 'Network Usage', - format: 'bps', - min: null, - seriesOverrides: [ - { - alias: '/egress .*/', - transform: 'negative-Y', - }, - ], - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - node_network_receive_bytes_total{ - keyspace="$keyspace", - shard=~"$shard", - instance=~"$host" - }[5m] - ) - ) - * 8 - |||, - legendFormat: 'ingress - {{instance}}', - }, - { - expr: - ||| - sum by (instance)( - rate( - node_network_transmit_bytes_total{ - keyspace="$keyspace", - shard=~"$shard", - instance=~"$host" - }[5m] - ) - ) - * 8 - |||, - legendFormat: 'egress - {{instance}}', - }, - ], - }, - - NetworkRxByInstance: - vttablet_host_view_panel_template - + node_ct.panel.null_as_zeros { - title: 'Network Rx Bytes', - format: 'bps', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - node_network_receive_bytes_total{ - instance=~"$host" - }[1m] - ) - ) - * 8 - |||, - legendFormat: 'ingress - {{instance}}', - }, - ], - }, - - NetworkTxByInstance: - vttablet_host_view_panel_template - + node_ct.panel.null_as_zeros { - title: 'Network Tx Bytes', - format: 'bps', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - node_network_transmit_bytes_total{ - instance=~"$host" - }[1m] - ) - ) - * 8 - |||, - legendFormat: 'egress - {{instance}}', - }, - ], - }, - - DiskUsageByInstance: - vtgate_panel_template - + node_ct.panel.null_as_zeros { - title: '/mnt disk free', - min: null, - targets: [ - { - expr: - ||| - avg by(instance)( - node_filesystem_avail_bytes{ - instance=~"$host", - mountpoint="%(vttabletMountpoint)s" - } - / - node_filesystem_size_bytes{ - instance=~"$host", - mountpoint="%(vttabletMountpoint)s" - } - ) - ||| % config._config, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - }, -} diff --git a/vitess-mixin/dashboards/resources/config/row_config.libsonnet b/vitess-mixin/dashboards/resources/config/row_config.libsonnet deleted file mode 100644 index 2fb6d6cb355..00000000000 --- a/vitess-mixin/dashboards/resources/config/row_config.libsonnet +++ /dev/null @@ -1,18 +0,0 @@ -{ - misc:: { - title: 'Misc', - collapse: true, - }, - mysqlTimings: { - title: 'MySQL Timings', - collapse: true, - }, - queryErrors:: { - title: 'Queries/Errors', - collapse: true, - }, - vitessTimings:: { - title: 'Vitess Timings', - collapse: true, - }, -} diff --git a/vitess-mixin/dashboards/resources/config/vtgate_config.libsonnet b/vitess-mixin/dashboards/resources/config/vtgate_config.libsonnet deleted file mode 100644 index acbc7e19efb..00000000000 --- a/vitess-mixin/dashboards/resources/config/vtgate_config.libsonnet +++ /dev/null @@ -1,765 +0,0 @@ -/** This is a configuration file containing metadata for vtgate grafana resources. */ - -local config = import '../../../config.libsonnet'; -local configuration_templates = import './configuration_templates.libsonnet'; -local vitess_ct = configuration_templates.prometheus_vitess; - -// TODO: move local template variables and fields to ./configuration_templates.libsonnet. -{ - // ____ _ - // | _ \ __ _ _ __ ___| |___ - // | |_) / _` | '_ \ / _ \ / __| - // | __/ (_| | | | | __/ \__ \ - // |_| \__,_|_| |_|\___|_|___/ - - // TODO: add description for each panel. - panels: { - - //Override default_panel values with custom configuration - local panel_template = { - datasource: '%(dataSource)s' % config._config, - format: 'rps', - fill: 0, - legend_values: true, - legend_alignAsTable: true, - legend_min: true, - legend_max: true, - legend_current: true, - legend_sort: 'current', - legend_sortDesc: true, - min: 0, - sort: 'decreasing', - }, - - local garbage_collector_panel_template = panel_template { - format: 's', - legend_sort: 'max', - }, - - vtgateRequests: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests', - fill: 1, - targets: [ - { - expr: ||| - sum ( - vitess_mixin:vtgate_api_count:rate1m - ) - |||, - legendFormat: 'Requests', - }, - ], - }, - - vtgateRequestsByKeyspace: - panel_template + - vitess_ct.panel.null_as_zeros { - title: 'Requests (by keyspace)', - targets: [ - { - expr: ||| - sum by(keyspace)( - vitess_mixin:vtgate_api_count_by_keyspace:rate1m - ) - ||| % config._config, - legendFormat: '{{keyspace}}', - }, - ], - }, - - - vtgateRequestsByDBType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests (by db_type)', - targets: [ - { - expr: ||| - sum by (db_type)( - vitess_mixin:vtgate_api_count_by_db_type:rate1m - ) - |||, - legendFormat: '{{db_type}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vtgateRequestsByInstanceDBType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests (by db_type)', - fill: 0, - targets: [ - { - expr: ||| - sum by (instance, db_type)( - rate( - vtgate_api_count{ - instance=~"$host", - }[1m] - ) - ) - |||, - legendFormat: '{{instance}} - {{db_type}}', - intervalFactor: 1, - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS TARGET - vtgateRequestsByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests', - fill: 0, - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vtgate_api_count{ - instance=~'$host' - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - - vtgateErrorRate: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate', - format: 'percentunit', - fill: 1, - aliasColors: { - 'Error rate': '#F2495C', - }, - targets: [ - { - expr: ||| - sum ( - vitess_mixin:vtgate_api_error_counts:rate1m) - / - sum ( - vitess_mixin:vtgate_api_count:rate1m) - |||, - legendFormat: 'Error rate', - }, - ], - }, - - vtgateErrorRateByKeyspace: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate (by keyspace)', - format: 'percentunit', - targets: [ - { - expr: ||| - sum by(keyspace)( - vitess_mixin:vtgate_api_error_counts_by_keyspace:rate1m) - / - sum by(keyspace)( - vitess_mixin:vtgate_api_count_by_keyspace:rate1m) - |||, - legendFormat: '{{keyspace}}', - }, - ], - }, - - vtgateErrorRateByDBType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate (by db_type)', - format: 'percentunit', - targets: [ - { - expr: ||| - sum by (db_type)( - vitess_mixin:vtgate_api_error_counts_by_db_type:rate1m - ) - / - sum by (db_type)( - vitess_mixin:vtgate_api_count_by_db_type:rate1m - ) - ||| % config._config, - legendFormat: '{{db_type}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS TARGET - vtgateErrorRateByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate', - fill: 0, - format: 'percentunit', - nullPointMode: 'null as zero', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - vtgate_api_error_counts[1m] - ) > 0 - ) - / - sum by(instance)( - rate( - vtgate_api_count[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - - //TODO Create RECORDING RULES FOR THESE PROM TARGETS - vtgateErrorRateByInstanceDBType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate (by db_type)', - fill: 0, - format: 'percentunit', - targets: [ - { - expr: - ||| - sum by(instance, db_type)( - rate(vtgate_api_error_counts{ - instance=~"$host" - }[1m] - ) > 0 - ) - / - sum by(instance, db_type)( - rate( - vtgate_api_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}} - {{db_type}}', - intervalFactor: 1, - }, - ], - }, - - vtgateDurationP99: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Duration 99th quantile', - fill: 1, - format: 's', - aliasColors: { - Duration: '#5794F2', - }, - targets: [ - { - expr: ||| - histogram_quantile( - 0.99, - sum by(le)( - vitess_mixin:vtgate_api_bucket:rate1m - ) - ) - |||, - legendFormat: 'Duration', - }, - ], - }, - - vtgateDurationP99ByKeyspace: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Duration 99th quantile (by keyspace)', - format: 's', - targets: [ - { - expr: ||| - histogram_quantile( - 0.99, - sum by(keyspace,le)( - vitess_mixin:vtgate_api_bucket_by_keyspace:rate1m - ) - ) - ||| % config._config, - legendFormat: '{{keyspace}}', - }, - ], - }, - - local vtgateDurationTemplate = - panel_template - + vitess_ct.panel.null_as_zeros { - fill: 1, - format: 's', - aliasColors: { - Duration: '#5794F2', - }, - }, - - //TODO crete a recording rule for this prometheus vitess target - vtgateDurationP99ByInstance: vtgateDurationTemplate { - title: 'Duration 99th quantile', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.99, - sum by(instance,le)( - rate( - vtgate_api_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - - //TODO crete a recording rule for this prometheus vitess target - vtgateDurationP99ByInstanceDBType: vtgateDurationTemplate { - title: 'Duration 99th quantile (by db_type)', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.99, - sum by(instance,db_type,le)( - rate( - vtgate_api_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}} - {{db_type}}', - intervalFactor: 1, - }, - ], - }, - - vtgateDurationP50: vtgateDurationTemplate { - title: 'Duration 50th quantile', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.50, - sum by(le)( - vitess_mixin:vtgate_api_bucket:rate1m - ) - ) - |||, - legendFormat: 'Duration p50', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vtgateDurationP50ByInstance: vtgateDurationTemplate { - title: 'Duration 50th quantile', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.50, - sum by(instance, le)( - rate( - vtgate_api_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vtgateDurationP95: vtgateDurationTemplate { - title: 'Duration 95th quantile', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.95, - sum by(le)( - vitess_mixin:vtgate_api_bucket:rate1m - ) - ) - |||, - legendFormat: 'Duration p95', - }, - ], - }, - - vtgateDurationP95ByInstance: vtgateDurationTemplate { - title: 'Duration 95th quantile', - fill: 0, - targets: [ - { - expr: ||| - histogram_quantile( - 0.95, - sum by(instance, le)( - rate( - vtgate_api_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO write a recording rule for this prometheus_vitess target - // only vtgate_api_sum requires a rule. Use 1m interval instead of 5m. - vtgateDurationAVG: vtgateDurationTemplate { - title: 'Duration (Avg)', - fill: 0, - targets: [ - { - expr: ||| - sum ( - rate( - vtgate_api_sum[5m] - ) - ) - / - sum ( - rate( - vtgate_api_count[5m] - ) - ) - |||, - legendFormat: 'Avg Latency', - }, - ], - }, - - //TODO write a recording rule for this prometheus_vitess target - vtgateDurationAVGByInstance: vtgateDurationTemplate { - title: 'Duration (Avg)', - fill: 0, - targets: [ - { - expr: ||| - sum by (instance)( - rate( - vtgate_api_sum{ - instance=~"$host" - }[5m] - ) - ) - / - sum by (instance)( - rate( - vtgate_api_count{ - instance=~"$host" - }[5m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vtgateDurationP99ByDBType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Duration 99th quantile (by db_type)', - format: 's', - targets: [ - { - expr: ||| - histogram_quantile( - 0.99, - sum by (db_type, le)( - vitess_mixin:vtgate_api_bucket_by_db_type:rate1m - ) - ) - |||, - legendFormat: '{{db_type}}', - }, - ], - }, - - vtgateErrorsByCode: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Errors (by code)', - format: 'cps', - targets: [ - { - expr: ||| - sum by (code)( - vitess_mixin:vtgate_api_error_counts_by_code:rate1m - ) - |||, - legendFormat: '{{code}}', - }, - ], - - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vtgateErrorsByInstanceCode: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Errors (by code)', - format: 'cps', - targets: [ - { - expr: ||| - sum by (instance,code)( - rate( - vtgate_api_error_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}} - {{code}}', - }, - ], - - }, - - vtgateErrorsByOperation: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Errors (by operation)', - format: 'cps', - targets: [ - { - expr: ||| - sum by (operation)( - vitess_mixin:vtgate_api_error_counts_by_operation:rate1m - ) - |||, - legendFormat: '{{operation}}', - }, - ], - - }, - - vtgateErrorsByDbtype: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Errors (by db_type)', - format: 'cps', - targets: [ - { - expr: ||| - sum by (db_type)( - vitess_mixin:vtgate_api_error_counts_by_db_type:rate1m - ) - |||, - legendFormat: '{{db_type}}', - }, - ], - - }, - - //TODO CREATE RECORDING RULE FOR THIS PROM TARGET - vtgateErrorsByInstanceKeyspace: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Errors (by keyspace)', - format: 'cps', - targets: [ - { - expr: ||| - sum by (instance,keyspace)( - rate( - vtgate_api_error_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{keyspace}}', - intervalFactor: 1, - }, - ], - }, - - vtgateRestart: { - title: 'vtgate', - bars: true, - datasource: '%(dataSource)s' % config._config, - fill: 0, - format: 'short', - legend_alignAsTable: true, - legend_current: false, - legend_max: true, - legend_min: false, - legend_sort: 'max', - legend_sortDesc: false, - legend_values: true, - lines: false, - min: 0, - shared_tooltip: false, - sort: 'increasing', - targets: [ - { - expr: ||| - sum by (instance)( - vitess_mixin:process_start_time_seconds_by_instance_job:sum5m{ - %(vtgateSelector)s - } - ) - ||| % config._config, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO crete a recording rule for this prometheus vitess target - vtgateGarbageCollectionCount: garbage_collector_panel_template { - title: 'GC Count', - format: 'ops', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - go_gc_duration_seconds_count{ - %(vtgateSelector)s - }[1m] - ) - ) - ||| % config._config, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - //TODO crete a recording rule for this prometheus vitess target - vtgateGarbageCollectionDuration: garbage_collector_panel_template { - title: 'GC Duration total per second', - description: 'A summary of the pause duration of garbage collection cycles', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - go_gc_duration_seconds_count{ - %(vtgateSelector)s - }[1m] - ) - ) - ||| % config._config, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - //TODO crete a recording rule for this prometheus vitess target - vtgateGarbageCollectionDurationQuantiles: garbage_collector_panel_template { - title: 'GC Duration quantiles', - targets: [ - { - expr: - ||| - sum by(quantile)( - rate( - go_gc_duration_seconds{ - %(vtgateSelector)s - }[1m] - ) - ) - ||| % config._config, - legendFormat: 'p{{quantile}}', - intervalFactor: 1, - }, - ], - }, - }, - - // _ _ _ _ - // ___(_)_ __ __ _| | ___ ___| |_ __ _| |_ ___ - // / __| | '_ \ / _` | |/ _ \/ __| __/ _` | __/ __| - // \__ \ | | | | (_| | | __/\__ \ || (_| | |_\__ \ - // |___/_|_| |_|\__, |_|\___||___/\__\__,_|\__|___/ - // |___/ - - //TODO move default configurations to helper code (vttablet_helper) - singlestats: { - - vtgateQPS: { - title: 'QPS - vtgate', - datasource: '%(dataSource)s' % config._config, - format: 'short', - valueFontSize: '70%', - valueName: 'current', - sparklineFull: true, - sparklineShow: true, - target: - { - expr: ||| - sum ( - vitess_mixin:vtgate_api_count:rate1m - ) - |||, - intervalFactor: 1, - }, - }, - - vtgateQueryLatencyP99: { - title: 'Query latency p99', - datasource: '%(dataSource)s' % config._config, - colorBackground: true, - decimals: 2, - format: 'ms', - valueFontSize: '70%', - valueName: 'current', - thresholds: '30,50', - target: - { - expr: ||| - 1000 * histogram_quantile( - 0.99, - sum by(le)( - vitess_mixin:vtgate_api_bucket:rate1m - ) - ) - |||, - instant: true, - intervalFactor: 1, - }, - }, - }, -} diff --git a/vitess-mixin/dashboards/resources/config/vttablet_config.libsonnet b/vitess-mixin/dashboards/resources/config/vttablet_config.libsonnet deleted file mode 100644 index 4dbd8a989de..00000000000 --- a/vitess-mixin/dashboards/resources/config/vttablet_config.libsonnet +++ /dev/null @@ -1,1073 +0,0 @@ -/** This is a configuration file containing metadata for vttablet grafana resources. */ - -local config = import '../../../config.libsonnet'; -local configuration_templates = import './configuration_templates.libsonnet'; -local vitess_ct = configuration_templates.prometheus_vitess; - -// TODO: move local template variables to ./configurations_templates.libsonnet. -{ - panels: { - // ____ _ - // | _ \ __ _ _ __ ___| |___ - // | |_) / _` | '_ \ / _ \ / __| - // | __/ (_| | | | | __/ \__ \ - // |_| \__,_|_| |_|\___|_|___/ - - // TODO: add description for each panel. - - //Override default_panel values with custom configuration - local vttablet_queries_killed = vitess_ct.panel.legend_min_max_avg + vitess_ct.panel.null_as_zeros, - local vttablet_query_errors_by_type = vitess_ct.panel.legend_min_max_avg + vitess_ct.panel.null_as_zeros, - - local panel_template = vitess_ct.panel.legend_min_max_current { - legend_sort: 'current', - legend_sortDesc: true, - shared_tooltip: true, - sort: 'decreasing', - }, - - local vttablet_host_view_panel_template = panel_template { - legend_sort: 'avg', - legend_avg: true, - legend_current: false, - }, - - //TODO Create a recording rule. - countServingTablets: - panel_template { - title: '# of serving tablets', - legend_sortDesc: false, - shared_tooltip: false, - sort: 'increasing', - targets: [ - { - expr: - ||| - count( - vttablet_tablet_server_state{ - %(vttabletSelector)s, - name="SERVING" - } - ) - ||| - % config._config, - legendFormat: 'SERVING', - }, - ], - }, - - vttabletRequestsByTable: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests (by table)', - format: 'rps', - targets: [ - { - expr: - ||| - sum by (table)( - vitess_mixin:vttablet_query_counts_by_keyspace_table:rate1m{ - table=~"$table" - } - ) - or - vector(0) - |||, - legendFormat: '{{table}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMEHTEUS TARGET - vttabletRequestsByPlanType: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests (by plan type)', - format: 'ops', - nullPointMode: 'null as zero', - targets: [ - { - expr: - ||| - sum by (plan_type)( - rate( - vttablet_queries_count{ - instance=~"$host" - } [1m] - ) - ) - |||, - legendFormat: '{{plan_type}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vttabletRequestsByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests', - format: 'ops', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - nullPointMode: 'null as zero', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_query_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vttabletRequestsByTableFilteredByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Requests (by table)', - format: 'ops', - nullPointMode: 'null as zero', - targets: [ - { - expr: - ||| - sum by (table)( - rate( - vttablet_query_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{table}}', - intervalFactor: 1, - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vttabletErrorRateByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate', - format: 'percentunit', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - / - ( - sum by (instance)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - + - sum by (instance)( - rate( - vttablet_query_counts{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vttabletErrorRateByPlanFilteredByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate (by plan type)', - format: 'percentunit', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - targets: [ - { - expr: - ||| - sum by (plan)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - / - ( - sum by (plan)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - + - sum by (plan)( - rate( - vttablet_query_counts{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{plan}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROM TARGET - vttabletErrorRateByTableFilteredByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Error rate (by table)', - format: 'percentunit', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - targets: [ - { - expr: - ||| - sum by (table)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - / - ( - sum by (table)( - rate( - vttablet_query_error_counts{ - instance=~"$host" - }[1m] - ) - ) - + - sum by (table)( - rate( - vttablet_query_counts{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{table}}', - }, - ], - }, - - vttabletRowsReturnedByTableFilteredByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Rows Returned (by table)', - targets: [ - { - expr: - ||| - sum by (table) ( - rate( - vttablet_query_row_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{table}}', - }, - ], - }, - - vttabletRowsReturnedByPlansFilterByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Rows Returned (by plan)', - targets: [ - { - expr: - ||| - sum by (plan) ( - rate( - vttablet_query_row_counts{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{plan}}', - }, - ], - }, - - //TODO DEDUPLICATE LEGEND CONFIGURATION FOR QUERY DURATION PANELS - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryDurationAvgByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Query Duration (avg)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - vttablet_queries_sum{ - instance=~"$host" - }[1m] - ) - ) - / - sum by(instance)( - rate( - vttablet_queries_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryDurationP50ByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Query Duration (p50)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.50,sum by(instance,le)( - rate( - vttablet_queries_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryDurationP95ByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Query Duration (p95)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.95,sum by(instance,le)( - rate( - vttablet_queries_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryDurationP99ByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Duration (p99)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.99,sum by(instance,le)( - rate( - vttablet_queries_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryDurationP99ByPlan: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Duration p99 (by plan type)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'avg', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.99,sum by(plan_type,le)( - rate( - vttablet_queries_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{plan_type}}', - }, - ], - }, - - //TODO DEDUPLICATE LEGEND CONFIGURATION FOR TRANSACTION DURATION PANELS - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionDurationAvgByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Transaction Duration (avg)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - vttablet_transactions_sum{ - instance=~"$host" - }[1m] - ) - ) - / - sum by(instance)( - rate( - vttablet_transactions_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionDurationP50ByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Transaction Duration (p50)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.50,sum by(instance,le)( - rate( - vttablet_transactions_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionDurationP95ByInstance: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Transaction Duration (p95)', - format: 's', - legend_current: false, - legend_avg: true, - legend_sort: 'max', - targets: [ - { - expr: - ||| - histogram_quantile( - 0.95,sum by(instance,le)( - rate( - vttablet_transactions_bucket{ - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vttabletQueryTransactionKilled: - panel_template - + vitess_ct.panel.null_as_zeros { - title: 'Query/Transaction killed', - format: 'cps', - legend_alignAsTable: true, - shared_tooltip: false, - targets: [ - { - expr: - ||| - sum ( - vitess_mixin:vttablet_kills:rate1m - ) - |||, - legendFormat: 'Killed', - }, - ], - }, - - vttabletRestart: { - title: 'vttablet', - bars: true, - datasource: '%(dataSource)s' % config._config, - fill: 0, - format: 'short', - legend_values: true, - legend_alignAsTable: true, - legend_max: true, - legend_sort: 'max', - legend_sortDesc: false, - lines: false, - min: 0, - shared_tooltip: false, - sort: 'increasing', - targets: [ - { - expr: - ||| - sum by (instance) ( - vitess_mixin:process_start_time_seconds_by_instance_job:sum5m{ - %(vttabletSelector)s - } - ) - ||| % config._config, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryPoolAvailableConnections: vttablet_host_view_panel_template { - title: 'Available Connections', - description: 'number of available connections in the pool in real-time', - format: 'short', - targets: [ - { - expr: - ||| - sum by (instance)( - vttablet_conn_pool_available{ - instance=~'$host' - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryPoolActiveConnections: vttablet_host_view_panel_template { - title: 'Active Connections', - description: 'count of in use connections to mysql', - format: 'short', - targets: [ - { - expr: - ||| - sum by(instance) ( - vttablet_conn_pool_active{ - instance=~'$host' - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryPoolIddleClosedRate: vttablet_host_view_panel_template { - title: 'Idle Closed Rate', - description: 'rate of closing connections due to the idle timeout', - format: 'ops', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_conn_pool_idle_closed{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryPoolWaitCount: vttablet_host_view_panel_template { - title: 'Wait count', - description: 'WaitCount will give you how often the transaction pool gets full that causes new transactions to wait.', - format: 'short', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_conn_pool_wait_count{ - instance=~'$host' - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryPoolAvgWaitTime: vttablet_host_view_panel_template { - title: 'Avg wait time', - format: 's', - description: 'WaitTime/WaitCount will tell you the average wait time.', - targets: [ - { - expr: - ||| - sum by (instance) ( - rate( - vttablet_conn_pool_wait_time{ - instance=~"$host" - }[1m] - ) - ) - / - sum by (instance) ( - rate( - vttablet_conn_pool_wait_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vttabletQueriesKilled: vttablet_queries_killed { - title: 'Queries Killed', - description: ||| - Kills reports the queries and transactions killed by VTTablet due to timeout. - It’s a very important variable to look at during outages. - |||, - targets: [ - { - expr: ||| - sum by (instance)( - vitess_mixin:vttablet_kills_by_instance:rate1m{ - instance=~"$host" - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - vttabletQueryErrorsByType: vttablet_query_errors_by_type { - title: 'Query errors (by error code)', - description: '', - targets: [ - { - expr: ||| - sum by (error_code)( - vitess_mixin:vttablet_errors:rate1m{ - instance=~"$host" - } - ) - |||, - legendFormat: 'ErrorCode: {{error_code}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionPoolAvailableConnections: vttablet_host_view_panel_template { - title: 'Available Connections', - description: 'number of available connections in the pool', - format: 'short', - targets: [ - { - expr: - ||| - sum by (instance)( - vttablet_transaction_pool_available{ - instance=~'$host' - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionPoolActiveConnections: vttablet_host_view_panel_template { - title: 'Active Connections', - description: 'Number of connections actually open to mysql', - format: 'short', - targets: [ - { - expr: - ||| - sum by(instance) ( - vttablet_transaction_pool_active{ - instance=~'$host' - } - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionPoolIddleClosedRate: vttablet_host_view_panel_template { - title: 'Idle Closed Rate', - description: 'Rate of closing connections due to the idle timeout', - format: 'ops', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_transaction_pool_idle_closed{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionPoolWaitCount: vttablet_host_view_panel_template { - title: 'Wait count', - description: 'WaitCount will give you how often the transaction pool gets full that causes new transactions to wait.', - format: 'short', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vttablet_transaction_pool_wait_count{ - instance=~'$host' - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletTransactionPoolAvgWaitTime: vttablet_host_view_panel_template { - title: 'Avg wait time', - format: 's', - description: 'WaitTime/WaitCount will tell you the average wait time.', - targets: [ - { - expr: - ||| - sum by (instance) ( - rate( - vttablet_transaction_pool_wait_time{ - instance=~"$host" - }[1m] - ) - ) - / - sum by (instance) ( - rate( - vttablet_transaction_pool_wait_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletGarbageCollectionCount: vitess_ct.panel.go_gc_ops { - title: 'GC Count', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - go_gc_duration_seconds_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletGarbageCollectionDuration: vitess_ct.panel.go_gc_seconds { - title: 'GC Duration total per second', - description: 'A summary of the pause duration of garbage collection cycles', - targets: [ - { - expr: - ||| - sum by(instance)( - rate( - go_gc_duration_seconds_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - intervalFactor: 1, - }, - ], - }, - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletGarbageCollectionDurationQuantiles: vitess_ct.panel.go_gc_seconds { - title: 'GC Duration quantiles (all hosts)', - targets: [ - { - expr: - ||| - sum by(quantile)( - rate( - go_gc_duration_seconds{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: 'p{{quantile}}', - intervalFactor: 1, - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletMysqlTimeAvgFilteredByInstance: vitess_ct.panel.mysql_timings { - title: 'MySQL time (avg)', - targets: [ - { - expr: - ||| - sum by (instance) ( - rate( - vttablet_mysql_sum{ - instance=~"$host" - }[1m] - ) - ) - / - sum by (instance) ( - rate( - vttablet_mysql_count{ - instance=~"$host" - }[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletMysqlExecTimeP50FilterebyInstance: vitess_ct.panel.mysql_timings { - title: 'MySQL Exec Time P50', - targets: [ - { - expr: ||| - histogram_quantile( - 0.50, - sum by (le, instance) ( - rate( - vttablet_mysql_bucket{ - operation="Exec", - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletMysqlExecTimeP95FilterebyInstance: vitess_ct.panel.mysql_timings { - title: 'MySQL Exec Time P95', - targets: [ - { - expr: ||| - histogram_quantile( - 0.95, - sum by (le, instance) ( - rate( - vttablet_mysql_bucket{ - operation="Exec", - instance=~"$host" - }[1m] - ) - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vtgateToVtTabletCallTimeAvgFilteredByInstance: vitess_ct.panel.vtgate_to_vttablet_calls { - title: 'VtGate -> VtTablet Call Time (avg)', - targets: [ - { - expr: - ||| - sum by (instance)( - rate( - vtgate_vttablet_call_sum[1m] - ) - ) - / - sum by (instance)( - rate( - vtgate_vttablet_call_count[1m] - ) - ) - |||, - legendFormat: '{{instance}}', - }, - ], - }, - - }, - - singlestats: { - // _ _ _ _ - // ___(_)_ __ __ _| | ___ ___| |_ __ _| |_ ___ - // / __| | '_ \ / _` | |/ _ \/ __| __/ _` | __/ __| - // \__ \ | | | | (_| | | __/\__ \ || (_| | |_\__ \ - // |___/_|_| |_|\__, |_|\___||___/\__\__,_|\__|___/ - // |___/ - - vttabletQPS: { - title: 'QPS - vttablet', - datasource: '%(dataSource)s' % config._config, - format: 'short', - valueFontSize: '70%', - valueName: 'current', - sparklineFull: true, - sparklineShow: true, - target: - { - expr: ||| - sum ( - vitess_mixin:vttablet_query_counts:rate1m - ) - |||, - intervalFactor: 1, - }, - }, - }, -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/heatmaps.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/heatmaps.libsonnet deleted file mode 100644 index 9a6e5f41527..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/heatmaps.libsonnet +++ /dev/null @@ -1,36 +0,0 @@ -// Re-cyclable components for heatmap resources -local config = import '../../../config.libsonnet'; -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; - -local heatmap = grafana.heatmapPanel; -local prometheus = grafana.prometheus; -{ - //TODO move to resources/vttablet - //TODO CREATE A RECORDING RULE FOR THIS PROMETHEUS TARGET - vttabletQueryTimeDistribution:: - heatmap.new( - title='Query Time Distribution (Heatmap)', - description='Shows a heatmap of the histogram bucketing of the time per read query.', - datasource='%(dataSource)s' % config._config, - dataFormat='tsbuckets', - yAxis_format='s', - color_cardColor='#FF9830', - color_exponent=0.3, - color_mode='opacity', - yAxis_decimals=0, - ).addTarget( - prometheus.target( - ||| - sum by (le) ( - rate( - vttablet_queries_bucket{ - instance=~"$host" - }[1m] - ) - ) - |||, - format='heatmap', - legendFormat='{{le}}' - ) - ), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/dashboard_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/dashboard_helper.libsonnet deleted file mode 100644 index d998cc65540..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/dashboard_helper.libsonnet +++ /dev/null @@ -1,16 +0,0 @@ -/** This is a helper library to load grafonnet dashboards using the mixin metadata stored in `config.libshonnet` */ - -local grafonnet_helper = import 'grafonnet_helper.libsonnet'; - -{ - /** - * Builds a dashboard using grafonnet and the configuration from `config.libsonnet` - * - * @name dashboard_helper.getDashboard - * - * @param config The dashboard configuration from mixin config file. - * @return A new graphPanel with the configuration specified in `config.libsonnet` - * - */ - getDashboard(config):: grafonnet_helper.getDashboard(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/grafonnet_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/grafonnet_helper.libsonnet deleted file mode 100644 index 2ff41c6a06f..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/grafonnet_helper.libsonnet +++ /dev/null @@ -1,376 +0,0 @@ -/** - * This is a helper library to generate grafana resources reading the configuration from a config file. - */ - -local grafana = import '../../../../vendor/grafonnet/grafana.libsonnet'; -local prometheus = grafana.prometheus; -local alert_condition = grafana.alertCondition; - -// _ _ _ -// __ _ _ __ _ __ ___ | |_ __ _| |_(_) ___ _ __ -// / _` | '_ \| '_ \ / _ \| __/ _` | __| |/ _ \| '_ \ -// | (_| | | | | | | | (_) | || (_| | |_| | (_) | | | | -// \__,_|_| |_|_| |_|\___/ \__\__,_|\__|_|\___/|_| |_| - -local getAnnotation(config) = if (config.name == 'default') then - grafana.annotation.default -else - // TODO when the properties are supported by grafonnet use the lib constructor - // instead of using composition - grafana.annotation.datasource( - config.name, - config.datasource - ) + - config.properties; - -// _ _ _ _ -// __| | __ _ ___| |__ | |__ ___ __ _ _ __ __| | -// / _` |/ _` / __| '_ \| '_ \ / _ \ / _` | '__/ _` | -// | (_| | (_| \__ \ | | | |_) | (_) | (_| | | | (_| | -// \__,_|\__,_|___/_| |_|_.__/ \___/ \__,_|_| \__,_| - -local getDashboard(config) = grafana.dashboard.new( - title=config.title, - description=config.description, - uid=config.uid, - time_from=config.time_from, - tags=(config.dashboardTags), - editable=true, - graphTooltip='shared_crosshair', -) + { - environments:: config.environments, -}; - -// _ -// _ __ __ _ _ __ ___| | -// | '_ \ / _` | '_ \ / _ \ | -// | |_) | (_| | | | | __/ | -// | .__/ \__,_|_| |_|\___|_| -// |_| -// The default panel contains all the parameters that we want to override. -// https://github.com/grafana/grafonnet-lib/blob/master/grafonnet/graph_panel.libsonnet - -local default_panel = { - title: '', - aliasColors: {}, - bars: false, - decimals: null, - description: null, - format: 'short', - fill: 1, - legend_alignAsTable: false, - legend_avg: false, - legend_current: false, - legend_hideZero: null, - legend_max: false, - legend_min: false, - legend_rightSide: false, - legend_sort: null, - legend_sortDesc: null, - legend_values: false, - lines: true, - linewidth: 1, - max: null, - min: null, - points: false, - pointradius: 5, - nullPointMode: 'null', - shared_tooltip: true, - sort: 0, - thresholds: [], -}; - -local default_prometheus_target = { - format: 'time_series', - instant: null, - intervalFactor: 2, - legendFormat: '', -}; - -local default_alert_condition = { - evaluatorParams: [], - evaluatorType: 'gt', - operatorType: 'and', - queryRefId: 'A', - queryTimeEnd: 'now', - queryTimeStart: '5m', - reducerParams: [], - reducerType: 'avg', -}; - -local getConditions(config) = - if std.objectHas(config.alert[std.extVar('env')], 'conditions') then - //reducerType is a grafonnet field value. This asserts the config is not legacy - if std.objectHas(config.alert[std.extVar('env')].conditions[0], 'reducerType') - then - local x = std.map( - function(c) default_alert_condition + c - , config.alert[std.extVar('env')].conditions - ); - std.map( - function(c) - alert_condition.new( - evaluatorParams=c.evaluatorParams, - evaluatorType=c.evaluatorType, - operatorType=c.operatorType, - queryRefId=c.queryRefId, - queryTimeEnd=c.queryTimeEnd, - queryTimeStart=c.queryTimeStart, - reducerParams=c.reducerParams, - reducerType=c.reducerType, - ) - , x - ) - else - //Legacy config files include calls to grafonnet.alert_condition.new() - //TODO update legacy config files to use alert conditions in json format, - config.alert[std.extVar('env')].conditions - else []; - -local getTargets(config) = - if std.objectHas(config, 'targets') then - if config.datasource != null && - std.startsWith(config.datasource, 'Prometheus') && - std.objectHas(config.targets[0], 'expr') - then - local x = std.map( - function(t) default_prometheus_target + t - , config.targets - ); - std.map( - function(t) - prometheus.target( - t.expr, - legendFormat=t.legendFormat, - instant=t.instant, - intervalFactor=t.intervalFactor, - format=t.format - ) - , x - ) - else - //When the datasource is not prometheus(elastic, graphite) config file - //include calls to graphite.target() and elasticsearch.target(). - //see webapp_config.lisonnet - //TODO Update this method to decouple grafonnet code from the configuration files. - //Legacy configuration files include prometheus.target() calls. - //TODO update legacy config files to use {'expr':'Prom query' ...} format, - config.targets - else []; - -// This method overriddes grafonnet graphPanel defaults with the values in the config file . -// https://github.com/grafana/grafonnet-lib/blob/master/grafonnet/graph_panel.libsonnet -// TODO: When grapPanel supports either addLinks (https://github.com/grafana/grafonnet-lib/pull/278) -// we should add the links there instead of composing the `options` field. -local initPanel(config) = - grafana.graphPanel.new( - title=config.title, - aliasColors=config.aliasColors, - bars=config.bars, - datasource=config.datasource, - decimals=config.decimals, - description=config.description, - fill=config.fill, - format=config.format, - legend_alignAsTable=config.legend_alignAsTable, - legend_avg=config.legend_avg, - legend_rightSide=config.legend_rightSide, - legend_hideZero=config.legend_hideZero, - legend_min=config.legend_min, - legend_max=config.legend_max, - legend_current=config.legend_current, - legend_sort=config.legend_sort, - legend_sortDesc=config.legend_sortDesc, - legend_values=config.legend_values, - lines=config.lines, - linewidth=config.linewidth, - max=config.max, - min=config.min, - points=config.points, - pointradius=config.pointradius, - nullPointMode=config.nullPointMode, - shared_tooltip=config.shared_tooltip, - sort=config.sort, - thresholds=config.thresholds, - ).addTargets( - getTargets(config) - ) + - { - [if std.objectHas(config, 'options') - then 'options']: - config.options, - }; - -local getPanel(c) = - if std.objectHas(c, 'alert') then - local config = default_panel + c; - local panel = initPanel(config).addAlert( - config.alert.name, - executionErrorState=config.alert.executionErrorState, - forDuration=config.alert.forDuration, - frequency=config.alert.frequency, - message=config.alert.message, - noDataState=config.alert.noDataState, - notifications=config.alert[std.extVar('env')].notifications, - ).addConditions( - getConditions(config) - ); - if std.objectHas(config, 'seriesOverrides') then - local it = panel; - std.foldl(function(p, o) p.addSeriesOverride(o), config.seriesOverrides, it) - else - panel - else - (local config = default_panel + c; - local panel = initPanel(config); - if std.objectHas(config, 'seriesOverrides') then - local it = panel; - std.foldl(function(p, o) p.addSeriesOverride(o), config.seriesOverrides, it) - else - panel); - -// _ __ _____ __ -// | '__/ _ \ \ /\ / / -// | | | (_) \ V V / -// |_| \___/ \_/\_/ - -local row_default = { - title: '', - height: null, - collapse: false, - repeat: null, - showTitle: null, - titleSize: 'h6', -}; - -local getRow(c) = - local config = row_default + c; - grafana.row.new( - title=config.title, - height=config.height, - collapse=config.collapse, - repeat=config.repeat, - showTitle=config.showTitle, - titleSize=config.titleSize - ); - -// _ _ _ _ -// ___(_)_ __ __ _| | ___ ___| |_ __ _| |_ -// / __| | '_ \ / _` | |/ _ \/ __| __/ _` | __| -// \__ \ | | | | (_| | | __/\__ \ || (_| | |_ -// |___/_|_| |_|\__, |_|\___||___/\__\__,_|\__| -// |___/ -//The default value should include all the parameters that are overridden by the objects that extend the default. -//Default values match grafonnet defaults > https://github.com/grafana/grafonnet-lib/blob/master/grafonnet/singlestat.libsonnet - -local default_singlestat = { - colors: [ - '#299c46', - 'rgba(237, 129, 40, 0.89)', - '#d44a3a', - ], - colorBackground: false, - decimals: null, - format: 'none', - valueFontSize: '80%', - valueName: 'avg', - sparklineFull: false, - sparklineShow: false, - thresholds: '', -}; - -local initSingleStat(config) = grafana.singlestat.new( - title=config.title, - datasource=config.datasource, - colors=config.colors, - colorBackground=config.colorBackground, - decimals=config.decimals, - format=config.format, - valueFontSize=config.valueFontSize, - valueName=config.valueName, - sparklineFull=config.sparklineFull, - sparklineShow=config.sparklineShow, - thresholds=config.thresholds, -); - -local getSingleStat(c) = if std.objectHas(c, 'target') -then - local config = default_singlestat + c; - local tc = default_prometheus_target + config.target; - local t = prometheus.target( - tc.expr, - legendFormat=tc.legendFormat, - instant=tc.instant, - intervalFactor=tc.intervalFactor, - format=tc.format - ); - initSingleStat(config).addTarget(t) -else - local config = default_singlestat + c; - initSingleStat(config); - -// _ _ _ -// | |_ ___ _ __ ___ _ __ | | __ _| |_ ___ -// | __/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \ -// | || __/ | | | | | |_) | | (_| | || __/ -// \__\___|_| |_| |_| .__/|_|\__,_|\__\___| -// |_| -// default values from https://github.com/grafana/grafonnet-lib/blob/master/grafonnet/template.libsonnet -local template_default = { - label: null, - allValues: null, - tagValuesQuery: '', - current: null, - hide: '', - regex: '', - refresh: 'never', - includeAll: false, - multi: false, - sort: 0, -}; -local getTemplate(c) = - local config = template_default + c; - grafana.template.new( - name=config.name, - datasource=config.datasource, - query=config.query, - label=config.label, - current=config.current, - regex=config.regex, - refresh=config.refresh, - sort=config.sort, - ); - -// _ _ _ _ _ _ _ -// __| | __ _ ___| |__ | |__ ___ __ _ _ __ __| | | (_)_ __ | | __ -// / _` |/ _` / __| '_ \| '_ \ / _ \ / _` | '__/ _` | | | | '_ \| |/ / -// | (_| | (_| \__ \ | | | |_) | (_) | (_| | | | (_| | | | | | | | < -// \__,_|\__,_|___/_| |_|_.__/ \___/ \__,_|_| \__,_| |_|_|_| |_|_|\_\ -local link_default = { - asDropdown: true, - includeVars: false, - keepTime: false, - icon: 'external link', - url: '', - targetBlank: false, - type: 'dashboards', -}; - -local getDashboardLink(c) = - local config = link_default + c; - grafana.link.dashboards( - title=config.title, - tags=config.tags, - keepTime=config.keepTime, - includeVars=config.includeVars, - ); - -{ - getAnnotation(config):: getAnnotation(config), - getDashboard(config):: getDashboard(config), - getPanel(config):: getPanel(config), - getRow(config):: getRow(config), - getSingleStat(config):: getSingleStat(config), - getTemplate(config):: getTemplate(config), - getDashboardLink(config):: getDashboardLink(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/helpers.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/helpers.libsonnet deleted file mode 100644 index a6d74985dd3..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/helpers.libsonnet +++ /dev/null @@ -1,9 +0,0 @@ -// TODO deduplicate helper code. Same/similar functions are used by vtgate, vttablet and orchestrator helpers -{ - dashboard:: import 'dashboard_helper.libsonnet', - default:: import 'grafonnet_helper.libsonnet', - mysql:: import 'mysql_helper.libsonnet', - os:: import 'os_helper.libsonnet', - vtgate:: import 'vtgate_helper.libsonnet', - vttablet:: import 'vttablet_helper.libsonnet', -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/mysql_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/mysql_helper.libsonnet deleted file mode 100644 index 3d0b1ff6a44..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/mysql_helper.libsonnet +++ /dev/null @@ -1,19 +0,0 @@ -/** - * This is a helper library to generate os resources reading the configuration from mysql_config.libsonnet - */ - -local grafonnet_helper = import './grafonnet_helper.libsonnet'; - -/** - * Builds grapPanel using grafonnet and the configuration from `mysql_config.libsonnet` - * - * @name mysql_helper.getPanel - * - * @param `config`: The panel configuration from mysql_config file. - * - * @return A new graphPanel with the configuration specified in `mysql_config.libsonnet` - * - */ -{ - getPanel(config):: grafonnet_helper.getPanel(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/os_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/os_helper.libsonnet deleted file mode 100644 index 2580d54e43a..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/os_helper.libsonnet +++ /dev/null @@ -1,19 +0,0 @@ -/** - * This is a helper library to generate os resources reading the configuration from os_config.libsonnet - */ - -local grafonnet_helper = import './grafonnet_helper.libsonnet'; - -{ - /** - * Builds grapPanel using grafonnet and the configuration from `os_config.libsonnet` - * - * @name os_helper.getPanel - * - * @param `config`: The panel configuration from os_config file. - * - * @return A new graphPanel with the configuration specified in `os_config.libsonnet` - * - */ - getPanel(config):: grafonnet_helper.getPanel(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/vtgate_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/vtgate_helper.libsonnet deleted file mode 100644 index 2997979edf4..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/vtgate_helper.libsonnet +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This is a helper library to generate vtgate resources reading the configuration from vtgate_config.libsonnet - */ - -local grafonnet_helper = import './grafonnet_helper.libsonnet'; - -{ - /** - * Builds grapPanel using grafonnet and the configuration from `vtgate_config.libsonnet` - * - * @name vtgate_helper.getPanel - * - * @param `config`: The panel configuration from vtgate_config file. - * - * @return A new graphPanel with the configuration specified in `vtgate_config.libsonnet` - * - */ - getPanel(config):: grafonnet_helper.getPanel(config), - - /** - * Builds a singlestat using grafonnet and the configuration from `vtgate_config.libsonnet` - * - * @name vtgate_helper.getSingleStat - * - * @param `config`: The singlestat configuration from vtgate_config file. - * - * @return A new singlestat with the configuration specified in `vtgate_config.libsonnet` - * - */ - getSingleStat(config):: grafonnet_helper.getSingleStat(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/helpers/vttablet_helper.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/helpers/vttablet_helper.libsonnet deleted file mode 100644 index 2613de0f094..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/helpers/vttablet_helper.libsonnet +++ /dev/null @@ -1,29 +0,0 @@ -/** - * This is a helper library to generate vttablet resources reading the configuration from `vttablet_config.libsonnet` - */ -local grafonnet_helper = import './grafonnet_helper.libsonnet'; - -{ - /** - * Builds grapPanel using grafonnet and the configuration from `vttablet_config.libsonnet` - * - * @name vttablet_helper.getPanel - * - * @param `config`: The panel configuration from vttablet_config file. - * - * @return A new graphPanel with the configuration specified in `vttablet_config.libsonnet` - * - */ - getPanel(config):: grafonnet_helper.getPanel(config), - /** - * Builds singlestat using grafonnet and the configuration from `vttablet_config.libsonnet` - * - * @name vttablet_helper.getPanel - * - * @param `config`: The singlestat configuration from vttablet_config file. - * - * @return A new singlestat with the configuration specified in `vttablet_config.libsonnet` - * - */ - getSingleStat(config):: grafonnet_helper.getSingleStat(config), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/panels.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/panels.libsonnet deleted file mode 100644 index 40c20a2cb10..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/panels.libsonnet +++ /dev/null @@ -1,65 +0,0 @@ -// Re-cyclable components for panel resources -local config = import '../../../config.libsonnet'; -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; - -local graphPanel = grafana.graphPanel; -local prometheus = grafana.prometheus; - -// TODO: add description for each panel. -// TODO: create a _helper _config file for each group [vtctld], -{ - // _ _ _ _ - // __ _| |_ ___| |_| | __| | - // \ \ / / __/ __| __| |/ _` | - // \ V /| || (__| |_| | (_| | - // \_/ \__\___|\__|_|\__,_| - // - - // _ - // _ __ ___ (_)___ ___ - // | '_ ` _ \| / __|/ __| - // | | | | | | \__ \ (__ - // |_| |_| |_|_|___/\___| - // - local default_notification_config = { - prod+: { - notifications: [ - { uid: 'alerts-vitess' }, - { uid: 'pagerduty-vitess' }, - ], - }, - dev+: { - notifications: [ - { uid: 'alerts-vitess-dev' }, - ], - }, - }, - - vtctldRestart:: - graphPanel.new( - 'vtctld', - bars=true, - datasource='%(dataSource)s' % config._config, - fill=0, - format='short', - legend_values=true, - legend_alignAsTable=true, - legend_max=true, - legend_sort='max', - legend_sortDesc=false, - lines=false, - min=0, - shared_tooltip=false, - sort='increasing', - ) - .addTarget(prometheus.target( - ||| - sum by (instance) ( - vitess_mixin:process_start_time_seconds_by_instance_job:sum5m{ - %(vtctldSelector)s - } - ) > 0 - ||| % config._config, - legendFormat='{{instance}}' - )), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/rows.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/rows.libsonnet deleted file mode 100644 index 54173c2a3f1..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/rows.libsonnet +++ /dev/null @@ -1,182 +0,0 @@ -// Re-cyclable components for row resources -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; -local row = grafana.row; - -//TODO move all rows to config/row_config.libsonnet and update the layouts to use grafonnet_helper.getRow() -{ - connection:: - row.new( - title='Connection', - ), - - cpu:: - row.new( - title='CPU', - collapse=true, - ), - - duration:: - row.new( - title='Duration', - collapse=true, - ), - - errorsRowsReturned:: - row.new( - title='Errors / Rows returned', - ), - - errors:: - row.new( - title='Errors', - collapse=true, - ), - - healthcheck:: - row.new( - title='Healthcheck', - collapse=true, - ), - - tabletsQueries:: - row.new( - title='Tablets/Queries', - ), - - mysql:: - row.new( - title='MySQL', - collapse=true, - ), - - misc:: - row.new( - title='Misc', - collapse=true, - ), - - networkingTCP:: - row.new( - title='Networking TCP', - collapse=true, - ), - - networkNIC:: - row.new( - title='Network NIC', - collapse=true, - ), - - OS:: - row.new( - title='OS', - collapse=true, - ), - - processes:: - row.new( - title='Processes', - collapse=true, - ), - - queryTimings:: - row.new( - // as we don't have timings by table (yet!) - title="Query/Transaction timings (table filter doesn't apply)", - collapse=true, - ), - - query:: - row.new( - title='Query', - ), - - RED:: - row.new( - title='RED - Requests / Error rate / Duration', - ), - - REDByKeyspace:: - row.new( - title='RED (by keyspace)', - collapse=true - ), - - REDByTabletType:: - row.new( - title='RED (by tablet type)', - collapse=true - ), - - REDByPlanType:: - row.new( - title='RED (by plan type)', - collapse=true - ), - - REDByShard:: - row.new( - title='RED (by shard)', - collapse=true - ), - - REDByTable:: - row.new( - title='RED (by table)', - collapse=true - ), - - - rowsReturned:: - row.new( - title='Rows returned', - collapse=true, - ), - - serviceRestart:: - row.new( - title='Service restart', - ), - - storage:: - row.new( - title='Storage', - collapse=true, - ), - - topLevel:: - row.new( - title='Top level', - ), - - topologyWatcher:: - row.new( - title='Topology watcher', - collapse=true, - ), - - vitessQueryPool:: - row.new( - title='Vitess - Query pool', - collapse=true, - ), - - vitessTransactionPool:: - row.new( - title='Vitess - Transaction pool', - collapse=true, - ), - - vtgate:: - row.new( - title='vtgate - Requests (by table / by plan / by keyspace )', - collapse=true, - ), - - vttablet:: - row.new( - title='vttablet - Requests (by table / by plan / by keyspace )', - collapse=true, - ), - -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/singlestats.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/singlestats.libsonnet deleted file mode 100644 index e3930e382d8..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/singlestats.libsonnet +++ /dev/null @@ -1,221 +0,0 @@ -// Re-cyclable components for singlestat resources -local config = import '../../../config.libsonnet'; -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; - -local singlestat = grafana.singlestat; -local prometheus = grafana.prometheus; - -{ - //TODO move to resource to use vtgate_config/vtgate_helper - vtgateSuccessRate:: - singlestat.new( - 'Query success - vtgate', - datasource='%(dataSource)s' % config._config, - colorBackground=true, - decimals=4, - format='percent', - colors=[ - '#d44a3a', - 'rgba(237, 129, 40, 0.89)', - '#299c46', - ], - valueFontSize='70%', - valueName='current', - thresholds='0.99,0.999', - ) - .addTarget( - prometheus.target( - ||| - 100 - - - sum( - rate( - vtgate_api_error_counts{ - %(vtgateSelector)s - }[$interval] - ) OR vector(0) - ) - / - sum( - rate( - vtgate_api_count{ - %(vtgateSelector)s - }[$interval] - ) - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - //TODO move to resource to use vtgate_config/vtgate_helper - vtgateUp:: - singlestat.new( - 'vtgate', - datasource='%(dataSource)s' % config._config, - valueFontSize='50%', - valueName='current', - ) - .addTarget( - prometheus.target( - ||| - sum( - up{ - %(vtgateSelector)s - } - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - //TODO move to resource to use vttablet_config/vttablet_helper - vttabletQuerySuccess:: - singlestat.new( - 'Query success - vttablet', - datasource='%(dataSource)s' % config._config, - colorBackground=true, - decimals=4, - format='percent', - colors=[ - '#d44a3a', - 'rgba(237, 129, 40, 0.89)', - '#299c46', - ], - valueFontSize='70%', - valueName='current', - thresholds='0.99,0.999', - ) - .addTarget( - prometheus.target( - ||| - 100 - - - ( - sum ( - vitess_mixin:vttablet_errors:rate1m - ) - / - sum ( - vitess_mixin:vttablet_query_counts:rate1m - ) - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - //TODO move to resource to use vttablet_config/vttablet_helper - vttabletUp:: - singlestat.new( - 'vttablet', - datasource='%(dataSource)s' % config._config, - valueFontSize='50%', - valueName='current', - ) - .addTarget( - prometheus.target( - ||| - sum( - up{ - %(vttabletSelector)s - } - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - - //TODO move to resource to use vttablet_config/vttablet_helper - keyspaceCount:: - singlestat.new( - 'keyspace', - description='count of keyspaces with active queries', - datasource='%(dataSource)s' % config._config, - valueFontSize='50%', - valueName='current', - ) - .addTarget( - prometheus.target( - ||| - count( - count by (keyspace)( - vtgate_vttablet_call_count{ - } - ) - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - //TODO move to resource to use vttablet_config/vttablet_helper - shardCount:: - singlestat.new( - 'shard', - datasource='%(dataSource)s' % config._config, - valueFontSize='50%', - valueName='current', - ) - .addTarget( - prometheus.target( - ||| - count( - count by(shard)( - vttablet_tablet_state{ - %(vttabletSelector)s - } - ) - ) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), - - mysqlQPS:: - singlestat.new( - 'QPS - MySQL', - datasource='%(dataSource)s' % config._config, - format='short', - valueFontSize='70%', - valueName='current', - sparklineFull=true, - sparklineShow=true, - ) - .addTarget( - prometheus.target( - ||| - sum ( - vitess_mixin:mysql_global_status_queries:rate1m - ) - |||, - intervalFactor=1 - ) - ), - - vtctldUp:: - singlestat.new( - 'vtctld', - datasource='%(dataSource)s' % config._config, - valueFontSize='50%', - valueName='current', - ) - .addTarget( - prometheus.target( - ||| - sum( - up{ - %(vtctldSelector)s}) - ||| % config._config, - instant=true, - intervalFactor=1 - ) - ), -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/templates.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/templates.libsonnet deleted file mode 100644 index a32b71283c4..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/templates.libsonnet +++ /dev/null @@ -1,51 +0,0 @@ -// Re-cyclable components for template resources -local config = import '../../../config.libsonnet'; -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; - -local template = grafana.template; -{ - interval:: template.interval( - name='interval', - label='Interval', - query='auto,1m,5m,10m,30m,1h,6h,12h', - current='auto', - auto_min='1m' - ), - - table:: - template.new( - 'table', - '%(dataSource)s' % config._config, - 'query_result(sum by(table)(vitess_mixin:vtgate_queries_processed_by_table:rate1m{keyspace="$keyspace"}))', - regex='.*table="(.*)".*', - label='Table', - refresh='time', - includeAll=true, - sort=1, - allValues='.*', - ), - - hostVtgate:: - template.new( - 'host', - '%(dataSource)s' % config._config, - 'label_values(vtgate_build_number, instance)', - label='Host(s)', - refresh='time', - multi=true, - allValues='.*', - ), - - hostVttablet:: - template.new( - 'host', - '%(dataSource)s' % config._config, - 'label_values(vttablet_build_number{}, instance)', - label='Host(s)', - refresh='time', - multi=true, - allValues='.*', - sort=1 - ), - -} diff --git a/vitess-mixin/dashboards/resources/grafonnet/texts.libsonnet b/vitess-mixin/dashboards/resources/grafonnet/texts.libsonnet deleted file mode 100644 index 44478b7a13f..00000000000 --- a/vitess-mixin/dashboards/resources/grafonnet/texts.libsonnet +++ /dev/null @@ -1,65 +0,0 @@ -// Re-cyclable components for text resources -local config = import '../../../config.libsonnet'; -local grafana = import '../../../vendor/grafonnet/grafana.libsonnet'; - -local text = grafana.text; - -// TODO: figure out how to make emoji work in jsonnet. They are not correctly handled -{ - - local footnote = - ||| - This Dasboard has been automatically generated using vitess-mixin. - If you want to contribute please visit [https://github.com/vitess/vitess-mixin](https://github.com/vitessio/vitess/tree/main/vitess-mixin)! - |||, - - local notes = { - footnote: footnote, - }, - - clusterOverview:: - text.new( - '', - mode='markdown', - content=||| - #### Cluster overview - - This is a general overview of the Vitess clusters. - - %(footnote)s - ||| % notes - ), - - vtgateOverview:: - text.new( - '', - mode='markdown', - content=||| - #### vtgate overview - - This is a general overview of the vtgate tier. - - %(footnote)s - ||| % notes - ), - - vtgateHost:: - text.new( - '', - mode='markdown', - content=||| - #### vtgate host - %s - ||| % footnote, - ), - - vttabletHost:: - text.new( - '', - mode='markdown', - content=||| - #### vttablet host - %s - ||| % footnote, - ), -} diff --git a/vitess-mixin/e2e/.env b/vitess-mixin/e2e/.env deleted file mode 100644 index 00e3ed4bf0a..00000000000 --- a/vitess-mixin/e2e/.env +++ /dev/null @@ -1,18 +0,0 @@ -TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 -topo_global_root vitess/global -GRPC_PORT=15999 -WEB_PORT=8080 -MYSQL_PORT=15306 - -CELL=local -KEYSPACE=commerce -DB=commerce - -EXTERNAL_DB=0 -DB_HOST=external_db_host -DB_PORT=3306 -DB_USER=external_db_user -DB_PASS=external_db_password -DB_CHARSET=CHARACTER SET utf8 COLLATE utf8_general_ci - -GRAFANA_VERSION=7.3.6 -DISPLAY= \ No newline at end of file diff --git a/vitess-mixin/e2e/Dockerfile b/vitess-mixin/e2e/Dockerfile deleted file mode 100644 index cf4a4a9f85e..00000000000 --- a/vitess-mixin/e2e/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -ARG CYPRESS_IMAGE - -FROM $CYPRESS_IMAGE -WORKDIR /e2e - -# dependencies will be installed only if the package files change -COPY package.json . -COPY package-lock.json . - -# by setting CI environment variable we switch the Cypress install messages -# to small "started / finished" and avoid 1000s of lines of progress messages -# https://github.com/cypress-io/cypress/issues/1243 -ENV CI=1 -RUN npm ci -# verify that Cypress has been installed correctly. -# running this command separately from "cypress run" will also cache its result -# to avoid verifying again when running the tests -RUN npx cypress verify diff --git a/vitess-mixin/e2e/backups/.gitignore b/vitess-mixin/e2e/backups/.gitignore deleted file mode 100644 index 35bc8010eb9..00000000000 --- a/vitess-mixin/e2e/backups/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# ignore all files in this dir... -* -# ... except for this one. -!.gitignore diff --git a/vitess-mixin/e2e/config/init_db.sql b/vitess-mixin/e2e/config/init_db.sql deleted file mode 100644 index 6059bbf7ca6..00000000000 --- a/vitess-mixin/e2e/config/init_db.sql +++ /dev/null @@ -1,79 +0,0 @@ -# This file is executed immediately after mysql_install_db, -# to initialize a fresh data directory. -############################################################################### -# Equivalent of mysql_secure_installation -############################################################################### -# We need to ensure that super_read_only is disabled so that we can execute -# these commands. Note that disabling it does NOT disable read_only. -# We save the current value so that we only re-enable it at the end if it was -# enabled before. -SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF'); -SET GLOBAL super_read_only='OFF'; -# Changes during the init db should not make it to the binlog. -# They could potentially create errant transactions on replicas. -SET sql_log_bin = 0; -# Remove anonymous users & disable remote root access (only allow UNIX socket). -DROP USER IF EXISTS ''@'%', ''@'localhost', 'root'@'%'; -# Remove test database. -DROP DATABASE IF EXISTS test; -############################################################################### -# Vitess defaults -############################################################################### -# Vitess-internal database. -CREATE DATABASE IF NOT EXISTS _vt; -# Note that definitions of local_metadata and shard_metadata should be the same -# as in production which is defined in go/vt/mysqlctl/metadata_tables.go. -CREATE TABLE IF NOT EXISTS _vt.local_metadata ( - name VARCHAR(255) NOT NULL, - value VARCHAR(255) NOT NULL, - db_name VARBINARY(255) NOT NULL, - PRIMARY KEY (db_name, name) - ) ENGINE=InnoDB; -CREATE TABLE IF NOT EXISTS _vt.shard_metadata ( - name VARCHAR(255) NOT NULL, - value MEDIUMBLOB NOT NULL, - db_name VARBINARY(255) NOT NULL, - PRIMARY KEY (db_name, name) - ) ENGINE=InnoDB; -# Admin user with all privileges. -CREATE USER 'vt_dba'@'localhost'; -GRANT ALL ON *.* TO 'vt_dba'@'localhost'; -GRANT GRANT OPTION ON *.* TO 'vt_dba'@'localhost'; -# User for app traffic, with global read-write access. -CREATE USER 'vt_app'@'localhost'; -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, - REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, - LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, - SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER - ON *.* TO 'vt_app'@'localhost'; -# User for app debug traffic, with global read access. -CREATE USER 'vt_appdebug'@'localhost'; -GRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost'; -# User for administrative operations that need to be executed as non-SUPER. -# Same permissions as vt_app here. -CREATE USER 'vt_allprivs'@'localhost'; -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, - REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, - LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, - SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER - ON *.* TO 'vt_allprivs'@'localhost'; -# User for slave replication connections. -# TODO: Should we set a password on this since it allows remote connections? -CREATE USER 'vt_repl'@'%'; -GRANT REPLICATION SLAVE ON *.* TO 'vt_repl'@'%'; -# User for Vitess filtered replication (binlog player). -# Same permissions as vt_app. -CREATE USER 'vt_filtered'@'localhost'; -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, - REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, - LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, - SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER - ON *.* TO 'vt_filtered'@'localhost'; - -RESET SLAVE ALL; -RESET MASTER; -# custom sql is used to add custom scripts like creating users/passwords. We use it in our tests -# {{custom_sql}} - -# We need to set super_read_only back to what it was before -SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'ON'); diff --git a/vitess-mixin/e2e/cypress.json b/vitess-mixin/e2e/cypress.json deleted file mode 100644 index c1ffae0a972..00000000000 --- a/vitess-mixin/e2e/cypress.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "viewportWidth": 1200, - "viewportHeight": 900 -} diff --git a/vitess-mixin/e2e/cypress/integration/cluster_overview_spec.js b/vitess-mixin/e2e/cypress/integration/cluster_overview_spec.js deleted file mode 100644 index 5bb40a68c3b..00000000000 --- a/vitess-mixin/e2e/cypress/integration/cluster_overview_spec.js +++ /dev/null @@ -1,56 +0,0 @@ -const fs = require('fs') - -describe('vitess-mixin: Cluster Overview Dashboard Test', function () { - - let panelTitles = [] - - before(function () { - cy.readFile('./test/cluster_overview.json').then((data) => { - cy.createDashboard(data) - }) - }) - it('renders cluster overview dashboard', function () { - cy.visit('/d/vitess-cluster-overview/cluster-overview-auto-generated') - }) - //TEMPLATES - it('contains the Interval Template', function () { - cy.get('.submenu-controls').contains('Interval'); - }) - //LINKS - it('contains vitess-mixin Dashboard links dropdown', function () { - cy.get('.submenu-controls').get('.gf-form').contains('vitess-mixin') - }) - // INIT PANELS - it('checks all panels in the cluster overview dashboard exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(22) - expect(titles).to.deep.eq([ - '', - 'Query success - vtgate', - 'Query success - vttablet', - 'Query latency p99', - 'QPS - vtgate', - 'QPS - MySQL', - 'vtgate', - 'vttablet', - 'QPS - vttablet', - 'keyspace', - 'shard', - 'vtctld', - 'Requests', - 'Error rate', - 'Duration 99th quantile', - 'Requests (by keyspace)', - 'Error rate (by keyspace)', - 'Duration 99th quantile (by keyspace)', - '# of serving tablets', - 'Slow queries', - 'Query/Transaction killed' - ]) - }) - }) -}) diff --git a/vitess-mixin/e2e/cypress/integration/vtgate_host_view.js b/vitess-mixin/e2e/cypress/integration/vtgate_host_view.js deleted file mode 100644 index 7cbbcdb0e9a..00000000000 --- a/vitess-mixin/e2e/cypress/integration/vtgate_host_view.js +++ /dev/null @@ -1,174 +0,0 @@ -const fs = require('fs') - -describe('vitess-mixin: Vtgate Host View Dashboard Test', function() { - - let panelTitles = [] - - before(function() { - cy.readFile('./test/vtgate_host_view.json').then((data) => { - cy.createDashboard(data) - }) - }) - it('renders vtgate hostview dashboard', function() { - cy.visit('/d/vitess-vtgate-host-view/vtgate - host view (auto-generated)') - }) - //SUB-MENU CONTROLS - it('contains the Host(s) Template', function() { - cy.get('.submenu-controls').contains('Host(s)'); - }) - it('contains vitess-mixin Dashboard links dropdown', function() { - cy.get('.submenu-controls').get('.gf-form').contains('vitess-mixin') - }) - //Rows are loaded at start time - it('contains 5 rows', function() { - cy.get('.dashboard-row').should('have.length',5) - }) - // RED ROW - it('contains the RED row', function() { - cy.get('.dashboard-row').contains('RED - Requests / Error rate / Duration') - }) - - it('checks all panels in the RED row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests', - 'Error rate', - 'Duration 99th quantile' - ]) - }) - }) - - it('collapses the RED row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED - Requests / Error rate / Duration').click(); - }) - - // ROW (BY TABLET TYPE) - it('contains the RED (by tablet type) row', function() { - cy.get('.dashboard-row').contains('RED (by tablet type)'); - }) - it('RED (by tablet type) row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('RED (by tablet type)'); - }) - it('expands the RED (by tablet type) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by tablet type)').click(); - }) - - it('checks all panels in the RED (by tablet type) row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests (by db_type)', - 'Error rate (by db_type)', - 'Duration 99th quantile (by db_type)' - ]) - }) - }) - - it('collapses the RED (by tablet type) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by tablet type)').click(); - cy.get('.dashboard-row--collapsed').contains('RED (by tablet type)'); - }) - - //ERRORS ROW - it('contains the Errors row', function() { - cy.get('.dashboard-row').contains('Errors'); - }) - it('Errors row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('Errors'); - }) - it('expands the Errors row', function(){ - cy.get('.dashboard-row__title.pointer').contains('Errors').scrollIntoView().click(); - }) - it('checks all panels in the Errors Row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(3) - expect(titles).to.deep.eq([ - '', - 'Errors (by keyspace)', - 'Errors (by code)' - ]) - }) - }) - it('collapses the Errors row', function(){ - cy.get('.dashboard-row__title.pointer').contains('Errors').click(); - cy.get('.dashboard-row--collapsed').contains('Errors'); - }) - //DURATION ROW - it('contains the Duration row', function() { - cy.get('.dashboard-row').contains(/^Duration/) - }) - it('Duration row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains(/^Duration/) - }) - it('expands the Duration row', function(){ - cy.get('.dashboard-row__title.pointer').contains(/^Duration/).click(); - }) - - it('checks all panels in the Duration row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Duration (Avg)', - 'Duration 50th quantile', - 'Duration 95th quantile' - ]) - }) - }) - - it('collapses the Duration row', function(){ - cy.get('.dashboard-row__title.pointer').contains(/^Duration/).click(); - cy.get('.dashboard-row--collapsed').contains(/^Duration/); - }) - //OS ROW - it('contains the OS row', function() { - cy.get('.dashboard-row').contains('OS') - }) - it('OS row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('OS') - }) - it('expands the OS row', function(){ - cy.get('.dashboard-row__title.pointer').contains('OS').click(); - }) - - it('checks all panels in the OS row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(5) - expect(titles).to.deep.eq([ - '', - 'CPU Usage', - 'Memory Usage', - 'Network Usage', - 'TCP Retransmissions' - ]) - }) - }) - - it('collapses the OS row', function(){ - cy.get('.dashboard-row__title.pointer').contains('OS').click(); - cy.get('.dashboard-row--collapsed').contains('OS'); - }) -}) diff --git a/vitess-mixin/e2e/cypress/integration/vtgate_overview.js b/vitess-mixin/e2e/cypress/integration/vtgate_overview.js deleted file mode 100644 index eb8122ca403..00000000000 --- a/vitess-mixin/e2e/cypress/integration/vtgate_overview.js +++ /dev/null @@ -1,201 +0,0 @@ -const fs = require('fs') - -describe('vitess-mixin: Vtgate Overview Dashboard Test', function() { - - let panelTitles = [] - - before(function() { - cy.readFile('./test/vtgate_overview.json').then((data) => { - cy.createDashboard(data) - }) - }) - it('renders vtgate overview dashboard', function() { - cy.visit('/d/vitess-vtgate-overview/vtgate - overview (auto-generated)') - }) - //SUB-MENU CONTROLS - it('contains vitess-mixin Dashboard links dropdown', function() { - cy.get('.submenu-controls').get('.gf-form').contains('vitess-mixin'); - }) - // RED ROW - it('contains the RED row', function() { - cy.get('.dashboard-row').contains('RED - Requests / Error rate / Duration'); - }) - - it('checks all panels in the RED row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests', - 'Error rate', - 'Duration 99th quantile' - ]) - }) - }) - - it('collapses the RED row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED - Requests / Error rate / Duration').click(); - }) - - // RED (BY KEYSPACE) ROW - it('contains the RED (by keyspace) row', function() { - cy.get('.dashboard-row').contains('RED (by keyspace)'); - }) - it('RED (by keyspace) row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('RED (by keyspace)'); - }) - it('expands the RED (by keyspace) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by keyspace)').click(); - }) - - it('checks all panels in the RED (by keyspace) row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests (by keyspace)', - 'Error rate (by keyspace)', - 'Duration 99th quantile (by keyspace)' - ]) - }) - }) - - it('collapses the RED (by keyspace) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by keyspace)').click(); - }) - - // ROW (BY TABLET TYPE) - it('contains the RED (by tablet type) row', function() { - cy.get('.dashboard-row').contains('RED (by tablet type)'); - }) - it('RED (by tablet type) row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('RED (by tablet type)'); - }) - it('expands the RED (by tablet type) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by tablet type)').click(); - }) - - it('checks all panels in the RED (By tablet type) row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests (by db_type)', - 'Error rate (by db_type)', - 'Duration 99th quantile (by db_type)' - ]) - }) - }) - - it('collapses the RED (by tablet type) row', function(){ - cy.get('.dashboard-row__title.pointer').contains('RED (by tablet type)').click(); - cy.get('.dashboard-row--collapsed').contains('RED (by tablet type)'); - }) - - //ERRORS ROW - it('contains the Errors row', function() { - cy.get('.dashboard-row').contains('Errors'); - }) - it('Errors row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('Errors'); - }) - it('expands the Errors row', function(){ - cy.get('.dashboard-row__title.pointer').contains('Errors').click(); - }) - - it('checks all panels in the Errors row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Errors (by code)', - 'Errors (by operation)', - 'Errors (by db_type)' - ]) - }) - }) - - it('collapses the Errors row', function(){ - cy.get('.dashboard-row__title.pointer').contains('Errors').click(); - }) - - //DURATION ROW - it('contains the Duration row', function() { - cy.get('.dashboard-row').contains(/^Duration/); - }) - it('Duration row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains(/^Duration/); - }) - it('expands the Duration row', function(){ - cy.get('.dashboard-row__title.pointer').contains(/^Duration/).click(); - }) - - it('checks all panels in the Duration row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Duration (Avg)', - 'Duration 50th quantile', - 'Duration 95th quantile' - ]) - }) - }) - - it('collapses the Duration row', function(){ - cy.get('.dashboard-row__title.pointer').contains(/^Duration/).click(); - }) - - //OS ROW - it('contains the OS row', function() { - cy.get('.dashboard-row').contains('OS'); - }) - it('OS row is collapsed', function() { - cy.get('.dashboard-row--collapsed').contains('OS'); - }) - it('expands the OS row', function(){ - cy.get('.dashboard-row__title.pointer').contains('OS').click(); - }) - - it('checks all panels in the row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(5) - expect(titles).to.deep.eq([ - '', - 'CPU Usage', - 'Memory Usage', - 'Network Usage', - 'TCP Retransmissions' - ]) - }) - }) - - it('collapses the OS row', function(){ - cy.get('.dashboard-row__title.pointer').contains('OS').click(); - cy.get('.dashboard-row--collapsed').contains('OS'); - }) -}) diff --git a/vitess-mixin/e2e/cypress/integration/vttablet_host_view.js b/vitess-mixin/e2e/cypress/integration/vttablet_host_view.js deleted file mode 100644 index f98ba803d85..00000000000 --- a/vitess-mixin/e2e/cypress/integration/vttablet_host_view.js +++ /dev/null @@ -1,409 +0,0 @@ -const fs = require('fs') - -describe('vitess-mixin: Vttablet Host View Dashboard Test', function () { - - let panelTitles = [] - - before(function () { - cy.readFile('./test/vttablet_host_view.json').then((data) => { - cy.createDashboard(data) - }) - }) - it('renders vttablet hostview dashboard', function () { - cy.visit('/d/vitess-vttablet-host-view/vttablet - host view (auto-generated)') - }) - //SUB-MENU CONTROLS - it('contains the Host(s) Template', function () { - cy.get('.submenu-controls').contains('Host(s)'); - }) - it('contains vitess-mixin Dashboard links dropdown', function () { - cy.get('.submenu-controls').get('.gf-form').contains('vitess-mixin') - }) - //All Rows are loaded at start time - it('contains 12 rows', function () { - cy.get('.dashboard-row').should('have.length', 12) - }) - - // RED ROW - it('contains the RED row', function () { - cy.get('.dashboard-row').contains('RED - Requests / Error rate / Duration') - }) - - it('checks all panels in the RED row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests', - 'Error rate', - 'Duration (p99)' - ]) - }) - }) - - it('collapses the RED row', function () { - cy.get('.dashboard-row__title.pointer').contains('RED - Requests / Error rate / Duration').click(); - }) - // RED BY PLAN TYPE ROW - - it('contains the RED (by plan type) row', function () { - cy.get('.dashboard-row').contains('RED (by plan type)') - }) - it('RED (by plan type) row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('RED (by plan type)') - }) - it('expands the RED (by plan type) row', function () { - cy.get('.dashboard-row__title.pointer').contains('RED (by plan type)').click(); - }) - - it('checks all panels in the RED (by plan type) row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'Requests (by plan type)', - 'Error rate (by plan type)', - 'Duration p99 (by plan type)' - ]) - }) - }) - - it('collapses the RED (by plan type) row', function () { - cy.get('.dashboard-row__title.pointer').contains('RED (by plan type)').click(); - cy.get('.dashboard-row--collapsed').contains('RED (by plan type)'); - }) - - // RED BY TABLE ROW - - it('contains the RED (by table) row', function () { - cy.get('.dashboard-row').contains('RED (by table)') - }) - it('RED (by table) row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('RED (by table)') - }) - it('expands the RED (by table) row', function () { - cy.get('.dashboard-row__title.pointer').contains('RED (by table)').click(); - }) - - it('checks all panels in the RED (by table) row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(3) - expect(titles).to.deep.eq([ - '', - 'Requests (by table)', - 'Error rate (by table)' - ]) - }) - }) - - it('collapses the RED (by table) row', function () { - cy.get('.dashboard-row__title.pointer').contains('RED (by table)').click(); - cy.get('.dashboard-row--collapsed').contains('RED (by table)'); - }) - - // Rows Returned - it('contains the Rows Returned row', function () { - cy.get('.dashboard-row').contains(/^Rows returned/) - }) - it('Rows returned row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains(/^Rows returned/) - }) - it('expands the Rows returned row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Rows returned/).click(); - }) - - it('checks all panels in the Rows returned row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(3) - expect(titles).to.deep.eq([ - '', - 'Rows Returned (by table)', - 'Rows Returned (by plan)' - ]) - }) - }) - - it('collapses the Rows returned row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Rows returned/).click(); - cy.get('.dashboard-row--collapsed').contains(/^Rows returned/); - }) - - // Queries/Errors - it('contains the Queries/Errors row', function () { - cy.get('.dashboard-row').contains(/^Queries\/Errors/) - }) - it('Queries/Errors row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains(/^Queries\/Errors/) - }) - it('expands the Queries/Errors row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Queries\/Errors/).click(); - }) - - it('checks all panels in the Queries/Errors row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(3) - expect(titles).to.deep.eq([ - '', - 'Queries Killed', - 'Query errors (by error code)' - ]) - }) - }) - - it('collapses the Queries/Errors row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Queries\/Errors/).click(); - cy.get('.dashboard-row--collapsed').contains(/^Queries\/Errors/); - }) - - // Vitess Query pool - it('contains the Vitess - Query pool row', function () { - cy.get('.dashboard-row').contains('Vitess - Query pool') - }) - it('Vitess - Query pool row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('Vitess - Query pool') - }) - it('expands the Vitess - Query pool row', function () { - cy.get('.dashboard-row__title.pointer').contains('Vitess - Query pool').click(); - }) - - it('checks all panels in the Query pool row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(6) - expect(titles).to.deep.eq([ - '', - 'Available Connections', - 'Active Connections', - 'Idle Closed Rate', - 'Wait count', - 'Avg wait time' - ]) - }) - }) - - it('collapses the Vitess - Query pool row', function () { - cy.get('.dashboard-row__title.pointer').contains('Vitess - Query pool').click(); - cy.get('.dashboard-row--collapsed').contains('Vitess - Query pool'); - }) - - // Vitess Transaction pool - it('contains the Vitess - Transaction pool row', function () { - cy.get('.dashboard-row').contains('Vitess - Transaction pool') - }) - it('Vitess - Transaction pool row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('Vitess - Transaction pool') - }) - it('expands the Vitess - Transaction pool row', function () { - cy.get('.dashboard-row__title.pointer').contains('Vitess - Transaction pool').click(); - }) - - it('checks all panels in the Transaction row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(6) - expect(titles).to.deep.eq([ - '', - 'Available Connections', - 'Active Connections', - 'Idle Closed Rate', - 'Wait count', - 'Avg wait time' - ]) - }) - }) - - it('collapses the Vitess - Transaction pool row', function () { - cy.get('.dashboard-row__title.pointer').contains('Vitess - Transaction pool').click(); - cy.get('.dashboard-row--collapsed').contains('Vitess - Transaction pool'); - }) - - //Vitess timings - it('contains the Vitess Timings row', function () { - cy.get('.dashboard-row').contains(/^Vitess Timings/) - }) - it('Vitess Timings row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains(/^Vitess Timings/) - }) - it('Vitess Timings row has 8 panels', function () { - cy.get('.dashboard-row').contains(/^Vitess Timings/).find('.dashboard-row__panel_count').contains('(8 panels)') - }) - it('expands the Vitess Timings row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Vitess Timings/).click(); - }) - - it('checks all panels in the Vitess Timings row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(9) - expect(titles).to.deep.eq([ - '', - 'Query Duration (avg)', - 'Query Duration (p50)', - 'Query Duration (p95)', - 'VtGate -> VtTablet Call Time (avg)', - 'Query Time Distribution (Heatmap)', - 'Transaction Duration (avg)', - 'Transaction Duration (p50)', - 'Transaction Duration (p95)' - ]) - }) - }) - - it('collapses the Vitess Timings row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Vitess Timings/).click(); - cy.get('.dashboard-row--collapsed').contains(/^Vitess Timings/); - }) - - - //MYSQL ROW - it('contains the MySQL row', function () { - cy.get('.dashboard-row').contains('MySQL'); - }) - it('MySQL row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('MySQL'); - }) - it('expands the MySQL row', function () { - cy.get('.dashboard-row__title.pointer').contains('MySQL').click(); - }) - it('checks all panels in the MySQL row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(2) - expect(titles).to.deep.eq([ - '', - 'Slow Queries' - ]) - }) - }) - it('collapses the MySQL row', function () { - cy.get('.dashboard-row__title.pointer').contains('MySQL').click(); - cy.get('.dashboard-row--collapsed').contains('MySQL'); - }) - - //MYSQL Timings ROW - it('contains the MySQL Timings row', function () { - cy.get('.dashboard-row').contains(/MySQL Timings/); - }) - it('MySQL Timings row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains(/MySQL Timings/); - }) - it('expands the MySQL Timings row', function () { - cy.get('.dashboard-row__title.pointer').contains(/MySQL Timings/).click(); - }) - - it('checks all panels in the MySQL row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'MySQL time (avg)', - 'MySQL Exec Time P50', - 'MySQL Exec Time P95' - ]) - }) - }) - - it('collapses the MySQL Timings row', function () { - cy.get('.dashboard-row__title.pointer').contains(/MySQL Timings/).click(); - cy.get('.dashboard-row--collapsed').contains(/MySQL Timings/); - }) - - //OS ROW - it('contains the OS row', function () { - cy.get('.dashboard-row').contains('OS'); - }) - it('OS row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains('OS'); - }) - it('expands the OS row', function () { - cy.get('.dashboard-row__title.pointer').contains('OS').scrollIntoView().click(); - }) - it('checks all panels in the OS row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(6) - expect(titles).to.deep.eq([ - '', - 'CPU Usage', - 'Memory Usage', - '/mnt disk free', - 'Network Tx Bytes', - 'Network Rx Bytes' - ]) - }) - }) - it('collapses the OS row', function () { - cy.get('.dashboard-row__title.pointer').contains('OS').click(); - cy.get('.dashboard-row--collapsed').contains('OS'); - }) - - //Misc ROW - it('contains the Misc row', function () { - cy.get('.dashboard-row').contains(/^Misc/); - }) - it('Misc row is collapsed', function () { - cy.get('.dashboard-row--collapsed').contains(/^Misc/); - }) - it('expands the Misc row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Misc/).click(); - }) - it('checks all panels in the Misc row exist',function() { - cy.get('.panel-title').should(($p) => { - let titles = $p.map((i,el) => { - return Cypress.$(el).text() - }) - titles = titles.get() - expect(titles).to.have.length(4) - expect(titles).to.deep.eq([ - '', - 'GC Count', - 'GC Duration total per second', - 'GC Duration quantiles (all hosts)' - ]) - }) - }) - it('collapses the Misc row', function () { - cy.get('.dashboard-row__title.pointer').contains(/^Misc/).click(); - cy.get('.dashboard-row--collapsed').contains(/^Misc/); - }) - -}) diff --git a/vitess-mixin/e2e/cypress/plugins/index.js b/vitess-mixin/e2e/cypress/plugins/index.js deleted file mode 100644 index aa9918d2153..00000000000 --- a/vitess-mixin/e2e/cypress/plugins/index.js +++ /dev/null @@ -1,21 +0,0 @@ -/// -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -/** - * @type {Cypress.PluginConfig} - */ -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config -} diff --git a/vitess-mixin/e2e/cypress/support/commands.js b/vitess-mixin/e2e/cypress/support/commands.js deleted file mode 100644 index 88dec8ed7b0..00000000000 --- a/vitess-mixin/e2e/cypress/support/commands.js +++ /dev/null @@ -1,33 +0,0 @@ -const http = require("http") - -Cypress.Commands.overwrite('visit', (orig, url, options) => { - options = options || {} - options.auth = { - username: 'admin', - password: 'admin', - } - return orig(url, options) -}) - -Cypress.Commands.add('createDashboard', function(dashboardJSON) { - - const payload = JSON.stringify({ - dashboard: dashboardJSON, - overwrite: true - }) - - const options = { - auth: 'admin:admin', - hostname: 'grafana', - port: 3000, - path: '/api/dashboards/db', - method: 'POST', - headers: { - 'Content-Type': 'application/json', - } - } - - const req = http.request(options) - req.write(payload) - req.end() -}) diff --git a/vitess-mixin/e2e/cypress/support/index.js b/vitess-mixin/e2e/cypress/support/index.js deleted file mode 100644 index 614041bb83f..00000000000 --- a/vitess-mixin/e2e/cypress/support/index.js +++ /dev/null @@ -1,28 +0,0 @@ -require('./commands') - -const fs = require('fs') - -// This does not use the usual Cypress.Commands.add registration so that it's -// performed synchronously and we're able to return the panelTitles variable. -cy.createDashboardFromUnitTests = function(testDir, uid, excludePanels=[]) { - let panelTitles = [] - cy.readFile(testDir).then(function(str) { - let panels = [] - for (let [i, [name, panel]] of Object.entries(Object.entries(str))) { - if (excludePanels.includes(name)) { - continue - } - panel['id'] = parseInt(i) - panel['gridPos'] = {'w': 6, 'h': 4, 'x': i * 6 % 24 } - panelTitles.push(panel.title) - panels.push(panel) - } - let dashboardJSON = { - 'uid': uid, - 'title': uid, - 'panels': panels - } - cy.createDashboard(dashboardJSON) - }) - return panelTitles -} diff --git a/vitess-mixin/e2e/dbcli.sh b/vitess-mixin/e2e/dbcli.sh deleted file mode 100755 index 6d56f0b2763..00000000000 --- a/vitess-mixin/e2e/dbcli.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -usage () { - echo "Starts a session on a sideloaded vttablet." - echo "Note that this is a direct MySQL connection; if you actually want to work with Vitess, connect via the vtgate with:" - echo " mysql --port=15306 --host=127.0.0.1" - echo - echo "Usage: $0 []" - echo " Don't forget the 'vt_' before the keyspace!" -} - -if [ $# -lt 1 ]; then - usage - exit -1 -fi - -keyspace=${2:-vt_test_keyspace} -long_alias=`printf "%010d" $1` -docker-compose exec vttablet$1 mysql -uvt_dba -S /vt/vtdataroot/vt_${long_alias}/mysql.sock $keyspace diff --git a/vitess-mixin/e2e/default_vschema.json b/vitess-mixin/e2e/default_vschema.json deleted file mode 100644 index e0b50a66037..00000000000 --- a/vitess-mixin/e2e/default_vschema.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "sharded": false, - "vindexes": { - "hash": { - "type": "hash" - } - } -} diff --git a/vitess-mixin/e2e/docker-compose.beginners.yml b/vitess-mixin/e2e/docker-compose.beginners.yml deleted file mode 100644 index 46eadd57801..00000000000 --- a/vitess-mixin/e2e/docker-compose.beginners.yml +++ /dev/null @@ -1,312 +0,0 @@ -version: "2.1" -services: - consul1: - image: consul:latest - hostname: "consul1" - ports: - - "8400:8400" - - "8500:8500" - - "8600:8600" - command: "agent -server -bootstrap-expect 3 -ui -disable-host-node-id -client 0.0.0.0" - consul2: - image: consul:latest - hostname: "consul2" - expose: - - "8400" - - "8500" - - "8600" - command: "agent -server -retry-join consul1 -disable-host-node-id" - depends_on: - - consul1 - consul3: - image: consul:latest - hostname: "consul3" - expose: - - "8400" - - "8500" - - "8600" - command: "agent -server -retry-join consul1 -disable-host-node-id" - depends_on: - - consul1 - # This is a convenience container to quickly test vitess against an external database. - # In practice you will point Vitess to your existing database and migrate to a Vitess managed cluster. - external_db_host: - build: - context: ./external_db/mysql - dockerfile: Dockerfile - restart: always - environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-pass} - MYSQL_DATABASE: ${DB:-commerce} - MYSQL_USER: ${DB_USER:-external_db_user} - MYSQL_PASSWORD: ${DB_PASS:-external_db_password} - volumes: - - ./external_db/mysql/:/docker-entrypoint-initdb.d/ - - ./external_db/mysql/log:/var/log/mysql - command: - - --server-id=1 - - --log-bin=mysql-bin - - --gtid_mode=ON - - --enforce_gtid_consistency - - --general_log=1 - - --slow_query_log=1 - healthcheck: - test: "/usr/bin/mysql --user=root --password=$${MYSQL_ROOT_PASSWORD} --execute \"SHOW DATABASES;\"" - timeout: 10s - retries: 10 - ports: - - "3306" - - vtctld: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15000:$WEB_PORT" - - "$GRPC_PORT" - command: ["sh", "-c", " /vt/bin/vtctld \ - $TOPOLOGY_FLAGS \ - -cell $CELL \ - -service_map 'grpc-vtctl' \ - -backup_storage_implementation file \ - -file_backup_storage_root /vt/vtdataroot/backups \ - -logtostderr=true \ - -port $WEB_PORT \ - -grpc_port $GRPC_PORT - "] - depends_on: - - consul1 - - consul2 - - consul3 - depends_on: - external_db_host: - condition: service_healthy - - vtgate: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15099:$WEB_PORT" - - "$GRPC_PORT" - - "15306:$MYSQL_PORT" - command: ["sh", "-c", "/vt/bin/vtgate \ - $TOPOLOGY_FLAGS \ - --logtostderr=true \ - --port $WEB_PORT \ - --grpc_port $GRPC_PORT \ - --mysql_server_port $MYSQL_PORT \ - --mysql_auth_server_impl none \ - --cell $CELL \ - --cells_to_watch $CELL \ - --tablet_types_to_wait PRIMARY,REPLICA \ - --service_map 'grpc-vtgateservice' \ - --enable_system_settings=true \ - "] - volumes: - - ".:/script" - environment: - - KEYSPACE - - DB - depends_on: - - vtctld - depends_on: - vttablet101: - condition: service_healthy - - schemaload: - image: vitess/lite:${VITESS_TAG:-latest} - command: - - sh - - -c - - /script/schemaload.sh - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - TARGETTAB - - SLEEPTIME - - VSCHEMA_FILE - - SCHEMA_FILES - - POST_LOAD_FILE - - EXTERNAL_DB - volumes: - - .:/script - depends_on: - vttablet101: - condition: service_healthy - - vttablet100: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15100:$WEB_PORT" - - "$GRPC_PORT" - - "3306" - volumes: - - ".:/script" - - "./backups:/vt/vtdataroot/backups" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - - ROLE=primary - command: ["sh", "-c", "[ $$EXTERNAL_DB -eq 1 ] && /script/vttablet-up.sh 100 || exit 0"] - depends_on: - - vtctld - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:$$WEB_PORT/debug/health"] - interval: 30s - timeout: 10s - retries: 15 - - vttablet101: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15101:$WEB_PORT" - - "$GRPC_PORT" - - "3306" - volumes: - - ".:/script" - - "./backups:/vt/vtdataroot/backups" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - - ROLE=primary - command: ["sh", "-c", "/script/vttablet-up.sh 101"] - depends_on: - - vtctld - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:$$WEB_PORT/debug/health"] - interval: 30s - timeout: 10s - retries: 15 - - vttablet102: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15102:$WEB_PORT" - - "$GRPC_PORT" - - "3306" - volumes: - - ".:/script" - - "./backups:/vt/vtdataroot/backups" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - command: ["sh", "-c", "/script/vttablet-up.sh 102"] - depends_on: - - vtctld - - vttablet101 - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:$$WEB_PORT/debug/health"] - interval: 30s - timeout: 10s - retries: 15 - - vttablet103: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15103:$WEB_PORT" - - "$GRPC_PORT" - - "3306" - volumes: - - ".:/script" - - "./backups:/vt/vtdataroot/backups" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - command: ["sh", "-c", "/script/vttablet-up.sh 103"] - depends_on: - - vtctld - - vttablet101 - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:$$WEB_PORT/debug/health"] - interval: 30s - timeout: 10s - retries: 15 - - vtorc: - image: vitess/lite:${VITESS_TAG:-latest} - command: ["sh", "-c", "/script/vtorc-up.sh"] - depends_on: - - vtctld - ports: - - "13000:3000" - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:3000/api/status"] - interval: 5s - timeout: 10s - retries: 15 - - vreplication: - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS - - WEB_PORT - - GRPC_PORT - - CELL - - KEYSPACE - - DB - - EXTERNAL_DB - - DB_PORT - - DB_HOST - - DB_USER - - DB_PASS - - DB_CHARSET - command: ["sh", "-c", "[ $$EXTERNAL_DB -eq 1 ] && /script/externaldb_vreplication.sh || exit 0"] - depends_on: - - vtctld diff --git a/vitess-mixin/e2e/docker-compose.dev.yml b/vitess-mixin/e2e/docker-compose.dev.yml deleted file mode 100644 index e5bb4f20ef5..00000000000 --- a/vitess-mixin/e2e/docker-compose.dev.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: '3' -services: - grafana: - image: grafana/grafana:${GRAFANA_VERSION?err} - ports: - - "3030:3000" - e2e: - build: - context: . - args: - CYPRESS_IMAGE: cypress/included:5.3.0 - image: grafonnet-e2e-dev - entrypoint: cypress open --project . - depends_on: - - grafana - environment: - - CYPRESS_baseUrl=http://grafana:3000 - - CYPRESS_video=false - - DISPLAY=${DISPLAY?err} - volumes: - - ./cypress:/e2e/cypress - - ./cypress.json:/e2e/cypress.json - - ../dashboards_out:/e2e/test - - /tmp/.X11-unix:/tmp/.X11-unix - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G -volumes: - prometheus-data: {} diff --git a/vitess-mixin/e2e/docker-compose.vt.yml b/vitess-mixin/e2e/docker-compose.vt.yml deleted file mode 100644 index 1132068f252..00000000000 --- a/vitess-mixin/e2e/docker-compose.vt.yml +++ /dev/null @@ -1,447 +0,0 @@ -version: '3' -services: - consul1: - command: agent -server -bootstrap-expect 3 -ui -disable-host-node-id -client 0.0.0.0 - hostname: consul1 - image: consul:latest - ports: - - 8400:8400 - - 8500:8500 - - 8600:8600 - consul2: - command: agent -server -retry-join consul1 -disable-host-node-id - depends_on: - - consul1 - expose: - - "8400" - - "8500" - - "8600" - hostname: consul2 - image: consul:latest - consul3: - command: agent -server -retry-join consul1 -disable-host-node-id - depends_on: - - consul1 - expose: - - "8400" - - "8500" - - "8600" - hostname: consul3 - image: consul:latest - external_db_host: - build: - context: ./external_db/mysql - dockerfile: Dockerfile - command: - - --server-id=1 - - --log-bin=mysql-bin - - --gtid_mode=ON - - --enforce_gtid_consistency - - --general_log=1 - - --slow_query_log=1 - environment: - MYSQL_DATABASE: ${DB:-commerce} - MYSQL_PASSWORD: ${DB_PASS:-external_db_password} - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-pass} - MYSQL_USER: ${DB_USER:-external_db_user} - healthcheck: - retries: 10 - test: /usr/bin/mysql --user=root --password=$${MYSQL_ROOT_PASSWORD} --execute - "SHOW DATABASES;" - timeout: 10s - ports: - - "3306" - restart: always - volumes: - - ./external_db/mysql/:/docker-entrypoint-initdb.d/ - - ./external_db/mysql/log:/var/log/mysql - schemaload_lookup_keyspace: - command: - - sh - - -c - - /script/schemaload.sh - depends_on: - vttablet301: - condition: service_healthy - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=lookup_keyspace - - TARGETTAB=test-0000000301 - - SLEEPTIME=15 - - VSCHEMA_FILE=lookup_keyspace_vschema.json - - SCHEMA_FILES=lookup_keyspace_schema_file.sql - - POST_LOAD_FILE= - - EXTERNAL_DB=0 - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - .:/script - schemaload_test_keyspace: - command: - - sh - - -c - - /script/schemaload.sh - depends_on: - vttablet101: - condition: service_healthy - vttablet201: - condition: service_healthy - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - TARGETTAB=test-0000000101 - - SLEEPTIME=15 - - VSCHEMA_FILE=test_keyspace_vschema.json - - SCHEMA_FILES=test_keyspace_schema_file.sql - - POST_LOAD_FILE= - - EXTERNAL_DB=0 - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - .:/script - vreplication: - command: - - sh - - -c - - '[ $$EXTERNAL_DB -eq 1 ] && /script/externaldb_vreplication.sh || exit 0' - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - EXTERNAL_DB=0 - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - .:/script - vtctld: - command: - - sh - - -c - - ' /vt/bin/vtctld -topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global -cell test - -service_map ''grpc-vtctl'' -backup_storage_implementation file -file_backup_storage_root - /vt/vtdataroot/backups -logtostderr=true -port 8080 -grpc_port 15999 ' - depends_on: - external_db_host: - condition: service_healthy - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15000:8080 - - "15999" - volumes: - - .:/script - vtgate: - command: - - sh - - -c - - '/script/run-forever.sh /vt/bin/vtgate --topo_implementation consul --topo_global_server_address - consul1:8500 --topo_global_root vitess/global --logtostderr=true --port 8080 --grpc_port - 15999 --mysql_server_port 15306 --mysql_auth_server_impl none --cell test --cells_to_watch - test --tablet_types_to_wait PRIMARY,REPLICA,RDONLY --service_map ''grpc-vtgateservice'' - --normalize_queries=true ' - depends_on: - - vtctld - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15099:8080 - - "15999" - - 15306:15306 - volumes: - - .:/script - vtorc: - command: - - sh - - -c - - /script/vtorc-up.sh - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - EXTERNAL_DB=0 - - DB_USER= - - DB_PASS= - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 13000:3000 - volumes: - - .:/script - vttablet101: - command: - - sh - - -c - - /script/vttablet-up.sh 101 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=-80 - - ROLE=primary - - VTHOST=vttablet101 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15101:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet102: - command: - - sh - - -c - - /script/vttablet-up.sh 102 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=-80 - - ROLE=replica - - VTHOST=vttablet102 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15102:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet201: - command: - - sh - - -c - - /script/vttablet-up.sh 201 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=80- - - ROLE=primary - - VTHOST=vttablet201 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15201:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet202: - command: - - sh - - -c - - /script/vttablet-up.sh 202 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=80- - - ROLE=replica - - VTHOST=vttablet202 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15202:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet301: - command: - - sh - - -c - - /script/vttablet-up.sh 301 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=lookup_keyspace - - SHARD=- - - ROLE=primary - - VTHOST=vttablet301 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15301:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet302: - command: - - sh - - -c - - /script/vttablet-up.sh 302 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=lookup_keyspace - - SHARD=- - - ROLE=replica - - VTHOST=vttablet302 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl -s --fail --show-error localhost:8080/debug/health - timeout: 10s - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - 15302:8080 - - "15999" - - "3306" - volumes: - - .:/script - prometheus: - image: prom/prometheus:v2.21.0 - ports: - - 9000:9090 - volumes: - - ./prometheus:/etc/prometheus - - ../prometheus_rules.yaml:/etc/prometheus/prometheus_rules.yaml - - prometheus-data:/prometheus - command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml - depends_on: - - vtctld - grafana: - image: grafana/grafana:${GRAFANA_VERSION?err} - ports: - - "3030:3000" - volumes: - - ./grafana/provisioning:/etc/grafana/provisioning - - ../dashboards_out/cluster_overview.json:/etc/grafana/provisioning/dashboards/cluster_overview.json - - ../dashboards_out/vtgate_overview.json:/etc/grafana/provisioning/dashboards/vtgate_overview.json - - ../dashboards_out/vtgate_host_view.json:/etc/grafana/provisioning/dashboards/vtgate_host_view.json - - ../dashboards_out/vttablet_host_view.json:/etc/grafana/provisioning/dashboards/vttablet_host_view.json - depends_on: - - prometheus - - vtgate - - vttablet101 - node-exporter: - image: prom/node-exporter - volumes: - - /proc:/host/proc:ro - - /sys:/host/sys:ro - - /:/rootfs:ro - command: - - '--path.procfs=/host/proc' - - '--path.sysfs=/host/sys' - - --collector.filesystem.ignored-mount-points - - "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)" - ports: - - '9100:9100' - deploy: - mode: global - mysqld_exporter: - image: prom/mysqld-exporter:latest - environment: - - DATA_SOURCE_NAME=root:pass@(external_db_host:3306)/ - ports: - - "9104:9104" - depends_on: - - external_db_host - # TODO: ADD CYPRESS FOR AUTOMATED TESTING -volumes: - prometheus-data: {} diff --git a/vitess-mixin/e2e/docker-compose.yml b/vitess-mixin/e2e/docker-compose.yml deleted file mode 100644 index e46fbcab849..00000000000 --- a/vitess-mixin/e2e/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: '3' -services: - grafana: - image: grafana/grafana:${GRAFANA_VERSION?err} - e2e: - build: - context: . - args: - CYPRESS_IMAGE: cypress/base:12 - image: grafonnet-e2e - command: npx cypress run - depends_on: - - grafana - environment: - - CYPRESS_baseUrl=http://grafana:3000 - - CYPRESS_video=false - volumes: - - ./cypress:/e2e/cypress - - ./cypress.json:/e2e/cypress.json - - ../dashboards_out:/e2e/test diff --git a/vitess-mixin/e2e/external_db/.env b/vitess-mixin/e2e/external_db/.env deleted file mode 100644 index f2745ff08ef..00000000000 --- a/vitess-mixin/e2e/external_db/.env +++ /dev/null @@ -1,4 +0,0 @@ -MYSQL_ROOT_PASSWORD=pass -MYSQL_USER=dbuser -MYSQL_PASSWORD=dbpass -MYSQL_DB=commerce \ No newline at end of file diff --git a/vitess-mixin/e2e/external_db/README.md b/vitess-mixin/e2e/external_db/README.md deleted file mode 100644 index 610a9350111..00000000000 --- a/vitess-mixin/e2e/external_db/README.md +++ /dev/null @@ -1,113 +0,0 @@ -**This README is kept here for reference, however the parent [README](../README) contains all the information necesaary to simulate this in a better way** - -# Simulate external/remote database for Vitess using docker-compose - -This directory has a docker-compose that will bring up a mysql instance. -You can then point your vitess cluster to it to understand how to use Vitess for your existing database -when you cannot install Vitess on the mysql instance. - -First you will need to [install docker-compose](https://docs.docker.com/compose/install/). - - -### Create new docker-machine -Create a new docker-machine that will run your mysql container. -Creating a new machine allows you to more comprehensively test the remote functionality. -``` -vitess/examples/compose/external_db$ docker-machine create remote-db -``` - -Grab the docker-machine ip -``` -vitess/examples/compose/external_db$ docker-machine ip remote-db -192.168.99.101 -``` - -Set the environment variables for the remote-db machine -``` -vitess/examples/compose/external_db$ eval $(docker-machine ip remote-db) -``` - -### Start mysql -Start the mysql instance -``` -vitess/examples/compose/external_db$ docker-compose up -d -``` -This will do the following; -1. Starts mysql service and exposes it at `:3306` -2. Creates a `commerce` database with `users` table -3. Adds sample data to the users table -4. Starts a lightweight adminer container to interact with the database accessible at `:8081` -5. Default credentials - ``` - MYSQL_DB: commerce - MYSQL_USER: dbuser - MYSQL_PASSWORD: dbpass - MYSQL_ROOT_PASSWORD: pass - ``` - -### Confirm containers are up -Run the following -``` -vitess/examples/compose/external_db$ docker-compose ps -``` - -A valid response should look like below -```sh - Name Command State Ports ---------------------------------------------------------------------------------------------------------- -external_db_adminer_1 entrypoint.sh docker-php-e ... Up 0.0.0.0:8081->8080/tcp -external_db_db_1 docker-entrypoint.sh mysqld Up (healthy) 0.0.0.0:3306->3306/tcp, 33060/tcp -``` -You now have a mysql instance ready to be *migrated* to Vitess. - -### Start Vitess pointed to this remote database -Head on to [vitess compose instructions](../README.md ) - -If using docker-compose.beginners.yml, run; -``` -vitess/examples/compose$ cp docker-compose.beginners.yml docker-compose.yml -``` -Update your `.env` file with these; -``` -KEYSPACE=commerce -DB=commerce -EXTERNAL_DB=1 -DB_HOST= -DB_PORT=3306 -DB_USER=dbuser -DB_PASS=dbpass -DB_CHARSET=CHARACTER SET latin1 COLLATE latin1_swedish_ci -``` - - -If using `vtcompose` command, run; -``` -vitess/examples/compose$ go run vtcompose/vtcompose.go -keyspaceData="commerce:0:2::" -externalDbData="commerce::3306:dbuser:dbpass:CHARACTER SET latin1 COLLATE latin1_swedish_ci" -``` - -**Ensure you start Vitess in a different docker-machine!!** -If not, run; -``` -vitess/examples/compose$ docker-machine create vitess -vitess/examples/compose$ $(docker-machine env vitess) -``` - -Start Vitess -``` -vitess/examples/compose$ docker-compose up -d -``` - -You should now have Vitess running against your external database instance. - -* [Follow this guide for advanced usage](../README.md#advanced-usage "Advanced Usage" ) -* [See this for common issues](../README.md#common-errors "Common Issues" ) - -### Migrating to Vitess -Migrating to Vitess entirely can be done from; -a) The Vitess Control Panel at http://:15000 -b) The `lvtctl.sh` Helper Script; - -The steps are same -1. Do an EmergencyReparentShard to make a replica the new primary. -2. Ran InitShardPrimary on the new primary. -3. If Vitess is wrong about who the MySQL primary is, you can update it with TabletExternallyReparented diff --git a/vitess-mixin/e2e/external_db/docker-compose.yml b/vitess-mixin/e2e/external_db/docker-compose.yml deleted file mode 100644 index 4c414324e63..00000000000 --- a/vitess-mixin/e2e/external_db/docker-compose.yml +++ /dev/null @@ -1,41 +0,0 @@ -version: '2.1' - -volumes: - vol-db: - -services: - db: - build: - context: ./mysql - dockerfile: Dockerfile - restart: always - environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-pass} - MYSQL_DATABASE: ${MYSQL_DB:-commerce} - MYSQL_USER: ${MYSQL_USER:-dbuser} - MYSQL_PASSWORD: ${MYSQL_PASSWORD:-dbpass} - volumes: - - vol-db:/var/lib/mysql - - ./mysql/:/docker-entrypoint-initdb.d/ - - ./mysql/mysql57.cnf:/etc/mysql/conf.d/mysql57.cnf:ro - - ./mysql/log:/var/log/mysql - command: - - --server-id=1 - - --log-bin=mysql-bin - - --gtid_mode=ON - - --enforce_gtid_consistency - - --general_log=1 - - --slow_query_log=1 - healthcheck: - test: "/usr/bin/mysql --user=root --password=$${MYSQL_ROOT_PASSWORD} --execute \"SHOW DATABASES;\"" - timeout: 10s - retries: 10 - ports: - - "3306:3306" - - adminer: - image: adminer - environment: - ADMINER_DESIGN: rmsoft - ports: - - "8081:8080" diff --git a/vitess-mixin/e2e/external_db/mysql/Dockerfile b/vitess-mixin/e2e/external_db/mysql/Dockerfile deleted file mode 100644 index f44c63951e3..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM mysql:5.7 -COPY . /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/vitess-mixin/e2e/external_db/mysql/commerce.sql b/vitess-mixin/e2e/external_db/mysql/commerce.sql deleted file mode 100644 index 8154d91e7f5..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/commerce.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE DATABASE IF NOT EXISTS commerce; -USE commerce; -DROP TABLE IF EXISTS users; -CREATE TABLE users ( - device_id BIGINT, - first_name VARCHAR(50), - last_name VARCHAR(50), - telephone BIGINT, - gender VARCHAR(16), - reference_id INT, - confidence INT, - coverage INT, - refstart DATETIME, - refstop DATETIME, - qrystart DATETIME, - qrystop DATETIME); - -LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/dataset.csv' INTO TABLE users FIELDS TERMINATED BY ','; - -ALTER TABLE users ADD id INT NOT NULL AUTO_INCREMENT PRIMARY KEY; \ No newline at end of file diff --git a/vitess-mixin/e2e/external_db/mysql/dataset.csv b/vitess-mixin/e2e/external_db/mysql/dataset.csv deleted file mode 100644 index f2af8d74ce7..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/dataset.csv +++ /dev/null @@ -1,1000 +0,0 @@ -1,Elianore,Dunbleton,867-921-5436,Female,1,4,90,2018-11-20 00:23:59,2018-02-11 11:32:09,2018-06-18 23:40:59,2018-07-14 00:59:56 -2,Isa,Gilfoyle,539-533-8647,Male,7,86,65,2018-03-22 18:52:41,2019-01-16 21:08:18,2019-01-03 10:48:54,2018-08-29 14:52:14 -3,Millicent,Jedrys,184-899-3979,Female,5,30,17,2018-06-29 14:14:44,2018-06-07 05:03:57,2018-04-08 03:56:39,2018-02-12 06:41:48 -4,Davey,Sutch,862-838-8206,Male,1,62,94,2018-11-14 06:47:18,2018-08-08 22:44:26,2018-07-12 21:09:27,2018-03-04 16:23:22 -5,Adiana,Strowger,792-848-5008,Female,6,97,75,2018-08-07 01:32:59,2018-08-06 16:19:48,2019-01-20 13:11:37,2018-09-02 22:39:39 -6,Oby,Winthrop,522-736-9711,Male,7,95,11,2018-09-29 06:49:44,2018-02-02 11:07:25,2018-08-17 12:49:31,2018-06-03 13:27:48 -7,Berte,Beldon,947-708-5622,Female,6,3,26,2018-11-21 14:55:27,2018-11-15 17:16:04,2018-01-23 06:12:07,2018-08-30 14:40:37 -8,Logan,Atack,103-849-8439,Male,1,20,86,2019-01-04 01:18:38,2018-09-20 23:59:42,2018-05-10 13:14:24,2018-09-25 10:05:29 -9,Vania,Rosenblum,302-132-8289,Female,5,85,32,2018-03-31 00:24:32,2018-07-28 14:50:39,2018-04-19 12:32:49,2018-04-03 08:31:11 -10,Giffie,Lindblad,312-429-3236,Male,1,52,65,2018-04-15 15:34:57,2018-09-03 05:54:49,2019-01-05 06:42:27,2018-11-05 21:47:08 -11,Bili,Weigh,442-992-2387,Female,5,88,97,2018-12-01 04:31:51,2018-08-22 15:52:23,2018-12-07 23:25:46,2018-08-08 07:47:35 -12,Marlin,Stair,854-643-9633,Male,1,62,61,2018-05-30 14:08:25,2018-03-02 03:34:27,2018-03-21 22:43:12,2018-06-03 18:02:22 -13,Dacey,Corradino,364-281-2170,Female,3,82,19,2018-04-10 01:42:36,2019-01-08 17:42:03,2018-05-20 04:07:33,2018-10-14 03:57:57 -14,Caresse,Santon,221-929-9690,Female,7,97,50,2018-11-20 23:15:03,2019-01-01 18:46:08,2018-04-08 05:49:39,2018-10-04 04:00:37 -15,Trixi,Westphalen,681-738-3653,Female,7,100,87,2018-07-09 18:04:01,2018-11-21 04:36:24,2018-11-25 09:43:50,2018-09-10 07:40:31 -16,Pauline,Breslauer,821-177-6696,Female,6,63,24,2018-11-02 19:56:35,2018-02-09 07:46:00,2019-01-08 03:21:02,2018-09-18 08:18:06 -17,Meridith,Briddock,716-528-7645,Female,3,72,24,2018-11-30 20:13:26,2018-04-04 00:17:34,2018-07-12 04:42:43,2018-07-13 02:53:00 -18,Cordy,Sothern,733-369-1763,Male,6,72,5,2018-08-19 02:02:51,2018-10-01 16:39:38,2019-01-18 12:58:50,2018-04-26 11:01:54 -19,Thom,Swarbrigg,566-424-7472,Male,3,56,29,2018-01-25 19:13:40,2018-09-06 20:39:48,2018-12-23 14:49:40,2018-09-19 13:03:37 -20,Amelina,Ekell,514-321-8056,Female,5,42,43,2018-12-15 14:21:28,2018-08-07 02:53:55,2018-09-30 04:29:03,2018-08-02 18:29:13 -21,Cesare,Lahy,446-382-1825,Male,2,32,10,2018-07-08 01:24:43,2018-03-24 15:25:21,2018-11-15 18:50:17,2018-03-27 19:18:16 -22,Elnora,Cheale,489-718-9700,Female,6,12,73,2018-10-26 17:34:35,2018-12-22 05:44:59,2018-05-09 01:25:04,2018-09-21 18:40:44 -23,Hadrian,Snarie,859-447-4644,Male,1,18,4,2018-08-31 12:15:30,2018-04-16 11:19:30,2018-02-28 10:55:26,2018-10-31 07:05:29 -24,Ravid,Meriott,518-484-9203,Male,1,83,12,2018-12-01 21:38:00,2018-02-12 17:25:00,2018-09-18 16:34:45,2018-09-08 17:32:17 -25,Elenore,De Gowe,180-237-8349,Female,7,75,3,2018-03-20 20:52:00,2018-12-22 19:52:58,2018-07-06 23:18:01,2018-08-12 22:02:21 -26,Juieta,Pridie,278-696-9233,Female,1,93,57,2018-09-04 18:45:44,2018-06-04 17:38:47,2018-11-16 10:31:12,2018-07-15 10:27:10 -27,Neddie,Mosedall,956-605-6537,Male,3,94,19,2018-04-09 13:54:22,2018-04-12 10:58:25,2018-08-21 10:57:27,2018-08-22 20:29:53 -28,Octavius,Fordham,797-217-3886,Male,3,32,82,2018-11-23 16:25:55,2018-11-15 12:08:34,2018-10-28 03:46:45,2018-06-22 03:16:15 -29,Edwin,Tapson,578-261-4030,Male,7,83,39,2018-12-16 01:07:34,2018-12-27 23:39:47,2018-12-03 00:30:10,2018-03-09 18:09:49 -30,Korry,Dyos,108-910-1353,Female,3,80,93,2018-06-14 09:39:58,2018-08-12 21:17:11,2018-09-14 12:22:43,2018-04-08 23:31:12 -31,Kenn,Leist,300-420-7371,Male,5,100,90,2018-11-24 01:42:36,2018-10-27 21:31:19,2019-01-05 02:32:45,2018-11-24 06:45:27 -32,Eldredge,Kemmis,451-974-5763,Male,2,44,42,2018-11-18 11:28:34,2018-02-17 08:01:53,2018-08-21 19:25:26,2018-12-23 12:29:15 -33,Suzanne,Matthiae,560-959-3441,Female,4,56,7,2018-05-04 04:19:19,2018-04-11 11:59:42,2018-02-01 16:22:38,2018-11-15 19:58:02 -34,Josh,Callendar,719-551-3561,Male,4,61,56,2018-10-12 07:20:47,2018-06-14 12:53:31,2018-07-20 09:35:33,2018-03-26 05:54:27 -35,Ian,Thoresby,392-740-5436,Male,7,77,8,2018-03-04 19:37:23,2018-08-07 02:19:40,2018-09-24 07:54:33,2018-07-09 15:36:52 -36,Cordi,Vanichkin,773-231-4509,Female,1,99,90,2018-07-02 02:43:15,2019-01-20 04:28:54,2018-09-05 05:02:38,2019-01-08 04:08:00 -37,Ariel,Le land,917-249-6942,Male,5,9,45,2018-04-29 18:48:49,2018-06-23 08:15:12,2018-01-22 01:29:55,2019-01-03 21:24:23 -38,Delila,Assard,119-780-7155,Female,3,83,70,2018-12-01 01:09:53,2018-05-22 00:23:40,2018-05-19 13:53:02,2018-02-17 03:43:18 -39,Deny,Cullrford,100-298-0840,Female,5,50,39,2018-05-09 23:21:57,2018-05-31 23:46:32,2018-12-03 09:53:47,2019-01-12 10:16:35 -40,Frannie,Sharer,410-855-0951,Male,6,72,43,2018-05-12 06:05:03,2018-04-21 17:15:14,2018-08-30 07:18:18,2018-06-20 04:51:13 -41,Jonis,Lintin,803-933-8038,Female,4,89,84,2018-09-13 20:13:23,2018-08-28 18:20:52,2018-03-13 03:07:16,2018-03-05 07:10:50 -42,Bessie,Hackett,443-436-4804,Female,4,20,36,2018-06-13 07:34:49,2018-06-01 11:23:42,2018-10-19 12:40:14,2018-02-10 12:37:05 -43,Gayel,Tabard,704-527-0263,Female,6,40,44,2019-01-04 14:41:19,2018-04-15 00:21:22,2018-12-30 07:24:38,2018-05-02 21:10:48 -44,Ardisj,Ridder,899-877-7365,Female,1,21,84,2018-06-13 21:09:11,2018-12-02 20:33:23,2018-03-25 07:43:03,2018-10-12 11:26:41 -45,Hammad,Stroband,874-825-9046,Male,3,30,83,2018-09-14 06:04:39,2018-10-23 13:35:20,2018-03-10 08:19:18,2018-07-18 20:31:55 -46,Darius,Sorel,750-599-8665,Male,7,98,76,2018-09-17 22:09:17,2018-06-02 14:07:06,2018-12-08 15:52:18,2018-05-05 12:38:37 -47,Dido,Stockin,339-433-0084,Female,1,89,59,2018-04-30 07:42:06,2018-10-18 22:27:31,2018-11-11 05:06:09,2019-01-01 14:19:17 -48,Sholom,Cobbing,828-431-0433,Male,4,53,86,2018-11-03 23:21:35,2018-10-23 13:33:47,2018-09-03 06:25:27,2019-01-18 06:26:39 -49,Melinde,Hynd,283-446-7128,Female,5,97,84,2018-07-31 06:28:22,2018-10-24 04:00:28,2018-07-28 03:47:24,2018-02-10 19:44:46 -50,Hedvige,Fontenot,534-558-8139,Female,4,94,62,2018-07-15 15:22:39,2018-03-20 18:21:30,2018-03-04 17:34:45,2018-05-25 22:41:39 -51,Killian,Gilmartin,722-114-3059,Male,1,47,8,2018-08-24 01:48:56,2018-07-21 08:24:06,2018-11-05 06:28:14,2018-05-06 13:37:33 -52,Inness,O'Cullinane,630-746-2431,Male,3,71,93,2018-06-14 22:12:56,2018-04-12 23:09:39,2018-02-02 09:42:12,2018-11-14 01:06:15 -53,Doretta,Galiford,528-456-0043,Female,3,84,95,2018-09-09 15:03:41,2018-03-30 03:54:32,2018-10-03 10:51:33,2018-12-15 22:54:24 -54,Alicia,Kemmons,695-461-8136,Female,7,16,82,2018-03-26 20:29:48,2018-03-25 15:58:54,2018-01-30 03:52:35,2018-02-11 04:14:39 -55,Brandea,Nannizzi,215-545-0363,Female,2,86,20,2018-11-05 15:18:22,2018-02-18 13:05:40,2018-11-27 14:37:52,2018-05-04 23:08:00 -56,Jordan,Parkman,473-392-8118,Male,1,41,46,2018-09-27 14:56:49,2018-04-27 06:35:47,2018-02-04 22:54:44,2018-12-06 04:53:24 -57,Bourke,Whittaker,712-907-5729,Male,2,71,6,2018-10-19 17:00:36,2018-12-02 03:28:48,2018-04-13 01:02:14,2018-04-11 23:42:42 -58,Honey,Adriano,822-890-9194,Female,4,31,95,2018-06-18 04:19:51,2018-03-12 03:05:16,2018-02-02 00:52:15,2019-01-07 13:33:51 -59,Tracie,Warrender,617-331-6980,Male,3,69,37,2018-07-09 15:19:55,2018-07-26 13:00:13,2018-03-06 19:39:06,2018-10-05 14:56:58 -60,Billy,Eadmead,556-100-5109,Female,6,16,63,2018-10-04 07:52:43,2018-07-02 07:34:18,2018-05-03 01:03:27,2018-06-03 11:04:04 -61,Jamesy,Mellenby,554-299-7370,Male,6,53,82,2018-10-25 22:03:32,2018-05-03 02:36:00,2018-01-26 21:04:03,2018-09-15 17:06:05 -62,Goober,Mawby,765-918-7080,Male,1,70,20,2018-08-05 15:03:53,2018-09-15 16:38:46,2018-03-02 01:37:07,2018-12-15 23:40:37 -63,Zach,Tompkins,798-498-7252,Male,6,45,65,2018-06-26 09:42:40,2018-04-20 17:05:50,2018-09-18 16:58:53,2018-06-24 00:57:54 -64,Augustine,Cornbill,600-318-2489,Male,7,30,38,2018-02-08 08:08:53,2018-08-14 07:05:17,2018-10-14 01:12:13,2018-09-20 19:42:49 -65,Cort,Rosingdall,915-533-3544,Male,5,81,82,2019-01-18 02:20:54,2018-03-12 08:02:19,2018-05-13 15:10:29,2018-05-16 21:38:26 -66,Broddie,Dziwisz,404-420-5799,Male,7,3,22,2018-08-30 21:01:34,2018-03-13 06:37:11,2018-04-27 16:13:37,2018-12-09 08:39:26 -67,Clarke,Goodge,499-845-2443,Male,2,14,95,2018-04-02 10:32:42,2018-04-27 00:42:32,2018-05-29 08:36:44,2018-04-01 23:40:09 -68,Madelyn,Knight,724-972-4025,Female,6,12,57,2018-04-25 04:45:31,2018-08-13 14:34:24,2018-05-25 09:58:32,2018-09-02 04:03:25 -69,Bibby,Pace,266-593-6853,Female,2,11,87,2018-04-12 22:35:20,2018-03-10 11:28:13,2018-04-12 15:22:53,2018-04-21 18:57:47 -70,Nedi,Tambling,534-778-4478,Female,5,69,95,2018-04-27 15:43:27,2018-07-27 11:55:14,2018-04-05 07:02:04,2018-08-26 01:25:05 -71,Veronica,Alejandro,208-365-2416,Female,1,22,32,2018-04-09 03:42:21,2018-03-30 02:47:59,2018-02-08 16:43:52,2018-03-10 19:51:53 -72,Cecil,Walewicz,133-144-8036,Male,3,58,23,2018-12-26 06:56:13,2018-06-08 09:09:35,2018-02-16 16:39:15,2018-12-21 00:33:53 -73,Salem,Armell,186-906-5312,Male,7,25,47,2018-10-08 00:28:48,2018-09-03 00:55:23,2018-01-31 20:13:21,2018-04-06 20:30:43 -74,Brook,Buckston,714-565-2523,Female,1,13,92,2018-02-12 13:53:51,2019-01-10 22:17:38,2018-08-03 18:27:58,2018-09-06 10:38:45 -75,Benson,MacParlan,881-685-7375,Male,7,95,39,2018-04-07 06:40:34,2018-05-10 22:04:48,2018-10-06 01:07:35,2018-12-25 18:36:48 -76,Lukas,Kittle,845-541-8229,Male,1,52,85,2018-04-14 08:08:32,2018-08-21 12:21:22,2018-11-17 23:14:34,2018-06-21 02:48:31 -77,Jessa,Claus,611-425-9914,Female,7,99,56,2018-10-22 02:50:57,2018-11-25 03:44:27,2018-06-30 15:33:40,2018-07-02 03:59:50 -78,Hieronymus,Schurig,840-630-9703,Male,6,98,77,2018-01-24 18:01:57,2018-06-05 08:22:05,2018-07-12 07:09:14,2018-07-31 08:09:20 -79,Quintilla,Risborough,367-606-2805,Female,4,15,15,2018-10-24 13:48:18,2018-12-16 11:17:17,2018-05-17 19:15:19,2018-06-22 16:46:31 -80,Arv,Billingsley,438-164-1166,Male,3,54,65,2018-07-21 13:35:44,2018-10-07 14:37:53,2018-11-16 15:38:23,2018-10-19 21:07:38 -81,Happy,Rodrigo,427-752-3843,Female,2,28,25,2018-01-28 21:31:16,2018-07-06 04:48:40,2018-02-19 10:50:55,2018-10-20 15:58:59 -82,Cos,Chalfain,609-228-7131,Male,6,12,80,2018-02-24 18:06:52,2018-07-21 03:12:50,2018-02-22 09:53:50,2018-12-04 18:31:35 -83,Dael,Crother,249-141-1807,Male,3,11,86,2018-09-09 23:04:41,2018-02-24 13:19:31,2018-11-05 15:18:33,2018-12-23 18:55:24 -84,Evin,Tettley,974-233-5051,Male,1,57,61,2018-12-26 14:24:36,2018-05-28 19:09:40,2018-09-18 10:01:10,2018-04-04 21:11:05 -85,Bethanne,Hynson,395-152-0590,Female,5,51,39,2018-11-12 01:12:14,2018-07-21 02:07:45,2019-01-06 17:16:22,2018-11-15 16:58:09 -86,Adrian,Sapson,962-473-8077,Female,4,19,63,2018-02-13 14:27:28,2018-06-26 14:23:38,2018-09-17 04:28:22,2018-07-19 18:25:11 -87,Zaneta,Alforde,961-173-4877,Female,2,70,67,2018-11-04 11:27:20,2018-06-09 18:02:24,2018-08-17 03:13:55,2018-09-02 00:28:34 -88,Grady,Kobiera,687-321-5987,Male,1,62,96,2018-06-23 20:06:04,2018-02-08 04:03:21,2018-12-05 23:36:55,2018-10-26 14:17:35 -89,Dominique,Carslake,230-143-4475,Male,4,38,64,2018-05-19 01:14:57,2018-09-24 20:05:20,2018-06-26 12:15:04,2018-10-30 18:21:59 -90,Julietta,Gude,585-759-9173,Female,7,59,75,2018-11-25 20:42:33,2018-08-31 21:59:40,2018-12-31 21:04:44,2018-11-23 04:31:37 -91,Lothaire,Macrow,510-775-2964,Male,1,91,59,2018-04-22 14:12:47,2018-07-05 11:15:49,2018-06-04 12:44:19,2018-10-12 10:28:46 -92,Agneta,Trematick,391-964-4713,Female,6,6,91,2018-01-31 13:00:06,2018-11-24 20:48:15,2018-07-27 00:12:28,2018-02-17 08:41:55 -93,Pet,Padgett,690-476-6060,Female,2,17,84,2018-03-21 11:54:39,2018-03-08 01:51:40,2018-12-21 16:41:23,2018-02-07 14:47:44 -94,Barclay,Binion,516-626-1251,Male,4,49,46,2018-10-19 13:16:50,2018-06-25 01:26:53,2018-02-23 06:44:17,2018-10-08 11:01:59 -95,Dillie,Quilleash,676-581-4684,Male,3,27,14,2019-01-02 01:50:23,2019-01-02 04:16:15,2018-07-21 11:54:44,2018-03-06 02:17:37 -96,Marissa,Twinterman,855-444-0657,Female,6,52,62,2018-07-27 09:41:53,2018-03-18 21:07:51,2018-09-05 04:45:41,2018-05-01 14:08:21 -97,Perl,Braun,639-977-9224,Female,7,93,88,2018-03-12 07:21:26,2018-11-12 18:45:36,2018-09-10 10:45:15,2018-09-30 10:28:01 -98,Gwenette,Jozef,804-642-8405,Female,1,67,64,2018-05-02 20:04:22,2018-05-25 14:26:42,2018-12-22 04:00:00,2018-04-27 17:36:21 -99,Gabbi,Nassey,998-336-4318,Female,3,35,79,2018-11-13 07:58:46,2018-02-23 01:11:32,2018-11-08 17:30:31,2018-07-24 03:14:25 -100,Susana,Ebben,826-329-4492,Female,5,9,98,2018-07-08 08:40:45,2018-07-12 00:41:34,2018-10-12 15:33:58,2018-06-16 15:33:32 -101,Mallorie,Marsters,637-209-9862,Female,5,18,34,2018-07-30 15:18:09,2018-09-23 17:22:45,2018-12-21 17:11:36,2018-07-06 19:42:09 -102,Marley,Bethell,102-272-8411,Female,6,70,7,2018-10-08 12:25:07,2018-04-13 04:50:24,2018-03-01 09:20:29,2018-04-05 02:02:24 -103,Genvieve,McMeekin,679-490-4369,Female,3,7,25,2018-02-25 15:34:48,2018-06-24 16:32:10,2018-07-03 20:04:57,2018-12-11 02:53:30 -104,Bartram,Leahey,830-491-8399,Male,3,100,57,2018-10-18 18:39:57,2018-04-08 02:16:41,2018-07-20 01:10:35,2018-06-20 09:41:56 -105,Livvyy,Thornewell,872-138-4425,Female,6,58,58,2019-01-17 09:36:59,2018-04-13 07:25:55,2018-11-28 12:44:14,2018-07-14 04:05:13 -106,Gabriella,Cornish,202-570-6308,Female,7,79,67,2018-08-25 01:20:02,2018-11-30 22:05:13,2018-10-21 11:47:58,2018-11-20 04:28:53 -107,Humberto,Lanfranchi,636-653-6377,Male,3,18,85,2018-08-21 03:38:03,2018-09-01 07:20:38,2018-04-27 04:23:16,2018-08-15 14:45:48 -108,Othella,Asaaf,386-100-6369,Female,4,59,93,2018-05-20 17:17:26,2018-10-23 01:32:55,2018-09-20 03:27:06,2018-12-17 21:11:18 -109,Mil,Booij,494-405-6566,Female,5,88,97,2018-07-12 19:07:28,2018-02-14 12:57:18,2018-12-11 19:22:18,2018-11-23 12:41:41 -110,Orel,Blaxland,309-372-2193,Female,7,30,93,2018-11-18 23:18:41,2018-06-21 19:30:46,2018-09-15 13:43:25,2018-02-04 09:51:54 -111,Sibeal,Fennelow,543-514-6831,Female,6,92,56,2018-10-09 14:48:56,2018-12-18 22:29:16,2018-04-09 03:30:48,2018-04-04 18:11:19 -112,Sidnee,Thorby,687-609-9785,Male,2,30,12,2018-03-28 10:27:39,2018-07-01 07:12:38,2018-02-16 12:58:34,2018-11-16 01:37:38 -113,Lora,Ridewood,164-690-9005,Female,1,37,55,2018-11-13 21:13:39,2018-09-06 23:00:39,2019-01-17 10:31:22,2018-12-05 22:14:39 -114,Velma,Brolan,359-817-6834,Female,6,26,38,2019-01-16 21:47:15,2018-11-25 16:54:49,2018-10-07 01:07:24,2018-10-11 01:14:02 -115,Vassili,Kirkbride,287-966-8144,Male,6,52,16,2018-12-20 23:23:45,2018-12-21 08:42:29,2018-02-25 02:07:40,2018-06-28 04:39:19 -116,Nettie,Bulmer,357-176-0651,Female,5,16,44,2018-09-19 15:07:17,2018-03-16 17:55:44,2018-09-06 22:48:36,2018-04-28 23:48:07 -117,Elyn,Matthew,176-489-8486,Female,4,25,95,2018-04-10 12:26:47,2019-01-10 03:12:46,2018-07-28 23:51:46,2018-07-07 16:15:50 -118,Nat,Enderlein,480-924-1165,Male,4,94,42,2018-09-10 06:56:16,2018-04-24 02:55:47,2018-03-17 15:48:28,2018-04-30 06:11:27 -119,Allister,Laundon,267-536-1588,Male,6,86,21,2018-08-21 09:06:13,2018-11-26 09:47:45,2018-04-05 15:01:24,2018-01-21 02:29:49 -120,Suzy,Dubery,631-694-1983,Female,5,54,24,2018-07-12 11:08:05,2018-07-21 06:22:14,2018-09-04 03:44:08,2018-11-14 04:59:58 -121,Reinaldo,Assel,927-809-0971,Male,3,4,44,2018-10-17 17:15:04,2018-12-24 21:34:45,2019-01-15 07:39:25,2018-02-06 19:16:38 -122,Claudell,Reckus,196-391-8789,Male,1,34,75,2018-08-12 02:29:09,2018-11-28 02:43:43,2018-08-21 09:11:37,2018-07-14 12:51:48 -123,Kary,Jee,656-508-4636,Female,2,67,47,2018-12-17 10:42:46,2018-05-16 14:59:10,2018-12-23 02:44:31,2018-12-19 01:28:44 -124,Giustino,Tinan,292-383-3412,Male,7,100,96,2018-02-05 08:16:51,2018-04-10 02:46:18,2018-12-07 23:33:47,2018-03-25 18:50:56 -125,Matthew,Palmer,562-655-9301,Male,5,87,100,2018-07-14 00:43:30,2018-01-22 19:53:17,2018-05-18 08:37:49,2018-04-16 10:03:59 -126,Helge,Paradyce,454-788-5166,Female,4,31,87,2018-12-29 12:15:52,2018-02-08 19:33:17,2018-12-29 06:51:56,2018-11-11 03:52:39 -127,Anthe,Cullinan,517-178-4457,Female,4,61,14,2018-07-10 05:46:54,2018-12-22 09:39:32,2018-12-06 16:59:53,2018-12-30 08:24:22 -128,Cindy,Bellie,284-376-7890,Female,6,26,95,2018-02-04 23:09:03,2018-09-06 16:30:50,2018-05-25 00:39:04,2018-12-20 19:03:33 -129,Deva,Branthwaite,272-973-9361,Female,5,4,74,2018-06-05 05:56:15,2018-06-26 03:23:22,2018-06-06 00:42:51,2018-12-01 12:32:06 -130,Karen,Frank,495-748-4715,Female,6,55,54,2018-10-26 02:19:25,2018-04-11 12:50:31,2019-01-12 15:29:42,2018-12-23 04:07:28 -131,Batsheva,Wressell,364-562-3308,Female,2,93,2,2018-12-08 11:50:47,2018-10-05 08:11:01,2018-12-29 23:04:37,2018-10-13 09:59:34 -132,Damian,Devon,617-622-5769,Male,1,81,84,2018-03-03 22:21:45,2018-02-09 02:46:29,2018-02-04 03:39:23,2018-06-24 17:15:50 -133,Mischa,Feldbrin,941-794-4981,Male,2,17,93,2018-07-05 04:20:06,2018-11-22 10:46:44,2018-10-25 23:05:17,2018-08-04 04:19:58 -134,Remus,Mochar,964-251-2864,Male,2,78,88,2018-05-08 23:51:18,2019-01-19 19:38:55,2018-06-13 09:14:44,2019-01-10 12:37:02 -135,Cleon,Ambroise,790-235-3681,Male,3,38,95,2018-08-11 11:07:40,2018-07-06 04:03:45,2018-12-18 09:47:22,2018-03-31 14:59:58 -136,Sidney,Duthy,739-113-2227,Male,4,95,79,2018-09-25 19:41:46,2018-09-05 07:30:26,2018-03-21 18:52:33,2018-04-25 13:58:28 -137,Xavier,Gon,942-422-7024,Male,5,35,47,2018-09-05 22:08:31,2018-05-10 20:19:08,2018-06-25 18:32:07,2018-04-11 04:44:32 -138,Ara,Gwyllt,450-595-4186,Male,4,4,28,2018-10-28 21:12:39,2018-02-13 08:26:45,2018-06-16 21:44:05,2018-08-01 11:08:43 -139,Libbey,Millwall,764-602-4598,Female,7,89,31,2019-01-14 17:04:08,2018-02-22 03:01:08,2018-02-27 08:56:59,2018-11-09 13:18:23 -140,Rosalynd,Wellard,798-378-3350,Female,4,58,44,2018-07-13 19:23:05,2018-11-20 20:46:20,2018-01-31 02:28:58,2018-10-25 13:31:05 -141,Reinaldo,O'Dea,896-868-5961,Male,2,72,69,2018-08-08 04:21:04,2018-06-23 08:34:34,2018-08-31 08:41:08,2018-11-19 09:43:28 -142,Veradis,Holyard,706-725-9446,Female,3,78,56,2018-09-05 17:38:33,2018-05-04 13:04:38,2018-11-05 12:46:29,2018-09-25 08:56:54 -143,Birdie,Collerd,319-380-7196,Female,2,22,1,2018-10-16 19:45:08,2018-08-05 06:38:47,2018-11-22 11:10:39,2018-10-20 09:48:22 -144,Sada,Schout,825-204-2108,Female,7,88,10,2018-04-13 13:44:13,2018-06-06 14:39:37,2018-11-09 10:29:00,2018-09-15 05:38:03 -145,Ambros,Mayoral,819-227-9360,Male,7,50,91,2018-03-27 15:27:05,2018-08-02 02:18:35,2018-06-27 17:10:44,2018-07-21 14:18:29 -146,Emile,Abraham,622-769-6584,Male,6,10,44,2018-09-15 10:24:46,2018-07-10 07:58:58,2018-06-18 22:49:01,2018-04-20 09:07:25 -147,Lira,Reboulet,983-623-7858,Female,4,54,39,2018-06-27 09:11:33,2018-10-01 07:52:19,2018-10-21 09:48:43,2018-09-09 22:17:51 -148,Bucky,Dubery,127-215-3377,Male,1,13,5,2018-02-15 22:03:55,2018-10-15 16:35:39,2018-02-20 10:22:26,2018-11-05 12:56:42 -149,Ced,Meert,482-685-6526,Male,1,85,40,2018-11-09 04:11:10,2019-01-16 14:34:41,2018-05-22 12:18:01,2018-03-13 13:09:46 -150,Hamlen,Boyson,723-641-9907,Male,7,3,25,2018-07-08 10:27:28,2018-09-06 08:34:00,2018-10-19 17:18:48,2018-02-22 19:31:50 -151,Scotty,Bromell,605-116-4137,Male,4,44,83,2018-02-03 11:10:35,2018-03-05 15:14:24,2018-06-20 01:47:46,2018-04-09 17:34:46 -152,Betti,Cuttelar,947-869-1635,Female,7,31,68,2018-07-14 23:35:44,2018-09-07 08:03:02,2018-05-02 15:32:32,2018-02-26 15:33:55 -153,Lothario,Whellams,959-671-9821,Male,3,91,85,2018-12-17 02:20:59,2018-08-31 16:54:24,2018-09-30 18:16:21,2018-06-06 21:30:55 -154,Maurits,Eisenberg,612-730-0598,Male,5,95,2,2018-07-11 05:38:06,2018-01-26 15:01:11,2018-11-11 22:30:48,2018-04-16 07:20:25 -155,Jeffry,Wilprecht,420-521-7374,Male,2,2,19,2018-07-31 12:28:42,2018-03-19 23:14:58,2018-11-29 11:25:28,2018-02-19 02:42:46 -156,Victor,Grinter,303-176-4062,Male,3,28,82,2018-04-15 17:22:33,2018-04-26 11:56:35,2018-10-06 23:26:58,2018-04-05 07:32:13 -157,Sonnie,Lobe,794-424-7798,Male,1,68,99,2018-12-23 13:36:28,2018-11-24 21:42:21,2018-03-23 12:37:58,2018-06-26 15:29:05 -158,Krishna,Fletcher,520-484-4343,Male,5,77,26,2018-05-15 11:17:35,2018-12-22 22:52:12,2018-05-10 22:50:32,2018-05-05 21:38:09 -159,Kerrie,Bartholomieu,654-465-0213,Female,4,7,56,2018-11-02 19:08:33,2018-01-27 09:11:25,2018-12-13 16:53:49,2018-05-06 13:16:06 -160,Rasla,Dibbs,192-692-8022,Female,5,58,38,2018-05-13 16:41:12,2018-12-17 01:00:54,2018-08-19 15:33:37,2019-01-11 00:33:40 -161,Mellisa,Prinn,884-570-1200,Female,3,2,44,2018-06-17 15:55:01,2018-02-09 22:16:46,2018-01-21 11:35:44,2018-03-22 01:43:34 -162,Shandeigh,Prise,284-912-2475,Female,1,24,63,2018-04-16 10:09:01,2018-09-06 02:59:22,2018-05-21 00:23:45,2018-05-18 15:59:58 -163,Aline,Pockey,145-621-3349,Female,5,46,99,2018-07-08 01:50:19,2018-07-23 03:08:04,2018-07-25 04:19:37,2018-08-02 04:28:24 -164,Quinton,Filon,646-285-5370,Male,7,71,90,2018-09-26 09:06:43,2018-09-15 14:33:28,2018-11-23 04:26:39,2019-01-20 06:07:08 -165,Brena,Bentke,336-549-2800,Female,6,52,73,2018-02-07 03:32:01,2018-09-21 09:41:58,2018-08-01 23:49:56,2018-04-24 04:41:42 -166,Kessia,Bentote,261-293-3478,Female,7,34,27,2019-01-03 17:12:12,2018-01-28 01:36:43,2018-09-06 07:29:49,2018-07-16 11:22:52 -167,Serene,Jellett,617-490-3045,Female,4,8,12,2018-08-01 05:18:42,2018-08-21 11:58:23,2018-02-17 11:36:57,2018-12-29 13:38:10 -168,Drugi,Chainey,642-531-9743,Male,1,27,14,2019-01-06 06:11:34,2018-11-02 16:07:48,2019-01-07 21:38:11,2018-10-26 19:58:30 -169,Benjamen,Angric,161-599-1534,Male,6,80,80,2018-03-25 19:49:25,2018-08-23 06:12:13,2018-05-09 05:22:56,2018-04-03 12:50:17 -170,Augustine,de Werk,986-128-9745,Male,7,40,35,2018-09-07 12:55:20,2018-09-15 16:46:53,2018-02-12 14:00:28,2018-02-20 11:54:00 -171,Rorke,Laidlaw,818-603-8046,Male,1,99,95,2018-12-25 21:27:03,2018-12-15 12:30:46,2018-11-06 04:14:51,2018-11-30 18:51:21 -172,Clywd,Cawdron,118-860-8931,Male,3,12,48,2018-10-28 00:46:43,2018-07-04 11:34:45,2018-01-24 04:40:57,2018-11-08 13:52:59 -173,Maudie,Habbijam,781-157-2628,Female,1,79,35,2018-11-30 12:07:21,2018-03-07 00:30:04,2018-11-14 11:01:28,2018-12-25 08:37:17 -174,Gina,Adamovitz,873-120-9534,Female,1,99,41,2018-10-15 08:16:08,2018-02-02 10:04:20,2018-03-11 05:28:50,2018-08-15 16:28:04 -175,Dorey,Berkeley,856-131-2818,Female,5,8,45,2018-06-14 02:47:10,2018-12-04 16:14:29,2018-02-20 02:19:22,2018-04-14 04:00:28 -176,Ashli,Stanistrete,507-365-9155,Female,3,50,85,2019-01-15 15:53:25,2018-09-08 00:21:37,2018-09-08 14:26:57,2018-08-12 18:04:42 -177,Aleta,Jessard,640-184-4123,Female,1,63,42,2018-12-13 11:45:35,2018-07-13 05:43:20,2018-07-19 01:29:59,2018-08-19 10:17:25 -178,Conney,Tansly,619-324-6788,Male,7,18,68,2018-02-06 08:22:33,2018-02-09 16:00:31,2018-02-17 20:35:12,2018-09-01 00:28:07 -179,Chaddie,Curling,967-821-4721,Male,3,50,28,2018-04-18 18:52:52,2018-10-04 03:42:09,2018-11-06 23:55:33,2018-12-23 04:01:13 -180,Skyler,Shard,173-185-5465,Male,7,48,76,2018-03-21 23:42:54,2018-05-22 07:52:04,2018-02-28 18:02:47,2018-08-20 09:21:32 -181,Alair,Bruggen,225-747-4685,Male,5,45,4,2018-03-13 03:01:40,2018-04-30 23:24:34,2018-04-25 03:14:01,2018-07-26 19:41:29 -182,Forester,Rackstraw,111-188-6870,Male,6,11,43,2018-09-26 04:05:12,2018-08-25 04:59:08,2018-02-09 16:50:13,2018-06-10 06:53:15 -183,Stinky,Klassmann,628-447-6394,Male,5,42,77,2018-12-29 18:37:51,2018-01-31 04:16:33,2018-05-27 09:10:31,2018-02-03 20:09:44 -184,Gabriella,Weeds,978-256-0633,Female,3,17,50,2018-10-10 14:56:11,2019-01-19 07:53:13,2018-08-28 10:02:39,2018-05-03 15:01:38 -185,Ingeborg,Swine,765-792-5768,Female,5,39,37,2018-10-13 03:17:12,2018-11-25 20:17:22,2018-08-25 21:54:45,2018-12-04 07:44:58 -186,Kain,Everingham,945-715-9320,Male,7,52,80,2018-10-22 01:58:35,2018-04-16 11:48:35,2018-02-22 17:07:19,2018-12-15 01:59:16 -187,Noble,Swadlinge,928-764-8545,Male,7,24,75,2018-07-02 20:12:53,2018-07-19 00:23:08,2018-08-06 21:50:01,2018-05-04 08:56:30 -188,Amber,Shropshire,983-928-3309,Female,1,100,37,2018-03-18 04:32:13,2018-08-09 03:16:35,2018-11-21 04:25:29,2018-10-03 06:20:54 -189,Hedy,Sapena,301-104-2652,Female,3,37,35,2018-07-04 12:54:06,2018-10-12 20:33:48,2018-04-10 07:32:31,2018-03-17 10:12:03 -190,Nerissa,Jedras,425-605-9508,Female,1,18,31,2019-01-12 14:05:35,2018-10-19 14:28:35,2018-06-14 21:07:02,2018-03-22 05:53:32 -191,Terrel,Kear,681-621-2157,Male,3,98,45,2018-02-20 10:42:05,2018-11-08 04:29:14,2018-03-09 02:33:02,2018-07-04 18:27:00 -192,Dennison,Theodoris,722-911-1627,Male,6,76,32,2018-11-18 05:15:23,2018-05-13 02:02:05,2019-01-15 21:45:30,2018-04-13 17:24:17 -193,Chrystel,Ferentz,497-580-2963,Female,2,96,6,2018-12-11 03:17:23,2018-05-23 04:35:09,2018-11-01 17:51:50,2018-08-02 02:44:29 -194,Devland,Butchers,313-172-9223,Male,6,42,38,2019-01-16 07:17:37,2018-11-09 17:37:48,2018-04-10 08:57:30,2018-05-02 13:47:28 -195,Simon,Astupenas,981-207-6441,Male,2,57,43,2018-11-07 15:02:00,2018-01-25 17:30:33,2018-07-13 05:08:19,2018-10-29 18:37:22 -196,Jordan,Attride,447-912-6034,Female,7,25,37,2018-06-06 14:29:43,2018-06-30 03:49:38,2018-12-09 18:11:23,2018-01-30 19:12:46 -197,Clerissa,Forsard,485-444-1412,Female,2,88,66,2018-09-19 00:56:28,2018-07-23 15:36:37,2018-11-17 11:43:09,2018-11-17 17:11:53 -198,Alastair,Toth,495-980-1189,Male,1,62,59,2018-03-04 17:35:31,2018-06-18 07:02:22,2018-07-30 02:31:33,2018-07-20 14:21:29 -199,Aldo,Bruton,488-482-2130,Male,2,33,99,2018-06-09 23:01:18,2018-08-22 04:11:53,2018-07-17 05:55:24,2018-04-08 10:13:23 -200,Lorin,Mourant,953-195-5245,Male,1,78,78,2018-02-04 07:07:36,2018-08-05 08:03:40,2018-11-22 13:04:30,2018-03-10 12:32:28 -201,Nonnah,Dreini,137-834-9350,Female,1,20,84,2018-11-23 21:47:29,2018-07-02 22:51:42,2018-05-28 23:33:57,2018-06-11 11:55:17 -202,Winnie,Muris,865-681-2171,Female,2,31,76,2018-10-29 21:53:21,2018-10-12 17:59:08,2018-03-21 12:37:41,2018-06-26 05:24:49 -203,Marybelle,Wedmore.,566-812-6518,Female,6,94,20,2018-04-08 17:51:07,2018-01-25 19:29:58,2018-05-29 08:33:21,2018-12-18 09:29:05 -204,Christophorus,La Batie,776-298-7693,Male,2,100,44,2018-11-26 01:22:44,2018-11-28 19:33:42,2018-01-26 20:34:09,2018-10-15 19:29:24 -205,Erhart,Laydon,425-854-5387,Male,7,15,35,2018-11-09 09:53:34,2018-11-11 01:43:14,2019-01-16 12:20:32,2018-08-01 09:34:47 -206,Myrta,Playfair,512-835-4158,Female,4,8,51,2018-05-04 15:28:01,2018-05-11 22:03:31,2018-05-21 02:28:31,2018-03-17 08:25:48 -207,Tybie,McGhee,155-902-0043,Female,5,25,55,2018-03-19 17:19:34,2018-11-11 01:53:03,2018-06-01 16:21:08,2018-08-21 09:39:26 -208,Augusto,Chelam,595-490-1187,Male,2,20,22,2018-02-26 17:51:20,2018-04-15 11:38:21,2018-11-29 19:44:24,2018-05-17 16:31:14 -209,Louisette,Firbanks,365-745-5229,Female,1,51,35,2018-04-17 19:42:14,2018-03-19 09:56:15,2018-04-22 09:48:27,2018-11-20 05:52:44 -210,Brucie,Speers,688-351-7130,Male,3,65,20,2018-09-22 06:54:04,2018-08-14 23:05:08,2018-03-13 17:38:11,2018-12-29 06:47:13 -211,Nathanial,Ayliff,974-831-8727,Male,1,23,95,2018-09-02 06:27:24,2018-06-18 22:51:54,2018-12-25 13:15:52,2018-03-09 05:29:17 -212,Shawnee,McClenan,177-754-4767,Female,4,54,82,2018-04-17 14:01:32,2018-08-15 14:02:31,2019-01-04 03:04:30,2018-10-20 15:25:45 -213,Giavani,Cay,976-869-6321,Male,1,92,27,2018-07-22 17:43:03,2018-02-20 03:19:34,2018-05-06 13:52:36,2018-12-05 18:14:41 -214,Claudia,Fazackerley,454-663-9623,Female,4,26,25,2019-01-07 16:15:34,2018-03-06 15:31:53,2018-02-06 23:08:37,2018-11-13 17:45:22 -215,Nevil,Phelp,255-488-7211,Male,5,22,40,2018-09-11 19:55:44,2018-05-13 12:07:30,2018-08-27 02:20:49,2019-01-17 21:11:30 -216,Elle,Antal,303-999-5794,Female,4,23,5,2018-02-15 19:05:09,2018-10-15 01:01:31,2018-12-31 16:08:16,2018-03-23 15:16:38 -217,Brnaby,Dewsbury,173-850-9221,Male,3,82,22,2018-05-19 14:05:10,2018-12-30 00:25:40,2018-09-27 06:32:26,2018-04-25 02:17:22 -218,Ronda,Dranfield,835-657-5998,Female,5,61,54,2018-10-18 03:51:07,2018-07-20 06:01:19,2018-11-17 15:09:04,2018-12-04 20:06:06 -219,Vania,Brannan,288-990-8986,Female,3,88,25,2018-07-03 11:19:29,2018-11-13 09:44:15,2018-02-28 13:57:43,2018-02-28 05:42:56 -220,Jessy,Baggelley,848-274-4914,Female,7,38,75,2018-12-04 13:44:16,2018-11-20 01:53:14,2018-02-25 03:07:40,2018-06-17 19:02:59 -221,Paxon,Kensall,262-215-6295,Male,1,3,63,2018-08-12 21:30:25,2018-11-24 01:13:12,2018-06-04 19:20:59,2018-08-16 14:48:22 -222,Tana,O'Donohue,514-853-5855,Female,4,99,1,2018-03-21 06:05:58,2018-05-01 00:39:55,2018-03-10 21:55:54,2018-10-31 10:25:10 -223,Thomasina,Gibbons,501-364-8398,Female,3,37,56,2018-11-22 03:07:49,2018-06-30 16:44:00,2018-08-05 18:41:13,2019-01-07 06:21:44 -224,Bellanca,Golston,673-979-3362,Female,1,57,53,2018-05-02 00:04:42,2018-01-21 22:51:57,2018-08-20 18:40:05,2018-02-09 08:22:11 -225,Maureene,Drejer,769-639-6612,Female,7,49,17,2018-02-20 12:00:24,2018-09-01 04:44:08,2018-08-15 22:04:06,2018-09-04 06:40:59 -226,Beatrisa,Blanche,914-368-0909,Female,4,47,77,2018-05-21 06:41:29,2018-10-04 19:21:53,2018-07-11 04:03:32,2018-04-05 01:26:21 -227,Melita,Filipczak,743-692-1202,Female,2,18,45,2018-04-04 09:49:49,2018-03-30 16:30:51,2019-01-09 03:34:15,2018-02-05 00:54:24 -228,Jean,Rzehor,983-469-9959,Male,2,76,95,2018-08-17 14:15:05,2018-09-25 10:05:56,2018-09-04 10:03:08,2018-02-16 04:46:04 -229,Netti,Odeson,140-282-6021,Female,7,46,99,2018-04-08 08:08:21,2018-05-07 06:33:55,2018-03-10 06:30:39,2018-08-27 01:08:06 -230,Lark,Komorowski,889-340-2588,Female,6,36,54,2018-05-27 12:55:35,2018-11-18 05:20:17,2018-11-19 04:18:03,2018-04-24 14:21:19 -231,Mae,Howells,972-510-2059,Female,2,54,97,2019-01-17 19:46:20,2018-07-10 05:29:24,2018-07-06 16:03:28,2018-07-18 17:41:40 -232,Brewer,Wolstencroft,243-516-4986,Male,4,68,84,2018-07-19 01:48:48,2018-12-31 10:44:05,2018-05-25 20:15:52,2018-04-27 22:38:48 -233,Chrystel,Buist,285-587-4608,Female,3,66,90,2018-02-06 05:43:09,2018-06-10 20:45:59,2018-11-27 09:40:02,2018-12-30 22:43:43 -234,Nicola,Feltoe,102-119-8958,Female,6,30,100,2018-05-26 00:46:42,2018-03-17 00:12:12,2019-01-16 18:40:38,2018-01-27 09:20:23 -235,Engelbert,Matveiko,868-192-6148,Male,3,3,6,2018-05-27 06:16:04,2018-12-24 00:22:43,2018-04-18 07:21:59,2018-12-03 08:49:41 -236,Lezley,M'Chirrie,749-737-2204,Male,4,16,17,2018-07-06 21:48:48,2018-02-09 05:08:49,2018-09-05 10:59:16,2018-03-22 01:13:02 -237,Josy,Larkins,826-241-0108,Female,1,8,18,2018-10-26 03:28:37,2018-02-24 22:01:17,2018-12-29 22:31:43,2018-05-23 06:28:27 -238,Armando,Girt,296-631-5842,Male,1,90,62,2018-03-14 20:02:06,2018-02-25 03:43:37,2018-05-29 18:43:28,2018-10-10 16:04:29 -239,Nevins,Boch,243-865-0986,Male,7,87,34,2018-04-27 05:11:05,2018-06-13 18:02:47,2018-04-17 23:28:45,2018-03-11 20:07:50 -240,Gordan,MacHoste,194-807-0099,Male,2,8,10,2018-11-30 11:09:40,2018-03-19 08:40:39,2018-07-07 07:58:57,2018-12-03 15:54:45 -241,Vlad,Urling,756-416-9308,Male,6,44,75,2018-07-01 08:10:44,2018-06-25 11:50:00,2018-02-18 09:41:26,2019-01-20 16:56:43 -242,Karney,Batteson,884-299-0885,Male,3,4,70,2018-04-21 18:15:47,2018-03-17 15:26:35,2018-09-21 06:49:36,2018-03-03 10:02:05 -243,Shep,Croisier,182-249-1703,Male,2,25,64,2018-11-27 15:36:38,2018-03-27 09:16:11,2018-07-27 14:14:49,2018-08-31 21:47:02 -244,Jackelyn,Franschini,203-947-2285,Female,5,93,18,2018-05-11 18:05:34,2018-07-09 02:56:23,2018-05-26 13:31:09,2018-11-12 13:51:54 -245,Kingston,Brazier,388-460-9266,Male,5,67,43,2018-11-17 16:06:03,2018-10-22 21:39:40,2018-11-03 04:17:45,2018-08-23 17:37:21 -246,Derwin,Postin,334-746-9914,Male,2,9,74,2018-04-28 10:39:48,2018-10-16 21:01:17,2019-01-17 12:54:27,2018-09-18 06:08:12 -247,Rustie,Boddington,499-187-3081,Male,7,75,92,2018-07-09 18:05:33,2018-09-15 11:50:52,2018-06-10 05:00:00,2018-09-23 05:52:23 -248,Araldo,MacConnulty,922-950-0398,Male,4,66,28,2018-11-11 12:46:18,2018-09-10 16:05:23,2018-09-21 00:16:24,2018-10-10 19:06:57 -249,Brear,Zuanelli,948-803-5705,Female,7,88,15,2018-03-03 08:12:37,2018-10-06 14:14:00,2018-09-06 21:02:50,2018-04-04 06:13:25 -250,Ruttger,Cartan,503-123-4758,Male,6,8,46,2018-07-02 10:33:15,2018-10-11 08:51:25,2018-02-16 18:01:35,2018-05-15 00:25:35 -251,Leta,Gravenell,798-643-9817,Female,6,19,50,2018-09-26 18:01:14,2018-12-31 01:08:01,2018-08-12 01:18:26,2018-08-12 11:04:31 -252,Nanny,Spellward,298-614-5133,Female,2,78,35,2018-07-31 14:38:53,2018-07-11 11:50:42,2018-06-24 03:47:24,2018-08-23 06:25:24 -253,Garwin,Overil,981-304-0345,Male,1,66,62,2018-02-20 05:57:01,2018-02-04 20:02:37,2018-04-21 16:30:20,2018-07-27 08:45:03 -254,Ancell,Bromidge,677-576-3535,Male,1,54,47,2018-02-27 19:07:09,2018-07-07 17:41:39,2018-03-14 05:31:23,2018-11-18 21:30:30 -255,Harmonia,McIleen,610-808-3838,Female,5,76,7,2018-05-09 14:49:35,2018-04-12 02:30:13,2019-01-17 21:59:23,2018-04-20 05:21:50 -256,Ginni,See,809-189-3574,Female,7,93,45,2018-04-11 20:22:07,2018-08-17 13:12:57,2018-04-20 06:30:33,2018-04-17 00:12:41 -257,Christi,Doorly,614-386-8893,Female,7,23,11,2018-08-09 05:01:14,2018-03-11 21:19:53,2018-05-09 23:37:07,2018-03-27 22:07:11 -258,Perice,Severy,433-906-1030,Male,1,18,5,2018-09-01 12:30:04,2018-09-13 05:34:16,2019-01-16 22:35:35,2019-01-09 20:31:49 -259,Dulsea,Yokel,279-965-4206,Female,2,93,50,2018-10-31 22:48:09,2018-07-13 09:25:20,2018-02-16 09:15:58,2018-05-12 21:55:26 -260,Marge,Cheng,549-350-8693,Female,2,10,68,2018-09-01 18:42:35,2018-04-07 10:58:53,2018-07-30 16:05:15,2018-10-20 05:45:19 -261,Baron,McIlmorow,283-456-4615,Male,2,41,89,2018-11-07 01:23:03,2018-12-20 18:25:28,2018-08-31 12:49:04,2018-05-27 07:39:41 -262,Rabbi,Beaglehole,904-724-1771,Male,2,94,67,2018-11-04 08:21:47,2018-12-28 20:54:40,2018-12-08 10:20:14,2018-11-29 19:47:40 -263,Olvan,Asher,310-502-8368,Male,7,76,67,2018-03-15 22:02:48,2018-07-30 12:08:26,2018-12-06 22:49:46,2018-06-17 22:03:05 -264,Yard,Beldon,209-784-5636,Male,7,90,9,2018-07-24 02:02:11,2018-05-11 03:54:15,2018-08-20 18:46:55,2018-03-10 04:11:33 -265,Enriqueta,Barraclough,332-372-0081,Female,6,75,69,2018-08-18 05:08:19,2018-01-27 11:36:23,2018-05-23 08:59:06,2018-02-11 04:14:36 -266,Alli,Smallcomb,255-741-1276,Female,2,8,1,2018-12-06 01:19:35,2018-07-16 16:10:12,2018-07-16 13:31:05,2018-10-26 07:03:09 -267,Shay,Amsden,816-821-9426,Male,6,25,35,2018-03-15 01:09:39,2018-11-26 05:57:30,2018-10-26 07:54:05,2018-04-14 01:42:13 -268,Jacynth,Boscott,970-121-0282,Female,1,88,89,2018-07-31 16:10:10,2018-05-10 10:28:44,2018-10-02 23:00:23,2018-07-02 13:55:14 -269,Dominique,Farny,782-337-7486,Male,1,17,29,2018-09-09 16:09:20,2018-04-10 15:04:16,2018-03-25 16:40:27,2019-01-04 20:02:55 -270,Keefe,Guerrero,440-254-1961,Male,4,96,29,2018-10-19 10:06:55,2018-07-28 18:31:17,2018-05-05 19:05:12,2018-06-01 05:55:25 -271,Buiron,Anfossi,512-333-8553,Male,2,92,51,2018-09-09 16:00:30,2018-02-20 14:27:22,2018-03-11 07:29:35,2018-07-12 02:19:45 -272,Eleonore,Puller,325-656-5909,Female,4,88,37,2018-12-04 20:39:40,2018-02-13 04:35:07,2018-08-16 18:26:05,2018-06-08 07:45:57 -273,Katuscha,Rasch,427-956-1046,Female,4,68,90,2018-06-19 01:20:15,2018-04-03 01:55:07,2018-04-17 19:09:09,2018-08-15 11:04:06 -274,Hoebart,Linger,972-926-3923,Male,4,74,74,2018-02-19 01:23:42,2018-01-26 15:34:23,2018-09-13 07:10:43,2018-06-07 23:26:33 -275,Patrick,Hryskiewicz,736-622-7490,Male,3,91,1,2019-01-13 09:57:23,2018-05-06 15:42:09,2018-07-01 17:16:14,2018-09-01 02:26:15 -276,Bert,Adrianello,485-126-1547,Female,7,33,12,2018-11-01 06:34:27,2018-09-14 23:29:20,2018-03-11 08:15:03,2018-09-21 21:53:26 -277,Burton,Spittall,570-586-9893,Male,7,46,33,2018-01-28 06:20:39,2018-06-15 19:15:06,2018-06-27 02:36:30,2018-03-24 02:52:03 -278,Tessy,Mitchley,167-983-7021,Female,5,45,26,2018-03-02 16:44:00,2018-12-25 18:48:13,2018-04-01 18:27:41,2018-04-03 20:39:05 -279,Nettle,Hause,489-296-7367,Female,2,99,15,2018-03-18 02:50:49,2018-03-02 01:31:53,2018-10-31 06:40:34,2018-04-28 11:21:14 -280,Pearce,Darwent,801-341-9474,Male,2,24,44,2018-05-28 23:54:50,2018-02-07 18:37:22,2018-09-11 02:48:52,2018-11-09 16:24:17 -281,Kelsey,Suttle,536-591-5133,Female,6,11,76,2018-02-14 19:05:31,2018-07-14 19:32:27,2018-03-26 04:59:22,2018-04-01 20:21:57 -282,Gillie,Sponton,270-390-2110,Female,2,94,57,2018-03-14 11:50:53,2018-03-27 13:10:53,2018-04-23 19:54:11,2018-08-22 21:53:12 -283,Marsha,Dietz,740-837-1891,Female,5,90,95,2018-03-18 04:53:06,2018-06-29 02:28:55,2018-08-10 05:14:09,2018-05-10 04:03:25 -284,Miles,Purchon,413-518-8673,Male,2,57,98,2018-04-02 15:49:11,2018-02-04 16:57:33,2018-09-09 22:23:44,2018-03-16 04:00:43 -285,Collette,Menego,440-637-0309,Female,3,21,56,2018-04-18 04:27:48,2018-05-05 08:32:40,2018-03-17 17:54:26,2018-04-12 00:24:45 -286,Heriberto,Dunkerton,321-657-4492,Male,5,99,91,2018-08-17 12:11:42,2018-10-26 14:33:07,2018-03-10 13:13:28,2018-05-03 02:14:30 -287,Hailee,Remington,671-722-2287,Female,6,69,53,2018-08-01 01:54:04,2018-08-20 04:05:47,2018-04-24 14:22:04,2018-11-02 14:15:55 -288,Ingunna,Errigo,378-401-4671,Female,3,83,66,2018-12-22 21:52:13,2018-12-24 18:41:25,2018-11-11 17:31:47,2018-06-27 14:34:11 -289,Barbie,Grishmanov,184-949-4040,Female,7,93,68,2018-08-14 21:25:04,2018-08-26 18:27:48,2018-04-28 10:50:33,2018-08-06 14:12:21 -290,Anderson,Freeland,842-434-1249,Male,6,22,71,2019-01-05 09:24:32,2018-06-13 07:19:06,2018-04-24 22:20:16,2018-05-31 21:18:59 -291,Olympie,Prantl,988-864-1736,Female,1,39,40,2018-04-06 05:52:26,2018-03-10 03:20:54,2018-02-06 16:53:55,2018-09-03 16:18:27 -292,Amos,Lanyon,552-486-3382,Male,1,17,35,2018-07-03 20:26:09,2018-11-16 06:37:27,2018-08-16 14:36:30,2018-04-07 19:59:08 -293,Gabby,Stockau,753-586-0632,Male,5,19,14,2018-12-10 13:52:07,2018-03-20 20:50:50,2018-04-11 20:54:39,2018-11-13 17:11:21 -294,Uta,Joan,660-241-5130,Female,7,67,41,2018-04-21 18:11:39,2018-07-12 17:47:45,2018-05-20 14:57:17,2018-09-19 10:15:02 -295,Elnar,Manjot,691-939-7359,Male,5,18,86,2018-11-24 20:27:24,2018-04-29 05:45:30,2018-09-06 04:15:04,2018-05-31 17:11:55 -296,Avram,Cowins,471-336-0418,Male,1,18,23,2018-10-07 19:35:52,2018-07-24 19:33:54,2018-05-09 12:43:10,2018-10-08 09:08:37 -297,Kyla,Fines,380-936-0659,Female,7,16,6,2018-12-04 05:02:51,2018-06-13 12:25:14,2018-05-15 10:17:43,2018-07-24 13:06:26 -298,Tymothy,Trevillion,740-586-6434,Male,4,99,5,2018-11-29 03:58:39,2018-07-10 01:02:27,2018-07-05 11:15:40,2018-07-17 11:17:00 -299,Rafaelita,Stiven,313-253-8470,Female,7,94,91,2018-05-11 22:09:50,2018-12-04 03:23:26,2018-06-04 22:13:06,2018-08-02 01:03:16 -300,Stanwood,Bracci,757-577-7619,Male,3,79,15,2018-06-02 08:42:52,2018-05-01 23:25:28,2018-10-27 06:54:40,2019-01-03 19:33:39 -301,Heddie,Pegden,750-484-0458,Female,3,85,74,2018-02-15 15:15:50,2018-08-13 10:31:12,2018-10-22 05:36:44,2018-07-27 21:33:04 -302,Letty,Ipplett,534-461-3389,Female,2,24,58,2018-12-30 15:03:42,2018-12-25 22:41:39,2018-08-06 08:13:19,2018-06-13 08:22:24 -303,Clarke,Buckberry,261-218-0110,Male,4,39,35,2018-11-25 02:26:48,2018-10-01 22:53:26,2019-01-01 07:32:49,2018-06-23 02:36:18 -304,Valina,Bouskill,292-930-7629,Female,2,63,32,2018-03-13 00:24:33,2018-12-08 10:39:51,2019-01-06 10:27:01,2018-07-13 00:19:13 -305,Jeth,Mosedall,326-529-0770,Male,7,44,30,2019-01-17 17:26:19,2018-03-23 23:40:12,2018-12-16 02:11:33,2018-09-08 07:21:24 -306,Mano,Komorowski,467-693-9454,Male,5,63,33,2018-12-05 21:37:13,2018-05-15 16:54:39,2018-11-21 08:06:01,2018-12-25 19:18:03 -307,Libby,Worters,651-420-4117,Female,6,62,73,2018-11-16 15:37:33,2018-04-10 08:47:08,2018-09-25 07:08:44,2018-12-20 18:11:17 -308,Ginnie,Dunnion,884-641-9401,Female,4,15,91,2018-02-25 04:25:07,2018-06-11 12:12:35,2018-12-20 05:03:34,2018-05-12 15:41:13 -309,Addi,Butterfill,454-471-6991,Female,6,45,37,2019-01-14 00:57:24,2018-10-22 12:37:53,2018-11-12 17:11:49,2018-04-13 08:39:20 -310,Eustace,Calway,260-583-1874,Male,3,98,96,2018-12-08 14:19:50,2018-03-09 04:33:52,2018-08-03 22:32:38,2018-12-17 16:12:12 -311,Greta,Tailour,864-452-3785,Female,5,63,78,2018-05-09 23:36:15,2018-09-16 21:21:51,2018-06-17 03:49:40,2018-06-25 12:40:03 -312,Nance,Ruston,102-299-0194,Female,4,66,33,2018-04-19 13:30:14,2018-08-22 20:55:14,2018-03-02 20:03:46,2018-03-23 09:40:10 -313,Harriette,Dicty,498-183-6908,Female,7,1,13,2018-12-31 04:35:08,2018-08-13 12:05:13,2018-04-30 22:42:00,2018-12-03 13:23:45 -314,Merrielle,Mapes,918-608-0262,Female,5,47,45,2018-12-16 07:21:41,2018-10-27 21:05:00,2018-03-23 14:05:12,2018-08-02 11:02:53 -315,Gris,Scurrell,392-726-5529,Male,4,71,95,2018-02-23 03:36:40,2018-04-09 20:52:39,2018-03-07 02:56:27,2018-10-22 11:26:37 -316,Novelia,Newdick,262-887-9640,Female,3,20,97,2018-05-18 12:00:02,2018-02-04 08:00:28,2018-01-28 09:59:37,2018-07-06 05:53:32 -317,Sean,Breton,304-133-1524,Male,4,91,49,2018-07-09 23:07:45,2018-10-27 06:20:49,2018-08-22 21:03:24,2018-06-13 05:33:30 -318,Winston,Springham,259-758-2788,Male,6,86,20,2018-03-20 19:07:57,2018-03-17 14:55:01,2018-08-05 20:39:20,2018-02-11 22:19:58 -319,Clemmie,Saywood,341-505-9072,Male,4,61,30,2018-06-08 02:47:28,2018-07-03 05:59:45,2018-10-28 00:28:02,2018-04-07 23:20:59 -320,Robinia,Vida,537-434-4616,Female,6,19,32,2018-05-03 10:52:24,2018-10-12 00:17:12,2018-11-27 23:47:32,2018-12-17 00:24:59 -321,Findley,Melanaphy,423-892-4436,Male,1,100,31,2018-02-04 19:41:01,2018-08-17 10:08:47,2018-11-04 14:37:46,2018-07-01 11:45:21 -322,Brooks,O'Keenan,840-842-8591,Female,4,82,84,2018-08-21 21:40:21,2018-08-31 04:07:15,2018-02-01 02:25:03,2018-12-09 10:50:21 -323,Caz,Leaf,797-315-7239,Male,6,75,22,2018-10-17 18:51:00,2018-11-22 19:03:52,2018-02-15 06:48:13,2018-04-19 22:25:23 -324,Ad,Harvey,336-617-2629,Male,4,46,5,2018-07-01 18:17:34,2018-05-24 05:31:23,2018-04-05 21:04:43,2018-07-21 06:50:26 -325,Berrie,Robardley,671-363-7428,Female,2,46,55,2018-05-14 01:56:01,2018-09-20 02:21:44,2019-01-14 15:24:34,2018-05-14 15:49:53 -326,Corliss,Halwell,154-276-2412,Female,3,63,16,2018-12-21 10:15:57,2018-11-26 00:14:11,2018-10-24 18:09:31,2018-05-27 11:41:11 -327,Carlina,Laird,357-488-1031,Female,5,59,27,2018-10-24 22:33:19,2018-10-23 00:27:39,2018-10-26 13:59:23,2018-07-19 02:41:32 -328,Rivalee,Bartolomucci,299-435-2483,Female,2,86,75,2018-06-02 23:51:58,2018-10-18 07:08:38,2019-01-11 07:36:58,2018-06-06 22:53:26 -329,Eleen,Girardy,254-561-4781,Female,6,99,58,2018-08-12 03:49:21,2019-01-04 17:17:54,2018-07-07 17:22:19,2018-02-08 00:26:15 -330,Junina,Scarisbrick,668-657-6435,Female,2,82,52,2018-10-08 01:58:04,2019-01-18 08:27:33,2018-10-13 10:36:18,2018-04-09 10:28:35 -331,Mufi,Insole,497-136-1156,Female,1,3,77,2018-07-01 05:18:23,2018-04-25 06:55:14,2018-12-23 07:35:00,2018-09-14 19:25:46 -332,Burk,Sawday,758-694-5610,Male,1,16,37,2018-05-18 17:42:50,2018-09-01 06:27:12,2018-05-06 06:30:31,2018-11-29 12:15:41 -333,Jess,Gully,330-430-8050,Female,5,2,75,2018-04-21 00:37:44,2018-06-12 02:34:07,2018-05-04 05:50:38,2018-11-25 21:02:42 -334,Dayna,Goublier,395-283-7995,Female,1,3,58,2018-03-10 13:08:34,2018-04-01 05:11:59,2018-07-17 13:31:35,2019-01-02 10:31:32 -335,Shandy,Grzegorczyk,271-236-1931,Female,6,32,34,2018-10-24 18:00:50,2018-03-17 19:11:58,2018-07-13 09:20:10,2018-07-07 03:03:48 -336,Alec,Nunnery,471-774-4412,Male,3,85,94,2018-02-15 09:59:45,2018-01-30 12:50:03,2018-03-01 13:47:47,2018-09-28 11:00:16 -337,Marti,Bedboro,799-912-3939,Female,3,88,26,2018-06-25 11:23:21,2018-10-30 08:43:52,2018-01-29 08:37:23,2018-06-06 00:28:49 -338,Malchy,Kobpac,819-568-9360,Male,4,9,14,2018-02-24 04:10:07,2018-10-05 18:35:23,2018-06-15 18:09:22,2018-11-15 08:05:17 -339,Egan,Dobbinson,366-886-7331,Male,5,43,13,2018-03-14 16:50:59,2018-08-08 23:17:17,2018-05-14 23:29:30,2018-08-19 04:54:16 -340,Maisie,Legg,700-620-6322,Female,7,85,21,2018-08-24 21:35:43,2018-08-30 17:01:27,2018-09-26 01:11:55,2018-12-29 12:04:35 -341,Fidel,Cossum,677-926-2862,Male,3,37,35,2018-07-26 05:42:32,2018-03-10 10:55:00,2018-12-22 17:20:15,2018-12-23 18:00:25 -342,Artemis,Beaton,301-959-5912,Male,7,15,26,2019-01-16 02:54:03,2018-10-28 11:08:44,2018-04-03 17:01:17,2018-04-13 04:28:34 -343,Culver,MacShirrie,126-770-5278,Male,4,28,43,2018-04-18 15:27:55,2018-08-01 10:35:51,2018-03-25 11:19:36,2018-06-01 19:23:11 -344,Jessa,Penreth,684-809-2622,Female,7,59,63,2018-08-04 18:24:37,2018-12-16 20:09:17,2018-04-11 13:14:28,2018-04-22 20:10:29 -345,Nydia,Hefner,535-519-6688,Female,3,70,29,2018-07-22 18:53:43,2018-09-02 00:30:03,2018-10-29 22:17:37,2018-05-07 11:46:24 -346,Ber,Naulty,311-674-2440,Male,6,85,70,2018-09-03 15:50:38,2018-07-04 22:30:51,2018-06-29 11:55:09,2018-05-16 11:27:56 -347,Margit,Greder,417-702-7174,Female,3,35,4,2018-04-28 01:58:34,2018-07-07 16:48:11,2018-10-08 13:45:45,2018-07-30 06:54:10 -348,Haroun,Kleynen,447-297-5270,Male,1,91,87,2018-05-14 13:40:54,2018-02-06 20:20:54,2018-04-24 19:09:01,2018-07-08 15:20:39 -349,Aylmer,Hubner,861-836-0360,Male,7,92,93,2018-02-10 06:55:44,2018-05-09 06:47:11,2018-07-09 15:46:54,2018-06-24 16:38:43 -350,Natty,Clemenzo,127-593-4758,Male,2,26,56,2018-02-01 13:02:29,2018-08-21 13:26:29,2018-12-24 09:27:03,2018-12-03 17:23:39 -351,Adriaens,Galier,704-551-4514,Female,1,64,55,2018-02-20 14:06:58,2018-09-17 22:53:46,2018-06-05 21:13:53,2018-02-25 03:51:27 -352,Raphaela,Higounet,493-470-8620,Female,7,72,86,2018-04-06 23:54:14,2018-11-09 00:01:09,2018-04-16 13:28:28,2018-10-15 09:06:54 -353,Nadia,Cureton,243-413-5780,Female,7,16,92,2018-10-20 06:35:07,2018-04-22 20:08:35,2018-04-07 15:26:39,2018-07-12 20:04:06 -354,Elliot,Bursell,301-524-4971,Male,6,59,44,2018-06-15 18:56:07,2018-03-14 21:30:37,2018-04-10 07:08:26,2018-10-03 23:57:13 -355,Miltie,Credland,318-601-5704,Male,3,5,47,2018-11-14 17:21:39,2018-04-18 22:02:24,2018-05-29 11:29:17,2018-08-28 19:44:37 -356,Andre,Dockray,631-438-3562,Male,2,1,36,2018-10-08 05:05:08,2018-10-07 10:51:00,2018-03-15 03:21:37,2018-08-31 02:22:35 -357,Marty,Vannah,864-526-0455,Male,5,32,9,2018-07-24 00:22:10,2018-08-26 02:40:08,2018-06-27 12:17:04,2018-05-23 03:24:49 -358,Timofei,Paddeley,941-127-2852,Male,4,75,28,2018-06-23 03:54:48,2018-06-16 19:23:26,2018-01-22 23:50:44,2018-09-17 11:00:42 -359,Susie,Bister,717-420-9064,Female,2,35,88,2018-08-09 20:57:50,2018-12-31 14:45:14,2018-04-16 17:44:38,2018-04-22 00:14:47 -360,Salvatore,Saenz,433-114-2254,Male,7,20,65,2018-02-14 15:55:26,2018-10-12 01:07:22,2018-11-29 04:17:51,2018-03-26 04:48:55 -361,Orin,Buttler,311-657-3727,Male,6,34,55,2018-04-05 00:11:44,2018-03-18 20:58:52,2018-09-14 10:40:07,2018-08-10 05:15:21 -362,Darbee,Garnam,956-529-4862,Male,1,75,26,2018-04-10 03:09:44,2018-06-29 01:39:43,2018-08-22 22:42:21,2018-09-15 23:23:04 -363,Lynne,Order,955-214-1203,Female,3,7,62,2018-11-15 23:40:31,2019-01-19 17:41:26,2018-02-14 19:18:25,2018-05-13 10:24:56 -364,Quinn,Hickinbottom,161-623-2666,Female,4,55,12,2018-10-24 13:06:05,2018-05-14 12:29:26,2018-10-03 06:49:08,2018-08-31 05:23:27 -365,Fionnula,Lonsbrough,271-974-9269,Female,2,24,86,2018-11-26 13:04:53,2018-04-30 00:03:02,2018-12-10 17:59:39,2018-11-02 17:56:01 -366,Blinni,Bound,991-243-7726,Female,3,34,55,2018-03-15 03:25:08,2018-07-17 18:13:35,2018-01-22 14:47:57,2018-07-03 10:31:07 -367,Joellyn,Duddin,562-523-2225,Female,3,91,7,2018-03-05 16:54:40,2018-07-11 18:24:57,2018-01-27 22:51:59,2018-06-14 14:18:32 -368,Shawn,McCandie,460-327-7535,Male,7,83,25,2018-03-04 04:08:42,2018-02-27 20:23:00,2018-05-03 04:17:09,2018-05-11 02:19:04 -369,Ferdinande,Beckinsall,555-188-2556,Female,1,23,71,2019-01-09 18:09:00,2018-11-05 21:40:44,2018-04-18 11:39:10,2018-05-26 04:58:28 -370,Dex,Hercock,124-933-7494,Male,4,66,59,2018-12-03 18:59:16,2018-08-24 14:54:44,2018-12-04 06:20:22,2018-02-12 20:16:12 -371,Auguste,Kindread,503-140-7531,Female,1,66,99,2018-09-06 02:28:55,2018-06-16 13:03:23,2018-12-18 05:54:52,2018-06-18 08:33:05 -372,Nicolle,McGarvie,977-633-1344,Female,3,80,30,2018-06-27 01:20:37,2019-01-03 07:13:42,2018-08-14 06:50:08,2018-03-11 19:28:21 -373,Meir,Poxson,979-687-3866,Male,4,95,64,2018-07-09 19:27:35,2018-05-02 06:46:01,2018-03-13 19:59:34,2018-02-14 17:37:01 -374,Aurore,Mathe,855-273-0680,Female,1,35,18,2018-12-25 19:52:38,2018-06-27 16:21:30,2018-09-05 07:24:39,2018-07-07 20:33:00 -375,Tara,Kovacs,289-503-0397,Female,1,96,65,2018-02-01 14:13:00,2018-09-13 12:52:31,2018-12-11 12:17:26,2018-01-27 11:08:31 -376,Oliver,Keitch,295-918-1908,Male,2,2,91,2018-04-25 08:41:36,2018-10-26 12:47:17,2018-09-17 07:21:55,2018-05-05 18:27:42 -377,Terrie,Van der Linde,437-439-0685,Female,5,40,86,2018-06-13 19:39:12,2018-09-27 20:24:10,2018-11-29 11:48:24,2018-08-03 10:38:12 -378,Dickie,Rhymes,812-341-6120,Male,1,20,77,2018-02-19 18:11:07,2018-07-04 05:36:40,2018-11-14 00:59:02,2018-11-24 17:13:06 -379,Lynette,Hadland,438-785-0370,Female,1,49,29,2018-04-01 23:24:07,2018-08-21 14:23:03,2018-05-13 18:28:29,2018-12-12 21:59:32 -380,Blanch,Smythin,325-174-1975,Female,1,13,78,2018-11-04 02:34:45,2018-10-22 10:28:57,2018-09-14 10:12:56,2018-10-23 19:59:00 -381,Camellia,Rickeard,681-592-9848,Female,5,53,4,2018-08-25 10:15:49,2018-04-05 06:53:58,2018-02-17 08:17:38,2018-09-11 01:16:02 -382,Muire,Minto,821-124-3681,Female,2,92,71,2018-10-16 14:05:30,2018-05-21 07:22:46,2018-10-26 09:45:10,2018-09-07 09:40:50 -383,Franz,Goullee,650-849-7354,Male,1,19,86,2018-07-14 09:46:05,2018-02-20 08:15:57,2018-06-05 10:37:07,2018-06-14 13:33:38 -384,Ardath,Salaman,542-596-2751,Female,6,3,76,2018-06-07 05:11:01,2018-09-17 09:28:04,2018-04-10 13:00:45,2018-11-27 21:22:09 -385,Graeme,Balshen,286-335-9657,Male,3,44,17,2018-07-18 15:23:20,2018-03-28 07:57:47,2018-11-12 18:58:13,2018-10-11 13:56:49 -386,Lola,Ainsbury,875-341-9340,Female,5,48,71,2018-03-12 03:05:33,2018-11-01 02:55:54,2018-02-15 04:37:51,2018-05-27 04:11:38 -387,Marchelle,Reynoollds,771-436-6596,Female,3,15,98,2018-07-21 06:24:35,2018-10-15 12:19:29,2018-10-21 17:19:01,2018-12-07 00:08:23 -388,Ruddie,Ginger,639-798-1010,Male,6,53,88,2018-10-27 08:25:56,2018-08-05 15:50:59,2018-05-26 08:38:25,2018-03-12 08:36:31 -389,Kathrine,Guiu,822-798-6112,Female,2,31,32,2018-07-21 23:07:18,2018-04-23 18:22:19,2018-12-14 04:50:14,2018-12-17 05:07:54 -390,Bobbie,Peet,321-618-4507,Male,6,40,10,2018-12-07 06:56:32,2018-05-26 07:54:01,2018-02-12 22:14:19,2018-03-02 09:00:13 -391,Waylon,Brignall,721-399-8864,Male,2,29,55,2018-03-05 23:01:40,2018-02-12 20:24:53,2018-10-03 20:50:03,2018-05-27 20:39:09 -392,Randene,M'Chirrie,274-833-8717,Female,7,5,29,2018-11-09 00:26:39,2018-05-08 06:51:45,2018-10-07 04:03:07,2018-07-11 15:11:59 -393,Venus,Burgise,888-311-2349,Female,5,49,10,2018-01-31 18:35:34,2018-06-11 17:52:44,2019-01-18 10:15:45,2018-01-29 11:19:22 -394,Patton,Atkirk,887-990-8528,Male,3,14,48,2018-09-02 04:16:21,2018-12-07 12:14:18,2018-09-11 02:15:29,2018-05-31 08:26:51 -395,Ethelda,Sclater,557-210-5737,Female,2,98,59,2018-10-08 02:45:35,2018-03-07 11:02:12,2018-03-09 22:30:08,2018-07-15 06:00:38 -396,Kerry,Mascall,178-504-3458,Male,3,83,65,2018-08-12 19:58:08,2018-07-06 21:04:42,2018-07-15 00:45:35,2018-11-11 14:30:45 -397,Kelsey,Bohills,477-245-9384,Female,4,23,40,2018-08-31 00:28:52,2018-04-23 15:33:52,2018-08-22 04:21:43,2018-12-27 08:56:06 -398,Brennen,Ahrendsen,666-924-8234,Male,3,47,82,2018-12-10 22:01:21,2018-11-13 15:03:16,2018-01-21 19:47:47,2018-07-28 11:39:10 -399,Carmelina,Mountcastle,871-952-4482,Female,6,14,79,2018-05-25 02:01:07,2018-05-15 19:52:19,2018-07-16 23:16:38,2018-05-22 23:32:19 -400,Dale,Eltone,663-128-1228,Male,1,80,26,2018-10-13 23:51:08,2018-02-19 19:49:01,2018-01-27 11:58:54,2018-07-02 14:05:44 -401,Brianna,Beauchop,922-667-1003,Female,5,12,12,2018-11-05 20:21:33,2018-06-24 22:17:20,2018-06-12 04:34:37,2018-07-09 06:48:22 -402,Guillema,MacKibbon,164-334-7955,Female,3,6,56,2018-06-24 21:01:56,2018-08-15 08:52:58,2018-07-21 21:42:02,2018-02-26 08:29:48 -403,Ettore,Brailsford,231-820-9624,Male,1,92,34,2019-01-17 05:37:42,2018-06-30 12:14:43,2018-04-11 20:55:10,2018-01-21 17:40:14 -404,Shawn,M'cowis,293-256-5912,Male,7,12,87,2018-02-07 20:27:20,2018-08-07 19:48:03,2019-01-01 18:32:27,2018-08-31 20:41:20 -405,Lolly,Rankcom,743-968-5736,Female,2,17,31,2018-11-03 21:37:26,2018-07-18 08:15:01,2018-12-28 23:22:36,2018-09-04 02:20:01 -406,Jeffry,Dingle,194-835-0524,Male,1,6,58,2018-10-21 16:42:07,2018-06-01 21:41:20,2018-06-17 04:34:34,2018-12-29 19:09:29 -407,Marcelle,Molder,766-356-8780,Female,3,85,45,2018-10-18 11:17:27,2018-10-17 20:18:59,2018-09-05 10:30:56,2018-08-10 06:31:09 -408,Binni,Ferney,214-353-4132,Female,6,6,98,2018-02-20 07:18:40,2018-06-24 11:40:51,2018-12-13 02:29:35,2018-10-04 10:52:07 -409,Pat,Whenham,885-713-4885,Male,7,64,5,2018-10-29 12:39:59,2018-11-08 18:24:31,2018-04-17 11:10:35,2018-10-13 22:45:02 -410,Towney,Mizzi,602-556-2702,Male,7,40,94,2018-03-02 22:07:54,2018-08-30 01:11:53,2018-12-21 22:30:09,2018-04-08 21:36:17 -411,Cecil,Bickerdike,577-476-2260,Male,2,2,65,2018-02-25 13:53:37,2018-02-13 04:10:01,2018-05-27 20:30:46,2018-04-11 01:36:56 -412,Franciskus,Thomlinson,539-919-8711,Male,4,69,14,2018-11-12 12:18:44,2018-02-07 14:40:19,2018-08-23 04:04:48,2018-02-11 00:53:06 -413,Valentino,Machent,281-308-6846,Male,6,76,23,2018-10-04 13:04:01,2018-09-13 11:56:13,2018-06-25 21:50:15,2018-06-03 04:08:35 -414,Evelin,Harpham,287-743-1401,Male,7,1,5,2018-06-15 01:25:03,2018-05-17 06:35:54,2018-10-22 08:02:14,2018-08-25 01:58:06 -415,Cassandre,Crum,685-341-7481,Female,3,25,79,2018-07-29 10:09:33,2018-01-30 23:16:22,2019-01-13 15:40:35,2018-07-14 15:57:17 -416,Loren,Leschelle,321-405-9197,Male,3,26,13,2018-04-29 06:52:46,2018-06-21 13:57:41,2018-07-30 18:39:32,2018-09-01 00:31:38 -417,Ilaire,Plose,336-197-4797,Male,1,53,50,2018-07-01 07:52:56,2018-10-30 02:18:43,2018-08-21 23:46:29,2018-08-07 13:03:11 -418,Hannis,Issacof,315-716-3782,Female,2,99,85,2019-01-19 10:40:46,2018-04-26 10:04:56,2018-11-15 02:42:19,2018-08-21 16:50:00 -419,Meggie,Beeke,556-174-4615,Female,1,13,85,2018-03-05 16:12:22,2018-09-19 22:31:27,2018-12-04 04:01:57,2018-04-14 20:14:40 -420,Clemens,Leades,183-447-0091,Male,7,98,12,2018-06-18 06:17:24,2018-04-10 09:59:20,2018-03-20 22:45:02,2018-05-10 17:11:21 -421,Dennis,Chifney,196-548-2180,Male,7,75,98,2018-12-09 00:19:15,2018-06-16 10:29:26,2018-09-12 03:26:46,2018-10-24 16:42:20 -422,Yuri,Laytham,783-967-4260,Male,7,72,60,2018-01-28 20:33:42,2018-11-10 15:59:58,2018-05-07 10:19:43,2018-03-08 01:03:28 -423,Rosaline,Gibbins,376-974-7633,Female,3,22,56,2018-06-26 01:09:00,2018-10-30 23:51:58,2018-07-31 09:43:54,2018-11-23 12:00:53 -424,Yule,Hadwick,795-430-0875,Male,2,99,87,2018-03-09 17:35:22,2018-07-18 20:38:41,2018-08-29 09:29:40,2018-12-12 13:21:09 -425,Albertine,Bernlin,415-360-6554,Female,2,40,34,2018-05-24 10:27:28,2018-10-31 10:36:51,2018-07-04 15:40:42,2018-05-23 02:22:57 -426,Donnell,Stammler,944-379-5489,Male,4,59,41,2018-06-28 16:01:29,2018-05-18 12:55:36,2018-03-07 06:37:32,2018-03-25 12:44:31 -427,Brant,Athy,987-827-3040,Male,5,52,7,2018-01-24 14:17:54,2018-10-06 04:10:01,2018-02-21 04:02:17,2018-05-27 20:44:43 -428,Rose,Barnaby,789-522-4912,Female,7,31,46,2018-11-30 14:09:29,2018-11-06 16:28:33,2018-12-13 23:06:42,2018-09-12 17:39:14 -429,Valina,Ply,729-373-7904,Female,3,65,27,2018-11-15 05:26:26,2018-11-28 15:21:13,2018-05-01 00:56:08,2018-02-05 07:37:50 -430,Berkley,Ferry,484-341-3250,Male,6,47,48,2018-07-26 11:27:11,2018-03-05 19:23:46,2018-08-05 08:09:19,2018-05-30 08:43:28 -431,Jarred,Cunnington,995-170-5820,Male,4,6,1,2018-07-12 11:36:19,2018-10-19 05:16:25,2018-06-28 12:38:16,2018-10-08 06:52:46 -432,Marys,Audry,449-892-8929,Female,2,25,86,2018-11-21 14:36:19,2018-11-26 13:31:27,2018-03-28 15:22:34,2018-01-28 08:07:21 -433,Coreen,Vinnicombe,267-868-6003,Female,6,64,45,2018-10-19 22:09:21,2018-12-08 23:41:39,2018-08-16 05:46:08,2018-11-18 14:46:52 -434,Spense,Sarfati,945-773-9494,Male,4,6,3,2018-03-18 13:44:54,2018-09-04 10:40:58,2019-01-15 18:23:55,2018-06-07 16:02:39 -435,Chandra,Burgin,130-446-4470,Female,4,95,96,2018-09-27 16:48:00,2018-05-20 20:44:56,2018-11-23 04:46:53,2018-01-31 16:31:14 -436,Tomas,Currin,756-279-5643,Male,4,41,4,2018-11-18 07:22:02,2018-11-14 14:03:44,2018-09-18 12:36:39,2018-06-05 09:28:43 -437,Conway,Wesson,754-769-3550,Male,1,52,46,2019-01-02 08:07:04,2018-02-14 00:52:12,2018-02-11 10:52:29,2018-02-16 15:31:25 -438,Stefa,Meese,610-105-6841,Female,7,39,28,2018-04-28 02:21:35,2018-10-21 01:33:19,2018-11-23 21:00:01,2019-01-10 08:36:35 -439,Theadora,Ubee,609-368-9924,Female,6,42,5,2018-04-22 17:02:17,2018-08-21 16:33:25,2018-08-25 04:12:23,2018-02-16 01:13:06 -440,Virginia,Flawn,711-955-7169,Female,3,20,19,2018-08-16 18:01:55,2018-04-18 10:08:19,2018-01-27 09:38:48,2018-05-29 02:29:24 -441,Marv,Mummery,820-192-1452,Male,5,75,95,2018-05-29 15:29:25,2018-03-19 14:00:54,2018-01-22 01:15:38,2018-08-17 08:36:00 -442,Fulton,Zelake,283-584-1765,Male,7,4,3,2019-01-13 23:55:52,2018-08-19 22:29:51,2018-04-16 02:28:54,2018-03-16 16:58:02 -443,Guillemette,Ferretti,776-408-8649,Female,3,24,79,2018-07-31 04:43:48,2018-08-04 15:42:51,2018-04-11 16:00:11,2019-01-07 22:56:20 -444,Egbert,Dureden,698-387-7895,Male,7,54,6,2018-02-25 13:06:41,2018-01-28 14:50:49,2019-01-01 05:38:28,2018-06-19 00:46:05 -445,Trumaine,Canniffe,563-399-5639,Male,1,79,93,2018-11-08 00:30:08,2018-04-07 04:15:13,2018-03-30 14:48:19,2018-04-10 23:29:00 -446,Burr,Goves,451-577-7757,Male,1,27,72,2018-03-16 22:57:50,2018-02-04 21:42:45,2018-06-27 04:37:53,2019-01-16 15:20:56 -447,Juditha,Luebbert,958-685-2937,Female,4,36,87,2018-08-30 23:36:55,2018-06-22 07:04:37,2018-08-23 08:03:08,2018-03-28 04:50:57 -448,Lilly,Smewings,246-392-5467,Female,7,61,65,2018-06-02 21:56:15,2018-09-21 22:08:51,2018-11-29 20:26:34,2018-09-09 13:36:55 -449,Beckie,Curd,239-783-9576,Female,2,18,69,2018-11-20 04:10:54,2018-07-09 08:10:52,2018-03-19 21:04:09,2018-06-19 12:09:53 -450,Cristie,Edmonds,203-875-9153,Female,6,75,68,2018-11-16 10:01:12,2018-08-05 10:10:51,2019-01-11 05:06:49,2018-02-27 23:12:37 -451,Richmound,Machans,259-901-3247,Male,6,7,81,2019-01-12 15:06:01,2018-08-04 16:50:11,2018-12-30 16:16:18,2018-04-24 01:22:55 -452,Murial,Heiss,686-151-1653,Female,6,62,44,2018-05-18 13:49:57,2018-07-31 04:58:55,2018-02-26 22:38:19,2018-06-03 12:20:39 -453,Leonhard,O'Hear,205-401-7116,Male,5,3,1,2018-12-01 20:43:01,2018-06-19 12:45:05,2018-06-17 21:31:22,2018-12-29 20:41:28 -454,Kin,Yakovlev,952-369-5846,Male,1,39,38,2018-03-05 07:22:54,2018-06-20 14:24:43,2018-12-24 17:56:41,2018-07-13 07:55:25 -455,Debee,Fransinelli,230-272-0203,Female,3,64,60,2018-03-28 12:01:56,2018-09-10 13:03:46,2018-05-10 07:50:05,2018-08-10 09:35:31 -456,Nappie,Seaton,809-725-5784,Male,1,67,52,2018-09-13 00:18:51,2018-07-10 10:46:33,2018-04-19 00:56:44,2018-06-17 12:12:31 -457,Adelheid,Wanjek,795-641-9749,Female,1,21,97,2018-03-09 22:00:35,2018-08-09 22:29:44,2018-05-22 14:09:09,2018-03-19 18:49:28 -458,Jeannette,Glanville,377-671-9024,Female,7,84,44,2018-10-05 10:17:32,2018-04-06 12:22:12,2018-05-10 03:19:20,2018-09-30 04:25:01 -459,Adrianna,Blezard,773-598-7742,Female,6,89,62,2018-04-25 21:46:25,2018-05-26 05:44:50,2018-07-14 12:21:26,2018-09-28 10:26:06 -460,Gloria,Keelin,120-823-7944,Female,4,9,68,2018-07-13 21:08:25,2018-03-14 15:55:09,2018-04-02 02:08:40,2019-01-09 11:56:17 -461,Becki,Gatling,845-125-4361,Female,4,1,71,2018-06-24 20:47:16,2018-08-28 04:29:09,2018-05-06 23:04:29,2018-06-01 05:37:42 -462,Gabriellia,Lobley,844-697-7445,Female,2,89,99,2018-09-15 13:57:53,2018-06-14 14:04:36,2018-12-09 22:49:10,2018-02-12 02:07:35 -463,Aaren,McVie,973-286-0455,Female,4,67,14,2018-10-24 23:51:19,2018-04-28 04:48:26,2018-08-01 00:36:09,2018-07-03 13:36:32 -464,Barbara,Luddy,270-772-2682,Female,6,31,58,2018-03-18 11:34:08,2018-11-10 07:14:55,2018-12-12 21:20:10,2018-08-31 00:15:05 -465,Ibrahim,Went,494-197-0863,Male,3,35,42,2018-10-27 09:01:43,2018-05-24 01:03:27,2018-11-12 00:22:15,2018-03-28 09:23:37 -466,Sherry,Meert,142-492-1426,Female,7,30,41,2018-09-05 17:22:28,2019-01-11 02:43:23,2018-08-24 21:28:14,2018-03-23 18:02:50 -467,Marietta,Caulwell,931-150-2069,Male,5,5,93,2018-10-20 06:55:32,2018-08-24 12:59:12,2018-02-05 08:19:35,2018-01-23 22:03:22 -468,Kaiser,Gossage,250-466-8664,Male,6,23,93,2018-08-30 13:38:00,2018-10-27 22:45:24,2018-06-20 08:32:02,2018-01-25 09:32:34 -469,Margie,Fenelon,570-190-5079,Female,7,83,33,2018-12-11 01:27:54,2018-02-18 13:46:59,2018-09-23 21:24:36,2018-09-12 19:05:02 -470,Alvin,Stallan,451-964-7576,Male,6,25,97,2018-10-10 09:53:05,2018-05-12 18:37:24,2018-04-16 18:11:41,2018-12-06 13:37:08 -471,Corbin,Lamport,950-956-7283,Male,2,80,15,2018-10-08 17:14:14,2018-12-03 17:06:55,2018-08-04 22:29:17,2018-12-03 12:04:13 -472,Imelda,Crat,346-373-3643,Female,3,60,21,2018-01-25 18:42:27,2018-02-02 11:29:22,2018-05-12 06:06:53,2018-05-24 14:31:31 -473,Kala,Aikenhead,665-137-0705,Female,3,5,83,2018-03-11 01:11:04,2019-01-18 14:28:39,2018-04-20 06:28:31,2018-06-21 01:18:27 -474,Bastien,Lavell,325-523-0512,Male,7,87,91,2019-01-14 08:13:00,2018-06-08 18:23:51,2018-12-02 08:49:53,2018-12-06 00:24:41 -475,Muriel,Cannon,174-249-0377,Female,7,11,49,2018-06-09 02:06:14,2018-05-19 03:47:34,2018-02-15 07:14:49,2018-03-19 22:10:50 -476,Duane,Presland,616-278-2852,Male,6,49,20,2018-02-10 17:43:55,2018-02-21 00:21:21,2018-10-01 16:17:22,2018-04-06 08:15:06 -477,Emmerich,Baildon,408-829-6965,Male,1,13,29,2018-11-08 20:46:52,2018-07-04 14:45:10,2018-05-22 03:30:35,2018-07-26 23:46:21 -478,El,Seabourne,745-257-4885,Male,6,13,60,2019-01-05 01:40:08,2019-01-07 01:30:58,2018-08-24 00:13:56,2018-08-20 02:39:03 -479,Rivalee,Robertsson,882-741-1264,Female,3,36,70,2018-10-07 07:27:41,2018-05-13 11:32:58,2018-12-07 16:22:21,2018-12-12 19:59:38 -480,Alexis,Lapping,852-596-1033,Female,1,48,44,2018-01-30 22:17:04,2018-08-30 00:34:37,2018-11-04 00:05:38,2018-12-11 02:01:32 -481,Francine,Slatcher,134-351-4974,Female,1,56,91,2018-12-25 00:49:27,2018-10-11 02:42:45,2018-10-09 12:40:08,2018-09-01 13:26:34 -482,Kristen,Petters,440-151-8788,Female,7,19,49,2018-02-17 01:34:14,2018-10-28 03:18:55,2018-09-13 14:14:48,2018-01-22 12:26:05 -483,Riobard,Helin,217-648-4050,Male,6,3,62,2019-01-08 20:13:28,2018-07-10 21:50:12,2018-02-14 10:54:30,2018-07-10 15:21:36 -484,Jere,Marrison,125-522-1752,Male,5,77,48,2018-03-27 12:35:57,2018-08-11 12:06:00,2018-07-10 09:48:33,2018-11-12 18:44:01 -485,Sheila,Edens,296-894-3200,Female,3,99,67,2018-09-02 05:54:01,2018-03-13 04:55:49,2019-01-07 04:42:32,2018-12-12 03:46:51 -486,Georgy,Sallings,860-751-2558,Male,5,42,98,2018-03-04 09:36:14,2018-12-18 03:43:57,2018-05-26 16:22:04,2018-09-02 12:56:41 -487,Marcellina,Ledgister,286-469-6281,Female,6,17,35,2018-07-04 19:56:40,2018-04-13 18:15:53,2018-06-22 16:02:20,2018-02-12 13:24:14 -488,Terra,Dodamead,913-630-9923,Female,1,82,1,2018-12-11 19:54:27,2018-12-11 20:39:38,2018-03-28 15:51:45,2018-08-25 04:08:21 -489,Alia,Morrel,431-923-1395,Female,7,7,38,2018-05-24 06:33:39,2018-03-16 20:23:58,2018-09-11 05:45:02,2018-02-10 15:26:52 -490,Henri,Cullivan,513-315-1874,Male,2,7,65,2018-02-21 12:36:28,2018-02-28 14:01:27,2018-11-04 00:27:37,2018-06-18 18:54:48 -491,Josie,Langrish,674-305-6918,Female,2,79,72,2018-07-26 02:09:25,2018-12-03 14:04:40,2018-10-18 18:24:47,2018-09-01 09:38:00 -492,Brittany,Redwall,197-871-1265,Female,2,98,39,2019-01-15 16:02:18,2018-07-28 14:31:51,2019-01-05 12:31:54,2018-02-17 02:21:53 -493,Phillie,Caulket,276-222-0475,Female,2,92,27,2018-10-19 10:58:15,2018-10-01 05:23:18,2018-10-31 20:41:31,2018-01-23 21:09:13 -494,Clair,Ring,789-696-3129,Female,1,60,89,2018-12-15 04:12:43,2018-03-14 18:18:51,2018-02-01 04:15:54,2018-05-24 23:34:59 -495,Allis,Sunner,601-505-2836,Female,3,37,9,2018-03-16 18:20:34,2018-10-03 23:52:03,2018-09-09 20:19:13,2018-09-12 13:27:03 -496,Madeleine,Haitlie,956-801-4088,Female,4,55,99,2018-05-23 09:24:40,2018-09-25 14:13:54,2018-12-07 06:01:21,2018-08-05 05:36:15 -497,Cirillo,Gronav,571-141-3522,Male,5,81,10,2018-10-11 20:52:40,2018-02-21 03:11:05,2018-09-16 08:35:42,2018-03-26 20:16:43 -498,Arturo,Cowitz,923-926-3273,Male,3,93,12,2018-11-22 05:37:54,2018-02-17 15:11:34,2018-03-31 00:15:46,2018-08-03 14:49:13 -499,Haley,Cartmill,139-891-8155,Female,2,79,56,2018-10-28 03:24:17,2018-09-26 03:42:15,2018-09-16 20:27:43,2018-10-21 06:51:02 -500,Caddric,Eim,386-491-4555,Male,4,88,81,2018-07-27 07:41:11,2018-11-06 13:25:15,2018-04-30 01:01:46,2018-10-27 13:14:40 -501,Sargent,Beart,958-909-4690,Male,1,44,9,2018-07-18 12:02:07,2018-07-23 05:06:07,2018-07-16 15:25:53,2018-08-26 13:12:34 -502,Dane,Gason,502-241-7120,Male,6,79,58,2018-11-17 04:47:55,2018-07-17 16:19:37,2018-12-02 13:39:55,2018-08-07 15:28:47 -503,Humfried,Canelas,275-518-1730,Male,3,82,87,2018-02-02 11:38:29,2018-10-18 04:09:03,2018-02-04 00:47:16,2018-07-23 00:37:30 -504,Sam,Freiberg,757-773-6048,Female,5,89,31,2018-12-01 22:51:12,2018-06-29 03:50:29,2018-07-25 14:13:37,2018-06-11 22:59:09 -505,Goddart,Crossgrove,820-183-6322,Male,3,41,25,2018-11-22 23:25:36,2018-01-29 08:12:28,2018-09-24 21:36:56,2018-03-04 00:40:37 -506,Joela,Bondesen,856-474-9498,Female,5,71,97,2018-05-08 08:23:42,2018-12-20 17:54:27,2018-08-13 11:11:11,2018-08-06 19:06:58 -507,Harrie,Nendick,943-670-9341,Female,3,66,6,2018-05-03 20:18:57,2018-11-06 16:35:09,2018-07-18 17:01:56,2018-03-29 06:23:00 -508,Farlay,Manderson,834-991-0018,Male,4,44,9,2018-08-16 12:51:08,2018-09-19 19:35:31,2018-09-28 07:49:16,2018-11-26 04:15:32 -509,Warren,Pegram,815-768-9711,Male,1,2,70,2018-11-03 16:08:12,2018-09-27 19:07:58,2018-02-15 09:57:42,2018-02-04 05:33:01 -510,Mylo,Haskayne,624-512-7407,Male,3,71,28,2018-11-05 07:00:48,2018-08-22 23:42:06,2018-10-13 09:30:14,2018-12-17 14:14:01 -511,Giacomo,Halsho,976-203-6826,Male,2,59,100,2018-04-11 12:30:03,2018-05-06 11:36:27,2019-01-03 21:44:26,2018-06-13 06:17:36 -512,Aloysia,Stuchburie,466-684-9228,Female,7,15,94,2018-05-05 20:22:16,2018-05-06 16:01:54,2018-11-13 03:57:27,2018-08-05 07:41:19 -513,Brit,Glentz,283-639-7723,Male,4,5,19,2018-04-07 12:25:00,2018-09-26 07:12:01,2018-06-05 14:15:20,2018-06-02 16:59:25 -514,Maddi,Kerfoot,543-438-1531,Female,3,16,67,2018-06-30 07:58:22,2018-12-16 23:14:43,2019-01-03 10:51:10,2018-09-10 17:15:42 -515,Ruy,Townson,801-852-6590,Male,1,31,55,2018-02-22 06:06:31,2019-01-20 20:38:59,2018-09-28 17:23:51,2018-09-30 05:48:30 -516,Rawley,Tatum,634-340-1379,Male,5,32,35,2018-02-14 04:43:24,2018-06-30 10:54:44,2018-11-22 11:23:10,2018-03-01 16:10:00 -517,Teddy,Pickford,404-551-3889,Male,2,82,54,2018-12-29 05:25:46,2018-04-13 05:46:18,2018-10-11 18:14:38,2018-11-07 08:35:59 -518,Randolph,Stealfox,750-802-5940,Male,3,91,11,2018-04-03 20:00:54,2018-11-29 19:15:41,2018-02-20 09:38:24,2018-03-25 15:38:52 -519,Filmer,Sumption,833-713-4339,Male,2,2,8,2018-01-26 04:26:32,2018-03-08 20:23:21,2018-07-27 10:41:05,2018-11-04 20:18:36 -520,Barbee,Salvador,475-228-6268,Female,1,13,71,2018-10-24 00:02:01,2018-01-21 21:29:45,2018-07-03 13:31:36,2019-01-07 14:59:36 -521,Valina,Spillett,588-767-5376,Female,5,27,8,2018-03-03 01:39:51,2018-01-28 01:22:11,2018-04-22 03:30:25,2018-03-08 04:45:22 -522,Taber,Faunt,428-608-8317,Male,5,46,93,2018-06-09 11:17:55,2018-09-01 01:34:32,2018-02-19 13:01:55,2018-08-15 06:00:48 -523,Lilas,Siemons,680-968-7597,Female,6,31,25,2018-11-26 22:08:43,2018-02-15 23:08:21,2018-12-26 05:40:57,2018-02-22 02:08:43 -524,Spence,Vosper,720-164-0499,Male,2,37,73,2018-01-31 08:38:29,2018-07-08 11:20:30,2018-10-31 09:36:46,2018-08-26 13:46:48 -525,Robinett,Le Breton De La Vieuville,690-247-8261,Female,6,47,79,2018-04-02 23:29:51,2018-04-26 14:43:49,2018-09-29 04:02:35,2018-02-22 14:19:00 -526,Pia,Favell,689-639-0553,Female,5,96,86,2018-09-27 09:10:13,2018-02-18 08:18:56,2018-09-16 10:20:42,2018-09-19 19:46:37 -527,Jody,Persich,875-503-4255,Female,5,1,63,2018-12-28 04:07:08,2018-02-19 06:37:40,2018-11-08 19:30:56,2018-04-16 19:36:13 -528,Mimi,Meach,664-906-5485,Female,3,46,59,2018-05-16 02:36:27,2018-02-06 06:52:54,2018-03-16 20:22:46,2018-12-24 10:29:20 -529,Nyssa,Hillborne,493-931-8360,Female,6,70,73,2018-12-08 00:07:34,2018-01-31 21:28:10,2018-04-14 12:33:22,2018-12-18 17:12:16 -530,Chrissie,Jagger,284-506-7117,Male,7,89,53,2018-03-21 21:11:02,2018-09-10 16:42:15,2019-01-17 21:11:31,2018-10-26 07:01:07 -531,Jacqueline,Hebblewhite,313-329-3935,Female,6,70,40,2018-07-29 17:39:44,2018-08-26 14:11:15,2018-12-18 12:39:49,2018-09-04 11:21:47 -532,Gunilla,Frarey,231-521-7913,Female,7,3,44,2018-03-05 06:12:04,2018-06-21 16:09:41,2018-01-27 13:30:18,2018-02-28 16:14:26 -533,Eleni,Fassum,149-906-0502,Female,1,40,27,2018-11-17 06:56:45,2018-06-22 05:04:09,2018-05-07 22:21:42,2018-12-21 21:39:19 -534,Kerr,Kelshaw,729-673-6161,Male,6,94,93,2018-11-23 00:31:03,2018-12-09 03:46:43,2018-02-22 16:54:17,2018-09-09 11:05:13 -535,Lisha,Curgenven,874-739-3351,Female,4,97,18,2018-02-20 18:11:36,2018-10-17 06:38:52,2018-12-26 02:40:15,2018-02-13 09:24:09 -536,Bevin,Jakeman,676-751-7045,Male,1,87,71,2018-02-20 13:08:18,2018-11-21 06:36:13,2018-09-22 09:22:49,2018-10-09 06:21:12 -537,Harland,Sidney,139-828-9659,Male,6,23,85,2018-09-18 02:15:28,2018-04-10 06:49:54,2018-12-05 20:08:51,2018-08-05 09:53:26 -538,Rori,Seys,180-907-6460,Female,5,27,23,2018-02-22 03:55:23,2018-08-01 08:40:28,2018-05-15 12:42:51,2018-10-22 00:24:22 -539,Baxy,Marjanski,580-759-7206,Male,4,95,30,2018-09-01 14:33:22,2018-12-14 23:01:00,2018-12-02 00:20:18,2018-08-25 13:54:47 -540,Martie,Dearsley,102-718-1278,Male,7,89,15,2018-03-15 10:57:25,2018-03-03 03:48:25,2018-07-12 03:48:36,2018-07-22 13:18:47 -541,Erin,Ruddick,969-222-3994,Male,1,97,56,2018-05-18 05:27:05,2018-02-23 12:22:10,2018-04-13 08:34:06,2018-11-25 15:51:09 -542,Tome,Lorne,842-424-5954,Male,4,58,76,2018-12-11 13:20:20,2018-07-29 14:26:59,2018-08-12 08:27:28,2018-04-03 13:46:52 -543,Nell,Borkin,228-448-5895,Female,1,3,1,2018-11-30 16:38:15,2018-07-27 09:33:59,2018-08-23 02:00:10,2018-09-28 00:28:48 -544,Teirtza,Springthorp,538-731-0003,Female,4,8,3,2018-03-28 08:52:40,2018-11-03 18:14:45,2019-01-02 06:05:23,2018-03-22 22:01:00 -545,Arlina,Feighney,977-853-6783,Female,1,18,40,2018-02-08 21:04:46,2018-03-02 23:43:32,2018-03-05 13:33:15,2018-05-12 17:12:38 -546,Melosa,Gifford,804-769-4197,Female,7,55,98,2018-02-04 08:50:49,2018-10-10 06:22:51,2018-06-01 01:45:08,2018-12-24 03:31:15 -547,Charin,Petrello,597-441-0171,Female,6,67,18,2018-09-10 08:11:34,2018-03-15 18:44:45,2018-10-22 23:24:05,2018-07-31 01:37:48 -548,Cristian,Stute,223-959-7392,Male,2,5,69,2018-11-01 17:37:10,2018-05-25 14:21:07,2018-10-09 08:14:38,2018-06-29 13:27:34 -549,Velvet,Morison,848-981-1316,Female,1,20,17,2018-02-14 02:16:51,2018-08-25 23:57:58,2018-04-20 10:47:18,2018-04-04 19:16:45 -550,Vivienne,Taillard,392-626-2926,Female,2,38,47,2019-01-20 11:03:04,2018-06-11 20:42:47,2018-05-13 17:10:39,2018-06-02 20:11:46 -551,Zach,Vials,406-733-0058,Male,1,28,88,2018-12-14 14:36:03,2018-02-25 21:52:58,2018-10-17 02:37:28,2018-02-05 17:26:59 -552,Christie,De Caville,268-836-0470,Male,6,28,91,2018-11-26 14:01:43,2018-06-27 22:05:24,2018-11-10 16:11:15,2018-07-20 12:01:34 -553,Dulce,Walesby,578-217-3628,Female,6,83,40,2018-04-12 08:24:30,2018-10-07 09:32:47,2018-04-10 12:21:16,2018-06-04 11:56:13 -554,Shermy,Martinek,627-924-0370,Male,1,54,86,2018-09-02 00:41:57,2018-09-16 02:42:47,2018-05-10 03:54:12,2018-11-14 17:54:47 -555,Curcio,Cudworth,355-447-1790,Male,2,43,26,2018-05-31 02:31:23,2018-11-18 23:47:19,2018-02-26 10:49:12,2018-08-22 04:36:14 -556,Newton,Zuan,810-756-5844,Male,5,85,20,2018-03-09 16:07:56,2018-10-12 16:45:42,2018-05-02 19:27:29,2018-04-21 12:37:09 -557,Gina,Keyho,566-476-0815,Female,4,8,83,2018-09-21 17:12:16,2018-03-20 10:13:51,2018-05-22 10:29:45,2018-09-23 17:23:36 -558,Emmanuel,Beacham,923-766-7627,Male,4,15,10,2018-10-14 04:16:42,2018-12-12 21:49:16,2018-04-06 14:49:00,2018-02-10 06:29:37 -559,Mel,Deniseau,577-125-8484,Female,3,12,6,2018-06-01 18:43:13,2018-11-09 14:24:38,2018-07-01 23:11:43,2018-11-24 10:28:42 -560,Deena,Knutton,544-886-5072,Female,2,98,57,2018-02-11 05:11:20,2018-08-19 14:06:35,2018-09-06 12:12:59,2018-10-07 13:53:21 -561,Flossy,Antonacci,108-542-7284,Female,2,20,36,2018-05-20 08:28:31,2018-04-01 14:07:20,2018-07-23 02:08:55,2018-08-29 00:40:11 -562,Gabriela,Gravy,565-992-0341,Female,3,54,70,2018-03-14 07:29:51,2018-11-24 05:40:57,2018-06-24 11:53:15,2018-12-13 15:23:43 -563,Emelen,Healey,821-210-6931,Male,7,16,79,2018-03-02 11:53:31,2018-07-04 07:43:45,2018-08-20 22:28:53,2018-08-20 07:13:10 -564,Anne-marie,Peatman,431-777-2495,Female,4,38,1,2018-02-28 18:38:14,2018-08-28 18:58:41,2018-09-01 22:16:42,2018-11-14 23:08:02 -565,Raymond,Truelock,671-694-3305,Male,5,20,76,2018-11-19 18:58:41,2018-10-26 03:22:35,2018-10-13 10:05:37,2018-10-20 00:19:39 -566,Gabriel,Matlock,704-620-9706,Female,1,29,24,2018-07-24 15:56:02,2018-12-23 10:03:48,2018-07-13 22:41:53,2018-06-12 13:42:42 -567,Leontine,Kollasch,793-692-0103,Female,4,68,78,2018-05-05 06:54:44,2018-07-26 19:41:30,2018-04-16 00:46:38,2018-11-20 19:18:17 -568,Amelina,Gullick,674-849-6707,Female,2,75,43,2019-01-01 12:18:11,2018-02-18 10:50:33,2018-09-11 05:30:18,2018-12-28 03:43:14 -569,Matthew,Gateley,450-774-0905,Male,5,93,62,2018-02-17 13:01:16,2018-06-17 01:27:48,2018-12-03 19:17:56,2018-08-31 08:39:46 -570,Alvan,Postance,415-301-3970,Male,5,36,24,2018-02-15 12:09:30,2018-07-26 19:38:06,2018-09-23 03:56:41,2018-09-17 12:13:43 -571,Ethelind,Otteridge,724-398-4832,Female,1,11,20,2019-01-09 07:06:55,2018-08-06 11:24:34,2018-02-04 09:08:33,2018-02-04 10:18:38 -572,Allayne,Pettegre,567-912-1393,Male,5,50,24,2019-01-17 18:14:12,2018-03-20 23:30:29,2018-07-08 17:53:55,2018-03-30 22:34:32 -573,Cindee,MacGill,218-267-2220,Female,3,85,36,2018-03-18 06:24:30,2018-08-12 14:08:59,2018-06-07 00:36:38,2018-07-28 18:35:16 -574,Jeramie,Fante,508-403-4318,Male,6,17,58,2018-09-05 21:09:00,2018-07-16 01:34:59,2018-05-30 20:15:51,2018-10-07 09:23:32 -575,Johannah,Treamayne,670-278-1704,Female,1,44,50,2018-09-01 12:25:07,2018-09-04 03:56:02,2018-03-25 08:47:56,2018-06-27 19:44:57 -576,Dari,Brocklesby,128-823-5176,Female,2,21,47,2018-11-06 21:06:13,2018-11-23 13:57:31,2019-01-01 00:06:22,2018-06-23 04:39:41 -577,Cob,Younglove,589-756-5544,Male,1,34,97,2018-06-06 05:48:43,2019-01-01 02:48:52,2018-09-20 02:52:35,2018-06-29 07:02:35 -578,Genevieve,Benois,718-259-0218,Female,1,83,84,2018-12-29 00:38:58,2019-01-17 14:12:58,2018-08-21 12:35:34,2018-07-15 16:50:51 -579,Demetra,Clineck,537-758-1797,Female,7,58,86,2018-04-18 09:28:08,2018-05-18 03:26:25,2018-02-24 07:51:24,2018-12-11 05:21:46 -580,Edithe,MacNeilage,254-201-0040,Female,5,2,46,2018-12-06 12:01:57,2018-02-16 02:10:30,2018-02-23 14:46:58,2018-12-31 17:43:21 -581,Osbourne,Scranny,682-363-4094,Male,3,29,17,2018-05-10 17:26:21,2018-11-02 03:59:01,2018-04-07 16:21:34,2018-07-31 23:17:47 -582,Con,Shyre,535-646-6697,Male,3,96,16,2018-07-14 00:36:39,2018-12-15 03:20:27,2018-07-23 10:48:18,2018-03-18 15:21:58 -583,Sylvester,Cannicott,456-905-3181,Male,1,2,37,2018-12-19 15:40:57,2018-06-18 08:08:39,2018-05-16 20:50:39,2018-10-02 13:56:35 -584,Any,Hayter,822-858-6900,Male,7,52,26,2018-11-06 13:05:00,2018-12-07 12:10:14,2018-12-30 08:34:38,2018-11-29 15:54:05 -585,Hebert,Casaro,238-642-2667,Male,5,86,80,2018-08-01 13:07:27,2018-11-03 12:14:52,2018-07-26 07:25:57,2019-01-19 03:35:48 -586,Lurlene,Feare,839-313-4455,Female,3,59,51,2018-08-26 04:27:58,2018-10-22 00:35:33,2018-06-26 19:50:51,2018-10-10 07:34:07 -587,Benjy,Mulvenna,623-742-2472,Male,3,63,37,2018-12-05 12:16:12,2018-06-01 06:27:24,2018-05-17 11:06:08,2018-11-03 18:34:32 -588,Odey,Burborough,705-824-5381,Male,7,35,7,2018-11-08 11:17:04,2018-10-02 17:39:13,2018-06-12 17:24:31,2018-11-16 00:36:52 -589,Marin,Piddletown,544-353-3265,Female,6,65,12,2018-06-05 02:00:30,2018-04-15 22:13:49,2018-10-25 08:48:07,2018-02-10 21:14:37 -590,Cyrille,holmes,735-579-6221,Male,7,40,75,2018-04-16 22:04:54,2018-04-25 22:55:07,2018-07-02 18:15:05,2018-08-10 21:27:54 -591,Maurice,Rains,484-638-1467,Male,5,73,91,2018-09-29 20:25:42,2018-05-09 00:14:24,2018-10-31 20:25:12,2018-10-07 19:50:59 -592,Caddric,Styant,859-759-9605,Male,6,10,38,2018-06-20 20:21:02,2018-12-09 17:47:12,2019-01-09 04:06:46,2018-07-19 05:01:01 -593,Vittorio,Straffon,643-403-5013,Male,3,46,7,2018-05-21 05:19:11,2018-12-06 16:33:18,2018-07-03 02:13:34,2018-11-03 12:50:20 -594,Filippo,Adamiak,414-171-7965,Male,5,13,70,2018-03-31 10:48:08,2018-07-07 00:41:10,2018-04-29 13:12:05,2018-08-12 07:32:33 -595,Abran,Blanning,940-243-9117,Male,6,88,72,2018-06-16 02:58:35,2018-08-17 14:00:04,2018-12-23 23:58:31,2018-04-15 17:28:52 -596,Ewart,Van Der Weedenburg,712-866-8225,Male,1,35,99,2018-12-03 12:43:02,2018-08-22 00:51:23,2018-06-03 09:07:10,2018-02-26 12:18:48 -597,Charmion,Toffoletto,139-517-9898,Female,2,60,33,2018-11-24 14:11:52,2018-10-26 03:35:48,2018-12-18 20:13:45,2018-09-23 22:05:26 -598,Marcellus,Casserly,253-327-1311,Male,3,41,81,2018-10-18 22:38:49,2018-03-13 20:31:39,2018-07-25 06:23:51,2018-06-05 20:55:02 -599,Bryant,Woonton,888-556-3681,Male,7,81,99,2018-02-28 09:31:55,2018-05-01 06:19:53,2019-01-09 14:08:26,2018-10-29 15:33:42 -600,Annnora,Beswick,518-587-0261,Female,6,56,22,2018-08-12 21:49:43,2019-01-08 19:34:20,2018-02-14 10:14:40,2018-08-01 03:40:27 -601,Donovan,Stenner,407-562-5695,Male,1,80,76,2018-08-31 07:45:11,2018-12-01 06:25:41,2018-02-28 03:57:11,2018-10-17 16:19:27 -602,Northrup,Limprecht,463-752-6075,Male,5,65,42,2018-11-03 02:27:29,2018-05-05 19:23:48,2018-02-18 06:54:36,2018-08-13 18:47:59 -603,Linoel,Havenhand,896-715-3769,Male,7,7,25,2018-05-10 18:45:39,2018-01-27 18:35:14,2018-06-14 18:17:37,2018-03-26 21:54:40 -604,Gerrilee,Morant,914-846-5569,Female,4,45,66,2018-02-17 20:40:10,2018-01-31 19:47:44,2018-10-09 22:28:47,2018-10-27 15:15:40 -605,Giralda,Daine,952-600-0863,Female,4,28,60,2018-06-15 19:09:55,2018-04-30 04:40:26,2018-09-14 06:48:06,2018-02-10 19:05:33 -606,Joela,Rand,808-932-6875,Female,1,27,3,2018-08-16 15:12:40,2018-09-27 15:12:49,2018-05-27 05:51:56,2018-04-13 14:52:35 -607,Obidiah,Beecham,324-361-0116,Male,7,72,18,2018-10-28 13:32:50,2018-06-20 18:58:47,2018-11-02 11:51:44,2018-03-11 23:29:03 -608,Karlik,Witherington,317-493-1871,Male,4,86,11,2019-01-20 03:58:33,2018-07-21 12:26:45,2018-08-23 20:09:48,2018-11-13 10:55:23 -609,Andras,Buttler,645-159-2747,Male,4,66,45,2018-05-19 10:32:36,2018-12-15 13:10:33,2018-01-31 23:04:41,2019-01-04 22:38:54 -610,Kevan,MacCorkell,902-102-9241,Male,5,35,56,2018-02-09 15:51:27,2018-07-17 04:54:50,2018-01-23 13:03:51,2018-07-12 19:59:05 -611,Dena,Welbelove,824-828-1515,Female,7,30,100,2018-03-13 11:53:11,2018-07-30 19:53:24,2019-01-12 19:12:36,2018-10-23 22:10:25 -612,Susette,Spurman,489-770-6265,Female,5,20,53,2018-05-08 12:17:52,2018-06-18 00:15:28,2018-04-14 14:12:49,2018-09-21 10:34:01 -613,Lisabeth,Clarycott,631-189-3198,Female,7,98,3,2018-08-30 00:26:48,2018-03-16 13:08:16,2018-10-12 07:44:50,2018-10-14 13:12:31 -614,Sheryl,Cicchinelli,508-453-8265,Female,6,77,4,2019-01-04 08:57:07,2018-07-27 00:56:42,2018-07-07 09:59:19,2018-08-03 11:54:06 -615,Milly,Harston,959-484-0888,Female,3,13,88,2018-05-02 06:02:08,2018-05-11 09:34:20,2019-01-11 22:42:26,2018-02-06 01:43:05 -616,Avery,Cant,144-536-3636,Male,5,59,83,2018-04-28 04:40:20,2018-02-20 10:21:26,2018-01-23 14:16:23,2018-06-13 17:25:06 -617,Odelle,Hauxley,311-843-6729,Female,2,15,33,2018-06-09 20:51:56,2018-03-22 15:09:29,2019-01-07 22:47:04,2018-10-30 05:38:26 -618,Symon,Dewi,944-566-4724,Male,6,79,26,2018-10-23 03:09:57,2018-04-20 15:52:10,2018-07-23 05:16:26,2018-09-05 13:15:24 -619,Nora,Ingerson,644-377-6341,Female,7,58,74,2018-12-31 01:35:50,2018-03-08 16:01:54,2018-04-02 13:25:27,2018-08-14 07:54:24 -620,Mariam,Ceschelli,722-520-3029,Female,5,65,57,2018-08-17 21:29:16,2018-11-14 18:13:13,2018-11-22 04:05:56,2018-03-25 21:13:21 -621,Guglielma,Fearey,399-683-0328,Female,2,48,46,2018-12-01 22:21:56,2018-05-05 09:53:28,2018-04-01 03:22:30,2018-10-31 05:13:13 -622,Putnem,Glanton,730-351-4499,Male,3,47,40,2018-05-06 05:22:19,2018-08-03 21:56:51,2018-07-27 03:42:36,2018-09-26 03:10:38 -623,Blancha,Penney,585-209-3640,Female,4,92,1,2018-04-24 13:18:47,2018-06-21 21:42:31,2018-03-11 01:50:30,2018-08-17 20:04:54 -624,Zacherie,Manoelli,211-774-0854,Male,7,41,38,2018-09-29 10:25:00,2018-11-03 11:49:35,2018-06-04 21:41:44,2018-10-24 16:29:50 -625,Seymour,Murphey,840-189-1695,Male,7,27,18,2018-11-22 02:51:55,2018-11-13 09:09:33,2018-04-26 15:24:33,2018-06-10 09:01:11 -626,Kiele,Potte,807-707-7776,Female,5,50,79,2018-12-10 09:07:14,2018-02-09 02:17:04,2018-12-02 09:39:41,2018-06-25 03:58:33 -627,Pascale,Keat,699-216-9743,Male,6,20,78,2018-11-23 01:30:15,2018-04-11 09:12:08,2018-03-14 20:14:59,2018-02-13 23:24:16 -628,Krisha,Sails,162-533-7679,Male,5,91,52,2019-01-17 01:56:16,2018-02-15 14:18:56,2018-03-05 23:19:21,2018-02-24 11:00:50 -629,Justen,McFeat,266-387-8084,Male,4,45,19,2018-10-17 20:09:40,2018-12-29 10:26:10,2018-07-21 12:46:49,2018-02-12 09:50:24 -630,Daloris,Adamson,173-669-4723,Female,4,46,42,2018-02-02 14:26:53,2018-08-15 00:31:20,2018-10-28 08:17:42,2018-04-21 16:28:19 -631,Saleem,Cawood,885-138-1413,Male,6,96,11,2018-09-04 09:51:41,2018-06-12 17:37:20,2018-12-09 22:22:56,2018-11-28 01:06:26 -632,Yettie,Glynn,672-547-0019,Female,3,84,66,2018-11-13 23:39:10,2018-07-14 16:14:12,2018-09-21 13:43:43,2018-09-29 15:57:10 -633,Waite,Smalls,320-394-9058,Male,4,2,55,2018-12-17 16:32:29,2018-11-15 01:45:06,2018-03-17 23:34:19,2018-03-06 15:12:35 -634,Tomkin,Adam,674-394-3276,Male,3,5,48,2018-02-07 03:48:38,2018-07-13 14:23:03,2018-06-02 14:48:09,2018-07-13 06:23:14 -635,Dilly,Strotone,507-532-7349,Male,2,63,15,2018-10-18 04:02:56,2018-08-29 04:49:57,2018-12-04 03:03:45,2018-10-13 05:54:24 -636,Townsend,Eytel,577-285-3662,Male,2,28,15,2018-06-01 12:29:01,2018-09-17 04:48:03,2018-08-12 21:57:59,2018-02-19 20:48:01 -637,Aurel,Taleworth,826-459-6823,Female,4,21,100,2018-08-04 08:00:57,2018-09-17 17:45:32,2018-10-01 19:40:32,2018-09-12 06:23:27 -638,Barnabe,Eldredge,303-934-8908,Male,1,96,66,2018-11-25 12:08:25,2018-09-28 04:15:54,2018-06-11 18:54:23,2018-01-29 01:27:18 -639,Brnaby,Kwietek,319-338-0342,Male,1,99,21,2018-07-11 05:00:49,2018-09-07 18:54:24,2019-01-02 06:20:42,2018-07-12 08:08:28 -640,Thea,Beamont,123-463-1082,Female,4,95,46,2018-03-04 16:30:12,2018-09-20 03:40:11,2018-07-15 14:34:10,2018-08-29 13:50:42 -641,Moyra,MacAne,973-363-3000,Female,3,50,66,2018-06-15 02:19:51,2018-07-18 23:41:04,2018-11-11 08:19:50,2018-07-28 23:40:30 -642,Luce,Hanmer,800-595-2765,Male,4,71,68,2018-12-29 07:24:16,2018-03-30 23:25:56,2018-12-20 17:22:17,2018-07-01 23:50:17 -643,Clement,Gobert,746-653-6801,Male,2,29,39,2018-03-16 20:33:17,2018-12-07 02:34:52,2018-12-12 16:45:55,2018-12-20 02:30:28 -644,Dalenna,Kingsnorth,366-634-1391,Female,5,42,29,2018-04-19 19:41:25,2018-11-24 02:02:50,2018-03-31 05:36:32,2018-07-16 23:22:03 -645,Gigi,MacGilrewy,807-983-4035,Female,2,5,59,2018-11-13 14:20:34,2018-09-08 20:54:02,2018-09-05 14:11:49,2018-06-05 21:12:39 -646,Josi,De Vere,191-357-7492,Female,3,26,63,2018-11-16 05:10:17,2018-05-10 22:27:04,2018-05-04 18:15:10,2018-06-28 04:26:52 -647,Ripley,Pedrozzi,564-644-3142,Male,4,81,64,2018-05-06 05:04:31,2018-09-08 07:15:00,2018-11-12 01:23:19,2018-08-14 01:45:01 -648,Angelina,Henriques,513-742-8132,Female,1,4,93,2018-08-13 00:14:12,2018-03-20 21:24:41,2018-08-07 23:30:14,2018-11-23 00:03:11 -649,Anthia,Dandy,983-456-4556,Female,4,7,96,2018-05-12 17:03:46,2018-12-07 05:19:51,2018-11-20 12:22:28,2018-10-03 06:06:09 -650,Audry,Mourge,237-352-0739,Female,3,87,13,2018-01-25 21:10:18,2018-04-08 08:11:55,2018-01-26 17:58:05,2018-11-22 16:05:01 -651,Konstanze,Skocroft,383-376-4511,Female,5,53,15,2018-07-06 21:47:19,2018-07-21 19:51:01,2019-01-05 19:31:14,2018-12-02 06:51:10 -652,Koo,Arington,553-175-9464,Female,4,51,72,2018-03-12 21:13:34,2018-01-29 22:50:56,2018-07-28 03:59:46,2018-09-08 20:40:26 -653,Mimi,Novakovic,282-495-5519,Female,2,13,7,2019-01-18 17:51:56,2018-03-21 21:03:27,2018-11-26 23:09:59,2018-02-15 16:11:04 -654,Aldus,Aguirrezabal,289-348-2177,Male,2,27,59,2018-11-06 12:55:08,2018-03-03 18:13:31,2018-04-12 18:22:35,2018-08-22 21:43:49 -655,Sullivan,Kelmere,595-312-2528,Male,1,42,45,2018-12-01 16:35:57,2018-10-25 18:48:22,2018-09-07 00:15:27,2018-04-27 11:34:49 -656,Taite,Ruffli,824-778-7852,Male,4,22,46,2018-07-28 22:54:17,2018-10-09 20:45:57,2018-08-03 04:38:39,2018-11-26 15:09:49 -657,Rosene,Missen,922-494-6731,Female,7,91,26,2018-08-17 20:06:33,2018-11-02 02:58:57,2018-03-05 00:03:11,2018-05-31 23:55:38 -658,Ty,Fucher,639-989-4144,Male,3,68,100,2018-07-22 01:36:24,2018-03-08 21:12:38,2018-05-04 21:30:03,2018-09-06 22:32:37 -659,Heddi,Assel,246-263-2031,Female,6,39,92,2018-02-15 08:32:02,2018-02-26 03:11:18,2018-01-27 11:33:06,2018-08-29 02:37:29 -660,Boonie,Djorvic,425-328-7219,Male,7,49,6,2018-02-11 23:21:23,2018-03-07 04:45:35,2019-01-16 02:27:45,2018-10-14 03:27:02 -661,Aurie,Esgate,216-596-1681,Female,4,44,39,2019-01-07 13:40:58,2018-09-29 18:40:04,2018-04-15 01:33:28,2018-11-16 00:59:28 -662,Dana,Edginton,762-855-7796,Male,7,11,7,2018-10-22 11:13:58,2018-02-25 07:53:13,2018-10-26 14:30:34,2018-02-21 08:22:28 -663,Christiana,Haslock(e),322-905-9384,Female,7,66,50,2018-04-08 07:38:08,2018-05-11 05:11:14,2018-03-13 07:31:38,2018-03-24 02:07:40 -664,Lelia,Kimmerling,462-373-6886,Female,2,22,47,2018-07-16 09:28:30,2018-01-31 12:00:37,2018-05-14 00:22:05,2018-04-02 06:04:19 -665,Kaleena,Ferrier,462-635-6827,Female,2,74,81,2018-06-05 11:09:52,2018-02-12 09:02:48,2018-09-11 19:00:25,2018-02-20 13:36:01 -666,Davon,Kroch,646-511-8893,Male,2,79,55,2018-08-11 12:22:33,2018-03-09 12:30:22,2018-10-04 12:31:33,2018-08-30 17:50:16 -667,Agathe,Kingwell,879-547-0641,Female,7,16,34,2018-06-12 18:22:16,2018-08-05 00:55:58,2018-12-27 12:31:25,2018-02-19 01:39:48 -668,Tami,Brum,925-535-6949,Female,6,13,16,2018-08-10 21:16:02,2018-07-10 10:42:55,2018-10-03 09:45:52,2018-09-02 08:04:13 -669,Meghan,Behan,666-973-3081,Female,2,37,72,2018-07-01 22:33:57,2018-12-23 00:46:46,2018-11-15 22:39:02,2018-02-15 12:20:24 -670,Elliott,Gumbley,891-324-8441,Male,3,100,20,2018-05-26 06:24:39,2018-08-24 00:11:20,2018-10-25 08:36:44,2018-03-14 08:39:54 -671,Roosevelt,Headan,845-354-1730,Male,5,3,90,2018-07-01 14:50:49,2018-09-15 12:12:40,2018-12-24 01:35:47,2018-09-20 01:17:08 -672,Judie,Cozins,719-163-5308,Female,6,64,26,2018-02-13 12:22:03,2018-11-17 08:43:37,2018-04-01 06:23:24,2018-09-21 04:32:48 -673,Zebulen,Bulger,201-223-1332,Male,5,98,53,2018-07-16 23:18:20,2018-05-29 12:17:27,2018-04-28 14:52:50,2018-06-12 16:22:23 -674,Lea,Fairpo,372-782-5016,Female,6,19,3,2018-09-03 14:58:22,2018-07-08 18:29:06,2018-05-16 18:23:32,2018-12-29 08:04:07 -675,Mayer,Demead,393-580-8088,Male,4,41,38,2018-09-26 07:35:23,2018-04-11 15:45:52,2018-03-27 15:23:59,2018-06-06 14:21:04 -676,Ana,Cannaway,492-510-5265,Female,7,61,68,2018-02-10 08:21:49,2019-01-17 12:57:29,2018-03-10 19:54:59,2018-05-05 03:55:19 -677,Cathrine,Featonby,618-545-3336,Female,2,13,20,2018-04-06 05:43:01,2018-08-08 21:16:04,2018-09-14 02:33:02,2018-02-21 21:27:00 -678,Wilt,Pitcher,482-827-8133,Male,3,100,4,2018-07-28 21:19:49,2018-05-26 09:01:20,2018-08-20 04:38:04,2018-12-20 10:33:58 -679,Mirabelle,Beric,266-468-3958,Female,5,22,72,2018-05-02 12:06:49,2018-04-08 13:34:02,2018-05-08 04:55:38,2018-04-08 07:43:46 -680,Kitti,Duell,600-603-0212,Female,6,63,11,2018-06-03 10:32:14,2018-02-28 16:15:11,2018-07-14 16:05:36,2018-12-09 20:55:23 -681,Pebrook,Tunuy,901-401-5075,Male,7,43,54,2018-05-03 21:20:23,2018-08-22 11:35:56,2019-01-16 05:29:13,2018-06-03 07:29:48 -682,Maryanna,Eayrs,722-426-6216,Female,1,44,84,2018-09-20 04:29:10,2018-03-25 00:25:02,2018-08-24 07:28:58,2019-01-03 12:51:01 -683,Obadias,Izzatt,379-850-7154,Male,6,6,27,2018-04-26 21:45:09,2018-02-05 01:27:51,2018-12-26 01:14:44,2018-08-29 23:20:18 -684,Cherye,Androletti,524-563-8173,Female,3,68,10,2018-04-21 19:56:00,2018-09-14 22:29:43,2018-12-29 20:14:49,2018-11-16 03:21:36 -685,Joachim,Dimitrescu,795-788-5797,Male,5,76,2,2018-12-11 21:33:57,2018-12-23 19:18:05,2018-11-25 10:00:13,2018-03-10 21:29:53 -686,Wynne,Heyward,438-352-0453,Female,2,24,17,2018-08-16 11:16:51,2018-07-01 06:49:35,2018-10-07 18:27:47,2018-12-09 16:04:47 -687,Renell,Ipwell,436-940-9778,Female,2,20,24,2018-11-20 12:06:05,2018-07-02 02:09:18,2018-09-08 02:49:34,2018-02-07 07:39:15 -688,Ricky,Alderson,299-400-6861,Male,6,41,97,2018-11-21 08:08:46,2018-08-15 09:54:31,2018-12-12 09:05:40,2018-11-13 16:44:40 -689,Rubi,Gail,300-475-1452,Female,4,37,26,2019-01-06 23:27:48,2018-11-12 10:44:21,2018-12-06 15:12:08,2018-03-19 12:15:14 -690,Sherill,Tallent,643-731-0806,Female,5,51,98,2018-10-30 15:13:26,2018-06-09 19:32:29,2018-02-06 16:40:35,2018-09-26 13:31:25 -691,Elia,Hairon,537-738-0445,Male,4,59,64,2018-06-18 11:14:46,2018-08-12 09:09:40,2018-03-22 09:13:44,2018-10-25 02:49:49 -692,Johny,Degoe,380-482-6021,Male,2,89,51,2018-12-18 10:28:50,2018-10-04 06:40:46,2018-05-17 13:11:00,2019-01-18 01:02:48 -693,Kirstin,Hopfer,520-920-5762,Female,7,7,29,2018-03-03 02:44:21,2018-07-08 01:31:26,2018-08-12 04:22:03,2018-10-07 12:47:55 -694,Addie,Hrycek,411-674-4016,Female,1,62,3,2018-08-02 04:43:18,2018-09-19 05:54:13,2018-09-30 17:33:04,2018-10-24 16:39:15 -695,Devinne,Dilrew,876-178-5135,Female,6,97,69,2018-01-22 00:39:19,2018-05-29 02:38:21,2018-10-17 03:17:47,2018-07-28 12:51:30 -696,Violet,Petren,352-136-0037,Female,3,20,80,2018-09-23 03:09:33,2018-05-22 01:24:08,2019-01-06 00:46:41,2018-04-13 04:27:36 -697,Inga,Cahalan,847-549-2394,Female,3,98,26,2018-03-24 12:37:49,2018-10-09 07:41:56,2019-01-07 22:18:43,2018-01-28 07:44:56 -698,Burg,Liepina,736-158-9051,Male,4,89,88,2018-02-04 05:58:15,2018-02-24 08:51:40,2018-12-01 18:20:15,2018-02-20 12:27:18 -699,Winnifred,Yakutin,165-178-2008,Female,1,74,93,2018-12-14 06:11:18,2018-12-23 02:09:43,2018-04-07 06:12:17,2018-08-16 08:12:28 -700,Boone,Walsom,432-415-6784,Male,3,91,63,2018-06-12 09:05:08,2018-09-21 04:24:21,2018-09-18 05:27:12,2018-09-10 10:46:37 -701,Alberto,Steadman,316-988-9996,Male,7,11,32,2019-01-13 23:25:22,2018-04-27 23:46:24,2018-12-07 20:28:14,2018-02-03 17:46:13 -702,Babbie,Ossulton,151-959-6676,Female,5,50,26,2018-08-25 20:54:00,2018-05-14 14:24:06,2019-01-14 14:14:51,2018-08-15 11:39:35 -703,Franni,Sparwell,411-855-1156,Female,6,95,65,2018-07-21 15:32:34,2018-07-03 10:42:20,2018-08-26 02:44:03,2018-04-13 05:52:48 -704,Carlos,MacNair,911-726-0315,Male,1,17,35,2018-12-05 14:25:42,2018-12-12 19:39:25,2018-04-29 02:34:46,2018-10-22 16:34:03 -705,Violetta,Crosbie,334-280-9073,Female,3,9,44,2018-01-30 22:36:27,2018-08-07 22:12:15,2018-11-27 09:47:02,2018-07-24 14:22:36 -706,Malanie,Perico,380-744-7181,Female,6,68,23,2019-01-03 09:08:46,2018-08-26 01:51:30,2018-12-02 23:44:58,2018-02-16 00:13:42 -707,Ivor,Bowcher,940-535-1313,Male,2,79,20,2018-09-05 08:48:25,2018-05-21 21:40:04,2018-05-02 19:33:24,2018-06-22 07:46:47 -708,Hyacinth,Trump,241-552-4852,Female,4,46,7,2018-02-27 17:57:22,2018-11-20 03:54:39,2018-10-27 00:44:50,2018-09-19 14:04:29 -709,Vittorio,Blincko,136-124-8825,Male,5,70,20,2018-12-17 01:45:05,2018-06-06 18:10:29,2018-12-01 18:11:21,2018-04-14 00:43:46 -710,Tadeas,Glendenning,676-274-2212,Male,3,70,6,2018-08-22 07:42:12,2018-07-12 17:41:15,2018-07-24 17:42:26,2018-12-27 05:34:05 -711,Sky,Flew,681-787-4952,Male,3,81,48,2018-11-13 09:16:39,2018-09-14 09:34:51,2018-09-23 01:44:43,2018-11-21 00:50:58 -712,Luise,Olivetti,707-121-6217,Female,4,68,4,2018-03-29 01:36:21,2018-05-06 13:38:59,2018-05-06 09:55:05,2018-02-04 21:27:46 -713,Drusy,Capinetti,432-896-1449,Female,5,94,80,2018-07-31 20:38:50,2018-11-28 22:41:39,2018-04-27 00:57:40,2018-08-30 16:16:05 -714,Miranda,Rissen,700-512-2672,Female,7,29,40,2018-03-15 22:30:44,2018-02-01 02:59:19,2018-11-25 08:02:09,2018-11-05 07:51:59 -715,Ario,Bashford,390-128-4254,Male,2,54,93,2018-06-14 08:22:43,2018-08-12 18:13:42,2018-11-28 21:40:32,2018-12-29 03:09:26 -716,Rochella,Shackesby,103-592-3468,Female,7,41,14,2018-02-12 09:44:28,2018-08-22 10:35:46,2019-01-09 02:25:18,2018-10-10 17:50:44 -717,Wes,Christofides,192-457-7659,Male,1,69,89,2018-05-29 07:31:48,2019-01-06 03:40:33,2018-02-04 22:20:47,2019-01-05 16:01:23 -718,Griselda,Lukes,232-886-4996,Female,2,96,24,2019-01-10 12:54:29,2019-01-16 20:13:57,2018-04-26 08:07:43,2018-10-11 15:19:29 -719,Dredi,Cooksey,432-670-0783,Female,2,24,32,2018-02-28 00:00:07,2018-06-20 03:18:14,2018-07-21 09:03:11,2018-07-06 03:35:06 -720,Coleman,Trudgian,273-535-1414,Male,4,97,47,2018-04-25 23:41:09,2018-03-11 00:03:13,2018-06-03 13:44:14,2018-08-08 09:07:58 -721,Averill,Shilstone,947-108-0865,Male,7,1,64,2018-08-18 22:21:07,2018-04-12 03:24:47,2018-03-10 08:58:27,2018-08-03 14:04:03 -722,Carmen,Syder,954-822-0919,Female,2,47,75,2018-10-09 09:52:34,2018-11-21 01:16:40,2018-02-12 03:27:35,2018-08-12 12:44:55 -723,Morgan,Leband,547-933-1630,Female,5,39,97,2018-03-25 07:19:57,2018-03-28 20:22:12,2018-09-05 13:29:46,2018-10-12 09:04:17 -724,Milzie,Fearnley,589-230-2628,Female,1,44,13,2018-05-17 23:12:31,2018-07-29 21:43:28,2018-07-06 23:27:59,2018-09-14 01:45:16 -725,Deb,Marjot,495-276-5931,Female,2,27,81,2018-09-28 15:27:35,2018-02-05 23:31:12,2018-07-29 04:18:34,2018-03-08 09:45:23 -726,Shayne,Artinstall,628-997-5039,Male,2,23,20,2018-11-19 12:44:15,2018-05-30 23:05:12,2018-11-23 10:18:23,2018-06-08 14:18:23 -727,Annabal,Standbridge,226-314-1568,Female,5,16,5,2018-08-11 00:40:31,2018-12-20 14:06:36,2018-04-15 04:33:53,2018-11-09 16:42:45 -728,Sheffield,Crielly,360-797-0933,Male,7,57,90,2018-03-08 03:32:17,2018-11-07 06:12:46,2019-01-12 22:10:52,2019-01-02 03:16:09 -729,Antonius,Delagua,336-343-1380,Male,2,64,60,2018-10-14 22:56:26,2018-11-13 00:50:03,2018-07-02 11:23:06,2018-08-09 09:29:32 -730,Brana,Cannell,157-563-3935,Female,2,74,73,2019-01-19 15:41:16,2018-04-20 09:34:06,2018-08-02 12:28:32,2018-02-21 06:29:31 -731,Bartram,Praundlin,631-372-3479,Male,2,35,7,2018-10-03 02:00:10,2018-07-31 21:29:22,2019-01-10 21:43:54,2018-08-28 13:29:28 -732,Anthiathia,Goodwins,664-616-3575,Female,7,76,19,2018-04-26 19:57:15,2018-10-28 17:07:05,2018-02-21 16:38:28,2018-04-18 17:58:31 -733,Deborah,Ekell,577-861-9112,Female,5,74,43,2018-10-19 06:10:04,2018-03-12 03:47:48,2018-05-17 13:04:37,2018-02-09 05:48:05 -734,Lauri,Arunowicz,862-427-5257,Female,4,58,81,2018-07-29 04:16:13,2018-04-23 19:30:17,2018-03-19 21:30:18,2018-11-18 20:46:33 -735,Fowler,Markus,496-831-3082,Male,7,18,52,2018-01-26 22:36:43,2019-01-14 00:15:25,2018-03-18 05:45:56,2018-02-27 16:55:19 -736,Klara,Ramme,103-225-9086,Female,7,28,67,2018-05-21 17:32:08,2018-10-05 08:11:16,2018-06-25 15:05:21,2018-03-13 14:44:42 -737,Melisenda,Chitham,158-699-0591,Female,2,49,88,2018-04-16 02:24:00,2018-10-27 14:52:15,2018-12-31 05:39:31,2018-12-09 09:15:25 -738,Hale,Layborn,106-961-8551,Male,3,66,90,2018-04-22 19:39:27,2018-08-12 19:37:50,2018-08-17 10:37:06,2018-09-14 15:17:48 -739,Ferdie,Stubbeley,686-279-8217,Male,7,62,96,2018-09-25 03:29:05,2018-06-27 23:31:12,2018-07-21 18:49:24,2018-06-19 05:08:00 -740,Licha,O' Kelleher,463-395-9023,Female,6,75,16,2018-07-05 08:29:21,2018-09-13 21:32:41,2018-08-26 17:50:16,2018-05-22 11:30:48 -741,Gualterio,Kernar,123-900-7702,Male,2,32,18,2018-12-30 04:11:35,2018-04-15 10:32:33,2018-06-21 01:01:16,2018-11-15 03:34:48 -742,Harley,Lyokhin,664-282-7716,Male,1,42,45,2018-07-26 12:07:21,2018-02-09 02:23:37,2018-05-10 13:39:44,2018-11-25 04:15:16 -743,Kylila,Hukin,726-438-0889,Female,2,2,74,2019-01-02 09:08:44,2018-04-07 07:18:19,2018-04-19 16:12:40,2018-03-03 19:00:47 -744,Natividad,Dahlbom,744-480-5437,Female,5,82,39,2018-12-30 01:10:05,2018-08-01 07:16:39,2018-05-29 02:44:28,2018-11-08 15:02:54 -745,Virgina,Couzens,947-544-5389,Female,6,14,38,2018-11-19 23:03:21,2018-11-21 13:32:21,2018-03-29 02:30:25,2018-12-31 17:15:49 -746,Peyter,Diano,292-294-3875,Male,2,23,76,2018-12-22 18:12:13,2018-09-23 11:29:07,2018-07-12 06:09:06,2018-07-28 01:53:40 -747,Jayme,O'Curneen,225-447-3103,Male,3,10,84,2018-06-20 10:29:48,2018-08-12 10:14:12,2018-04-28 06:15:40,2018-07-19 08:52:24 -748,Frederik,Wilkisson,963-312-1892,Male,3,4,18,2018-09-11 01:05:52,2018-05-17 07:03:54,2018-09-07 08:19:47,2018-12-27 05:51:37 -749,Yankee,Harrower,918-854-5590,Male,7,14,88,2019-01-12 12:01:21,2018-08-24 08:15:58,2018-06-19 00:06:07,2018-06-19 07:16:40 -750,Tamas,MacRinn,856-289-3684,Male,6,83,91,2018-05-18 15:58:10,2018-06-09 14:45:50,2018-06-16 17:21:20,2018-12-18 02:23:35 -751,Valentin,Rawlings,663-758-9646,Male,4,16,34,2018-06-27 02:03:36,2018-12-10 04:32:16,2018-07-07 05:22:18,2018-02-03 06:54:36 -752,Colver,Yarr,382-717-8711,Male,5,23,10,2018-05-13 09:06:22,2018-04-06 13:41:41,2018-05-07 22:03:59,2018-11-12 22:30:08 -753,Alisa,Gaynesford,417-789-3077,Female,2,87,12,2018-07-16 18:03:56,2018-02-06 07:27:34,2018-07-12 08:51:47,2018-02-22 19:25:29 -754,Xavier,Cornwell,777-401-4183,Male,7,12,13,2018-12-03 01:19:40,2018-05-30 23:16:32,2018-10-01 21:33:13,2018-04-13 23:28:08 -755,Hy,Raftery,563-495-4017,Male,7,54,93,2018-03-25 23:10:24,2018-11-20 07:01:06,2018-03-27 13:09:16,2018-08-03 19:07:10 -756,Holt,Rosenfeld,962-871-1674,Male,2,43,35,2018-08-07 04:15:12,2018-05-21 13:42:27,2018-11-13 19:28:52,2018-03-27 10:14:19 -757,Zola,Andreopolos,543-481-8409,Female,4,31,62,2018-02-08 17:26:50,2018-12-12 15:18:24,2018-02-22 22:58:13,2019-01-02 05:55:39 -758,Letty,Scotting,546-656-5808,Female,5,15,94,2018-10-21 18:22:43,2018-05-26 22:09:39,2018-08-04 15:48:15,2018-08-28 06:14:32 -759,Celina,Lauchlan,202-835-6732,Female,7,47,9,2018-02-26 21:58:16,2019-01-10 01:22:46,2018-11-03 06:10:35,2018-04-21 11:00:49 -760,Drusy,Izakov,129-552-5886,Female,1,45,2,2018-10-11 13:12:08,2018-06-26 11:16:28,2018-08-24 23:58:00,2018-09-09 05:46:23 -761,Shana,Ference,915-610-3990,Female,3,1,7,2018-10-31 18:47:12,2018-09-13 14:33:49,2018-10-02 08:57:46,2018-02-18 19:30:28 -762,Colin,Broy,868-631-8529,Male,2,22,32,2018-05-23 19:06:02,2018-09-08 07:49:35,2018-12-13 21:44:07,2018-06-25 07:15:53 -763,Farlay,Cromett,640-335-8081,Male,7,34,25,2018-06-29 00:34:53,2018-12-08 12:49:01,2018-12-03 13:22:54,2018-06-24 16:33:04 -764,Leandra,Hamberstone,786-332-2588,Female,2,37,90,2018-12-22 15:35:04,2018-02-04 16:23:41,2018-01-28 07:51:51,2018-06-01 00:25:34 -765,Gan,McCahey,450-198-7472,Male,2,79,7,2018-06-26 07:22:06,2018-09-27 09:42:20,2018-03-13 20:28:52,2018-02-10 02:05:39 -766,Brose,Gane,302-470-1094,Male,7,27,25,2018-11-05 10:16:11,2018-12-27 12:00:35,2018-12-13 06:00:05,2018-08-30 01:03:46 -767,Mabel,Nurdin,417-183-7374,Female,1,73,62,2018-12-09 01:11:47,2018-06-09 12:03:13,2018-11-30 04:52:49,2018-04-24 11:08:53 -768,Melinda,Belliard,277-126-4396,Female,6,39,83,2018-07-13 11:17:51,2018-08-04 10:46:43,2018-11-19 23:27:57,2018-02-19 10:08:24 -769,Percy,Yakolev,433-703-6347,Male,4,78,23,2018-11-02 23:32:50,2018-12-19 16:21:10,2018-02-17 21:43:15,2018-12-09 00:57:58 -770,Portia,Legonidec,761-180-7070,Female,6,27,1,2018-11-01 18:06:54,2018-05-16 10:56:05,2018-08-06 20:45:16,2018-08-14 23:11:03 -771,Harry,Lapley,950-309-5667,Male,5,8,58,2018-03-01 15:09:46,2018-05-13 05:24:49,2018-03-22 16:01:05,2018-08-18 02:05:37 -772,Cort,Gathwaite,964-902-3053,Male,5,33,89,2018-08-18 20:12:14,2018-01-27 16:39:37,2018-12-26 22:46:04,2018-02-16 22:31:58 -773,Moselle,Davidsson,813-238-6494,Female,4,13,60,2019-01-10 17:47:31,2018-11-04 08:31:17,2018-04-30 12:09:52,2018-04-14 19:47:23 -774,Avril,Britton,340-286-1678,Female,3,4,16,2018-03-18 00:19:38,2018-12-29 06:21:49,2019-01-03 02:03:40,2018-11-29 12:05:59 -775,Linn,Confait,176-807-2635,Female,6,18,70,2018-09-18 15:11:21,2018-05-02 18:32:49,2018-03-25 13:46:21,2018-10-06 04:29:26 -776,Joletta,Fyldes,547-358-7132,Female,3,92,6,2019-01-07 18:53:22,2018-09-07 21:09:08,2018-10-22 08:38:19,2018-07-08 07:01:37 -777,Alvira,Donnersberg,712-756-5926,Female,1,20,77,2018-06-09 12:41:30,2018-12-29 01:15:22,2018-02-11 19:44:50,2018-02-21 21:33:12 -778,Kirbee,Sherer,434-167-9643,Female,4,84,40,2018-10-18 16:54:05,2018-04-02 11:16:17,2018-02-26 17:45:53,2018-10-21 05:24:45 -779,Griffy,Guitton,326-132-8573,Male,4,60,19,2018-06-22 17:59:44,2018-09-11 16:22:32,2018-11-10 19:43:30,2018-02-06 10:06:41 -780,Emmott,Allitt,969-852-2661,Male,2,48,37,2018-04-24 21:17:55,2018-11-01 06:07:42,2018-07-30 22:56:18,2018-11-13 22:12:50 -781,Tailor,Dalman,521-811-9925,Male,5,60,72,2018-12-14 09:37:55,2018-12-26 17:43:11,2018-12-10 03:38:52,2018-04-07 11:21:07 -782,Brennen,Vasilechko,176-109-0551,Male,6,90,55,2018-08-31 12:29:00,2018-05-23 03:06:41,2018-10-10 17:44:50,2018-10-21 00:47:28 -783,Dotty,MacCallam,161-881-1371,Female,1,56,3,2018-03-01 02:18:19,2019-01-06 18:00:59,2018-04-28 10:26:11,2018-02-05 06:43:37 -784,Jedidiah,Guerin,645-152-7671,Male,5,56,83,2018-04-02 15:07:20,2018-08-24 12:42:12,2018-12-21 09:17:44,2018-10-06 00:19:03 -785,Hannie,Danes,716-637-6821,Female,5,40,18,2019-01-08 07:08:18,2019-01-05 20:40:19,2019-01-16 12:16:28,2018-03-23 12:28:41 -786,Galen,Scogin,453-714-4492,Male,6,38,18,2018-10-27 06:54:20,2018-06-19 09:26:07,2019-01-10 20:55:20,2018-10-18 17:04:44 -787,Aleta,Melonby,207-524-3356,Female,3,98,3,2018-04-04 12:13:59,2018-06-06 11:50:34,2018-05-05 17:38:56,2018-03-11 12:56:42 -788,Adlai,Mauchlen,601-977-7616,Male,7,88,64,2018-03-24 04:33:36,2018-03-07 16:46:25,2018-03-16 19:25:21,2018-07-20 14:23:29 -789,Amelie,Le Barre,576-950-1963,Female,5,28,53,2018-08-10 15:52:25,2018-05-07 07:19:32,2018-12-21 21:24:49,2018-07-21 01:11:54 -790,Rodrique,Lestor,723-918-4771,Male,4,26,72,2018-08-29 10:37:42,2018-11-16 09:49:01,2018-08-31 05:08:59,2018-12-18 10:17:32 -791,Gifford,Challoner,411-352-9364,Male,5,63,18,2018-10-16 12:33:24,2018-11-24 23:28:34,2018-05-29 22:33:36,2018-11-06 07:45:09 -792,Dorene,Pogosian,391-363-6103,Female,4,74,78,2018-04-26 20:52:42,2018-08-02 21:57:23,2018-04-29 21:18:02,2018-02-13 20:06:09 -793,Lynnell,De Filippi,418-713-4087,Female,7,78,47,2018-12-03 11:11:47,2019-01-05 12:23:37,2018-05-05 19:10:42,2018-04-22 16:11:38 -794,Tod,Willicott,354-257-4541,Male,5,34,18,2018-07-19 20:11:25,2018-08-12 01:02:55,2018-08-05 23:52:34,2018-02-15 00:20:31 -795,Myrlene,Wornham,331-165-6672,Female,7,51,75,2018-11-24 15:52:43,2018-07-01 06:12:47,2018-08-08 19:45:02,2018-11-19 14:51:56 -796,Sibyl,Burnsyde,981-826-0517,Female,2,24,2,2018-11-01 05:15:20,2018-10-15 22:30:33,2018-05-27 21:38:42,2018-05-08 15:34:52 -797,Barron,Hanrott,700-573-3103,Male,6,81,99,2018-08-12 21:14:38,2018-03-09 17:36:14,2018-06-03 16:23:47,2018-10-13 22:34:58 -798,Marylee,Hunnawill,501-536-2494,Female,7,30,33,2018-10-19 01:54:52,2018-04-12 03:02:28,2018-09-12 02:31:37,2018-06-14 10:58:08 -799,Chip,Hunnaball,249-377-3740,Male,3,98,59,2018-04-25 10:02:32,2019-01-18 16:00:40,2018-02-14 02:06:39,2018-06-17 23:32:24 -800,Major,Milsap,444-230-6774,Male,7,20,23,2018-03-11 15:00:30,2018-01-24 21:48:22,2018-12-27 13:31:21,2018-08-10 23:29:32 -801,Ashli,Romain,886-453-6140,Female,6,12,19,2018-02-24 23:38:53,2018-05-01 04:29:06,2018-06-03 17:41:53,2018-04-21 00:29:25 -802,Keeley,Frankom,894-599-8867,Female,3,30,4,2019-01-05 18:11:47,2018-03-25 21:31:27,2018-05-26 03:52:58,2018-10-23 16:17:28 -803,Curcio,Widmoor,934-987-4248,Male,5,23,84,2018-03-31 07:42:11,2018-10-25 03:00:08,2018-10-18 23:14:42,2018-05-07 19:58:59 -804,Crawford,Ballston,771-623-5016,Male,5,24,48,2018-12-27 07:13:13,2019-01-09 10:21:22,2018-05-20 08:49:26,2018-09-16 08:46:49 -805,Templeton,Snibson,650-275-2922,Male,3,55,83,2018-12-04 05:22:30,2018-09-29 21:23:56,2018-03-08 17:58:24,2018-08-15 02:38:52 -806,Gail,Peachment,906-123-1774,Male,4,59,13,2018-09-21 07:44:03,2018-08-02 22:34:51,2018-03-08 07:11:39,2018-08-25 15:39:59 -807,Adriano,Escale,888-817-1180,Male,3,92,78,2018-07-24 16:32:20,2018-02-22 12:50:50,2018-06-26 12:34:44,2018-06-06 08:04:35 -808,Trista,Tudgay,340-171-5505,Female,5,44,62,2018-09-04 12:09:41,2018-01-31 01:51:09,2018-09-13 08:38:11,2018-06-06 05:49:50 -809,Angie,Carradice,507-239-1908,Female,1,12,69,2018-08-13 18:36:13,2018-11-23 03:57:42,2018-06-17 07:44:13,2018-12-09 16:37:23 -810,Maureen,Perllman,116-299-8383,Female,1,91,1,2018-04-10 06:12:02,2018-08-02 04:31:50,2018-06-18 00:58:20,2018-10-12 02:31:31 -811,Renaud,Roylance,267-492-3743,Male,3,36,85,2018-02-05 00:59:50,2018-11-26 02:06:43,2018-11-16 00:25:18,2018-02-02 08:38:37 -812,Dasi,Rhucroft,505-753-6245,Female,4,96,84,2018-11-10 18:36:26,2018-07-17 05:54:10,2018-07-12 13:34:58,2018-11-10 01:57:49 -813,Arlee,Gerdts,220-186-9711,Female,6,76,30,2018-12-26 11:24:38,2018-11-21 22:09:49,2018-04-16 14:09:09,2018-05-27 06:24:32 -814,Darrel,Maseres,540-324-4576,Male,6,20,52,2018-01-25 13:38:00,2019-01-11 23:26:49,2018-07-10 03:23:20,2018-06-27 20:41:34 -815,Merle,Haggie,867-109-5010,Male,5,96,73,2018-05-11 09:41:28,2018-02-26 23:39:01,2019-01-18 06:20:26,2018-11-24 20:35:34 -816,Jordanna,Slocket,561-552-2274,Female,3,64,28,2018-06-05 00:07:31,2018-10-24 18:30:56,2018-04-11 09:26:10,2018-07-17 15:09:53 -817,Rosa,Naulty,104-742-5724,Female,1,49,36,2018-07-25 05:49:28,2018-12-11 01:12:50,2018-04-02 22:12:09,2019-01-03 01:54:51 -818,Abbott,Nenci,465-121-4813,Male,3,79,57,2018-11-14 21:12:41,2018-03-22 04:16:18,2018-08-26 18:31:33,2018-05-16 10:32:25 -819,Edsel,Brockley,602-592-8501,Male,1,30,96,2018-01-21 00:58:41,2018-12-18 18:52:15,2018-03-18 23:16:05,2018-11-22 00:32:00 -820,Rickie,Tace,237-311-6775,Female,4,14,43,2018-07-28 16:49:11,2018-12-14 07:30:09,2018-02-18 22:51:29,2018-06-05 16:20:34 -821,Shaun,Stagg,356-435-7464,Female,7,54,35,2018-09-08 08:01:19,2018-03-09 16:11:16,2019-01-16 17:00:44,2018-11-30 14:34:15 -822,Alfred,Durden,512-204-4387,Male,2,79,46,2018-12-31 13:42:16,2018-05-24 21:54:26,2018-07-10 23:33:53,2018-08-10 04:33:54 -823,Christoffer,Bolderstone,868-441-3575,Male,6,4,30,2018-11-03 00:46:09,2018-04-30 04:41:20,2018-07-26 23:17:02,2018-04-27 19:17:50 -824,Ellette,Robard,806-623-1247,Female,2,59,70,2018-01-31 22:31:04,2018-01-28 04:26:39,2018-06-10 10:50:30,2018-11-01 17:27:42 -825,Loren,Mitrovic,840-960-0930,Male,7,27,31,2018-11-09 15:53:11,2018-03-25 02:53:57,2018-12-15 15:59:47,2018-06-20 19:00:48 -826,Leigh,Beebee,483-570-2017,Male,5,56,99,2018-03-27 09:56:26,2018-09-05 03:40:42,2018-12-13 03:28:25,2018-11-23 13:45:15 -827,Debby,Beldham,686-330-6591,Female,5,65,17,2018-08-01 18:59:48,2018-03-24 14:20:35,2019-01-10 21:11:42,2018-12-19 08:48:47 -828,Barron,Lowell,115-742-2050,Male,5,85,65,2018-03-03 04:32:02,2018-04-24 11:36:33,2018-09-15 15:08:52,2018-06-25 22:46:54 -829,Randi,Skydall,223-820-2793,Male,2,86,47,2018-07-20 00:15:51,2018-06-26 06:23:43,2018-12-28 12:30:07,2018-08-25 21:27:50 -830,Isabel,Roggerone,927-569-8210,Female,4,85,41,2018-09-23 13:54:09,2018-03-09 05:31:36,2018-06-11 18:42:42,2018-04-13 18:03:27 -831,Alvan,Geake,401-432-6471,Male,5,71,66,2018-03-29 20:49:43,2018-04-25 14:10:14,2018-07-24 01:39:45,2018-12-24 09:39:46 -832,Sophey,Jeandel,338-361-7635,Female,6,60,18,2018-08-05 04:29:15,2018-09-21 05:26:30,2018-06-08 07:30:41,2018-12-27 19:45:07 -833,Howie,Maxsted,197-553-3905,Male,5,94,69,2018-08-25 23:10:38,2019-01-20 02:12:00,2019-01-15 20:11:44,2018-02-13 17:46:32 -834,Padraig,Torr,529-469-0039,Male,1,62,17,2018-03-14 04:21:56,2018-06-08 14:24:59,2018-10-08 09:31:56,2018-08-30 02:59:15 -835,Shirl,Jeratt,713-937-2841,Female,2,18,89,2018-09-25 03:56:45,2018-07-17 02:54:21,2019-01-08 21:13:42,2018-02-20 17:16:17 -836,Durward,Kermott,625-654-9223,Male,6,67,25,2018-02-14 15:04:10,2018-03-23 06:42:12,2018-09-16 13:56:48,2018-03-10 11:02:08 -837,Rici,Francie,992-830-9527,Female,5,75,22,2018-07-21 07:35:59,2018-01-24 21:24:42,2018-12-20 10:46:19,2018-04-27 01:28:33 -838,Vivian,Suddell,715-471-1918,Female,6,81,45,2018-07-29 02:06:46,2018-10-15 14:05:00,2018-06-12 17:01:30,2018-05-12 22:22:36 -839,Eugenia,Tudhope,527-791-1359,Female,2,95,25,2019-01-05 12:54:58,2018-12-12 20:07:15,2018-12-22 12:11:13,2018-12-25 06:49:43 -840,Hamnet,Gateman,792-883-5589,Male,1,84,45,2018-06-26 04:15:53,2018-02-21 14:45:49,2018-08-29 18:01:14,2019-01-15 09:03:43 -841,Laraine,Emma,256-645-5057,Female,3,88,52,2018-05-29 03:26:20,2018-03-10 02:05:24,2018-05-12 21:29:38,2018-12-10 02:39:56 -842,Harley,D'Ruel,359-498-9270,Male,4,16,57,2018-02-15 07:39:22,2018-08-24 22:23:10,2018-07-19 02:07:06,2018-02-13 01:45:52 -843,Theda,Eades,222-998-5683,Female,7,2,71,2018-03-06 07:09:18,2018-09-14 11:46:16,2018-11-23 01:07:59,2018-12-02 03:37:22 -844,Giselbert,Klimentyev,165-127-0115,Male,6,88,93,2018-11-13 03:56:59,2018-04-09 02:33:25,2018-07-04 00:34:57,2018-06-04 05:56:23 -845,Lynnet,Tidd,370-452-0577,Female,6,47,3,2018-08-25 20:45:24,2018-08-27 16:50:01,2018-08-22 21:33:48,2018-06-27 22:32:52 -846,Donetta,Giannassi,913-466-0403,Female,2,39,55,2018-02-26 16:34:20,2018-07-10 03:35:10,2018-09-29 14:23:34,2018-10-10 13:02:02 -847,Conrade,Ruddell,514-722-6544,Male,3,13,100,2018-05-31 18:14:29,2018-10-19 05:51:32,2018-11-22 09:45:08,2018-02-22 05:00:31 -848,Tynan,Ritchie,552-416-9192,Male,4,50,26,2018-02-13 01:36:31,2018-07-24 03:28:00,2018-02-22 16:37:36,2018-02-28 07:16:54 -849,Erv,Huggins,528-946-8385,Male,3,73,82,2018-03-23 14:37:41,2018-08-12 12:26:08,2018-02-09 16:56:21,2018-08-09 06:33:34 -850,Darby,Ambrogini,266-338-3612,Male,6,92,21,2018-04-27 07:57:01,2018-10-19 20:49:49,2018-02-10 16:39:59,2018-09-03 00:53:41 -851,Devondra,Boc,775-193-7341,Female,5,36,51,2018-10-18 04:36:21,2018-10-28 14:06:15,2018-03-25 15:47:47,2018-08-20 22:31:48 -852,Meggy,Paxforde,435-917-5199,Female,2,40,85,2018-08-27 05:39:35,2018-01-23 20:18:58,2018-02-01 16:43:58,2018-08-07 12:15:36 -853,Pattie,Macallam,901-370-6579,Female,1,4,32,2018-07-11 10:30:06,2018-10-01 12:33:55,2018-02-08 02:35:59,2018-11-30 18:29:14 -854,Ray,Thayre,822-459-4971,Male,7,13,79,2018-07-13 03:44:05,2018-07-07 04:47:58,2018-08-28 19:24:34,2018-08-13 10:49:03 -855,Sindee,Gong,919-731-7167,Female,6,23,3,2018-12-08 15:31:48,2018-04-27 17:10:40,2018-07-14 14:10:46,2018-09-23 22:25:52 -856,Giovanni,Elsie,739-171-4273,Male,3,100,20,2018-11-22 21:14:50,2018-09-29 00:12:07,2018-05-17 09:43:48,2018-04-05 15:26:17 -857,Hadley,Davidde,813-908-2619,Male,7,64,65,2018-01-31 19:26:32,2018-11-10 09:08:19,2018-06-20 20:16:01,2018-04-18 19:33:00 -858,Jud,Schleicher,248-874-9513,Male,1,24,8,2018-04-06 16:54:03,2018-12-08 11:46:05,2018-10-02 20:22:44,2018-04-27 09:04:18 -859,Berget,Rasmus,599-370-5265,Female,2,46,8,2018-11-11 16:46:30,2018-11-24 16:42:40,2019-01-05 12:53:51,2018-12-17 18:41:54 -860,Floris,Lelliott,495-754-4852,Female,1,35,72,2019-01-06 22:27:28,2018-06-14 07:45:20,2018-10-25 10:22:56,2018-07-09 00:48:19 -861,Marianna,Huge,136-171-1910,Female,1,92,73,2018-05-04 21:19:28,2018-04-08 18:45:35,2018-02-08 18:06:55,2018-07-12 04:08:00 -862,Federica,Seakings,778-573-1492,Female,5,42,100,2018-02-18 23:40:45,2018-08-29 22:07:35,2018-06-27 21:37:10,2018-06-27 18:13:29 -863,Christophorus,Tett,516-196-0657,Male,3,68,89,2018-09-28 20:37:26,2018-07-03 17:19:03,2018-04-20 09:01:09,2018-06-11 11:31:56 -864,Kathlin,Hubbart,400-384-9734,Female,5,75,62,2018-09-23 11:16:50,2018-11-22 07:00:07,2018-11-12 09:29:23,2018-03-19 17:19:13 -865,Toinette,Christophersen,222-218-6841,Female,4,81,80,2018-06-24 07:27:29,2018-03-08 17:25:42,2018-11-19 23:39:15,2018-04-02 19:04:26 -866,Mei,Dragon,891-366-6658,Female,2,14,22,2018-03-17 07:33:08,2018-06-23 20:11:56,2018-10-30 02:21:14,2018-10-21 08:13:29 -867,Wileen,Guittet,118-965-5819,Female,7,22,73,2018-04-12 00:04:07,2018-08-23 08:56:44,2018-07-09 08:29:36,2018-02-22 06:45:41 -868,Bill,Skechley,531-261-9052,Female,1,93,45,2018-03-25 13:30:53,2018-10-17 03:47:35,2018-10-18 02:26:47,2018-12-08 19:05:40 -869,Chrissy,Rapley,863-731-8995,Female,7,17,8,2018-09-12 01:35:07,2018-07-22 15:02:10,2018-06-18 19:06:47,2018-12-22 20:00:52 -870,Gwynne,Hymers,287-878-7144,Female,4,6,29,2018-08-19 13:41:56,2018-12-10 18:23:35,2018-03-26 01:25:26,2018-07-05 16:38:09 -871,Noland,Hornung,922-794-4200,Male,3,66,82,2018-12-10 23:49:55,2018-09-15 01:16:20,2018-10-24 20:37:00,2018-10-27 07:56:58 -872,Sybila,Caren,883-754-0514,Female,1,40,33,2018-11-01 03:29:07,2018-03-07 23:07:07,2018-09-06 01:46:46,2018-03-17 17:02:04 -873,Arnaldo,Ortelt,648-204-0219,Male,5,24,20,2018-04-19 00:26:30,2018-06-09 12:00:33,2018-09-30 00:21:33,2018-07-12 18:59:39 -874,Sascha,Thurner,504-586-1976,Male,4,9,34,2018-09-03 11:21:47,2018-12-06 09:23:43,2018-11-21 03:43:51,2018-05-28 10:34:36 -875,Janeva,Stallion,168-726-9745,Female,7,66,60,2018-07-05 04:40:09,2018-02-19 12:25:04,2018-05-31 06:47:34,2018-01-24 21:43:59 -876,Imelda,Daintrey,786-279-9676,Female,5,26,12,2018-07-29 01:32:45,2018-05-21 03:09:18,2018-10-03 07:09:16,2018-12-28 16:07:06 -877,Kaia,Pauleit,937-468-0457,Female,5,36,63,2018-08-20 03:23:06,2018-09-20 08:02:05,2018-05-13 23:35:38,2018-03-19 03:48:06 -878,Fons,Coton,673-868-5084,Male,6,51,39,2018-02-28 14:51:40,2018-08-02 02:13:10,2018-02-01 01:38:38,2018-09-22 00:49:46 -879,Amalee,Groneway,336-875-1596,Female,5,19,58,2018-04-12 20:12:37,2018-11-27 06:39:14,2018-09-18 01:05:22,2018-04-22 08:39:02 -880,Paquito,O'Dwyer,324-526-6202,Male,7,99,41,2018-10-12 02:35:53,2018-02-10 00:52:03,2018-02-07 03:12:35,2018-10-18 21:47:13 -881,Shea,Forst,307-995-7972,Female,1,41,41,2018-10-02 02:03:39,2018-10-24 23:10:36,2019-01-09 17:11:05,2018-05-16 22:15:02 -882,Sylvan,McKimm,999-270-7047,Male,1,21,29,2018-04-13 22:42:31,2018-12-10 08:47:39,2018-05-25 01:01:54,2018-04-17 08:03:17 -883,Peyter,Rotte,919-508-2810,Male,3,51,43,2018-05-25 10:20:40,2018-05-07 09:22:17,2018-10-29 16:34:13,2018-05-08 18:00:18 -884,Ernestine,Jankowski,998-337-8068,Female,3,7,44,2018-01-22 22:18:12,2018-11-04 08:03:53,2019-01-14 13:07:45,2018-01-25 10:53:54 -885,Bridget,Pettet,701-799-8814,Female,5,84,73,2018-04-24 13:06:17,2018-09-27 02:37:43,2018-11-23 08:52:31,2018-08-30 18:46:39 -886,Arlana,Wisniowski,321-679-5349,Female,7,1,72,2018-09-20 23:41:45,2018-07-29 00:16:49,2018-02-08 09:55:35,2018-04-07 15:34:38 -887,Darbie,Verzey,936-723-9548,Female,6,95,2,2018-09-15 23:29:11,2018-01-28 09:02:28,2018-12-05 08:05:15,2018-02-08 01:02:29 -888,Quintana,Nutley,896-674-7083,Female,3,38,16,2018-07-22 20:52:42,2018-09-19 19:39:52,2018-04-29 01:58:40,2018-07-30 22:07:46 -889,Padgett,Urwen,141-490-6319,Male,6,32,96,2018-05-09 19:03:45,2018-04-07 12:16:47,2018-07-17 13:53:15,2018-09-19 15:54:14 -890,Beret,Gilchrest,524-146-3660,Female,3,30,45,2018-12-09 18:08:35,2018-02-09 07:44:41,2019-01-09 06:31:54,2018-06-03 05:03:43 -891,Jacquette,McBlain,180-111-2719,Female,5,45,49,2018-08-25 23:50:05,2018-08-14 04:10:24,2018-06-28 01:21:56,2018-05-09 06:07:09 -892,Heriberto,Hardway,934-411-2153,Male,7,100,67,2018-08-12 07:20:08,2018-08-30 23:04:44,2018-08-09 09:18:15,2018-08-21 13:19:44 -893,Charo,Cheeney,934-194-4292,Female,2,79,49,2018-02-19 02:30:34,2018-07-26 21:32:10,2018-03-14 13:44:53,2019-01-02 19:07:53 -894,Barty,Delacour,352-181-7260,Male,7,68,1,2018-02-08 11:54:33,2018-12-22 15:26:11,2018-05-05 05:29:07,2018-01-28 16:34:01 -895,Arel,Qusklay,776-527-2939,Male,6,72,24,2018-02-10 23:05:47,2018-10-31 16:14:34,2018-04-17 06:36:20,2018-09-21 15:13:20 -896,Cleon,Westcarr,735-686-0389,Male,1,56,68,2018-12-14 09:21:13,2018-08-04 15:56:37,2018-09-09 11:38:56,2018-03-19 03:56:38 -897,Nicole,Gorrie,216-361-4858,Female,2,65,77,2018-08-05 12:50:07,2018-03-10 14:07:01,2018-02-15 13:44:04,2019-01-06 01:05:50 -898,Issiah,Patters,901-518-7348,Male,7,40,78,2018-04-27 08:43:08,2018-11-08 01:40:02,2018-02-05 13:31:35,2018-08-05 21:26:55 -899,Kimbell,Torvey,614-432-0846,Male,3,46,34,2018-10-10 17:10:59,2018-04-09 13:30:10,2018-12-26 11:39:55,2018-03-11 23:16:21 -900,Arabel,Reaney,250-158-0650,Female,1,39,42,2018-06-24 20:58:36,2018-06-13 01:05:57,2018-09-21 12:17:09,2018-05-12 01:20:04 -901,Lowrance,Birckmann,707-493-5823,Male,3,40,81,2018-10-30 04:51:25,2018-04-14 15:18:25,2018-11-26 23:12:20,2018-11-19 04:09:43 -902,Sande,Tinson,644-792-0309,Female,1,4,93,2018-06-05 12:30:15,2018-06-05 01:29:00,2018-04-13 08:38:54,2018-12-10 03:36:34 -903,Antonetta,Twelve,506-143-6120,Female,7,95,49,2018-10-15 14:45:58,2018-11-02 11:22:24,2018-02-20 23:03:06,2018-02-13 22:09:09 -904,Marietta,Christensen,356-415-2235,Male,5,80,58,2018-10-22 11:01:49,2018-02-01 17:42:35,2018-11-22 02:54:09,2018-09-30 12:05:18 -905,Jodee,Pietraszek,300-188-3774,Female,4,10,37,2018-10-23 06:33:49,2018-10-21 00:19:46,2018-11-29 18:55:51,2018-11-06 15:41:47 -906,Marthena,Kitson,601-214-9309,Female,4,28,26,2018-07-23 16:23:23,2018-06-22 12:00:30,2018-12-01 12:31:45,2018-12-23 15:09:43 -907,Daron,Mackison,682-377-7219,Female,4,89,96,2018-05-28 03:03:57,2018-03-02 01:25:11,2018-12-01 09:00:59,2018-02-21 02:24:22 -908,Hube,Feldhuhn,942-914-1709,Male,5,24,35,2018-10-02 04:25:27,2018-06-28 02:29:41,2018-02-06 01:40:17,2018-04-23 22:52:35 -909,Loretta,Pritty,613-563-4790,Female,7,75,82,2018-07-08 17:13:07,2018-11-22 22:05:00,2018-10-30 22:21:57,2018-08-13 01:05:15 -910,Cathyleen,McCallion,883-828-7510,Female,2,45,11,2018-09-09 14:13:19,2018-01-31 15:57:37,2018-08-13 04:55:36,2018-09-09 10:40:55 -911,Haleigh,Gleader,682-121-8965,Female,3,8,38,2018-12-20 06:38:29,2019-01-17 01:03:40,2019-01-19 16:23:53,2018-08-17 03:24:51 -912,Charles,Rosengarten,618-810-0078,Male,2,93,36,2018-10-15 16:20:15,2018-12-28 14:31:32,2018-09-12 08:52:44,2018-07-15 21:25:15 -913,Bjorn,Erskine Sandys,529-581-3333,Male,3,75,81,2018-04-14 17:13:49,2018-10-21 15:46:05,2018-05-28 06:44:30,2018-08-10 04:37:46 -914,Darill,Bostock,625-801-8242,Male,2,81,23,2018-10-11 19:47:21,2018-06-12 04:06:41,2019-01-15 07:56:54,2018-04-28 18:50:01 -915,Noellyn,Benwell,722-714-8266,Female,2,11,12,2018-02-15 07:48:35,2018-04-07 17:41:22,2018-05-18 02:39:40,2018-07-22 07:12:38 -916,Dov,Letrange,300-443-5277,Male,5,91,80,2018-12-27 15:44:06,2018-06-01 01:17:13,2018-06-04 08:44:49,2018-05-07 08:43:09 -917,Olympie,Louden,465-432-6397,Female,1,19,13,2018-01-25 05:55:27,2018-06-19 10:44:49,2018-10-06 16:38:12,2018-11-22 20:46:37 -918,Finley,Casbon,425-531-2684,Male,4,85,21,2018-09-04 05:24:44,2018-10-19 21:14:24,2018-09-24 15:11:59,2018-07-02 05:41:48 -919,Dewitt,Krolak,700-648-7734,Male,7,43,3,2018-04-11 09:56:52,2018-07-11 01:42:09,2018-02-28 00:53:56,2018-06-20 15:39:09 -920,Noby,De la Yglesia,405-211-0709,Male,4,1,49,2018-12-05 02:27:53,2018-07-03 10:21:49,2018-09-23 09:16:19,2018-05-12 09:47:56 -921,Aloysius,Baggs,272-379-1280,Male,2,40,53,2018-05-14 22:08:41,2018-12-03 09:03:58,2018-07-15 04:40:33,2018-09-15 06:12:36 -922,Karilynn,Costa,732-871-1192,Female,2,68,76,2018-12-29 05:05:50,2018-12-23 08:00:43,2018-04-13 17:50:47,2018-03-24 11:13:51 -923,Ky,Waggett,413-701-9663,Male,5,7,59,2018-02-05 06:17:54,2018-07-07 03:47:33,2018-09-13 00:11:05,2018-12-21 03:34:37 -924,Leeanne,Neasam,130-573-1360,Female,4,74,77,2018-11-30 04:33:22,2018-03-26 07:40:00,2018-05-03 16:40:09,2018-05-10 20:32:41 -925,Muffin,Eades,789-128-6773,Male,4,84,25,2018-04-19 09:16:22,2018-11-08 03:55:54,2018-02-03 05:36:52,2018-10-21 22:14:13 -926,Iormina,Baudry,644-418-1313,Female,4,72,19,2019-01-16 00:35:47,2018-11-23 14:35:13,2018-04-06 17:59:52,2018-02-24 14:59:31 -927,Fabe,Ziemke,161-651-6080,Male,6,36,12,2019-01-14 08:28:41,2018-10-28 13:42:55,2018-07-07 04:53:18,2018-08-04 15:37:00 -928,Danni,Leese,768-599-1814,Female,7,30,71,2018-11-08 21:26:44,2018-05-01 17:49:56,2018-08-03 00:06:41,2018-10-18 08:20:47 -929,Rycca,Petegre,433-887-8926,Female,4,5,34,2018-07-02 07:56:41,2018-02-10 11:51:30,2018-04-08 10:08:07,2018-06-11 19:43:31 -930,Berkie,Reveland,791-499-2738,Male,1,57,80,2018-07-18 08:14:02,2018-04-15 08:54:18,2018-09-25 23:13:59,2018-08-12 23:49:27 -931,Tommy,Swett,915-667-6497,Male,1,98,11,2018-06-26 21:33:59,2018-07-10 07:15:47,2018-07-15 03:48:37,2018-04-01 11:58:09 -932,Derrek,Perkinson,169-674-1053,Male,4,85,25,2018-08-23 05:51:09,2018-09-17 23:57:57,2018-03-06 01:30:46,2018-05-06 22:10:10 -933,Lonni,Polycote,996-492-4081,Female,2,7,6,2018-06-09 22:12:53,2018-04-09 09:26:53,2018-07-19 03:36:09,2018-12-01 16:50:15 -934,Phyllis,Gallamore,788-489-0287,Female,4,32,71,2018-07-08 11:07:20,2018-05-25 09:24:00,2018-04-23 04:53:35,2019-01-19 16:11:17 -935,Brittne,Caccavari,799-716-9817,Female,2,53,25,2018-12-11 00:47:47,2018-01-22 09:05:30,2018-09-30 14:03:22,2018-08-09 05:13:34 -936,Quinn,Torricina,342-560-9404,Female,3,60,72,2019-01-06 06:26:23,2018-11-21 02:21:54,2018-02-15 20:43:28,2018-08-15 17:59:55 -937,Jacklyn,Bohling,824-878-8873,Female,1,41,34,2018-06-23 18:52:40,2018-05-14 22:58:13,2018-06-08 07:11:42,2018-08-04 15:57:46 -938,Hunfredo,Millam,816-916-1240,Male,1,86,58,2019-01-08 04:02:45,2019-01-12 17:57:33,2019-01-20 14:58:14,2018-12-03 22:29:35 -939,Hymie,Vosse,980-181-0718,Male,4,67,59,2018-12-25 10:58:52,2018-03-09 06:50:03,2018-03-03 04:06:28,2018-07-17 18:26:14 -940,Olia,Wyse,875-970-0069,Female,4,54,96,2018-11-01 03:11:42,2018-12-29 18:01:06,2018-05-01 00:58:58,2018-08-29 17:41:08 -941,Arline,Bierton,582-902-5400,Female,4,36,83,2018-11-19 01:06:41,2018-07-20 08:22:25,2018-02-15 09:56:13,2018-07-07 12:00:06 -942,Nevsa,Jacquot,393-800-6240,Female,3,76,100,2018-12-03 03:10:20,2018-10-05 15:30:34,2018-07-03 08:10:26,2019-01-15 02:21:14 -943,Analise,Bechley,178-276-2761,Female,4,10,4,2018-08-03 05:49:50,2018-12-25 22:04:16,2019-01-18 22:16:01,2018-03-07 14:10:26 -944,Siffre,Cumbridge,484-369-3900,Male,1,30,98,2018-11-08 05:35:17,2018-07-06 03:41:16,2018-03-26 11:58:13,2018-10-05 22:55:01 -945,Berget,Oldred,470-380-7016,Female,2,34,3,2018-12-24 01:06:10,2018-03-01 08:09:07,2018-08-27 19:47:44,2018-07-15 17:16:39 -946,Aaron,Arnison,195-265-7576,Male,4,68,94,2018-06-02 08:58:18,2018-08-03 00:56:00,2018-05-06 14:32:24,2018-02-16 07:54:16 -947,Fay,Sarfas,659-275-5381,Female,6,34,96,2019-01-02 00:06:51,2018-12-05 05:47:36,2018-04-22 03:52:40,2018-09-20 19:16:51 -948,Pennie,Rappaport,851-746-8484,Female,5,74,57,2018-06-13 14:50:19,2018-05-10 00:00:37,2018-05-03 15:48:50,2018-12-06 19:15:10 -949,Ennis,Schindler,685-873-8208,Male,2,9,15,2018-12-06 10:23:57,2018-06-05 08:10:38,2018-08-19 04:20:22,2018-08-31 04:33:19 -950,Sean,Breckwell,511-213-8051,Male,4,65,20,2018-06-20 04:24:36,2018-12-24 06:27:41,2018-07-17 12:13:34,2018-06-02 06:09:01 -951,Carlene,Vials,130-632-1736,Female,2,71,12,2018-03-26 06:16:26,2018-03-25 23:10:14,2018-03-02 15:43:13,2018-06-01 08:30:44 -952,Nerita,Paolinelli,943-836-6191,Female,2,88,24,2018-11-19 20:39:05,2018-09-18 20:22:25,2018-07-16 13:15:28,2018-12-21 02:47:25 -953,Benoite,Gheorghescu,378-772-1101,Female,4,78,44,2018-11-09 02:22:49,2019-01-09 18:23:07,2018-04-05 11:06:02,2018-05-14 05:39:56 -954,Erik,Auchterlonie,766-720-0406,Male,1,17,56,2018-03-01 23:55:26,2018-10-18 17:00:40,2018-07-12 00:30:26,2018-11-30 15:38:30 -955,Jesse,Laurenty,586-274-7629,Female,2,10,63,2018-08-16 12:07:51,2018-05-30 23:14:43,2018-06-19 02:24:42,2018-03-17 09:24:46 -956,Lynnet,Cuel,652-339-4808,Female,1,26,91,2018-11-05 19:14:13,2018-11-22 14:06:17,2018-12-25 13:52:54,2018-10-28 04:14:09 -957,Marge,Adnet,901-394-6344,Female,7,46,51,2018-02-21 02:14:23,2018-12-29 22:39:34,2018-03-27 11:48:32,2019-01-05 10:26:02 -958,Clara,Rangeley,154-876-9501,Female,6,73,50,2018-07-06 13:52:31,2018-05-28 12:09:22,2018-09-08 04:19:54,2018-09-02 19:04:27 -959,Ciel,Ching,205-133-7293,Female,7,26,19,2018-06-13 01:00:22,2018-06-26 05:13:24,2018-03-12 09:15:19,2018-06-29 23:55:03 -960,Phebe,Pentecust,671-551-3717,Female,6,79,26,2018-07-17 05:39:55,2018-05-28 11:52:54,2018-11-17 17:20:32,2018-07-27 07:39:40 -961,Koralle,Doleman,733-411-3555,Female,4,50,86,2018-10-28 12:28:47,2018-04-19 14:24:23,2018-04-19 20:04:57,2018-11-03 19:27:30 -962,Gypsy,Ashard,627-318-6598,Female,4,84,97,2018-10-29 08:41:04,2018-04-12 21:17:30,2019-01-12 05:14:18,2018-08-11 13:20:16 -963,Zebedee,Guilayn,442-936-9333,Male,3,35,49,2018-06-20 19:42:39,2019-01-19 12:44:29,2018-10-03 09:52:26,2018-11-23 22:02:46 -964,Waldemar,Isaak,931-973-9119,Male,4,82,45,2018-04-23 15:37:02,2018-05-09 15:24:30,2018-02-14 08:08:10,2018-07-03 18:15:44 -965,Zackariah,Donaway,407-803-4328,Male,1,89,1,2018-07-08 18:27:27,2018-03-04 22:13:59,2018-12-18 03:57:10,2018-07-07 10:37:23 -966,Amie,Graddon,806-683-2495,Female,7,24,48,2018-08-12 05:59:08,2018-02-02 02:33:10,2018-12-27 15:24:26,2018-09-09 14:21:34 -967,Homere,Hinkes,540-511-8058,Male,2,18,21,2018-02-15 19:40:23,2018-03-12 20:21:06,2018-07-24 20:35:51,2018-11-05 01:00:48 -968,Hildy,Romaint,578-715-3279,Female,1,64,42,2018-08-05 12:04:55,2018-10-30 20:39:13,2018-11-01 10:01:51,2018-10-13 16:01:35 -969,Norbie,Reinhardt,522-463-8856,Male,6,73,39,2018-12-26 16:31:22,2018-05-04 07:05:54,2018-11-01 19:36:06,2018-08-22 23:10:40 -970,Farlee,Robb,921-988-0129,Male,2,92,32,2018-09-25 21:50:48,2018-01-29 06:17:06,2018-12-05 20:31:07,2018-10-13 17:19:53 -971,Husain,Coomes,167-999-0871,Male,7,43,13,2018-06-22 13:30:21,2018-10-26 10:44:10,2019-01-18 20:06:38,2018-12-02 03:52:12 -972,Milo,Ikringill,848-791-7005,Male,6,93,81,2018-04-23 10:40:56,2018-11-16 14:25:18,2018-05-08 11:02:49,2018-09-27 02:14:23 -973,Bendite,Ivan,797-480-5441,Female,4,19,47,2018-03-24 15:48:07,2019-01-18 21:56:06,2018-12-06 11:16:03,2018-03-11 17:19:09 -974,Dall,Hewson,361-271-3138,Male,7,51,12,2018-12-01 16:04:22,2018-07-19 15:52:08,2018-11-26 22:45:09,2018-02-12 13:20:52 -975,Alfonse,Paddell,215-108-6430,Male,3,67,39,2018-07-20 13:46:01,2019-01-09 15:28:08,2018-05-15 18:34:09,2018-09-24 12:02:27 -976,Rachelle,Parysowna,448-408-3939,Female,6,75,37,2019-01-08 01:40:17,2019-01-14 14:50:14,2018-09-08 20:13:56,2018-08-26 17:34:13 -977,Vlad,Massimo,958-382-7108,Male,6,83,50,2019-01-10 14:14:56,2018-04-03 09:05:13,2018-07-12 05:33:43,2018-08-03 07:52:29 -978,Orran,Labarre,603-601-4448,Male,1,62,88,2018-08-02 15:34:45,2018-11-25 10:40:27,2018-02-25 06:26:19,2018-08-02 08:35:57 -979,Goldi,McGaw,418-474-0723,Female,4,92,65,2018-03-02 17:07:20,2018-03-04 17:41:59,2018-08-24 13:07:56,2018-11-04 17:29:39 -980,Ddene,O'Halloran,269-505-5567,Female,5,40,82,2018-07-19 04:42:22,2018-10-21 20:43:40,2018-05-31 18:32:46,2018-05-27 23:48:19 -981,Franciska,Randalston,518-473-9956,Female,2,31,23,2018-08-10 19:43:25,2018-07-27 07:50:34,2018-09-05 22:19:23,2018-07-03 10:32:00 -982,Izak,Aaronson,559-374-9622,Male,3,42,87,2018-08-15 00:25:50,2018-04-15 10:04:12,2018-06-28 14:35:41,2018-01-21 11:06:29 -983,Trey,Battany,836-241-1102,Male,2,15,41,2019-01-10 17:37:08,2018-09-21 17:33:14,2018-10-31 07:41:53,2018-05-02 04:23:23 -984,Monty,Print,851-362-4374,Male,1,72,54,2018-07-29 11:59:40,2018-02-03 04:49:31,2019-01-10 13:05:52,2018-12-15 23:29:32 -985,Ashton,Cunnah,780-629-9147,Male,4,45,20,2018-02-10 13:25:53,2018-12-25 15:32:25,2018-01-23 10:29:44,2018-05-31 16:54:21 -986,Becky,Stavers,700-388-4222,Female,6,10,79,2018-03-04 20:32:59,2018-06-13 23:55:18,2018-06-02 22:41:53,2018-11-04 01:01:48 -987,Udall,Undrell,187-686-5781,Male,3,62,28,2018-07-29 04:00:33,2018-08-10 09:03:52,2018-12-20 19:09:22,2019-01-08 10:29:39 -988,Wait,Kippie,649-986-8035,Male,6,59,99,2018-08-26 01:11:54,2018-11-11 11:43:07,2018-11-26 18:10:23,2018-05-03 06:50:49 -989,Laurence,Dubs,725-348-9456,Male,5,80,78,2018-12-29 16:41:25,2018-03-04 01:25:41,2018-07-24 13:07:42,2018-03-02 01:22:54 -990,Cyrille,Ansley,464-181-4696,Male,7,71,25,2018-10-12 23:36:32,2018-05-18 07:03:48,2018-12-20 18:06:28,2018-09-16 15:37:18 -991,Emory,Manwell,415-640-8797,Male,5,12,56,2018-07-21 03:32:53,2018-11-15 00:05:50,2018-06-11 19:00:20,2018-03-30 06:39:44 -992,Chevalier,Pelosi,210-721-7355,Male,1,3,53,2018-09-10 01:51:52,2018-08-05 09:51:36,2018-07-09 12:50:42,2018-12-20 17:33:50 -993,Vale,Havenhand,885-493-5138,Male,5,37,72,2018-11-01 03:19:32,2018-11-02 06:12:05,2019-01-18 19:09:41,2018-07-29 06:54:36 -994,Shel,Kislingbury,683-829-9112,Female,2,57,75,2018-07-06 02:01:25,2018-11-17 02:11:03,2018-07-20 22:39:14,2018-05-08 16:48:52 -995,Kris,Rodear,296-572-9182,Male,5,24,22,2018-05-21 05:50:41,2018-12-04 14:27:38,2018-09-01 22:26:00,2018-09-05 14:46:56 -996,Jillayne,Mackerel,971-775-5324,Female,4,77,29,2018-08-29 09:36:26,2018-09-18 17:04:42,2018-12-08 03:41:26,2018-11-28 11:52:45 -997,Wilona,Yonnie,985-459-5111,Female,4,36,62,2018-08-07 01:17:54,2018-08-25 03:30:42,2018-02-17 20:26:24,2018-03-09 21:08:39 -998,Herbert,Liver,278-295-4343,Male,1,10,92,2018-04-27 00:14:36,2018-08-27 15:24:57,2018-02-11 18:53:26,2018-05-05 07:57:16 -999,Charmian,Robison,320-515-4401,Female,4,66,52,2018-11-29 19:32:40,2018-09-14 07:10:38,2018-07-04 09:36:16,2018-02-20 20:59:30 -1000,Cad,Alster,344-476-5489,Male,6,50,52,2018-09-12 09:49:44,2018-04-09 17:52:16,2018-12-18 02:15:47,2018-04-22 03:31:11 diff --git a/vitess-mixin/e2e/external_db/mysql/grant.sh b/vitess-mixin/e2e/external_db/mysql/grant.sh deleted file mode 100755 index 9371377d074..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/grant.sh +++ /dev/null @@ -1,7 +0,0 @@ - -echo '**********GRANTING PRIVILEGES START*******************' -echo ${mysql[@]} -# PURGE BINARY LOGS BEFORE DATE(NOW()); -mysql --protocol=socket -uroot -hlocalhost --socket=/var/run/mysqld/mysqld.sock -p$MYSQL_ROOT_PASSWORD -e \ -"GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD'" -echo '*************GRANTING PRIVILEGES END****************' diff --git a/vitess-mixin/e2e/external_db/mysql/mysql56.cnf b/vitess-mixin/e2e/external_db/mysql/mysql56.cnf deleted file mode 100644 index fdd34b1bd2e..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/mysql56.cnf +++ /dev/null @@ -1,41 +0,0 @@ -[mysqld] -# Options for enabling GTID -# https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html -gtid_mode = ON -log_bin -log_slave_updates -enforce_gtid_consistency - -# Crash-safe replication settings. -master_info_repository = TABLE -relay_log_info_repository = TABLE -relay_log_purge = 1 -relay_log_recovery = 1 - -# Native AIO tends to run into aio-max-nr limit during test startup. -innodb_use_native_aio = 0 - -# Semi-sync replication is required for automated unplanned failover -# (when the master goes away). Here we just load the plugin so it's -# available if desired, but it's disabled at startup. -# -# VTTablet will enable semi-sync at the proper time when replication is set up, -# or when a primary is promoted or demoted based on the durability policy configured. -plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so - -# When semi-sync is enabled, don't allow fallback to async -# if you get no ack, or have no slaves. This is necessary to -# prevent alternate futures when doing a failover in response to -# a master that becomes unresponsive. -rpl_semi_sync_master_timeout = 1000000000000000000 -rpl_semi_sync_master_wait_no_slave = 1 -server-id = 1 -# Remove ONLY_FULL_GROUP_BY until queries are fixed -sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" - -general_log = 1 -general_log_file = /var/log/mysql/query.log - -slow_query_log = 1 -long_query_time = 1 # seconds -slow_query_log_file = /var/log/mysql/slow.log \ No newline at end of file diff --git a/vitess-mixin/e2e/external_db/mysql/mysql57.cnf b/vitess-mixin/e2e/external_db/mysql/mysql57.cnf deleted file mode 100644 index ebf301187eb..00000000000 --- a/vitess-mixin/e2e/external_db/mysql/mysql57.cnf +++ /dev/null @@ -1,43 +0,0 @@ -# This file is auto-included when MySQL 5.7 is detected. - -# MySQL 5.7 does not enable the binary log by default, and -# info repositories default to file -[mysqld] -gtid_mode = ON -log_slave_updates -enforce_gtid_consistency -expire_logs_days = 3 -master_info_repository = TABLE -relay_log_info_repository = TABLE -relay_log_purge = 1 -relay_log_recovery = 1 - -# In MySQL 5.7 the default charset is latin1 - -character_set_server = utf8 -collation_server = utf8_general_ci - -# Semi-sync replication is required for automated unplanned failover -# (when the master goes away). Here we just load the plugin so it's -# available if desired, but it's disabled at startup. -# -# VTTablet will enable semi-sync at the proper time when replication is set up, -# or when a primary is promoted or demoted based on the durability policy configured. -plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so - -# When semi-sync is enabled, don't allow fallback to async -# if you get no ack, or have no slaves. This is necessary to -# prevent alternate futures when doing a failover in response to -# a master that becomes unresponsive. -rpl_semi_sync_master_timeout = 1000000000000000000 -rpl_semi_sync_master_wait_no_slave = 1 - -## Specific edits for this external_db ## -log_bin -server-id = 1 -general_log = 1 -general_log_file = /var/log/mysql/query.log - -slow_query_log = 1 -long_query_time = 1 # seconds -slow_query_log_file = /var/log/mysql/slow.log diff --git a/vitess-mixin/e2e/externaldb_vreplication.sh b/vitess-mixin/e2e/externaldb_vreplication.sh deleted file mode 100755 index 1138909aa13..00000000000 --- a/vitess-mixin/e2e/externaldb_vreplication.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -# Copyright 2020 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. - -set -ex - -VTCTLD_SERVER=${VTCTLD_SERVER:-'vtctld:15999'} - -# Wait until source and destination primaries are available -until (/vt/bin/vtctlclient --server $VTCTLD_SERVER ListAllTablets | grep "ext_" | grep "primary" ); do - echo 'waiting for external primary..'; - sleep 1; -done - -until (/vt/bin/vtctlclient --server $VTCTLD_SERVER ListAllTablets | grep -v "ext_" | grep "primary" ); do - echo 'waiting for managed primary..'; - sleep 1; -done - - -# Get source and destination tablet and shard information -TABLET_INFO=$(/vt/bin/vtctlclient --server $VTCTLD_SERVER ListAllTablets) -source_alias=$(echo "$TABLET_INFO "| grep "ext_" | grep "primary" | awk '{ print $1 }') -dest_alias=$(echo "$TABLET_INFO "| grep -v "ext_" | grep "primary" | awk '{ print $1 }') -source_keyspace=$(echo "$TABLET_INFO "| grep "ext_" | grep "primary" | awk '{ print $2 }') -dest_keyspace=$(echo "$TABLET_INFO "| grep -v "ext_" | grep "primary" | awk '{ print $2 }') -source_shard=$(echo "$TABLET_INFO "| grep "ext_" | grep "primary" | awk '{ print $3 }') -dest_shard=$(echo "$TABLET_INFO "| grep -v "ext_" | grep "primary" | awk '{ print $3 }') -source_tablet=$(echo "$TABLET_INFO "| grep "ext_" | grep "primary" | awk '{ print $2 "/" $3}') -dest_tablet=$(echo "$TABLET_INFO "| grep -v "ext_" | grep "primary" | awk '{ print $2 "/" $3}') - - -# Disable foreign_key checks on destination -/vt/bin/vtctlclient --server $VTCTLD_SERVER ExecuteFetchAsDba $dest_alias 'SET GLOBAL FOREIGN_KEY_CHECKS=0;' - -# Get source_sql mode -source_sql_mode=$(/vt/bin/vtctlclient --server $VTCTLD_SERVER ExecuteFetchAsDba $source_alias 'SELECT @@GLOBAL.sql_mode' | awk 'NR==4 {print $2}') - -# Apply source sql_mode to destination -# The intention is to avoid replication errors -/vt/bin/vtctlclient --server $VTCTLD_SERVER ExecuteFetchAsDba $dest_alias "SET GLOBAL sql_mode='$source_sql_mode';" - -# Verify sql_mode matches -[ $source_sql_mode == $(/vt/bin/vtctlclient --server $VTCTLD_SERVER ExecuteFetchAsDba $dest_alias 'SELECT @@GLOBAL.sql_mode' | awk 'NR==4 {print $2}') ] && \ -echo "Source and Destination sql_mode Match." || echo "sql_mode MisMatch" - -until /vt/bin/vtctlclient --server $VTCTLD_SERVER GetSchema $dest_alias; do - echo "Waiting for destination schema to be ready.."; - sleep 3; -done - -# Copy schema from source to destination shard -/vt/bin/vtctlclient --server $VTCTLD_SERVER CopySchemaShard $source_tablet $dest_tablet || true - -# Verify schema -/vt/bin/vtctlclient --server $VTCTLD_SERVER GetSchema $dest_alias - -# Start vreplication -/vt/bin/vtctlclient --server $VTCTLD_SERVER VReplicationExec $dest_alias 'insert into _vt.vreplication (db_name, source, pos, max_tps, max_replication_lag, tablet_types, time_updated, transaction_timestamp, state) values('"'"''"$dest_keyspace"''"'"', '"'"'keyspace:\"'"$source_keyspace"'\" shard:\"'"$source_shard"'\" filter: > on_ddl:EXEC_IGNORE '"'"', '"'"''"'"', 9999, 9999, '"'"'primary'"'"', 0, 0, '"'"'Running'"'"')' - -# Check vreplication status -/vt/bin/vtctlclient --server $VTCTLD_SERVER VReplicationExec $dest_alias 'select * from _vt.vreplication' - diff --git a/vitess-mixin/e2e/fix_replication.sh b/vitess-mixin/e2e/fix_replication.sh deleted file mode 100755 index e6a06c71124..00000000000 --- a/vitess-mixin/e2e/fix_replication.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This is a helper script to sync replicas for mysql. -# It handles the special case where the primary has purged bin logs that the replica requires. -# To use it place a mysql dump of the database on the same directory as this script. -# The name of the dump must be $KEYSPACE.sql. The script can also download the mysqldump for you. -# Replication is fixed by restoring the mysqldump and resetting the replica. -# https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-disable-gtids.html -# https://www.percona.com/blog/2013/02/08/how-to-createrestore-a-slave-using-gtid-replication-in-mysql-5-6/ - -cd "$(dirname "${BASH_SOURCE[0]}")" - -function get_replication_status() { - # Get replica status - STATUS_LINE=$(mysql -u$DB_USER -p$DB_PASS -h 127.0.0.1 -e "SHOW SLAVE STATUS\G") - LAST_ERRNO=$(grep "Last_IO_Errno:" <<< "$STATUS_LINE" | awk '{ print $2 }') - SLAVE_SQL_RUNNING=$(grep "Slave_SQL_Running:" <<< "$STATUS_LINE" | awk '{ print $2 }') - SLAVE_IO_RUNNING=$(grep "Slave_IO_Running:" <<< "$STATUS_LINE" | awk '{ print $2 }') - MASTER_HOST=$(grep "Master_Host:" <<< "$STATUS_LINE" | awk '{ print $2 }') - MASTER_PORT=$(grep "Master_Port:" <<< "$STATUS_LINE" | awk '{ print $2 }') - - echo "Slave_SQL_Running: $SLAVE_SQL_RUNNING" - echo "Slave_IO_Running: $SLAVE_IO_RUNNING" - echo "Last_IO_Errno: $LAST_ERRNO" -} - -function reset_replication() { - # Necessary before sql file can be imported - echo "Importing MysqlDump: $KEYSPACE.sql" - mysql -u$DB_USER -p$DB_PASS -h 127.0.0.1 -e "RESET MASTER;STOP SLAVE;CHANGE MASTER TO MASTER_AUTO_POSITION = 0;source $KEYSPACE.sql;START SLAVE;" - # Restore Master Auto Position - echo "Restoring Master Auto Setting" - mysql -u$DB_USER -p$DB_PASS -h 127.0.0.1 -e "STOP SLAVE;CHANGE MASTER TO MASTER_AUTO_POSITION = 1;START SLAVE;" -} - -# Retrieve replication status -get_replication_status - -# Exit script if called with argument 'status' -[ ${1:-''} != 'status' ] || exit 0; - -# Check if SLAVE_IO is running -if [[ $SLAVE_IO_RUNNING = "No" && $LAST_ERRNO = 1236 ]]; then - - echo "Primary has purged bin logs that replica requires. Sync will require restore from mysqldump" - if [[ -f $KEYSPACE.sql ]] ; then - echo "mysqldump file $KEYSPACE.sql exists, attempting to restore.." - echo "Resetting replication.." - reset_replication - else - echo "Starting mysqldump. This may take a while.." - # Modify flags to user's requirements - if mysqldump -h $MASTER_HOST -P $MASTER_PORT -u$DB_USER -p$DB_PASS --databases $KEYSPACE \ - --triggers --routines --events --hex-blob --master-data=1 --quick --order-by-primary \ - --no-autocommit --skip-comments --skip-add-drop-table --skip-add-locks \ - --skip-disable-keys --single-transaction --set-gtid-purged=on --verbose > $KEYSPACE.sql; then - echo "mysqldump complete for database $KEYSPACE" - echo "Resetting replication.." - reset_replication - else - echo "mysqldump failed for database $KEYSPACE" - fi - fi - -else - - echo "No Actions to perform" - -fi diff --git a/vitess-mixin/e2e/grafana/provisioning/dashboards/dashboard.yml b/vitess-mixin/e2e/grafana/provisioning/dashboards/dashboard.yml deleted file mode 100644 index edfcd4f2271..00000000000 --- a/vitess-mixin/e2e/grafana/provisioning/dashboards/dashboard.yml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: 1 - -providers: -- name: 'Vitess Mixin' - orgId: 1 - folder: '' - type: file - disableDeletion: false - editable: true - options: - path: /etc/grafana/provisioning/dashboards \ No newline at end of file diff --git a/vitess-mixin/e2e/grafana/provisioning/datasources/datasource.yml b/vitess-mixin/e2e/grafana/provisioning/datasources/datasource.yml deleted file mode 100644 index a2140b8834e..00000000000 --- a/vitess-mixin/e2e/grafana/provisioning/datasources/datasource.yml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: 1 - -deleteDatasources: - - name: Prometheus - orgId: 1 - -datasources: - -- name: Prometheus - type: prometheus - access: proxy - orgId: 1 - url: http://prometheus:9090 - user: - database: - basicAuth: false - basicAuthUser: - basicAuthPassword: - withCredentials: - isDefault: true - version: 1 - editable: true \ No newline at end of file diff --git a/vitess-mixin/e2e/lfixrepl.sh b/vitess-mixin/e2e/lfixrepl.sh deleted file mode 100755 index bd3e5646019..00000000000 --- a/vitess-mixin/e2e/lfixrepl.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Enable tty for Windows users using git-bash or cygwin -if [[ "$OSTYPE" == "msys" ]]; then - # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) - tty=winpty - script=//script//fix_replication.sh -fi - -# This is a convenience script to fix replication on replicas. -exec $tty docker-compose exec ${CS:-vttablet2} ${script:-/script/fix_replication.sh} "$@" \ No newline at end of file diff --git a/vitess-mixin/e2e/lmysql.sh b/vitess-mixin/e2e/lmysql.sh deleted file mode 100755 index d735e3783a8..00000000000 --- a/vitess-mixin/e2e/lmysql.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Enable tty for Windows users using git-bash or cygwin -if [[ "$OSTYPE" == "msys" ]]; then - # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) - tty=winpty -fi - -# This is a convenience script to run mysql client against the local example. -exec $tty docker-compose exec ${CS:-vttablet101} mysql "$@" diff --git a/vitess-mixin/e2e/load_test.sql b/vitess-mixin/e2e/load_test.sql deleted file mode 100644 index 71e7d805386..00000000000 --- a/vitess-mixin/e2e/load_test.sql +++ /dev/null @@ -1,46 +0,0 @@ --- INSERT TEST DATA --- mysql --port=15306 --host=127.0.0.1 < load_test.sql --- SIMULATED QUERIES --- mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=test_keyspace:80-@primary --query="SELECT * FROM messages;" --- mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=test_keyspace:80-@replica --query="SELECT * FROM messages;" --- mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=lookup_keyspace:-@primary --query="SELECT * FROM messages_message_lookup;" --- mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=lookup_keyspace:-@replica --query="SELECT * FROM messages_message_lookup;" --- SIMULATED ERRORS --- ╰─$ mysqlslap --port=15306 --host=127.0.0.1 --iterations=10000 --create-schema=test_keyspace:80-@primary --query="SELECT name FROM messages;" --- ╰─$ mysqlslap --port=15306 --host=127.0.0.1 --iterations=10000 --create-schema=lookup_keyspace:-@replica --query="SELECT name FROM messages_message_lookup;" - -USE test_keyspace:80-@primary; -INSERT INTO messages (page,time_created_ns,message) VALUES -(1,1,'test'), -(2,2,'test'), -(3,3,'test'), -(4,4,'test'), -(5,5,'test'), -(6,6,'test'), -(7,7,'test'), -(8,8,'test'), -(9,9,'test'); - -USE test_keyspace:-80@primary; -INSERT INTO messages (page,time_created_ns,message) VALUES -(10,1,'test'), -(11,2,'test'), -(12,3,'test'), -(13,4,'test'), -(14,5,'test'), -(15,6,'test'), -(16,7,'test'), -(17,8,'test'), -(18,9,'test'); - -USE lookup_keyspace:-@primary; -INSERT INTO messages_message_lookup (id,page,message) VALUES -(1,1,'test'), -(2,2,'test'), -(3,3,'test'), -(4,4,'test'), -(5,5,'test'), -(6,6,'test'), -(7,7,'test'), -(8,8,'test'), -(9,9,'test'); diff --git a/vitess-mixin/e2e/lookup_keyspace_vschema.json b/vitess-mixin/e2e/lookup_keyspace_vschema.json deleted file mode 100644 index f67289821fe..00000000000 --- a/vitess-mixin/e2e/lookup_keyspace_vschema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "sharded": true, - "tables": { - "messages_message_lookup": { - "column_vindexes": [ - { - "column": "id", - "name": "hash" - } - ] - }, - "tokens_token_lookup": { - "column_vindexes": [ - { - "column": "id", - "name": "hash" - } - ] - } - }, - "vindexes": { - "hash": { - "type": "hash" - } - } -} \ No newline at end of file diff --git a/vitess-mixin/e2e/lvtctl.sh b/vitess-mixin/e2e/lvtctl.sh deleted file mode 100755 index 64110743073..00000000000 --- a/vitess-mixin/e2e/lvtctl.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Enable tty for Windows users using git-bash or cygwin -if [[ "$OSTYPE" == "msys" ]]; then - # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) - tty=winpty -fi - -# This is a convenience script to run vtctlclient against the local example. -exec $tty docker-compose exec ${CS:-vtctld} vtctlclient -server vtctld:15999 "$@" diff --git a/vitess-mixin/e2e/package-lock.json b/vitess-mixin/e2e/package-lock.json deleted file mode 100644 index d686ef99233..00000000000 --- a/vitess-mixin/e2e/package-lock.json +++ /dev/null @@ -1,1483 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true - }, - "@cypress/request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", - "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.10.4", - "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - } - }, - "@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "@types/node": { - "version": "18.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.17.tgz", - "integrity": "sha512-cOxcXsQ2sxiwkykdJqvyFS+MLQPLvIdwh5l6gNg8qF6s+C7XSkEWOZjK+XhUZd+mYvHV/180g2cnCcIl4l06Pw==", - "dev": true - }, - "@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true - }, - "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true - }, - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cypress": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.2.0.tgz", - "integrity": "sha512-AvDQxBydE771GTq0TR4ZUBvv9m9ffXuB/ueEtpDF/6gOcvFR96amgwSJP16Yhqw6VhmwqspT5nAGzoxxB+D89g==", - "dev": true, - "requires": { - "@cypress/request": "^3.0.0", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^18.17.5", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.6.0", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "requires": { - "pify": "^2.2.0" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "requires": { - "async": "^3.2.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "requires": { - "ini": "2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true - }, - "listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/vitess-mixin/e2e/package.json b/vitess-mixin/e2e/package.json deleted file mode 100644 index ccc95ba93b0..00000000000 --- a/vitess-mixin/e2e/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "license": "Apache-2.0", - "devDependencies": { - "cypress": "^13.2.0" - } -} diff --git a/vitess-mixin/e2e/prometheus/prometheus.yml b/vitess-mixin/e2e/prometheus/prometheus.yml deleted file mode 100644 index bd8fe98dfa7..00000000000 --- a/vitess-mixin/e2e/prometheus/prometheus.yml +++ /dev/null @@ -1,61 +0,0 @@ -global: - scrape_interval: 5s - scrape_timeout: 2s - -rule_files: - - prometheus_rules.yaml - -scrape_configs: - - job_name: vitess-vtctld - metrics_path: /metrics - static_configs: - - targets: - - 'vtctld:8080' - - job_name: vitess-vtgate - metrics_path: /metrics - static_configs: - - targets: - - 'vtgate:8080' - - job_name: vitess-vttablet - metrics_path: /metrics - static_configs: - - targets: - - 'vttablet101:8080' - - 'vttablet102:8080' - - 'vttablet201:8080' - - 'vttablet202:8080' - - 'vttablet301:8080' - - 'vttablet302:8080' - # Mock mysql exporter for vttablet - - job_name: mysql - metrics_path: /metrics - static_configs: - - targets: - - 'mysqld_exporter:9104' - metric_relabel_configs: - - source_labels: [ instance ] - target_label: instance - action: replace - replacement: vttablet101:8080 - # Mock node exporter for vtgate - - job_name: node-exporter-vitess-vtgate - metrics_path: /metrics - static_configs: - - targets: - - 'node-exporter:9100' - metric_relabel_configs: - - source_labels: [ instance ] - target_label: instance - action: replace - replacement: vtgate:8080 - # Mock node exporter for vttablet - - job_name: node-exporter-vitess-vttablet - metrics_path: /metrics - static_configs: - - targets: - - 'node-exporter:9100' - metric_relabel_configs: - - source_labels: [ instance ] - target_label: instance - action: replace - replacement: vttablet101:8080 diff --git a/vitess-mixin/e2e/run-forever.sh b/vitess-mixin/e2e/run-forever.sh deleted file mode 100755 index 51e511be77a..00000000000 --- a/vitess-mixin/e2e/run-forever.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -while true -do - $@ - sleep 2 -done diff --git a/vitess-mixin/e2e/schemaload.sh b/vitess-mixin/e2e/schemaload.sh deleted file mode 100755 index b8f13ee8812..00000000000 --- a/vitess-mixin/e2e/schemaload.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -e - -# Copyright 2020 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. - -sleeptime=${SLEEPTIME:-0} -targettab=${TARGETTAB:-"${CELL}-0000000101"} -schema_files=${SCHEMA_FILES:-'create_messages.sql create_tokens.sql create'} -vschema_file=${VSCHEMA_FILE:-'default_vschema.json'} -load_file=${POST_LOAD_FILE:-''} -external_db=${EXTERNAL_DB:-'0'} -export PATH=/vt/bin:$PATH - -sleep $sleeptime - -if [ ! -f schema_run ]; then - while true; do - vtctlclient -server vtctld:$GRPC_PORT GetTablet $targettab && break - sleep 1 - done - if [ "$external_db" = "0" ]; then - for schema_file in $schema_files; do - echo "Applying Schema ${schema_file} to ${KEYSPACE}" - vtctlclient -server vtctld:$GRPC_PORT ApplySchema -sql-file /script/tables/${schema_file} $KEYSPACE || \ - vtctlclient -server vtctld:$GRPC_PORT ApplySchema -sql "$(cat /script/tables/${schema_file})" $KEYSPACE || true - done - fi - echo "Applying VSchema ${vschema_file} to ${KEYSPACE}" - - vtctlclient -server vtctld:$GRPC_PORT ApplyVSchema -vschema_file /script/${vschema_file} $KEYSPACE || \ - vtctlclient -server vtctld:$GRPC_PORT ApplyVSchema -vschema "$(cat /script/${vschema_file})" $KEYSPACE - - echo "List All Tablets" - vtctlclient -server vtctld:$GRPC_PORT ListAllTablets - - if [ -n "$load_file" ]; then - # vtgate can take a REALLY long time to come up fully - sleep 60 - mysql --port=15306 --host=vtgate < /script/$load_file - fi - - touch /vt/schema_run - echo "Time: $(date). SchemaLoad completed at $(date "+%FT%T") " >> /vt/schema_run - echo "Done Loading Schema at $(date "+%FT%T")" -fi diff --git a/vitess-mixin/e2e/tables/create_dinosaurs.sql b/vitess-mixin/e2e/tables/create_dinosaurs.sql deleted file mode 100644 index ee9a5b624da..00000000000 --- a/vitess-mixin/e2e/tables/create_dinosaurs.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE dinosaurs ( - id BIGINT UNSIGNED, - time_created_ns BIGINT UNSIGNED, - name VARCHAR(255), - PRIMARY KEY (id) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/create_eggs.sql b/vitess-mixin/e2e/tables/create_eggs.sql deleted file mode 100644 index 7e74c50b5a1..00000000000 --- a/vitess-mixin/e2e/tables/create_eggs.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE eggs ( - id BIGINT UNSIGNED, - time_created_ns BIGINT UNSIGNED, - species VARCHAR(255), - PRIMARY KEY (id) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/create_messages.sql b/vitess-mixin/e2e/tables/create_messages.sql deleted file mode 100644 index 44c4cc16e87..00000000000 --- a/vitess-mixin/e2e/tables/create_messages.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE messages ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - message VARCHAR(10000), - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/create_messages_message_lookup.sql b/vitess-mixin/e2e/tables/create_messages_message_lookup.sql deleted file mode 100644 index 1eb667dac93..00000000000 --- a/vitess-mixin/e2e/tables/create_messages_message_lookup.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE messages_message_lookup ( - id BIGINT NOT NULL AUTO_INCREMENT, - page BIGINT UNSIGNED, - message VARCHAR(1000), - PRIMARY KEY (id), - UNIQUE KEY idx_message_page (`message`, `page`) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/create_tokens.sql b/vitess-mixin/e2e/tables/create_tokens.sql deleted file mode 100644 index 69f1be03dec..00000000000 --- a/vitess-mixin/e2e/tables/create_tokens.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE tokens ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - token VARCHAR(255) DEFAULT NULL, - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/create_tokens_token_lookup.sql b/vitess-mixin/e2e/tables/create_tokens_token_lookup.sql deleted file mode 100644 index d3208fdfc41..00000000000 --- a/vitess-mixin/e2e/tables/create_tokens_token_lookup.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE tokens_token_lookup ( - id BIGINT NOT NULL AUTO_INCREMENT, - page BIGINT UNSIGNED, - token VARCHAR(255) DEFAULT NULL, - PRIMARY KEY (id), - UNIQUE KEY idx_token_page (`token`, `page`) -) ENGINE=InnoDB; \ No newline at end of file diff --git a/vitess-mixin/e2e/tables/lookup_keyspace_schema_file.sql b/vitess-mixin/e2e/tables/lookup_keyspace_schema_file.sql deleted file mode 100644 index e9c66144176..00000000000 --- a/vitess-mixin/e2e/tables/lookup_keyspace_schema_file.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE tokens_token_lookup ( - id BIGINT NOT NULL AUTO_INCREMENT, - page BIGINT UNSIGNED, - token VARCHAR(255) DEFAULT NULL, - PRIMARY KEY (id), - UNIQUE KEY idx_token_page (`token`, `page`) -) ENGINE=InnoDB; - -CREATE TABLE messages_message_lookup ( - id BIGINT NOT NULL AUTO_INCREMENT, - page BIGINT UNSIGNED, - message VARCHAR(1000), - PRIMARY KEY (id), - UNIQUE KEY idx_message_page (`message`, `page`) -) ENGINE=InnoDB; - diff --git a/vitess-mixin/e2e/tables/test_keyspace_schema_file.sql b/vitess-mixin/e2e/tables/test_keyspace_schema_file.sql deleted file mode 100644 index b049e4ef211..00000000000 --- a/vitess-mixin/e2e/tables/test_keyspace_schema_file.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE messages ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - message VARCHAR(10000), - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB; - -CREATE TABLE tokens ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - token VARCHAR(255) DEFAULT NULL, - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB; - diff --git a/vitess-mixin/e2e/tablet.yml b/vitess-mixin/e2e/tablet.yml deleted file mode 100644 index 86cc8316a41..00000000000 --- a/vitess-mixin/e2e/tablet.yml +++ /dev/null @@ -1,24 +0,0 @@ -externalConnections: - erpl: - flavor: FilePos - host: external_db_host - port: 3306 - dbName: commerce - app: - user: external_db_user - password: external_db_password - dba: - user: external_db_user - password: external_db_password - filtered: - user: external_db_user - password: external_db_password - repl: - user: external_db_user - password: external_db_password - appdebug: - user: external_db_user - password: external_db_password - allprivs: - user: external_db_user - password: external_db_password \ No newline at end of file diff --git a/vitess-mixin/e2e/test_keyspace_vschema.json b/vitess-mixin/e2e/test_keyspace_vschema.json deleted file mode 100644 index 55d0df96204..00000000000 --- a/vitess-mixin/e2e/test_keyspace_vschema.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "sharded": true, - "tables": { - "messages": { - "column_vindexes": [ - { - "column": "page", - "name": "hash" - }, - { - "column": "message", - "name": "messages_message_lookup" - } - ] - }, - "tokens": { - "column_vindexes": [ - { - "column": "page", - "name": "hash" - }, - { - "column": "token", - "name": "tokens_token_lookup" - } - ] - } - }, - "vindexes": { - "hash": { - "type": "hash" - }, - "messages_message_lookup": { - "type": "lookup_hash", - "params": { - "table": "lookup_keyspace.messages_message_lookup", - "from": "message", - "to": "page", - "autocommit": "true" - }, - "owner": "messages" - }, - "tokens_token_lookup": { - "type": "lookup_hash", - "params": { - "table": "lookup_keyspace.tokens_token_lookup", - "from": "token", - "to": "page", - "autocommit": "true" - }, - "owner": "tokens" - } - } -} \ No newline at end of file diff --git a/vitess-mixin/e2e/vtcompose/base_vschema.json b/vitess-mixin/e2e/vtcompose/base_vschema.json deleted file mode 100644 index b867400e5ee..00000000000 --- a/vitess-mixin/e2e/vtcompose/base_vschema.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "sharded": true, - "vindexes": { - "hash": { - "type": "hash" - } - }, - "tables": { - } -} diff --git a/vitess-mixin/e2e/vtcompose/docker-compose.base.yml b/vitess-mixin/e2e/vtcompose/docker-compose.base.yml deleted file mode 100644 index 2f2fbc12c70..00000000000 --- a/vitess-mixin/e2e/vtcompose/docker-compose.base.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: "2.1" -services: - consul1: - image: consul:latest - hostname: "consul1" - ports: - - "8400:8400" - - "8500:8500" - - "8600:8600" - command: "agent -server -bootstrap-expect 3 -ui -disable-host-node-id -client 0.0.0.0" - consul2: - image: consul:latest - hostname: "consul2" - expose: - - "8400" - - "8500" - - "8600" - command: "agent -server -retry-join consul1 -disable-host-node-id" - depends_on: - - consul1 - consul3: - image: consul:latest - hostname: "consul3" - expose: - - "8400" - - "8500" - - "8600" - command: "agent -server -retry-join consul1 -disable-host-node-id" - depends_on: - - consul1 - # This is a convenience container to quickly test vitess against an external database. - # In practice you will point Vitess to your existing database and migrate to a Vitess managed cluster. - external_db_host: - build: - context: ./external_db/mysql - dockerfile: Dockerfile - restart: always - environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-pass} - MYSQL_DATABASE: ${DB:-commerce} - MYSQL_USER: ${DB_USER:-external_db_user} - MYSQL_PASSWORD: ${DB_PASS:-external_db_password} - volumes: - - ./external_db/mysql/:/docker-entrypoint-initdb.d/ - - ./external_db/mysql/log:/var/log/mysql - command: - - --server-id=1 - - --log-bin=mysql-bin - - --gtid_mode=ON - - --enforce_gtid_consistency - - --general_log=1 - - --slow_query_log=1 - healthcheck: - test: "/usr/bin/mysql --user=root --password=$${MYSQL_ROOT_PASSWORD} --execute \"SHOW DATABASES;\"" - timeout: 10s - retries: 10 - ports: - - "3306" \ No newline at end of file diff --git a/vitess-mixin/e2e/vtcompose/docker-compose.test.yml b/vitess-mixin/e2e/vtcompose/docker-compose.test.yml deleted file mode 100644 index e6928d73acc..00000000000 --- a/vitess-mixin/e2e/vtcompose/docker-compose.test.yml +++ /dev/null @@ -1,303 +0,0 @@ -# This file was generated by running `go run vtcompose/vtcompose.go` with no arguments. - -services: - consul1: - command: agent -server -bootstrap-expect 3 -ui -disable-host-node-id -client 0.0.0.0 - hostname: consul1 - image: consul:latest - ports: - - 8400:8400 - - 8500:8500 - - 8600:8600 - consul2: - command: agent -server -retry-join consul1 -disable-host-node-id - depends_on: - - consul1 - expose: - - "8400" - - "8500" - - "8600" - hostname: consul2 - image: consul:latest - consul3: - command: agent -server -retry-join consul1 -disable-host-node-id - depends_on: - - consul1 - expose: - - "8400" - - "8500" - - "8600" - hostname: consul3 - image: consul:latest - schemaload_test_keyspace: - command: - - sh - - -c - - /script/schemaload.sh - depends_on: - vttablet101: - condition: service_healthy - vttablet201: - condition: service_healthy - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - TARGETTAB=test-0000000101 - - SLEEPTIME=15 - - VSCHEMA_FILE=test_keyspace_vschema.json - - SCHEMA_FILES=test_keyspace_schema_file.sql - - POST_LOAD_FILE= - - EXTERNAL_DB=0 - image: vitess/lite - volumes: - - .:/script - schemaload_unsharded_keyspace: - command: - - sh - - -c - - /script/schemaload.sh - depends_on: - vttablet301: - condition: service_healthy - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=unsharded_keyspace - - TARGETTAB=test-0000000301 - - SLEEPTIME=15 - - VSCHEMA_FILE=unsharded_keyspace_vschema.json - - SCHEMA_FILES=unsharded_keyspace_schema_file.sql - - POST_LOAD_FILE= - - EXTERNAL_DB=0 - image: vitess/lite - volumes: - - .:/script - vtctld: - command: - - sh - - -c - - ' $$VTROOT/bin/vtctld -topo_implementation consul -topo_global_server_address - consul1:8500 -topo_global_root vitess/global -cell test ''grpc-vtctl'' -backup_storage_implementation - file -file_backup_storage_root $$VTDATAROOT/backups -logtostderr=true -port - 8080 -grpc_port 15999 -pid_file $$VTDATAROOT/tmp/vtctld.pid ' - depends_on: - - consul1 - - consul2 - - consul3 - image: vitess/lite - ports: - - 15000:8080 - - "15999" - volumes: - - .:/script - vtgate: - command: - - sh - - -c - - '/script/run-forever.sh $$VTROOT/bin/vtgate --topo_implementation consul --topo_global_server_address - consul1:8500 --topo_global_root vitess/global --logtostderr=true --port 8080 --grpc_port - 15999 --mysql_server_port 15306 --mysql_auth_server_impl none --cell test --cells_to_watch - test --tablet_types_to_wait PRIMARY,REPLICA,RDONLY --service_map ''grpc-vtgateservice'' - --pid_file $$VTDATAROOT/tmp/vtgate.pid --normalize_queries=true ' - depends_on: - - vtctld - image: vitess/lite - ports: - - 15099:8080 - - "15999" - - 15306:15306 - volumes: - - .:/script - vttablet101: - command: - - sh - - -c - - /script/vttablet-up.sh 101 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=-80 - - ROLE=primary - - VTHOST=vttablet101 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl localhost:8080/debug/health - timeout: 10s - image: vitess/lite - ports: - - 15101:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet102: - command: - - sh - - -c - - /script/vttablet-up.sh 102 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=-80 - - ROLE=replica - - VTHOST=vttablet102 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl localhost:8080/debug/health - timeout: 10s - image: vitess/lite - ports: - - 15102:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet201: - command: - - sh - - -c - - /script/vttablet-up.sh 201 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=80- - - ROLE=primary - - VTHOST=vttablet201 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl localhost:8080/debug/health - timeout: 10s - image: vitess/lite - ports: - - 15201:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet202: - command: - - sh - - -c - - /script/vttablet-up.sh 202 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=test_keyspace - - SHARD=80- - - ROLE=replica - - VTHOST=vttablet202 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl localhost:8080/debug/health - timeout: 10s - image: vitess/lite - ports: - - 15202:8080 - - "15999" - - "3306" - volumes: - - .:/script - vttablet301: - command: - - sh - - -c - - /script/vttablet-up.sh 301 - depends_on: - - vtctld - environment: - - TOPOLOGY_FLAGS=-topo_implementation consul -topo_global_server_address consul1:8500 - -topo_global_root vitess/global - - WEB_PORT=8080 - - GRPC_PORT=15999 - - CELL=test - - KEYSPACE=unsharded_keyspace - - SHARD=- - - ROLE=primary - - VTHOST=vttablet301 - - EXTERNAL_DB=0 - - DB_PORT= - - DB_HOST= - - DB_USER= - - DB_PASS= - - DB_CHARSET= - healthcheck: - interval: 30s - retries: 15 - test: - - CMD-SHELL - - curl localhost:8080/debug/health - timeout: 10s - image: vitess/lite - ports: - - 15301:8080 - - "15999" - - "3306" - volumes: - - .:/script -version: "2.1" diff --git a/vitess-mixin/e2e/vtcompose/vtcompose.go b/vitess-mixin/e2e/vtcompose/vtcompose.go deleted file mode 100644 index d272c7330ff..00000000000 --- a/vitess-mixin/e2e/vtcompose/vtcompose.go +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright 2020 The Vitess Authors. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "math" - "os" - "regexp" - "strconv" - "strings" - - jsonpatch "github.com/evanphx/json-patch" - yamlpatch "github.com/krishicks/yaml-patch" - - "vitess.io/vitess/go/vt/log" -) - -const ( - DefaultWebPort = 8080 - webPortUsage = "Web port to be used" - DefaultGrpcPort = 15999 - gRpcPortUsage = "gRPC port to be used" - DefaultMysqlPort = 15306 - mySqlPortUsage = "mySql port to be used" - DefaultKeyspaceData = "test_keyspace:2:1:create_messages.sql,create_tokens.sql;unsharded_keyspace:0:0:create_dinosaurs.sql,create_eggs.sql" - keyspaceDataUsage = "List of keyspace_name/external_db_name:num_of_shards:num_of_replica_tablets:schema_files:lookup_keyspace_name separated by ';'" - DefaultCell = "test" - cellUsage = "Vitess Cell name" - DefaultExternalDbData = "" - externalDbDataUsage = "List of Data corresponding to external DBs. List of ,,,,, separated by ';'" - DefaultTopologyFlags = "-topo_implementation consul -topo_global_server_address consul1:8500 -topo_global_root vitess/global" - topologyFlagsUsage = "Vitess Topology Flags config" -) - -var ( - tabletsUsed = 0 - tablesPath = "tables/" - baseDockerComposeFile = flag.String("base_yaml", "vtcompose/docker-compose.base.yml", "Starting docker-compose yaml") - baseVschemaFile = flag.String("base_vschema", "vtcompose/base_vschema.json", "Starting vschema json") - - topologyFlags = flag.String("topologyFlags", DefaultTopologyFlags, topologyFlagsUsage) - webPort = flag.Int("webPort", DefaultWebPort, webPortUsage) - gRpcPort = flag.Int("gRpcPort", DefaultGrpcPort, gRpcPortUsage) - mySqlPort = flag.Int("mySqlPort", DefaultMysqlPort, mySqlPortUsage) - cell = flag.String("cell", DefaultCell, cellUsage) - keyspaceData = flag.String("keyspaceData", DefaultKeyspaceData, keyspaceDataUsage) - externalDbData = flag.String("externalDbData", DefaultExternalDbData, externalDbDataUsage) -) - -type vtOptions struct { - webPort int - gRpcPort int - mySqlPort int - topologyFlags string - cell string -} - -type keyspaceInfo struct { - keyspace string - shards int - replicaTablets int - lookupKeyspace string - useLookups bool - schemaFile *os.File - schemaFileNames []string -} - -type externalDbInfo struct { - dbName string - dbHost string - dbPort string - dbUser string - dbPass string - dbCharset string -} - -func newKeyspaceInfo( - keyspace string, - shards int, - replicaTablets int, - schemaFiles []string, - lookupKeyspace string, -) keyspaceInfo { - k := keyspaceInfo{ - keyspace: keyspace, - shards: shards, - replicaTablets: replicaTablets, - schemaFileNames: schemaFiles, - lookupKeyspace: lookupKeyspace, - } - if len(strings.TrimSpace(lookupKeyspace)) == 0 { - k.useLookups = false - } else { - k.useLookups = true - } - - k.schemaFile = nil - return k -} - -func newExternalDbInfo(dbName, dbHost, dbPort, dbUser, dbPass, dbCharset string) externalDbInfo { - return externalDbInfo{ - dbName: dbName, - dbHost: dbHost, - dbPort: dbPort, - dbUser: dbUser, - dbPass: dbPass, - dbCharset: dbCharset, - } -} - -func parseKeyspaceInfo(keyspaceData string) map[string]keyspaceInfo { - keyspaceInfoMap := make(map[string]keyspaceInfo) - - for _, v := range strings.Split(keyspaceData, ";") { - tokens := strings.Split(v, ":") - shards, _ := strconv.Atoi(tokens[1]) - replicaTablets, _ := strconv.Atoi(tokens[2]) - schemaFileNames := []string{} - // Make schemafiles argument optional - if len(tokens) > 3 { - f := func(c rune) bool { - return c == ',' - } - schemaFileNames = strings.FieldsFunc(tokens[3], f) - } - - if len(tokens) > 4 { - keyspaceInfoMap[tokens[0]] = newKeyspaceInfo(tokens[0], shards, replicaTablets, schemaFileNames, tokens[4]) - } else { - keyspaceInfoMap[tokens[0]] = newKeyspaceInfo(tokens[0], shards, replicaTablets, schemaFileNames, "") - } - } - - return keyspaceInfoMap -} - -func parseExternalDbData(externalDbData string) map[string]externalDbInfo { - externalDbInfoMap := make(map[string]externalDbInfo) - for _, v := range strings.Split(externalDbData, ";") { - tokens := strings.Split(v, ":") - if len(tokens) > 1 { - externalDbInfoMap[tokens[0]] = - newExternalDbInfo(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]) - } - } - - return externalDbInfoMap -} - -func main() { - flag.Parse() - keyspaceInfoMap := parseKeyspaceInfo(*keyspaceData) - externalDbInfoMap := parseExternalDbData(*externalDbData) - vtOpts := vtOptions{ - webPort: *webPort, - gRpcPort: *gRpcPort, - mySqlPort: *mySqlPort, - topologyFlags: *topologyFlags, - cell: *cell, - } - - // Write schemaFile. - for k, v := range keyspaceInfoMap { - if _, ok := externalDbInfoMap[k]; !ok { - v.schemaFile = createFile(fmt.Sprintf("%s%s_schema_file.sql", tablesPath, v.keyspace)) - appendToSqlFile(v.schemaFileNames, v.schemaFile) - closeFile(v.schemaFile) - } - } - - // Vschema Patching - for k, keyspaceData := range keyspaceInfoMap { - vSchemaFile := readFile(*baseVschemaFile) - if keyspaceData.shards == 0 { - vSchemaFile = applyJsonInMemoryPatch(vSchemaFile, `[{"op": "replace","path": "/sharded", "value": false}]`) - } - - // Check if it is an external_db - if _, ok := externalDbInfoMap[k]; ok { - //This is no longer necessary, but we'll keep it for reference - //https://github.com/vitessio/vitess/pull/4868, https://github.com/vitessio/vitess/pull/5010 - //vSchemaFile = applyJsonInMemoryPatch(vSchemaFile,`[{"op": "add","path": "/tables/*", "value": {}}]`) - } else { - var primaryTableColumns map[string]string - vSchemaFile, primaryTableColumns = addTablesVschemaPatch(vSchemaFile, keyspaceData.schemaFileNames) - - if keyspaceData.useLookups { - lookup := keyspaceInfoMap[keyspaceData.lookupKeyspace] - vSchemaFile = addLookupDataToVschema(vSchemaFile, lookup.schemaFileNames, primaryTableColumns, lookup.keyspace) - } - } - - writeVschemaFile(vSchemaFile, fmt.Sprintf("%s_vschema.json", keyspaceData.keyspace)) - } - - // Docker Compose File Patches - dockerComposeFile := readFile(*baseDockerComposeFile) - dockerComposeFile = applyDockerComposePatches(dockerComposeFile, keyspaceInfoMap, externalDbInfoMap, vtOpts) - writeFile(dockerComposeFile, "docker-compose.yml") -} - -func applyFilePatch(dockerYaml []byte, patchFile string) []byte { - yamlPatch, err := os.ReadFile(patchFile) - if err != nil { - log.Fatalf("reading yaml patch file %s: %s", patchFile, err) - } - - patch, err := yamlpatch.DecodePatch(yamlPatch) - if err != nil { - log.Fatalf("decoding patch failed: %s", err) - } - - bs, err := patch.Apply(dockerYaml) - if err != nil { - log.Fatalf("applying patch failed: %s", err) - } - return bs -} - -func applyJsonInMemoryPatch(vSchemaFile []byte, patchString string) []byte { - patch, err := jsonpatch.DecodePatch([]byte(patchString)) - if err != nil { - log.Fatalf("decoding vschema patch failed: %s", err) - } - - modified, err := patch.Apply(vSchemaFile) - if err != nil { - log.Fatalf("applying vschema patch failed: %s", err) - } - return modified -} - -func applyInMemoryPatch(dockerYaml []byte, patchString string) []byte { - patch, err := yamlpatch.DecodePatch([]byte(patchString)) - if err != nil { - log.Fatalf("decoding patch failed: %s", err) - } - - bs, err := patch.Apply(dockerYaml) - if err != nil { - log.Fatalf("applying patch failed: %s", err) - } - return bs -} - -func createFile(filePath string) *os.File { - f, err := os.Create(filePath) - if err != nil { - log.Fatalf("creating %s %s", filePath, err) - } - return f -} - -func readFile(filePath string) []byte { - file, err := os.ReadFile(filePath) - - if err != nil { - log.Fatalf("reading %s: %s", filePath, err) - } - - return file -} - -func closeFile(file *os.File) { - err := file.Close() - if err != nil { - log.Fatalf("Closing schema_file.sql %s", err) - } -} - -func handleError(err error) { - if err != nil { - log.Fatalf("Error: %s", err) - } -} - -func appendToSqlFile(schemaFileNames []string, f *os.File) { - for _, file := range schemaFileNames { - data, err := os.ReadFile(tablesPath + file) - if err != nil { - log.Fatalf("reading %s: %s", tablesPath+file, err) - } - - _, err = f.Write(data) - handleError(err) - - _, err = f.WriteString("\n\n") - handleError(err) - - err = f.Sync() - handleError(err) - } -} - -func getTableName(sqlFile string) string { - sqlFileData, err := os.ReadFile(sqlFile) - if err != nil { - log.Fatalf("reading sqlFile file %s: %s", sqlFile, err) - } - - r, _ := regexp.Compile("CREATE TABLE ([a-z_-]*) \\(") - rs := r.FindStringSubmatch(string(sqlFileData)) - // replace all ` from table name if exists - return strings.ReplaceAll(rs[1], "`", "") -} - -func getPrimaryKey(sqlFile string) string { - sqlFileData, err := os.ReadFile(sqlFile) - if err != nil { - log.Fatalf("reading sqlFile file %s: %s", sqlFile, err) - } - - r, _ := regexp.Compile("PRIMARY KEY \\((.*)\\).*") - rs := r.FindStringSubmatch(string(sqlFileData)) - - return rs[1] -} - -func getKeyColumns(sqlFile string) string { - sqlFileData, err := os.ReadFile(sqlFile) - if err != nil { - log.Fatalf("reading sqlFile file %s: %s", sqlFile, err) - } - - r, _ := regexp.Compile("[^PRIMARY] (KEY|UNIQUE KEY) .*\\((.*)\\).*") - rs := r.FindStringSubmatch(string(sqlFileData)) - // replace all ` from column names if exists - return strings.ReplaceAll(rs[2], "`", "") -} - -func addTablesVschemaPatch(vSchemaFile []byte, schemaFileNames []string) ([]byte, map[string]string) { - indexedColumns := "" - primaryTableColumns := make(map[string]string) - for _, fileName := range schemaFileNames { - tableName := getTableName(tablesPath + fileName) - indexedColumns = getPrimaryKey(tablesPath + fileName) - firstColumnName := strings.Split(indexedColumns, ", ")[0] - vSchemaFile = applyJsonInMemoryPatch(vSchemaFile, generatePrimaryVIndex(tableName, firstColumnName, "hash")) - primaryTableColumns[tableName] = firstColumnName - } - - return vSchemaFile, primaryTableColumns -} - -func addLookupDataToVschema( - vSchemaFile []byte, - schemaFileNames []string, - primaryTableColumns map[string]string, - keyspace string, -) []byte { - for _, fileName := range schemaFileNames { - tableName := fileName[7 : len(fileName)-4] - lookupTableOwner := "" - - // Find owner of lookup table - for primaryTableName := range primaryTableColumns { - if strings.HasPrefix(tableName, primaryTableName) && len(primaryTableName) > len(lookupTableOwner) { - lookupTableOwner = primaryTableName - } - } - - indexedColumns := getKeyColumns(tablesPath + fileName) - firstColumnName := strings.Split(indexedColumns, ", ")[0] - - // Lookup patch under "tables" - vSchemaFile = applyJsonInMemoryPatch(vSchemaFile, addToColumnVIndexes(lookupTableOwner, firstColumnName, tableName)) - - // Generate Vschema lookup hash types - lookupHash := generateVschemaLookupHash(tableName, keyspace, firstColumnName, primaryTableColumns[lookupTableOwner], lookupTableOwner) - vSchemaFile = applyJsonInMemoryPatch(vSchemaFile, lookupHash) - } - - return vSchemaFile -} - -func writeVschemaFile(file []byte, fileName string) { - // Format json file - var buf bytes.Buffer - err := json.Indent(&buf, file, "", "\t") - handleError(err) - file = buf.Bytes() - - writeFile(file, fileName) -} - -func writeFile(file []byte, fileName string) { - err := os.WriteFile(fileName, file, 0644) - if err != nil { - log.Fatalf("writing %s %s", fileName, err) - } -} - -func applyKeyspaceDependentPatches( - dockerComposeFile []byte, - keyspaceData keyspaceInfo, - externalDbInfoMap map[string]externalDbInfo, - opts vtOptions, -) []byte { - var externalDbInfo externalDbInfo - if val, ok := externalDbInfoMap[keyspaceData.keyspace]; ok { - externalDbInfo = val - } - tabAlias := 0 + tabletsUsed*100 - shard := "-" - var primaryTablets []string - if tabletsUsed == 0 { - primaryTablets = append(primaryTablets, "101") - } else { - primaryTablets = append(primaryTablets, strconv.Itoa((tabletsUsed+1)*100+1)) - } - interval := int(math.Floor(256 / float64(keyspaceData.shards))) - - for i := 1; i < keyspaceData.shards; i++ { - primaryTablets = append(primaryTablets, strconv.Itoa((i+1)*100+1)) - } - - schemaLoad := generateSchemaload(primaryTablets, "", keyspaceData.keyspace, externalDbInfo, opts) - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, schemaLoad) - - // Append Primary and Replica Tablets - if keyspaceData.shards < 2 { - tabAlias = tabAlias + 100 - dockerComposeFile = applyTabletPatches(dockerComposeFile, tabAlias, shard, keyspaceData, externalDbInfoMap, opts) - dockerComposeFile = applyShardPatches(dockerComposeFile, tabAlias, shard, keyspaceData, externalDbInfoMap, opts) - } else { - // Determine shard range - for i := 0; i < keyspaceData.shards; i++ { - if i == 0 { - shard = fmt.Sprintf("-%x", interval) - } else if i == (keyspaceData.shards - 1) { - shard = fmt.Sprintf("%x-", interval*i) - } else { - shard = fmt.Sprintf("%x-%x", interval*(i), interval*(i+1)) - } - tabAlias = tabAlias + 100 - dockerComposeFile = applyTabletPatches(dockerComposeFile, tabAlias, shard, keyspaceData, externalDbInfoMap, opts) - dockerComposeFile = applyShardPatches(dockerComposeFile, tabAlias, shard, keyspaceData, externalDbInfoMap, opts) - } - } - - tabletsUsed += len(primaryTablets) - return dockerComposeFile -} - -func applyDefaultDockerPatches( - dockerComposeFile []byte, - keyspaceInfoMap map[string]keyspaceInfo, - externalDbInfoMap map[string]externalDbInfo, - opts vtOptions, -) []byte { - - var dbInfo externalDbInfo - // This is a workaround to check if there are any externalDBs defined - for _, keyspaceData := range keyspaceInfoMap { - if val, ok := externalDbInfoMap[keyspaceData.keyspace]; ok { - dbInfo = val - } - } - - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateVtctld(opts)) - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateVtgate(opts)) - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateVreplication(dbInfo, opts)) - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateVTOrc(dbInfo, opts)) - return dockerComposeFile -} - -func applyDockerComposePatches( - dockerComposeFile []byte, - keyspaceInfoMap map[string]keyspaceInfo, - externalDbInfoMap map[string]externalDbInfo, - vtOpts vtOptions, -) []byte { - // Vtctld, vtgate, vtwork patches. - dockerComposeFile = applyDefaultDockerPatches(dockerComposeFile, keyspaceInfoMap, externalDbInfoMap, vtOpts) - for _, keyspaceData := range keyspaceInfoMap { - dockerComposeFile = applyKeyspaceDependentPatches(dockerComposeFile, keyspaceData, externalDbInfoMap, vtOpts) - } - - return dockerComposeFile -} - -func applyShardPatches( - dockerComposeFile []byte, - tabAlias int, - shard string, - keyspaceData keyspaceInfo, - externalDbInfoMap map[string]externalDbInfo, - opts vtOptions, -) []byte { - var dbInfo externalDbInfo - if val, ok := externalDbInfoMap[keyspaceData.keyspace]; ok { - dbInfo = val - } - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateExternalPrimary(tabAlias, shard, keyspaceData, dbInfo, opts)) - return dockerComposeFile -} - -func generateDefaultShard(tabAlias int, shard string, keyspaceData keyspaceInfo, opts vtOptions) string { - aliases := []int{tabAlias + 1} // primary alias, e.g. 201 - for i := 0; i < keyspaceData.replicaTablets; i++ { - aliases = append(aliases, tabAlias+2+i) // replica aliases, e.g. 202, 203, ... - } - tabletDepends := make([]string, len(aliases)) - for i, tabletId := range aliases { - tabletDepends[i] = fmt.Sprintf("vttablet%d: {condition : service_healthy}", tabletId) - } - // Wait on all shard tablets to be healthy - dependsOn := "depends_on: {" + strings.Join(tabletDepends, ", ") + "}" - - return fmt.Sprintf(` -- op: add - path: /services/init_shard_primary%[2]d - value: - image: vitess/lite:${VITESS_TAG:-latest} - command: ["sh", "-c", "/vt/bin/vtctlclient %[5]s InitShardPrimary -force %[4]s/%[3]s %[6]s-%[2]d "] - %[1]s -`, dependsOn, aliases[0], shard, keyspaceData.keyspace, opts.topologyFlags, opts.cell) -} - -func generateExternalPrimary( - tabAlias int, - shard string, - keyspaceData keyspaceInfo, - dbInfo externalDbInfo, - opts vtOptions, -) string { - - aliases := []int{tabAlias + 1} // primary alias, e.g. 201 - for i := 0; i < keyspaceData.replicaTablets; i++ { - aliases = append(aliases, tabAlias+2+i) // replica aliases, e.g. 202, 203, ... - } - - externalPrimaryTab := tabAlias - externalDb := "0" - - if dbInfo.dbName != "" { - externalDb = "1" - } else { - return fmt.Sprintf(``) - } - - return fmt.Sprintf(` -- op: add - path: /services/vttablet%[1]d - value: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15%[1]d:%[3]d" - - "%[4]d" - - "3306" - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS=%[2]s - - WEB_PORT=%[3]d - - GRPC_PORT=%[4]d - - CELL=%[5]s - - SHARD=%[6]s - - KEYSPACE=%[7]s - - ROLE=primary - - VTHOST=vttablet%[1]d - - EXTERNAL_DB=%[8]s - - DB_PORT=%[9]s - - DB_HOST=%[10]s - - DB_USER=%[11]s - - DB_PASS=%[12]s - - DB_CHARSET=%[13]s - command: ["sh", "-c", "[ $$EXTERNAL_DB -eq 1 ] && /script/vttablet-up.sh %[1]d || exit 0"] - depends_on: - - vtctld - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:%[3]d/debug/health"] - interval: 30s - timeout: 10s - retries: 15 -`, externalPrimaryTab, opts.topologyFlags, opts.webPort, opts.gRpcPort, opts.cell, shard, keyspaceData.keyspace, externalDb, dbInfo.dbPort, dbInfo.dbHost, dbInfo.dbUser, dbInfo.dbPass, dbInfo.dbCharset) -} - -func applyTabletPatches( - dockerComposeFile []byte, - tabAlias int, - shard string, - keyspaceData keyspaceInfo, - externalDbInfoMap map[string]externalDbInfo, - opts vtOptions, -) []byte { - var dbInfo externalDbInfo - if val, ok := externalDbInfoMap[keyspaceData.keyspace]; ok { - dbInfo = val - } - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateDefaultTablet(tabAlias+1, shard, "primary", keyspaceData.keyspace, dbInfo, opts)) - for i := 0; i < keyspaceData.replicaTablets; i++ { - dockerComposeFile = applyInMemoryPatch(dockerComposeFile, generateDefaultTablet(tabAlias+2+i, shard, "replica", keyspaceData.keyspace, dbInfo, opts)) - } - return dockerComposeFile -} - -func generateDefaultTablet(tabAlias int, shard, role, keyspace string, dbInfo externalDbInfo, opts vtOptions) string { - externalDb := "0" - if dbInfo.dbName != "" { - externalDb = "1" - } - - return fmt.Sprintf(` -- op: add - path: /services/vttablet%[1]d - value: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15%[1]d:%[4]d" - - "%[5]d" - - "3306" - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS=%[7]s - - WEB_PORT=%[4]d - - GRPC_PORT=%[5]d - - CELL=%[8]s - - KEYSPACE=%[6]s - - SHARD=%[2]s - - ROLE=%[3]s - - VTHOST=vttablet%[1]d - - EXTERNAL_DB=%[9]s - - DB_PORT=%[10]s - - DB_HOST=%[11]s - - DB_USER=%[12]s - - DB_PASS=%[13]s - - DB_CHARSET=%[14]s - command: ["sh", "-c", "/script/vttablet-up.sh %[1]d"] - depends_on: - - vtctld - healthcheck: - test: ["CMD-SHELL","curl -s --fail --show-error localhost:%[4]d/debug/health"] - interval: 30s - timeout: 10s - retries: 15 -`, tabAlias, shard, role, opts.webPort, opts.gRpcPort, keyspace, opts.topologyFlags, opts.cell, externalDb, dbInfo.dbPort, dbInfo.dbHost, dbInfo.dbUser, dbInfo.dbPass, dbInfo.dbCharset) -} - -func generateVtctld(opts vtOptions) string { - return fmt.Sprintf(` -- op: add - path: /services/vtctld - value: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15000:%[1]d" - - "%[2]d" - command: ["sh", "-c", " /vt/bin/vtctld \ - %[3]s \ - -cell %[4]s \ - -service_map 'grpc-vtctl' \ - -backup_storage_implementation file \ - -file_backup_storage_root /vt/vtdataroot/backups \ - -logtostderr=true \ - -port %[1]d \ - -grpc_port %[2]d \ - "] - volumes: - - .:/script - depends_on: - - consul1 - - consul2 - - consul3 - depends_on: - external_db_host: - condition: service_healthy -`, opts.webPort, opts.gRpcPort, opts.topologyFlags, opts.cell) -} - -func generateVtgate(opts vtOptions) string { - return fmt.Sprintf(` -- op: add - path: /services/vtgate - value: - image: vitess/lite:${VITESS_TAG:-latest} - ports: - - "15099:%[1]d" - - "%[2]d" - - "15306:%[3]d" - command: ["sh", "-c", "/script/run-forever.sh /vt/bin/vtgate \ - %[4]s \ - --logtostderr=true \ - --port %[1]d \ - --grpc_port %[2]d \ - --mysql_server_port %[3]d \ - --mysql_auth_server_impl none \ - --cell %[5]s \ - --cells_to_watch %[5]s \ - --tablet_types_to_wait PRIMARY,REPLICA,RDONLY \ - --service_map 'grpc-vtgateservice' \ - --normalize_queries=true \ - "] - volumes: - - .:/script - depends_on: - - vtctld -`, opts.webPort, opts.gRpcPort, opts.mySqlPort, opts.topologyFlags, opts.cell) -} - -func generateVTOrc(dbInfo externalDbInfo, opts vtOptions) string { - externalDb := "0" - if dbInfo.dbName != "" { - externalDb = "1" - } - return fmt.Sprintf(` -- op: add - path: /services/vtorc - value: - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS=%[1]s - - EXTERNAL_DB=%[2]s - - DB_USER=%[3]s - - DB_PASS=%[4]s - ports: - - "13000:3000" - command: ["sh", "-c", "/script/vtorc-up.sh"] - depends_on: - - vtctld -`, opts.topologyFlags, externalDb, dbInfo.dbUser, dbInfo.dbPass) -} - -func generateVreplication(dbInfo externalDbInfo, opts vtOptions) string { - externalDb := "0" - if dbInfo.dbName != "" { - externalDb = "1" - } - return fmt.Sprintf(` -- op: add - path: /services/vreplication - value: - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS=%[1]s - - EXTERNAL_DB=%[2]s - command: ["sh", "-c", "[ $$EXTERNAL_DB -eq 1 ] && /script/externaldb_vreplication.sh || exit 0"] - depends_on: - - vtctld -`, opts.topologyFlags, externalDb) -} - -func generateSchemaload( - tabletAliases []string, - postLoadFile string, - keyspace string, - dbInfo externalDbInfo, - opts vtOptions, -) string { - targetTab := tabletAliases[0] - schemaFileName := fmt.Sprintf("%s_schema_file.sql", keyspace) - externalDb := "0" - - if dbInfo.dbName != "" { - schemaFileName = "" - externalDb = "1" - } - - // Formatting for list in yaml - for i, tabletId := range tabletAliases { - tabletAliases[i] = "vttablet" + tabletId + ": " + "{condition : service_healthy}" - } - dependsOn := "depends_on: {" + strings.Join(tabletAliases, ", ") + "}" - - return fmt.Sprintf(` -- op: add - path: /services/schemaload_%[7]s - value: - image: vitess/lite:${VITESS_TAG:-latest} - volumes: - - ".:/script" - environment: - - TOPOLOGY_FLAGS=%[3]s - - WEB_PORT=%[4]d - - GRPC_PORT=%[5]d - - CELL=%[6]s - - KEYSPACE=%[7]s - - TARGETTAB=%[6]s-0000000%[2]s - - SLEEPTIME=15 - - VSCHEMA_FILE=%[7]s_vschema.json - - SCHEMA_FILES=%[9]s - - POST_LOAD_FILE=%[8]s - - EXTERNAL_DB=%[10]s - command: ["sh", "-c", "/script/schemaload.sh"] - %[1]s -`, dependsOn, targetTab, opts.topologyFlags, opts.webPort, opts.gRpcPort, opts.cell, keyspace, postLoadFile, schemaFileName, externalDb) -} - -func generatePrimaryVIndex(tableName, column, name string) string { - return fmt.Sprintf(` -[{"op": "add", -"path": "/tables/%[1]s", -"value": - {"column_vindexes": [ - { - "column": "%[2]s", - "name": "%[3]s" - } - ]} -}] -`, tableName, column, name) -} - -func generateVschemaLookupHash(tableName, tableKeyspace, from, to, owner string) string { - return fmt.Sprintf(` -[{"op": "add", -"path": "/vindexes/%[1]s", -"value": - {"type": "lookup_hash", - "params": { - "table": "%[2]s.%[1]s", - "from": "%[3]s", - "to": "%[4]s", - "autocommit": "true" - }, - "owner": "%[5]s" - } -}] -`, tableName, tableKeyspace, from, to, owner) -} - -func addToColumnVIndexes(tableName, column, referenceName string) string { - return fmt.Sprintf(` -[{"op": "add", -"path": "/tables/%[1]s/column_vindexes/-", -"value": - { - "column": "%[2]s", - "name": "%[3]s" - } -}] -`, tableName, column, referenceName) -} diff --git a/vitess-mixin/e2e/vtcompose/vtcompose_test.go b/vitess-mixin/e2e/vtcompose/vtcompose_test.go deleted file mode 100644 index 8e5cfaa2b89..00000000000 --- a/vitess-mixin/e2e/vtcompose/vtcompose_test.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2019 The Vitess Authors. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - referenceYaml = string(readFile("./docker-compose.test.yml")) - testComposeFile = readFile("./docker-compose.base.yml") - testKeyspaceInfoMap = parseKeyspaceInfo(DefaultKeyspaceData) - testExternalDbInfoMap = parseExternalDbData(DefaultExternalDbData) - - testVtOpts = vtOptions{ - webPort: DefaultWebPort, - gRpcPort: DefaultGrpcPort, - mySqlPort: DefaultMysqlPort, - topologyFlags: DefaultTopologyFlags, - cell: DefaultCell, - } -) - -func TestGenerateCorrectFileWithDefaultOpts(t *testing.T) { - baseFile := testComposeFile - finalFile := applyDockerComposePatches(baseFile, testKeyspaceInfoMap, testExternalDbInfoMap, testVtOpts) - - yamlString := string(finalFile) - assert.YAMLEq(t, referenceYaml, yamlString) -} - -func TestOptsAppliedThroughoutGeneratedFile(t *testing.T) { - baseFile := testComposeFile - options := vtOptions{ - webPort: 55_555, - gRpcPort: 66_666, - mySqlPort: 77_777, - topologyFlags: "-custom -flags", - cell: "custom cell", - } - finalFile := applyDockerComposePatches(baseFile, testKeyspaceInfoMap, testExternalDbInfoMap, options) - yamlString := string(finalFile) - - // These asserts are not exhaustive, but should cover most cases. - assert.NotContains(t, yamlString, strconv.Itoa(DefaultWebPort)) - assert.Contains(t, yamlString, strconv.Itoa(options.webPort)) - - assert.NotContains(t, yamlString, strconv.Itoa(DefaultGrpcPort)) - assert.Contains(t, yamlString, strconv.Itoa(options.gRpcPort)) - - assert.NotContains(t, yamlString, ":"+strconv.Itoa(DefaultMysqlPort)) - assert.Contains(t, yamlString, ":"+strconv.Itoa(options.webPort)) - - assert.NotContains(t, yamlString, fmt.Sprintf("-cell %s", DefaultCell)) - assert.Contains(t, yamlString, fmt.Sprintf("-cell %s", options.cell)) - - assert.Contains(t, yamlString, fmt.Sprintf("- TOPOLOGY_FLAGS=%s", options.topologyFlags)) - assert.NotContains(t, yamlString, DefaultTopologyFlags) -} diff --git a/vitess-mixin/e2e/vtorc-up.sh b/vitess-mixin/e2e/vtorc-up.sh deleted file mode 100755 index 9d71831c3ea..00000000000 --- a/vitess-mixin/e2e/vtorc-up.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# Copyright 2020 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. - -set -u - -external=${EXTERNAL_DB:-0} -config=${VTORC_CONFIG:-/vt/vtorc/config.json} -# Copy config directory -cp -R /script/vtorc /vt -# Update credentials -if [ $external = 1 ] ; then - # Terrible substitution but we don't have jq in this image - # This can be overridden by passing VTORC_CONFIG env variable - echo "Updating $config..." - cp /vt/vtorc/default.json /vt/vtorc/tmp.json - sed -i '/MySQLTopologyUser/c\ \"MySQLTopologyUser\" : \"'"$DB_USER"'\",' /vt/vtorc/tmp.json - sed -i '/MySQLTopologyPassword/c\ \"MySQLTopologyPassword\" : \"'"$DB_PASS"'\",' /vt/vtorc/tmp.json - sed -i '/MySQLReplicaUser/c\ \"MySQLReplicaUser\" : \"'"$DB_USER"'\",' /vt/vtorc/tmp.json - sed -i '/MySQLReplicaPassword/c\ \"MySQLReplicaPassword\" : \"'"$DB_PASS"'\",' /vt/vtorc/tmp.json - cat /vt/vtorc/tmp.json - cp /vt/vtorc/tmp.json /vt/vtorc/config.json -else - cp /vt/vtorc/default.json /vt/vtorc/config.json -fi - -echo "Starting vtorc..." -exec /vt/bin/vtorc \ -$TOPOLOGY_FLAGS \ --logtostderr=true \ --config $config diff --git a/vitess-mixin/e2e/vtorc/default.json b/vitess-mixin/e2e/vtorc/default.json deleted file mode 100644 index e0a03884c99..00000000000 --- a/vitess-mixin/e2e/vtorc/default.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Debug": true, - "EnableSyslog": false, - "MySQLTopologyUser": "orc_client_user", - "MySQLTopologyPassword": "orc_client_user_password", - "MySQLReplicaUser": "vt_repl", - "MySQLReplicaPassword": "", - "BackendDB": "sqlite", - "SQLite3DataFile": "/tmp/vtorc.sqlite3", - "RecoverMasterClusterFilters": ["*"], - "RecoveryPeriodBlockSeconds": 5, - "DelayMasterPromotionIfSQLThreadNotUpToDate": true -} diff --git a/vitess-mixin/e2e/vttablet-up.sh b/vitess-mixin/e2e/vttablet-up.sh deleted file mode 100755 index 0bc9d7a629d..00000000000 --- a/vitess-mixin/e2e/vttablet-up.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash - -# Copyright 2020 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. - -set -u -export VTROOT=/vt -export VTDATAROOT=/vt/vtdataroot - -keyspace=${KEYSPACE:-'test_keyspace'} -shard=${SHARD:-'0'} -grpc_port=${GRPC_PORT:-'15999'} -web_port=${WEB_PORT:-'8080'} -role=${ROLE:-'replica'} -vthost=${VTHOST:-`hostname -i`} -sleeptime=${SLEEPTIME:-'0'} -uid=$1 -external=${EXTERNAL_DB:-0} - -# If DB is not explicitly set, we default to behaviour of prefixing with vt_ -# If there is an external db, the db_nmae will always match the keyspace name -[ $external = 0 ] && db_name=${DB:-"vt_$keyspace"} || db_name=${DB:-"$keyspace"} -db_charset=${DB_CHARSET:-''} -tablet_hostname='' - -# Use IPs to simplify connections when testing in docker. -# Otherwise, blank hostname means the tablet auto-detects FQDN. -# This is now set further up - -printf -v alias '%s-%010d' $CELL $uid -printf -v tablet_dir 'vt_%010d' $uid - -tablet_role=$role -tablet_type='replica' - -# Make every 3rd tablet rdonly -if (( $uid % 100 % 3 == 0 )) ; then - tablet_type='rdonly' -fi - -# Consider every tablet with %d00 as external primary -if [ $external = 1 ] && (( $uid % 100 == 0 )) ; then - tablet_type='replica' - tablet_role='externalprimary' - keyspace="ext_$keyspace" -fi - -# Copy config directory -cp -R /script/config $VTROOT -init_db_sql_file="$VTROOT/config/init_db.sql" -# Clear in-place edits of init_db_sql_file if any exist -sed -i '/##\[CUSTOM_SQL/{:a;N;/END\]##/!ba};//d' $init_db_sql_file - -echo "##[CUSTOM_SQL_START]##" >> $init_db_sql_file - -if [ "$external" = "1" ]; then - # We need a common user for the unmanaged and managed tablets else tools like orchestrator will not function correctly - echo "Creating matching user for managed tablets..." - echo "CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASS';" >> $init_db_sql_file - echo "GRANT ALL ON *.* TO '$DB_USER'@'%';" >> $init_db_sql_file -fi -echo "##[CUSTOM_SQL_END]##" >> $init_db_sql_file - -echo "##[CUSTOM_SQL_END]##" >> $init_db_sql_file - -mkdir -p $VTDATAROOT/backups - - -export KEYSPACE=$keyspace -export SHARD=$shard -export TABLET_ID=$alias -export TABLET_DIR=$tablet_dir -export MYSQL_PORT=3306 -export TABLET_ROLE=$tablet_role -export DB_PORT=${DB_PORT:-3306} -export DB_HOST=${DB_HOST:-""} -export DB_NAME=$db_name - -# Delete socket files before running mysqlctld if exists. -# This is the primary reason for unhealthy state on restart. -# https://github.com/vitessio/vitess/pull/5115/files -echo "Removing $VTDATAROOT/$tablet_dir/{mysql.sock,mysql.sock.lock}..." -rm -rf $VTDATAROOT/$tablet_dir/{mysql.sock,mysql.sock.lock} - -# Create mysql instances -# Do not create mysql instance for primary if connecting to external mysql database -if [[ $tablet_role != "externalprimary" ]]; then - echo "Initing mysql for tablet: $uid role: $role external: $external.. " - $VTROOT/bin/mysqlctld \ - --init_db_sql_file=$init_db_sql_file \ - --logtostderr=true \ - --tablet_uid=$uid \ - & -fi - -sleep $sleeptime - -# Create the cell -# https://vitess.io/blog/2020-04-27-life-of-a-cluster/ -$VTROOT/bin/vtctlclient --server vtctld:$GRPC_PORT -- AddCellInfo --root vitess/$CELL --server_address consul1:8500 $CELL || true - -#Populate external db conditional args -if [ $tablet_role = "externalprimary" ]; then - echo "Setting external db args for primary: $DB_NAME" - external_db_args="--db_host $DB_HOST \ - --db_port $DB_PORT \ - --init_db_name_override $DB_NAME \ - --init_tablet_type $tablet_type \ - --mycnf_server_id $uid \ - --db_app_user $DB_USER \ - --db_app_password $DB_PASS \ - --db_allprivs_user $DB_USER \ - --db_allprivs_password $DB_PASS \ - --db_appdebug_user $DB_USER \ - --db_appdebug_password $DB_PASS \ - --db_dba_user $DB_USER \ - --db_dba_password $DB_PASS \ - --db_filtered_user $DB_USER \ - --db_filtered_password $DB_PASS \ - --db_repl_user $DB_USER \ - --db_repl_password $DB_PASS \ - --enable_replication_reporter=false \ - --enforce_strict_trans_tables=false \ - --track_schema_versions=true \ - --watch_replication_stream=true" -else - external_db_args="--init_db_name_override $DB_NAME \ - --init_tablet_type $tablet_type \ - --enable_replication_reporter=true \ - --restore_from_backup" -fi - - -echo "Starting vttablet..." -exec $VTROOT/bin/vttablet \ - $TOPOLOGY_FLAGS \ - --logtostderr=true \ - --tablet-path $alias \ - --tablet_hostname "$vthost" \ - --health_check_interval 5s \ - --disable_active_reparents=true \ - --port $web_port \ - --grpc_port $grpc_port \ - --service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' \ - --init_keyspace $keyspace \ - --init_shard $shard \ - --backup_storage_implementation file \ - --file_backup_storage_root $VTDATAROOT/backups \ - --queryserver-config-schema-reload-time 60 \ - $external_db_args diff --git a/vitess-mixin/go.mod b/vitess-mixin/go.mod deleted file mode 100644 index 20d3f33eed8..00000000000 --- a/vitess-mixin/go.mod +++ /dev/null @@ -1,132 +0,0 @@ -module vitess-mixin - -go 1.22.5 - -require ( - github.com/evanphx/json-patch v5.9.0+incompatible - github.com/google/go-jsonnet v0.16.0 - github.com/jsonnet-bundler/jsonnet-bundler v0.4.0 - github.com/krishicks/yaml-patch v0.0.10 - // Believe it or not, this is actually version 2.13.1 - // See https://github.com/prometheus/prometheus/issues/5590#issuecomment-546368944 - github.com/prometheus/prometheus v1.8.2-0.20191017095924-6f92ce560538 - github.com/stretchr/testify v1.9.0 - vitess.io/vitess v0.19.4 -) - -require ( - cloud.google.com/go/compute v1.25.0 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - github.com/Azure/azure-sdk-for-go v23.2.0+incompatible // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.1 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect - github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.50.32 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/fatih/color v1.16.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-kit/kit v0.9.0 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/golang/glog v1.2.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.2 // indirect - github.com/gophercloud/gophercloud v0.3.0 // indirect - github.com/hashicorp/consul/api v1.28.2 // 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.2 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/hashicorp/serf v0.10.1 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/jpillora/backoff v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.41 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/nxadm/tail v1.4.11 // indirect - github.com/oklog/ulid v1.3.1 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.49.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75 // indirect - github.com/spf13/pflag v1.0.5 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/time v0.5.0 // indirect - google.golang.org/api v0.168.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 // indirect - google.golang.org/grpc v1.62.1 // indirect - google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect - gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.26.1 // indirect - k8s.io/apimachinery v0.26.1 // indirect - k8s.io/client-go v0.26.1 // indirect - k8s.io/klog/v2 v2.90.0 // indirect - k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 // indirect - k8s.io/utils v0.0.0-20230115233650-391b47cb4029 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) - -replace k8s.io/client-go v2.0.0-alpha.0.0.20181121191925-a47917edff34+incompatible => k8s.io/client-go v2.0.0-alpha.1+incompatible diff --git a/vitess-mixin/go.sum b/vitess-mixin/go.sum deleted file mode 100644 index 73171b17f6a..00000000000 --- a/vitess-mixin/go.sum +++ /dev/null @@ -1,908 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go/compute v1.25.0 h1:H1/4SqSUhjPFE7L5ddzHOfY2bCAvjwNRZPNl6Ni5oYU= -cloud.google.com/go/compute v1.25.0/go.mod h1:GR7F0ZPZH8EhChlMo9FkLd7eUTwEymjqQagxzilIxIE= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs= -github.com/Azure/azure-sdk-for-go v23.2.0+incompatible h1:bch1RS060vGpHpY3zvQDV4rOiRw25J1zmR/B9a76aSA= -github.com/Azure/azure-sdk-for-go v23.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI= -github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -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/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.23.12/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.50.32 h1:POt81DvegnpQKM4DMDLlHz1CO6OBnEoQ1gRhYFd7QRY= -github.com/aws/aws-sdk-go v1.50.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= -github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v0.0.0-20181017004759-096ff4a8a059/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= -github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.17.2/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.17.2/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.18.0/go.mod h1:uI6pHuxWYTy94zZxgcwJkUWa9wbIlhteGfloI10GD4U= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.3/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.17.2/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.4/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.17.2/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -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/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-jsonnet v0.16.0 h1:Nb4EEOp+rdeGGyB1rQ5eisgSAqrTnhf9ip+X6lzZbY0= -github.com/google/go-jsonnet v0.16.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 h1:XTnP8fJpa4Kvpw2qARB4KS9izqxPS0Sd92cDlY3uk+w= -github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= -github.com/gophercloud/gophercloud v0.3.0 h1:6sjpKIpVwRIIwmcEGp+WwNovNsem+c+2vm6oxshRpL8= -github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= -github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= -github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= -github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= -github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k= -github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/jessevdk/go-flags v0.0.0-20180331124232-1c38ed7ad0cc/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jsonnet-bundler/jsonnet-bundler v0.4.0 h1:4BKZ6LDqPc2wJDmaKnmYD/vDjUptJtnUpai802MibFc= -github.com/jsonnet-bundler/jsonnet-bundler v0.4.0/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E= -github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME= -github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -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/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= -github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v0.0.0-20170117200651-66bb6560562f/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= -github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/prometheus/alertmanager v0.18.0/go.mod h1:WcxHBl40VSPuOaqWae6l6HpnEOVRIycEJ7i9iYkadEE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.2.0/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI= -github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.0.0-20180315085919-58e2a31db8de/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= -github.com/prometheus/prometheus v1.8.2-0.20191017095924-6f92ce560538 h1:iyerK9/VU1F02ASqYyIXp60gKxo7ualRoEezXPqbQZE= -github.com/prometheus/prometheus v1.8.2-0.20191017095924-6f92ce560538/go.mod h1:SgN99nHQ/tVJyAuyLKKz6i2j5cJx3eLy9MCRCPOXqUI= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75 h1:cA+Ubq9qEVIQhIWvP2kNuSZ2CmnfBJFSRq+kO1pu2cc= -github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/vfsgen v0.0.0-20180825020608-02ddb050ef6b/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.0.4/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -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-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190918214516-5a1a30219888/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY= -google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20240304212257-790db918fca8 h1:Fe8QycXyEd9mJgnwB9kmw00WgB43eQ/xYO5C6gceybQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= -k8s.io/api v0.0.0-20190813020757-36bff7324fb7/go.mod h1:3Iy+myeAORNCLgjd/Xu9ebwN7Vh59Bw0vh9jhoX+V58= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= -k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= -k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6/go.mod h1:RZvgC8MSN6DjiMV6oIfEE9pDL9CYXokkfaCKZeHm3nc= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 h1:vV3ZKAUX0nMjTflyfVea98dTfROpIxDaEsQws0FT2Ts= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= -k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= -k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20230115233650-391b47cb4029 h1:L8zDtT4jrxj+TaQYD0k8KNlr556WaVQylDXswKmX+dE= -k8s.io/utils v0.0.0-20230115233650-391b47cb4029/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -vitess.io/vitess v0.19.4 h1:fJhZm5RknYbF7YUBXBmcvST/mvA4CeevlI9N0TLlYXA= -vitess.io/vitess v0.19.4/go.mod h1:15uIi9x/Gu+BdDhUR80yP0M1v7aMG2mZQXSd56CE2t0= diff --git a/vitess-mixin/jsonnetfile.json b/vitess-mixin/jsonnetfile.json deleted file mode 100644 index 93f3316ec38..00000000000 --- a/vitess-mixin/jsonnetfile.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": 1, - "dependencies": [ - { - "source": { - "git": { - "remote": "https://github.com/grafana/grafonnet-lib.git", - "subdir": "grafonnet" - } - }, - "version": "master" - } - ], - "legacyImports": true -} diff --git a/vitess-mixin/lib/alerts.jsonnet b/vitess-mixin/lib/alerts.jsonnet deleted file mode 100644 index d396a38cd71..00000000000 --- a/vitess-mixin/lib/alerts.jsonnet +++ /dev/null @@ -1 +0,0 @@ -std.manifestYamlDoc((import '../mixin.libsonnet').prometheusAlerts) diff --git a/vitess-mixin/lib/dashboards.jsonnet b/vitess-mixin/lib/dashboards.jsonnet deleted file mode 100644 index c260feb80e3..00000000000 --- a/vitess-mixin/lib/dashboards.jsonnet +++ /dev/null @@ -1,10 +0,0 @@ -local dashboards = (import '../mixin.libsonnet').grafanaDashboards; - -local config = (import '../config.libsonnet'); -local deploy_list = config._config.deploy_list; - -{ - [name]: dashboards[name] - for name in std.objectFields(dashboards) - if std.member(dashboards[name].environments, std.extVar('env')) -} diff --git a/vitess-mixin/lib/rules.jsonnet b/vitess-mixin/lib/rules.jsonnet deleted file mode 100644 index 2d7fa91f7ca..00000000000 --- a/vitess-mixin/lib/rules.jsonnet +++ /dev/null @@ -1 +0,0 @@ -std.manifestYamlDoc((import '../mixin.libsonnet').prometheusRules) diff --git a/vitess-mixin/mixin.libsonnet b/vitess-mixin/mixin.libsonnet deleted file mode 100644 index b9831f9380b..00000000000 --- a/vitess-mixin/mixin.libsonnet +++ /dev/null @@ -1,4 +0,0 @@ -(import 'config.libsonnet') + -(import 'alerts/alerts.libsonnet') + -(import 'dashboards/dashboards.libsonnet') + -(import 'rules/rules.libsonnet') diff --git a/vitess-mixin/rules/rules.libsonnet b/vitess-mixin/rules/rules.libsonnet deleted file mode 100644 index 903212ca351..00000000000 --- a/vitess-mixin/rules/rules.libsonnet +++ /dev/null @@ -1,221 +0,0 @@ -// Recording rules can be used to continually evaluate queries and -// store their results as new timeseries. This is commonly used to -// calculate expensive aggregates prior to querying them. You can have -// any number of rules, split across any number of files. -// -// Reference: https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/ -local config = import '../config.libsonnet'; - -{ - prometheusRules+:: { - groups: [ - { - name: 'vitess_mixin_1', - rules: [ - { - record: 'vitess_mixin:vttablet_errors:rate1m', - expr: 'sum (rate(vttablet_errors[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_2', - rules: [ - { - record: 'vitess_mixin:vttablet_query_counts:rate1m', - expr: 'sum (rate(vttablet_query_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_3', - rules: [ - { - record: 'vitess_mixin:mysql_global_status_queries:rate1m', - expr: 'sum (rate(mysql_global_status_queries[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_4', - rules: [ - { - record: 'vitess_mixin:vtgate_api_bucket:rate1m', - expr: 'sum by(le)(rate(vtgate_api_bucket[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_5', - rules: [ - { - record: 'vitess_mixin:vtgate_api_bucket_by_keyspace:rate1m', - expr: 'sum by(le,keyspace)(rate(vtgate_api_bucket[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_6', - rules: [ - { - record: 'vitess_mixin:vtgate_api_error_counts:rate1m', - expr: 'sum (rate(vtgate_api_error_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_7', - rules: [ - { - record: 'vitess_mixin:vtgate_api_count:rate1m', - expr: 'sum (rate(vtgate_api_count[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_8', - rules: [ - { - record: 'vitess_mixin:vtgate_api_error_counts_by_keyspace:rate1m', - expr: 'sum by(keyspace)(rate(vtgate_api_error_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_9', - rules: [ - { - record: 'vitess_mixin:vtgate_api_count_by_keyspace:rate1m', - expr: 'sum by(keyspace)(rate(vtgate_api_count[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_10', - rules: [ - { - record: 'vitess_mixin:vttablet_kills:rate1m', - expr: 'sum by (keyspace,shard)(rate(vttablet_kills[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_11', - rules: [ - { - record: 'vitess_mixin:vtgate_vttablet_call_error_count_byinstance:rate1m', - expr: 'sum by(instance)(rate(vtgate_vttablet_call_error_count[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_12', - rules: [ - { - record: 'vitess_mixin:vtgate_api_error_counts_by_db_type:rate1m', - expr: 'sum by(db_type)(rate(vtgate_api_error_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_13', - rules: [ - { - record: 'vitess_mixin:vtgate_api_count_by_db_type:rate1m', - expr: 'sum by(db_type)(rate(vtgate_api_count[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_14', - rules: [ - { - record: 'vitess_mixin:vtgate_api_bucket_by_db_type:rate1m', - expr: 'sum by(le,db_type)(rate(vtgate_api_bucket[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_15', - rules: [ - { - record: 'vitess_mixin:vtgate_api_error_counts_by_operation:rate1m', - expr: 'sum by(operation)(rate(vtgate_api_error_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_16', - rules: [ - { - record: 'vitess_mixin:vtgate_api_error_counts_by_code:rate1m', - expr: 'sum by(code)(rate(vtgate_api_error_counts[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_17', - rules: [ - { - record: 'vitess_mixin:vttablet_queries_sum_by_keyspace_shard:rate1m', - expr: 'sum by(keyspace,shard)(rate(vttablet_queries_sum[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_18', - rules: [ - { - record: 'vitess_mixin:vttablet_queries_count_by_keyspace_shard:rate1m', - expr: 'sum by(keyspace,shard)(rate(vttablet_queries_count[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_19', - rules: [ - { - record: 'vitess_mixin:vttablet_transactions_bucket_by_keyspace_shard:rate1m', - expr: 'sum by(keyspace,shard,le)(rate(vttablet_transactions_bucket[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_20', - rules: [ - { - record: 'vitess_mixin:process_start_time_seconds_by_instance_job:sum5m', - expr: 'sum by (instance,job) (changes (process_start_time_seconds[5m]))', - }, - ], - }, - { - name: 'vitess_mixin_21', - rules: [ - { - record: 'vitess_mixin:vttablet_kills_by_instance:rate1m', - expr: 'sum by(instance)(rate(vttablet_kills[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_22', - rules: [ - { - record: 'vitess_mixin:vttablet_errors:rate1m', - expr: 'sum by(keyspace,shard,instance,error_code)(rate(vttablet_errors[1m]))', - }, - ], - }, - { - name: 'vitess_mixin_23', - rules: [ - { - record: 'vitess_mixin:vtgate_queries_processed_by_table:rate1m', - expr: 'sum by(keyspace,plan,table) (rate(vtgate_queries_processed_by_table{plan!="Rollback"}[1m]))', - }, - ], - }, - ], - }, -} diff --git a/vitess-mixin/scripts/fmt.sh b/vitess-mixin/scripts/fmt.sh deleted file mode 100755 index e1a5976ee8e..00000000000 --- a/vitess-mixin/scripts/fmt.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash -#/ Usage: fmt [--check] -#/ --check Fail if changed files need changes, do not format in place. - -set -eu - -usage() { - grep '^#/' "$0" | cut -c'4-' >&2 - exit "$1" -} - -if ! [ -x "$(command -v jsonnet)" ] && ! [ -x "$(command -v jsonnetfmt)" ]; then - echo 'jsonnet or jsonnetfmt executable not found' - exit 1 -fi - -if [ -x "$(command -v jsonnetfmt)" ]; then - JSONNET_COMMAND='jsonnetfmt' -else - JSONNET_COMMAND='jsonnet fmt' -fi - -CHECK="false" -EXIT_STATUS=0 -FILES_CHANGED="$(git diff --name-only origin/main --diff-filter=d | grep -E '(jsonnet|TEMPLATE|libsonnet)$' || true)" - -while [ "$#" -gt 0 ]; do - case "$1" in - -c|--check) CHECK="true"; shift;; - *) usage ;; - esac -done - -if [ "${CHECK}" == "true" ]; then - if [ -n "${FILES_CHANGED}" ]; then - for FILE in ${FILES_CHANGED}; do - set +e - echo -n "Checking $FILE: " - ${JSONNET_COMMAND} --test "${FILE}" - EC=$? - if [ ${EC} -ne 0 ]; then - echo "⚠️" - EXIT_STATUS=1 - else - echo "✅" - fi - set -e - done - echo "" - fi - - echo -n "STATUS:" - if [ "$EXIT_STATUS" -eq 0 ]; then - echo "✅" - else - echo "❌" - fi - - exit $EXIT_STATUS - -else - for FILE in $FILES_CHANGED; do - echo -n "Formatting $FILE: " - $JSONNET_COMMAND -n 2 --max-blank-lines 2 --string-style s --comment-style s -i ../$FILE - echo "✅" - done -fi diff --git a/vitess-mixin/scripts/vitess-mixin-plan.sh b/vitess-mixin/scripts/vitess-mixin-plan.sh deleted file mode 100755 index 8c305601956..00000000000 --- a/vitess-mixin/scripts/vitess-mixin-plan.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -if [[ -z "$ENV" || ("${ENV}" != 'dev' && "${ENV}" != 'prod') ]]; then - echo -e "##ERROR\nPlease specify ENV (prod or dev)\nUsage: ENV='prod' ./vitess-mixin-plan.sh" 1>&2 - exit 1 -fi - -export ENVIRONMENT=$ENV - -EXIT_STATUS=0; - -echo "#### Building origin/main" -REPODIR="$(pwd)" -TEMPDIR="$(mktemp -d)" - -cd $TEMPDIR -git clone git@github.com:vitessio/vitess.git > /dev/null 2>&1 -cd vitess/vitess-mixin -jb install > /dev/null 2>&1 -make dashboards_out > /dev/null 2>&1 -make prometheus_rules.yaml > /dev/null 2>&1 -# TODO enalbe when alerts are not empty. -# make prometheus_alerts.yaml > /dev/null 2>&1 - -echo -e "\nDone!\n" - -cd $REPODIR -make dashboards_out > /dev/null 2>&1 -make prometheus_rules.yaml > /dev/null 2>&1 -# TODO enalbe when alerts are not empty. -# make prometheus_alerts.yaml > /dev/null 2>&1 - -branch=$(git rev-parse --abbrev-ref HEAD) -echo -e "#### Diff origin/main with $branch:\n" - -# TODO check prometheus_alerts.yaml - -t="# Checking prometheus_rules.yaml..."; -d=$(diff -urt --label origin/main/prometheus_rules.yaml "$TEMPDIR/vitess/vitess-mixin/prometheus_rules.yaml" --label $branch/prometheus_rules.yaml "prometheus_rules.yaml" 2>/dev/null) -if [ "$?" = "0" ]; -then - echo $t OK -else - echo $t NOK - echo "$d" - EXIT_STATUS=2 -fi - -DASHBOARDS=() -for filename in $(ls dashboards_out) -do - t="# Checking $filename..." - DASHBOARDS+=($filename) - d=$(diff -urt --label origin/main/$filename "$TEMPDIR/vitess/vitess-mixin/dashboards_out/"$filename --label $branch/$filename "dashboards_out/"$filename 2>/dev/null) - if [ "$?" = "0" ]; - then - echo $t OK - else - if [ -e "$TEMPDIR/vitess-mixin/dashboards_out/"$filename ]; - then - echo $t NOK - echo "$d" - else - echo $t "This is a new dashboard not present in origin/main" NOK - fi - EXIT_STATUS=2 - fi -done - -for filename in $(ls $TEMPDIR/vitess/vitess-mixin/dashboards_out) -do - t="# Checking $filename..." - if [[ ! " ${DASHBOARDS[*]} " == *"$filename"* ]]; - then - echo $t This dashboard has been removed NOK ; - EXIT_STATUS=2 - fi -done - -echo -e "\nEXIT STATUS:" -if [ "$EXIT_STATUS" -eq 0 ]; then - echo -e "✅ Your dashboards local version matches the origin/main version" -elif [ "$EXIT_STATUS" -eq 2 ]; then - echo -e "👀 If you are happy with your changes open a PR" -else - echo "❌" - exit 1 -fi - -rm -rf $TEMPDIR diff --git a/vitess-mixin/tools.go b/vitess-mixin/tools.go deleted file mode 100644 index 63cc73e0bbb..00000000000 --- a/vitess-mixin/tools.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build tools -// +build tools - -package main - -import ( - _ "github.com/google/go-jsonnet/cmd/jsonnet" - _ "github.com/google/go-jsonnet/cmd/jsonnetfmt" - _ "github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb" - _ "github.com/prometheus/prometheus/cmd/promtool" -) diff --git a/vitess-mixin/vitess-mixin-quickstart.md b/vitess-mixin/vitess-mixin-quickstart.md deleted file mode 100644 index e15e6126211..00000000000 --- a/vitess-mixin/vitess-mixin-quickstart.md +++ /dev/null @@ -1,323 +0,0 @@ -# Vitess Mixin QuickStart - -## Table of Contents - -- [Vitess Mixin QuickStart](#vitess-mixin-quickstart) - - [Table of Contents](#table-of-contents) - - [What is the Vitess Mixin](#what-is-the-vitess-mixin) - - [Development](#development) - - [Building](#building) - - [1. Prometheus Recording Rules](#1-prometheus-recording-rules) - - [2. Grafana Dashboards](#2-grafana-dashboards) - - [Formatting](#formatting) - - [Linting](#linting) - - [Cleaning up](#cleaning-up) - - [Define a new Dashboard](#define-a-new-dashboard) - - [Update Existing Dashboards](#update-existing-dashboards) - - [Edit existing resources](#edit-existing-resources) - - [Adding new resources](#adding-new-resources) - - [Test and Deploy](#test-and-deploy) - - [Local Unit Tests with `make all`](#local-unit-tests-with-make-all) - - [Local e2e tests using Cypress (Alpha)](#local-e2e-tests-using-cypress-alpha) - - [Local e2e manual testing using compose (Alpha)](#local-e2e-manual-testing-using-compose-alpha) - -## What is the Vitess Mixin - -Vitess [mixin](https://en.wikipedia.org/wiki/Mixin) is a monitoring mixin defined using [jsonnet](https://jsonnet.org/) data templating language. The grafana `jsonnet` library for creating dashboards is [grafonnet](https://github.com/grafana/grafonnet-lib). While the package manager for easily reusing and extending the mixin is [jsonnet-bundler](https://github.com/jsonnet-bundler/jsonnet-bundler). - -## Development - -If you want to see all available targets run `make help`. - -Choose an IDE of your preference. We use VSCode with `heptio.jsonnet` plugin which includes some nice features like on mouse over documentation and (ctrl+space) autocomplete. - -### Building - -#### 1. Prometheus Recording Rules - - ```shell - $ make prometheus_rules.yaml - # Building 'prometheus_rules.yaml'... - - Done! - ``` - - Once generated the Vitess Mixin Prometheus recording rules are available at `prometheus_rules.yaml`. - - **Note:** The Vitess Mixin only includes recording rules for Prometheus Vitess metrics. Other metric like Prometheus Node are not currently included in the rules. - -#### 2. Grafana Dashboards - -The vitess mixin supports DEV/PROD configurations (Currently it is possible to enable/disable dashboards. And set different alert configurations for DEV/PROD). - - **Prod dashboards**: - - ```shell - $ ENV='prod' make dashboards_out - # Building Grafana dashboards... - - dashboards_out/cluster_overview.json - dashboards_out/vtgate_host_view.json - dashboards_out/vtgate_overview.json - dashboards_out/vttablet_host_view.json - - Done! - ``` - - **Dev dashboards**: - - ```shell - $ ENV=dev make dashboards_out - - # Building Grafana dashboards... - - dashboards_out/cluster_overview.json - dashboards_out/vtgate_host_view.json - dashboards_out/vtgate_overview.json - dashboards_out/vttablet_host_view.json - - Done! - ``` - - Voila!! the generated dashboards definitions in `.json` format are now available under `/dashboards_out`. (**Note**: dev and prod dashboards have the same names and they are stored in the same output folder. It is a good practice to run `make clean` after each build to make sure we are working with a clean `/dashboards_out` folder). - -### Formatting - - ```shell - $ make fmt - # Formatting all .libsonnet and .jsonnet files... - - Formatting dashboards/alerts_memory_events.libsonnet: ✅ - - Done! - ``` - -### Linting - - ```shell - $ make lint - # Linting all .libsonnet and .jsonnet files... - - Checking dashboards/alerts_memory_events.libsonnet: ✅ - - STATUS:✅ - - Done! - - # Linting 'prometheus_rules.yaml' and 'prometheus_alerts.yaml'... - TO BE IMPLEMENTED - Done! - ``` - -### Cleaning up - - ```shell - $ make clean - # Cleaning up all generated files... - - rm -rf dashboards_out prometheus_alerts.yaml prometheus_rules.yaml - - Done! - ``` - -## Define a new Dashboard - - Dashboards are defined in `.libsonnet` format under the `/dashboards` folder. - **Note** Files designed for import by convention end with `.libsonnet`. - - 1. Update the Mixin config to include the new **dashboard metadata** `config.libsonnet`. - The metadata needs to be added under `grafanaDashboardMetadata`. For example for `vtgate-overview dashboard` it looks like this: - - ```bash - vtgateOverview: { - environments: ['dev', 'prod'], - uid: 'vitess-vtgate-overview', - title: 'vtgate - overview %(dashboardNameSuffix)s' % $._config.grafanaDashboardMetadataDefault, - description: 'General vtgate overview', - dashboardTags: $._config.grafanaDashboardMetadataDefault.dashboardTags + ['overview', 'vtgate'], - } - ``` - - **Note**: It is possible to add/remove a dashboard from specific environments using the `environments` array field. - - 2. Define the **dashboard layout**: Create a new `.libsonnet` file following _Naming Convention_ (**TODO** Define a naming convention) in the `/dashboards/layouts` folder. - The dashboard skeleton should look something like this: - - ```js - local helpers = import '../resources/helpers.libsonnet'; - - local config = import '../../config.libsonnet'; - - { - grafanaDashboards+:: { - 'DASHBOARD_NAME.json': - - helpers.dashboard.getDashboard(config._config.grafanaDashboardMetadata.DASHBOARD_NAME) - .addTemplates( - [ - - ] - ).addLink(helpers.default.getDashboardLink(config._config.dashborardLinks)) - .addPanels( - [ - - ], - ), - }, - } - ``` - - 3. Import the new dashboard in the `dashboard.libsonnet` library. - - 4. Add/Edit dashboard resources. - - **Note:** Some of the resources have been grouped in the following categories `vtgate`, `vttablet`, `vtorc`, `webapp`, `os` for convenience. The resources under this categories follow a helper/config pattern. The `.*_helper.libsonnet` libraries within `grafonnet` folder functions to retrieve resources such as `getPanel(panel_name_config)`, reading the configuration by name for the desired resource from the corresponding `.*_config.libsonnet` library . - - **Note:** To isolate **PROD** and **DEV** the configuration files have a section for each environment where we can define specific `notifications`(ex: pagerduty, vitess-alerts...) and `conditions` (alert thresholds). - - In this example the alert has a different notification config. For **PROD** it pages and **DEV** it doesn't: - - ```js - alert: { - name: 'vitess-mixin - # of tablets with MySQL replication lag > 300s', - frequency: '1m', - forDuration: '3m', - noDataState: 'ok', - executionErrorState: 'keep_state', - message: ||| - The number of tablets with MySQL replication lag > 300s is above the threshold. - This usually indicate that replicas are not able to keep up with the write loads on the primary. Please take a look. - |||, - - prod+: { - notifications: [ - { uid: 'alerts-vitess' }, - { uid: 'pagerduty-vitess' }, - ], - conditions: [ - alert_condition.new( - evaluatorParams=[1], - evaluatorType='gt', - operatorType='and', - queryRefId='A', - queryTimeStart='1m', - reducerType='max'), - ], - }, - //override PROD notifications. - dev+: self.prod { - notifications: [ - { uid: 'alerts-vitess' }, - ], - }, - }, - ``` - - **Warning:** Editing existing resources can change other dashboards behavior. Since basic resources like `panels`, `rows`, `texts`... can be shared across dashboards. This can be easily checked running `make all` as explained bellow. - -## Update Existing Dashboards - - Same steps as **Define a new Dashboard** starting from step `.4`. - -### Edit existing resources - - 1. Look for the dashboard you want to edit in the `dashboards/layouts` folder. - 2. Find the resource you want to update in the `dashboards/resources` folder. - -### Adding new resources - - 1. Create the resource in the corresponding location under `dashboards/resources` folder. - 2. Add the resource to the desired layout in `dashboards/layouts`. - -## Test and Deploy - -### Local Unit Tests with `make all` - -These tests attempt to assert truth to the following: - -- Does this mixin generate valid dashboard JSON? -- Does this mixin generate valid recording rules YAML? -- Do the configured elements do what they are expected to do? - -This make target will format, lint, build all generated dashboards and recording rules using `origin/main` and diff with them your `local branch`. Printing a report to the `stdout`. - -```shell - $ pwd - /manfontan/vitess-mixin - $ ENV='prod' make all - #### Building origin/main - - Done! - - #### Diff origin/main with main: - - # Checking prometheus_rules.yaml... OK - # Checking cluster_overview.json... OK - # Checking vtgate_host_view.json... OK - # Checking vtgate_overview.json... OK - # Checking vttablet_host_view.json... OK - - EXIT STATUS: - ✅ Your dashboards local version matches the origin/main version -``` - -The above execution shows the report for a `local branch` matching `origin/main`. Any changes will be reported as **NOK** along with the diff report. This doesn't mean something is wrong it just points that there are changes in your local branch compared to `origin/main` which is expected. Review the diff report and once you are happy with your changes create a PR. - -### Local e2e tests using Cypress (Alpha) - -These tests attempt to assert truth to the following: - -- Are dashboard elements displayed as expected? - -The spec for each dashboard can be found at `/e2e/cypress/integration`. - -`docker-compose` is used to run Cypress and Grafana. There are two targets in -[Makefile](../Makefile) to help run it. - -- `make e2e`: runs tests headless and exits. - -- `make e2e-dev`: opens the [the test -runner](https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview) -and exposes Grafana to the host machine - http://localhost:3030. This requires -an X11 server to work. [This -post](https://www.cypress.io/blog/2019/05/02/run-cypress-with-a-single-docker-command/#Interactive-mode) -describes how to set this up with [XQuartz](https://www.xquartz.org/). - -**Note** The dummy Grafana server is not connected to a Prometheus Backend for this reason dashboards will not display any data, templates will fail to load etc... If you don't have a Dev Prometheus server. Replacing prometheus datasources(`Prometheus_Vitess`, `Prometheus_Node` ...) with an empty string in the generated JSON file will default to the dummy datasource displaying dummy data. This is useful when testing using interactive mode `make e2e-dev`. - -### Local e2e manual testing using compose (Alpha) - -**Note**: This targets have been tested using docker for Mac. You may need to change the IPs and configurations for your specific setup. - -Before we run the local environment using compose it is necessary to generate the dashboards and recording rules using `ENV=dev make all` (Note: choose the environment you want to test). - -Once our dashboards are available simply run: - -- `make e2e-compose-up`: spin up the cluster - -Changes to the dashboards are not dynamically loaded so you will need to bring down the cluster and initialized it again to load your changes. - -If you are done testing or the cluster gets in a bad state quit and clean up using: - -- `make e2e-compose-down`: cleanup compose resources - -In order to generate some metrics we can use the following commands: - -```shell -## INSERT TEST DATA -mysql --port=15306 --host=127.0.0.1 < load_test.sql -## SIMULATED QUERIES -mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=test_keyspace:80-@primary --query="SELECT * FROM messages;" -mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=test_keyspace:80-@replica --query="SELECT * FROM messages;" -mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=lookup_keyspace:-@primary --query="SELECT * FROM messages_message_lookup;" -mysqlslap -c 5 --port=15306 --host=127.0.0.1 --iterations=1000 --create-schema=lookup_keyspace:-@replica --query="SELECT * FROM messages_message_lookup;" -## SIMULATED ERRORS -mysqlslap --port=15306 --host=127.0.0.1 --iterations=10000 --create-schema=test_keyspace:80-@primary --query="SELECT name FROM messages;" -mysqlslap --port=15306 --host=127.0.0.1 --iterations=10000 --create-schema=lookup_keyspace:-@replica --query="SELECT name FROM messages_message_lookup;" -``` - -Once the cluster is up and running you should be able to access: - -- grafana (default credentials > admin/admin) http://localhost:3030/ -- prometheus http://localhost:9000/ -- vitess control panel http://localhost:15000/ diff --git a/web/vtadmin/package-lock.json b/web/vtadmin/package-lock.json index a14da6bf0ee..cda1061d5d0 100644 --- a/web/vtadmin/package-lock.json +++ b/web/vtadmin/package-lock.json @@ -10339,7 +10339,7 @@ "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^12.0.1", - "ws": "^8.13.0", + "ws": "^8.17.1", "xml-name-validator": "^4.0.0" }, "engines": { @@ -10777,11 +10777,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -18182,9 +18182,9 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/web/vtadmin/src/api/http.ts b/web/vtadmin/src/api/http.ts index 33d192dbb6f..64d75b23a42 100644 --- a/web/vtadmin/src/api/http.ts +++ b/web/vtadmin/src/api/http.ts @@ -265,7 +265,9 @@ export const deleteTablet = async ({ allowPrimary, clusterID, alias }: DeleteTab req.append('allow_primary', allowPrimary.toString()); } - const { result } = await vtfetch(`/api/tablet/${alias}?${req}`, { method: 'delete' }); + const { result } = await vtfetch(`/api/tablet/${alias}?${req}`, { + method: 'delete', + }); const err = pb.DeleteTabletResponse.verify(result); if (err) throw Error(err); @@ -437,6 +439,15 @@ export const fetchWorkflow = async (params: { clusterID: string; keyspace: strin return pb.Workflow.create(result); }; +export const fetchWorkflowStatus = async (params: { clusterID: string; keyspace: string; name: string }) => { + const { result } = await vtfetch(`/api/workflow/${params.clusterID}/${params.keyspace}/${params.name}/status`); + + const err = vtctldata.WorkflowStatusResponse.verify(result); + if (err) throw Error(err); + + return vtctldata.WorkflowStatusResponse.create(result); +}; + export const fetchVTExplain = async ({ cluster, keyspace, sql }: R) => { // As an easy enhancement for later, we can also validate the request parameters on the front-end // instead of defaulting to '', to save a round trip. @@ -553,7 +564,9 @@ export const reloadSchema = async (params: ReloadSchemaParams) => { req.append('wait_position', params.waitPosition); } - const { result } = await vtfetch(`/api/schemas/reload?${req}`, { method: 'put' }); + const { result } = await vtfetch(`/api/schemas/reload?${req}`, { + method: 'put', + }); const err = pb.ReloadSchemasResponse.verify(result); if (err) throw Error(err); @@ -574,7 +587,9 @@ export const deleteShard = async (params: DeleteShardParams) => { req.append('even_if_serving', String(params.evenIfServing)); req.append('recursive', String(params.recursive)); - const { result } = await vtfetch(`/api/shards/${params.clusterID}?${req}`, { method: 'delete' }); + const { result } = await vtfetch(`/api/shards/${params.clusterID}?${req}`, { + method: 'delete', + }); const err = vtctldata.DeleteShardsResponse.verify(result); if (err) throw Error(err); @@ -701,7 +716,10 @@ export interface RebuildKeyspaceGraphParams { export const rebuildKeyspaceGraph = async (params: RebuildKeyspaceGraphParams) => { const { result } = await vtfetch(`/api/keyspace/${params.clusterID}/${params.keyspace}/rebuild_keyspace_graph`, { method: 'put', - body: JSON.stringify({ cells: params.cells, allow_partial: params.allowPartial }), + body: JSON.stringify({ + cells: params.cells, + allow_partial: params.allowPartial, + }), }); const err = pb.RebuildKeyspaceGraphRequest.verify(result); if (err) throw Error(err); @@ -720,7 +738,11 @@ export interface RemoveKeyspaceCellParams { export const removeKeyspaceCell = async (params: RemoveKeyspaceCellParams) => { const { result } = await vtfetch(`/api/keyspace/${params.clusterID}/${params.keyspace}/remove_keyspace_cell`, { method: 'put', - body: JSON.stringify({ cell: params.cell, force: params.force, recursive: params.recursive }), + body: JSON.stringify({ + cell: params.cell, + force: params.force, + recursive: params.recursive, + }), }); const err = pb.RemoveKeyspaceCellRequest.verify(result); if (err) throw Error(err); 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..4cbd827ee30 100644 --- a/web/vtadmin/src/components/routes/workflow/Workflow.tsx +++ b/web/vtadmin/src/components/routes/workflow/Workflow.tsx @@ -24,6 +24,7 @@ import { WorkspaceTitle } from '../../layout/WorkspaceTitle'; import { useDocumentTitle } from '../../../hooks/useDocumentTitle'; import { KeyspaceLink } from '../../links/KeyspaceLink'; import { WorkflowStreams } from './WorkflowStreams'; +import { WorkflowDetails } from './WorkflowDetails'; import { ContentContainer } from '../../layout/ContentContainer'; import { TabContainer } from '../../tabs/TabContainer'; import { Tab } from '../../tabs/Tab'; @@ -53,22 +54,28 @@ export const Workflow = () => { {name} -
- - Cluster: {clusterID} - - - Target keyspace:{' '} - - {keyspace} - - +
+
+ + Cluster: {clusterID} + + + Target keyspace:{' '} + + {keyspace} + + +
+
+ @@ -77,6 +84,10 @@ export const Workflow = () => { + + + + diff --git a/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx b/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx new file mode 100644 index 00000000000..93023274b27 --- /dev/null +++ b/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx @@ -0,0 +1,260 @@ +/** + * 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. + */ + +import { orderBy } from 'lodash-es'; +import React, { useMemo } from 'react'; +import { Link } from 'react-router-dom'; + +import { useWorkflow, useWorkflowStatus, useWorkflows } from '../../../hooks/api'; +import { formatDateTime } from '../../../util/time'; +import { + TableCopyState, + formatStreamKey, + getReverseWorkflow, + getStreams, + getTableCopyStates, +} from '../../../util/workflows'; +import { DataTable } from '../../dataTable/DataTable'; +import { vtctldata } from '../../../proto/vtadmin'; +import { DataCell } from '../../dataTable/DataCell'; +import { StreamStatePip } from '../../pips/StreamStatePip'; +import { ThrottleThresholdSeconds } from '../Workflows'; + +interface Props { + clusterID: string; + keyspace: string; + name: string; +} + +const SUMMARY_COLUMNS = ['Stream Status', 'Traffic Status', 'Max VReplication Lag', 'Reverse Workflow']; + +const LOG_COLUMNS = ['Type', 'State', 'Updated At', 'Message', 'Count']; + +const TABLE_COPY_STATE_COLUMNS = ['Table Name', 'Total Bytes', 'Bytes Copied', 'Total Rows', 'Rows Copied']; + +const STREAM_COLUMNS = ['Stream', 'State', 'Message', 'Transaction Timestamp', 'Database Name']; + +export const WorkflowDetails = ({ clusterID, keyspace, name }: Props) => { + const { data: workflowData } = useWorkflow({ clusterID, keyspace, name }); + + const { data: workflowsData = [] } = useWorkflows(); + + const { data: workflowStatus } = useWorkflowStatus({ + clusterID, + keyspace, + name, + }); + + const reverseWorkflow = getReverseWorkflow(workflowsData, workflowData); + + const tableCopyStates = getTableCopyStates(workflowStatus); + + const streams = useMemo(() => { + const rows = getStreams(workflowData).map((stream) => ({ + key: formatStreamKey(stream), + ...stream, + })); + + return orderBy(rows, 'streamKey'); + }, [workflowData]); + + const getStreamsSummary = (streamList: typeof streams): string => { + const numStreamsByState: { [key: string]: number } = { + Copying: 0, + Throttled: 0, + Stopped: 0, + Running: 0, + Error: 0, + }; + streamList.forEach((stream) => { + var isThrottled = + Number(stream.throttler_status?.time_throttled?.seconds) > Date.now() / 1000 - ThrottleThresholdSeconds; + const streamState = isThrottled ? 'Throttled' : stream.state; + if (streamState) { + numStreamsByState[streamState]++; + } + }); + const states = Object.keys(numStreamsByState); + let message = ''; + states.forEach((state) => { + if (numStreamsByState[state]) { + let desc = state; + if (state === 'Error') { + desc = 'Failed'; + } + desc += numStreamsByState[state] > 1 ? ' Streams' : ' Stream'; + message += `${numStreamsByState[state]} ${desc}. `; + } + }); + return message; + }; + + const workflowSummary = { + streamSummary: getStreamsSummary(streams), + workflowStatus, + workflowData, + reverseWorkflow, + }; + + const renderSummaryRows = (rows: (typeof workflowSummary)[]) => { + return rows.map((row) => { + const reverseWorkflow = row.reverseWorkflow; + return ( +
+ {row.streamSummary ? row.streamSummary : '-'} + {row.workflowStatus ? row.workflowStatus.traffic_state : '-'} + + {row.workflowData && row.workflowData.workflow?.max_v_replication_lag + ? `${row.workflowData.workflow?.max_v_replication_lag}` + : '-'} + + + {reverseWorkflow ? ( + + {reverseWorkflow.workflow?.name} + + ) : ( + '-' + )} + + + ); + }); + }; + + const renderStreamRows = (rows: typeof streams) => { + return rows.map((row) => { + const href = + row.tablet && row.id + ? `/workflow/${clusterID}/${keyspace}/${name}/stream/${row.tablet.cell}/${row.tablet.uid}/${row.id}` + : null; + + 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} +
+ {rowState} + {row.message ? row.message : '-'} + + {row.transaction_timestamp && row.transaction_timestamp.seconds + ? formatDateTime(row.transaction_timestamp.seconds) + : '-'} + + {row.db_name} +
+ ); + }); + }; + + const renderLogRows = (rows: vtctldata.Workflow.Stream.ILog[]) => { + return rows.map((row) => { + let message: string = row.message ? `${row.message}` : '-'; + // TODO: Investigate if message needs to be JSON parsed in case of "Stream Created" + if (row.type === 'Stream Created') { + message = '-'; + } + return ( + + {`${row.type}`} + {`${row.state}`} + {`${formatDateTime(parseInt(`${row.updated_at?.seconds}`, 10))}`} + {message} + {`${row.count}`} + + ); + }); + }; + + const renderTableCopyStateRows = (tableCopyStates: TableCopyState[]) => { + return tableCopyStates.map((copyState, index) => { + const tableKey = `${copyState.tableName}/${index}`; + return ( + + {`${copyState.tableName}`} + {copyState.bytes_total ? `${copyState.bytes_total}` : `N/A`} + + {copyState.bytes_copied ? `${copyState.bytes_copied}` : `N/A`}{' '} + {copyState.bytes_percentage ? `(${copyState.bytes_percentage}%)` : ``} + + {copyState.rows_total ? `${copyState.rows_total}` : `N/A`} + + {copyState.rows_copied ? `${copyState.rows_copied}` : `N/A`}{' '} + {copyState.rows_percentage ? `(${copyState.rows_percentage}%)` : ``} + + + ); + }); + }; + + return ( +
+ + + {tableCopyStates && ( + + )} +

Recent Logs

+ {streams.map((stream) => ( +
+ +
+ ))} +
+ ); +}; diff --git a/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx b/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx index 6c9bcae2dfa..ef521406e3d 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 { 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/hooks/api.ts b/web/vtadmin/src/hooks/api.ts index f84eff40cf4..536293702c1 100644 --- a/web/vtadmin/src/hooks/api.ts +++ b/web/vtadmin/src/hooks/api.ts @@ -41,6 +41,7 @@ import { fetchVtctlds, fetchVTExplain, fetchWorkflow, + fetchWorkflowStatus, fetchWorkflows, TabletDebugVarsResponse, refreshState, @@ -449,6 +450,16 @@ export const useWorkflow = ( }); }; +/** + * useWorkflowStatus is a query hook that fetches status for a single workflow. + */ +export const useWorkflowStatus = ( + params: Parameters[0], + options?: UseQueryOptions | undefined +) => { + return useQuery(['workflow_status', params], () => fetchWorkflowStatus(params)); +}; + /** * useReloadSchema is a mutate hook that reloads schemas in one or more * keyspaces, shards, or tablets in the cluster, depending on the request parameters. diff --git a/web/vtadmin/src/proto/vtadmin.d.ts b/web/vtadmin/src/proto/vtadmin.d.ts index 67b1fca3d05..23eae247065 100644 --- a/web/vtadmin/src/proto/vtadmin.d.ts +++ b/web/vtadmin/src/proto/vtadmin.d.ts @@ -513,6 +513,48 @@ export namespace vtadmin { */ public getWorkflows(request: vtadmin.IGetWorkflowsRequest): Promise; + /** + * Calls GetWorkflowStatus. + * @param request GetWorkflowStatusRequest message or plain object + * @param callback Node-style callback called with the error, if any, and WorkflowStatusResponse + */ + public getWorkflowStatus(request: vtadmin.IGetWorkflowStatusRequest, callback: vtadmin.VTAdmin.GetWorkflowStatusCallback): void; + + /** + * Calls GetWorkflowStatus. + * @param request GetWorkflowStatusRequest message or plain object + * @returns Promise + */ + public getWorkflowStatus(request: vtadmin.IGetWorkflowStatusRequest): Promise; + + /** + * Calls StartWorkflow. + * @param request StartWorkflowRequest message or plain object + * @param callback Node-style callback called with the error, if any, and WorkflowUpdateResponse + */ + public startWorkflow(request: vtadmin.IStartWorkflowRequest, callback: vtadmin.VTAdmin.StartWorkflowCallback): void; + + /** + * Calls StartWorkflow. + * @param request StartWorkflowRequest message or plain object + * @returns Promise + */ + public startWorkflow(request: vtadmin.IStartWorkflowRequest): Promise; + + /** + * Calls StopWorkflow. + * @param request StopWorkflowRequest message or plain object + * @param callback Node-style callback called with the error, if any, and WorkflowUpdateResponse + */ + public stopWorkflow(request: vtadmin.IStopWorkflowRequest, callback: vtadmin.VTAdmin.StopWorkflowCallback): void; + + /** + * Calls StopWorkflow. + * @param request StopWorkflowRequest message or plain object + * @returns Promise + */ + public stopWorkflow(request: vtadmin.IStopWorkflowRequest): Promise; + /** * Calls LaunchSchemaMigration. * @param request LaunchSchemaMigrationRequest message or plain object @@ -1083,6 +1125,27 @@ export namespace vtadmin { */ type GetWorkflowsCallback = (error: (Error|null), response?: vtadmin.GetWorkflowsResponse) => void; + /** + * Callback as used by {@link vtadmin.VTAdmin#getWorkflowStatus}. + * @param error Error, if any + * @param [response] WorkflowStatusResponse + */ + type GetWorkflowStatusCallback = (error: (Error|null), response?: vtctldata.WorkflowStatusResponse) => void; + + /** + * Callback as used by {@link vtadmin.VTAdmin#startWorkflow}. + * @param error Error, if any + * @param [response] WorkflowUpdateResponse + */ + type StartWorkflowCallback = (error: (Error|null), response?: vtctldata.WorkflowUpdateResponse) => void; + + /** + * Callback as used by {@link vtadmin.VTAdmin#stopWorkflow}. + * @param error Error, if any + * @param [response] WorkflowUpdateResponse + */ + type StopWorkflowCallback = (error: (Error|null), response?: vtctldata.WorkflowUpdateResponse) => void; + /** * Callback as used by {@link vtadmin.VTAdmin#launchSchemaMigration}. * @param error Error, if any @@ -8616,6 +8679,333 @@ export namespace vtadmin { public static getTypeUrl(typeUrlPrefix?: string): string; } + /** Properties of a GetWorkflowStatusRequest. */ + interface IGetWorkflowStatusRequest { + + /** GetWorkflowStatusRequest cluster_id */ + cluster_id?: (string|null); + + /** GetWorkflowStatusRequest keyspace */ + keyspace?: (string|null); + + /** GetWorkflowStatusRequest name */ + name?: (string|null); + } + + /** Represents a GetWorkflowStatusRequest. */ + class GetWorkflowStatusRequest implements IGetWorkflowStatusRequest { + + /** + * Constructs a new GetWorkflowStatusRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtadmin.IGetWorkflowStatusRequest); + + /** GetWorkflowStatusRequest cluster_id. */ + public cluster_id: string; + + /** GetWorkflowStatusRequest keyspace. */ + public keyspace: string; + + /** GetWorkflowStatusRequest name. */ + public name: string; + + /** + * Creates a new GetWorkflowStatusRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns GetWorkflowStatusRequest instance + */ + public static create(properties?: vtadmin.IGetWorkflowStatusRequest): vtadmin.GetWorkflowStatusRequest; + + /** + * Encodes the specified GetWorkflowStatusRequest message. Does not implicitly {@link vtadmin.GetWorkflowStatusRequest.verify|verify} messages. + * @param message GetWorkflowStatusRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtadmin.IGetWorkflowStatusRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified GetWorkflowStatusRequest message, length delimited. Does not implicitly {@link vtadmin.GetWorkflowStatusRequest.verify|verify} messages. + * @param message GetWorkflowStatusRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtadmin.IGetWorkflowStatusRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a GetWorkflowStatusRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns GetWorkflowStatusRequest + * @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): vtadmin.GetWorkflowStatusRequest; + + /** + * Decodes a GetWorkflowStatusRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns GetWorkflowStatusRequest + * @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)): vtadmin.GetWorkflowStatusRequest; + + /** + * Verifies a GetWorkflowStatusRequest 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 GetWorkflowStatusRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns GetWorkflowStatusRequest + */ + public static fromObject(object: { [k: string]: any }): vtadmin.GetWorkflowStatusRequest; + + /** + * Creates a plain object from a GetWorkflowStatusRequest message. Also converts values to other types if specified. + * @param message GetWorkflowStatusRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtadmin.GetWorkflowStatusRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this GetWorkflowStatusRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for GetWorkflowStatusRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a StartWorkflowRequest. */ + interface IStartWorkflowRequest { + + /** StartWorkflowRequest cluster_id */ + cluster_id?: (string|null); + + /** StartWorkflowRequest keyspace */ + keyspace?: (string|null); + + /** StartWorkflowRequest workflow */ + workflow?: (string|null); + } + + /** Represents a StartWorkflowRequest. */ + class StartWorkflowRequest implements IStartWorkflowRequest { + + /** + * Constructs a new StartWorkflowRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtadmin.IStartWorkflowRequest); + + /** StartWorkflowRequest cluster_id. */ + public cluster_id: string; + + /** StartWorkflowRequest keyspace. */ + public keyspace: string; + + /** StartWorkflowRequest workflow. */ + public workflow: string; + + /** + * Creates a new StartWorkflowRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns StartWorkflowRequest instance + */ + public static create(properties?: vtadmin.IStartWorkflowRequest): vtadmin.StartWorkflowRequest; + + /** + * Encodes the specified StartWorkflowRequest message. Does not implicitly {@link vtadmin.StartWorkflowRequest.verify|verify} messages. + * @param message StartWorkflowRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtadmin.IStartWorkflowRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified StartWorkflowRequest message, length delimited. Does not implicitly {@link vtadmin.StartWorkflowRequest.verify|verify} messages. + * @param message StartWorkflowRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtadmin.IStartWorkflowRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a StartWorkflowRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns StartWorkflowRequest + * @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): vtadmin.StartWorkflowRequest; + + /** + * Decodes a StartWorkflowRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns StartWorkflowRequest + * @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)): vtadmin.StartWorkflowRequest; + + /** + * Verifies a StartWorkflowRequest 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 StartWorkflowRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns StartWorkflowRequest + */ + public static fromObject(object: { [k: string]: any }): vtadmin.StartWorkflowRequest; + + /** + * Creates a plain object from a StartWorkflowRequest message. Also converts values to other types if specified. + * @param message StartWorkflowRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtadmin.StartWorkflowRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this StartWorkflowRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for StartWorkflowRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a StopWorkflowRequest. */ + interface IStopWorkflowRequest { + + /** StopWorkflowRequest cluster_id */ + cluster_id?: (string|null); + + /** StopWorkflowRequest keyspace */ + keyspace?: (string|null); + + /** StopWorkflowRequest workflow */ + workflow?: (string|null); + } + + /** Represents a StopWorkflowRequest. */ + class StopWorkflowRequest implements IStopWorkflowRequest { + + /** + * Constructs a new StopWorkflowRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtadmin.IStopWorkflowRequest); + + /** StopWorkflowRequest cluster_id. */ + public cluster_id: string; + + /** StopWorkflowRequest keyspace. */ + public keyspace: string; + + /** StopWorkflowRequest workflow. */ + public workflow: string; + + /** + * Creates a new StopWorkflowRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns StopWorkflowRequest instance + */ + public static create(properties?: vtadmin.IStopWorkflowRequest): vtadmin.StopWorkflowRequest; + + /** + * Encodes the specified StopWorkflowRequest message. Does not implicitly {@link vtadmin.StopWorkflowRequest.verify|verify} messages. + * @param message StopWorkflowRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtadmin.IStopWorkflowRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified StopWorkflowRequest message, length delimited. Does not implicitly {@link vtadmin.StopWorkflowRequest.verify|verify} messages. + * @param message StopWorkflowRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtadmin.IStopWorkflowRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a StopWorkflowRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns StopWorkflowRequest + * @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): vtadmin.StopWorkflowRequest; + + /** + * Decodes a StopWorkflowRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns StopWorkflowRequest + * @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)): vtadmin.StopWorkflowRequest; + + /** + * Verifies a StopWorkflowRequest 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 StopWorkflowRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns StopWorkflowRequest + */ + public static fromObject(object: { [k: string]: any }): vtadmin.StopWorkflowRequest; + + /** + * Creates a plain object from a StopWorkflowRequest message. Also converts values to other types if specified. + * @param message StopWorkflowRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtadmin.StopWorkflowRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this StopWorkflowRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for StopWorkflowRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + /** Properties of a GetWorkflowsRequest. */ interface IGetWorkflowsRequest { @@ -29518,6 +29908,9 @@ export namespace tabletmanagerdata { /** VDiffReportOptions max_sample_rows */ max_sample_rows?: (number|Long|null); + + /** VDiffReportOptions row_diff_column_truncate_at */ + row_diff_column_truncate_at?: (number|Long|null); } /** Represents a VDiffReportOptions. */ @@ -29541,6 +29934,9 @@ export namespace tabletmanagerdata { /** VDiffReportOptions max_sample_rows. */ public max_sample_rows: (number|Long); + /** VDiffReportOptions row_diff_column_truncate_at. */ + public row_diff_column_truncate_at: (number|Long); + /** * Creates a new VDiffReportOptions instance using the specified properties. * @param [properties] Properties to set @@ -30630,6 +31026,16 @@ export namespace tabletmanagerdata { public static getTypeUrl(typeUrlPrefix?: string): string; } + /** CheckThrottlerResponseCode enum. */ + enum CheckThrottlerResponseCode { + UNDEFINED = 0, + OK = 1, + THRESHOLD_EXCEEDED = 2, + APP_DENIED = 3, + UNKNOWN_METRIC = 4, + INTERNAL_ERROR = 5 + } + /** Properties of a CheckThrottlerResponse. */ interface ICheckThrottlerResponse { @@ -30653,6 +31059,15 @@ export namespace tabletmanagerdata { /** CheckThrottlerResponse metrics */ metrics?: ({ [k: string]: tabletmanagerdata.CheckThrottlerResponse.IMetric }|null); + + /** CheckThrottlerResponse app_name */ + app_name?: (string|null); + + /** CheckThrottlerResponse summary */ + summary?: (string|null); + + /** CheckThrottlerResponse response_code */ + response_code?: (tabletmanagerdata.CheckThrottlerResponseCode|null); } /** Represents a CheckThrottlerResponse. */ @@ -30685,6 +31100,15 @@ export namespace tabletmanagerdata { /** CheckThrottlerResponse metrics. */ public metrics: { [k: string]: tabletmanagerdata.CheckThrottlerResponse.IMetric }; + /** CheckThrottlerResponse app_name. */ + public app_name: string; + + /** CheckThrottlerResponse summary. */ + public summary: string; + + /** CheckThrottlerResponse response_code. */ + public response_code: tabletmanagerdata.CheckThrottlerResponseCode; + /** * Creates a new CheckThrottlerResponse instance using the specified properties. * @param [properties] Properties to set @@ -30788,6 +31212,9 @@ export namespace tabletmanagerdata { /** Metric scope */ scope?: (string|null); + + /** Metric response_code */ + response_code?: (tabletmanagerdata.CheckThrottlerResponseCode|null); } /** Represents a Metric. */ @@ -30820,6 +31247,9 @@ export namespace tabletmanagerdata { /** Metric scope. */ public scope: string; + /** Metric response_code. */ + public response_code: tabletmanagerdata.CheckThrottlerResponseCode; + /** * Creates a new Metric instance using the specified properties. * @param [properties] Properties to set @@ -31405,6 +31835,9 @@ export namespace tabletmanagerdata { /** RecentApp status_code */ status_code?: (number|null); + + /** RecentApp response_code */ + response_code?: (tabletmanagerdata.CheckThrottlerResponseCode|null); } /** Represents a RecentApp. */ @@ -31422,6 +31855,9 @@ export namespace tabletmanagerdata { /** RecentApp status_code. */ public status_code: number; + /** RecentApp response_code. */ + public response_code: tabletmanagerdata.CheckThrottlerResponseCode; + /** * Creates a new RecentApp instance using the specified properties. * @param [properties] Properties to set @@ -33086,6 +33522,9 @@ export namespace binlogdata { /** RowEvent flags */ flags?: (number|null); + + /** RowEvent is_internal_table */ + is_internal_table?: (boolean|null); } /** Represents a RowEvent. */ @@ -33112,6 +33551,9 @@ export namespace binlogdata { /** RowEvent flags. */ public flags: number; + /** RowEvent is_internal_table. */ + public is_internal_table: boolean; + /** * Creates a new RowEvent instance using the specified properties. * @param [properties] Properties to set @@ -33207,6 +33649,9 @@ export namespace binlogdata { /** FieldEvent enum_set_string_values */ enum_set_string_values?: (boolean|null); + + /** FieldEvent is_internal_table */ + is_internal_table?: (boolean|null); } /** Represents a FieldEvent. */ @@ -33233,6 +33678,9 @@ export namespace binlogdata { /** FieldEvent enum_set_string_values. */ public enum_set_string_values: boolean; + /** FieldEvent is_internal_table. */ + public is_internal_table: boolean; + /** * Creates a new FieldEvent instance using the specified properties. * @param [properties] Properties to set @@ -33809,6 +34257,9 @@ export namespace binlogdata { /** VEvent throttled */ throttled?: (boolean|null); + + /** VEvent throttled_reason */ + throttled_reason?: (string|null); } /** Represents a VEvent. */ @@ -33862,6 +34313,9 @@ export namespace binlogdata { /** VEvent throttled. */ public throttled: boolean; + /** VEvent throttled_reason. */ + public throttled_reason: string; + /** * Creates a new VEvent instance using the specified properties. * @param [properties] Properties to set @@ -34152,6 +34606,103 @@ export namespace binlogdata { public static getTypeUrl(typeUrlPrefix?: string): string; } + /** Properties of a VStreamOptions. */ + interface IVStreamOptions { + + /** VStreamOptions internal_tables */ + internal_tables?: (string[]|null); + } + + /** Represents a VStreamOptions. */ + class VStreamOptions implements IVStreamOptions { + + /** + * Constructs a new VStreamOptions. + * @param [properties] Properties to set + */ + constructor(properties?: binlogdata.IVStreamOptions); + + /** VStreamOptions internal_tables. */ + public internal_tables: string[]; + + /** + * Creates a new VStreamOptions instance using the specified properties. + * @param [properties] Properties to set + * @returns VStreamOptions instance + */ + public static create(properties?: binlogdata.IVStreamOptions): binlogdata.VStreamOptions; + + /** + * Encodes the specified VStreamOptions message. Does not implicitly {@link binlogdata.VStreamOptions.verify|verify} messages. + * @param message VStreamOptions message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: binlogdata.IVStreamOptions, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified VStreamOptions message, length delimited. Does not implicitly {@link binlogdata.VStreamOptions.verify|verify} messages. + * @param message VStreamOptions message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: binlogdata.IVStreamOptions, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a VStreamOptions message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns VStreamOptions + * @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): binlogdata.VStreamOptions; + + /** + * Decodes a VStreamOptions message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns VStreamOptions + * @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)): binlogdata.VStreamOptions; + + /** + * Verifies a VStreamOptions 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 VStreamOptions message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns VStreamOptions + */ + public static fromObject(object: { [k: string]: any }): binlogdata.VStreamOptions; + + /** + * Creates a plain object from a VStreamOptions message. Also converts values to other types if specified. + * @param message VStreamOptions + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: binlogdata.VStreamOptions, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this VStreamOptions to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for VStreamOptions + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + /** Properties of a VStreamRequest. */ interface IVStreamRequest { @@ -34172,6 +34723,9 @@ export namespace binlogdata { /** VStreamRequest table_last_p_ks */ table_last_p_ks?: (binlogdata.ITableLastPK[]|null); + + /** VStreamRequest options */ + options?: (binlogdata.IVStreamOptions|null); } /** Represents a VStreamRequest. */ @@ -34201,6 +34755,9 @@ export namespace binlogdata { /** VStreamRequest table_last_p_ks. */ public table_last_p_ks: binlogdata.ITableLastPK[]; + /** VStreamRequest options. */ + public options?: (binlogdata.IVStreamOptions|null); + /** * Creates a new VStreamRequest instance using the specified properties. * @param [properties] Properties to set @@ -34520,6 +35077,9 @@ export namespace binlogdata { /** VStreamRowsResponse heartbeat */ heartbeat?: (boolean|null); + + /** VStreamRowsResponse throttled_reason */ + throttled_reason?: (string|null); } /** Represents a VStreamRowsResponse. */ @@ -34552,6 +35112,9 @@ export namespace binlogdata { /** VStreamRowsResponse heartbeat. */ public heartbeat: boolean; + /** VStreamRowsResponse throttled_reason. */ + public throttled_reason: string; + /** * Creates a new VStreamRowsResponse instance using the specified properties. * @param [properties] Properties to set @@ -35943,7 +36506,8 @@ export namespace query { EXPRESSION = 31, HEXNUM = 4128, HEXVAL = 4129, - BITNUM = 4130 + BITNUM = 4130, + VECTOR = 2083 } /** Properties of a Value. */ @@ -40102,6 +40666,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 +43158,9 @@ export namespace query { /** RealtimeStats udfs_changed */ udfs_changed?: (boolean|null); + + /** RealtimeStats tx_unresolved */ + tx_unresolved?: (boolean|null); } /** Represents a RealtimeStats. */ @@ -42426,6 +43199,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 +43520,8 @@ export namespace query { enum TransactionState { UNKNOWN = 0, PREPARE = 1, - COMMIT = 2, - ROLLBACK = 3 + ROLLBACK = 2, + COMMIT = 3 } /** Properties of a TransactionMetadata. */ @@ -50426,26 +51202,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. */ @@ -50457,26 +51218,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. @@ -50556,142 +51302,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 { @@ -58860,59 +59470,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. */ @@ -58924,59 +59483,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. @@ -59056,318 +59564,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 { @@ -63424,6 +63620,9 @@ export namespace vtctldata { /** PlannedReparentShardRequest tolerable_replication_lag */ tolerable_replication_lag?: (vttime.IDuration|null); + + /** PlannedReparentShardRequest allow_cross_cell_promotion */ + allow_cross_cell_promotion?: (boolean|null); } /** Represents a PlannedReparentShardRequest. */ @@ -63453,6 +63652,9 @@ export namespace vtctldata { /** PlannedReparentShardRequest tolerable_replication_lag. */ public tolerable_replication_lag?: (vttime.IDuration|null); + /** PlannedReparentShardRequest allow_cross_cell_promotion. */ + public allow_cross_cell_promotion: boolean; + /** * Creates a new PlannedReparentShardRequest instance using the specified properties. * @param [properties] Properties to set @@ -71651,6 +71853,9 @@ export namespace vtctldata { /** VDiffCreateRequest max_diff_duration */ max_diff_duration?: (vttime.IDuration|null); + + /** VDiffCreateRequest row_diff_column_truncate_at */ + row_diff_column_truncate_at?: (number|Long|null); } /** Represents a VDiffCreateRequest. */ @@ -71722,6 +71927,9 @@ export namespace vtctldata { /** VDiffCreateRequest max_diff_duration. */ public max_diff_duration?: (vttime.IDuration|null); + /** VDiffCreateRequest row_diff_column_truncate_at. */ + public row_diff_column_truncate_at: (number|Long); + /** * Creates a new VDiffCreateRequest instance using the specified properties. * @param [properties] Properties to set diff --git a/web/vtadmin/src/proto/vtadmin.js b/web/vtadmin/src/proto/vtadmin.js index f36e43dadec..b6d0dc5a341 100644 --- a/web/vtadmin/src/proto/vtadmin.js +++ b/web/vtadmin/src/proto/vtadmin.js @@ -1203,6 +1203,105 @@ export const vtadmin = $root.vtadmin = (() => { * @variation 2 */ + /** + * Callback as used by {@link vtadmin.VTAdmin#getWorkflowStatus}. + * @memberof vtadmin.VTAdmin + * @typedef GetWorkflowStatusCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {vtctldata.WorkflowStatusResponse} [response] WorkflowStatusResponse + */ + + /** + * Calls GetWorkflowStatus. + * @function getWorkflowStatus + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IGetWorkflowStatusRequest} request GetWorkflowStatusRequest message or plain object + * @param {vtadmin.VTAdmin.GetWorkflowStatusCallback} callback Node-style callback called with the error, if any, and WorkflowStatusResponse + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(VTAdmin.prototype.getWorkflowStatus = function getWorkflowStatus(request, callback) { + return this.rpcCall(getWorkflowStatus, $root.vtadmin.GetWorkflowStatusRequest, $root.vtctldata.WorkflowStatusResponse, request, callback); + }, "name", { value: "GetWorkflowStatus" }); + + /** + * Calls GetWorkflowStatus. + * @function getWorkflowStatus + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IGetWorkflowStatusRequest} request GetWorkflowStatusRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + + /** + * Callback as used by {@link vtadmin.VTAdmin#startWorkflow}. + * @memberof vtadmin.VTAdmin + * @typedef StartWorkflowCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {vtctldata.WorkflowUpdateResponse} [response] WorkflowUpdateResponse + */ + + /** + * Calls StartWorkflow. + * @function startWorkflow + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IStartWorkflowRequest} request StartWorkflowRequest message or plain object + * @param {vtadmin.VTAdmin.StartWorkflowCallback} callback Node-style callback called with the error, if any, and WorkflowUpdateResponse + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(VTAdmin.prototype.startWorkflow = function startWorkflow(request, callback) { + return this.rpcCall(startWorkflow, $root.vtadmin.StartWorkflowRequest, $root.vtctldata.WorkflowUpdateResponse, request, callback); + }, "name", { value: "StartWorkflow" }); + + /** + * Calls StartWorkflow. + * @function startWorkflow + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IStartWorkflowRequest} request StartWorkflowRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + + /** + * Callback as used by {@link vtadmin.VTAdmin#stopWorkflow}. + * @memberof vtadmin.VTAdmin + * @typedef StopWorkflowCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {vtctldata.WorkflowUpdateResponse} [response] WorkflowUpdateResponse + */ + + /** + * Calls StopWorkflow. + * @function stopWorkflow + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IStopWorkflowRequest} request StopWorkflowRequest message or plain object + * @param {vtadmin.VTAdmin.StopWorkflowCallback} callback Node-style callback called with the error, if any, and WorkflowUpdateResponse + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(VTAdmin.prototype.stopWorkflow = function stopWorkflow(request, callback) { + return this.rpcCall(stopWorkflow, $root.vtadmin.StopWorkflowRequest, $root.vtctldata.WorkflowUpdateResponse, request, callback); + }, "name", { value: "StopWorkflow" }); + + /** + * Calls StopWorkflow. + * @function stopWorkflow + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IStopWorkflowRequest} request StopWorkflowRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link vtadmin.VTAdmin#launchSchemaMigration}. * @memberof vtadmin.VTAdmin @@ -19514,6 +19613,756 @@ export const vtadmin = $root.vtadmin = (() => { return GetWorkflowRequest; })(); + vtadmin.GetWorkflowStatusRequest = (function() { + + /** + * Properties of a GetWorkflowStatusRequest. + * @memberof vtadmin + * @interface IGetWorkflowStatusRequest + * @property {string|null} [cluster_id] GetWorkflowStatusRequest cluster_id + * @property {string|null} [keyspace] GetWorkflowStatusRequest keyspace + * @property {string|null} [name] GetWorkflowStatusRequest name + */ + + /** + * Constructs a new GetWorkflowStatusRequest. + * @memberof vtadmin + * @classdesc Represents a GetWorkflowStatusRequest. + * @implements IGetWorkflowStatusRequest + * @constructor + * @param {vtadmin.IGetWorkflowStatusRequest=} [properties] Properties to set + */ + function GetWorkflowStatusRequest(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]]; + } + + /** + * GetWorkflowStatusRequest cluster_id. + * @member {string} cluster_id + * @memberof vtadmin.GetWorkflowStatusRequest + * @instance + */ + GetWorkflowStatusRequest.prototype.cluster_id = ""; + + /** + * GetWorkflowStatusRequest keyspace. + * @member {string} keyspace + * @memberof vtadmin.GetWorkflowStatusRequest + * @instance + */ + GetWorkflowStatusRequest.prototype.keyspace = ""; + + /** + * GetWorkflowStatusRequest name. + * @member {string} name + * @memberof vtadmin.GetWorkflowStatusRequest + * @instance + */ + GetWorkflowStatusRequest.prototype.name = ""; + + /** + * Creates a new GetWorkflowStatusRequest instance using the specified properties. + * @function create + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {vtadmin.IGetWorkflowStatusRequest=} [properties] Properties to set + * @returns {vtadmin.GetWorkflowStatusRequest} GetWorkflowStatusRequest instance + */ + GetWorkflowStatusRequest.create = function create(properties) { + return new GetWorkflowStatusRequest(properties); + }; + + /** + * Encodes the specified GetWorkflowStatusRequest message. Does not implicitly {@link vtadmin.GetWorkflowStatusRequest.verify|verify} messages. + * @function encode + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {vtadmin.IGetWorkflowStatusRequest} message GetWorkflowStatusRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetWorkflowStatusRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.cluster_id != null && Object.hasOwnProperty.call(message, "cluster_id")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.cluster_id); + if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.keyspace); + if (message.name != null && Object.hasOwnProperty.call(message, "name")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.name); + return writer; + }; + + /** + * Encodes the specified GetWorkflowStatusRequest message, length delimited. Does not implicitly {@link vtadmin.GetWorkflowStatusRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {vtadmin.IGetWorkflowStatusRequest} message GetWorkflowStatusRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetWorkflowStatusRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetWorkflowStatusRequest message from the specified reader or buffer. + * @function decode + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtadmin.GetWorkflowStatusRequest} GetWorkflowStatusRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetWorkflowStatusRequest.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.vtadmin.GetWorkflowStatusRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.cluster_id = reader.string(); + break; + } + case 2: { + message.keyspace = reader.string(); + break; + } + case 3: { + message.name = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetWorkflowStatusRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtadmin.GetWorkflowStatusRequest} GetWorkflowStatusRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetWorkflowStatusRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetWorkflowStatusRequest message. + * @function verify + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetWorkflowStatusRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + if (!$util.isString(message.cluster_id)) + return "cluster_id: string expected"; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + if (!$util.isString(message.keyspace)) + return "keyspace: string expected"; + if (message.name != null && message.hasOwnProperty("name")) + if (!$util.isString(message.name)) + return "name: string expected"; + return null; + }; + + /** + * Creates a GetWorkflowStatusRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {Object.} object Plain object + * @returns {vtadmin.GetWorkflowStatusRequest} GetWorkflowStatusRequest + */ + GetWorkflowStatusRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtadmin.GetWorkflowStatusRequest) + return object; + let message = new $root.vtadmin.GetWorkflowStatusRequest(); + if (object.cluster_id != null) + message.cluster_id = String(object.cluster_id); + if (object.keyspace != null) + message.keyspace = String(object.keyspace); + if (object.name != null) + message.name = String(object.name); + return message; + }; + + /** + * Creates a plain object from a GetWorkflowStatusRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {vtadmin.GetWorkflowStatusRequest} message GetWorkflowStatusRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetWorkflowStatusRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.cluster_id = ""; + object.keyspace = ""; + object.name = ""; + } + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + object.cluster_id = message.cluster_id; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + object.keyspace = message.keyspace; + if (message.name != null && message.hasOwnProperty("name")) + object.name = message.name; + return object; + }; + + /** + * Converts this GetWorkflowStatusRequest to JSON. + * @function toJSON + * @memberof vtadmin.GetWorkflowStatusRequest + * @instance + * @returns {Object.} JSON object + */ + GetWorkflowStatusRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for GetWorkflowStatusRequest + * @function getTypeUrl + * @memberof vtadmin.GetWorkflowStatusRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + GetWorkflowStatusRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtadmin.GetWorkflowStatusRequest"; + }; + + return GetWorkflowStatusRequest; + })(); + + vtadmin.StartWorkflowRequest = (function() { + + /** + * Properties of a StartWorkflowRequest. + * @memberof vtadmin + * @interface IStartWorkflowRequest + * @property {string|null} [cluster_id] StartWorkflowRequest cluster_id + * @property {string|null} [keyspace] StartWorkflowRequest keyspace + * @property {string|null} [workflow] StartWorkflowRequest workflow + */ + + /** + * Constructs a new StartWorkflowRequest. + * @memberof vtadmin + * @classdesc Represents a StartWorkflowRequest. + * @implements IStartWorkflowRequest + * @constructor + * @param {vtadmin.IStartWorkflowRequest=} [properties] Properties to set + */ + function StartWorkflowRequest(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]]; + } + + /** + * StartWorkflowRequest cluster_id. + * @member {string} cluster_id + * @memberof vtadmin.StartWorkflowRequest + * @instance + */ + StartWorkflowRequest.prototype.cluster_id = ""; + + /** + * StartWorkflowRequest keyspace. + * @member {string} keyspace + * @memberof vtadmin.StartWorkflowRequest + * @instance + */ + StartWorkflowRequest.prototype.keyspace = ""; + + /** + * StartWorkflowRequest workflow. + * @member {string} workflow + * @memberof vtadmin.StartWorkflowRequest + * @instance + */ + StartWorkflowRequest.prototype.workflow = ""; + + /** + * Creates a new StartWorkflowRequest instance using the specified properties. + * @function create + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {vtadmin.IStartWorkflowRequest=} [properties] Properties to set + * @returns {vtadmin.StartWorkflowRequest} StartWorkflowRequest instance + */ + StartWorkflowRequest.create = function create(properties) { + return new StartWorkflowRequest(properties); + }; + + /** + * Encodes the specified StartWorkflowRequest message. Does not implicitly {@link vtadmin.StartWorkflowRequest.verify|verify} messages. + * @function encode + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {vtadmin.IStartWorkflowRequest} message StartWorkflowRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StartWorkflowRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.cluster_id != null && Object.hasOwnProperty.call(message, "cluster_id")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.cluster_id); + if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.keyspace); + if (message.workflow != null && Object.hasOwnProperty.call(message, "workflow")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.workflow); + return writer; + }; + + /** + * Encodes the specified StartWorkflowRequest message, length delimited. Does not implicitly {@link vtadmin.StartWorkflowRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {vtadmin.IStartWorkflowRequest} message StartWorkflowRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StartWorkflowRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a StartWorkflowRequest message from the specified reader or buffer. + * @function decode + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtadmin.StartWorkflowRequest} StartWorkflowRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StartWorkflowRequest.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.vtadmin.StartWorkflowRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.cluster_id = reader.string(); + break; + } + case 2: { + message.keyspace = reader.string(); + break; + } + case 3: { + message.workflow = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a StartWorkflowRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtadmin.StartWorkflowRequest} StartWorkflowRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StartWorkflowRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a StartWorkflowRequest message. + * @function verify + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + StartWorkflowRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + if (!$util.isString(message.cluster_id)) + return "cluster_id: string 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"; + return null; + }; + + /** + * Creates a StartWorkflowRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {Object.} object Plain object + * @returns {vtadmin.StartWorkflowRequest} StartWorkflowRequest + */ + StartWorkflowRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtadmin.StartWorkflowRequest) + return object; + let message = new $root.vtadmin.StartWorkflowRequest(); + if (object.cluster_id != null) + message.cluster_id = String(object.cluster_id); + if (object.keyspace != null) + message.keyspace = String(object.keyspace); + if (object.workflow != null) + message.workflow = String(object.workflow); + return message; + }; + + /** + * Creates a plain object from a StartWorkflowRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {vtadmin.StartWorkflowRequest} message StartWorkflowRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + StartWorkflowRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.cluster_id = ""; + object.keyspace = ""; + object.workflow = ""; + } + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + object.cluster_id = message.cluster_id; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + object.keyspace = message.keyspace; + if (message.workflow != null && message.hasOwnProperty("workflow")) + object.workflow = message.workflow; + return object; + }; + + /** + * Converts this StartWorkflowRequest to JSON. + * @function toJSON + * @memberof vtadmin.StartWorkflowRequest + * @instance + * @returns {Object.} JSON object + */ + StartWorkflowRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for StartWorkflowRequest + * @function getTypeUrl + * @memberof vtadmin.StartWorkflowRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + StartWorkflowRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtadmin.StartWorkflowRequest"; + }; + + return StartWorkflowRequest; + })(); + + vtadmin.StopWorkflowRequest = (function() { + + /** + * Properties of a StopWorkflowRequest. + * @memberof vtadmin + * @interface IStopWorkflowRequest + * @property {string|null} [cluster_id] StopWorkflowRequest cluster_id + * @property {string|null} [keyspace] StopWorkflowRequest keyspace + * @property {string|null} [workflow] StopWorkflowRequest workflow + */ + + /** + * Constructs a new StopWorkflowRequest. + * @memberof vtadmin + * @classdesc Represents a StopWorkflowRequest. + * @implements IStopWorkflowRequest + * @constructor + * @param {vtadmin.IStopWorkflowRequest=} [properties] Properties to set + */ + function StopWorkflowRequest(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]]; + } + + /** + * StopWorkflowRequest cluster_id. + * @member {string} cluster_id + * @memberof vtadmin.StopWorkflowRequest + * @instance + */ + StopWorkflowRequest.prototype.cluster_id = ""; + + /** + * StopWorkflowRequest keyspace. + * @member {string} keyspace + * @memberof vtadmin.StopWorkflowRequest + * @instance + */ + StopWorkflowRequest.prototype.keyspace = ""; + + /** + * StopWorkflowRequest workflow. + * @member {string} workflow + * @memberof vtadmin.StopWorkflowRequest + * @instance + */ + StopWorkflowRequest.prototype.workflow = ""; + + /** + * Creates a new StopWorkflowRequest instance using the specified properties. + * @function create + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {vtadmin.IStopWorkflowRequest=} [properties] Properties to set + * @returns {vtadmin.StopWorkflowRequest} StopWorkflowRequest instance + */ + StopWorkflowRequest.create = function create(properties) { + return new StopWorkflowRequest(properties); + }; + + /** + * Encodes the specified StopWorkflowRequest message. Does not implicitly {@link vtadmin.StopWorkflowRequest.verify|verify} messages. + * @function encode + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {vtadmin.IStopWorkflowRequest} message StopWorkflowRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StopWorkflowRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.cluster_id != null && Object.hasOwnProperty.call(message, "cluster_id")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.cluster_id); + if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.keyspace); + if (message.workflow != null && Object.hasOwnProperty.call(message, "workflow")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.workflow); + return writer; + }; + + /** + * Encodes the specified StopWorkflowRequest message, length delimited. Does not implicitly {@link vtadmin.StopWorkflowRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {vtadmin.IStopWorkflowRequest} message StopWorkflowRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StopWorkflowRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a StopWorkflowRequest message from the specified reader or buffer. + * @function decode + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtadmin.StopWorkflowRequest} StopWorkflowRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StopWorkflowRequest.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.vtadmin.StopWorkflowRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.cluster_id = reader.string(); + break; + } + case 2: { + message.keyspace = reader.string(); + break; + } + case 3: { + message.workflow = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a StopWorkflowRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtadmin.StopWorkflowRequest} StopWorkflowRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StopWorkflowRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a StopWorkflowRequest message. + * @function verify + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + StopWorkflowRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + if (!$util.isString(message.cluster_id)) + return "cluster_id: string 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"; + return null; + }; + + /** + * Creates a StopWorkflowRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {Object.} object Plain object + * @returns {vtadmin.StopWorkflowRequest} StopWorkflowRequest + */ + StopWorkflowRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtadmin.StopWorkflowRequest) + return object; + let message = new $root.vtadmin.StopWorkflowRequest(); + if (object.cluster_id != null) + message.cluster_id = String(object.cluster_id); + if (object.keyspace != null) + message.keyspace = String(object.keyspace); + if (object.workflow != null) + message.workflow = String(object.workflow); + return message; + }; + + /** + * Creates a plain object from a StopWorkflowRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {vtadmin.StopWorkflowRequest} message StopWorkflowRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + StopWorkflowRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.cluster_id = ""; + object.keyspace = ""; + object.workflow = ""; + } + if (message.cluster_id != null && message.hasOwnProperty("cluster_id")) + object.cluster_id = message.cluster_id; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + object.keyspace = message.keyspace; + if (message.workflow != null && message.hasOwnProperty("workflow")) + object.workflow = message.workflow; + return object; + }; + + /** + * Converts this StopWorkflowRequest to JSON. + * @function toJSON + * @memberof vtadmin.StopWorkflowRequest + * @instance + * @returns {Object.} JSON object + */ + StopWorkflowRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for StopWorkflowRequest + * @function getTypeUrl + * @memberof vtadmin.StopWorkflowRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + StopWorkflowRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtadmin.StopWorkflowRequest"; + }; + + return StopWorkflowRequest; + })(); + vtadmin.GetWorkflowsRequest = (function() { /** @@ -68245,6 +69094,7 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * @property {boolean|null} [debug_query] VDiffReportOptions debug_query * @property {string|null} [format] VDiffReportOptions format * @property {number|Long|null} [max_sample_rows] VDiffReportOptions max_sample_rows + * @property {number|Long|null} [row_diff_column_truncate_at] VDiffReportOptions row_diff_column_truncate_at */ /** @@ -68294,6 +69144,14 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { */ VDiffReportOptions.prototype.max_sample_rows = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + /** + * VDiffReportOptions row_diff_column_truncate_at. + * @member {number|Long} row_diff_column_truncate_at + * @memberof tabletmanagerdata.VDiffReportOptions + * @instance + */ + VDiffReportOptions.prototype.row_diff_column_truncate_at = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + /** * Creates a new VDiffReportOptions instance using the specified properties. * @function create @@ -68326,6 +69184,8 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { writer.uint32(/* id 3, wireType 2 =*/26).string(message.format); if (message.max_sample_rows != null && Object.hasOwnProperty.call(message, "max_sample_rows")) writer.uint32(/* id 4, wireType 0 =*/32).int64(message.max_sample_rows); + if (message.row_diff_column_truncate_at != null && Object.hasOwnProperty.call(message, "row_diff_column_truncate_at")) + writer.uint32(/* id 5, wireType 0 =*/40).int64(message.row_diff_column_truncate_at); return writer; }; @@ -68376,6 +69236,10 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.max_sample_rows = reader.int64(); break; } + case 5: { + message.row_diff_column_truncate_at = reader.int64(); + break; + } default: reader.skipType(tag & 7); break; @@ -68423,6 +69287,9 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { if (message.max_sample_rows != null && message.hasOwnProperty("max_sample_rows")) if (!$util.isInteger(message.max_sample_rows) && !(message.max_sample_rows && $util.isInteger(message.max_sample_rows.low) && $util.isInteger(message.max_sample_rows.high))) return "max_sample_rows: integer|Long expected"; + if (message.row_diff_column_truncate_at != null && message.hasOwnProperty("row_diff_column_truncate_at")) + if (!$util.isInteger(message.row_diff_column_truncate_at) && !(message.row_diff_column_truncate_at && $util.isInteger(message.row_diff_column_truncate_at.low) && $util.isInteger(message.row_diff_column_truncate_at.high))) + return "row_diff_column_truncate_at: integer|Long expected"; return null; }; @@ -68453,6 +69320,15 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.max_sample_rows = object.max_sample_rows; else if (typeof object.max_sample_rows === "object") message.max_sample_rows = new $util.LongBits(object.max_sample_rows.low >>> 0, object.max_sample_rows.high >>> 0).toNumber(); + if (object.row_diff_column_truncate_at != null) + if ($util.Long) + (message.row_diff_column_truncate_at = $util.Long.fromValue(object.row_diff_column_truncate_at)).unsigned = false; + else if (typeof object.row_diff_column_truncate_at === "string") + message.row_diff_column_truncate_at = parseInt(object.row_diff_column_truncate_at, 10); + else if (typeof object.row_diff_column_truncate_at === "number") + message.row_diff_column_truncate_at = object.row_diff_column_truncate_at; + else if (typeof object.row_diff_column_truncate_at === "object") + message.row_diff_column_truncate_at = new $util.LongBits(object.row_diff_column_truncate_at.low >>> 0, object.row_diff_column_truncate_at.high >>> 0).toNumber(); return message; }; @@ -68478,6 +69354,11 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { object.max_sample_rows = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; } else object.max_sample_rows = options.longs === String ? "0" : 0; + if ($util.Long) { + let long = new $util.Long(0, 0, false); + object.row_diff_column_truncate_at = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.row_diff_column_truncate_at = options.longs === String ? "0" : 0; } if (message.only_pks != null && message.hasOwnProperty("only_pks")) object.only_pks = message.only_pks; @@ -68490,6 +69371,11 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { object.max_sample_rows = options.longs === String ? String(message.max_sample_rows) : message.max_sample_rows; else object.max_sample_rows = options.longs === String ? $util.Long.prototype.toString.call(message.max_sample_rows) : options.longs === Number ? new $util.LongBits(message.max_sample_rows.low >>> 0, message.max_sample_rows.high >>> 0).toNumber() : message.max_sample_rows; + if (message.row_diff_column_truncate_at != null && message.hasOwnProperty("row_diff_column_truncate_at")) + if (typeof message.row_diff_column_truncate_at === "number") + object.row_diff_column_truncate_at = options.longs === String ? String(message.row_diff_column_truncate_at) : message.row_diff_column_truncate_at; + else + object.row_diff_column_truncate_at = options.longs === String ? $util.Long.prototype.toString.call(message.row_diff_column_truncate_at) : options.longs === Number ? new $util.LongBits(message.row_diff_column_truncate_at.low >>> 0, message.row_diff_column_truncate_at.high >>> 0).toNumber() : message.row_diff_column_truncate_at; return object; }; @@ -71270,6 +72156,28 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { return CheckThrottlerRequest; })(); + /** + * CheckThrottlerResponseCode enum. + * @name tabletmanagerdata.CheckThrottlerResponseCode + * @enum {number} + * @property {number} UNDEFINED=0 UNDEFINED value + * @property {number} OK=1 OK value + * @property {number} THRESHOLD_EXCEEDED=2 THRESHOLD_EXCEEDED value + * @property {number} APP_DENIED=3 APP_DENIED value + * @property {number} UNKNOWN_METRIC=4 UNKNOWN_METRIC value + * @property {number} INTERNAL_ERROR=5 INTERNAL_ERROR value + */ + tabletmanagerdata.CheckThrottlerResponseCode = (function() { + const valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "UNDEFINED"] = 0; + values[valuesById[1] = "OK"] = 1; + values[valuesById[2] = "THRESHOLD_EXCEEDED"] = 2; + values[valuesById[3] = "APP_DENIED"] = 3; + values[valuesById[4] = "UNKNOWN_METRIC"] = 4; + values[valuesById[5] = "INTERNAL_ERROR"] = 5; + return values; + })(); + tabletmanagerdata.CheckThrottlerResponse = (function() { /** @@ -71283,6 +72191,9 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * @property {string|null} [message] CheckThrottlerResponse message * @property {boolean|null} [recently_checked] CheckThrottlerResponse recently_checked * @property {Object.|null} [metrics] CheckThrottlerResponse metrics + * @property {string|null} [app_name] CheckThrottlerResponse app_name + * @property {string|null} [summary] CheckThrottlerResponse summary + * @property {tabletmanagerdata.CheckThrottlerResponseCode|null} [response_code] CheckThrottlerResponse response_code */ /** @@ -71357,6 +72268,30 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { */ CheckThrottlerResponse.prototype.metrics = $util.emptyObject; + /** + * CheckThrottlerResponse app_name. + * @member {string} app_name + * @memberof tabletmanagerdata.CheckThrottlerResponse + * @instance + */ + CheckThrottlerResponse.prototype.app_name = ""; + + /** + * CheckThrottlerResponse summary. + * @member {string} summary + * @memberof tabletmanagerdata.CheckThrottlerResponse + * @instance + */ + CheckThrottlerResponse.prototype.summary = ""; + + /** + * CheckThrottlerResponse response_code. + * @member {tabletmanagerdata.CheckThrottlerResponseCode} response_code + * @memberof tabletmanagerdata.CheckThrottlerResponse + * @instance + */ + CheckThrottlerResponse.prototype.response_code = 0; + /** * Creates a new CheckThrottlerResponse instance using the specified properties. * @function create @@ -71398,6 +72333,12 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { writer.uint32(/* id 7, wireType 2 =*/58).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); $root.tabletmanagerdata.CheckThrottlerResponse.Metric.encode(message.metrics[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); } + if (message.app_name != null && Object.hasOwnProperty.call(message, "app_name")) + writer.uint32(/* id 8, wireType 2 =*/66).string(message.app_name); + if (message.summary != null && Object.hasOwnProperty.call(message, "summary")) + writer.uint32(/* id 9, wireType 2 =*/74).string(message.summary); + if (message.response_code != null && Object.hasOwnProperty.call(message, "response_code")) + writer.uint32(/* id 10, wireType 0 =*/80).int32(message.response_code); return writer; }; @@ -71479,6 +72420,18 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.metrics[key] = value; break; } + case 8: { + message.app_name = reader.string(); + break; + } + case 9: { + message.summary = reader.string(); + break; + } + case 10: { + message.response_code = reader.int32(); + break; + } default: reader.skipType(tag & 7); break; @@ -71542,6 +72495,24 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { return "metrics." + error; } } + if (message.app_name != null && message.hasOwnProperty("app_name")) + if (!$util.isString(message.app_name)) + return "app_name: string expected"; + if (message.summary != null && message.hasOwnProperty("summary")) + if (!$util.isString(message.summary)) + return "summary: string expected"; + if (message.response_code != null && message.hasOwnProperty("response_code")) + switch (message.response_code) { + default: + return "response_code: enum value expected"; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + break; + } return null; }; @@ -71579,6 +72550,42 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.metrics[keys[i]] = $root.tabletmanagerdata.CheckThrottlerResponse.Metric.fromObject(object.metrics[keys[i]]); } } + if (object.app_name != null) + message.app_name = String(object.app_name); + if (object.summary != null) + message.summary = String(object.summary); + switch (object.response_code) { + default: + if (typeof object.response_code === "number") { + message.response_code = object.response_code; + break; + } + break; + case "UNDEFINED": + case 0: + message.response_code = 0; + break; + case "OK": + case 1: + message.response_code = 1; + break; + case "THRESHOLD_EXCEEDED": + case 2: + message.response_code = 2; + break; + case "APP_DENIED": + case 3: + message.response_code = 3; + break; + case "UNKNOWN_METRIC": + case 4: + message.response_code = 4; + break; + case "INTERNAL_ERROR": + case 5: + message.response_code = 5; + break; + } return message; }; @@ -71604,6 +72611,9 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { object.error = ""; object.message = ""; object.recently_checked = false; + object.app_name = ""; + object.summary = ""; + object.response_code = options.enums === String ? "UNDEFINED" : 0; } if (message.status_code != null && message.hasOwnProperty("status_code")) object.status_code = message.status_code; @@ -71623,6 +72633,12 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { for (let j = 0; j < keys2.length; ++j) object.metrics[keys2[j]] = $root.tabletmanagerdata.CheckThrottlerResponse.Metric.toObject(message.metrics[keys2[j]], options); } + if (message.app_name != null && message.hasOwnProperty("app_name")) + object.app_name = message.app_name; + if (message.summary != null && message.hasOwnProperty("summary")) + object.summary = message.summary; + if (message.response_code != null && message.hasOwnProperty("response_code")) + object.response_code = options.enums === String ? $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] === undefined ? message.response_code : $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] : message.response_code; return object; }; @@ -71665,6 +72681,7 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * @property {string|null} [error] Metric error * @property {string|null} [message] Metric message * @property {string|null} [scope] Metric scope + * @property {tabletmanagerdata.CheckThrottlerResponseCode|null} [response_code] Metric response_code */ /** @@ -71738,6 +72755,14 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { */ Metric.prototype.scope = ""; + /** + * Metric response_code. + * @member {tabletmanagerdata.CheckThrottlerResponseCode} response_code + * @memberof tabletmanagerdata.CheckThrottlerResponse.Metric + * @instance + */ + Metric.prototype.response_code = 0; + /** * Creates a new Metric instance using the specified properties. * @function create @@ -71776,6 +72801,8 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { 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); + if (message.response_code != null && Object.hasOwnProperty.call(message, "response_code")) + writer.uint32(/* id 8, wireType 0 =*/64).int32(message.response_code); return writer; }; @@ -71838,6 +72865,10 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.scope = reader.string(); break; } + case 8: { + message.response_code = reader.int32(); + break; + } default: reader.skipType(tag & 7); break; @@ -71894,6 +72925,18 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { if (message.scope != null && message.hasOwnProperty("scope")) if (!$util.isString(message.scope)) return "scope: string expected"; + if (message.response_code != null && message.hasOwnProperty("response_code")) + switch (message.response_code) { + default: + return "response_code: enum value expected"; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + break; + } return null; }; @@ -71923,6 +72966,38 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.message = String(object.message); if (object.scope != null) message.scope = String(object.scope); + switch (object.response_code) { + default: + if (typeof object.response_code === "number") { + message.response_code = object.response_code; + break; + } + break; + case "UNDEFINED": + case 0: + message.response_code = 0; + break; + case "OK": + case 1: + message.response_code = 1; + break; + case "THRESHOLD_EXCEEDED": + case 2: + message.response_code = 2; + break; + case "APP_DENIED": + case 3: + message.response_code = 3; + break; + case "UNKNOWN_METRIC": + case 4: + message.response_code = 4; + break; + case "INTERNAL_ERROR": + case 5: + message.response_code = 5; + break; + } return message; }; @@ -71947,6 +73022,7 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { object.error = ""; object.message = ""; object.scope = ""; + object.response_code = options.enums === String ? "UNDEFINED" : 0; } if (message.name != null && message.hasOwnProperty("name")) object.name = message.name; @@ -71962,6 +73038,8 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { object.message = message.message; if (message.scope != null && message.hasOwnProperty("scope")) object.scope = message.scope; + if (message.response_code != null && message.hasOwnProperty("response_code")) + object.response_code = options.enums === String ? $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] === undefined ? message.response_code : $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] : message.response_code; return object; }; @@ -73480,6 +74558,7 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * @interface IRecentApp * @property {vttime.ITime|null} [checked_at] RecentApp checked_at * @property {number|null} [status_code] RecentApp status_code + * @property {tabletmanagerdata.CheckThrottlerResponseCode|null} [response_code] RecentApp response_code */ /** @@ -73513,6 +74592,14 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { */ RecentApp.prototype.status_code = 0; + /** + * RecentApp response_code. + * @member {tabletmanagerdata.CheckThrottlerResponseCode} response_code + * @memberof tabletmanagerdata.GetThrottlerStatusResponse.RecentApp + * @instance + */ + RecentApp.prototype.response_code = 0; + /** * Creates a new RecentApp instance using the specified properties. * @function create @@ -73541,6 +74628,8 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { $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); + if (message.response_code != null && Object.hasOwnProperty.call(message, "response_code")) + writer.uint32(/* id 3, wireType 0 =*/24).int32(message.response_code); return writer; }; @@ -73583,6 +74672,10 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { message.status_code = reader.int32(); break; } + case 3: { + message.response_code = reader.int32(); + break; + } default: reader.skipType(tag & 7); break; @@ -73626,6 +74719,18 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { if (message.status_code != null && message.hasOwnProperty("status_code")) if (!$util.isInteger(message.status_code)) return "status_code: integer expected"; + if (message.response_code != null && message.hasOwnProperty("response_code")) + switch (message.response_code) { + default: + return "response_code: enum value expected"; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + break; + } return null; }; @@ -73648,6 +74753,38 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { } if (object.status_code != null) message.status_code = object.status_code | 0; + switch (object.response_code) { + default: + if (typeof object.response_code === "number") { + message.response_code = object.response_code; + break; + } + break; + case "UNDEFINED": + case 0: + message.response_code = 0; + break; + case "OK": + case 1: + message.response_code = 1; + break; + case "THRESHOLD_EXCEEDED": + case 2: + message.response_code = 2; + break; + case "APP_DENIED": + case 3: + message.response_code = 3; + break; + case "UNKNOWN_METRIC": + case 4: + message.response_code = 4; + break; + case "INTERNAL_ERROR": + case 5: + message.response_code = 5; + break; + } return message; }; @@ -73667,11 +74804,14 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { if (options.defaults) { object.checked_at = null; object.status_code = 0; + object.response_code = options.enums === String ? "UNDEFINED" : 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; + if (message.response_code != null && message.hasOwnProperty("response_code")) + object.response_code = options.enums === String ? $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] === undefined ? message.response_code : $root.tabletmanagerdata.CheckThrottlerResponseCode[message.response_code] : message.response_code; return object; }; @@ -77827,6 +78967,7 @@ export const binlogdata = $root.binlogdata = (() => { * @property {string|null} [keyspace] RowEvent keyspace * @property {string|null} [shard] RowEvent shard * @property {number|null} [flags] RowEvent flags + * @property {boolean|null} [is_internal_table] RowEvent is_internal_table */ /** @@ -77885,6 +79026,14 @@ export const binlogdata = $root.binlogdata = (() => { */ RowEvent.prototype.flags = 0; + /** + * RowEvent is_internal_table. + * @member {boolean} is_internal_table + * @memberof binlogdata.RowEvent + * @instance + */ + RowEvent.prototype.is_internal_table = false; + /** * Creates a new RowEvent instance using the specified properties. * @function create @@ -77920,6 +79069,8 @@ export const binlogdata = $root.binlogdata = (() => { writer.uint32(/* id 4, wireType 2 =*/34).string(message.shard); if (message.flags != null && Object.hasOwnProperty.call(message, "flags")) writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.flags); + if (message.is_internal_table != null && Object.hasOwnProperty.call(message, "is_internal_table")) + writer.uint32(/* id 6, wireType 0 =*/48).bool(message.is_internal_table); return writer; }; @@ -77976,6 +79127,10 @@ export const binlogdata = $root.binlogdata = (() => { message.flags = reader.uint32(); break; } + case 6: { + message.is_internal_table = reader.bool(); + break; + } default: reader.skipType(tag & 7); break; @@ -78032,6 +79187,9 @@ export const binlogdata = $root.binlogdata = (() => { if (message.flags != null && message.hasOwnProperty("flags")) if (!$util.isInteger(message.flags)) return "flags: integer expected"; + if (message.is_internal_table != null && message.hasOwnProperty("is_internal_table")) + if (typeof message.is_internal_table !== "boolean") + return "is_internal_table: boolean expected"; return null; }; @@ -78065,6 +79223,8 @@ export const binlogdata = $root.binlogdata = (() => { message.shard = String(object.shard); if (object.flags != null) message.flags = object.flags >>> 0; + if (object.is_internal_table != null) + message.is_internal_table = Boolean(object.is_internal_table); return message; }; @@ -78088,6 +79248,7 @@ export const binlogdata = $root.binlogdata = (() => { object.keyspace = ""; object.shard = ""; object.flags = 0; + object.is_internal_table = false; } if (message.table_name != null && message.hasOwnProperty("table_name")) object.table_name = message.table_name; @@ -78102,6 +79263,8 @@ export const binlogdata = $root.binlogdata = (() => { object.shard = message.shard; if (message.flags != null && message.hasOwnProperty("flags")) object.flags = message.flags; + if (message.is_internal_table != null && message.hasOwnProperty("is_internal_table")) + object.is_internal_table = message.is_internal_table; return object; }; @@ -78145,6 +79308,7 @@ export const binlogdata = $root.binlogdata = (() => { * @property {string|null} [keyspace] FieldEvent keyspace * @property {string|null} [shard] FieldEvent shard * @property {boolean|null} [enum_set_string_values] FieldEvent enum_set_string_values + * @property {boolean|null} [is_internal_table] FieldEvent is_internal_table */ /** @@ -78203,6 +79367,14 @@ export const binlogdata = $root.binlogdata = (() => { */ FieldEvent.prototype.enum_set_string_values = false; + /** + * FieldEvent is_internal_table. + * @member {boolean} is_internal_table + * @memberof binlogdata.FieldEvent + * @instance + */ + FieldEvent.prototype.is_internal_table = false; + /** * Creates a new FieldEvent instance using the specified properties. * @function create @@ -78238,6 +79410,8 @@ export const binlogdata = $root.binlogdata = (() => { writer.uint32(/* id 4, wireType 2 =*/34).string(message.shard); if (message.enum_set_string_values != null && Object.hasOwnProperty.call(message, "enum_set_string_values")) writer.uint32(/* id 25, wireType 0 =*/200).bool(message.enum_set_string_values); + if (message.is_internal_table != null && Object.hasOwnProperty.call(message, "is_internal_table")) + writer.uint32(/* id 26, wireType 0 =*/208).bool(message.is_internal_table); return writer; }; @@ -78294,6 +79468,10 @@ export const binlogdata = $root.binlogdata = (() => { message.enum_set_string_values = reader.bool(); break; } + case 26: { + message.is_internal_table = reader.bool(); + break; + } default: reader.skipType(tag & 7); break; @@ -78350,6 +79528,9 @@ export const binlogdata = $root.binlogdata = (() => { if (message.enum_set_string_values != null && message.hasOwnProperty("enum_set_string_values")) if (typeof message.enum_set_string_values !== "boolean") return "enum_set_string_values: boolean expected"; + if (message.is_internal_table != null && message.hasOwnProperty("is_internal_table")) + if (typeof message.is_internal_table !== "boolean") + return "is_internal_table: boolean expected"; return null; }; @@ -78383,6 +79564,8 @@ export const binlogdata = $root.binlogdata = (() => { message.shard = String(object.shard); if (object.enum_set_string_values != null) message.enum_set_string_values = Boolean(object.enum_set_string_values); + if (object.is_internal_table != null) + message.is_internal_table = Boolean(object.is_internal_table); return message; }; @@ -78406,6 +79589,7 @@ export const binlogdata = $root.binlogdata = (() => { object.keyspace = ""; object.shard = ""; object.enum_set_string_values = false; + object.is_internal_table = false; } if (message.table_name != null && message.hasOwnProperty("table_name")) object.table_name = message.table_name; @@ -78420,6 +79604,8 @@ export const binlogdata = $root.binlogdata = (() => { object.shard = message.shard; if (message.enum_set_string_values != null && message.hasOwnProperty("enum_set_string_values")) object.enum_set_string_values = message.enum_set_string_values; + if (message.is_internal_table != null && message.hasOwnProperty("is_internal_table")) + object.is_internal_table = message.is_internal_table; return object; }; @@ -79683,6 +80869,7 @@ export const binlogdata = $root.binlogdata = (() => { * @property {string|null} [keyspace] VEvent keyspace * @property {string|null} [shard] VEvent shard * @property {boolean|null} [throttled] VEvent throttled + * @property {string|null} [throttled_reason] VEvent throttled_reason */ /** @@ -79812,6 +80999,14 @@ export const binlogdata = $root.binlogdata = (() => { */ VEvent.prototype.throttled = false; + /** + * VEvent throttled_reason. + * @member {string} throttled_reason + * @memberof binlogdata.VEvent + * @instance + */ + VEvent.prototype.throttled_reason = ""; + /** * Creates a new VEvent instance using the specified properties. * @function create @@ -79864,6 +81059,8 @@ export const binlogdata = $root.binlogdata = (() => { writer.uint32(/* id 23, wireType 2 =*/186).string(message.shard); if (message.throttled != null && Object.hasOwnProperty.call(message, "throttled")) writer.uint32(/* id 24, wireType 0 =*/192).bool(message.throttled); + if (message.throttled_reason != null && Object.hasOwnProperty.call(message, "throttled_reason")) + writer.uint32(/* id 25, wireType 2 =*/202).string(message.throttled_reason); return writer; }; @@ -79954,6 +81151,10 @@ export const binlogdata = $root.binlogdata = (() => { message.throttled = reader.bool(); break; } + case 25: { + message.throttled_reason = reader.string(); + break; + } default: reader.skipType(tag & 7); break; @@ -80065,6 +81266,9 @@ export const binlogdata = $root.binlogdata = (() => { if (message.throttled != null && message.hasOwnProperty("throttled")) if (typeof message.throttled !== "boolean") return "throttled: boolean expected"; + if (message.throttled_reason != null && message.hasOwnProperty("throttled_reason")) + if (!$util.isString(message.throttled_reason)) + return "throttled_reason: string expected"; return null; }; @@ -80227,6 +81431,8 @@ export const binlogdata = $root.binlogdata = (() => { message.shard = String(object.shard); if (object.throttled != null) message.throttled = Boolean(object.throttled); + if (object.throttled_reason != null) + message.throttled_reason = String(object.throttled_reason); return message; }; @@ -80266,6 +81472,7 @@ export const binlogdata = $root.binlogdata = (() => { object.keyspace = ""; object.shard = ""; object.throttled = false; + object.throttled_reason = ""; } if (message.type != null && message.hasOwnProperty("type")) object.type = options.enums === String ? $root.binlogdata.VEventType[message.type] === undefined ? message.type : $root.binlogdata.VEventType[message.type] : message.type; @@ -80301,6 +81508,8 @@ export const binlogdata = $root.binlogdata = (() => { object.shard = message.shard; if (message.throttled != null && message.hasOwnProperty("throttled")) object.throttled = message.throttled; + if (message.throttled_reason != null && message.hasOwnProperty("throttled_reason")) + object.throttled_reason = message.throttled_reason; return object; }; @@ -80887,6 +82096,225 @@ export const binlogdata = $root.binlogdata = (() => { return MinimalSchema; })(); + binlogdata.VStreamOptions = (function() { + + /** + * Properties of a VStreamOptions. + * @memberof binlogdata + * @interface IVStreamOptions + * @property {Array.|null} [internal_tables] VStreamOptions internal_tables + */ + + /** + * Constructs a new VStreamOptions. + * @memberof binlogdata + * @classdesc Represents a VStreamOptions. + * @implements IVStreamOptions + * @constructor + * @param {binlogdata.IVStreamOptions=} [properties] Properties to set + */ + function VStreamOptions(properties) { + this.internal_tables = []; + 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]]; + } + + /** + * VStreamOptions internal_tables. + * @member {Array.} internal_tables + * @memberof binlogdata.VStreamOptions + * @instance + */ + VStreamOptions.prototype.internal_tables = $util.emptyArray; + + /** + * Creates a new VStreamOptions instance using the specified properties. + * @function create + * @memberof binlogdata.VStreamOptions + * @static + * @param {binlogdata.IVStreamOptions=} [properties] Properties to set + * @returns {binlogdata.VStreamOptions} VStreamOptions instance + */ + VStreamOptions.create = function create(properties) { + return new VStreamOptions(properties); + }; + + /** + * Encodes the specified VStreamOptions message. Does not implicitly {@link binlogdata.VStreamOptions.verify|verify} messages. + * @function encode + * @memberof binlogdata.VStreamOptions + * @static + * @param {binlogdata.IVStreamOptions} message VStreamOptions message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VStreamOptions.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.internal_tables != null && message.internal_tables.length) + for (let i = 0; i < message.internal_tables.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.internal_tables[i]); + return writer; + }; + + /** + * Encodes the specified VStreamOptions message, length delimited. Does not implicitly {@link binlogdata.VStreamOptions.verify|verify} messages. + * @function encodeDelimited + * @memberof binlogdata.VStreamOptions + * @static + * @param {binlogdata.IVStreamOptions} message VStreamOptions message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VStreamOptions.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a VStreamOptions message from the specified reader or buffer. + * @function decode + * @memberof binlogdata.VStreamOptions + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {binlogdata.VStreamOptions} VStreamOptions + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VStreamOptions.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.binlogdata.VStreamOptions(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.internal_tables && message.internal_tables.length)) + message.internal_tables = []; + message.internal_tables.push(reader.string()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a VStreamOptions message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof binlogdata.VStreamOptions + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {binlogdata.VStreamOptions} VStreamOptions + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VStreamOptions.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a VStreamOptions message. + * @function verify + * @memberof binlogdata.VStreamOptions + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + VStreamOptions.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.internal_tables != null && message.hasOwnProperty("internal_tables")) { + if (!Array.isArray(message.internal_tables)) + return "internal_tables: array expected"; + for (let i = 0; i < message.internal_tables.length; ++i) + if (!$util.isString(message.internal_tables[i])) + return "internal_tables: string[] expected"; + } + return null; + }; + + /** + * Creates a VStreamOptions message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof binlogdata.VStreamOptions + * @static + * @param {Object.} object Plain object + * @returns {binlogdata.VStreamOptions} VStreamOptions + */ + VStreamOptions.fromObject = function fromObject(object) { + if (object instanceof $root.binlogdata.VStreamOptions) + return object; + let message = new $root.binlogdata.VStreamOptions(); + if (object.internal_tables) { + if (!Array.isArray(object.internal_tables)) + throw TypeError(".binlogdata.VStreamOptions.internal_tables: array expected"); + message.internal_tables = []; + for (let i = 0; i < object.internal_tables.length; ++i) + message.internal_tables[i] = String(object.internal_tables[i]); + } + return message; + }; + + /** + * Creates a plain object from a VStreamOptions message. Also converts values to other types if specified. + * @function toObject + * @memberof binlogdata.VStreamOptions + * @static + * @param {binlogdata.VStreamOptions} message VStreamOptions + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + VStreamOptions.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.internal_tables = []; + if (message.internal_tables && message.internal_tables.length) { + object.internal_tables = []; + for (let j = 0; j < message.internal_tables.length; ++j) + object.internal_tables[j] = message.internal_tables[j]; + } + return object; + }; + + /** + * Converts this VStreamOptions to JSON. + * @function toJSON + * @memberof binlogdata.VStreamOptions + * @instance + * @returns {Object.} JSON object + */ + VStreamOptions.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for VStreamOptions + * @function getTypeUrl + * @memberof binlogdata.VStreamOptions + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + VStreamOptions.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/binlogdata.VStreamOptions"; + }; + + return VStreamOptions; + })(); + binlogdata.VStreamRequest = (function() { /** @@ -80899,6 +82327,7 @@ export const binlogdata = $root.binlogdata = (() => { * @property {string|null} [position] VStreamRequest position * @property {binlogdata.IFilter|null} [filter] VStreamRequest filter * @property {Array.|null} [table_last_p_ks] VStreamRequest table_last_p_ks + * @property {binlogdata.IVStreamOptions|null} [options] VStreamRequest options */ /** @@ -80965,6 +82394,14 @@ export const binlogdata = $root.binlogdata = (() => { */ VStreamRequest.prototype.table_last_p_ks = $util.emptyArray; + /** + * VStreamRequest options. + * @member {binlogdata.IVStreamOptions|null|undefined} options + * @memberof binlogdata.VStreamRequest + * @instance + */ + VStreamRequest.prototype.options = null; + /** * Creates a new VStreamRequest instance using the specified properties. * @function create @@ -81002,6 +82439,8 @@ export const binlogdata = $root.binlogdata = (() => { if (message.table_last_p_ks != null && message.table_last_p_ks.length) for (let i = 0; i < message.table_last_p_ks.length; ++i) $root.binlogdata.TableLastPK.encode(message.table_last_p_ks[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); + if (message.options != null && Object.hasOwnProperty.call(message, "options")) + $root.binlogdata.VStreamOptions.encode(message.options, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); return writer; }; @@ -81062,6 +82501,10 @@ export const binlogdata = $root.binlogdata = (() => { message.table_last_p_ks.push($root.binlogdata.TableLastPK.decode(reader, reader.uint32())); break; } + case 7: { + message.options = $root.binlogdata.VStreamOptions.decode(reader, reader.uint32()); + break; + } default: reader.skipType(tag & 7); break; @@ -81129,6 +82572,11 @@ export const binlogdata = $root.binlogdata = (() => { return "table_last_p_ks." + error; } } + if (message.options != null && message.hasOwnProperty("options")) { + let error = $root.binlogdata.VStreamOptions.verify(message.options); + if (error) + return "options." + error; + } return null; }; @@ -81176,6 +82624,11 @@ export const binlogdata = $root.binlogdata = (() => { message.table_last_p_ks[i] = $root.binlogdata.TableLastPK.fromObject(object.table_last_p_ks[i]); } } + if (object.options != null) { + if (typeof object.options !== "object") + throw TypeError(".binlogdata.VStreamRequest.options: object expected"); + message.options = $root.binlogdata.VStreamOptions.fromObject(object.options); + } return message; }; @@ -81200,6 +82653,7 @@ export const binlogdata = $root.binlogdata = (() => { object.target = null; object.position = ""; object.filter = null; + object.options = 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); @@ -81216,6 +82670,8 @@ export const binlogdata = $root.binlogdata = (() => { for (let j = 0; j < message.table_last_p_ks.length; ++j) object.table_last_p_ks[j] = $root.binlogdata.TableLastPK.toObject(message.table_last_p_ks[j], options); } + if (message.options != null && message.hasOwnProperty("options")) + object.options = $root.binlogdata.VStreamOptions.toObject(message.options, options); return object; }; @@ -81801,6 +83257,7 @@ export const binlogdata = $root.binlogdata = (() => { * @property {query.IRow|null} [lastpk] VStreamRowsResponse lastpk * @property {boolean|null} [throttled] VStreamRowsResponse throttled * @property {boolean|null} [heartbeat] VStreamRowsResponse heartbeat + * @property {string|null} [throttled_reason] VStreamRowsResponse throttled_reason */ /** @@ -81877,6 +83334,14 @@ export const binlogdata = $root.binlogdata = (() => { */ VStreamRowsResponse.prototype.heartbeat = false; + /** + * VStreamRowsResponse throttled_reason. + * @member {string} throttled_reason + * @memberof binlogdata.VStreamRowsResponse + * @instance + */ + VStreamRowsResponse.prototype.throttled_reason = ""; + /** * Creates a new VStreamRowsResponse instance using the specified properties. * @function create @@ -81918,6 +83383,8 @@ export const binlogdata = $root.binlogdata = (() => { writer.uint32(/* id 6, wireType 0 =*/48).bool(message.throttled); if (message.heartbeat != null && Object.hasOwnProperty.call(message, "heartbeat")) writer.uint32(/* id 7, wireType 0 =*/56).bool(message.heartbeat); + if (message.throttled_reason != null && Object.hasOwnProperty.call(message, "throttled_reason")) + writer.uint32(/* id 8, wireType 2 =*/66).string(message.throttled_reason); return writer; }; @@ -81986,6 +83453,10 @@ export const binlogdata = $root.binlogdata = (() => { message.heartbeat = reader.bool(); break; } + case 8: { + message.throttled_reason = reader.string(); + break; + } default: reader.skipType(tag & 7); break; @@ -82062,6 +83533,9 @@ export const binlogdata = $root.binlogdata = (() => { if (message.heartbeat != null && message.hasOwnProperty("heartbeat")) if (typeof message.heartbeat !== "boolean") return "heartbeat: boolean expected"; + if (message.throttled_reason != null && message.hasOwnProperty("throttled_reason")) + if (!$util.isString(message.throttled_reason)) + return "throttled_reason: string expected"; return null; }; @@ -82118,6 +83592,8 @@ export const binlogdata = $root.binlogdata = (() => { message.throttled = Boolean(object.throttled); if (object.heartbeat != null) message.heartbeat = Boolean(object.heartbeat); + if (object.throttled_reason != null) + message.throttled_reason = String(object.throttled_reason); return message; }; @@ -82144,6 +83620,7 @@ export const binlogdata = $root.binlogdata = (() => { object.lastpk = null; object.throttled = false; object.heartbeat = false; + object.throttled_reason = ""; } if (message.fields && message.fields.length) { object.fields = []; @@ -82168,6 +83645,8 @@ export const binlogdata = $root.binlogdata = (() => { object.throttled = message.throttled; if (message.heartbeat != null && message.hasOwnProperty("heartbeat")) object.heartbeat = message.heartbeat; + if (message.throttled_reason != null && message.hasOwnProperty("throttled_reason")) + object.throttled_reason = message.throttled_reason; return object; }; @@ -85549,6 +87028,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 +87067,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 +87256,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.value != null && message.hasOwnProperty("value")) @@ -85942,6 +87424,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 +87700,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.value != null && message.hasOwnProperty("value")) @@ -86390,6 +87877,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 +89371,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.table != null && message.hasOwnProperty("table")) @@ -88073,6 +89565,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 +98174,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 +104776,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 +104868,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 +104920,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 +104996,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 +105070,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 +105123,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 +105157,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 +105186,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 +105824,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 +106073,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 +106699,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } return null; @@ -104859,6 +106868,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 +110458,7 @@ export const vschema = $root.vschema = (() => { case 4128: case 4129: case 4130: + case 2083: break; } return null; @@ -108611,6 +110625,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 +112169,7 @@ export const vschema = $root.vschema = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.invisible != null && message.hasOwnProperty("invisible")) @@ -110344,6 +112363,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); @@ -124935,13 +126958,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 */ /** @@ -124953,7 +126971,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) @@ -124961,60 +126978,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. @@ -125040,23 +127017,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; }; @@ -125087,55 +127051,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: @@ -125173,33 +127098,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; }; @@ -125216,27 +127123,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; }; @@ -125254,34 +127149,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; }; @@ -125311,348 +127186,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; })(); @@ -144559,24 +146092,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 */ /** @@ -144588,12 +146104,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) @@ -144601,148 +146111,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 + * GetThrottlerStatusResponse status. + * @member {tabletmanagerdata.IGetThrottlerStatusResponse|null|undefined} status * @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 - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.recent_apps = $util.emptyObject; + GetThrottlerStatusResponse.prototype.status = null; /** * Creates a new GetThrottlerStatusResponse instance using the specified properties. @@ -144768,56 +146142,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; }; @@ -144848,194 +146174,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: @@ -145073,97 +146217,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; }; @@ -145180,83 +146237,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; }; @@ -145274,83 +146258,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; }; @@ -145380,711 +146291,6 @@ export const vtctldata = $root.vtctldata = (() => { return typeUrlPrefix + "/vtctldata.GetThrottlerStatusResponse"; }; - GetThrottlerStatusResponse.MetricResult = (function() { - - /** - * Properties of a MetricResult. - * @memberof vtctldata.GetThrottlerStatusResponse - * @interface IMetricResult - * @property {number|null} [value] MetricResult value - * @property {string|null} [error] MetricResult error - */ - - /** - * 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]]; - } - - /** - * MetricResult value. - * @member {number} value - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @instance - */ - MetricResult.prototype.value = 0; - - /** - * MetricResult error. - * @member {string} error - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @instance - */ - MetricResult.prototype.error = ""; - - /** - * 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); - }; - - /** - * 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; - }; - - /** - * 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(); - }; - - /** - * 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); - 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()); - }; - - /** - * 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; - }; - - /** - * 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; - }; - - /** - * 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; - 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; - })(); - - GetThrottlerStatusResponse.MetricHealth = (function() { - - /** - * 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 - */ - - /** - * 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]]; - } - - /** - * 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; })(); @@ -156055,6 +156261,7 @@ export const vtctldata = $root.vtctldata = (() => { * @property {topodata.ITabletAlias|null} [avoid_primary] PlannedReparentShardRequest avoid_primary * @property {vttime.IDuration|null} [wait_replicas_timeout] PlannedReparentShardRequest wait_replicas_timeout * @property {vttime.IDuration|null} [tolerable_replication_lag] PlannedReparentShardRequest tolerable_replication_lag + * @property {boolean|null} [allow_cross_cell_promotion] PlannedReparentShardRequest allow_cross_cell_promotion */ /** @@ -156120,6 +156327,14 @@ export const vtctldata = $root.vtctldata = (() => { */ PlannedReparentShardRequest.prototype.tolerable_replication_lag = null; + /** + * PlannedReparentShardRequest allow_cross_cell_promotion. + * @member {boolean} allow_cross_cell_promotion + * @memberof vtctldata.PlannedReparentShardRequest + * @instance + */ + PlannedReparentShardRequest.prototype.allow_cross_cell_promotion = false; + /** * Creates a new PlannedReparentShardRequest instance using the specified properties. * @function create @@ -156156,6 +156371,8 @@ export const vtctldata = $root.vtctldata = (() => { $root.vttime.Duration.encode(message.wait_replicas_timeout, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); if (message.tolerable_replication_lag != null && Object.hasOwnProperty.call(message, "tolerable_replication_lag")) $root.vttime.Duration.encode(message.tolerable_replication_lag, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); + if (message.allow_cross_cell_promotion != null && Object.hasOwnProperty.call(message, "allow_cross_cell_promotion")) + writer.uint32(/* id 7, wireType 0 =*/56).bool(message.allow_cross_cell_promotion); return writer; }; @@ -156214,6 +156431,10 @@ export const vtctldata = $root.vtctldata = (() => { message.tolerable_replication_lag = $root.vttime.Duration.decode(reader, reader.uint32()); break; } + case 7: { + message.allow_cross_cell_promotion = reader.bool(); + break; + } default: reader.skipType(tag & 7); break; @@ -156275,6 +156496,9 @@ export const vtctldata = $root.vtctldata = (() => { if (error) return "tolerable_replication_lag." + error; } + if (message.allow_cross_cell_promotion != null && message.hasOwnProperty("allow_cross_cell_promotion")) + if (typeof message.allow_cross_cell_promotion !== "boolean") + return "allow_cross_cell_promotion: boolean expected"; return null; }; @@ -156314,6 +156538,8 @@ export const vtctldata = $root.vtctldata = (() => { throw TypeError(".vtctldata.PlannedReparentShardRequest.tolerable_replication_lag: object expected"); message.tolerable_replication_lag = $root.vttime.Duration.fromObject(object.tolerable_replication_lag); } + if (object.allow_cross_cell_promotion != null) + message.allow_cross_cell_promotion = Boolean(object.allow_cross_cell_promotion); return message; }; @@ -156337,6 +156563,7 @@ export const vtctldata = $root.vtctldata = (() => { object.avoid_primary = null; object.wait_replicas_timeout = null; object.tolerable_replication_lag = null; + object.allow_cross_cell_promotion = false; } if (message.keyspace != null && message.hasOwnProperty("keyspace")) object.keyspace = message.keyspace; @@ -156350,6 +156577,8 @@ export const vtctldata = $root.vtctldata = (() => { object.wait_replicas_timeout = $root.vttime.Duration.toObject(message.wait_replicas_timeout, options); if (message.tolerable_replication_lag != null && message.hasOwnProperty("tolerable_replication_lag")) object.tolerable_replication_lag = $root.vttime.Duration.toObject(message.tolerable_replication_lag, options); + if (message.allow_cross_cell_promotion != null && message.hasOwnProperty("allow_cross_cell_promotion")) + object.allow_cross_cell_promotion = message.allow_cross_cell_promotion; return object; }; @@ -175157,6 +175386,7 @@ export const vtctldata = $root.vtctldata = (() => { * @property {boolean|null} [verbose] VDiffCreateRequest verbose * @property {number|Long|null} [max_report_sample_rows] VDiffCreateRequest max_report_sample_rows * @property {vttime.IDuration|null} [max_diff_duration] VDiffCreateRequest max_diff_duration + * @property {number|Long|null} [row_diff_column_truncate_at] VDiffCreateRequest row_diff_column_truncate_at */ /** @@ -175338,6 +175568,14 @@ export const vtctldata = $root.vtctldata = (() => { */ VDiffCreateRequest.prototype.max_diff_duration = null; + /** + * VDiffCreateRequest row_diff_column_truncate_at. + * @member {number|Long} row_diff_column_truncate_at + * @memberof vtctldata.VDiffCreateRequest + * @instance + */ + VDiffCreateRequest.prototype.row_diff_column_truncate_at = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + /** * Creates a new VDiffCreateRequest instance using the specified properties. * @function create @@ -175409,6 +175647,8 @@ export const vtctldata = $root.vtctldata = (() => { writer.uint32(/* id 19, wireType 0 =*/152).int64(message.max_report_sample_rows); if (message.max_diff_duration != null && Object.hasOwnProperty.call(message, "max_diff_duration")) $root.vttime.Duration.encode(message.max_diff_duration, writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim(); + if (message.row_diff_column_truncate_at != null && Object.hasOwnProperty.call(message, "row_diff_column_truncate_at")) + writer.uint32(/* id 21, wireType 0 =*/168).int64(message.row_diff_column_truncate_at); return writer; }; @@ -175536,6 +175776,10 @@ export const vtctldata = $root.vtctldata = (() => { message.max_diff_duration = $root.vttime.Duration.decode(reader, reader.uint32()); break; } + case 21: { + message.row_diff_column_truncate_at = reader.int64(); + break; + } default: reader.skipType(tag & 7); break; @@ -175673,6 +175917,9 @@ export const vtctldata = $root.vtctldata = (() => { if (error) return "max_diff_duration." + error; } + if (message.row_diff_column_truncate_at != null && message.hasOwnProperty("row_diff_column_truncate_at")) + if (!$util.isInteger(message.row_diff_column_truncate_at) && !(message.row_diff_column_truncate_at && $util.isInteger(message.row_diff_column_truncate_at.low) && $util.isInteger(message.row_diff_column_truncate_at.high))) + return "row_diff_column_truncate_at: integer|Long expected"; return null; }; @@ -175846,6 +176093,15 @@ export const vtctldata = $root.vtctldata = (() => { throw TypeError(".vtctldata.VDiffCreateRequest.max_diff_duration: object expected"); message.max_diff_duration = $root.vttime.Duration.fromObject(object.max_diff_duration); } + if (object.row_diff_column_truncate_at != null) + if ($util.Long) + (message.row_diff_column_truncate_at = $util.Long.fromValue(object.row_diff_column_truncate_at)).unsigned = false; + else if (typeof object.row_diff_column_truncate_at === "string") + message.row_diff_column_truncate_at = parseInt(object.row_diff_column_truncate_at, 10); + else if (typeof object.row_diff_column_truncate_at === "number") + message.row_diff_column_truncate_at = object.row_diff_column_truncate_at; + else if (typeof object.row_diff_column_truncate_at === "object") + message.row_diff_column_truncate_at = new $util.LongBits(object.row_diff_column_truncate_at.low >>> 0, object.row_diff_column_truncate_at.high >>> 0).toNumber(); return message; }; @@ -175897,6 +176153,11 @@ export const vtctldata = $root.vtctldata = (() => { } else object.max_report_sample_rows = options.longs === String ? "0" : 0; object.max_diff_duration = null; + if ($util.Long) { + let long = new $util.Long(0, 0, false); + object.row_diff_column_truncate_at = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.row_diff_column_truncate_at = options.longs === String ? "0" : 0; } if (message.workflow != null && message.hasOwnProperty("workflow")) object.workflow = message.workflow; @@ -175959,6 +176220,11 @@ export const vtctldata = $root.vtctldata = (() => { object.max_report_sample_rows = options.longs === String ? $util.Long.prototype.toString.call(message.max_report_sample_rows) : options.longs === Number ? new $util.LongBits(message.max_report_sample_rows.low >>> 0, message.max_report_sample_rows.high >>> 0).toNumber() : message.max_report_sample_rows; if (message.max_diff_duration != null && message.hasOwnProperty("max_diff_duration")) object.max_diff_duration = $root.vttime.Duration.toObject(message.max_diff_duration, options); + if (message.row_diff_column_truncate_at != null && message.hasOwnProperty("row_diff_column_truncate_at")) + if (typeof message.row_diff_column_truncate_at === "number") + object.row_diff_column_truncate_at = options.longs === String ? String(message.row_diff_column_truncate_at) : message.row_diff_column_truncate_at; + else + object.row_diff_column_truncate_at = options.longs === String ? $util.Long.prototype.toString.call(message.row_diff_column_truncate_at) : options.longs === Number ? new $util.LongBits(message.row_diff_column_truncate_at.low >>> 0, message.row_diff_column_truncate_at.high >>> 0).toNumber() : message.row_diff_column_truncate_at; return object; }; diff --git a/web/vtadmin/src/util/workflows.ts b/web/vtadmin/src/util/workflows.ts index 66e8d765961..3a0a03dc51b 100644 --- a/web/vtadmin/src/util/workflows.ts +++ b/web/vtadmin/src/util/workflows.ts @@ -94,3 +94,49 @@ export const getStreamTablets = (workflow: W | null | un return [...aliases]; }; + +/** + * getReverseWorkflow returns the reverse workflow of `originalWorkflow` by looking for the '_reverse' + * suffix and the source and target keyspace from all `workflows` list. + */ +export const getReverseWorkflow = ( + workflows: W[], + originalWorkflow: W | undefined | null +): W | undefined => { + if (!originalWorkflow) return; + const originalWorkflowName = originalWorkflow.workflow?.name!; + let reverseWorkflowName = originalWorkflowName.concat('_reverse'); + if (originalWorkflowName.endsWith('_reverse')) { + reverseWorkflowName = originalWorkflowName.split('_reverse')[0]; + } + return workflows.find( + (workflow) => + workflow.workflow?.name === reverseWorkflowName && + workflow.workflow?.source?.keyspace === originalWorkflow.workflow?.target?.keyspace && + workflow.workflow?.target?.keyspace === originalWorkflow.workflow?.source?.keyspace + ); +}; + +export interface TableCopyState extends vtctldata.WorkflowStatusResponse.ITableCopyState { + tableName: string; +} + +/** + * getTableCopyStates returns a list of table copy states with `tableName` included + * in the `TableCopyState` object, from the `workflowStatus` output. + */ +export const getTableCopyStates = ( + workflowStatus: vtctldata.WorkflowStatusResponse | undefined +): TableCopyState[] | undefined => { + if (!workflowStatus) return; + const tableNames = Object.keys(workflowStatus.table_copy_state); + if (!tableNames.length) return; + const tableCopyState: TableCopyState[] = tableNames.map((tableName) => { + const tableState = workflowStatus.table_copy_state[tableName]; + return { + tableName, + ...tableState, + }; + }); + return tableCopyState; +};