diff --git a/.gitignore b/.gitignore index 3a52aa40dda..86b6f1b3850 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ *.swp tags +# emacs +*~ + # Eclipse files .classpath .project @@ -21,6 +24,9 @@ tags *.iml .idea +# vscode +.vscode/ + # C build dirs **/build diff --git a/.travis.yml b/.travis.yml index df27bd2e952..312dfda58eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ services: language: go go: - - 1.9 + - 1.11.x go_import_path: vitess.io/vitess env: global: @@ -42,7 +42,7 @@ env: # See: https://docs.travis-ci.com/user/customizing-the-build#Build-Timeouts # To diagnose stuck tests, add "-follow" to TEST_FLAGS below. Then test.go # will print the test's output. - - TEST_FLAGS="-docker -use_docker_cache -timeout=8m -print-log -remote-stats=http://enisoc.com:15123/travis/stats" + - TEST_FLAGS="-docker -use_docker_cache -timeout=8m -print-log" matrix: # NOTE: Travis CI schedules up to 5 tests simultaneously. # All our tests should be spread out as evenly as possible across these 5 slots. diff --git a/Makefile b/Makefile index 5dd4db4d398..06446dd88f9 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,9 @@ docker_lite_percona: docker_lite_percona57: cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) percona57 +docker_lite_alpine: + cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) alpine + docker_guestbook: cd examples/kubernetes/guestbook && ./build.sh @@ -233,7 +236,7 @@ docker_unit_test: # tests in Travis. The results are saved in test/config.json, which you can # then commit and push. rebalance_tests: - go run test.go -rebalance 5 -remote-stats http://enisoc.com:15123/travis/stats + go run test.go -rebalance 5 # Release a version. # This will generate a tar.gz file into the releases folder with the current source diff --git a/config/init_db.sql b/config/init_db.sql index dd13817c2f9..4a278549dd6 100644 --- a/config/init_db.sql +++ b/config/init_db.sql @@ -37,10 +37,12 @@ CREATE TABLE IF NOT EXISTS _vt.shard_metadata ( ) 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, @@ -48,10 +50,12 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, 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, @@ -59,10 +63,12 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, ON *.* TO 'vt_allprivs'@'localhost'; # User for slave replication 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, @@ -70,10 +76,11 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, ON *.* TO 'vt_filtered'@'localhost'; # User for Orchestrator (https://github.com/github/orchestrator). +CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD - ON *.* TO 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; + ON *.* TO 'orc_client_user'@'%'; GRANT SELECT - ON _vt.* TO 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; + ON _vt.* TO 'orc_client_user'@'%'; FLUSH PRIVILEGES; diff --git a/config/mycnf/default-fast.cnf b/config/mycnf/default-fast.cnf index 02ddadac9fc..16aebb3c77f 100644 --- a/config/mycnf/default-fast.cnf +++ b/config/mycnf/default-fast.cnf @@ -32,13 +32,12 @@ max_connections = 100 net_write_timeout = 60 pid-file = {{.PidFile}} port = {{.MysqlPort}} -query_cache_size = 0 -query_cache_type = 0 # all db instances should start in read-only mode - once the db is started and # fully functional, we'll push it into read-write mode read-only read_buffer_size = 1M read_rnd_buffer_size = 1M +secure_file_priv = NULL server-id = {{.ServerID}} skip-name-resolve # we now need networking for replication. this is a tombstone to simpler times. diff --git a/config/mycnf/default.cnf b/config/mycnf/default.cnf index dec456f303c..59177071ca8 100644 --- a/config/mycnf/default.cnf +++ b/config/mycnf/default.cnf @@ -22,7 +22,6 @@ innodb_log_file_size = 64M innodb_log_files_in_group = 2 innodb_log_group_home_dir = {{.InnodbLogGroupHomeDir}} innodb_max_dirty_pages_pct = 75 -innodb_support_xa = 0 innodb_thread_concurrency = 20 key_buffer_size = 32M log-error = {{.ErrorLogPath}} @@ -32,13 +31,12 @@ max_connections = 100 net_write_timeout = 60 pid-file = {{.PidFile}} port = {{.MysqlPort}} -query_cache_size = 0 -query_cache_type = 0 # all db instances should start in read-only mode - once the db is started and # fully functional, we'll push it into read-write mode read-only read_buffer_size = 1M read_rnd_buffer_size = 1M +secure_file_priv = NULL server-id = {{.ServerID}} skip-name-resolve # all db instances should skip the slave startup - that way we can do any @@ -56,20 +54,3 @@ thread_cache_size = 200 tmpdir = {{.TmpDir}} tmp_table_size = 32M transaction-isolation = REPEATABLE-READ - -# 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. -# -# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync -# at the proper time when replication is set up, or when masters are -# promoted or demoted. -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 - diff --git a/config/mycnf/master_mariadb.cnf b/config/mycnf/master_mariadb.cnf index b76a7816a8a..83f6f318e4c 100644 --- a/config/mycnf/master_mariadb.cnf +++ b/config/mycnf/master_mariadb.cnf @@ -1,3 +1,20 @@ # enable strict mode so it's safe to compare sequence numbers across different server IDs. gtid_strict_mode = 1 innodb_stats_persistent = 0 +innodb_support_xa = 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. +# +# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync +# at the proper time when replication is set up, or when masters are +# promoted or demoted. +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 diff --git a/config/mycnf/master_mariadb103.cnf b/config/mycnf/master_mariadb103.cnf new file mode 100644 index 00000000000..a4dfb50ab18 --- /dev/null +++ b/config/mycnf/master_mariadb103.cnf @@ -0,0 +1,21 @@ +# enable strict mode so it's safe to compare sequence numbers across different server IDs. +gtid_strict_mode = 1 +innodb_stats_persistent = 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. +# +# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync +# at the proper time when replication is set up, or when masters are +# promoted or demoted. + +# semi_sync has been merged into master as of mariadb 10.3 so this is no longer needed +#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 diff --git a/config/mycnf/master_mysql56.cnf b/config/mycnf/master_mysql56.cnf index 2934975d751..2c802b2332a 100644 --- a/config/mycnf/master_mysql56.cnf +++ b/config/mycnf/master_mysql56.cnf @@ -13,3 +13,19 @@ 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. +# +# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync +# at the proper time when replication is set up, or when masters are +# promoted or demoted. +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 diff --git a/data/test/vtgate/dml_cases.txt b/data/test/vtgate/dml_cases.txt index 40a9c69a542..fc06a5f3558 100644 --- a/data/test/vtgate/dml_cases.txt +++ b/data/test/vtgate/dml_cases.txt @@ -1512,3 +1512,24 @@ "Query": "delete from unsharded where col = (select id from unsharded_a where id = unsharded.col)" } } + +# update vindex value to null +"update user set name = null where id = 1" +{ + "Original": "update user set name = null where id = 1", + "Instructions": { + "Opcode": "UpdateEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "update user set name = null where id = 1", + "Vindex": "user_index", + "Values": [1], + "ChangedVindexValues": { + "name_user_map": [null] + }, + "Table": "user", + "OwnedVindexQuery": "select Name, Costly from user where id = 1 for update" + } +} diff --git a/data/test/vtgate/select_cases.txt b/data/test/vtgate/select_cases.txt index cfc528b251e..92da4638a33 100644 --- a/data/test/vtgate/select_cases.txt +++ b/data/test/vtgate/select_cases.txt @@ -105,6 +105,68 @@ } } +# select with partial scatter directive +"select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user" +{ + "Original": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user", + "Instructions": { + "Opcode": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user", + "FieldQuery": "select * from user where 1 != 1", + "ScatterErrorsAsWarnings": true + } +} + +# select aggregation with partial scatter directive +"select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ count(*) from user" +{ + "Original": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ count(*) from user", + "Instructions": { + "Aggregates": [ + { + "Opcode": "count", + "Col": 0 + } + ], + "Keys": null, + "Input": { + "Opcode": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ count(*) from user", + "FieldQuery": "select count(*) from user where 1 != 1", + "ScatterErrorsAsWarnings": true + } + } +} + +# select limit with partial scatter directive +"select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user limit 10" +{ + "Original": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user limit 10", + "Instructions": { + "Opcode": "Limit", + "Count": 10, + "Offset": null, + "Input": { + "Opcode": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ * from user limit :__upper_limit", + "FieldQuery": "select * from user where 1 != 1", + "ScatterErrorsAsWarnings": true + } + } +} + # qualified '*' expression for simple route "select user.* from user" { diff --git a/doc/FAQ.md b/doc/FAQ.md new file mode 100644 index 00000000000..b84d14740d0 --- /dev/null +++ b/doc/FAQ.md @@ -0,0 +1,77 @@ +## Does the application need to know about the sharding scheme underneath Vitess? + +The application does not need to know about how the data is sharded. This information is stored in a VSchema which the VTGates use to automatically route your queries. This allows the application to connect to vitess and use it as if it’s a single giant database server. + +## Can I address a specific shard if I want to? + +If necessary, you can access a specific shard by connecting to it using the shard specific database name. For a keyspace `ks` and shard `-80`, you would connect to `ks:-80`. + +## How do I choose between master vs. replica for queries? + +You can qualify the keyspace name with the desired tablet type using the `@` suffix. This can be specified as part of the connection as the database name, or can be changed on the fly through the `USE` command. + +For example, `ks@master` will select `ks` as the default keyspace with all queries being sent to the master. Consequently `ks@replica` will load balance requests across all `REPLICA` tablet types, and `ks@rdonly` will choose `RDONLY`. + +You can also specify the database name as `@master`, etc, which instructs vitess that no default keyspace was specified, but that the requests are for the specified tablet type. + +If no tablet type was specified, then VTGate chooses its default, which can be overridden with the `-default_tablet_type` command line argument. + +## There seems to be a 10,000 row limit per query. What if I want to do a full table scan? + +Vitess supports different modes. In OLTP mode, the result size is typically limited to a preset number (10,000 rows by default). This limit can be adjusted based on your needs. + +However, OLAP mode has no limit to the number of rows returned. In order to change to this mode, you may issue the following command command before executing your query: + +``` +set workload='olap' +``` + +You can also set the workload to `dba` mode, which allows you to override the implicit timeouts that exist in vttablet. However, this mode should be used judiciously as it supersedes shutdown and reparent commands. + +The general convention is to send OLTP queries to `REPLICA` tablet types, and OLAP queries to `RDONLY`. + +## Is there a list of supported/unsupported queries? + +The list of unsupported constructs is currently in the form of test cases contained in this [test file](https://github.com/vitessio/vitess/blob/master/data/test/vtgate/unsupported_cases.txt). However, contrary to the test cases, there is limited support for SET, DDL and DBA constructs. This will be documented soon. + + +## If I have a log of all queries from my app. Is there a way I can try them against vitess to see how they’ll work? + +Yes. The [vtexplain tool]({% link user-guide/vtexplain.md %}) can be used to preview how your queries will be executed by vitess. It can also be used to try different sharding scenarios before deciding on one. + +## Does the Primary Vindex for a tablet have to be the same as its Primary Key. + +It is not necessary that a Primary Vindex be the same as the Primary Key. In fact, there are many use cases where you would not want this. For example, if there are tables with one-to-many relationships, the Primary Vindex of the main table is likely to be the same as the Primary Key. However, if you want the rows of the secondary table to reside in the same shard as the parent row, the Primary Vindex for that table must be the foreign key that points to the main table. A typical example is a `user` and `order` table. In this case, the order table has the `user_id` as a foreign key to the `id` of the `user` table. The `order_id` may be the primary key for `order`, but you may still want to choose `user_id` as Primary Vindex, which will make a user's orders live in the same shard as the user. + +## How do I connect to vtgate using mysql protocol? + +If you look at the example [vtgate-up.sh script](https://github.com/vitessio/vitess/blob/master/examples/local/vtgate-up.sh), you'll see the following lines: + + +``` + -mysql_server_port $mysql_server_port \ + -mysql_server_socket_path $mysql_server_socket_path \ + -mysql_auth_server_static_file "./mysql_auth_server_static_creds.json" \ +``` + +In that example, vtgate accepts mysql connections on port 15306, and the authentication info is stored in the json file. So, you should be able to connect to it using the following command: + +``` +mysql -h 127.0.0.1 -P 15306 -u mysql_user --password=mysql_password +``` + +## Can I override the default db name from `vt_xxx` to my own? + +Yes. You can start vttablet with the `-init_db_name_override` command line option to specify a different db name. There is no downside to performing this override. + +## I cannot start a cluster, and see these errors in the logs: Could not open required defaults file: /path/to/my.cnf + +Most likely this means that apparmor is running on your server and is preventing vitess processes from accessing the my.cnf file. The workaround is to uninstall apparmor: + +``` +sudo service apparmor stop +sudo service apparmor teardown +sudo update-rc.d -f apparmor remove +``` + +You may also need to reboot the machine after this. Many programs automatically install apparmor, so you may need to uninstall again. diff --git a/doc/GettingStarted.md b/doc/GettingStarted.md index 8d39de3e92e..46142b13b2b 100644 --- a/doc/GettingStarted.md +++ b/doc/GettingStarted.md @@ -73,7 +73,7 @@ OS X 10.11 (El Capitan) should work as well, the installation instructions are b In addition, Vitess requires the software and libraries listed below. -1. [Install Go 1.9+](http://golang.org/doc/install). +1. [Install Go 1.11+](http://golang.org/doc/install). 2. Install [MariaDB 10.0](https://downloads.mariadb.org/) or [MySQL 5.6](http://dev.mysql.com/downloads/mysql). You can use any diff --git a/doc/GettingStartedKubernetes.md b/doc/GettingStartedKubernetes.md index d0d358e3f8e..318c659ce5d 100644 --- a/doc/GettingStartedKubernetes.md +++ b/doc/GettingStartedKubernetes.md @@ -13,13 +13,13 @@ To complete the exercise in this guide, you must [install etcd-operator](https://github.com/coreos/etcd-operator/blob/master/doc/user/install_guide.md) in the same namespace in which you plan to run Vitess. -You also must locally install Go 1.9+, +You also must locally install Go 1.11+, the Vitess' `vtctlclient` tool, and `kubectl`. The following sections explain how to set these up in your environment. -### Install Go 1.9+ +### Install Go 1.11+ -You need to install [Go 1.9+](http://golang.org/doc/install) to build the +You need to install [Go 1.11+](http://golang.org/doc/install) to build the `vtctlclient` tool, which issues commands to Vitess. After installing Go, make sure your `GOPATH` environment diff --git a/doc/V3VindexDesign.md b/doc/V3VindexDesign.md index bf5528e7a83..f6d051b77d5 100644 --- a/doc/V3VindexDesign.md +++ b/doc/V3VindexDesign.md @@ -12,7 +12,7 @@ Some changes have been made to the system since the last time the doc was writte * There's one VSchema per keyspace instead of a global one. * The concept of Table Class has been eliminated. * A new `sequence` table has been introduced, and sequences are orthogonal to vindexes. Any column can now be tied to a sequence. -* We've introduced the concept of a pinned table, which allows an unsharded table to be pinned to a keypsace id, allowing you to avoid creating a separate keyspace for tiny tables. This is yet to be implemented. +* We've introduced the concept of a pinned table, which allows an unsharded table to be pinned to a keyspace id, allowing you to avoid creating a separate keyspace for tiny tables. This is yet to be implemented. * Instead of a vschema editor, the DDL language will be extended to manage vindexes, and the DDL deployment tools will perform the necessary work. ## Objective diff --git a/doc/VSchema.md b/doc/VSchema.md index 052a6bd451b..aafcd35f8ac 100644 --- a/doc/VSchema.md +++ b/doc/VSchema.md @@ -337,4 +337,4 @@ VSchema is still evolving. Features are mostly added on demand. The following fe * DDL support * Lookup Vindex backfill -* Pinned tables: This feature will allow unsharded tables to be pinned to a keypsace id. This avoids the need for a separate unsharded keyspace to contain them. +* Pinned tables: This feature will allow unsharded tables to be pinned to a keyspace id. This avoids the need for a separate unsharded keyspace to contain them. diff --git a/doc/VTTabletModes.md b/doc/VTTabletModes.md new file mode 100644 index 00000000000..5e89fe65cff --- /dev/null +++ b/doc/VTTabletModes.md @@ -0,0 +1,107 @@ +VTTablet can be configured to control mysql at many levels. At the level with the most control, vttablet can perform backups and restores, respond to reparenting commands coming through vtctld, automatically fix replication, and enforce semi-sync settings. + +At the level with the least control, vttablet just sends the application’s queries to mysql. The level of desired control is achieved through various command line arguments, explained below. + +## Managed MySQL + +In the mode with the highest control, VTTablet can take backups. It can also automatically restore from an existing backup to prime a new replica. For this mode, vttablet needs to run on the same host as mysql, and must be given access to mysql's my.cnf file. Additionally, the flags must not contain any connectivity parameters like `-db_host` or `-db_socket`; VTTablet will fetch the socket information from my.cnf and use that to connect to the local mysql. + +It will also load other information from the my.cnf, like the location of data files, etc. When it receives a request to take a backup, it will shut down mysql, copy the mysql data files to the backup store, and restart mysql. + +The my.cnf file can be specified the following ways: + +* Implicit: If mysql was initialized by the `mysqlctl` tool, then vttablet can find it based on just the `-tablet-path`. The default location for this file is `$VTDATAROOT/vt_/my.cnf`. +* `-mycnf-file`: This option can be used if the file is not present in the default location. +* `-my_cnf_server_id` and other flags: You can specify all values of the my.cnf file from the command line, and vttablet will behave as it read this information from a physical file. + +Specifying a `-db_host` or a `-db_socket` parameter will cause vttablet to skip the loading of the my.cnf file, and will disable its ability to perform backups or restores. + +### -restore\_from\_backup + +The default value for this flag is false. If set to true, and the my.cnf file was successfully loaded, then vttablet can perform automatic restores as follows: + +If started against a mysql instance that has no data files, it will search the list of backups for the latest one, and initiate a restore. After this, it will point the mysql to the current master and wait for replication to catch up. Once replication is caught up to the specified tolerance limit, it will advertise itself as serving. This will cause the vtgates to add it to the list of healthy tablets to serve queries from. + +If this flag is true, but my.cnf was not loaded, then vttablet will fatally exit with an error message. + +You can additionally control the level of concurrency for a restore with the `-restore_concurrency` flag. This is typically useful in cloud environments to prevent the restore process from becoming a 'noisy' neighbor by consuming all available disk IOPS. + +## Unmanaged or remote MySQL + +You can start a vttablet against a remote mysql by simply specifying the connection parameters `-db_host` and `-db_port` on the command line. In this mode, backup and restore operations will be disabled. If you start vttablet against a local mysql, you can specify a `-db_socket` instead, which will still make vttablet treat mysql as if it was remote. + +Specifically, the absence of a my.cnf file indicates to vttablet that it's connecting to a remote MySQL. + +## Partially managed MySQL + +Even if a MySQL is remote, you can still make vttablet perform some management functions. They are as follows: + +* `-disable_active_reparents`: If this flag is set, then any reparent or slave commands will not be allowed. These are InitShardMaster, PlannedReparent, PlannedReparent, EmergencyReparent, and ReparentTablet. In this mode, you should use the TabletExternallyReparented command to inform vitess of the current master. +* `-master_connect_retry`: This value is give to mysql when it connects a slave to the master as the retry duration parameter. +* `-enable_replication_reporter`: If this flag is set, then vttablet will transmit replica lag related information to the vtgates, which will allow it to balance load better. Additionally, enabling this will also cause vttablet to restart replication if it was stopped. However, it will do this only if -disable_active_reparents was not turned on. +* `-enable_semi_sync`: This option will automatically enable semi-sync on new replicas as well as on any tablet that transitions into a replica type. This includes the demotion of a master to a replica. +* `-heatbeat_enable` and `-heartbeat_interval_duration`: cause vttablet to write heartbeats to the sidecar database. This information is also used by the replication reporter to assess replica lag. + +## Typical vttablet command line flags + +### Minimal vttablet to enable query serving +``` +$TOPOLOGY_FLAGS +-tablet-path $alias +-init_keyspace $keyspace +-init_shard $shard +-init_tablet_type $tablet_type +-port $port +-grpc_port $grpc_port +-service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' +``` + +$alias needs to be of the form: `-id`, and the cell should match one of the local cells that was created in the topology. The id can be left padded with zeroes: `cell-100` and `cell-000000100` are synonymous. + +Example TOPOLOGY\_FLAGS for a lockserver like zookeeper: + +`-topo_implementation zk2 -topo_global_server_address localhost:21811,localhost:21812,localhost:21813 -topo_global_root /vitess/global` + +### Additional parameters to enable cluster management +``` +-enable_semi_sync +-enable_replication_reporter +-backup_storage_implementation file +-file_backup_storage_root $BACKUP_MOUNT +-restore_from_backup +-vtctld_addr http://$hostname:$vtctld_web_port/ +``` + +### Additional parameters for running in prod + +``` +-queryserver-config-pool-size 24 +-queryserver-config-stream-pool-size 24 +-queryserver-config-transaction-cap 300 +``` + +More tuning parameters are available, but the above overrides are definitely needed for serving reasonable production traffic. + +### Connecting vttablet to an already running mysql + +``` +-db_host $MYSQL_HOST +-db_port $MYSQL_PORT +-db_app_user $USER +-db_app_password $PASSWORD +``` + +### Additional user credentials that need to be supplied for performing various operations + +``` +-db_allprivs_user +-db_allprivs_password +-db_appdebug_user +-db_appdebug_password +-db_dba_user +-db_dba_password +-db_filtered_user +-db_filtered_password +``` + +Other flags exist for finer control. diff --git a/doc/vtctlReference.md b/doc/vtctlReference.md index cd2527e1e98..4d294919d42 100644 --- a/doc/vtctlReference.md +++ b/doc/vtctlReference.md @@ -181,6 +181,8 @@ Validates that all nodes reachable from the global replication graph and that al * [GetKeyspaces](#getkeyspaces) * [MigrateServedFrom](#migrateservedfrom) * [MigrateServedTypes](#migrateservedtypes) +* [CancelResharding](#cancelresharding) +* [ShowResharding](#showresharding) * [RebuildKeyspaceGraph](#rebuildkeyspacegraph) * [RemoveKeyspaceCell](#removekeyspacecell) * [SetKeyspaceServedFrom](#setkeyspaceservedfrom) @@ -278,7 +280,6 @@ Outputs a JSON structure that contains information about the Keyspace. Outputs a sorted list of all keyspaces. - ### MigrateServedFrom Makes the <destination keyspace/shard> serve the given type. This command also rebuilds the serving graph. @@ -334,9 +335,10 @@ Migrates a serving type from the source shard to the shards that it replicates t | Name | Type | Definition | | :-------- | :--------- | :--------- | | cells | string | Specifies a comma-separated list of cells to update | -| filtered_replication_wait_time | Duration | Specifies the maximum time to wait, in seconds, for filtered replication to catch up on master migrations | +| filtered\_replication\_wait\_time | Duration | Specifies the maximum time to wait, in seconds, for filtered replication to catch up on master migrations | | reverse | Boolean | Moves the served tablet type backward instead of forward. Use in case of trouble | | skip-refresh-state | Boolean | Skips refreshing the state of the source tablets after the migration, meaning that the refresh will need to be done manually, replica and rdonly only) | +| reverse\_replication | Boolean | For master migration, enabling this flag reverses replication which allows you to rollback | #### Arguments @@ -365,6 +367,24 @@ Migrates a serving type from the source shard to the shards that it replicates t * the <skip-refresh-state> flag can only be specified for non-master migrations +### CancelResharding + +Permanently cancels a resharding in progress. All resharding related metadata will be deleted. + +#### Arguments + +* <keyspace/shard> – Required. The name of a sharded database that contains one or more tables as well as the shard associated with the command. The keyspace must be identified by a string that does not contain whitepace, while the shard is typically identified by a string in the format <range start>-<range end>. + + +### ShowResharding + +"Displays all metadata about a resharding in progress. + +#### Arguments + +* <keyspace/shard> – Required. The name of a sharded database that contains one or more tables as well as the shard associated with the command. The keyspace must be identified by a string that does not contain whitepace, while the shard is typically identified by a string in the format <range start>-<range end>. + + ### RebuildKeyspaceGraph Rebuilds the serving data for the keyspace. This command may trigger an update to all connected clients. diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index 76929379ce4..84e3f7670af 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -12,9 +12,10 @@ FROM vitess/bootstrap:mysql57 USER root COPY . /vt/src/vitess.io/vitess +# Build Vitess +RUN make build + # Fix permissions RUN chown -R vitess:vitess /vt USER vitess -# Build Vitess -RUN make build diff --git a/docker/base/Dockerfile.mariadb b/docker/base/Dockerfile.mariadb index 8bc40f2d25b..a3f9771334f 100644 --- a/docker/base/Dockerfile.mariadb +++ b/docker/base/Dockerfile.mariadb @@ -4,9 +4,10 @@ FROM vitess/bootstrap:mariadb USER root COPY . /vt/src/vitess.io/vitess +# Build Vitess +RUN make build + # Fix permissions RUN chown -R vitess:vitess /vt USER vitess -# Build Vitess -RUN make build diff --git a/docker/base/Dockerfile.mysql56 b/docker/base/Dockerfile.mysql56 index a5670e341f8..5d1f55079fa 100644 --- a/docker/base/Dockerfile.mysql56 +++ b/docker/base/Dockerfile.mysql56 @@ -4,9 +4,10 @@ FROM vitess/bootstrap:mysql56 USER root COPY . /vt/src/vitess.io/vitess +# Build Vitess +RUN make build + # Fix permissions RUN chown -R vitess:vitess /vt USER vitess -# Build Vitess -RUN make build diff --git a/docker/base/Dockerfile.percona57 b/docker/base/Dockerfile.percona57 index 7e2dda3d717..4f396c9c86b 100644 --- a/docker/base/Dockerfile.percona57 +++ b/docker/base/Dockerfile.percona57 @@ -4,9 +4,10 @@ FROM vitess/bootstrap:percona57 USER root COPY . /vt/src/vitess.io/vitess +# Build Vitess +RUN make build + # Fix permissions RUN chown -R vitess:vitess /vt USER vitess -# Build Vitess -RUN make build diff --git a/docker/bootstrap/Dockerfile.common b/docker/bootstrap/Dockerfile.common index f148e298fc7..df663fe95bd 100644 --- a/docker/bootstrap/Dockerfile.common +++ b/docker/bootstrap/Dockerfile.common @@ -1,4 +1,4 @@ -FROM golang:1.9 +FROM golang:1.10 # Install Vitess build dependencies RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ @@ -49,6 +49,7 @@ ENV GOPATH $VTROOT ENV PATH $VTROOT/bin:$VTROOT/dist/maven/bin:$VTROOT/dist/chromedriver:$PATH ENV VT_MYSQL_ROOT /usr ENV PKG_CONFIG_PATH $VTROOT/lib +ENV USER vitess # Copy files needed for bootstrap COPY bootstrap.sh dev.env /vt/src/vitess.io/vitess/ diff --git a/docker/bootstrap/Dockerfile.mariadb b/docker/bootstrap/Dockerfile.mariadb index 2b1a4d0ace6..437ea492771 100644 --- a/docker/bootstrap/Dockerfile.mariadb +++ b/docker/bootstrap/Dockerfile.mariadb @@ -8,8 +8,6 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess + USER vitess -# Required by e2e test dependencies e.g. test/environment.py. -ENV USER vitess -ENV MYSQL_FLAVOR MariaDB RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.mysql56 b/docker/bootstrap/Dockerfile.mysql56 index fb556292901..eebb7807f62 100644 --- a/docker/bootstrap/Dockerfile.mysql56 +++ b/docker/bootstrap/Dockerfile.mysql56 @@ -9,8 +9,7 @@ RUN for i in $(seq 1 10); do apt-key adv --recv-keys --keyserver ha.pool.sks-key # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -USER vitess -# Required by e2e test dependencies e.g. test/environment.py. -ENV USER vitess + ENV MYSQL_FLAVOR MySQL56 +USER vitess RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.mysql57 b/docker/bootstrap/Dockerfile.mysql57 index c8bd52e7d31..514b63b441c 100644 --- a/docker/bootstrap/Dockerfile.mysql57 +++ b/docker/bootstrap/Dockerfile.mysql57 @@ -9,8 +9,8 @@ RUN for i in $(seq 1 10); do apt-key adv --recv-keys --keyserver ha.pool.sks-key # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -USER vitess -# Required by e2e test dependencies e.g. test/environment.py. -ENV USER vitess + + ENV MYSQL_FLAVOR MySQL56 -RUN ./bootstrap.sh +USER vitess +RUN ./bootstrap.sh \ No newline at end of file diff --git a/docker/bootstrap/Dockerfile.percona b/docker/bootstrap/Dockerfile.percona index 5b770a7ad80..9cad25dec48 100644 --- a/docker/bootstrap/Dockerfile.percona +++ b/docker/bootstrap/Dockerfile.percona @@ -15,8 +15,7 @@ RUN for i in $(seq 1 10); do apt-key adv --keyserver keys.gnupg.net --recv-keys # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -USER vitess -# Required by e2e test dependencies e.g. test/environment.py. -ENV USER vitess + ENV MYSQL_FLAVOR MySQL56 -RUN ./bootstrap.sh +USER vitess +RUN ./bootstrap.sh \ No newline at end of file diff --git a/docker/bootstrap/Dockerfile.percona57 b/docker/bootstrap/Dockerfile.percona57 index 117af2277b3..22a743525cf 100644 --- a/docker/bootstrap/Dockerfile.percona57 +++ b/docker/bootstrap/Dockerfile.percona57 @@ -15,8 +15,7 @@ RUN for i in $(seq 1 10); do apt-key adv --keyserver keys.gnupg.net --recv-keys # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -USER vitess -# Required by e2e test dependencies e.g. test/environment.py. -ENV USER vitess + ENV MYSQL_FLAVOR MySQL56 +USER vitess RUN ./bootstrap.sh diff --git a/docker/k8s/Dockerfile b/docker/k8s/Dockerfile index 16a773d545b..826c6cadd74 100644 --- a/docker/k8s/Dockerfile +++ b/docker/k8s/Dockerfile @@ -35,6 +35,7 @@ COPY --from=base $VTTOP/config/init_db.sql /vt/config/ # mysql flavor files for db specific .cnf settings COPY --from=base $VTTOP/config/mycnf/master_mysql56.cnf /vt/config/mycnf/ COPY --from=base $VTTOP/config/mycnf/master_mariadb.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/master_mariadb103.cnf /vt/config/mycnf/ # settings for different types of instances COPY --from=base $VTTOP/config/mycnf/default.cnf /vt/config/mycnf/ diff --git a/docker/k8s/orchestrator/Dockerfile b/docker/k8s/orchestrator/Dockerfile index bfa5a06751f..f4bb465ddac 100644 --- a/docker/k8s/orchestrator/Dockerfile +++ b/docker/k8s/orchestrator/Dockerfile @@ -11,9 +11,9 @@ COPY --from=k8s /vt/bin/vtctlclient /usr/bin/ RUN apt-get update && \ apt-get upgrade -qq && \ apt-get install wget -qq --no-install-recommends && \ - wget https://github.com/github/orchestrator/releases/download/v3.0.11/orchestrator_3.0.11_amd64.deb && \ - dpkg -i orchestrator_3.0.11_amd64.deb && \ - rm orchestrator_3.0.11_amd64.deb && \ + wget https://github.com/github/orchestrator/releases/download/v3.0.13/orchestrator_3.0.13_amd64.deb && \ + dpkg -i orchestrator_3.0.13_amd64.deb && \ + rm orchestrator_3.0.13_amd64.deb && \ apt-get purge wget -qq && \ apt-get autoremove -qq && \ apt-get clean && \ diff --git a/docker/k8s/pmm-client/Dockerfile b/docker/k8s/pmm-client/Dockerfile index 105c4e44c23..e5e4418b7e4 100644 --- a/docker/k8s/pmm-client/Dockerfile +++ b/docker/k8s/pmm-client/Dockerfile @@ -1,16 +1,16 @@ -FROM vitess/base AS base +FROM vitess/k8s AS k8s FROM debian:stretch-slim # Copy CA certs for https calls -COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=k8s /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt RUN apt-get update && \ apt-get upgrade -qq && \ apt-get install wget -qq --no-install-recommends && \ - wget https://www.percona.com/redir/downloads/pmm-client/1.10.0/binary/debian/stretch/x86_64/pmm-client_1.10.0-1.stretch_amd64.deb && \ - dpkg -i pmm-client_1.10.0-1.stretch_amd64.deb && \ - rm pmm-client_1.10.0-1.stretch_amd64.deb && \ + wget https://www.percona.com/redir/downloads/pmm-client/1.15.0/binary/debian/stretch/x86_64/pmm-client_1.15.0-1.stretch_amd64.deb && \ + dpkg -i pmm-client_1.15.0-1.stretch_amd64.deb && \ + rm pmm-client_1.15.0-1.stretch_amd64.deb && \ apt-get purge wget -qq && \ apt-get autoremove -qq && \ apt-get clean && \ diff --git a/docker/lite/Dockerfile.alpine b/docker/lite/Dockerfile.alpine new file mode 100644 index 00000000000..4a79ab80d94 --- /dev/null +++ b/docker/lite/Dockerfile.alpine @@ -0,0 +1,38 @@ +# This image is only meant to be built from within the build.sh script. +FROM vitess/base AS builder +FROM alpine:3.8 AS staging + +RUN mkdir -p /vt/vtdataroot/ && mkdir -p /vt/bin && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 + +COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/web/ +COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/web/vtctld2/ +COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config +COPY --from=builder /vt/bin/mysqlctld /vt/bin/ +COPY --from=builder /vt/bin/vtctld /vt/bin/ +COPY --from=builder /vt/bin/vtctlclient /vt/bin/ +COPY --from=builder /vt/bin/vtgate /vt/bin/ +COPY --from=builder /vt/bin/vttablet /vt/bin/ +COPY --from=builder /vt/bin/vtworker /vt/bin/ + +FROM alpine:3.8 + +# Install dependencies +RUN echo '@edge http://nl.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories && \ + apk add --no-cache mariadb@edge mariadb-client@edge bzip2 bash + +# Set up Vitess environment (just enough to run pre-built Go binaries) +ENV VTTOP /vt/src/vitess.io/vitess +ENV VTROOT /vt +ENV GOTOP $VTTOP/go +ENV VTDATAROOT $VTROOT/vtdataroot +ENV GOBIN $VTROOT/bin +ENV GOPATH $VTROOT +ENV PATH $VTROOT/bin:$PATH +ENV VT_MYSQL_ROOT /usr +ENV PKG_CONFIG_PATH $VTROOT/lib +ENV MYSQL_FLAVOR MariaDB103 + +# Create vitess user +RUN addgroup -S vitess && adduser -S -G vitess vitess && mkdir -p /vt +COPY --from=staging /vt/ /vt/ +USER vitess diff --git a/docker/lite/Dockerfile.mariadb b/docker/lite/Dockerfile.mariadb index 34470035a60..7df86adb0e0 100644 --- a/docker/lite/Dockerfile.mariadb +++ b/docker/lite/Dockerfile.mariadb @@ -30,3 +30,4 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess && \ # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot +USER vitess \ No newline at end of file diff --git a/docker/lite/Dockerfile.mysql56 b/docker/lite/Dockerfile.mysql56 index 6dedf491189..79e5381f909 100644 --- a/docker/lite/Dockerfile.mysql56 +++ b/docker/lite/Dockerfile.mysql56 @@ -33,3 +33,4 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess && \ # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot +USER vitess \ No newline at end of file diff --git a/docker/lite/Dockerfile.percona b/docker/lite/Dockerfile.percona index f65d5fb172d..47a7430b825 100644 --- a/docker/lite/Dockerfile.percona +++ b/docker/lite/Dockerfile.percona @@ -35,3 +35,4 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess && \ # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot +USER vitess \ No newline at end of file diff --git a/docker/lite/Dockerfile.percona57 b/docker/lite/Dockerfile.percona57 index b5f5096762e..1b824cec101 100644 --- a/docker/lite/Dockerfile.percona57 +++ b/docker/lite/Dockerfile.percona57 @@ -35,3 +35,4 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess && \ # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot +USER vitess \ No newline at end of file diff --git a/docker/test/run.sh b/docker/test/run.sh index 7e4fb85960e..775f987c8c3 100755 --- a/docker/test/run.sh +++ b/docker/test/run.sh @@ -137,6 +137,9 @@ mkdir -p /tmp/mavencache chmod 777 /tmp/mavencache args="$args -v /tmp/mavencache:/home/vitess/.m2" +# Add in the vitess user +args="$args --user vitess" + # Mount in host VTDATAROOT if one exists, since it might be a RAM disk or SSD. if [[ -n "$VTDATAROOT" ]]; then hostdir=`mktemp -d $VTDATAROOT/test-XXX` diff --git a/examples/kubernetes/guestbook/requirements.txt b/examples/kubernetes/guestbook/requirements.txt index 07bfdd2f3fc..b1dae5a2716 100644 --- a/examples/kubernetes/guestbook/requirements.txt +++ b/examples/kubernetes/guestbook/requirements.txt @@ -1,3 +1,3 @@ -Flask==0.10 +Flask==0.12.3 grpcio==1.12.0 -grpcio-tools==1.12.0 \ No newline at end of file +grpcio-tools==1.12.0 diff --git a/examples/local/vtgate-up.sh b/examples/local/vtgate-up.sh index faa9fb9d932..71d2d6eb474 100755 --- a/examples/local/vtgate-up.sh +++ b/examples/local/vtgate-up.sh @@ -66,6 +66,7 @@ fi $VTROOT/bin/vtgate \ $TOPOLOGY_FLAGS \ -log_dir $VTDATAROOT/tmp \ + -log_queries_to_file $VTDATAROOT/tmp/vtgate_querylog.txt \ -port $web_port \ -grpc_port $grpc_port \ -mysql_server_port $mysql_server_port \ diff --git a/examples/local/vttablet-up.sh b/examples/local/vttablet-up.sh index 0bd71527b16..893621345ef 100755 --- a/examples/local/vttablet-up.sh +++ b/examples/local/vttablet-up.sh @@ -95,6 +95,7 @@ for uid_index in $uids; do grpc_port=$[$grpc_port_base + $uid_index] printf -v alias '%s-%010d' $cell $uid printf -v tablet_dir 'vt_%010d' $uid + printf -v tablet_logfile 'vttablet_%010d_querylog.txt' $uid tablet_type=replica if [[ $uid_index -gt 2 ]]; then tablet_type=rdonly @@ -105,6 +106,7 @@ for uid_index in $uids; do $VTROOT/bin/vttablet \ $TOPOLOGY_FLAGS \ -log_dir $VTDATAROOT/tmp \ + -log_queries_to_file $VTDATAROOT/tmp/$tablet_logfile \ -tablet-path $alias \ -tablet_hostname "$tablet_hostname" \ -init_keyspace $keyspace \ diff --git a/go/bucketpool/bucketpool.go b/go/bucketpool/bucketpool.go new file mode 100644 index 00000000000..be0ec18aa7d --- /dev/null +++ b/go/bucketpool/bucketpool.go @@ -0,0 +1,91 @@ +package bucketpool + +import ( + "math" + "sync" +) + +type sizedPool struct { + size int + pool sync.Pool +} + +func newSizedPool(size int) *sizedPool { + return &sizedPool{ + size: size, + pool: sync.Pool{ + New: func() interface{} { return makeSlicePointer(size) }, + }, + } +} + +// Pool is actually multiple pools which store buffers of specific size. +// i.e. it can be three pools which return buffers 32K, 64K and 128K. +type Pool struct { + minSize int + maxSize int + pools []*sizedPool +} + +// New returns Pool which has buckets from minSize to maxSize. +// Buckets increase with the power of two, i.e with multiplier 2: [2b, 4b, 16b, ... , 1024b] +// Last pool will always be capped to maxSize. +func New(minSize, maxSize int) *Pool { + if maxSize < minSize { + panic("maxSize can't be less than minSize") + } + const multiplier = 2 + var pools []*sizedPool + curSize := minSize + for curSize < maxSize { + pools = append(pools, newSizedPool(curSize)) + curSize *= multiplier + } + pools = append(pools, newSizedPool(maxSize)) + return &Pool{ + minSize: minSize, + maxSize: maxSize, + pools: pools, + } +} + +func (p *Pool) findPool(size int) *sizedPool { + if size > p.maxSize { + return nil + } + idx := int(math.Ceil(math.Log2(float64(size) / float64(p.minSize)))) + if idx < 0 { + idx = 0 + } + if idx > len(p.pools)-1 { + return nil + } + return p.pools[idx] +} + +// Get returns pointer to []byte which has len size. +// If there is no bucket with buffers >= size, slice will be allocated. +func (p *Pool) Get(size int) *[]byte { + sp := p.findPool(size) + if sp == nil { + return makeSlicePointer(size) + } + buf := sp.pool.Get().(*[]byte) + *buf = (*buf)[:size] + return buf +} + +// Put returns pointer to slice to some bucket. Discards slice for which there is no bucket +func (p *Pool) Put(b *[]byte) { + sp := p.findPool(cap(*b)) + if sp == nil { + return + } + *b = (*b)[:cap(*b)] + sp.pool.Put(b) +} + +func makeSlicePointer(size int) *[]byte { + data := make([]byte, size) + return &data +} diff --git a/go/bucketpool/bucketpool_test.go b/go/bucketpool/bucketpool_test.go new file mode 100644 index 00000000000..a7e2cf0e75c --- /dev/null +++ b/go/bucketpool/bucketpool_test.go @@ -0,0 +1,202 @@ +package bucketpool + +import ( + "math/rand" + "testing" +) + +func TestPool(t *testing.T) { + maxSize := 16384 + pool := New(1024, maxSize) + if pool.maxSize != maxSize { + t.Fatalf("Invalid max pool size: %d, expected %d", pool.maxSize, maxSize) + } + if len(pool.pools) != 5 { + t.Fatalf("Invalid number of pools: %d, expected %d", len(pool.pools), 5) + } + + buf := pool.Get(64) + if len(*buf) != 64 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1024 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + + // get from same pool, check that length is right + buf = pool.Get(128) + if len(*buf) != 128 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1024 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + // get boundary size + buf = pool.Get(1024) + if len(*buf) != 1024 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1024 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + // get from the middle + buf = pool.Get(5000) + if len(*buf) != 5000 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 8192 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + // check last pool + buf = pool.Get(16383) + if len(*buf) != 16383 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 16384 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + // get big buffer + buf = pool.Get(16385) + if len(*buf) != 16385 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 16385 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) +} + +func TestPoolOneSize(t *testing.T) { + maxSize := 1024 + pool := New(1024, maxSize) + if pool.maxSize != maxSize { + t.Fatalf("Invalid max pool size: %d, expected %d", pool.maxSize, maxSize) + } + buf := pool.Get(64) + if len(*buf) != 64 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1024 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + buf = pool.Get(1025) + if len(*buf) != 1025 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1025 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) +} + +func TestPoolTwoSizeNotMultiplier(t *testing.T) { + maxSize := 2000 + pool := New(1024, maxSize) + if pool.maxSize != maxSize { + t.Fatalf("Invalid max pool size: %d, expected %d", pool.maxSize, maxSize) + } + buf := pool.Get(64) + if len(*buf) != 64 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 1024 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + buf = pool.Get(2001) + if len(*buf) != 2001 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 2001 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) +} + +func TestPoolWeirdMaxSize(t *testing.T) { + maxSize := 15000 + pool := New(1024, maxSize) + if pool.maxSize != maxSize { + t.Fatalf("Invalid max pool size: %d, expected %d", pool.maxSize, maxSize) + } + + buf := pool.Get(14000) + if len(*buf) != 14000 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 15000 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) + + buf = pool.Get(16383) + if len(*buf) != 16383 { + t.Fatalf("unexpected buf length: %d", len(*buf)) + } + if cap(*buf) != 16383 { + t.Fatalf("unexepected buf cap: %d", cap(*buf)) + } + pool.Put(buf) +} + +func TestFuzz(t *testing.T) { + maxTestSize := 16384 + for i := 0; i < 20000; i++ { + minSize := rand.Intn(maxTestSize) + maxSize := rand.Intn(maxTestSize-minSize) + minSize + p := New(minSize, maxSize) + bufSize := rand.Intn(maxTestSize) + buf := p.Get(bufSize) + if len(*buf) != bufSize { + t.Fatalf("Invalid length %d, expected %d", len(*buf), bufSize) + } + sPool := p.findPool(bufSize) + if sPool == nil { + if cap(*buf) != len(*buf) { + t.Fatalf("Invalid cap %d, expected %d", cap(*buf), len(*buf)) + } + } else { + if cap(*buf) != sPool.size { + t.Fatalf("Invalid cap %d, expected %d", cap(*buf), sPool.size) + } + } + p.Put(buf) + } +} + +func BenchmarkPool(b *testing.B) { + pool := New(2, 16384) + b.SetParallelism(16) + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + randomSize := rand.Intn(pool.maxSize) + data := pool.Get(randomSize) + pool.Put(data) + } + }) +} + +func BenchmarkPoolGet(b *testing.B) { + pool := New(2, 16384) + b.SetParallelism(16) + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + randomSize := rand.Intn(pool.maxSize) + data := pool.Get(randomSize) + _ = data + } + }) +} diff --git a/go/cmd/vtbench/vtbench.go b/go/cmd/vtbench/vtbench.go index b7bee9cee3c..eb18d9a2b22 100644 --- a/go/cmd/vtbench/vtbench.go +++ b/go/cmd/vtbench/vtbench.go @@ -78,11 +78,12 @@ import ( var ( // connection flags - host = flag.String("host", "", "vtgate host(s) in the form 'host1,host2,...'") - port = flag.Int("port", 0, "vtgate port") - protocol = flag.String("protocol", "mysql", "client protocol, either mysql (default), grpc-vtgate, or grpc-vttablet") - user = flag.String("user", "", "username to connect using mysql (password comes from the db-credentials-file)") - db = flag.String("db", "", "db name to use when connecting / running the queries (e.g. @replica, keyspace, keyspace/shard etc)") + host = flag.String("host", "", "vtgate host(s) in the form 'host1,host2,...'") + port = flag.Int("port", 0, "vtgate port") + unixSocket = flag.String("unix_socket", "", "vtgate unix socket") + protocol = flag.String("protocol", "mysql", "client protocol, either mysql (default), grpc-vtgate, or grpc-vttablet") + user = flag.String("user", "", "username to connect using mysql (password comes from the db-credentials-file)") + db = flag.String("db", "", "db name to use when connecting / running the queries (e.g. @replica, keyspace, keyspace/shard etc)") // test flags deadline = flag.Duration("deadline", 5*time.Minute, "maximum duration for the test run (default 5 minutes)") @@ -112,12 +113,20 @@ func main() { log.Exitf("invalid client protocol %s", *protocol) } - if *host == "" { - log.Exitf("must specify host(s)") + if (*host != "" || *port != 0) && *unixSocket != "" { + log.Exitf("can't specify both host:port and unix_socket") } - if *port == 0 { - log.Exitf("must specify port") + if *host != "" && *port == 0 { + log.Exitf("must specify port when using host") + } + + if *host == "" && *port != 0 { + log.Exitf("must specify host when using port") + } + + if *host == "" && *port == 0 && *unixSocket == "" { + log.Exitf("vtbench requires either host/port or unix_socket") } if *sql == "" { @@ -134,12 +143,13 @@ func main() { } connParams := vtbench.ConnParams{ - Hosts: strings.Split(*host, ","), - Port: *port, - Protocol: clientProto, - DB: *db, - Username: *user, - Password: password, + Hosts: strings.Split(*host, ","), + Port: *port, + UnixSocket: *unixSocket, + Protocol: clientProto, + DB: *db, + Username: *user, + Password: password, } b := vtbench.NewBench(*threads, *count, connParams, *sql) diff --git a/go/cmd/vtexplain/vtexplain.go b/go/cmd/vtexplain/vtexplain.go index 77f7688f4f4..41be6d2cc98 100644 --- a/go/cmd/vtexplain/vtexplain.go +++ b/go/cmd/vtexplain/vtexplain.go @@ -178,5 +178,7 @@ func parseAndRun() error { fmt.Print(vtexplain.ExplainsAsJSON(plans)) } + vtexplain.Stop() + return nil } diff --git a/go/cmd/vttestserver/main.go b/go/cmd/vttestserver/main.go index c0b926ca804..a018135913a 100644 --- a/go/cmd/vttestserver/main.go +++ b/go/cmd/vttestserver/main.go @@ -87,6 +87,10 @@ func parseFlags() (config vttest.Config, env vttest.Environment, err error) { "Default directory for initial schema files. If no schema is found"+ " in schema_dir, default to this location.") + flag.StringVar(&config.DataDir, "data_dir", "", + "Directory where the data files will be placed, defaults to a random "+ + "directory under /vt/vtdataroot") + flag.BoolVar(&config.OnlyMySQL, "mysql_only", false, "If this flag is set only mysql is initialized."+ " The rest of the vitess components are not started."+ @@ -145,12 +149,21 @@ func parseFlags() (config vttest.Config, env vttest.Environment, err error) { flag.StringVar(&config.SnapshotFile, "snapshot_file", "", "A MySQL DB snapshot file") + flag.StringVar(&config.TransactionMode, "transaction_mode", "MULTI", "Transaction mode MULTI (default), SINGLE or TWOPC ") + flag.Parse() if basePort != 0 { - env, err = vttest.NewLocalTestEnv("", basePort) - if err != nil { - return + if config.DataDir == "" { + env, err = vttest.NewLocalTestEnv("", basePort) + if err != nil { + return + } + } else { + env, err = vttest.NewLocalTestEnvWithDirectory("", basePort, config.DataDir) + if err != nil { + return + } } } diff --git a/go/cmd/vtworker/vtworker.go b/go/cmd/vtworker/vtworker.go index e2cef98b1f7..c190ff01828 100644 --- a/go/cmd/vtworker/vtworker.go +++ b/go/cmd/vtworker/vtworker.go @@ -31,6 +31,7 @@ import ( "golang.org/x/net/context" "vitess.io/vitess/go/exit" + "vitess.io/vitess/go/vt/callerid" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/servenv" @@ -41,6 +42,7 @@ import ( var ( cell = flag.String("cell", "", "cell to pick servers from") commandDisplayInterval = flag.Duration("command_display_interval", time.Second, "Interval between each status update when vtworker is executing a single command from the command line") + username = flag.String("username", "", "If set, value is set as immediate caller id in the request and used by vttablet for TableACL check") ) func init() { @@ -87,7 +89,15 @@ func main() { wi.InitInteractiveMode() } else { // In single command mode, just run it. - worker, done, err := wi.RunCommand(context.Background(), args, nil /*custom wrangler*/, true /*runFromCli*/) + ctx := context.Background() + + if *username != "" { + ctx = callerid.NewContext(ctx, + callerid.NewEffectiveCallerID("vtworker", "" /* component */, "" /* subComponent */), + callerid.NewImmediateCallerID(*username)) + } + + worker, done, err := wi.RunCommand(ctx, args, nil /*custom wrangler*/, true /*runFromCli*/) if err != nil { log.Error(err) exit.Return(1) diff --git a/go/mysql/binlog_event_json.go b/go/mysql/binlog_event_json.go index e843938794d..a59c3a759ac 100644 --- a/go/mysql/binlog_event_json.go +++ b/go/mysql/binlog_event_json.go @@ -51,6 +51,13 @@ const ( // printJSONData parses the MySQL binary format for JSON data, and prints // the result as a string. func printJSONData(data []byte) ([]byte, error) { + // It's possible for data to be empty. If so, we have to + // treat it as 'null'. + // The mysql code also says why, but this wasn't reproduceable: + // https://github.com/mysql/mysql-server/blob/8.0/sql/json_binary.cc#L1070 + if len(data) == 0 { + return []byte("'null'"), nil + } result := &bytes.Buffer{} typ := data[0] if err := printJSONValue(typ, data[1:], true /* toplevel */, result); err != nil { diff --git a/go/mysql/binlog_event_json_test.go b/go/mysql/binlog_event_json_test.go index 4681e295530..a1b25f9889f 100644 --- a/go/mysql/binlog_event_json_test.go +++ b/go/mysql/binlog_event_json_test.go @@ -26,6 +26,9 @@ func TestJSON(t *testing.T) { data []byte expected string }{{ + data: []byte{}, + expected: `'null'`, + }, { data: []byte{0, 1, 0, 14, 0, 11, 0, 1, 0, 12, 12, 0, 97, 1, 98}, expected: `JSON_OBJECT('a','b')`, }, { diff --git a/go/mysql/client.go b/go/mysql/client.go index 119640a8237..1cc117a8f6e 100644 --- a/go/mysql/client.go +++ b/go/mysql/client.go @@ -166,6 +166,28 @@ func Connect(ctx context.Context, params *ConnParams) (*Conn, error) { return c, nil } +// Ping implements mysql ping command. +func (c *Conn) Ping() error { + // This is a new command, need to reset the sequence. + c.sequence = 0 + + if err := c.writePacket([]byte{ComPing}); err != nil { + return NewSQLError(CRServerGone, SSUnknownSQLState, "%v", err) + } + data, err := c.readEphemeralPacket() + if err != nil { + return NewSQLError(CRServerLost, SSUnknownSQLState, "%v", err) + } + defer c.recycleReadPacket() + switch data[0] { + case OKPacket: + return nil + case ErrPacket: + return ParseErrorPacket(data) + } + return fmt.Errorf("unexpected packet type: %d", data[0]) +} + // parseCharacterSet parses the provided character set. // Returns SQLError(CRCantReadCharset) if it can't. func parseCharacterSet(cs string) (uint8, error) { @@ -210,7 +232,10 @@ func (c *Conn) clientHandshake(characterSet uint8, params *ConnParams) error { // Remember a subset of the capabilities, so we can use them // later in the protocol. - c.Capabilities = capabilities & (CapabilityClientDeprecateEOF) + c.Capabilities = 0 + if !params.DisableClientDeprecateEOF { + c.Capabilities = capabilities & (CapabilityClientDeprecateEOF) + } // Handle switch to SSL if necessary. if params.Flags&CapabilityClientSSL > 0 { @@ -250,8 +275,7 @@ func (c *Conn) clientHandshake(characterSet uint8, params *ConnParams) error { // Switch to SSL. conn := tls.Client(c.conn, clientConfig) c.conn = conn - c.reader.Reset(conn) - c.writer.Reset(conn) + c.bufferedReader.Reset(conn) c.Capabilities |= CapabilityClientSSL } @@ -508,7 +532,7 @@ func (c *Conn) writeSSLRequest(capabilities uint32, characterSet uint8, params * pos = writeByte(data, pos, characterSet) // And send it as is. - if err := c.writeEphemeralPacket(true /* direct */); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerLost, SSUnknownSQLState, "cannot send SSLRequest: %v", err) } return nil @@ -600,7 +624,7 @@ func (c *Conn) writeHandshakeResponse41(capabilities uint32, scrambledPassword [ return NewSQLError(CRMalformedPacket, SSUnknownSQLState, "writeHandshakeResponse41: only packed %v bytes, out of %v allocated", pos, len(data)) } - if err := c.writeEphemeralPacket(true /* direct */); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerLost, SSUnknownSQLState, "cannot send HandshakeResponse41: %v", err) } return nil @@ -627,5 +651,5 @@ func (c *Conn) writeClearTextPassword(params *ConnParams) error { if pos != len(data) { return fmt.Errorf("error building ClearTextPassword packet: got %v bytes expected %v", pos, len(data)) } - return c.writeEphemeralPacket(true) + return c.writeEphemeralPacket() } diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 4a08057ead4..15751f61116 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -18,12 +18,18 @@ package mysql import ( "bufio" + "errors" "fmt" "io" "net" "strings" "sync" + "time" + "vitess.io/vitess/go/bucketpool" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/sync2" + "vitess.io/vitess/go/vt/log" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -40,32 +46,11 @@ const ( // read or write a packet while one is already used. ephemeralUnused = iota - // ephemeralWriteGlobalBuffer means conn.buffer was used to write - // a packet. The first four bytes contain size and sequence. - ephemeralWriteGlobalBuffer + // ephemeralWrite means we currently in process of writing from currentEphemeralBuffer + ephemeralWrite - // ephemeralWriteSingleBuffer means a single buffer was - // allocated to write a packet. It is in - // c.currentEphemeralWriteBuffer. The first four bytes contain size - // and sequence. - ephemeralWriteSingleBuffer - - // ephemeralWriteBigBuffer means a big buffer was allocated to - // write a packet, and will need to be split when sending. - // The allocated buffer is in c.currentEphemeralWriteBuffer. - ephemeralWriteBigBuffer - - // ephemeralReadGlobalBuffer means conn.buffer was used for reading - // an ephemeral packet. - ephemeralReadGlobalBuffer - - // ephemeralReadSingleBuffer means we are using a pool of buffers - // for reading. - ephemeralReadSingleBuffer - - // ephemeralReadBigBuffer means we allocated a very big buffer - // and we can't reuse it at all. - ephemeralReadBigBuffer + // ephemeralRead means we currently in process of reading into currentEphemeralBuffer + ephemeralRead ) // A Getter has a Get() @@ -85,14 +70,17 @@ type Conn struct { // If there are any ongoing reads or writes, they may get interrupted. conn net.Conn + // For server-side connections, listener points to the server object. + listener *Listener + // ConnectionID is set: // - at Connect() time for clients, with the value returned by // the server. // - at accept time for the server. ConnectionID uint32 - // Closed is set to true when Close() is called on the connection. - Closed bool + // closed is set to true when Close() is called on the connection. + closed sync2.AtomicBool // Capabilities is the current set of features this connection // is using. It is the features that are both supported by @@ -144,9 +132,9 @@ type Conn struct { ClientData interface{} // Packet encoding variables. - reader *bufio.Reader - writer *bufio.Writer - sequence uint8 + bufferedReader *bufio.Reader + bufferedWriter *bufio.Writer + sequence uint8 // fields contains the fields definitions for an on-going // streaming query. It is set by ExecuteStreamFetch, and @@ -155,201 +143,163 @@ type Conn struct { // fields, this is set to an empty array (but not nil). fields []*querypb.Field - // Internal buffer for zero-allocation reads and writes. This - // uses the fact that both sides of a connection either read - // packets, or write packets, but never do both, and both - // sides know who is expected to read or write a packet next. - // - // Reading side: if the next expected packet will most likely be - // small, and we don't need to hand on to the memory after reading - // the packet, use readEphemeralPacket instead of readPacket. - // If the packet is too big, it will revert to the usual read. - // But if the packet is smaller than connBufferSize, this buffer - // will be used instead. - // - // Writing side: if the next packet to write is smaller than - // connBufferSize-4, this buffer can be used to create a - // packet. It will contain both the size and sequence header, - // and the contents of the packet. - // Call startEphemeralPacket(length) to get a buffer. If length - // is smaller or equal than connBufferSize-4, this buffer will be used. - // Otherwise memory will be allocated for it. - buffer []byte - // Keep track of how and of the buffer we allocated for an // ephemeral packet on the read and write sides. // These fields are used by: // - startEphemeralPacket / writeEphemeralPacket methods for writes. // - readEphemeralPacket / recycleReadPacket methods for reads. currentEphemeralPolicy int - // TODO (danieltahara): Ultimately get rid of this delineation. - // currentEphemeralWriteBuffer and currentEphemeralReadBuffer used for tracking - // allocated temporary buffers for writes and reads respectively. - currentEphemeralWriteBuffer *[]byte - currentEphemeralReadBuffer *[]byte + // currentEphemeralBuffer for tracking allocated temporary buffer for writes and reads respectively. + // It can be allocated from bufPool or heap and should be recycled in the same manner. + currentEphemeralBuffer *[]byte } // bufPool is used to allocate and free buffers in an efficient way. -var bufPool = sync.Pool{} - -// length is always > connBufferSize here, for smaller buffers static buffer field is used -func getBuf(length int) *[]byte { - i := bufPool.Get() - if i == nil { - buf := make([]byte, length) - return &buf - } - // We got an array from the pool, see if it's - // big enough. - buf := i.(*[]byte) - if cap(*buf) >= length { - // big enough, shrink to length and use it. - *buf = (*buf)[:length] - return buf - } - // not big enough: allocate a new one, put smaller buffer back to the pool - bufPool.Put(buf) - data := make([]byte, length) - return &data -} +var bufPool = bucketpool.New(connBufferSize, MaxPacketSize) + +// writersPool is used for pooling bufio.Writer objects. +var writersPool = sync.Pool{New: func() interface{} { return bufio.NewWriterSize(nil, connBufferSize) }} // newConn is an internal method to create a Conn. Used by client and server // side for common creation code. func newConn(conn net.Conn) *Conn { return &Conn{ - conn: conn, - - reader: bufio.NewReaderSize(conn, connBufferSize), - writer: bufio.NewWriterSize(conn, connBufferSize), - sequence: 0, - buffer: make([]byte, connBufferSize), + conn: conn, + closed: sync2.NewAtomicBool(false), + bufferedReader: bufio.NewReaderSize(conn, connBufferSize), } } -// readPacketDirect attempts to read a packet from the socket directly. -// It needs to be used for the first handshake packet the server receives, -// so we do't buffer the SSL negotiation packet. As a shortcut, only -// packets smaller than MaxPacketSize can be read here. -func (c *Conn) readPacketDirect() ([]byte, error) { - var header [4]byte - if _, err := io.ReadFull(c.conn, header[:]); err != nil { - // Propagate as is so server can ignore this kind of error - // Same as readEphemeralPacket() - if err == io.EOF { - return nil, err - } - // Treat connection reset by peer as io.EOF, otherwise is too spammy. - if strings.HasSuffix(err.Error(), "read: connection reset by peer") { - return nil, io.EOF - } - return nil, fmt.Errorf("io.ReadFull(header size) failed: %v", err) - } - - sequence := uint8(header[3]) - if sequence != c.sequence { - return nil, fmt.Errorf("invalid sequence, expected %v got %v", c.sequence, sequence) - } +// newServerConn should be used to create server connections. +// +// It stashes a reference to the listener to be able to determine if +// the server is shutting down, and has the ability to control buffer +// size for reads. +func newServerConn(conn net.Conn, listener *Listener) *Conn { + c := &Conn{ + conn: conn, + listener: listener, + closed: sync2.NewAtomicBool(false), + } + if listener.connReadBufferSize > 0 { + c.bufferedReader = bufio.NewReaderSize(conn, listener.connReadBufferSize) + } + return c +} - c.sequence++ +// startWriterBuffering starts using buffered writes. This should +// be terminated by a call to flush. +func (c *Conn) startWriterBuffering() { + c.bufferedWriter = writersPool.Get().(*bufio.Writer) + c.bufferedWriter.Reset(c.conn) +} - length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16) - if length <= cap(c.buffer) { - // Fast path: read into buffer, we're good. - c.buffer = c.buffer[:length] - if _, err := io.ReadFull(c.conn, c.buffer); err != nil { - return nil, fmt.Errorf("io.ReadFull(direct packet body of length %v) failed: %v", length, err) - } - return c.buffer, nil +// flush flushes the written data to the socket. +// This must be called to terminate startBuffering. +func (c *Conn) flush() error { + if c.bufferedWriter == nil { + return nil } - // Sanity check - if length == MaxPacketSize { - return nil, fmt.Errorf("readPacketDirect doesn't support more than one packet") - } + defer func() { + c.bufferedWriter.Reset(nil) + writersPool.Put(c.bufferedWriter) + c.bufferedWriter = nil + }() - // Slow path, revert to allocating. - data := make([]byte, length) - if _, err := io.ReadFull(c.conn, data); err != nil { - return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) + return c.bufferedWriter.Flush() +} + +// getWriter returns the current writer. It may be either +// the original connection or a wrapper. +func (c *Conn) getWriter() io.Writer { + if c.bufferedWriter != nil { + return c.bufferedWriter } - return data, nil + return c.conn } -// readEphemeralPacket attempts to read a packet into c.buffer. Do -// not use this method if the contents of the packet needs to be kept -// after the next readEphemeralPacket. If the packet is bigger than -// connBufferSize, we revert to using the same behavior as a regular -// readPacket. recycleReadPacket() has to be called after this method -// is used, and before we read or write any other packet on the connection. -// -// Note if the connection is closed already, an error will be -// returned, and it may not be io.EOF. If the connection closes while -// we are stuck waiting for data, an error will also be returned, and -// it most likely will be io.EOF. -func (c *Conn) readEphemeralPacket() ([]byte, error) { - if c.currentEphemeralPolicy != ephemeralUnused { - panic(fmt.Errorf("readEphemeralPacket: unexpected currentEphemeralPolicy: %v", c.currentEphemeralPolicy)) +// getReader returns reader for connection. It can be *bufio.Reader or net.Conn +// depending on which buffer size was passed to newServerConn. +func (c *Conn) getReader() io.Reader { + if c.bufferedReader != nil { + return c.bufferedReader } + return c.conn +} +func (c *Conn) readHeaderFrom(r io.Reader) (int, error) { + var header [4]byte // Note io.ReadFull will return two different types of errors: // 1. if the socket is already closed, and the go runtime knows it, // then ReadFull will return an error (different than EOF), // someting like 'read: connection reset by peer'. // 2. if the socket is not closed while we start the read, // but gets closed after the read is started, we'll get io.EOF. - var header [4]byte - if _, err := io.ReadFull(c.reader, header[:]); err != nil { + if _, err := io.ReadFull(r, header[:]); err != nil { // The special casing of propagating io.EOF up // is used by the server side only, to suppress an error // message if a client just disconnects. if err == io.EOF { - return nil, err + return 0, err } if strings.HasSuffix(err.Error(), "read: connection reset by peer") { - return nil, io.EOF + return 0, io.EOF } - return nil, fmt.Errorf("io.ReadFull(header size) failed: %v", err) + return 0, fmt.Errorf("io.ReadFull(header size) failed: %v", err) } sequence := uint8(header[3]) if sequence != c.sequence { - return nil, fmt.Errorf("invalid sequence, expected %v got %v", c.sequence, sequence) + return 0, fmt.Errorf("invalid sequence, expected %v got %v", c.sequence, sequence) } c.sequence++ - length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16) + return int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16), nil +} + +// readEphemeralPacket attempts to read a packet into buffer from sync.Pool. Do +// not use this method if the contents of the packet needs to be kept +// after the next readEphemeralPacket. +// +// Note if the connection is closed already, an error will be +// returned, and it may not be io.EOF. If the connection closes while +// we are stuck waiting for data, an error will also be returned, and +// it most likely will be io.EOF. +func (c *Conn) readEphemeralPacket() ([]byte, error) { + if c.currentEphemeralPolicy != ephemeralUnused { + panic(fmt.Errorf("readEphemeralPacket: unexpected currentEphemeralPolicy: %v", c.currentEphemeralPolicy)) + } + + r := c.getReader() + + length, err := c.readHeaderFrom(r) + if err != nil { + return nil, err + } + if length == 0 { // This can be caused by the packet after a packet of // exactly size MaxPacketSize. return nil, nil } - if length <= cap(c.buffer) { - // Fast path: read into buffer, we're good. - c.currentEphemeralPolicy = ephemeralReadGlobalBuffer - c.buffer = c.buffer[:length] - if _, err := io.ReadFull(c.reader, c.buffer); err != nil { - return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) - } - return c.buffer, nil - } - // Slightly slower path: single packet. Use the bufPool. + c.currentEphemeralPolicy = ephemeralRead + // Use the bufPool. if length < MaxPacketSize { - c.currentEphemeralPolicy = ephemeralReadSingleBuffer - c.currentEphemeralReadBuffer = getBuf(length) - if _, err := io.ReadFull(c.reader, *c.currentEphemeralReadBuffer); err != nil { + c.currentEphemeralBuffer = bufPool.Get(length) + if _, err := io.ReadFull(r, *c.currentEphemeralBuffer); err != nil { return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) } - return *c.currentEphemeralReadBuffer, nil + return *c.currentEphemeralBuffer, nil } // Much slower path, revert to allocating everything from scratch. // We're going to concatenate a lot of data anyway, can't really // optimize this code path easily. - c.currentEphemeralPolicy = ephemeralReadBigBuffer data := make([]byte, length) - if _, err := io.ReadFull(c.reader, data); err != nil { + if _, err := io.ReadFull(r, data); err != nil { return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) } for { @@ -372,43 +322,63 @@ func (c *Conn) readEphemeralPacket() ([]byte, error) { return data, nil } +// readEphemeralPacketDirect attempts to read a packet from the socket directly. +// It needs to be used for the first handshake packet the server receives, +// so we do't buffer the SSL negotiation packet. As a shortcut, only +// packets smaller than MaxPacketSize can be read here. +// This function usually shouldn't be used - use readEphemeralPacket. +func (c *Conn) readEphemeralPacketDirect() ([]byte, error) { + if c.currentEphemeralPolicy != ephemeralUnused { + panic(fmt.Errorf("readEphemeralPacketDirect: unexpected currentEphemeralPolicy: %v", c.currentEphemeralPolicy)) + } + + var r io.Reader = c.conn + + length, err := c.readHeaderFrom(r) + if err != nil { + return nil, err + } + + if length == 0 { + // This can be caused by the packet after a packet of + // exactly size MaxPacketSize. + return nil, nil + } + + c.currentEphemeralPolicy = ephemeralRead + if length < MaxPacketSize { + c.currentEphemeralBuffer = bufPool.Get(length) + if _, err := io.ReadFull(r, *c.currentEphemeralBuffer); err != nil { + return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) + } + return *c.currentEphemeralBuffer, nil + } + + return nil, fmt.Errorf("readEphemeralPacketDirect doesn't support more than one packet") +} + // recycleReadPacket recycles the read packet. It needs to be called // after readEphemeralPacket was called. func (c *Conn) recycleReadPacket() { - switch c.currentEphemeralPolicy { - case ephemeralReadGlobalBuffer: - // We used small built-in buffer, nothing to do. - case ephemeralReadSingleBuffer: - // We are using the pool, put the buffer back in. - bufPool.Put(c.currentEphemeralReadBuffer) - c.currentEphemeralReadBuffer = nil - case ephemeralReadBigBuffer: - // We allocated a one-time buffer we can't re-use. - // Nothing to do. Nil out for safety. - c.currentEphemeralReadBuffer = nil - case ephemeralUnused, ephemeralWriteGlobalBuffer, ephemeralWriteSingleBuffer, ephemeralWriteBigBuffer: + if c.currentEphemeralPolicy != ephemeralRead { // Programming error. panic(fmt.Errorf("trying to call recycleReadPacket while currentEphemeralPolicy is %d", c.currentEphemeralPolicy)) } + if c.currentEphemeralBuffer != nil { + // We are using the pool, put the buffer back in. + bufPool.Put(c.currentEphemeralBuffer) + c.currentEphemeralBuffer = nil + } c.currentEphemeralPolicy = ephemeralUnused } // readOnePacket reads a single packet into a newly allocated buffer. func (c *Conn) readOnePacket() ([]byte, error) { - var header [4]byte - - if _, err := io.ReadFull(c.reader, header[:]); err != nil { - return nil, fmt.Errorf("io.ReadFull(header size) failed: %v", err) - } - - sequence := uint8(header[3]) - if sequence != c.sequence { - return nil, fmt.Errorf("invalid sequence, expected %v got %v", c.sequence, sequence) + r := c.getReader() + length, err := c.readHeaderFrom(r) + if err != nil { + return nil, err } - - c.sequence++ - - length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16) if length == 0 { // This can be caused by the packet after a packet of // exactly size MaxPacketSize. @@ -416,7 +386,7 @@ func (c *Conn) readOnePacket() ([]byte, error) { } data := make([]byte, length) - if _, err := io.ReadFull(c.reader, data); err != nil { + if _, err := io.ReadFull(r, data); err != nil { return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err) } return data, nil @@ -480,6 +450,8 @@ func (c *Conn) writePacket(data []byte) error { index := 0 length := len(data) + w := c.getWriter() + for { // Packet length is capped to MaxPacketSize. packetLength := length @@ -493,14 +465,14 @@ func (c *Conn) writePacket(data []byte) error { header[1] = byte(packetLength >> 8) header[2] = byte(packetLength >> 16) header[3] = c.sequence - if n, err := c.writer.Write(header[:]); err != nil { + if n, err := w.Write(header[:]); err != nil { return fmt.Errorf("Write(header) failed: %v", err) } else if n != 4 { return fmt.Errorf("Write(header) returned a short write: %v < 4", n) } // Write the body. - if n, err := c.writer.Write(data[index : index+packetLength]); err != nil { + if n, err := w.Write(data[index : index+packetLength]); err != nil { return fmt.Errorf("Write(packet) failed: %v", err) } else if n != packetLength { return fmt.Errorf("Write(packet) returned a short write: %v < %v", n, packetLength) @@ -518,7 +490,7 @@ func (c *Conn) writePacket(data []byte) error { header[1] = 0 header[2] = 0 header[3] = c.sequence - if n, err := c.writer.Write(header[:]); err != nil { + if n, err := w.Write(header[:]); err != nil { return fmt.Errorf("Write(empty header) failed: %v", err) } else if n != 4 { return fmt.Errorf("Write(empty header) returned a short write: %v < 4", n) @@ -536,78 +508,23 @@ func (c *Conn) startEphemeralPacket(length int) []byte { panic("startEphemeralPacket cannot be used while a packet is already started.") } - // Fast path: we can reuse a single memory buffer for - // both the header and the data. - if length <= cap(c.buffer)-4 { - c.currentEphemeralPolicy = ephemeralWriteGlobalBuffer - c.buffer = c.buffer[:length+4] - c.buffer[0] = byte(length) - c.buffer[1] = byte(length >> 8) - c.buffer[2] = byte(length >> 16) - c.buffer[3] = c.sequence - c.sequence++ - return c.buffer[4:] - } - - // Slower path: we can use a single buffer for both the header and the data, but it has to be allocated. - if length < MaxPacketSize { - c.currentEphemeralPolicy = ephemeralWriteSingleBuffer - - c.currentEphemeralWriteBuffer = getBuf(length + 4) - (*c.currentEphemeralWriteBuffer)[0] = byte(length) - (*c.currentEphemeralWriteBuffer)[1] = byte(length >> 8) - (*c.currentEphemeralWriteBuffer)[2] = byte(length >> 16) - (*c.currentEphemeralWriteBuffer)[3] = c.sequence - c.sequence++ - return (*c.currentEphemeralWriteBuffer)[4:] - } - - // Even slower path: create a full size buffer and return it. - c.currentEphemeralPolicy = ephemeralWriteBigBuffer - data := make([]byte, length) - c.currentEphemeralWriteBuffer = &data - return *c.currentEphemeralWriteBuffer + c.currentEphemeralPolicy = ephemeralWrite + // get buffer from pool or it'll be allocated if length is too big + c.currentEphemeralBuffer = bufPool.Get(length) + return *c.currentEphemeralBuffer } // writeEphemeralPacket writes the packet that was allocated by -// startEphemeralPacket. If 'direct' is set, we write to the -// underlying connection directly, by-passing the write buffer. -func (c *Conn) writeEphemeralPacket(direct bool) error { +// startEphemeralPacket. +func (c *Conn) writeEphemeralPacket() error { defer c.recycleWritePacket() - var w io.Writer = c.writer - if direct { - w = c.conn - } - switch c.currentEphemeralPolicy { - case ephemeralWriteGlobalBuffer: - // Just write c.buffer as a single buffer. - // It has both header and data. - if n, err := w.Write(c.buffer); err != nil { - return fmt.Errorf("Conn %v: Write(c.buffer) failed: %v", c.ID(), err) - } else if n != len(c.buffer) { - return fmt.Errorf("Conn %v: Write(c.buffer) returned a short write: %v < %v", c.ID(), n, len(c.buffer)) - } - case ephemeralWriteSingleBuffer: - // Write the allocated buffer as a single buffer. - // It has both header and data. - if n, err := w.Write(*c.currentEphemeralWriteBuffer); err != nil { - return fmt.Errorf("Conn %v: Write(*c.currentEphemeralWriteBuffer) failed: %v", c.ID(), err) - } else if n != len(*c.currentEphemeralWriteBuffer) { - return fmt.Errorf("Conn %v: Write(*c.currentEphemeralWriteBuffer) returned a short write: %v < %v", c.ID(), n, len(*c.currentEphemeralWriteBuffer)) - } - case ephemeralWriteBigBuffer: - // This is the slower path for big data. - // With direct=true, the caller expects a flush, so we call it - // manually. - if err := c.writePacket(*c.currentEphemeralWriteBuffer); err != nil { + case ephemeralWrite: + if err := c.writePacket(*c.currentEphemeralBuffer); err != nil { return fmt.Errorf("Conn %v: %v", c.ID(), err) } - if direct { - return c.flush() - } - case ephemeralUnused, ephemeralReadGlobalBuffer, ephemeralReadSingleBuffer, ephemeralReadBigBuffer: + case ephemeralUnused, ephemeralRead: // Programming error. panic(fmt.Errorf("Conn %v: trying to call writeEphemeralPacket while currentEphemeralPolicy is %v", c.ID(), c.currentEphemeralPolicy)) } @@ -618,35 +535,16 @@ func (c *Conn) writeEphemeralPacket(direct bool) error { // recycleWritePacket recycles the write packet. It needs to be called // after writeEphemeralPacket was called. func (c *Conn) recycleWritePacket() { - switch c.currentEphemeralPolicy { - case ephemeralWriteGlobalBuffer: - // We used small built-in buffer, nothing to do. - case ephemeralWriteSingleBuffer: - // Release our reference so the buffer can be gced - bufPool.Put(c.currentEphemeralWriteBuffer) - c.currentEphemeralWriteBuffer = nil - case ephemeralWriteBigBuffer: - // We allocated a one-time buffer we can't re-use. - // N.B. Unlike the read packet, we actually assign the big buffer to currentEphemeralReadBuffer, - // so we should remove our reference to it. - c.currentEphemeralWriteBuffer = nil - case ephemeralUnused, ephemeralReadGlobalBuffer, - ephemeralReadSingleBuffer, ephemeralReadBigBuffer: + if c.currentEphemeralPolicy != ephemeralWrite { // Programming error. panic(fmt.Errorf("trying to call recycleWritePacket while currentEphemeralPolicy is %d", c.currentEphemeralPolicy)) } + // Release our reference so the buffer can be gced + bufPool.Put(c.currentEphemeralBuffer) + c.currentEphemeralBuffer = nil c.currentEphemeralPolicy = ephemeralUnused } -// flush flushes the written data to the socket. -// This method returns a generic error, not a SQLError. -func (c *Conn) flush() error { - if err := c.writer.Flush(); err != nil { - return fmt.Errorf("Conn %v: Flush() failed: %v", c.ID(), err) - } - return nil -} - // writeComQuit writes a Quit message for the server, to indicate we // want to close the connection. // Client -> Server. @@ -657,7 +555,7 @@ func (c *Conn) writeComQuit() error { data := c.startEphemeralPacket(1) data[0] = ComQuit - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, err.Error()) } return nil @@ -681,23 +579,23 @@ func (c *Conn) String() string { // Close closes the connection. It can be called from a different go // routine to interrupt the current connection. func (c *Conn) Close() { - c.Closed = true - c.conn.Close() + if c.closed.CompareAndSwap(false, true) { + c.conn.Close() + } } // IsClosed returns true if this connection was ever closed by the // Close() method. Note if the other side closes the connection, but // Close() wasn't called, this will return false. func (c *Conn) IsClosed() bool { - return c.Closed + return c.closed.Get() } // // Packet writing methods, for generic packets. // -// writeOKPacket writes an OK packet, directly. Do not use this if -// there is already a packet in the buffer. +// writeOKPacket writes an OK packet. // Server -> Client. // This method returns a generic error, not a SQLError. func (c *Conn) writeOKPacket(affectedRows, lastInsertID uint64, flags uint16, warnings uint16) error { @@ -714,7 +612,7 @@ func (c *Conn) writeOKPacket(affectedRows, lastInsertID uint64, flags uint16, wa pos = writeUint16(data, pos, flags) pos = writeUint16(data, pos, warnings) - return c.writeEphemeralPacket(true) + return c.writeEphemeralPacket() } // writeOKPacketWithEOFHeader writes an OK packet with an EOF header. @@ -736,15 +634,10 @@ func (c *Conn) writeOKPacketWithEOFHeader(affectedRows, lastInsertID uint64, fla pos = writeUint16(data, pos, flags) pos = writeUint16(data, pos, warnings) - if err := c.writeEphemeralPacket(false); err != nil { - return err - } - return c.flush() + return c.writeEphemeralPacket() } // writeErrorPacket writes an error packet. -// It writes directly to the socket, so this cannot be called after other -// packets have already been written. // Server -> Client. // This method returns a generic error, not a SQLError. func (c *Conn) writeErrorPacket(errorCode uint16, sqlState string, format string, args ...interface{}) error { @@ -764,7 +657,7 @@ func (c *Conn) writeErrorPacket(errorCode uint16, sqlState string, format string pos = writeEOFString(data, pos, sqlState) pos = writeEOFString(data, pos, errorMessage) - return c.writeEphemeralPacket(true) + return c.writeEphemeralPacket() } // writeErrorPacketFromError writes an error packet, from a regular error. @@ -787,7 +680,167 @@ func (c *Conn) writeEOFPacket(flags uint16, warnings uint16) error { pos = writeUint16(data, pos, warnings) pos = writeUint16(data, pos, flags) - return c.writeEphemeralPacket(false) + return c.writeEphemeralPacket() +} + +// handleNextCommand is called in the server loop to process +// incoming packets. +func (c *Conn) handleNextCommand(handler Handler) error { + c.sequence = 0 + data, err := c.readEphemeralPacket() + if err != nil { + // Don't log EOF errors. They cause too much spam. + // Note the EOF detection is not 100% + // guaranteed, in the case where the client + // connection is already closed before we call + // 'readEphemeralPacket'. This is a corner + // case though, and very unlikely to happen, + // and the only downside is we log a bit more then. + if err != io.EOF { + log.Errorf("Error reading packet from %s: %v", c, err) + } + return err + } + + switch data[0] { + case ComQuit: + c.recycleReadPacket() + return errors.New("ComQuit") + case ComInitDB: + db := c.parseComInitDB(data) + c.recycleReadPacket() + c.SchemaName = db + if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil { + log.Errorf("Error writing ComInitDB result to %s: %v", c, err) + return err + } + case ComQuery: + // flush is called at the end of this block. + // We cannot encapsulate it with a defer inside a func because + // we have to return from this func if it fails. + c.startWriterBuffering() + + queryStart := time.Now() + query := c.parseComQuery(data) + c.recycleReadPacket() + fieldSent := false + // sendFinished is set if the response should just be an OK packet. + sendFinished := false + + err := handler.ComQuery(c, query, func(qr *sqltypes.Result) error { + if sendFinished { + // Failsafe: Unreachable if server is well-behaved. + return io.EOF + } + + if !fieldSent { + fieldSent = true + + if len(qr.Fields) == 0 { + sendFinished = true + + // A successful callback with no fields means that this was a + // DML or other write-only operation. + // + // We should not send any more packets after this, but make sure + // to extract the affected rows and last insert id from the result + // struct here since clients expect it. + return c.writeOKPacket(qr.RowsAffected, qr.InsertID, c.StatusFlags, handler.WarningCount(c)) + } + if err := c.writeFields(qr); err != nil { + return err + } + } + + return c.writeRows(qr) + }) + + // If no field was sent, we expect an error. + if !fieldSent { + // This is just a failsafe. Should never happen. + if err == nil || err == io.EOF { + err = NewSQLErrorFromError(errors.New("unexpected: query ended without no results and no error")) + } + if werr := c.writeErrorPacketFromError(err); werr != nil { + // If we can't even write the error, we're done. + log.Errorf("Error writing query error to %s: %v", c, werr) + return werr + } + } else { + if err != nil { + // We can't send an error in the middle of a stream. + // All we can do is abort the send, which will cause a 2013. + log.Errorf("Error in the middle of a stream to %s: %v", c, err) + return err + } + + // Send the end packet only sendFinished is false (results were streamed). + // In this case the affectedRows and lastInsertID are always 0 since it + // was a read operation. + if !sendFinished { + if err := c.writeEndResult(false, 0, 0, handler.WarningCount(c)); err != nil { + log.Errorf("Error writing result to %s: %v", c, err) + return err + } + } + } + + timings.Record(queryTimingKey, queryStart) + + if err := c.flush(); err != nil { + log.Errorf("Conn %v: Flush() failed: %v", c.ID(), err) + return err + } + + case ComPing: + c.recycleReadPacket() + // Return error if listener was shut down and OK otherwise + if c.listener.isShutdown() { + if err := c.writeErrorPacket(ERServerShutdown, SSServerShutdown, "Server shutdown in progress"); err != nil { + log.Errorf("Error writing ComPing error to %s: %v", c, err) + return err + } + } else { + if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil { + log.Errorf("Error writing ComPing result to %s: %v", c, err) + return err + } + } + case ComSetOption: + if operation, ok := c.parseComSetOption(data); ok { + switch operation { + case 0: + c.Capabilities |= CapabilityClientMultiStatements + case 1: + c.Capabilities &^= CapabilityClientMultiStatements + default: + log.Errorf("Got unhandled packet from client %v, returning error: %v", c.ConnectionID, data) + if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil { + log.Errorf("Error writing error packet to client: %v", err) + return err + } + } + if err := c.writeEndResult(false, 0, 0, 0); err != nil { + log.Errorf("Error writeEndResult error %v ", err) + return err + } + } else { + log.Errorf("Got unhandled packet from client %v, returning error: %v", c.ConnectionID, data) + if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil { + log.Errorf("Error writing error packet to client: %v", err) + return err + } + } + default: + log.Errorf("Got unhandled packet from %s, returning error: %v", c, data) + c.recycleReadPacket() + if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "command handling not implemented yet: %v", data[0]); err != nil { + log.Errorf("Error writing error packet to %s: %s", c, err) + return err + } + } + + return nil } // @@ -814,14 +867,21 @@ func isEOFPacket(data []byte) bool { return data[0] == EOFPacket && len(data) < 9 } -// parseEOFPacket returns true if there are more results to receive. -func parseEOFPacket(data []byte) (bool, error) { +// parseEOFPacket returns the warning count and a boolean to indicate if there +// are more results to receive. +// +// Note: This is only valid on actual EOF packets and not on OK packets with the EOF +// type code set, i.e. should not be used if ClientDeprecateEOF is set. +func parseEOFPacket(data []byte) (warnings uint16, more bool, err error) { + // The warning count is in position 2 & 3 + warnings, _, ok := readUint16(data, 1) + // The status flag is in position 4 & 5 statusFlags, _, ok := readUint16(data, 3) if !ok { - return false, fmt.Errorf("invalid EOF packet statusFlags: %v", data) + return 0, false, fmt.Errorf("invalid EOF packet statusFlags: %v", data) } - return (statusFlags & ServerMoreResultsExists) != 0, nil + return warnings, (statusFlags & ServerMoreResultsExists) != 0, nil } func parseOKPacket(data []byte) (uint64, uint64, uint16, uint16, error) { diff --git a/go/mysql/conn_params.go b/go/mysql/conn_params.go index ae739c9b59c..5af81b1202a 100644 --- a/go/mysql/conn_params.go +++ b/go/mysql/conn_params.go @@ -38,6 +38,10 @@ type ConnParams struct { // The following is only set when the deprecated "dbname" flags are // supplied and will be removed. DeprecatedDBName string + + // The following is only set to force the client to connect without + // using CapabilityClientDeprecateEOF + DisableClientDeprecateEOF bool } // EnableSSL will set the right flag on the parameters. diff --git a/go/mysql/conn_test.go b/go/mysql/conn_test.go index 50b99714d31..3ff4e0889a7 100644 --- a/go/mysql/conn_test.go +++ b/go/mysql/conn_test.go @@ -77,26 +77,22 @@ func useWritePacket(t *testing.T, cConn *Conn, data []byte) { if err := cConn.writePacket(data); err != nil { t.Fatalf("writePacket failed: %v", err) } - if err := cConn.flush(); err != nil { - t.Fatalf("flush failed: %v", err) - } } -func useWriteEphemeralPacket(t *testing.T, cConn *Conn, data []byte) { +func useWriteEphemeralPacketBuffered(t *testing.T, cConn *Conn, data []byte) { defer func() { if x := recover(); x != nil { t.Fatalf("%v", x) } }() + cConn.startWriterBuffering() + defer cConn.flush() buf := cConn.startEphemeralPacket(len(data)) copy(buf, data) - if err := cConn.writeEphemeralPacket(false); err != nil { + if err := cConn.writeEphemeralPacket(); err != nil { t.Fatalf("writeEphemeralPacket(false) failed: %v", err) } - if err := cConn.flush(); err != nil { - t.Fatalf("flush failed: %v", err) - } } func useWriteEphemeralPacketDirect(t *testing.T, cConn *Conn, data []byte) { @@ -108,7 +104,7 @@ func useWriteEphemeralPacketDirect(t *testing.T, cConn *Conn, data []byte) { buf := cConn.startEphemeralPacket(len(data)) copy(buf, data) - if err := cConn.writeEphemeralPacket(true); err != nil { + if err := cConn.writeEphemeralPacket(); err != nil { t.Fatalf("writeEphemeralPacket(true) failed: %v", err) } } @@ -139,22 +135,25 @@ func verifyPacketCommsSpecific(t *testing.T, cConn *Conn, data []byte, func verifyPacketComms(t *testing.T, cConn, sConn *Conn, data []byte) { // All three writes, with ReadPacket. verifyPacketCommsSpecific(t, cConn, data, useWritePacket, sConn.ReadPacket) - verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacket, sConn.ReadPacket) + verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketBuffered, sConn.ReadPacket) verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketDirect, sConn.ReadPacket) // All three writes, with readEphemeralPacket. verifyPacketCommsSpecific(t, cConn, data, useWritePacket, sConn.readEphemeralPacket) sConn.recycleReadPacket() - verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacket, sConn.readEphemeralPacket) + verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketBuffered, sConn.readEphemeralPacket) sConn.recycleReadPacket() verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketDirect, sConn.readEphemeralPacket) sConn.recycleReadPacket() - // All three writes, with readPacketDirect, if size allows it. + // All three writes, with readEphemeralPacketDirect, if size allows it. if len(data) < MaxPacketSize { - verifyPacketCommsSpecific(t, cConn, data, useWritePacket, sConn.readPacketDirect) - verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacket, sConn.readPacketDirect) - verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketDirect, sConn.readPacketDirect) + verifyPacketCommsSpecific(t, cConn, data, useWritePacket, sConn.readEphemeralPacketDirect) + sConn.recycleReadPacket() + verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketBuffered, sConn.readEphemeralPacketDirect) + sConn.recycleReadPacket() + verifyPacketCommsSpecific(t, cConn, data, useWriteEphemeralPacketDirect, sConn.readEphemeralPacketDirect) + sConn.recycleReadPacket() } } @@ -254,9 +253,6 @@ func TestBasicPackets(t *testing.T) { if err := sConn.writeEOFPacket(0x8912, 0xabba); err != nil { t.Fatalf("writeEOFPacket failed: %v", err) } - if err := sConn.flush(); err != nil { - t.Fatalf("flush failed: %v", err) - } data, err = cConn.ReadPacket() if err != nil || len(data) == 0 || !isEOFPacket(data) { t.Fatalf("cConn.ReadPacket - EOFPacket failed: %v %v", data, err) diff --git a/go/mysql/constants.go b/go/mysql/constants.go index afe203847be..dc961154734 100644 --- a/go/mysql/constants.go +++ b/go/mysql/constants.go @@ -440,6 +440,9 @@ const ( // SSHandshakeError is ER_HANDSHAKE_ERROR SSHandshakeError = "08S01" + // SSServerShutdown is ER_SERVER_SHUTDOWN + SSServerShutdown = "08S01" + // SSDataTooLong is ER_DATA_TOO_LONG SSDataTooLong = "22001" diff --git a/go/mysql/endtoend/client_test.go b/go/mysql/endtoend/client_test.go index e2ad2d3fb2e..0a190944952 100644 --- a/go/mysql/endtoend/client_test.go +++ b/go/mysql/endtoend/client_test.go @@ -142,23 +142,30 @@ func TestClientFoundRows(t *testing.T) { } } -func TestMultiResult(t *testing.T) { +func doTestMultiResult(t *testing.T, disableClientDeprecateEOF bool) { ctx := context.Background() + connParams.DisableClientDeprecateEOF = disableClientDeprecateEOF + conn, err := mysql.Connect(ctx, &connParams) expectNoError(t, err) defer conn.Close() + connParams.DisableClientDeprecateEOF = false + + expectFlag(t, "Negotiated ClientDeprecateEOF flag", (conn.Capabilities&mysql.CapabilityClientDeprecateEOF) != 0, !disableClientDeprecateEOF) + defer conn.Close() + qr, more, err := conn.ExecuteFetchMulti("select 1 from dual; set autocommit=1; select 1 from dual", 10, true) expectNoError(t, err) expectFlag(t, "ExecuteMultiFetch(multi result)", more, true) expectRows(t, "ExecuteMultiFetch(multi result)", qr, 1) - qr, more, err = conn.ReadQueryResult(10, true) + qr, more, _, err = conn.ReadQueryResult(10, true) expectNoError(t, err) expectFlag(t, "ReadQueryResult(1)", more, true) expectRows(t, "ReadQueryResult(1)", qr, 0) - qr, more, err = conn.ReadQueryResult(10, true) + qr, more, _, err = conn.ReadQueryResult(10, true) expectNoError(t, err) expectFlag(t, "ReadQueryResult(2)", more, false) expectRows(t, "ReadQueryResult(2)", qr, 1) @@ -172,6 +179,63 @@ func TestMultiResult(t *testing.T) { expectNoError(t, err) expectFlag(t, "ExecuteMultiFetch(no result)", more, false) expectRows(t, "ExecuteMultiFetch(no result)", qr, 0) + + // The ClientDeprecateEOF protocol change has a subtle twist in which an EOF or OK + // packet happens to have the status flags in the same position if the affected_rows + // and last_insert_id are both one byte long: + // + // https://dev.mysql.com/doc/internals/en/packet-EOF_Packet.html + // https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html + // + // It turns out that there are no actual cases in which clients end up needing to make + // this distinction. If either affected_rows or last_insert_id are non-zero, the protocol + // sends an OK packet unilaterally which is properly parsed. If not, then regardless of the + // negotiated version, it can properly send the status flags. + // + result, err := conn.ExecuteFetch("create table a(id int, name varchar(128), primary key(id))", 0, false) + if err != nil { + t.Fatalf("create table failed: %v", err) + } + if result.RowsAffected != 0 { + t.Errorf("create table returned RowsAffected %v, was expecting 0", result.RowsAffected) + } + + for i := 0; i < 255; i++ { + result, err := conn.ExecuteFetch(fmt.Sprintf("insert into a(id, name) values(%v, 'nice name %v')", 1000+i, i), 1000, true) + if err != nil { + t.Fatalf("ExecuteFetch(%v) failed: %v", i, err) + } + if result.RowsAffected != 1 { + t.Errorf("insert into returned RowsAffected %v, was expecting 1", result.RowsAffected) + } + } + + qr, more, err = conn.ExecuteFetchMulti("update a set name = concat(name, ' updated'); select * from a; select count(*) from a", 300, true) + expectNoError(t, err) + expectFlag(t, "ExecuteMultiFetch(multi result)", more, true) + expectRows(t, "ExecuteMultiFetch(multi result)", qr, 255) + + qr, more, _, err = conn.ReadQueryResult(300, true) + expectNoError(t, err) + expectFlag(t, "ReadQueryResult(1)", more, true) + expectRows(t, "ReadQueryResult(1)", qr, 255) + + qr, more, _, err = conn.ReadQueryResult(300, true) + expectNoError(t, err) + expectFlag(t, "ReadQueryResult(2)", more, false) + expectRows(t, "ReadQueryResult(2)", qr, 1) + + result, err = conn.ExecuteFetch("drop table a", 10, true) + if err != nil { + t.Fatalf("drop table failed: %v", err) + } +} + +func TestMultiResultDeprecateEOF(t *testing.T) { + doTestMultiResult(t, false) +} +func TestMultiResultNoDeprecateEOF(t *testing.T) { + doTestMultiResult(t, true) } func expectNoError(t *testing.T, err error) { diff --git a/go/mysql/endtoend/query_test.go b/go/mysql/endtoend/query_test.go index c432bdef5fa..185a6de5627 100644 --- a/go/mysql/endtoend/query_test.go +++ b/go/mysql/endtoend/query_test.go @@ -237,3 +237,57 @@ func readRowsUsingStream(t *testing.T, conn *mysql.Conn, expectedCount int) { } conn.CloseResult() } + +func doTestWarnings(t *testing.T, disableClientDeprecateEOF bool) { + ctx := context.Background() + + connParams.DisableClientDeprecateEOF = disableClientDeprecateEOF + + conn, err := mysql.Connect(ctx, &connParams) + expectNoError(t, err) + defer conn.Close() + + connParams.DisableClientDeprecateEOF = false + + expectFlag(t, "Negotiated ClientDeprecateEOF flag", (conn.Capabilities&mysql.CapabilityClientDeprecateEOF) != 0, !disableClientDeprecateEOF) + defer conn.Close() + + result, err := conn.ExecuteFetch("create table a(id int, val int not null, primary key(id))", 0, false) + if err != nil { + t.Fatalf("create table failed: %v", err) + } + if result.RowsAffected != 0 { + t.Errorf("create table returned RowsAffected %v, was expecting 0", result.RowsAffected) + } + + // Disable strict mode + result, err = conn.ExecuteFetch("set session sql_mode=''", 0, false) + if err != nil { + t.Fatalf("disable strict mode failed: %v", err) + } + + // Try a simple insert with a null value + result, warnings, err := conn.ExecuteFetchWithWarningCount("insert into a(id) values(10)", 1000, true) + if err != nil { + t.Fatalf("insert failed: %v", err) + } + if result.RowsAffected != 1 || len(result.Rows) != 0 { + t.Errorf("unexpected result for insert: %v", result) + } + if warnings != 1 { + t.Errorf("unexpected result for warnings: %v", warnings) + } + + result, err = conn.ExecuteFetch("drop table a", 0, false) + if err != nil { + t.Fatalf("create table failed: %v", err) + } +} + +func TestWarningsDeprecateEOF(t *testing.T) { + doTestWarnings(t, false) +} + +func TestWarningsNoDeprecateEOF(t *testing.T) { + doTestWarnings(t, true) +} diff --git a/go/mysql/fakesqldb/server.go b/go/mysql/fakesqldb/server.go index 4aaf965b02a..2272b17d7cb 100644 --- a/go/mysql/fakesqldb/server.go +++ b/go/mysql/fakesqldb/server.go @@ -320,6 +320,11 @@ func (db *DB) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Resu return db.Handler.HandleQuery(c, query, callback) } +// WarningCount is part of the mysql.Handler interface. +func (db *DB) WarningCount(c *mysql.Conn) uint16 { + return 0 +} + // HandleQuery is the default implementation of the QueryHandler interface func (db *DB) HandleQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error { if db.AllowAll { diff --git a/go/mysql/query.go b/go/mysql/query.go index b9dd2aaeddb..ebaabb27a6a 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -40,7 +40,7 @@ func (c *Conn) WriteComQuery(query string) error { data := c.startEphemeralPacket(len(query) + 1) data[0] = ComQuery copy(data[1:], query) - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, err.Error()) } return nil @@ -53,7 +53,7 @@ func (c *Conn) writeComInitDB(db string) error { data := c.startEphemeralPacket(len(db) + 1) data[0] = ComInitDB copy(data[1:], db) - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, err.Error()) } return nil @@ -65,7 +65,7 @@ func (c *Conn) writeComSetOption(operation uint16) error { data := c.startEphemeralPacket(16 + 1) data[0] = ComSetOption writeUint16(data, 1, operation) - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, err.Error()) } return nil @@ -311,22 +311,45 @@ func (c *Conn) ExecuteFetchMulti(query string, maxrows int, wantfields bool) (re return nil, false, err } - return c.ReadQueryResult(maxrows, wantfields) + res, more, _, err := c.ReadQueryResult(maxrows, wantfields) + return res, more, err +} + +// ExecuteFetchWithWarningCount is for fetching results and a warning count +// Note: In a future iteration this should be abolished and merged into the +// ExecuteFetch API. +func (c *Conn) ExecuteFetchWithWarningCount(query string, maxrows int, wantfields bool) (result *sqltypes.Result, warnings uint16, err error) { + defer func() { + if err != nil { + if sqlerr, ok := err.(*SQLError); ok { + sqlerr.Query = query + } + } + }() + + // Send the query as a COM_QUERY packet. + if err = c.WriteComQuery(query); err != nil { + return nil, 0, err + } + + res, _, warnings, err := c.ReadQueryResult(maxrows, wantfields) + return res, warnings, err } // ReadQueryResult gets the result from the last written query. -func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.Result, more bool, err error) { +func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.Result, more bool, warnings uint16, err error) { // Get the result. - affectedRows, lastInsertID, colNumber, more, err := c.readComQueryResponse() + affectedRows, lastInsertID, colNumber, more, warnings, err := c.readComQueryResponse() if err != nil { - return nil, false, err + return nil, false, 0, err } + if colNumber == 0 { // OK packet, means no results. Just use the numbers. return &sqltypes.Result{ RowsAffected: affectedRows, InsertID: lastInsertID, - }, more, nil + }, more, warnings, nil } fields := make([]querypb.Field, colNumber) @@ -341,11 +364,11 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.R if wantfields { if err := c.readColumnDefinition(result.Fields[i], i); err != nil { - return nil, false, err + return nil, false, 0, err } } else { if err := c.readColumnDefinitionType(result.Fields[i], i); err != nil { - return nil, false, err + return nil, false, 0, err } } } @@ -354,19 +377,21 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.R // EOF is only present here if it's not deprecated. data, err := c.readEphemeralPacket() if err != nil { - return nil, false, NewSQLError(CRServerLost, SSUnknownSQLState, "%v", err) + return nil, false, 0, NewSQLError(CRServerLost, SSUnknownSQLState, "%v", err) } if isEOFPacket(data) { + // This is what we expect. // Warnings and status flags are ignored. c.recycleReadPacket() // goto: read row loop + } else if isErrorPacket(data) { defer c.recycleReadPacket() - return nil, false, ParseErrorPacket(data) + return nil, false, 0, ParseErrorPacket(data) } else { defer c.recycleReadPacket() - return nil, false, fmt.Errorf("unexpected packet after fields: %v", data) + return nil, false, 0, fmt.Errorf("unexpected packet after fields: %v", data) } } @@ -374,7 +399,7 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.R for { data, err := c.ReadPacket() if err != nil { - return nil, false, err + return nil, false, 0, err } if isEOFPacket(data) { @@ -383,28 +408,41 @@ func (c *Conn) ReadQueryResult(maxrows int, wantfields bool) (result *sqltypes.R result.Fields = nil } result.RowsAffected = uint64(len(result.Rows)) - more, err := parseEOFPacket(data) - if err != nil { - return nil, false, err + + // The deprecated EOF packets change means that this is either an + // EOF packet or an OK packet with the EOF type code. + if c.Capabilities&CapabilityClientDeprecateEOF == 0 { + warnings, more, err = parseEOFPacket(data) + if err != nil { + return nil, false, 0, err + } + } else { + var statusFlags uint16 + _, _, statusFlags, warnings, err = parseOKPacket(data) + if err != nil { + return nil, false, 0, err + } + more = (statusFlags & ServerMoreResultsExists) != 0 } - return result, more, nil + return result, more, warnings, nil + } else if isErrorPacket(data) { // Error packet. - return nil, false, ParseErrorPacket(data) + return nil, false, 0, ParseErrorPacket(data) } // Check we're not over the limit before we add more. if len(result.Rows) == maxrows { if err := c.drainResults(); err != nil { - return nil, false, err + return nil, false, 0, err } - return nil, false, NewSQLError(ERVitessMaxRowsExceeded, SSUnknownSQLState, "Row count exceeded %d", maxrows) + return nil, false, 0, NewSQLError(ERVitessMaxRowsExceeded, SSUnknownSQLState, "Row count exceeded %d", maxrows) } // Regular row. row, err := c.parseRow(data, result.Fields) if err != nil { - return nil, false, err + return nil, false, 0, err } result.Rows = append(result.Rows, row) } @@ -428,36 +466,35 @@ func (c *Conn) drainResults() error { } } -func (c *Conn) readComQueryResponse() (uint64, uint64, int, bool, error) { +func (c *Conn) readComQueryResponse() (affectedRows uint64, lastInsertID uint64, status int, more bool, warnings uint16, err error) { data, err := c.readEphemeralPacket() if err != nil { - return 0, 0, 0, false, NewSQLError(CRServerLost, SSUnknownSQLState, "%v", err) + return 0, 0, 0, false, 0, NewSQLError(CRServerLost, SSUnknownSQLState, "%v", err) } defer c.recycleReadPacket() if len(data) == 0 { - return 0, 0, 0, false, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "invalid empty COM_QUERY response packet") + return 0, 0, 0, false, 0, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "invalid empty COM_QUERY response packet") } switch data[0] { case OKPacket: - affectedRows, lastInsertID, status, _, err := parseOKPacket(data) - return affectedRows, lastInsertID, 0, (status & ServerMoreResultsExists) != 0, err + affectedRows, lastInsertID, status, warnings, err := parseOKPacket(data) + return affectedRows, lastInsertID, 0, (status & ServerMoreResultsExists) != 0, warnings, err case ErrPacket: // Error - return 0, 0, 0, false, ParseErrorPacket(data) + return 0, 0, 0, false, 0, ParseErrorPacket(data) case 0xfb: // Local infile - return 0, 0, 0, false, fmt.Errorf("not implemented") + return 0, 0, 0, false, 0, fmt.Errorf("not implemented") } - n, pos, ok := readLenEncInt(data, 0) if !ok { - return 0, 0, 0, false, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "cannot get column number") + return 0, 0, 0, false, 0, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "cannot get column number") } if pos != len(data) { - return 0, 0, 0, false, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "extra data in COM_QUERY response") + return 0, 0, 0, false, 0, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "extra data in COM_QUERY response") } - return 0, 0, int(n), false, nil + return 0, 0, int(n), false, 0, nil } // @@ -481,7 +518,7 @@ func (c *Conn) sendColumnCount(count uint64) error { length := lenEncIntSize(count) data := c.startEphemeralPacket(length) writeLenEncInt(data, 0, count) - return c.writeEphemeralPacket(false) + return c.writeEphemeralPacket() } func (c *Conn) writeColumnDefinition(field *querypb.Field) error { @@ -528,7 +565,7 @@ func (c *Conn) writeColumnDefinition(field *querypb.Field) error { return fmt.Errorf("internal error: packing of column definition used %v bytes instead of %v", pos, len(data)) } - return c.writeEphemeralPacket(false) + return c.writeEphemeralPacket() } func (c *Conn) writeRow(row []sqltypes.Value) error { @@ -558,7 +595,7 @@ func (c *Conn) writeRow(row []sqltypes.Value) error { return fmt.Errorf("internal error packet row: got %v bytes but expected %v", pos, length) } - return c.writeEphemeralPacket(false) + return c.writeEphemeralPacket() } // writeFields writes the fields of a Result. It should be called only @@ -598,23 +635,20 @@ func (c *Conn) writeRows(result *sqltypes.Result) error { // writeEndResult concludes the sending of a Result. // if more is set to true, then it means there are more results afterwords -func (c *Conn) writeEndResult(more bool) error { +func (c *Conn) writeEndResult(more bool, affectedRows, lastInsertID uint64, warnings uint16) error { // Send either an EOF, or an OK packet. // See doc.go. - flag := c.StatusFlags + flags := c.StatusFlags if more { - flag |= ServerMoreResultsExists + flags |= ServerMoreResultsExists } if c.Capabilities&CapabilityClientDeprecateEOF == 0 { - if err := c.writeEOFPacket(flag, 0); err != nil { - return err - } - if err := c.flush(); err != nil { + if err := c.writeEOFPacket(flags, warnings); err != nil { return err } } else { // This will flush too. - if err := c.writeOKPacketWithEOFHeader(0, 0, flag, 0); err != nil { + if err := c.writeOKPacketWithEOFHeader(affectedRows, lastInsertID, flags, warnings); err != nil { return err } } diff --git a/go/mysql/query_benchmark_test.go b/go/mysql/query_benchmark_test.go index 173932ec00c..de3c9c417df 100644 --- a/go/mysql/query_benchmark_test.go +++ b/go/mysql/query_benchmark_test.go @@ -17,6 +17,7 @@ limitations under the License. package mysql import ( + "flag" "math/rand" "net" "strings" @@ -25,12 +26,27 @@ import ( "golang.org/x/net/context" ) +var testReadConnBufferSize = connBufferSize + +func init() { + flag.IntVar(&testReadConnBufferSize, "test.read_conn_buffer_size", connBufferSize, "buffer size for reads from connections in tests") +} + +const benchmarkQueryPrefix = "benchmark " + func benchmarkQuery(b *testing.B, threads int, query string) { th := &testHandler{} authServer := &AuthServerNone{} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + lCfg := ListenerConfig{ + Protocol: "tcp", + Address: ":0", + AuthServer: authServer, + Handler: th, + ConnReadBufferSize: testReadConnBufferSize, + } + l, err := NewListenerWithConfig(lCfg) if err != nil { b.Fatalf("NewListener failed: %v", err) } @@ -57,6 +73,9 @@ func benchmarkQuery(b *testing.B, threads int, query string) { b.ResetTimer() + // MaxPacketSize is too big for benchmarks, so choose something smaller + maxPacketSize := connBufferSize * 4 + b.RunParallel(func(pb *testing.PB) { conn, err := Connect(ctx, params) if err != nil { @@ -71,8 +90,9 @@ func benchmarkQuery(b *testing.B, threads int, query string) { execQuery := query if execQuery == "" { // generate random query - n := rand.Intn(MaxPacketSize-2) + 1 - execQuery = strings.Repeat("x", n) + n := rand.Intn(maxPacketSize-len(benchmarkQueryPrefix)) + 1 + execQuery = benchmarkQueryPrefix + strings.Repeat("x", n) + } if _, err := conn.ExecuteFetch(execQuery, 1000, true); err != nil { b.Fatalf("ExecuteFetch failed: %v", err) @@ -87,11 +107,11 @@ func benchmarkQuery(b *testing.B, threads int, query string) { // executes M queries on them, then closes them. // It is meant as a somewhat real load test. func BenchmarkParallelShortQueries(b *testing.B) { - benchmarkQuery(b, 10, "select rows") + benchmarkQuery(b, 10, benchmarkQueryPrefix+"select rows") } func BenchmarkParallelMediumQueries(b *testing.B) { - benchmarkQuery(b, 10, "select"+strings.Repeat("x", connBufferSize)) + benchmarkQuery(b, 10, benchmarkQueryPrefix+"select"+strings.Repeat("x", connBufferSize)) } func BenchmarkParallelRandomQueries(b *testing.B) { diff --git a/go/mysql/query_test.go b/go/mysql/query_test.go index e8a957ed334..c2ae6cf4176 100644 --- a/go/mysql/query_test.go +++ b/go/mysql/query_test.go @@ -300,20 +300,24 @@ func checkQuery(t *testing.T, query string, sConn, cConn *Conn, result *sqltypes sConn.Capabilities = 0 cConn.Capabilities = 0 - checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, true /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, false /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, false /* allRows */) + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, true /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, false /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, false /* allRows */, false /* warnings */) + + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */, true /* warnings */) sConn.Capabilities = CapabilityClientDeprecateEOF cConn.Capabilities = CapabilityClientDeprecateEOF - checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, true /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, false /* allRows */) - checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, false /* allRows */) + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, true /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, false /* allRows */, false /* warnings */) + checkQueryInternal(t, query, sConn, cConn, result, false /* wantfields */, false /* allRows */, false /* warnings */) + + checkQueryInternal(t, query, sConn, cConn, result, true /* wantfields */, true /* allRows */, true /* warnings */) } -func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result *sqltypes.Result, wantfields, allRows bool) { +func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result *sqltypes.Result, wantfields, allRows, warnings bool) { if sConn.Capabilities&CapabilityClientDeprecateEOF > 0 { query += " NOEOF" @@ -331,6 +335,14 @@ func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result * query += " PARTIAL" } + var warningCount uint16 + if warnings { + query += " WARNINGS" + warningCount = 99 + } else { + query += " NOWARNINGS" + } + // Use a go routine to run ExecuteFetch. wg := sync.WaitGroup{} wg.Add(1) @@ -343,7 +355,7 @@ func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result * // Asking for just one row max. The results that have more will fail. maxrows = 1 } - got, err := cConn.ExecuteFetch(query, maxrows, wantfields) + got, gotWarnings, err := cConn.ExecuteFetchWithWarningCount(query, maxrows, wantfields) if !allRows && len(result.Rows) > 1 { if err == nil { t.Errorf("ExecuteFetch should have failed but got: %v", got) @@ -371,6 +383,10 @@ func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result * t.Fatalf("ExecuteFetch(wantfields=%v) returned:\n%v\nBut was expecting:\n%v", wantfields, got, expected) } + if gotWarnings != warningCount { + t.Errorf("ExecuteFetch(%v) expected %v warnings got %v", query, warningCount, gotWarnings) + } + // Test ExecuteStreamFetch, build a Result. expected = *result if err := cConn.ExecuteStreamFetch(query); err != nil { @@ -425,22 +441,16 @@ func checkQueryInternal(t *testing.T, query string, sConn, cConn *Conn, result * count-- } + handler := testHandler{ + result: result, + warnings: warningCount, + } + for i := 0; i < count; i++ { - comQuery, err := sConn.ReadPacket() + err := sConn.handleNextCommand(&handler) if err != nil { - t.Fatalf("server cannot read query: %v", err) - } - if comQuery[0] != ComQuery { - t.Fatalf("server got bad packet: %v", comQuery) - } - got := sConn.parseComQuery(comQuery) - if got != query { - t.Errorf("server got query '%v' but expected '%v'", got, query) - } - if err := writeResult(sConn, result); err != nil { - t.Errorf("Error writing result to client: %v", err) + t.Fatalf("error handling command: %v", err) } - sConn.sequence = 0 } wg.Wait() @@ -456,7 +466,7 @@ func writeResult(conn *Conn, result *sqltypes.Result) error { if err := conn.writeRows(result); err != nil { return err } - return conn.writeEndResult(false) + return conn.writeEndResult(false, 0, 0, 0) } func RowString(row []sqltypes.Value) string { diff --git a/go/mysql/replication.go b/go/mysql/replication.go index 3797728dbe7..e59db547d6a 100644 --- a/go/mysql/replication.go +++ b/go/mysql/replication.go @@ -34,7 +34,7 @@ func (c *Conn) WriteComBinlogDump(serverID uint32, binlogFilename string, binlog pos = writeUint16(data, pos, flags) pos = writeUint32(data, pos, serverID) pos = writeEOFString(data, pos, binlogFilename) - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, "%v", err) } return nil @@ -62,7 +62,7 @@ func (c *Conn) WriteComBinlogDumpGTID(serverID uint32, binlogFilename string, bi pos = writeUint64(data, pos, binlogPos) pos = writeUint32(data, pos, uint32(len(gtidSet))) pos += copy(data[pos:], gtidSet) - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return NewSQLError(CRServerGone, SSUnknownSQLState, "%v", err) } return nil diff --git a/go/mysql/server.go b/go/mysql/server.go index 40b38622145..37d5e2b3e5b 100644 --- a/go/mysql/server.go +++ b/go/mysql/server.go @@ -18,7 +18,6 @@ package mysql import ( "crypto/tls" - "errors" "fmt" "io" "net" @@ -27,6 +26,7 @@ import ( "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/sync2" "vitess.io/vitess/go/tb" "vitess.io/vitess/go/vt/log" ) @@ -47,6 +47,15 @@ var ( connCount = stats.NewGauge("MysqlServerConnCount", "Active MySQL server connections") connAccept = stats.NewCounter("MysqlServerConnAccepted", "Connections accepted by MySQL server") connSlow = stats.NewCounter("MysqlServerConnSlow", "Connections that took more than the configured mysql_slow_connect_warn_threshold to establish") + + connCountPerUser = stats.NewGaugesWithSingleLabel("MysqlServerConnCountPerUser", "Active MySQL server connections per user", "count") + _ = stats.NewGaugeFunc("MysqlServerConnCountUnauthenticated", "Active MySQL server connections that haven't authenticated yet", func() int64 { + totalUsers := int64(0) + for _, v := range connCountPerUser.Counts() { + totalUsers += v + } + return connCount.Get() - totalUsers + }) ) // A Handler is an interface used by Listener to send queries. @@ -75,6 +84,13 @@ type Handler interface { // the first call to callback. So the Handler should not // hang on to the byte slice. ComQuery(c *Conn, query string, callback func(*sqltypes.Result) error) error + + // WarningCount is called at the end of each query to obtain + // the value to be returned to the client in the EOF packet. + // Note that this will be called either in the context of the + // ComQuery callback if the result does not contain any fields, + // or after the last ComQuery call completes. + WarningCount(c *Conn) uint16 } // Listener is the MySQL server protocol listener. @@ -120,19 +136,25 @@ type Listener struct { connReadTimeout time.Duration // Write timeout on a given connection connWriteTimeout time.Duration + // connReadBufferSize is size of buffer for reads from underlying connection. + // Reads are unbuffered if it's <=0. + connReadBufferSize int + + // shutdown indicates that Shutdown method was called. + shutdown sync2.AtomicBool } // NewFromListener creares a new mysql listener from an existing net.Listener func NewFromListener(l net.Listener, authServer AuthServer, handler Handler, connReadTimeout time.Duration, connWriteTimeout time.Duration) (*Listener, error) { - return &Listener{ - authServer: authServer, - handler: handler, - listener: l, - ServerVersion: DefaultServerVersion, - connectionID: 1, - connReadTimeout: connReadTimeout, - connWriteTimeout: connWriteTimeout, - }, nil + cfg := ListenerConfig{ + Listener: l, + AuthServer: authServer, + Handler: handler, + ConnReadTimeout: connReadTimeout, + ConnWriteTimeout: connWriteTimeout, + ConnReadBufferSize: connBufferSize, + } + return NewListenerWithConfig(cfg) } // NewListener creates a new Listener. @@ -145,6 +167,45 @@ func NewListener(protocol, address string, authServer AuthServer, handler Handle return NewFromListener(listener, authServer, handler, connReadTimeout, connWriteTimeout) } +// ListenerConfig should be used with NewListenerWithConfig to specify listener parameters. +type ListenerConfig struct { + // Protocol-Address pair and Listener are mutually exclusive parameters + Protocol string + Address string + Listener net.Listener + AuthServer AuthServer + Handler Handler + ConnReadTimeout time.Duration + ConnWriteTimeout time.Duration + ConnReadBufferSize int +} + +// NewListenerWithConfig creates new listener using provided config. There are +// no default values for config, so caller should ensure its correctness. +func NewListenerWithConfig(cfg ListenerConfig) (*Listener, error) { + var l net.Listener + if cfg.Listener != nil { + l = cfg.Listener + } else { + listener, err := net.Listen(cfg.Protocol, cfg.Address) + if err != nil { + return nil, err + } + l = listener + } + + return &Listener{ + authServer: cfg.AuthServer, + handler: cfg.Handler, + listener: l, + ServerVersion: DefaultServerVersion, + connectionID: 1, + connReadTimeout: cfg.ConnReadTimeout, + connWriteTimeout: cfg.ConnWriteTimeout, + connReadBufferSize: cfg.ConnReadBufferSize, + }, nil +} + // Addr returns the listener address. func (l *Listener) Addr() net.Addr { return l.listener.Addr() @@ -177,7 +238,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti if l.connReadTimeout != 0 || l.connWriteTimeout != 0 { conn = netutil.NewConnWithTimeouts(conn, l.connReadTimeout, l.connWriteTimeout) } - c := newConn(conn) + c := newServerConn(conn, l) c.ConnectionID = connectionID // Catch panics, and close the connection in any case. @@ -185,6 +246,10 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti if x := recover(); x != nil { log.Errorf("mysql_server caught panic:\n%v\n%s", x, tb.Stack(4)) } + // We call flush here in case there's a premature return after + // startWriterBuffering is called + c.flush() + conn.Close() }() @@ -204,7 +269,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti // Wait for the client response. This has to be a direct read, // so we don't buffer the TLS negotiation packets. - response, err := c.readPacketDirect() + response, err := c.readEphemeralPacketDirect() if err != nil { // Don't log EOF errors. They cause too much spam, same as main read loop. if err != io.EOF { @@ -218,6 +283,8 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti return } + c.recycleReadPacket() + if c.Capabilities&CapabilityClientSSL > 0 { // SSL was enabled. We need to re-read the auth packet. response, err = c.readEphemeralPacket() @@ -295,6 +362,11 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti c.UserData = userData } + if c.User != "" { + connCountPerUser.Add(c.User, 1) + defer connCountPerUser.Add(c.User, -1) + } + // Negotiation worked, send OK packet. if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil { log.Errorf("Cannot write OK packet to %s: %v", c, err) @@ -312,143 +384,30 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti } for { - c.sequence = 0 - data, err := c.readEphemeralPacket() + err := c.handleNextCommand(l.handler) if err != nil { - // Don't log EOF errors. They cause too much spam. - // Note the EOF detection is not 100% - // guaranteed, in the case where the client - // connection is already closed before we call - // 'readEphemeralPacket'. This is a corner - // case though, and very unlikely to happen, - // and the only downside is we log a bit more then. - if err != io.EOF { - log.Errorf("Error reading packet from %s: %v", c, err) - } return } - - switch data[0] { - case ComQuit: - c.recycleReadPacket() - return - case ComInitDB: - db := c.parseComInitDB(data) - c.recycleReadPacket() - c.SchemaName = db - if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil { - log.Errorf("Error writing ComInitDB result to %s: %v", c, err) - return - } - case ComQuery: - queryStart := time.Now() - query := c.parseComQuery(data) - c.recycleReadPacket() - fieldSent := false - // sendFinished is set if the response should just be an OK packet. - sendFinished := false - err := l.handler.ComQuery(c, query, func(qr *sqltypes.Result) error { - if sendFinished { - // Failsafe: Unreachable if server is well-behaved. - return io.EOF - } - - if !fieldSent { - fieldSent = true - - if len(qr.Fields) == 0 { - sendFinished = true - // We should not send any more packets after this. - return c.writeOKPacket(qr.RowsAffected, qr.InsertID, c.StatusFlags, 0) - } - if err := c.writeFields(qr); err != nil { - return err - } - } - - return c.writeRows(qr) - }) - - // If no field was sent, we expect an error. - if !fieldSent { - // This is just a failsafe. Should never happen. - if err == nil || err == io.EOF { - err = NewSQLErrorFromError(errors.New("unexpected: query ended without no results and no error")) - } - if werr := c.writeErrorPacketFromError(err); werr != nil { - // If we can't even write the error, we're done. - log.Errorf("Error writing query error to %s: %v", c, werr) - return - } - continue - } - - if err != nil { - // We can't send an error in the middle of a stream. - // All we can do is abort the send, which will cause a 2013. - log.Errorf("Error in the middle of a stream to %s: %v", c, err) - return - } - - // Send the end packet only sendFinished is false (results were streamed). - if !sendFinished { - if err := c.writeEndResult(false); err != nil { - log.Errorf("Error writing result to %s: %v", c, err) - return - } - } - - timings.Record(queryTimingKey, queryStart) - - case ComPing: - // No payload to that one, just return OKPacket. - c.recycleReadPacket() - if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil { - log.Errorf("Error writing ComPing result to %s: %v", c, err) - return - } - case ComSetOption: - if operation, ok := c.parseComSetOption(data); ok { - switch operation { - case 0: - c.Capabilities |= CapabilityClientMultiStatements - case 1: - c.Capabilities &^= CapabilityClientMultiStatements - default: - log.Errorf("Got unhandled packet from client %v, returning error: %v", c.ConnectionID, data) - if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil { - log.Errorf("Error writing error packet to client: %v", err) - return - } - } - if err := c.writeEndResult(false); err != nil { - log.Errorf("Error writeEndResult error %v ", err) - return - } - } else { - log.Errorf("Got unhandled packet from client %v, returning error: %v", c.ConnectionID, data) - if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil { - log.Errorf("Error writing error packet to client: %v", err) - return - } - } - default: - log.Errorf("Got unhandled packet from %s, returning error: %v", c, data) - c.recycleReadPacket() - if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "command handling not implemented yet: %v", data[0]); err != nil { - log.Errorf("Error writing error packet to %s: %s", c, err) - return - } - - } } } -// Close stops the listener, and closes all connections. +// Close stops the listener, which prevents accept of any new connections. Existing connections won't be closed. func (l *Listener) Close() { l.listener.Close() } +// Shutdown closes listener and fails any Ping requests from existing connections. +// This can be used for graceful shutdown, to let clients know that they should reconnect to another server. +func (l *Listener) Shutdown() { + if l.shutdown.CompareAndSwap(false, true) { + l.Close() + } +} + +func (l *Listener) isShutdown() bool { + return l.shutdown.Get() +} + // writeHandshakeV10 writes the Initial Handshake Packet, server side. // It returns the salt data. func (c *Conn) writeHandshakeV10(serverVersion string, authServer AuthServer, enableTLS bool) ([]byte, error) { @@ -537,7 +496,7 @@ func (c *Conn) writeHandshakeV10(serverVersion string, authServer AuthServer, en return nil, fmt.Errorf("error building Handshake packet: got %v bytes expected %v", pos, len(data)) } - if err := c.writeEphemeralPacket(true); err != nil { + if err := c.writeEphemeralPacket(); err != nil { return nil, err } @@ -593,8 +552,7 @@ func (l *Listener) parseClientHandshakePacket(c *Conn, firstTime bool, data []by // Need to switch to TLS, and then re-read the packet. conn := tls.Server(c.conn, l.TLSConfig) c.conn = conn - c.reader.Reset(conn) - c.writer.Reset(conn) + c.bufferedReader.Reset(conn) c.Capabilities |= CapabilityClientSSL return "", "", nil, nil } @@ -689,5 +647,5 @@ func (c *Conn) writeAuthSwitchRequest(pluginName string, pluginData []byte) erro if pos != len(data) { return fmt.Errorf("error building AuthSwitchRequestPacket packet: got %v bytes expected %v", pos, len(data)) } - return c.writeEphemeralPacket(true) + return c.writeEphemeralPacket() } diff --git a/go/mysql/server_test.go b/go/mysql/server_test.go index ee51eeeea2a..7023df61bb0 100644 --- a/go/mysql/server_test.go +++ b/go/mysql/server_test.go @@ -65,7 +65,9 @@ var selectRowsResult = &sqltypes.Result{ type testHandler struct { lastConn *Conn + result *sqltypes.Result err error + warnings uint16 } func (th *testHandler) NewConnection(c *Conn) { @@ -76,6 +78,11 @@ func (th *testHandler) ConnectionClosed(c *Conn) { } func (th *testHandler) ComQuery(c *Conn, query string, callback func(*sqltypes.Result) error) error { + if th.result != nil { + callback(th.result) + return nil + } + switch query { case "error": return th.err @@ -143,11 +150,31 @@ func (th *testHandler) ComQuery(c *Conn, query string, callback func(*sqltypes.R }, }) default: + if strings.HasPrefix(query, benchmarkQueryPrefix) { + callback(&sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "result", + Type: querypb.Type_VARCHAR, + }, + }, + Rows: [][]sqltypes.Value{ + { + sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte(query)), + }, + }, + }) + } + callback(&sqltypes.Result{}) } return nil } +func (th *testHandler) WarningCount(c *Conn) uint16 { + return th.warnings +} + func getHostPort(t *testing.T, a net.Addr) (string, int) { // For the host name, we resolve 'localhost' into an address. // This works around a few travis issues where IPv6 is not 100% enabled. @@ -398,6 +425,83 @@ func TestClientFoundRows(t *testing.T) { c.Close() } +func TestConnCounts(t *testing.T) { + th := &testHandler{} + + initialNumUsers := len(connCountPerUser.Counts()) + + user := "anotherNotYetConnectedUser1" + passwd := "password1" + + authServer := NewAuthServerStatic() + authServer.Entries[user] = []*AuthServerStaticEntry{{ + Password: passwd, + UserData: "userData1", + }} + l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + if err != nil { + t.Fatalf("NewListener failed: %v", err) + } + defer l.Close() + go l.Accept() + + host, port := getHostPort(t, l.Addr()) + + // Test with one new connection. + params := &ConnParams{ + Host: host, + Port: port, + Uname: user, + Pass: passwd, + } + + c, err := Connect(context.Background(), params) + if err != nil { + t.Fatal(err) + } + + connCounts := connCountPerUser.Counts() + if l := len(connCounts); l-initialNumUsers != 1 { + t.Errorf("Expected 1 new user, got %d", l) + } + checkCountsForUser(t, user, 1) + + // Test with a second new connection. + c2, err := Connect(context.Background(), params) + if err != nil { + t.Fatal(err) + } + + connCounts = connCountPerUser.Counts() + // There is still only one new user. + if l2 := len(connCounts); l2-initialNumUsers != 1 { + t.Errorf("Expected 1 new user, got %d", l2) + } + checkCountsForUser(t, user, 2) + + // Test after closing connections. time.Sleep lets it work, but seems flakey. + c.Close() + //time.Sleep(10 * time.Millisecond) + //checkCountsForUser(t, user, 1) + + c2.Close() + //time.Sleep(10 * time.Millisecond) + //checkCountsForUser(t, user, 0) +} + +func checkCountsForUser(t *testing.T, user string, expected int64) { + connCounts := connCountPerUser.Counts() + + userCount, ok := connCounts[user] + if ok { + if userCount != expected { + t.Errorf("Expected connection count for user to be %d, got %d", expected, userCount) + } + } else { + t.Errorf("No count found for user %s", user) + } +} + func TestServer(t *testing.T) { th := &testHandler{} @@ -496,6 +600,23 @@ func TestServer(t *testing.T) { !strings.Contains(output, "2 rows in set") { t.Errorf("Unexpected output for 'select rows'") } + if strings.Contains(output, "warnings") { + t.Errorf("Unexpected warnings in 'select rows'") + } + + // Run a 'select rows' command with warnings + th.warnings = 13 + output, ok = runMysql(t, params, "select rows") + if !ok { + t.Fatalf("mysql failed: %v", output) + } + if !strings.Contains(output, "nice name") || + !strings.Contains(output, "nicer name") || + !strings.Contains(output, "2 rows in set") || + !strings.Contains(output, "13 warnings") { + t.Errorf("Unexpected output for 'select rows': %v", output) + } + th.warnings = 0 // If there's an error after streaming has started, // we should get a 2013 @@ -777,25 +898,37 @@ func TestTLSServer(t *testing.T) { } // Run a 'select rows' command with results. - output, ok := runMysql(t, params, "select rows") - if !ok { - t.Fatalf("mysql failed: %v", output) + conn, err := Connect(context.Background(), params) + //output, ok := runMysql(t, params, "select rows") + if err != nil { + t.Fatalf("mysql failed: %v", err) } - if !strings.Contains(output, "nice name") || - !strings.Contains(output, "nicer name") || - !strings.Contains(output, "2 rows in set") { - t.Errorf("Unexpected output for 'select rows'") + results, err := conn.ExecuteFetch("select rows", 1000, true) + if err != nil { + t.Fatalf("mysql fetch failed: %v", err) + } + output := "" + for _, row := range results.Rows { + r := make([]string, 0) + for _, col := range row { + r = append(r, col.String()) + } + output = output + strings.Join(r, ",") + "\n" + } + + if results.Rows[0][1].ToString() != "nice name" || + results.Rows[1][1].ToString() != "nicer name" || + len(results.Rows) != 2 { + t.Errorf("Unexpected output for 'select rows': %v", output) } // make sure this went through SSL - output, ok = runMysql(t, params, "ssl echo") - if !ok { - t.Fatalf("mysql failed: %v", output) + results, err = conn.ExecuteFetch("ssl echo", 1000, true) + if err != nil { + t.Fatalf("mysql fetch failed: %v", err) } - if !strings.Contains(output, "ssl_flag") || - !strings.Contains(output, "ON") || - !strings.Contains(output, "1 row in set") { - t.Errorf("Unexpected output for 'ssl echo': %v", output) + if results.Rows[0][0].ToString() != "ON" { + t.Errorf("Unexpected output for 'ssl echo': %v", results) } } @@ -982,3 +1115,60 @@ func binaryPath(root, binary string) (string, error) { return "", fmt.Errorf("%s not found in any of %s/{%s}", binary, root, strings.Join(subdirs, ",")) } + +func TestListenerShutdown(t *testing.T) { + th := &testHandler{} + authServer := NewAuthServerStatic() + authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + Password: "password1", + UserData: "userData1", + }} + l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + if err != nil { + t.Fatalf("NewListener failed: %v", err) + } + defer l.Close() + go l.Accept() + + host, port := getHostPort(t, l.Addr()) + + // Setup the right parameters. + params := &ConnParams{ + Host: host, + Port: port, + Uname: "user1", + Pass: "password1", + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := Connect(ctx, params) + if err != nil { + t.Fatalf("Can't connect to listener: %v", err) + } + + if err := conn.Ping(); err != nil { + t.Fatalf("Ping failed: %v", err) + } + + l.Shutdown() + + if err := conn.Ping(); err != nil { + sqlErr, ok := err.(*SQLError) + if !ok { + t.Fatalf("Wrong error type: %T", err) + } + if sqlErr.Number() != ERServerShutdown { + t.Fatalf("Unexpected sql error code: %d", sqlErr.Number()) + } + if sqlErr.SQLState() != SSServerShutdown { + t.Fatalf("Unexpected error sql state: %s", sqlErr.SQLState()) + } + if sqlErr.Message != "Server shutdown in progress" { + t.Fatalf("Unexpected error message: %s", sqlErr.Message) + } + } else { + t.Fatalf("Ping should fail after shutdown") + } +} diff --git a/go/mysql/streaming_query.go b/go/mysql/streaming_query.go index f93ab193b23..c606a20f469 100644 --- a/go/mysql/streaming_query.go +++ b/go/mysql/streaming_query.go @@ -47,7 +47,7 @@ func (c *Conn) ExecuteStreamFetch(query string) (err error) { } // Get the result. - _, _, colNumber, _, err := c.readComQueryResponse() + _, _, colNumber, _, _, err := c.readComQueryResponse() if err != nil { return err } diff --git a/go/sqltypes/arithmetic.go b/go/sqltypes/arithmetic.go index 9b02ec56048..f0f074ef2da 100644 --- a/go/sqltypes/arithmetic.go +++ b/go/sqltypes/arithmetic.go @@ -198,7 +198,7 @@ func ToUint64(v Value) (uint64, error) { panic("unreachable") } -// ToInt64 converts Value to uint64. +// ToInt64 converts Value to int64. func ToInt64(v Value) (int64, error) { num, err := newIntegralNumeric(v) if err != nil { diff --git a/go/sqltypes/value.go b/go/sqltypes/value.go index b788700be81..95f326ee161 100644 --- a/go/sqltypes/value.go +++ b/go/sqltypes/value.go @@ -110,6 +110,11 @@ func NewUint64(v uint64) Value { return MakeTrusted(Uint64, strconv.AppendUint(nil, v, 10)) } +// NewUint32 builds an Uint32 Value. +func NewUint32(v uint32) Value { + return MakeTrusted(Uint32, strconv.AppendUint(nil, uint64(v), 10)) +} + // NewFloat64 builds an Float64 Value. func NewFloat64(v float64) Value { return MakeTrusted(Float64, strconv.AppendFloat(nil, v, 'g', -1, 64)) diff --git a/go/stats/counters.go b/go/stats/counters.go index ebe1149f619..b3bcac4d4b3 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -172,6 +172,11 @@ func (c *CountersWithSingleLabel) Add(name string, value int64) { atomic.AddInt64(a, value) } +// ResetAll clears the counters +func (c *CountersWithSingleLabel) ResetAll() { + c.counters.ResetAll() +} + // CountersWithMultiLabels is a multidimensional counters implementation. // Internally, each tuple of dimensions ("labels") is stored as a single // label value where all label values are joined with ".". diff --git a/go/sync2/atomic.go b/go/sync2/atomic.go index 9ebbfb5e2b6..2c56ccfdd76 100644 --- a/go/sync2/atomic.go +++ b/go/sync2/atomic.go @@ -139,6 +139,18 @@ func (i *AtomicBool) Get() bool { return atomic.LoadInt32(&i.int32) != 0 } +// CompareAndSwap atomatically swaps the old with the new value. +func (i *AtomicBool) CompareAndSwap(o, n bool) bool { + var old, new int32 + if o { + old = 1 + } + if n { + new = 1 + } + return atomic.CompareAndSwapInt32(&i.int32, old, new) +} + // AtomicString gives you atomic-style APIs for string, but // it's only a convenience wrapper that uses a mutex. So, it's // not as efficient as the rest of the atomic types. diff --git a/go/sync2/atomic_test.go b/go/sync2/atomic_test.go index 7809a4d33d7..8547989dcee 100644 --- a/go/sync2/atomic_test.go +++ b/go/sync2/atomic_test.go @@ -56,4 +56,20 @@ func TestAtomicBool(t *testing.T) { if !b.Get() { t.Error("b.Get: false, want true") } + + if b.CompareAndSwap(false, true) { + t.Error("b.CompareAndSwap false, true should fail") + } + if !b.CompareAndSwap(true, false) { + t.Error("b.CompareAndSwap true, false should succeed") + } + if !b.CompareAndSwap(false, false) { + t.Error("b.CompareAndSwap false, false should NOP") + } + if !b.CompareAndSwap(false, true) { + t.Error("b.CompareAndSwap false, true should succeed") + } + if !b.CompareAndSwap(true, true) { + t.Error("b.CompareAndSwap true, true should NOP") + } } diff --git a/go/timer/timer.go b/go/timer/timer.go index b538a31ef33..08076ab48f4 100644 --- a/go/timer/timer.go +++ b/go/timer/timer.go @@ -87,16 +87,20 @@ func (tm *Timer) Start(keephouse func()) { } func (tm *Timer) run(keephouse func()) { + var timer *time.Timer for { var ch <-chan time.Time interval := tm.interval.Get() - if interval <= 0 { - ch = nil - } else { - ch = time.After(interval) + if interval > 0 { + timer = time.NewTimer(interval) + ch = timer.C } select { case action := <-tm.msg: + if timer != nil { + timer.Stop() + timer = nil + } switch action { case timerStop: return diff --git a/go/vt/binlog/binlogplayer/binlog_player.go b/go/vt/binlog/binlogplayer/binlog_player.go index 3e81c95c639..b76fa52f42c 100644 --- a/go/vt/binlog/binlogplayer/binlog_player.go +++ b/go/vt/binlog/binlogplayer/binlog_player.go @@ -29,6 +29,7 @@ import ( "github.com/golang/protobuf/proto" "golang.org/x/net/context" + "vitess.io/vitess/go/history" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" @@ -72,7 +73,7 @@ type Stats struct { lastPosition mysql.Position SecondsBehindMaster sync2.AtomicInt64 - LastMessage sync2.AtomicString + History *history.History } // SetLastPosition sets the last replication position. @@ -89,11 +90,24 @@ func (bps *Stats) LastPosition() mysql.Position { return bps.lastPosition } +// MessageHistory gets all the messages, we store 3 at a time +func (bps *Stats) MessageHistory() []string { + strs := make([]string, 0, 3) + for _, h := range bps.History.Records() { + h1, _ := h.(*StatsHistoryRecord) + if h1 != nil { + strs = append(strs, h1.Message) + } + } + return strs +} + // NewStats creates a new Stats structure. func NewStats() *Stats { bps := &Stats{} bps.Timings = stats.NewTimings("", "", "") bps.Rates = stats.NewRates("", bps.Timings, 15, 60e9) + bps.History = history.New(3) return bps } @@ -156,15 +170,16 @@ func NewBinlogPlayerTables(dbClient DBClient, tablet *topodatapb.Tablet, tables // If an error is encountered, it updates the vreplication state to "Error". // If a stop position was specifed, and reached, the state is updated to "Stopped". func (blp *BinlogPlayer) ApplyBinlogEvents(ctx context.Context) error { - // Clear previous error, if any. if err := setVReplicationState(blp.dbClient, blp.uid, BlpRunning, ""); err != nil { log.Errorf("Error writing Running state: %v", err) } - blp.blplStats.LastMessage.Set("") if err := blp.applyEvents(ctx); err != nil { msg := err.Error() - blp.blplStats.LastMessage.Set(msg) + blp.blplStats.History.Add(&StatsHistoryRecord{ + Time: time.Now(), + Message: msg, + }) if err := setVReplicationState(blp.dbClient, blp.uid, BlpError, msg); err != nil { log.Errorf("Error writing stop state: %v", err) } @@ -531,6 +546,14 @@ func CreateVReplication(workflow string, source *binlogdatapb.BinlogSource, posi encodeString(workflow), encodeString(source.String()), encodeString(position), maxTPS, maxReplicationLag, timeUpdated, BlpRunning) } +// CreateVReplicationStopped returns a statement to create a stopped vreplication. +func CreateVReplicationStopped(workflow string, source *binlogdatapb.BinlogSource, position string) string { + return fmt.Sprintf("insert into _vt.vreplication "+ + "(workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state) "+ + "values (%v, %v, %v, %v, %v, %v, 0, '%v')", + encodeString(workflow), encodeString(source.String()), encodeString(position), throttler.MaxRateModuleDisabled, throttler.ReplicationLagModuleDisabled, time.Now().Unix(), BlpStopped) +} + // updateVReplicationPos returns a statement to update a value in the // _vt.vreplication table. func updateVReplicationPos(uid uint32, pos mysql.Position, timeUpdated int64, txTimestamp int64) string { @@ -582,3 +605,14 @@ func encodeString(in string) string { func ReadVReplicationPos(index uint32) string { return fmt.Sprintf("select pos from _vt.vreplication where id=%v", index) } + +// StatsHistoryRecord is used to store a Message with timestamp +type StatsHistoryRecord struct { + Time time.Time + Message string +} + +// IsDuplicate implements history.Deduplicable +func (r *StatsHistoryRecord) IsDuplicate(other interface{}) bool { + return false +} diff --git a/go/vt/binlog/binlogplayer/fake_dbclient.go b/go/vt/binlog/binlogplayer/fake_dbclient.go index a2f4e091fb9..24bb2a4b043 100644 --- a/go/vt/binlog/binlogplayer/fake_dbclient.go +++ b/go/vt/binlog/binlogplayer/fake_dbclient.go @@ -76,6 +76,8 @@ func (dc *fakeDBClient) ExecuteFetch(query string, maxrows int) (qr *sqltypes.Re ), nil } return &sqltypes.Result{}, nil + case strings.HasPrefix(query, "use"): + return &sqltypes.Result{}, nil } return nil, fmt.Errorf("unexpected: %v", query) } diff --git a/go/vt/concurrency/error_recorder.go b/go/vt/concurrency/error_recorder.go index 6087a55158d..f0a2015cd32 100644 --- a/go/vt/concurrency/error_recorder.go +++ b/go/vt/concurrency/error_recorder.go @@ -135,3 +135,13 @@ func (aer *AllErrorRecorder) ErrorStrings() []string { } return errs } + +// GetErrors returns a reference to the internal errors array. +// +// Note that the array is not copied, so this should only be used +// once the recording is complete. +func (aer *AllErrorRecorder) GetErrors() []error { + aer.mu.Lock() + defer aer.mu.Unlock() + return aer.Errors +} diff --git a/go/vt/mysqlctl/backup.go b/go/vt/mysqlctl/backup.go index 61accab83c0..7120e9f6c7a 100644 --- a/go/vt/mysqlctl/backup.go +++ b/go/vt/mysqlctl/backup.go @@ -173,6 +173,16 @@ func isDbDir(p string) bool { if strings.HasSuffix(fi.Name(), ".frm") { return true } + + // .frm files were removed in MySQL 8, so we need to check for two other file types + // https://dev.mysql.com/doc/refman/8.0/en/data-dictionary-file-removal.html + if strings.HasSuffix(fi.Name(), ".ibd") { + return true + } + // https://dev.mysql.com/doc/refman/8.0/en/serialized-dictionary-information.html + if strings.HasSuffix(fi.Name(), ".sdi") { + return true + } } return false @@ -194,6 +204,26 @@ func addDirectory(fes []FileEntry, base string, baseDir string, subDir string) ( return fes, nil } +// addMySQL8DataDictionary checks to see if the new data dictionary introduced in MySQL 8 exists +// and adds it to the backup manifest if it does +// https://dev.mysql.com/doc/refman/8.0/en/data-dictionary-transactional-storage.html +func addMySQL8DataDictionary(fes []FileEntry, base string, baseDir string) ([]FileEntry, error) { + const dataDictionaryFile = "mysql.ibd" + filePath := path.Join(baseDir, dataDictionaryFile) + + // no-op if this file doesn't exist + if _, err := os.Stat(filePath); os.IsNotExist(err) { + return fes, nil + } + + fes = append(fes, FileEntry{ + Base: base, + Name: dataDictionaryFile, + }) + + return fes, nil +} + func findFilesToBackup(cnf *Mycnf) ([]FileEntry, error) { var err error var result []FileEntry @@ -208,6 +238,12 @@ func findFilesToBackup(cnf *Mycnf) ([]FileEntry, error) { return nil, err } + // then add the transactional data dictionary if it exists + result, err = addMySQL8DataDictionary(result, backupData, cnf.DataDir) + if err != nil { + return nil, err + } + // then add DB directories fis, err := ioutil.ReadDir(cnf.DataDir) if err != nil { diff --git a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go index 2f78d173d39..a7d945f06b6 100644 --- a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go @@ -28,6 +28,7 @@ import ( "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/sync2" "vitess.io/vitess/go/vt/dbconnpool" "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/mysqlctl/tmutils" @@ -125,7 +126,7 @@ type FakeMysqlDaemon struct { FetchSuperQueryMap map[string]*sqltypes.Result // BinlogPlayerEnabled is used by {Enable,Disable}BinlogPlayer - BinlogPlayerEnabled bool + BinlogPlayerEnabled sync2.AtomicBool // SemiSyncMasterEnabled represents the state of rpl_semi_sync_master_enabled. SemiSyncMasterEnabled bool @@ -345,13 +346,13 @@ func (fmd *FakeMysqlDaemon) FetchSuperQuery(ctx context.Context, query string) ( // EnableBinlogPlayback is part of the MysqlDaemon interface func (fmd *FakeMysqlDaemon) EnableBinlogPlayback() error { - fmd.BinlogPlayerEnabled = true + fmd.BinlogPlayerEnabled.Set(true) return nil } // DisableBinlogPlayback disable playback of binlog events func (fmd *FakeMysqlDaemon) DisableBinlogPlayback() error { - fmd.BinlogPlayerEnabled = false + fmd.BinlogPlayerEnabled.Set(false) return nil } diff --git a/go/vt/mysqlctl/mysqld.go b/go/vt/mysqlctl/mysqld.go index 46c2acf6fe1..c754d0cafd7 100644 --- a/go/vt/mysqlctl/mysqld.go +++ b/go/vt/mysqlctl/mysqld.go @@ -611,6 +611,15 @@ func (mysqld *Mysqld) initConfig(root string, cnf *Mycnf, outFile string) error return ioutil.WriteFile(outFile, []byte(configData), 0664) } +func contains(haystack []string, needle string) bool { + for _, v := range haystack { + if v == needle { + return true + } + } + return false +} + func getMycnfTemplates(root string) []string { if *mycnfTemplateFile != "" { return []string{*mycnfTemplateFile} @@ -627,6 +636,25 @@ func getMycnfTemplates(root string) []string { cnfTemplatePaths = append(cnfTemplatePaths, parts...) } + switch mysqlFlavor := os.Getenv("MYSQL_FLAVOR"); mysqlFlavor { + case "MariaDB": + path := path.Join(root, "config/mycnf/master_mariadb.cnf") + if !contains(cnfTemplatePaths, path) { + cnfTemplatePaths = append(cnfTemplatePaths, path) + } + case "MariaDB103": + path := path.Join(root, "config/mycnf/master_mariadb103.cnf") + if !contains(cnfTemplatePaths, path) { + cnfTemplatePaths = append(cnfTemplatePaths, path) + } + default: + path := path.Join(root, "config/mycnf/master_mysql56.cnf") + // By default we assume Mysql56 compatable + if !contains(cnfTemplatePaths, path) { + cnfTemplatePaths = append(cnfTemplatePaths, path) + } + } + return cnfTemplatePaths } diff --git a/go/vt/mysqlctl/s3backupstorage/README.txt b/go/vt/mysqlctl/s3backupstorage/README.txt new file mode 100644 index 00000000000..52b58f89bfe --- /dev/null +++ b/go/vt/mysqlctl/s3backupstorage/README.txt @@ -0,0 +1,17 @@ +Recently added options to enable usage of an S3 appliance: Cloudian +HyperStore: + -s3_backup_aws_endpoint (port is required) + -s3_backup_force_path_style=true/false + -s3_backup_log_level can be one of: LogOff, LogDebug, LogDebugWithSigning, LogDebugWithHTTPBody, LogDebugWithRequestRetries, LogDebugWithRequestErrors. Default: LogOff + +By default the s3 client will try to connect to +..amazonaws.com. Adjusting the endpoint will allow this +to be changed. + +Given the way the FQDN is configured the TLS certificate may not match the +server's "base" (.) due to the leading +so setting -s3_backup_force_path_style=true will force the s3 client to +connect to . and then make a request using the full +path within the http calls. + +-s3backup_log_level enables more verbose logging of the S3 calls. diff --git a/go/vt/mysqlctl/s3backupstorage/s3.go b/go/vt/mysqlctl/s3backupstorage/s3.go index 2ccae58bd0d..fe63c6c5191 100644 --- a/go/vt/mysqlctl/s3backupstorage/s3.go +++ b/go/vt/mysqlctl/s3backupstorage/s3.go @@ -24,14 +24,18 @@ limitations under the License. package s3backupstorage import ( + "crypto/tls" "flag" "fmt" "io" "math" + "net/http" "sort" "strings" "sync" + "vitess.io/vitess/go/vt/log" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" @@ -46,12 +50,23 @@ var ( // AWS API region region = flag.String("s3_backup_aws_region", "us-east-1", "AWS region to use") + // AWS endpoint, defaults to amazonaws.com but appliances may use a different location + endpoint = flag.String("s3_backup_aws_endpoint", "amazonaws.com", "endpoint of the S3 backend (region must be provided)") + // bucket is where the backups will go. bucket = flag.String("s3_backup_storage_bucket", "", "S3 bucket to use for backups") // root is a prefix added to all object names. root = flag.String("s3_backup_storage_root", "", "root prefix for all backup-related object names") + // forcePath is used to ensure that the certificate and path used match the endpoint + region + forcePath = flag.Bool("s3_backup_force_path_style", false, "force the s3 path style") + + tlsSkipVerifyCert = flag.Bool("s3_backup_tls_skip_verify_cert", false, "skip the 'certificate is valid' check for SSL connections") + + // verboseLogging provides more verbose logging of AWS actions + requiredLogLevel = flag.String("s3_backup_log_level", "LogOff", "determine the S3 loglevel to use from LogOff, LogDebug, LogDebugWithSigning, LogDebugWithHTTPBody, LogDebugWithRequestRetries, LogDebugWithRequestErrors") + // sse is the server-side encryption algorithm used when storing this object in S3 sse = flag.String("s3_backup_server_side_encryption", "", "server-side encryption algorithm (e.g., AES256, aws:kms)") @@ -59,6 +74,10 @@ var ( delimiter = "/" ) +type logNameToLogLevel map[string]aws.LogLevelType + +var logNameMap logNameToLogLevel + // S3BackupHandle implements the backupstorage.BackupHandle interface. type S3BackupHandle struct { client *s3.S3 @@ -169,6 +188,7 @@ type S3BackupStorage struct { // ListBackups is part of the backupstorage.BackupStorage interface. func (bs *S3BackupStorage) ListBackups(ctx context.Context, dir string) ([]backupstorage.BackupHandle, error) { + log.Infof("ListBackups: [s3] dir: %v, bucket: %v", dir, *bucket) c, err := bs.client() if err != nil { return nil, err @@ -217,6 +237,7 @@ func (bs *S3BackupStorage) ListBackups(ctx context.Context, dir string) ([]backu // StartBackup is part of the backupstorage.BackupStorage interface. func (bs *S3BackupStorage) StartBackup(ctx context.Context, dir, name string) (backupstorage.BackupHandle, error) { + log.Infof("StartBackup: [s3] dir: %v, name: %v, bucket: %v", dir, name, *bucket) c, err := bs.client() if err != nil { return nil, err @@ -233,6 +254,8 @@ func (bs *S3BackupStorage) StartBackup(ctx context.Context, dir, name string) (b // RemoveBackup is part of the backupstorage.BackupStorage interface. func (bs *S3BackupStorage) RemoveBackup(ctx context.Context, dir, name string) error { + log.Infof("RemoveBackup: [s3] dir: %v, name: %v, bucket: %v", dir, name, *bucket) + c, err := bs.client() if err != nil { return err @@ -293,11 +316,34 @@ func (bs *S3BackupStorage) Close() error { var _ backupstorage.BackupStorage = (*S3BackupStorage)(nil) +// getLogLevel converts the string loglevel to an aws.LogLevelType +func getLogLevel() *aws.LogLevelType { + l := new(aws.LogLevelType) + *l = aws.LogOff // default setting + if level, found := logNameMap[*requiredLogLevel]; found { + *l = level // adjust as required + } + return l +} + func (bs *S3BackupStorage) client() (*s3.S3, error) { bs.mu.Lock() defer bs.mu.Unlock() if bs._client == nil { - bs._client = s3.New(session.New(), &aws.Config{Region: aws.String(*region)}) + logLevel := getLogLevel() + + tlsClientConf := &tls.Config{InsecureSkipVerify: *tlsSkipVerifyCert} + httpTransport := &http.Transport{TLSClientConfig: tlsClientConf} + httpClient := &http.Client{Transport: httpTransport} + + bs._client = s3.New(session.New(), + &aws.Config{ + HTTPClient: httpClient, + LogLevel: logLevel, + Endpoint: aws.String(*endpoint), + Region: aws.String(*region), + S3ForcePathStyle: aws.Bool(*forcePath), + }) if len(*bucket) == 0 { return nil, fmt.Errorf("-s3_backup_storage_bucket required") @@ -321,4 +367,13 @@ func objName(parts ...string) *string { func init() { backupstorage.BackupStorageMap["s3"] = &S3BackupStorage{} + + logNameMap = logNameToLogLevel{ + "LogOff": aws.LogOff, + "LogDebug": aws.LogDebug, + "LogDebugWithSigning": aws.LogDebugWithSigning, + "LogDebugWithHTTPBody": aws.LogDebugWithHTTPBody, + "LogDebugWithRequestRetries": aws.LogDebugWithRequestRetries, + "LogDebugWithRequestErrors": aws.LogDebugWithRequestErrors, + } } diff --git a/go/vt/proto/query/query.pb.go b/go/vt/proto/query/query.pb.go index 98f8a7ac9f7..8df47083a92 100644 --- a/go/vt/proto/query/query.pb.go +++ b/go/vt/proto/query/query.pb.go @@ -95,7 +95,7 @@ func (x MySqlFlag) String() string { return proto.EnumName(MySqlFlag_name, int32(x)) } func (MySqlFlag) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{0} + return fileDescriptor_query_9111254583ad7475, []int{0} } // Flag allows us to qualify types by their common properties. @@ -134,7 +134,7 @@ func (x Flag) String() string { return proto.EnumName(Flag_name, int32(x)) } func (Flag) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{1} + return fileDescriptor_query_9111254583ad7475, []int{1} } // Type defines the various supported data types in bind vars @@ -315,7 +315,7 @@ func (x Type) String() string { return proto.EnumName(Type_name, int32(x)) } func (Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{2} + return fileDescriptor_query_9111254583ad7475, []int{2} } // TransactionState represents the state of a distributed transaction. @@ -345,7 +345,7 @@ func (x TransactionState) String() string { return proto.EnumName(TransactionState_name, int32(x)) } func (TransactionState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{3} + return fileDescriptor_query_9111254583ad7475, []int{3} } type ExecuteOptions_IncludedFields int32 @@ -371,7 +371,7 @@ func (x ExecuteOptions_IncludedFields) String() string { return proto.EnumName(ExecuteOptions_IncludedFields_name, int32(x)) } func (ExecuteOptions_IncludedFields) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{6, 0} + return fileDescriptor_query_9111254583ad7475, []int{6, 0} } type ExecuteOptions_Workload int32 @@ -400,7 +400,7 @@ func (x ExecuteOptions_Workload) String() string { return proto.EnumName(ExecuteOptions_Workload_name, int32(x)) } func (ExecuteOptions_Workload) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{6, 1} + return fileDescriptor_query_9111254583ad7475, []int{6, 1} } type ExecuteOptions_TransactionIsolation int32 @@ -432,7 +432,7 @@ func (x ExecuteOptions_TransactionIsolation) String() string { return proto.EnumName(ExecuteOptions_TransactionIsolation_name, int32(x)) } func (ExecuteOptions_TransactionIsolation) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{6, 2} + return fileDescriptor_query_9111254583ad7475, []int{6, 2} } // The category of one statement. @@ -459,7 +459,7 @@ func (x StreamEvent_Statement_Category) String() string { return proto.EnumName(StreamEvent_Statement_Category_name, int32(x)) } func (StreamEvent_Statement_Category) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{11, 0, 0} + return fileDescriptor_query_9111254583ad7475, []int{12, 0, 0} } type SplitQueryRequest_Algorithm int32 @@ -482,7 +482,7 @@ func (x SplitQueryRequest_Algorithm) String() string { return proto.EnumName(SplitQueryRequest_Algorithm_name, int32(x)) } func (SplitQueryRequest_Algorithm) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{49, 0} + return fileDescriptor_query_9111254583ad7475, []int{50, 0} } // Target describes what the client expects the tablet is. @@ -503,7 +503,7 @@ func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} func (*Target) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{0} + return fileDescriptor_query_9111254583ad7475, []int{0} } func (m *Target) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Target.Unmarshal(m, b) @@ -571,7 +571,7 @@ func (m *VTGateCallerID) Reset() { *m = VTGateCallerID{} } func (m *VTGateCallerID) String() string { return proto.CompactTextString(m) } func (*VTGateCallerID) ProtoMessage() {} func (*VTGateCallerID) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{1} + return fileDescriptor_query_9111254583ad7475, []int{1} } func (m *VTGateCallerID) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VTGateCallerID.Unmarshal(m, b) @@ -627,7 +627,7 @@ func (m *EventToken) Reset() { *m = EventToken{} } func (m *EventToken) String() string { return proto.CompactTextString(m) } func (*EventToken) ProtoMessage() {} func (*EventToken) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{2} + return fileDescriptor_query_9111254583ad7475, []int{2} } func (m *EventToken) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_EventToken.Unmarshal(m, b) @@ -681,7 +681,7 @@ func (m *Value) Reset() { *m = Value{} } func (m *Value) String() string { return proto.CompactTextString(m) } func (*Value) ProtoMessage() {} func (*Value) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{3} + return fileDescriptor_query_9111254583ad7475, []int{3} } func (m *Value) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Value.Unmarshal(m, b) @@ -730,7 +730,7 @@ func (m *BindVariable) Reset() { *m = BindVariable{} } func (m *BindVariable) String() string { return proto.CompactTextString(m) } func (*BindVariable) ProtoMessage() {} func (*BindVariable) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{4} + return fileDescriptor_query_9111254583ad7475, []int{4} } func (m *BindVariable) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BindVariable.Unmarshal(m, b) @@ -787,7 +787,7 @@ func (m *BoundQuery) Reset() { *m = BoundQuery{} } func (m *BoundQuery) String() string { return proto.CompactTextString(m) } func (*BoundQuery) ProtoMessage() {} func (*BoundQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{5} + return fileDescriptor_query_9111254583ad7475, []int{5} } func (m *BoundQuery) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BoundQuery.Unmarshal(m, b) @@ -861,7 +861,7 @@ func (m *ExecuteOptions) Reset() { *m = ExecuteOptions{} } func (m *ExecuteOptions) String() string { return proto.CompactTextString(m) } func (*ExecuteOptions) ProtoMessage() {} func (*ExecuteOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{6} + return fileDescriptor_query_9111254583ad7475, []int{6} } func (m *ExecuteOptions) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteOptions.Unmarshal(m, b) @@ -967,7 +967,7 @@ func (m *Field) Reset() { *m = Field{} } func (m *Field) String() string { return proto.CompactTextString(m) } func (*Field) ProtoMessage() {} func (*Field) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{7} + return fileDescriptor_query_9111254583ad7475, []int{7} } func (m *Field) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Field.Unmarshal(m, b) @@ -1075,7 +1075,7 @@ func (m *Row) Reset() { *m = Row{} } func (m *Row) String() string { return proto.CompactTextString(m) } func (*Row) ProtoMessage() {} func (*Row) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{8} + return fileDescriptor_query_9111254583ad7475, []int{8} } func (m *Row) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Row.Unmarshal(m, b) @@ -1127,7 +1127,7 @@ func (m *ResultExtras) Reset() { *m = ResultExtras{} } func (m *ResultExtras) String() string { return proto.CompactTextString(m) } func (*ResultExtras) ProtoMessage() {} func (*ResultExtras) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{9} + return fileDescriptor_query_9111254583ad7475, []int{9} } func (m *ResultExtras) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ResultExtras.Unmarshal(m, b) @@ -1185,7 +1185,7 @@ func (m *QueryResult) Reset() { *m = QueryResult{} } func (m *QueryResult) String() string { return proto.CompactTextString(m) } func (*QueryResult) ProtoMessage() {} func (*QueryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{10} + return fileDescriptor_query_9111254583ad7475, []int{10} } func (m *QueryResult) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryResult.Unmarshal(m, b) @@ -1240,6 +1240,54 @@ func (m *QueryResult) GetExtras() *ResultExtras { return nil } +// QueryWarning is used to convey out of band query execution warnings +// by storing in the vtgate.Session +type QueryWarning struct { + Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *QueryWarning) Reset() { *m = QueryWarning{} } +func (m *QueryWarning) String() string { return proto.CompactTextString(m) } +func (*QueryWarning) ProtoMessage() {} +func (*QueryWarning) Descriptor() ([]byte, []int) { + return fileDescriptor_query_9111254583ad7475, []int{11} +} +func (m *QueryWarning) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_QueryWarning.Unmarshal(m, b) +} +func (m *QueryWarning) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_QueryWarning.Marshal(b, m, deterministic) +} +func (dst *QueryWarning) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryWarning.Merge(dst, src) +} +func (m *QueryWarning) XXX_Size() int { + return xxx_messageInfo_QueryWarning.Size(m) +} +func (m *QueryWarning) XXX_DiscardUnknown() { + xxx_messageInfo_QueryWarning.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryWarning proto.InternalMessageInfo + +func (m *QueryWarning) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *QueryWarning) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + // StreamEvent describes a set of transformations that happened as a // single transactional unit on a server. It is streamed back by the // Update Stream calls. @@ -1257,7 +1305,7 @@ func (m *StreamEvent) Reset() { *m = StreamEvent{} } func (m *StreamEvent) String() string { return proto.CompactTextString(m) } func (*StreamEvent) ProtoMessage() {} func (*StreamEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{11} + return fileDescriptor_query_9111254583ad7475, []int{12} } func (m *StreamEvent) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamEvent.Unmarshal(m, b) @@ -1310,7 +1358,7 @@ func (m *StreamEvent_Statement) Reset() { *m = StreamEvent_Statement{} } func (m *StreamEvent_Statement) String() string { return proto.CompactTextString(m) } func (*StreamEvent_Statement) ProtoMessage() {} func (*StreamEvent_Statement) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{11, 0} + return fileDescriptor_query_9111254583ad7475, []int{12, 0} } func (m *StreamEvent_Statement) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamEvent_Statement.Unmarshal(m, b) @@ -1382,7 +1430,7 @@ func (m *ExecuteRequest) Reset() { *m = ExecuteRequest{} } func (m *ExecuteRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteRequest) ProtoMessage() {} func (*ExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{12} + return fileDescriptor_query_9111254583ad7475, []int{13} } func (m *ExecuteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteRequest.Unmarshal(m, b) @@ -1456,7 +1504,7 @@ func (m *ExecuteResponse) Reset() { *m = ExecuteResponse{} } func (m *ExecuteResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteResponse) ProtoMessage() {} func (*ExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{13} + return fileDescriptor_query_9111254583ad7475, []int{14} } func (m *ExecuteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteResponse.Unmarshal(m, b) @@ -1500,7 +1548,7 @@ func (m *ResultWithError) Reset() { *m = ResultWithError{} } func (m *ResultWithError) String() string { return proto.CompactTextString(m) } func (*ResultWithError) ProtoMessage() {} func (*ResultWithError) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{14} + return fileDescriptor_query_9111254583ad7475, []int{15} } func (m *ResultWithError) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ResultWithError.Unmarshal(m, b) @@ -1552,7 +1600,7 @@ func (m *ExecuteBatchRequest) Reset() { *m = ExecuteBatchRequest{} } func (m *ExecuteBatchRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchRequest) ProtoMessage() {} func (*ExecuteBatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{15} + return fileDescriptor_query_9111254583ad7475, []int{16} } func (m *ExecuteBatchRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchRequest.Unmarshal(m, b) @@ -1633,7 +1681,7 @@ func (m *ExecuteBatchResponse) Reset() { *m = ExecuteBatchResponse{} } func (m *ExecuteBatchResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchResponse) ProtoMessage() {} func (*ExecuteBatchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{16} + return fileDescriptor_query_9111254583ad7475, []int{17} } func (m *ExecuteBatchResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchResponse.Unmarshal(m, b) @@ -1676,7 +1724,7 @@ func (m *StreamExecuteRequest) Reset() { *m = StreamExecuteRequest{} } func (m *StreamExecuteRequest) String() string { return proto.CompactTextString(m) } func (*StreamExecuteRequest) ProtoMessage() {} func (*StreamExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{17} + return fileDescriptor_query_9111254583ad7475, []int{18} } func (m *StreamExecuteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteRequest.Unmarshal(m, b) @@ -1743,7 +1791,7 @@ func (m *StreamExecuteResponse) Reset() { *m = StreamExecuteResponse{} } func (m *StreamExecuteResponse) String() string { return proto.CompactTextString(m) } func (*StreamExecuteResponse) ProtoMessage() {} func (*StreamExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{18} + return fileDescriptor_query_9111254583ad7475, []int{19} } func (m *StreamExecuteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteResponse.Unmarshal(m, b) @@ -1785,7 +1833,7 @@ func (m *BeginRequest) Reset() { *m = BeginRequest{} } func (m *BeginRequest) String() string { return proto.CompactTextString(m) } func (*BeginRequest) ProtoMessage() {} func (*BeginRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{19} + return fileDescriptor_query_9111254583ad7475, []int{20} } func (m *BeginRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginRequest.Unmarshal(m, b) @@ -1845,7 +1893,7 @@ func (m *BeginResponse) Reset() { *m = BeginResponse{} } func (m *BeginResponse) String() string { return proto.CompactTextString(m) } func (*BeginResponse) ProtoMessage() {} func (*BeginResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{20} + return fileDescriptor_query_9111254583ad7475, []int{21} } func (m *BeginResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginResponse.Unmarshal(m, b) @@ -1887,7 +1935,7 @@ func (m *CommitRequest) Reset() { *m = CommitRequest{} } func (m *CommitRequest) String() string { return proto.CompactTextString(m) } func (*CommitRequest) ProtoMessage() {} func (*CommitRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{21} + return fileDescriptor_query_9111254583ad7475, []int{22} } func (m *CommitRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitRequest.Unmarshal(m, b) @@ -1946,7 +1994,7 @@ func (m *CommitResponse) Reset() { *m = CommitResponse{} } func (m *CommitResponse) String() string { return proto.CompactTextString(m) } func (*CommitResponse) ProtoMessage() {} func (*CommitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{22} + return fileDescriptor_query_9111254583ad7475, []int{23} } func (m *CommitResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitResponse.Unmarshal(m, b) @@ -1981,7 +2029,7 @@ func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } func (*RollbackRequest) ProtoMessage() {} func (*RollbackRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{23} + return fileDescriptor_query_9111254583ad7475, []int{24} } func (m *RollbackRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackRequest.Unmarshal(m, b) @@ -2040,7 +2088,7 @@ func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } func (*RollbackResponse) ProtoMessage() {} func (*RollbackResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{24} + return fileDescriptor_query_9111254583ad7475, []int{25} } func (m *RollbackResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackResponse.Unmarshal(m, b) @@ -2076,7 +2124,7 @@ func (m *PrepareRequest) Reset() { *m = PrepareRequest{} } func (m *PrepareRequest) String() string { return proto.CompactTextString(m) } func (*PrepareRequest) ProtoMessage() {} func (*PrepareRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{25} + return fileDescriptor_query_9111254583ad7475, []int{26} } func (m *PrepareRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PrepareRequest.Unmarshal(m, b) @@ -2142,7 +2190,7 @@ func (m *PrepareResponse) Reset() { *m = PrepareResponse{} } func (m *PrepareResponse) String() string { return proto.CompactTextString(m) } func (*PrepareResponse) ProtoMessage() {} func (*PrepareResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{26} + return fileDescriptor_query_9111254583ad7475, []int{27} } func (m *PrepareResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PrepareResponse.Unmarshal(m, b) @@ -2177,7 +2225,7 @@ func (m *CommitPreparedRequest) Reset() { *m = CommitPreparedRequest{} } func (m *CommitPreparedRequest) String() string { return proto.CompactTextString(m) } func (*CommitPreparedRequest) ProtoMessage() {} func (*CommitPreparedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{27} + return fileDescriptor_query_9111254583ad7475, []int{28} } func (m *CommitPreparedRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitPreparedRequest.Unmarshal(m, b) @@ -2236,7 +2284,7 @@ func (m *CommitPreparedResponse) Reset() { *m = CommitPreparedResponse{} func (m *CommitPreparedResponse) String() string { return proto.CompactTextString(m) } func (*CommitPreparedResponse) ProtoMessage() {} func (*CommitPreparedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{28} + return fileDescriptor_query_9111254583ad7475, []int{29} } func (m *CommitPreparedResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitPreparedResponse.Unmarshal(m, b) @@ -2272,7 +2320,7 @@ func (m *RollbackPreparedRequest) Reset() { *m = RollbackPreparedRequest func (m *RollbackPreparedRequest) String() string { return proto.CompactTextString(m) } func (*RollbackPreparedRequest) ProtoMessage() {} func (*RollbackPreparedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{29} + return fileDescriptor_query_9111254583ad7475, []int{30} } func (m *RollbackPreparedRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackPreparedRequest.Unmarshal(m, b) @@ -2338,7 +2386,7 @@ func (m *RollbackPreparedResponse) Reset() { *m = RollbackPreparedRespon func (m *RollbackPreparedResponse) String() string { return proto.CompactTextString(m) } func (*RollbackPreparedResponse) ProtoMessage() {} func (*RollbackPreparedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{30} + return fileDescriptor_query_9111254583ad7475, []int{31} } func (m *RollbackPreparedResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackPreparedResponse.Unmarshal(m, b) @@ -2374,7 +2422,7 @@ func (m *CreateTransactionRequest) Reset() { *m = CreateTransactionReque func (m *CreateTransactionRequest) String() string { return proto.CompactTextString(m) } func (*CreateTransactionRequest) ProtoMessage() {} func (*CreateTransactionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{31} + return fileDescriptor_query_9111254583ad7475, []int{32} } func (m *CreateTransactionRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CreateTransactionRequest.Unmarshal(m, b) @@ -2440,7 +2488,7 @@ func (m *CreateTransactionResponse) Reset() { *m = CreateTransactionResp func (m *CreateTransactionResponse) String() string { return proto.CompactTextString(m) } func (*CreateTransactionResponse) ProtoMessage() {} func (*CreateTransactionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{32} + return fileDescriptor_query_9111254583ad7475, []int{33} } func (m *CreateTransactionResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CreateTransactionResponse.Unmarshal(m, b) @@ -2476,7 +2524,7 @@ func (m *StartCommitRequest) Reset() { *m = StartCommitRequest{} } func (m *StartCommitRequest) String() string { return proto.CompactTextString(m) } func (*StartCommitRequest) ProtoMessage() {} func (*StartCommitRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{33} + return fileDescriptor_query_9111254583ad7475, []int{34} } func (m *StartCommitRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StartCommitRequest.Unmarshal(m, b) @@ -2542,7 +2590,7 @@ func (m *StartCommitResponse) Reset() { *m = StartCommitResponse{} } func (m *StartCommitResponse) String() string { return proto.CompactTextString(m) } func (*StartCommitResponse) ProtoMessage() {} func (*StartCommitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{34} + return fileDescriptor_query_9111254583ad7475, []int{35} } func (m *StartCommitResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StartCommitResponse.Unmarshal(m, b) @@ -2578,7 +2626,7 @@ func (m *SetRollbackRequest) Reset() { *m = SetRollbackRequest{} } func (m *SetRollbackRequest) String() string { return proto.CompactTextString(m) } func (*SetRollbackRequest) ProtoMessage() {} func (*SetRollbackRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{35} + return fileDescriptor_query_9111254583ad7475, []int{36} } func (m *SetRollbackRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SetRollbackRequest.Unmarshal(m, b) @@ -2644,7 +2692,7 @@ func (m *SetRollbackResponse) Reset() { *m = SetRollbackResponse{} } func (m *SetRollbackResponse) String() string { return proto.CompactTextString(m) } func (*SetRollbackResponse) ProtoMessage() {} func (*SetRollbackResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{36} + return fileDescriptor_query_9111254583ad7475, []int{37} } func (m *SetRollbackResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SetRollbackResponse.Unmarshal(m, b) @@ -2679,7 +2727,7 @@ func (m *ConcludeTransactionRequest) Reset() { *m = ConcludeTransactionR func (m *ConcludeTransactionRequest) String() string { return proto.CompactTextString(m) } func (*ConcludeTransactionRequest) ProtoMessage() {} func (*ConcludeTransactionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{37} + return fileDescriptor_query_9111254583ad7475, []int{38} } func (m *ConcludeTransactionRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConcludeTransactionRequest.Unmarshal(m, b) @@ -2738,7 +2786,7 @@ func (m *ConcludeTransactionResponse) Reset() { *m = ConcludeTransaction func (m *ConcludeTransactionResponse) String() string { return proto.CompactTextString(m) } func (*ConcludeTransactionResponse) ProtoMessage() {} func (*ConcludeTransactionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{38} + return fileDescriptor_query_9111254583ad7475, []int{39} } func (m *ConcludeTransactionResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConcludeTransactionResponse.Unmarshal(m, b) @@ -2773,7 +2821,7 @@ func (m *ReadTransactionRequest) Reset() { *m = ReadTransactionRequest{} func (m *ReadTransactionRequest) String() string { return proto.CompactTextString(m) } func (*ReadTransactionRequest) ProtoMessage() {} func (*ReadTransactionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{39} + return fileDescriptor_query_9111254583ad7475, []int{40} } func (m *ReadTransactionRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ReadTransactionRequest.Unmarshal(m, b) @@ -2833,7 +2881,7 @@ func (m *ReadTransactionResponse) Reset() { *m = ReadTransactionResponse func (m *ReadTransactionResponse) String() string { return proto.CompactTextString(m) } func (*ReadTransactionResponse) ProtoMessage() {} func (*ReadTransactionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{40} + return fileDescriptor_query_9111254583ad7475, []int{41} } func (m *ReadTransactionResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ReadTransactionResponse.Unmarshal(m, b) @@ -2876,7 +2924,7 @@ func (m *BeginExecuteRequest) Reset() { *m = BeginExecuteRequest{} } func (m *BeginExecuteRequest) String() string { return proto.CompactTextString(m) } func (*BeginExecuteRequest) ProtoMessage() {} func (*BeginExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{41} + return fileDescriptor_query_9111254583ad7475, []int{42} } func (m *BeginExecuteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginExecuteRequest.Unmarshal(m, b) @@ -2949,7 +2997,7 @@ func (m *BeginExecuteResponse) Reset() { *m = BeginExecuteResponse{} } func (m *BeginExecuteResponse) String() string { return proto.CompactTextString(m) } func (*BeginExecuteResponse) ProtoMessage() {} func (*BeginExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{42} + return fileDescriptor_query_9111254583ad7475, []int{43} } func (m *BeginExecuteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginExecuteResponse.Unmarshal(m, b) @@ -3007,7 +3055,7 @@ func (m *BeginExecuteBatchRequest) Reset() { *m = BeginExecuteBatchReque func (m *BeginExecuteBatchRequest) String() string { return proto.CompactTextString(m) } func (*BeginExecuteBatchRequest) ProtoMessage() {} func (*BeginExecuteBatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{43} + return fileDescriptor_query_9111254583ad7475, []int{44} } func (m *BeginExecuteBatchRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginExecuteBatchRequest.Unmarshal(m, b) @@ -3087,7 +3135,7 @@ func (m *BeginExecuteBatchResponse) Reset() { *m = BeginExecuteBatchResp func (m *BeginExecuteBatchResponse) String() string { return proto.CompactTextString(m) } func (*BeginExecuteBatchResponse) ProtoMessage() {} func (*BeginExecuteBatchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{44} + return fileDescriptor_query_9111254583ad7475, []int{45} } func (m *BeginExecuteBatchResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginExecuteBatchResponse.Unmarshal(m, b) @@ -3144,7 +3192,7 @@ func (m *MessageStreamRequest) Reset() { *m = MessageStreamRequest{} } func (m *MessageStreamRequest) String() string { return proto.CompactTextString(m) } func (*MessageStreamRequest) ProtoMessage() {} func (*MessageStreamRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{45} + return fileDescriptor_query_9111254583ad7475, []int{46} } func (m *MessageStreamRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageStreamRequest.Unmarshal(m, b) @@ -3204,7 +3252,7 @@ func (m *MessageStreamResponse) Reset() { *m = MessageStreamResponse{} } func (m *MessageStreamResponse) String() string { return proto.CompactTextString(m) } func (*MessageStreamResponse) ProtoMessage() {} func (*MessageStreamResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{46} + return fileDescriptor_query_9111254583ad7475, []int{47} } func (m *MessageStreamResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageStreamResponse.Unmarshal(m, b) @@ -3248,7 +3296,7 @@ func (m *MessageAckRequest) Reset() { *m = MessageAckRequest{} } func (m *MessageAckRequest) String() string { return proto.CompactTextString(m) } func (*MessageAckRequest) ProtoMessage() {} func (*MessageAckRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{47} + return fileDescriptor_query_9111254583ad7475, []int{48} } func (m *MessageAckRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageAckRequest.Unmarshal(m, b) @@ -3318,7 +3366,7 @@ func (m *MessageAckResponse) Reset() { *m = MessageAckResponse{} } func (m *MessageAckResponse) String() string { return proto.CompactTextString(m) } func (*MessageAckResponse) ProtoMessage() {} func (*MessageAckResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{48} + return fileDescriptor_query_9111254583ad7475, []int{49} } func (m *MessageAckResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageAckResponse.Unmarshal(m, b) @@ -3366,7 +3414,7 @@ func (m *SplitQueryRequest) Reset() { *m = SplitQueryRequest{} } func (m *SplitQueryRequest) String() string { return proto.CompactTextString(m) } func (*SplitQueryRequest) ProtoMessage() {} func (*SplitQueryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{49} + return fileDescriptor_query_9111254583ad7475, []int{50} } func (m *SplitQueryRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryRequest.Unmarshal(m, b) @@ -3457,7 +3505,7 @@ func (m *QuerySplit) Reset() { *m = QuerySplit{} } func (m *QuerySplit) String() string { return proto.CompactTextString(m) } func (*QuerySplit) ProtoMessage() {} func (*QuerySplit) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{50} + return fileDescriptor_query_9111254583ad7475, []int{51} } func (m *QuerySplit) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QuerySplit.Unmarshal(m, b) @@ -3504,7 +3552,7 @@ func (m *SplitQueryResponse) Reset() { *m = SplitQueryResponse{} } func (m *SplitQueryResponse) String() string { return proto.CompactTextString(m) } func (*SplitQueryResponse) ProtoMessage() {} func (*SplitQueryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{51} + return fileDescriptor_query_9111254583ad7475, []int{52} } func (m *SplitQueryResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryResponse.Unmarshal(m, b) @@ -3542,7 +3590,7 @@ func (m *StreamHealthRequest) Reset() { *m = StreamHealthRequest{} } func (m *StreamHealthRequest) String() string { return proto.CompactTextString(m) } func (*StreamHealthRequest) ProtoMessage() {} func (*StreamHealthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{52} + return fileDescriptor_query_9111254583ad7475, []int{53} } func (m *StreamHealthRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamHealthRequest.Unmarshal(m, b) @@ -3601,7 +3649,7 @@ func (m *RealtimeStats) Reset() { *m = RealtimeStats{} } func (m *RealtimeStats) String() string { return proto.CompactTextString(m) } func (*RealtimeStats) ProtoMessage() {} func (*RealtimeStats) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{53} + return fileDescriptor_query_9111254583ad7475, []int{54} } func (m *RealtimeStats) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RealtimeStats.Unmarshal(m, b) @@ -3689,7 +3737,7 @@ func (m *AggregateStats) Reset() { *m = AggregateStats{} } func (m *AggregateStats) String() string { return proto.CompactTextString(m) } func (*AggregateStats) ProtoMessage() {} func (*AggregateStats) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{54} + return fileDescriptor_query_9111254583ad7475, []int{55} } func (m *AggregateStats) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AggregateStats.Unmarshal(m, b) @@ -3801,7 +3849,7 @@ func (m *StreamHealthResponse) Reset() { *m = StreamHealthResponse{} } func (m *StreamHealthResponse) String() string { return proto.CompactTextString(m) } func (*StreamHealthResponse) ProtoMessage() {} func (*StreamHealthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{55} + return fileDescriptor_query_9111254583ad7475, []int{56} } func (m *StreamHealthResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamHealthResponse.Unmarshal(m, b) @@ -3885,7 +3933,7 @@ func (m *UpdateStreamRequest) Reset() { *m = UpdateStreamRequest{} } func (m *UpdateStreamRequest) String() string { return proto.CompactTextString(m) } func (*UpdateStreamRequest) ProtoMessage() {} func (*UpdateStreamRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{56} + return fileDescriptor_query_9111254583ad7475, []int{57} } func (m *UpdateStreamRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UpdateStreamRequest.Unmarshal(m, b) @@ -3952,7 +4000,7 @@ func (m *UpdateStreamResponse) Reset() { *m = UpdateStreamResponse{} } func (m *UpdateStreamResponse) String() string { return proto.CompactTextString(m) } func (*UpdateStreamResponse) ProtoMessage() {} func (*UpdateStreamResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{57} + return fileDescriptor_query_9111254583ad7475, []int{58} } func (m *UpdateStreamResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UpdateStreamResponse.Unmarshal(m, b) @@ -3994,7 +4042,7 @@ func (m *TransactionMetadata) Reset() { *m = TransactionMetadata{} } func (m *TransactionMetadata) String() string { return proto.CompactTextString(m) } func (*TransactionMetadata) ProtoMessage() {} func (*TransactionMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_query_05c95bca0e3aaf7a, []int{58} + return fileDescriptor_query_9111254583ad7475, []int{59} } func (m *TransactionMetadata) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransactionMetadata.Unmarshal(m, b) @@ -4055,6 +4103,7 @@ func init() { proto.RegisterType((*Row)(nil), "query.Row") proto.RegisterType((*ResultExtras)(nil), "query.ResultExtras") proto.RegisterType((*QueryResult)(nil), "query.QueryResult") + proto.RegisterType((*QueryWarning)(nil), "query.QueryWarning") proto.RegisterType((*StreamEvent)(nil), "query.StreamEvent") proto.RegisterType((*StreamEvent_Statement)(nil), "query.StreamEvent.Statement") proto.RegisterType((*ExecuteRequest)(nil), "query.ExecuteRequest") @@ -4115,209 +4164,210 @@ func init() { proto.RegisterEnum("query.SplitQueryRequest_Algorithm", SplitQueryRequest_Algorithm_name, SplitQueryRequest_Algorithm_value) } -func init() { proto.RegisterFile("query.proto", fileDescriptor_query_05c95bca0e3aaf7a) } - -var fileDescriptor_query_05c95bca0e3aaf7a = []byte{ - // 3202 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcb, 0x73, 0x1b, 0xc7, - 0x99, 0xd7, 0xe0, 0x41, 0x02, 0x1f, 0x08, 0xb0, 0xd9, 0x20, 0x25, 0x88, 0xf2, 0x83, 0x3b, 0xb6, - 0x6c, 0x2e, 0xed, 0xa5, 0x64, 0x4a, 0xd6, 0x6a, 0xed, 0x5d, 0xaf, 0x86, 0xe0, 0x50, 0x86, 0x85, - 0x97, 0x1a, 0x03, 0xc9, 0x52, 0xb9, 0x6a, 0x6a, 0x08, 0xb4, 0xc0, 0x29, 0x0e, 0x30, 0xd0, 0xcc, - 0x80, 0x14, 0x6f, 0xda, 0xf5, 0x7a, 0xdf, 0x0f, 0xef, 0xd3, 0xeb, 0xdd, 0x5a, 0x6f, 0xaa, 0x72, - 0xcf, 0xdf, 0x90, 0xca, 0x1f, 0x90, 0x5b, 0x0e, 0x49, 0x0e, 0x39, 0xa4, 0x52, 0x39, 0xa4, 0xca, - 0x95, 0x53, 0x0e, 0x39, 0xa4, 0x52, 0xfd, 0x98, 0xc1, 0x80, 0x84, 0x1e, 0x56, 0x72, 0xa1, 0xec, - 0x5b, 0xf7, 0xf7, 0x7d, 0xfd, 0xf8, 0xfd, 0xbe, 0x6f, 0xbe, 0xee, 0xe9, 0x6e, 0xc8, 0xdd, 0x1f, - 0x51, 0xef, 0x70, 0x7d, 0xe8, 0xb9, 0x81, 0x8b, 0xd3, 0xbc, 0xb2, 0x5c, 0x08, 0xdc, 0xa1, 0xdb, - 0xb5, 0x02, 0x4b, 0x88, 0x97, 0x73, 0xfb, 0x81, 0x37, 0xec, 0x88, 0x8a, 0xfa, 0x89, 0x02, 0x33, - 0x86, 0xe5, 0xf5, 0x68, 0x80, 0x97, 0x21, 0xb3, 0x47, 0x0f, 0xfd, 0xa1, 0xd5, 0xa1, 0x25, 0x65, - 0x45, 0x59, 0xcd, 0x92, 0xa8, 0x8e, 0x17, 0x21, 0xed, 0xef, 0x5a, 0x5e, 0xb7, 0x94, 0xe0, 0x0a, - 0x51, 0xc1, 0x6f, 0x43, 0x2e, 0xb0, 0x76, 0x1c, 0x1a, 0x98, 0xc1, 0xe1, 0x90, 0x96, 0x92, 0x2b, - 0xca, 0x6a, 0x61, 0x63, 0x71, 0x3d, 0x1a, 0xcf, 0xe0, 0x4a, 0xe3, 0x70, 0x48, 0x09, 0x04, 0x51, - 0x19, 0x63, 0x48, 0x75, 0xa8, 0xe3, 0x94, 0x52, 0xbc, 0x2f, 0x5e, 0x56, 0xb7, 0xa0, 0x70, 0xcb, - 0xb8, 0x6e, 0x05, 0xb4, 0x6c, 0x39, 0x0e, 0xf5, 0x2a, 0x5b, 0x6c, 0x3a, 0x23, 0x9f, 0x7a, 0x03, - 0xab, 0x1f, 0x4d, 0x27, 0xac, 0xe3, 0xd3, 0x30, 0xd3, 0xf3, 0xdc, 0xd1, 0xd0, 0x2f, 0x25, 0x56, - 0x92, 0xab, 0x59, 0x22, 0x6b, 0xea, 0x47, 0x00, 0xfa, 0x3e, 0x1d, 0x04, 0x86, 0xbb, 0x47, 0x07, - 0xf8, 0x05, 0xc8, 0x06, 0x76, 0x9f, 0xfa, 0x81, 0xd5, 0x1f, 0xf2, 0x2e, 0x92, 0x64, 0x2c, 0x78, - 0x04, 0xa4, 0x65, 0xc8, 0x0c, 0x5d, 0xdf, 0x0e, 0x6c, 0x77, 0xc0, 0xf1, 0x64, 0x49, 0x54, 0x57, - 0xdf, 0x83, 0xf4, 0x2d, 0xcb, 0x19, 0x51, 0xfc, 0x32, 0xa4, 0x38, 0x60, 0x85, 0x03, 0xce, 0xad, - 0x0b, 0xd2, 0x39, 0x4e, 0xae, 0x60, 0x7d, 0xef, 0x33, 0x4b, 0xde, 0xf7, 0x1c, 0x11, 0x15, 0x75, - 0x0f, 0xe6, 0x36, 0xed, 0x41, 0xf7, 0x96, 0xe5, 0xd9, 0x8c, 0x8c, 0x67, 0xec, 0x06, 0xbf, 0x0a, - 0x33, 0xbc, 0xe0, 0x97, 0x92, 0x2b, 0xc9, 0xd5, 0xdc, 0xc6, 0x9c, 0x6c, 0xc8, 0xe7, 0x46, 0xa4, - 0x4e, 0xfd, 0x9e, 0x02, 0xb0, 0xe9, 0x8e, 0x06, 0xdd, 0x9b, 0x4c, 0x89, 0x11, 0x24, 0xfd, 0xfb, - 0x8e, 0x24, 0x92, 0x15, 0xf1, 0x0d, 0x28, 0xec, 0xd8, 0x83, 0xae, 0xb9, 0x2f, 0xa7, 0x23, 0xb8, - 0xcc, 0x6d, 0xbc, 0x2a, 0xbb, 0x1b, 0x37, 0x5e, 0x8f, 0xcf, 0xda, 0xd7, 0x07, 0x81, 0x77, 0x48, - 0xf2, 0x3b, 0x71, 0xd9, 0x72, 0x1b, 0xf0, 0x71, 0x23, 0x36, 0xe8, 0x1e, 0x3d, 0x0c, 0x07, 0xdd, - 0xa3, 0x87, 0xf8, 0x0f, 0xe3, 0x88, 0x72, 0x1b, 0xc5, 0x70, 0xac, 0x58, 0x5b, 0x09, 0xf3, 0x9d, - 0xc4, 0x55, 0x45, 0xfd, 0x45, 0x1a, 0x0a, 0xfa, 0x03, 0xda, 0x19, 0x05, 0xb4, 0x31, 0x64, 0x3e, - 0xf0, 0xf1, 0x3a, 0x14, 0xed, 0x41, 0xc7, 0x19, 0x75, 0xa9, 0x49, 0x99, 0xab, 0xcd, 0x80, 0xf9, - 0x9a, 0xf7, 0x97, 0x21, 0x0b, 0x52, 0x15, 0x0b, 0x02, 0x0d, 0x8a, 0x1d, 0xb7, 0x3f, 0xb4, 0xbc, - 0x49, 0xfb, 0x24, 0x1f, 0x7f, 0x41, 0x8e, 0x3f, 0xb6, 0x27, 0x0b, 0xd2, 0x3a, 0xd6, 0x45, 0x0d, - 0xe6, 0x65, 0xbf, 0x5d, 0xf3, 0x9e, 0x4d, 0x9d, 0xae, 0xcf, 0x43, 0xb7, 0x10, 0x51, 0x35, 0x39, - 0xc5, 0xf5, 0x8a, 0x34, 0xde, 0xe6, 0xb6, 0xa4, 0x60, 0x4f, 0xd4, 0xf1, 0x1a, 0x2c, 0x74, 0x1c, - 0x9b, 0x4d, 0xe5, 0x1e, 0xa3, 0xd8, 0xf4, 0xdc, 0x03, 0xbf, 0x94, 0xe6, 0xf3, 0x9f, 0x17, 0x8a, - 0x6d, 0x26, 0x27, 0xee, 0x81, 0x8f, 0xdf, 0x81, 0xcc, 0x81, 0xeb, 0xed, 0x39, 0xae, 0xd5, 0x2d, - 0xcd, 0xf0, 0x31, 0x5f, 0x9a, 0x3e, 0xe6, 0x6d, 0x69, 0x45, 0x22, 0x7b, 0xbc, 0x0a, 0xc8, 0xbf, - 0xef, 0x98, 0x3e, 0x75, 0x68, 0x27, 0x30, 0x1d, 0xbb, 0x6f, 0x07, 0xa5, 0x0c, 0xff, 0x0a, 0x0a, - 0xfe, 0x7d, 0xa7, 0xc5, 0xc5, 0x55, 0x26, 0xc5, 0x26, 0x2c, 0x05, 0x9e, 0x35, 0xf0, 0xad, 0x0e, - 0xeb, 0xcc, 0xb4, 0x7d, 0xd7, 0xb1, 0xf8, 0x17, 0x90, 0xe5, 0x43, 0xae, 0x4d, 0x1f, 0xd2, 0x18, - 0x37, 0xa9, 0x84, 0x2d, 0xc8, 0x62, 0x30, 0x45, 0x8a, 0xdf, 0x82, 0x25, 0x7f, 0xcf, 0x1e, 0x9a, - 0xbc, 0x1f, 0x73, 0xe8, 0x58, 0x03, 0xb3, 0x63, 0x75, 0x76, 0x69, 0x09, 0x38, 0x6c, 0xcc, 0x94, - 0x3c, 0xd4, 0x9a, 0x8e, 0x35, 0x28, 0x33, 0x8d, 0xfa, 0x2e, 0x14, 0x26, 0x79, 0xc4, 0x0b, 0x90, - 0x37, 0xee, 0x34, 0x75, 0x53, 0xab, 0x6f, 0x99, 0x75, 0xad, 0xa6, 0xa3, 0x53, 0x38, 0x0f, 0x59, - 0x2e, 0x6a, 0xd4, 0xab, 0x77, 0x90, 0x82, 0x67, 0x21, 0xa9, 0x55, 0xab, 0x28, 0xa1, 0x5e, 0x85, - 0x4c, 0x48, 0x08, 0x9e, 0x87, 0x5c, 0xbb, 0xde, 0x6a, 0xea, 0xe5, 0xca, 0x76, 0x45, 0xdf, 0x42, - 0xa7, 0x70, 0x06, 0x52, 0x8d, 0xaa, 0xd1, 0x44, 0x8a, 0x28, 0x69, 0x4d, 0x94, 0x60, 0x2d, 0xb7, - 0x36, 0x35, 0x94, 0x54, 0x03, 0x58, 0x9c, 0x86, 0x0b, 0xe7, 0x60, 0x76, 0x4b, 0xdf, 0xd6, 0xda, - 0x55, 0x03, 0x9d, 0xc2, 0x45, 0x98, 0x27, 0x7a, 0x53, 0xd7, 0x0c, 0x6d, 0xb3, 0xaa, 0x9b, 0x44, - 0xd7, 0xb6, 0x90, 0x82, 0x31, 0x14, 0x58, 0xc9, 0x2c, 0x37, 0x6a, 0xb5, 0x8a, 0x61, 0xe8, 0x5b, - 0x28, 0x81, 0x17, 0x01, 0x71, 0x59, 0xbb, 0x3e, 0x96, 0x26, 0x31, 0x82, 0xb9, 0x96, 0x4e, 0x2a, - 0x5a, 0xb5, 0x72, 0x97, 0x75, 0x80, 0x52, 0x1f, 0xa4, 0x32, 0x0a, 0x4a, 0xa8, 0x9f, 0x25, 0x20, - 0xcd, 0xb1, 0xb2, 0x0c, 0x19, 0xcb, 0x7b, 0xbc, 0x1c, 0x65, 0x8b, 0xc4, 0x63, 0xb2, 0x05, 0x4f, - 0xb2, 0x32, 0x6f, 0x89, 0x0a, 0x3e, 0x07, 0x59, 0xd7, 0xeb, 0x99, 0x42, 0x23, 0x32, 0x6e, 0xc6, - 0xf5, 0x7a, 0x3c, 0x35, 0xb3, 0x6c, 0xc7, 0x12, 0xf5, 0x8e, 0xe5, 0x53, 0x1e, 0x81, 0x59, 0x12, - 0xd5, 0xf1, 0x59, 0x60, 0x76, 0x26, 0x9f, 0xc7, 0x0c, 0xd7, 0xcd, 0xba, 0x5e, 0xaf, 0xce, 0xa6, - 0xf2, 0x0a, 0xe4, 0x3b, 0xae, 0x33, 0xea, 0x0f, 0x4c, 0x87, 0x0e, 0x7a, 0xc1, 0x6e, 0x69, 0x76, - 0x45, 0x59, 0xcd, 0x93, 0x39, 0x21, 0xac, 0x72, 0x19, 0x2e, 0xc1, 0x6c, 0x67, 0xd7, 0xf2, 0x7c, - 0x2a, 0xa2, 0x2e, 0x4f, 0xc2, 0x2a, 0x1f, 0x95, 0x76, 0xec, 0xbe, 0xe5, 0xf8, 0x3c, 0xc2, 0xf2, - 0x24, 0xaa, 0x33, 0x10, 0xf7, 0x1c, 0xab, 0xe7, 0xf3, 0xc8, 0xc8, 0x13, 0x51, 0x51, 0xff, 0x18, - 0x92, 0xc4, 0x3d, 0x60, 0x5d, 0x8a, 0x01, 0xfd, 0x92, 0xb2, 0x92, 0x5c, 0xc5, 0x24, 0xac, 0xb2, - 0x05, 0x41, 0xe6, 0x44, 0x91, 0x2a, 0xc3, 0x2c, 0xf8, 0x11, 0xcc, 0x11, 0xea, 0x8f, 0x9c, 0x40, - 0x7f, 0x10, 0x78, 0x96, 0x8f, 0x37, 0x20, 0x17, 0xcf, 0x02, 0xca, 0xa3, 0xb2, 0x00, 0xd0, 0xf1, - 0xe7, 0x5f, 0x82, 0xd9, 0x7b, 0x1e, 0xf5, 0x77, 0xa9, 0x27, 0xb3, 0x4c, 0x58, 0x65, 0x39, 0x36, - 0xc7, 0xc3, 0x56, 0x8c, 0xc1, 0x32, 0xb3, 0xcc, 0x0f, 0xca, 0x44, 0x66, 0xe6, 0x4e, 0x25, 0x52, - 0xc7, 0xd8, 0x63, 0x9f, 0xbc, 0x69, 0xdd, 0xbb, 0x47, 0x3b, 0x01, 0x15, 0x0b, 0x50, 0x8a, 0xcc, - 0x31, 0xa1, 0x26, 0x65, 0xcc, 0x6d, 0xf6, 0xc0, 0xa7, 0x5e, 0x60, 0xda, 0x5d, 0xee, 0xd0, 0x14, - 0xc9, 0x08, 0x41, 0xa5, 0x8b, 0x5f, 0x82, 0x14, 0x4f, 0x1a, 0x29, 0x3e, 0x0a, 0xc8, 0x51, 0x88, - 0x7b, 0x40, 0xb8, 0x1c, 0xbf, 0x01, 0x33, 0x94, 0xe3, 0xe5, 0x4e, 0x1d, 0xa7, 0xd9, 0x38, 0x15, - 0x44, 0x9a, 0xa8, 0xdf, 0x4a, 0x42, 0xae, 0x15, 0x78, 0xd4, 0xea, 0x73, 0xfc, 0xf8, 0x4f, 0x01, - 0xfc, 0xc0, 0x0a, 0x68, 0x9f, 0x0e, 0x82, 0x10, 0xc8, 0x0b, 0xb2, 0x83, 0x98, 0xdd, 0x7a, 0x2b, - 0x34, 0x22, 0x31, 0xfb, 0xa3, 0x04, 0x27, 0x9e, 0x82, 0xe0, 0xe5, 0x2f, 0x12, 0x90, 0x8d, 0x7a, - 0xc3, 0x1a, 0x64, 0x3a, 0x56, 0x40, 0x7b, 0xae, 0x77, 0x28, 0x57, 0xc6, 0xf3, 0x8f, 0x1b, 0x7d, - 0xbd, 0x2c, 0x8d, 0x49, 0xd4, 0x0c, 0xbf, 0x08, 0x62, 0xbb, 0x21, 0x82, 0x57, 0xac, 0xef, 0x59, - 0x2e, 0xe1, 0xe1, 0xfb, 0x0e, 0xe0, 0xa1, 0x67, 0xf7, 0x2d, 0xef, 0xd0, 0xdc, 0xa3, 0x87, 0x61, - 0x4a, 0x4f, 0x4e, 0x71, 0x19, 0x92, 0x76, 0x37, 0xe8, 0xa1, 0x4c, 0x42, 0x57, 0x27, 0xdb, 0xca, - 0xa0, 0x3b, 0xee, 0x88, 0x58, 0x4b, 0xbe, 0x2e, 0xfb, 0xe1, 0x0a, 0x9c, 0xe6, 0xf1, 0xc9, 0x8a, - 0xea, 0xeb, 0x90, 0x09, 0x27, 0x8f, 0xb3, 0x90, 0xd6, 0x3d, 0xcf, 0xf5, 0xd0, 0x29, 0x9e, 0x8b, - 0x6a, 0x55, 0x91, 0xce, 0xb6, 0xb6, 0x58, 0x3a, 0xfb, 0x6e, 0x22, 0x5a, 0x06, 0x09, 0xbd, 0x3f, - 0xa2, 0x7e, 0x80, 0xff, 0x1c, 0x8a, 0x94, 0xc7, 0x8a, 0xbd, 0x4f, 0xcd, 0x0e, 0xdf, 0x33, 0xb1, - 0x48, 0x11, 0x01, 0x3d, 0xbf, 0x2e, 0xb6, 0x78, 0xe1, 0x5e, 0x8a, 0x2c, 0x44, 0xb6, 0x52, 0xd4, - 0xc5, 0x3a, 0x14, 0xed, 0x7e, 0x9f, 0x76, 0x6d, 0x2b, 0x88, 0x77, 0x20, 0x1c, 0xb6, 0x14, 0x6e, - 0x29, 0x26, 0xb6, 0x64, 0x64, 0x21, 0x6a, 0x11, 0x75, 0x73, 0x1e, 0x66, 0x02, 0xbe, 0x7d, 0x94, - 0x2b, 0x6a, 0x3e, 0xcc, 0x4b, 0x5c, 0x48, 0xa4, 0x12, 0xbf, 0x0e, 0x62, 0x33, 0xca, 0x33, 0xd0, - 0x38, 0x20, 0xc6, 0x7b, 0x0c, 0x22, 0xf4, 0xf8, 0x3c, 0x14, 0x26, 0x96, 0xa2, 0x2e, 0x27, 0x2c, - 0x49, 0xf2, 0xf1, 0x75, 0xa5, 0x8b, 0x2f, 0xc0, 0xac, 0x2b, 0x96, 0x21, 0x9e, 0x9b, 0xc6, 0x33, - 0x9e, 0x5c, 0xa3, 0x48, 0x68, 0xa5, 0xfe, 0x19, 0xcc, 0x47, 0x0c, 0xfa, 0x43, 0x77, 0xe0, 0x53, - 0xbc, 0x06, 0x33, 0x1e, 0xff, 0x20, 0x24, 0x6b, 0x58, 0x76, 0x11, 0xfb, 0xa2, 0x89, 0xb4, 0x50, - 0xbb, 0x30, 0x2f, 0x24, 0xb7, 0xed, 0x60, 0x97, 0x3b, 0x0a, 0x9f, 0x87, 0x34, 0x65, 0x85, 0x23, - 0x9c, 0x93, 0x66, 0x99, 0xeb, 0x89, 0xd0, 0xc6, 0x46, 0x49, 0x3c, 0x71, 0x94, 0x5f, 0x26, 0xa0, - 0x28, 0x67, 0xb9, 0x69, 0x05, 0x9d, 0xdd, 0x13, 0xea, 0xec, 0x37, 0x60, 0x96, 0xc9, 0xed, 0xe8, - 0xc3, 0x98, 0xe2, 0xee, 0xd0, 0x82, 0x39, 0xdc, 0xf2, 0xcd, 0x98, 0x77, 0xe5, 0x56, 0x28, 0x6f, - 0xf9, 0xb1, 0x85, 0x78, 0x4a, 0x5c, 0xcc, 0x3c, 0x21, 0x2e, 0x66, 0x9f, 0x2a, 0x2e, 0xb6, 0x60, - 0x71, 0x92, 0x71, 0x19, 0x1c, 0x6f, 0xc2, 0xac, 0x70, 0x4a, 0x98, 0x02, 0xa7, 0xf9, 0x2d, 0x34, - 0x51, 0xff, 0x3f, 0x01, 0x8b, 0x32, 0x3b, 0x7d, 0x3d, 0x3e, 0xd3, 0x18, 0xcf, 0xe9, 0xa7, 0xe2, - 0xb9, 0x0c, 0x4b, 0x47, 0x08, 0x7a, 0x86, 0xaf, 0xf0, 0x4b, 0x05, 0xe6, 0x36, 0x69, 0xcf, 0x1e, - 0x9c, 0x50, 0x7a, 0x63, 0xac, 0xa5, 0x9e, 0x8a, 0xb5, 0x2b, 0x90, 0x97, 0x78, 0x25, 0x5b, 0xc7, - 0x3f, 0x03, 0x65, 0xca, 0x67, 0xa0, 0xfe, 0x4c, 0x81, 0x7c, 0xd9, 0xed, 0xf7, 0xed, 0xe0, 0x84, - 0x32, 0x75, 0x1c, 0x67, 0x6a, 0x1a, 0x4e, 0x04, 0x85, 0x10, 0xa6, 0x20, 0x48, 0xfd, 0xb9, 0x02, - 0xf3, 0xc4, 0x75, 0x9c, 0x1d, 0xab, 0xb3, 0xf7, 0x7c, 0x63, 0xc7, 0x80, 0xc6, 0x40, 0x25, 0xfa, - 0x5f, 0x2b, 0x50, 0x68, 0x7a, 0x94, 0xfd, 0xbf, 0x3e, 0xd7, 0xe0, 0xd9, 0x0f, 0x52, 0x37, 0x90, - 0x9b, 0x83, 0x2c, 0xe1, 0x65, 0x75, 0x01, 0xe6, 0x23, 0xec, 0x92, 0x8f, 0x1f, 0x29, 0xb0, 0x24, - 0x02, 0x44, 0x6a, 0xba, 0x27, 0x94, 0x96, 0x10, 0x6f, 0x2a, 0x86, 0xb7, 0x04, 0xa7, 0x8f, 0x62, - 0x93, 0xb0, 0x3f, 0x4e, 0xc0, 0x99, 0x30, 0x36, 0x4e, 0x38, 0xf0, 0xdf, 0x21, 0x1e, 0x96, 0xa1, - 0x74, 0x9c, 0x04, 0xc9, 0xd0, 0xa7, 0x09, 0x28, 0x95, 0x3d, 0x6a, 0x05, 0x34, 0xb6, 0xc9, 0x78, - 0x7e, 0x62, 0x03, 0xbf, 0x05, 0x73, 0x43, 0xcb, 0x0b, 0xec, 0x8e, 0x3d, 0xb4, 0xd8, 0x6f, 0x5c, - 0x9a, 0xef, 0x61, 0x8e, 0x74, 0x30, 0x61, 0xa2, 0x9e, 0x83, 0xb3, 0x53, 0x18, 0x91, 0x7c, 0xfd, - 0x46, 0x01, 0xdc, 0x0a, 0x2c, 0x2f, 0xf8, 0x1a, 0xac, 0x2a, 0x53, 0x83, 0x69, 0x09, 0x8a, 0x13, - 0xf8, 0xe3, 0xbc, 0xd0, 0xe0, 0x6b, 0xb1, 0xe2, 0x3c, 0x92, 0x97, 0x38, 0x7e, 0xc9, 0xcb, 0x4f, - 0x14, 0x58, 0x2e, 0xbb, 0xe2, 0xfc, 0xee, 0xb9, 0xfc, 0xc2, 0xd4, 0x17, 0xe1, 0xdc, 0x54, 0x80, - 0x92, 0x80, 0x1f, 0x2b, 0x70, 0x9a, 0x50, 0xab, 0xfb, 0x7c, 0x82, 0xbf, 0x09, 0x67, 0x8e, 0x81, - 0x93, 0x3b, 0xd4, 0x2b, 0x90, 0xe9, 0xd3, 0xc0, 0xea, 0x5a, 0x81, 0x25, 0x21, 0x2d, 0x87, 0xfd, - 0x8e, 0xad, 0x6b, 0xd2, 0x82, 0x44, 0xb6, 0xea, 0x17, 0x09, 0x28, 0xf2, 0xbd, 0xee, 0x37, 0x7f, - 0x50, 0xd3, 0xff, 0x05, 0x3e, 0x55, 0x60, 0x71, 0x92, 0xa0, 0xe8, 0x9f, 0xe0, 0xf7, 0x7d, 0x10, - 0x31, 0x25, 0x21, 0x24, 0xa7, 0x6d, 0x41, 0xbf, 0x9f, 0x80, 0x52, 0x7c, 0x4a, 0xdf, 0x1c, 0x5a, - 0x4c, 0x1e, 0x5a, 0x7c, 0xe5, 0x53, 0xaa, 0xcf, 0x14, 0x38, 0x3b, 0x85, 0xd0, 0xaf, 0xe6, 0xe8, - 0xd8, 0xd1, 0x45, 0xe2, 0x89, 0x47, 0x17, 0x4f, 0xeb, 0xea, 0x1f, 0x2a, 0xb0, 0x58, 0xa3, 0xbe, - 0x6f, 0xf5, 0xa8, 0xf8, 0x8f, 0x3f, 0xb9, 0xd9, 0x8c, 0x1f, 0x0a, 0xa7, 0xc6, 0x37, 0x2b, 0x6a, - 0x19, 0x96, 0x8e, 0x40, 0x7b, 0x86, 0xb3, 0x89, 0x5f, 0x29, 0xb0, 0x20, 0x7b, 0xd1, 0x4e, 0xec, - 0x46, 0x60, 0x0a, 0x3b, 0xf8, 0x25, 0x48, 0xda, 0xdd, 0x70, 0x07, 0x39, 0x79, 0xd7, 0xcc, 0x14, - 0xea, 0x35, 0xc0, 0x71, 0xdc, 0xcf, 0x40, 0xdd, 0x0f, 0x92, 0xb0, 0xd0, 0x1a, 0x3a, 0x76, 0x20, - 0x95, 0xcf, 0x77, 0xe2, 0xff, 0x03, 0x98, 0xf3, 0x19, 0x58, 0x53, 0xdc, 0x96, 0x71, 0x62, 0xb3, - 0x24, 0xc7, 0x65, 0x65, 0x2e, 0xc2, 0x2f, 0x43, 0x2e, 0x34, 0x19, 0x0d, 0x02, 0x79, 0xd2, 0x09, - 0xd2, 0x62, 0x34, 0x08, 0xf0, 0x65, 0x38, 0x33, 0x18, 0xf5, 0xf9, 0xcd, 0xb1, 0x39, 0xa4, 0x5e, - 0x78, 0xaf, 0x6a, 0x79, 0xe1, 0x0d, 0x6f, 0x71, 0x30, 0xea, 0x13, 0xf7, 0xc0, 0x6f, 0x52, 0x4f, - 0xdc, 0xab, 0x5a, 0x5e, 0x80, 0xaf, 0x41, 0xd6, 0x72, 0x7a, 0xae, 0x67, 0x07, 0xbb, 0x7d, 0x79, - 0xb5, 0xab, 0x86, 0x57, 0x2b, 0x47, 0xe9, 0x5f, 0xd7, 0x42, 0x4b, 0x32, 0x6e, 0xa4, 0xbe, 0x09, - 0xd9, 0x48, 0x8e, 0x11, 0xcc, 0xe9, 0x37, 0xdb, 0x5a, 0xd5, 0x6c, 0x35, 0xab, 0x15, 0xa3, 0x25, - 0xae, 0x63, 0xb7, 0xdb, 0xd5, 0xaa, 0xd9, 0x2a, 0x6b, 0x75, 0xa4, 0xa8, 0x04, 0x80, 0x77, 0xc9, - 0x3b, 0x1f, 0x13, 0xa4, 0x3c, 0x81, 0xa0, 0x73, 0x90, 0xf5, 0xdc, 0x03, 0x89, 0x3d, 0xc1, 0xe1, - 0x64, 0x3c, 0xf7, 0x80, 0x23, 0x57, 0x35, 0xc0, 0xf1, 0xb9, 0xca, 0x68, 0x8b, 0x25, 0x6f, 0x65, - 0x22, 0x79, 0x8f, 0xc7, 0x8f, 0x92, 0xb7, 0xd8, 0xca, 0xb3, 0xef, 0xfc, 0x7d, 0x6a, 0x39, 0x41, - 0xb8, 0x5e, 0xa9, 0xdf, 0x4e, 0x40, 0x9e, 0x30, 0x89, 0xdd, 0xa7, 0xad, 0xc0, 0x0a, 0x7c, 0xe6, - 0xa9, 0x5d, 0x6e, 0x62, 0x8e, 0xd3, 0x6e, 0x96, 0xe4, 0x84, 0x4c, 0x5c, 0x02, 0x6c, 0xc0, 0x92, - 0x4f, 0x3b, 0xee, 0xa0, 0xeb, 0x9b, 0x3b, 0x74, 0xd7, 0x1e, 0x74, 0xcd, 0xbe, 0xe5, 0x07, 0xf2, - 0xa6, 0x30, 0x4f, 0x8a, 0x52, 0xb9, 0xc9, 0x75, 0x35, 0xae, 0xc2, 0x17, 0x61, 0x71, 0xc7, 0x1e, - 0x38, 0x6e, 0xcf, 0x1c, 0x3a, 0xd6, 0x21, 0xf5, 0x7c, 0x09, 0x95, 0x85, 0x57, 0x9a, 0x60, 0xa1, - 0x6b, 0x0a, 0x95, 0x70, 0xf7, 0x5d, 0x58, 0x9b, 0x3a, 0x8a, 0x79, 0xcf, 0x76, 0x02, 0xea, 0xd1, - 0xae, 0xe9, 0xd1, 0xa1, 0x63, 0x77, 0xc4, 0xa5, 0xbd, 0xd8, 0xbb, 0xbf, 0x36, 0x65, 0xe8, 0x6d, - 0x69, 0x4e, 0xc6, 0xd6, 0x8c, 0xed, 0xce, 0x70, 0x64, 0x8e, 0xd8, 0x07, 0xcc, 0x57, 0x31, 0x85, - 0x64, 0x3a, 0xc3, 0x51, 0x9b, 0xd5, 0x31, 0x82, 0xe4, 0xfd, 0xa1, 0x58, 0xbc, 0x14, 0xc2, 0x8a, - 0xea, 0x97, 0x0a, 0x14, 0xb4, 0x5e, 0xcf, 0xa3, 0x3d, 0x2b, 0x90, 0x34, 0x5d, 0x84, 0x45, 0x41, - 0xc9, 0xa1, 0x29, 0x5f, 0x03, 0x09, 0x3c, 0x8a, 0xc0, 0x23, 0x75, 0xe2, 0x2d, 0x50, 0x18, 0xbe, - 0xa7, 0x47, 0x83, 0xa9, 0x6d, 0x12, 0xbc, 0xcd, 0x62, 0xa4, 0x8d, 0xb7, 0xfa, 0x13, 0x38, 0x3b, - 0x9d, 0x85, 0xbe, 0x2d, 0xde, 0x73, 0xe4, 0xc9, 0xe9, 0x29, 0xa0, 0x6b, 0xf6, 0xe0, 0x31, 0x4d, - 0xad, 0x07, 0x9c, 0xaf, 0x47, 0x34, 0xb5, 0x1e, 0xa8, 0x3f, 0x8d, 0x8e, 0xf6, 0xc3, 0x70, 0x89, - 0x56, 0xe3, 0x30, 0x2f, 0x28, 0x8f, 0xcb, 0x0b, 0x25, 0x98, 0xf5, 0xa9, 0xb7, 0x6f, 0x0f, 0x7a, - 0xe1, 0xed, 0xb1, 0xac, 0xe2, 0x16, 0xbc, 0x26, 0xb1, 0xd3, 0x07, 0x01, 0xf5, 0x06, 0x96, 0xe3, - 0x1c, 0x9a, 0xe2, 0xa0, 0x62, 0x10, 0xd0, 0xae, 0x39, 0x7e, 0xbb, 0x24, 0x56, 0xe4, 0x57, 0x84, - 0xb5, 0x1e, 0x19, 0x93, 0xc8, 0xd6, 0x88, 0x5e, 0x35, 0xbd, 0x0b, 0x05, 0x4f, 0x06, 0xb1, 0xe9, - 0x33, 0xf7, 0xc8, 0x7c, 0xb4, 0x18, 0x5d, 0x01, 0xc7, 0x22, 0x9c, 0xe4, 0xbd, 0x89, 0x80, 0x7f, - 0x0f, 0xe6, 0xad, 0xd0, 0xb7, 0xb2, 0xf5, 0xe4, 0xbe, 0x65, 0xd2, 0xf3, 0xa4, 0x60, 0x4d, 0x46, - 0xc2, 0x55, 0x98, 0x93, 0x88, 0x2c, 0xc7, 0xb6, 0xc6, 0x1b, 0xdb, 0x23, 0x0f, 0xc2, 0x34, 0xa6, - 0x24, 0xf2, 0xe9, 0x18, 0xaf, 0xb0, 0xff, 0xe8, 0x62, 0x7b, 0xd8, 0xe5, 0x3d, 0x9d, 0xe0, 0xdd, - 0x45, 0xfc, 0xf5, 0x58, 0x6a, 0xf2, 0xf5, 0xd8, 0xe4, 0x6b, 0xb4, 0xf4, 0x91, 0xd7, 0x68, 0xea, - 0x35, 0x58, 0x9c, 0xc4, 0x2f, 0xa3, 0x6c, 0x15, 0xd2, 0xfc, 0xa6, 0xfc, 0xc8, 0x32, 0x1a, 0xbb, - 0x0a, 0x27, 0xc2, 0x40, 0xfd, 0x8e, 0x02, 0xc5, 0x29, 0xbf, 0x58, 0xd1, 0xff, 0x9b, 0x12, 0x3b, - 0x1e, 0xfa, 0x23, 0x48, 0xf3, 0x3b, 0x7b, 0xf9, 0x98, 0xe4, 0xcc, 0xf1, 0x3f, 0x34, 0x7e, 0xbf, - 0x4e, 0x84, 0x15, 0x4b, 0x84, 0x3c, 0xa0, 0x3a, 0xfc, 0x7c, 0x28, 0xdc, 0x21, 0xe6, 0x98, 0x4c, - 0x1c, 0x19, 0x1d, 0x3f, 0x70, 0x4a, 0x3d, 0xf1, 0xc0, 0x69, 0xed, 0xdf, 0x92, 0x90, 0xad, 0x1d, - 0xb6, 0xee, 0x3b, 0xdb, 0x8e, 0xd5, 0xe3, 0x17, 0xe0, 0xb5, 0xa6, 0x71, 0x07, 0x9d, 0xc2, 0x0b, - 0x90, 0xaf, 0x37, 0x0c, 0xb3, 0xce, 0x96, 0x92, 0xed, 0xaa, 0x76, 0x1d, 0x29, 0x6c, 0xad, 0x69, - 0x92, 0x8a, 0x79, 0x43, 0xbf, 0x23, 0x24, 0x09, 0x5c, 0x84, 0xf9, 0x76, 0xbd, 0x72, 0xb3, 0xad, - 0x8f, 0x85, 0x29, 0xbc, 0x04, 0x0b, 0xb5, 0x76, 0xd5, 0xa8, 0x34, 0xab, 0x31, 0x71, 0x86, 0xad, - 0x4b, 0x9b, 0xd5, 0xc6, 0xa6, 0xa8, 0x22, 0xd6, 0x7f, 0xbb, 0xde, 0xaa, 0x5c, 0xaf, 0xeb, 0x5b, - 0x42, 0xb4, 0xc2, 0x44, 0x77, 0x75, 0xd2, 0xd8, 0xae, 0x84, 0x43, 0x5e, 0xc3, 0x08, 0x72, 0x9b, - 0x95, 0xba, 0x46, 0x64, 0x2f, 0x0f, 0x15, 0x5c, 0x80, 0xac, 0x5e, 0x6f, 0xd7, 0x64, 0x3d, 0x81, - 0x4b, 0x50, 0xd4, 0xda, 0x46, 0xc3, 0xac, 0xd4, 0xcb, 0x44, 0xaf, 0xe9, 0x75, 0x43, 0x6a, 0x52, - 0xb8, 0x08, 0x05, 0xa3, 0x52, 0xd3, 0x5b, 0x86, 0x56, 0x6b, 0x4a, 0x21, 0x9b, 0x45, 0xa6, 0xa5, - 0x87, 0x36, 0x08, 0x2f, 0xc3, 0x52, 0xbd, 0x61, 0xca, 0x47, 0x45, 0xe6, 0x2d, 0xad, 0xda, 0xd6, - 0xa5, 0x6e, 0x05, 0x9f, 0x01, 0xdc, 0xa8, 0x9b, 0xed, 0xe6, 0x96, 0x66, 0xe8, 0x66, 0xbd, 0x71, - 0x5b, 0x2a, 0xae, 0xe1, 0x02, 0x64, 0xc6, 0x33, 0x78, 0xc8, 0x58, 0xc8, 0x37, 0x35, 0x62, 0x8c, - 0xc1, 0x3e, 0x7c, 0xc8, 0xc8, 0x82, 0xeb, 0xa4, 0xd1, 0x6e, 0x8e, 0xcd, 0x16, 0x20, 0x27, 0xc9, - 0x92, 0xa2, 0x14, 0x13, 0x6d, 0x56, 0xea, 0xe5, 0x68, 0x7e, 0x0f, 0x33, 0xcb, 0x09, 0xa4, 0xac, - 0xed, 0x41, 0x8a, 0xbb, 0x23, 0x03, 0xa9, 0x7a, 0xa3, 0xae, 0xa3, 0x53, 0x78, 0x1e, 0xa0, 0xd2, - 0xaa, 0xd4, 0x0d, 0xfd, 0x3a, 0xd1, 0xaa, 0x0c, 0x36, 0x17, 0x84, 0x04, 0x32, 0xb4, 0x73, 0x30, - 0x5b, 0x69, 0x6d, 0x57, 0x1b, 0x9a, 0x21, 0x61, 0x56, 0x5a, 0x37, 0xdb, 0x0d, 0x83, 0x29, 0x11, - 0xce, 0xc1, 0x4c, 0xa5, 0x65, 0xe8, 0x1f, 0x1a, 0x0c, 0x17, 0xd7, 0x09, 0x56, 0xd1, 0xc3, 0x6b, - 0x6b, 0x9f, 0x27, 0x21, 0xc5, 0x5f, 0x84, 0xe6, 0x21, 0xcb, 0xbd, 0x6d, 0xdc, 0x69, 0xb2, 0x21, - 0xb3, 0x90, 0xaa, 0xd4, 0x8d, 0xab, 0xe8, 0x2f, 0x12, 0x18, 0x20, 0xdd, 0xe6, 0xe5, 0xbf, 0x9c, - 0x61, 0xe5, 0x4a, 0xdd, 0x78, 0xeb, 0x0a, 0xfa, 0x38, 0xc1, 0xba, 0x6d, 0x8b, 0xca, 0x5f, 0x85, - 0x8a, 0x8d, 0xcb, 0xe8, 0x93, 0x48, 0xb1, 0x71, 0x19, 0xfd, 0x75, 0xa8, 0xb8, 0xb4, 0x81, 0xfe, - 0x26, 0x52, 0x5c, 0xda, 0x40, 0x7f, 0x1b, 0x2a, 0xae, 0x5c, 0x46, 0x7f, 0x17, 0x29, 0xae, 0x5c, - 0x46, 0x7f, 0x3f, 0xc3, 0xb0, 0x70, 0x24, 0x97, 0x36, 0xd0, 0x3f, 0x64, 0xa2, 0xda, 0x95, 0xcb, - 0xe8, 0x1f, 0x33, 0xcc, 0xff, 0x91, 0x57, 0xd1, 0x3f, 0x21, 0x36, 0x4d, 0xe6, 0x20, 0xf4, 0xcf, - 0xbc, 0xc8, 0x54, 0xe8, 0x5f, 0x10, 0xc3, 0xc8, 0xa4, 0xbc, 0xfa, 0x29, 0xd7, 0xdc, 0xd1, 0x35, - 0x82, 0xfe, 0x75, 0x46, 0xbc, 0x21, 0x2b, 0x57, 0x6a, 0x5a, 0x15, 0x61, 0xde, 0x82, 0xb1, 0xf2, - 0xef, 0x17, 0x59, 0x91, 0x85, 0x27, 0xfa, 0x8f, 0x26, 0x1b, 0xf0, 0x96, 0x46, 0xca, 0xef, 0x6b, - 0x04, 0xfd, 0xe7, 0x45, 0x36, 0xe0, 0x2d, 0x8d, 0x48, 0xbe, 0xfe, 0xab, 0xc9, 0x0c, 0xb9, 0xea, - 0xb3, 0x8b, 0x6c, 0xd2, 0x52, 0xfe, 0xdf, 0x4d, 0x9c, 0x81, 0xe4, 0x66, 0xc5, 0x40, 0x9f, 0xf3, - 0xd1, 0x58, 0x88, 0xa2, 0xff, 0x41, 0x4c, 0xd8, 0xd2, 0x0d, 0xf4, 0xbf, 0x4c, 0x98, 0x36, 0xda, - 0xcd, 0xaa, 0x8e, 0x5e, 0x60, 0x93, 0xbb, 0xae, 0x37, 0x6a, 0xba, 0x41, 0xee, 0xa0, 0xff, 0xe3, - 0xe6, 0x1f, 0xb4, 0x1a, 0x75, 0xf4, 0x05, 0xc2, 0x05, 0x00, 0xfd, 0xc3, 0x26, 0xd1, 0x5b, 0xad, - 0x4a, 0xa3, 0x8e, 0x5e, 0x5e, 0xdb, 0x06, 0x74, 0x34, 0x1d, 0x30, 0x00, 0xed, 0xfa, 0x8d, 0x7a, - 0xe3, 0x76, 0x1d, 0x9d, 0x62, 0x95, 0x26, 0xd1, 0x9b, 0x1a, 0xd1, 0x91, 0x82, 0x01, 0x66, 0xc4, - 0x0b, 0x37, 0x94, 0xc0, 0x73, 0x90, 0x21, 0x8d, 0x6a, 0x75, 0x53, 0x2b, 0xdf, 0x40, 0xc9, 0xcd, - 0xb7, 0x61, 0xde, 0x76, 0xd7, 0xf7, 0xed, 0x80, 0xfa, 0xbe, 0x78, 0x73, 0x7c, 0x57, 0x95, 0x35, - 0xdb, 0xbd, 0x20, 0x4a, 0x17, 0x7a, 0xee, 0x85, 0xfd, 0xe0, 0x02, 0xd7, 0x5e, 0xe0, 0x19, 0x63, - 0x67, 0x86, 0x57, 0x2e, 0xfd, 0x36, 0x00, 0x00, 0xff, 0xff, 0xce, 0x37, 0xe1, 0xd4, 0xd1, 0x2c, - 0x00, 0x00, +func init() { proto.RegisterFile("query.proto", fileDescriptor_query_9111254583ad7475) } + +var fileDescriptor_query_9111254583ad7475 = []byte{ + // 3231 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x4b, 0x73, 0x1b, 0xc7, + 0x76, 0xd6, 0xe0, 0x41, 0x02, 0x07, 0x04, 0xd8, 0x6c, 0x90, 0x12, 0x44, 0xf9, 0xda, 0xcc, 0xdc, + 0xab, 0x7b, 0x19, 0xde, 0x1b, 0x4a, 0xa6, 0x64, 0x45, 0xb1, 0x1d, 0x47, 0x43, 0x70, 0x28, 0xc3, + 0xc2, 0x4b, 0x8d, 0x81, 0x64, 0xa9, 0x5c, 0x35, 0x35, 0x04, 0x5a, 0xe0, 0x14, 0x07, 0x33, 0xd0, + 0xcc, 0x80, 0x14, 0x77, 0x4a, 0x1c, 0xe7, 0xfd, 0x70, 0x9e, 0x8e, 0x93, 0x8a, 0x93, 0xaa, 0xec, + 0xf3, 0x1b, 0x52, 0xf9, 0x01, 0xd9, 0x65, 0x91, 0x64, 0x91, 0x45, 0x2a, 0x95, 0x45, 0xaa, 0x5c, + 0x59, 0x65, 0x91, 0x45, 0x2a, 0xd5, 0x8f, 0x19, 0x0c, 0x48, 0xe8, 0x61, 0xe5, 0x6e, 0x28, 0x7b, + 0xd7, 0x7d, 0xce, 0xe9, 0xc7, 0xf7, 0x9d, 0x33, 0xa7, 0x7b, 0xba, 0x1b, 0x0a, 0x8f, 0xc7, 0xd4, + 0x3f, 0xde, 0x1c, 0xf9, 0x5e, 0xe8, 0xe1, 0x2c, 0xaf, 0xac, 0x96, 0x42, 0x6f, 0xe4, 0xf5, 0xad, + 0xd0, 0x12, 0xe2, 0xd5, 0xc2, 0x61, 0xe8, 0x8f, 0x7a, 0xa2, 0xa2, 0x7e, 0xa6, 0xc0, 0x9c, 0x61, + 0xf9, 0x03, 0x1a, 0xe2, 0x55, 0xc8, 0x1d, 0xd0, 0xe3, 0x60, 0x64, 0xf5, 0x68, 0x45, 0x59, 0x53, + 0xd6, 0xf3, 0x24, 0xae, 0xe3, 0x65, 0xc8, 0x06, 0xfb, 0x96, 0xdf, 0xaf, 0xa4, 0xb8, 0x42, 0x54, + 0xf0, 0x3b, 0x50, 0x08, 0xad, 0x3d, 0x87, 0x86, 0x66, 0x78, 0x3c, 0xa2, 0x95, 0xf4, 0x9a, 0xb2, + 0x5e, 0xda, 0x5a, 0xde, 0x8c, 0xc7, 0x33, 0xb8, 0xd2, 0x38, 0x1e, 0x51, 0x02, 0x61, 0x5c, 0xc6, + 0x18, 0x32, 0x3d, 0xea, 0x38, 0x95, 0x0c, 0xef, 0x8b, 0x97, 0xd5, 0x1d, 0x28, 0xdd, 0x33, 0x6e, + 0x5b, 0x21, 0xad, 0x5a, 0x8e, 0x43, 0xfd, 0xda, 0x0e, 0x9b, 0xce, 0x38, 0xa0, 0xbe, 0x6b, 0x0d, + 0xe3, 0xe9, 0x44, 0x75, 0x7c, 0x1e, 0xe6, 0x06, 0xbe, 0x37, 0x1e, 0x05, 0x95, 0xd4, 0x5a, 0x7a, + 0x3d, 0x4f, 0x64, 0x4d, 0xfd, 0x04, 0x40, 0x3f, 0xa4, 0x6e, 0x68, 0x78, 0x07, 0xd4, 0xc5, 0x6f, + 0x40, 0x3e, 0xb4, 0x87, 0x34, 0x08, 0xad, 0xe1, 0x88, 0x77, 0x91, 0x26, 0x13, 0xc1, 0x33, 0x20, + 0xad, 0x42, 0x6e, 0xe4, 0x05, 0x76, 0x68, 0x7b, 0x2e, 0xc7, 0x93, 0x27, 0x71, 0x5d, 0xfd, 0x00, + 0xb2, 0xf7, 0x2c, 0x67, 0x4c, 0xf1, 0x5b, 0x90, 0xe1, 0x80, 0x15, 0x0e, 0xb8, 0xb0, 0x29, 0x48, + 0xe7, 0x38, 0xb9, 0x82, 0xf5, 0x7d, 0xc8, 0x2c, 0x79, 0xdf, 0x0b, 0x44, 0x54, 0xd4, 0x03, 0x58, + 0xd8, 0xb6, 0xdd, 0xfe, 0x3d, 0xcb, 0xb7, 0x19, 0x19, 0xaf, 0xd8, 0x0d, 0xfe, 0x01, 0xcc, 0xf1, + 0x42, 0x50, 0x49, 0xaf, 0xa5, 0xd7, 0x0b, 0x5b, 0x0b, 0xb2, 0x21, 0x9f, 0x1b, 0x91, 0x3a, 0xf5, + 0xef, 0x15, 0x80, 0x6d, 0x6f, 0xec, 0xf6, 0xef, 0x32, 0x25, 0x46, 0x90, 0x0e, 0x1e, 0x3b, 0x92, + 0x48, 0x56, 0xc4, 0x77, 0xa0, 0xb4, 0x67, 0xbb, 0x7d, 0xf3, 0x50, 0x4e, 0x47, 0x70, 0x59, 0xd8, + 0xfa, 0x81, 0xec, 0x6e, 0xd2, 0x78, 0x33, 0x39, 0xeb, 0x40, 0x77, 0x43, 0xff, 0x98, 0x14, 0xf7, + 0x92, 0xb2, 0xd5, 0x2e, 0xe0, 0xd3, 0x46, 0x6c, 0xd0, 0x03, 0x7a, 0x1c, 0x0d, 0x7a, 0x40, 0x8f, + 0xf1, 0xcf, 0x26, 0x11, 0x15, 0xb6, 0xca, 0xd1, 0x58, 0x89, 0xb6, 0x12, 0xe6, 0xbb, 0xa9, 0x9b, + 0x8a, 0xfa, 0x9f, 0x59, 0x28, 0xe9, 0x4f, 0x68, 0x6f, 0x1c, 0xd2, 0xd6, 0x88, 0xf9, 0x20, 0xc0, + 0x9b, 0x50, 0xb6, 0xdd, 0x9e, 0x33, 0xee, 0x53, 0x93, 0x32, 0x57, 0x9b, 0x21, 0xf3, 0x35, 0xef, + 0x2f, 0x47, 0x96, 0xa4, 0x2a, 0x11, 0x04, 0x1a, 0x94, 0x7b, 0xde, 0x70, 0x64, 0xf9, 0xd3, 0xf6, + 0x69, 0x3e, 0xfe, 0x92, 0x1c, 0x7f, 0x62, 0x4f, 0x96, 0xa4, 0x75, 0xa2, 0x8b, 0x06, 0x2c, 0xca, + 0x7e, 0xfb, 0xe6, 0x23, 0x9b, 0x3a, 0xfd, 0x80, 0x87, 0x6e, 0x29, 0xa6, 0x6a, 0x7a, 0x8a, 0x9b, + 0x35, 0x69, 0xbc, 0xcb, 0x6d, 0x49, 0xc9, 0x9e, 0xaa, 0xe3, 0x0d, 0x58, 0xea, 0x39, 0x36, 0x9b, + 0xca, 0x23, 0x46, 0xb1, 0xe9, 0x7b, 0x47, 0x41, 0x25, 0xcb, 0xe7, 0xbf, 0x28, 0x14, 0xbb, 0x4c, + 0x4e, 0xbc, 0xa3, 0x00, 0xbf, 0x0b, 0xb9, 0x23, 0xcf, 0x3f, 0x70, 0x3c, 0xab, 0x5f, 0x99, 0xe3, + 0x63, 0xbe, 0x39, 0x7b, 0xcc, 0xfb, 0xd2, 0x8a, 0xc4, 0xf6, 0x78, 0x1d, 0x50, 0xf0, 0xd8, 0x31, + 0x03, 0xea, 0xd0, 0x5e, 0x68, 0x3a, 0xf6, 0xd0, 0x0e, 0x2b, 0x39, 0xfe, 0x15, 0x94, 0x82, 0xc7, + 0x4e, 0x87, 0x8b, 0xeb, 0x4c, 0x8a, 0x4d, 0x58, 0x09, 0x7d, 0xcb, 0x0d, 0xac, 0x1e, 0xeb, 0xcc, + 0xb4, 0x03, 0xcf, 0xb1, 0xf8, 0x17, 0x90, 0xe7, 0x43, 0x6e, 0xcc, 0x1e, 0xd2, 0x98, 0x34, 0xa9, + 0x45, 0x2d, 0xc8, 0x72, 0x38, 0x43, 0x8a, 0xdf, 0x86, 0x95, 0xe0, 0xc0, 0x1e, 0x99, 0xbc, 0x1f, + 0x73, 0xe4, 0x58, 0xae, 0xd9, 0xb3, 0x7a, 0xfb, 0xb4, 0x02, 0x1c, 0x36, 0x66, 0x4a, 0x1e, 0x6a, + 0x6d, 0xc7, 0x72, 0xab, 0x4c, 0xa3, 0xbe, 0x07, 0xa5, 0x69, 0x1e, 0xf1, 0x12, 0x14, 0x8d, 0x07, + 0x6d, 0xdd, 0xd4, 0x9a, 0x3b, 0x66, 0x53, 0x6b, 0xe8, 0xe8, 0x1c, 0x2e, 0x42, 0x9e, 0x8b, 0x5a, + 0xcd, 0xfa, 0x03, 0xa4, 0xe0, 0x79, 0x48, 0x6b, 0xf5, 0x3a, 0x4a, 0xa9, 0x37, 0x21, 0x17, 0x11, + 0x82, 0x17, 0xa1, 0xd0, 0x6d, 0x76, 0xda, 0x7a, 0xb5, 0xb6, 0x5b, 0xd3, 0x77, 0xd0, 0x39, 0x9c, + 0x83, 0x4c, 0xab, 0x6e, 0xb4, 0x91, 0x22, 0x4a, 0x5a, 0x1b, 0xa5, 0x58, 0xcb, 0x9d, 0x6d, 0x0d, + 0xa5, 0xd5, 0x10, 0x96, 0x67, 0xe1, 0xc2, 0x05, 0x98, 0xdf, 0xd1, 0x77, 0xb5, 0x6e, 0xdd, 0x40, + 0xe7, 0x70, 0x19, 0x16, 0x89, 0xde, 0xd6, 0x35, 0x43, 0xdb, 0xae, 0xeb, 0x26, 0xd1, 0xb5, 0x1d, + 0xa4, 0x60, 0x0c, 0x25, 0x56, 0x32, 0xab, 0xad, 0x46, 0xa3, 0x66, 0x18, 0xfa, 0x0e, 0x4a, 0xe1, + 0x65, 0x40, 0x5c, 0xd6, 0x6d, 0x4e, 0xa4, 0x69, 0x8c, 0x60, 0xa1, 0xa3, 0x93, 0x9a, 0x56, 0xaf, + 0x3d, 0x64, 0x1d, 0xa0, 0xcc, 0x47, 0x99, 0x9c, 0x82, 0x52, 0xea, 0x17, 0x29, 0xc8, 0x72, 0xac, + 0x2c, 0x43, 0x26, 0xf2, 0x1e, 0x2f, 0xc7, 0xd9, 0x22, 0xf5, 0x9c, 0x6c, 0xc1, 0x93, 0xac, 0xcc, + 0x5b, 0xa2, 0x82, 0x2f, 0x41, 0xde, 0xf3, 0x07, 0xa6, 0xd0, 0x88, 0x8c, 0x9b, 0xf3, 0xfc, 0x01, + 0x4f, 0xcd, 0x2c, 0xdb, 0xb1, 0x44, 0xbd, 0x67, 0x05, 0x94, 0x47, 0x60, 0x9e, 0xc4, 0x75, 0x7c, + 0x11, 0x98, 0x9d, 0xc9, 0xe7, 0x31, 0xc7, 0x75, 0xf3, 0x9e, 0x3f, 0x68, 0xb2, 0xa9, 0x7c, 0x1f, + 0x8a, 0x3d, 0xcf, 0x19, 0x0f, 0x5d, 0xd3, 0xa1, 0xee, 0x20, 0xdc, 0xaf, 0xcc, 0xaf, 0x29, 0xeb, + 0x45, 0xb2, 0x20, 0x84, 0x75, 0x2e, 0xc3, 0x15, 0x98, 0xef, 0xed, 0x5b, 0x7e, 0x40, 0x45, 0xd4, + 0x15, 0x49, 0x54, 0xe5, 0xa3, 0xd2, 0x9e, 0x3d, 0xb4, 0x9c, 0x80, 0x47, 0x58, 0x91, 0xc4, 0x75, + 0x06, 0xe2, 0x91, 0x63, 0x0d, 0x02, 0x1e, 0x19, 0x45, 0x22, 0x2a, 0xea, 0xcf, 0x43, 0x9a, 0x78, + 0x47, 0xac, 0x4b, 0x31, 0x60, 0x50, 0x51, 0xd6, 0xd2, 0xeb, 0x98, 0x44, 0x55, 0xb6, 0x20, 0xc8, + 0x9c, 0x28, 0x52, 0x65, 0x94, 0x05, 0x3f, 0x81, 0x05, 0x42, 0x83, 0xb1, 0x13, 0xea, 0x4f, 0x42, + 0xdf, 0x0a, 0xf0, 0x16, 0x14, 0x92, 0x59, 0x40, 0x79, 0x56, 0x16, 0x00, 0x3a, 0xf9, 0xfc, 0x2b, + 0x30, 0xff, 0xc8, 0xa7, 0xc1, 0x3e, 0xf5, 0x65, 0x96, 0x89, 0xaa, 0x2c, 0xc7, 0x16, 0x78, 0xd8, + 0x8a, 0x31, 0x58, 0x66, 0x96, 0xf9, 0x41, 0x99, 0xca, 0xcc, 0xdc, 0xa9, 0x44, 0xea, 0x18, 0x7b, + 0xec, 0x93, 0x37, 0xad, 0x47, 0x8f, 0x68, 0x2f, 0xa4, 0x62, 0x01, 0xca, 0x90, 0x05, 0x26, 0xd4, + 0xa4, 0x8c, 0xb9, 0xcd, 0x76, 0x03, 0xea, 0x87, 0xa6, 0xdd, 0xe7, 0x0e, 0xcd, 0x90, 0x9c, 0x10, + 0xd4, 0xfa, 0xf8, 0x4d, 0xc8, 0xf0, 0xa4, 0x91, 0xe1, 0xa3, 0x80, 0x1c, 0x85, 0x78, 0x47, 0x84, + 0xcb, 0xf1, 0x8f, 0x61, 0x8e, 0x72, 0xbc, 0xdc, 0xa9, 0x93, 0x34, 0x9b, 0xa4, 0x82, 0x48, 0x13, + 0xf5, 0x7d, 0x58, 0xe0, 0x18, 0xee, 0x5b, 0xbe, 0x6b, 0xbb, 0x03, 0xbe, 0x3a, 0x7b, 0x7d, 0x11, + 0x7b, 0x45, 0xc2, 0xcb, 0x8c, 0x82, 0x21, 0x0d, 0x02, 0x6b, 0x40, 0xe5, 0x6a, 0x19, 0x55, 0xd5, + 0xbf, 0x4e, 0x43, 0xa1, 0x13, 0xfa, 0xd4, 0x1a, 0x72, 0xf6, 0xf0, 0xfb, 0x00, 0x41, 0x68, 0x85, + 0x74, 0x48, 0xdd, 0x30, 0xa2, 0xe1, 0x0d, 0x39, 0x7c, 0xc2, 0x6e, 0xb3, 0x13, 0x19, 0x91, 0x84, + 0xfd, 0x49, 0xf7, 0xa4, 0x5e, 0xc2, 0x3d, 0xab, 0x5f, 0xa5, 0x20, 0x1f, 0xf7, 0x86, 0x35, 0xc8, + 0xf5, 0xac, 0x90, 0x0e, 0x3c, 0xff, 0x58, 0xae, 0xab, 0x97, 0x9f, 0x37, 0xfa, 0x66, 0x55, 0x1a, + 0x93, 0xb8, 0x19, 0xfe, 0x1e, 0x88, 0xcd, 0x8a, 0x08, 0x7d, 0x81, 0x37, 0xcf, 0x25, 0x3c, 0xf8, + 0xdf, 0x05, 0x3c, 0xf2, 0xed, 0xa1, 0xe5, 0x1f, 0x9b, 0x07, 0xf4, 0x38, 0x5a, 0x10, 0xd2, 0x33, + 0x1c, 0x8e, 0xa4, 0xdd, 0x1d, 0x7a, 0x2c, 0x53, 0xd8, 0xcd, 0xe9, 0xb6, 0x32, 0x64, 0x4f, 0xbb, + 0x31, 0xd1, 0x92, 0xaf, 0xea, 0x41, 0xb4, 0x7e, 0x67, 0x79, 0x74, 0xb3, 0xa2, 0xfa, 0x23, 0xc8, + 0x45, 0x93, 0xc7, 0x79, 0xc8, 0xea, 0xbe, 0xef, 0xf9, 0xe8, 0x1c, 0xcf, 0x64, 0x8d, 0xba, 0x48, + 0x86, 0x3b, 0x3b, 0x2c, 0x19, 0xfe, 0x5d, 0x2a, 0x5e, 0x44, 0x09, 0x7d, 0x3c, 0xa6, 0x41, 0x88, + 0x7f, 0x09, 0xca, 0x94, 0x47, 0x9a, 0x7d, 0x48, 0xcd, 0x1e, 0xdf, 0x71, 0xb1, 0x38, 0x13, 0x9f, + 0xc3, 0xe2, 0xa6, 0xd8, 0x20, 0x46, 0x3b, 0x31, 0xb2, 0x14, 0xdb, 0x4a, 0x51, 0x1f, 0xeb, 0x50, + 0xb6, 0x87, 0x43, 0xda, 0xb7, 0xad, 0x30, 0xd9, 0x81, 0x70, 0xd8, 0x4a, 0xb4, 0x21, 0x99, 0xda, + 0xd0, 0x91, 0xa5, 0xb8, 0x45, 0xdc, 0xcd, 0x65, 0x98, 0x0b, 0xf9, 0xe6, 0x53, 0xae, 0xc7, 0xc5, + 0x28, 0xab, 0x71, 0x21, 0x91, 0x4a, 0xfc, 0x23, 0x10, 0x5b, 0x59, 0x9e, 0xbf, 0x26, 0x01, 0x31, + 0xd9, 0xa1, 0x10, 0xa1, 0xc7, 0x97, 0xa1, 0x34, 0xb5, 0x90, 0xf5, 0x39, 0x61, 0x69, 0x52, 0x4c, + 0xae, 0x4a, 0x7d, 0x7c, 0x05, 0xe6, 0x3d, 0xb1, 0x88, 0xf1, 0xcc, 0x36, 0x99, 0xf1, 0xf4, 0x0a, + 0x47, 0x22, 0x2b, 0xf5, 0x17, 0x61, 0x31, 0x66, 0x30, 0x18, 0x79, 0x6e, 0x40, 0xf1, 0x06, 0xcc, + 0xf9, 0xfc, 0x73, 0x92, 0xac, 0x61, 0xd9, 0x45, 0x22, 0x1f, 0x10, 0x69, 0xa1, 0xf6, 0x61, 0x51, + 0x48, 0xee, 0xdb, 0xe1, 0x3e, 0x77, 0x14, 0xbe, 0x0c, 0x59, 0xca, 0x0a, 0x27, 0x38, 0x27, 0xed, + 0x2a, 0xd7, 0x13, 0xa1, 0x4d, 0x8c, 0x92, 0x7a, 0xe1, 0x28, 0xff, 0x95, 0x82, 0xb2, 0x9c, 0xe5, + 0xb6, 0x15, 0xf6, 0xf6, 0xcf, 0xa8, 0xb3, 0x7f, 0x0c, 0xf3, 0x4c, 0x6e, 0xc7, 0x1f, 0xc6, 0x0c, + 0x77, 0x47, 0x16, 0xcc, 0xe1, 0x56, 0x60, 0x26, 0xbc, 0x2b, 0x37, 0x52, 0x45, 0x2b, 0x48, 0x2c, + 0xe3, 0x33, 0xe2, 0x62, 0xee, 0x05, 0x71, 0x31, 0xff, 0x52, 0x71, 0xb1, 0x03, 0xcb, 0xd3, 0x8c, + 0xcb, 0xe0, 0xf8, 0x09, 0xcc, 0x0b, 0xa7, 0x44, 0x29, 0x70, 0x96, 0xdf, 0x22, 0x13, 0xf5, 0xaf, + 0x52, 0xb0, 0x2c, 0xb3, 0xd3, 0xb7, 0xe3, 0x33, 0x4d, 0xf0, 0x9c, 0x7d, 0x29, 0x9e, 0xab, 0xb0, + 0x72, 0x82, 0xa0, 0x57, 0xf8, 0x0a, 0xbf, 0x56, 0x60, 0x61, 0x9b, 0x0e, 0x6c, 0xf7, 0x8c, 0xd2, + 0x9b, 0x60, 0x2d, 0xf3, 0x52, 0xac, 0xdd, 0x80, 0xa2, 0xc4, 0x2b, 0xd9, 0x3a, 0xfd, 0x19, 0x28, + 0x33, 0x3e, 0x03, 0xf5, 0xdf, 0x15, 0x28, 0x56, 0xbd, 0xe1, 0xd0, 0x0e, 0xcf, 0x28, 0x53, 0xa7, + 0x71, 0x66, 0x66, 0xe1, 0x44, 0x50, 0x8a, 0x60, 0x0a, 0x82, 0xd4, 0xff, 0x50, 0x60, 0x91, 0x78, + 0x8e, 0xb3, 0x67, 0xf5, 0x0e, 0x5e, 0x6f, 0xec, 0x18, 0xd0, 0x04, 0xa8, 0x44, 0xff, 0x3f, 0x0a, + 0x94, 0xda, 0x3e, 0x65, 0x7f, 0xbf, 0xaf, 0x35, 0x78, 0xb6, 0xc5, 0xed, 0x87, 0x72, 0x73, 0x90, + 0x27, 0xbc, 0xac, 0x2e, 0xc1, 0x62, 0x8c, 0x5d, 0xf2, 0xf1, 0xcf, 0x0a, 0xac, 0x88, 0x00, 0x91, + 0x9a, 0xfe, 0x19, 0xa5, 0x25, 0xc2, 0x9b, 0x49, 0xe0, 0xad, 0xc0, 0xf9, 0x93, 0xd8, 0x24, 0xec, + 0x4f, 0x53, 0x70, 0x21, 0x8a, 0x8d, 0x33, 0x0e, 0xfc, 0xff, 0x11, 0x0f, 0xab, 0x50, 0x39, 0x4d, + 0x82, 0x64, 0xe8, 0xf3, 0x14, 0x54, 0xaa, 0x3e, 0xb5, 0x42, 0x9a, 0xd8, 0x64, 0xbc, 0x3e, 0xb1, + 0x81, 0xdf, 0x86, 0x85, 0x91, 0xe5, 0x87, 0x76, 0xcf, 0x1e, 0x59, 0xec, 0x37, 0x2e, 0xcb, 0xf7, + 0x30, 0x27, 0x3a, 0x98, 0x32, 0x51, 0x2f, 0xc1, 0xc5, 0x19, 0x8c, 0x48, 0xbe, 0xfe, 0x57, 0x01, + 0xdc, 0x09, 0x2d, 0x3f, 0xfc, 0x16, 0xac, 0x2a, 0x33, 0x83, 0x69, 0x05, 0xca, 0x53, 0xf8, 0x93, + 0xbc, 0xd0, 0xf0, 0x5b, 0xb1, 0xe2, 0x3c, 0x93, 0x97, 0x24, 0x7e, 0xc9, 0xcb, 0xbf, 0x2a, 0xb0, + 0x5a, 0xf5, 0xc4, 0xe9, 0xdf, 0x6b, 0xf9, 0x85, 0xa9, 0xdf, 0x83, 0x4b, 0x33, 0x01, 0x4a, 0x02, + 0xfe, 0x45, 0x81, 0xf3, 0x84, 0x5a, 0xfd, 0xd7, 0x13, 0xfc, 0x5d, 0xb8, 0x70, 0x0a, 0x9c, 0xdc, + 0xa1, 0xde, 0x80, 0xdc, 0x90, 0x86, 0x56, 0xdf, 0x0a, 0x2d, 0x09, 0x69, 0x35, 0xea, 0x77, 0x62, + 0xdd, 0x90, 0x16, 0x24, 0xb6, 0x55, 0xbf, 0x4a, 0x41, 0x99, 0xef, 0x75, 0xbf, 0xfb, 0x83, 0x9a, + 0xfd, 0x2f, 0xf0, 0xb9, 0x02, 0xcb, 0xd3, 0x04, 0xc5, 0xff, 0x04, 0x3f, 0xed, 0x83, 0x88, 0x19, + 0x09, 0x21, 0x3d, 0x6b, 0x0b, 0xfa, 0x0f, 0x29, 0xa8, 0x24, 0xa7, 0xf4, 0xdd, 0xa1, 0xc5, 0xf4, + 0xa1, 0xc5, 0x37, 0x3e, 0xa5, 0xfa, 0x42, 0x81, 0x8b, 0x33, 0x08, 0xfd, 0x66, 0x8e, 0x4e, 0x1c, + 0x5d, 0xa4, 0x5e, 0x78, 0x74, 0xf1, 0xb2, 0xae, 0xfe, 0x27, 0x05, 0x96, 0x1b, 0xe2, 0xc4, 0x58, + 0xfc, 0xc7, 0x9f, 0xdd, 0x6c, 0xc6, 0x0f, 0x85, 0x33, 0x93, 0x7b, 0x19, 0xb5, 0x0a, 0x2b, 0x27, + 0xa0, 0xbd, 0xc2, 0xd9, 0xc4, 0x7f, 0x2b, 0xb0, 0x24, 0x7b, 0xd1, 0xce, 0xec, 0x46, 0x60, 0x06, + 0x3b, 0xf8, 0x4d, 0x48, 0xdb, 0xfd, 0x68, 0x07, 0x39, 0x7d, 0x53, 0xcd, 0x14, 0xea, 0x2d, 0xc0, + 0x49, 0xdc, 0xaf, 0x40, 0xdd, 0x3f, 0xa6, 0x61, 0xa9, 0x33, 0x72, 0xec, 0x50, 0x2a, 0x5f, 0xef, + 0xc4, 0xff, 0x33, 0xb0, 0x10, 0x30, 0xb0, 0xa6, 0xb8, 0x6b, 0xe3, 0xc4, 0xe6, 0x49, 0x81, 0xcb, + 0xaa, 0x5c, 0x84, 0xdf, 0x82, 0x42, 0x64, 0x32, 0x76, 0x43, 0x79, 0xd2, 0x09, 0xd2, 0x62, 0xec, + 0x86, 0xf8, 0x3a, 0x5c, 0x70, 0xc7, 0x43, 0x7e, 0xef, 0x6c, 0x8e, 0xa8, 0x1f, 0xdd, 0xca, 0x5a, + 0x7e, 0x74, 0x3f, 0x5c, 0x76, 0xc7, 0x43, 0xe2, 0x1d, 0x05, 0x6d, 0xea, 0x8b, 0x5b, 0x59, 0xcb, + 0x0f, 0xf1, 0x2d, 0xc8, 0x5b, 0xce, 0xc0, 0xf3, 0xed, 0x70, 0x7f, 0x28, 0x2f, 0x86, 0xd5, 0xe8, + 0x6a, 0xe5, 0x24, 0xfd, 0x9b, 0x5a, 0x64, 0x49, 0x26, 0x8d, 0xd4, 0x9f, 0x40, 0x3e, 0x96, 0x63, + 0x04, 0x0b, 0xfa, 0xdd, 0xae, 0x56, 0x37, 0x3b, 0xed, 0x7a, 0xcd, 0xe8, 0x88, 0xcb, 0xdc, 0xdd, + 0x6e, 0xbd, 0x6e, 0x76, 0xaa, 0x5a, 0x13, 0x29, 0x2a, 0x01, 0xe0, 0x5d, 0xf2, 0xce, 0x27, 0x04, + 0x29, 0x2f, 0x20, 0xe8, 0x12, 0xe4, 0x7d, 0xef, 0x48, 0x62, 0x4f, 0x71, 0x38, 0x39, 0xdf, 0x3b, + 0xe2, 0xc8, 0x55, 0x0d, 0x70, 0x72, 0xae, 0x32, 0xda, 0x12, 0xc9, 0x5b, 0x99, 0x4a, 0xde, 0x93, + 0xf1, 0xe3, 0xe4, 0x2d, 0xb6, 0xf2, 0xec, 0x3b, 0xff, 0x90, 0x5a, 0x4e, 0x18, 0xad, 0x57, 0xea, + 0xdf, 0xa4, 0xa0, 0x48, 0x98, 0xc4, 0x1e, 0xd2, 0x4e, 0x68, 0x85, 0x01, 0xf3, 0xd4, 0x3e, 0x37, + 0x31, 0x27, 0x69, 0x37, 0x4f, 0x0a, 0x42, 0x26, 0x2e, 0x01, 0xb6, 0x60, 0x25, 0xa0, 0x3d, 0xcf, + 0xed, 0x07, 0xe6, 0x1e, 0xdd, 0xb7, 0xdd, 0xbe, 0x39, 0xb4, 0x82, 0x50, 0xde, 0x33, 0x16, 0x49, + 0x59, 0x2a, 0xb7, 0xb9, 0xae, 0xc1, 0x55, 0xf8, 0x2a, 0x2c, 0xef, 0xd9, 0xae, 0xe3, 0x0d, 0xcc, + 0x91, 0x63, 0x1d, 0x53, 0x3f, 0x90, 0x50, 0x59, 0x78, 0x65, 0x09, 0x16, 0xba, 0xb6, 0x50, 0x09, + 0x77, 0x3f, 0x84, 0x8d, 0x99, 0xa3, 0x98, 0x8f, 0x6c, 0x27, 0xa4, 0x3e, 0xed, 0x9b, 0x3e, 0x1d, + 0x39, 0x76, 0x4f, 0x5c, 0xf9, 0x8b, 0xbd, 0xfb, 0x0f, 0x67, 0x0c, 0xbd, 0x2b, 0xcd, 0xc9, 0xc4, + 0x9a, 0xb1, 0xdd, 0x1b, 0x8d, 0xcd, 0x31, 0xbf, 0x1a, 0x64, 0xab, 0x98, 0x42, 0x72, 0xbd, 0xd1, + 0xb8, 0xcb, 0xea, 0x18, 0x41, 0xfa, 0xf1, 0x48, 0x2c, 0x5e, 0x0a, 0x61, 0x45, 0xf5, 0x6b, 0x05, + 0x4a, 0xda, 0x60, 0xe0, 0xd3, 0x81, 0x15, 0x4a, 0x9a, 0xae, 0xc2, 0xb2, 0xa0, 0xe4, 0xd8, 0x94, + 0x6f, 0x89, 0x04, 0x1e, 0x45, 0xe0, 0x91, 0x3a, 0xf1, 0x92, 0x28, 0x0a, 0xdf, 0xf3, 0x63, 0x77, + 0x66, 0x9b, 0x14, 0x6f, 0xb3, 0x1c, 0x6b, 0x93, 0xad, 0x7e, 0x01, 0x2e, 0xce, 0x66, 0x61, 0x68, + 0x8b, 0xd7, 0x20, 0x45, 0x72, 0x7e, 0x06, 0xe8, 0x86, 0xed, 0x3e, 0xa7, 0xa9, 0xf5, 0x84, 0xf3, + 0xf5, 0x8c, 0xa6, 0xd6, 0x13, 0xf5, 0xdf, 0xe2, 0xa3, 0xfd, 0x28, 0x5c, 0xe2, 0xd5, 0x38, 0xca, + 0x0b, 0xca, 0xf3, 0xf2, 0x42, 0x05, 0xe6, 0x03, 0xea, 0x1f, 0xda, 0xee, 0x20, 0xba, 0x7b, 0x96, + 0x55, 0xdc, 0x81, 0x1f, 0x4a, 0xec, 0xf4, 0x49, 0x48, 0x7d, 0xd7, 0x72, 0x9c, 0x63, 0x53, 0x1c, + 0x54, 0xb8, 0x21, 0xed, 0x9b, 0x93, 0x97, 0x4f, 0x62, 0x45, 0xfe, 0xbe, 0xb0, 0xd6, 0x63, 0x63, + 0x12, 0xdb, 0x1a, 0xf1, 0x9b, 0xa8, 0xf7, 0xa0, 0xe4, 0xcb, 0x20, 0x36, 0x03, 0xe6, 0x1e, 0x99, + 0x8f, 0x96, 0xe3, 0x0b, 0xe4, 0x44, 0x84, 0x93, 0xa2, 0x3f, 0x15, 0xf0, 0x1f, 0xc0, 0xa2, 0x15, + 0xf9, 0x56, 0xb6, 0x9e, 0xde, 0xb7, 0x4c, 0x7b, 0x9e, 0x94, 0xac, 0xe9, 0x48, 0xb8, 0x09, 0x0b, + 0x12, 0x91, 0xe5, 0xd8, 0xd6, 0x64, 0x63, 0x7b, 0xe2, 0x39, 0x99, 0xc6, 0x94, 0x44, 0x3e, 0x3c, + 0xe3, 0x15, 0xf6, 0x1f, 0x5d, 0xee, 0x8e, 0xfa, 0xbc, 0xa7, 0x33, 0xbc, 0xbb, 0x48, 0xbe, 0x3d, + 0xcb, 0x4c, 0xbf, 0x3d, 0x9b, 0x7e, 0xcb, 0x96, 0x3d, 0xf1, 0x96, 0x4d, 0xbd, 0x05, 0xcb, 0xd3, + 0xf8, 0x65, 0x94, 0xad, 0x43, 0x96, 0xdf, 0x94, 0x9f, 0x58, 0x46, 0x13, 0x57, 0xe1, 0x44, 0x18, + 0xa8, 0x7f, 0xab, 0x40, 0x79, 0xc6, 0x2f, 0x56, 0xfc, 0xff, 0xa6, 0x24, 0x8e, 0x87, 0x7e, 0x0e, + 0xb2, 0xfc, 0xce, 0x5e, 0x3e, 0x45, 0xb9, 0x70, 0xfa, 0x0f, 0x8d, 0xdf, 0xaf, 0x13, 0x61, 0xc5, + 0x12, 0x21, 0x0f, 0xa8, 0x1e, 0x3f, 0x1f, 0x8a, 0x76, 0x88, 0x05, 0x26, 0x13, 0x47, 0x46, 0xa7, + 0x0f, 0x9c, 0x32, 0x2f, 0x3c, 0x70, 0xda, 0xf8, 0xc3, 0x34, 0xe4, 0x1b, 0xc7, 0x9d, 0xc7, 0xce, + 0xae, 0x63, 0x0d, 0xf8, 0x05, 0x78, 0xa3, 0x6d, 0x3c, 0x40, 0xe7, 0xf0, 0x12, 0x14, 0x9b, 0x2d, + 0xc3, 0x6c, 0xb2, 0xa5, 0x64, 0xb7, 0xae, 0xdd, 0x46, 0x0a, 0x5b, 0x6b, 0xda, 0xa4, 0x66, 0xde, + 0xd1, 0x1f, 0x08, 0x49, 0x0a, 0x97, 0x61, 0xb1, 0xdb, 0xac, 0xdd, 0xed, 0xea, 0x13, 0x61, 0x06, + 0xaf, 0xc0, 0x52, 0xa3, 0x5b, 0x37, 0x6a, 0xed, 0x7a, 0x42, 0x9c, 0x63, 0xeb, 0xd2, 0x76, 0xbd, + 0xb5, 0x2d, 0xaa, 0x88, 0xf5, 0xdf, 0x6d, 0x76, 0x6a, 0xb7, 0x9b, 0xfa, 0x8e, 0x10, 0xad, 0x31, + 0xd1, 0x43, 0x9d, 0xb4, 0x76, 0x6b, 0xd1, 0x90, 0xb7, 0x30, 0x82, 0xc2, 0x76, 0xad, 0xa9, 0x11, + 0xd9, 0xcb, 0x53, 0x05, 0x97, 0x20, 0xaf, 0x37, 0xbb, 0x0d, 0x59, 0x4f, 0xe1, 0x0a, 0x94, 0xb5, + 0xae, 0xd1, 0x32, 0x6b, 0xcd, 0x2a, 0xd1, 0x1b, 0x7a, 0xd3, 0x90, 0x9a, 0x0c, 0x2e, 0x43, 0xc9, + 0xa8, 0x35, 0xf4, 0x8e, 0xa1, 0x35, 0xda, 0x52, 0xc8, 0x66, 0x91, 0xeb, 0xe8, 0x91, 0x0d, 0xc2, + 0xab, 0xb0, 0xd2, 0x6c, 0x99, 0xf2, 0x49, 0x92, 0x79, 0x4f, 0xab, 0x77, 0x75, 0xa9, 0x5b, 0xc3, + 0x17, 0x00, 0xb7, 0x9a, 0x66, 0xb7, 0xbd, 0xa3, 0x19, 0xba, 0xd9, 0x6c, 0xdd, 0x97, 0x8a, 0x5b, + 0xb8, 0x04, 0xb9, 0xc9, 0x0c, 0x9e, 0x32, 0x16, 0x8a, 0x6d, 0x8d, 0x18, 0x13, 0xb0, 0x4f, 0x9f, + 0x32, 0xb2, 0xe0, 0x36, 0x69, 0x75, 0xdb, 0x13, 0xb3, 0x25, 0x28, 0x48, 0xb2, 0xa4, 0x28, 0xc3, + 0x44, 0xdb, 0xb5, 0x66, 0x35, 0x9e, 0xdf, 0xd3, 0xdc, 0x6a, 0x0a, 0x29, 0x1b, 0x07, 0x90, 0xe1, + 0xee, 0xc8, 0x41, 0xa6, 0xd9, 0x6a, 0xea, 0xe8, 0x1c, 0x5e, 0x04, 0xa8, 0x75, 0x6a, 0x4d, 0x43, + 0xbf, 0x4d, 0xb4, 0x3a, 0x83, 0xcd, 0x05, 0x11, 0x81, 0x0c, 0xed, 0x02, 0xcc, 0xd7, 0x3a, 0xbb, + 0xf5, 0x96, 0x66, 0x48, 0x98, 0xb5, 0xce, 0xdd, 0x6e, 0xcb, 0x60, 0x4a, 0x84, 0x0b, 0x30, 0x57, + 0xeb, 0x18, 0xfa, 0xc7, 0x06, 0xc3, 0xc5, 0x75, 0x82, 0x55, 0xf4, 0xf4, 0xd6, 0xc6, 0x97, 0x69, + 0xc8, 0xf0, 0xf7, 0xa4, 0x45, 0xc8, 0x73, 0x6f, 0x1b, 0x0f, 0xda, 0x6c, 0xc8, 0x3c, 0x64, 0x6a, + 0x4d, 0xe3, 0x26, 0xfa, 0xe5, 0x14, 0x06, 0xc8, 0x76, 0x79, 0xf9, 0x57, 0xe6, 0x58, 0xb9, 0xd6, + 0x34, 0xde, 0xbe, 0x81, 0x3e, 0x4d, 0xb1, 0x6e, 0xbb, 0xa2, 0xf2, 0xab, 0x91, 0x62, 0xeb, 0x3a, + 0xfa, 0x2c, 0x56, 0x6c, 0x5d, 0x47, 0xbf, 0x16, 0x29, 0xae, 0x6d, 0xa1, 0x5f, 0x8f, 0x15, 0xd7, + 0xb6, 0xd0, 0x6f, 0x44, 0x8a, 0x1b, 0xd7, 0xd1, 0x6f, 0xc6, 0x8a, 0x1b, 0xd7, 0xd1, 0x6f, 0xcd, + 0x31, 0x2c, 0x1c, 0xc9, 0xb5, 0x2d, 0xf4, 0xdb, 0xb9, 0xb8, 0x76, 0xe3, 0x3a, 0xfa, 0x9d, 0x1c, + 0xf3, 0x7f, 0xec, 0x55, 0xf4, 0xbb, 0x88, 0x4d, 0x93, 0x39, 0x08, 0xfd, 0x1e, 0x2f, 0x32, 0x15, + 0xfa, 0x7d, 0xc4, 0x30, 0x32, 0x29, 0xaf, 0x7e, 0xce, 0x35, 0x0f, 0x74, 0x8d, 0xa0, 0x3f, 0x98, + 0x13, 0x2f, 0xd0, 0xaa, 0xb5, 0x86, 0x56, 0x47, 0x98, 0xb7, 0x60, 0xac, 0xfc, 0xd1, 0x55, 0x56, + 0x64, 0xe1, 0x89, 0xfe, 0xb8, 0xcd, 0x06, 0xbc, 0xa7, 0x91, 0xea, 0x87, 0x1a, 0x41, 0x7f, 0x72, + 0x95, 0x0d, 0x78, 0x4f, 0x23, 0x92, 0xaf, 0x3f, 0x6d, 0x33, 0x43, 0xae, 0xfa, 0xe2, 0x2a, 0x9b, + 0xb4, 0x94, 0xff, 0x59, 0x1b, 0xe7, 0x20, 0xbd, 0x5d, 0x33, 0xd0, 0x97, 0x7c, 0x34, 0x16, 0xa2, + 0xe8, 0xcf, 0x11, 0x13, 0x76, 0x74, 0x03, 0xfd, 0x05, 0x13, 0x66, 0x8d, 0x6e, 0xbb, 0xae, 0xa3, + 0x37, 0xd8, 0xe4, 0x6e, 0xeb, 0xad, 0x86, 0x6e, 0x90, 0x07, 0xe8, 0x2f, 0xb9, 0xf9, 0x47, 0x9d, + 0x56, 0x13, 0x7d, 0x85, 0x70, 0x09, 0x40, 0xff, 0xb8, 0x4d, 0xf4, 0x4e, 0xa7, 0xd6, 0x6a, 0xa2, + 0xb7, 0x36, 0x76, 0x01, 0x9d, 0x4c, 0x07, 0x0c, 0x40, 0xb7, 0x79, 0xa7, 0xd9, 0xba, 0xdf, 0x44, + 0xe7, 0x58, 0xa5, 0x4d, 0xf4, 0xb6, 0x46, 0x74, 0xa4, 0x60, 0x80, 0x39, 0xf1, 0x3e, 0x0e, 0xa5, + 0xf0, 0x02, 0xe4, 0x48, 0xab, 0x5e, 0xdf, 0xd6, 0xaa, 0x77, 0x50, 0x7a, 0xfb, 0x1d, 0x58, 0xb4, + 0xbd, 0xcd, 0x43, 0x3b, 0xa4, 0x41, 0x20, 0x5e, 0x2c, 0x3f, 0x54, 0x65, 0xcd, 0xf6, 0xae, 0x88, + 0xd2, 0x95, 0x81, 0x77, 0xe5, 0x30, 0xbc, 0xc2, 0xb5, 0x57, 0x78, 0xc6, 0xd8, 0x9b, 0xe3, 0x95, + 0x6b, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xda, 0x0b, 0x47, 0xfb, 0x0f, 0x2d, 0x00, 0x00, } diff --git a/go/vt/proto/topodata/topodata.pb.go b/go/vt/proto/topodata/topodata.pb.go index a9743090119..6fe977f8396 100644 --- a/go/vt/proto/topodata/topodata.pb.go +++ b/go/vt/proto/topodata/topodata.pb.go @@ -48,7 +48,7 @@ func (x KeyspaceIdType) String() string { return proto.EnumName(KeyspaceIdType_name, int32(x)) } func (KeyspaceIdType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{0} + return fileDescriptor_topodata_23985cc74c86747c, []int{0} } // TabletType represents the type of a given tablet. @@ -117,7 +117,7 @@ func (x TabletType) String() string { return proto.EnumName(TabletType_name, int32(x)) } func (TabletType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{1} + return fileDescriptor_topodata_23985cc74c86747c, []int{1} } // KeyRange describes a range of sharding keys, when range-based @@ -134,7 +134,7 @@ func (m *KeyRange) Reset() { *m = KeyRange{} } func (m *KeyRange) String() string { return proto.CompactTextString(m) } func (*KeyRange) ProtoMessage() {} func (*KeyRange) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{0} + return fileDescriptor_topodata_23985cc74c86747c, []int{0} } func (m *KeyRange) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_KeyRange.Unmarshal(m, b) @@ -184,7 +184,7 @@ func (m *TabletAlias) Reset() { *m = TabletAlias{} } func (m *TabletAlias) String() string { return proto.CompactTextString(m) } func (*TabletAlias) ProtoMessage() {} func (*TabletAlias) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{1} + return fileDescriptor_topodata_23985cc74c86747c, []int{1} } func (m *TabletAlias) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TabletAlias.Unmarshal(m, b) @@ -260,7 +260,7 @@ func (m *Tablet) Reset() { *m = Tablet{} } func (m *Tablet) String() string { return proto.CompactTextString(m) } func (*Tablet) ProtoMessage() {} func (*Tablet) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{2} + return fileDescriptor_topodata_23985cc74c86747c, []int{2} } func (m *Tablet) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Tablet.Unmarshal(m, b) @@ -394,7 +394,7 @@ func (m *Shard) Reset() { *m = Shard{} } func (m *Shard) String() string { return proto.CompactTextString(m) } func (*Shard) ProtoMessage() {} func (*Shard) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{3} + return fileDescriptor_topodata_23985cc74c86747c, []int{3} } func (m *Shard) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Shard.Unmarshal(m, b) @@ -469,7 +469,7 @@ func (m *Shard_ServedType) Reset() { *m = Shard_ServedType{} } func (m *Shard_ServedType) String() string { return proto.CompactTextString(m) } func (*Shard_ServedType) ProtoMessage() {} func (*Shard_ServedType) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{3, 0} + return fileDescriptor_topodata_23985cc74c86747c, []int{3, 0} } func (m *Shard_ServedType) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Shard_ServedType.Unmarshal(m, b) @@ -526,7 +526,7 @@ func (m *Shard_SourceShard) Reset() { *m = Shard_SourceShard{} } func (m *Shard_SourceShard) String() string { return proto.CompactTextString(m) } func (*Shard_SourceShard) ProtoMessage() {} func (*Shard_SourceShard) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{3, 1} + return fileDescriptor_topodata_23985cc74c86747c, []int{3, 1} } func (m *Shard_SourceShard) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Shard_SourceShard.Unmarshal(m, b) @@ -587,8 +587,11 @@ type Shard_TabletControl struct { TabletType TabletType `protobuf:"varint,1,opt,name=tablet_type,json=tabletType,enum=topodata.TabletType" json:"tablet_type,omitempty"` Cells []string `protobuf:"bytes,2,rep,name=cells" json:"cells,omitempty"` // what to do - DisableQueryService bool `protobuf:"varint,3,opt,name=disable_query_service,json=disableQueryService" json:"disable_query_service,omitempty"` - BlacklistedTables []string `protobuf:"bytes,4,rep,name=blacklisted_tables,json=blacklistedTables" json:"blacklisted_tables,omitempty"` + DisableQueryService bool `protobuf:"varint,3,opt,name=disable_query_service,json=disableQueryService" json:"disable_query_service,omitempty"` + BlacklistedTables []string `protobuf:"bytes,4,rep,name=blacklisted_tables,json=blacklistedTables" json:"blacklisted_tables,omitempty"` + // frozen is set if we've started failing over traffic for + // the master. If set, this record should not be removed. + Frozen bool `protobuf:"varint,5,opt,name=frozen" json:"frozen,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -598,7 +601,7 @@ func (m *Shard_TabletControl) Reset() { *m = Shard_TabletControl{} } func (m *Shard_TabletControl) String() string { return proto.CompactTextString(m) } func (*Shard_TabletControl) ProtoMessage() {} func (*Shard_TabletControl) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{3, 2} + return fileDescriptor_topodata_23985cc74c86747c, []int{3, 2} } func (m *Shard_TabletControl) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Shard_TabletControl.Unmarshal(m, b) @@ -646,6 +649,13 @@ func (m *Shard_TabletControl) GetBlacklistedTables() []string { return nil } +func (m *Shard_TabletControl) GetFrozen() bool { + if m != nil { + return m.Frozen + } + return false +} + // A Keyspace contains data about a keyspace. type Keyspace struct { // name of the column used for sharding @@ -666,7 +676,7 @@ func (m *Keyspace) Reset() { *m = Keyspace{} } func (m *Keyspace) String() string { return proto.CompactTextString(m) } func (*Keyspace) ProtoMessage() {} func (*Keyspace) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{4} + return fileDescriptor_topodata_23985cc74c86747c, []int{4} } func (m *Keyspace) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Keyspace.Unmarshal(m, b) @@ -725,7 +735,7 @@ func (m *Keyspace_ServedFrom) Reset() { *m = Keyspace_ServedFrom{} } func (m *Keyspace_ServedFrom) String() string { return proto.CompactTextString(m) } func (*Keyspace_ServedFrom) ProtoMessage() {} func (*Keyspace_ServedFrom) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{4, 0} + return fileDescriptor_topodata_23985cc74c86747c, []int{4, 0} } func (m *Keyspace_ServedFrom) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Keyspace_ServedFrom.Unmarshal(m, b) @@ -781,7 +791,7 @@ func (m *ShardReplication) Reset() { *m = ShardReplication{} } func (m *ShardReplication) String() string { return proto.CompactTextString(m) } func (*ShardReplication) ProtoMessage() {} func (*ShardReplication) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{5} + return fileDescriptor_topodata_23985cc74c86747c, []int{5} } func (m *ShardReplication) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ShardReplication.Unmarshal(m, b) @@ -820,7 +830,7 @@ func (m *ShardReplication_Node) Reset() { *m = ShardReplication_Node{} } func (m *ShardReplication_Node) String() string { return proto.CompactTextString(m) } func (*ShardReplication_Node) ProtoMessage() {} func (*ShardReplication_Node) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{5, 0} + return fileDescriptor_topodata_23985cc74c86747c, []int{5, 0} } func (m *ShardReplication_Node) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ShardReplication_Node.Unmarshal(m, b) @@ -861,7 +871,7 @@ func (m *ShardReference) Reset() { *m = ShardReference{} } func (m *ShardReference) String() string { return proto.CompactTextString(m) } func (*ShardReference) ProtoMessage() {} func (*ShardReference) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{6} + return fileDescriptor_topodata_23985cc74c86747c, []int{6} } func (m *ShardReference) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ShardReference.Unmarshal(m, b) @@ -912,7 +922,7 @@ func (m *SrvKeyspace) Reset() { *m = SrvKeyspace{} } func (m *SrvKeyspace) String() string { return proto.CompactTextString(m) } func (*SrvKeyspace) ProtoMessage() {} func (*SrvKeyspace) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{7} + return fileDescriptor_topodata_23985cc74c86747c, []int{7} } func (m *SrvKeyspace) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SrvKeyspace.Unmarshal(m, b) @@ -974,7 +984,7 @@ func (m *SrvKeyspace_KeyspacePartition) Reset() { *m = SrvKeyspace_Keysp func (m *SrvKeyspace_KeyspacePartition) String() string { return proto.CompactTextString(m) } func (*SrvKeyspace_KeyspacePartition) ProtoMessage() {} func (*SrvKeyspace_KeyspacePartition) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{7, 0} + return fileDescriptor_topodata_23985cc74c86747c, []int{7, 0} } func (m *SrvKeyspace_KeyspacePartition) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SrvKeyspace_KeyspacePartition.Unmarshal(m, b) @@ -1024,7 +1034,7 @@ func (m *SrvKeyspace_ServedFrom) Reset() { *m = SrvKeyspace_ServedFrom{} func (m *SrvKeyspace_ServedFrom) String() string { return proto.CompactTextString(m) } func (*SrvKeyspace_ServedFrom) ProtoMessage() {} func (*SrvKeyspace_ServedFrom) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{7, 1} + return fileDescriptor_topodata_23985cc74c86747c, []int{7, 1} } func (m *SrvKeyspace_ServedFrom) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SrvKeyspace_ServedFrom.Unmarshal(m, b) @@ -1082,7 +1092,7 @@ func (m *CellInfo) Reset() { *m = CellInfo{} } func (m *CellInfo) String() string { return proto.CompactTextString(m) } func (*CellInfo) ProtoMessage() {} func (*CellInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_topodata_cb9e1ed4dfa42564, []int{8} + return fileDescriptor_topodata_23985cc74c86747c, []int{8} } func (m *CellInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CellInfo.Unmarshal(m, b) @@ -1146,80 +1156,81 @@ func init() { proto.RegisterEnum("topodata.TabletType", TabletType_name, TabletType_value) } -func init() { proto.RegisterFile("topodata.proto", fileDescriptor_topodata_cb9e1ed4dfa42564) } - -var fileDescriptor_topodata_cb9e1ed4dfa42564 = []byte{ - // 1145 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x5f, 0x6f, 0xe2, 0x46, - 0x10, 0xaf, 0xc1, 0x10, 0x18, 0x03, 0xe7, 0xdb, 0xe6, 0x2a, 0xcb, 0xd5, 0xa9, 0x08, 0xe9, 0x54, - 0x74, 0x55, 0xa1, 0xe2, 0x7a, 0x6d, 0x74, 0x52, 0xa5, 0x10, 0xc2, 0xf5, 0xc8, 0x1f, 0x42, 0x0d, - 0x51, 0x9b, 0x4a, 0x95, 0xe5, 0xe0, 0x0d, 0x67, 0xc5, 0x78, 0xb9, 0xdd, 0x05, 0x89, 0xcf, 0x70, - 0x0f, 0xbd, 0xe7, 0x7e, 0x93, 0x3e, 0xf5, 0xb1, 0x5f, 0xab, 0xda, 0x5d, 0x1b, 0x0c, 0x69, 0xd2, - 0x5c, 0x95, 0xb7, 0x99, 0x9d, 0x3f, 0x9e, 0xf9, 0xcd, 0x6f, 0x06, 0xa0, 0xc2, 0xc9, 0x8c, 0xf8, - 0x1e, 0xf7, 0x1a, 0x33, 0x4a, 0x38, 0x41, 0x85, 0x44, 0xaf, 0xb5, 0xa0, 0x70, 0x8c, 0x97, 0x8e, - 0x17, 0x4d, 0x30, 0xda, 0x85, 0x1c, 0xe3, 0x1e, 0xe5, 0x96, 0x56, 0xd5, 0xea, 0x25, 0x47, 0x29, - 0xc8, 0x84, 0x2c, 0x8e, 0x7c, 0x2b, 0x23, 0xdf, 0x84, 0x58, 0x7b, 0x01, 0xc6, 0xc8, 0xbb, 0x0c, - 0x31, 0x6f, 0x87, 0x81, 0xc7, 0x10, 0x02, 0x7d, 0x8c, 0xc3, 0x50, 0x46, 0x15, 0x1d, 0x29, 0x8b, - 0xa0, 0x79, 0xa0, 0x82, 0xca, 0x8e, 0x10, 0x6b, 0x7f, 0xea, 0x90, 0x57, 0x51, 0xe8, 0x2b, 0xc8, - 0x79, 0x22, 0x52, 0x46, 0x18, 0xad, 0x27, 0x8d, 0x55, 0x75, 0xa9, 0xb4, 0x8e, 0xf2, 0x41, 0x36, - 0x14, 0xde, 0x12, 0xc6, 0x23, 0x6f, 0x8a, 0x65, 0xba, 0xa2, 0xb3, 0xd2, 0xd1, 0x1e, 0x14, 0x66, - 0x84, 0x72, 0x77, 0xea, 0xcd, 0x2c, 0xbd, 0x9a, 0xad, 0x1b, 0xad, 0xa7, 0xdb, 0xb9, 0x1a, 0x03, - 0x42, 0xf9, 0xa9, 0x37, 0xeb, 0x46, 0x9c, 0x2e, 0x9d, 0x9d, 0x99, 0xd2, 0x44, 0xd6, 0x6b, 0xbc, - 0x64, 0x33, 0x6f, 0x8c, 0xad, 0x9c, 0xca, 0x9a, 0xe8, 0x12, 0x86, 0xb7, 0x1e, 0xf5, 0xad, 0xbc, - 0x34, 0x28, 0x05, 0x35, 0xa1, 0x78, 0x8d, 0x97, 0x2e, 0x15, 0x48, 0x59, 0x3b, 0xb2, 0x70, 0xb4, - 0xfe, 0x58, 0x82, 0xa1, 0x4c, 0xa3, 0xd0, 0xac, 0x83, 0xce, 0x97, 0x33, 0x6c, 0x15, 0xaa, 0x5a, - 0xbd, 0xd2, 0xda, 0xdd, 0x2e, 0x6c, 0xb4, 0x9c, 0x61, 0x47, 0x7a, 0xa0, 0x3a, 0x98, 0xfe, 0xa5, - 0x2b, 0x3a, 0x72, 0xc9, 0x02, 0x53, 0x1a, 0xf8, 0xd8, 0x2a, 0xca, 0x6f, 0x57, 0xfc, 0xcb, 0xbe, - 0x37, 0xc5, 0x67, 0xf1, 0x2b, 0x6a, 0x80, 0xce, 0xbd, 0x09, 0xb3, 0x40, 0x36, 0x6b, 0xdf, 0x68, - 0x76, 0xe4, 0x4d, 0x98, 0xea, 0x54, 0xfa, 0xa1, 0x67, 0x50, 0x99, 0x2e, 0xd9, 0xbb, 0xd0, 0x5d, - 0x41, 0x58, 0x92, 0x79, 0xcb, 0xf2, 0xf5, 0x4d, 0x82, 0xe3, 0x53, 0x00, 0xe5, 0x26, 0xe0, 0xb1, - 0xca, 0x55, 0xad, 0x9e, 0x73, 0x8a, 0xf2, 0x45, 0xa0, 0x67, 0xbf, 0x82, 0x52, 0x1a, 0x45, 0x31, - 0xdc, 0x6b, 0xbc, 0x8c, 0xe7, 0x2d, 0x44, 0x01, 0xd9, 0xc2, 0x0b, 0xe7, 0x6a, 0x42, 0x39, 0x47, - 0x29, 0xaf, 0x32, 0x7b, 0x9a, 0xfd, 0x3d, 0x14, 0x57, 0x45, 0xfd, 0x57, 0x60, 0x31, 0x15, 0x78, - 0xa4, 0x17, 0xb2, 0xa6, 0x7e, 0xa4, 0x17, 0x0c, 0xb3, 0x54, 0x7b, 0x9f, 0x87, 0xdc, 0x50, 0x4e, - 0x61, 0x0f, 0x4a, 0x53, 0x8f, 0x71, 0x4c, 0xdd, 0x7b, 0x30, 0xc8, 0x50, 0xae, 0x8a, 0xa5, 0x1b, - 0xf3, 0xcb, 0xdc, 0x63, 0x7e, 0x3f, 0x40, 0x89, 0x61, 0xba, 0xc0, 0xbe, 0x2b, 0x86, 0xc4, 0xac, - 0xec, 0x36, 0xe6, 0xb2, 0xa2, 0xc6, 0x50, 0xfa, 0xc8, 0x69, 0x1a, 0x6c, 0x25, 0x33, 0xb4, 0x0f, - 0x65, 0x46, 0xe6, 0x74, 0x8c, 0x5d, 0xc9, 0x1f, 0x16, 0x13, 0xf4, 0xf3, 0x1b, 0xf1, 0xd2, 0x49, - 0xca, 0x4e, 0x89, 0xad, 0x15, 0x26, 0xb0, 0x11, 0xbb, 0xc4, 0xac, 0x5c, 0x35, 0x2b, 0xb0, 0x91, - 0x0a, 0x7a, 0x0d, 0x8f, 0xb8, 0xec, 0xd1, 0x1d, 0x93, 0x88, 0x53, 0x12, 0x32, 0x2b, 0xbf, 0x4d, - 0x7d, 0x95, 0x59, 0x41, 0xd1, 0x51, 0x5e, 0x4e, 0x85, 0xa7, 0x55, 0x66, 0x5f, 0x00, 0xac, 0x4b, - 0x47, 0x2f, 0xc1, 0x88, 0xb3, 0x4a, 0xce, 0x6a, 0x77, 0x70, 0x16, 0xf8, 0x4a, 0x5e, 0x97, 0x98, - 0x49, 0x95, 0x68, 0xff, 0xa1, 0x81, 0x91, 0x6a, 0x2b, 0x39, 0x06, 0xda, 0xea, 0x18, 0x6c, 0xac, - 0x5f, 0xe6, 0xb6, 0xf5, 0xcb, 0xde, 0xba, 0x7e, 0xfa, 0x3d, 0xc6, 0xf7, 0x19, 0xe4, 0x65, 0xa1, - 0x09, 0x7c, 0xb1, 0x66, 0xff, 0xa5, 0x41, 0x79, 0x03, 0x99, 0x07, 0xed, 0x1d, 0xb5, 0xe0, 0x89, - 0x1f, 0x30, 0xe1, 0xe5, 0xbe, 0x9b, 0x63, 0xba, 0x74, 0x05, 0x27, 0x82, 0x31, 0x96, 0xdd, 0x14, - 0x9c, 0x4f, 0x63, 0xe3, 0x4f, 0xc2, 0x36, 0x54, 0x26, 0xf4, 0x35, 0xa0, 0xcb, 0xd0, 0x1b, 0x5f, - 0x87, 0x01, 0xe3, 0x82, 0x6e, 0xaa, 0x6c, 0x5d, 0xa6, 0x7d, 0x9c, 0xb2, 0xc8, 0x42, 0x58, 0xed, - 0xef, 0x8c, 0xbc, 0xd9, 0x0a, 0xad, 0x6f, 0x60, 0x57, 0x02, 0x14, 0x44, 0x13, 0x77, 0x4c, 0xc2, - 0xf9, 0x34, 0x92, 0x87, 0x24, 0xde, 0x31, 0x94, 0xd8, 0x3a, 0xd2, 0x24, 0x6e, 0x09, 0x3a, 0xba, - 0x19, 0x21, 0xfb, 0xce, 0xc8, 0xbe, 0xad, 0x0d, 0x50, 0xe5, 0x37, 0x7a, 0x8a, 0xdd, 0x5b, 0xb9, - 0x24, 0x06, 0xfb, 0xab, 0x1d, 0xb9, 0xa2, 0x64, 0xca, 0x6e, 0x1e, 0xe1, 0x24, 0x47, 0xbc, 0x26, - 0xaf, 0x29, 0x99, 0x26, 0x6b, 0x22, 0x64, 0x66, 0xcf, 0x13, 0x1a, 0x0a, 0xf5, 0x61, 0x47, 0x91, - 0x26, 0x59, 0x76, 0x93, 0x64, 0xea, 0xba, 0xd4, 0xde, 0x6b, 0x60, 0xaa, 0xcd, 0xc3, 0xb3, 0x30, - 0x18, 0x7b, 0x3c, 0x20, 0x11, 0x7a, 0x09, 0xb9, 0x88, 0xf8, 0x58, 0xdc, 0x16, 0xd1, 0xcc, 0x17, - 0x5b, 0x6b, 0x95, 0x72, 0x6d, 0xf4, 0x89, 0x8f, 0x1d, 0xe5, 0x6d, 0xef, 0x83, 0x2e, 0x54, 0x71, - 0xa1, 0xe2, 0x16, 0xee, 0x73, 0xa1, 0xf8, 0x5a, 0xa9, 0x9d, 0x43, 0x25, 0xfe, 0xc2, 0x15, 0xa6, - 0x38, 0x1a, 0x63, 0xf1, 0xcb, 0x9a, 0x1a, 0xa6, 0x94, 0x3f, 0xfa, 0x8e, 0xd5, 0x3e, 0xe8, 0x60, - 0x0c, 0xe9, 0x62, 0xc5, 0x98, 0x1f, 0x01, 0x66, 0x1e, 0xe5, 0x81, 0xe8, 0x20, 0x69, 0xf2, 0xcb, - 0x54, 0x93, 0x6b, 0xd7, 0xd5, 0xf4, 0x06, 0x89, 0xbf, 0x93, 0x0a, 0xbd, 0x95, 0x7a, 0x99, 0x8f, - 0xa6, 0x5e, 0xf6, 0x7f, 0x50, 0xaf, 0x0d, 0x46, 0x8a, 0x7a, 0x31, 0xf3, 0xaa, 0xff, 0xde, 0x47, - 0x8a, 0x7c, 0xb0, 0x26, 0x9f, 0xfd, 0xbb, 0x06, 0x8f, 0x6f, 0xb4, 0x28, 0x38, 0x98, 0xba, 0xfb, - 0x77, 0x73, 0x70, 0x7d, 0xf0, 0x51, 0x07, 0x4c, 0x59, 0xa5, 0x4b, 0x93, 0xf1, 0x29, 0x3a, 0x1a, - 0xe9, 0xbe, 0x36, 0xe7, 0xeb, 0x3c, 0x62, 0x1b, 0x3a, 0xb3, 0xdd, 0x87, 0xd8, 0x86, 0x3b, 0x8e, - 0xeb, 0x91, 0x5e, 0xc8, 0x99, 0xf9, 0xda, 0x6f, 0x50, 0xe8, 0xe0, 0x30, 0xec, 0x45, 0x57, 0x44, - 0xfc, 0x45, 0x90, 0x5d, 0x50, 0xd7, 0xf3, 0x7d, 0x8a, 0x19, 0x8b, 0xd9, 0x56, 0x56, 0xaf, 0x6d, - 0xf5, 0x28, 0xa8, 0x48, 0x09, 0xe1, 0x71, 0x42, 0x29, 0x8b, 0x13, 0x4b, 0xf1, 0x24, 0x20, 0x51, - 0xbc, 0x5e, 0xb1, 0xf6, 0xbc, 0x05, 0x95, 0xcd, 0x01, 0xa2, 0x22, 0xe4, 0xce, 0xfb, 0xc3, 0xee, - 0xc8, 0xfc, 0x04, 0x01, 0xe4, 0xcf, 0x7b, 0xfd, 0xd1, 0x77, 0xdf, 0x9a, 0x9a, 0x78, 0x3e, 0xb8, - 0x18, 0x75, 0x87, 0x66, 0xe6, 0xf9, 0x07, 0x0d, 0x60, 0xdd, 0x0f, 0x32, 0x60, 0xe7, 0xbc, 0x7f, - 0xdc, 0x3f, 0xfb, 0xb9, 0xaf, 0x42, 0x4e, 0xdb, 0xc3, 0x51, 0xd7, 0x31, 0x35, 0x61, 0x70, 0xba, - 0x83, 0x93, 0x5e, 0xa7, 0x6d, 0x66, 0x84, 0xc1, 0x39, 0x3c, 0xeb, 0x9f, 0x5c, 0x98, 0x59, 0x99, - 0xab, 0x3d, 0xea, 0xbc, 0x51, 0xe2, 0x70, 0xd0, 0x76, 0xba, 0xa6, 0x8e, 0x4c, 0x28, 0x75, 0x7f, - 0x19, 0x74, 0x9d, 0xde, 0x69, 0xb7, 0x3f, 0x6a, 0x9f, 0x98, 0x39, 0x11, 0x73, 0xd0, 0xee, 0x1c, - 0x9f, 0x0f, 0xcc, 0xbc, 0x4a, 0x36, 0x1c, 0x9d, 0x39, 0x5d, 0x73, 0x47, 0x28, 0x87, 0x4e, 0xbb, - 0xd7, 0xef, 0x1e, 0x9a, 0x05, 0x3b, 0x63, 0x6a, 0x07, 0x7b, 0xf0, 0x28, 0x20, 0x8d, 0x45, 0xc0, - 0x31, 0x63, 0xea, 0x7f, 0xf3, 0xaf, 0xcf, 0x62, 0x2d, 0x20, 0x4d, 0x25, 0x35, 0x27, 0xa4, 0xb9, - 0xe0, 0x4d, 0x69, 0x6d, 0x26, 0x83, 0xb9, 0xcc, 0x4b, 0xfd, 0xc5, 0x3f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0xad, 0xf5, 0xb6, 0x82, 0x77, 0x0b, 0x00, 0x00, +func init() { proto.RegisterFile("topodata.proto", fileDescriptor_topodata_23985cc74c86747c) } + +var fileDescriptor_topodata_23985cc74c86747c = []byte{ + // 1162 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x6f, 0x8f, 0xda, 0x46, + 0x13, 0x7f, 0x0c, 0x86, 0x33, 0x63, 0x8e, 0x38, 0xfb, 0x24, 0x95, 0xe5, 0x2a, 0x2a, 0x42, 0x8a, + 0x8a, 0x52, 0x15, 0x2a, 0xd2, 0xb4, 0xa7, 0x48, 0x95, 0x42, 0x08, 0x69, 0xb8, 0x24, 0x1c, 0x5d, + 0x38, 0xb5, 0xa9, 0x54, 0x59, 0x3e, 0xbc, 0x47, 0xac, 0x33, 0x5e, 0xb2, 0xbb, 0x20, 0xd1, 0xaf, + 0xd0, 0x17, 0xcd, 0xeb, 0xbe, 0xed, 0xa7, 0xe8, 0x27, 0xe8, 0x47, 0xe8, 0xd7, 0xa9, 0x76, 0xd7, + 0x06, 0xc3, 0x35, 0xe9, 0xa5, 0xba, 0x77, 0x33, 0x3b, 0x7f, 0x3c, 0xf3, 0x9b, 0xdf, 0x0c, 0x40, + 0x4d, 0xd0, 0x05, 0x0d, 0x03, 0x11, 0xb4, 0x16, 0x8c, 0x0a, 0x8a, 0xac, 0x4c, 0x6f, 0x74, 0xc0, + 0x7a, 0x4e, 0xd6, 0x38, 0x48, 0x66, 0x04, 0xdd, 0x82, 0x12, 0x17, 0x01, 0x13, 0xae, 0x51, 0x37, + 0x9a, 0x55, 0xac, 0x15, 0xe4, 0x40, 0x91, 0x24, 0xa1, 0x5b, 0x50, 0x6f, 0x52, 0x6c, 0xdc, 0x07, + 0x7b, 0x12, 0x9c, 0xc5, 0x44, 0x74, 0xe3, 0x28, 0xe0, 0x08, 0x81, 0x39, 0x25, 0x71, 0xac, 0xa2, + 0x2a, 0x58, 0xc9, 0x32, 0x68, 0x19, 0xe9, 0xa0, 0x43, 0x2c, 0xc5, 0xc6, 0x1f, 0x26, 0x94, 0x75, + 0x14, 0xfa, 0x0c, 0x4a, 0x81, 0x8c, 0x54, 0x11, 0x76, 0xe7, 0x76, 0x6b, 0x53, 0x5d, 0x2e, 0x2d, + 0xd6, 0x3e, 0xc8, 0x03, 0xeb, 0x35, 0xe5, 0x22, 0x09, 0xe6, 0x44, 0xa5, 0xab, 0xe0, 0x8d, 0x8e, + 0x8e, 0xc0, 0x5a, 0x50, 0x26, 0xfc, 0x79, 0xb0, 0x70, 0xcd, 0x7a, 0xb1, 0x69, 0x77, 0xee, 0xec, + 0xe7, 0x6a, 0x8d, 0x28, 0x13, 0x2f, 0x83, 0x45, 0x3f, 0x11, 0x6c, 0x8d, 0x0f, 0x16, 0x5a, 0x93, + 0x59, 0x2f, 0xc8, 0x9a, 0x2f, 0x82, 0x29, 0x71, 0x4b, 0x3a, 0x6b, 0xa6, 0x2b, 0x18, 0x5e, 0x07, + 0x2c, 0x74, 0xcb, 0xca, 0xa0, 0x15, 0xd4, 0x86, 0xca, 0x05, 0x59, 0xfb, 0x4c, 0x22, 0xe5, 0x1e, + 0xa8, 0xc2, 0xd1, 0xf6, 0x63, 0x19, 0x86, 0x2a, 0x8d, 0x46, 0xb3, 0x09, 0xa6, 0x58, 0x2f, 0x88, + 0x6b, 0xd5, 0x8d, 0x66, 0xad, 0x73, 0x6b, 0xbf, 0xb0, 0xc9, 0x7a, 0x41, 0xb0, 0xf2, 0x40, 0x4d, + 0x70, 0xc2, 0x33, 0x5f, 0x76, 0xe4, 0xd3, 0x15, 0x61, 0x2c, 0x0a, 0x89, 0x5b, 0x51, 0xdf, 0xae, + 0x85, 0x67, 0xc3, 0x60, 0x4e, 0x4e, 0xd2, 0x57, 0xd4, 0x02, 0x53, 0x04, 0x33, 0xee, 0x82, 0x6a, + 0xd6, 0xbb, 0xd4, 0xec, 0x24, 0x98, 0x71, 0xdd, 0xa9, 0xf2, 0x43, 0x77, 0xa1, 0x36, 0x5f, 0xf3, + 0x37, 0xb1, 0xbf, 0x81, 0xb0, 0xaa, 0xf2, 0x1e, 0xaa, 0xd7, 0x67, 0x19, 0x8e, 0x77, 0x00, 0xb4, + 0x9b, 0x84, 0xc7, 0x3d, 0xac, 0x1b, 0xcd, 0x12, 0xae, 0xa8, 0x17, 0x89, 0x9e, 0xf7, 0x10, 0xaa, + 0x79, 0x14, 0xe5, 0x70, 0x2f, 0xc8, 0x3a, 0x9d, 0xb7, 0x14, 0x25, 0x64, 0xab, 0x20, 0x5e, 0xea, + 0x09, 0x95, 0xb0, 0x56, 0x1e, 0x16, 0x8e, 0x0c, 0xef, 0x6b, 0xa8, 0x6c, 0x8a, 0xfa, 0xb7, 0xc0, + 0x4a, 0x2e, 0xf0, 0xd8, 0xb4, 0x8a, 0x8e, 0x79, 0x6c, 0x5a, 0xb6, 0x53, 0x6d, 0xfc, 0x5e, 0x86, + 0xd2, 0x58, 0x4d, 0xe1, 0x08, 0xaa, 0xf3, 0x80, 0x0b, 0xc2, 0xfc, 0x2b, 0x30, 0xc8, 0xd6, 0xae, + 0x9a, 0xa5, 0x3b, 0xf3, 0x2b, 0x5c, 0x61, 0x7e, 0xdf, 0x40, 0x95, 0x13, 0xb6, 0x22, 0xa1, 0x2f, + 0x87, 0xc4, 0xdd, 0xe2, 0x3e, 0xe6, 0xaa, 0xa2, 0xd6, 0x58, 0xf9, 0xa8, 0x69, 0xda, 0x7c, 0x23, + 0x73, 0xf4, 0x08, 0x0e, 0x39, 0x5d, 0xb2, 0x29, 0xf1, 0x15, 0x7f, 0x78, 0x4a, 0xd0, 0x8f, 0x2f, + 0xc5, 0x2b, 0x27, 0x25, 0xe3, 0x2a, 0xdf, 0x2a, 0x5c, 0x62, 0x23, 0x77, 0x89, 0xbb, 0xa5, 0x7a, + 0x51, 0x62, 0xa3, 0x14, 0xf4, 0x14, 0x6e, 0x08, 0xd5, 0xa3, 0x3f, 0xa5, 0x89, 0x60, 0x34, 0xe6, + 0x6e, 0x79, 0x9f, 0xfa, 0x3a, 0xb3, 0x86, 0xa2, 0xa7, 0xbd, 0x70, 0x4d, 0xe4, 0x55, 0xee, 0xbd, + 0x02, 0xd8, 0x96, 0x8e, 0x1e, 0x80, 0x9d, 0x66, 0x55, 0x9c, 0x35, 0xde, 0xc3, 0x59, 0x10, 0x1b, + 0x79, 0x5b, 0x62, 0x21, 0x57, 0xa2, 0xf7, 0x9b, 0x01, 0x76, 0xae, 0xad, 0xec, 0x18, 0x18, 0x9b, + 0x63, 0xb0, 0xb3, 0x7e, 0x85, 0x77, 0xad, 0x5f, 0xf1, 0x9d, 0xeb, 0x67, 0x5e, 0x61, 0x7c, 0x1f, + 0x41, 0x59, 0x15, 0x9a, 0xc1, 0x97, 0x6a, 0xde, 0x5f, 0x06, 0x1c, 0xee, 0x20, 0x73, 0xad, 0xbd, + 0xa3, 0x0e, 0xdc, 0x0e, 0x23, 0x2e, 0xbd, 0xfc, 0x37, 0x4b, 0xc2, 0xd6, 0xbe, 0xe4, 0x44, 0x34, + 0x25, 0xaa, 0x1b, 0x0b, 0xff, 0x3f, 0x35, 0x7e, 0x27, 0x6d, 0x63, 0x6d, 0x42, 0x9f, 0x03, 0x3a, + 0x8b, 0x83, 0xe9, 0x45, 0x1c, 0x71, 0x21, 0xe9, 0xa6, 0xcb, 0x36, 0x55, 0xda, 0x9b, 0x39, 0x8b, + 0x2a, 0x84, 0xcb, 0xce, 0xce, 0x19, 0xfd, 0x99, 0x24, 0xea, 0x72, 0x59, 0x38, 0xd5, 0x1a, 0x7f, + 0x16, 0xd4, 0x2d, 0xd7, 0x28, 0x7e, 0x01, 0xb7, 0x14, 0x70, 0x51, 0x32, 0xf3, 0xa7, 0x34, 0x5e, + 0xce, 0x13, 0x75, 0x60, 0xd2, 0xdd, 0x43, 0x99, 0xad, 0xa7, 0x4c, 0xf2, 0xc6, 0xa0, 0xe3, 0xcb, + 0x11, 0x0a, 0x8f, 0x82, 0xc2, 0xc3, 0xdd, 0x01, 0x5b, 0x7d, 0x63, 0xa0, 0x59, 0xbf, 0x97, 0x4b, + 0x61, 0xf3, 0x68, 0xb3, 0x3b, 0xe7, 0x8c, 0xce, 0xf9, 0xe5, 0xe3, 0x9c, 0xe5, 0x48, 0xd7, 0xe7, + 0x29, 0xa3, 0xf3, 0x6c, 0x7d, 0xa4, 0xcc, 0xbd, 0x65, 0x46, 0x4f, 0xa9, 0x5e, 0xef, 0x88, 0xf2, + 0xe4, 0x2b, 0xee, 0x92, 0x4f, 0x5f, 0x9d, 0xc6, 0x2f, 0x06, 0x38, 0x7a, 0x23, 0xc9, 0x22, 0x8e, + 0xa6, 0x81, 0x88, 0x68, 0x82, 0x1e, 0x40, 0x29, 0xa1, 0x21, 0x91, 0x37, 0x47, 0x36, 0xf3, 0xc9, + 0xde, 0xba, 0xe5, 0x5c, 0x5b, 0x43, 0x1a, 0x12, 0xac, 0xbd, 0xbd, 0x47, 0x60, 0x4a, 0x55, 0x5e, + 0xae, 0xb4, 0x85, 0xab, 0x5c, 0x2e, 0xb1, 0x55, 0x1a, 0xa7, 0x50, 0x4b, 0xbf, 0x70, 0x4e, 0x18, + 0x49, 0xa6, 0x44, 0xfe, 0xe2, 0xe6, 0x86, 0xa9, 0xe4, 0x0f, 0xbe, 0x6f, 0x8d, 0xb7, 0x26, 0xd8, + 0x63, 0xb6, 0xda, 0x30, 0xe6, 0x5b, 0x80, 0x45, 0xc0, 0x44, 0x24, 0x3b, 0xc8, 0x9a, 0xfc, 0x34, + 0xd7, 0xe4, 0xd6, 0x75, 0x33, 0xbd, 0x51, 0xe6, 0x8f, 0x73, 0xa1, 0xef, 0xa4, 0x5e, 0xe1, 0x83, + 0xa9, 0x57, 0xfc, 0x0f, 0xd4, 0xeb, 0x82, 0x9d, 0xa3, 0x5e, 0xca, 0xbc, 0xfa, 0x3f, 0xf7, 0x91, + 0x23, 0x1f, 0x6c, 0xc9, 0xe7, 0xfd, 0x6a, 0xc0, 0xcd, 0x4b, 0x2d, 0x4a, 0x0e, 0xe6, 0x7e, 0x0f, + 0xde, 0xcf, 0xc1, 0xed, 0x0f, 0x01, 0xea, 0x81, 0xa3, 0xaa, 0xf4, 0x59, 0x36, 0x3e, 0x4d, 0x47, + 0x3b, 0xdf, 0xd7, 0xee, 0x7c, 0xf1, 0x0d, 0xbe, 0xa3, 0x73, 0xcf, 0xbf, 0x8e, 0x6d, 0x78, 0xcf, + 0xd1, 0x3d, 0x36, 0xad, 0x92, 0x53, 0x6e, 0xfc, 0x04, 0x56, 0x8f, 0xc4, 0xf1, 0x20, 0x39, 0xa7, + 0xf2, 0xaf, 0x83, 0xea, 0x82, 0xf9, 0x41, 0x18, 0x32, 0xc2, 0x79, 0xca, 0xb6, 0x43, 0xfd, 0xda, + 0xd5, 0x8f, 0x92, 0x8a, 0x8c, 0x52, 0x91, 0x26, 0x54, 0xb2, 0x3c, 0x50, 0x8c, 0xcc, 0x22, 0x9a, + 0xa4, 0xeb, 0x95, 0x6a, 0xf7, 0x3a, 0x50, 0xdb, 0x1d, 0x20, 0xaa, 0x40, 0xe9, 0x74, 0x38, 0xee, + 0x4f, 0x9c, 0xff, 0x21, 0x80, 0xf2, 0xe9, 0x60, 0x38, 0xf9, 0xea, 0x4b, 0xc7, 0x90, 0xcf, 0x8f, + 0x5f, 0x4d, 0xfa, 0x63, 0xa7, 0x70, 0xef, 0xad, 0x01, 0xb0, 0xed, 0x07, 0xd9, 0x70, 0x70, 0x3a, + 0x7c, 0x3e, 0x3c, 0xf9, 0x7e, 0xa8, 0x43, 0x5e, 0x76, 0xc7, 0x93, 0x3e, 0x76, 0x0c, 0x69, 0xc0, + 0xfd, 0xd1, 0x8b, 0x41, 0xaf, 0xeb, 0x14, 0xa4, 0x01, 0x3f, 0x39, 0x19, 0xbe, 0x78, 0xe5, 0x14, + 0x55, 0xae, 0xee, 0xa4, 0xf7, 0x4c, 0x8b, 0xe3, 0x51, 0x17, 0xf7, 0x1d, 0x13, 0x39, 0x50, 0xed, + 0xff, 0x30, 0xea, 0xe3, 0xc1, 0xcb, 0xfe, 0x70, 0xd2, 0x7d, 0xe1, 0x94, 0x64, 0xcc, 0xe3, 0x6e, + 0xef, 0xf9, 0xe9, 0xc8, 0x29, 0xeb, 0x64, 0xe3, 0xc9, 0x09, 0xee, 0x3b, 0x07, 0x52, 0x79, 0x82, + 0xbb, 0x83, 0x61, 0xff, 0x89, 0x63, 0x79, 0x05, 0xc7, 0x78, 0x7c, 0x04, 0x37, 0x22, 0xda, 0x5a, + 0x45, 0x82, 0x70, 0xae, 0xff, 0x4f, 0xff, 0x78, 0x37, 0xd5, 0x22, 0xda, 0xd6, 0x52, 0x7b, 0x46, + 0xdb, 0x2b, 0xd1, 0x56, 0xd6, 0x76, 0x36, 0x98, 0xb3, 0xb2, 0xd2, 0xef, 0xff, 0x1d, 0x00, 0x00, + 0xff, 0xff, 0x74, 0x1e, 0xdb, 0x99, 0x8f, 0x0b, 0x00, 0x00, } diff --git a/go/vt/proto/vtgate/vtgate.pb.go b/go/vt/proto/vtgate/vtgate.pb.go index 5a625e55257..8c76c8fe00e 100644 --- a/go/vt/proto/vtgate/vtgate.pb.go +++ b/go/vt/proto/vtgate/vtgate.pb.go @@ -53,7 +53,7 @@ func (x TransactionMode) String() string { return proto.EnumName(TransactionMode_name, int32(x)) } func (TransactionMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{0} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{0} } // Session objects are exchanged like cookies through various @@ -86,17 +86,19 @@ type Session struct { // options is used only for V3. Options *query.ExecuteOptions `protobuf:"bytes,6,opt,name=options" json:"options,omitempty"` // transaction_mode specifies the current transaction mode. - TransactionMode TransactionMode `protobuf:"varint,7,opt,name=transaction_mode,json=transactionMode,enum=vtgate.TransactionMode" json:"transaction_mode,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + TransactionMode TransactionMode `protobuf:"varint,7,opt,name=transaction_mode,json=transactionMode,enum=vtgate.TransactionMode" json:"transaction_mode,omitempty"` + // warnings contains non-fatal warnings from the previous query + Warnings []*query.QueryWarning `protobuf:"bytes,8,rep,name=warnings" json:"warnings,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Session) Reset() { *m = Session{} } func (m *Session) String() string { return proto.CompactTextString(m) } func (*Session) ProtoMessage() {} func (*Session) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{0} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{0} } func (m *Session) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Session.Unmarshal(m, b) @@ -165,6 +167,13 @@ func (m *Session) GetTransactionMode() TransactionMode { return TransactionMode_UNSPECIFIED } +func (m *Session) GetWarnings() []*query.QueryWarning { + if m != nil { + return m.Warnings + } + return nil +} + type Session_ShardSession struct { Target *query.Target `protobuf:"bytes,1,opt,name=target" json:"target,omitempty"` TransactionId int64 `protobuf:"varint,2,opt,name=transaction_id,json=transactionId" json:"transaction_id,omitempty"` @@ -177,7 +186,7 @@ func (m *Session_ShardSession) Reset() { *m = Session_ShardSession{} } func (m *Session_ShardSession) String() string { return proto.CompactTextString(m) } func (*Session_ShardSession) ProtoMessage() {} func (*Session_ShardSession) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{0, 0} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{0, 0} } func (m *Session_ShardSession) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Session_ShardSession.Unmarshal(m, b) @@ -235,7 +244,7 @@ func (m *ExecuteRequest) Reset() { *m = ExecuteRequest{} } func (m *ExecuteRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteRequest) ProtoMessage() {} func (*ExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{1} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{1} } func (m *ExecuteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteRequest.Unmarshal(m, b) @@ -323,7 +332,7 @@ func (m *ExecuteResponse) Reset() { *m = ExecuteResponse{} } func (m *ExecuteResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteResponse) ProtoMessage() {} func (*ExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{2} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{2} } func (m *ExecuteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteResponse.Unmarshal(m, b) @@ -393,7 +402,7 @@ func (m *ExecuteShardsRequest) Reset() { *m = ExecuteShardsRequest{} } func (m *ExecuteShardsRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteShardsRequest) ProtoMessage() {} func (*ExecuteShardsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{3} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{3} } func (m *ExecuteShardsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteShardsRequest.Unmarshal(m, b) @@ -488,7 +497,7 @@ func (m *ExecuteShardsResponse) Reset() { *m = ExecuteShardsResponse{} } func (m *ExecuteShardsResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteShardsResponse) ProtoMessage() {} func (*ExecuteShardsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{4} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{4} } func (m *ExecuteShardsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteShardsResponse.Unmarshal(m, b) @@ -559,7 +568,7 @@ func (m *ExecuteKeyspaceIdsRequest) Reset() { *m = ExecuteKeyspaceIdsReq func (m *ExecuteKeyspaceIdsRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteKeyspaceIdsRequest) ProtoMessage() {} func (*ExecuteKeyspaceIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{5} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{5} } func (m *ExecuteKeyspaceIdsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteKeyspaceIdsRequest.Unmarshal(m, b) @@ -654,7 +663,7 @@ func (m *ExecuteKeyspaceIdsResponse) Reset() { *m = ExecuteKeyspaceIdsRe func (m *ExecuteKeyspaceIdsResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteKeyspaceIdsResponse) ProtoMessage() {} func (*ExecuteKeyspaceIdsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{6} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{6} } func (m *ExecuteKeyspaceIdsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteKeyspaceIdsResponse.Unmarshal(m, b) @@ -725,7 +734,7 @@ func (m *ExecuteKeyRangesRequest) Reset() { *m = ExecuteKeyRangesRequest func (m *ExecuteKeyRangesRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteKeyRangesRequest) ProtoMessage() {} func (*ExecuteKeyRangesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{7} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{7} } func (m *ExecuteKeyRangesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteKeyRangesRequest.Unmarshal(m, b) @@ -820,7 +829,7 @@ func (m *ExecuteKeyRangesResponse) Reset() { *m = ExecuteKeyRangesRespon func (m *ExecuteKeyRangesResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteKeyRangesResponse) ProtoMessage() {} func (*ExecuteKeyRangesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{8} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{8} } func (m *ExecuteKeyRangesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteKeyRangesResponse.Unmarshal(m, b) @@ -893,7 +902,7 @@ func (m *ExecuteEntityIdsRequest) Reset() { *m = ExecuteEntityIdsRequest func (m *ExecuteEntityIdsRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteEntityIdsRequest) ProtoMessage() {} func (*ExecuteEntityIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{9} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{9} } func (m *ExecuteEntityIdsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteEntityIdsRequest.Unmarshal(m, b) @@ -992,7 +1001,7 @@ func (m *ExecuteEntityIdsRequest_EntityId) Reset() { *m = ExecuteEntityI func (m *ExecuteEntityIdsRequest_EntityId) String() string { return proto.CompactTextString(m) } func (*ExecuteEntityIdsRequest_EntityId) ProtoMessage() {} func (*ExecuteEntityIdsRequest_EntityId) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{9, 0} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{9, 0} } func (m *ExecuteEntityIdsRequest_EntityId) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteEntityIdsRequest_EntityId.Unmarshal(m, b) @@ -1052,7 +1061,7 @@ func (m *ExecuteEntityIdsResponse) Reset() { *m = ExecuteEntityIdsRespon func (m *ExecuteEntityIdsResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteEntityIdsResponse) ProtoMessage() {} func (*ExecuteEntityIdsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{10} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{10} } func (m *ExecuteEntityIdsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteEntityIdsResponse.Unmarshal(m, b) @@ -1117,7 +1126,7 @@ func (m *ExecuteBatchRequest) Reset() { *m = ExecuteBatchRequest{} } func (m *ExecuteBatchRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchRequest) ProtoMessage() {} func (*ExecuteBatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{11} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{11} } func (m *ExecuteBatchRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchRequest.Unmarshal(m, b) @@ -1205,7 +1214,7 @@ func (m *ExecuteBatchResponse) Reset() { *m = ExecuteBatchResponse{} } func (m *ExecuteBatchResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchResponse) ProtoMessage() {} func (*ExecuteBatchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{12} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{12} } func (m *ExecuteBatchResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchResponse.Unmarshal(m, b) @@ -1265,7 +1274,7 @@ func (m *BoundShardQuery) Reset() { *m = BoundShardQuery{} } func (m *BoundShardQuery) String() string { return proto.CompactTextString(m) } func (*BoundShardQuery) ProtoMessage() {} func (*BoundShardQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{13} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{13} } func (m *BoundShardQuery) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BoundShardQuery.Unmarshal(m, b) @@ -1333,7 +1342,7 @@ func (m *ExecuteBatchShardsRequest) Reset() { *m = ExecuteBatchShardsReq func (m *ExecuteBatchShardsRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchShardsRequest) ProtoMessage() {} func (*ExecuteBatchShardsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{14} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{14} } func (m *ExecuteBatchShardsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchShardsRequest.Unmarshal(m, b) @@ -1414,7 +1423,7 @@ func (m *ExecuteBatchShardsResponse) Reset() { *m = ExecuteBatchShardsRe func (m *ExecuteBatchShardsResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchShardsResponse) ProtoMessage() {} func (*ExecuteBatchShardsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{15} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{15} } func (m *ExecuteBatchShardsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchShardsResponse.Unmarshal(m, b) @@ -1475,7 +1484,7 @@ func (m *BoundKeyspaceIdQuery) Reset() { *m = BoundKeyspaceIdQuery{} } func (m *BoundKeyspaceIdQuery) String() string { return proto.CompactTextString(m) } func (*BoundKeyspaceIdQuery) ProtoMessage() {} func (*BoundKeyspaceIdQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{16} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{16} } func (m *BoundKeyspaceIdQuery) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BoundKeyspaceIdQuery.Unmarshal(m, b) @@ -1542,7 +1551,7 @@ func (m *ExecuteBatchKeyspaceIdsRequest) Reset() { *m = ExecuteBatchKeys func (m *ExecuteBatchKeyspaceIdsRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchKeyspaceIdsRequest) ProtoMessage() {} func (*ExecuteBatchKeyspaceIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{17} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{17} } func (m *ExecuteBatchKeyspaceIdsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchKeyspaceIdsRequest.Unmarshal(m, b) @@ -1623,7 +1632,7 @@ func (m *ExecuteBatchKeyspaceIdsResponse) Reset() { *m = ExecuteBatchKey func (m *ExecuteBatchKeyspaceIdsResponse) String() string { return proto.CompactTextString(m) } func (*ExecuteBatchKeyspaceIdsResponse) ProtoMessage() {} func (*ExecuteBatchKeyspaceIdsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{18} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{18} } func (m *ExecuteBatchKeyspaceIdsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecuteBatchKeyspaceIdsResponse.Unmarshal(m, b) @@ -1687,7 +1696,7 @@ func (m *StreamExecuteRequest) Reset() { *m = StreamExecuteRequest{} } func (m *StreamExecuteRequest) String() string { return proto.CompactTextString(m) } func (*StreamExecuteRequest) ProtoMessage() {} func (*StreamExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{19} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{19} } func (m *StreamExecuteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteRequest.Unmarshal(m, b) @@ -1766,7 +1775,7 @@ func (m *StreamExecuteResponse) Reset() { *m = StreamExecuteResponse{} } func (m *StreamExecuteResponse) String() string { return proto.CompactTextString(m) } func (*StreamExecuteResponse) ProtoMessage() {} func (*StreamExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{20} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{20} } func (m *StreamExecuteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteResponse.Unmarshal(m, b) @@ -1817,7 +1826,7 @@ func (m *StreamExecuteShardsRequest) Reset() { *m = StreamExecuteShardsR func (m *StreamExecuteShardsRequest) String() string { return proto.CompactTextString(m) } func (*StreamExecuteShardsRequest) ProtoMessage() {} func (*StreamExecuteShardsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{21} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{21} } func (m *StreamExecuteShardsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteShardsRequest.Unmarshal(m, b) @@ -1894,7 +1903,7 @@ func (m *StreamExecuteShardsResponse) Reset() { *m = StreamExecuteShards func (m *StreamExecuteShardsResponse) String() string { return proto.CompactTextString(m) } func (*StreamExecuteShardsResponse) ProtoMessage() {} func (*StreamExecuteShardsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{22} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{22} } func (m *StreamExecuteShardsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteShardsResponse.Unmarshal(m, b) @@ -1946,7 +1955,7 @@ func (m *StreamExecuteKeyspaceIdsRequest) Reset() { *m = StreamExecuteKe func (m *StreamExecuteKeyspaceIdsRequest) String() string { return proto.CompactTextString(m) } func (*StreamExecuteKeyspaceIdsRequest) ProtoMessage() {} func (*StreamExecuteKeyspaceIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{23} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{23} } func (m *StreamExecuteKeyspaceIdsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteKeyspaceIdsRequest.Unmarshal(m, b) @@ -2023,7 +2032,7 @@ func (m *StreamExecuteKeyspaceIdsResponse) Reset() { *m = StreamExecuteK func (m *StreamExecuteKeyspaceIdsResponse) String() string { return proto.CompactTextString(m) } func (*StreamExecuteKeyspaceIdsResponse) ProtoMessage() {} func (*StreamExecuteKeyspaceIdsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{24} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{24} } func (m *StreamExecuteKeyspaceIdsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteKeyspaceIdsResponse.Unmarshal(m, b) @@ -2075,7 +2084,7 @@ func (m *StreamExecuteKeyRangesRequest) Reset() { *m = StreamExecuteKeyR func (m *StreamExecuteKeyRangesRequest) String() string { return proto.CompactTextString(m) } func (*StreamExecuteKeyRangesRequest) ProtoMessage() {} func (*StreamExecuteKeyRangesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{25} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{25} } func (m *StreamExecuteKeyRangesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteKeyRangesRequest.Unmarshal(m, b) @@ -2152,7 +2161,7 @@ func (m *StreamExecuteKeyRangesResponse) Reset() { *m = StreamExecuteKey func (m *StreamExecuteKeyRangesResponse) String() string { return proto.CompactTextString(m) } func (*StreamExecuteKeyRangesResponse) ProtoMessage() {} func (*StreamExecuteKeyRangesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{26} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{26} } func (m *StreamExecuteKeyRangesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StreamExecuteKeyRangesResponse.Unmarshal(m, b) @@ -2198,7 +2207,7 @@ func (m *BeginRequest) Reset() { *m = BeginRequest{} } func (m *BeginRequest) String() string { return proto.CompactTextString(m) } func (*BeginRequest) ProtoMessage() {} func (*BeginRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{27} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{27} } func (m *BeginRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginRequest.Unmarshal(m, b) @@ -2245,7 +2254,7 @@ func (m *BeginResponse) Reset() { *m = BeginResponse{} } func (m *BeginResponse) String() string { return proto.CompactTextString(m) } func (*BeginResponse) ProtoMessage() {} func (*BeginResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{28} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{28} } func (m *BeginResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_BeginResponse.Unmarshal(m, b) @@ -2293,7 +2302,7 @@ func (m *CommitRequest) Reset() { *m = CommitRequest{} } func (m *CommitRequest) String() string { return proto.CompactTextString(m) } func (*CommitRequest) ProtoMessage() {} func (*CommitRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{29} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{29} } func (m *CommitRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitRequest.Unmarshal(m, b) @@ -2345,7 +2354,7 @@ func (m *CommitResponse) Reset() { *m = CommitResponse{} } func (m *CommitResponse) String() string { return proto.CompactTextString(m) } func (*CommitResponse) ProtoMessage() {} func (*CommitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{30} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{30} } func (m *CommitResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommitResponse.Unmarshal(m, b) @@ -2381,7 +2390,7 @@ func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } func (*RollbackRequest) ProtoMessage() {} func (*RollbackRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{31} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{31} } func (m *RollbackRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackRequest.Unmarshal(m, b) @@ -2426,7 +2435,7 @@ func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } func (*RollbackResponse) ProtoMessage() {} func (*RollbackResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{32} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{32} } func (m *RollbackResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RollbackResponse.Unmarshal(m, b) @@ -2462,7 +2471,7 @@ func (m *ResolveTransactionRequest) Reset() { *m = ResolveTransactionReq func (m *ResolveTransactionRequest) String() string { return proto.CompactTextString(m) } func (*ResolveTransactionRequest) ProtoMessage() {} func (*ResolveTransactionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{33} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{33} } func (m *ResolveTransactionRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ResolveTransactionRequest.Unmarshal(m, b) @@ -2518,7 +2527,7 @@ func (m *MessageStreamRequest) Reset() { *m = MessageStreamRequest{} } func (m *MessageStreamRequest) String() string { return proto.CompactTextString(m) } func (*MessageStreamRequest) ProtoMessage() {} func (*MessageStreamRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{34} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{34} } func (m *MessageStreamRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageStreamRequest.Unmarshal(m, b) @@ -2593,7 +2602,7 @@ func (m *MessageAckRequest) Reset() { *m = MessageAckRequest{} } func (m *MessageAckRequest) String() string { return proto.CompactTextString(m) } func (*MessageAckRequest) ProtoMessage() {} func (*MessageAckRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{35} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{35} } func (m *MessageAckRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageAckRequest.Unmarshal(m, b) @@ -2657,7 +2666,7 @@ func (m *IdKeyspaceId) Reset() { *m = IdKeyspaceId{} } func (m *IdKeyspaceId) String() string { return proto.CompactTextString(m) } func (*IdKeyspaceId) ProtoMessage() {} func (*IdKeyspaceId) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{36} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{36} } func (m *IdKeyspaceId) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_IdKeyspaceId.Unmarshal(m, b) @@ -2710,7 +2719,7 @@ func (m *MessageAckKeyspaceIdsRequest) Reset() { *m = MessageAckKeyspace func (m *MessageAckKeyspaceIdsRequest) String() string { return proto.CompactTextString(m) } func (*MessageAckKeyspaceIdsRequest) ProtoMessage() {} func (*MessageAckKeyspaceIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{37} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{37} } func (m *MessageAckKeyspaceIdsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MessageAckKeyspaceIdsRequest.Unmarshal(m, b) @@ -2769,7 +2778,7 @@ func (m *ResolveTransactionResponse) Reset() { *m = ResolveTransactionRe func (m *ResolveTransactionResponse) String() string { return proto.CompactTextString(m) } func (*ResolveTransactionResponse) ProtoMessage() {} func (*ResolveTransactionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{38} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{38} } func (m *ResolveTransactionResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ResolveTransactionResponse.Unmarshal(m, b) @@ -2887,7 +2896,7 @@ func (m *SplitQueryRequest) Reset() { *m = SplitQueryRequest{} } func (m *SplitQueryRequest) String() string { return proto.CompactTextString(m) } func (*SplitQueryRequest) ProtoMessage() {} func (*SplitQueryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{39} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{39} } func (m *SplitQueryRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryRequest.Unmarshal(m, b) @@ -2976,7 +2985,7 @@ func (m *SplitQueryResponse) Reset() { *m = SplitQueryResponse{} } func (m *SplitQueryResponse) String() string { return proto.CompactTextString(m) } func (*SplitQueryResponse) ProtoMessage() {} func (*SplitQueryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{40} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{40} } func (m *SplitQueryResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryResponse.Unmarshal(m, b) @@ -3017,7 +3026,7 @@ func (m *SplitQueryResponse_KeyRangePart) Reset() { *m = SplitQueryRespo func (m *SplitQueryResponse_KeyRangePart) String() string { return proto.CompactTextString(m) } func (*SplitQueryResponse_KeyRangePart) ProtoMessage() {} func (*SplitQueryResponse_KeyRangePart) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{40, 0} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{40, 0} } func (m *SplitQueryResponse_KeyRangePart) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryResponse_KeyRangePart.Unmarshal(m, b) @@ -3065,7 +3074,7 @@ func (m *SplitQueryResponse_ShardPart) Reset() { *m = SplitQueryResponse func (m *SplitQueryResponse_ShardPart) String() string { return proto.CompactTextString(m) } func (*SplitQueryResponse_ShardPart) ProtoMessage() {} func (*SplitQueryResponse_ShardPart) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{40, 1} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{40, 1} } func (m *SplitQueryResponse_ShardPart) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryResponse_ShardPart.Unmarshal(m, b) @@ -3118,7 +3127,7 @@ func (m *SplitQueryResponse_Part) Reset() { *m = SplitQueryResponse_Part func (m *SplitQueryResponse_Part) String() string { return proto.CompactTextString(m) } func (*SplitQueryResponse_Part) ProtoMessage() {} func (*SplitQueryResponse_Part) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{40, 2} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{40, 2} } func (m *SplitQueryResponse_Part) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SplitQueryResponse_Part.Unmarshal(m, b) @@ -3179,7 +3188,7 @@ func (m *GetSrvKeyspaceRequest) Reset() { *m = GetSrvKeyspaceRequest{} } func (m *GetSrvKeyspaceRequest) String() string { return proto.CompactTextString(m) } func (*GetSrvKeyspaceRequest) ProtoMessage() {} func (*GetSrvKeyspaceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{41} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{41} } func (m *GetSrvKeyspaceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetSrvKeyspaceRequest.Unmarshal(m, b) @@ -3219,7 +3228,7 @@ func (m *GetSrvKeyspaceResponse) Reset() { *m = GetSrvKeyspaceResponse{} func (m *GetSrvKeyspaceResponse) String() string { return proto.CompactTextString(m) } func (*GetSrvKeyspaceResponse) ProtoMessage() {} func (*GetSrvKeyspaceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{42} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{42} } func (m *GetSrvKeyspaceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetSrvKeyspaceResponse.Unmarshal(m, b) @@ -3277,7 +3286,7 @@ func (m *UpdateStreamRequest) Reset() { *m = UpdateStreamRequest{} } func (m *UpdateStreamRequest) String() string { return proto.CompactTextString(m) } func (*UpdateStreamRequest) ProtoMessage() {} func (*UpdateStreamRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{43} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{43} } func (m *UpdateStreamRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UpdateStreamRequest.Unmarshal(m, b) @@ -3365,7 +3374,7 @@ func (m *UpdateStreamResponse) Reset() { *m = UpdateStreamResponse{} } func (m *UpdateStreamResponse) String() string { return proto.CompactTextString(m) } func (*UpdateStreamResponse) ProtoMessage() {} func (*UpdateStreamResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_vtgate_229a16ae636de397, []int{44} + return fileDescriptor_vtgate_071b9c990aff35bf, []int{44} } func (m *UpdateStreamResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UpdateStreamResponse.Unmarshal(m, b) @@ -3453,125 +3462,126 @@ func init() { proto.RegisterEnum("vtgate.TransactionMode", TransactionMode_name, TransactionMode_value) } -func init() { proto.RegisterFile("vtgate.proto", fileDescriptor_vtgate_229a16ae636de397) } - -var fileDescriptor_vtgate_229a16ae636de397 = []byte{ - // 1858 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0x5b, 0x8f, 0x23, 0x47, - 0x15, 0xa6, 0xbb, 0x7d, 0x3d, 0xbe, 0x6e, 0xad, 0x77, 0xd7, 0x71, 0x86, 0x1d, 0xa7, 0xc3, 0x28, - 0x4e, 0xb2, 0xf2, 0x10, 0x07, 0x02, 0x42, 0x48, 0x90, 0xf1, 0x0e, 0x91, 0x95, 0x9d, 0xcd, 0x50, - 0xf6, 0x26, 0x80, 0x88, 0x5a, 0x3d, 0x76, 0xc9, 0xdb, 0xd8, 0xee, 0x76, 0xba, 0xca, 0x0e, 0xc3, - 0x03, 0xca, 0x3f, 0x88, 0x78, 0x40, 0x42, 0x11, 0x12, 0x42, 0x42, 0x42, 0x42, 0xe2, 0x15, 0x09, - 0x78, 0xe1, 0x8d, 0x47, 0xc4, 0x13, 0xef, 0xfc, 0x01, 0x24, 0x7e, 0x41, 0xd4, 0x55, 0xd5, 0x17, - 0xf7, 0x8c, 0x3d, 0x1e, 0xcf, 0x45, 0xde, 0xb7, 0xae, 0x53, 0xd5, 0x55, 0xdf, 0xf9, 0xce, 0x57, - 0xa7, 0x4e, 0x97, 0x0d, 0xf9, 0x39, 0x1b, 0x9a, 0x8c, 0x34, 0xa7, 0xae, 0xc3, 0x1c, 0x94, 0x12, - 0xad, 0x5a, 0xee, 0x93, 0x19, 0x71, 0x4f, 0x85, 0xb1, 0x56, 0x64, 0xce, 0xd4, 0x19, 0x98, 0xcc, - 0x94, 0xed, 0xdc, 0x9c, 0xb9, 0xd3, 0xbe, 0x68, 0xe8, 0x7f, 0xd2, 0x20, 0xdd, 0x25, 0x94, 0x5a, - 0x8e, 0x8d, 0xf6, 0xa0, 0x68, 0xd9, 0x06, 0x73, 0x4d, 0x9b, 0x9a, 0x7d, 0x66, 0x39, 0x76, 0x55, - 0xa9, 0x2b, 0x8d, 0x0c, 0x2e, 0x58, 0x76, 0x2f, 0x34, 0xa2, 0x36, 0x14, 0xe9, 0x73, 0xd3, 0x1d, - 0x18, 0x54, 0xbc, 0x47, 0xab, 0x6a, 0x5d, 0x6b, 0xe4, 0x5a, 0x3b, 0x4d, 0x89, 0x45, 0xce, 0xd7, - 0xec, 0x7a, 0xa3, 0x64, 0x03, 0x17, 0x68, 0xa4, 0x45, 0xd1, 0xcb, 0x90, 0xa5, 0x96, 0x3d, 0x1c, - 0x13, 0x63, 0x70, 0x52, 0xd5, 0xf8, 0x32, 0x19, 0x61, 0x78, 0x7c, 0x82, 0x1e, 0x02, 0x98, 0x33, - 0xe6, 0xf4, 0x9d, 0xc9, 0xc4, 0x62, 0xd5, 0x04, 0xef, 0x8d, 0x58, 0xd0, 0xab, 0x50, 0x60, 0xa6, - 0x3b, 0x24, 0xcc, 0xa0, 0xcc, 0xb5, 0xec, 0x61, 0x35, 0x59, 0x57, 0x1a, 0x59, 0x9c, 0x17, 0xc6, - 0x2e, 0xb7, 0xa1, 0x7d, 0x48, 0x3b, 0x53, 0xc6, 0xf1, 0xa5, 0xea, 0x4a, 0x23, 0xd7, 0xba, 0xd7, - 0x14, 0xac, 0x1c, 0xfe, 0x9c, 0xf4, 0x67, 0x8c, 0x7c, 0x20, 0x3a, 0xb1, 0x3f, 0x0a, 0x1d, 0x40, - 0x39, 0xe2, 0xbb, 0x31, 0x71, 0x06, 0xa4, 0x9a, 0xae, 0x2b, 0x8d, 0x62, 0xeb, 0x81, 0xef, 0x59, - 0x84, 0x86, 0x23, 0x67, 0x40, 0x70, 0x89, 0x2d, 0x1a, 0x6a, 0x3f, 0x85, 0x7c, 0xd4, 0x6b, 0xb4, - 0x07, 0x29, 0x01, 0x8a, 0x53, 0x99, 0x6b, 0x15, 0x24, 0x86, 0x1e, 0x37, 0x62, 0xd9, 0xe9, 0x31, - 0x1f, 0x5d, 0xda, 0x1a, 0x54, 0xd5, 0xba, 0xd2, 0xd0, 0x70, 0x21, 0x62, 0xed, 0x0c, 0xf4, 0x7f, - 0xa9, 0x50, 0x94, 0xe8, 0x31, 0xf9, 0x64, 0x46, 0x28, 0x43, 0x8f, 0x20, 0xdb, 0x37, 0xc7, 0x63, - 0xe2, 0x7a, 0x2f, 0x89, 0x35, 0x4a, 0x4d, 0x11, 0xe0, 0x36, 0xb7, 0x77, 0x1e, 0xe3, 0x8c, 0x18, - 0xd1, 0x19, 0xa0, 0xd7, 0x21, 0x2d, 0x83, 0xc6, 0x17, 0x10, 0x63, 0xa3, 0x31, 0xc3, 0x7e, 0x3f, - 0x7a, 0x0d, 0x92, 0x1c, 0x2a, 0x0f, 0x4e, 0xae, 0x75, 0x47, 0x02, 0x3f, 0x70, 0x66, 0xf6, 0xe0, - 0x87, 0xde, 0x23, 0x16, 0xfd, 0xe8, 0x9b, 0x90, 0x63, 0xe6, 0xc9, 0x98, 0x30, 0x83, 0x9d, 0x4e, - 0x09, 0x8f, 0x56, 0xb1, 0x55, 0x69, 0x06, 0xa2, 0xeb, 0xf1, 0xce, 0xde, 0xe9, 0x94, 0x60, 0x60, - 0xc1, 0x33, 0x7a, 0x04, 0xc8, 0x76, 0x98, 0x11, 0x13, 0x5c, 0x92, 0xc7, 0xba, 0x6c, 0x3b, 0xac, - 0xb3, 0xa0, 0xb9, 0x3d, 0x28, 0x8e, 0xc8, 0x29, 0x9d, 0x9a, 0x7d, 0x62, 0x70, 0x21, 0xf1, 0x98, - 0x66, 0x71, 0xc1, 0xb7, 0x72, 0xd6, 0xa3, 0x31, 0x4f, 0xaf, 0x13, 0x73, 0xfd, 0x73, 0x05, 0x4a, - 0x01, 0xa3, 0x74, 0xea, 0xd8, 0x94, 0xa0, 0x3d, 0x48, 0x12, 0xd7, 0x75, 0xdc, 0x18, 0x9d, 0xf8, - 0xb8, 0x7d, 0xe8, 0x99, 0xb1, 0xe8, 0xbd, 0x0c, 0x97, 0x6f, 0x40, 0xca, 0x25, 0x74, 0x36, 0x66, - 0x92, 0x4c, 0x24, 0x51, 0x09, 0x1e, 0x79, 0x0f, 0x96, 0x23, 0xf4, 0xff, 0xaa, 0x50, 0x91, 0x88, - 0xb8, 0x4f, 0x74, 0x7b, 0x22, 0x5d, 0x83, 0x8c, 0x4f, 0x37, 0x0f, 0x73, 0x16, 0x07, 0x6d, 0x74, - 0x1f, 0x52, 0x3c, 0x2e, 0xb4, 0x9a, 0xac, 0x6b, 0x8d, 0x2c, 0x96, 0xad, 0xb8, 0x3a, 0x52, 0x57, - 0x52, 0x47, 0x7a, 0x89, 0x3a, 0x22, 0x61, 0xcf, 0xac, 0x15, 0xf6, 0x5f, 0x2b, 0x70, 0x2f, 0x46, - 0xf2, 0x56, 0x04, 0xff, 0xff, 0x2a, 0xbc, 0x24, 0x71, 0xbd, 0x2f, 0x99, 0xed, 0xbc, 0x28, 0x0a, - 0x78, 0x05, 0xf2, 0xc1, 0x16, 0xb5, 0xa4, 0x0e, 0xf2, 0x38, 0x37, 0x0a, 0xfd, 0xd8, 0x52, 0x31, - 0x7c, 0xa1, 0x40, 0xed, 0x3c, 0xd2, 0xb7, 0x42, 0x11, 0x9f, 0x69, 0xf0, 0x20, 0x04, 0x87, 0x4d, - 0x7b, 0x48, 0x5e, 0x10, 0x3d, 0xbc, 0x05, 0x30, 0x22, 0xa7, 0x86, 0xcb, 0x21, 0x73, 0x35, 0x78, - 0x9e, 0x06, 0xb1, 0xf6, 0xbd, 0xc1, 0xd9, 0x91, 0xef, 0xd7, 0x96, 0xea, 0xe3, 0x37, 0x0a, 0x54, - 0xcf, 0x86, 0x60, 0x2b, 0xd4, 0xf1, 0xd7, 0x44, 0xa0, 0x8e, 0x43, 0x9b, 0x59, 0xec, 0xf4, 0x85, - 0xc9, 0x16, 0x8f, 0x00, 0x11, 0x8e, 0xd8, 0xe8, 0x3b, 0xe3, 0xd9, 0xc4, 0x36, 0x6c, 0x73, 0x42, - 0x64, 0x1d, 0x57, 0x16, 0x3d, 0x6d, 0xde, 0xf1, 0xd4, 0x9c, 0x10, 0xf4, 0x23, 0xb8, 0x2b, 0x47, - 0x2f, 0xa4, 0x98, 0x14, 0x17, 0x55, 0xc3, 0x47, 0xba, 0x84, 0x89, 0xa6, 0x6f, 0xc0, 0x77, 0xc4, - 0x24, 0xef, 0x2f, 0x4f, 0x49, 0xe9, 0x2b, 0x49, 0x2e, 0x73, 0xb1, 0xe4, 0xb2, 0xeb, 0x48, 0xae, - 0x76, 0x02, 0x19, 0x1f, 0x34, 0xda, 0x85, 0x04, 0x87, 0xa6, 0x70, 0x68, 0x39, 0xbf, 0x80, 0xf4, - 0x10, 0xf1, 0x0e, 0x54, 0x81, 0xe4, 0xdc, 0x1c, 0xcf, 0x08, 0x0f, 0x5c, 0x1e, 0x8b, 0x06, 0xda, - 0x85, 0x5c, 0x84, 0x2b, 0x1e, 0xab, 0x3c, 0x86, 0x30, 0x1b, 0x47, 0x65, 0x1d, 0x61, 0x6c, 0x2b, - 0x64, 0xfd, 0x6f, 0x15, 0xee, 0x4a, 0x68, 0x07, 0x26, 0xeb, 0x3f, 0xbf, 0x71, 0x49, 0xbf, 0x09, - 0x69, 0x0f, 0x8d, 0x45, 0x68, 0x55, 0xe3, 0x9a, 0x3a, 0x47, 0xd4, 0xfe, 0x88, 0x4d, 0x0b, 0xde, - 0x3d, 0x28, 0x9a, 0xf4, 0x9c, 0x62, 0xb7, 0x60, 0xd2, 0xdb, 0xa8, 0x74, 0xbf, 0x50, 0x82, 0xba, - 0x52, 0x72, 0x7a, 0x63, 0xa1, 0xfe, 0x3a, 0xa4, 0x45, 0x20, 0x7d, 0x36, 0xef, 0x4b, 0x6c, 0x22, - 0xcc, 0x1f, 0x59, 0xec, 0xb9, 0x98, 0xda, 0x1f, 0xa6, 0xdb, 0x50, 0xe2, 0x4c, 0x73, 0xdf, 0x38, - 0xdd, 0x61, 0x96, 0x51, 0x2e, 0x91, 0x65, 0xd4, 0xa5, 0x55, 0xa9, 0x16, 0xad, 0x4a, 0xf5, 0xbf, - 0x84, 0x75, 0x16, 0x27, 0xe3, 0x96, 0x2a, 0xed, 0xb7, 0xe2, 0x32, 0x0b, 0x3e, 0x2c, 0x63, 0xde, - 0xdf, 0x96, 0xd8, 0x2e, 0xfb, 0x8d, 0xac, 0xff, 0x36, 0xac, 0x95, 0x16, 0x88, 0xbb, 0x31, 0x2d, - 0x3d, 0x8a, 0x6b, 0xe9, 0xbc, 0xbc, 0x11, 0xe8, 0xe8, 0x97, 0x50, 0xe1, 0x4c, 0x86, 0x19, 0xfe, - 0x1a, 0xc5, 0x14, 0x2f, 0x70, 0xb5, 0x33, 0x05, 0xae, 0xfe, 0x0f, 0x15, 0x1e, 0x46, 0xe9, 0xb9, - 0xcd, 0x22, 0xfe, 0x9d, 0xb8, 0xb8, 0x76, 0x16, 0xc4, 0x15, 0xa3, 0x64, 0x6b, 0x15, 0xf6, 0x7b, - 0x05, 0x76, 0x97, 0x52, 0xb8, 0x25, 0x32, 0xfb, 0xa3, 0x0a, 0x95, 0x2e, 0x73, 0x89, 0x39, 0xb9, - 0xd2, 0x6d, 0x4c, 0xa0, 0x4a, 0xf5, 0x72, 0x57, 0x2c, 0xda, 0xfa, 0x21, 0x8a, 0x1d, 0x25, 0x89, - 0x0b, 0x8e, 0x92, 0xe4, 0x5a, 0x17, 0x65, 0x11, 0x5e, 0x53, 0xab, 0x79, 0xd5, 0xdb, 0x70, 0x2f, - 0x46, 0x94, 0x0c, 0x61, 0x58, 0x0e, 0x28, 0x17, 0x96, 0x03, 0x9f, 0xab, 0x50, 0x5b, 0x98, 0xe5, - 0x2a, 0xe9, 0x7a, 0x6d, 0xd2, 0xa3, 0xa9, 0x40, 0x5b, 0x7a, 0xae, 0x24, 0x56, 0xdd, 0x76, 0x24, - 0xd7, 0x0c, 0xd4, 0xa5, 0x37, 0x49, 0x07, 0x5e, 0x3e, 0x97, 0x90, 0x0d, 0xc8, 0xfd, 0x9d, 0x0a, - 0xbb, 0x0b, 0x73, 0x5d, 0x39, 0x67, 0x5d, 0x0b, 0xc3, 0xf1, 0x64, 0x9b, 0xb8, 0xf0, 0x36, 0xe1, - 0xc6, 0xc8, 0x7e, 0x0a, 0xf5, 0xe5, 0x04, 0x6d, 0xc0, 0xf8, 0x9f, 0x55, 0xf8, 0x6a, 0x7c, 0xc2, - 0xab, 0x7c, 0xd8, 0x5f, 0x0b, 0xdf, 0x8b, 0x5f, 0xeb, 0x89, 0x0d, 0xbe, 0xd6, 0x6f, 0x8c, 0xff, - 0x27, 0xf0, 0x70, 0x19, 0x5d, 0x1b, 0xb0, 0xff, 0x63, 0xc8, 0x1f, 0x90, 0xa1, 0x65, 0x6f, 0xc6, - 0xf5, 0xc2, 0xcf, 0x16, 0xea, 0xe2, 0xcf, 0x16, 0xfa, 0x77, 0xa0, 0x20, 0xa7, 0x96, 0xb8, 0x22, - 0x89, 0x52, 0xb9, 0x20, 0x51, 0x7e, 0xa6, 0x40, 0xa1, 0xcd, 0x7f, 0xdd, 0xb8, 0xf1, 0x42, 0xe1, - 0x3e, 0xa4, 0x4c, 0xe6, 0x4c, 0xac, 0xbe, 0xfc, 0xdd, 0x45, 0xb6, 0xf4, 0x32, 0x14, 0x7d, 0x04, - 0x02, 0xbf, 0xfe, 0x33, 0x28, 0x61, 0x67, 0x3c, 0x3e, 0x31, 0xfb, 0xa3, 0x9b, 0x46, 0xa5, 0x23, - 0x28, 0x87, 0x6b, 0xc9, 0xf5, 0x3f, 0x86, 0x97, 0x30, 0xa1, 0xce, 0x78, 0x4e, 0x22, 0x25, 0xc5, - 0x66, 0x48, 0x10, 0x24, 0x06, 0x4c, 0xfe, 0xae, 0x92, 0xc5, 0xfc, 0x59, 0xff, 0xbb, 0x02, 0x95, - 0x23, 0x42, 0xa9, 0x39, 0x24, 0x42, 0x60, 0x9b, 0x4d, 0xbd, 0xaa, 0x66, 0xac, 0x40, 0x52, 0x9c, - 0xbc, 0x62, 0xbf, 0x89, 0x06, 0xda, 0x87, 0x6c, 0xb0, 0xd9, 0xf8, 0x99, 0x7c, 0xfe, 0x5e, 0xcb, - 0xf8, 0x7b, 0xcd, 0x43, 0x1f, 0xb9, 0x1f, 0xe1, 0xcf, 0xfa, 0xaf, 0x14, 0xb8, 0x23, 0xd1, 0xbf, - 0xbb, 0x69, 0x7c, 0x56, 0x41, 0xf7, 0xd7, 0xd4, 0xc2, 0x35, 0xd1, 0x43, 0xd0, 0xfc, 0x64, 0x9c, - 0x6b, 0xe5, 0xe5, 0x2e, 0xfb, 0xd0, 0x1c, 0xcf, 0x08, 0xf6, 0x3a, 0xf4, 0x23, 0xc8, 0x77, 0x22, - 0x95, 0x26, 0xda, 0x01, 0x35, 0x80, 0xb1, 0x38, 0x5c, 0xb5, 0x06, 0xf1, 0x2b, 0x0a, 0xf5, 0xcc, - 0x15, 0xc5, 0xdf, 0x14, 0xd8, 0x09, 0x5d, 0xbc, 0xf2, 0xc1, 0x74, 0x59, 0x6f, 0xbf, 0x0b, 0x25, - 0x6b, 0x60, 0x9c, 0x39, 0x86, 0x72, 0xad, 0x8a, 0xaf, 0xe2, 0xa8, 0xb3, 0xb8, 0x60, 0x45, 0x5a, - 0x54, 0xdf, 0x81, 0xda, 0x79, 0xe2, 0x95, 0xd2, 0xfe, 0x9f, 0x0a, 0x77, 0xba, 0xd3, 0xb1, 0xc5, - 0x64, 0x8e, 0xba, 0x6e, 0x7f, 0xd6, 0xbe, 0xa4, 0x7b, 0x05, 0xf2, 0xd4, 0xc3, 0x21, 0xef, 0xe1, - 0x64, 0x41, 0x93, 0xe3, 0x36, 0x71, 0x03, 0xe7, 0xc5, 0xc9, 0x1f, 0x32, 0xb3, 0x19, 0x17, 0xa1, - 0x86, 0x41, 0x8e, 0x98, 0xd9, 0x0c, 0x7d, 0x03, 0x1e, 0xd8, 0xb3, 0x89, 0xe1, 0x3a, 0x9f, 0x52, - 0x63, 0x4a, 0x5c, 0x83, 0xcf, 0x6c, 0x4c, 0x4d, 0x97, 0xf1, 0x14, 0xaf, 0xe1, 0xbb, 0xf6, 0x6c, - 0x82, 0x9d, 0x4f, 0xe9, 0x31, 0x71, 0xf9, 0xe2, 0xc7, 0xa6, 0xcb, 0xd0, 0xf7, 0x21, 0x6b, 0x8e, - 0x87, 0x8e, 0x6b, 0xb1, 0xe7, 0x13, 0x79, 0xf1, 0xa6, 0x4b, 0x98, 0x67, 0x98, 0x69, 0xbe, 0xeb, - 0x8f, 0xc4, 0xe1, 0x4b, 0xe8, 0x4d, 0x40, 0x33, 0x4a, 0x0c, 0x01, 0x4e, 0x2c, 0x3a, 0x6f, 0xc9, - 0x5b, 0xb8, 0xd2, 0x8c, 0x92, 0x70, 0x9a, 0x0f, 0x5b, 0xfa, 0x3f, 0x35, 0x40, 0xd1, 0x79, 0x65, - 0x8e, 0xfe, 0x16, 0xa4, 0xf8, 0xfb, 0xb4, 0xaa, 0xf0, 0xd8, 0xee, 0x06, 0x19, 0xea, 0xcc, 0xd8, - 0xa6, 0x07, 0x1b, 0xcb, 0xe1, 0xb5, 0x8f, 0x21, 0xef, 0xef, 0x54, 0xee, 0x4e, 0x34, 0x1a, 0xca, - 0xca, 0xd3, 0x55, 0x5d, 0xe3, 0x74, 0xad, 0x7d, 0x0f, 0xb2, 0xbc, 0xaa, 0xbb, 0x70, 0xee, 0xb0, - 0x16, 0x55, 0xa3, 0xb5, 0x68, 0xed, 0x3f, 0x0a, 0x24, 0xf8, 0xcb, 0x6b, 0x7f, 0xfc, 0x1e, 0xf1, - 0xef, 0x05, 0x81, 0x52, 0x44, 0x4f, 0x24, 0xed, 0xd7, 0x56, 0x50, 0x12, 0xa5, 0x00, 0xe7, 0x47, - 0x51, 0x42, 0xda, 0x00, 0xe2, 0x7f, 0x02, 0x7c, 0x2a, 0xa1, 0xc3, 0xaf, 0xad, 0x98, 0x2a, 0x70, - 0x17, 0x67, 0x69, 0xe0, 0x39, 0x82, 0x04, 0xb5, 0x7e, 0x21, 0xb2, 0xa4, 0x86, 0xf9, 0xb3, 0xfe, - 0x36, 0xdc, 0x7b, 0x8f, 0xb0, 0xae, 0x3b, 0xf7, 0xb7, 0x9b, 0xbf, 0x7d, 0x56, 0xd0, 0xa4, 0x63, - 0xb8, 0x1f, 0x7f, 0x49, 0x2a, 0xe0, 0xdb, 0x90, 0xa7, 0xee, 0xdc, 0x58, 0x78, 0xd3, 0xab, 0x4a, - 0x82, 0xf0, 0x44, 0x5f, 0xca, 0xd1, 0xb0, 0xa1, 0xff, 0x41, 0x85, 0xbb, 0xcf, 0xa6, 0x03, 0x93, - 0x6d, 0xfb, 0xf9, 0xb1, 0x61, 0xa9, 0xb6, 0x03, 0x59, 0x66, 0x4d, 0x08, 0x65, 0xe6, 0x64, 0x2a, - 0x77, 0x72, 0x68, 0xf0, 0x74, 0x45, 0xe6, 0xc4, 0x66, 0xf2, 0x02, 0xd2, 0xd7, 0xd5, 0xa1, 0x67, - 0xeb, 0x39, 0x23, 0x62, 0x63, 0xd1, 0xaf, 0x8f, 0xa0, 0xb2, 0xc8, 0x92, 0x24, 0xbe, 0xe1, 0x4f, - 0xb0, 0x58, 0xb5, 0xc9, 0x62, 0xcf, 0xeb, 0x91, 0x33, 0xa0, 0xd7, 0xa1, 0xec, 0x95, 0x6f, 0x13, - 0x62, 0x84, 0x78, 0xc4, 0x3f, 0x24, 0x4a, 0xc2, 0xde, 0xf3, 0xcd, 0x6f, 0x3c, 0x86, 0x52, 0xec, - 0x5f, 0x1a, 0xa8, 0x04, 0xb9, 0x67, 0x4f, 0xbb, 0xc7, 0x87, 0xed, 0xce, 0x0f, 0x3a, 0x87, 0x8f, - 0xcb, 0x5f, 0x41, 0x00, 0xa9, 0x6e, 0xe7, 0xe9, 0x7b, 0x4f, 0x0e, 0xcb, 0x0a, 0xca, 0x42, 0xf2, - 0xe8, 0xd9, 0x93, 0x5e, 0xa7, 0xac, 0x7a, 0x8f, 0xbd, 0x8f, 0x3e, 0x38, 0x6e, 0x97, 0xb5, 0x83, - 0x77, 0xa0, 0x64, 0x39, 0xcd, 0xb9, 0xc5, 0x08, 0xa5, 0xe2, 0x9f, 0x32, 0x3f, 0x79, 0x55, 0xb6, - 0x2c, 0x67, 0x5f, 0x3c, 0xed, 0x0f, 0x9d, 0xfd, 0x39, 0xdb, 0xe7, 0xbd, 0xfb, 0x42, 0xd6, 0x27, - 0x29, 0xde, 0x7a, 0xfb, 0xcb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, 0xd9, 0xf8, 0xab, 0x97, 0x23, - 0x00, 0x00, +func init() { proto.RegisterFile("vtgate.proto", fileDescriptor_vtgate_071b9c990aff35bf) } + +var fileDescriptor_vtgate_071b9c990aff35bf = []byte{ + // 1883 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0x4f, 0x8f, 0x23, 0x47, + 0x15, 0xa7, 0xbb, 0xfd, 0xf7, 0xf9, 0xef, 0xd6, 0x78, 0x77, 0x1d, 0x67, 0xd8, 0x99, 0x74, 0x18, + 0xc5, 0x49, 0x56, 0x36, 0x71, 0x20, 0x20, 0x84, 0x04, 0x19, 0xef, 0x10, 0x59, 0xd9, 0xd9, 0x0c, + 0x65, 0x6f, 0x16, 0x10, 0x51, 0xab, 0xc7, 0x2e, 0x79, 0x1b, 0xdb, 0xdd, 0x4e, 0x57, 0xd9, 0xcb, + 0x70, 0x40, 0xf9, 0x06, 0x11, 0x07, 0x24, 0x14, 0x21, 0x21, 0x24, 0x24, 0x4e, 0x5c, 0x91, 0x80, + 0x0b, 0x37, 0x8e, 0x88, 0x13, 0x07, 0x6e, 0x7c, 0x01, 0x24, 0x3e, 0x41, 0xd4, 0x55, 0xd5, 0x7f, + 0xdc, 0x33, 0xf6, 0x78, 0x3c, 0x3b, 0x2b, 0xef, 0xc5, 0xea, 0x7a, 0x55, 0xf5, 0xea, 0xbd, 0xdf, + 0xfb, 0xd5, 0xab, 0xd7, 0xd5, 0x86, 0xfc, 0x9c, 0x0d, 0x4d, 0x46, 0x1a, 0x53, 0xd7, 0x61, 0x0e, + 0x4a, 0x89, 0x56, 0x2d, 0xf7, 0xe9, 0x8c, 0xb8, 0x67, 0x42, 0x58, 0x2b, 0x32, 0x67, 0xea, 0x0c, + 0x4c, 0x66, 0xca, 0x76, 0x6e, 0xce, 0xdc, 0x69, 0x5f, 0x34, 0xf4, 0xff, 0x68, 0x90, 0xee, 0x12, + 0x4a, 0x2d, 0xc7, 0x46, 0x07, 0x50, 0xb4, 0x6c, 0x83, 0xb9, 0xa6, 0x4d, 0xcd, 0x3e, 0xb3, 0x1c, + 0xbb, 0xaa, 0xec, 0x2b, 0xf5, 0x0c, 0x2e, 0x58, 0x76, 0x2f, 0x14, 0xa2, 0x36, 0x14, 0xe9, 0x53, + 0xd3, 0x1d, 0x18, 0x54, 0xcc, 0xa3, 0x55, 0x75, 0x5f, 0xab, 0xe7, 0x5a, 0xbb, 0x0d, 0x69, 0x8b, + 0xd4, 0xd7, 0xe8, 0x7a, 0xa3, 0x64, 0x03, 0x17, 0x68, 0xa4, 0x45, 0xd1, 0xab, 0x90, 0xa5, 0x96, + 0x3d, 0x1c, 0x13, 0x63, 0x70, 0x5a, 0xd5, 0xf8, 0x32, 0x19, 0x21, 0x78, 0x70, 0x8a, 0xee, 0x01, + 0x98, 0x33, 0xe6, 0xf4, 0x9d, 0xc9, 0xc4, 0x62, 0xd5, 0x04, 0xef, 0x8d, 0x48, 0xd0, 0xeb, 0x50, + 0x60, 0xa6, 0x3b, 0x24, 0xcc, 0xa0, 0xcc, 0xb5, 0xec, 0x61, 0x35, 0xb9, 0xaf, 0xd4, 0xb3, 0x38, + 0x2f, 0x84, 0x5d, 0x2e, 0x43, 0x4d, 0x48, 0x3b, 0x53, 0xc6, 0xed, 0x4b, 0xed, 0x2b, 0xf5, 0x5c, + 0xeb, 0x76, 0x43, 0xa0, 0x72, 0xf4, 0x73, 0xd2, 0x9f, 0x31, 0xf2, 0x91, 0xe8, 0xc4, 0xfe, 0x28, + 0x74, 0x08, 0xe5, 0x88, 0xef, 0xc6, 0xc4, 0x19, 0x90, 0x6a, 0x7a, 0x5f, 0xa9, 0x17, 0x5b, 0x77, + 0x7d, 0xcf, 0x22, 0x30, 0x1c, 0x3b, 0x03, 0x82, 0x4b, 0x6c, 0x51, 0x80, 0x9a, 0x90, 0x79, 0x66, + 0xba, 0xb6, 0x65, 0x0f, 0x69, 0x35, 0xc3, 0x51, 0xd9, 0x91, 0xab, 0xfe, 0xd0, 0xfb, 0x7d, 0x22, + 0xfa, 0x70, 0x30, 0xa8, 0xf6, 0x53, 0xc8, 0x47, 0x61, 0x42, 0x07, 0x90, 0x12, 0x5e, 0x70, 0xec, + 0x73, 0xad, 0x82, 0x9c, 0xde, 0xe3, 0x42, 0x2c, 0x3b, 0xbd, 0x50, 0x45, 0x6d, 0xb5, 0x06, 0x55, + 0x75, 0x5f, 0xa9, 0x6b, 0xb8, 0x10, 0x91, 0x76, 0x06, 0xfa, 0x3f, 0x55, 0x28, 0x4a, 0x77, 0x31, + 0xf9, 0x74, 0x46, 0x28, 0x43, 0xf7, 0x21, 0xdb, 0x37, 0xc7, 0x63, 0xe2, 0x7a, 0x93, 0xc4, 0x1a, + 0xa5, 0x86, 0x60, 0x44, 0x9b, 0xcb, 0x3b, 0x0f, 0x70, 0x46, 0x8c, 0xe8, 0x0c, 0xd0, 0x9b, 0x90, + 0x96, 0x51, 0xe6, 0x0b, 0x88, 0xb1, 0xd1, 0x20, 0x63, 0xbf, 0x1f, 0xbd, 0x01, 0x49, 0x6e, 0x2a, + 0x8f, 0x66, 0xae, 0x75, 0x4b, 0x1a, 0x7e, 0xe8, 0xcc, 0xec, 0x01, 0x77, 0x1e, 0x8b, 0x7e, 0xf4, + 0x4d, 0xc8, 0x31, 0xf3, 0x74, 0x4c, 0x98, 0xc1, 0xce, 0xa6, 0x84, 0x87, 0xb7, 0xd8, 0xaa, 0x34, + 0x02, 0x96, 0xf6, 0x78, 0x67, 0xef, 0x6c, 0x4a, 0x30, 0xb0, 0xe0, 0x19, 0xdd, 0x07, 0x64, 0x3b, + 0xcc, 0x88, 0x31, 0x34, 0xc9, 0xc9, 0x51, 0xb6, 0x1d, 0xd6, 0x59, 0x20, 0xe9, 0x01, 0x14, 0x47, + 0xe4, 0x8c, 0x4e, 0xcd, 0x3e, 0x31, 0x38, 0xf3, 0x38, 0x09, 0xb2, 0xb8, 0xe0, 0x4b, 0x39, 0xea, + 0x51, 0x92, 0xa4, 0xd7, 0x21, 0x89, 0xfe, 0xb9, 0x02, 0xa5, 0x00, 0x51, 0x3a, 0x75, 0x6c, 0x4a, + 0xd0, 0x01, 0x24, 0x89, 0xeb, 0x3a, 0x6e, 0x0c, 0x4e, 0x7c, 0xd2, 0x3e, 0xf2, 0xc4, 0x58, 0xf4, + 0x5e, 0x05, 0xcb, 0xb7, 0x20, 0xe5, 0x12, 0x3a, 0x1b, 0x33, 0x09, 0x26, 0x8a, 0x92, 0x08, 0xf3, + 0x1e, 0x2c, 0x47, 0xe8, 0xff, 0x55, 0xa1, 0x22, 0x2d, 0xe2, 0x3e, 0xd1, 0xed, 0x89, 0x74, 0x0d, + 0x32, 0x3e, 0xdc, 0x3c, 0xcc, 0x59, 0x1c, 0xb4, 0xd1, 0x1d, 0x48, 0xf1, 0xb8, 0xd0, 0x6a, 0x72, + 0x5f, 0xab, 0x67, 0xb1, 0x6c, 0xc5, 0xd9, 0x91, 0xba, 0x16, 0x3b, 0xd2, 0x4b, 0xd8, 0x11, 0x09, + 0x7b, 0x66, 0xad, 0xb0, 0xff, 0x5a, 0x81, 0xdb, 0x31, 0x90, 0xb7, 0x22, 0xf8, 0xff, 0x57, 0xe1, + 0x15, 0x69, 0xd7, 0x87, 0x12, 0xd9, 0xce, 0xcb, 0xc2, 0x80, 0xd7, 0x20, 0x1f, 0x6c, 0x51, 0x4b, + 0xf2, 0x20, 0x8f, 0x73, 0xa3, 0xd0, 0x8f, 0x2d, 0x25, 0xc3, 0x17, 0x0a, 0xd4, 0x2e, 0x02, 0x7d, + 0x2b, 0x18, 0xf1, 0x99, 0x06, 0x77, 0x43, 0xe3, 0xb0, 0x69, 0x0f, 0xc9, 0x4b, 0xc2, 0x87, 0x77, + 0x00, 0x46, 0xe4, 0xcc, 0x70, 0xb9, 0xc9, 0x9c, 0x0d, 0x9e, 0xa7, 0x41, 0xac, 0x7d, 0x6f, 0x70, + 0x76, 0xe4, 0xfb, 0xb5, 0xa5, 0xfc, 0xf8, 0x8d, 0x02, 0xd5, 0xf3, 0x21, 0xd8, 0x0a, 0x76, 0xfc, + 0x25, 0x11, 0xb0, 0xe3, 0xc8, 0x66, 0x16, 0x3b, 0x7b, 0x69, 0xb2, 0xc5, 0x7d, 0x40, 0x84, 0x5b, + 0x6c, 0xf4, 0x9d, 0xf1, 0x6c, 0x62, 0x1b, 0xb6, 0x39, 0x21, 0xb2, 0xf0, 0x2b, 0x8b, 0x9e, 0x36, + 0xef, 0x78, 0x64, 0x4e, 0x08, 0xfa, 0x11, 0xec, 0xc8, 0xd1, 0x0b, 0x29, 0x26, 0xc5, 0x49, 0x55, + 0xf7, 0x2d, 0x5d, 0x82, 0x44, 0xc3, 0x17, 0xe0, 0x5b, 0x42, 0xc9, 0x87, 0xcb, 0x53, 0x52, 0xfa, + 0x5a, 0x94, 0xcb, 0x5c, 0x4e, 0xb9, 0xec, 0x3a, 0x94, 0xab, 0x9d, 0x42, 0xc6, 0x37, 0x1a, 0xed, + 0x41, 0x82, 0x9b, 0xa6, 0x70, 0xd3, 0x72, 0x7e, 0x01, 0xe9, 0x59, 0xc4, 0x3b, 0x50, 0x05, 0x92, + 0x73, 0x73, 0x3c, 0x23, 0x3c, 0x70, 0x79, 0x2c, 0x1a, 0x68, 0x0f, 0x72, 0x11, 0xac, 0x78, 0xac, + 0xf2, 0x18, 0xc2, 0x6c, 0x1c, 0xa5, 0x75, 0x04, 0xb1, 0xad, 0xa0, 0xf5, 0xbf, 0x54, 0xd8, 0x91, + 0xa6, 0x1d, 0x9a, 0xac, 0xff, 0xf4, 0xc6, 0x29, 0xfd, 0x36, 0xa4, 0x3d, 0x6b, 0x2c, 0x42, 0xab, + 0x1a, 0xe7, 0xd4, 0x05, 0xa4, 0xf6, 0x47, 0x6c, 0x5a, 0xf0, 0x1e, 0x40, 0xd1, 0xa4, 0x17, 0x14, + 0xbb, 0x05, 0x93, 0xbe, 0x88, 0x4a, 0xf7, 0x0b, 0x25, 0xa8, 0x2b, 0x25, 0xa6, 0x37, 0x16, 0xea, + 0xaf, 0x43, 0x5a, 0x04, 0xd2, 0x47, 0xf3, 0x8e, 0xb4, 0x4d, 0x84, 0xf9, 0x89, 0xc5, 0x9e, 0x0a, + 0xd5, 0xfe, 0x30, 0xdd, 0x86, 0x12, 0x47, 0x9a, 0xfb, 0xc6, 0xe1, 0x0e, 0xb3, 0x8c, 0x72, 0x85, + 0x2c, 0xa3, 0x2e, 0xad, 0x4a, 0xb5, 0x68, 0x55, 0xaa, 0xff, 0x39, 0xac, 0xb3, 0x38, 0x18, 0x2f, + 0xa8, 0xd2, 0x7e, 0x27, 0x4e, 0xb3, 0xe0, 0x4d, 0x34, 0xe6, 0xfd, 0x8b, 0x22, 0xdb, 0x55, 0x5f, + 0xaa, 0xf5, 0xdf, 0x86, 0xb5, 0xd2, 0x02, 0x70, 0x37, 0xc6, 0xa5, 0xfb, 0x71, 0x2e, 0x5d, 0x94, + 0x37, 0x02, 0x1e, 0xfd, 0x12, 0x2a, 0x1c, 0xc9, 0x30, 0xc3, 0x3f, 0x47, 0x32, 0xc5, 0x0b, 0x5c, + 0xed, 0x5c, 0x81, 0xab, 0xff, 0x5d, 0x85, 0x7b, 0x51, 0x78, 0x5e, 0x64, 0x11, 0xff, 0x5e, 0x9c, + 0x5c, 0xbb, 0x0b, 0xe4, 0x8a, 0x41, 0xb2, 0xb5, 0x0c, 0xfb, 0xbd, 0x02, 0x7b, 0x4b, 0x21, 0xdc, + 0x12, 0x9a, 0xfd, 0x51, 0x85, 0x4a, 0x97, 0xb9, 0xc4, 0x9c, 0x5c, 0xeb, 0x36, 0x26, 0x60, 0xa5, + 0x7a, 0xb5, 0x2b, 0x16, 0x6d, 0xfd, 0x10, 0xc5, 0x8e, 0x92, 0xc4, 0x25, 0x47, 0x49, 0x72, 0xad, + 0x9b, 0xb5, 0x08, 0xae, 0xa9, 0xd5, 0xb8, 0xea, 0x6d, 0xb8, 0x1d, 0x03, 0x4a, 0x86, 0x30, 0x2c, + 0x07, 0x94, 0x4b, 0xcb, 0x81, 0xcf, 0x55, 0xa8, 0x2d, 0x68, 0xb9, 0x4e, 0xba, 0x5e, 0x1b, 0xf4, + 0x68, 0x2a, 0xd0, 0x96, 0x9e, 0x2b, 0x89, 0x55, 0xb7, 0x1d, 0xc9, 0x35, 0x03, 0x75, 0xe5, 0x4d, + 0xd2, 0x81, 0x57, 0x2f, 0x04, 0x64, 0x03, 0x70, 0x7f, 0xa7, 0xc2, 0xde, 0x82, 0xae, 0x6b, 0xe7, + 0xac, 0xe7, 0x82, 0x70, 0x3c, 0xd9, 0x26, 0x2e, 0xbd, 0x4d, 0xb8, 0x31, 0xb0, 0x1f, 0xc1, 0xfe, + 0x72, 0x80, 0x36, 0x40, 0xfc, 0x4f, 0x2a, 0x7c, 0x35, 0xae, 0xf0, 0x3a, 0x2f, 0xf6, 0xcf, 0x05, + 0xef, 0xc5, 0xb7, 0xf5, 0xc4, 0x06, 0x6f, 0xeb, 0x37, 0x86, 0xff, 0x43, 0xb8, 0xb7, 0x0c, 0xae, + 0x0d, 0xd0, 0xff, 0x31, 0xe4, 0x0f, 0xc9, 0xd0, 0xb2, 0x37, 0xc3, 0x7a, 0xe1, 0x3b, 0x87, 0xba, + 0xf8, 0x9d, 0x43, 0xff, 0x0e, 0x14, 0xa4, 0x6a, 0x69, 0x57, 0x24, 0x51, 0x2a, 0x97, 0x24, 0xca, + 0xcf, 0x14, 0x28, 0xb4, 0xf9, 0xe7, 0x90, 0x1b, 0x2f, 0x14, 0xee, 0x40, 0xca, 0x64, 0xce, 0xc4, + 0xea, 0xcb, 0x0f, 0x35, 0xb2, 0xa5, 0x97, 0xa1, 0xe8, 0x5b, 0x20, 0xec, 0xd7, 0x7f, 0x06, 0x25, + 0xec, 0x8c, 0xc7, 0xa7, 0x66, 0x7f, 0x74, 0xd3, 0x56, 0xe9, 0x08, 0xca, 0xe1, 0x5a, 0x72, 0xfd, + 0x4f, 0xe0, 0x15, 0x4c, 0xa8, 0x33, 0x9e, 0x93, 0x48, 0x49, 0xb1, 0x99, 0x25, 0x08, 0x12, 0x03, + 0x26, 0xbf, 0xab, 0x64, 0x31, 0x7f, 0xd6, 0xff, 0xa6, 0x40, 0xe5, 0x98, 0x50, 0x6a, 0x0e, 0x89, + 0x20, 0xd8, 0x66, 0xaa, 0x57, 0xd5, 0x8c, 0x15, 0x48, 0x8a, 0x93, 0x57, 0xec, 0x37, 0xd1, 0x40, + 0x4d, 0xc8, 0x06, 0x9b, 0x8d, 0x9f, 0xc9, 0x17, 0xef, 0xb5, 0x8c, 0xbf, 0xd7, 0x3c, 0xeb, 0x23, + 0xf7, 0x23, 0xfc, 0x59, 0xff, 0x95, 0x02, 0xb7, 0xa4, 0xf5, 0xef, 0x6f, 0x1a, 0x9f, 0x55, 0xa6, + 0xfb, 0x6b, 0x6a, 0xe1, 0x9a, 0xe8, 0x1e, 0x68, 0x7e, 0x32, 0xce, 0xb5, 0xf2, 0x72, 0x97, 0x7d, + 0x6c, 0x8e, 0x67, 0x04, 0x7b, 0x1d, 0xfa, 0x31, 0xe4, 0x3b, 0x91, 0x4a, 0x13, 0xed, 0x82, 0x1a, + 0x98, 0xb1, 0x38, 0x5c, 0xb5, 0x06, 0xf1, 0x2b, 0x0a, 0xf5, 0xdc, 0x15, 0xc5, 0x5f, 0x15, 0xd8, + 0x0d, 0x5d, 0xbc, 0xf6, 0xc1, 0x74, 0x55, 0x6f, 0xbf, 0x0b, 0x25, 0x6b, 0x60, 0x9c, 0x3b, 0x86, + 0x72, 0xad, 0x8a, 0xcf, 0xe2, 0xa8, 0xb3, 0xb8, 0x60, 0x45, 0x5a, 0x54, 0xdf, 0x85, 0xda, 0x45, + 0xe4, 0x95, 0xd4, 0xfe, 0x9f, 0x0a, 0xb7, 0xba, 0xd3, 0xb1, 0xc5, 0x64, 0x8e, 0x7a, 0xde, 0xfe, + 0xac, 0x7d, 0x49, 0xf7, 0x1a, 0xe4, 0xa9, 0x67, 0x87, 0xbc, 0x87, 0x93, 0x05, 0x4d, 0x8e, 0xcb, + 0xc4, 0x0d, 0x9c, 0x17, 0x27, 0x7f, 0xc8, 0xcc, 0x66, 0x9c, 0x84, 0x1a, 0x06, 0x39, 0x62, 0x66, + 0x33, 0xf4, 0x0d, 0xb8, 0x6b, 0xcf, 0x26, 0x86, 0xeb, 0x3c, 0xa3, 0xc6, 0x94, 0xb8, 0x06, 0xd7, + 0x6c, 0x4c, 0x4d, 0x97, 0xf1, 0x14, 0xaf, 0xe1, 0x1d, 0x7b, 0x36, 0xc1, 0xce, 0x33, 0x7a, 0x42, + 0x5c, 0xbe, 0xf8, 0x89, 0xe9, 0x32, 0xf4, 0x7d, 0xc8, 0x9a, 0xe3, 0xa1, 0xe3, 0x5a, 0xec, 0xe9, + 0x44, 0x5e, 0xbc, 0xe9, 0xd2, 0xcc, 0x73, 0xc8, 0x34, 0xde, 0xf7, 0x47, 0xe2, 0x70, 0x12, 0x7a, + 0x1b, 0xd0, 0x8c, 0x12, 0x43, 0x18, 0x27, 0x16, 0x9d, 0xb7, 0xe4, 0x2d, 0x5c, 0x69, 0x46, 0x49, + 0xa8, 0xe6, 0xe3, 0x96, 0xfe, 0x0f, 0x0d, 0x50, 0x54, 0xaf, 0xcc, 0xd1, 0xdf, 0x82, 0x14, 0x9f, + 0x4f, 0xab, 0x0a, 0x8f, 0xed, 0x5e, 0x90, 0xa1, 0xce, 0x8d, 0x6d, 0x78, 0x66, 0x63, 0x39, 0xbc, + 0xf6, 0x09, 0xe4, 0xfd, 0x9d, 0xca, 0xdd, 0x89, 0x46, 0x43, 0x59, 0x79, 0xba, 0xaa, 0x6b, 0x9c, + 0xae, 0xb5, 0xef, 0x41, 0x96, 0x57, 0x75, 0x97, 0xea, 0x0e, 0x6b, 0x51, 0x35, 0x5a, 0x8b, 0xd6, + 0xfe, 0xad, 0x40, 0x82, 0x4f, 0x5e, 0xfb, 0xe5, 0xf7, 0x98, 0xbf, 0x2f, 0x08, 0x2b, 0x45, 0xf4, + 0x44, 0xd2, 0x7e, 0x63, 0x05, 0x24, 0x51, 0x08, 0x70, 0x7e, 0x14, 0x05, 0xa4, 0x0d, 0x20, 0xfe, + 0x58, 0xc0, 0x55, 0x09, 0x1e, 0x7e, 0x6d, 0x85, 0xaa, 0xc0, 0x5d, 0x9c, 0xa5, 0x81, 0xe7, 0x08, + 0x12, 0xd4, 0xfa, 0x85, 0xc8, 0x92, 0x1a, 0xe6, 0xcf, 0xfa, 0xbb, 0x70, 0xfb, 0x03, 0xc2, 0xba, + 0xee, 0xdc, 0xdf, 0x6e, 0xfe, 0xf6, 0x59, 0x01, 0x93, 0x8e, 0xe1, 0x4e, 0x7c, 0x92, 0x64, 0xc0, + 0xb7, 0x21, 0x4f, 0xdd, 0xb9, 0xb1, 0x30, 0xd3, 0xab, 0x4a, 0x82, 0xf0, 0x44, 0x27, 0xe5, 0x68, + 0xd8, 0xd0, 0xff, 0xa0, 0xc2, 0xce, 0xe3, 0xe9, 0xc0, 0x64, 0xdb, 0x7e, 0x7e, 0x6c, 0x58, 0xaa, + 0xed, 0x42, 0x96, 0x59, 0x13, 0x42, 0x99, 0x39, 0x99, 0xca, 0x9d, 0x1c, 0x0a, 0x3c, 0x5e, 0x91, + 0x39, 0xb1, 0x99, 0xbc, 0x80, 0xf4, 0x79, 0x75, 0xe4, 0xc9, 0x7a, 0xce, 0x88, 0xd8, 0x58, 0xf4, + 0xeb, 0x23, 0xa8, 0x2c, 0xa2, 0x24, 0x81, 0xaf, 0xfb, 0x0a, 0x16, 0xab, 0x36, 0x59, 0xec, 0x79, + 0x3d, 0x52, 0x03, 0x7a, 0x13, 0xca, 0x5e, 0xf9, 0x36, 0x21, 0x46, 0x68, 0x8f, 0xf8, 0x87, 0x44, + 0x49, 0xc8, 0x7b, 0xbe, 0xf8, 0xad, 0x07, 0x50, 0x8a, 0xfd, 0xad, 0x03, 0x95, 0x20, 0xf7, 0xf8, + 0x51, 0xf7, 0xe4, 0xa8, 0xdd, 0xf9, 0x41, 0xe7, 0xe8, 0x41, 0xf9, 0x2b, 0x08, 0x20, 0xd5, 0xed, + 0x3c, 0xfa, 0xe0, 0xe1, 0x51, 0x59, 0x41, 0x59, 0x48, 0x1e, 0x3f, 0x7e, 0xd8, 0xeb, 0x94, 0x55, + 0xef, 0xb1, 0xf7, 0xe4, 0xa3, 0x93, 0x76, 0x59, 0x3b, 0x7c, 0x0f, 0x4a, 0x96, 0xd3, 0x98, 0x5b, + 0x8c, 0x50, 0x2a, 0xfe, 0x5a, 0xf3, 0x93, 0xd7, 0x65, 0xcb, 0x72, 0x9a, 0xe2, 0xa9, 0x39, 0x74, + 0x9a, 0x73, 0xd6, 0xe4, 0xbd, 0x4d, 0x41, 0xeb, 0xd3, 0x14, 0x6f, 0xbd, 0xfb, 0x65, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x52, 0xf0, 0x0f, 0xdd, 0xc8, 0x23, 0x00, 0x00, } diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index 010d63aafda..1c459cee5b9 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -91,7 +91,7 @@ func Preview(sql string) int { return StmtRollback } switch loweredFirstWord { - case "create", "alter", "rename", "drop", "truncate": + case "create", "alter", "rename", "drop", "truncate", "flush": return StmtDDL case "set": return StmtSet diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index 1cf53209db8..e0107dd1cfe 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -114,6 +114,12 @@ func ParseStrictDDL(sql string) (Statement, error) { return tokenizer.ParseTree, nil } +// ParseTokenizer is a raw interface to parse from the given tokenizer. +// This does not used pooled parsers, and should not be used in general. +func ParseTokenizer(tokenizer *Tokenizer) int { + return yyParse(tokenizer) +} + // ParseNext parses a single SQL statement from the tokenizer // returning a Statement which is the AST representation of the query. // The tokenizer will always read up to the end of the statement, allowing for @@ -581,6 +587,7 @@ func (*ParenSelect) iInsertRows() {} // If you add fields here, consider adding them to calls to validateSubquerySamePlan. type Update struct { Comments Comments + Ignore string TableExprs TableExprs Exprs UpdateExprs Where *Where @@ -590,8 +597,8 @@ type Update struct { // Format formats the node. func (node *Update) Format(buf *TrackedBuffer) { - buf.Myprintf("update %v%v set %v%v%v%v", - node.Comments, node.TableExprs, + buf.Myprintf("update %v%s%v set %v%v%v%v", + node.Comments, node.Ignore, node.TableExprs, node.Exprs, node.Where, node.OrderBy, node.Limit) } @@ -732,6 +739,7 @@ const ( DropStr = "drop" RenameStr = "rename" TruncateStr = "truncate" + FlushStr = "flush" CreateVindexStr = "create vindex" AddColVindexStr = "add vindex" DropColVindexStr = "drop vindex" @@ -765,6 +773,8 @@ func (node *DDL) Format(buf *TrackedBuffer) { } else { buf.Myprintf("%s table %v", node.Action, node.Table) } + case FlushStr: + buf.Myprintf("%s", node.Action) case CreateVindexStr: buf.Myprintf("%s %v %v", node.Action, node.VindexSpec.Name, node.VindexSpec) case AddColVindexStr: @@ -1479,10 +1489,10 @@ type Show struct { // Format formats the node. func (node *Show) Format(buf *TrackedBuffer) { - if (node.Type == "tables" || node.Type == "columns") && node.ShowTablesOpt != nil { + if (node.Type == "tables" || node.Type == "columns" || node.Type == "fields") && node.ShowTablesOpt != nil { opt := node.ShowTablesOpt buf.Myprintf("show %s%s", opt.Full, node.Type) - if node.Type == "columns" && node.HasOnTable() { + if (node.Type == "columns" || node.Type == "fields") && node.HasOnTable() { buf.Myprintf(" from %v", node.OnTable) } if opt.DbName != "" { diff --git a/go/vt/sqlparser/ast_test.go b/go/vt/sqlparser/ast_test.go index cd4854b9c76..cf1d8d9c375 100644 --- a/go/vt/sqlparser/ast_test.go +++ b/go/vt/sqlparser/ast_test.go @@ -191,6 +191,119 @@ func TestSetLimit(t *testing.T) { } } +func TestSetAutocommitON(t *testing.T) { + stmt, err := Parse("SET autocommit=ON") + if err != nil { + t.Error(err) + } + s, ok := stmt.(*Set) + if !ok { + t.Errorf("SET statement is not Set: %T", s) + } + + if len(s.Exprs) < 1 { + t.Errorf("SET statement has no expressions") + } + + e := s.Exprs[0] + switch v := e.Expr.(type) { + case *SQLVal: + if v.Type != StrVal { + t.Errorf("SET statement value is not StrVal: %T", v) + } + + if !bytes.Equal([]byte("on"), v.Val) { + t.Errorf("SET statement value want: on, got: %s", v.Val) + } + default: + t.Errorf("SET statement expression is not SQLVal: %T", e.Expr) + } + + stmt, err = Parse("SET @@session.autocommit=ON") + if err != nil { + t.Error(err) + } + s, ok = stmt.(*Set) + if !ok { + t.Errorf("SET statement is not Set: %T", s) + } + + if len(s.Exprs) < 1 { + t.Errorf("SET statement has no expressions") + } + + e = s.Exprs[0] + switch v := e.Expr.(type) { + case *SQLVal: + if v.Type != StrVal { + t.Errorf("SET statement value is not StrVal: %T", v) + } + + if !bytes.Equal([]byte("on"), v.Val) { + t.Errorf("SET statement value want: on, got: %s", v.Val) + } + default: + t.Errorf("SET statement expression is not SQLVal: %T", e.Expr) + } +} + +func TestSetAutocommitOFF(t *testing.T) { + stmt, err := Parse("SET autocommit=OFF") + if err != nil { + t.Error(err) + } + s, ok := stmt.(*Set) + if !ok { + t.Errorf("SET statement is not Set: %T", s) + } + + if len(s.Exprs) < 1 { + t.Errorf("SET statement has no expressions") + } + + e := s.Exprs[0] + switch v := e.Expr.(type) { + case *SQLVal: + if v.Type != StrVal { + t.Errorf("SET statement value is not StrVal: %T", v) + } + + if !bytes.Equal([]byte("off"), v.Val) { + t.Errorf("SET statement value want: on, got: %s", v.Val) + } + default: + t.Errorf("SET statement expression is not SQLVal: %T", e.Expr) + } + + stmt, err = Parse("SET @@session.autocommit=OFF") + if err != nil { + t.Error(err) + } + s, ok = stmt.(*Set) + if !ok { + t.Errorf("SET statement is not Set: %T", s) + } + + if len(s.Exprs) < 1 { + t.Errorf("SET statement has no expressions") + } + + e = s.Exprs[0] + switch v := e.Expr.(type) { + case *SQLVal: + if v.Type != StrVal { + t.Errorf("SET statement value is not StrVal: %T", v) + } + + if !bytes.Equal([]byte("off"), v.Val) { + t.Errorf("SET statement value want: on, got: %s", v.Val) + } + default: + t.Errorf("SET statement expression is not SQLVal: %T", e.Expr) + } + +} + func TestWhere(t *testing.T) { var w *Where buf := NewTrackedBuffer(nil) diff --git a/go/vt/sqlparser/comments.go b/go/vt/sqlparser/comments.go index 94bfb7aaadf..06f6307da5c 100644 --- a/go/vt/sqlparser/comments.go +++ b/go/vt/sqlparser/comments.go @@ -30,6 +30,8 @@ const ( DirectiveSkipQueryPlanCache = "SKIP_QUERY_PLAN_CACHE" // DirectiveQueryTimeout sets a query timeout in vtgate. Only supported for SELECTS. DirectiveQueryTimeout = "QUERY_TIMEOUT_MS" + // DirectiveScatterErrorsAsWarnings enables partial success scatter select queries + DirectiveScatterErrorsAsWarnings = "SCATTER_ERRORS_AS_WARNINGS" ) func isNonSpace(r rune) bool { diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index c86abe01d98..57a897550ed 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -573,6 +573,9 @@ var ( output: "select 1 from t", }, { input: "select /* dual */ 1 from dual", + }, { + input: "select * from (select 'tables') tables", + output: "select * from (select 'tables' from dual) as `tables`", }, { input: "insert /* simple */ into a values (1)", }, { @@ -663,6 +666,8 @@ var ( }, { input: "update foo f join bar b on f.name = b.name set f.id = b.id where b.name = 'test'", output: "update foo as f join bar as b on f.name = b.name set f.id = b.id where b.name = 'test'", + }, { + input: "update /* ignore */ ignore a set b = 3", }, { input: "delete /* simple */ from a", }, { @@ -694,6 +699,18 @@ var ( input: "set @@session.'autocommit' = true", }, { input: "set @@session.\"autocommit\" = true", + }, { + input: "set @@session.autocommit = ON", + output: "set @@session.autocommit = 'on'", + }, { + input: "set @@session.autocommit= OFF", + output: "set @@session.autocommit = 'off'", + }, { + input: "set autocommit = on", + output: "set autocommit = 'on'", + }, { + input: "set autocommit = off", + output: "set autocommit = 'off'", }, { input: "set names utf8 collate foo", output: "set names 'utf8'", @@ -980,6 +997,12 @@ var ( }, { input: "analyze table a", output: "alter table a", + }, { + input: "flush tables", + output: "flush", + }, { + input: "flush tables with read lock", + output: "flush", }, { input: "show binary logs", output: "show binary logs", @@ -1140,6 +1163,10 @@ var ( input: "show full columns from a like '%'", }, { input: "show full columns from messages from test_keyspace like '%'", + }, { + input: "show full fields from a like '%'", + }, { + input: "show fields from a like '%'", }, { input: "show triggers", output: "show triggers", @@ -1169,6 +1196,9 @@ var ( }, { input: "show warnings", output: "show warnings", + }, { + input: "select warnings from t", + output: "select `warnings` from t", }, { input: "show foobar", output: "show foobar", @@ -1388,6 +1418,29 @@ func TestValidParallel(t *testing.T) { wg.Wait() } +func TestInvalid(t *testing.T) { + invalidSQL := []struct { + input string + err string + }{{ + input: "select a from (select * from tbl)", + err: "Every derived table must have its own alias", + }, { + input: "select a, b from (select * from tbl) sort by a", + err: "syntax error", + }} + + for _, tcase := range invalidSQL { + _, err := Parse(tcase.input) + if err == nil { + t.Errorf("Parse invalid query(%q), got: nil, want: %s...", tcase.input, tcase.err) + } + if err != nil && !strings.Contains(err.Error(), tcase.err) { + t.Errorf("Parse invalid query(%q), got: %v, want: %s...", tcase.input, err, tcase.err) + } + } +} + func TestCaseSensitivity(t *testing.T) { validSQL := []struct { input string diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index a3f59678552..7004dd4feba 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -169,180 +169,184 @@ const BIT_LITERAL = 57406 const NULL = 57407 const TRUE = 57408 const FALSE = 57409 -const OR = 57410 -const AND = 57411 -const NOT = 57412 -const BETWEEN = 57413 -const CASE = 57414 -const WHEN = 57415 -const THEN = 57416 -const ELSE = 57417 -const END = 57418 -const LE = 57419 -const GE = 57420 -const NE = 57421 -const NULL_SAFE_EQUAL = 57422 -const IS = 57423 -const LIKE = 57424 -const REGEXP = 57425 -const IN = 57426 -const SHIFT_LEFT = 57427 -const SHIFT_RIGHT = 57428 -const DIV = 57429 -const MOD = 57430 -const UNARY = 57431 -const COLLATE = 57432 -const BINARY = 57433 -const UNDERSCORE_BINARY = 57434 -const UNDERSCORE_UTF8MB4 = 57435 -const INTERVAL = 57436 -const JSON_EXTRACT_OP = 57437 -const JSON_UNQUOTE_EXTRACT_OP = 57438 -const CREATE = 57439 -const ALTER = 57440 -const DROP = 57441 -const RENAME = 57442 -const ANALYZE = 57443 -const ADD = 57444 -const SCHEMA = 57445 -const TABLE = 57446 -const INDEX = 57447 -const VIEW = 57448 -const TO = 57449 -const IGNORE = 57450 -const IF = 57451 -const UNIQUE = 57452 -const PRIMARY = 57453 -const COLUMN = 57454 -const SPATIAL = 57455 -const FULLTEXT = 57456 -const KEY_BLOCK_SIZE = 57457 -const ACTION = 57458 -const CASCADE = 57459 -const CONSTRAINT = 57460 -const FOREIGN = 57461 -const NO = 57462 -const REFERENCES = 57463 -const RESTRICT = 57464 -const SHOW = 57465 -const DESCRIBE = 57466 -const EXPLAIN = 57467 -const DATE = 57468 -const ESCAPE = 57469 -const REPAIR = 57470 -const OPTIMIZE = 57471 -const TRUNCATE = 57472 -const MAXVALUE = 57473 -const PARTITION = 57474 -const REORGANIZE = 57475 -const LESS = 57476 -const THAN = 57477 -const PROCEDURE = 57478 -const TRIGGER = 57479 -const VINDEX = 57480 -const VINDEXES = 57481 -const STATUS = 57482 -const VARIABLES = 57483 -const BEGIN = 57484 -const START = 57485 -const TRANSACTION = 57486 -const COMMIT = 57487 -const ROLLBACK = 57488 -const BIT = 57489 -const TINYINT = 57490 -const SMALLINT = 57491 -const MEDIUMINT = 57492 -const INT = 57493 -const INTEGER = 57494 -const BIGINT = 57495 -const INTNUM = 57496 -const REAL = 57497 -const DOUBLE = 57498 -const FLOAT_TYPE = 57499 -const DECIMAL = 57500 -const NUMERIC = 57501 -const TIME = 57502 -const TIMESTAMP = 57503 -const DATETIME = 57504 -const YEAR = 57505 -const CHAR = 57506 -const VARCHAR = 57507 -const BOOL = 57508 -const CHARACTER = 57509 -const VARBINARY = 57510 -const NCHAR = 57511 -const TEXT = 57512 -const TINYTEXT = 57513 -const MEDIUMTEXT = 57514 -const LONGTEXT = 57515 -const BLOB = 57516 -const TINYBLOB = 57517 -const MEDIUMBLOB = 57518 -const LONGBLOB = 57519 -const JSON = 57520 -const ENUM = 57521 -const GEOMETRY = 57522 -const POINT = 57523 -const LINESTRING = 57524 -const POLYGON = 57525 -const GEOMETRYCOLLECTION = 57526 -const MULTIPOINT = 57527 -const MULTILINESTRING = 57528 -const MULTIPOLYGON = 57529 -const NULLX = 57530 -const AUTO_INCREMENT = 57531 -const APPROXNUM = 57532 -const SIGNED = 57533 -const UNSIGNED = 57534 -const ZEROFILL = 57535 -const COLLATION = 57536 -const DATABASES = 57537 -const TABLES = 57538 -const VITESS_KEYSPACES = 57539 -const VITESS_SHARDS = 57540 -const VITESS_TABLETS = 57541 -const VSCHEMA_TABLES = 57542 -const VITESS_TARGET = 57543 -const FULL = 57544 -const PROCESSLIST = 57545 -const COLUMNS = 57546 -const NAMES = 57547 -const CHARSET = 57548 -const GLOBAL = 57549 -const SESSION = 57550 -const ISOLATION = 57551 -const LEVEL = 57552 -const READ = 57553 -const WRITE = 57554 -const ONLY = 57555 -const REPEATABLE = 57556 -const COMMITTED = 57557 -const UNCOMMITTED = 57558 -const SERIALIZABLE = 57559 -const CURRENT_TIMESTAMP = 57560 -const DATABASE = 57561 -const CURRENT_DATE = 57562 -const CURRENT_TIME = 57563 -const LOCALTIME = 57564 -const LOCALTIMESTAMP = 57565 -const UTC_DATE = 57566 -const UTC_TIME = 57567 -const UTC_TIMESTAMP = 57568 -const REPLACE = 57569 -const CONVERT = 57570 -const CAST = 57571 -const SUBSTR = 57572 -const SUBSTRING = 57573 -const GROUP_CONCAT = 57574 -const SEPARATOR = 57575 -const MATCH = 57576 -const AGAINST = 57577 -const BOOLEAN = 57578 -const LANGUAGE = 57579 -const WITH = 57580 -const QUERY = 57581 -const EXPANSION = 57582 -const UNUSED = 57583 +const OFF = 57410 +const OR = 57411 +const AND = 57412 +const NOT = 57413 +const BETWEEN = 57414 +const CASE = 57415 +const WHEN = 57416 +const THEN = 57417 +const ELSE = 57418 +const END = 57419 +const LE = 57420 +const GE = 57421 +const NE = 57422 +const NULL_SAFE_EQUAL = 57423 +const IS = 57424 +const LIKE = 57425 +const REGEXP = 57426 +const IN = 57427 +const SHIFT_LEFT = 57428 +const SHIFT_RIGHT = 57429 +const DIV = 57430 +const MOD = 57431 +const UNARY = 57432 +const COLLATE = 57433 +const BINARY = 57434 +const UNDERSCORE_BINARY = 57435 +const UNDERSCORE_UTF8MB4 = 57436 +const INTERVAL = 57437 +const JSON_EXTRACT_OP = 57438 +const JSON_UNQUOTE_EXTRACT_OP = 57439 +const CREATE = 57440 +const ALTER = 57441 +const DROP = 57442 +const RENAME = 57443 +const ANALYZE = 57444 +const ADD = 57445 +const FLUSH = 57446 +const SCHEMA = 57447 +const TABLE = 57448 +const INDEX = 57449 +const VIEW = 57450 +const TO = 57451 +const IGNORE = 57452 +const IF = 57453 +const UNIQUE = 57454 +const PRIMARY = 57455 +const COLUMN = 57456 +const SPATIAL = 57457 +const FULLTEXT = 57458 +const KEY_BLOCK_SIZE = 57459 +const ACTION = 57460 +const CASCADE = 57461 +const CONSTRAINT = 57462 +const FOREIGN = 57463 +const NO = 57464 +const REFERENCES = 57465 +const RESTRICT = 57466 +const SHOW = 57467 +const DESCRIBE = 57468 +const EXPLAIN = 57469 +const DATE = 57470 +const ESCAPE = 57471 +const REPAIR = 57472 +const OPTIMIZE = 57473 +const TRUNCATE = 57474 +const MAXVALUE = 57475 +const PARTITION = 57476 +const REORGANIZE = 57477 +const LESS = 57478 +const THAN = 57479 +const PROCEDURE = 57480 +const TRIGGER = 57481 +const VINDEX = 57482 +const VINDEXES = 57483 +const STATUS = 57484 +const VARIABLES = 57485 +const WARNINGS = 57486 +const BEGIN = 57487 +const START = 57488 +const TRANSACTION = 57489 +const COMMIT = 57490 +const ROLLBACK = 57491 +const BIT = 57492 +const TINYINT = 57493 +const SMALLINT = 57494 +const MEDIUMINT = 57495 +const INT = 57496 +const INTEGER = 57497 +const BIGINT = 57498 +const INTNUM = 57499 +const REAL = 57500 +const DOUBLE = 57501 +const FLOAT_TYPE = 57502 +const DECIMAL = 57503 +const NUMERIC = 57504 +const TIME = 57505 +const TIMESTAMP = 57506 +const DATETIME = 57507 +const YEAR = 57508 +const CHAR = 57509 +const VARCHAR = 57510 +const BOOL = 57511 +const CHARACTER = 57512 +const VARBINARY = 57513 +const NCHAR = 57514 +const TEXT = 57515 +const TINYTEXT = 57516 +const MEDIUMTEXT = 57517 +const LONGTEXT = 57518 +const BLOB = 57519 +const TINYBLOB = 57520 +const MEDIUMBLOB = 57521 +const LONGBLOB = 57522 +const JSON = 57523 +const ENUM = 57524 +const GEOMETRY = 57525 +const POINT = 57526 +const LINESTRING = 57527 +const POLYGON = 57528 +const GEOMETRYCOLLECTION = 57529 +const MULTIPOINT = 57530 +const MULTILINESTRING = 57531 +const MULTIPOLYGON = 57532 +const NULLX = 57533 +const AUTO_INCREMENT = 57534 +const APPROXNUM = 57535 +const SIGNED = 57536 +const UNSIGNED = 57537 +const ZEROFILL = 57538 +const COLLATION = 57539 +const DATABASES = 57540 +const TABLES = 57541 +const VITESS_KEYSPACES = 57542 +const VITESS_SHARDS = 57543 +const VITESS_TABLETS = 57544 +const VSCHEMA_TABLES = 57545 +const VITESS_TARGET = 57546 +const FULL = 57547 +const PROCESSLIST = 57548 +const COLUMNS = 57549 +const FIELDS = 57550 +const NAMES = 57551 +const CHARSET = 57552 +const GLOBAL = 57553 +const SESSION = 57554 +const ISOLATION = 57555 +const LEVEL = 57556 +const READ = 57557 +const WRITE = 57558 +const ONLY = 57559 +const REPEATABLE = 57560 +const COMMITTED = 57561 +const UNCOMMITTED = 57562 +const SERIALIZABLE = 57563 +const CURRENT_TIMESTAMP = 57564 +const DATABASE = 57565 +const CURRENT_DATE = 57566 +const CURRENT_TIME = 57567 +const LOCALTIME = 57568 +const LOCALTIMESTAMP = 57569 +const UTC_DATE = 57570 +const UTC_TIME = 57571 +const UTC_TIMESTAMP = 57572 +const REPLACE = 57573 +const CONVERT = 57574 +const CAST = 57575 +const SUBSTR = 57576 +const SUBSTRING = 57577 +const GROUP_CONCAT = 57578 +const SEPARATOR = 57579 +const MATCH = 57580 +const AGAINST = 57581 +const BOOLEAN = 57582 +const LANGUAGE = 57583 +const WITH = 57584 +const QUERY = 57585 +const EXPANSION = 57586 +const UNUSED = 57587 var yyToknames = [...]string{ "$end", @@ -415,6 +419,7 @@ var yyToknames = [...]string{ "NULL", "TRUE", "FALSE", + "OFF", "OR", "AND", "NOT", @@ -464,6 +469,7 @@ var yyToknames = [...]string{ "RENAME", "ANALYZE", "ADD", + "FLUSH", "SCHEMA", "TABLE", "INDEX", @@ -503,6 +509,7 @@ var yyToknames = [...]string{ "VINDEXES", "STATUS", "VARIABLES", + "WARNINGS", "BEGIN", "START", "TRANSACTION", @@ -566,6 +573,7 @@ var yyToknames = [...]string{ "FULL", "PROCESSLIST", "COLUMNS", + "FIELDS", "NAMES", "CHARSET", "GLOBAL", @@ -617,1204 +625,1226 @@ var yyExca = [...]int{ 1, -1, -2, 0, -1, 3, - 5, 28, + 5, 29, -2, 4, - -1, 36, - 157, 288, - 158, 288, - -2, 280, - -1, 254, - 111, 615, - -2, 611, - -1, 255, - 111, 616, - -2, 612, - -1, 325, - 81, 782, - -2, 59, + -1, 37, + 159, 292, + 160, 292, + -2, 282, + -1, 262, + 112, 622, + -2, 618, + -1, 263, + 112, 623, + -2, 619, -1, 326, - 81, 740, + 82, 791, -2, 60, - -1, 331, - 81, 722, - -2, 577, - -1, 333, - 81, 761, - -2, 579, - -1, 601, - 53, 42, - 55, 42, - -2, 44, - -1, 737, - 111, 618, - -2, 614, - -1, 949, - 5, 29, - -2, 422, - -1, 974, - 5, 28, - -2, 552, - -1, 1201, + -1, 327, + 82, 749, + -2, 61, + -1, 332, + 82, 729, + -2, 584, + -1, 334, + 82, 770, + -2, 586, + -1, 586, + 1, 344, + 5, 344, + 12, 344, + 13, 344, + 14, 344, + 15, 344, + 17, 344, + 19, 344, + 30, 344, + 31, 344, + 42, 344, + 43, 344, + 44, 344, + 45, 344, + 46, 344, + 48, 344, + 49, 344, + 52, 344, + 53, 344, + 55, 344, + 56, 344, + 263, 344, + -2, 362, + -1, 589, + 53, 43, + 55, 43, + -2, 45, + -1, 725, + 112, 625, + -2, 621, + -1, 937, + 5, 30, + -2, 428, + -1, 962, 5, 29, - -2, 553, - -1, 1247, - 5, 28, - -2, 555, - -1, 1313, + -2, 558, + -1, 1202, + 5, 30, + -2, 559, + -1, 1252, 5, 29, - -2, 556, + -2, 561, + -1, 1325, + 5, 30, + -2, 562, } const yyPrivate = 57344 -const yyLast = 11326 +const yyLast = 11302 var yyAct = [...]int{ - 255, 1348, 1304, 548, 673, 1338, 1207, 799, 888, 285, - 1258, 1108, 1136, 817, 1039, 1109, 839, 977, 595, 882, - 233, 1105, 915, 848, 838, 835, 593, 1013, 800, 330, - 460, 80, 762, 993, 772, 198, 941, 702, 198, 1030, - 1042, 852, 1082, 611, 769, 788, 982, 480, 739, 486, - 547, 3, 610, 429, 878, 324, 257, 796, 242, 55, - 492, 597, 500, 923, 198, 198, 80, 321, 319, 54, - 198, 562, 198, 582, 80, 1341, 1325, 1336, 1311, 905, - 1333, 889, 1324, 1310, 1100, 1195, 434, 1268, 1130, 1001, - 310, 830, 1000, 904, 455, 1002, 246, 311, 1131, 1132, - 232, 1144, 1145, 1146, 231, 193, 189, 190, 191, 1149, - 1147, 312, 259, 831, 832, 612, 248, 613, 230, 1021, - 471, 909, 861, 225, 1220, 59, 862, 472, 469, 1236, - 903, 869, 443, 868, 1284, 513, 512, 522, 523, 515, - 516, 517, 518, 519, 520, 521, 514, 1184, 1182, 524, - 61, 62, 63, 64, 65, 224, 1083, 1335, 457, 1332, - 459, 466, 467, 1305, 1063, 797, 1296, 226, 227, 228, - 229, 478, 855, 1259, 853, 187, 1266, 1352, 1356, 900, - 897, 898, 444, 896, 437, 681, 1261, 198, 855, 198, - 456, 458, 1085, 818, 820, 198, 186, 1060, 187, 855, - 672, 430, 198, 1062, 992, 991, 80, 80, 80, 80, - 990, 80, 432, 907, 910, 440, 201, 1014, 188, 1289, - 80, 192, 536, 537, 1087, 1204, 1091, 1069, 1086, 957, - 1084, 836, 935, 711, 504, 1089, 1050, 463, 464, 465, - 450, 468, 1153, 317, 1088, 524, 708, 703, 902, 80, - 475, 430, 1260, 497, 917, 499, 869, 1090, 1092, 1050, - 771, 514, 954, 1294, 524, 1048, 854, 68, 819, 499, - 901, 851, 849, 454, 850, 1267, 1265, 1148, 195, 847, - 853, 1350, 854, 428, 1351, 1163, 1349, 1309, 1048, 489, - 746, 980, 1154, 854, 789, 614, 488, 1061, 1285, 1059, - 714, 715, 69, 1102, 744, 745, 743, 676, 320, 906, - 198, 498, 497, 431, 789, 433, 964, 198, 198, 198, - 1019, 1298, 908, 80, 446, 447, 448, 704, 499, 80, - 1049, 916, 932, 933, 934, 1054, 1051, 1044, 1052, 1047, - 729, 731, 732, 1045, 1046, 730, 1357, 498, 497, 286, - 49, 483, 487, 1049, 476, 477, 494, 1053, 1054, 1051, - 1044, 1052, 1047, 1056, 499, 490, 1045, 1046, 505, 52, - 564, 565, 566, 567, 568, 569, 570, 858, 1315, 742, - 1053, 1227, 859, 498, 497, 1358, 1043, 602, 1226, 185, - 608, 515, 516, 517, 518, 519, 520, 521, 514, 49, - 499, 524, 763, 549, 764, 1292, 1034, 238, 953, 710, - 952, 1033, 560, 316, 513, 512, 522, 523, 515, 516, - 517, 518, 519, 520, 521, 514, 498, 497, 524, 198, - 441, 1022, 442, 1003, 80, 1004, 436, 1317, 449, 1295, - 198, 198, 80, 499, 198, 451, 709, 198, 1243, 1224, - 1014, 198, 309, 80, 80, 80, 80, 80, 80, 80, - 80, 1066, 498, 497, 671, 1031, 942, 80, 80, 1251, - 1334, 479, 680, 21, 198, 1321, 479, 52, 1009, 499, - 690, 1191, 479, 691, 692, 693, 694, 695, 696, 697, - 698, 891, 80, 498, 497, 765, 198, 699, 700, 687, - 1104, 686, 80, 517, 518, 519, 520, 521, 514, 716, - 499, 524, 438, 439, 688, 1251, 1302, 740, 513, 512, - 522, 523, 515, 516, 517, 518, 519, 520, 521, 514, - 677, 237, 524, 675, 737, 670, 284, 1318, 275, 274, - 277, 278, 279, 280, 1251, 1263, 80, 276, 281, 718, - 1251, 479, 1273, 577, 452, 461, 461, 461, 461, 445, - 461, 1272, 601, 1269, 733, 1251, 1252, 78, 735, 461, - 1216, 1215, 1127, 479, 1203, 479, 605, 198, 1160, 1159, - 198, 198, 198, 198, 198, 1156, 1157, 1150, 49, 1156, - 1155, 706, 198, 766, 767, 198, 947, 479, 856, 198, - 978, 776, 329, 533, 198, 198, 535, 824, 80, 604, - 435, 579, 479, 1106, 726, 727, 978, 793, 606, 786, - 604, 80, 584, 587, 588, 589, 585, 774, 586, 590, - 825, 1199, 983, 984, 546, 1326, 550, 551, 552, 553, - 554, 555, 556, 557, 558, 776, 561, 563, 563, 563, - 563, 563, 563, 563, 563, 571, 572, 573, 574, 823, - 822, 717, 828, 827, 814, 23, 594, 549, 781, 784, - 779, 780, 622, 198, 790, 843, 80, 802, 80, 23, - 805, 23, 198, 678, 679, 198, 80, 682, 1072, 884, - 685, 801, 803, 804, 979, 806, 774, 479, 621, 620, - 56, 578, 198, 972, 198, 198, 892, 973, 894, 1246, - 579, 979, 1162, 52, 674, 1158, 913, 705, 1005, 773, - 775, 880, 881, 959, 956, 829, 579, 52, 239, 52, - 1301, 834, 947, 947, 607, 791, 712, 579, 1231, 725, - 947, 737, 329, 329, 329, 329, 1222, 329, 863, 883, - 1141, 1121, 1008, 740, 978, 879, 329, 864, 865, 866, - 867, 874, 924, 873, 925, 816, 1343, 958, 955, 870, - 871, 872, 886, 875, 876, 877, 52, 983, 984, 1339, - 1143, 1106, 1035, 461, 986, 502, 684, 473, 724, 989, - 988, 461, 937, 584, 587, 588, 589, 585, 808, 586, - 590, 807, 461, 461, 461, 461, 461, 461, 461, 461, - 811, 920, 777, 778, 809, 812, 461, 461, 785, 810, - 798, 813, 80, 588, 589, 198, 921, 922, 1330, 487, - 243, 244, 792, 963, 794, 795, 1323, 1068, 493, 80, - 1329, 995, 930, 997, 929, 481, 1026, 974, 826, 619, - 453, 996, 987, 491, 1018, 1006, 1300, 482, 1299, 329, - 1244, 1016, 1010, 1197, 1232, 616, 893, 683, 592, 240, - 241, 493, 234, 998, 928, 1278, 235, 56, 1277, 1234, - 1015, 979, 927, 261, 474, 49, 701, 80, 80, 495, - 80, 948, 1011, 1012, 1025, 1345, 1027, 1028, 1029, 1286, - 550, 1345, 1344, 1221, 707, 58, 965, 60, 603, 53, - 1, 1337, 890, 80, 1032, 1038, 887, 899, 1037, 1303, - 1257, 252, 1135, 846, 837, 911, 67, 198, 912, 316, - 316, 316, 316, 316, 427, 66, 80, 944, 1055, 1293, - 845, 945, 844, 1064, 594, 914, 821, 315, 949, 950, - 951, 1264, 1065, 316, 1219, 857, 1020, 960, 860, 1142, - 1297, 1017, 966, 462, 967, 968, 969, 970, 627, 625, - 329, 626, 624, 629, 628, 1076, 80, 80, 329, 623, - 1107, 1075, 1081, 1110, 931, 209, 1093, 737, 322, 329, - 329, 329, 329, 329, 329, 329, 329, 1094, 1023, 1024, - 591, 615, 885, 329, 329, 496, 80, 1117, 80, 80, - 1115, 70, 1058, 1057, 1129, 895, 470, 211, 532, 1041, - 926, 1101, 999, 328, 1134, 461, 1112, 461, 720, 327, - 1133, 946, 1113, 1138, 1067, 461, 198, 1116, 502, 1139, - 1140, 329, 713, 485, 80, 1276, 1233, 961, 962, 1151, - 1152, 559, 787, 260, 728, 1128, 273, 80, 198, 270, - 272, 271, 719, 971, 80, 506, 258, 250, 314, 575, - 80, 583, 581, 198, 580, 985, 981, 313, 1071, 1194, - 1283, 1103, 768, 723, 25, 801, 936, 57, 1171, 1172, - 245, 801, 782, 782, 19, 18, 1118, 1119, 782, 1173, - 1120, 17, 20, 1122, 16, 15, 14, 1180, 29, 13, - 12, 11, 10, 9, 8, 782, 7, 6, 1080, 5, - 4, 236, 80, 22, 80, 80, 80, 198, 80, 1198, - 1209, 1210, 1211, 2, 80, 0, 0, 1206, 0, 0, - 534, 0, 80, 0, 329, 1212, 975, 976, 1218, 1214, - 1006, 0, 0, 0, 0, 0, 0, 329, 0, 0, - 0, 0, 80, 80, 80, 1126, 1164, 0, 0, 0, - 1070, 0, 0, 0, 316, 0, 0, 1229, 0, 1166, - 1230, 0, 1169, 0, 538, 539, 540, 541, 542, 543, - 544, 545, 1228, 0, 0, 0, 0, 0, 0, 0, - 315, 0, 0, 0, 80, 80, 0, 0, 0, 1110, - 1177, 1178, 329, 1179, 329, 1245, 1181, 80, 1183, 0, - 0, 1196, 329, 0, 0, 0, 1256, 0, 549, 1262, - 0, 0, 80, 0, 0, 0, 0, 461, 1274, 0, - 0, 0, 0, 0, 0, 0, 0, 1174, 329, 1270, - 0, 1271, 80, 1247, 1176, 0, 1110, 0, 1287, 0, - 0, 0, 461, 0, 1217, 1185, 1186, 1187, 1291, 0, - 1190, 0, 0, 0, 0, 0, 0, 0, 0, 1161, - 0, 0, 1307, 1200, 1201, 1202, 327, 1205, 0, 1223, - 80, 1225, 0, 0, 1312, 0, 0, 198, 0, 1288, - 0, 1168, 0, 0, 0, 0, 80, 1319, 0, 0, - 0, 0, 1235, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1111, 1328, 49, 0, 80, 1327, 0, - 0, 0, 0, 1331, 0, 0, 484, 0, 0, 0, - 1123, 1124, 1125, 1342, 0, 0, 0, 1353, 522, 523, - 515, 516, 517, 518, 519, 520, 521, 514, 994, 0, - 524, 0, 0, 0, 0, 0, 1242, 0, 0, 0, - 0, 196, 0, 0, 223, 329, 0, 0, 0, 0, - 0, 1253, 1254, 1255, 0, 0, 0, 0, 0, 0, - 0, 741, 0, 0, 1306, 549, 0, 0, 249, 801, - 196, 196, 0, 0, 0, 0, 196, 0, 196, 1279, - 1280, 1281, 1282, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 316, 1036, 329, 0, 329, 0, 738, 0, - 0, 747, 748, 749, 750, 751, 752, 753, 754, 755, - 756, 757, 758, 759, 760, 761, 0, 0, 0, 329, - 1193, 0, 0, 0, 0, 1308, 0, 0, 0, 0, - 1313, 0, 0, 315, 315, 315, 315, 315, 736, 0, - 0, 0, 329, 0, 0, 1320, 0, 0, 315, 0, - 23, 24, 50, 26, 27, 0, 0, 315, 0, 0, - 0, 0, 0, 0, 329, 0, 0, 0, 0, 42, - 0, 0, 0, 0, 28, 47, 48, 0, 0, 782, - 0, 461, 1114, 994, 0, 782, 1188, 479, 1354, 1355, - 0, 0, 0, 196, 37, 196, 0, 0, 52, 0, - 0, 196, 0, 0, 0, 0, 0, 0, 196, 0, - 1316, 0, 329, 0, 329, 1137, 0, 0, 0, 1111, - 0, 207, 1248, 513, 512, 522, 523, 515, 516, 517, - 518, 519, 520, 521, 514, 0, 0, 524, 0, 0, - 0, 327, 0, 0, 0, 219, 0, 0, 0, 0, - 1165, 0, 1275, 0, 840, 0, 0, 0, 30, 31, - 33, 32, 35, 1167, 0, 0, 1111, 0, 49, 0, - 1170, 0, 0, 0, 0, 0, 329, 0, 0, 0, - 0, 0, 0, 0, 36, 43, 44, 0, 0, 45, - 46, 34, 0, 0, 0, 202, 0, 741, 0, 0, - 0, 0, 204, 38, 39, 0, 40, 41, 0, 210, - 206, 0, 0, 0, 0, 0, 196, 0, 0, 0, - 0, 0, 0, 196, 599, 196, 0, 0, 1208, 0, - 1208, 1208, 1208, 0, 1213, 0, 938, 939, 940, 0, - 329, 208, 0, 0, 212, 736, 0, 0, 1208, 0, - 0, 0, 0, 0, 0, 1340, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 329, 329, - 329, 0, 203, 0, 0, 0, 0, 0, 315, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, - 205, 0, 214, 215, 216, 218, 217, 222, 1192, 0, - 1249, 1250, 221, 220, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1137, 479, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 196, 0, 0, 1208, 0, - 0, 0, 0, 0, 0, 0, 196, 196, 0, 0, - 196, 0, 0, 196, 0, 0, 0, 689, 1290, 0, - 513, 512, 522, 523, 515, 516, 517, 518, 519, 520, - 521, 514, 840, 0, 524, 0, 0, 0, 0, 0, - 196, 513, 512, 522, 523, 515, 516, 517, 518, 519, - 520, 521, 514, 782, 0, 524, 1314, 0, 0, 0, - 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, - 0, 689, 1322, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1040, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1208, 1078, 1079, 0, 0, 0, 0, - 1189, 0, 0, 0, 0, 0, 0, 1095, 1096, 0, - 1098, 1099, 0, 249, 0, 0, 0, 0, 249, 249, - 0, 0, 783, 783, 249, 0, 0, 0, 783, 1074, - 0, 0, 0, 0, 0, 0, 0, 0, 249, 249, - 249, 249, 0, 196, 0, 783, 196, 196, 196, 196, - 196, 1097, 0, 0, 0, 0, 0, 0, 815, 0, - 0, 196, 0, 0, 0, 599, 0, 0, 0, 0, - 196, 196, 0, 513, 512, 522, 523, 515, 516, 517, - 518, 519, 520, 521, 514, 0, 315, 524, 0, 0, - 0, 0, 0, 0, 508, 0, 511, 0, 0, 840, - 0, 840, 525, 526, 527, 528, 529, 530, 531, 0, - 509, 510, 507, 513, 512, 522, 523, 515, 516, 517, - 518, 519, 520, 521, 514, 0, 0, 524, 0, 1175, - 0, 0, 0, 0, 0, 644, 0, 0, 0, 196, - 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, - 0, 196, 512, 522, 523, 515, 516, 517, 518, 519, - 520, 521, 514, 1074, 0, 524, 0, 0, 196, 0, - 918, 919, 1077, 0, 0, 0, 0, 0, 689, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 249, 0, 513, 512, 522, 523, 515, 516, 517, 518, - 519, 520, 521, 514, 0, 0, 524, 0, 0, 0, - 0, 0, 632, 0, 513, 512, 522, 523, 515, 516, - 517, 518, 519, 520, 521, 514, 0, 840, 524, 0, - 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, - 1237, 1238, 0, 1239, 1240, 1241, 0, 0, 645, 0, - 0, 0, 0, 249, 0, 0, 1040, 840, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 658, - 659, 660, 661, 662, 663, 664, 0, 665, 666, 667, - 668, 669, 646, 647, 648, 649, 630, 631, 0, 0, - 633, 196, 634, 635, 636, 637, 638, 639, 640, 641, - 642, 643, 650, 651, 652, 653, 654, 655, 656, 657, - 943, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 513, 512, 522, 523, 515, 516, 517, 518, 519, 520, - 521, 514, 0, 0, 524, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1346, 196, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 783, - 0, 0, 0, 0, 0, 783, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 599, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 415, 405, 0, 377, 418, 355, 369, 426, 370, 371, - 398, 341, 385, 134, 367, 0, 358, 336, 364, 337, - 356, 379, 101, 382, 354, 407, 388, 417, 115, 424, - 117, 393, 0, 153, 126, 0, 0, 381, 409, 383, - 403, 376, 399, 346, 392, 419, 368, 396, 420, 0, - 0, 0, 79, 0, 841, 842, 0, 0, 0, 0, - 0, 94, 0, 395, 414, 366, 397, 335, 394, 0, - 339, 342, 425, 412, 361, 362, 1007, 0, 0, 0, - 0, 0, 0, 380, 384, 400, 374, 0, 0, 0, - 0, 0, 0, 0, 0, 359, 0, 391, 0, 0, - 0, 343, 340, 783, 0, 378, 0, 0, 0, 345, - 0, 360, 401, 196, 334, 404, 410, 375, 199, 413, - 373, 372, 416, 140, 0, 156, 106, 114, 82, 88, - 0, 105, 132, 145, 149, 408, 357, 365, 97, 363, - 147, 136, 168, 390, 137, 146, 118, 160, 141, 167, - 200, 175, 158, 174, 83, 157, 166, 95, 150, 85, - 164, 155, 124, 110, 111, 84, 0, 144, 100, 104, - 99, 133, 161, 162, 98, 183, 89, 173, 87, 90, - 172, 131, 159, 165, 125, 122, 86, 163, 123, 121, - 113, 102, 107, 138, 120, 139, 108, 128, 127, 129, - 0, 338, 0, 154, 170, 184, 92, 353, 411, 176, - 177, 178, 179, 180, 0, 0, 93, 130, 91, 109, - 151, 112, 119, 143, 182, 135, 148, 96, 169, 152, - 349, 352, 347, 348, 386, 387, 421, 422, 423, 402, - 344, 0, 350, 351, 0, 406, 389, 81, 0, 116, - 181, 142, 103, 171, 415, 405, 0, 377, 418, 355, - 369, 426, 370, 371, 398, 341, 385, 134, 367, 0, - 358, 336, 364, 337, 356, 379, 101, 382, 354, 407, - 388, 417, 115, 424, 117, 393, 0, 153, 126, 0, - 0, 381, 409, 383, 403, 376, 399, 346, 392, 419, - 368, 396, 420, 0, 0, 0, 79, 0, 841, 842, - 0, 0, 0, 0, 0, 94, 0, 395, 414, 366, - 397, 335, 394, 0, 339, 342, 425, 412, 361, 362, - 0, 0, 0, 0, 0, 0, 0, 380, 384, 400, - 374, 0, 0, 0, 0, 0, 0, 0, 0, 359, - 0, 391, 0, 0, 0, 343, 340, 0, 0, 378, - 0, 0, 0, 345, 0, 360, 401, 0, 334, 404, - 410, 375, 199, 413, 373, 372, 416, 140, 0, 156, - 106, 114, 82, 88, 0, 105, 132, 145, 149, 408, - 357, 365, 97, 363, 147, 136, 168, 390, 137, 146, - 118, 160, 141, 167, 200, 175, 158, 174, 83, 157, - 166, 95, 150, 85, 164, 155, 124, 110, 111, 84, - 0, 144, 100, 104, 99, 133, 161, 162, 98, 183, - 89, 173, 87, 90, 172, 131, 159, 165, 125, 122, - 86, 163, 123, 121, 113, 102, 107, 138, 120, 139, - 108, 128, 127, 129, 0, 338, 0, 154, 170, 184, - 92, 353, 411, 176, 177, 178, 179, 180, 0, 0, - 93, 130, 91, 109, 151, 112, 119, 143, 182, 135, - 148, 96, 169, 152, 349, 352, 347, 348, 386, 387, - 421, 422, 423, 402, 344, 0, 350, 351, 0, 406, - 389, 81, 0, 116, 181, 142, 103, 171, 415, 405, - 0, 377, 418, 355, 369, 426, 370, 371, 398, 341, - 385, 134, 367, 0, 358, 336, 364, 337, 356, 379, - 101, 382, 354, 407, 388, 417, 115, 424, 117, 393, - 0, 153, 126, 0, 0, 381, 409, 383, 403, 376, - 399, 346, 392, 419, 368, 396, 420, 52, 0, 0, - 79, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 0, 395, 414, 366, 397, 335, 394, 0, 339, 342, - 425, 412, 361, 362, 0, 0, 0, 0, 0, 0, - 0, 380, 384, 400, 374, 0, 0, 0, 0, 0, - 0, 0, 0, 359, 0, 391, 0, 0, 0, 343, - 340, 0, 0, 378, 0, 0, 0, 345, 0, 360, - 401, 0, 334, 404, 410, 375, 199, 413, 373, 372, - 416, 140, 0, 156, 106, 114, 82, 88, 0, 105, - 132, 145, 149, 408, 357, 365, 97, 363, 147, 136, - 168, 390, 137, 146, 118, 160, 141, 167, 200, 175, - 158, 174, 83, 157, 166, 95, 150, 85, 164, 155, - 124, 110, 111, 84, 0, 144, 100, 104, 99, 133, - 161, 162, 98, 183, 89, 173, 87, 90, 172, 131, - 159, 165, 125, 122, 86, 163, 123, 121, 113, 102, - 107, 138, 120, 139, 108, 128, 127, 129, 0, 338, - 0, 154, 170, 184, 92, 353, 411, 176, 177, 178, - 179, 180, 0, 0, 93, 130, 91, 109, 151, 112, - 119, 143, 182, 135, 148, 96, 169, 152, 349, 352, - 347, 348, 386, 387, 421, 422, 423, 402, 344, 0, - 350, 351, 0, 406, 389, 81, 0, 116, 181, 142, - 103, 171, 415, 405, 0, 377, 418, 355, 369, 426, - 370, 371, 398, 341, 385, 134, 367, 0, 358, 336, - 364, 337, 356, 379, 101, 382, 354, 407, 388, 417, - 115, 424, 117, 393, 0, 153, 126, 0, 0, 381, - 409, 383, 403, 376, 399, 346, 392, 419, 368, 396, - 420, 0, 0, 0, 79, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 0, 395, 414, 366, 397, 335, - 394, 0, 339, 342, 425, 412, 361, 362, 0, 0, - 0, 0, 0, 0, 0, 380, 384, 400, 374, 0, - 0, 0, 0, 0, 0, 1073, 0, 359, 0, 391, - 0, 0, 0, 343, 340, 0, 0, 378, 0, 0, - 0, 345, 0, 360, 401, 0, 334, 404, 410, 375, - 199, 413, 373, 372, 416, 140, 0, 156, 106, 114, - 82, 88, 0, 105, 132, 145, 149, 408, 357, 365, - 97, 363, 147, 136, 168, 390, 137, 146, 118, 160, - 141, 167, 200, 175, 158, 174, 83, 157, 166, 95, - 150, 85, 164, 155, 124, 110, 111, 84, 0, 144, - 100, 104, 99, 133, 161, 162, 98, 183, 89, 173, - 87, 90, 172, 131, 159, 165, 125, 122, 86, 163, - 123, 121, 113, 102, 107, 138, 120, 139, 108, 128, - 127, 129, 0, 338, 0, 154, 170, 184, 92, 353, - 411, 176, 177, 178, 179, 180, 0, 0, 93, 130, - 91, 109, 151, 112, 119, 143, 182, 135, 148, 96, - 169, 152, 349, 352, 347, 348, 386, 387, 421, 422, - 423, 402, 344, 0, 350, 351, 0, 406, 389, 81, - 0, 116, 181, 142, 103, 171, 415, 405, 0, 377, - 418, 355, 369, 426, 370, 371, 398, 341, 385, 134, - 367, 0, 358, 336, 364, 337, 356, 379, 101, 382, - 354, 407, 388, 417, 115, 424, 117, 393, 0, 153, - 126, 0, 0, 381, 409, 383, 403, 376, 399, 346, - 392, 419, 368, 396, 420, 0, 0, 0, 254, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 0, 395, - 414, 366, 397, 335, 394, 0, 339, 342, 425, 412, - 361, 362, 0, 0, 0, 0, 0, 0, 0, 380, - 384, 400, 374, 0, 0, 0, 0, 0, 0, 734, - 0, 359, 0, 391, 0, 0, 0, 343, 340, 0, - 0, 378, 0, 0, 0, 345, 0, 360, 401, 0, - 334, 404, 410, 375, 199, 413, 373, 372, 416, 140, - 0, 156, 106, 114, 82, 88, 0, 105, 132, 145, - 149, 408, 357, 365, 97, 363, 147, 136, 168, 390, - 137, 146, 118, 160, 141, 167, 200, 175, 158, 174, - 83, 157, 166, 95, 150, 85, 164, 155, 124, 110, - 111, 84, 0, 144, 100, 104, 99, 133, 161, 162, - 98, 183, 89, 173, 87, 90, 172, 131, 159, 165, - 125, 122, 86, 163, 123, 121, 113, 102, 107, 138, - 120, 139, 108, 128, 127, 129, 0, 338, 0, 154, - 170, 184, 92, 353, 411, 176, 177, 178, 179, 180, - 0, 0, 93, 130, 91, 109, 151, 112, 119, 143, - 182, 135, 148, 96, 169, 152, 349, 352, 347, 348, - 386, 387, 421, 422, 423, 402, 344, 0, 350, 351, - 0, 406, 389, 81, 0, 116, 181, 142, 103, 171, - 415, 405, 0, 377, 418, 355, 369, 426, 370, 371, - 398, 341, 385, 134, 367, 0, 358, 336, 364, 337, - 356, 379, 101, 382, 354, 407, 388, 417, 115, 424, - 117, 393, 0, 153, 126, 0, 0, 381, 409, 383, - 403, 376, 399, 346, 392, 419, 368, 396, 420, 0, - 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 0, 395, 414, 366, 397, 335, 394, 0, - 339, 342, 425, 412, 361, 362, 0, 0, 0, 0, - 0, 0, 0, 380, 384, 400, 374, 0, 0, 0, - 0, 0, 0, 0, 0, 359, 0, 391, 0, 0, - 0, 343, 340, 0, 0, 378, 0, 0, 0, 345, - 0, 360, 401, 0, 334, 404, 410, 375, 199, 413, - 373, 372, 416, 140, 0, 156, 106, 114, 82, 88, - 0, 105, 132, 145, 149, 408, 357, 365, 97, 363, - 147, 136, 168, 390, 137, 146, 118, 160, 141, 167, - 200, 175, 158, 174, 83, 157, 166, 95, 150, 85, - 164, 155, 124, 110, 111, 84, 0, 144, 100, 104, - 99, 133, 161, 162, 98, 183, 89, 173, 87, 90, - 172, 131, 159, 165, 125, 122, 86, 163, 123, 121, - 113, 102, 107, 138, 120, 139, 108, 128, 127, 129, - 0, 338, 0, 154, 170, 184, 92, 353, 411, 176, - 177, 178, 179, 180, 0, 0, 93, 130, 91, 109, - 151, 112, 119, 143, 182, 135, 148, 96, 169, 152, - 349, 352, 347, 348, 386, 387, 421, 422, 423, 402, - 344, 0, 350, 351, 0, 406, 389, 81, 0, 116, - 181, 142, 103, 171, 415, 405, 0, 377, 418, 355, - 369, 426, 370, 371, 398, 341, 385, 134, 367, 0, - 358, 336, 364, 337, 356, 379, 101, 382, 354, 407, - 388, 417, 115, 424, 117, 393, 0, 153, 126, 0, - 0, 381, 409, 383, 403, 376, 399, 346, 392, 419, - 368, 396, 420, 0, 0, 0, 254, 0, 0, 0, - 0, 0, 0, 0, 0, 94, 0, 395, 414, 366, - 397, 335, 394, 0, 339, 342, 425, 412, 361, 362, - 0, 0, 0, 0, 0, 0, 0, 380, 384, 400, - 374, 0, 0, 0, 0, 0, 0, 0, 0, 359, - 0, 391, 0, 0, 0, 343, 340, 0, 0, 378, - 0, 0, 0, 345, 0, 360, 401, 0, 334, 404, - 410, 375, 199, 413, 373, 372, 416, 140, 0, 156, - 106, 114, 82, 88, 0, 105, 132, 145, 149, 408, - 357, 365, 97, 363, 147, 136, 168, 390, 137, 146, - 118, 160, 141, 167, 200, 175, 158, 174, 83, 157, - 166, 95, 150, 85, 164, 155, 124, 110, 111, 84, - 0, 144, 100, 104, 99, 133, 161, 162, 98, 183, - 89, 173, 87, 90, 172, 131, 159, 165, 125, 122, - 86, 163, 123, 121, 113, 102, 107, 138, 120, 139, - 108, 128, 127, 129, 0, 338, 0, 154, 170, 184, - 92, 353, 411, 176, 177, 178, 179, 180, 0, 0, - 93, 130, 91, 109, 151, 112, 119, 143, 182, 135, - 148, 96, 169, 152, 349, 352, 347, 348, 386, 387, - 421, 422, 423, 402, 344, 0, 350, 351, 0, 406, - 389, 81, 0, 116, 181, 142, 103, 171, 415, 405, - 0, 377, 418, 355, 369, 426, 370, 371, 398, 341, - 385, 134, 367, 0, 358, 336, 364, 337, 356, 379, - 101, 382, 354, 407, 388, 417, 115, 424, 117, 393, - 0, 153, 126, 0, 0, 381, 409, 383, 403, 376, - 399, 346, 392, 419, 368, 396, 420, 0, 0, 0, - 79, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 0, 395, 414, 366, 397, 335, 394, 0, 339, 342, - 425, 412, 361, 362, 0, 0, 0, 0, 0, 0, - 0, 380, 384, 400, 374, 0, 0, 0, 0, 0, - 0, 0, 0, 359, 0, 391, 0, 0, 0, 343, - 340, 0, 0, 378, 0, 0, 0, 345, 0, 360, - 401, 0, 334, 404, 410, 375, 199, 413, 373, 372, - 416, 140, 0, 156, 106, 114, 82, 88, 0, 105, - 132, 145, 149, 408, 357, 365, 97, 363, 147, 136, - 168, 390, 137, 146, 118, 160, 141, 167, 200, 175, - 158, 174, 83, 157, 166, 95, 150, 85, 164, 155, - 124, 110, 111, 84, 0, 144, 100, 104, 99, 133, - 161, 162, 98, 183, 89, 173, 87, 332, 172, 131, - 159, 165, 125, 122, 86, 163, 123, 121, 113, 102, - 107, 138, 120, 139, 108, 128, 127, 129, 0, 338, - 0, 154, 170, 184, 92, 353, 411, 176, 177, 178, - 179, 180, 0, 0, 93, 333, 331, 109, 151, 112, - 119, 143, 182, 135, 148, 96, 169, 152, 349, 352, - 347, 348, 386, 387, 421, 422, 423, 402, 344, 0, - 350, 351, 0, 406, 389, 81, 0, 116, 181, 142, - 103, 171, 415, 405, 0, 377, 418, 355, 369, 426, - 370, 371, 398, 341, 385, 134, 367, 0, 358, 336, - 364, 337, 356, 379, 101, 382, 354, 407, 388, 417, - 115, 424, 117, 393, 0, 153, 126, 0, 0, 381, - 409, 383, 403, 376, 399, 346, 392, 419, 368, 396, - 420, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 0, 395, 414, 366, 397, 335, - 394, 0, 339, 342, 425, 412, 361, 362, 0, 0, - 0, 0, 0, 0, 0, 380, 384, 400, 374, 0, - 0, 0, 0, 0, 0, 0, 0, 359, 0, 391, - 0, 0, 0, 343, 340, 0, 0, 378, 0, 0, - 0, 345, 0, 360, 401, 0, 334, 404, 410, 375, - 199, 413, 373, 372, 416, 140, 0, 156, 106, 114, - 82, 88, 0, 105, 132, 145, 149, 408, 357, 365, - 97, 363, 147, 136, 168, 390, 137, 146, 118, 160, - 141, 167, 200, 175, 158, 174, 83, 157, 166, 95, - 150, 85, 164, 155, 124, 110, 111, 84, 0, 144, - 100, 104, 99, 133, 161, 162, 98, 183, 89, 173, - 87, 90, 172, 131, 159, 165, 125, 122, 86, 163, - 123, 121, 113, 102, 107, 138, 120, 139, 108, 128, - 127, 129, 0, 338, 0, 154, 170, 184, 92, 353, - 411, 176, 177, 178, 179, 180, 0, 0, 93, 130, - 91, 109, 151, 112, 119, 143, 182, 135, 148, 96, - 169, 152, 349, 352, 347, 348, 386, 387, 421, 422, - 423, 402, 344, 0, 350, 351, 0, 406, 389, 81, - 0, 116, 181, 142, 103, 171, 415, 405, 0, 377, - 418, 355, 369, 426, 370, 371, 398, 341, 385, 134, - 367, 0, 358, 336, 364, 337, 356, 379, 101, 382, - 354, 407, 388, 417, 115, 424, 117, 393, 0, 153, - 126, 0, 0, 381, 409, 383, 403, 376, 399, 346, - 392, 419, 368, 396, 420, 0, 0, 0, 79, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 0, 395, - 414, 366, 397, 335, 394, 0, 339, 342, 425, 412, - 361, 362, 0, 0, 0, 0, 0, 0, 0, 380, - 384, 400, 374, 0, 0, 0, 0, 0, 0, 0, - 0, 359, 0, 391, 0, 0, 0, 343, 340, 0, - 0, 378, 0, 0, 0, 345, 0, 360, 401, 0, - 334, 404, 410, 375, 199, 413, 373, 372, 416, 140, - 0, 156, 106, 114, 82, 88, 0, 105, 132, 145, - 149, 408, 357, 365, 97, 363, 147, 136, 168, 390, - 137, 146, 118, 160, 141, 167, 200, 175, 158, 174, - 83, 157, 609, 95, 150, 85, 164, 155, 124, 110, - 111, 84, 0, 144, 100, 104, 99, 133, 161, 162, - 98, 183, 89, 173, 87, 332, 172, 131, 159, 165, - 125, 122, 86, 163, 123, 121, 113, 102, 107, 138, - 120, 139, 108, 128, 127, 129, 0, 338, 0, 154, - 170, 184, 92, 353, 411, 176, 177, 178, 179, 180, - 0, 0, 93, 333, 331, 109, 151, 112, 119, 143, - 182, 135, 148, 96, 169, 152, 349, 352, 347, 348, - 386, 387, 421, 422, 423, 402, 344, 0, 350, 351, - 0, 406, 389, 81, 0, 116, 181, 142, 103, 171, - 415, 405, 0, 377, 418, 355, 369, 426, 370, 371, - 398, 341, 385, 134, 367, 0, 358, 336, 364, 337, - 356, 379, 101, 382, 354, 407, 388, 417, 115, 424, - 117, 393, 0, 153, 126, 0, 0, 381, 409, 383, - 403, 376, 399, 346, 392, 419, 368, 396, 420, 0, - 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 0, 395, 414, 366, 397, 335, 394, 0, - 339, 342, 425, 412, 361, 362, 0, 0, 0, 0, - 0, 0, 0, 380, 384, 400, 374, 0, 0, 0, - 0, 0, 0, 0, 0, 359, 0, 391, 0, 0, - 0, 343, 340, 0, 0, 378, 0, 0, 0, 345, - 0, 360, 401, 0, 334, 404, 410, 375, 199, 413, - 373, 372, 416, 140, 0, 156, 106, 114, 82, 88, - 0, 105, 132, 145, 149, 408, 357, 365, 97, 363, - 147, 136, 168, 390, 137, 146, 118, 160, 141, 167, - 200, 175, 158, 174, 83, 157, 323, 95, 150, 85, - 164, 155, 124, 110, 111, 84, 0, 144, 100, 104, - 99, 133, 161, 162, 98, 183, 89, 173, 87, 332, - 172, 131, 159, 165, 125, 122, 86, 163, 123, 121, - 113, 102, 107, 138, 120, 139, 108, 128, 127, 129, - 0, 338, 0, 154, 170, 184, 92, 353, 411, 176, - 177, 178, 179, 180, 0, 0, 93, 333, 331, 326, - 325, 112, 119, 143, 182, 135, 148, 96, 169, 152, - 349, 352, 347, 348, 386, 387, 421, 422, 423, 402, - 344, 0, 350, 351, 0, 406, 389, 81, 0, 116, - 181, 142, 103, 171, 134, 0, 0, 770, 0, 256, - 0, 0, 0, 101, 0, 253, 0, 0, 0, 115, - 296, 117, 0, 0, 153, 126, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 52, 0, 0, 254, 275, 274, 277, 278, 279, 280, - 0, 0, 94, 276, 281, 282, 283, 0, 0, 251, - 268, 0, 295, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 265, 266, 247, 0, 0, 0, 307, 0, - 267, 0, 0, 262, 263, 264, 269, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, - 0, 0, 305, 0, 140, 0, 156, 106, 114, 82, - 88, 0, 105, 132, 145, 149, 0, 0, 0, 97, - 0, 147, 136, 168, 0, 137, 146, 118, 160, 141, - 167, 200, 175, 158, 174, 83, 157, 166, 95, 150, - 85, 164, 155, 124, 110, 111, 84, 0, 144, 100, - 104, 99, 133, 161, 162, 98, 183, 89, 173, 87, - 90, 172, 131, 159, 165, 125, 122, 86, 163, 123, - 121, 113, 102, 107, 138, 120, 139, 108, 128, 127, - 129, 0, 0, 0, 154, 170, 184, 92, 0, 0, - 176, 177, 178, 179, 180, 0, 0, 93, 130, 91, - 109, 151, 112, 119, 143, 182, 135, 148, 96, 169, - 152, 297, 306, 303, 304, 301, 302, 300, 299, 298, - 308, 289, 290, 291, 292, 294, 0, 293, 81, 0, - 116, 181, 142, 103, 171, 134, 0, 0, 0, 0, - 256, 0, 0, 0, 101, 0, 253, 0, 0, 0, - 115, 296, 117, 0, 0, 153, 126, 0, 0, 0, - 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, - 0, 52, 0, 479, 254, 275, 274, 277, 278, 279, - 280, 0, 0, 94, 276, 281, 282, 283, 0, 0, - 251, 268, 0, 295, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 265, 266, 0, 0, 0, 0, 307, - 0, 267, 0, 0, 262, 263, 264, 269, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 199, 0, 0, 305, 0, 140, 0, 156, 106, 114, - 82, 88, 0, 105, 132, 145, 149, 0, 0, 0, - 97, 0, 147, 136, 168, 0, 137, 146, 118, 160, - 141, 167, 200, 175, 158, 174, 83, 157, 166, 95, - 150, 85, 164, 155, 124, 110, 111, 84, 0, 144, - 100, 104, 99, 133, 161, 162, 98, 183, 89, 173, - 87, 90, 172, 131, 159, 165, 125, 122, 86, 163, - 123, 121, 113, 102, 107, 138, 120, 139, 108, 128, - 127, 129, 0, 0, 0, 154, 170, 184, 92, 0, - 0, 176, 177, 178, 179, 180, 0, 0, 93, 130, - 91, 109, 151, 112, 119, 143, 182, 135, 148, 96, - 169, 152, 297, 306, 303, 304, 301, 302, 300, 299, - 298, 308, 289, 290, 291, 292, 294, 0, 293, 81, - 0, 116, 181, 142, 103, 171, 134, 0, 0, 0, - 0, 256, 0, 0, 0, 101, 0, 253, 0, 0, - 0, 115, 296, 117, 0, 0, 153, 126, 0, 0, - 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, - 0, 0, 52, 0, 0, 254, 275, 274, 277, 278, - 279, 280, 0, 0, 94, 276, 281, 282, 283, 0, - 0, 251, 268, 0, 295, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 265, 266, 247, 0, 0, 0, - 307, 0, 267, 0, 0, 262, 263, 264, 269, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 199, 0, 0, 305, 0, 140, 0, 156, 106, - 114, 82, 88, 0, 105, 132, 145, 149, 0, 0, - 0, 97, 0, 147, 136, 168, 0, 137, 146, 118, - 160, 141, 167, 200, 175, 158, 174, 83, 157, 166, - 95, 150, 85, 164, 155, 124, 110, 111, 84, 0, - 144, 100, 104, 99, 133, 161, 162, 98, 183, 89, - 173, 87, 90, 172, 131, 159, 165, 125, 122, 86, - 163, 123, 121, 113, 102, 107, 138, 120, 139, 108, - 128, 127, 129, 0, 0, 0, 154, 170, 184, 92, - 0, 0, 176, 177, 178, 179, 180, 0, 0, 93, - 130, 91, 109, 151, 112, 119, 143, 182, 135, 148, - 96, 169, 152, 297, 306, 303, 304, 301, 302, 300, - 299, 298, 308, 289, 290, 291, 292, 294, 0, 293, - 81, 0, 116, 181, 142, 103, 171, 134, 0, 0, - 0, 0, 256, 0, 0, 0, 101, 0, 253, 0, - 0, 0, 115, 296, 117, 0, 0, 153, 126, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 833, 0, 52, 0, 0, 254, 275, 274, 277, - 278, 279, 280, 0, 0, 94, 276, 281, 282, 283, - 0, 0, 251, 268, 0, 295, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 265, 266, 0, 0, 0, - 0, 307, 0, 267, 0, 0, 262, 263, 264, 269, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 199, 0, 0, 305, 0, 140, 0, 156, - 106, 114, 82, 88, 0, 105, 132, 145, 149, 0, - 0, 0, 97, 0, 147, 136, 168, 0, 137, 146, - 118, 160, 141, 167, 200, 175, 158, 174, 83, 157, - 166, 95, 150, 85, 164, 155, 124, 110, 111, 84, - 0, 144, 100, 104, 99, 133, 161, 162, 98, 183, - 89, 173, 87, 90, 172, 131, 159, 165, 125, 122, - 86, 163, 123, 121, 113, 102, 107, 138, 120, 139, - 108, 128, 127, 129, 0, 0, 0, 154, 170, 184, - 92, 0, 0, 176, 177, 178, 179, 180, 0, 0, - 93, 130, 91, 109, 151, 112, 119, 143, 182, 135, - 148, 96, 169, 152, 297, 306, 303, 304, 301, 302, - 300, 299, 298, 308, 289, 290, 291, 292, 294, 23, - 293, 81, 0, 116, 181, 142, 103, 171, 0, 0, - 0, 134, 0, 0, 0, 0, 256, 0, 0, 0, - 101, 0, 253, 0, 0, 0, 115, 296, 117, 0, - 0, 153, 126, 0, 0, 0, 0, 287, 288, 0, - 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, - 254, 275, 274, 277, 278, 279, 280, 0, 0, 94, - 276, 281, 282, 283, 0, 0, 251, 268, 0, 295, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 265, - 266, 0, 0, 0, 0, 307, 0, 267, 0, 0, - 262, 263, 264, 269, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 199, 0, 0, 305, - 0, 140, 0, 156, 106, 114, 82, 88, 0, 105, - 132, 145, 149, 0, 0, 0, 97, 0, 147, 136, - 168, 0, 137, 146, 118, 160, 141, 167, 200, 175, - 158, 174, 83, 157, 166, 95, 150, 85, 164, 155, - 124, 110, 111, 84, 0, 144, 100, 104, 99, 133, - 161, 162, 98, 183, 89, 173, 87, 90, 172, 131, - 159, 165, 125, 122, 86, 163, 123, 121, 113, 102, - 107, 138, 120, 139, 108, 128, 127, 129, 0, 0, - 0, 154, 170, 184, 92, 0, 0, 176, 177, 178, - 179, 180, 0, 0, 93, 130, 91, 109, 151, 112, - 119, 143, 182, 135, 148, 96, 169, 152, 297, 306, - 303, 304, 301, 302, 300, 299, 298, 308, 289, 290, - 291, 292, 294, 0, 293, 81, 0, 116, 181, 142, - 103, 171, 134, 0, 0, 0, 0, 256, 0, 0, - 0, 101, 0, 253, 0, 0, 0, 115, 296, 117, - 0, 0, 153, 126, 0, 0, 0, 0, 287, 288, - 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, - 0, 254, 275, 274, 277, 278, 279, 280, 0, 0, - 94, 276, 281, 282, 283, 0, 0, 251, 268, 0, - 295, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 265, 266, 0, 0, 0, 0, 307, 0, 267, 0, - 0, 262, 263, 264, 269, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, - 305, 0, 140, 0, 156, 106, 114, 82, 88, 0, - 105, 132, 145, 149, 0, 0, 0, 97, 0, 147, - 136, 168, 0, 137, 146, 118, 160, 141, 167, 200, - 175, 158, 174, 83, 157, 166, 95, 150, 85, 164, - 155, 124, 110, 111, 84, 0, 144, 100, 104, 99, - 133, 161, 162, 98, 183, 89, 173, 87, 90, 172, - 131, 159, 165, 125, 122, 86, 163, 123, 121, 113, - 102, 107, 138, 120, 139, 108, 128, 127, 129, 0, - 0, 0, 154, 170, 184, 92, 0, 0, 176, 177, - 178, 179, 180, 0, 0, 93, 130, 91, 109, 151, - 112, 119, 143, 182, 135, 148, 96, 169, 152, 297, - 306, 303, 304, 301, 302, 300, 299, 298, 308, 289, - 290, 291, 292, 294, 134, 293, 81, 0, 116, 181, - 142, 103, 171, 101, 0, 0, 0, 0, 0, 115, - 296, 117, 0, 0, 153, 126, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 52, 0, 0, 254, 275, 274, 277, 278, 279, 280, - 0, 0, 94, 276, 281, 282, 283, 0, 0, 0, - 268, 0, 295, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 265, 266, 0, 0, 0, 0, 307, 0, - 267, 0, 0, 262, 263, 264, 269, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, - 0, 0, 305, 0, 140, 0, 156, 106, 114, 82, - 88, 0, 105, 132, 145, 149, 0, 0, 0, 97, - 0, 147, 136, 168, 1347, 137, 146, 118, 160, 141, - 167, 200, 175, 158, 174, 83, 157, 166, 95, 150, - 85, 164, 155, 124, 110, 111, 84, 0, 144, 100, - 104, 99, 133, 161, 162, 98, 183, 89, 173, 87, - 90, 172, 131, 159, 165, 125, 122, 86, 163, 123, - 121, 113, 102, 107, 138, 120, 139, 108, 128, 127, - 129, 0, 0, 0, 154, 170, 184, 92, 0, 0, - 176, 177, 178, 179, 180, 0, 0, 93, 130, 91, - 109, 151, 112, 119, 143, 182, 135, 148, 96, 169, - 152, 297, 306, 303, 304, 301, 302, 300, 299, 298, - 308, 289, 290, 291, 292, 294, 134, 293, 81, 0, - 116, 181, 142, 103, 171, 101, 0, 0, 0, 0, - 0, 115, 296, 117, 0, 0, 153, 126, 0, 0, - 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, - 0, 0, 52, 0, 0, 254, 275, 274, 277, 278, - 279, 280, 0, 0, 94, 276, 281, 282, 283, 0, - 0, 0, 268, 0, 295, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 265, 266, 0, 0, 0, 0, - 307, 0, 267, 0, 0, 262, 263, 264, 269, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 199, 0, 0, 305, 0, 140, 0, 156, 106, - 114, 82, 88, 0, 105, 132, 145, 149, 0, 0, - 0, 97, 0, 147, 136, 168, 0, 137, 146, 118, - 160, 141, 167, 200, 175, 158, 174, 83, 157, 166, - 95, 150, 85, 164, 155, 124, 110, 111, 84, 0, - 144, 100, 104, 99, 133, 161, 162, 98, 183, 89, - 173, 87, 90, 172, 131, 159, 165, 125, 122, 86, - 163, 123, 121, 113, 102, 107, 138, 120, 139, 108, - 128, 127, 129, 0, 0, 0, 154, 170, 184, 92, - 0, 0, 176, 177, 178, 179, 180, 0, 0, 93, - 130, 91, 109, 151, 112, 119, 143, 182, 135, 148, - 96, 169, 152, 297, 306, 303, 304, 301, 302, 300, - 299, 298, 308, 289, 290, 291, 292, 294, 134, 293, - 81, 0, 116, 181, 142, 103, 171, 101, 0, 0, - 0, 0, 0, 115, 0, 117, 0, 0, 153, 126, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 513, 512, 522, 523, 515, 516, 517, 518, - 519, 520, 521, 514, 0, 0, 524, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 199, 0, 0, 0, 0, 140, 0, - 156, 106, 114, 82, 88, 0, 105, 132, 145, 149, - 0, 0, 0, 97, 0, 147, 136, 168, 0, 137, - 146, 118, 160, 141, 167, 200, 175, 158, 174, 83, - 157, 166, 95, 150, 85, 164, 155, 124, 110, 111, - 84, 0, 144, 100, 104, 99, 133, 161, 162, 98, - 183, 89, 173, 87, 90, 172, 131, 159, 165, 125, - 122, 86, 163, 123, 121, 113, 102, 107, 138, 120, - 139, 108, 128, 127, 129, 0, 0, 0, 154, 170, - 184, 92, 0, 0, 176, 177, 178, 179, 180, 0, - 0, 93, 130, 91, 109, 151, 112, 119, 143, 182, - 135, 148, 96, 169, 152, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 134, 0, 0, 0, 501, 0, - 0, 0, 81, 101, 116, 181, 142, 103, 171, 115, - 0, 117, 0, 0, 153, 126, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 79, 0, 503, 0, 0, 0, 0, - 0, 0, 94, 0, 0, 0, 0, 498, 497, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 499, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, - 0, 0, 0, 0, 140, 0, 156, 106, 114, 82, - 88, 0, 105, 132, 145, 149, 0, 0, 0, 97, - 0, 147, 136, 168, 0, 137, 146, 118, 160, 141, - 167, 200, 175, 158, 174, 83, 157, 166, 95, 150, - 85, 164, 155, 124, 110, 111, 84, 0, 144, 100, - 104, 99, 133, 161, 162, 98, 183, 89, 173, 87, - 90, 172, 131, 159, 165, 125, 122, 86, 163, 123, - 121, 113, 102, 107, 138, 120, 139, 108, 128, 127, - 129, 0, 0, 0, 154, 170, 184, 92, 0, 0, - 176, 177, 178, 179, 180, 0, 0, 93, 130, 91, - 109, 151, 112, 119, 143, 182, 135, 148, 96, 169, - 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 134, 0, 0, 0, 0, 0, 0, 0, 81, 101, - 116, 181, 142, 103, 171, 115, 0, 117, 0, 0, - 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, - 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 75, 76, 0, 71, 0, 0, 0, 77, - 140, 0, 156, 106, 114, 82, 88, 0, 105, 132, - 145, 149, 0, 0, 0, 97, 0, 147, 136, 168, - 0, 137, 146, 118, 160, 141, 167, 73, 175, 158, - 174, 83, 157, 166, 95, 150, 85, 164, 155, 124, - 110, 111, 84, 0, 144, 100, 104, 99, 133, 161, - 162, 98, 183, 89, 173, 87, 90, 172, 131, 159, - 165, 125, 122, 86, 163, 123, 121, 113, 102, 107, - 138, 120, 139, 108, 128, 127, 129, 0, 0, 0, - 154, 170, 184, 92, 0, 0, 176, 177, 178, 179, - 180, 0, 0, 93, 130, 91, 109, 151, 112, 119, - 143, 182, 135, 148, 96, 169, 152, 0, 74, 0, - 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, - 598, 0, 0, 0, 81, 101, 116, 181, 142, 103, - 171, 115, 0, 117, 0, 0, 153, 126, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 197, 0, 600, 0, 0, - 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 199, 0, 0, 0, 0, 140, 0, 156, 106, - 114, 82, 88, 0, 105, 132, 145, 149, 0, 0, - 0, 97, 0, 147, 136, 168, 0, 137, 146, 118, - 160, 141, 167, 200, 175, 158, 174, 83, 157, 166, - 95, 150, 85, 164, 155, 124, 110, 111, 84, 0, - 144, 100, 104, 99, 133, 161, 162, 98, 183, 89, - 173, 87, 90, 172, 131, 159, 165, 125, 122, 86, - 163, 123, 121, 113, 102, 107, 138, 120, 139, 108, - 128, 127, 129, 0, 0, 0, 154, 170, 184, 92, - 0, 0, 176, 177, 178, 179, 180, 0, 0, 93, - 130, 91, 109, 151, 112, 119, 143, 182, 135, 148, - 96, 169, 152, 0, 0, 0, 23, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 134, 0, - 81, 0, 116, 181, 142, 103, 171, 101, 0, 0, - 0, 0, 0, 115, 0, 117, 0, 0, 153, 126, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 52, 0, 0, 79, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 199, 0, 0, 0, 0, 140, 0, - 156, 106, 114, 82, 88, 0, 105, 132, 145, 149, - 0, 0, 0, 97, 0, 147, 136, 168, 0, 137, - 146, 118, 160, 141, 167, 200, 175, 158, 174, 83, - 157, 166, 95, 150, 85, 164, 155, 124, 110, 111, - 84, 0, 144, 100, 104, 99, 133, 161, 162, 98, - 183, 89, 173, 87, 90, 172, 131, 159, 165, 125, - 122, 86, 163, 123, 121, 113, 102, 107, 138, 120, - 139, 108, 128, 127, 129, 0, 0, 0, 154, 170, - 184, 92, 0, 0, 176, 177, 178, 179, 180, 0, - 0, 93, 130, 91, 109, 151, 112, 119, 143, 182, - 135, 148, 96, 169, 152, 0, 0, 0, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 134, 0, 81, 0, 116, 181, 142, 103, 171, 101, - 0, 0, 0, 0, 0, 115, 0, 117, 0, 0, - 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 52, 0, 0, 197, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, - 140, 0, 156, 106, 114, 82, 88, 0, 105, 132, - 145, 149, 0, 0, 0, 97, 0, 147, 136, 168, - 0, 137, 146, 118, 160, 141, 167, 200, 175, 158, - 174, 83, 157, 166, 95, 150, 85, 164, 155, 124, - 110, 111, 84, 0, 144, 100, 104, 99, 133, 161, - 162, 98, 183, 89, 173, 87, 90, 172, 131, 159, - 165, 125, 122, 86, 163, 123, 121, 113, 102, 107, - 138, 120, 139, 108, 128, 127, 129, 0, 0, 0, - 154, 170, 184, 92, 0, 0, 176, 177, 178, 179, - 180, 0, 0, 93, 130, 91, 109, 151, 112, 119, - 143, 182, 135, 148, 96, 169, 152, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, - 0, 0, 0, 0, 81, 101, 116, 181, 142, 103, - 171, 115, 0, 117, 0, 0, 153, 126, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 79, 0, 0, 721, 0, - 0, 722, 0, 0, 94, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 199, 0, 0, 0, 0, 140, 0, 156, 106, - 114, 82, 88, 0, 105, 132, 145, 149, 0, 0, - 0, 97, 0, 147, 136, 168, 0, 137, 146, 118, - 160, 141, 167, 200, 175, 158, 174, 83, 157, 166, - 95, 150, 85, 164, 155, 124, 110, 111, 84, 0, - 144, 100, 104, 99, 133, 161, 162, 98, 183, 89, - 173, 87, 90, 172, 131, 159, 165, 125, 122, 86, - 163, 123, 121, 113, 102, 107, 138, 120, 139, 108, - 128, 127, 129, 0, 0, 0, 154, 170, 184, 92, - 0, 0, 176, 177, 178, 179, 180, 0, 0, 93, - 130, 91, 109, 151, 112, 119, 143, 182, 135, 148, - 96, 169, 152, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 134, 0, - 81, 0, 116, 181, 142, 103, 171, 101, 0, 618, - 0, 0, 0, 115, 0, 117, 0, 0, 153, 126, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 79, 0, 617, - 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 199, 0, 0, 0, 0, 140, 0, - 156, 106, 114, 82, 88, 0, 105, 132, 145, 149, - 0, 0, 0, 97, 0, 147, 136, 168, 0, 137, - 146, 118, 160, 141, 167, 200, 175, 158, 174, 83, - 157, 166, 95, 150, 85, 164, 155, 124, 110, 111, - 84, 0, 144, 100, 104, 99, 133, 161, 162, 98, - 183, 89, 173, 87, 90, 172, 131, 159, 165, 125, - 122, 86, 163, 123, 121, 113, 102, 107, 138, 120, - 139, 108, 128, 127, 129, 0, 0, 0, 154, 170, - 184, 92, 0, 0, 176, 177, 178, 179, 180, 0, - 0, 93, 130, 91, 109, 151, 112, 119, 143, 182, - 135, 148, 96, 169, 152, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 134, 0, 0, 0, 598, 0, - 0, 0, 81, 101, 116, 181, 142, 103, 171, 115, - 0, 117, 0, 0, 153, 126, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 197, 0, 600, 0, 0, 0, 0, - 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, - 0, 0, 0, 0, 140, 0, 156, 106, 114, 82, - 88, 0, 105, 132, 145, 149, 0, 0, 0, 97, - 0, 147, 136, 168, 0, 596, 146, 118, 160, 141, - 167, 200, 175, 158, 174, 83, 157, 166, 95, 150, - 85, 164, 155, 124, 110, 111, 84, 0, 144, 100, - 104, 99, 133, 161, 162, 98, 183, 89, 173, 87, - 90, 172, 131, 159, 165, 125, 122, 86, 163, 123, - 121, 113, 102, 107, 138, 120, 139, 108, 128, 127, - 129, 0, 0, 0, 154, 170, 184, 92, 0, 0, - 176, 177, 178, 179, 180, 0, 0, 93, 130, 91, - 109, 151, 112, 119, 143, 182, 135, 148, 96, 169, - 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 134, 0, 0, 0, 0, 0, 0, 0, 81, 101, - 116, 181, 142, 103, 171, 115, 0, 117, 0, 0, - 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 52, 0, 0, 197, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, - 140, 0, 156, 106, 114, 82, 88, 0, 105, 132, - 145, 149, 0, 0, 0, 97, 0, 147, 136, 168, - 0, 137, 146, 118, 160, 141, 167, 200, 175, 158, - 174, 83, 157, 166, 95, 150, 85, 164, 155, 124, - 110, 111, 84, 0, 144, 100, 104, 99, 133, 161, - 162, 98, 183, 89, 173, 87, 90, 172, 131, 159, - 165, 125, 122, 86, 163, 123, 121, 113, 102, 107, - 138, 120, 139, 108, 128, 127, 129, 0, 0, 0, - 154, 170, 184, 92, 0, 0, 176, 177, 178, 179, - 180, 0, 0, 93, 130, 91, 109, 151, 112, 119, - 143, 182, 135, 148, 96, 169, 152, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, - 0, 0, 0, 0, 81, 101, 116, 181, 142, 103, - 171, 115, 0, 117, 0, 0, 153, 126, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 197, 0, 600, 0, 0, - 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 263, 1360, 1350, 1316, 876, 661, 965, 551, 1264, 1103, + 983, 241, 804, 1137, 1034, 1100, 966, 267, 1104, 903, + 850, 870, 293, 989, 836, 826, 57, 802, 269, 1008, + 1222, 1110, 82, 1116, 856, 750, 204, 1077, 260, 204, + 690, 929, 1037, 760, 550, 3, 1025, 823, 806, 599, + 840, 483, 776, 727, 866, 791, 489, 827, 430, 495, + 784, 294, 51, 232, 503, 598, 322, 204, 82, 325, + 265, 582, 204, 911, 204, 331, 82, 250, 320, 56, + 1353, 1337, 1348, 1323, 1345, 877, 757, 1336, 1322, 583, + 1095, 1196, 565, 435, 1275, 1131, 240, 1145, 1146, 1147, + 1132, 1133, 818, 819, 817, 1150, 1148, 254, 233, 234, + 235, 236, 996, 51, 239, 995, 238, 600, 997, 601, + 456, 246, 759, 24, 25, 52, 27, 28, 1291, 516, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 237, 43, 527, 1016, 849, 61, 29, 48, 49, + 199, 195, 196, 197, 474, 1225, 1241, 857, 1185, 1183, + 231, 475, 472, 473, 467, 468, 1347, 38, 1344, 461, + 1317, 54, 63, 64, 65, 66, 67, 1058, 785, 841, + 1307, 1265, 1368, 1273, 445, 438, 458, 193, 460, 444, + 984, 986, 669, 204, 1267, 204, 1055, 192, 843, 193, + 660, 204, 1057, 1126, 1125, 1124, 433, 441, 204, 207, + 194, 905, 82, 82, 82, 82, 1296, 82, 457, 459, + 539, 540, 1364, 1205, 1064, 843, 945, 82, 923, 824, + 699, 507, 31, 32, 34, 33, 36, 451, 50, 516, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 527, 696, 527, 1009, 1154, 502, 82, 1305, 37, + 44, 45, 1266, 70, 46, 47, 35, 985, 198, 517, + 1164, 491, 527, 462, 462, 462, 462, 1149, 462, 39, + 40, 588, 41, 42, 1274, 1272, 857, 1114, 462, 904, + 481, 492, 930, 537, 842, 1292, 1321, 602, 1056, 71, + 1054, 479, 480, 455, 691, 1097, 1155, 777, 51, 541, + 542, 543, 544, 545, 546, 547, 548, 201, 204, 204, + 204, 842, 843, 536, 82, 664, 538, 500, 1362, 1014, + 82, 1363, 1193, 1361, 518, 519, 520, 521, 522, 523, + 524, 517, 1310, 502, 527, 497, 581, 586, 321, 1327, + 777, 431, 952, 432, 549, 434, 553, 554, 555, 556, + 557, 558, 559, 560, 561, 53, 564, 566, 566, 566, + 566, 566, 566, 566, 566, 574, 575, 576, 577, 1232, + 587, 191, 464, 465, 466, 692, 469, 447, 448, 449, + 596, 846, 431, 1231, 493, 1329, 478, 847, 590, 567, + 568, 569, 570, 571, 572, 573, 516, 515, 525, 526, + 518, 519, 520, 521, 522, 523, 524, 517, 842, 54, + 527, 1029, 734, 839, 837, 429, 838, 501, 500, 730, + 204, 835, 841, 942, 1099, 82, 732, 733, 731, 1369, + 1028, 204, 204, 82, 502, 204, 317, 318, 204, 702, + 703, 1017, 204, 437, 82, 82, 82, 82, 82, 82, + 82, 82, 520, 521, 522, 523, 524, 517, 82, 82, + 527, 941, 1303, 940, 442, 1306, 443, 204, 1370, 463, + 1248, 22, 450, 501, 500, 501, 500, 1229, 1061, 452, + 501, 500, 920, 921, 922, 82, 462, 501, 500, 204, + 502, 1026, 502, 704, 462, 82, 751, 502, 752, 998, + 1009, 999, 1004, 698, 502, 462, 462, 462, 462, 462, + 462, 462, 462, 1270, 1346, 676, 879, 678, 753, 462, + 462, 439, 440, 728, 717, 719, 720, 675, 292, 729, + 718, 245, 1333, 482, 1270, 1314, 482, 328, 726, 82, + 697, 735, 736, 737, 738, 739, 740, 741, 742, 743, + 744, 745, 746, 747, 748, 749, 674, 501, 500, 721, + 80, 706, 1270, 482, 1270, 1297, 769, 772, 1270, 1269, + 204, 723, 778, 725, 502, 1220, 1219, 1330, 204, 204, + 665, 663, 204, 204, 1207, 482, 82, 658, 764, 580, + 51, 589, 1204, 482, 659, 453, 330, 1161, 1160, 82, + 754, 755, 668, 446, 436, 553, 586, 1157, 1158, 812, + 586, 774, 1280, 679, 680, 681, 682, 683, 684, 685, + 686, 1157, 1156, 935, 482, 788, 482, 687, 688, 852, + 853, 854, 855, 1078, 762, 482, 609, 608, 24, 803, + 810, 1279, 1276, 587, 24, 863, 864, 865, 858, 859, + 860, 204, 781, 815, 82, 814, 82, 1151, 831, 990, + 204, 990, 960, 204, 82, 844, 961, 765, 766, 872, + 1080, 1101, 1251, 773, 1113, 811, 593, 592, 1067, 1113, + 204, 58, 204, 204, 762, 787, 54, 780, 1200, 782, + 783, 788, 54, 662, 1163, 947, 1159, 1000, 816, 868, + 869, 610, 788, 1082, 1113, 1086, 24, 1081, 944, 1079, + 788, 935, 666, 667, 1084, 462, 670, 462, 594, 673, + 592, 935, 935, 1083, 595, 462, 525, 526, 518, 519, + 520, 521, 522, 523, 524, 517, 1085, 1087, 527, 946, + 330, 330, 330, 330, 728, 330, 913, 912, 693, 700, + 729, 874, 943, 247, 54, 330, 54, 1338, 1313, 1236, + 1227, 926, 927, 928, 851, 725, 1212, 871, 1142, 1003, + 713, 1117, 1118, 705, 867, 925, 924, 862, 861, 204, + 204, 204, 204, 204, 1355, 505, 1351, 1144, 1120, 1101, + 1030, 204, 672, 328, 204, 967, 476, 712, 204, 1045, + 977, 54, 204, 1123, 1122, 978, 974, 586, 586, 586, + 586, 586, 973, 1342, 1335, 975, 1063, 82, 951, 962, + 976, 908, 586, 880, 919, 882, 992, 1341, 1043, 991, + 586, 761, 763, 901, 251, 252, 963, 964, 764, 496, + 587, 587, 587, 587, 587, 980, 988, 779, 918, 917, + 968, 786, 330, 971, 494, 803, 993, 987, 604, 979, + 1010, 797, 798, 587, 813, 82, 82, 1021, 82, 969, + 970, 934, 972, 484, 1001, 607, 454, 1018, 1019, 1006, + 1007, 1013, 1237, 1312, 256, 485, 1311, 949, 1249, 1011, + 1005, 82, 1198, 881, 1020, 1044, 1022, 1023, 1024, 1027, + 1049, 1046, 1039, 1047, 1042, 204, 671, 801, 1040, 1041, + 248, 249, 496, 916, 82, 242, 1285, 243, 1050, 58, + 1284, 915, 1048, 1239, 990, 477, 689, 462, 1051, 1357, + 1356, 1357, 875, 1060, 498, 1293, 1226, 1036, 695, 60, + 62, 899, 591, 55, 900, 1, 1349, 878, 1033, 887, + 1315, 1263, 462, 1136, 82, 82, 834, 1102, 1071, 1073, + 1074, 902, 825, 330, 69, 428, 1096, 1088, 967, 1076, + 1089, 330, 1090, 1091, 1105, 1093, 1094, 724, 82, 1112, + 68, 1304, 330, 330, 330, 330, 330, 330, 330, 330, + 833, 82, 832, 82, 82, 1121, 330, 330, 1107, 1271, + 1224, 1070, 845, 1015, 848, 1130, 1128, 1143, 1309, 1127, + 1012, 725, 615, 1106, 613, 51, 1134, 614, 612, 1139, + 617, 204, 616, 708, 611, 215, 1140, 1141, 323, 82, + 800, 603, 873, 505, 932, 1032, 330, 499, 933, 72, + 1053, 1052, 82, 204, 883, 937, 938, 939, 470, 82, + 1135, 471, 217, 535, 948, 82, 1152, 1153, 204, 954, + 1059, 955, 956, 957, 958, 328, 914, 994, 329, 1108, + 1172, 701, 488, 1283, 1238, 950, 562, 756, 828, 775, + 1173, 268, 1190, 982, 716, 1174, 586, 770, 770, 1178, + 1179, 1165, 1180, 770, 1181, 1182, 281, 1184, 278, 280, + 279, 1176, 707, 959, 1167, 509, 266, 1170, 1199, 258, + 585, 578, 792, 283, 282, 285, 286, 287, 288, 587, + 1209, 967, 284, 289, 330, 82, 790, 486, 490, 1208, + 1218, 789, 1119, 82, 1115, 584, 1066, 330, 1195, 793, + 796, 797, 798, 794, 508, 795, 799, 1194, 1290, 1221, + 711, 26, 59, 82, 82, 82, 516, 515, 525, 526, + 518, 519, 520, 521, 522, 523, 524, 517, 1234, 724, + 527, 253, 19, 18, 17, 20, 1214, 1215, 1216, 552, + 16, 1228, 1001, 1230, 15, 14, 1065, 30, 563, 21, + 13, 12, 330, 11, 330, 82, 82, 10, 82, 9, + 8, 7, 330, 82, 1240, 82, 82, 82, 204, 1250, + 1257, 82, 1235, 1105, 462, 1075, 6, 5, 1242, 1243, + 1262, 1244, 1245, 1246, 1268, 4, 244, 82, 330, 23, + 893, 2, 0, 1258, 0, 1259, 1260, 1261, 1252, 793, + 796, 797, 798, 794, 892, 795, 799, 0, 0, 1117, + 1118, 1294, 1106, 0, 0, 1253, 0, 1281, 0, 0, + 0, 82, 1302, 1301, 1105, 0, 1277, 0, 1278, 0, + 0, 0, 897, 0, 0, 0, 0, 0, 0, 0, + 0, 891, 0, 1319, 0, 0, 0, 82, 1295, 1282, + 1324, 0, 0, 0, 0, 0, 828, 0, 204, 0, + 0, 967, 1162, 1106, 0, 51, 0, 0, 82, 0, + 1331, 0, 0, 0, 0, 0, 770, 0, 0, 0, + 0, 0, 1233, 0, 1169, 0, 1339, 1340, 0, 82, + 0, 888, 885, 886, 0, 884, 0, 0, 0, 0, + 0, 0, 1354, 0, 1045, 0, 0, 1035, 0, 1365, + 0, 1175, 0, 0, 0, 330, 487, 0, 1177, 1343, + 0, 0, 694, 0, 0, 0, 895, 898, 0, 1186, + 1187, 1188, 0, 1043, 1191, 0, 0, 0, 0, 0, + 0, 1358, 0, 0, 0, 714, 715, 1201, 1202, 1203, + 0, 1206, 202, 1069, 0, 230, 0, 0, 0, 1352, + 0, 0, 890, 1031, 330, 0, 330, 0, 1217, 0, + 0, 0, 0, 0, 0, 1092, 0, 0, 0, 0, + 257, 0, 0, 202, 889, 0, 0, 0, 202, 330, + 202, 0, 0, 0, 0, 0, 0, 0, 552, 0, + 1044, 767, 768, 0, 0, 1049, 1046, 1039, 1047, 1042, + 0, 0, 330, 1040, 1041, 0, 1192, 482, 0, 0, + 0, 0, 0, 0, 894, 0, 0, 1048, 0, 0, + 828, 0, 828, 1038, 330, 0, 1247, 896, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 822, 0, 770, + 0, 0, 1109, 1111, 516, 515, 525, 526, 518, 519, + 520, 521, 522, 523, 524, 517, 0, 0, 527, 0, + 0, 0, 0, 0, 0, 0, 1111, 0, 0, 0, + 0, 0, 0, 1286, 1287, 1288, 1289, 0, 213, 330, + 0, 330, 1138, 0, 1069, 0, 0, 0, 0, 0, + 1298, 1299, 1300, 0, 0, 0, 0, 0, 0, 202, + 0, 202, 226, 0, 0, 0, 0, 202, 0, 0, + 0, 0, 0, 0, 202, 0, 0, 1166, 0, 0, + 0, 1320, 0, 0, 0, 0, 1325, 0, 0, 1328, + 1168, 0, 909, 910, 482, 490, 0, 1171, 0, 0, + 0, 0, 0, 330, 0, 0, 1332, 0, 0, 0, + 0, 0, 0, 208, 828, 0, 0, 0, 0, 0, + 210, 0, 0, 0, 0, 0, 0, 0, 216, 212, + 0, 516, 515, 525, 526, 518, 519, 520, 521, 522, + 523, 524, 517, 1035, 828, 527, 0, 0, 0, 1366, + 1367, 0, 770, 0, 0, 0, 0, 936, 0, 0, + 214, 0, 0, 218, 0, 0, 225, 0, 0, 1189, + 482, 0, 953, 330, 0, 0, 0, 0, 0, 0, + 0, 1223, 0, 0, 202, 202, 202, 0, 0, 0, + 0, 0, 209, 0, 0, 0, 0, 0, 0, 0, + 0, 330, 330, 330, 0, 0, 0, 516, 515, 525, + 526, 518, 519, 520, 521, 522, 523, 524, 517, 219, + 211, 527, 220, 221, 222, 224, 223, 229, 0, 0, + 0, 0, 0, 228, 227, 0, 0, 0, 0, 0, + 0, 0, 0, 1254, 1255, 0, 1256, 0, 0, 0, + 0, 1223, 0, 1223, 1223, 1223, 0, 0, 0, 1138, + 511, 0, 514, 0, 0, 0, 0, 0, 528, 529, + 530, 531, 532, 533, 534, 1223, 512, 513, 510, 516, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 0, 0, 527, 0, 0, 202, 0, 0, 1072, + 1062, 0, 0, 0, 0, 0, 0, 202, 202, 1308, + 0, 202, 0, 0, 202, 0, 0, 0, 677, 516, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 0, 770, 527, 0, 1326, 0, 0, 0, 0, + 0, 0, 0, 202, 0, 0, 0, 1098, 0, 0, + 0, 0, 0, 0, 0, 0, 1334, 0, 0, 0, + 0, 0, 0, 0, 0, 202, 931, 0, 0, 0, + 0, 0, 0, 0, 677, 0, 0, 1223, 0, 0, + 0, 0, 0, 0, 0, 1129, 516, 515, 525, 526, + 518, 519, 520, 521, 522, 523, 524, 517, 0, 0, + 527, 516, 515, 525, 526, 518, 519, 520, 521, 522, + 523, 524, 517, 0, 0, 527, 257, 0, 0, 0, + 0, 257, 257, 0, 0, 771, 771, 257, 0, 0, + 0, 771, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 257, 257, 257, 257, 632, 202, 0, 0, 0, + 0, 0, 0, 0, 202, 808, 0, 0, 202, 202, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 0, 0, 527, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1197, 0, 0, 0, 0, 0, + 0, 552, 0, 0, 0, 0, 0, 0, 0, 1210, + 0, 0, 1211, 0, 0, 1213, 0, 0, 0, 0, + 0, 0, 0, 620, 0, 0, 0, 202, 0, 0, + 0, 0, 0, 0, 0, 0, 202, 0, 0, 202, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 202, 0, 906, 907, + 633, 0, 0, 0, 0, 0, 677, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 257, 0, + 0, 0, 646, 647, 648, 649, 650, 651, 652, 0, + 653, 654, 655, 656, 657, 634, 635, 636, 637, 618, + 619, 0, 0, 621, 0, 622, 623, 624, 625, 626, + 627, 628, 629, 630, 631, 638, 639, 640, 641, 642, + 643, 644, 645, 0, 0, 257, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 257, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 771, 202, 202, 202, 202, 202, + 0, 0, 0, 0, 0, 0, 0, 981, 0, 0, + 202, 0, 0, 0, 808, 0, 0, 0, 202, 1318, + 552, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 257, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 257, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 677, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 0, 0, 771, 0, 0, + 0, 0, 0, 103, 0, 0, 0, 0, 0, 119, + 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 202, 0, 516, + 515, 525, 526, 518, 519, 520, 521, 522, 523, 524, + 517, 0, 0, 527, 0, 0, 0, 0, 0, 202, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 205, 0, 0, 202, 0, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 0, 0, + 0, 99, 0, 151, 140, 173, 0, 141, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 171, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 771, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 92, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 0, 0, 158, 175, 190, + 94, 0, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 134, 93, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 83, 0, 120, 187, 146, 105, 176, 416, + 407, 0, 378, 419, 356, 370, 427, 371, 372, 400, + 342, 386, 138, 368, 808, 359, 337, 365, 338, 357, + 380, 103, 383, 355, 409, 389, 418, 119, 425, 121, + 394, 0, 157, 130, 0, 0, 382, 411, 384, 405, + 377, 401, 347, 393, 420, 369, 398, 421, 0, 0, + 0, 81, 0, 829, 830, 0, 0, 0, 0, 0, + 96, 0, 396, 415, 367, 397, 399, 336, 395, 0, + 340, 343, 426, 413, 362, 363, 1002, 0, 0, 0, + 0, 0, 0, 381, 385, 402, 375, 0, 0, 0, + 771, 0, 0, 0, 0, 360, 0, 392, 0, 0, + 0, 344, 341, 0, 202, 379, 0, 0, 0, 346, + 0, 361, 403, 0, 335, 108, 406, 412, 376, 205, + 414, 374, 373, 417, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 410, 358, 366, 99, + 364, 151, 140, 173, 391, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 339, 0, 158, 175, 190, 94, 354, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 350, 353, 348, 349, 387, 388, 422, + 423, 424, 404, 345, 0, 351, 352, 0, 408, 390, + 83, 0, 120, 187, 146, 105, 176, 416, 407, 0, + 378, 419, 356, 370, 427, 371, 372, 400, 342, 386, + 138, 368, 0, 359, 337, 365, 338, 357, 380, 103, + 383, 355, 409, 389, 418, 119, 425, 121, 394, 0, + 157, 130, 0, 0, 382, 411, 384, 405, 377, 401, + 347, 393, 420, 369, 398, 421, 0, 0, 0, 81, + 0, 829, 830, 0, 0, 0, 0, 0, 96, 0, + 396, 415, 367, 397, 399, 336, 395, 0, 340, 343, + 426, 413, 362, 363, 0, 0, 0, 0, 0, 0, + 0, 381, 385, 402, 375, 0, 0, 0, 0, 0, + 0, 0, 0, 360, 0, 392, 0, 0, 0, 344, + 341, 0, 0, 379, 0, 0, 0, 346, 0, 361, + 403, 0, 335, 108, 406, 412, 376, 205, 414, 374, + 373, 417, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 410, 358, 366, 99, 364, 151, + 140, 173, 391, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 339, 0, 158, 175, 190, 94, 354, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 350, 353, 348, 349, 387, 388, 422, 423, 424, + 404, 345, 0, 351, 352, 0, 408, 390, 83, 0, + 120, 187, 146, 105, 176, 416, 407, 0, 378, 419, + 356, 370, 427, 371, 372, 400, 342, 386, 138, 368, + 0, 359, 337, 365, 338, 357, 380, 103, 383, 355, + 409, 389, 418, 119, 425, 121, 394, 0, 157, 130, + 0, 0, 382, 411, 384, 405, 377, 401, 347, 393, + 420, 369, 398, 421, 54, 0, 0, 81, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 396, 415, + 367, 397, 399, 336, 395, 0, 340, 343, 426, 413, + 362, 363, 0, 0, 0, 0, 0, 0, 0, 381, + 385, 402, 375, 0, 0, 0, 0, 0, 0, 0, + 0, 360, 0, 392, 0, 0, 0, 344, 341, 0, + 0, 379, 0, 0, 0, 346, 0, 361, 403, 0, + 335, 108, 406, 412, 376, 205, 414, 374, 373, 417, + 144, 0, 160, 110, 118, 84, 90, 0, 109, 136, + 149, 153, 410, 358, 366, 99, 364, 151, 140, 173, + 391, 141, 150, 122, 165, 145, 172, 206, 180, 162, + 179, 186, 85, 161, 171, 97, 154, 87, 169, 159, + 128, 114, 115, 86, 0, 148, 102, 106, 101, 137, + 166, 167, 100, 189, 91, 178, 89, 92, 177, 135, + 164, 170, 129, 126, 88, 168, 127, 125, 117, 104, + 111, 142, 124, 143, 112, 132, 131, 133, 0, 339, + 0, 158, 175, 190, 94, 354, 163, 181, 182, 183, + 184, 185, 0, 0, 95, 107, 134, 93, 113, 155, + 116, 123, 147, 188, 139, 152, 98, 174, 156, 350, + 353, 348, 349, 387, 388, 422, 423, 424, 404, 345, + 0, 351, 352, 0, 408, 390, 83, 0, 120, 187, + 146, 105, 176, 416, 407, 0, 378, 419, 356, 370, + 427, 371, 372, 400, 342, 386, 138, 368, 0, 359, + 337, 365, 338, 357, 380, 103, 383, 355, 409, 389, + 418, 119, 425, 121, 394, 0, 157, 130, 0, 0, + 382, 411, 384, 405, 377, 401, 347, 393, 420, 369, + 398, 421, 0, 0, 0, 81, 0, 0, 0, 0, + 0, 0, 0, 0, 96, 0, 396, 415, 367, 397, + 399, 336, 395, 0, 340, 343, 426, 413, 362, 363, + 0, 0, 0, 0, 0, 0, 0, 381, 385, 402, + 375, 0, 0, 0, 0, 0, 0, 1068, 0, 360, + 0, 392, 0, 0, 0, 344, 341, 0, 0, 379, + 0, 0, 0, 346, 0, 361, 403, 0, 335, 108, + 406, 412, 376, 205, 414, 374, 373, 417, 144, 0, + 160, 110, 118, 84, 90, 0, 109, 136, 149, 153, + 410, 358, 366, 99, 364, 151, 140, 173, 391, 141, + 150, 122, 165, 145, 172, 206, 180, 162, 179, 186, + 85, 161, 171, 97, 154, 87, 169, 159, 128, 114, + 115, 86, 0, 148, 102, 106, 101, 137, 166, 167, + 100, 189, 91, 178, 89, 92, 177, 135, 164, 170, + 129, 126, 88, 168, 127, 125, 117, 104, 111, 142, + 124, 143, 112, 132, 131, 133, 0, 339, 0, 158, + 175, 190, 94, 354, 163, 181, 182, 183, 184, 185, + 0, 0, 95, 107, 134, 93, 113, 155, 116, 123, + 147, 188, 139, 152, 98, 174, 156, 350, 353, 348, + 349, 387, 388, 422, 423, 424, 404, 345, 0, 351, + 352, 0, 408, 390, 83, 0, 120, 187, 146, 105, + 176, 416, 407, 0, 378, 419, 356, 370, 427, 371, + 372, 400, 342, 386, 138, 368, 0, 359, 337, 365, + 338, 357, 380, 103, 383, 355, 409, 389, 418, 119, + 425, 121, 394, 0, 157, 130, 0, 0, 382, 411, + 384, 405, 377, 401, 347, 393, 420, 369, 398, 421, + 0, 0, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 396, 415, 367, 397, 399, 336, + 395, 0, 340, 343, 426, 413, 362, 363, 0, 0, + 0, 0, 0, 0, 0, 381, 385, 402, 375, 0, + 0, 0, 0, 0, 0, 722, 0, 360, 0, 392, + 0, 0, 0, 344, 341, 0, 0, 379, 0, 0, + 0, 346, 0, 361, 403, 0, 335, 108, 406, 412, + 376, 205, 414, 374, 373, 417, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 410, 358, + 366, 99, 364, 151, 140, 173, 391, 141, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 171, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 0, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 92, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 339, 0, 158, 175, 190, + 94, 354, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 134, 93, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 350, 353, 348, 349, 387, + 388, 422, 423, 424, 404, 345, 0, 351, 352, 0, + 408, 390, 83, 0, 120, 187, 146, 105, 176, 416, + 407, 0, 378, 419, 356, 370, 427, 371, 372, 400, + 342, 386, 138, 368, 0, 359, 337, 365, 338, 357, + 380, 103, 383, 355, 409, 389, 418, 119, 425, 121, + 394, 0, 157, 130, 0, 0, 382, 411, 384, 405, + 377, 401, 347, 393, 420, 369, 398, 421, 0, 0, + 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 396, 415, 367, 397, 399, 336, 395, 0, + 340, 343, 426, 413, 362, 363, 0, 0, 0, 0, + 0, 0, 0, 381, 385, 402, 375, 0, 0, 0, + 0, 0, 0, 0, 0, 360, 0, 392, 0, 0, + 0, 344, 341, 0, 0, 379, 0, 0, 0, 346, + 0, 361, 403, 0, 335, 108, 406, 412, 376, 205, + 414, 374, 373, 417, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 410, 358, 366, 99, + 364, 151, 140, 173, 391, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 339, 0, 158, 175, 190, 94, 354, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 350, 353, 348, 349, 387, 388, 422, + 423, 424, 404, 345, 0, 351, 352, 0, 408, 390, + 83, 0, 120, 187, 146, 105, 176, 416, 407, 0, + 378, 419, 356, 370, 427, 371, 372, 400, 342, 386, + 138, 368, 0, 359, 337, 365, 338, 357, 380, 103, + 383, 355, 409, 389, 418, 119, 425, 121, 394, 0, + 157, 130, 0, 0, 382, 411, 384, 405, 377, 401, + 347, 393, 420, 369, 398, 421, 0, 0, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 396, 415, 367, 397, 399, 336, 395, 0, 340, 343, + 426, 413, 362, 363, 0, 0, 0, 0, 0, 0, + 0, 381, 385, 402, 375, 0, 0, 0, 0, 0, + 0, 0, 0, 360, 0, 392, 0, 0, 0, 344, + 341, 0, 0, 379, 0, 0, 0, 346, 0, 361, + 403, 0, 335, 108, 406, 412, 376, 205, 414, 374, + 373, 417, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 410, 358, 366, 99, 364, 151, + 140, 173, 391, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 339, 0, 158, 175, 190, 94, 354, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 350, 353, 348, 349, 387, 388, 422, 423, 424, + 404, 345, 0, 351, 352, 0, 408, 390, 83, 0, + 120, 187, 146, 105, 176, 416, 407, 0, 378, 419, + 356, 370, 427, 371, 372, 400, 342, 386, 138, 368, + 0, 359, 337, 365, 338, 357, 380, 103, 383, 355, + 409, 389, 418, 119, 425, 121, 394, 0, 157, 130, + 0, 0, 382, 411, 384, 405, 377, 401, 347, 393, + 420, 369, 398, 421, 0, 0, 0, 81, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 396, 415, + 367, 397, 399, 336, 395, 0, 340, 343, 426, 413, + 362, 363, 0, 0, 0, 0, 0, 0, 0, 381, + 385, 402, 375, 0, 0, 0, 0, 0, 0, 0, + 0, 360, 0, 392, 0, 0, 0, 344, 341, 0, + 0, 379, 0, 0, 0, 346, 0, 361, 403, 0, + 335, 108, 406, 412, 376, 205, 414, 374, 373, 417, + 144, 0, 160, 110, 118, 84, 90, 0, 109, 136, + 149, 153, 410, 358, 366, 99, 364, 151, 140, 173, + 391, 141, 150, 122, 165, 145, 172, 206, 180, 162, + 179, 186, 85, 161, 171, 97, 154, 87, 169, 159, + 128, 114, 115, 86, 0, 148, 102, 106, 101, 137, + 166, 167, 100, 189, 91, 178, 89, 333, 177, 135, + 164, 170, 129, 126, 88, 168, 127, 125, 117, 104, + 111, 142, 124, 143, 112, 132, 131, 133, 0, 339, + 0, 158, 175, 190, 94, 354, 163, 181, 182, 183, + 184, 185, 0, 0, 95, 107, 334, 332, 113, 155, + 116, 123, 147, 188, 139, 152, 98, 174, 156, 350, + 353, 348, 349, 387, 388, 422, 423, 424, 404, 345, + 0, 351, 352, 0, 408, 390, 83, 0, 120, 187, + 146, 105, 176, 416, 407, 0, 378, 419, 356, 370, + 427, 371, 372, 400, 342, 386, 138, 368, 0, 359, + 337, 365, 338, 357, 380, 103, 383, 355, 409, 389, + 418, 119, 425, 121, 394, 0, 157, 130, 0, 0, + 382, 411, 384, 405, 377, 401, 347, 393, 420, 369, + 398, 421, 0, 0, 0, 203, 0, 0, 0, 0, + 0, 0, 0, 0, 96, 0, 396, 415, 367, 397, + 399, 336, 395, 0, 340, 343, 426, 413, 362, 363, + 0, 0, 0, 0, 0, 0, 0, 381, 385, 402, + 375, 0, 0, 0, 0, 0, 0, 0, 0, 360, + 0, 392, 0, 0, 0, 344, 341, 0, 0, 379, + 0, 0, 0, 346, 0, 361, 403, 0, 335, 108, + 406, 412, 376, 205, 414, 374, 373, 417, 144, 0, + 160, 110, 118, 84, 90, 0, 109, 136, 149, 153, + 410, 358, 366, 99, 364, 151, 140, 173, 391, 141, + 150, 122, 165, 145, 172, 206, 180, 162, 179, 186, + 85, 161, 171, 97, 154, 87, 169, 159, 128, 114, + 115, 86, 0, 148, 102, 106, 101, 137, 166, 167, + 100, 189, 91, 178, 89, 92, 177, 135, 164, 170, + 129, 126, 88, 168, 127, 125, 117, 104, 111, 142, + 124, 143, 112, 132, 131, 133, 0, 339, 0, 158, + 175, 190, 94, 354, 163, 181, 182, 183, 184, 185, + 0, 0, 95, 107, 134, 93, 113, 155, 116, 123, + 147, 188, 139, 152, 98, 174, 156, 350, 353, 348, + 349, 387, 388, 422, 423, 424, 404, 345, 0, 351, + 352, 0, 408, 390, 83, 0, 120, 187, 146, 105, + 176, 416, 407, 0, 378, 419, 356, 370, 427, 371, + 372, 400, 342, 386, 138, 368, 0, 359, 337, 365, + 338, 357, 380, 103, 383, 355, 409, 389, 418, 119, + 425, 121, 394, 0, 157, 130, 0, 0, 382, 411, + 384, 405, 377, 401, 347, 393, 420, 369, 398, 421, + 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 396, 415, 367, 397, 399, 336, + 395, 0, 340, 343, 426, 413, 362, 363, 0, 0, + 0, 0, 0, 0, 0, 381, 385, 402, 375, 0, + 0, 0, 0, 0, 0, 0, 0, 360, 0, 392, + 0, 0, 0, 344, 341, 0, 0, 379, 0, 0, + 0, 346, 0, 361, 403, 0, 335, 108, 406, 412, + 376, 205, 414, 374, 373, 417, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 410, 358, + 366, 99, 364, 151, 140, 173, 391, 141, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 597, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 0, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 333, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 339, 0, 158, 175, 190, + 94, 354, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 334, 332, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 350, 353, 348, 349, 387, + 388, 422, 423, 424, 404, 345, 0, 351, 352, 0, + 408, 390, 83, 0, 120, 187, 146, 105, 176, 416, + 407, 0, 378, 419, 356, 370, 427, 371, 372, 400, + 342, 386, 138, 368, 0, 359, 337, 365, 338, 357, + 380, 103, 383, 355, 409, 389, 418, 119, 425, 121, + 394, 0, 157, 130, 0, 0, 382, 411, 384, 405, + 377, 401, 347, 393, 420, 369, 398, 421, 0, 0, + 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 396, 415, 367, 397, 399, 336, 395, 0, + 340, 343, 426, 413, 362, 363, 0, 0, 0, 0, + 0, 0, 0, 381, 385, 402, 375, 0, 0, 0, + 0, 0, 0, 0, 0, 360, 0, 392, 0, 0, + 0, 344, 341, 0, 0, 379, 0, 0, 0, 346, + 0, 361, 403, 0, 335, 108, 406, 412, 376, 205, + 414, 374, 373, 417, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 410, 358, 366, 99, + 364, 151, 140, 173, 391, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 324, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 333, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 339, 0, 158, 175, 190, 94, 354, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 334, 332, 327, 326, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 350, 353, 348, 349, 387, 388, 422, + 423, 424, 404, 345, 0, 351, 352, 0, 408, 390, + 83, 0, 120, 187, 146, 105, 176, 138, 0, 0, + 0, 0, 264, 0, 0, 0, 103, 0, 261, 0, + 0, 0, 119, 304, 121, 0, 0, 157, 130, 0, + 0, 0, 0, 295, 296, 0, 0, 0, 0, 0, + 0, 820, 0, 54, 0, 0, 262, 283, 282, 285, + 286, 287, 288, 0, 0, 96, 284, 289, 290, 291, + 821, 0, 0, 259, 276, 0, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 273, 274, 0, 0, + 0, 0, 315, 0, 275, 0, 0, 270, 271, 272, + 277, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 313, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 305, 314, + 311, 312, 309, 310, 308, 307, 306, 316, 297, 298, + 299, 300, 302, 0, 301, 83, 0, 120, 187, 146, + 105, 176, 138, 0, 0, 758, 0, 264, 0, 0, + 0, 103, 0, 261, 0, 0, 0, 119, 304, 121, + 0, 0, 157, 130, 0, 0, 0, 0, 295, 296, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, + 0, 262, 283, 282, 285, 286, 287, 288, 0, 0, + 96, 284, 289, 290, 291, 0, 0, 0, 259, 276, + 0, 303, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 273, 274, 255, 0, 0, 0, 315, 0, 275, + 0, 0, 270, 271, 272, 277, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 0, 0, 0, 205, + 0, 0, 313, 0, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 0, 0, 0, 99, + 0, 151, 140, 173, 0, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 0, 0, 158, 175, 190, 94, 0, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 305, 314, 311, 312, 309, 310, 308, + 307, 306, 316, 297, 298, 299, 300, 302, 0, 301, + 83, 0, 120, 187, 146, 105, 176, 138, 0, 0, + 0, 0, 264, 0, 0, 0, 103, 0, 261, 0, + 0, 0, 119, 304, 121, 0, 0, 157, 130, 0, + 0, 0, 0, 295, 296, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 482, 262, 283, 282, 285, + 286, 287, 288, 0, 0, 96, 284, 289, 290, 291, + 0, 0, 0, 259, 276, 0, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 273, 274, 0, 0, + 0, 0, 315, 0, 275, 0, 0, 270, 271, 272, + 277, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 313, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 305, 314, + 311, 312, 309, 310, 308, 307, 306, 316, 297, 298, + 299, 300, 302, 0, 301, 83, 0, 120, 187, 146, + 105, 176, 138, 0, 0, 0, 0, 264, 0, 0, + 0, 103, 0, 261, 0, 0, 0, 119, 304, 121, + 0, 0, 157, 130, 0, 0, 0, 0, 295, 296, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, + 0, 262, 283, 282, 285, 286, 287, 288, 0, 0, + 96, 284, 289, 290, 291, 0, 0, 0, 259, 276, + 0, 303, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 273, 274, 255, 0, 0, 0, 315, 0, 275, + 0, 0, 270, 271, 272, 277, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 0, 0, 0, 205, + 0, 0, 313, 0, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 0, 0, 0, 99, + 0, 151, 140, 173, 0, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 0, 0, 158, 175, 190, 94, 0, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 305, 314, 311, 312, 309, 310, 308, + 307, 306, 316, 297, 298, 299, 300, 302, 24, 301, + 83, 0, 120, 187, 146, 105, 176, 0, 0, 0, + 138, 0, 0, 0, 0, 264, 0, 0, 0, 103, + 0, 261, 0, 0, 0, 119, 304, 121, 0, 0, + 157, 130, 0, 0, 0, 0, 295, 296, 0, 0, + 0, 0, 0, 0, 0, 0, 54, 0, 0, 262, + 283, 282, 285, 286, 287, 288, 0, 0, 96, 284, + 289, 290, 291, 0, 0, 0, 259, 276, 0, 303, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 273, + 274, 0, 0, 0, 0, 315, 0, 275, 0, 0, + 270, 271, 272, 277, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, + 313, 0, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 0, 0, 0, 99, 0, 151, + 140, 173, 0, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 0, 0, 158, 175, 190, 94, 0, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 305, 314, 311, 312, 309, 310, 308, 307, 306, + 316, 297, 298, 299, 300, 302, 0, 301, 83, 0, + 120, 187, 146, 105, 176, 138, 0, 0, 0, 0, + 264, 0, 0, 0, 103, 0, 261, 0, 0, 0, + 119, 304, 121, 0, 0, 157, 130, 0, 0, 0, + 0, 295, 296, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 262, 283, 282, 285, 286, 287, + 288, 0, 0, 96, 284, 289, 290, 291, 0, 0, + 0, 259, 276, 0, 303, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 273, 274, 0, 0, 0, 0, + 315, 0, 275, 0, 0, 270, 271, 272, 277, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, + 0, 0, 205, 0, 0, 313, 0, 144, 0, 160, + 110, 118, 84, 90, 0, 109, 136, 149, 153, 0, + 0, 0, 99, 0, 151, 140, 173, 0, 141, 150, + 122, 165, 145, 172, 206, 180, 162, 179, 186, 85, + 161, 171, 97, 154, 87, 169, 159, 128, 114, 115, + 86, 0, 148, 102, 106, 101, 137, 166, 167, 100, + 189, 91, 178, 89, 92, 177, 135, 164, 170, 129, + 126, 88, 168, 127, 125, 117, 104, 111, 142, 124, + 143, 112, 132, 131, 133, 0, 0, 0, 158, 175, + 190, 94, 0, 163, 181, 182, 183, 184, 185, 0, + 0, 95, 107, 134, 93, 113, 155, 116, 123, 147, + 188, 139, 152, 98, 174, 156, 305, 314, 311, 312, + 309, 310, 308, 307, 306, 316, 297, 298, 299, 300, + 302, 138, 301, 83, 0, 120, 187, 146, 105, 176, + 103, 0, 0, 0, 0, 0, 119, 304, 121, 0, + 0, 157, 130, 0, 0, 0, 0, 295, 296, 0, + 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, + 262, 283, 282, 285, 286, 287, 288, 0, 0, 96, + 284, 289, 290, 291, 0, 0, 0, 0, 276, 0, + 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 273, 274, 0, 0, 0, 0, 315, 0, 275, 0, + 0, 270, 271, 272, 277, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 108, 0, 0, 0, 205, 0, + 0, 313, 0, 144, 0, 160, 110, 118, 84, 90, + 0, 109, 136, 149, 153, 0, 0, 0, 99, 0, + 151, 140, 173, 1359, 141, 150, 122, 165, 145, 172, + 206, 180, 162, 179, 186, 85, 161, 171, 97, 154, + 87, 169, 159, 128, 114, 115, 86, 0, 148, 102, + 106, 101, 137, 166, 167, 100, 189, 91, 178, 89, + 92, 177, 135, 164, 170, 129, 126, 88, 168, 127, + 125, 117, 104, 111, 142, 124, 143, 112, 132, 131, + 133, 0, 0, 0, 158, 175, 190, 94, 0, 163, + 181, 182, 183, 184, 185, 0, 0, 95, 107, 134, + 93, 113, 155, 116, 123, 147, 188, 139, 152, 98, + 174, 156, 305, 314, 311, 312, 309, 310, 308, 307, + 306, 316, 297, 298, 299, 300, 302, 138, 301, 83, + 0, 120, 187, 146, 105, 176, 103, 0, 0, 0, + 0, 0, 119, 304, 121, 0, 0, 157, 130, 0, + 0, 0, 0, 295, 296, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 0, 262, 283, 282, 285, + 286, 287, 288, 0, 0, 96, 284, 289, 290, 291, + 0, 0, 0, 0, 276, 0, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 273, 274, 0, 0, + 0, 0, 315, 0, 275, 0, 0, 270, 271, 272, + 277, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 313, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 305, 314, + 311, 312, 309, 310, 308, 307, 306, 316, 297, 298, + 299, 300, 302, 0, 301, 83, 0, 120, 187, 146, + 105, 176, 138, 0, 0, 0, 504, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 119, 0, 121, + 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 81, 0, 506, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 501, 500, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 502, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 0, 0, 0, 205, + 0, 0, 0, 0, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 0, 0, 0, 99, + 0, 151, 140, 173, 0, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 0, 0, 158, 175, 190, 94, 0, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, + 83, 103, 120, 187, 146, 105, 176, 119, 0, 121, + 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 77, 78, 0, 73, + 0, 0, 0, 79, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 0, 0, 0, 99, + 0, 151, 140, 173, 0, 141, 150, 122, 165, 145, + 172, 75, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 0, 0, 158, 175, 190, 94, 0, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 0, 76, 0, 0, 0, 0, 0, + 0, 0, 138, 0, 0, 0, 807, 0, 0, 0, + 83, 103, 120, 187, 146, 105, 176, 119, 0, 121, + 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 203, 0, 809, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 0, 0, 0, 205, + 0, 0, 0, 0, 144, 0, 160, 110, 118, 84, + 90, 0, 109, 136, 149, 153, 0, 0, 0, 99, + 0, 151, 140, 173, 0, 141, 150, 122, 165, 145, + 172, 206, 180, 162, 179, 186, 85, 161, 171, 97, + 154, 87, 169, 159, 128, 114, 115, 86, 0, 148, + 102, 106, 101, 137, 166, 167, 100, 189, 91, 178, + 89, 92, 177, 135, 164, 170, 129, 126, 88, 168, + 127, 125, 117, 104, 111, 142, 124, 143, 112, 132, + 131, 133, 0, 0, 0, 158, 175, 190, 94, 0, + 163, 181, 182, 183, 184, 185, 0, 0, 95, 107, + 134, 93, 113, 155, 116, 123, 147, 188, 139, 152, + 98, 174, 156, 0, 0, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, + 83, 0, 120, 187, 146, 105, 176, 103, 0, 0, + 0, 0, 0, 119, 0, 121, 0, 0, 157, 130, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, 0, 81, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 108, 0, 0, 0, 205, 0, 0, 0, 0, + 144, 0, 160, 110, 118, 84, 90, 0, 109, 136, + 149, 153, 0, 0, 0, 99, 0, 151, 140, 173, + 0, 141, 150, 122, 165, 145, 172, 206, 180, 162, + 179, 186, 85, 161, 171, 97, 154, 87, 169, 159, + 128, 114, 115, 86, 0, 148, 102, 106, 101, 137, + 166, 167, 100, 189, 91, 178, 89, 92, 177, 135, + 164, 170, 129, 126, 88, 168, 127, 125, 117, 104, + 111, 142, 124, 143, 112, 132, 131, 133, 0, 0, + 0, 158, 175, 190, 94, 0, 163, 181, 182, 183, + 184, 185, 0, 0, 95, 107, 134, 93, 113, 155, + 116, 123, 147, 188, 139, 152, 98, 174, 156, 0, + 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 0, 83, 0, 120, 187, + 146, 105, 176, 103, 0, 0, 0, 0, 0, 119, + 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 0, 0, 203, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 205, 0, 0, 0, 0, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 0, 0, + 0, 99, 0, 151, 140, 173, 0, 141, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 171, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 0, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 92, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 0, 0, 158, 175, 190, + 94, 0, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 134, 93, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 0, 0, 0, 807, 0, + 0, 0, 83, 103, 120, 187, 146, 105, 176, 119, + 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 0, 809, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 205, 0, 0, 0, 0, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 0, 0, + 0, 99, 0, 151, 140, 173, 0, 805, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 171, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 0, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 92, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 0, 0, 158, 175, 190, + 94, 0, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 134, 93, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, + 0, 0, 83, 103, 120, 187, 146, 105, 176, 119, + 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 81, 0, 0, 709, 0, 0, 710, + 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 205, 0, 0, 0, 0, 144, 0, 160, 110, + 118, 84, 90, 0, 109, 136, 149, 153, 0, 0, + 0, 99, 0, 151, 140, 173, 0, 141, 150, 122, + 165, 145, 172, 206, 180, 162, 179, 186, 85, 161, + 171, 97, 154, 87, 169, 159, 128, 114, 115, 86, + 0, 148, 102, 106, 101, 137, 166, 167, 100, 189, + 91, 178, 89, 92, 177, 135, 164, 170, 129, 126, + 88, 168, 127, 125, 117, 104, 111, 142, 124, 143, + 112, 132, 131, 133, 0, 0, 0, 158, 175, 190, + 94, 0, 163, 181, 182, 183, 184, 185, 0, 0, + 95, 107, 134, 93, 113, 155, 116, 123, 147, 188, + 139, 152, 98, 174, 156, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 0, 83, 0, 120, 187, 146, 105, 176, 103, + 0, 606, 0, 0, 0, 119, 0, 121, 0, 0, + 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, + 0, 605, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, + 0, 0, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 0, 0, 0, 99, 0, 151, + 140, 173, 0, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 0, 0, 158, 175, 190, 94, 0, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 0, 0, 0, 0, 0, 0, 0, 83, 103, + 120, 187, 146, 105, 176, 119, 0, 121, 0, 0, + 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 54, 0, 0, 203, + 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, + 0, 0, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 0, 0, 0, 99, 0, 151, + 140, 173, 0, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 0, 0, 158, 175, 190, 94, 0, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 0, 0, 0, 0, 0, 0, 0, 83, 103, + 120, 187, 146, 105, 176, 119, 0, 121, 0, 0, + 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, + 0, 809, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, + 0, 0, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 0, 0, 0, 99, 0, 151, + 140, 173, 0, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 0, 0, 158, 175, 190, 94, 0, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 0, 0, 0, 0, 0, 0, 0, 83, 103, + 120, 187, 146, 105, 176, 119, 0, 121, 0, 0, + 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, + 0, 506, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 199, 0, 0, 0, 0, 140, 0, 156, 106, - 114, 82, 88, 0, 105, 132, 145, 149, 0, 0, - 0, 97, 0, 147, 136, 168, 0, 137, 146, 118, - 160, 141, 167, 200, 175, 158, 174, 83, 157, 166, - 95, 150, 85, 164, 155, 124, 110, 111, 84, 0, - 144, 100, 104, 99, 133, 161, 162, 98, 183, 89, - 173, 87, 90, 172, 131, 159, 165, 125, 122, 86, - 163, 123, 121, 113, 102, 107, 138, 120, 139, 108, - 128, 127, 129, 0, 0, 0, 154, 170, 184, 92, - 0, 0, 176, 177, 178, 179, 180, 0, 0, 93, - 130, 91, 109, 151, 112, 119, 143, 182, 135, 148, - 96, 169, 152, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, - 81, 101, 116, 181, 142, 103, 171, 115, 0, 117, - 0, 0, 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 0, 503, 0, 0, 0, 0, 0, 0, - 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, + 0, 0, 144, 0, 160, 110, 118, 84, 90, 0, + 109, 136, 149, 153, 0, 0, 0, 99, 0, 151, + 140, 173, 0, 141, 150, 122, 165, 145, 172, 206, + 180, 162, 179, 186, 85, 161, 171, 97, 154, 87, + 169, 159, 128, 114, 115, 86, 0, 148, 102, 106, + 101, 137, 166, 167, 100, 189, 91, 178, 89, 92, + 177, 135, 164, 170, 129, 126, 88, 168, 127, 125, + 117, 104, 111, 142, 124, 143, 112, 132, 131, 133, + 0, 0, 0, 158, 175, 190, 94, 0, 163, 181, + 182, 183, 184, 185, 0, 0, 95, 107, 134, 93, + 113, 155, 116, 123, 147, 188, 139, 152, 98, 174, + 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 138, 83, 0, + 120, 187, 146, 105, 176, 579, 103, 0, 0, 0, + 0, 0, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, - 0, 0, 140, 0, 156, 106, 114, 82, 88, 0, - 105, 132, 145, 149, 0, 0, 0, 97, 0, 147, - 136, 168, 0, 137, 146, 118, 160, 141, 167, 200, - 175, 158, 174, 83, 157, 166, 95, 150, 85, 164, - 155, 124, 110, 111, 84, 0, 144, 100, 104, 99, - 133, 161, 162, 98, 183, 89, 173, 87, 90, 172, - 131, 159, 165, 125, 122, 86, 163, 123, 121, 113, - 102, 107, 138, 120, 139, 108, 128, 127, 129, 0, - 0, 0, 154, 170, 184, 92, 0, 0, 176, 177, - 178, 179, 180, 0, 0, 93, 130, 91, 109, 151, - 112, 119, 143, 182, 135, 148, 96, 169, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 134, 81, 0, 116, 181, - 142, 103, 171, 576, 101, 0, 0, 0, 0, 0, - 115, 0, 117, 0, 0, 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, + 319, 0, 0, 0, 0, 0, 0, 138, 0, 0, + 0, 0, 0, 0, 0, 83, 103, 120, 187, 146, + 105, 176, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 199, 0, 0, 0, 0, 140, 0, 156, 106, 114, - 82, 88, 0, 105, 132, 145, 149, 0, 0, 0, - 97, 0, 147, 136, 168, 0, 137, 146, 118, 160, - 141, 167, 200, 175, 158, 174, 83, 157, 166, 95, - 150, 85, 164, 155, 124, 110, 111, 84, 0, 144, - 100, 104, 99, 133, 161, 162, 98, 183, 89, 173, - 87, 90, 172, 131, 159, 165, 125, 122, 86, 163, - 123, 121, 113, 102, 107, 138, 120, 139, 108, 128, - 127, 129, 0, 0, 0, 154, 170, 184, 92, 0, - 0, 176, 177, 178, 179, 180, 0, 0, 93, 130, - 91, 109, 151, 112, 119, 143, 182, 135, 148, 96, - 169, 152, 0, 0, 318, 0, 0, 0, 0, 0, - 0, 134, 0, 0, 0, 0, 0, 0, 0, 81, - 101, 116, 181, 142, 103, 171, 115, 0, 117, 0, - 0, 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 197, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, + 0, 0, 0, 0, 0, 83, 103, 120, 187, 146, + 105, 176, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, - 0, 140, 0, 156, 106, 114, 82, 88, 0, 105, - 132, 145, 149, 0, 0, 0, 97, 0, 147, 136, - 168, 0, 137, 146, 118, 160, 141, 167, 200, 175, - 158, 174, 83, 157, 166, 95, 150, 85, 164, 155, - 124, 110, 111, 84, 0, 144, 100, 104, 99, 133, - 161, 162, 98, 183, 89, 173, 87, 90, 172, 131, - 159, 165, 125, 122, 86, 163, 123, 121, 113, 102, - 107, 138, 120, 139, 108, 128, 127, 129, 0, 0, - 0, 154, 170, 184, 92, 0, 0, 176, 177, 178, - 179, 180, 0, 0, 93, 130, 91, 109, 151, 112, - 119, 143, 182, 135, 148, 96, 169, 152, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 134, 0, 0, - 0, 0, 0, 0, 0, 81, 101, 116, 181, 142, - 103, 171, 115, 0, 117, 0, 0, 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, - 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 200, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, + 0, 0, 0, 0, 0, 83, 103, 120, 187, 146, + 105, 176, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 194, 0, 199, 0, 0, 0, 0, 140, 0, 156, - 106, 114, 82, 88, 0, 105, 132, 145, 149, 0, - 0, 0, 97, 0, 147, 136, 168, 0, 137, 146, - 118, 160, 141, 167, 200, 175, 158, 174, 83, 157, - 166, 95, 150, 85, 164, 155, 124, 110, 111, 84, - 0, 144, 100, 104, 99, 133, 161, 162, 98, 183, - 89, 173, 87, 90, 172, 131, 159, 165, 125, 122, - 86, 163, 123, 121, 113, 102, 107, 138, 120, 139, - 108, 128, 127, 129, 0, 0, 0, 154, 170, 184, - 92, 0, 0, 176, 177, 178, 179, 180, 0, 0, - 93, 130, 91, 109, 151, 112, 119, 143, 182, 135, - 148, 96, 169, 152, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, - 0, 81, 101, 116, 181, 142, 103, 171, 115, 0, - 117, 0, 0, 153, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, + 0, 0, 0, 0, 0, 83, 103, 120, 187, 146, + 105, 176, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 199, 0, - 0, 0, 0, 140, 0, 156, 106, 114, 82, 88, - 0, 105, 132, 145, 149, 0, 0, 0, 97, 0, - 147, 136, 168, 0, 137, 146, 118, 160, 141, 167, - 200, 175, 158, 174, 83, 157, 166, 95, 150, 85, - 164, 155, 124, 110, 111, 84, 0, 144, 100, 104, - 99, 133, 161, 162, 98, 183, 89, 173, 87, 90, - 172, 131, 159, 165, 125, 122, 86, 163, 123, 121, - 113, 102, 107, 138, 120, 139, 108, 128, 127, 129, - 0, 0, 0, 154, 170, 184, 92, 0, 0, 176, - 177, 178, 179, 180, 0, 0, 93, 130, 91, 109, - 151, 112, 119, 143, 182, 135, 148, 96, 169, 152, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, - 0, 0, 0, 0, 0, 0, 0, 81, 101, 116, - 181, 142, 103, 171, 115, 0, 117, 0, 0, 153, - 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, + 0, 0, 0, 0, 0, 83, 103, 120, 187, 146, + 105, 176, 119, 0, 121, 0, 0, 157, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 199, 0, 0, 0, 0, 140, - 0, 156, 106, 114, 82, 88, 0, 105, 132, 145, - 149, 0, 0, 0, 97, 0, 147, 136, 168, 0, - 137, 146, 118, 160, 141, 167, 200, 175, 158, 174, - 83, 157, 166, 95, 150, 85, 164, 155, 124, 110, - 111, 84, 0, 144, 100, 104, 99, 133, 161, 162, - 98, 183, 89, 173, 87, 90, 172, 131, 159, 165, - 125, 122, 86, 163, 123, 121, 113, 102, 107, 138, - 120, 139, 108, 128, 127, 129, 0, 0, 0, 154, - 170, 184, 92, 0, 0, 176, 177, 178, 179, 180, - 0, 0, 93, 130, 91, 109, 151, 112, 119, 143, - 182, 135, 148, 96, 169, 152, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, - 0, 0, 0, 81, 101, 116, 181, 142, 103, 171, - 115, 0, 117, 0, 0, 153, 126, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 205, 0, 0, 0, 0, 144, + 0, 160, 110, 118, 84, 90, 0, 109, 136, 149, + 153, 0, 0, 0, 99, 0, 151, 140, 173, 0, + 141, 150, 122, 165, 145, 172, 206, 180, 162, 179, + 186, 85, 161, 171, 97, 154, 87, 169, 159, 128, + 114, 115, 86, 0, 148, 102, 106, 101, 137, 166, + 167, 100, 189, 91, 178, 89, 92, 177, 135, 164, + 170, 129, 126, 88, 168, 127, 125, 117, 104, 111, + 142, 124, 143, 112, 132, 131, 133, 0, 0, 0, + 158, 175, 190, 94, 0, 163, 181, 182, 183, 184, + 185, 0, 0, 95, 107, 134, 93, 113, 155, 116, + 123, 147, 188, 139, 152, 98, 174, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 199, 0, 0, 0, 0, 140, 0, 156, 106, 114, - 82, 88, 0, 105, 132, 145, 149, 0, 0, 0, - 97, 0, 147, 136, 168, 0, 137, 146, 118, 160, - 141, 167, 200, 175, 158, 174, 83, 157, 166, 95, - 150, 85, 164, 155, 124, 110, 111, 84, 0, 144, - 100, 104, 99, 133, 161, 162, 98, 183, 89, 173, - 87, 90, 172, 131, 159, 165, 125, 122, 86, 163, - 123, 121, 113, 102, 107, 138, 120, 139, 108, 128, - 127, 129, 0, 0, 0, 154, 170, 184, 92, 0, - 0, 176, 177, 178, 179, 180, 0, 0, 93, 130, - 91, 109, 151, 112, 119, 143, 182, 135, 148, 96, - 169, 152, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, - 0, 116, 181, 142, 103, 171, + 0, 0, 0, 0, 0, 83, 0, 120, 187, 146, + 105, 176, } var yyPact = [...]int{ - 1474, -1000, -190, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 117, -1000, -184, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 862, 900, -1000, -1000, -1000, -1000, -1000, -1000, 213, - 7652, 73, 97, -15, 10389, 95, 1518, 10841, -1000, -6, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -95, -109, 659, - -1000, -1000, -1000, -1000, -1000, 855, 860, 722, 849, 790, - -1000, 5778, 50, 9252, 10163, 5055, -1000, -1000, 194, 10841, - 90, 10841, -158, 10615, 58, 58, 58, -1000, -1000, -1000, + -1000, -1000, 914, 944, -1000, -1000, -1000, -1000, -1000, -1000, + 209, 7564, 72, 87, 28, 10349, 86, 1505, 10809, -1000, + -4, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -75, -100, + -1000, 710, -1000, -1000, -1000, -1000, -1000, 908, 911, 757, + 900, 804, -1000, 6124, 60, 60, 10119, 5144, -1000, -1000, + 335, 10809, 82, 10809, -155, 10579, 57, 57, 57, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -1825,23 +1855,22 @@ 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, 94, 10841, -1000, 10841, 56, - 502, 56, 56, 56, 10841, -1000, 129, -1000, -1000, -1000, - -1000, 10841, 497, 820, 37, 3023, 3023, 3023, 3023, 4, - 3023, -93, 735, 872, -1000, -1000, -1000, -1000, -1000, 3023, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 415, 826, 6504, 6504, 862, -1000, 659, -1000, - -1000, -1000, 817, -1000, -1000, 291, 878, -1000, 7426, 123, - -1000, 6504, 1891, 423, -1000, -1000, 423, -1000, -1000, 110, - -1000, -1000, 6968, 6968, 6968, 6968, 6968, 6968, 6968, 6968, + -1000, 84, 10809, -1000, 10809, 56, 556, 56, 56, 56, + 10809, -1000, 125, -1000, -1000, -1000, -1000, 10809, 548, 856, + 63, 3080, 3080, 3080, 3080, 5, 3080, -62, 754, 923, + -1000, -1000, -1000, -1000, -1000, -1000, 3080, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 423, -1000, 6263, 423, 423, 423, - 423, 423, 423, 423, 423, 6504, 423, 423, 423, 423, - 423, 423, 423, 423, 423, 423, 423, 423, 423, 9937, - 671, 751, -1000, -1000, -1000, 846, 8342, 9026, 10841, 565, - -1000, 679, 4801, -111, -1000, -1000, -1000, 214, 8800, -1000, - -1000, -1000, 819, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 490, 864, 6617, 6617, 914, -1000, 710, -1000, -1000, -1000, + 828, -1000, -1000, 280, 933, -1000, 7334, 119, -1000, 6617, + 1686, 712, -1000, -1000, 712, -1000, -1000, 107, -1000, -1000, + 7089, 7089, 7089, 7089, 7089, 7089, 7089, 7089, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 712, -1000, 6372, 712, 712, 712, 712, 712, + 712, 712, 712, 6617, 712, 712, 712, 712, 712, 712, + 712, 712, 712, 712, 712, 712, 712, 9889, 9192, 10809, + 675, -1000, 679, 4886, -113, -1000, -1000, -1000, 215, 8962, + -1000, -1000, -1000, 855, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -1849,274 +1878,279 @@ 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, 643, 10841, -1000, - 1975, -1000, 478, 3023, 77, 661, 476, 234, 473, 10841, - 10841, 3023, 61, 10841, 844, 734, 10841, 444, 442, -1000, - 4547, -1000, 3023, 3023, 3023, 3023, 3023, 3023, 3023, 3023, - -1000, -1000, -1000, -1000, -1000, -1000, 3023, 3023, -1000, 875, - 236, -1000, -1000, 10841, 6504, -1000, -1000, -1000, -1000, -1000, - -1000, 895, 155, 391, 122, 681, -1000, 276, 855, 415, - 790, 8568, 745, -1000, -1000, 10841, -1000, 6504, 6504, 272, - -1000, 9704, -1000, -1000, 3531, 167, 6968, 315, 215, 6968, - 6968, 6968, 6968, 6968, 6968, 6968, 6968, 6968, 6968, 6968, - 6968, 6968, 6968, 6968, 345, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 438, -1000, 659, 480, 480, 139, 139, - 139, 139, 139, 139, 139, 7200, 5296, 415, 641, 312, - 6263, 5778, 5778, 6504, 6504, 11067, 11067, 5778, 850, 217, - 312, 11067, -1000, 415, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 5778, 5778, 5778, 5778, 16, 10841, -1000, 11067, 9252, - 9252, 9252, 9252, 9252, -1000, 759, 756, -1000, 772, 768, - 779, 10841, -1000, 556, 8342, 143, 423, -1000, 9478, -1000, - -1000, 16, 554, 9252, 10841, -1000, -1000, 4293, 679, -111, - 670, -1000, -136, -116, 6019, 125, -1000, -1000, -1000, -1000, - 2769, 144, 542, 309, -87, -1000, -1000, -1000, 694, -1000, - 694, 694, 694, 694, -53, -53, -53, -53, -1000, -1000, - -1000, -1000, -1000, 709, 707, -1000, 694, 694, 694, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 701, 701, 701, 695, 695, - 719, -1000, 10841, -174, 434, 3023, 843, 3023, -1000, 64, - -1000, 10841, -1000, -1000, 10841, 3023, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 591, 10809, + -1000, 1915, -1000, 540, 3080, 75, 650, 534, 251, 533, + 10809, 10809, 3080, 66, 10809, 893, 750, 10809, 509, 480, + -1000, 4628, -1000, 3080, 3080, 3080, 3080, 3080, 3080, 3080, + 3080, -1000, -1000, -1000, -1000, -1000, -1000, 3080, 3080, -1000, + 925, 293, -1000, -1000, -1000, -1000, 10809, 6617, -1000, -1000, + -1000, -1000, -1000, -1000, 939, 160, 495, 118, 704, -1000, + 425, 908, 490, 804, 8726, 764, -1000, -1000, 10809, -1000, + 6617, 6617, 466, -1000, 9652, -1000, -1000, 3596, 167, 7089, + 365, 346, 7089, 7089, 7089, 7089, 7089, 7089, 7089, 7089, + 7089, 7089, 7089, 7089, 7089, 7089, 7089, 449, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 471, -1000, 710, 1065, + 1065, 144, 144, 144, 144, 144, 144, 144, 2306, 5634, + 490, 589, 413, 6372, 6124, 6124, 6617, 6617, 11039, 11039, + 6124, 901, 229, 413, 11039, -1000, 490, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 6124, 6124, 6124, 6124, 27, 10809, + -1000, 665, 1107, -1000, -1000, -1000, 895, 8266, 8496, 27, + 632, 9192, 10809, -1000, -1000, 4370, 679, -113, 653, -1000, + -127, -131, 5389, 122, -1000, -1000, -1000, -1000, 2822, 294, + 619, 323, -67, -1000, -1000, -1000, 720, -1000, 720, 720, + 720, 720, -30, -30, -30, -30, -1000, -1000, -1000, -1000, + -1000, 734, 733, -1000, 720, 720, 720, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 10841, 242, 10841, 10841, -1000, 312, -1000, 773, 6504, - 6504, 4039, 6504, -1000, -1000, -1000, 826, -1000, 850, 863, - -1000, 810, 808, 5778, -1000, -1000, 167, 181, -1000, -1000, - 264, -1000, -1000, -1000, -1000, 121, 423, -1000, 1992, -1000, - -1000, -1000, -1000, 315, 6968, 6968, 6968, 322, 1992, 2108, - 1254, 1929, 139, 405, 405, 158, 158, 158, 158, 158, - 295, 295, -1000, -1000, -1000, 415, -1000, -1000, -1000, 415, - 5778, 678, -1000, -1000, 6504, -1000, 415, 541, 541, 355, - 240, 713, -1000, 118, 712, 541, 5778, 237, -1000, 6504, - 415, -1000, 541, 415, 541, 541, 673, 423, -1000, 699, - -1000, 210, 751, 725, 732, 580, -1000, -1000, -1000, -1000, - 748, -1000, 747, -1000, -1000, -1000, -1000, -1000, 88, 83, - 82, 10615, -1000, 869, 9252, 682, -1000, -1000, 670, -111, - -139, -1000, -1000, -1000, 312, -1000, 376, 663, 2515, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 698, 421, -1000, 834, - 171, 160, 393, 833, -1000, -1000, -1000, 825, -1000, 252, - -91, -1000, -1000, 371, -53, -53, -1000, -1000, 125, 816, - 125, 125, 125, 406, 406, -1000, -1000, -1000, -1000, 351, - -1000, -1000, -1000, 346, -1000, 730, 10615, 3023, -1000, 3785, - -1000, -1000, -1000, -1000, -1000, -1000, 231, 208, 175, -1000, + -1000, -1000, -1000, 730, 730, 730, 723, 723, 708, -1000, + 10809, -174, 469, 3080, 880, 3080, -1000, 1225, -1000, 10809, + -1000, -1000, 10809, 3080, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 10809, + 199, 10809, 10809, -1000, 413, -1000, 793, 6617, 6617, 4112, + 6617, -1000, -1000, -1000, 864, -1000, 901, 912, -1000, 825, + 824, 6124, -1000, -1000, 167, 254, -1000, -1000, 424, -1000, + -1000, -1000, -1000, 116, 712, -1000, 1808, -1000, -1000, -1000, + -1000, 365, 7089, 7089, 7089, 146, 1808, 1793, 641, 1866, + 144, 363, 363, 165, 165, 165, 165, 165, 237, 237, + -1000, -1000, -1000, 490, -1000, -1000, -1000, 490, 6124, 666, + -1000, -1000, 6617, -1000, 490, 578, 578, 418, 411, 707, + -1000, 114, 694, 578, 6124, 272, -1000, 6617, 490, -1000, + 578, 490, 578, 578, 642, 712, -1000, 11039, 9192, 9192, + 9192, 9192, 9192, -1000, 780, 774, -1000, 783, 768, 827, + 10809, -1000, 580, 8266, 140, 712, -1000, 9422, -1000, -1000, + 922, 9192, 657, -1000, -1000, 653, -113, -120, -1000, -1000, + -1000, -1000, 413, -1000, 452, 652, 2564, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 725, 455, -1000, 872, 170, 197, + 453, 871, -1000, -1000, -1000, 862, -1000, 261, -69, -1000, + -1000, 391, -30, -30, -1000, -1000, 122, 847, 122, 122, + 122, 442, 442, -1000, -1000, -1000, -1000, 380, -1000, -1000, + -1000, 361, -1000, 748, 10579, 3080, -1000, 3854, -1000, -1000, + -1000, -1000, -1000, -1000, 1326, 781, 174, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 26, -1000, + 3080, -1000, 293, -1000, 429, 6617, -1000, -1000, 787, 413, + 413, 112, -1000, -1000, 10809, -1000, -1000, -1000, -1000, 677, + -1000, -1000, -1000, 3338, 6124, -1000, 146, 1808, 1726, -1000, + 7089, 7089, -1000, -1000, 578, 6124, 413, -1000, -1000, -1000, + 535, 449, 535, 7089, 7089, 4112, 7089, 7089, -166, 676, + 224, -1000, 6617, 355, -1000, -1000, -1000, -1000, -1000, 747, + 11039, 712, -1000, 8030, 10579, 659, -1000, 205, 1107, 729, + 746, 1207, -1000, -1000, -1000, -1000, 772, -1000, 771, -1000, + -1000, -1000, -1000, -1000, 81, 80, 79, 10579, -1000, 914, + 6617, 657, -1000, -1000, -1000, -137, -136, -1000, -1000, -1000, + 2822, -1000, 2822, 10579, 41, -1000, 453, 453, -1000, -1000, + -1000, 724, 745, 38, -1000, -1000, -1000, 611, 122, 122, + -1000, 198, -1000, -1000, -1000, 576, -1000, 562, 651, 552, + 10809, -1000, -1000, 649, -1000, 188, -1000, -1000, 10579, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 15, -1000, 3023, -1000, 236, -1000, 402, 6504, -1000, -1000, - 798, 312, 312, 116, -1000, -1000, 10841, -1000, -1000, -1000, - -1000, 677, -1000, -1000, -1000, 3277, 5778, -1000, 322, 1992, - 1970, -1000, 6968, 6968, -1000, -1000, 541, 5778, 312, -1000, - -1000, -1000, 49, 345, 49, 6968, 6968, 4039, 6968, 6968, - -168, 685, 223, -1000, 6504, 422, -1000, -1000, -1000, -1000, - -1000, 729, 11067, 423, -1000, 8110, 10615, 862, 11067, 6504, - 6504, -1000, -1000, 6504, 697, -1000, 6504, -1000, -1000, -1000, - 423, 423, 423, 517, -1000, 862, 682, -1000, -1000, -1000, - -140, -134, -1000, -1000, -1000, 2769, -1000, 2769, 10615, 38, - -1000, 393, 393, -1000, -1000, -1000, 696, 728, 42, -1000, - -1000, -1000, 531, 125, 125, -1000, 185, -1000, -1000, -1000, - 534, -1000, 530, 660, 523, 10841, -1000, -1000, 657, -1000, - 204, -1000, -1000, 10615, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 10615, 10841, -1000, -1000, - -1000, -1000, -1000, 10615, -1000, 242, -1000, 312, -1000, 3785, - -1000, 869, 9252, -1000, -1000, 415, -1000, 6968, 1992, 1992, - -1000, -1000, 415, 694, 694, -1000, 694, 695, -1000, 694, - -21, 694, -22, 415, 415, 1461, 1851, -1000, 426, 1719, - 423, -165, -1000, 312, 6504, -1000, 836, 561, 576, -1000, - -1000, 5537, 415, 519, 114, 517, 855, -1000, 312, 312, - 312, 10615, 312, 10615, 10615, 10615, 7878, 10615, 855, -1000, - -1000, -1000, -1000, 2515, -1000, 515, -1000, 694, -1000, -1000, - -1000, 10615, -82, 894, -1000, -1000, -1000, -1000, 692, -1000, - -1000, -1000, -1000, -1000, -1000, -53, 390, -53, 328, -1000, - 321, 3023, 3785, 2769, -1000, 684, -1000, -1000, -1000, -1000, - 838, -1000, 866, 655, -1000, 1992, -1000, -1000, 72, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 6968, 6968, - -1000, 6968, 6968, 6968, 415, 389, 312, 832, -1000, 423, - -1000, -1000, 675, 10615, 10615, -1000, -1000, 510, -1000, 495, - 495, 495, 143, -1000, -1000, 120, 10615, -1000, 489, 148, - -1000, -148, 507, 125, -1000, 125, 505, 496, -1000, -1000, - -1000, 10615, 423, 864, 859, -1000, -1000, 1698, 1698, 1698, - 1698, 43, -1000, -1000, 890, -1000, 423, -1000, 659, 108, - -1000, 10615, -1000, -1000, -1000, -1000, -1000, 120, -1000, 348, - 182, 380, -1000, 28, 255, 830, -1000, 828, 676, -1000, - -1000, -1000, -1000, -1000, 460, 14, -1000, 6504, 6504, -1000, - -1000, -1000, -1000, 415, 34, -178, 11067, 576, 415, 10615, - -1000, -1000, -1000, 318, -1000, -1000, 10841, -1000, 378, -1000, - -1000, 481, 661, 420, -1000, 10615, 312, 572, -1000, 797, - -172, -181, 545, -1000, -1000, -1000, 581, -1000, -1000, -174, - -1000, 14, 806, -1000, 789, -1000, 10615, -1000, -1000, 8, - -175, 414, 5, -179, 727, 423, -182, 714, -1000, 892, - 6736, -1000, -1000, 886, 147, 147, 1698, 415, -1000, -1000, - -1000, 45, 317, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 10579, 10809, -1000, -1000, -1000, -1000, -1000, 10579, -1000, + 199, -1000, 413, -1000, 3854, -1000, 922, 9192, -1000, -1000, + 490, -1000, 7089, 1808, 1808, -1000, -1000, 490, 720, 720, + -1000, 720, 723, -1000, 720, -13, 720, -14, 490, 490, + 1614, 1073, -1000, 1411, 313, 712, -163, -1000, 413, 6617, + -1000, 875, 629, 643, -1000, -1000, 5879, 490, 547, 111, + 539, -1000, 914, 11039, 6617, -1000, -1000, 6617, 722, -1000, + 6617, -1000, -1000, -1000, 712, 712, 712, 539, 908, 413, + -1000, -1000, -1000, -1000, 2564, -1000, 530, -1000, 720, -1000, + -1000, -1000, 10579, -54, 937, -1000, -1000, -1000, -1000, 716, + -1000, -1000, -1000, -1000, -1000, -1000, -30, 428, -30, 333, + -1000, 319, 3080, 3854, 2822, -1000, 715, -1000, -1000, -1000, + -1000, 866, -1000, 920, 646, -1000, 1808, -1000, -1000, 99, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 7089, + 7089, -1000, 7089, 7089, 7089, 490, 421, 413, 870, -1000, + 712, -1000, -1000, 648, 10579, 10579, -1000, 10579, 908, -1000, + 413, 413, 10579, 413, 10579, 10579, 10579, 7794, -1000, 128, + 10579, -1000, 523, -1000, 155, -1000, -145, 596, 122, -1000, + 122, 595, 566, -1000, -1000, -1000, 10579, 712, 916, 910, + -1000, -1000, 1538, 1538, 1538, 1538, 36, -1000, -1000, 936, + -1000, 712, -1000, 710, 104, -1000, -1000, -1000, 519, 517, + 517, 517, 140, 128, -1000, 415, 176, 416, -1000, 40, + 10579, 276, 868, -1000, 865, 714, -1000, -1000, -1000, -1000, + -1000, 489, 19, -1000, 6617, 6617, -1000, -1000, -1000, -1000, + 490, 39, -177, 11039, 643, 490, 10579, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 289, -1000, -1000, 10809, -1000, -1000, + 336, -1000, -1000, 531, 650, 487, -1000, 10579, 413, 639, + -1000, 785, -171, -180, 634, -1000, -1000, -1000, 713, -1000, + -1000, -174, -1000, 19, 803, -1000, 784, -1000, 10579, -1000, + -1000, 15, -175, 468, 12, -178, 744, 712, -181, 742, + -1000, 930, 6853, -1000, -1000, 932, 192, 192, 1538, 490, + -1000, -1000, -1000, 47, 410, -1000, -1000, -1000, -1000, -1000, + -1000, } var yyPgo = [...]int{ - 0, 1133, 50, 473, 1123, 1121, 1120, 1119, 1117, 1116, - 1114, 1113, 1112, 1111, 1110, 1109, 1108, 1106, 1105, 1104, - 1102, 1101, 1095, 1094, 125, 1090, 1087, 1084, 60, 1083, - 58, 1080, 1079, 36, 260, 44, 34, 116, 1078, 26, - 97, 111, 1077, 46, 1076, 1075, 68, 1074, 73, 1072, - 1071, 243, 1069, 1068, 13, 17, 1067, 1066, 1065, 1063, - 56, 921, 1062, 1061, 1060, 1059, 1056, 1054, 48, 3, - 11, 9, 15, 1053, 883, 112, 1052, 45, 1051, 1048, - 1046, 1045, 59, 1043, 49, 1042, 20, 47, 1032, 6, - 57, 33, 21, 7, 67, 52, 1023, 28, 55, 43, - 1022, 1020, 389, 1018, 1017, 37, 1016, 22, 132, 436, - 1015, 1013, 1012, 1011, 29, 0, 536, 963, 62, 1005, - 1002, 1001, 1336, 63, 61, 18, 1000, 123, 30, 32, - 988, 985, 42, 979, 974, 973, 972, 971, 969, 968, - 126, 961, 960, 959, 133, 25, 958, 956, 54, 19, - 955, 954, 951, 39, 53, 942, 940, 41, 27, 939, - 935, 934, 926, 924, 24, 16, 923, 12, 922, 10, - 920, 23, 919, 2, 917, 14, 915, 8, 912, 4, - 40, 1, 911, 5, 910, 909, 349, 171, 908, 907, - 71, + 0, 1241, 44, 481, 1239, 1236, 1235, 1227, 1226, 1211, + 1210, 1209, 1207, 1203, 1201, 1200, 1199, 1197, 1195, 1194, + 1190, 1185, 1184, 1183, 1182, 146, 1181, 1162, 1161, 59, + 1160, 77, 1158, 1148, 41, 122, 86, 43, 894, 1146, + 27, 71, 89, 1145, 33, 1144, 1142, 78, 1141, 55, + 1136, 1122, 281, 1121, 1120, 10, 23, 1119, 1116, 1115, + 1113, 70, 38, 1112, 1110, 1109, 1108, 1106, 1094, 53, + 7, 9, 22, 18, 1091, 28, 17, 1089, 52, 1086, + 1085, 1084, 1083, 26, 1082, 56, 1081, 11, 51, 1079, + 30, 60, 31, 15, 6, 66, 65, 1078, 16, 69, + 49, 1077, 1076, 381, 1063, 1062, 40, 1061, 1058, 19, + 189, 453, 1054, 1051, 1050, 1049, 75, 0, 538, 479, + 64, 1047, 1042, 1041, 1366, 73, 48, 12, 1040, 63, + 169, 35, 1038, 1035, 37, 1034, 1032, 1030, 1028, 1027, + 1024, 1022, 20, 1020, 1018, 1017, 34, 47, 1014, 1013, + 54, 21, 1012, 1010, 1009, 46, 58, 1002, 1000, 50, + 29, 991, 990, 975, 974, 972, 25, 57, 966, 13, + 963, 8, 961, 24, 960, 3, 959, 14, 958, 4, + 957, 5, 42, 1, 956, 2, 955, 953, 61, 290, + 952, 950, 92, } var yyR1 = [...]int{ - 0, 184, 185, 185, 1, 1, 1, 1, 1, 1, + 0, 186, 187, 187, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 6, 3, 4, 4, - 5, 5, 7, 7, 27, 27, 8, 9, 9, 9, - 188, 188, 46, 46, 90, 90, 10, 10, 10, 10, - 95, 95, 99, 99, 99, 100, 100, 100, 100, 130, - 130, 11, 11, 11, 11, 11, 11, 11, 11, 179, - 179, 178, 177, 177, 176, 176, 175, 16, 160, 162, - 162, 161, 161, 161, 161, 154, 133, 133, 133, 133, - 136, 136, 134, 134, 134, 134, 134, 134, 134, 135, - 135, 135, 135, 135, 137, 137, 137, 137, 137, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, - 139, 139, 153, 153, 140, 140, 148, 148, 149, 149, - 149, 146, 146, 147, 147, 150, 150, 150, 141, 141, - 141, 141, 141, 141, 141, 141, 143, 143, 143, 151, - 151, 144, 144, 144, 145, 145, 145, 152, 152, 152, - 152, 152, 142, 142, 155, 155, 170, 170, 169, 169, - 169, 159, 159, 166, 166, 166, 166, 166, 157, 157, - 158, 158, 168, 168, 167, 156, 156, 171, 171, 171, - 171, 182, 183, 181, 181, 181, 181, 181, 163, 163, - 163, 164, 164, 164, 165, 165, 165, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 180, 180, 180, 180, - 180, 180, 180, 180, 180, 180, 180, 174, 172, 172, - 173, 173, 13, 14, 14, 14, 14, 14, 15, 15, - 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 106, 106, - 104, 104, 105, 105, 105, 107, 107, 107, 131, 131, - 131, 19, 19, 21, 21, 22, 23, 20, 20, 20, - 20, 20, 20, 20, 189, 24, 25, 25, 26, 26, - 26, 30, 30, 30, 28, 28, 29, 29, 35, 35, - 34, 34, 36, 36, 36, 36, 119, 119, 119, 118, - 118, 38, 38, 39, 39, 40, 40, 41, 41, 41, - 53, 53, 89, 89, 91, 91, 42, 42, 42, 42, - 43, 43, 44, 44, 45, 45, 126, 126, 125, 125, - 125, 124, 124, 47, 47, 47, 49, 48, 48, 48, - 48, 50, 50, 52, 52, 51, 51, 54, 54, 54, - 54, 55, 55, 37, 37, 37, 37, 37, 37, 37, - 103, 103, 57, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 67, 67, 67, 67, 67, 67, - 58, 58, 58, 58, 58, 58, 58, 33, 33, 68, - 68, 68, 74, 69, 69, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 65, 65, 65, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, - 64, 64, 64, 190, 190, 66, 66, 66, 66, 31, - 31, 31, 31, 31, 129, 129, 132, 132, 132, 132, - 132, 132, 132, 132, 132, 132, 132, 132, 132, 78, - 78, 32, 32, 76, 76, 77, 79, 79, 75, 75, - 75, 60, 60, 60, 60, 60, 60, 60, 60, 62, - 62, 62, 80, 80, 81, 81, 82, 82, 83, 83, - 84, 85, 85, 85, 86, 86, 86, 86, 87, 87, - 87, 59, 59, 59, 59, 59, 59, 88, 88, 88, - 88, 92, 92, 70, 70, 72, 72, 71, 73, 93, - 93, 97, 94, 94, 98, 98, 98, 96, 96, 96, - 121, 121, 121, 101, 101, 108, 108, 109, 109, 102, - 102, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 111, 111, 111, 112, 112, 113, 113, 113, 120, - 120, 116, 116, 117, 117, 122, 122, 123, 123, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 186, 187, - 127, 128, 128, 128, + 1, 1, 1, 1, 2, 2, 2, 6, 3, 4, + 4, 5, 5, 7, 7, 28, 28, 8, 9, 9, + 9, 190, 190, 47, 47, 91, 91, 10, 10, 10, + 10, 96, 96, 100, 100, 100, 101, 101, 101, 101, + 132, 132, 11, 11, 11, 11, 11, 11, 11, 11, + 181, 181, 180, 179, 179, 178, 178, 177, 17, 162, + 164, 164, 163, 163, 163, 163, 156, 135, 135, 135, + 135, 138, 138, 136, 136, 136, 136, 136, 136, 136, + 137, 137, 137, 137, 137, 139, 139, 139, 139, 139, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, + 141, 141, 141, 155, 155, 142, 142, 150, 150, 151, + 151, 151, 148, 148, 149, 149, 152, 152, 152, 143, + 143, 143, 143, 143, 143, 143, 143, 145, 145, 145, + 153, 153, 146, 146, 146, 147, 147, 147, 154, 154, + 154, 154, 154, 144, 144, 157, 157, 172, 172, 171, + 171, 171, 161, 161, 168, 168, 168, 168, 168, 159, + 159, 160, 160, 170, 170, 169, 158, 158, 173, 173, + 173, 173, 184, 185, 183, 183, 183, 183, 183, 165, + 165, 165, 166, 166, 166, 167, 167, 167, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 176, 174, + 174, 175, 175, 13, 14, 14, 14, 14, 14, 15, + 15, 18, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 107, 107, 105, 105, 108, 108, 106, 106, 106, 109, + 109, 109, 133, 133, 133, 20, 20, 22, 22, 23, + 24, 21, 21, 21, 21, 21, 21, 21, 16, 191, + 25, 26, 26, 27, 27, 27, 31, 31, 31, 29, + 29, 30, 30, 36, 36, 35, 35, 37, 37, 37, + 37, 121, 121, 121, 120, 120, 39, 39, 40, 40, + 41, 41, 42, 42, 42, 42, 54, 54, 90, 90, + 92, 92, 43, 43, 43, 43, 44, 44, 45, 45, + 46, 46, 128, 128, 127, 127, 127, 126, 126, 48, + 48, 48, 50, 49, 49, 49, 49, 51, 51, 53, + 53, 52, 52, 55, 55, 55, 55, 56, 56, 38, + 38, 38, 38, 38, 38, 38, 104, 104, 58, 58, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 68, 68, 68, 68, 68, 68, 59, 59, 59, 59, + 59, 59, 59, 34, 34, 69, 69, 69, 75, 70, + 70, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 66, 66, 66, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 65, 65, 65, 65, 65, 65, 65, 65, 192, + 192, 67, 67, 67, 67, 32, 32, 32, 32, 32, + 131, 131, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 79, 79, 33, 33, 77, + 77, 78, 80, 80, 76, 76, 76, 61, 61, 61, + 61, 61, 61, 61, 61, 63, 63, 63, 81, 81, + 82, 82, 83, 83, 84, 84, 85, 86, 86, 86, + 87, 87, 87, 87, 88, 88, 88, 60, 60, 60, + 60, 60, 60, 89, 89, 89, 89, 93, 93, 71, + 71, 73, 73, 72, 74, 94, 94, 98, 95, 95, + 99, 99, 99, 99, 97, 97, 97, 123, 123, 123, + 102, 102, 110, 110, 111, 111, 103, 103, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, + 113, 114, 114, 115, 115, 115, 122, 122, 118, 118, + 119, 119, 124, 124, 125, 125, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 188, + 189, 129, 130, 130, 130, } var yyR2 = [...]int{ 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 4, 6, 7, 5, 10, 1, 3, - 1, 3, 7, 8, 1, 1, 8, 8, 7, 6, - 1, 1, 1, 3, 0, 4, 3, 4, 5, 4, - 1, 3, 3, 2, 2, 2, 2, 2, 1, 1, - 1, 2, 2, 8, 4, 6, 5, 5, 5, 0, - 2, 1, 0, 2, 1, 3, 3, 4, 4, 2, - 4, 1, 3, 3, 3, 8, 3, 1, 1, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 1, 2, 2, 2, 1, 4, - 4, 2, 2, 3, 3, 3, 3, 1, 1, 1, - 1, 1, 6, 6, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 0, 3, 0, 5, 0, 3, - 5, 0, 1, 0, 1, 0, 1, 2, 0, 2, - 2, 2, 2, 2, 4, 2, 0, 3, 5, 0, - 1, 0, 3, 3, 0, 2, 2, 0, 2, 1, - 2, 1, 0, 2, 5, 4, 1, 2, 2, 3, - 2, 0, 1, 2, 3, 3, 2, 2, 1, 1, - 0, 1, 1, 3, 2, 3, 1, 10, 11, 11, - 12, 3, 3, 1, 1, 2, 2, 2, 0, 1, - 3, 1, 2, 3, 1, 1, 1, 6, 7, 7, - 12, 7, 7, 7, 4, 5, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 7, 1, 3, - 8, 8, 5, 4, 6, 5, 4, 4, 3, 2, - 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, - 3, 3, 3, 4, 3, 7, 5, 4, 2, 2, - 4, 4, 2, 2, 2, 2, 2, 3, 1, 1, - 0, 1, 0, 2, 2, 0, 2, 2, 0, 1, - 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, - 2, 2, 3, 3, 0, 2, 0, 2, 1, 2, - 2, 0, 1, 1, 0, 1, 0, 1, 0, 1, - 1, 3, 1, 2, 3, 5, 0, 1, 2, 1, - 1, 0, 2, 1, 3, 1, 1, 1, 3, 3, - 3, 7, 1, 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, 0, 5, 5, - 5, 0, 2, 1, 3, 3, 2, 3, 1, 2, - 0, 3, 1, 1, 3, 3, 4, 4, 5, 3, - 4, 5, 6, 2, 1, 2, 1, 2, 1, 2, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, - 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 4, 6, 7, 5, 10, 1, + 3, 1, 3, 7, 8, 1, 1, 9, 8, 7, + 6, 1, 1, 1, 3, 0, 4, 3, 4, 5, + 4, 1, 3, 3, 2, 2, 2, 2, 2, 1, + 1, 1, 2, 2, 8, 4, 6, 5, 5, 5, + 0, 2, 1, 0, 2, 1, 3, 3, 4, 4, + 2, 4, 1, 3, 3, 3, 8, 3, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, + 4, 4, 2, 2, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 6, 6, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 0, 3, 0, 5, 0, + 3, 5, 0, 1, 0, 1, 0, 1, 2, 0, + 2, 2, 2, 2, 2, 4, 2, 0, 3, 5, + 0, 1, 0, 3, 3, 0, 2, 2, 0, 2, + 1, 2, 1, 0, 2, 5, 4, 1, 2, 2, + 3, 2, 0, 1, 2, 3, 3, 2, 2, 1, + 1, 0, 1, 1, 3, 2, 3, 1, 10, 11, + 11, 12, 3, 3, 1, 1, 2, 2, 2, 0, + 1, 3, 1, 2, 3, 1, 1, 1, 6, 7, + 7, 12, 7, 7, 7, 4, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 7, 1, + 3, 8, 8, 5, 4, 6, 5, 4, 4, 3, + 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 4, 3, 7, 5, 4, 2, + 2, 4, 4, 2, 2, 2, 2, 2, 2, 3, + 1, 1, 0, 1, 1, 1, 0, 2, 2, 0, + 2, 2, 0, 1, 1, 2, 1, 1, 2, 1, + 1, 2, 2, 2, 2, 2, 3, 3, 2, 0, + 2, 0, 2, 1, 2, 2, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 1, 3, 1, 2, 3, + 5, 0, 1, 2, 1, 1, 0, 2, 1, 3, + 1, 1, 1, 3, 1, 3, 3, 7, 1, 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, 0, 5, 5, 5, 0, 2, 1, + 3, 3, 2, 3, 1, 2, 0, 3, 1, 1, + 3, 3, 4, 4, 5, 3, 4, 5, 6, 2, + 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 1, 1, 1, 3, 1, + 3, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, - 2, 2, 3, 1, 1, 1, 1, 4, 5, 6, - 4, 4, 6, 6, 6, 6, 8, 8, 6, 8, - 8, 9, 7, 5, 4, 2, 2, 2, 2, 2, - 2, 2, 2, 0, 2, 4, 4, 4, 4, 0, - 3, 4, 7, 3, 1, 1, 2, 3, 3, 1, - 2, 2, 1, 2, 1, 2, 2, 1, 2, 0, - 1, 0, 2, 1, 2, 4, 0, 2, 1, 3, - 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 0, 3, 0, 2, 0, 3, 1, 3, - 2, 0, 1, 1, 0, 2, 4, 4, 0, 2, - 4, 2, 1, 3, 5, 4, 6, 1, 3, 3, - 5, 0, 5, 1, 3, 1, 2, 3, 1, 1, - 3, 3, 1, 3, 3, 3, 3, 1, 2, 1, - 1, 1, 1, 1, 1, 0, 2, 0, 3, 0, + 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, + 1, 1, 1, 4, 5, 6, 4, 4, 6, 6, + 6, 6, 8, 8, 6, 8, 8, 9, 7, 5, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 4, 4, 4, 4, 0, 3, 4, 7, 3, + 1, 1, 2, 3, 3, 1, 2, 2, 1, 2, + 1, 2, 2, 1, 2, 0, 1, 0, 2, 1, + 2, 4, 0, 2, 1, 3, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 0, 3, + 0, 2, 0, 3, 1, 3, 2, 0, 1, 1, + 0, 2, 4, 4, 0, 2, 4, 2, 1, 3, + 5, 4, 6, 1, 3, 3, 5, 0, 5, 1, + 3, 1, 2, 3, 1, 1, 3, 3, 1, 3, + 3, 3, 3, 3, 1, 2, 1, 1, 1, 1, + 1, 1, 0, 2, 0, 3, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 0, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 1, 1, 1, 0, 1, 1, 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, 1, @@ -2137,301 +2171,305 @@ 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, - 0, 0, 1, 1, + 1, 0, 0, 1, 1, } var yyChk = [...]int{ - -1000, -184, -1, -2, -6, -7, -8, -9, -10, -11, - -12, -13, -14, -15, -17, -18, -19, -21, -22, -23, - -20, -3, -4, 6, 7, -27, 9, 10, 30, -16, - 114, 115, 117, 116, 147, 118, 140, 50, 159, 160, - 162, 163, 25, 141, 142, 145, 146, 31, 32, -186, - 8, 244, 54, -185, 259, -82, 15, -26, 5, -24, - -189, -24, -24, -24, -24, -24, -160, -162, 54, 89, - -113, 123, 71, 155, 236, 120, 121, 127, -116, 57, - -115, 252, 133, 159, 170, 164, 191, 183, 134, 181, - 184, 223, 211, 221, 66, 162, 232, 143, 179, 175, - 173, 27, 196, 257, 174, 136, 131, 197, 201, 224, - 168, 169, 226, 195, 132, 33, 254, 35, 151, 227, - 199, 194, 190, 193, 167, 189, 39, 203, 202, 204, - 222, 186, 137, 176, 18, 230, 146, 149, 198, 200, - 128, 153, 256, 228, 172, 138, 150, 145, 231, 139, - 163, 225, 234, 38, 208, 166, 130, 160, 157, 187, - 152, 177, 178, 192, 165, 188, 161, 154, 147, 233, - 209, 258, 185, 182, 158, 156, 214, 215, 216, 217, - 218, 255, 229, 180, 210, -102, 123, 125, 121, 121, - 122, 123, 236, 120, 121, -51, -122, 57, -115, 123, - 155, 121, 107, 184, 114, 212, 122, 33, 153, -131, - 121, -104, 156, 211, 214, 215, 216, 218, 217, 57, - 225, 224, 219, -122, 161, -127, -127, -127, -127, -127, - 213, 213, -2, -86, 17, 16, -5, -3, -186, 6, - 20, 21, -30, 40, 41, -25, -36, 98, -37, -122, - -56, 73, -61, 29, 57, -115, 23, -60, -57, -75, - -73, -74, 107, 108, 109, 96, 97, 104, 74, 110, - -65, -63, -64, -66, 59, 58, 67, 60, 61, 62, - 63, 68, 69, 70, -116, -71, -186, 44, 45, 245, - 246, 247, 248, 251, 249, 76, 34, 235, 243, 242, - 241, 239, 240, 237, 238, 126, 236, 102, 244, -102, - -39, -40, -41, -42, -53, -74, -186, -51, 11, -46, - -51, -94, -130, 161, -98, 225, 224, -117, -96, -116, - -114, 223, 184, 222, 119, 72, 22, 24, 206, 75, - 107, 16, 76, 106, 245, 114, 48, 237, 238, 235, - 247, 248, 236, 212, 29, 10, 25, 141, 21, 100, - 116, 79, 80, 144, 23, 142, 70, 19, 51, 11, - 13, 14, 126, 125, 91, 122, 46, 8, 110, 26, - 88, 42, 28, 44, 89, 17, 239, 240, 31, 251, - 148, 102, 49, 36, 73, 68, 52, 71, 15, 47, - 90, 117, 244, 45, 120, 6, 250, 30, 140, 43, - 121, 213, 78, 124, 69, 5, 127, 32, 9, 50, - 53, 241, 242, 243, 34, 77, 12, -161, 89, -154, - 57, -51, 122, -51, 244, -116, -109, 126, -109, -109, - 121, -51, -51, -108, 126, 57, -108, -108, -108, -51, - 111, -51, 57, 30, 236, 57, 153, 121, 154, 123, - -128, -186, -117, -128, -128, -128, 157, 158, -128, 221, - -106, 213, 220, 52, 12, -128, -127, -127, -187, 56, - -87, 19, 31, -37, -122, -83, -84, -37, -82, -2, - -24, 36, -28, 21, 65, 11, -119, 72, 71, 88, - -118, 22, -116, 59, 111, -37, -58, 91, 73, 89, - 90, 75, 93, 92, 103, 96, 97, 98, 99, 100, - 101, 102, 94, 95, 106, 81, 82, 83, 84, 85, - 86, 87, -103, -186, -74, -186, 112, 113, -61, -61, - -61, -61, -61, -61, -61, -61, -186, -2, -69, -37, - -186, -186, -186, -186, -186, -186, -186, -186, -186, -78, - -37, -186, -190, -186, -190, -190, -190, -190, -190, -190, - -190, -186, -186, -186, -186, -52, 26, -51, 30, 55, - -47, -49, -48, -50, 42, 46, 48, 43, 44, 45, - 49, -126, 22, -39, -186, -125, 149, -124, 22, -122, - 59, -51, -46, -188, 55, 11, 53, 55, -94, 161, - -95, -99, 226, 228, 81, -121, -116, 59, 29, 30, - 56, 55, -51, -133, -136, -138, -137, -139, -134, -135, - 181, 182, 107, 185, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 30, 143, 177, 178, 179, 180, - 197, 198, 199, 200, 201, 202, 203, 204, 164, 165, - 166, 167, 168, 169, 170, 172, 173, 174, 175, 176, - 57, -128, 123, -179, 53, 57, 73, 57, -51, -51, - -128, 124, -51, 23, 52, -51, 57, 57, -123, -122, - -114, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, 11, -105, 11, 91, -51, -37, 9, 91, 55, - 18, 111, 55, -85, 24, 25, -86, -187, -30, -62, - -116, 60, 63, -29, 43, -51, -37, -37, -67, 68, - 73, 69, 70, -118, 98, -123, -117, -114, -61, -68, - -71, -74, 64, 91, 89, 90, 75, -61, -61, -61, - -61, -61, -61, -61, -61, -61, -61, -61, -61, -61, - -61, -61, -129, 57, 59, 57, -60, -60, -116, -35, - 21, -34, -36, -187, 55, -187, -2, -34, -34, -37, - -37, -75, -116, -122, -75, -34, -28, -76, -77, 77, - -75, -187, -34, -35, -34, -34, -90, 149, -51, -93, - -97, -75, -40, -41, -41, -40, -41, 42, 42, 42, - 47, 42, 47, 42, -48, -122, -187, -54, 50, 125, - 51, -186, -124, -90, 53, -39, -51, -98, -95, 55, - 227, 229, 230, 52, -37, -145, 106, -163, -164, -165, - -117, 59, 60, -154, -155, -156, -166, 135, -171, 128, - 130, 127, -157, 136, 122, 28, 56, -150, 68, 73, - -146, 209, -140, 54, -140, -140, -140, -140, -144, 184, - -144, -144, -144, 54, 54, -140, -140, -140, -148, 54, - -148, -148, -149, 54, -149, -120, 53, -51, -177, 255, - -178, 57, -128, 23, -128, -110, 119, 116, 117, -174, - 115, 206, 184, 66, 29, 15, 245, 149, 258, 57, - 150, -51, -51, -128, -51, -107, 89, 12, -122, -122, - 38, -37, -37, -123, -84, -87, -101, 19, 11, 34, - 34, -34, 68, 69, 70, 111, -186, -68, -61, -61, - -61, -33, 144, 72, -187, -187, -34, 55, -37, -187, - -187, -187, 55, 53, 22, 55, 11, 111, 55, 11, - -187, -34, -79, -77, 79, -37, -187, -187, -187, -187, - -187, -59, 30, 34, -2, -186, -186, -55, 55, 12, - 81, -44, -43, 52, 53, -45, 52, -43, 42, 42, - 122, 122, 122, -91, -116, -55, -39, -55, -99, -100, - 231, 228, 234, 57, 59, 55, -165, 81, 54, 57, - 28, -157, -157, -158, 57, -158, 28, -141, 29, 68, - -147, 210, 60, -144, -144, -145, 30, -145, -145, -145, - -153, 59, -153, 60, 60, 52, -116, -128, -176, -175, - -117, -127, -180, 155, 129, 135, 136, 131, 57, 122, - 28, 128, 130, 149, 127, -180, 155, -111, -112, 124, - 22, 122, 28, 149, -128, -105, 59, -37, 39, 111, - -51, -38, 11, 98, -117, -35, -33, 72, -61, -61, - -187, -36, -132, 107, 181, 143, 179, 175, 195, 186, - 208, 177, 209, -129, -132, -61, -61, -117, -61, -61, - 252, -82, 80, -37, 78, -92, 52, -93, -70, -72, - -71, -186, -2, -88, -116, -91, -82, -97, -37, -37, - -37, 54, -37, -186, -186, -186, -187, 55, -82, -55, - 228, 232, 233, -164, -165, -168, -167, -116, -171, -158, - -158, 54, -143, 52, 59, 60, 61, 68, 235, 67, - 56, -145, -145, 57, 107, 56, 55, 56, 55, 56, - 55, -51, 55, 81, -127, -116, -127, -116, -51, -127, - -116, -107, -55, -39, -187, -61, -187, -140, -140, -140, - -149, -140, 169, -140, 169, -187, -187, -187, 55, 19, - -187, 55, 19, -186, -32, 250, -37, 27, -92, 55, - -187, -187, -187, 55, 111, -187, -86, -89, -116, -89, - -89, -89, -125, -116, -86, 56, 55, -140, -89, -151, - 206, 9, 54, -144, 59, -144, 60, 60, -128, -175, - -165, 54, 26, -80, 13, -144, 57, -61, -61, -61, - -61, -61, -187, 59, 28, -72, 34, -2, -186, -116, - -116, 55, 56, -187, -187, -187, -54, -170, -169, 53, - 132, 66, -167, 56, -152, 128, 28, 127, 235, 56, - -145, -145, 56, 56, -89, -186, -81, 14, 16, -187, - -187, -187, -187, -31, 91, 255, 9, -70, -2, 111, - -116, -169, 57, -159, 81, 59, 138, -142, 66, 28, - 28, 54, 56, -172, -173, 149, -37, -69, -187, 253, - 49, 256, -93, -187, -116, 60, -51, 59, 56, -179, - -187, 55, -116, 39, 254, 257, 54, -177, -173, 34, - 39, -89, 151, 255, 56, 152, 256, -182, -183, 52, - -186, 257, -183, 52, 10, 9, -61, 148, -181, 139, - 134, 137, 30, -181, -187, -187, 133, 29, 68, + -1000, -186, -1, -2, -6, -7, -8, -9, -10, -11, + -12, -13, -14, -15, -18, -19, -20, -22, -23, -24, + -21, -16, -3, -4, 6, 7, -28, 9, 10, 30, + -17, 115, 116, 118, 117, 149, 119, 142, 50, 162, + 163, 165, 166, 25, 143, 144, 147, 148, 31, 32, + 121, -188, 8, 248, 54, -187, 263, -83, 15, -27, + 5, -25, -191, -25, -25, -25, -25, -25, -162, -164, + 54, 90, -115, 125, 72, 157, 240, 122, 123, 129, + -118, 57, -117, 256, 135, 162, 173, 167, 194, 186, + 136, 184, 187, 227, 214, 224, 66, 165, 236, 145, + 182, 178, 176, 27, 199, 261, 177, 225, 121, 138, + 133, 200, 204, 228, 171, 172, 230, 198, 134, 33, + 258, 35, 153, 231, 202, 197, 193, 196, 170, 192, + 39, 206, 205, 207, 226, 189, 139, 179, 18, 234, + 148, 151, 201, 203, 130, 155, 260, 232, 175, 140, + 152, 147, 235, 141, 166, 229, 238, 38, 211, 169, + 132, 163, 159, 216, 190, 154, 180, 181, 195, 168, + 191, 164, 156, 149, 237, 212, 262, 188, 185, 160, + 158, 217, 218, 219, 220, 221, 161, 259, 233, 183, + 213, -103, 125, 127, 123, 123, 124, 125, 240, 122, + 123, -52, -124, 57, -117, 125, 157, 123, 108, 187, + 115, 215, 124, 33, 155, -133, 123, -105, 158, 214, + 217, 218, 219, 221, 220, 161, 57, 229, 228, 222, + -124, 164, -129, -129, -129, -129, -129, 216, 216, -129, + -2, -87, 17, 16, -5, -3, -188, 6, 20, 21, + -31, 40, 41, -26, -37, 99, -38, -124, -57, 74, + -62, 29, 57, -117, 23, -61, -58, -76, -74, -75, + 108, 109, 110, 97, 98, 105, 75, 111, -66, -64, + -65, -67, 59, 58, 67, 60, 61, 62, 63, 68, + 69, 70, -118, -72, -188, 44, 45, 249, 250, 251, + 252, 255, 253, 77, 34, 239, 247, 246, 245, 243, + 244, 241, 242, 128, 240, 103, 248, -103, -103, 11, + -47, -52, -95, -132, 164, -99, 229, 228, -119, -97, + -118, -116, 227, 187, 226, 120, 73, 22, 24, 209, + 76, 108, 16, 77, 107, 249, 115, 48, 241, 242, + 239, 251, 252, 240, 215, 29, 10, 25, 143, 21, + 101, 117, 80, 81, 146, 23, 144, 70, 19, 51, + 11, 13, 14, 128, 127, 92, 124, 46, 8, 111, + 26, 89, 42, 28, 44, 90, 17, 243, 244, 31, + 255, 150, 103, 49, 36, 74, 68, 71, 52, 72, + 15, 47, 91, 118, 248, 45, 122, 6, 254, 30, + 142, 43, 123, 79, 126, 69, 5, 129, 32, 9, + 50, 53, 245, 246, 247, 34, 78, 12, -163, 90, + -156, 57, -52, 124, -52, 248, -118, -111, 128, -111, + -111, 123, -52, -52, -110, 128, 57, -110, -110, -110, + -52, 112, -52, 57, 30, 240, 57, 155, 123, 156, + 125, -130, -188, -119, -130, -130, -130, 159, 160, -130, + -108, -107, 224, 225, 216, 223, 52, 12, -130, -129, + -129, -189, 56, -88, 19, 31, -38, -124, -84, -85, + -38, -83, -2, -25, 36, -29, 21, 65, 11, -121, + 73, 72, 89, -120, 22, -118, 59, 112, -38, -59, + 92, 74, 90, 91, 76, 94, 93, 104, 97, 98, + 99, 100, 101, 102, 103, 95, 96, 107, 82, 83, + 84, 85, 86, 87, 88, -104, -188, -75, -188, 113, + 114, -62, -62, -62, -62, -62, -62, -62, -62, -188, + -2, -70, -38, -188, -188, -188, -188, -188, -188, -188, + -188, -188, -79, -38, -188, -192, -188, -192, -192, -192, + -192, -192, -192, -192, -188, -188, -188, -188, -53, 26, + -52, -40, -41, -42, -43, -54, -75, -188, -52, -52, + -47, -190, 55, 11, 53, 55, -95, 164, -96, -100, + 230, 232, 82, -123, -118, 59, 29, 30, 56, 55, + -52, -135, -138, -140, -139, -141, -136, -137, 184, 185, + 108, 188, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 30, 145, 180, 181, 182, 183, 200, 201, + 202, 203, 204, 205, 206, 207, 167, 168, 169, 170, + 171, 172, 173, 175, 176, 177, 178, 179, 57, -130, + 125, -181, 53, 57, 74, 57, -52, -52, -130, 126, + -52, 23, 52, -52, 57, 57, -125, -124, -116, -130, + -130, -130, -130, -130, -130, -130, -130, -130, -130, 11, + -106, 11, 92, -52, -38, 9, 92, 55, 18, 112, + 55, -86, 24, 25, -87, -189, -31, -63, -118, 60, + 63, -30, 43, -52, -38, -38, -68, 68, 74, 69, + 70, -120, 99, -125, -119, -116, -62, -69, -72, -75, + 64, 92, 90, 91, 76, -62, -62, -62, -62, -62, + -62, -62, -62, -62, -62, -62, -62, -62, -62, -62, + -131, 57, 59, 57, -61, -61, -118, -36, 21, -35, + -37, -189, 55, -189, -2, -35, -35, -38, -38, -76, + -118, -124, -76, -35, -29, -77, -78, 78, -76, -189, + -35, -36, -35, -35, -91, 151, -52, 30, 55, -48, + -50, -49, -51, 42, 46, 48, 43, 44, 45, 49, + -128, 22, -40, -188, -127, 151, -126, 22, -124, 59, + -91, 53, -40, -52, -99, -96, 55, 231, 233, 234, + 52, 71, -38, -147, 107, -165, -166, -167, -119, 59, + 60, -156, -157, -158, -168, 137, -173, 130, 132, 129, + -159, 138, 124, 28, 56, -152, 68, 74, -148, 212, + -142, 54, -142, -142, -142, -142, -146, 187, -146, -146, + -146, 54, 54, -142, -142, -142, -150, 54, -150, -150, + -151, 54, -151, -122, 53, -52, -179, 259, -180, 57, + -130, 23, -130, -112, 120, 117, 118, -176, 116, 209, + 187, 66, 29, 15, 249, 151, 262, 57, 152, -52, + -52, -130, -52, -109, 90, 12, -124, -124, 38, -38, + -38, -125, -85, -88, -102, 19, 11, 34, 34, -35, + 68, 69, 70, 112, -188, -69, -62, -62, -62, -34, + 146, 73, -189, -189, -35, 55, -38, -189, -189, -189, + 55, 53, 22, 55, 11, 112, 55, 11, -189, -35, + -80, -78, 80, -38, -189, -189, -189, -189, -189, -60, + 30, 34, -2, -188, -188, -94, -98, -76, -41, -42, + -42, -41, -42, 42, 42, 42, 47, 42, 47, 42, + -49, -124, -189, -55, 50, 127, 51, -188, -126, -56, + 12, -40, -56, -100, -101, 235, 232, 238, 57, 59, + 55, -167, 82, 54, 57, 28, -159, -159, -160, 57, + -160, 28, -143, 29, 68, -149, 213, 60, -146, -146, + -147, 30, -147, -147, -147, -155, 59, -155, 60, 60, + 52, -118, -130, -178, -177, -119, -129, -182, 157, 131, + 137, 138, 133, 57, 124, 28, 130, 132, 151, 129, + -182, 157, -113, -114, 126, 22, 124, 28, 151, -130, + -106, 59, -38, 39, 112, -52, -39, 11, 99, -119, + -36, -34, 73, -62, -62, -189, -37, -134, 108, 184, + 145, 182, 178, 198, 189, 211, 180, 212, -131, -134, + -62, -62, -119, -62, -62, 256, -83, 81, -38, 79, + -93, 52, -94, -71, -73, -72, -188, -2, -89, -118, + -92, -118, -56, 55, 82, -45, -44, 52, 53, -46, + 52, -44, 42, 42, 124, 124, 124, -92, -83, -38, + -56, 232, 236, 237, -166, -167, -170, -169, -118, -173, + -160, -160, 54, -145, 52, 59, 60, 61, 68, 239, + 67, 56, -147, -147, 57, 108, 56, 55, 56, 55, + 56, 55, -52, 55, 82, -129, -118, -129, -118, -52, + -129, -118, -109, -56, -40, -189, -62, -189, -142, -142, + -142, -151, -142, 172, -142, 172, -189, -189, -189, 55, + 19, -189, 55, 19, -188, -33, 254, -38, 27, -93, + 55, -189, -189, -189, 55, 112, -189, 55, -83, -98, + -38, -38, 54, -38, -188, -188, -188, -189, -87, 56, + 55, -142, -90, -118, -153, 209, 9, 54, -146, 59, + -146, 60, 60, -130, -177, -167, 54, 26, -81, 13, + -146, 57, -62, -62, -62, -62, -62, -189, 59, 28, + -73, 34, -2, -188, -118, -118, -118, -87, -90, -90, + -90, -90, -127, -172, -171, 53, 134, 66, -169, 56, + 55, -154, 130, 28, 129, 239, 56, -147, -147, 56, + 56, -90, -188, -82, 14, 16, -189, -189, -189, -189, + -32, 92, 259, 9, -71, -2, 112, 56, -189, -189, + -189, -55, -171, 57, -161, 82, 59, 140, -118, -144, + 66, 28, 28, 54, 56, -174, -175, 151, -38, -70, + -189, 257, 49, 260, -94, -189, -118, 60, -52, 59, + 56, -181, -189, 55, -118, 39, 258, 261, 54, -179, + -175, 34, 39, -90, 153, 259, 56, 154, 260, -184, + -185, 52, -188, 261, -185, 52, 10, 9, -62, 150, + -183, 141, 136, 139, 30, -183, -189, -189, 135, 29, + 68, } var yyDef = [...]int{ - 22, -2, 2, -2, 5, 6, 7, 8, 9, 10, + 23, -2, 2, -2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 536, 0, 304, 304, 304, 304, 304, 304, 0, - 606, 589, 0, 0, 0, 0, -2, 292, 293, 0, - 295, 296, 820, 820, 820, 820, 820, 0, 0, 0, - 34, 35, 818, 1, 3, 544, 0, 0, 308, 311, - 306, 0, 589, 0, 0, 0, 61, 62, 0, 0, - 0, 806, 0, 807, 587, 587, 587, 607, 608, 611, - 612, 712, 713, 714, 715, 716, 717, 718, 719, 720, - 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, - 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, - 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, - 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, - 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, - 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, - 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, - 801, 802, 803, 804, 805, 808, 809, 810, 811, 812, - 813, 814, 815, 816, 817, 0, 0, 590, 0, 585, - 0, 585, 585, 585, 0, 249, 375, 615, 616, 806, - 807, 0, 0, 0, 0, 821, 821, 821, 821, 0, - 821, 0, 268, 269, 272, 273, 274, 275, 276, 821, - 289, 290, 281, 291, 294, 297, 298, 299, 300, 301, - 820, 820, 28, 548, 0, 0, 536, 30, 0, 304, - 309, 310, 314, 312, 313, 305, 0, 322, 326, 0, - 383, 0, 388, 390, -2, -2, 0, 425, 426, 427, - 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, - 453, 454, 455, 456, 521, 522, 523, 524, 525, 526, - 527, 528, 392, 393, 518, 568, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 509, 0, 483, 483, 483, - 483, 483, 483, 483, 483, 0, 0, 0, 0, 0, - 0, 333, 335, 336, 337, 356, 0, 358, 0, 0, - 42, 46, 0, 797, 572, -2, -2, 0, 0, 613, - 614, -2, 721, -2, 619, 620, 621, 622, 623, 624, - 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, - 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, - 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, - 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, - 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, - 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, - 705, 706, 707, 708, 709, 710, 711, 0, 0, 81, - 0, 79, 0, 821, 0, 69, 0, 0, 0, 0, - 0, 821, 0, 0, 0, 0, 0, 0, 0, 248, - 0, 250, 821, 821, 821, 821, 821, 821, 821, 821, - 259, 822, 823, 260, 261, 262, 821, 821, 264, 0, - 282, 278, 279, 0, 0, 277, 302, 303, 29, 819, - 23, 0, 0, 545, 0, 537, 538, 541, 544, 28, - 311, 0, 316, 315, 307, 0, 323, 0, 0, 0, - 327, 0, 329, 330, 0, 386, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 410, 411, 412, 413, 414, - 415, 416, 389, 0, 403, 0, 0, 0, 445, 446, - 447, 448, 449, 450, 451, 0, 318, 28, 0, 423, - 0, 0, 0, 0, 0, 0, 0, 0, 314, 0, - 510, 0, 475, 0, 476, 477, 478, 479, 480, 481, - 482, 0, 318, 0, 0, 44, 0, 374, 0, 0, - 0, 0, 0, 0, 363, 0, 0, 366, 0, 0, - 0, 0, 357, 0, 0, 377, 768, 359, 0, 361, - 362, -2, 0, 0, 0, 40, 41, 0, 47, 797, - 49, 50, 0, 0, 0, 164, 580, 581, 582, 578, - 208, 0, 0, 145, 141, 87, 88, 89, 134, 91, - 134, 134, 134, 134, 161, 161, 161, 161, 117, 118, - 119, 120, 121, 0, 0, 104, 134, 134, 134, 108, - 124, 125, 126, 127, 128, 129, 130, 131, 92, 93, - 94, 95, 96, 97, 98, 136, 136, 136, 138, 138, - 609, 64, 0, 72, 0, 821, 0, 821, 77, 0, - 224, 0, 243, 586, 0, 821, 246, 247, 376, 617, - 618, 251, 252, 253, 254, 255, 256, 257, 258, 263, - 267, 0, 285, 0, 0, 271, 270, 549, 0, 0, - 0, 0, 0, 540, 542, 543, 548, 31, 314, 0, - 529, 0, 0, 0, 317, 26, 384, 385, 387, 404, - 0, 406, 408, 328, 324, 0, 519, -2, 394, 395, - 419, 420, 421, 0, 0, 0, 0, 417, 399, 0, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 444, 494, 495, 0, 442, 443, 452, 0, - 0, 319, 320, 422, 0, 567, 28, 0, 0, 0, - 0, 0, 518, 0, 0, 0, 0, 516, 513, 0, - 0, 484, 0, 0, 0, 0, 0, 0, 373, 381, - 569, 0, 334, 352, 354, 0, 349, 364, 365, 367, - 0, 369, 0, 371, 372, 338, 339, 340, 0, 0, - 0, 0, 360, 381, 0, 381, 43, 573, 48, 0, - 0, 53, 54, 574, 575, 576, 0, 78, 209, 211, - 214, 215, 216, 82, 83, 84, 0, 0, 196, 0, - 0, 190, 190, 0, 188, 189, 80, 148, 146, 0, - 143, 142, 90, 0, 161, 161, 111, 112, 164, 0, - 164, 164, 164, 0, 0, 105, 106, 107, 99, 0, - 100, 101, 102, 0, 103, 0, 0, 821, 66, 0, - 70, 71, 67, 588, 68, 820, 0, 0, 601, 225, - 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, - 0, 242, 821, 245, 282, 266, 0, 0, 283, 284, - 0, 546, 547, 0, 539, 24, 0, 583, 584, 530, - 531, 331, 405, 407, 409, 0, 318, 396, 417, 400, - 0, 397, 0, 0, 391, 457, 0, 0, 424, -2, - 460, 461, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 536, 0, 514, 0, 0, 474, 485, 486, 487, - 488, 561, 0, 0, -2, 0, 0, 536, 0, 0, - 0, 346, 353, 0, 0, 347, 0, 348, 368, 370, - 0, 0, 0, 0, 344, 536, 381, 39, 51, 52, - 0, 0, 58, 165, 166, 0, 212, 0, 0, 0, - 183, 190, 190, 186, 191, 187, 0, 156, 0, 147, - 86, 144, 0, 164, 164, 113, 0, 114, 115, 116, - 0, 132, 0, 0, 0, 0, 610, 65, 73, 74, - 0, 217, 820, 0, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 820, 0, 0, 820, 602, - 603, 604, 605, 0, 244, 285, 286, 287, 550, 0, - 25, 381, 0, 325, 520, 0, 398, 0, 418, 401, - 458, 321, 0, 134, 134, 499, 134, 138, 502, 134, - 504, 134, 507, 0, 0, 0, 0, 519, 0, 0, - 0, 511, 473, 517, 0, 32, 0, 561, 551, 563, - 565, 0, 28, 0, 557, 0, 544, 570, 382, 571, - 350, 0, 355, 0, 0, 0, 358, 0, 544, 38, - 55, 56, 57, 210, 213, 0, 192, 134, 195, 184, - 185, 0, 159, 0, 149, 150, 151, 152, 153, 155, - 135, 109, 110, 162, 163, 161, 0, 161, 0, 139, - 0, 821, 0, 0, 218, 0, 219, 221, 222, 223, - 0, 265, 532, 332, 459, 402, 462, 496, 161, 500, - 501, 503, 505, 506, 508, 464, 463, 465, 0, 0, - 468, 0, 0, 0, 0, 0, 515, 0, 33, 0, - 566, -2, 0, 0, 0, 45, 36, 0, 342, 0, - 0, 0, 377, 345, 37, 175, 0, 194, 0, 167, - 160, 0, 0, 164, 133, 164, 0, 0, 63, 75, - 76, 0, 0, 534, 0, 497, 498, 0, 0, 0, - 0, 489, 472, 512, 0, 564, 0, -2, 0, 559, - 558, 0, 351, 378, 379, 380, 341, 174, 176, 0, - 181, 0, 193, 0, 172, 0, 169, 171, 157, 154, - 122, 123, 137, 140, 0, 0, 27, 0, 0, 466, - 467, 469, 470, 0, 0, 0, 0, 554, 28, 0, - 343, 177, 178, 0, 182, 180, 0, 85, 0, 168, - 170, 0, 69, 0, 238, 0, 535, 533, 471, 0, - 0, 0, 562, -2, 560, 179, 0, 173, 158, 72, - 237, 0, 0, 490, 0, 493, 0, 220, 239, 0, - 491, 0, 0, 0, 197, 0, 0, 198, 199, 0, - 0, 492, 200, 0, 0, 0, 0, 0, 201, 203, - 204, 0, 0, 202, 240, 241, 205, 206, 207, + 21, 22, 542, 0, 309, 309, 309, 309, 309, 309, + 0, 613, 596, 0, 0, 0, 0, -2, 296, 297, + 0, 299, 300, 831, 831, 831, 831, 831, 0, 0, + 831, 0, 35, 36, 829, 1, 3, 550, 0, 0, + 313, 316, 311, 0, 596, 596, 0, 0, 62, 63, + 0, 0, 0, 816, 0, 817, 594, 594, 594, 614, + 615, 618, 619, 719, 720, 721, 722, 723, 724, 725, + 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, + 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, + 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, + 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, + 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, + 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, + 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, + 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, + 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, + 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, + 828, 0, 0, 597, 0, 592, 0, 592, 592, 592, + 0, 250, 381, 622, 623, 816, 817, 0, 0, 0, + 0, 832, 832, 832, 832, 0, 832, 0, 269, 270, + 273, 274, 275, 276, 277, 278, 832, 293, 294, 283, + 295, 298, 301, 302, 303, 304, 305, 831, 831, 308, + 29, 554, 0, 0, 542, 31, 0, 309, 314, 315, + 319, 317, 318, 310, 0, 327, 331, 0, 389, 0, + 394, 396, -2, -2, 0, 431, 432, 433, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 0, 459, 460, + 461, 462, 527, 528, 529, 530, 531, 532, 533, 534, + 398, 399, 524, 574, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 515, 0, 489, 489, 489, 489, 489, + 489, 489, 489, 0, 0, 0, 0, 0, 0, 0, + 0, 43, 47, 0, 807, 578, -2, -2, 0, 0, + 620, 621, -2, 728, -2, 626, 627, 628, 629, 630, + 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, + 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, + 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, + 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, + 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, + 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, + 711, 712, 713, 714, 715, 716, 717, 718, 0, 0, + 82, 0, 80, 0, 832, 0, 70, 0, 0, 0, + 0, 0, 832, 0, 0, 0, 0, 0, 0, 0, + 249, 0, 251, 832, 832, 832, 832, 832, 832, 832, + 832, 260, 833, 834, 261, 262, 263, 832, 832, 265, + 0, 286, 284, 285, 280, 281, 0, 0, 279, 306, + 307, 30, 830, 24, 0, 0, 551, 0, 543, 544, + 547, 550, 29, 316, 0, 321, 320, 312, 0, 328, + 0, 0, 0, 332, 0, 334, 335, 0, 392, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 416, 417, + 418, 419, 420, 421, 422, 395, 0, 409, 0, 0, + 0, 451, 452, 453, 454, 455, 456, 457, 0, 323, + 29, 0, 429, 0, 0, 0, 0, 0, 0, 0, + 0, 319, 0, 516, 0, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 323, 0, 0, 45, 0, + 380, 0, 338, 340, 341, 342, -2, 0, 364, -2, + 0, 0, 0, 41, 42, 0, 48, 807, 50, 51, + 0, 0, 0, 165, 587, 588, 589, 585, 209, 0, + 0, 146, 142, 88, 89, 90, 135, 92, 135, 135, + 135, 135, 162, 162, 162, 162, 118, 119, 120, 121, + 122, 0, 0, 105, 135, 135, 135, 109, 125, 126, + 127, 128, 129, 130, 131, 132, 93, 94, 95, 96, + 97, 98, 99, 137, 137, 137, 139, 139, 616, 65, + 0, 73, 0, 832, 0, 832, 78, 0, 225, 0, + 244, 593, 0, 832, 247, 248, 382, 624, 625, 252, + 253, 254, 255, 256, 257, 258, 259, 264, 268, 0, + 289, 0, 0, 272, 271, 555, 0, 0, 0, 0, + 0, 546, 548, 549, 554, 32, 319, 0, 535, 0, + 0, 0, 322, 27, 390, 391, 393, 410, 0, 412, + 414, 333, 329, 0, 525, -2, 400, 401, 425, 426, + 427, 0, 0, 0, 0, 423, 405, 0, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, + 450, 500, 501, 0, 448, 449, 458, 0, 0, 324, + 325, 428, 0, 573, 29, 0, 0, 0, 0, 0, + 524, 0, 0, 0, 0, 522, 519, 0, 0, 490, + 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 372, 0, 0, 0, + 0, 363, 0, 0, 383, 777, 365, 0, 367, 368, + 387, 0, 387, 44, 579, 49, 0, 0, 54, 55, + 580, 581, 582, 583, 0, 79, 210, 212, 215, 216, + 217, 83, 84, 85, 0, 0, 197, 0, 0, 191, + 191, 0, 189, 190, 81, 149, 147, 0, 144, 143, + 91, 0, 162, 162, 112, 113, 165, 0, 165, 165, + 165, 0, 0, 106, 107, 108, 100, 0, 101, 102, + 103, 0, 104, 0, 0, 832, 67, 0, 71, 72, + 68, 595, 69, 831, 0, 0, 608, 226, 598, 599, + 600, 601, 602, 603, 604, 605, 606, 607, 0, 243, + 832, 246, 286, 267, 0, 0, 287, 288, 0, 552, + 553, 0, 545, 25, 0, 590, 591, 536, 537, 336, + 411, 413, 415, 0, 323, 402, 423, 406, 0, 403, + 0, 0, 397, 463, 0, 0, 430, -2, 466, 467, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 542, + 0, 520, 0, 0, 480, 491, 492, 493, 494, 567, + 0, 0, -2, 0, 0, 387, 575, 0, 339, 358, + 360, 0, 355, 370, 371, 373, 0, 375, 0, 377, + 378, 343, 345, 346, 0, 0, 0, 0, 366, 542, + 0, 387, 40, 52, 53, 0, 0, 59, 166, 167, + 0, 213, 0, 0, 0, 184, 191, 191, 187, 192, + 188, 0, 157, 0, 148, 87, 145, 0, 165, 165, + 114, 0, 115, 116, 117, 0, 133, 0, 0, 0, + 0, 617, 66, 74, 75, 0, 218, 831, 0, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 831, 0, 0, 831, 609, 610, 611, 612, 0, 245, + 289, 290, 291, 556, 0, 26, 387, 0, 330, 526, + 0, 404, 0, 424, 407, 464, 326, 0, 135, 135, + 505, 135, 139, 508, 135, 510, 135, 513, 0, 0, + 0, 0, 525, 0, 0, 0, 517, 479, 523, 0, + 33, 0, 567, 557, 569, 571, 0, 29, 0, 563, + 0, 350, 542, 0, 0, 352, 359, 0, 0, 353, + 0, 354, 374, 376, 0, 0, 0, 0, 550, 388, + 39, 56, 57, 58, 211, 214, 0, 193, 135, 196, + 185, 186, 0, 160, 0, 150, 151, 152, 153, 154, + 156, 136, 110, 111, 163, 164, 162, 0, 162, 0, + 140, 0, 832, 0, 0, 219, 0, 220, 222, 223, + 224, 0, 266, 538, 337, 465, 408, 468, 502, 162, + 506, 507, 509, 511, 512, 514, 470, 469, 471, 0, + 0, 474, 0, 0, 0, 0, 0, 521, 0, 34, + 0, 572, -2, 0, 0, 0, 46, 0, 550, 576, + 577, 356, 0, 361, 0, 0, 0, 364, 38, 176, + 0, 195, 0, 348, 168, 161, 0, 0, 165, 134, + 165, 0, 0, 64, 76, 77, 0, 0, 540, 0, + 503, 504, 0, 0, 0, 0, 495, 478, 518, 0, + 570, 0, -2, 0, 565, 564, 351, 37, 0, 0, + 0, 0, 383, 175, 177, 0, 182, 0, 194, 0, + 0, 173, 0, 170, 172, 158, 155, 123, 124, 138, + 141, 0, 0, 28, 0, 0, 472, 473, 475, 476, + 0, 0, 0, 0, 560, 29, 0, 357, 384, 385, + 386, 347, 178, 179, 0, 183, 181, 0, 349, 86, + 0, 169, 171, 0, 70, 0, 239, 0, 541, 539, + 477, 0, 0, 0, 568, -2, 566, 180, 0, 174, + 159, 73, 238, 0, 0, 496, 0, 499, 0, 221, + 240, 0, 497, 0, 0, 0, 198, 0, 0, 199, + 200, 0, 0, 498, 201, 0, 0, 0, 0, 0, + 202, 204, 205, 0, 0, 203, 241, 242, 206, 207, + 208, } 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, 74, 3, 3, 3, 101, 93, 3, - 54, 56, 98, 96, 55, 97, 111, 99, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 259, - 82, 81, 83, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 75, 3, 3, 3, 102, 94, 3, + 54, 56, 99, 97, 55, 98, 112, 100, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 263, + 83, 82, 84, 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, 103, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 104, 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, 92, 3, 104, + 3, 3, 3, 3, 93, 3, 105, } var yyTok2 = [...]int{ @@ -2441,10 +2479,10 @@ var yyTok2 = [...]int{ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, - 76, 77, 78, 79, 80, 84, 85, 86, 87, 88, - 89, 90, 91, 94, 95, 100, 102, 105, 106, 107, - 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 76, 77, 78, 79, 80, 81, 85, 86, 87, 88, + 89, 90, 91, 92, 95, 96, 101, 103, 106, 107, + 108, 109, 110, 111, 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, 148, @@ -2459,6 +2497,7 @@ var yyTok2 = [...]int{ 229, 230, 231, 232, 233, 234, 235, 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, } var yyTok3 = [...]int{ 0, @@ -2803,35 +2842,35 @@ yydefault: case 1: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:313 +//line sql.y:313 { setParseTree(yylex, yyDollar[1].statement) } case 2: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:318 +//line sql.y:318 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:319 +//line sql.y:319 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:323 +//line sql.y:323 { yyVAL.statement = yyDollar[1].selStmt } - case 22: + case 23: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:344 +//line sql.y:345 { setParseTree(yylex, nil) } - case 23: + case 24: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:350 +//line sql.y:351 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -2839,57 +2878,57 @@ yydefault: sel.Lock = yyDollar[4].str yyVAL.selStmt = sel } - case 24: + case 25: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:358 +//line sql.y:359 { yyVAL.selStmt = &Union{Type: yyDollar[2].str, Left: yyDollar[1].selStmt, Right: yyDollar[3].selStmt, OrderBy: yyDollar[4].orderBy, Limit: yyDollar[5].limit, Lock: yyDollar[6].str} } - case 25: + case 26: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:362 +//line sql.y:363 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Cache: yyDollar[3].str, SelectExprs: SelectExprs{Nextval{Expr: yyDollar[5].expr}}, From: TableExprs{&AliasedTableExpr{Expr: yyDollar[7].tableName}}} } - case 26: + case 27: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:368 +//line sql.y:369 { yyVAL.statement = &Stream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName} } - case 27: + case 28: yyDollar = yyS[yypt-10 : yypt+1] - //line sql.y:375 +//line sql.y:376 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Cache: yyDollar[3].str, Distinct: yyDollar[4].str, Hints: yyDollar[5].str, SelectExprs: yyDollar[6].selectExprs, From: yyDollar[7].tableExprs, Where: NewWhere(WhereStr, yyDollar[8].expr), GroupBy: GroupBy(yyDollar[9].exprs), Having: NewWhere(HavingStr, yyDollar[10].expr)} } - case 28: + case 29: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:381 +//line sql.y:382 { yyVAL.selStmt = yyDollar[1].selStmt } - case 29: + case 30: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:385 +//line sql.y:386 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } - case 30: + case 31: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:391 +//line sql.y:392 { yyVAL.selStmt = yyDollar[1].selStmt } - case 31: + case 32: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:395 +//line sql.y:396 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } - case 32: + case 33: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:402 +//line sql.y:403 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].ins @@ -2901,9 +2940,9 @@ yydefault: ins.OnDup = OnDup(yyDollar[7].updateExprs) yyVAL.statement = ins } - case 33: + case 34: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:414 +//line sql.y:415 { cols := make(Columns, 0, len(yyDollar[7].updateExprs)) vals := make(ValTuple, 0, len(yyDollar[8].updateExprs)) @@ -2913,203 +2952,203 @@ yydefault: } yyVAL.statement = &Insert{Action: yyDollar[1].str, Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].str, Table: yyDollar[4].tableName, Partitions: yyDollar[5].partitions, Columns: cols, Rows: Values{vals}, OnDup: OnDup(yyDollar[8].updateExprs)} } - case 34: + case 35: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:426 +//line sql.y:427 { yyVAL.str = InsertStr } - case 35: + case 36: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:430 +//line sql.y:431 { yyVAL.str = ReplaceStr } - case 36: - yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:436 + case 37: + yyDollar = yyS[yypt-9 : yypt+1] +//line sql.y:437 { - yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), TableExprs: yyDollar[3].tableExprs, Exprs: yyDollar[5].updateExprs, Where: NewWhere(WhereStr, yyDollar[6].expr), OrderBy: yyDollar[7].orderBy, Limit: yyDollar[8].limit} + yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].str, TableExprs: yyDollar[4].tableExprs, Exprs: yyDollar[6].updateExprs, Where: NewWhere(WhereStr, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } - case 37: + case 38: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:442 +//line sql.y:443 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[4].tableName}}, Partitions: yyDollar[5].partitions, Where: NewWhere(WhereStr, yyDollar[6].expr), OrderBy: yyDollar[7].orderBy, Limit: yyDollar[8].limit} } - case 38: + case 39: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:446 +//line sql.y:447 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereStr, yyDollar[7].expr)} } - case 39: + case 40: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:450 +//line sql.y:451 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[3].tableNames, TableExprs: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr)} } - case 40: + case 41: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:455 +//line sql.y:456 { } - case 41: + case 42: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:456 +//line sql.y:457 { } - case 42: + case 43: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:460 +//line sql.y:461 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } - case 43: + case 44: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:464 +//line sql.y:465 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } - case 44: + case 45: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:469 +//line sql.y:470 { yyVAL.partitions = nil } - case 45: + case 46: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:473 +//line sql.y:474 { yyVAL.partitions = yyDollar[3].partitions } - case 46: + case 47: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:479 +//line sql.y:480 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[3].setExprs} } - case 47: + case 48: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:483 +//line sql.y:484 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].str, Exprs: yyDollar[4].setExprs} } - case 48: + case 49: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:487 +//line sql.y:488 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].str, Exprs: yyDollar[5].setExprs} } - case 49: + case 50: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:491 +//line sql.y:492 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[4].setExprs} } - case 50: + case 51: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:497 +//line sql.y:498 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } - case 51: + case 52: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:501 +//line sql.y:502 { yyVAL.setExprs = append(yyVAL.setExprs, yyDollar[3].setExpr) } - case 52: + case 53: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:507 +//line sql.y:508 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(yyDollar[3].str))} } - case 53: + case 54: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:511 +//line sql.y:512 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(TxReadWrite))} } - case 54: + case 55: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:515 +//line sql.y:516 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(TxReadOnly))} } - case 55: + case 56: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:521 +//line sql.y:522 { yyVAL.str = IsolationLevelRepeatableRead } - case 56: + case 57: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:525 +//line sql.y:526 { yyVAL.str = IsolationLevelReadCommitted } - case 57: + case 58: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:529 +//line sql.y:530 { yyVAL.str = IsolationLevelReadUncommitted } - case 58: + case 59: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:533 +//line sql.y:534 { yyVAL.str = IsolationLevelSerializable } - case 59: + case 60: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:539 +//line sql.y:540 { yyVAL.str = SessionStr } - case 60: + case 61: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:543 +//line sql.y:544 { yyVAL.str = GlobalStr } - case 61: + case 62: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:549 +//line sql.y:550 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } - case 62: + case 63: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:554 +//line sql.y:555 { // Create table [name] like [name] yyDollar[1].ddl.OptLike = yyDollar[2].optLike yyVAL.statement = yyDollar[1].ddl } - case 63: + case 64: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:560 +//line sql.y:561 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[7].tableName, NewName: yyDollar[7].tableName} } - case 64: + case 65: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:565 +//line sql.y:566 { yyVAL.statement = &DDL{Action: CreateStr, NewName: yyDollar[3].tableName.ToViewName()} } - case 65: + case 66: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:569 +//line sql.y:570 { yyVAL.statement = &DDL{Action: CreateStr, NewName: yyDollar[5].tableName.ToViewName()} } - case 66: + case 67: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:573 +//line sql.y:574 { yyVAL.statement = &DDL{Action: CreateVindexStr, VindexSpec: &VindexSpec{ Name: yyDollar[3].colIdent, @@ -3117,122 +3156,122 @@ yydefault: Params: yyDollar[5].vindexParams, }} } - case 67: + case 68: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:581 +//line sql.y:582 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } - case 68: + case 69: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:585 +//line sql.y:586 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } - case 69: + case 70: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:590 +//line sql.y:591 { yyVAL.colIdent = NewColIdent("") } - case 70: + case 71: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:594 +//line sql.y:595 { yyVAL.colIdent = yyDollar[2].colIdent } - case 71: + case 72: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:600 +//line sql.y:601 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 72: + case 73: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:605 +//line sql.y:606 { var v []VindexParam yyVAL.vindexParams = v } - case 73: + case 74: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:610 +//line sql.y:611 { yyVAL.vindexParams = yyDollar[2].vindexParams } - case 74: + case 75: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:616 +//line sql.y:617 { yyVAL.vindexParams = make([]VindexParam, 0, 4) yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[1].vindexParam) } - case 75: + case 76: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:621 +//line sql.y:622 { yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[3].vindexParam) } - case 76: + case 77: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:627 +//line sql.y:628 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].colIdent, Val: yyDollar[3].str} } - case 77: + case 78: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:633 +//line sql.y:634 { yyVAL.ddl = &DDL{Action: CreateStr, NewName: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } - case 78: + case 79: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:640 +//line sql.y:641 { yyVAL.TableSpec = yyDollar[2].TableSpec yyVAL.TableSpec.Options = yyDollar[4].str } - case 79: + case 80: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:647 +//line sql.y:648 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[2].tableName} } - case 80: + case 81: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:651 +//line sql.y:652 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[3].tableName} } - case 81: + case 82: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:657 +//line sql.y:658 { yyVAL.TableSpec = &TableSpec{} yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) } - case 82: + case 83: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:662 +//line sql.y:663 { yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) } - case 83: + case 84: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:666 +//line sql.y:667 { yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) } - case 84: + case 85: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:670 +//line sql.y:671 { yyVAL.TableSpec.AddConstraint(yyDollar[3].constraintDefinition) } - case 85: + case 86: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:676 +//line sql.y:677 { yyDollar[2].columnType.NotNull = yyDollar[3].boolVal yyDollar[2].columnType.Default = yyDollar[4].optVal @@ -3242,80 +3281,72 @@ yydefault: yyDollar[2].columnType.Comment = yyDollar[8].optVal yyVAL.columnDefinition = &ColumnDefinition{Name: NewColIdent(string(yyDollar[1].bytes)), Type: yyDollar[2].columnType} } - case 86: + case 87: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:687 +//line sql.y:688 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolVal yyVAL.columnType.Zerofill = yyDollar[3].boolVal } - case 90: + case 91: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:698 +//line sql.y:699 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].optVal } - case 91: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:703 - { - yyVAL.columnType = yyDollar[1].columnType - } case 92: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:709 +//line sql.y:704 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = yyDollar[1].columnType } case 93: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:713 +//line sql.y:710 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 94: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:717 +//line sql.y:714 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 95: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:721 +//line sql.y:718 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 96: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:725 +//line sql.y:722 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 97: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:729 +//line sql.y:726 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 98: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:733 +//line sql.y:730 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 99: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:739 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:734 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} - yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 100: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:745 +//line sql.y:740 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -3323,7 +3354,7 @@ yydefault: } case 101: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:751 +//line sql.y:746 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -3331,7 +3362,7 @@ yydefault: } case 102: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:757 +//line sql.y:752 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -3339,721 +3370,729 @@ yydefault: } case 103: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:763 +//line sql.y:758 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 104: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:771 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:764 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 105: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:775 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:772 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 106: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:779 +//line sql.y:776 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 107: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:783 +//line sql.y:780 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 108: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:787 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:784 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 109: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:793 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:788 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 110: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:797 +//line sql.y:794 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 111: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:801 + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:798 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 112: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:805 +//line sql.y:802 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 113: - yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:809 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:806 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 114: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:813 +//line sql.y:810 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 115: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:817 +//line sql.y:814 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 116: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:821 +//line sql.y:818 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 117: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:825 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:822 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 118: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:829 +//line sql.y:826 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 119: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:833 +//line sql.y:830 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 120: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:837 +//line sql.y:834 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 121: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:841 +//line sql.y:838 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 122: - yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:845 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:842 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 123: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:850 +//line sql.y:846 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 124: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:856 + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:851 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 125: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:860 +//line sql.y:857 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 126: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:864 +//line sql.y:861 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 127: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:868 +//line sql.y:865 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 128: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:872 +//line sql.y:869 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 129: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:876 +//line sql.y:873 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 130: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:880 +//line sql.y:877 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 131: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:884 +//line sql.y:881 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 132: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:890 +//line sql.y:885 + { + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + } + case 133: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:891 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, "'"+string(yyDollar[1].bytes)+"'") } - case 133: + case 134: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:895 +//line sql.y:896 { yyVAL.strs = append(yyDollar[1].strs, "'"+string(yyDollar[3].bytes)+"'") } - case 134: + case 135: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:900 +//line sql.y:901 { yyVAL.optVal = nil } - case 135: + case 136: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:904 +//line sql.y:905 { yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } - case 136: + case 137: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:909 +//line sql.y:910 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 137: + case 138: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:913 +//line sql.y:914 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), Scale: NewIntVal(yyDollar[4].bytes), } } - case 138: + case 139: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:921 +//line sql.y:922 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 139: + case 140: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:925 +//line sql.y:926 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), } } - case 140: + case 141: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:931 +//line sql.y:932 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), Scale: NewIntVal(yyDollar[4].bytes), } } - case 141: + case 142: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:939 +//line sql.y:940 { yyVAL.boolVal = BoolVal(false) } - case 142: + case 143: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:943 +//line sql.y:944 { yyVAL.boolVal = BoolVal(true) } - case 143: + case 144: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:948 +//line sql.y:949 { yyVAL.boolVal = BoolVal(false) } - case 144: + case 145: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:952 +//line sql.y:953 { yyVAL.boolVal = BoolVal(true) } - case 145: + case 146: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:958 +//line sql.y:959 { yyVAL.boolVal = BoolVal(false) } - case 146: + case 147: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:962 +//line sql.y:963 { yyVAL.boolVal = BoolVal(false) } - case 147: + case 148: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:966 +//line sql.y:967 { yyVAL.boolVal = BoolVal(true) } - case 148: + case 149: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:971 +//line sql.y:972 { yyVAL.optVal = nil } - case 149: + case 150: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:975 +//line sql.y:976 { yyVAL.optVal = NewStrVal(yyDollar[2].bytes) } - case 150: + case 151: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:979 +//line sql.y:980 { yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } - case 151: + case 152: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:983 +//line sql.y:984 { yyVAL.optVal = NewFloatVal(yyDollar[2].bytes) } - case 152: + case 153: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:987 +//line sql.y:988 { yyVAL.optVal = NewValArg(yyDollar[2].bytes) } - case 153: + case 154: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:991 +//line sql.y:992 { yyVAL.optVal = NewValArg(yyDollar[2].bytes) } - case 154: + case 155: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:995 +//line sql.y:996 { yyVAL.optVal = NewValArg(yyDollar[2].bytes) } - case 155: + case 156: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:999 +//line sql.y:1000 { yyVAL.optVal = NewBitVal(yyDollar[2].bytes) } - case 156: + case 157: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1004 +//line sql.y:1005 { yyVAL.optVal = nil } - case 157: + case 158: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1008 +//line sql.y:1009 { yyVAL.optVal = NewValArg(yyDollar[3].bytes) } - case 158: + case 159: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1012 +//line sql.y:1013 { yyVAL.optVal = NewValArg(yyDollar[3].bytes) } - case 159: + case 160: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1017 +//line sql.y:1018 { yyVAL.boolVal = BoolVal(false) } - case 160: + case 161: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1021 +//line sql.y:1022 { yyVAL.boolVal = BoolVal(true) } - case 161: + case 162: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1026 +//line sql.y:1027 { yyVAL.str = "" } - case 162: + case 163: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1030 +//line sql.y:1031 { yyVAL.str = string(yyDollar[3].bytes) } - case 163: + case 164: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1034 +//line sql.y:1035 { yyVAL.str = string(yyDollar[3].bytes) } - case 164: + case 165: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1039 +//line sql.y:1040 { yyVAL.str = "" } - case 165: + case 166: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1043 +//line sql.y:1044 { yyVAL.str = string(yyDollar[2].bytes) } - case 166: + case 167: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1047 +//line sql.y:1048 { yyVAL.str = string(yyDollar[2].bytes) } - case 167: + case 168: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1052 +//line sql.y:1053 { yyVAL.colKeyOpt = colKeyNone } - case 168: + case 169: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1056 +//line sql.y:1057 { yyVAL.colKeyOpt = colKeyPrimary } - case 169: + case 170: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1060 +//line sql.y:1061 { yyVAL.colKeyOpt = colKey } - case 170: + case 171: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1064 +//line sql.y:1065 { yyVAL.colKeyOpt = colKeyUniqueKey } - case 171: + case 172: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1068 +//line sql.y:1069 { yyVAL.colKeyOpt = colKeyUnique } - case 172: + case 173: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1073 +//line sql.y:1074 { yyVAL.optVal = nil } - case 173: + case 174: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1077 +//line sql.y:1078 { yyVAL.optVal = NewStrVal(yyDollar[2].bytes) } - case 174: + case 175: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1083 +//line sql.y:1084 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns, Options: yyDollar[5].indexOptions} } - case 175: + case 176: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1087 +//line sql.y:1088 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns} } - case 176: + case 177: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1093 +//line sql.y:1094 { yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } - case 177: + case 178: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1097 +//line sql.y:1098 { yyVAL.indexOptions = append(yyVAL.indexOptions, yyDollar[2].indexOption) } - case 178: + case 179: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1103 +//line sql.y:1104 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Using: string(yyDollar[2].bytes)} } - case 179: + case 180: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1107 +//line sql.y:1108 { // should not be string yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewIntVal(yyDollar[3].bytes)} } - case 180: + case 181: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1112 +//line sql.y:1113 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewStrVal(yyDollar[2].bytes)} } - case 181: + case 182: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1118 +//line sql.y:1119 { yyVAL.str = "" } - case 182: + case 183: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1122 +//line sql.y:1123 { yyVAL.str = string(yyDollar[1].bytes) } - case 183: + case 184: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1128 +//line sql.y:1129 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } - case 184: + case 185: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1132 +//line sql.y:1133 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Spatial: true, Unique: false} } - case 185: + case 186: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1136 +//line sql.y:1137 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Unique: true} } - case 186: + case 187: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1140 +//line sql.y:1141 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(yyDollar[2].str), Unique: true} } - case 187: + case 188: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1144 +//line sql.y:1145 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(yyDollar[2].str), Unique: false} } - case 188: + case 189: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1150 +//line sql.y:1151 { yyVAL.str = string(yyDollar[1].bytes) } - case 189: + case 190: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1154 +//line sql.y:1155 { yyVAL.str = string(yyDollar[1].bytes) } - case 190: + case 191: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1159 +//line sql.y:1160 { yyVAL.str = "" } - case 191: + case 192: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1163 +//line sql.y:1164 { yyVAL.str = string(yyDollar[1].bytes) } - case 192: + case 193: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1169 +//line sql.y:1170 { yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } - case 193: + case 194: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1173 +//line sql.y:1174 { yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) } - case 194: + case 195: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1179 +//line sql.y:1180 { yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].optVal} } - case 195: + case 196: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1185 +//line sql.y:1186 { yyVAL.constraintDefinition = &ConstraintDefinition{Name: string(yyDollar[2].bytes), Details: yyDollar[3].constraintInfo} } - case 196: + case 197: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1189 +//line sql.y:1190 { yyVAL.constraintDefinition = &ConstraintDefinition{Details: yyDollar[1].constraintInfo} } - case 197: + case 198: yyDollar = yyS[yypt-10 : yypt+1] - //line sql.y:1196 +//line sql.y:1197 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns} } - case 198: + case 199: yyDollar = yyS[yypt-11 : yypt+1] - //line sql.y:1200 +//line sql.y:1201 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction} } - case 199: + case 200: yyDollar = yyS[yypt-11 : yypt+1] - //line sql.y:1204 +//line sql.y:1205 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnUpdate: yyDollar[11].ReferenceAction} } - case 200: + case 201: yyDollar = yyS[yypt-12 : yypt+1] - //line sql.y:1208 +//line sql.y:1209 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction, OnUpdate: yyDollar[12].ReferenceAction} } - case 201: + case 202: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1214 +//line sql.y:1215 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } - case 202: + case 203: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1220 +//line sql.y:1221 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } - case 203: + case 204: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1226 +//line sql.y:1227 { yyVAL.ReferenceAction = Restrict } - case 204: + case 205: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1230 +//line sql.y:1231 { yyVAL.ReferenceAction = Cascade } - case 205: + case 206: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1234 +//line sql.y:1235 { yyVAL.ReferenceAction = NoAction } - case 206: + case 207: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1238 +//line sql.y:1239 { yyVAL.ReferenceAction = SetDefault } - case 207: + case 208: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1242 +//line sql.y:1243 { yyVAL.ReferenceAction = SetNull } - case 208: + case 209: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1247 +//line sql.y:1248 { yyVAL.str = "" } - case 209: + case 210: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1251 +//line sql.y:1252 { yyVAL.str = " " + string(yyDollar[1].str) } - case 210: + case 211: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1255 +//line sql.y:1256 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } - case 211: + case 212: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1263 +//line sql.y:1264 { yyVAL.str = yyDollar[1].str } - case 212: + case 213: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1267 +//line sql.y:1268 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } - case 213: + case 214: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1271 +//line sql.y:1272 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } - case 214: + case 215: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1277 +//line sql.y:1278 { yyVAL.str = yyDollar[1].colIdent.String() } - case 215: + case 216: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1281 +//line sql.y:1282 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } - case 216: + case 217: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1285 +//line sql.y:1286 { yyVAL.str = string(yyDollar[1].bytes) } - case 217: + case 218: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1291 +//line sql.y:1292 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } - case 218: + case 219: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1295 +//line sql.y:1296 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } - case 219: + case 220: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1299 +//line sql.y:1300 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } - case 220: + case 221: yyDollar = yyS[yypt-12 : yypt+1] - //line sql.y:1303 +//line sql.y:1304 { yyVAL.statement = &DDL{ Action: AddColVindexStr, @@ -4066,9 +4105,9 @@ yydefault: VindexCols: yyDollar[9].columns, } } - case 221: + case 222: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1316 +//line sql.y:1317 { yyVAL.statement = &DDL{ Action: DropColVindexStr, @@ -4078,71 +4117,71 @@ yydefault: }, } } - case 222: + case 223: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1326 +//line sql.y:1327 { // Change this to a rename statement yyVAL.statement = &DDL{Action: RenameStr, Table: yyDollar[4].tableName, NewName: yyDollar[7].tableName} } - case 223: + case 224: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1331 +//line sql.y:1332 { // Rename an index can just be an alter yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } - case 224: + case 225: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1336 +//line sql.y:1337 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName.ToViewName(), NewName: yyDollar[3].tableName.ToViewName()} } - case 225: + case 226: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1340 +//line sql.y:1341 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} } - case 237: + case 238: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1359 +//line sql.y:1360 { yyVAL.partSpec = &PartitionSpec{Action: ReorganizeStr, Name: yyDollar[3].colIdent, Definitions: yyDollar[6].partDefs} } - case 238: + case 239: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1365 +//line sql.y:1366 { yyVAL.partDefs = []*PartitionDefinition{yyDollar[1].partDef} } - case 239: + case 240: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1369 +//line sql.y:1370 { yyVAL.partDefs = append(yyDollar[1].partDefs, yyDollar[3].partDef) } - case 240: + case 241: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:1375 +//line sql.y:1376 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Limit: yyDollar[7].expr} } - case 241: + case 242: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:1379 +//line sql.y:1380 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Maxvalue: true} } - case 242: + case 243: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1385 +//line sql.y:1386 { yyVAL.statement = &DDL{Action: RenameStr, Table: yyDollar[3].tableName, NewName: yyDollar[5].tableName} } - case 243: + case 244: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1391 +//line sql.y:1392 { var exists bool if yyDollar[3].byt != 0 { @@ -4150,16 +4189,16 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, Table: yyDollar[4].tableName, IfExists: exists} } - case 244: + case 245: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1399 +//line sql.y:1400 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[5].tableName, NewName: yyDollar[5].tableName} } - case 245: + case 246: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1404 +//line sql.y:1405 { var exists bool if yyDollar[3].byt != 0 { @@ -4167,130 +4206,130 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, Table: yyDollar[4].tableName.ToViewName(), IfExists: exists} } - case 246: + case 247: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1412 +//line sql.y:1413 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 247: + case 248: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1416 +//line sql.y:1417 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 248: + case 249: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1422 +//line sql.y:1423 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[3].tableName} } - case 249: + case 250: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1426 +//line sql.y:1427 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[2].tableName} } - case 250: + case 251: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1431 +//line sql.y:1432 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName, NewName: yyDollar[3].tableName} } - case 251: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1437 - { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} - } case 252: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1441 +//line sql.y:1438 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 253: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1445 +//line sql.y:1442 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 254: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1450 +//line sql.y:1446 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 255: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1454 +//line sql.y:1451 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 256: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1458 +//line sql.y:1455 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 257: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1462 +//line sql.y:1459 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 258: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1466 +//line sql.y:1463 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 259: - yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1470 + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:1467 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 260: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1474 +//line sql.y:1471 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 261: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1478 +//line sql.y:1475 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 262: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1482 +//line sql.y:1479 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 263: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:1483 + { + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + } + case 264: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1486 +//line sql.y:1487 { yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } - case 264: + case 265: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1490 +//line sql.y:1491 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 265: + case 266: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1494 +//line sql.y:1495 { showTablesOpt := &ShowTablesOpt{Full: yyDollar[2].str, DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter} - yyVAL.statement = &Show{Type: string(yyDollar[3].bytes), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName} + yyVAL.statement = &Show{Type: string(yyDollar[3].str), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName} } - case 266: + case 267: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1499 +//line sql.y:1500 { // this is ugly, but I couldn't find a better way for now if yyDollar[3].str == "processlist" { @@ -4300,618 +4339,650 @@ yydefault: yyVAL.statement = &Show{Type: yyDollar[3].str, ShowTablesOpt: showTablesOpt} } } - case 267: + case 268: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1509 +//line sql.y:1510 { yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } - case 268: + case 269: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1513 +//line sql.y:1514 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 269: + case 270: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1517 +//line sql.y:1518 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 270: + case 271: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1521 +//line sql.y:1522 { // Cannot dereference $4 directly, or else the parser stackcannot be pooled. See yyParsePooled showCollationFilterOpt := yyDollar[4].expr yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: &showCollationFilterOpt} } - case 271: + case 272: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1527 +//line sql.y:1528 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), OnTable: yyDollar[4].tableName} } - case 272: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1531 - { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} - } case 273: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1535 +//line sql.y:1532 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 274: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1539 +//line sql.y:1536 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 275: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1543 +//line sql.y:1540 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 276: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1547 +//line sql.y:1544 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 277: - yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1557 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:1548 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 278: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:1552 + { + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + } + case 279: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:1562 + { + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + } + case 280: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1563 +//line sql.y:1568 { yyVAL.str = string(yyDollar[1].bytes) } - case 279: + case 281: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1567 +//line sql.y:1572 { yyVAL.str = string(yyDollar[1].bytes) } - case 280: + case 282: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1573 +//line sql.y:1578 { yyVAL.str = "" } - case 281: + case 283: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1577 +//line sql.y:1582 { yyVAL.str = "full " } - case 282: + case 284: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:1588 + { + yyVAL.str = string(yyDollar[1].bytes) + } + case 285: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:1592 + { + yyVAL.str = string(yyDollar[1].bytes) + } + case 286: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1583 +//line sql.y:1598 { yyVAL.str = "" } - case 283: + case 287: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1587 +//line sql.y:1602 { yyVAL.str = yyDollar[2].tableIdent.v } - case 284: + case 288: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1591 +//line sql.y:1606 { yyVAL.str = yyDollar[2].tableIdent.v } - case 285: + case 289: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1597 +//line sql.y:1612 { yyVAL.showFilter = nil } - case 286: + case 290: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1601 +//line sql.y:1616 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } - case 287: + case 291: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1605 +//line sql.y:1620 { yyVAL.showFilter = &ShowFilter{Filter: yyDollar[2].expr} } - case 288: + case 292: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1611 +//line sql.y:1626 { yyVAL.str = "" } - case 289: + case 293: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1615 +//line sql.y:1630 { yyVAL.str = SessionStr } - case 290: + case 294: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1619 +//line sql.y:1634 { yyVAL.str = GlobalStr } - case 291: + case 295: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1625 +//line sql.y:1640 { yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } - case 292: + case 296: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1629 +//line sql.y:1644 { yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } - case 293: + case 297: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1635 +//line sql.y:1650 { yyVAL.statement = &Begin{} } - case 294: + case 298: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1639 +//line sql.y:1654 { yyVAL.statement = &Begin{} } - case 295: + case 299: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1645 +//line sql.y:1660 { yyVAL.statement = &Commit{} } - case 296: + case 300: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1651 +//line sql.y:1666 { yyVAL.statement = &Rollback{} } - case 297: + case 301: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1657 +//line sql.y:1672 { yyVAL.statement = &OtherRead{} } - case 298: + case 302: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1661 +//line sql.y:1676 { yyVAL.statement = &OtherRead{} } - case 299: + case 303: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1665 +//line sql.y:1680 { yyVAL.statement = &OtherRead{} } - case 300: + case 304: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1669 +//line sql.y:1684 { yyVAL.statement = &OtherAdmin{} } - case 301: + case 305: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1673 +//line sql.y:1688 { yyVAL.statement = &OtherAdmin{} } - case 302: + case 306: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1677 +//line sql.y:1692 { yyVAL.statement = &OtherAdmin{} } - case 303: + case 307: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1681 +//line sql.y:1696 { yyVAL.statement = &OtherAdmin{} } - case 304: + case 308: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:1702 + { + yyVAL.statement = &DDL{Action: FlushStr} + } + case 309: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1686 +//line sql.y:1706 { setAllowComments(yylex, true) } - case 305: + case 310: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1690 +//line sql.y:1710 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } - case 306: + case 311: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1696 +//line sql.y:1716 { yyVAL.bytes2 = nil } - case 307: + case 312: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1700 +//line sql.y:1720 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } - case 308: + case 313: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1706 +//line sql.y:1726 { yyVAL.str = UnionStr } - case 309: + case 314: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1710 +//line sql.y:1730 { yyVAL.str = UnionAllStr } - case 310: + case 315: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1714 +//line sql.y:1734 { yyVAL.str = UnionDistinctStr } - case 311: + case 316: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1719 +//line sql.y:1739 { yyVAL.str = "" } - case 312: + case 317: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1723 +//line sql.y:1743 { yyVAL.str = SQLNoCacheStr } - case 313: + case 318: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1727 +//line sql.y:1747 { yyVAL.str = SQLCacheStr } - case 314: + case 319: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1732 +//line sql.y:1752 { yyVAL.str = "" } - case 315: + case 320: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1736 +//line sql.y:1756 { yyVAL.str = DistinctStr } - case 316: + case 321: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1741 +//line sql.y:1761 { yyVAL.str = "" } - case 317: + case 322: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1745 +//line sql.y:1765 { yyVAL.str = StraightJoinHint } - case 318: + case 323: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1750 +//line sql.y:1770 { yyVAL.selectExprs = nil } - case 319: + case 324: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1754 +//line sql.y:1774 { yyVAL.selectExprs = yyDollar[1].selectExprs } - case 320: + case 325: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1760 +//line sql.y:1780 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } - case 321: + case 326: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1764 +//line sql.y:1784 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } - case 322: + case 327: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1770 +//line sql.y:1790 { yyVAL.selectExpr = &StarExpr{} } - case 323: + case 328: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1774 +//line sql.y:1794 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } - case 324: + case 329: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1778 +//line sql.y:1798 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } - case 325: + case 330: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1782 +//line sql.y:1802 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } - case 326: + case 331: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1787 +//line sql.y:1807 { yyVAL.colIdent = ColIdent{} } - case 327: + case 332: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1791 +//line sql.y:1811 { yyVAL.colIdent = yyDollar[1].colIdent } - case 328: + case 333: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1795 +//line sql.y:1815 { yyVAL.colIdent = yyDollar[2].colIdent } - case 330: + case 335: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1802 +//line sql.y:1822 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 331: + case 336: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1807 +//line sql.y:1827 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } - case 332: + case 337: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1811 +//line sql.y:1831 { yyVAL.tableExprs = yyDollar[2].tableExprs } - case 333: + case 338: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1817 +//line sql.y:1837 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } - case 334: + case 339: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1821 +//line sql.y:1841 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } - case 337: + case 342: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1831 +//line sql.y:1851 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } - case 338: + case 343: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1835 +//line sql.y:1855 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } - case 339: + case 344: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:1859 + { + // missed alias for subquery + yylex.Error("Every derived table must have its own alias") + return 1 + } + case 345: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1839 +//line sql.y:1865 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } - case 340: + case 346: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1845 +//line sql.y:1871 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } - case 341: + case 347: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1849 +//line sql.y:1875 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } - case 342: + case 348: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1855 +//line sql.y:1881 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 343: + case 349: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1859 +//line sql.y:1885 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 344: + case 350: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1865 +//line sql.y:1891 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } - case 345: + case 351: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1869 +//line sql.y:1895 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } - case 346: + case 352: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1882 +//line sql.y:1908 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 347: + case 353: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1886 +//line sql.y:1912 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 348: + case 354: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1890 +//line sql.y:1916 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 349: + case 355: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1894 +//line sql.y:1920 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} } - case 350: + case 356: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1900 +//line sql.y:1926 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 351: + case 357: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1902 +//line sql.y:1928 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } - case 352: + case 358: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1906 +//line sql.y:1932 { yyVAL.joinCondition = JoinCondition{} } - case 353: + case 359: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1908 +//line sql.y:1934 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 354: + case 360: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1912 +//line sql.y:1938 { yyVAL.joinCondition = JoinCondition{} } - case 355: + case 361: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1914 +//line sql.y:1940 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 356: + case 362: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1917 +//line sql.y:1943 { yyVAL.empty = struct{}{} } - case 357: + case 363: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1919 +//line sql.y:1945 { yyVAL.empty = struct{}{} } - case 358: + case 364: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1922 +//line sql.y:1948 { yyVAL.tableIdent = NewTableIdent("") } - case 359: + case 365: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1926 +//line sql.y:1952 { yyVAL.tableIdent = yyDollar[1].tableIdent } - case 360: + case 366: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1930 +//line sql.y:1956 { yyVAL.tableIdent = yyDollar[2].tableIdent } - case 362: + case 368: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1937 +//line sql.y:1963 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 363: + case 369: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1943 +//line sql.y:1969 { yyVAL.str = JoinStr } - case 364: + case 370: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1947 +//line sql.y:1973 { yyVAL.str = JoinStr } - case 365: + case 371: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1951 +//line sql.y:1977 { yyVAL.str = JoinStr } - case 366: + case 372: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1957 +//line sql.y:1983 { yyVAL.str = StraightJoinStr } - case 367: + case 373: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1963 +//line sql.y:1989 { yyVAL.str = LeftJoinStr } - case 368: + case 374: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1967 +//line sql.y:1993 { yyVAL.str = LeftJoinStr } - case 369: + case 375: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1971 +//line sql.y:1997 { yyVAL.str = RightJoinStr } - case 370: + case 376: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1975 +//line sql.y:2001 { yyVAL.str = RightJoinStr } - case 371: + case 377: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1981 +//line sql.y:2007 { yyVAL.str = NaturalJoinStr } - case 372: + case 378: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1985 +//line sql.y:2011 { if yyDollar[2].str == LeftJoinStr { yyVAL.str = NaturalLeftJoinStr @@ -4919,459 +4990,459 @@ yydefault: yyVAL.str = NaturalRightJoinStr } } - case 373: + case 379: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1995 +//line sql.y:2021 { yyVAL.tableName = yyDollar[2].tableName } - case 374: + case 380: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1999 +//line sql.y:2025 { yyVAL.tableName = yyDollar[1].tableName } - case 375: + case 381: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2005 +//line sql.y:2031 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 376: + case 382: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2009 +//line sql.y:2035 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } - case 377: + case 383: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2014 +//line sql.y:2040 { yyVAL.indexHints = nil } - case 378: + case 384: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2018 +//line sql.y:2044 { yyVAL.indexHints = &IndexHints{Type: UseStr, Indexes: yyDollar[4].columns} } - case 379: + case 385: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2022 +//line sql.y:2048 { yyVAL.indexHints = &IndexHints{Type: IgnoreStr, Indexes: yyDollar[4].columns} } - case 380: + case 386: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2026 +//line sql.y:2052 { yyVAL.indexHints = &IndexHints{Type: ForceStr, Indexes: yyDollar[4].columns} } - case 381: + case 387: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2031 +//line sql.y:2057 { yyVAL.expr = nil } - case 382: + case 388: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2035 +//line sql.y:2061 { yyVAL.expr = yyDollar[2].expr } - case 383: + case 389: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2041 +//line sql.y:2067 { yyVAL.expr = yyDollar[1].expr } - case 384: + case 390: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2045 +//line sql.y:2071 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 385: + case 391: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2049 +//line sql.y:2075 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 386: + case 392: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2053 +//line sql.y:2079 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } - case 387: + case 393: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2057 +//line sql.y:2083 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].str, Expr: yyDollar[1].expr} } - case 388: + case 394: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2061 +//line sql.y:2087 { yyVAL.expr = yyDollar[1].expr } - case 389: + case 395: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2065 +//line sql.y:2091 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } - case 390: + case 396: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2071 +//line sql.y:2097 { yyVAL.str = "" } - case 391: + case 397: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2075 +//line sql.y:2101 { yyVAL.str = string(yyDollar[2].bytes) } - case 392: + case 398: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2081 +//line sql.y:2107 { yyVAL.boolVal = BoolVal(true) } - case 393: + case 399: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2085 +//line sql.y:2111 { yyVAL.boolVal = BoolVal(false) } - case 394: + case 400: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2091 +//line sql.y:2117 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} } - case 395: + case 401: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2095 +//line sql.y:2121 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} } - case 396: + case 402: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2099 +//line sql.y:2125 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} } - case 397: + case 403: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2103 +//line sql.y:2129 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } - case 398: + case 404: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2107 +//line sql.y:2133 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } - case 399: + case 405: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2111 +//line sql.y:2137 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} } - case 400: + case 406: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2115 +//line sql.y:2141 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} } - case 401: + case 407: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2119 +//line sql.y:2145 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} } - case 402: + case 408: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2123 +//line sql.y:2149 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} } - case 403: + case 409: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2127 +//line sql.y:2153 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } - case 404: + case 410: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2133 +//line sql.y:2159 { yyVAL.str = IsNullStr } - case 405: + case 411: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2137 +//line sql.y:2163 { yyVAL.str = IsNotNullStr } - case 406: + case 412: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2141 +//line sql.y:2167 { yyVAL.str = IsTrueStr } - case 407: + case 413: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2145 +//line sql.y:2171 { yyVAL.str = IsNotTrueStr } - case 408: + case 414: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2149 +//line sql.y:2175 { yyVAL.str = IsFalseStr } - case 409: + case 415: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2153 +//line sql.y:2179 { yyVAL.str = IsNotFalseStr } - case 410: + case 416: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2159 +//line sql.y:2185 { yyVAL.str = EqualStr } - case 411: + case 417: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2163 +//line sql.y:2189 { yyVAL.str = LessThanStr } - case 412: + case 418: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2167 +//line sql.y:2193 { yyVAL.str = GreaterThanStr } - case 413: + case 419: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2171 +//line sql.y:2197 { yyVAL.str = LessEqualStr } - case 414: + case 420: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2175 +//line sql.y:2201 { yyVAL.str = GreaterEqualStr } - case 415: + case 421: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2179 +//line sql.y:2205 { yyVAL.str = NotEqualStr } - case 416: + case 422: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2183 +//line sql.y:2209 { yyVAL.str = NullSafeEqualStr } - case 417: + case 423: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2188 +//line sql.y:2214 { yyVAL.expr = nil } - case 418: + case 424: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2192 +//line sql.y:2218 { yyVAL.expr = yyDollar[2].expr } - case 419: + case 425: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2198 +//line sql.y:2224 { yyVAL.colTuple = yyDollar[1].valTuple } - case 420: + case 426: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2202 +//line sql.y:2228 { yyVAL.colTuple = yyDollar[1].subquery } - case 421: + case 427: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2206 +//line sql.y:2232 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } - case 422: + case 428: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2212 +//line sql.y:2238 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } - case 423: + case 429: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2218 +//line sql.y:2244 { yyVAL.exprs = Exprs{yyDollar[1].expr} } - case 424: + case 430: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2222 +//line sql.y:2248 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } - case 425: + case 431: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2228 +//line sql.y:2254 { yyVAL.expr = yyDollar[1].expr } - case 426: + case 432: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2232 +//line sql.y:2258 { yyVAL.expr = yyDollar[1].boolVal } - case 427: + case 433: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2236 +//line sql.y:2262 { yyVAL.expr = yyDollar[1].colName } - case 428: + case 434: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2240 +//line sql.y:2266 { yyVAL.expr = yyDollar[1].expr } - case 429: + case 435: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2244 +//line sql.y:2270 { yyVAL.expr = yyDollar[1].subquery } - case 430: + case 436: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2248 +//line sql.y:2274 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} } - case 431: + case 437: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2252 +//line sql.y:2278 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} } - case 432: + case 438: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2256 +//line sql.y:2282 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} } - case 433: + case 439: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2260 +//line sql.y:2286 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} } - case 434: + case 440: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2264 +//line sql.y:2290 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} } - case 435: + case 441: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2268 +//line sql.y:2294 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} } - case 436: + case 442: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2272 +//line sql.y:2298 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} } - case 437: + case 443: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2276 +//line sql.y:2302 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} } - case 438: + case 444: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2280 +//line sql.y:2306 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 439: + case 445: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2284 +//line sql.y:2310 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 440: + case 446: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2288 +//line sql.y:2314 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} } - case 441: + case 447: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2292 +//line sql.y:2318 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} } - case 442: + case 448: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2296 +//line sql.y:2322 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } - case 443: + case 449: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2300 +//line sql.y:2326 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } - case 444: + case 450: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2304 +//line sql.y:2330 { yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } - case 445: + case 451: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2308 +//line sql.y:2334 { yyVAL.expr = &UnaryExpr{Operator: BinaryStr, Expr: yyDollar[2].expr} } - case 446: + case 452: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2312 +//line sql.y:2338 { yyVAL.expr = &UnaryExpr{Operator: UBinaryStr, Expr: yyDollar[2].expr} } - case 447: + case 453: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2316 +//line sql.y:2342 { yyVAL.expr = &UnaryExpr{Operator: Utf8mb4Str, Expr: yyDollar[2].expr} } - case 448: + case 454: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2320 +//line sql.y:2346 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { yyVAL.expr = num @@ -5379,9 +5450,9 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UPlusStr, Expr: yyDollar[2].expr} } } - case 449: + case 455: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2328 +//line sql.y:2354 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { // Handle double negative @@ -5395,21 +5466,21 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UMinusStr, Expr: yyDollar[2].expr} } } - case 450: + case 456: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2342 +//line sql.y:2368 { yyVAL.expr = &UnaryExpr{Operator: TildaStr, Expr: yyDollar[2].expr} } - case 451: + case 457: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2346 +//line sql.y:2372 { yyVAL.expr = &UnaryExpr{Operator: BangStr, Expr: yyDollar[2].expr} } - case 452: + case 458: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2350 +//line sql.y:2376 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -5417,431 +5488,431 @@ yydefault: // will be non-trivial because of grammar conflicts. yyVAL.expr = &IntervalExpr{Expr: yyDollar[2].expr, Unit: yyDollar[3].colIdent.String()} } - case 457: + case 463: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2368 +//line sql.y:2394 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } - case 458: + case 464: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2372 +//line sql.y:2398 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 459: + case 465: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2376 +//line sql.y:2402 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } - case 460: + case 466: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2386 +//line sql.y:2412 { yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } - case 461: + case 467: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2390 +//line sql.y:2416 { yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } - case 462: + case 468: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2394 +//line sql.y:2420 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 463: + case 469: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2398 +//line sql.y:2424 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 464: + case 470: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2402 +//line sql.y:2428 { yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } - case 465: + case 471: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2406 +//line sql.y:2432 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} } - case 466: + case 472: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:2410 +//line sql.y:2436 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 467: + case 473: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:2414 +//line sql.y:2440 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 468: + case 474: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2418 +//line sql.y:2444 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} } - case 469: + case 475: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:2422 +//line sql.y:2448 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 470: + case 476: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:2426 +//line sql.y:2452 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 471: + case 477: yyDollar = yyS[yypt-9 : yypt+1] - //line sql.y:2430 +//line sql.y:2456 { yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].str} } - case 472: + case 478: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:2434 +//line sql.y:2460 { yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} } - case 473: + case 479: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2438 +//line sql.y:2464 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } - case 474: + case 480: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2442 +//line sql.y:2468 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } - case 475: + case 481: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2452 +//line sql.y:2478 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } - case 476: + case 482: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2456 +//line sql.y:2482 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } - case 477: + case 483: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2460 +//line sql.y:2486 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } - case 478: + case 484: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2464 +//line sql.y:2490 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } - case 479: + case 485: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2469 +//line sql.y:2495 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } - case 480: + case 486: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2474 +//line sql.y:2500 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } - case 481: + case 487: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2479 +//line sql.y:2505 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } - case 482: + case 488: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2484 +//line sql.y:2510 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } - case 485: + case 491: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2498 +//line sql.y:2524 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } - case 486: + case 492: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2502 +//line sql.y:2528 { yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } - case 487: + case 493: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2506 +//line sql.y:2532 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } - case 488: + case 494: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2510 +//line sql.y:2536 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } - case 489: + case 495: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2516 +//line sql.y:2542 { yyVAL.str = "" } - case 490: + case 496: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2520 +//line sql.y:2546 { yyVAL.str = BooleanModeStr } - case 491: + case 497: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2524 +//line sql.y:2550 { yyVAL.str = NaturalLanguageModeStr } - case 492: + case 498: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:2528 +//line sql.y:2554 { yyVAL.str = NaturalLanguageModeWithQueryExpansionStr } - case 493: + case 499: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2532 +//line sql.y:2558 { yyVAL.str = QueryExpansionStr } - case 494: + case 500: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2538 +//line sql.y:2564 { yyVAL.str = string(yyDollar[1].bytes) } - case 495: + case 501: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2542 +//line sql.y:2568 { yyVAL.str = string(yyDollar[1].bytes) } - case 496: + case 502: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2548 +//line sql.y:2574 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 497: + case 503: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2552 +//line sql.y:2578 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Operator: CharacterSetStr} } - case 498: + case 504: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2556 +//line sql.y:2582 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: string(yyDollar[3].bytes)} } - case 499: + case 505: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2560 +//line sql.y:2586 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 500: + case 506: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2564 +//line sql.y:2590 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 501: + case 507: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2568 +//line sql.y:2594 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 502: + case 508: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2574 +//line sql.y:2600 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 503: + case 509: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2578 +//line sql.y:2604 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 504: + case 510: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2582 +//line sql.y:2608 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 505: + case 511: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2586 +//line sql.y:2612 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 506: + case 512: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2590 +//line sql.y:2616 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 507: + case 513: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2594 +//line sql.y:2620 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 508: + case 514: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2598 +//line sql.y:2624 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 509: + case 515: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2603 +//line sql.y:2629 { yyVAL.expr = nil } - case 510: + case 516: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2607 +//line sql.y:2633 { yyVAL.expr = yyDollar[1].expr } - case 511: + case 517: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2612 +//line sql.y:2638 { yyVAL.str = string("") } - case 512: + case 518: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2616 +//line sql.y:2642 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 513: + case 519: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2622 +//line sql.y:2648 { yyVAL.whens = []*When{yyDollar[1].when} } - case 514: + case 520: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2626 +//line sql.y:2652 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 515: + case 521: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2632 +//line sql.y:2658 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 516: + case 522: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2637 +//line sql.y:2663 { yyVAL.expr = nil } - case 517: + case 523: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2641 +//line sql.y:2667 { yyVAL.expr = yyDollar[2].expr } - case 518: + case 524: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2647 +//line sql.y:2673 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } - case 519: + case 525: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2651 +//line sql.y:2677 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } - case 520: + case 526: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2655 +//line sql.y:2681 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } - case 521: + case 527: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2661 +//line sql.y:2687 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 522: + case 528: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2665 +//line sql.y:2691 { yyVAL.expr = NewHexVal(yyDollar[1].bytes) } - case 523: + case 529: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2669 +//line sql.y:2695 { yyVAL.expr = NewBitVal(yyDollar[1].bytes) } - case 524: + case 530: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2673 +//line sql.y:2699 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 525: + case 531: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2677 +//line sql.y:2703 { yyVAL.expr = NewFloatVal(yyDollar[1].bytes) } - case 526: + case 532: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2681 +//line sql.y:2707 { yyVAL.expr = NewHexNum(yyDollar[1].bytes) } - case 527: + case 533: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2685 +//line sql.y:2711 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 528: + case 534: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2689 +//line sql.y:2715 { yyVAL.expr = &NullVal{} } - case 529: + case 535: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2695 +//line sql.y:2721 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -5850,239 +5921,239 @@ yydefault: } yyVAL.expr = NewIntVal([]byte("1")) } - case 530: + case 536: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2704 +//line sql.y:2730 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 531: + case 537: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2708 +//line sql.y:2734 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 532: + case 538: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2713 +//line sql.y:2739 { yyVAL.exprs = nil } - case 533: + case 539: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2717 +//line sql.y:2743 { yyVAL.exprs = yyDollar[3].exprs } - case 534: + case 540: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2722 +//line sql.y:2748 { yyVAL.expr = nil } - case 535: + case 541: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2726 +//line sql.y:2752 { yyVAL.expr = yyDollar[2].expr } - case 536: + case 542: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2731 +//line sql.y:2757 { yyVAL.orderBy = nil } - case 537: + case 543: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2735 +//line sql.y:2761 { yyVAL.orderBy = yyDollar[3].orderBy } - case 538: + case 544: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2741 +//line sql.y:2767 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 539: + case 545: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2745 +//line sql.y:2771 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 540: + case 546: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2751 +//line sql.y:2777 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].str} } - case 541: + case 547: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2756 +//line sql.y:2782 { yyVAL.str = AscScr } - case 542: + case 548: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2760 +//line sql.y:2786 { yyVAL.str = AscScr } - case 543: + case 549: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2764 +//line sql.y:2790 { yyVAL.str = DescScr } - case 544: + case 550: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2769 +//line sql.y:2795 { yyVAL.limit = nil } - case 545: + case 551: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2773 +//line sql.y:2799 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } - case 546: + case 552: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2777 +//line sql.y:2803 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } - case 547: + case 553: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2781 +//line sql.y:2807 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } - case 548: + case 554: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2786 +//line sql.y:2812 { yyVAL.str = "" } - case 549: + case 555: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2790 +//line sql.y:2816 { yyVAL.str = ForUpdateStr } - case 550: + case 556: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2794 +//line sql.y:2820 { yyVAL.str = ShareModeStr } - case 551: + case 557: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2807 +//line sql.y:2833 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 552: + case 558: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2811 +//line sql.y:2837 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 553: + case 559: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2815 +//line sql.y:2841 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Rows: yyDollar[2].selStmt} } - case 554: + case 560: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2820 +//line sql.y:2846 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 555: + case 561: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2824 +//line sql.y:2850 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 556: + case 562: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2828 +//line sql.y:2854 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].selStmt} } - case 557: + case 563: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2835 +//line sql.y:2861 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 558: + case 564: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2839 +//line sql.y:2865 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 559: + case 565: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2843 +//line sql.y:2869 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 560: + case 566: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2847 +//line sql.y:2873 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 561: + case 567: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2852 +//line sql.y:2878 { yyVAL.updateExprs = nil } - case 562: + case 568: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2856 +//line sql.y:2882 { yyVAL.updateExprs = yyDollar[5].updateExprs } - case 563: + case 569: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2862 +//line sql.y:2888 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 564: + case 570: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2866 +//line sql.y:2892 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 565: + case 571: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2872 +//line sql.y:2898 { yyVAL.valTuple = yyDollar[1].valTuple } - case 566: + case 572: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2876 +//line sql.y:2902 { yyVAL.valTuple = ValTuple{} } - case 567: + case 573: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2882 +//line sql.y:2908 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 568: + case 574: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2888 +//line sql.y:2914 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = &ParenExpr{yyDollar[1].valTuple[0]} @@ -6090,306 +6161,312 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 569: + case 575: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2898 +//line sql.y:2924 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 570: + case 576: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2902 +//line sql.y:2928 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 571: + case 577: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2908 +//line sql.y:2934 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 572: + case 578: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2914 +//line sql.y:2940 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } - case 573: + case 579: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2918 +//line sql.y:2944 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } - case 574: + case 580: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2924 +//line sql.y:2950 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("on"))} } - case 575: + case 581: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:2954 + { + yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("off"))} + } + case 582: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2928 +//line sql.y:2958 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: yyDollar[3].expr} } - case 576: + case 583: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2932 +//line sql.y:2962 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Expr: yyDollar[2].expr} } - case 578: + case 585: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2939 +//line sql.y:2969 { yyVAL.bytes = []byte("charset") } - case 580: + case 587: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2946 +//line sql.y:2976 { yyVAL.expr = NewStrVal([]byte(yyDollar[1].colIdent.String())) } - case 581: + case 588: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2950 +//line sql.y:2980 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 582: + case 589: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2954 +//line sql.y:2984 { yyVAL.expr = &Default{} } - case 585: + case 592: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2963 +//line sql.y:2993 { yyVAL.byt = 0 } - case 586: + case 593: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2965 +//line sql.y:2995 { yyVAL.byt = 1 } - case 587: + case 594: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2968 +//line sql.y:2998 { yyVAL.empty = struct{}{} } - case 588: + case 595: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2970 +//line sql.y:3000 { yyVAL.empty = struct{}{} } - case 589: + case 596: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2973 +//line sql.y:3003 { yyVAL.str = "" } - case 590: + case 597: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2975 +//line sql.y:3005 { yyVAL.str = IgnoreStr } - case 591: + case 598: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2979 +//line sql.y:3009 { yyVAL.empty = struct{}{} } - case 592: + case 599: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2981 +//line sql.y:3011 { yyVAL.empty = struct{}{} } - case 593: + case 600: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2983 +//line sql.y:3013 { yyVAL.empty = struct{}{} } - case 594: + case 601: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2985 +//line sql.y:3015 { yyVAL.empty = struct{}{} } - case 595: + case 602: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2987 +//line sql.y:3017 { yyVAL.empty = struct{}{} } - case 596: + case 603: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2989 +//line sql.y:3019 { yyVAL.empty = struct{}{} } - case 597: + case 604: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2991 +//line sql.y:3021 { yyVAL.empty = struct{}{} } - case 598: + case 605: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2993 +//line sql.y:3023 { yyVAL.empty = struct{}{} } - case 599: + case 606: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2995 +//line sql.y:3025 { yyVAL.empty = struct{}{} } - case 600: + case 607: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2997 +//line sql.y:3027 { yyVAL.empty = struct{}{} } - case 601: + case 608: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:3000 +//line sql.y:3030 { yyVAL.empty = struct{}{} } - case 602: + case 609: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3002 +//line sql.y:3032 { yyVAL.empty = struct{}{} } - case 603: + case 610: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3004 +//line sql.y:3034 { yyVAL.empty = struct{}{} } - case 604: + case 611: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3008 +//line sql.y:3038 { yyVAL.empty = struct{}{} } - case 605: + case 612: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3010 +//line sql.y:3040 { yyVAL.empty = struct{}{} } - case 606: + case 613: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:3013 +//line sql.y:3043 { yyVAL.empty = struct{}{} } - case 607: + case 614: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3015 +//line sql.y:3045 { yyVAL.empty = struct{}{} } - case 608: + case 615: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3017 +//line sql.y:3047 { yyVAL.empty = struct{}{} } - case 609: + case 616: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:3020 +//line sql.y:3050 { yyVAL.colIdent = ColIdent{} } - case 610: + case 617: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:3022 +//line sql.y:3052 { yyVAL.colIdent = yyDollar[2].colIdent } - case 611: + case 618: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3026 +//line sql.y:3056 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 612: + case 619: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3030 +//line sql.y:3060 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 614: + case 621: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3037 +//line sql.y:3067 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 615: + case 622: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3043 +//line sql.y:3073 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 616: + case 623: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3047 +//line sql.y:3077 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 618: + case 625: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3054 +//line sql.y:3084 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 818: + case 829: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3279 +//line sql.y:3313 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 819: + case 830: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3288 +//line sql.y:3322 { decNesting(yylex) } - case 820: + case 831: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:3293 +//line sql.y:3327 { forceEOF(yylex) } - case 821: + case 832: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:3298 +//line sql.y:3332 { forceEOF(yylex) } - case 822: + case 833: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3302 +//line sql.y:3336 { forceEOF(yylex) } - case 823: + case 834: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:3306 +//line sql.y:3340 { forceEOF(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 9914eb5b808..a228742861b 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -127,7 +127,7 @@ func forceEOF(yylex interface{}) { %left ON USING %token '(' ',' ')' %token ID HEX STRING INTEGRAL FLOAT HEXNUM VALUE_ARG LIST_ARG COMMENT COMMENT_KEYWORD BIT_LITERAL -%token NULL TRUE FALSE +%token NULL TRUE FALSE OFF // Precedence dictated by mysql. But the vitess grammar is simplified. // Some of these operators don't conflict in our situation. Nevertheless, @@ -156,13 +156,13 @@ func forceEOF(yylex interface{}) { %token JSON_EXTRACT_OP JSON_UNQUOTE_EXTRACT_OP // DDL Tokens -%token CREATE ALTER DROP RENAME ANALYZE ADD +%token CREATE ALTER DROP RENAME ANALYZE ADD FLUSH %token SCHEMA TABLE INDEX VIEW TO IGNORE IF UNIQUE PRIMARY COLUMN SPATIAL FULLTEXT KEY_BLOCK_SIZE %token ACTION CASCADE CONSTRAINT FOREIGN NO REFERENCES RESTRICT %token SHOW DESCRIBE EXPLAIN DATE ESCAPE REPAIR OPTIMIZE TRUNCATE %token MAXVALUE PARTITION REORGANIZE LESS THAN PROCEDURE TRIGGER %token VINDEX VINDEXES -%token STATUS VARIABLES +%token STATUS VARIABLES WARNINGS // Transaction Tokens %token BEGIN START TRANSACTION COMMIT ROLLBACK @@ -180,7 +180,7 @@ func forceEOF(yylex interface{}) { %token NULLX AUTO_INCREMENT APPROXNUM SIGNED UNSIGNED ZEROFILL // Supported SHOW tokens -%token COLLATION DATABASES TABLES VITESS_KEYSPACES VITESS_SHARDS VITESS_TABLETS VSCHEMA_TABLES VITESS_TARGET FULL PROCESSLIST COLUMNS +%token COLLATION DATABASES TABLES VITESS_KEYSPACES VITESS_SHARDS VITESS_TABLETS VSCHEMA_TABLES VITESS_TARGET FULL PROCESSLIST COLUMNS FIELDS // SET tokens %token NAMES CHARSET GLOBAL SESSION ISOLATION LEVEL READ WRITE ONLY REPEATABLE COMMITTED UNCOMMITTED SERIALIZABLE @@ -203,7 +203,7 @@ func forceEOF(yylex interface{}) { %type command %type select_statement base_select union_lhs union_rhs %type stream_statement insert_statement update_statement delete_statement set_statement -%type create_statement alter_statement rename_statement drop_statement truncate_statement +%type create_statement alter_statement rename_statement drop_statement truncate_statement flush_statement %type create_table_prefix %type analyze_statement show_statement use_statement other_statement %type begin_statement commit_statement rollback_statement @@ -258,7 +258,7 @@ func forceEOF(yylex interface{}) { %type isolation_level %type for_from %type ignore_opt default_opt -%type full_opt from_database_opt tables_or_processlist +%type full_opt from_database_opt tables_or_processlist columns_or_fields %type like_or_where_opt %type exists_opt %type not_exists_opt non_add_drop_or_rename_operation to_opt index_opt constraint_opt @@ -340,6 +340,7 @@ command: | commit_statement | rollback_statement | other_statement +| flush_statement | /*empty*/ { setParseTree(yylex, nil) @@ -432,9 +433,9 @@ insert_or_replace: } update_statement: - UPDATE comment_opt table_references SET update_list where_expression_opt order_by_opt limit_opt + UPDATE comment_opt ignore_opt table_references SET update_list where_expression_opt order_by_opt limit_opt { - $$ = &Update{Comments: Comments($2), TableExprs: $3, Exprs: $5, Where: NewWhere(WhereStr, $6), OrderBy: $7, Limit: $8} + $$ = &Update{Comments: Comments($2), Ignore: $3, TableExprs: $4, Exprs: $6, Where: NewWhere(WhereStr, $7), OrderBy: $8, Limit: $9} } delete_statement: @@ -1490,7 +1491,7 @@ show_statement: { $$ = &Show{Type: string($2)} } -| SHOW full_opt COLUMNS FROM table_name from_database_opt like_or_where_opt +| SHOW full_opt columns_or_fields FROM table_name from_database_opt like_or_where_opt { showTablesOpt := &ShowTablesOpt{Full:$2, DbName:$6, Filter:$7} $$ = &Show{Type: string($3), ShowTablesOpt: showTablesOpt, OnTable: $5} @@ -1547,6 +1548,10 @@ show_statement: { $$ = &Show{Type: string($2)} } +| SHOW WARNINGS + { + $$ = &Show{Type: string($2)} + } /* * Catch-all for show statements without vitess keywords: * @@ -1578,6 +1583,16 @@ full_opt: $$ = "full " } +columns_or_fields: + COLUMNS + { + $$ = string($1) + } +| FIELDS + { + $$ = string($1) + } + from_database_opt: /* empty */ { @@ -1682,6 +1697,11 @@ other_statement: $$ = &OtherAdmin{} } +flush_statement: + FLUSH force_eof + { + $$ = &DDL{Action: FlushStr} + } comment_opt: { setAllowComments(yylex, true) @@ -1835,6 +1855,12 @@ table_factor: { $$ = &AliasedTableExpr{Expr:$1, As: $3} } +| subquery + { + // missed alias for subquery + yylex.Error("Every derived table must have its own alias") + return 1 + } | openb table_references closeb { $$ = &ParenTableExpr{Exprs: $2} @@ -2924,6 +2950,10 @@ set_expression: { $$ = &SetExpr{Name: $1, Expr: NewStrVal([]byte("on"))} } +| reserved_sql_id '=' OFF + { + $$ = &SetExpr{Name: $1, Expr: NewStrVal([]byte("off"))} + } | reserved_sql_id '=' expression { $$ = &SetExpr{Name: $1, Expr: $3} @@ -3127,6 +3157,7 @@ reserved_keyword: | NEXT // next should be doable as non-reserved, but is not due to the special `select next num_val` query that vitess supports | NOT | NULL +| OFF | ON | OR | ORDER @@ -3142,7 +3173,6 @@ reserved_keyword: | SHOW | STRAIGHT_JOIN | TABLE -| TABLES | THEN | TO | TRUE @@ -3191,6 +3221,8 @@ non_reserved_keyword: | ENUM | EXPANSION | FLOAT_TYPE +| FIELDS +| FLUSH | FOREIGN | FULLTEXT | GEOMETRY @@ -3245,6 +3277,7 @@ non_reserved_keyword: | SPATIAL | START | STATUS +| TABLES | TEXT | THAN | TIME @@ -3269,6 +3302,7 @@ non_reserved_keyword: | VITESS_TABLETS | VSCHEMA_TABLES | VITESS_TARGET +| WARNINGS | WITH | WRITE | YEAR diff --git a/go/vt/sqlparser/token.go b/go/vt/sqlparser/token.go index 47be2aa9668..2058dcac7ab 100644 --- a/go/vt/sqlparser/token.go +++ b/go/vt/sqlparser/token.go @@ -175,9 +175,11 @@ var keywords = map[string]int{ "expansion": EXPANSION, "false": FALSE, "fetch": UNUSED, + "fields": FIELDS, "float": FLOAT_TYPE, "float4": UNUSED, "float8": UNUSED, + "flush": FLUSH, "for": FOR, "force": FORCE, "foreign": FOREIGN, @@ -270,6 +272,7 @@ var keywords = map[string]int{ "no_write_to_binlog": UNUSED, "null": NULL, "numeric": NUMERIC, + "off": OFF, "offset": OFFSET, "on": ON, "only": ONLY, @@ -389,6 +392,7 @@ var keywords = map[string]int{ "vitess_tablets": VITESS_TABLETS, "vitess_target": VITESS_TARGET, "vschema_tables": VSCHEMA_TABLES, + "warnings": WARNINGS, "when": WHEN, "where": WHERE, "while": UNUSED, diff --git a/go/vt/topo/consultopo/server.go b/go/vt/topo/consultopo/server.go index a9380e87352..56e1026f34a 100644 --- a/go/vt/topo/consultopo/server.go +++ b/go/vt/topo/consultopo/server.go @@ -20,13 +20,28 @@ Package consultopo implements topo.Server with consul as the backend. package consultopo import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" "sync" "github.com/hashicorp/consul/api" + "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/topo" ) +var ( + consulAuthClientStaticFile = flag.String("consul_auth_static_file", "", "JSON File to read the topos/tokens from.") +) + +// ClientAuthCred credential to use for consul clusters +type ClientAuthCred struct { + // ACLToken when provided, the client will use this token when making requests to the Consul server. + ACLToken string `json:"acl_token,omitempty"` +} + // Factory is the consul topo.Factory implementation. type Factory struct{} @@ -37,7 +52,29 @@ func (f Factory) HasGlobalReadOnlyCell(serverAddr, root string) bool { // Create is part of the topo.Factory interface. func (f Factory) Create(cell, serverAddr, root string) (topo.Conn, error) { - return NewServer(serverAddr, root) + return NewServer(cell, serverAddr, root) +} + +func getClientCreds() (creds map[string]*ClientAuthCred, err error) { + creds = make(map[string]*ClientAuthCred) + + if *consulAuthClientStaticFile == "" { + // Not configured, nothing to do. + log.Infof("Consul client auth is not set up. consul_auth_static_file was not provided") + return nil, nil + } + + data, err := ioutil.ReadFile(*consulAuthClientStaticFile) + if err != nil { + err = fmt.Errorf("Failed to read consul_auth_static_file file: %v", err) + return creds, err + } + + if err := json.Unmarshal(data, &creds); err != nil { + err = fmt.Errorf(fmt.Sprintf("Error parsing consul_auth_static_file: %v", err)) + return creds, err + } + return creds, nil } // Server is the implementation of topo.Server for consul. @@ -66,9 +103,18 @@ type lockInstance struct { } // NewServer returns a new consultopo.Server. -func NewServer(serverAddr, root string) (*Server, error) { +func NewServer(cell, serverAddr, root string) (*Server, error) { + creds, err := getClientCreds() + if err != nil { + return nil, err + } cfg := api.DefaultConfig() cfg.Address = serverAddr + if creds != nil && creds[cell] != nil { + cfg.Token = creds[cell].ACLToken + } else { + log.Warningf("Client auth not configured for cell: %v", cell) + } client, err := api.NewClient(cfg) if err != nil { return nil, err diff --git a/go/vt/topo/consultopo/server_test.go b/go/vt/topo/consultopo/server_test.go index d8b098c786c..c914d116be5 100644 --- a/go/vt/topo/consultopo/server_test.go +++ b/go/vt/topo/consultopo/server_test.go @@ -38,7 +38,7 @@ import ( // startConsul starts a consul subprocess, and waits for it to be ready. // Returns the exec.Cmd forked, the config file to remove after the test, // and the server address to RPC-connect to. -func startConsul(t *testing.T) (*exec.Cmd, string, string) { +func startConsul(t *testing.T, authToken string) (*exec.Cmd, string, string) { // Create a temporary config file, as ports cannot all be set // via command line. The file name has to end with '.json' so // we're not using TempFile. @@ -64,6 +64,15 @@ func startConsul(t *testing.T) (*exec.Cmd, string, string) { "serf_wan": port + 3, }, } + + if authToken != "" { + config["datacenter"] = "vitess" + config["acl_datacenter"] = "vitess" + config["acl_master_token"] = authToken + config["acl_default_policy"] = "deny" + config["acl_down_policy"] = "extend-cache" + } + data, err := json.Marshal(config) if err != nil { t.Fatalf("cannot json-encode config: %v", err) @@ -88,6 +97,9 @@ func startConsul(t *testing.T) (*exec.Cmd, string, string) { serverAddr := fmt.Sprintf("localhost:%v", port+1) cfg := api.DefaultConfig() cfg.Address = serverAddr + if authToken != "" { + cfg.Token = authToken + } c, err := api.NewClient(cfg) if err != nil { t.Fatalf("api.NewClient(%v) failed: %v", serverAddr, err) @@ -97,11 +109,12 @@ func startConsul(t *testing.T) (*exec.Cmd, string, string) { start := time.Now() kv := c.KV() for { - if _, _, err := kv.List("/", nil); err == nil { + _, _, err := kv.List("/", nil) + if err == nil { break } if time.Since(start) > 10*time.Second { - t.Fatalf("Failed to start consul daemon in time") + t.Fatalf("Failed to start consul daemon in time. Consul is returning error: %v", err) } time.Sleep(10 * time.Millisecond) } @@ -114,7 +127,7 @@ func TestConsulTopo(t *testing.T) { *watchPollDuration = 100 * time.Millisecond // Start a single consul in the background. - cmd, configFilename, serverAddr := startConsul(t) + cmd, configFilename, serverAddr := startConsul(t, "") defer func() { cmd.Process.Kill() cmd.Wait() @@ -145,3 +158,98 @@ func TestConsulTopo(t *testing.T) { return ts }) } + +func TestConsulTopoWithAuth(t *testing.T) { + // One test is going to wait that full period, so make it shorter. + *watchPollDuration = 100 * time.Millisecond + + // Start a single consul in the background. + cmd, configFilename, serverAddr := startConsul(t, "123456") + defer func() { + cmd.Process.Kill() + cmd.Wait() + os.Remove(configFilename) + }() + + // Run the TopoServerTestSuite tests. + testIndex := 0 + tmpFile, err := ioutil.TempFile("", "consul_auth_client_static_file.json") + + if err != nil { + t.Fatalf("couldn't create temp file: %v", err) + } + defer os.Remove(tmpFile.Name()) + + *consulAuthClientStaticFile = tmpFile.Name() + + jsonConfig := "{\"global\":{\"acl_token\":\"123456\"}, \"test\":{\"acl_token\":\"123456\"}}" + if err := ioutil.WriteFile(tmpFile.Name(), []byte(jsonConfig), 0600); err != nil { + t.Fatalf("couldn't write temp file: %v", err) + } + + test.TopoServerTestSuite(t, func() *topo.Server { + // Each test will use its own sub-directories. + testRoot := fmt.Sprintf("test-%v", testIndex) + testIndex++ + + // Create the server on the new root. + ts, err := topo.OpenServer("consul", serverAddr, path.Join(testRoot, topo.GlobalCell)) + if err != nil { + t.Fatalf("OpenServer() failed: %v", err) + } + + // Create the CellInfo. + if err := ts.CreateCellInfo(context.Background(), test.LocalCellName, &topodatapb.CellInfo{ + ServerAddress: serverAddr, + Root: path.Join(testRoot, test.LocalCellName), + }); err != nil { + t.Fatalf("CreateCellInfo() failed: %v", err) + } + + return ts + }) +} + +func TestConsulTopoWithAuthFailure(t *testing.T) { + // One test is going to wait that full period, so make it shorter. + *watchPollDuration = 100 * time.Millisecond + + // Start a single consul in the background. + cmd, configFilename, serverAddr := startConsul(t, "123456") + defer func() { + cmd.Process.Kill() + cmd.Wait() + os.Remove(configFilename) + }() + + tmpFile, err := ioutil.TempFile("", "consul_auth_client_static_file.json") + + if err != nil { + t.Fatalf("couldn't create temp file: %v", err) + } + defer os.Remove(tmpFile.Name()) + + *consulAuthClientStaticFile = tmpFile.Name() + + jsonConfig := "{\"global\":{\"acl_token\":\"badtoken\"}}" + if err := ioutil.WriteFile(tmpFile.Name(), []byte(jsonConfig), 0600); err != nil { + t.Fatalf("couldn't write temp file: %v", err) + } + + // Create the server on the new root. + ts, err := topo.OpenServer("consul", serverAddr, path.Join("globalRoot", topo.GlobalCell)) + if err != nil { + t.Fatalf("OpenServer() failed: %v", err) + } + + // Attempt to Create the CellInfo. + err = ts.CreateCellInfo(context.Background(), test.LocalCellName, &topodatapb.CellInfo{ + ServerAddress: serverAddr, + Root: path.Join("globalRoot", test.LocalCellName), + }) + + want := "Failed request: ACL not found" + if err == nil || err.Error() != want { + t.Errorf("Expected CreateCellInfo to fail: got %v, want %s", err, want) + } +} diff --git a/go/vt/topo/shard.go b/go/vt/topo/shard.go index a6697b283a2..eff52454207 100644 --- a/go/vt/topo/shard.go +++ b/go/vt/topo/shard.go @@ -440,8 +440,6 @@ func (si *ShardInfo) UpdateDisableQueryService(ctx context.Context, tabletType t DisableQueryService: true, BlacklistedTables: nil, }) - } else { - log.Warningf("Trying to remove TabletControl.DisableQueryService for missing type %v for shard %v/%v", tabletType, si.keyspace, si.shardName) } return nil } @@ -452,12 +450,16 @@ func (si *ShardInfo) UpdateDisableQueryService(ctx context.Context, tabletType t return fmt.Errorf("cannot safely alter DisableQueryService as BlacklistedTables is set") } if !tc.DisableQueryService { + // This code is unreachable because we always delete the control record when we enable QueryService. return fmt.Errorf("cannot safely alter DisableQueryService as DisableQueryService is not set, this record should not be there for shard %v/%v", si.keyspace, si.shardName) } if disableQueryService { tc.Cells = addCells(tc.Cells, cells) } else { + if tc.Frozen { + return fmt.Errorf("migrate has gone past the point of no return, cannot re-enable serving for %v/%v", si.keyspace, si.shardName) + } si.removeCellsFromTabletControl(tc, tabletType, cells) } return nil @@ -501,56 +503,15 @@ func (si *ShardInfo) GetServedTypesPerCell(cell string) []topodatapb.TabletType return result } -// CheckServedTypesMigration makes sure the provided migration is possible -func (si *ShardInfo) CheckServedTypesMigration(tabletType topodatapb.TabletType, cells []string, remove bool) error { - // we can't remove a type we don't have - if si.GetServedType(tabletType) == nil && remove { - return fmt.Errorf("supplied type %v cannot be migrated out of the shard because it is not a served type: %v", tabletType, si) - } - - // master is a special case with a few extra checks - if tabletType == topodatapb.TabletType_MASTER { - if len(cells) > 0 { - return fmt.Errorf("cannot migrate only some cells for MASTER in shard %v/%v. Do not specify a list of cells", si.keyspace, si.shardName) - } - if remove && len(si.ServedTypes) > 1 { - // Log which types must be migrated first. - var types []string - for _, servedType := range si.ServedTypes { - if servedType.TabletType != topodatapb.TabletType_MASTER { - types = append(types, servedType.TabletType.String()) - } - } - return fmt.Errorf("cannot migrate MASTER away from %v/%v until everything else is migrated. Make sure that the following types are migrated first: %v", si.keyspace, si.shardName, strings.Join(types, ", ")) - } - } - - return nil -} - -// UpdateServedTypesMap handles ServedTypesMap. It can add or remove -// records, cells, ... +// UpdateServedTypesMap handles ServedTypesMap. It can add or remove cells. func (si *ShardInfo) UpdateServedTypesMap(tabletType topodatapb.TabletType, cells []string, remove bool) error { - // check parameters to be sure - if err := si.CheckServedTypesMigration(tabletType, cells, remove); err != nil { - return err - } - sst := si.GetServedType(tabletType) - if sst == nil { - // the record doesn't exist - if remove { - log.Warningf("Trying to remove ShardServedType for missing type %v in shard %v/%v", tabletType, si.keyspace, si.shardName) - } else { - si.ServedTypes = append(si.ServedTypes, &topodatapb.Shard_ServedType{ - TabletType: tabletType, - Cells: cells, - }) - } - return nil - } if remove { + if sst == nil { + // nothing to remove + return nil + } result, emptyList := removeCells(sst.Cells, cells, si.Cells) if emptyList { // we don't have any cell left, we need to clear this record @@ -561,12 +522,21 @@ func (si *ShardInfo) UpdateServedTypesMap(tabletType topodatapb.TabletType, cell } } si.ServedTypes = servedTypes - } else { - sst.Cells = result + return nil } - } else { - sst.Cells = addCells(sst.Cells, cells) + sst.Cells = result + return nil + } + + // add + if sst == nil { + si.ServedTypes = append(si.ServedTypes, &topodatapb.Shard_ServedType{ + TabletType: tabletType, + Cells: cells, + }) + return nil } + sst.Cells = addCells(sst.Cells, cells) return nil } diff --git a/go/vt/topo/shard_test.go b/go/vt/topo/shard_test.go index b7652498b42..9323f0c85c4 100644 --- a/go/vt/topo/shard_test.go +++ b/go/vt/topo/shard_test.go @@ -18,7 +18,6 @@ package topo import ( "reflect" - "strings" "testing" "golang.org/x/net/context" @@ -329,29 +328,16 @@ func TestUpdateServedTypesMap(t *testing.T) { t.Fatalf("migrate master failed: %v", err) } - // try to migrate master away, see it fail - if err := si.UpdateServedTypesMap(topodatapb.TabletType_MASTER, nil, true); err == nil || err.Error() != "cannot migrate MASTER away from ks/sh until everything else is migrated. Make sure that the following types are migrated first: RDONLY, REPLICA" { - t.Fatalf("migrate master away unexpected error: %v", err) - } - // Migrate each serving type away from this shard. // RDONLY if err := si.UpdateServedTypesMap(topodatapb.TabletType_RDONLY, nil, true); err != nil { t.Fatalf("remove master failed: %v", err) } - // Cannot migrate a type away (here RDONLY) which is not served (anymore). - if err := si.UpdateServedTypesMap(topodatapb.TabletType_RDONLY, nil, true); err == nil || !strings.HasPrefix(err.Error(), "supplied type RDONLY cannot be migrated out of the shard because it is not a served type: ") { - t.Fatalf("migrate rdonly should have failed because it's already migrated: %v", err) - } // REPLICA if err := si.UpdateServedTypesMap(topodatapb.TabletType_REPLICA, nil, true); err != nil { t.Fatalf("remove master failed: %v", err) } // MASTER - // Migration fails if a list of cells is specified. - if err := si.UpdateServedTypesMap(topodatapb.TabletType_MASTER, []string{"first", "third"}, true); err == nil || err.Error() != "cannot migrate only some cells for MASTER in shard ks/sh. Do not specify a list of cells" { - t.Fatalf("remove master failed: %v", err) - } if err := si.UpdateServedTypesMap(topodatapb.TabletType_MASTER, nil, true); err != nil { t.Fatalf("remove master failed: %v", err) } diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 9fc6b7d7d99..0251e14b010 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -311,6 +311,12 @@ var commands = []commandGroup{ {"MigrateServedFrom", commandMigrateServedFrom, "[-cells=c1,c2,...] [-reverse] ", "Makes the serve the given type. This command also rebuilds the serving graph."}, + {"CancelResharding", commandCancelResharding, + "", + "Permanently cancels a resharding in progress. All resharding related metadata will be deleted."}, + {"ShowResharding", commandShowResharding, + "", + "Displays all metadata about a resharding in progress."}, {"FindAllShardsInKeyspace", commandFindAllShardsInKeyspace, "", "Displays all of the shards in the specified keyspace."}, @@ -1684,6 +1690,7 @@ func commandMigrateServedTypes(ctx context.Context, wr *wrangler.Wrangler, subFl reverse := subFlags.Bool("reverse", false, "Moves the served tablet type backward instead of forward. Use in case of trouble") skipReFreshState := subFlags.Bool("skip-refresh-state", false, "Skips refreshing the state of the source tablets after the migration, meaning that the refresh will need to be done manually, replica and rdonly only)") filteredReplicationWaitTime := subFlags.Duration("filtered_replication_wait_time", 30*time.Second, "Specifies the maximum time to wait, in seconds, for filtered replication to catch up on master migrations") + reverseReplication := subFlags.Bool("reverse_replication", false, "For master migration, enabling this flag reverses replication which allows you to rollback") if err := subFlags.Parse(args); err != nil { return err } @@ -1706,7 +1713,7 @@ func commandMigrateServedTypes(ctx context.Context, wr *wrangler.Wrangler, subFl if *cellsStr != "" { cells = strings.Split(*cellsStr, ",") } - return wr.MigrateServedTypes(ctx, keyspace, shard, cells, servedType, *reverse, *skipReFreshState, *filteredReplicationWaitTime) + return wr.MigrateServedTypes(ctx, keyspace, shard, cells, servedType, *reverse, *skipReFreshState, *filteredReplicationWaitTime, *reverseReplication) } func commandMigrateServedFrom(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { @@ -1735,6 +1742,36 @@ func commandMigrateServedFrom(ctx context.Context, wr *wrangler.Wrangler, subFla return wr.MigrateServedFrom(ctx, keyspace, shard, servedType, cells, *reverse, *filteredReplicationWaitTime) } +func commandCancelResharding(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 1 { + return fmt.Errorf(" required for CancelResharding command") + } + + keyspace, shard, err := topoproto.ParseKeyspaceShard(subFlags.Arg(0)) + if err != nil { + return err + } + return wr.CancelResharding(ctx, keyspace, shard) +} + +func commandShowResharding(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 1 { + return fmt.Errorf(" required for ShowResharding command") + } + + keyspace, shard, err := topoproto.ParseKeyspaceShard(subFlags.Arg(0)) + if err != nil { + return err + } + return wr.ShowResharding(ctx, keyspace, shard) +} + func commandFindAllShardsInKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err diff --git a/go/vt/vtctld/api.go b/go/vt/vtctld/api.go index 645a14bec31..54da31b7653 100644 --- a/go/vt/vtctld/api.go +++ b/go/vt/vtctld/api.go @@ -169,6 +169,52 @@ func initAPI(ctx context.Context, ts *topo.Server, actions *ActionRepository, re } }) + handleCollection("keyspace", func(r *http.Request) (interface{}, error) { + // Valid requests: api/keyspace/my_ks/tablets (all shards) + // Valid requests: api/keyspace/my_ks/tablets/-80 (specific shard) + itemPath := getItemPath(r.URL.Path) + parts := strings.SplitN(itemPath, "/", 3) + + malformedRequestError := fmt.Errorf("invalid keyspace path: %q expected path: /keyspace//tablets or /keyspace//tablets/", itemPath) + if len(parts) < 2 { + return nil, malformedRequestError + } + if parts[1] != "tablets" { + return nil, malformedRequestError + } + + keyspace := parts[0] + if keyspace == "" { + return nil, errors.New("keyspace is required") + } + var shardNames []string + if len(parts) > 2 && parts[2] != "" { + shardNames = []string{parts[2]} + } else { + var err error + shardNames, err = ts.GetShardNames(ctx, keyspace) + if err != nil { + return nil, err + } + } + tablets := [](*topodatapb.Tablet){} + for _, shard := range shardNames { + // Get tablets for this shard. + tabletAliases, err := ts.FindAllTabletAliasesInShard(ctx, keyspace, shard) + if err != nil && !topo.IsErrType(err, topo.PartialResult) { + return nil, err + } + for _, tabletAlias := range tabletAliases { + t, err := ts.GetTablet(ctx, tabletAlias) + if err != nil { + return nil, err + } + tablets = append(tablets, t.Tablet) + } + } + return tablets, nil + }) + // Shards handleCollection("shards", func(r *http.Request) (interface{}, error) { shardPath := getItemPath(r.URL.Path) @@ -454,8 +500,7 @@ func initAPI(ctx context.Context, ts *topo.Server, actions *ActionRepository, re logstream := logutil.NewMemoryLogger() wr := wrangler.New(logstream, ts, tmClient) - // TODO(enisoc): Context for run command should be request-scoped. - err := vtctl.RunCommand(ctx, wr, args) + err := vtctl.RunCommand(r.Context(), wr, args) if err != nil { resp.Error = err.Error() } diff --git a/go/vt/vtexplain/vtexplain.go b/go/vt/vtexplain/vtexplain.go index 8f118ec2f44..8176890a3a2 100644 --- a/go/vt/vtexplain/vtexplain.go +++ b/go/vt/vtexplain/vtexplain.go @@ -21,6 +21,7 @@ package vtexplain import ( "bytes" + "flag" "fmt" "sort" "time" @@ -34,6 +35,10 @@ import ( querypb "vitess.io/vitess/go/vt/proto/query" ) +var ( + batchInterval = flag.Duration("batch-interval", 10*time.Millisecond, "Interval between logical time slots.") +) + // ExecutorMode controls the mode of operation for the vtexplain simulator type ExecutorMode string @@ -164,6 +169,16 @@ func Init(vSchemaStr, sqlSchema string, opts *Options) error { return nil } +// Stop and cleans up fake execution environment +func Stop() { + // Cleanup all created fake dbs. + if explainTopo != nil { + for _, conn := range explainTopo.TabletConns { + conn.db.Close() + } + } +} + func parseSchema(sqlSchema string, opts *Options) ([]*sqlparser.DDL, error) { parsedDDLs := make([]*sqlparser.DDL, 0, 16) for { @@ -238,7 +253,7 @@ func Run(sql string) ([]*Explain, error) { if sql != "" { // Reset the global time simulator for each query - batchTime = sync2.NewBatcher(time.Duration(10 * time.Millisecond)) + batchTime = sync2.NewBatcher(*batchInterval) log.V(100).Infof("explain %s", sql) e, err := explain(sql) if err != nil { diff --git a/go/vt/vtgate/api.go b/go/vt/vtgate/api.go new file mode 100644 index 00000000000..51ea913e0b2 --- /dev/null +++ b/go/vt/vtgate/api.go @@ -0,0 +1,145 @@ +/* +Copyright 2018 GitHub Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreedto 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 ( + "encoding/json" + "fmt" + "net/http" + "strings" + + "golang.org/x/net/context" + "vitess.io/vitess/go/vt/discovery" + "vitess.io/vitess/go/vt/log" +) + +// This file implements a REST-style API for the vtgate web interface. + +const ( + apiPrefix = "/api/" + + jsonContentType = "application/json; charset=utf-8" +) + +func httpErrorf(w http.ResponseWriter, r *http.Request, format string, args ...interface{}) { + errMsg := fmt.Sprintf(format, args...) + log.Errorf("HTTP error on %v: %v, request: %#v", r.URL.Path, errMsg, r) + http.Error(w, errMsg, http.StatusInternalServerError) +} + +func handleAPI(apiPath string, handlerFunc func(w http.ResponseWriter, r *http.Request) error) { + http.HandleFunc(apiPrefix+apiPath, func(w http.ResponseWriter, r *http.Request) { + defer func() { + if x := recover(); x != nil { + httpErrorf(w, r, "uncaught panic: %v", x) + } + }() + if err := handlerFunc(w, r); err != nil { + httpErrorf(w, r, "%v", err) + } + }) +} + +func handleCollection(collection string, getFunc func(*http.Request) (interface{}, error)) { + handleAPI(collection+"/", func(w http.ResponseWriter, r *http.Request) error { + // Get the requested object. + obj, err := getFunc(r) + if err != nil { + return fmt.Errorf("can't get %v: %v", collection, err) + } + + // JSON encode response. + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return fmt.Errorf("cannot marshal data: %v", err) + } + w.Header().Set("Content-Type", jsonContentType) + w.Write(data) + return nil + }) +} + +func getItemPath(url string) string { + // Strip API prefix. + if !strings.HasPrefix(url, apiPrefix) { + return "" + } + url = url[len(apiPrefix):] + + // Strip collection name. + parts := strings.SplitN(url, "/", 2) + if len(parts) != 2 { + return "" + } + return parts[1] +} + +func initAPI(ctx context.Context, hc discovery.HealthCheck) { + // Healthcheck real time status per (cell, keyspace, tablet type, metric). + handleCollection("health-check", func(r *http.Request) (interface{}, error) { + cacheStatus := hc.CacheStatus() + + itemPath := getItemPath(r.URL.Path) + if itemPath == "" { + return cacheStatus, nil + } + parts := strings.SplitN(itemPath, "/", 2) + collectionFilter := parts[0] + if collectionFilter == "" { + return cacheStatus, nil + } + if len(parts) != 2 { + return nil, fmt.Errorf("invalid health-check path: %q expected path: / or /cell/ or /keyspace/ or /tablet/", itemPath) + } + value := parts[1] + + switch collectionFilter { + case "cell": + { + filteredStatus := make(discovery.TabletsCacheStatusList, 0) + for _, tabletCacheStatus := range cacheStatus { + if tabletCacheStatus.Cell == value { + filteredStatus = append(filteredStatus, tabletCacheStatus) + } + } + return filteredStatus, nil + } + case "keyspace": + { + filteredStatus := make(discovery.TabletsCacheStatusList, 0) + for _, tabletCacheStatus := range cacheStatus { + if tabletCacheStatus.Target.Keyspace == value { + filteredStatus = append(filteredStatus, tabletCacheStatus) + } + } + return filteredStatus, nil + } + case "tablet": + { + // Return a _specific tablet_ + for _, tabletCacheStatus := range cacheStatus { + for _, tabletStats := range tabletCacheStatus.TabletsStats { + if tabletStats.Name == value || tabletStats.Tablet.MysqlHostname == value { + return tabletStats, nil + } + } + } + } + } + return nil, fmt.Errorf("cannot find health for: %s", itemPath) + }) +} diff --git a/go/vt/vtgate/engine/delete.go b/go/vt/vtgate/engine/delete.go index 0cf3075b72d..4930d0933fc 100644 --- a/go/vt/vtgate/engine/delete.go +++ b/go/vt/vtgate/engine/delete.go @@ -134,6 +134,11 @@ func (code DeleteOpcode) MarshalJSON() ([]byte, error) { return json.Marshal(delName[code]) } +// RouteType returns a description of the query routing type used by the primitive +func (del *Delete) RouteType() string { + return delName[del.Opcode] +} + // Execute performs a non-streaming exec. func (del *Delete) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { switch del.Opcode { @@ -233,5 +238,6 @@ func (del *Delete) execDeleteByDestination(vcursor VCursor, bindVars map[string] } } autocommit := (len(rss) == 1 || del.MultiShardAutocommit) && vcursor.AutocommitApproval() - return vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) + res, errs := vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) + return res, vterrors.Aggregate(errs) } diff --git a/go/vt/vtgate/engine/fake_primitive_test.go b/go/vt/vtgate/engine/fake_primitive_test.go index cee10a996fc..70c1f7210d1 100644 --- a/go/vt/vtgate/engine/fake_primitive_test.go +++ b/go/vt/vtgate/engine/fake_primitive_test.go @@ -45,6 +45,10 @@ func (f *fakePrimitive) rewind() { f.log = nil } +func (f *fakePrimitive) RouteType() string { + return "Fake" +} + func (f *fakePrimitive) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { f.log = append(f.log, fmt.Sprintf("Execute %v %v", printBindVars(bindVars), wantfields)) if f.results == nil { diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index 17d0699b9d5..c0e11b84b07 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -46,6 +46,9 @@ func (t noopVCursor) SetContextTimeout(timeout time.Duration) context.CancelFunc return func() {} } +func (t noopVCursor) RecordWarning(warning *querypb.QueryWarning) { +} + func (t noopVCursor) Execute(method string, query string, bindvars map[string]*querypb.BindVariable, isDML bool) (*sqltypes.Result, error) { panic("unimplemented") } @@ -54,7 +57,7 @@ func (t noopVCursor) ExecuteAutocommit(method string, query string, bindvars map panic("unimplemented") } -func (t noopVCursor) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, autocommit bool) (*sqltypes.Result, error) { +func (t noopVCursor) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, autocommit bool) (*sqltypes.Result, []error) { panic("unimplemented") } @@ -88,24 +91,40 @@ type loggingVCursor struct { curResult int resultErr error + warnings []*querypb.QueryWarning + + // Optional errors that can be returned from nextResult() alongside the results for + // multi-shard queries + multiShardErrs []error + log []string } func (f *loggingVCursor) Context() context.Context { return context.Background() } + func (f *loggingVCursor) SetContextTimeout(timeout time.Duration) context.CancelFunc { return func() {} } +func (f *loggingVCursor) RecordWarning(warning *querypb.QueryWarning) { + f.warnings = append(f.warnings, warning) +} + func (f *loggingVCursor) Execute(method string, query string, bindvars map[string]*querypb.BindVariable, isDML bool) (*sqltypes.Result, error) { f.log = append(f.log, fmt.Sprintf("Execute %s %v %v", query, printBindVars(bindvars), isDML)) return f.nextResult() } -func (f *loggingVCursor) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, error) { +func (f *loggingVCursor) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, []error) { f.log = append(f.log, fmt.Sprintf("ExecuteMultiShard %v%v %v", printResolvedShardQueries(rss, queries), isDML, canAutocommit)) - return f.nextResult() + res, err := f.nextResult() + if err != nil { + return nil, []error{err} + } + + return res, f.multiShardErrs } func (f *loggingVCursor) AutocommitApproval() bool { @@ -197,10 +216,18 @@ func (f *loggingVCursor) ExpectLog(t *testing.T, want []string) { } } +func (f *loggingVCursor) ExpectWarnings(t *testing.T, want []*querypb.QueryWarning) { + t.Helper() + if !reflect.DeepEqual(f.warnings, want) { + t.Errorf("vc.warnings:\n%+v\nwant:\n%+v", f.warnings, want) + } +} + func (f *loggingVCursor) Rewind() { f.curShardForKsid = 0 f.curResult = 0 f.log = nil + f.warnings = nil } func (f *loggingVCursor) nextResult() (*sqltypes.Result, error) { diff --git a/go/vt/vtgate/engine/insert.go b/go/vt/vtgate/engine/insert.go index 80696fcc2d5..72d5e20da56 100644 --- a/go/vt/vtgate/engine/insert.go +++ b/go/vt/vtgate/engine/insert.go @@ -153,6 +153,11 @@ func (code InsertOpcode) MarshalJSON() ([]byte, error) { return json.Marshal(insName[code]) } +// RouteType returns a description of the query routing type used by the primitive +func (ins *Insert) RouteType() string { + return insName[ins.Opcode] +} + // Execute performs a non-streaming exec. func (ins *Insert) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { switch ins.Opcode { @@ -215,9 +220,9 @@ func (ins *Insert) execInsertSharded(vcursor VCursor, bindVars map[string]*query } autocommit := (len(rss) == 1 || ins.MultiShardAutocommit) && vcursor.AutocommitApproval() - result, err := vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) - if err != nil { - return nil, vterrors.Wrap(err, "execInsertSharded") + result, errs := vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) + if errs != nil { + return nil, vterrors.Wrap(vterrors.Aggregate(errs), "execInsertSharded") } if insertID != 0 { diff --git a/go/vt/vtgate/engine/join.go b/go/vt/vtgate/engine/join.go index 9bb03c6a5f3..e6f3e6e629b 100644 --- a/go/vt/vtgate/engine/join.go +++ b/go/vt/vtgate/engine/join.go @@ -218,6 +218,11 @@ func (code JoinOpcode) MarshalJSON() ([]byte, error) { return ([]byte)(fmt.Sprintf("\"%s\"", code.String())), nil } +// RouteType returns a description of the query routing type used by the primitive +func (jn *Join) RouteType() string { + return "Join" +} + func combineVars(bv1, bv2 map[string]*querypb.BindVariable) map[string]*querypb.BindVariable { out := make(map[string]*querypb.BindVariable) for k, v := range bv1 { diff --git a/go/vt/vtgate/engine/limit.go b/go/vt/vtgate/engine/limit.go index 28d6cec5451..f357c412a08 100644 --- a/go/vt/vtgate/engine/limit.go +++ b/go/vt/vtgate/engine/limit.go @@ -52,6 +52,11 @@ func (l *Limit) MarshalJSON() ([]byte, error) { return json.Marshal(marshalLimit) } +// RouteType returns a description of the query routing type used by the primitive +func (l *Limit) RouteType() string { + return l.Input.RouteType() +} + // Execute satisfies the Primtive interface. func (l *Limit) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { count, err := l.fetchCount(bindVars) diff --git a/go/vt/vtgate/engine/ordered_aggregate.go b/go/vt/vtgate/engine/ordered_aggregate.go index 88b0a629e97..ebaf630c0fa 100644 --- a/go/vt/vtgate/engine/ordered_aggregate.go +++ b/go/vt/vtgate/engine/ordered_aggregate.go @@ -91,6 +91,11 @@ func (code AggregateOpcode) MarshalJSON() ([]byte, error) { return ([]byte)(fmt.Sprintf("\"%s\"", code.String())), nil } +// RouteType returns a description of the query routing type used by the primitive +func (oa *OrderedAggregate) RouteType() string { + return oa.Input.RouteType() +} + // Execute is a Primitive function. func (oa *OrderedAggregate) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { qr, err := oa.execute(vcursor, bindVars, wantfields) diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index abb2b4d34b5..6760c42dd62 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -46,13 +46,16 @@ type VCursor interface { // SetContextTimeout updates the context and sets a timeout. SetContextTimeout(timeout time.Duration) context.CancelFunc + // RecordWarning stores the given warning in the current session + RecordWarning(warning *querypb.QueryWarning) + // V3 functions. Execute(method string, query string, bindvars map[string]*querypb.BindVariable, isDML bool) (*sqltypes.Result, error) ExecuteAutocommit(method string, query string, bindvars map[string]*querypb.BindVariable, isDML bool) (*sqltypes.Result, error) AutocommitApproval() bool // Shard-level functions. - ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, error) + ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, []error) ExecuteStandalone(query string, bindvars map[string]*querypb.BindVariable, rs *srvtopo.ResolvedShard) (*sqltypes.Result, error) StreamExecuteMulti(query string, rss []*srvtopo.ResolvedShard, bindVars []map[string]*querypb.BindVariable, callback func(reply *sqltypes.Result) error) error @@ -119,6 +122,7 @@ func (p *Plan) Size() int { // Primitive is the interface that needs to be satisfied by // all primitives of a plan. type Primitive interface { + RouteType() string Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) StreamExecute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantields bool, callback func(*sqltypes.Result) error) error GetFields(vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index fcaccac8acf..c2ab138b9f8 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -23,7 +23,9 @@ import ( "time" "vitess.io/vitess/go/jsonutil" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/srvtopo" "vitess.io/vitess/go/vt/vterrors" @@ -71,6 +73,9 @@ type Route struct { // QueryTimeout contains the optional timeout (in milliseconds) to apply to this query QueryTimeout int + + // ScatterErrorsAsWarnings is true if results should be returned even if some shards have an error + ScatterErrorsAsWarnings bool } // OrderbyParams specifies the parameters for ordering. @@ -88,25 +93,27 @@ func (route *Route) MarshalJSON() ([]byte, error) { vindexName = route.Vindex.String() } marshalRoute := struct { - Opcode RouteOpcode - Keyspace *vindexes.Keyspace `json:",omitempty"` - Query string `json:",omitempty"` - FieldQuery string `json:",omitempty"` - Vindex string `json:",omitempty"` - Values []sqltypes.PlanValue `json:",omitempty"` - OrderBy []OrderbyParams `json:",omitempty"` - TruncateColumnCount int `json:",omitempty"` - QueryTimeout int `json:",omitempty"` + Opcode RouteOpcode + Keyspace *vindexes.Keyspace `json:",omitempty"` + Query string `json:",omitempty"` + FieldQuery string `json:",omitempty"` + Vindex string `json:",omitempty"` + Values []sqltypes.PlanValue `json:",omitempty"` + OrderBy []OrderbyParams `json:",omitempty"` + TruncateColumnCount int `json:",omitempty"` + QueryTimeout int `json:",omitempty"` + ScatterErrorsAsWarnings bool `json:",omitempty"` }{ - Opcode: route.Opcode, - Keyspace: route.Keyspace, - Query: route.Query, - FieldQuery: route.FieldQuery, - Vindex: vindexName, - Values: route.Values, - OrderBy: route.OrderBy, - TruncateColumnCount: route.TruncateColumnCount, - QueryTimeout: route.QueryTimeout, + Opcode: route.Opcode, + Keyspace: route.Keyspace, + Query: route.Query, + FieldQuery: route.FieldQuery, + Vindex: vindexName, + Values: route.Values, + OrderBy: route.OrderBy, + TruncateColumnCount: route.TruncateColumnCount, + QueryTimeout: route.QueryTimeout, + ScatterErrorsAsWarnings: route.ScatterErrorsAsWarnings, } return jsonutil.MarshalNoEscape(marshalRoute) } @@ -152,12 +159,21 @@ var routeName = map[RouteOpcode]string{ SelectDBA: "SelectDBA", } +var ( + partialSuccessScatterQueries = stats.NewCounter("PartialSuccessScatterQueries", "Count of partially successful scatter queries") +) + // MarshalJSON serializes the RouteOpcode as a JSON string. // It's used for testing and diagnostics. func (code RouteOpcode) MarshalJSON() ([]byte, error) { return json.Marshal(routeName[code]) } +// RouteType returns a description of the query routing type used by the primitive +func (route *Route) RouteType() string { + return routeName[route.Opcode] +} + // Execute performs a non-streaming exec. func (route *Route) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { if route.QueryTimeout != 0 { @@ -204,9 +220,22 @@ func (route *Route) execute(vcursor VCursor, bindVars map[string]*querypb.BindVa } queries := getQueries(route.Query, bvs) - result, err := vcursor.ExecuteMultiShard(rss, queries, false /* isDML */, false /* autocommit */) - if err != nil { - return nil, err + result, errs := vcursor.ExecuteMultiShard(rss, queries, false /* isDML */, false /* autocommit */) + + if errs != nil { + if route.ScatterErrorsAsWarnings { + partialSuccessScatterQueries.Add(1) + + for _, err := range errs { + if err != nil { + serr := mysql.NewSQLErrorFromError(err).(*mysql.SQLError) + vcursor.RecordWarning(&querypb.QueryWarning{Code: uint32(serr.Num), Message: err.Error()}) + } + } + // fall through + } else { + return nil, vterrors.Aggregate(errs) + } } if len(route.OrderBy) == 0 { return result, nil @@ -416,12 +445,13 @@ func execAnyShard(vcursor VCursor, query string, bindVars map[string]*querypb.Bi func execShard(vcursor VCursor, query string, bindVars map[string]*querypb.BindVariable, rs *srvtopo.ResolvedShard, isDML, canAutocommit bool) (*sqltypes.Result, error) { autocommit := canAutocommit && vcursor.AutocommitApproval() - return vcursor.ExecuteMultiShard([]*srvtopo.ResolvedShard{rs}, []*querypb.BoundQuery{ + result, errs := vcursor.ExecuteMultiShard([]*srvtopo.ResolvedShard{rs}, []*querypb.BoundQuery{ { Sql: query, BindVariables: bindVars, }, }, isDML, autocommit) + return result, vterrors.Aggregate(errs) } func getQueries(query string, bvs []map[string]*querypb.BindVariable) []*querypb.BoundQuery { diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go index ad77cdb9f2d..7aaf3fb3ce7 100644 --- a/go/vt/vtgate/engine/route_test.go +++ b/go/vt/vtgate/engine/route_test.go @@ -20,10 +20,10 @@ import ( "errors" "testing" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/vtgate/vindexes" - querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/vtgate/vindexes" ) var defaultSelectResult = sqltypes.MakeTestResult( @@ -782,6 +782,7 @@ func TestParamsFail(t *testing.T) { } func TestExecFail(t *testing.T) { + // Unsharded error sel := &Route{ Opcode: SelectUnsharded, Keyspace: &vindexes.Keyspace{ @@ -792,11 +793,110 @@ func TestExecFail(t *testing.T) { FieldQuery: "dummy_select_field", } - vc := &loggingVCursor{shards: []string{"0"}, resultErr: errors.New("result error")} + vc := &loggingVCursor{shards: []string{"0"}, resultErr: mysql.NewSQLError(mysql.ERQueryInterrupted, "", "query timeout")} _, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) - expectError(t, "sel.Execute err", err, "result error") + expectError(t, "sel.Execute err", err, "query timeout (errno 1317) (sqlstate HY000)") + vc.ExpectWarnings(t, nil) vc.Rewind() _, err = wrapStreamExecute(sel, vc, map[string]*querypb.BindVariable{}, false) - expectError(t, "sel.StreamExecute err", err, "result error") + expectError(t, "sel.StreamExecute err", err, "query timeout (errno 1317) (sqlstate HY000)") + + // Scatter fails if one of N fails without ScatterErrorsAsWarnings + sel = &Route{ + Opcode: SelectScatter, + Keyspace: &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + Query: "dummy_select", + FieldQuery: "dummy_select_field", + } + + vc = &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + multiShardErrs: []error{ + errors.New("result error -20"), + }, + } + _, err = sel.Execute(vc, map[string]*querypb.BindVariable{}, false) + expectError(t, "sel.Execute err", err, "result error -20") + vc.ExpectWarnings(t, nil) + vc.ExpectLog(t, []string{ + `ResolveDestinations ks [] Destinations:DestinationAllShards()`, + `ExecuteMultiShard ks.-20: dummy_select {} ks.20-: dummy_select {} false false`, + }) + + vc.Rewind() + + // Scatter succeeds if all shards fail with ScatterErrorsAsWarnings + sel = &Route{ + Opcode: SelectScatter, + Keyspace: &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + Query: "dummy_select", + FieldQuery: "dummy_select_field", + ScatterErrorsAsWarnings: true, + } + + vc = &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + multiShardErrs: []error{ + mysql.NewSQLError(mysql.ERQueryInterrupted, "", "query timeout -20"), + errors.New("not a sql error 20-"), + }, + } + _, err = sel.Execute(vc, map[string]*querypb.BindVariable{}, false) + if err != nil { + t.Errorf("unexpected ScatterErrorsAsWarnings error %v", err) + } + + // Ensure that the error code is preserved from SQLErrors and that it + // turns into ERUnknownError for all others + vc.ExpectWarnings(t, []*querypb.QueryWarning{ + {Code: mysql.ERQueryInterrupted, Message: "query timeout -20 (errno 1317) (sqlstate HY000)"}, + {Code: mysql.ERUnknownError, Message: "not a sql error 20-"}, + }) + vc.ExpectLog(t, []string{ + `ResolveDestinations ks [] Destinations:DestinationAllShards()`, + `ExecuteMultiShard ks.-20: dummy_select {} ks.20-: dummy_select {} false false`, + }) + + vc.Rewind() + + // Scatter succeeds if one of N fails with ScatterErrorsAsWarnings + sel = &Route{ + Opcode: SelectScatter, + Keyspace: &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + Query: "dummy_select", + FieldQuery: "dummy_select_field", + ScatterErrorsAsWarnings: true, + } + + vc = &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + multiShardErrs: []error{ + errors.New("result error -20"), + nil, + }, + } + result, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) + if err != nil { + t.Errorf("unexpected ScatterErrorsAsWarnings error %v", err) + } + vc.ExpectLog(t, []string{ + `ResolveDestinations ks [] Destinations:DestinationAllShards()`, + `ExecuteMultiShard ks.-20: dummy_select {} ks.20-: dummy_select {} false false`, + }) + expectResult(t, "sel.Execute", result, defaultSelectResult) + + vc.Rewind() } diff --git a/go/vt/vtgate/engine/subquery.go b/go/vt/vtgate/engine/subquery.go index 8c6c17d8894..0bd7f2735e8 100644 --- a/go/vt/vtgate/engine/subquery.go +++ b/go/vt/vtgate/engine/subquery.go @@ -31,6 +31,11 @@ type Subquery struct { Subquery Primitive } +// RouteType returns a description of the query routing type used by the primitive +func (sq *Subquery) RouteType() string { + return sq.Subquery.RouteType() +} + // Execute performs a non-streaming exec. func (sq *Subquery) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { inner, err := sq.Subquery.Execute(vcursor, bindVars, wantfields) diff --git a/go/vt/vtgate/engine/update.go b/go/vt/vtgate/engine/update.go index b2f17fe4c75..6f013541b3a 100644 --- a/go/vt/vtgate/engine/update.go +++ b/go/vt/vtgate/engine/update.go @@ -129,6 +129,11 @@ func (code UpdateOpcode) MarshalJSON() ([]byte, error) { return json.Marshal(updName[code]) } +// RouteType returns a description of the query routing type used by the primitive +func (upd *Update) RouteType() string { + return updName[upd.Opcode] +} + // Execute performs a non-streaming exec. func (upd *Update) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { switch upd.Opcode { @@ -246,5 +251,6 @@ func (upd *Update) execUpdateByDestination(vcursor VCursor, bindVars map[string] } } autocommit := (len(rss) == 1 || upd.MultiShardAutocommit) && vcursor.AutocommitApproval() - return vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) + result, errs := vcursor.ExecuteMultiShard(rss, queries, true /* isDML */, autocommit) + return result, vterrors.Aggregate(errs) } diff --git a/go/vt/vtgate/engine/vindex_func.go b/go/vt/vtgate/engine/vindex_func.go index 86a25070f0a..fa7b19b22fe 100644 --- a/go/vt/vtgate/engine/vindex_func.go +++ b/go/vt/vtgate/engine/vindex_func.go @@ -79,6 +79,11 @@ func (code VindexOpcode) MarshalJSON() ([]byte, error) { return json.Marshal(vindexOpcodeName[code]) } +// RouteType returns a description of the query routing type used by the primitive +func (vf *VindexFunc) RouteType() string { + return vindexOpcodeName[vf.Opcode] +} + // Execute performs a non-streaming exec. func (vf *VindexFunc) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { return vf.mapVindex(vcursor, bindVars) diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 0ff13d4c5e9..12671d3f191 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -57,6 +57,9 @@ import ( var ( errNoKeyspace = vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "no keyspace in database name specified. Supported database name format (items in <> are optional): keyspace<:shard><@type> or keyspace<[range]><@type>") defaultTabletType topodatapb.TabletType + + queriesProcessed = stats.NewCountersWithSingleLabel("QueriesProcessed", "Queries processed at vtgate by plan type", "Plan") + queriesRouted = stats.NewCountersWithSingleLabel("QueriesRouted", "Queries routed from vtgate to vttablet by plan type", "Plan") ) func init() { @@ -156,6 +159,17 @@ func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql st stmtType := sqlparser.Preview(sql) logStats.StmtType = sqlparser.StmtType(stmtType) + // Mysql warnings are scoped to the current session, but are + // cleared when a "non-diagnostic statement" is executed: + // https://dev.mysql.com/doc/refman/8.0/en/show-warnings.html + // + // To emulate this behavior, clear warnings from the session + // for all statements _except_ SHOW, so that SHOW WARNINGS + // can actually return them. + if stmtType != sqlparser.StmtShow { + safeSession.ClearWarnings() + } + switch stmtType { case sqlparser.StmtSelect: return e.handleExec(ctx, safeSession, sql, bindVars, destKeyspace, destTabletType, dest, logStats) @@ -229,6 +243,8 @@ func (e *Executor) handleExec(ctx context.Context, safeSession *SafeSession, sql // TODO(sougou): change this flow to go through V3 functions // which will allow us to benefit from the autocommitable flag. + queriesProcessed.Add("ShardDirect", 1) + if destKeyspace == "" { return nil, errNoKeyspace } @@ -259,6 +275,7 @@ func (e *Executor) handleExec(ctx context.Context, safeSession *SafeSession, sql logStats.BindVariables = bindVars result, err := e.destinationExec(ctx, safeSession, sql, bindVars, dest, destKeyspace, destTabletType, logStats) logStats.ExecuteTime = time.Now().Sub(execStart) + queriesRouted.Add("ShardDirect", int64(logStats.ShardQueries)) return result, err } @@ -282,7 +299,11 @@ func (e *Executor) handleExec(ctx context.Context, safeSession *SafeSession, sql } qr, err := plan.Instructions.Execute(vcursor, bindVars, true) + logStats.ExecuteTime = time.Since(execStart) + queriesProcessed.Add(plan.Instructions.RouteType(), 1) + queriesRouted.Add(plan.Instructions.RouteType(), int64(logStats.ShardQueries)) + var errCount uint64 if err != nil { logStats.Error = err @@ -337,6 +358,10 @@ func (e *Executor) handleDDL(ctx context.Context, safeSession *SafeSession, sql logStats.PlanTime = execStart.Sub(logStats.StartTime) result, err := e.destinationExec(ctx, safeSession, sql, bindVars, dest, destKeyspace, destTabletType, logStats) logStats.ExecuteTime = time.Since(execStart) + + queriesProcessed.Add("DDL", 1) + queriesRouted.Add("DDL", int64(logStats.ShardQueries)) + return result, err } @@ -493,6 +518,9 @@ func (e *Executor) handleBegin(ctx context.Context, safeSession *SafeSession, sq logStats.PlanTime = execStart.Sub(logStats.StartTime) err := e.txConn.Begin(ctx, safeSession) logStats.ExecuteTime = time.Since(execStart) + + queriesProcessed.Add("Begin", 1) + return &sqltypes.Result{}, err } @@ -500,6 +528,8 @@ func (e *Executor) handleCommit(ctx context.Context, safeSession *SafeSession, s execStart := time.Now() logStats.PlanTime = execStart.Sub(logStats.StartTime) logStats.ShardQueries = uint32(len(safeSession.ShardSessions)) + queriesProcessed.Add("Commit", 1) + queriesRouted.Add("Commit", int64(logStats.ShardQueries)) err := e.txConn.Commit(ctx, safeSession) logStats.CommitTime = time.Since(execStart) return &sqltypes.Result{}, err @@ -509,6 +539,8 @@ func (e *Executor) handleRollback(ctx context.Context, safeSession *SafeSession, execStart := time.Now() logStats.PlanTime = execStart.Sub(logStats.StartTime) logStats.ShardQueries = uint32(len(safeSession.ShardSessions)) + queriesProcessed.Add("Rollback", 1) + queriesRouted.Add("Rollback", int64(logStats.ShardQueries)) err := e.txConn.Rollback(ctx, safeSession) logStats.CommitTime = time.Since(execStart) return &sqltypes.Result{}, err @@ -948,7 +980,28 @@ func (e *Executor) handleShow(ctx context.Context, safeSession *SafeSession, sql Rows: rows, RowsAffected: uint64(len(rows)), }, nil + case sqlparser.KeywordString(sqlparser.WARNINGS): + fields := []*querypb.Field{ + {Name: "Level", Type: sqltypes.VarChar}, + {Name: "Type", Type: sqltypes.Uint16}, + {Name: "Message", Type: sqltypes.VarChar}, + } + rows := make([][]sqltypes.Value, 0, 0) + + if safeSession.Warnings != nil { + for _, warning := range safeSession.Warnings { + rows = append(rows, []sqltypes.Value{ + sqltypes.NewVarChar("Warning"), + sqltypes.NewUint32(warning.Code), + sqltypes.NewVarChar(warning.Message), + }) + } + } + return &sqltypes.Result{ + Fields: fields, + Rows: rows, + }, nil } // Any other show statement is passed through @@ -1004,6 +1057,10 @@ func (e *Executor) handleOther(ctx context.Context, safeSession *SafeSession, sq } execStart := time.Now() result, err := e.destinationExec(ctx, safeSession, sql, bindVars, dest, destKeyspace, destTabletType, logStats) + + queriesProcessed.Add("Other", 1) + queriesRouted.Add("Other", int64(logStats.ShardQueries)) + logStats.ExecuteTime = time.Since(execStart) return result, err } diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index b7c30fc48c4..0499b0d60b6 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -31,6 +31,7 @@ import ( 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" ) func TestSelectNext(t *testing.T) { @@ -231,7 +232,7 @@ func TestStreamBuffering(t *testing.T) { } func TestSelectBindvars(t *testing.T) { - executor, sbc1, sbc2, _ := createExecutorEnv() + executor, sbc1, sbc2, lookup := createExecutorEnv() logChan := QueryLogger.Subscribe("Test") defer QueryLogger.Unsubscribe(logChan) @@ -255,6 +256,7 @@ func TestSelectBindvars(t *testing.T) { sbc1.Queries = nil testQueryLog(t, logChan, "TestExecute", "SELECT", sql, 1) + // Test with StringBindVariable sql = "select id from user where name in (:name1, :name2)" _, err = executorExec(executor, sql, map[string]*querypb.BindVariable{ "name1": sqltypes.StringBindVariable("foo1"), @@ -279,6 +281,7 @@ func TestSelectBindvars(t *testing.T) { testQueryLog(t, logChan, "VindexLookup", "SELECT", "select user_id from name_user_map where name = :name", 1) testQueryLog(t, logChan, "TestExecute", "SELECT", sql, 1) + // Test with BytesBindVariable sql = "select id from user where name in (:name1, :name2)" _, err = executorExec(executor, sql, map[string]*querypb.BindVariable{ "name1": sqltypes.BytesBindVariable([]byte("foo1")), @@ -302,6 +305,51 @@ func TestSelectBindvars(t *testing.T) { testQueryLog(t, logChan, "VindexLookup", "SELECT", "select user_id from name_user_map where name = :name", 1) testQueryLog(t, logChan, "VindexLookup", "SELECT", "select user_id from name_user_map where name = :name", 1) testQueryLog(t, logChan, "TestExecute", "SELECT", sql, 1) + + // Test no match in the lookup vindex + sbc1.Queries = nil + lookup.Queries = nil + lookup.SetResults([]*sqltypes.Result{{ + Fields: []*querypb.Field{ + {Name: "user_id", Type: sqltypes.Int32}, + }, + RowsAffected: 0, + InsertID: 0, + Rows: [][]sqltypes.Value{}, + }}) + + sql = "select id from user where name = :name" + _, err = executorExec(executor, sql, map[string]*querypb.BindVariable{ + "name": sqltypes.StringBindVariable("nonexistent"), + }) + if err != nil { + t.Error(err) + } + + // When there are no matching rows in the vindex, vtgate still needs the field info + wantQueries = []*querypb.BoundQuery{{ + Sql: "select id from user where 1 != 1", + BindVariables: map[string]*querypb.BindVariable{ + "name": sqltypes.StringBindVariable("nonexistent"), + }, + }} + if !reflect.DeepEqual(sbc1.Queries, wantQueries) { + t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) + } + + wantLookupQueries := []*querypb.BoundQuery{{ + Sql: "select user_id from name_user_map where name = :name", + BindVariables: map[string]*querypb.BindVariable{ + "name": sqltypes.StringBindVariable("nonexistent"), + }, + }} + if !reflect.DeepEqual(lookup.Queries, wantLookupQueries) { + t.Errorf("lookup.Queries: %+v, want %+v\n", lookup.Queries, wantLookupQueries) + } + + testQueryLog(t, logChan, "VindexLookup", "SELECT", "select user_id from name_user_map where name = :name", 1) + testQueryLog(t, logChan, "TestExecute", "SELECT", sql, 1) + } func TestSelectEqual(t *testing.T) { @@ -735,6 +783,67 @@ func TestSelectScatter(t *testing.T) { testQueryLog(t, logChan, "TestExecute", "SELECT", wantQueries[0].Sql, 8) } +func TestSelectScatterPartial(t *testing.T) { + // Special setup: Don't use createExecutorEnv. + cell := "aa" + hc := discovery.NewFakeHealthCheck() + s := createSandbox("TestExecutor") + s.VSchema = executorVSchema + getSandbox(KsTestUnsharded).VSchema = unshardedVSchema + serv := new(sandboxTopo) + resolver := newTestResolver(hc, serv, cell) + shards := []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"} + var conns []*sandboxconn.SandboxConn + for _, shard := range shards { + sbc := hc.AddTestTablet(cell, shard, 1, "TestExecutor", shard, topodatapb.TabletType_MASTER, true, 1, nil) + conns = append(conns, sbc) + } + + executor := NewExecutor(context.Background(), serv, cell, "", resolver, false, testBufferSize, testCacheSize, false) + logChan := QueryLogger.Subscribe("Test") + defer QueryLogger.Unsubscribe(logChan) + + // Fail 1 of N without the directive fails the whole operation + conns[2].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + results, err := executorExec(executor, "select id from user", nil) + wantErr := "target: TestExecutor.40-60.master, used tablet: aa-0 (40-60), RESOURCE_EXHAUSTED error" + if err == nil || err.Error() != wantErr { + t.Errorf("want error %v, got %v", wantErr, err) + } + if results != nil { + t.Errorf("want nil results, got %v", results) + } + testQueryLog(t, logChan, "TestExecute", "SELECT", "select id from user", 8) + + // Fail 1 of N with the directive succeeds with 7 rows + results, err = executorExec(executor, "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ id from user", nil) + if err != nil { + t.Error(err) + } + if results == nil || len(results.Rows) != 7 { + t.Errorf("want 7 results, got %v", results) + } + testQueryLog(t, logChan, "TestExecute", "SELECT", "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ id from user", 8) + + // Even if all shards fail the operation succeeds with 0 rows + conns[0].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[1].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[3].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[4].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[5].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[6].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + conns[7].MustFailCodes[vtrpcpb.Code_RESOURCE_EXHAUSTED] = 1000 + + results, err = executorExec(executor, "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ id from user", nil) + if err != nil { + t.Error(err) + } + if results == nil || len(results.Rows) != 0 { + t.Errorf("want 0 result rows, got %v", results) + } + testQueryLog(t, logChan, "TestExecute", "SELECT", "select /*vt+ SCATTER_ERRORS_AS_WARNINGS=1 */ id from user", 8) +} + func TestStreamSelectScatter(t *testing.T) { // Special setup: Don't use createExecutorEnv. cell := "aa" diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 0d70f20d8a6..b659f7e6ba6 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -27,6 +27,7 @@ import ( "golang.org/x/net/context" "github.com/golang/protobuf/proto" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/callerid" "vitess.io/vitess/go/vt/sqlparser" @@ -737,6 +738,58 @@ func TestExecutorShow(t *testing.T) { t.Errorf("show vindexes on user: %v, want %v", err, wantErr) } + qr, err = executor.Execute(context.Background(), "TestExecute", session, "show warnings", nil) + wantqr = &sqltypes.Result{ + Fields: []*querypb.Field{ + {Name: "Level", Type: sqltypes.VarChar}, + {Name: "Type", Type: sqltypes.Uint16}, + {Name: "Message", Type: sqltypes.VarChar}, + }, + Rows: [][]sqltypes.Value{}, + RowsAffected: 0, + } + if !reflect.DeepEqual(qr, wantqr) { + t.Errorf("show warnings:\n%+v, want\n%+v", qr, wantqr) + + } + + session.Warnings = []*querypb.QueryWarning{} + qr, err = executor.Execute(context.Background(), "TestExecute", session, "show warnings", nil) + wantqr = &sqltypes.Result{ + Fields: []*querypb.Field{ + {Name: "Level", Type: sqltypes.VarChar}, + {Name: "Type", Type: sqltypes.Uint16}, + {Name: "Message", Type: sqltypes.VarChar}, + }, + Rows: [][]sqltypes.Value{}, + RowsAffected: 0, + } + if !reflect.DeepEqual(qr, wantqr) { + t.Errorf("show warnings:\n%+v, want\n%+v", qr, wantqr) + } + + session.Warnings = []*querypb.QueryWarning{ + {Code: mysql.ERBadTable, Message: "bad table"}, + {Code: mysql.EROutOfResources, Message: "ks/-40: query timed out"}, + } + qr, err = executor.Execute(context.Background(), "TestExecute", session, "show warnings", nil) + wantqr = &sqltypes.Result{ + Fields: []*querypb.Field{ + {Name: "Level", Type: sqltypes.VarChar}, + {Name: "Type", Type: sqltypes.Uint16}, + {Name: "Message", Type: sqltypes.VarChar}, + }, + + Rows: [][]sqltypes.Value{ + {sqltypes.NewVarChar("Warning"), sqltypes.NewUint32(mysql.ERBadTable), sqltypes.NewVarChar("bad table")}, + {sqltypes.NewVarChar("Warning"), sqltypes.NewUint32(mysql.EROutOfResources), sqltypes.NewVarChar("ks/-40: query timed out")}, + }, + RowsAffected: 0, + } + if !reflect.DeepEqual(qr, wantqr) { + t.Errorf("show warnings:\n%+v, want\n%+v", qr, wantqr) + } + // Make sure it still works when one of the keyspaces is in a bad state getSandbox("TestExecutor").SrvKeyspaceMustFail++ qr, err = executor.Execute(context.Background(), "TestExecute", session, "show vitess_shards", nil) diff --git a/go/vt/vtgate/gateway/discoverygateway.go b/go/vt/vtgate/gateway/discoverygateway.go index b8950a22e9d..6d5d4ed7522 100644 --- a/go/vt/vtgate/gateway/discoverygateway.go +++ b/go/vt/vtgate/gateway/discoverygateway.go @@ -235,7 +235,7 @@ func (dg *discoveryGateway) CacheStatus() TabletCacheStatusList { // the middle of a transaction. While returning the error check if it maybe a result of // a resharding event, and set the re-resolve bit and let the upper layers // re-resolve and retry. -func (dg *discoveryGateway) withRetry(ctx context.Context, target *querypb.Target, conn queryservice.QueryService, name string, inTransaction bool, inner func(ctx context.Context, target *querypb.Target, conn queryservice.QueryService) (error, bool)) error { +func (dg *discoveryGateway) withRetry(ctx context.Context, target *querypb.Target, unused queryservice.QueryService, name string, inTransaction bool, inner func(ctx context.Context, target *querypb.Target, conn queryservice.QueryService) (error, bool)) error { var tabletLastUsed *topodatapb.Tablet var err error invalidTablets := make(map[string]bool) diff --git a/go/vt/vtgate/planbuilder/expr.go b/go/vt/vtgate/planbuilder/expr.go index 3fe0702113f..8ade06522d8 100644 --- a/go/vt/vtgate/planbuilder/expr.go +++ b/go/vt/vtgate/planbuilder/expr.go @@ -48,12 +48,10 @@ func splitAndExpression(filters []sqlparser.Expr, node sqlparser.Expr) []sqlpars // skipParenthesis skips the parenthesis (if any) of an expression and // returns the innermost unparenthesized expression. func skipParenthesis(node sqlparser.Expr) sqlparser.Expr { - for { - if node, ok := node.(*sqlparser.ParenExpr); ok { - return skipParenthesis(node.Expr) - } - return node + if node, ok := node.(*sqlparser.ParenExpr); ok { + return skipParenthesis(node.Expr) } + return node } // findOrigin identifies the right-most origin referenced by expr. In situations where diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 74c5ed8a6e6..19a3401f931 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -82,7 +82,12 @@ func (pb *primitiveBuilder) processSelect(sel *sqlparser.Select, outer *symtab) if rb.ERoute.TargetDestination != nil { return errors.New("unsupported: SELECT with a target destination") } + + if directives.IsSet(sqlparser.DirectiveScatterErrorsAsWarnings) { + rb.ERoute.ScatterErrorsAsWarnings = true + } } + // Set the outer symtab after processing of FROM clause. // This is because correlation is not allowed there. pb.st.Outer = outer diff --git a/go/vt/vtgate/planbuilder/update.go b/go/vt/vtgate/planbuilder/update.go index bbc870a176b..33c4a366d4b 100644 --- a/go/vt/vtgate/planbuilder/update.go +++ b/go/vt/vtgate/planbuilder/update.go @@ -172,7 +172,7 @@ func generateUpdateSubquery(upd *sqlparser.Update, table *vindexes.Table) string // it's holding. At the moment it only supports: StrVal, HexVal, IntVal, ValArg. // If a complex expression is provided (e.g set name = name + 1), the update will be rejected. func extractValueFromUpdate(upd *sqlparser.UpdateExpr) (pv sqltypes.PlanValue, err error) { - if !sqlparser.IsValue(upd.Expr) { + if !sqlparser.IsValue(upd.Expr) && !sqlparser.IsNull(upd.Expr) { err := vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: Only values are supported. Invalid update on column: %v", upd.Name.Name) return sqltypes.PlanValue{}, err } diff --git a/go/vt/vtgate/plugin_mysql_server.go b/go/vt/vtgate/plugin_mysql_server.go index 37628f9cb3c..e67e1026e3b 100644 --- a/go/vt/vtgate/plugin_mysql_server.go +++ b/go/vt/vtgate/plugin_mysql_server.go @@ -158,6 +158,14 @@ func (vh *vtgateHandler) ComQuery(c *mysql.Conn, query string, callback func(*sq return callback(result) } +func (vh *vtgateHandler) WarningCount(c *mysql.Conn) uint16 { + session, _ := c.ClientData.(*vtgatepb.Session) + if session != nil { + return uint16(len(session.GetWarnings())) + } + return 0 +} + var mysqlListener *mysql.Listener var mysqlUnixListener *mysql.Listener diff --git a/go/vt/vtgate/plugin_mysql_server_test.go b/go/vt/vtgate/plugin_mysql_server_test.go index 70281f33ca1..c873206e6ad 100644 --- a/go/vt/vtgate/plugin_mysql_server_test.go +++ b/go/vt/vtgate/plugin_mysql_server_test.go @@ -43,6 +43,10 @@ func (th *testHandler) ComQuery(c *mysql.Conn, q string, callback func(*sqltypes return nil } +func (th *testHandler) WarningCount(c *mysql.Conn) uint16 { + return 0 +} + func TestConnectionUnixSocket(t *testing.T) { th := &testHandler{} diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index 4c54928e4ce..6461ac86cc9 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -22,6 +22,7 @@ import ( "github.com/golang/protobuf/proto" "vitess.io/vitess/go/vt/vterrors" + querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" @@ -182,6 +183,20 @@ func (session *SafeSession) MustRollback() bool { return session.mustRollback } +// RecordWarning stores the given warning in the session +func (session *SafeSession) RecordWarning(warning *querypb.QueryWarning) { + session.mu.Lock() + defer session.mu.Unlock() + session.Session.Warnings = append(session.Session.Warnings, warning) +} + +// ClearWarnings removes all the warnings from the session +func (session *SafeSession) ClearWarnings() { + session.mu.Lock() + defer session.mu.Unlock() + session.Session.Warnings = nil +} + // Reset clears the session func (session *SafeSession) Reset() { if session == nil || session.Session == nil { diff --git a/go/vt/vtgate/scatter_conn.go b/go/vt/vtgate/scatter_conn.go index 896f2062528..32283678d33 100644 --- a/go/vt/vtgate/scatter_conn.go +++ b/go/vt/vtgate/scatter_conn.go @@ -132,7 +132,7 @@ func (stc *ScatterConn) Execute( var mu sync.Mutex qr := new(sqltypes.Result) - err := stc.multiGoTransaction( + allErrors := stc.multiGoTransaction( ctx, "Execute", rss, @@ -160,11 +160,16 @@ func (stc *ScatterConn) Execute( qr.AppendResult(innerqr) return transactionID, nil }) - return qr, err + + return qr, allErrors.AggrError(vterrors.Aggregate) } // ExecuteMultiShard is like Execute, // but each shard gets its own Sql Queries and BindVariables. +// +// It always returns a non-nil query result and an array of +// shard errors which may be nil so that callers can optionally +// process a partially-successful operation. func (stc *ScatterConn) ExecuteMultiShard( ctx context.Context, rss []*srvtopo.ResolvedShard, @@ -173,13 +178,13 @@ func (stc *ScatterConn) ExecuteMultiShard( session *SafeSession, notInTransaction bool, autocommit bool, -) (*sqltypes.Result, error) { +) (qr *sqltypes.Result, errs []error) { // mu protects qr var mu sync.Mutex - qr := new(sqltypes.Result) + qr = new(sqltypes.Result) - err := stc.multiGoTransaction( + allErrors := stc.multiGoTransaction( ctx, "Execute", rss, @@ -213,7 +218,8 @@ func (stc *ScatterConn) ExecuteMultiShard( qr.AppendResult(innerqr) return transactionID, nil }) - return qr, err + + return qr, allErrors.GetErrors() } func (stc *ScatterConn) executeAutocommit(ctx context.Context, rs *srvtopo.ResolvedShard, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions) (*sqltypes.Result, error) { @@ -246,7 +252,7 @@ func (stc *ScatterConn) ExecuteEntityIds( var mu sync.Mutex qr := new(sqltypes.Result) - err := stc.multiGoTransaction( + allErrors := stc.multiGoTransaction( ctx, "ExecuteEntityIds", rss, @@ -271,7 +277,8 @@ func (stc *ScatterConn) ExecuteEntityIds( qr.AppendResult(innerqr) return transactionID, nil }) - return qr, err + + return qr, allErrors.AggrError(vterrors.Aggregate) } // scatterBatchRequest needs to be built to perform a scatter batch query. @@ -359,6 +366,7 @@ func (stc *ScatterConn) ExecuteBatch( asTransaction bool, session *SafeSession, options *querypb.ExecuteOptions) (qrs []sqltypes.Result, err error) { + allErrors := new(concurrency.AllErrorRecorder) results := make([]sqltypes.Result, batchRequest.length) @@ -759,6 +767,10 @@ func (stc *ScatterConn) multiGo( // and updates the Session with the transaction id. If the session already // contains a transaction id for the shard, it reuses it. // The action function must match the shardActionTransactionFunc signature. +// +// It returns an error recorder in which each shard error is recorded positionally, +// i.e. if rss[2] had an error, then the error recorder will store that error +// in the second position. func (stc *ScatterConn) multiGoTransaction( ctx context.Context, name string, @@ -767,12 +779,14 @@ func (stc *ScatterConn) multiGoTransaction( session *SafeSession, notInTransaction bool, action shardActionTransactionFunc, -) error { - if len(rss) == 0 { - return nil - } +) (allErrors *concurrency.AllErrorRecorder) { - allErrors := new(concurrency.AllErrorRecorder) + numShards := len(rss) + allErrors = new(concurrency.AllErrorRecorder) + + if numShards == 0 { + return allErrors + } oneShard := func(rs *srvtopo.ResolvedShard, i int) { var err error startTime, statsKey := stc.startAction(name, rs.Target) @@ -791,7 +805,7 @@ func (stc *ScatterConn) multiGoTransaction( } var wg sync.WaitGroup - if len(rss) == 1 { + if numShards == 1 { // only one shard, do it synchronously. for i, rs := range rss { oneShard(rs, i) @@ -812,10 +826,7 @@ end: if session.MustRollback() { stc.txConn.Rollback(ctx, session) } - if allErrors.HasErrors() { - return allErrors.AggrError(vterrors.Aggregate) - } - return nil + return allErrors } // transactionInfo looks at the current session, and returns: diff --git a/go/vt/vtgate/scatter_conn_test.go b/go/vt/vtgate/scatter_conn_test.go index 91f4931504f..50d52060ce6 100644 --- a/go/vt/vtgate/scatter_conn_test.go +++ b/go/vt/vtgate/scatter_conn_test.go @@ -68,7 +68,8 @@ func TestScatterConnExecuteMulti(t *testing.T) { } } - return sc.ExecuteMultiShard(context.Background(), rss, queries, topodatapb.TabletType_REPLICA, nil, false, false) + qr, errs := sc.ExecuteMultiShard(context.Background(), rss, queries, topodatapb.TabletType_REPLICA, nil, false, false) + return qr, vterrors.Aggregate(errs) }) } diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index 60b7328231d..5ae671037f9 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -81,6 +81,11 @@ func (vc *vcursorImpl) SetContextTimeout(timeout time.Duration) context.CancelFu return cancel } +// RecordWarning stores the given warning in the current session +func (vc *vcursorImpl) RecordWarning(warning *querypb.QueryWarning) { + vc.safeSession.RecordWarning(warning) +} + // 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) { @@ -152,13 +157,14 @@ func (vc *vcursorImpl) ExecuteAutocommit(method string, query string, BindVars m } // ExecuteMultiShard is part of the engine.VCursor interface. -func (vc *vcursorImpl) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, autocommit bool) (*sqltypes.Result, error) { +func (vc *vcursorImpl) ExecuteMultiShard(rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, isDML, autocommit bool) (*sqltypes.Result, []error) { atomic.AddUint32(&vc.logStats.ShardQueries, uint32(len(queries))) - qr, err := vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, rss, commentedShardQueries(queries, vc.marginComments), vc.tabletType, vc.safeSession, false, autocommit) - if err == nil { + qr, errs := vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, rss, commentedShardQueries(queries, vc.marginComments), vc.tabletType, vc.safeSession, false, autocommit) + + if errs == nil { vc.hasPartialDML = true } - return qr, err + return qr, errs } // AutocommitApproval is part of the engine.VCursor interface. @@ -177,7 +183,8 @@ func (vc *vcursorImpl) ExecuteStandalone(query string, bindVars map[string]*quer } // The autocommit flag is always set to false because we currently don't // execute DMLs through ExecuteStandalone. - return vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, rss, bqs, vc.tabletType, NewAutocommitSession(vc.safeSession.Session), false, false /* autocommit */) + qr, errs := vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, rss, bqs, vc.tabletType, NewAutocommitSession(vc.safeSession.Session), false, false /* autocommit */) + return qr, vterrors.Aggregate(errs) } // StreamExeculteMulti is the streaming version of ExecuteMultiShard. diff --git a/go/vt/vtgate/vindexes/hash.go b/go/vt/vtgate/vindexes/hash.go index f05b40c5606..03882620daf 100644 --- a/go/vt/vtgate/vindexes/hash.go +++ b/go/vt/vtgate/vindexes/hash.go @@ -23,6 +23,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" + "strconv" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" @@ -69,7 +70,19 @@ func (vind *Hash) IsFunctional() bool { func (vind *Hash) Map(cursor VCursor, ids []sqltypes.Value) ([]key.Destination, error) { out := make([]key.Destination, len(ids)) for i, id := range ids { - num, err := sqltypes.ToUint64(id) + var num uint64 + var err error + + if id.IsSigned() { + // This is ToUint64 with no check on negative values. + str := id.ToString() + var ival int64 + ival, err = strconv.ParseInt(str, 10, 64) + num = uint64(ival) + } else { + num, err = sqltypes.ToUint64(id) + } + if err != nil { out[i] = key.DestinationNone{} continue diff --git a/go/vt/vtgate/vindexes/hash_test.go b/go/vt/vtgate/vindexes/hash_test.go index 562f0513862..40ea714745a 100644 --- a/go/vt/vtgate/vindexes/hash_test.go +++ b/go/vt/vtgate/vindexes/hash_test.go @@ -56,6 +56,12 @@ func TestHashMap(t *testing.T) { sqltypes.NewInt64(4), sqltypes.NewInt64(5), sqltypes.NewInt64(6), + sqltypes.NewInt64(0), + sqltypes.NewInt64(-1), + sqltypes.NewUint64(18446744073709551615), // 2^64 - 1 + sqltypes.NewInt64(9223372036854775807), // 2^63 - 1 + sqltypes.NewUint64(9223372036854775807), // 2^63 - 1 + sqltypes.NewInt64(-9223372036854775808), // - 2^63 }) if err != nil { t.Error(err) @@ -68,9 +74,19 @@ func TestHashMap(t *testing.T) { key.DestinationKeyspaceID([]byte("\xd2\xfd\x88g\xd5\r-\xfe")), key.DestinationKeyspaceID([]byte("p\xbb\x02<\x81\f\xa8z")), key.DestinationKeyspaceID([]byte("\xf0\x98H\n\xc4ľq")), + key.DestinationKeyspaceID([]byte("\x8c\xa6M\xe9\xc1\xb1#\xa7")), + key.DestinationKeyspaceID([]byte("5UP\xb2\x15\x0e$Q")), + key.DestinationKeyspaceID([]byte("5UP\xb2\x15\x0e$Q")), + key.DestinationKeyspaceID([]byte("\xf7}H\xaaݡ\xf1\xbb")), + key.DestinationKeyspaceID([]byte("\xf7}H\xaaݡ\xf1\xbb")), + key.DestinationKeyspaceID([]byte("\x95\xf8\xa5\xe5\xdd1\xd9\x00")), } if !reflect.DeepEqual(got, want) { - t.Errorf("Map(): %#v, want %+v", got, want) + for i, v := range got { + if v.String() != want[i].String() { + t.Errorf("Map() %d: %#v, want %#v", i, v, want[i]) + } + } } } @@ -95,11 +111,39 @@ func TestHashVerify(t *testing.T) { } func TestHashReverseMap(t *testing.T) { - got, err := hash.(Reversible).ReverseMap(nil, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}) + got, err := hash.(Reversible).ReverseMap(nil, [][]byte{ + []byte("\x16k@\xb4J\xbaK\xd6"), + []byte("\x06\xe7\xea\"Βp\x8f"), + []byte("N\xb1\x90ɢ\xfa\x16\x9c"), + []byte("\xd2\xfd\x88g\xd5\r-\xfe"), + []byte("p\xbb\x02<\x81\f\xa8z"), + []byte("\xf0\x98H\n\xc4ľq"), + []byte("\x8c\xa6M\xe9\xc1\xb1#\xa7"), + []byte("5UP\xb2\x15\x0e$Q"), + []byte("5UP\xb2\x15\x0e$Q"), + []byte("\xf7}H\xaaݡ\xf1\xbb"), + []byte("\xf7}H\xaaݡ\xf1\xbb"), + []byte("\x95\xf8\xa5\xe5\xdd1\xd9\x00"), + }) if err != nil { t.Error(err) } - want := []sqltypes.Value{sqltypes.NewUint64(uint64(1))} + neg1 := int64(-1) + negmax := int64(-9223372036854775808) + want := []sqltypes.Value{ + sqltypes.NewUint64(uint64(1)), + sqltypes.NewUint64(2), + sqltypes.NewUint64(3), + sqltypes.NewUint64(4), + sqltypes.NewUint64(5), + sqltypes.NewUint64(6), + sqltypes.NewUint64(0), + sqltypes.NewUint64(uint64(neg1)), + sqltypes.NewUint64(18446744073709551615), // 2^64 - 1 + sqltypes.NewUint64(9223372036854775807), // 2^63 - 1 + sqltypes.NewUint64(9223372036854775807), // 2^63 - 1 + sqltypes.NewUint64(uint64(negmax)), // - 2^63 + } if !reflect.DeepEqual(got, want) { t.Errorf("ReverseMap(): %v, want %v", got, want) } diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index 6ab1fcff121..0e85e7af4d7 100644 --- a/go/vt/vtgate/vtgate.go +++ b/go/vt/vtgate/vtgate.go @@ -253,6 +253,8 @@ func Init(ctx context.Context, hc discovery.HealthCheck, serv srvtopo.Server, ce log.Fatalf("error initializing query logger: %v", err) } + initAPI(ctx, hc) + return rpcVTGate } diff --git a/go/vt/vtgate/vtgate_test.go b/go/vt/vtgate/vtgate_test.go index d0d372a2a5c..e77270bb42d 100644 --- a/go/vt/vtgate/vtgate_test.go +++ b/go/vt/vtgate/vtgate_test.go @@ -2032,7 +2032,7 @@ func testErrorPropagation(t *testing.T, sbcs []*sandboxconn.SandboxConn, before } else { ec := vterrors.Code(err) if ec != expected { - t.Errorf("unexpected error, got %v want %v: %v", ec, expected, err) + t.Errorf("unexpected error, got code %v err %v, want %v", ec, err, expected) } } for _, sbc := range sbcs { diff --git a/go/vt/vtqueryserver/endtoend_test.go b/go/vt/vtqueryserver/endtoend_test.go index dc4fb82e426..fce6827ccc9 100644 --- a/go/vt/vtqueryserver/endtoend_test.go +++ b/go/vt/vtqueryserver/endtoend_test.go @@ -481,7 +481,7 @@ func TestQueryDeadline(t *testing.T) { t.Errorf("Unexpected error code: %d, want %d", got, want) } - _, _, err = conn.ReadQueryResult(1000, false) + _, _, _, err = conn.ReadQueryResult(1000, false) if err != nil { t.Errorf("unexpected error %v", err) } diff --git a/go/vt/vtqueryserver/plugin_mysql_server.go b/go/vt/vtqueryserver/plugin_mysql_server.go index ab0327b6273..804cd207f8b 100644 --- a/go/vt/vtqueryserver/plugin_mysql_server.go +++ b/go/vt/vtqueryserver/plugin_mysql_server.go @@ -132,6 +132,10 @@ func (mh *proxyHandler) ComQuery(c *mysql.Conn, query string, callback func(*sql return callback(result) } +func (mh *proxyHandler) WarningCount(c *mysql.Conn) uint16 { + return 0 +} + var mysqlListener *mysql.Listener var mysqlUnixListener *mysql.Listener diff --git a/go/vt/vtqueryserver/plugin_mysql_server_test.go b/go/vt/vtqueryserver/plugin_mysql_server_test.go index 40eab721d26..ca0f6b806cd 100644 --- a/go/vt/vtqueryserver/plugin_mysql_server_test.go +++ b/go/vt/vtqueryserver/plugin_mysql_server_test.go @@ -43,6 +43,10 @@ func (th *testHandler) ComQuery(c *mysql.Conn, q string, callback func(*sqltypes return nil } +func (th *testHandler) WarningCount(c *mysql.Conn) uint16 { + return 0 +} + func TestConnectionUnixSocket(t *testing.T) { th := &testHandler{} diff --git a/go/vt/vttablet/endtoend/framework/server.go b/go/vt/vttablet/endtoend/framework/server.go index ce6c7bd59ef..d267c231f41 100644 --- a/go/vt/vttablet/endtoend/framework/server.go +++ b/go/vt/vttablet/endtoend/framework/server.go @@ -22,6 +22,8 @@ import ( "net/http" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/mysql" @@ -79,13 +81,13 @@ func StartServer(connParams, connAppDebugParams mysql.ConnParams, dbName string) Server.Register() err := Server.StartService(Target, dbcfgs) if err != nil { - return fmt.Errorf("could not start service: %v", err) + return vterrors.Wrap(err, "could not start service") } // Start http service. ln, err := net.Listen("tcp", ":0") if err != nil { - return fmt.Errorf("could not start listener: %v", err) + return vterrors.Wrap(err, "could not start listener") } ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String()) go http.Serve(ln, nil) diff --git a/go/vt/vttablet/endtoend/framework/testcase.go b/go/vt/vttablet/endtoend/framework/testcase.go index 291a86bf03e..765e8ca0ec5 100644 --- a/go/vt/vttablet/endtoend/framework/testcase.go +++ b/go/vt/vttablet/endtoend/framework/testcase.go @@ -22,6 +22,8 @@ import ( "reflect" "strings" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -52,7 +54,7 @@ func (tq TestQuery) Test(name string, client *QueryClient) error { if name == "" { return err } - return fmt.Errorf("%s: Execute failed: %v", name, err) + return vterrors.Wrapf(err, "%s: Execute failed", name) } return nil } @@ -108,7 +110,7 @@ func (tc *TestCase) Test(name string, client *QueryClient) error { qr, err := exec(client, tc.Query, tc.BindVars) if err != nil { - return fmt.Errorf("%s: Execute failed: %v", name, err) + return vterrors.Wrapf(err, "%s: Execute failed", name) } if tc.Result != nil { diff --git a/go/vt/vttablet/heartbeat/reader.go b/go/vt/vttablet/heartbeat/reader.go index b75eb9ada80..b0eb91728d9 100644 --- a/go/vt/vttablet/heartbeat/reader.go +++ b/go/vt/vttablet/heartbeat/reader.go @@ -21,6 +21,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/hack" @@ -153,12 +155,12 @@ func (r *Reader) readHeartbeat() { res, err := r.fetchMostRecentHeartbeat(ctx) if err != nil { - r.recordError(fmt.Errorf("Failed to read most recent heartbeat: %v", err)) + r.recordError(vterrors.Wrap(err, "Failed to read most recent heartbeat")) return } ts, err := parseHeartbeatResult(res) if err != nil { - r.recordError(fmt.Errorf("Failed to parse heartbeat result: %v", err)) + r.recordError(vterrors.Wrap(err, "Failed to parse heartbeat result")) return } diff --git a/go/vt/vttablet/heartbeat/writer.go b/go/vt/vttablet/heartbeat/writer.go index 5503aad3599..9d5ee58a772 100644 --- a/go/vt/vttablet/heartbeat/writer.go +++ b/go/vt/vttablet/heartbeat/writer.go @@ -21,6 +21,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/hack" @@ -157,7 +159,7 @@ func (w *Writer) Close() { func (w *Writer) initializeTables(cp *mysql.ConnParams) error { conn, err := dbconnpool.NewDBConnection(cp, stats.NewTimings("", "", "")) if err != nil { - return fmt.Errorf("Failed to create connection for heartbeat: %v", err) + return vterrors.Wrap(err, "Failed to create connection for heartbeat") } defer conn.Close() statements := []string{ @@ -167,16 +169,16 @@ func (w *Writer) initializeTables(cp *mysql.ConnParams) error { } for _, s := range statements { if _, err := conn.ExecuteFetch(s, 0, false); err != nil { - return fmt.Errorf("Failed to execute heartbeat init query: %v", err) + return vterrors.Wrap(err, "Failed to execute heartbeat init query") } } insert, err := w.bindHeartbeatVars(sqlInsertInitialRow) if err != nil { - return fmt.Errorf("Failed to bindHeartbeatVars initial heartbeat insert: %v", err) + return vterrors.Wrap(err, "Failed to bindHeartbeatVars initial heartbeat insert") } _, err = conn.ExecuteFetch(insert, 0, false) if err != nil { - return fmt.Errorf("Failed to execute initial heartbeat insert: %v", err) + return vterrors.Wrap(err, "Failed to execute initial heartbeat insert") } writes.Add(1) return nil diff --git a/go/vt/vttablet/tabletmanager/action_agent.go b/go/vt/vttablet/tabletmanager/action_agent.go index 9bda98cc001..d2673b48a76 100644 --- a/go/vt/vttablet/tabletmanager/action_agent.go +++ b/go/vt/vttablet/tabletmanager/action_agent.go @@ -44,6 +44,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "github.com/golang/protobuf/proto" @@ -246,7 +248,7 @@ func NewActionAgent( // try to initialize the tablet if we have to if err := agent.InitTablet(port, gRPCPort); err != nil { - return nil, fmt.Errorf("agent.InitTablet failed: %v", err) + return nil, vterrors.Wrap(err, "agent.InitTablet failed") } // Create the TabletType stats @@ -351,16 +353,16 @@ func NewTestActionAgent(batchCtx context.Context, ts *topo.Server, tabletAlias * // Start will update the topology and setup services. if err := agent.Start(batchCtx, "", 0, vtPort, grpcPort, false); err != nil { - panic(fmt.Errorf("agent.Start(%v) failed: %v", tabletAlias, err)) + panic(vterrors.Wrapf(err, "agent.Start(%v) failed", tabletAlias)) } // Update our running state. Need to take action lock. if err := agent.lock(batchCtx); err != nil { - panic(fmt.Errorf("agent.lock() failed: %v", err)) + panic(vterrors.Wrap(err, "agent.lock() failed")) } defer agent.unlock() if err := agent.refreshTablet(batchCtx, "Start"); err != nil { - panic(fmt.Errorf("agent.refreshTablet(%v) failed: %v", tabletAlias, err)) + panic(vterrors.Wrapf(err, "agent.refreshTablet(%v) failed", tabletAlias)) } return agent @@ -393,21 +395,21 @@ func NewComboActionAgent(batchCtx context.Context, ts *topo.Server, tabletAlias *initShard = shard *initTabletType = tabletType if err := agent.InitTablet(vtPort, grpcPort); err != nil { - panic(fmt.Errorf("agent.InitTablet failed: %v", err)) + panic(vterrors.Wrap(err, "agent.InitTablet failed")) } // Start the agent. if err := agent.Start(batchCtx, "", 0, vtPort, grpcPort, false); err != nil { - panic(fmt.Errorf("agent.Start(%v) failed: %v", tabletAlias, err)) + panic(vterrors.Wrapf(err, "agent.Start(%v) failed", tabletAlias)) } // And update our running state (need to take the Action lock). if err := agent.lock(batchCtx); err != nil { - panic(fmt.Errorf("agent.lock() failed: %v", err)) + panic(vterrors.Wrap(err, "agent.lock() failed")) } defer agent.unlock() if err := agent.refreshTablet(batchCtx, "Start"); err != nil { - panic(fmt.Errorf("agent.refreshTablet(%v) failed: %v", tabletAlias, err)) + panic(vterrors.Wrapf(err, "agent.refreshTablet(%v) failed", tabletAlias)) } return agent @@ -628,7 +630,7 @@ func (agent *ActionAgent) Start(ctx context.Context, mysqlHost string, mysqlPort Shard: agent.initialTablet.Shard, TabletType: agent.initialTablet.Type, }, agent.DBConfigs); err != nil { - return fmt.Errorf("failed to InitDBConfig: %v", err) + return vterrors.Wrap(err, "failed to InitDBConfig") } // export a few static variables diff --git a/go/vt/vttablet/tabletmanager/init_tablet.go b/go/vt/vttablet/tabletmanager/init_tablet.go index 3d71cf76913..9a28e0fac38 100644 --- a/go/vt/vttablet/tabletmanager/init_tablet.go +++ b/go/vt/vttablet/tabletmanager/init_tablet.go @@ -24,6 +24,8 @@ import ( "fmt" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/flagutil" "vitess.io/vitess/go/netutil" @@ -62,7 +64,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { // parse init_tablet_type tabletType, err := topoproto.ParseTabletType(*initTabletType) if err != nil { - return fmt.Errorf("invalid init_tablet_type %v: %v", *initTabletType, err) + return vterrors.Wrapf(err, "invalid init_tablet_type %v", *initTabletType) } if tabletType == topodatapb.TabletType_MASTER { // We disallow MASTER, so we don't have to change @@ -73,7 +75,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { // parse and validate shard name shard, keyRange, err := topo.ValidateShardName(*initShard) if err != nil { - return fmt.Errorf("cannot validate shard name %v: %v", *initShard, err) + return vterrors.Wrapf(err, "cannot validate shard name %v", *initShard) } // Create a context for this whole operation. Note we will @@ -89,7 +91,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { si, err = agent.TopoServer.GetOrCreateShard(ctx, *initKeyspace, shard) return err }); err != nil { - return fmt.Errorf("InitTablet cannot GetOrCreateShard shard: %v", err) + return vterrors.Wrap(err, "InitTablet cannot GetOrCreateShard shard") } if si.MasterAlias != nil && topoproto.TabletAliasEqual(si.MasterAlias, agent.TabletAlias) { // We're marked as master in the shard record, which could mean the master @@ -115,7 +117,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { agent.setExternallyReparentedTime(time.Now()) } default: - return fmt.Errorf("InitTablet failed to read existing tablet record: %v", err) + return vterrors.Wrap(err, "InitTablet failed to read existing tablet record") } } @@ -132,7 +134,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { }) return err }); err != nil { - return fmt.Errorf("couldn't add tablet's cell to shard record: %v", err) + return vterrors.Wrap(err, "couldn't add tablet's cell to shard record") } } log.Infof("Initializing the tablet for type %v", tabletType) @@ -179,7 +181,7 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { // it. So we read it first. oldTablet, err := agent.TopoServer.GetTablet(ctx, tablet.Alias) if err != nil { - return fmt.Errorf("InitTablet failed to read existing tablet record: %v", err) + return vterrors.Wrap(err, "InitTablet failed to read existing tablet record") } // Sanity check the keyspace and shard @@ -198,10 +200,10 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { // Then overwrite everything, ignoring version mismatch. if err := agent.TopoServer.UpdateTablet(ctx, topo.NewTabletInfo(tablet, nil)); err != nil { - return fmt.Errorf("UpdateTablet failed: %v", err) + return vterrors.Wrap(err, "UpdateTablet failed") } default: - return fmt.Errorf("CreateTablet failed: %v", err) + return vterrors.Wrap(err, "CreateTablet failed") } return nil diff --git a/go/vt/vttablet/tabletmanager/orchestrator.go b/go/vt/vttablet/tabletmanager/orchestrator.go index f80e5d314d4..87a1eacdaea 100644 --- a/go/vt/vttablet/tabletmanager/orchestrator.go +++ b/go/vt/vttablet/tabletmanager/orchestrator.go @@ -27,6 +27,8 @@ import ( "strconv" "time" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/timer" "vitess.io/vitess/go/vt/log" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -53,7 +55,7 @@ func newOrcClient() (*orcClient, error) { } apiRoot, err := url.Parse(*orcAddr) if err != nil { - return nil, fmt.Errorf("can't parse -orc_api_url flag value (%v): %v", *orcAddr, err) + return nil, vterrors.Wrapf(err, "can't parse -orc_api_url flag value (%v)", *orcAddr) } return &orcClient{ apiRoot: apiRoot, diff --git a/go/vt/vttablet/tabletmanager/replication_reporter.go b/go/vt/vttablet/tabletmanager/replication_reporter.go index 8115db0710c..97c4590269b 100644 --- a/go/vt/vttablet/tabletmanager/replication_reporter.go +++ b/go/vt/vttablet/tabletmanager/replication_reporter.go @@ -22,6 +22,8 @@ import ( "html/template" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/mysql" @@ -138,7 +140,7 @@ func repairReplication(ctx context.Context, agent *ActionAgent) error { // lock any other actions on this tablet by Orchestrator. if err := agent.orc.BeginMaintenance(agent.Tablet(), "vttablet has been told to StopSlave"); err != nil { log.Warningf("Orchestrator BeginMaintenance failed: %v", err) - return fmt.Errorf("Orchestrator BeginMaintenance failed :%v, skipping repairReplication", err) + return vterrors.Wrap(err, "orchestrator BeginMaintenance failed, skipping repairReplication") } } diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index 030b575b4a2..55a3a57285d 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -20,6 +20,8 @@ import ( "flag" "fmt" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/log" @@ -63,12 +65,12 @@ func (agent *ActionAgent) restoreDataLocked(ctx context.Context, logger logutil. tablet.Type = topodatapb.TabletType_RESTORE return nil }); err != nil { - return fmt.Errorf("Cannot change type to RESTORE: %v", err) + return vterrors.Wrap(err, "Cannot change type to RESTORE") } // let's update our internal state (stop query service and other things) if err := agent.refreshTablet(ctx, "restore from backup"); err != nil { - return fmt.Errorf("failed to update state before restore: %v", err) + return vterrors.Wrap(err, "failed to update state before restore") } // Try to restore. Depending on the reason for failure, we may be ok. @@ -102,7 +104,7 @@ func (agent *ActionAgent) restoreDataLocked(ctx context.Context, logger logutil. return nil }) agent.refreshTablet(ctx, "failed for restore from backup") - return fmt.Errorf("Can't restore backup: %v", err) + return vterrors.Wrap(err, "Can't restore backup") } // If we had type BACKUP or RESTORE it's better to set our type to the init_tablet_type to make result of the restore @@ -119,12 +121,12 @@ func (agent *ActionAgent) restoreDataLocked(ctx context.Context, logger logutil. tablet.Type = originalType return nil }); err != nil { - return fmt.Errorf("Cannot change type back to %v: %v", originalType, err) + return vterrors.Wrapf(err, "Cannot change type back to %v", originalType) } // let's update our internal state (start query service and other things) if err := agent.refreshTablet(context.Background(), "after restore from backup"); err != nil { - return fmt.Errorf("failed to update state after backup: %v", err) + return vterrors.Wrap(err, "failed to update state after backup") } return nil @@ -136,19 +138,19 @@ func (agent *ActionAgent) startReplication(ctx context.Context, pos mysql.Positi "RESET SLAVE ALL", // "ALL" makes it forget master host:port. } if err := agent.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds); err != nil { - return fmt.Errorf("failed to reset slave: %v", err) + return vterrors.Wrap(err, "failed to reset slave") } // Set the position at which to resume from the master. if err := agent.MysqlDaemon.SetSlavePosition(ctx, pos); err != nil { - return fmt.Errorf("failed to set slave position: %v", err) + return vterrors.Wrap(err, "failed to set slave position") } // Read the shard to find the current master, and its location. tablet := agent.Tablet() si, err := agent.TopoServer.GetShard(ctx, tablet.Keyspace, tablet.Shard) if err != nil { - return fmt.Errorf("can't read shard: %v", err) + return vterrors.Wrap(err, "can't read shard") } if si.MasterAlias == nil { // We've restored, but there's no master. This is fine, since we've @@ -168,7 +170,7 @@ func (agent *ActionAgent) startReplication(ctx context.Context, pos mysql.Positi } ti, err := agent.TopoServer.GetTablet(ctx, si.MasterAlias) if err != nil { - return fmt.Errorf("Cannot read master tablet %v: %v", si.MasterAlias, err) + return vterrors.Wrapf(err, "Cannot read master tablet %v", si.MasterAlias) } // If using semi-sync, we need to enable it before connecting to master. @@ -178,7 +180,7 @@ func (agent *ActionAgent) startReplication(ctx context.Context, pos mysql.Positi // Set master and start slave. if err := agent.MysqlDaemon.SetMaster(ctx, topoproto.MysqlHostname(ti.Tablet), int(topoproto.MysqlPort(ti.Tablet)), false /* slaveStopBefore */, true /* slaveStartAfter */); err != nil { - return fmt.Errorf("MysqlDaemon.SetMaster failed: %v", err) + return vterrors.Wrap(err, "MysqlDaemon.SetMaster failed") } return nil } diff --git a/go/vt/vttablet/tabletmanager/rpc_actions.go b/go/vt/vttablet/tabletmanager/rpc_actions.go index ba0413969a4..67f1aaab471 100644 --- a/go/vt/vttablet/tabletmanager/rpc_actions.go +++ b/go/vt/vttablet/tabletmanager/rpc_actions.go @@ -21,6 +21,8 @@ import ( "regexp" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/hook" @@ -81,7 +83,7 @@ func (agent *ActionAgent) ChangeType(ctx context.Context, tabletType topodatapb. // Let's see if we need to fix semi-sync acking. if err := agent.fixSemiSyncAndReplication(agent.Tablet().Type); err != nil { - return fmt.Errorf("fixSemiSyncAndReplication failed, may not ack correctly: %v", err) + return vterrors.Wrap(err, "fixSemiSyncAndReplication failed, may not ack correctly") } // and re-run health check diff --git a/go/vt/vttablet/tabletmanager/rpc_query.go b/go/vt/vttablet/tabletmanager/rpc_query.go index 4df9206c957..672f631a8f2 100644 --- a/go/vt/vttablet/tabletmanager/rpc_query.go +++ b/go/vt/vttablet/tabletmanager/rpc_query.go @@ -19,6 +19,7 @@ package tabletmanager import ( "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/log" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -60,7 +61,10 @@ func (agent *ActionAgent) ExecuteFetchAsDba(ctx context.Context, query []byte, d } if err == nil && reloadSchema { - agent.QueryServiceControl.ReloadSchema(ctx) + reloadErr := agent.QueryServiceControl.ReloadSchema(ctx) + if reloadErr != nil { + log.Errorf("failed to reload the schema %v", reloadErr) + } } return sqltypes.ResultToProto3(result), err } @@ -84,7 +88,10 @@ func (agent *ActionAgent) ExecuteFetchAsAllPrivs(ctx context.Context, query []by result, err := conn.ExecuteFetch(string(query), maxrows, true /*wantFields*/) if err == nil && reloadSchema { - agent.QueryServiceControl.ReloadSchema(ctx) + reloadErr := agent.QueryServiceControl.ReloadSchema(ctx) + if reloadErr != nil { + log.Errorf("failed to reload the schema %v", reloadErr) + } } return sqltypes.ResultToProto3(result), err } diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 0193aa494eb..f11d2875bd1 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -21,6 +21,8 @@ import ( "fmt" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/mysql" @@ -305,7 +307,7 @@ func (agent *ActionAgent) DemoteMaster(ctx context.Context) (string, error) { // let vtgate keep serving read traffic from this master (see comment below). log.Infof("DemoteMaster disabling query service") if _ /* state changed */, err := agent.QueryServiceControl.SetServingType(tablet.Type, false, nil); err != nil { - return "", fmt.Errorf("SetServingType(serving=false) failed: %v", err) + return "", vterrors.Wrap(err, "SetServingType(serving=false) failed") } // Now, set the server read-only. Note all active connections are not @@ -539,19 +541,19 @@ func (agent *ActionAgent) StopReplicationAndGetStatus(ctx context.Context) (*rep // get the status before we stop replication rs, err := agent.MysqlDaemon.SlaveStatus() if err != nil { - return nil, fmt.Errorf("before status failed: %v", err) + return nil, vterrors.Wrap(err, "before status failed") } if !rs.SlaveIORunning && !rs.SlaveSQLRunning { // no replication is running, just return what we got return mysql.SlaveStatusToProto(rs), nil } if err := agent.stopSlaveLocked(ctx); err != nil { - return nil, fmt.Errorf("stop slave failed: %v", err) + return nil, vterrors.Wrap(err, "stop slave failed") } // now patch in the current position rs.Position, err = agent.MysqlDaemon.MasterPosition() if err != nil { - return nil, fmt.Errorf("after position failed: %v", err) + return nil, vterrors.Wrap(err, "after position failed") } return mysql.SlaveStatusToProto(rs), nil } @@ -631,7 +633,7 @@ func (agent *ActionAgent) fixSemiSyncAndReplication(tabletType topodatapb.Tablet } if err := agent.fixSemiSync(tabletType); err != nil { - return fmt.Errorf("failed to fixSemiSync(%v): %v", tabletType, err) + return vterrors.Wrapf(err, "failed to fixSemiSync(%v)", tabletType) } // If replication is running, but the status is wrong, @@ -650,7 +652,7 @@ func (agent *ActionAgent) fixSemiSyncAndReplication(tabletType topodatapb.Tablet shouldAck := isMasterEligible(tabletType) acking, err := agent.MysqlDaemon.SemiSyncSlaveStatus() if err != nil { - return fmt.Errorf("failed to get SemiSyncSlaveStatus: %v", err) + return vterrors.Wrap(err, "failed to get SemiSyncSlaveStatus") } if shouldAck == acking { return nil @@ -659,10 +661,10 @@ func (agent *ActionAgent) fixSemiSyncAndReplication(tabletType topodatapb.Tablet // We need to restart replication log.Infof("Restarting replication for semi-sync flag change to take effect from %v to %v", acking, shouldAck) if err := agent.MysqlDaemon.StopSlave(agent.hookExtraEnv()); err != nil { - return fmt.Errorf("failed to StopSlave: %v", err) + return vterrors.Wrap(err, "failed to StopSlave") } if err := agent.MysqlDaemon.StartSlave(agent.hookExtraEnv()); err != nil { - return fmt.Errorf("failed to StartSlave: %v", err) + return vterrors.Wrap(err, "failed to StartSlave") } return nil } diff --git a/go/vt/vttablet/tabletmanager/rpc_schema.go b/go/vt/vttablet/tabletmanager/rpc_schema.go index 0c760cbb423..de6f802f23a 100644 --- a/go/vt/vttablet/tabletmanager/rpc_schema.go +++ b/go/vt/vttablet/tabletmanager/rpc_schema.go @@ -17,7 +17,7 @@ limitations under the License. package tabletmanager import ( - "fmt" + "vitess.io/vitess/go/vt/vterrors" "golang.org/x/net/context" @@ -46,7 +46,7 @@ func (agent *ActionAgent) ReloadSchema(ctx context.Context, waitPosition string) if waitPosition != "" { pos, err := mysql.DecodePosition(waitPosition) if err != nil { - return fmt.Errorf("ReloadSchema: can't parse wait position (%q): %v", waitPosition, err) + return vterrors.Wrapf(err, "ReloadSchema: can't parse wait position (%q)", waitPosition) } log.Infof("ReloadSchema: waiting for replication position: %v", waitPosition) if err := agent.MysqlDaemon.WaitMasterPos(ctx, pos); err != nil { diff --git a/go/vt/vttablet/tabletmanager/rpc_server.go b/go/vt/vttablet/tabletmanager/rpc_server.go index 555faa0e1c6..7b5bdc19de8 100644 --- a/go/vt/vttablet/tabletmanager/rpc_server.go +++ b/go/vt/vttablet/tabletmanager/rpc_server.go @@ -19,6 +19,8 @@ package tabletmanager import ( "fmt" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/tb" "vitess.io/vitess/go/vt/callinfo" @@ -87,7 +89,7 @@ func (agent *ActionAgent) HandleRPCPanic(ctx context.Context, name string, args, if *err != nil { // error case log.Warningf("TabletManager.%v(%v)(on %v from %v) error: %v", name, args, topoproto.TabletAliasString(agent.TabletAlias), from, (*err).Error()) - *err = fmt.Errorf("TabletManager.%v on %v error: %v", name, topoproto.TabletAliasString(agent.TabletAlias), *err) + *err = vterrors.Wrapf(*err, "TabletManager.%v on %v error: %v", name, topoproto.TabletAliasString(agent.TabletAlias)) } else { // success case log.Infof("TabletManager.%v(%v)(on %v from %v): %#v", name, args, topoproto.TabletAliasString(agent.TabletAlias), from, reply) diff --git a/go/vt/vttablet/tabletmanager/state_change.go b/go/vt/vttablet/tabletmanager/state_change.go index 3f615067e68..8dafe948279 100644 --- a/go/vt/vttablet/tabletmanager/state_change.go +++ b/go/vt/vttablet/tabletmanager/state_change.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/event" @@ -137,7 +139,7 @@ func (agent *ActionAgent) refreshTablet(ctx context.Context, reason string) erro ti, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias) if err != nil { log.Warningf("Failed rereading tablet after %v - services may be inconsistent: %v", reason, err) - return fmt.Errorf("refreshTablet failed rereading tablet after %v: %v", reason, err) + return vterrors.Wrapf(err, "refreshTablet failed rereading tablet after %v", reason) } tablet := ti.Tablet diff --git a/go/vt/vttablet/tabletmanager/vreplication/controller.go b/go/vt/vttablet/tabletmanager/vreplication/controller.go index cf5f8f98f89..784d104c1f8 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/controller.go +++ b/go/vt/vttablet/tabletmanager/vreplication/controller.go @@ -22,6 +22,8 @@ import ( "strconv" "time" + "vitess.io/vitess/go/vt/vterrors" + "github.com/golang/protobuf/proto" "golang.org/x/net/context" @@ -157,7 +159,7 @@ func (ct *controller) runBlp(ctx context.Context) (err error) { dbClient := ct.dbClientFactory() if err := dbClient.Connect(); err != nil { - return fmt.Errorf("can't connect to database: %v", err) + return vterrors.Wrap(err, "can't connect to database") } defer dbClient.Close() @@ -171,7 +173,7 @@ func (ct *controller) runBlp(ctx context.Context) (err error) { // Table names can have search patterns. Resolve them against the schema. tables, err := mysqlctl.ResolveTables(ct.mysqld, dbClient.DBName(), ct.source.Tables) if err != nil { - return fmt.Errorf("failed to resolve table names: %v", err) + return vterrors.Wrap(err, "failed to resolve table names") } player := binlogplayer.NewBinlogPlayerTables(dbClient, tablet, tables, ct.id, ct.blpStats) diff --git a/go/vt/vttablet/tabletmanager/vreplication/engine.go b/go/vt/vttablet/tabletmanager/vreplication/engine.go index abf1b0b9efd..1b272473694 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/engine.go +++ b/go/vt/vttablet/tabletmanager/vreplication/engine.go @@ -194,6 +194,13 @@ func (vre *Engine) Exec(query string) (*sqltypes.Result, error) { vre.mustCreate = false } + // Change the database to ensure that these events don't get + // replicated by another vreplication. This can happen when + // we reverse replication. + if _, err := dbClient.ExecuteFetch("use _vt", 1); err != nil { + return nil, err + } + switch plan.opcode { case insertQuery: qr, err := dbClient.ExecuteFetch(plan.query, 1) diff --git a/go/vt/vttablet/tabletmanager/vreplication/engine_test.go b/go/vt/vttablet/tabletmanager/vreplication/engine_test.go index d10f91ff177..24c2140e5dd 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/engine_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/engine_test.go @@ -99,6 +99,7 @@ func TestEngineExec(t *testing.T) { } defer vre.Close() + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("insert into _vt.vreplication values (null)", &sqltypes.Result{InsertID: 1}, nil) dbClient.ExpectRequest("select * from _vt.vreplication where id = 1", sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -138,6 +139,7 @@ func TestEngineExec(t *testing.T) { savedBlp := ct.blpStats + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("update _vt.vreplication set pos = 'MariaDB/0-1-1084', state = 'Running' where id = 1", testDMLResponse, nil) dbClient.ExpectRequest("select * from _vt.vreplication where id = 1", sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -177,6 +179,7 @@ func TestEngineExec(t *testing.T) { // Test Delete + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) delQuery := "delete from _vt.vreplication where id = 1" dbClient.ExpectRequest(delQuery, testDMLResponse, nil) @@ -220,6 +223,7 @@ func TestEngineBadInsert(t *testing.T) { } defer vre.Close() + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("insert into _vt.vreplication values (null)", &sqltypes.Result{}, nil) _, err := vre.Exec("insert into _vt.vreplication values(null)") want := "insert failed to generate an id" @@ -250,6 +254,7 @@ func TestEngineSelect(t *testing.T) { } defer vre.Close() + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) wantQuery := "select * from _vt.vreplication where workflow = 'x'" wantResult := sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -400,6 +405,7 @@ func TestCreateDBAndTable(t *testing.T) { dbClient.ExpectRequest("CREATE DATABASE IF NOT EXISTS _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("DROP TABLE IF EXISTS _vt.blp_checkpoint", &sqltypes.Result{}, nil) dbClient.ExpectRequestRE("CREATE TABLE IF NOT EXISTS _vt.vreplication.*", &sqltypes.Result{}, nil) + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("insert into _vt.vreplication values (null)", &sqltypes.Result{InsertID: 1}, nil) dbClient.ExpectRequest("select * from _vt.vreplication where id = 1", sqltypes.MakeTestResult( sqltypes.MakeTestFields( diff --git a/go/vt/vttablet/tabletmanager/vreplication/stats.go b/go/vt/vttablet/tabletmanager/vreplication/stats.go index 81079ffa796..b80e6de4ad5 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/stats.go +++ b/go/vt/vttablet/tabletmanager/vreplication/stats.go @@ -137,7 +137,7 @@ func (st *vrStats) status() *EngineStatus { Rates: ct.blpStats.Rates.Get(), State: state, SourceTablet: ct.sourceTablet.Get(), - LastMessage: ct.blpStats.LastMessage.Get(), + Messages: ct.blpStats.MessageHistory(), } i++ } @@ -163,7 +163,7 @@ type ControllerStatus struct { Rates map[string][]float64 State string SourceTablet string - LastMessage string + Messages []string } var vreplicationTemplate = ` @@ -191,7 +191,7 @@ var vreplicationTemplate = ` {{.SecondsBehindMaster}} {{range $key, $value := .Counts}}{{$key}}: {{$value}}
{{end}} {{range $key, $values := .Rates}}{{$key}}: {{range $values}}{{.}} {{end}}
{{end}} - {{.LastMessage}} + {{range $index, $value := .Messages}}{{$value}}
{{end}} {{end}} {{else}}VReplication is closed.{{end}} ` diff --git a/go/vt/vttablet/tabletmanager/vreplication/stats_test.go b/go/vt/vttablet/tabletmanager/vreplication/stats_test.go index 7c1c9975400..a047ede7955 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/stats_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/stats_test.go @@ -20,6 +20,7 @@ import ( "bytes" "html/template" "testing" + "time" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/vt/binlog/binlogplayer" @@ -51,7 +52,7 @@ VReplication state: Open
2 All: 0
- Test Message + Test Message2
Test Message1
2 keyspace:"ks" shard:"1" @@ -62,7 +63,7 @@ VReplication state: Open
2 All: 0
- Test Message + Test Message2
Test Message1
` @@ -76,7 +77,8 @@ func TestStatusHtml(t *testing.T) { blpStats := binlogplayer.NewStats() blpStats.SetLastPosition(pos) blpStats.SecondsBehindMaster.Set(2) - blpStats.LastMessage.Set("Test Message") + blpStats.History.Add(&binlogplayer.StatsHistoryRecord{Time: time.Now(), Message: "Test Message1"}) + blpStats.History.Add(&binlogplayer.StatsHistoryRecord{Time: time.Now(), Message: "Test Message2"}) testStats := &vrStats{} testStats.isOpen = true diff --git a/go/vt/vttablet/tabletmanager/vreplication/tablet_picker.go b/go/vt/vttablet/tabletmanager/vreplication/tablet_picker.go index e0ac82471c4..4003db8e35f 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/tablet_picker.go +++ b/go/vt/vttablet/tabletmanager/vreplication/tablet_picker.go @@ -22,6 +22,8 @@ import ( "math/rand" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/discovery" @@ -75,7 +77,7 @@ func newTabletPicker(ts *topo.Server, cell, keyspace, shard, tabletTypesStr stri func (tp *tabletPicker) Pick(ctx context.Context) (*topodatapb.Tablet, error) { // wait for any of required the tablets (useful for the first run at least, fast for next runs) if err := tp.statsCache.WaitForAnyTablet(ctx, tp.cell, tp.keyspace, tp.shard, tp.tabletTypes); err != nil { - return nil, fmt.Errorf("error waiting for tablets for %v %v %v: %v", tp.cell, tp.keyspace, tp.shard, err) + return nil, vterrors.Wrapf(err, "error waiting for tablets for %v %v %v", tp.cell, tp.keyspace, tp.shard) } // Find the server list from the health check. diff --git a/go/vt/vttablet/tabletserver/connpool/dbconn.go b/go/vt/vttablet/tabletserver/connpool/dbconn.go index a38119340d7..8c020f143a6 100644 --- a/go/vt/vttablet/tabletserver/connpool/dbconn.go +++ b/go/vt/vttablet/tabletserver/connpool/dbconn.go @@ -22,6 +22,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/mysql" @@ -235,7 +237,7 @@ func (dbc *DBConn) VerifyMode(strictTransTables bool) (BinlogFormat, error) { if strictTransTables { qr, err := dbc.conn.ExecuteFetch(getModeSQL, 2, false) if err != nil { - return 0, fmt.Errorf("could not verify mode: %v", err) + return 0, vterrors.Wrap(err, "could not verify mode") } if len(qr.Rows) != 1 { return 0, fmt.Errorf("incorrect rowcount received for %s: %d", getModeSQL, len(qr.Rows)) @@ -246,7 +248,7 @@ func (dbc *DBConn) VerifyMode(strictTransTables bool) (BinlogFormat, error) { } qr, err := dbc.conn.ExecuteFetch(getAutocommit, 2, false) if err != nil { - return 0, fmt.Errorf("could not verify mode: %v", err) + return 0, vterrors.Wrap(err, "could not verify mode") } if len(qr.Rows) != 1 { return 0, fmt.Errorf("incorrect rowcount received for %s: %d", getAutocommit, len(qr.Rows)) @@ -256,7 +258,7 @@ func (dbc *DBConn) VerifyMode(strictTransTables bool) (BinlogFormat, error) { } qr, err = dbc.conn.ExecuteFetch(getAutoIsNull, 2, false) if err != nil { - return 0, fmt.Errorf("could not verify mode: %v", err) + return 0, vterrors.Wrap(err, "could not verify mode") } if len(qr.Rows) != 1 { return 0, fmt.Errorf("incorrect rowcount received for %s: %d", getAutoIsNull, len(qr.Rows)) @@ -266,7 +268,7 @@ func (dbc *DBConn) VerifyMode(strictTransTables bool) (BinlogFormat, error) { } qr, err = dbc.conn.ExecuteFetch(showBinlog, 10, false) if err != nil { - return 0, fmt.Errorf("could not fetch binlog format: %v", err) + return 0, vterrors.Wrap(err, "could not fetch binlog format") } if len(qr.Rows) != 1 { return 0, fmt.Errorf("incorrect rowcount received for %s: %d", showBinlog, len(qr.Rows)) diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index e3c89ef4656..847b8923e28 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -395,7 +395,12 @@ func (qre *QueryExecutor) execDDL() (*sqltypes.Result, error) { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "DDL is not understood") } - defer qre.tsv.se.Reload(qre.ctx) + defer func() { + err := qre.tsv.se.Reload(qre.ctx) + if err != nil { + log.Errorf("failed to reload schema %v", err) + } + }() if qre.transactionID != 0 { conn, err := qre.tsv.te.txPool.Get(qre.transactionID, "DDL begin again") @@ -450,7 +455,7 @@ func (qre *QueryExecutor) execNextval() (*sqltypes.Result, error) { } nextID, err := sqltypes.ToInt64(qr.Rows[0][0]) if err != nil { - return nil, fmt.Errorf("error loading sequence %s: %v", tableName, err) + return nil, vterrors.Wrapf(err, "error loading sequence %s", tableName) } // Initialize SequenceInfo.NextVal if it wasn't already. if t.SequenceInfo.NextVal == 0 { @@ -458,7 +463,7 @@ func (qre *QueryExecutor) execNextval() (*sqltypes.Result, error) { } cache, err := sqltypes.ToInt64(qr.Rows[0][1]) if err != nil { - return nil, fmt.Errorf("error loading sequence %s: %v", tableName, err) + return nil, vterrors.Wrapf(err, "error loading sequence %s", tableName) } if cache < 1 { return nil, fmt.Errorf("invalid cache value for sequence %s: %d", tableName, cache) diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index daf887b5792..84d0d02f455 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -1989,7 +1989,7 @@ func newTestTabletServer(ctx context.Context, flags executorFlags, db *fakesqldb func newTransaction(tsv *TabletServer, options *querypb.ExecuteOptions) int64 { transactionID, err := tsv.Begin(context.Background(), &tsv.target, options) if err != nil { - panic(fmt.Errorf("failed to start a transaction: %v", err)) + panic(vterrors.Wrap(err, "failed to start a transaction")) } return transactionID } diff --git a/go/vt/vttablet/tabletserver/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index 91a588791a7..e0f59421bde 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -19,7 +19,6 @@ package schema import ( "bytes" "encoding/json" - "fmt" "net/http" "sync" "time" @@ -242,7 +241,7 @@ func (se *Engine) Reload(ctx context.Context) error { return curTime, tableData, nil }() if err != nil { - return fmt.Errorf("could not get table list for reload: %v", err) + return vterrors.Wrap(err, "could not get table list for reload") } // Reload any tables that have changed. We try every table even if some fail, @@ -256,21 +255,12 @@ func (se *Engine) Reload(ctx context.Context) error { createTime, _ := sqltypes.ToInt64(row[2]) // Check if we know about the table or it has been recreated. if _, ok := se.tables[tableName]; !ok || createTime >= se.lastChange { - func() { - // Unlock so TableWasCreatedOrAltered can lock. - se.mu.Unlock() - defer se.mu.Lock() - log.Infof("Reloading schema for table: %s", tableName) - rec.RecordError(se.TableWasCreatedOrAltered(ctx, tableName)) - }() - // In case someone closed se when lock was released. - if !se.isOpen { - return nil - } - continue + log.Infof("Reloading schema for table: %s", tableName) + rec.RecordError(se.tableWasCreatedOrAltered(ctx, tableName)) + } else { + // Only update table_rows, data_length, index_length, max_data_length + se.tables[tableName].SetMysqlStats(row[4], row[5], row[6], row[7], row[8]) } - // Only update table_rows, data_length, index_length, max_data_length - se.tables[tableName].SetMysqlStats(row[4], row[5], row[6], row[7], row[8]) } se.lastChange = curTime @@ -284,7 +274,7 @@ func (se *Engine) Reload(ctx context.Context) error { dropped = append(dropped, tableName) } // We only need to broadcast dropped tables because - // TableWasCreatedOrAltered will broadcast the other changes. + // tableWasCreatedOrAltered will broadcast the other changes. if len(dropped) > 0 { se.broadcast(nil, nil, dropped) } @@ -306,10 +296,9 @@ func (se *Engine) mysqlTime(ctx context.Context, conn *connpool.DBConn) (int64, return t, nil } -// TableWasCreatedOrAltered must be called if a DDL was applied to that table. -func (se *Engine) TableWasCreatedOrAltered(ctx context.Context, tableName string) error { - se.mu.Lock() - defer se.mu.Unlock() +// tableWasCreatedOrAltered must be called if a DDL was applied to that table. +// the se.mu mutex _must_ be locked before entering this method +func (se *Engine) tableWasCreatedOrAltered(ctx context.Context, tableName string) error { if !se.isOpen { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "DDL called on closed schema") } @@ -322,7 +311,7 @@ func (se *Engine) TableWasCreatedOrAltered(ctx context.Context, tableName string tableData, err := conn.Exec(ctx, mysql.BaseShowTablesForTable(tableName), 1, false) if err != nil { tabletenv.InternalErrors.Add("Schema", 1) - return vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "TableWasCreatedOrAltered: information_schema query failed for table %s: %v", tableName, err) + return vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "tableWasCreatedOrAltered: information_schema query failed for table %s: %v", tableName, err) } if len(tableData.Rows) != 1 { // This can happen if DDLs race with each other. @@ -337,7 +326,7 @@ func (se *Engine) TableWasCreatedOrAltered(ctx context.Context, tableName string ) if err != nil { tabletenv.InternalErrors.Add("Schema", 1) - return vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "TableWasCreatedOrAltered: failed to load table %s: %v", tableName, err) + return vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "tableWasCreatedOrAltered: failed to load table %s: %v", tableName, err) } // table_rows, data_length, index_length, max_data_length table.SetMysqlStats(row[4], row[5], row[6], row[7], row[8]) @@ -407,7 +396,7 @@ func (se *Engine) GetTable(tableName sqlparser.TableIdent) *Table { } // GetSchema returns the current The Tables are a shared -// data strucutre and must be treated as read-only. +// data structure and must be treated as read-only. func (se *Engine) GetSchema() map[string]*Table { se.mu.Lock() defer se.mu.Unlock() diff --git a/go/vt/vttablet/tabletserver/schema/engine_test.go b/go/vt/vttablet/tabletserver/schema/engine_test.go index 2d535f3d0d8..09ab7089379 100644 --- a/go/vt/vttablet/tabletserver/schema/engine_test.go +++ b/go/vt/vttablet/tabletserver/schema/engine_test.go @@ -241,7 +241,7 @@ func TestCreateOrUpdateTableFailedDuetoExecErr(t *testing.T) { defer se.Close() originalSchemaErrorCount := tabletenv.InternalErrors.Counts()["Schema"] // should silently fail: no errors returned, but increment a counter - se.TableWasCreatedOrAltered(context.Background(), "test_table") + se.tableWasCreatedOrAltered(context.Background(), "test_table") newSchemaErrorCount := tabletenv.InternalErrors.Counts()["Schema"] schemaErrorDiff := newSchemaErrorCount - originalSchemaErrorCount @@ -285,7 +285,7 @@ func TestCreateOrUpdateTable(t *testing.T) { i++ }) defer se.UnregisterNotifier("test") - if err := se.TableWasCreatedOrAltered(context.Background(), "test_table_01"); err != nil { + if err := se.tableWasCreatedOrAltered(context.Background(), "test_table_01"); err != nil { t.Fatal(err) } if i < 2 { @@ -327,7 +327,7 @@ func TestUpdatedMysqlStats(t *testing.T) { mysql.BaseShowTablesRow(tableName.String(), false, ""), }, }) - // Add queries necessary for TableWasCreatedOrAltered() and NewTable() + // Add queries necessary for tableWasCreatedOrAltered() and NewTable() db.AddQuery(mysql.BaseShowTablesForTable(tableName.String()), &sqltypes.Result{ Fields: mysql.BaseShowTablesFields, RowsAffected: 1, diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 2ae3ca6ac82..07231489dce 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -702,8 +702,7 @@ func (tsv *TabletServer) isMySQLReachable() bool { // ReloadSchema reloads the schema. func (tsv *TabletServer) ReloadSchema(ctx context.Context) error { - tsv.se.Reload(ctx) - return nil + return tsv.se.Reload(ctx) } // ClearQueryPlanCache clears internal query plan cache @@ -1683,7 +1682,7 @@ func (se *splitQuerySQLExecuter) SQLExecute( // we don't have to parse the query again here. ast, err := sqlparser.Parse(sql) if err != nil { - return nil, fmt.Errorf("splitQuerySQLExecuter: parsing sql failed with: %v", err) + return nil, vterrors.Wrap(err, "splitQuerySQLExecuter: parsing sql failed with") } parsedQuery := sqlparser.NewParsedQuery(ast) diff --git a/go/vt/vttablet/tabletserver/twopc.go b/go/vt/vttablet/tabletserver/twopc.go index b707d41b6c2..292c47594bd 100644 --- a/go/vt/vttablet/tabletserver/twopc.go +++ b/go/vt/vttablet/tabletserver/twopc.go @@ -422,7 +422,7 @@ func (tpc *TwoPC) ReadTransaction(ctx context.Context, dtid string) (*querypb.Tr result.Dtid = qr.Rows[0][0].ToString() st, err := sqltypes.ToInt64(qr.Rows[0][1]) if err != nil { - return nil, fmt.Errorf("Error parsing state for dtid %s: %v", dtid, err) + 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 { diff --git a/go/vt/vttest/environment.go b/go/vt/vttest/environment.go index 05b3772b114..330ca80a759 100644 --- a/go/vt/vttest/environment.go +++ b/go/vt/vttest/environment.go @@ -118,6 +118,9 @@ func GetMySQLOptions(flavor string) (string, []string, error) { mycnf := []string{"config/mycnf/vtcombo.cnf"} switch flavor { + case "MariaDB103": + mycnf = append(mycnf, "config/mycnf/default-fast.cnf") + mycnf = append(mycnf, "config/mycnf/master_mariadb103.cnf") case "MariaDB": mycnf = append(mycnf, "config/mycnf/default-fast.cnf") mycnf = append(mycnf, "config/mycnf/master_mariadb.cnf") @@ -216,9 +219,6 @@ func (env *LocalTestEnv) TearDown() error { func tmpdir(dataroot string) (dir string, err error) { dir, err = ioutil.TempDir(dataroot, "vttest") - if err == nil { - err = os.Mkdir(path.Join(dir, "logs"), 0700) - } return } @@ -244,12 +244,22 @@ func randomPort() int { // given MySQL flavor. This will use the `mysqlctl` command to initialize and // teardown a single mysqld instance. func NewLocalTestEnv(flavor string, basePort int) (*LocalTestEnv, error) { - flavor, mycnf, err := GetMySQLOptions(flavor) + directory, err := tmpdir(os.Getenv("VTDATAROOT")) if err != nil { return nil, err } + return NewLocalTestEnvWithDirectory(flavor, basePort, directory) +} - directory, err := tmpdir(os.Getenv("VTDATAROOT")) +// NewLocalTestEnvWithDirectory returns a new instance of the default test +// environment with a directory explicitly specified. +func NewLocalTestEnvWithDirectory(flavor string, basePort int, directory string) (*LocalTestEnv, error) { + err := os.Mkdir(path.Join(directory, "logs"), 0700) + if err != nil { + return nil, err + } + + flavor, mycnf, err := GetMySQLOptions(flavor) if err != nil { return nil, err } diff --git a/go/vt/vttest/local_cluster.go b/go/vt/vttest/local_cluster.go index fd4e308cbab..b69c2ccec74 100644 --- a/go/vt/vttest/local_cluster.go +++ b/go/vt/vttest/local_cluster.go @@ -66,6 +66,11 @@ type Config struct { // If no schema is found in SchemaDir, default to this location. DefaultSchemaDir string + // DataDir is the directory where the data files will be placed. + // If no directory is specified a random directory will be used + // under VTDATAROOT. + DataDir string + // Charset is the default charset used by MySQL Charset string @@ -91,6 +96,9 @@ type Config struct { // initialize the mysqld instance in the cluster. Note that some environments // do not suppport initialization through snapshot files. SnapshotFile string + + // TransactionMode is SINGLE, MULTI or TWOPC + TransactionMode string } // InitSchemas is a shortcut for tests that just want to setup a single @@ -413,6 +421,7 @@ func (db *LocalCluster) JSONConfig() interface{} { "port": db.vt.Port, "socket": db.mysql.UnixSocket(), "vtcombo_mysql_port": db.Env.PortForProtocol("vtcombo_mysql_port", ""), + "mysql": db.Env.PortForProtocol("mysql", ""), } if grpc := db.vt.PortGrpc; grpc != 0 { diff --git a/go/vt/vttest/vtprocess.go b/go/vt/vttest/vtprocess.go index af5901edabd..e3065477033 100644 --- a/go/vt/vttest/vtprocess.go +++ b/go/vt/vttest/vtprocess.go @@ -23,10 +23,12 @@ import ( "net/http" "os" "os/exec" - "path" + "strings" "syscall" "time" + "vitess.io/vitess/go/vt/log" + "github.com/golang/protobuf/proto" ) @@ -134,15 +136,16 @@ func (vtp *VtProcess) WaitStart() (err error) { vtp.proc.Args = append(vtp.proc.Args, vtp.ExtraArgs...) - logfile := path.Join(vtp.LogDirectory, fmt.Sprintf("%s.%d.log", vtp.Name, vtp.Port)) - vtp.proc.Stderr, err = os.Create(logfile) - if err != nil { - return - } + vtp.proc.Stderr = os.Stderr + vtp.proc.Stdout = os.Stdout vtp.proc.Env = append(vtp.proc.Env, os.Environ()...) vtp.proc.Env = append(vtp.proc.Env, vtp.Env...) + vtp.proc.Stderr = os.Stderr + vtp.proc.Stderr = os.Stdout + + log.Infof("%v %v", strings.Join(vtp.proc.Args, " ")) err = vtp.proc.Start() if err != nil { return @@ -231,6 +234,9 @@ func VtcomboProcess(env Environment, args *Config, mysql MySQLManager) *VtProces if args.WebDir2 != "" { vt.ExtraArgs = append(vt.ExtraArgs, []string{"-web_dir2", args.WebDir2}...) } + if args.TransactionMode != "" { + vt.ExtraArgs = append(vt.ExtraArgs, []string{"-transaction_mode", args.TransactionMode}...) + } if socket != "" { vt.ExtraArgs = append(vt.ExtraArgs, []string{ diff --git a/go/vt/vttls/vttls.go b/go/vt/vttls/vttls.go index bfbace45db0..03926e0647b 100644 --- a/go/vt/vttls/vttls.go +++ b/go/vt/vttls/vttls.go @@ -23,10 +23,38 @@ import ( "io/ioutil" ) +// Updated list of acceptable cipher suits to address +// Fixed upstream in https://github.com/golang/go/issues/13385 +// This removed CBC mode ciphers that are suseptiable to Lucky13 style attacks +func newTLSConfig() *tls.Config { + return &tls.Config{ + // MySQL Community edition has some problems with TLS1.2 + // TODO: Validate this will not break servers using mysql community edition < 5.7.10 + // MinVersion: tls.VersionTLS12, + + // Default ordering taken from + // go 1.11 crypto/tls/cipher_suites.go + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_128_CBC_SHA, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + }, + } +} + // ClientConfig returns the TLS config to use for a client to // connect to a server with the provided parameters. func ClientConfig(cert, key, ca, name string) (*tls.Config, error) { - config := &tls.Config{} + config := newTLSConfig() // Load the client-side cert & key if any. if cert != "" && key != "" { @@ -61,7 +89,7 @@ func ClientConfig(cert, key, ca, name string) (*tls.Config, error) { // ServerConfig returns the TLS config to use for a server to // accept client connections. func ServerConfig(cert, key, ca string) (*tls.Config, error) { - config := &tls.Config{} + config := newTLSConfig() // Load the server cert and key. crt, err := tls.LoadX509KeyPair(cert, key) diff --git a/go/vt/worker/block_cmd.go b/go/vt/worker/block_cmd.go index 4644030d673..a2e27411d5d 100644 --- a/go/vt/worker/block_cmd.go +++ b/go/vt/worker/block_cmd.go @@ -22,6 +22,8 @@ import ( "html/template" "net/http" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/wrangler" ) @@ -57,14 +59,14 @@ func commandBlock(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagSet, a worker, err := NewBlockWorker(wr) if err != nil { - return nil, fmt.Errorf("Could not create Block worker: %v", err) + return nil, vterrors.Wrap(err, "Could not create Block worker") } return worker, nil } func interactiveBlock(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("Cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } if submit := r.FormValue("submit"); submit == "" { @@ -74,7 +76,7 @@ func interactiveBlock(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, wrk, err := NewBlockWorker(wr) if err != nil { - return nil, nil, nil, fmt.Errorf("Could not create Block worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "Could not create Block worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/chunk.go b/go/vt/worker/chunk.go index 8cb75771e8d..9a005b7956e 100644 --- a/go/vt/worker/chunk.go +++ b/go/vt/worker/chunk.go @@ -19,6 +19,8 @@ package worker import ( "fmt" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqlescape" @@ -95,7 +97,7 @@ func generateChunks(ctx context.Context, wr *wrangler.Wrangler, tablet *topodata qr, err := wr.TabletManagerClient().ExecuteFetchAsApp(shortCtx, tablet, true, []byte(query), 1) cancel() if err != nil { - return nil, fmt.Errorf("tablet: %v, table: %v: cannot determine MIN and MAX of the first primary key column. ExecuteFetchAsApp: %v", topoproto.TabletAliasString(tablet.Alias), td.Name, err) + return nil, vterrors.Wrapf(err, "tablet: %v, table: %v: cannot determine MIN and MAX of the first primary key column. ExecuteFetchAsApp: %v", topoproto.TabletAliasString(tablet.Alias), td.Name) } if len(qr.Rows) != 1 { return nil, fmt.Errorf("tablet: %v, table: %v: cannot determine MIN and MAX of the first primary key column. Zero rows were returned", topoproto.TabletAliasString(tablet.Alias), td.Name) @@ -155,7 +157,7 @@ func generateChunks(ctx context.Context, wr *wrangler.Wrangler, tablet *topodata end := add(start, interval) chunk, err := toChunk(start, end, i+1, chunkCount) if err != nil { - return nil, fmt.Errorf("tablet: %v, table: %v: %v", topoproto.TabletAliasString(tablet.Alias), td.Name, err) + return nil, vterrors.Wrapf(err, "tablet: %v, table: %v", topoproto.TabletAliasString(tablet.Alias), td.Name) } chunks[i] = chunk start = end @@ -185,11 +187,11 @@ func add(start, interval interface{}) interface{} { func toChunk(start, end interface{}, number, total int) (chunk, error) { startValue, err := sqltypes.InterfaceToValue(start) if err != nil { - return chunk{}, fmt.Errorf("failed to convert calculated start value (%v) into internal sqltypes.Value: %v", start, err) + return chunk{}, vterrors.Wrapf(err, "failed to convert calculated start value (%v) into internal sqltypes.Value", start) } endValue, err := sqltypes.InterfaceToValue(end) if err != nil { - return chunk{}, fmt.Errorf("failed to convert calculated end value (%v) into internal sqltypes.Value: %v", end, err) + return chunk{}, vterrors.Wrapf(err, "failed to convert calculated end value (%v) into internal sqltypes.Value", end) } return chunk{startValue, endValue, number, total}, nil } diff --git a/go/vt/worker/diff_utils.go b/go/vt/worker/diff_utils.go index 339a96c533a..ae9ba1a6ba9 100644 --- a/go/vt/worker/diff_utils.go +++ b/go/vt/worker/diff_utils.go @@ -26,6 +26,8 @@ import ( "strings" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "github.com/golang/protobuf/proto" @@ -79,7 +81,7 @@ func NewQueryResultReaderForTablet(ctx context.Context, ts *topo.Server, tabletA // read the columns, or grab the error cols, err := stream.Recv() if err != nil { - return nil, fmt.Errorf("Cannot read Fields for query '%v': %v", sql, err) + return nil, vterrors.Wrapf(err, "Cannot read Fields for query '%v'", sql) } return &QueryResultReader{ @@ -211,7 +213,7 @@ func TableScanByKeyRange(ctx context.Context, log logutil.Logger, ts *topo.Serve // switch to v3 mode. keyResolver, err := newV3ResolverFromColumnList(keyspaceSchema, td.Name, orderedColumns(td)) if err != nil { - return nil, fmt.Errorf("cannot resolve v3 sharding keys for table %v: %v", td.Name, err) + return nil, vterrors.Wrapf(err, "cannot resolve v3 sharding keys for table %v", td.Name) } // full table scan @@ -497,6 +499,7 @@ func (rd *RowDiffer) Go(log logutil.Logger) (dr DiffReport, err error) { } // drain right, update count + log.Errorf("Draining extra row(s) found on the right starting with: %v", right) if count, err := rd.right.Drain(); err != nil { return dr, err } else { @@ -507,6 +510,7 @@ func (rd *RowDiffer) Go(log logutil.Logger) (dr DiffReport, err error) { if right == nil { // no more rows from the right // we know we have rows from left, drain, update count + log.Errorf("Draining extra row(s) found on the left starting with: %v", left) if count, err := rd.left.Drain(); err != nil { return dr, err } else { diff --git a/go/vt/worker/executor.go b/go/vt/worker/executor.go index 2018cccef79..bc9cedfce87 100644 --- a/go/vt/worker/executor.go +++ b/go/vt/worker/executor.go @@ -20,6 +20,8 @@ import ( "fmt" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/discovery" @@ -75,7 +77,7 @@ func (e *executor) fetchLoop(ctx context.Context, insertChannel chan string) err _, err := e.wr.TabletManagerClient().ExecuteFetchAsApp(ctx, tablet, true, []byte(cmd), 0) return err }); err != nil { - return fmt.Errorf("ExecuteFetch failed: %v", err) + return vterrors.Wrap(err, "ExecuteFetch failed") } case <-ctx.Done(): // Doesn't really matter if this select gets starved, because the other case @@ -232,7 +234,7 @@ func (e *executor) checkError(ctx context.Context, err error, isRetry bool, mast statsRetryCounters.Add(retryCategoryConnectionError, 1) case errNo == "1062": if !isRetry { - return false, fmt.Errorf("ExecuteFetch failed on %v on the first attempt; not retrying as this is not a recoverable error: %v", tabletString, err) + return false, vterrors.Wrapf(err, "ExecuteFetch failed on %v on the first attempt; not retrying as this is not a recoverable error", tabletString) } e.wr.Logger().Infof("ExecuteFetch failed on %v with a duplicate entry error; marking this as a success, because of the likelihood that this query has already succeeded before being retried: %v", tabletString, err) return true, nil diff --git a/go/vt/worker/interactive.go b/go/vt/worker/interactive.go index 4ac62976e01..dc4a7cba5ac 100644 --- a/go/vt/worker/interactive.go +++ b/go/vt/worker/interactive.go @@ -57,8 +57,8 @@ const subIndexHTML = ` ` func httpError(w http.ResponseWriter, format string, args ...interface{}) { - log.Errorf(format, args) - http.Error(w, fmt.Sprintf(format, args), http.StatusInternalServerError) + log.Errorf(format, args...) + http.Error(w, fmt.Sprintf(format, args...), http.StatusInternalServerError) } func mustParseTemplate(name, contents string) *template.Template { @@ -72,7 +72,7 @@ func mustParseTemplate(name, contents string) *template.Template { func executeTemplate(w http.ResponseWriter, t *template.Template, data interface{}) { if err := t.Execute(w, data); err != nil { - httpError(w, "error executing template", err) + httpError(w, "error executing template: %v", err) } } diff --git a/go/vt/worker/key_resolver.go b/go/vt/worker/key_resolver.go index 07498a7520c..193d807dba4 100644 --- a/go/vt/worker/key_resolver.go +++ b/go/vt/worker/key_resolver.go @@ -20,6 +20,8 @@ import ( "errors" "fmt" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" @@ -80,7 +82,7 @@ func (r *v2Resolver) keyspaceID(row []sqltypes.Value) ([]byte, error) { case topodatapb.KeyspaceIdType_UINT64: i, err := sqltypes.ToUint64(v) if err != nil { - return nil, fmt.Errorf("Non numerical value: %v", err) + return nil, vterrors.Wrap(err, "Non numerical value") } return key.Uint64Key(i).Bytes(), nil default: diff --git a/go/vt/worker/legacy_split_clone.go b/go/vt/worker/legacy_split_clone.go index df6c0dbc2f2..08bbb39ebff 100644 --- a/go/vt/worker/legacy_split_clone.go +++ b/go/vt/worker/legacy_split_clone.go @@ -27,6 +27,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/event" @@ -235,7 +237,7 @@ func (scw *LegacySplitCloneWorker) Run(ctx context.Context) error { func (scw *LegacySplitCloneWorker) run(ctx context.Context) error { // first state: read what we need to do if err := scw.init(ctx); err != nil { - return fmt.Errorf("init() failed: %v", err) + return vterrors.Wrap(err, "init() failed") } if err := checkDone(ctx); err != nil { return err @@ -243,7 +245,7 @@ func (scw *LegacySplitCloneWorker) run(ctx context.Context) error { // second state: find targets if err := scw.findTargets(ctx); err != nil { - return fmt.Errorf("findTargets() failed: %v", err) + return vterrors.Wrap(err, "findTargets() failed") } if err := checkDone(ctx); err != nil { return err @@ -251,7 +253,7 @@ func (scw *LegacySplitCloneWorker) run(ctx context.Context) error { // third state: copy data if err := scw.copy(ctx); err != nil { - return fmt.Errorf("copy() failed: %v", err) + return vterrors.Wrap(err, "copy() failed") } return nil @@ -268,7 +270,7 @@ func (scw *LegacySplitCloneWorker) init(ctx context.Context) error { scw.keyspaceInfo, err = scw.wr.TopoServer().GetKeyspace(shortCtx, scw.keyspace) cancel() if err != nil { - return fmt.Errorf("cannot read keyspace %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot read keyspace %v", scw.keyspace) } // find the OverlappingShards in the keyspace @@ -276,7 +278,7 @@ func (scw *LegacySplitCloneWorker) init(ctx context.Context) error { osList, err := topotools.FindOverlappingShards(shortCtx, scw.wr.TopoServer(), scw.keyspace) cancel() if err != nil { - return fmt.Errorf("cannot FindOverlappingShards in %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot FindOverlappingShards in %v", scw.keyspace) } // find the shard we mentioned in there, if any @@ -336,7 +338,7 @@ func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error { for i, si := range scw.sourceShards { scw.sourceAliases[i], err = FindWorkerTablet(ctx, scw.wr, scw.cleaner, scw.tsc, scw.cell, si.Keyspace(), si.ShardName(), scw.minHealthyRdonlyTablets, topodatapb.TabletType_RDONLY) if err != nil { - return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", scw.cell, si.Keyspace(), si.ShardName(), err) + return vterrors.Wrapf(err, "FindWorkerTablet() failed for %v/%v/%v", scw.cell, si.Keyspace(), si.ShardName()) } scw.wr.Logger().Infof("Using tablet %v as source for %v/%v", topoproto.TabletAliasString(scw.sourceAliases[i]), si.Keyspace(), si.ShardName()) } @@ -348,7 +350,7 @@ func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error { ti, err := scw.wr.TopoServer().GetTablet(shortCtx, alias) cancel() if err != nil { - return fmt.Errorf("cannot read tablet %v: %v", topoproto.TabletAliasString(alias), err) + return vterrors.Wrapf(err, "cannot read tablet %v", topoproto.TabletAliasString(alias)) } scw.sourceTablets[i] = ti.Tablet @@ -378,7 +380,7 @@ func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error { waitCtx, waitCancel := context.WithTimeout(ctx, 10*time.Second) defer waitCancel() if err := scw.tsc.WaitForTablets(waitCtx, scw.cell, si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER); err != nil { - return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v: %v", si.Keyspace(), si.ShardName(), err) + return vterrors.Wrapf(err, "cannot find MASTER tablet for destination shard for %v/%v", si.Keyspace(), si.ShardName()) } masters := scw.tsc.GetHealthyTabletStats(si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER) if len(masters) == 0 { @@ -391,7 +393,7 @@ func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error { ti, err := scw.wr.TopoServer().GetTablet(shortCtx, master.Tablet.Alias) cancel() if err != nil { - return fmt.Errorf("cannot get the TabletInfo for destination master (%v) to find out its db name: %v", topoproto.TabletAliasString(master.Tablet.Alias), err) + return vterrors.Wrapf(err, "cannot get the TabletInfo for destination master (%v) to find out its db name", topoproto.TabletAliasString(master.Tablet.Alias)) } keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName()) scw.destinationDbNames[keyspaceAndShard] = ti.DbName() @@ -406,7 +408,7 @@ func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error { t, err := throttler.NewThrottler( keyspaceAndShard, "transactions", scw.destinationWriterCount, scw.maxTPS, throttler.ReplicationLagModuleDisabled) if err != nil { - return fmt.Errorf("cannot instantiate throttler: %v", err) + return vterrors.Wrap(err, "cannot instantiate throttler") } scw.destinationThrottlers[keyspaceAndShard] = t } @@ -434,7 +436,7 @@ func (scw *LegacySplitCloneWorker) copy(ctx context.Context) error { sourceSchemaDefinition, err := scw.wr.GetSchema(shortCtx, scw.sourceAliases[0], nil, scw.excludeTables, false /* includeViews */) cancel() if err != nil { - return fmt.Errorf("cannot get schema from source %v: %v", topoproto.TabletAliasString(scw.sourceAliases[0]), err) + return vterrors.Wrapf(err, "cannot get schema from source %v", topoproto.TabletAliasString(scw.sourceAliases[0])) } if len(sourceSchemaDefinition.TableDefinitions) == 0 { return fmt.Errorf("no tables matching the table filter in tablet %v", topoproto.TabletAliasString(scw.sourceAliases[0])) @@ -498,7 +500,7 @@ func (scw *LegacySplitCloneWorker) copy(ctx context.Context) error { if *useV3ReshardingMode { kschema, err := scw.wr.TopoServer().GetVSchema(ctx, scw.keyspace) if err != nil { - return fmt.Errorf("cannot load VSchema for keyspace %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot load VSchema for keyspace %v", scw.keyspace) } if kschema == nil { return fmt.Errorf("no VSchema for keyspace %v", scw.keyspace) @@ -506,7 +508,7 @@ func (scw *LegacySplitCloneWorker) copy(ctx context.Context) error { keyspaceSchema, err = vindexes.BuildKeyspaceSchema(kschema, scw.keyspace) if err != nil { - return fmt.Errorf("cannot build vschema for keyspace %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot build vschema for keyspace %v", scw.keyspace) } } @@ -520,12 +522,12 @@ func (scw *LegacySplitCloneWorker) copy(ctx context.Context) error { if *useV3ReshardingMode { keyResolver, err = newV3ResolverFromTableDefinition(keyspaceSchema, td) if err != nil { - return fmt.Errorf("cannot resolve v3 sharding keys for keyspace %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot resolve v3 sharding keys for keyspace %v", scw.keyspace) } } else { keyResolver, err = newV2Resolver(scw.keyspaceInfo, td) if err != nil { - return fmt.Errorf("cannot resolve sharding keys for keyspace %v: %v", scw.keyspace, err) + return vterrors.Wrapf(err, "cannot resolve sharding keys for keyspace %v", scw.keyspace) } } rowSplitter := NewRowSplitter(scw.destinationShards, keyResolver) @@ -657,7 +659,7 @@ func (scw *LegacySplitCloneWorker) processData(ctx context.Context, dbNames []st // Split the rows by keyspace ID, and insert each chunk into each destination if err := rowSplitter.Split(sr, r.Rows); err != nil { - return fmt.Errorf("RowSplitter failed for table %v: %v", td.Name, err) + return vterrors.Wrapf(err, "RowSplitter failed for table %v", td.Name) } scw.tableStatusList.addCopiedRows(tableIndex, len(r.Rows)) diff --git a/go/vt/worker/legacy_split_clone_cmd.go b/go/vt/worker/legacy_split_clone_cmd.go index 8abfcd630b2..ff48c291d4b 100644 --- a/go/vt/worker/legacy_split_clone_cmd.go +++ b/go/vt/worker/legacy_split_clone_cmd.go @@ -27,6 +27,8 @@ import ( "strconv" "strings" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/wrangler" @@ -110,14 +112,14 @@ func commandLegacySplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *flag } worker, err := NewLegacySplitCloneWorker(wr, wi.cell, keyspace, shard, excludeTableArray, *sourceReaderCount, *destinationPackCount, *destinationWriterCount, *minHealthyRdonlyTablets, *maxTPS) if err != nil { - return nil, fmt.Errorf("cannot create split clone worker: %v", err) + return nil, vterrors.Wrap(err, "cannot create split clone worker") } return worker, nil } func interactiveLegacySplitClone(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } keyspace := r.FormValue("keyspace") @@ -158,32 +160,32 @@ func interactiveLegacySplitClone(ctx context.Context, wi *Instance, wr *wrangler } sourceReaderCount, err := strconv.ParseInt(sourceReaderCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse sourceReaderCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse sourceReaderCount") } destinationPackCount, err := strconv.ParseInt(destinationPackCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse destinationPackCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse destinationPackCount") } destinationWriterCountStr := r.FormValue("destinationWriterCount") destinationWriterCount, err := strconv.ParseInt(destinationWriterCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse destinationWriterCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse destinationWriterCount") } minHealthyRdonlyTabletsStr := r.FormValue("minHealthyRdonlyTablets") minHealthyRdonlyTablets, err := strconv.ParseInt(minHealthyRdonlyTabletsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minHealthyRdonlyTablets: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minHealthyRdonlyTablets") } maxTPSStr := r.FormValue("maxTPS") maxTPS, err := strconv.ParseInt(maxTPSStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse maxTPS: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse maxTPS") } // start the clone job wrk, err := NewLegacySplitCloneWorker(wr, wi.cell, keyspace, shard, excludeTableArray, int(sourceReaderCount), int(destinationPackCount), int(destinationWriterCount), int(minHealthyRdonlyTablets), maxTPS) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot create worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot create worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/panic_cmd.go b/go/vt/worker/panic_cmd.go index 45c2ae08e62..efe1f6a8b2d 100644 --- a/go/vt/worker/panic_cmd.go +++ b/go/vt/worker/panic_cmd.go @@ -18,10 +18,11 @@ package worker import ( "flag" - "fmt" "html/template" "net/http" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/wrangler" ) @@ -29,7 +30,7 @@ import ( func commandPanic(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) (Worker, error) { worker, err := NewPanicWorker(wr) if err != nil { - return nil, fmt.Errorf("Could not create Panic worker: %v", err) + return nil, vterrors.Wrap(err, "Could not create Panic worker") } return worker, nil } @@ -37,7 +38,7 @@ func commandPanic(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagSet, a func interactivePanic(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { wrk, err := NewPanicWorker(wr) if err != nil { - return nil, nil, nil, fmt.Errorf("Could not create Panic worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "Could not create Panic worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/ping_cmd.go b/go/vt/worker/ping_cmd.go index 52b1ef9b36a..f0658ab1264 100644 --- a/go/vt/worker/ping_cmd.go +++ b/go/vt/worker/ping_cmd.go @@ -22,6 +22,8 @@ import ( "html/template" "net/http" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/wrangler" ) @@ -60,14 +62,14 @@ func commandPing(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagSet, ar worker, err := NewPingWorker(wr, message) if err != nil { - return nil, fmt.Errorf("Could not create Ping worker: %v", err) + return nil, vterrors.Wrap(err, "Could not create Ping worker") } return worker, nil } func interactivePing(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("Cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "Cannot parse form") } message := r.FormValue("message") @@ -78,7 +80,7 @@ func interactivePing(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w wrk, err := NewPingWorker(wr, message) if err != nil { - return nil, nil, nil, fmt.Errorf("Could not create Ping worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "Could not create Ping worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/restartable_result_reader.go b/go/vt/worker/restartable_result_reader.go index cc4452db699..1a629e57236 100644 --- a/go/vt/worker/restartable_result_reader.go +++ b/go/vt/worker/restartable_result_reader.go @@ -23,6 +23,8 @@ import ( "strings" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqlescape" @@ -82,10 +84,10 @@ func NewRestartableResultReader(ctx context.Context, logger logutil.Logger, tp t // If the initial connection fails, we do not restart. if _ /* retryable */, err := r.getTablet(); err != nil { - return nil, fmt.Errorf("tablet=unknown: %v", err) + return nil, vterrors.Wrap(err, "tablet=unknown") } if _ /* retryable */, err := r.startStream(); err != nil { - return nil, fmt.Errorf("tablet=%v: %v", topoproto.TabletAliasString(r.tablet.Alias), err) + return nil, vterrors.Wrapf(err, "tablet=%v", topoproto.TabletAliasString(r.tablet.Alias)) } return r, nil } @@ -107,13 +109,13 @@ func (r *RestartableResultReader) getTablet() (bool, error) { // Get a tablet from the tablet provider. tablet, err := r.tp.getTablet() if err != nil { - return true /* retryable */, fmt.Errorf("failed get tablet for streaming query: %v", err) + return true /* retryable */, vterrors.Wrap(err, "failed get tablet for streaming query") } // Connect (dial) to the tablet. conn, err := tabletconn.GetDialer()(tablet, grpcclient.FailFast(false)) if err != nil { - return false /* retryable */, fmt.Errorf("failed to get dialer for tablet: %v", err) + return false /* retryable */, vterrors.Wrap(err, "failed to get dialer for tablet") } r.tablet = tablet r.conn = conn @@ -136,7 +138,7 @@ func (r *RestartableResultReader) startStream() (bool, error) { // Read the fields information. cols, err := stream.Recv() if err != nil { - return true /* retryable */, fmt.Errorf("cannot read Fields for query '%v': %v", r.query, err) + return true /* retryable */, vterrors.Wrapf(err, "cannot read Fields for query '%v'", r.query) } r.fields = cols.Fields r.output = stream @@ -225,7 +227,7 @@ func (r *RestartableResultReader) nextWithRetries() (*sqltypes.Result, error) { retry: if attempt == 2 && !r.allowMultipleRetries { // Offline source tablets must not be retried forever. Fail early. - return nil, fmt.Errorf("%v: first retry to restart the streaming query on the same tablet failed. We're failing at this point because we're not allowed to keep retrying. err: %v", r.tp.description(), err) + return nil, vterrors.Wrapf(err, "%v: first retry to restart the streaming query on the same tablet failed. We're failing at this point because we're not allowed to keep retrying. err", r.tp.description()) } alias := "unknown" diff --git a/go/vt/worker/result_merger.go b/go/vt/worker/result_merger.go index 62c8e95a809..d5a2ca26c94 100644 --- a/go/vt/worker/result_merger.go +++ b/go/vt/worker/result_merger.go @@ -21,6 +21,8 @@ import ( "fmt" "io" + "vitess.io/vitess/go/vt/vterrors" + "github.com/golang/protobuf/proto" "vitess.io/vitess/go/sqltypes" @@ -83,7 +85,7 @@ func NewResultMerger(inputs []ResultReader, pkFieldCount int) (*ResultMerger, er if err == io.EOF { continue } - return nil, fmt.Errorf("failed to read from input at index: %v ResultReader: %v err: %v", i, input, err) + return nil, vterrors.Wrapf(err, "failed to read from input at index: %v ResultReader: %v err", i, input) } activeInputs = append(activeInputs, input) heap.Push(nextRowHeap, nextRow) @@ -149,7 +151,7 @@ func (rm *ResultMerger) Next() (*sqltypes.Result, error) { rm.lastRowReaderDrained = true break } else { - return nil, fmt.Errorf("failed to read from input ResultReader: %v err: %v", next.input, err) + return nil, vterrors.Wrapf(err, "failed to read from input ResultReader: %v err", next.input) } } // Input has more rows. Add it back to the priority queue. diff --git a/go/vt/worker/row_differ.go b/go/vt/worker/row_differ.go index a6be54c2f4f..1253f95f72c 100644 --- a/go/vt/worker/row_differ.go +++ b/go/vt/worker/row_differ.go @@ -20,6 +20,8 @@ import ( "fmt" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" @@ -278,11 +280,11 @@ func (rd *RowDiffer2) reconcileRow(row []sqltypes.Value, typ DiffType) error { } destShardIndex, err := rd.router.Route(row) if err != nil { - return fmt.Errorf("failed to route row (%v) to correct shard: %v", row, err) + return vterrors.Wrapf(err, "failed to route row (%v) to correct shard", row) } if err := rd.aggregators[destShardIndex][typ].Add(row); err != nil { - return fmt.Errorf("failed to add row update to RowAggregator: %v", err) + return vterrors.Wrap(err, "failed to add row update to RowAggregator") } // TODO(mberlin): Add more fine granular stats here. rd.tableStatusList.addCopiedRows(rd.tableIndex, 1) @@ -300,25 +302,25 @@ func (rd *RowDiffer2) updateRow(newRow, oldRow []sqltypes.Value, typ DiffType) e } destShardIndexOld, err := rd.router.Route(oldRow) if err != nil { - return fmt.Errorf("failed to route old row (%v) to correct shard: %v", oldRow, err) + return vterrors.Wrapf(err, "failed to route old row (%v) to correct shard", oldRow) } destShardIndexNew, err := rd.router.Route(newRow) if err != nil { - return fmt.Errorf("failed to route new row (%v) to correct shard: %v", newRow, err) + return vterrors.Wrapf(err, "failed to route new row (%v) to correct shard", newRow) } if destShardIndexOld == destShardIndexNew { // keyspace_id has not changed. Update the row in place on the destination. if err := rd.aggregators[destShardIndexNew][typ].Add(newRow); err != nil { - return fmt.Errorf("failed to add row update to RowAggregator (keyspace_id not changed): %v", err) + return vterrors.Wrap(err, "failed to add row update to RowAggregator (keyspace_id not changed)") } } else { // keyspace_id has changed. Delete the old row and insert the new one. if err := rd.aggregators[destShardIndexOld][DiffExtraneous].Add(oldRow); err != nil { - return fmt.Errorf("failed to add row update to RowAggregator (keyspace_id changed, deleting old row): %v", err) + return vterrors.Wrap(err, "failed to add row update to RowAggregator (keyspace_id changed, deleting old row)") } if err := rd.aggregators[destShardIndexNew][DiffMissing].Add(newRow); err != nil { - return fmt.Errorf("failed to add row update to RowAggregator (keyspace_id changed, inserting new row): %v", err) + return vterrors.Wrap(err, "failed to add row update to RowAggregator (keyspace_id changed, inserting new row)") } } diff --git a/go/vt/worker/split_clone.go b/go/vt/worker/split_clone.go index 191676d1857..6fe32e9a26d 100644 --- a/go/vt/worker/split_clone.go +++ b/go/vt/worker/split_clone.go @@ -24,6 +24,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/event" @@ -425,7 +427,7 @@ func (scw *SplitCloneWorker) Run(ctx context.Context) error { func (scw *SplitCloneWorker) run(ctx context.Context) error { // Phase 1: read what we need to do. if err := scw.init(ctx); err != nil { - return fmt.Errorf("init() failed: %v", err) + return vterrors.Wrap(err, "init() failed") } if err := checkDone(ctx); err != nil { return err @@ -433,7 +435,7 @@ func (scw *SplitCloneWorker) run(ctx context.Context) error { // Phase 2a: Find destination master tablets. if err := scw.findDestinationMasters(ctx); err != nil { - return fmt.Errorf("findDestinationMasters() failed: %v", err) + return vterrors.Wrap(err, "findDestinationMasters() failed") } if err := checkDone(ctx); err != nil { return err @@ -442,7 +444,7 @@ func (scw *SplitCloneWorker) run(ctx context.Context) error { // diff). Note that while we wait for the minimum number, we'll always use // *all* available RDONLY tablets from each destination shard. if err := scw.waitForTablets(ctx, scw.destinationShards, *waitForHealthyTabletsTimeout); err != nil { - return fmt.Errorf("waitForDestinationTablets(destinationShards) failed: %v", err) + return vterrors.Wrap(err, "waitForDestinationTablets(destinationShards) failed") } if err := checkDone(ctx); err != nil { return err @@ -453,12 +455,12 @@ func (scw *SplitCloneWorker) run(ctx context.Context) error { scw.wr.Logger().Infof("Online clone will be run now.") // 3a: Wait for minimum number of source tablets (required for the diff). if err := scw.waitForTablets(ctx, scw.sourceShards, *waitForHealthyTabletsTimeout); err != nil { - return fmt.Errorf("waitForDestinationTablets(sourceShards) failed: %v", err) + return vterrors.Wrap(err, "waitForDestinationTablets(sourceShards) failed") } // 3b: Clone the data. start := time.Now() if err := scw.clone(ctx, WorkerStateCloneOnline); err != nil { - return fmt.Errorf("online clone() failed: %v", err) + return vterrors.Wrap(err, "online clone() failed") } d := time.Since(start) if err := checkDone(ctx); err != nil { @@ -485,7 +487,7 @@ func (scw *SplitCloneWorker) run(ctx context.Context) error { // 4a: Take source tablets out of serving for an exact snapshot. if err := scw.findOfflineSourceTablets(ctx); err != nil { - return fmt.Errorf("findSourceTablets() failed: %v", err) + return vterrors.Wrap(err, "findSourceTablets() failed") } if err := checkDone(ctx); err != nil { return err @@ -494,7 +496,7 @@ func (scw *SplitCloneWorker) run(ctx context.Context) error { // 4b: Clone the data. start := time.Now() if err := scw.clone(ctx, WorkerStateCloneOffline); err != nil { - return fmt.Errorf("offline clone() failed: %v", err) + return vterrors.Wrap(err, "offline clone() failed") } d := time.Since(start) if err := checkDone(ctx); err != nil { @@ -521,28 +523,28 @@ func (scw *SplitCloneWorker) init(ctx context.Context) error { scw.destinationKeyspaceInfo, err = scw.wr.TopoServer().GetKeyspace(shortCtx, scw.destinationKeyspace) cancel() if err != nil { - return fmt.Errorf("cannot read (destination) keyspace %v: %v", scw.destinationKeyspace, err) + return vterrors.Wrapf(err, "cannot read (destination) keyspace %v", scw.destinationKeyspace) } // Set source and destination shard infos. switch scw.cloneType { case horizontalResharding: if err := scw.initShardsForHorizontalResharding(ctx); err != nil { - return fmt.Errorf("failed initShardsForHorizontalResharding: %s", err) + return vterrors.Wrap(err, "failed initShardsForHorizontalResharding") } case verticalSplit: if err := scw.initShardsForVerticalSplit(ctx); err != nil { - return fmt.Errorf("failed initShardsForVerticalSplit: %s", err) + return vterrors.Wrap(err, "failed initShardsForVerticalSplit") } } if err := scw.sanityCheckShardInfos(); err != nil { - return fmt.Errorf("failed sanityCheckShardInfos: %s", err) + return vterrors.Wrap(err, "failed sanityCheckShardInfos") } if scw.cloneType == horizontalResharding { if err := scw.loadVSchema(ctx); err != nil { - return fmt.Errorf("failed loadVSchema: %s", err) + return vterrors.Wrap(err, "failed loadVSchema") } } @@ -570,7 +572,7 @@ func (scw *SplitCloneWorker) initShardsForHorizontalResharding(ctx context.Conte osList, err := topotools.FindOverlappingShards(shortCtx, scw.wr.TopoServer(), scw.destinationKeyspace) cancel() if err != nil { - return fmt.Errorf("cannot FindOverlappingShards in %v: %v", scw.destinationKeyspace, err) + return vterrors.Wrapf(err, "cannot FindOverlappingShards in %v", scw.destinationKeyspace) } // find the shard we mentioned in there, if any @@ -619,7 +621,7 @@ func (scw *SplitCloneWorker) initShardsForVerticalSplit(ctx context.Context) err shardMap, err := scw.wr.TopoServer().FindAllShardsInKeyspace(shortCtx, sourceKeyspace) cancel() if err != nil { - return fmt.Errorf("cannot find source shard for source keyspace %s: %s", sourceKeyspace, err) + return vterrors.Wrapf(err, "cannot find source shard for source keyspace %s", sourceKeyspace) } if len(shardMap) != 1 { return fmt.Errorf("found the wrong number of source shards, there should be only one, %v", shardMap) @@ -689,7 +691,7 @@ func (scw *SplitCloneWorker) loadVSchema(ctx context.Context) error { if *useV3ReshardingMode { kschema, err := scw.wr.TopoServer().GetVSchema(ctx, scw.destinationKeyspace) if err != nil { - return fmt.Errorf("cannot load VSchema for keyspace %v: %v", scw.destinationKeyspace, err) + return vterrors.Wrapf(err, "cannot load VSchema for keyspace %v", scw.destinationKeyspace) } if kschema == nil { return fmt.Errorf("no VSchema for keyspace %v", scw.destinationKeyspace) @@ -697,7 +699,7 @@ func (scw *SplitCloneWorker) loadVSchema(ctx context.Context) error { keyspaceSchema, err = vindexes.BuildKeyspaceSchema(kschema, scw.destinationKeyspace) if err != nil { - return fmt.Errorf("cannot build vschema for keyspace %v: %v", scw.destinationKeyspace, err) + return vterrors.Wrapf(err, "cannot build vschema for keyspace %v", scw.destinationKeyspace) } scw.keyspaceSchema = keyspaceSchema } @@ -717,7 +719,7 @@ func (scw *SplitCloneWorker) findOfflineSourceTablets(ctx context.Context) error var err error scw.offlineSourceAliases[i], err = FindWorkerTablet(ctx, scw.wr, scw.cleaner, scw.tsc, scw.cell, si.Keyspace(), si.ShardName(), scw.minHealthyRdonlyTablets, topodatapb.TabletType_RDONLY) if err != nil { - return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", scw.cell, si.Keyspace(), si.ShardName(), err) + return vterrors.Wrapf(err, "FindWorkerTablet() failed for %v/%v/%v", scw.cell, si.Keyspace(), si.ShardName()) } scw.wr.Logger().Infof("Using tablet %v as source for %v/%v", topoproto.TabletAliasString(scw.offlineSourceAliases[i]), si.Keyspace(), si.ShardName()) } @@ -730,7 +732,7 @@ func (scw *SplitCloneWorker) findOfflineSourceTablets(ctx context.Context) error ti, err := scw.wr.TopoServer().GetTablet(shortCtx, alias) cancel() if err != nil { - return fmt.Errorf("cannot read tablet %v: %v", topoproto.TabletAliasString(alias), err) + return vterrors.Wrapf(err, "cannot read tablet %v", topoproto.TabletAliasString(alias)) } scw.sourceTablets[i] = ti.Tablet @@ -757,7 +759,7 @@ func (scw *SplitCloneWorker) findDestinationMasters(ctx context.Context) error { waitCtx, waitCancel := context.WithTimeout(ctx, *waitForHealthyTabletsTimeout) defer waitCancel() if err := scw.tsc.WaitForTablets(waitCtx, scw.cell, si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER); err != nil { - return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v (in cell: %v): %v", si.Keyspace(), si.ShardName(), scw.cell, err) + return vterrors.Wrapf(err, "cannot find MASTER tablet for destination shard for %v/%v (in cell: %v)", si.Keyspace(), si.ShardName(), scw.cell) } masters := scw.tsc.GetHealthyTabletStats(si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER) if len(masters) == 0 { @@ -1126,7 +1128,7 @@ func (scw *SplitCloneWorker) getSourceSchema(ctx context.Context, tablet *topoda sourceSchemaDefinition, err := scw.wr.GetSchema(shortCtx, tablet.Alias, scw.tables, scw.excludeTables, false /* includeViews */) cancel() if err != nil { - return nil, fmt.Errorf("cannot get schema from source %v: %v", topoproto.TabletAliasString(tablet.Alias), err) + return nil, vterrors.Wrapf(err, "cannot get schema from source %v", topoproto.TabletAliasString(tablet.Alias)) } if len(sourceSchemaDefinition.TableDefinitions) == 0 { return nil, fmt.Errorf("no tables matching the table filter in tablet %v", topoproto.TabletAliasString(tablet.Alias)) @@ -1189,7 +1191,7 @@ func (scw *SplitCloneWorker) createThrottlers() error { keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName()) t, err := throttler.NewThrottler(keyspaceAndShard, "transactions", scw.destinationWriterCount, scw.maxTPS, scw.maxReplicationLag) if err != nil { - return fmt.Errorf("cannot instantiate throttler: %v", err) + return vterrors.Wrap(err, "cannot instantiate throttler") } scw.throttlers[keyspaceAndShard] = t } diff --git a/go/vt/worker/split_clone_cmd.go b/go/vt/worker/split_clone_cmd.go index 281ad912dc6..9285ae2f4cb 100644 --- a/go/vt/worker/split_clone_cmd.go +++ b/go/vt/worker/split_clone_cmd.go @@ -25,6 +25,8 @@ import ( "strings" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/topo/topoproto" @@ -84,7 +86,7 @@ const splitCloneHTML2 = `

- +
@@ -108,7 +110,7 @@ func commandSplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagS destinationWriterCount := subFlags.Int("destination_writer_count", defaultDestinationWriterCount, "number of concurrent RPCs to execute on the destination") minHealthyRdonlyTablets := subFlags.Int("min_healthy_rdonly_tablets", defaultMinHealthyRdonlyTablets, "minimum number of healthy RDONLY tablets in the source and destination shard at start") maxTPS := subFlags.Int64("max_tps", defaultMaxTPS, "rate limit of maximum number of (write) transactions/second on the destination (unlimited by default)") - maxReplicationLag := subFlags.Int64("max_replication_lag", defaultMaxReplicationLag, "if set, the adapative throttler will be enabled and automatically adjust the write rate to keep the lag below the set value (disabled by default)") + maxReplicationLag := subFlags.Int64("max_replication_lag", defaultMaxReplicationLag, "if set, the adapative throttler will be enabled and automatically adjust the write rate to keep the lag below the set value in seconds (disabled by default)") if err := subFlags.Parse(args); err != nil { return nil, err } @@ -127,7 +129,7 @@ func commandSplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagS } worker, err := newSplitCloneWorker(wr, wi.cell, keyspace, shard, *online, *offline, excludeTableArray, *chunkCount, *minRowsPerChunk, *sourceReaderCount, *writeQueryMaxRows, *writeQueryMaxSize, *destinationWriterCount, *minHealthyRdonlyTablets, *maxTPS, *maxReplicationLag) if err != nil { - return nil, fmt.Errorf("cannot create split clone worker: %v", err) + return nil, vterrors.Wrap(err, "cannot create split clone worker") } return worker, nil } @@ -137,7 +139,7 @@ func keyspacesWithOverlappingShards(ctx context.Context, wr *wrangler.Wrangler) keyspaces, err := wr.TopoServer().GetKeyspaces(shortCtx) cancel() if err != nil { - return nil, fmt.Errorf("failed to get list of keyspaces: %v", err) + return nil, vterrors.Wrap(err, "failed to get list of keyspaces") } wg := sync.WaitGroup{} @@ -178,7 +180,7 @@ func keyspacesWithOverlappingShards(ctx context.Context, wr *wrangler.Wrangler) func interactiveSplitClone(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } keyspace := r.FormValue("keyspace") @@ -229,52 +231,52 @@ func interactiveSplitClone(ctx context.Context, wi *Instance, wr *wrangler.Wrang chunkCountStr := r.FormValue("chunkCount") chunkCount, err := strconv.ParseInt(chunkCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse chunkCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse chunkCount") } minRowsPerChunkStr := r.FormValue("minRowsPerChunk") minRowsPerChunk, err := strconv.ParseInt(minRowsPerChunkStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minRowsPerChunk: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minRowsPerChunk") } sourceReaderCount, err := strconv.ParseInt(sourceReaderCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse sourceReaderCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse sourceReaderCount") } writeQueryMaxRowsStr := r.FormValue("writeQueryMaxRows") writeQueryMaxRows, err := strconv.ParseInt(writeQueryMaxRowsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse writeQueryMaxRows: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse writeQueryMaxRows") } writeQueryMaxSizeStr := r.FormValue("writeQueryMaxSize") writeQueryMaxSize, err := strconv.ParseInt(writeQueryMaxSizeStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse writeQueryMaxSize: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse writeQueryMaxSize") } destinationWriterCountStr := r.FormValue("destinationWriterCount") destinationWriterCount, err := strconv.ParseInt(destinationWriterCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse destinationWriterCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse destinationWriterCount") } minHealthyRdonlyTabletsStr := r.FormValue("minHealthyRdonlyTablets") minHealthyRdonlyTablets, err := strconv.ParseInt(minHealthyRdonlyTabletsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minHealthyRdonlyTablets: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minHealthyRdonlyTablets") } maxTPSStr := r.FormValue("maxTPS") maxTPS, err := strconv.ParseInt(maxTPSStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse maxTPS: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse maxTPS") } maxReplicationLagStr := r.FormValue("maxReplicationLag") maxReplicationLag, err := strconv.ParseInt(maxReplicationLagStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse maxReplicationLag: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse maxReplicationLag") } // start the clone job wrk, err := newSplitCloneWorker(wr, wi.cell, keyspace, shard, online, offline, excludeTableArray, int(chunkCount), int(minRowsPerChunk), int(sourceReaderCount), int(writeQueryMaxRows), int(writeQueryMaxSize), int(destinationWriterCount), int(minHealthyRdonlyTablets), maxTPS, maxReplicationLag) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot create worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot create worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/split_diff.go b/go/vt/worker/split_diff.go index 08eafafbbfd..a4f07cdf60b 100644 --- a/go/vt/worker/split_diff.go +++ b/go/vt/worker/split_diff.go @@ -22,6 +22,8 @@ import ( "sort" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" @@ -142,7 +144,7 @@ func (sdw *SplitDiffWorker) Run(ctx context.Context) error { func (sdw *SplitDiffWorker) run(ctx context.Context) error { // first state: read what we need to do if err := sdw.init(ctx); err != nil { - return fmt.Errorf("init() failed: %v", err) + return vterrors.Wrap(err, "init() failed") } if err := checkDone(ctx); err != nil { return err @@ -150,7 +152,7 @@ func (sdw *SplitDiffWorker) run(ctx context.Context) error { // second state: find targets if err := sdw.findTargets(ctx); err != nil { - return fmt.Errorf("findTargets() failed: %v", err) + return vterrors.Wrap(err, "findTargets() failed") } if err := checkDone(ctx); err != nil { return err @@ -158,7 +160,7 @@ func (sdw *SplitDiffWorker) run(ctx context.Context) error { // third phase: synchronize replication if err := sdw.synchronizeReplication(ctx); err != nil { - return fmt.Errorf("synchronizeReplication() failed: %v", err) + return vterrors.Wrap(err, "synchronizeReplication() failed") } if err := checkDone(ctx); err != nil { return err @@ -166,7 +168,7 @@ func (sdw *SplitDiffWorker) run(ctx context.Context) error { // fourth phase: diff if err := sdw.diff(ctx); err != nil { - return fmt.Errorf("diff() failed: %v", err) + return vterrors.Wrap(err, "diff() failed") } if err := checkDone(ctx); err != nil { return err @@ -185,13 +187,13 @@ func (sdw *SplitDiffWorker) init(ctx context.Context) error { sdw.keyspaceInfo, err = sdw.wr.TopoServer().GetKeyspace(shortCtx, sdw.keyspace) cancel() if err != nil { - return fmt.Errorf("cannot read keyspace %v: %v", sdw.keyspace, err) + return vterrors.Wrapf(err, "cannot read keyspace %v", sdw.keyspace) } shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout) sdw.shardInfo, err = sdw.wr.TopoServer().GetShard(shortCtx, sdw.keyspace, sdw.shard) cancel() if err != nil { - return fmt.Errorf("cannot read shard %v/%v: %v", sdw.keyspace, sdw.shard, err) + return vterrors.Wrapf(err, "cannot read shard %v/%v", sdw.keyspace, sdw.shard) } if len(sdw.shardInfo.SourceShards) == 0 { @@ -243,7 +245,7 @@ func (sdw *SplitDiffWorker) findTargets(ctx context.Context) error { sdw.destinationTabletType, ) if err != nil { - return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", sdw.cell, sdw.keyspace, sdw.shard, err) + return vterrors.Wrapf(err, "FindWorkerTablet() failed for %v/%v/%v", sdw.cell, sdw.keyspace, sdw.shard) } // find an appropriate tablet in the source shard @@ -295,7 +297,7 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { defer cancel() masterInfo, err := sdw.wr.TopoServer().GetTablet(shortCtx, sdw.shardInfo.MasterAlias) if err != nil { - return fmt.Errorf("synchronizeReplication: cannot get Tablet record for master %v: %v", sdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "synchronizeReplication: cannot get Tablet record for master %v", sdw.shardInfo.MasterAlias) } // 1 - stop the master binlog replication, get its current position @@ -304,12 +306,12 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { defer cancel() _, err = sdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.StopVReplication(sdw.sourceShard.Uid, "for split diff")) if err != nil { - return fmt.Errorf("VReplicationExec(stop) for %v failed: %v", sdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "VReplicationExec(stop) for %v failed", sdw.shardInfo.MasterAlias) } wrangler.RecordVReplicationAction(sdw.cleaner, masterInfo.Tablet, binlogplayer.StartVReplication(sdw.sourceShard.Uid)) p3qr, err := sdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.ReadVReplicationPos(sdw.sourceShard.Uid)) if err != nil { - return fmt.Errorf("VReplicationExec(stop) for %v failed: %v", sdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "VReplicationExec(stop) for %v failed", sdw.shardInfo.MasterAlias) } qr := sqltypes.Proto3ToResult(p3qr) if len(qr.Rows) != 1 || len(qr.Rows[0]) != 1 { @@ -329,7 +331,7 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { defer cancel() mysqlPos, err := sdw.wr.TabletManagerClient().StopSlaveMinimum(shortCtx, sourceTablet.Tablet, vreplicationPos, *remoteActionsTimeout) if err != nil { - return fmt.Errorf("cannot stop slave %v at right binlog position %v: %v", sdw.sourceAlias, vreplicationPos, err) + return vterrors.Wrapf(err, "cannot stop slave %v at right binlog position %v", sdw.sourceAlias, vreplicationPos) } // change the cleaner actions from ChangeSlaveType(rdonly) @@ -343,14 +345,14 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { defer cancel() _, err = sdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.StartVReplicationUntil(sdw.sourceShard.Uid, mysqlPos)) if err != nil { - return fmt.Errorf("VReplication(start until) for %v until %v failed: %v", sdw.shardInfo.MasterAlias, mysqlPos, err) + return vterrors.Wrapf(err, "VReplication(start until) for %v until %v failed", sdw.shardInfo.MasterAlias, mysqlPos) } if err := sdw.wr.TabletManagerClient().VReplicationWaitForPos(shortCtx, masterInfo.Tablet, int(sdw.sourceShard.Uid), mysqlPos); err != nil { - return fmt.Errorf("VReplicationWaitForPos for %v until %v failed: %v", sdw.shardInfo.MasterAlias, mysqlPos, err) + return vterrors.Wrapf(err, "VReplicationWaitForPos for %v until %v failed", sdw.shardInfo.MasterAlias, mysqlPos) } masterPos, err := sdw.wr.TabletManagerClient().MasterPosition(shortCtx, masterInfo.Tablet) if err != nil { - return fmt.Errorf("MasterPosition for %v failed: %v", sdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "MasterPosition for %v failed", sdw.shardInfo.MasterAlias) } // 4 - wait until the destination tablet is equal or passed @@ -365,7 +367,7 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout) defer cancel() if _, err = sdw.wr.TabletManagerClient().StopSlaveMinimum(shortCtx, destinationTablet.Tablet, masterPos, *remoteActionsTimeout); err != nil { - return fmt.Errorf("StopSlaveMinimum for %v at %v failed: %v", sdw.destinationAlias, masterPos, err) + return vterrors.Wrapf(err, "StopSlaveMinimum for %v at %v failed", sdw.destinationAlias, masterPos) } wrangler.RecordStartSlaveAction(sdw.cleaner, destinationTablet.Tablet) @@ -374,7 +376,7 @@ func (sdw *SplitDiffWorker) synchronizeReplication(ctx context.Context) error { shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout) defer cancel() if _, err = sdw.wr.TabletManagerClient().VReplicationExec(ctx, masterInfo.Tablet, binlogplayer.StartVReplication(sdw.sourceShard.Uid)); err != nil { - return fmt.Errorf("VReplicationExec(start) failed for %v: %v", sdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "VReplicationExec(start) failed for %v", sdw.shardInfo.MasterAlias) } return nil @@ -433,7 +435,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { if *useV3ReshardingMode { kschema, err := sdw.wr.TopoServer().GetVSchema(ctx, sdw.keyspace) if err != nil { - return fmt.Errorf("cannot load VSchema for keyspace %v: %v", sdw.keyspace, err) + return vterrors.Wrapf(err, "cannot load VSchema for keyspace %v", sdw.keyspace) } if kschema == nil { return fmt.Errorf("no VSchema for keyspace %v", sdw.keyspace) @@ -441,7 +443,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { keyspaceSchema, err = vindexes.BuildKeyspaceSchema(kschema, sdw.keyspace) if err != nil { - return fmt.Errorf("cannot build vschema for keyspace %v: %v", sdw.keyspace, err) + return vterrors.Wrapf(err, "cannot build vschema for keyspace %v", sdw.keyspace) } } @@ -451,7 +453,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { // we'll filter. overlap, err := key.KeyRangesOverlap(sdw.shardInfo.KeyRange, sdw.sourceShard.KeyRange) if err != nil { - return fmt.Errorf("Source shard doesn't overlap with destination: %v", err) + return vterrors.Wrap(err, "Source shard doesn't overlap with destination") } // run the diffs, 8 at a time @@ -492,7 +494,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { sourceQueryResultReader, err = TableScanByKeyRange(ctx, sdw.wr.Logger(), sdw.wr.TopoServer(), sdw.sourceAlias, tableDefinition, overlap, keyspaceSchema, sdw.keyspaceInfo.ShardingColumnName, sdw.keyspaceInfo.ShardingColumnType) } if err != nil { - newErr := fmt.Errorf("TableScan(ByKeyRange?)(source) failed: %v", err) + newErr := vterrors.Wrap(err, "TableScan(ByKeyRange?)(source) failed") rec.RecordError(newErr) sdw.wr.Logger().Errorf("%v", newErr) return @@ -508,7 +510,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { destinationQueryResultReader, err = TableScanByKeyRange(ctx, sdw.wr.Logger(), sdw.wr.TopoServer(), sdw.destinationAlias, tableDefinition, overlap, keyspaceSchema, sdw.keyspaceInfo.ShardingColumnName, sdw.keyspaceInfo.ShardingColumnType) } if err != nil { - newErr := fmt.Errorf("TableScan(ByKeyRange?)(destination) failed: %v", err) + newErr := vterrors.Wrap(err, "TableScan(ByKeyRange?)(destination) failed") rec.RecordError(newErr) sdw.wr.Logger().Errorf("%v", newErr) return @@ -518,7 +520,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { // Create the row differ. differ, err := NewRowDiffer(sourceQueryResultReader, destinationQueryResultReader, tableDefinition) if err != nil { - newErr := fmt.Errorf("NewRowDiffer() failed: %v", err) + newErr := vterrors.Wrap(err, "NewRowDiffer() failed") rec.RecordError(newErr) sdw.wr.Logger().Errorf("%v", newErr) return diff --git a/go/vt/worker/split_diff_cmd.go b/go/vt/worker/split_diff_cmd.go index 4520cf6a11e..39178646f8f 100644 --- a/go/vt/worker/split_diff_cmd.go +++ b/go/vt/worker/split_diff_cmd.go @@ -25,6 +25,8 @@ import ( "strings" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/topo/topoproto" @@ -115,7 +117,7 @@ func shardsWithSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[string keyspaces, err := wr.TopoServer().GetKeyspaces(shortCtx) cancel() if err != nil { - return nil, fmt.Errorf("failed to get list of keyspaces: %v", err) + return nil, vterrors.Wrap(err, "failed to get list of keyspaces") } wg := sync.WaitGroup{} @@ -130,7 +132,7 @@ func shardsWithSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[string shards, err := wr.TopoServer().GetShardNames(shortCtx, keyspace) cancel() if err != nil { - rec.RecordError(fmt.Errorf("failed to get list of shards for keyspace '%v': %v", keyspace, err)) + rec.RecordError(vterrors.Wrapf(err, "failed to get list of shards for keyspace '%v'", keyspace)) return } for _, shard := range shards { @@ -141,7 +143,7 @@ func shardsWithSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[string si, err := wr.TopoServer().GetShard(shortCtx, keyspace, shard) cancel() if err != nil { - rec.RecordError(fmt.Errorf("failed to get details for shard '%v': %v", topoproto.KeyspaceShardString(keyspace, shard), err)) + rec.RecordError(vterrors.Wrapf(err, "failed to get details for shard '%v'", topoproto.KeyspaceShardString(keyspace, shard))) return } @@ -170,7 +172,7 @@ func shardsWithSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[string func interactiveSplitDiff(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } keyspace := r.FormValue("keyspace") shard := r.FormValue("shard") @@ -203,7 +205,7 @@ func interactiveSplitDiff(ctx context.Context, wi *Instance, wr *wrangler.Wrangl sourceUIDStr := r.FormValue("sourceUID") sourceUID, err := strconv.ParseInt(sourceUIDStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse sourceUID: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse sourceUID") } excludeTables := r.FormValue("excludeTables") var excludeTableArray []string @@ -215,7 +217,7 @@ func interactiveSplitDiff(ctx context.Context, wi *Instance, wr *wrangler.Wrangl minHealthyRdonlyTablets, err := strconv.ParseInt(minHealthyRdonlyTabletsStr, 0, 64) parallelDiffsCount, err := strconv.ParseInt(parallelDiffsCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minHealthyRdonlyTablets: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minHealthyRdonlyTablets") } // start the diff job diff --git a/go/vt/worker/tablet_provider.go b/go/vt/worker/tablet_provider.go index e22da22c1a8..f03602af4c6 100644 --- a/go/vt/worker/tablet_provider.go +++ b/go/vt/worker/tablet_provider.go @@ -19,6 +19,8 @@ package worker import ( "fmt" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/discovery" @@ -59,7 +61,7 @@ func (p *singleTabletProvider) getTablet() (*topodatapb.Tablet, error) { tablet, err := p.ts.GetTablet(shortCtx, p.alias) cancel() if err != nil { - return nil, fmt.Errorf("failed to resolve tablet alias: %v err: %v", topoproto.TabletAliasString(p.alias), err) + return nil, vterrors.Wrapf(err, "failed to resolve tablet alias: %v err", topoproto.TabletAliasString(p.alias)) } return tablet.Tablet, err } diff --git a/go/vt/worker/topo_utils.go b/go/vt/worker/topo_utils.go index 6c078352b88..4a57f007e9e 100644 --- a/go/vt/worker/topo_utils.go +++ b/go/vt/worker/topo_utils.go @@ -22,6 +22,8 @@ import ( "math/rand" "time" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/log" @@ -76,7 +78,7 @@ func waitForHealthyTablets(ctx context.Context, wr *wrangler.Wrangler, tsc *disc // Wait for at least one RDONLY tablet initially before checking the list. if err := tsc.WaitForTablets(busywaitCtx, cell, keyspace, shard, tabletType); err != nil { - return nil, fmt.Errorf("error waiting for %v tablets for (%v,%v/%v): %v", tabletType, cell, keyspace, shard, err) + return nil, vterrors.Wrapf(err, "error waiting for %v tablets for (%v,%v/%v)", tabletType, cell, keyspace, shard) } var healthyTablets []discovery.TabletStats diff --git a/go/vt/worker/utils_test.go b/go/vt/worker/utils_test.go index ad9dc1c44e8..98bdd416e7f 100644 --- a/go/vt/worker/utils_test.go +++ b/go/vt/worker/utils_test.go @@ -25,6 +25,7 @@ import ( "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/faketmclient" "vitess.io/vitess/go/vt/vttablet/tmclient" "vitess.io/vitess/go/vt/wrangler" @@ -43,15 +44,15 @@ func runCommand(t *testing.T, wi *Instance, wr *wrangler.Wrangler, args []string worker, done, err := wi.RunCommand(ctx, args, wr, false /* runFromCli */) if err != nil { - return fmt.Errorf("Worker creation failed: %v", err) + return vterrors.Wrap(err, "Worker creation failed") } if err := wi.WaitForCommand(worker, done); err != nil { - return fmt.Errorf("Worker failed: %v", err) + return vterrors.Wrap(err, "Worker failed") } t.Logf("Got status: %v", worker.StatusAsText()) if worker.State() != WorkerStateDone { - return fmt.Errorf("Worker finished but not successfully: %v", err) + return vterrors.Wrap(err, "Worker finished but not successfully") } return nil } diff --git a/go/vt/worker/vertical_split_clone_cmd.go b/go/vt/worker/vertical_split_clone_cmd.go index ba04fec7d9f..c2d5a0b074c 100644 --- a/go/vt/worker/vertical_split_clone_cmd.go +++ b/go/vt/worker/vertical_split_clone_cmd.go @@ -25,6 +25,8 @@ import ( "strings" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/topo/topoproto" @@ -83,7 +85,7 @@ const verticalSplitCloneHTML2 = `

- +
@@ -106,7 +108,7 @@ func commandVerticalSplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *fl destinationWriterCount := subFlags.Int("destination_writer_count", defaultDestinationWriterCount, "number of concurrent RPCs to execute on the destination") minHealthyRdonlyTablets := subFlags.Int("min_healthy_rdonly_tablets", defaultMinHealthyRdonlyTablets, "minimum number of healthy RDONLY tablets before taking out one") maxTPS := subFlags.Int64("max_tps", defaultMaxTPS, "if non-zero, limit copy to maximum number of (write) transactions/second on the destination (unlimited by default)") - maxReplicationLag := subFlags.Int64("max_replication_lag", defaultMaxReplicationLag, "if set, the adapative throttler will be enabled and automatically adjust the write rate to keep the lag below the set value (disabled by default)") + maxReplicationLag := subFlags.Int64("max_replication_lag", defaultMaxReplicationLag, "if set, the adapative throttler will be enabled and automatically adjust the write rate to keep the lag below the set value in seconds (disabled by default)") if err := subFlags.Parse(args); err != nil { return nil, err } @@ -127,7 +129,7 @@ func commandVerticalSplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *fl } worker, err := newVerticalSplitCloneWorker(wr, wi.cell, keyspace, shard, *online, *offline, tableArray, *chunkCount, *minRowsPerChunk, *sourceReaderCount, *writeQueryMaxRows, *writeQueryMaxSize, *destinationWriterCount, *minHealthyRdonlyTablets, *maxTPS, *maxReplicationLag) if err != nil { - return nil, fmt.Errorf("cannot create worker: %v", err) + return nil, vterrors.Wrap(err, "cannot create worker") } return worker, nil } @@ -139,7 +141,7 @@ func keyspacesWithServedFrom(ctx context.Context, wr *wrangler.Wrangler) ([]stri keyspaces, err := wr.TopoServer().GetKeyspaces(shortCtx) cancel() if err != nil { - return nil, fmt.Errorf("failed to get list of keyspaces: %v", err) + return nil, vterrors.Wrap(err, "failed to get list of keyspaces") } wg := sync.WaitGroup{} @@ -154,7 +156,7 @@ func keyspacesWithServedFrom(ctx context.Context, wr *wrangler.Wrangler) ([]stri ki, err := wr.TopoServer().GetKeyspace(shortCtx, keyspace) cancel() if err != nil { - rec.RecordError(fmt.Errorf("failed to get details for keyspace '%v': %v", keyspace, err)) + rec.RecordError(vterrors.Wrapf(err, "failed to get details for keyspace '%v'", keyspace)) return } if len(ki.ServedFroms) > 0 { @@ -177,7 +179,7 @@ func keyspacesWithServedFrom(ctx context.Context, wr *wrangler.Wrangler) ([]stri func interactiveVerticalSplitClone(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } keyspace := r.FormValue("keyspace") @@ -221,47 +223,47 @@ func interactiveVerticalSplitClone(ctx context.Context, wi *Instance, wr *wrangl chunkCountStr := r.FormValue("chunkCount") chunkCount, err := strconv.ParseInt(chunkCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse chunkCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse chunkCount") } minRowsPerChunkStr := r.FormValue("minRowsPerChunk") minRowsPerChunk, err := strconv.ParseInt(minRowsPerChunkStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minRowsPerChunk: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minRowsPerChunk") } sourceReaderCountStr := r.FormValue("sourceReaderCount") sourceReaderCount, err := strconv.ParseInt(sourceReaderCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse sourceReaderCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse sourceReaderCount") } writeQueryMaxRowsStr := r.FormValue("writeQueryMaxRows") writeQueryMaxRows, err := strconv.ParseInt(writeQueryMaxRowsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse writeQueryMaxRows: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse writeQueryMaxRows") } writeQueryMaxSizeStr := r.FormValue("writeQueryMaxSize") writeQueryMaxSize, err := strconv.ParseInt(writeQueryMaxSizeStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse writeQueryMaxSize: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse writeQueryMaxSize") } destinationWriterCountStr := r.FormValue("destinationWriterCount") destinationWriterCount, err := strconv.ParseInt(destinationWriterCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse destinationWriterCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse destinationWriterCount") } minHealthyRdonlyTabletsStr := r.FormValue("minHealthyRdonlyTablets") minHealthyRdonlyTablets, err := strconv.ParseInt(minHealthyRdonlyTabletsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minHealthyRdonlyTablets: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minHealthyRdonlyTablets") } maxTPSStr := r.FormValue("maxTPS") maxTPS, err := strconv.ParseInt(maxTPSStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse maxTPS: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse maxTPS") } maxReplicationLagStr := r.FormValue("maxReplicationLag") maxReplicationLag, err := strconv.ParseInt(maxReplicationLagStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse maxReplicationLag: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse maxReplicationLag") } // Figure out the shard @@ -269,7 +271,7 @@ func interactiveVerticalSplitClone(ctx context.Context, wi *Instance, wr *wrangl shardMap, err := wr.TopoServer().FindAllShardsInKeyspace(shortCtx, keyspace) cancel() if err != nil { - return nil, nil, nil, fmt.Errorf("cannot find shard name for keyspace %s: %s", keyspace, err) + return nil, nil, nil, vterrors.Wrapf(err, "cannot find shard name for keyspace %s", keyspace) } if len(shardMap) != 1 { return nil, nil, nil, fmt.Errorf("found the wrong number of shards, there should be only one, %v", shardMap) @@ -282,7 +284,7 @@ func interactiveVerticalSplitClone(ctx context.Context, wi *Instance, wr *wrangl // start the clone job wrk, err := newVerticalSplitCloneWorker(wr, wi.cell, keyspace, shard, online, offline, tableArray, int(chunkCount), int(minRowsPerChunk), int(sourceReaderCount), int(writeQueryMaxRows), int(writeQueryMaxSize), int(destinationWriterCount), int(minHealthyRdonlyTablets), maxTPS, maxReplicationLag) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot create worker: %v", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot create worker") } return wrk, nil, nil, nil } diff --git a/go/vt/worker/vertical_split_diff.go b/go/vt/worker/vertical_split_diff.go index f6766e17b90..c79321312ab 100644 --- a/go/vt/worker/vertical_split_diff.go +++ b/go/vt/worker/vertical_split_diff.go @@ -21,6 +21,8 @@ import ( "html/template" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" @@ -134,7 +136,7 @@ func (vsdw *VerticalSplitDiffWorker) Run(ctx context.Context) error { func (vsdw *VerticalSplitDiffWorker) run(ctx context.Context) error { // first state: read what we need to do if err := vsdw.init(ctx); err != nil { - return fmt.Errorf("init() failed: %v", err) + return vterrors.Wrap(err, "init() failed") } if err := checkDone(ctx); err != nil { return err @@ -142,7 +144,7 @@ func (vsdw *VerticalSplitDiffWorker) run(ctx context.Context) error { // second state: find targets if err := vsdw.findTargets(ctx); err != nil { - return fmt.Errorf("findTargets() failed: %v", err) + return vterrors.Wrap(err, "findTargets() failed") } if err := checkDone(ctx); err != nil { return err @@ -150,7 +152,7 @@ func (vsdw *VerticalSplitDiffWorker) run(ctx context.Context) error { // third phase: synchronize replication if err := vsdw.synchronizeReplication(ctx); err != nil { - return fmt.Errorf("synchronizeReplication() failed: %v", err) + return vterrors.Wrap(err, "synchronizeReplication() failed") } if err := checkDone(ctx); err != nil { return err @@ -158,7 +160,7 @@ func (vsdw *VerticalSplitDiffWorker) run(ctx context.Context) error { // fourth phase: diff if err := vsdw.diff(ctx); err != nil { - return fmt.Errorf("diff() failed: %v", err) + return vterrors.Wrap(err, "diff() failed") } if err := checkDone(ctx); err != nil { return err @@ -177,7 +179,7 @@ func (vsdw *VerticalSplitDiffWorker) init(ctx context.Context) error { // read the keyspace and validate it vsdw.keyspaceInfo, err = vsdw.wr.TopoServer().GetKeyspace(ctx, vsdw.keyspace) if err != nil { - return fmt.Errorf("cannot read keyspace %v: %v", vsdw.keyspace, err) + return vterrors.Wrapf(err, "cannot read keyspace %v", vsdw.keyspace) } if len(vsdw.keyspaceInfo.ServedFroms) == 0 { return fmt.Errorf("keyspace %v has no KeyspaceServedFrom", vsdw.keyspace) @@ -186,7 +188,7 @@ func (vsdw *VerticalSplitDiffWorker) init(ctx context.Context) error { // read the shardinfo and validate it vsdw.shardInfo, err = vsdw.wr.TopoServer().GetShard(ctx, vsdw.keyspace, vsdw.shard) if err != nil { - return fmt.Errorf("cannot read shard %v/%v: %v", vsdw.keyspace, vsdw.shard, err) + return vterrors.Wrapf(err, "cannot read shard %v/%v", vsdw.keyspace, vsdw.shard) } if len(vsdw.shardInfo.SourceShards) != 1 { return fmt.Errorf("shard %v/%v has bad number of source shards", vsdw.keyspace, vsdw.shard) @@ -222,13 +224,13 @@ func (vsdw *VerticalSplitDiffWorker) findTargets(ctx context.Context) error { vsdw.destinationTabletType, ) if err != nil { - return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", vsdw.cell, vsdw.keyspace, vsdw.shard, err) + return vterrors.Wrapf(err, "FindWorkerTablet() failed for %v/%v/%v", vsdw.cell, vsdw.keyspace, vsdw.shard) } // find an appropriate tablet in the source shard vsdw.sourceAlias, err = FindWorkerTablet(ctx, vsdw.wr, vsdw.cleaner, nil /* tsc */, vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard, vsdw.minHealthyRdonlyTablets, topodatapb.TabletType_RDONLY) if err != nil { - return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard, err) + return vterrors.Wrapf(err, "FindWorkerTablet() failed for %v/%v/%v", vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard) } return nil @@ -259,7 +261,7 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) defer cancel() masterInfo, err := vsdw.wr.TopoServer().GetTablet(shortCtx, vsdw.shardInfo.MasterAlias) if err != nil { - return fmt.Errorf("synchronizeReplication: cannot get Tablet record for master %v: %v", topoproto.TabletAliasString(vsdw.shardInfo.MasterAlias), err) + return vterrors.Wrapf(err, "synchronizeReplication: cannot get Tablet record for master %v", topoproto.TabletAliasString(vsdw.shardInfo.MasterAlias)) } ss := vsdw.shardInfo.SourceShards[0] @@ -270,12 +272,12 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) defer cancel() _, err = vsdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.StopVReplication(ss.Uid, "for split diff")) if err != nil { - return fmt.Errorf("Stop VReplication on master %v failed: %v", topoproto.TabletAliasString(vsdw.shardInfo.MasterAlias), err) + return vterrors.Wrapf(err, "Stop VReplication on master %v failed", topoproto.TabletAliasString(vsdw.shardInfo.MasterAlias)) } wrangler.RecordVReplicationAction(vsdw.cleaner, masterInfo.Tablet, binlogplayer.StartVReplication(ss.Uid)) p3qr, err := vsdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.ReadVReplicationPos(ss.Uid)) if err != nil { - return fmt.Errorf("VReplicationExec(stop) for %v failed: %v", vsdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "VReplicationExec(stop) for %v failed", vsdw.shardInfo.MasterAlias) } qr := sqltypes.Proto3ToResult(p3qr) if len(qr.Rows) != 1 || len(qr.Rows[0]) != 1 { @@ -293,7 +295,7 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) } mysqlPos, err := vsdw.wr.TabletManagerClient().StopSlaveMinimum(shortCtx, sourceTablet.Tablet, vreplicationPos, *remoteActionsTimeout) if err != nil { - return fmt.Errorf("cannot stop slave %v at right binlog position %v: %v", topoproto.TabletAliasString(vsdw.sourceAlias), vreplicationPos, err) + return vterrors.Wrapf(err, "cannot stop slave %v at right binlog position %v", topoproto.TabletAliasString(vsdw.sourceAlias), vreplicationPos) } // change the cleaner actions from ChangeSlaveType(rdonly) @@ -307,14 +309,14 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) defer cancel() _, err = vsdw.wr.TabletManagerClient().VReplicationExec(shortCtx, masterInfo.Tablet, binlogplayer.StartVReplicationUntil(ss.Uid, mysqlPos)) if err != nil { - return fmt.Errorf("VReplication(start until) for %v until %v failed: %v", vsdw.shardInfo.MasterAlias, mysqlPos, err) + return vterrors.Wrapf(err, "VReplication(start until) for %v until %v failed", vsdw.shardInfo.MasterAlias, mysqlPos) } if err := vsdw.wr.TabletManagerClient().VReplicationWaitForPos(shortCtx, masterInfo.Tablet, int(ss.Uid), mysqlPos); err != nil { - return fmt.Errorf("VReplicationWaitForPos for %v until %v failed: %v", vsdw.shardInfo.MasterAlias, mysqlPos, err) + return vterrors.Wrapf(err, "VReplicationWaitForPos for %v until %v failed", vsdw.shardInfo.MasterAlias, mysqlPos) } masterPos, err := vsdw.wr.TabletManagerClient().MasterPosition(shortCtx, masterInfo.Tablet) if err != nil { - return fmt.Errorf("MasterPosition for %v failed: %v", vsdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "MasterPosition for %v failed", vsdw.shardInfo.MasterAlias) } // 4 - wait until the destination tablet is equal or passed @@ -330,7 +332,7 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) defer cancel() _, err = vsdw.wr.TabletManagerClient().StopSlaveMinimum(shortCtx, destinationTablet.Tablet, masterPos, *remoteActionsTimeout) if err != nil { - return fmt.Errorf("StopSlaveMinimum on %v at %v failed: %v", topoproto.TabletAliasString(vsdw.destinationAlias), masterPos, err) + return vterrors.Wrapf(err, "StopSlaveMinimum on %v at %v failed", topoproto.TabletAliasString(vsdw.destinationAlias), masterPos) } wrangler.RecordStartSlaveAction(vsdw.cleaner, destinationTablet.Tablet) @@ -339,7 +341,7 @@ func (vsdw *VerticalSplitDiffWorker) synchronizeReplication(ctx context.Context) shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout) defer cancel() if _, err = vsdw.wr.TabletManagerClient().VReplicationExec(ctx, masterInfo.Tablet, binlogplayer.StartVReplication(ss.Uid)); err != nil { - return fmt.Errorf("VReplicationExec(start) failed for %v: %v", vsdw.shardInfo.MasterAlias, err) + return vterrors.Wrapf(err, "VReplicationExec(start) failed for %v", vsdw.shardInfo.MasterAlias) } return nil @@ -406,7 +408,7 @@ func (vsdw *VerticalSplitDiffWorker) diff(ctx context.Context) error { vsdw.wr.Logger().Infof("Starting the diff on table %v", tableDefinition.Name) sourceQueryResultReader, err := TableScan(ctx, vsdw.wr.Logger(), vsdw.wr.TopoServer(), vsdw.sourceAlias, tableDefinition) if err != nil { - newErr := fmt.Errorf("TableScan(source) failed: %v", err) + newErr := vterrors.Wrap(err, "TableScan(source) failed") rec.RecordError(newErr) vsdw.wr.Logger().Errorf("%v", newErr) return @@ -415,7 +417,7 @@ func (vsdw *VerticalSplitDiffWorker) diff(ctx context.Context) error { destinationQueryResultReader, err := TableScan(ctx, vsdw.wr.Logger(), vsdw.wr.TopoServer(), vsdw.destinationAlias, tableDefinition) if err != nil { - newErr := fmt.Errorf("TableScan(destination) failed: %v", err) + newErr := vterrors.Wrap(err, "TableScan(destination) failed") rec.RecordError(newErr) vsdw.wr.Logger().Errorf("%v", newErr) return @@ -424,7 +426,7 @@ func (vsdw *VerticalSplitDiffWorker) diff(ctx context.Context) error { differ, err := NewRowDiffer(sourceQueryResultReader, destinationQueryResultReader, tableDefinition) if err != nil { - newErr := fmt.Errorf("NewRowDiffer() failed: %v", err) + newErr := vterrors.Wrap(err, "NewRowDiffer() failed") rec.RecordError(newErr) vsdw.wr.Logger().Errorf("%v", newErr) return diff --git a/go/vt/worker/vertical_split_diff_cmd.go b/go/vt/worker/vertical_split_diff_cmd.go index c3ae174deac..7eebf106f5a 100644 --- a/go/vt/worker/vertical_split_diff_cmd.go +++ b/go/vt/worker/vertical_split_diff_cmd.go @@ -24,6 +24,8 @@ import ( "strconv" "sync" + "vitess.io/vitess/go/vt/vterrors" + "golang.org/x/net/context" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/topo/topoproto" @@ -103,7 +105,7 @@ func shardsWithTablesSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[ keyspaces, err := wr.TopoServer().GetKeyspaces(shortCtx) cancel() if err != nil { - return nil, fmt.Errorf("failed to get list of keyspaces: %v", err) + return nil, vterrors.Wrap(err, "failed to get list of keyspaces") } wg := sync.WaitGroup{} @@ -118,7 +120,7 @@ func shardsWithTablesSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[ shards, err := wr.TopoServer().GetShardNames(shortCtx, keyspace) cancel() if err != nil { - rec.RecordError(fmt.Errorf("failed to get list of shards for keyspace '%v': %v", keyspace, err)) + rec.RecordError(vterrors.Wrapf(err, "failed to get list of shards for keyspace '%v'", keyspace)) return } for _, shard := range shards { @@ -129,7 +131,7 @@ func shardsWithTablesSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[ si, err := wr.TopoServer().GetShard(shortCtx, keyspace, shard) cancel() if err != nil { - rec.RecordError(fmt.Errorf("failed to get details for shard '%v': %v", topoproto.KeyspaceShardString(keyspace, shard), err)) + rec.RecordError(vterrors.Wrapf(err, "failed to get details for shard '%v'", topoproto.KeyspaceShardString(keyspace, shard))) return } @@ -158,7 +160,7 @@ func shardsWithTablesSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[ func interactiveVerticalSplitDiff(ctx context.Context, wi *Instance, wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) (Worker, *template.Template, map[string]interface{}, error) { if err := r.ParseForm(); err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse form: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse form") } keyspace := r.FormValue("keyspace") shard := r.FormValue("shard") @@ -190,12 +192,12 @@ func interactiveVerticalSplitDiff(ctx context.Context, wi *Instance, wr *wrangle minHealthyRdonlyTabletsStr := r.FormValue("minHealthyRdonlyTablets") minHealthyRdonlyTablets, err := strconv.ParseInt(minHealthyRdonlyTabletsStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse minHealthyRdonlyTablets: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse minHealthyRdonlyTablets") } parallelDiffsCountStr := r.FormValue("parallelDiffsCount") parallelDiffsCount, err := strconv.ParseInt(parallelDiffsCountStr, 0, 64) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot parse parallelDiffsCount: %s", err) + return nil, nil, nil, vterrors.Wrap(err, "cannot parse parallelDiffsCount") } // start the diff job diff --git a/go/vt/worker/vtworkerclienttest/client_testsuite.go b/go/vt/worker/vtworkerclienttest/client_testsuite.go index 1dd4e7be806..5cf4d56ca71 100644 --- a/go/vt/worker/vtworkerclienttest/client_testsuite.go +++ b/go/vt/worker/vtworkerclienttest/client_testsuite.go @@ -26,7 +26,6 @@ package vtworkerclienttest // (e.g. zookeeper) won't be drawn into production binaries as well. import ( - "fmt" "io" "strings" "sync" @@ -102,7 +101,7 @@ func commandSucceeds(t *testing.T, client vtworkerclient.Client) { func runVtworkerCommand(client vtworkerclient.Client, args []string) error { stream, err := client.ExecuteVtworkerCommand(context.Background(), args) if err != nil { - return fmt.Errorf("cannot execute remote command: %v", err) + return vterrors.Wrap(err, "cannot execute remote command") } for { @@ -142,7 +141,7 @@ func commandErrorsBecauseBusy(t *testing.T, client vtworkerclient.Client, server // We see CANCELED from the RPC client (client side cancelation) or // from vtworker itself (server side cancelation). if vterrors.Code(err) != vtrpcpb.Code_CANCELED { - errorCodeCheck = fmt.Errorf("Block command should only error due to canceled context: %v", err) + errorCodeCheck = vterrors.Wrap(err, "Block command should only error due to canceled context") } // Stream has finished. break @@ -227,11 +226,11 @@ func resetVtworker(t *testing.T, client vtworkerclient.Client) error { } if time.Since(start) > 5*time.Second { - return fmt.Errorf("Reset was not successful after 5s and %d attempts: %v", attempts, err) + return vterrors.Wrapf(err, "Reset was not successful after 5s and %d attempts", attempts) } if !strings.Contains(err.Error(), "worker still executing") { - return fmt.Errorf("Reset must not fail: %v", err) + return vterrors.Wrap(err, "Reset must not fail") } t.Logf("retrying to Reset vtworker because the previous command has not finished yet. got err: %v", err) diff --git a/go/vt/workflow/resharding/mock_resharding_wrangler_test.go b/go/vt/workflow/resharding/mock_resharding_wrangler_test.go index 42e735c5a3e..21b68ce7f45 100644 --- a/go/vt/workflow/resharding/mock_resharding_wrangler_test.go +++ b/go/vt/workflow/resharding/mock_resharding_wrangler_test.go @@ -61,13 +61,13 @@ func (mr *MockReshardingWranglerMockRecorder) WaitForFilteredReplication(ctx, ke } // MigrateServedTypes mocks base method -func (m *MockReshardingWrangler) MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodata.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration) error { - ret := m.ctrl.Call(m, "MigrateServedTypes", ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime) +func (m *MockReshardingWrangler) MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodata.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration, reverseReplication bool) error { + ret := m.ctrl.Call(m, "MigrateServedTypes", ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime, reverseReplication) ret0, _ := ret[0].(error) return ret0 } // MigrateServedTypes indicates an expected call of MigrateServedTypes -func (mr *MockReshardingWranglerMockRecorder) MigrateServedTypes(ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MigrateServedTypes", reflect.TypeOf((*MockReshardingWrangler)(nil).MigrateServedTypes), ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime) +func (mr *MockReshardingWranglerMockRecorder) MigrateServedTypes(ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime, reverseReplication interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MigrateServedTypes", reflect.TypeOf((*MockReshardingWrangler)(nil).MigrateServedTypes), ctx, keyspace, shard, cells, servedType, reverse, skipReFreshState, filteredReplicationWaitTime, reverseReplication) } diff --git a/go/vt/workflow/resharding/resharding_wrangler.go b/go/vt/workflow/resharding/resharding_wrangler.go index 6b988f1c6a9..c06405df2b9 100644 --- a/go/vt/workflow/resharding/resharding_wrangler.go +++ b/go/vt/workflow/resharding/resharding_wrangler.go @@ -33,5 +33,5 @@ type ReshardingWrangler interface { WaitForFilteredReplication(ctx context.Context, keyspace, shard string, maxDelay time.Duration) error - MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodatapb.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration) error + MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodatapb.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration, reverseReplication bool) error } diff --git a/go/vt/workflow/resharding/tasks.go b/go/vt/workflow/resharding/tasks.go index 61ae80e5b97..c545a08ab7e 100644 --- a/go/vt/workflow/resharding/tasks.go +++ b/go/vt/workflow/resharding/tasks.go @@ -120,5 +120,5 @@ func (hw *horizontalReshardingWorkflow) runMigrate(ctx context.Context, t *workf return fmt.Errorf("wrong served type to be migrated: %v", servedTypeStr) } - return hw.wr.MigrateServedTypes(ctx, keyspace, sourceShard, nil /* cells */, servedType, false /* reverse */, false /* skipReFreshState */, wrangler.DefaultFilteredReplicationWaitTime) + return hw.wr.MigrateServedTypes(ctx, keyspace, sourceShard, nil /* cells */, servedType, false /* reverse */, false /* skipReFreshState */, wrangler.DefaultFilteredReplicationWaitTime, false /* reverseReplication */) } diff --git a/go/vt/workflow/resharding/workflow_test.go b/go/vt/workflow/resharding/workflow_test.go index b5c384a85f1..631adc975b6 100644 --- a/go/vt/workflow/resharding/workflow_test.go +++ b/go/vt/workflow/resharding/workflow_test.go @@ -166,7 +166,7 @@ func setupMockWrangler(ctrl *gomock.Controller, keyspace string) *MockResharding topodatapb.TabletType_REPLICA, topodatapb.TabletType_MASTER} for _, servedType := range servedTypeParams { - mockWranglerInterface.EXPECT().MigrateServedTypes(gomock.Any(), keyspace, "0", nil /* cells */, servedType, false /* reverse */, false /* skipReFreshState */, wrangler.DefaultFilteredReplicationWaitTime).Return(nil) + mockWranglerInterface.EXPECT().MigrateServedTypes(gomock.Any(), keyspace, "0", nil /* cells */, servedType, false /* reverse */, false /* skipReFreshState */, wrangler.DefaultFilteredReplicationWaitTime, false /* reverseReplication */).Return(nil) } return mockWranglerInterface } diff --git a/go/vt/wrangler/keyspace.go b/go/vt/wrangler/keyspace.go index f8bec63978a..5b49bd07fd9 100644 --- a/go/vt/wrangler/keyspace.go +++ b/go/vt/wrangler/keyspace.go @@ -25,6 +25,7 @@ import ( "golang.org/x/net/context" "vitess.io/vitess/go/event" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/discovery" @@ -33,6 +34,7 @@ import ( "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/topotools/events" + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" ) @@ -87,9 +89,142 @@ func (wr *Wrangler) SetKeyspaceShardingInfo(ctx context.Context, keyspace, shard return wr.ts.UpdateKeyspace(ctx, ki) } +// ShowResharding shows all resharding related metadata for the keyspace/shard. +func (wr *Wrangler) ShowResharding(ctx context.Context, keyspace, shard string) (err error) { + ki, err := wr.ts.GetKeyspace(ctx, keyspace) + if err != nil { + return err + } + if len(ki.ServedFroms) == 0 { + return wr.showHorizontalResharding(ctx, keyspace, shard) + } + return wr.showVerticalResharding(ctx, keyspace, shard) +} + +func (wr *Wrangler) showHorizontalResharding(ctx context.Context, keyspace, shard string) error { + osList, err := topotools.FindOverlappingShards(ctx, wr.ts, keyspace) + if err != nil { + return fmt.Errorf("FindOverlappingShards failed: %v", err) + } + os := topotools.OverlappingShardsForShard(osList, shard) + if os == nil { + wr.Logger().Printf("No resharding in progress\n") + return nil + } + + sourceShards, destinationShards, err := wr.findSourceDest(ctx, os) + if err != nil { + return err + } + wr.Logger().Printf("Horizontal Resharding for %v:\n", keyspace) + wr.Logger().Printf(" Sources:\n") + if err := wr.printShards(ctx, sourceShards); err != nil { + return err + } + wr.Logger().Printf(" Destinations:\n") + return wr.printShards(ctx, destinationShards) +} + +func (wr *Wrangler) printShards(ctx context.Context, si []*topo.ShardInfo) error { + for _, si := range si { + wr.Logger().Printf(" Shard: %v\n", si.ShardName()) + if len(si.SourceShards) != 0 { + wr.Logger().Printf(" Source Shards: %v\n", si.SourceShards) + } + ti, err := wr.ts.GetTablet(ctx, si.MasterAlias) + if err != nil { + return err + } + qr, err := wr.tmc.VReplicationExec(ctx, ti.Tablet, "select * from _vt.vreplication") + if err != nil { + return err + } + res := sqltypes.Proto3ToResult(qr) + if len(res.Rows) != 0 { + wr.Logger().Printf(" VReplication:\n") + for _, row := range res.Rows { + wr.Logger().Printf(" %v\n", row) + } + } + if len(si.ServedTypes) != 0 { + wr.Logger().Printf(" Served Types: %v\n", si.ServedTypes) + } + if len(si.TabletControls) != 0 { + wr.Logger().Printf(" Tablet Controls: %v\n", si.TabletControls) + } + } + return nil +} + +// CancelResharding cancels any resharding in progress on the specified keyspace/shard. +// This works for horizontal as well as vertical resharding. +func (wr *Wrangler) CancelResharding(ctx context.Context, keyspace, shard string) (err error) { + ctx, unlock, lockErr := wr.ts.LockKeyspace(ctx, keyspace, "CancelResharding") + if lockErr != nil { + return lockErr + } + defer unlock(&err) + + ki, err := wr.ts.GetKeyspace(ctx, keyspace) + if err != nil { + return err + } + if len(ki.ServedFroms) == 0 { + return wr.cancelHorizontalResharding(ctx, keyspace, shard) + } + return wr.cancelVerticalResharding(ctx, keyspace, shard) +} + +func (wr *Wrangler) cancelHorizontalResharding(ctx context.Context, keyspace, shard string) error { + wr.Logger().Infof("Finding the overlapping shards in keyspace %v", keyspace) + osList, err := topotools.FindOverlappingShards(ctx, wr.ts, keyspace) + if err != nil { + return fmt.Errorf("FindOverlappingShards failed: %v", err) + } + + // find our shard in there + os := topotools.OverlappingShardsForShard(osList, shard) + if os == nil { + return fmt.Errorf("Shard %v is not involved in any overlapping shards", shard) + } + + _, destinationShards, err := wr.findSourceDest(ctx, os) + if err != nil { + return err + } + for _, si := range destinationShards { + if len(si.ServedTypes) != 0 { + return fmt.Errorf("some served types have migrated for %v/%v, please undo them before canceling", keyspace, shard) + } + } + for i, si := range destinationShards { + ti, err := wr.ts.GetTablet(ctx, si.MasterAlias) + if err != nil { + return err + } + for _, sourceShard := range si.SourceShards { + if _, err := wr.tmc.VReplicationExec(ctx, ti.Tablet, binlogplayer.DeleteVReplication(sourceShard.Uid)); err != nil { + return err + } + } + destinationShards[i], err = wr.ts.UpdateShardFields(ctx, si.Keyspace(), si.ShardName(), func(si *topo.ShardInfo) error { + si.TabletControls = nil + si.SourceShards = nil + return nil + }) + if err != nil { + return err + } + if err := wr.RefreshTabletsByShard(ctx, si, nil, nil); err != nil { + return err + } + } + return nil +} + // MigrateServedTypes is used during horizontal splits to migrate a // served type from a list of shards to another. -func (wr *Wrangler) MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodatapb.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration) (err error) { +func (wr *Wrangler) MigrateServedTypes(ctx context.Context, keyspace, shard string, cells []string, servedType topodatapb.TabletType, reverse, skipReFreshState bool, filteredReplicationWaitTime time.Duration, reverseReplication bool) (err error) { // check input parameters if servedType == topodatapb.TabletType_MASTER { // we cannot migrate a master back, since when master migration @@ -126,54 +261,14 @@ func (wr *Wrangler) MigrateServedTypes(ctx context.Context, keyspace, shard stri return fmt.Errorf("Shard %v is not involved in any overlapping shards", shard) } - // find which list is which: the sources have no source - // shards, the destination have source shards. We check the - // first entry in the lists, then just check they're - // consistent - var sourceShards []*topo.ShardInfo - var destinationShards []*topo.ShardInfo - if len(os.Left[0].SourceShards) == 0 { - if len(os.Right[0].SourceShards) == 0 { - return fmt.Errorf("neither Shard '%v' nor Shard '%v' have a 'SourceShards' entry. Did you successfully run vtworker SplitClone before? Or did you already migrate the MASTER type?", os.Left[0].ShardName(), os.Right[0].ShardName()) - } - sourceShards = os.Left - destinationShards = os.Right - } else { - sourceShards = os.Right - destinationShards = os.Left - } - - // Verify the sources has the type we're migrating (or not if reverse) - for _, si := range sourceShards { - if err := si.CheckServedTypesMigration(servedType, cells, !reverse); err != nil { - return err - } - } - - // Verify the destinations do not have the type we're - // migrating (or do if reverse) - for _, si := range destinationShards { - if err := si.CheckServedTypesMigration(servedType, cells, reverse); err != nil { - return err - } - } - - // re-read all the shards so we are up to date - wr.Logger().Infof("Re-reading all shards") - for i, si := range sourceShards { - if sourceShards[i], err = wr.ts.GetShard(ctx, si.Keyspace(), si.ShardName()); err != nil { - return err - } - } - for i, si := range destinationShards { - if destinationShards[i], err = wr.ts.GetShard(ctx, si.Keyspace(), si.ShardName()); err != nil { - return err - } + sourceShards, destinationShards, err := wr.findSourceDest(ctx, os) + if err != nil { + return err } // execute the migration if servedType == topodatapb.TabletType_MASTER { - if err = wr.masterMigrateServedType(ctx, keyspace, sourceShards, destinationShards, filteredReplicationWaitTime); err != nil { + if err = wr.masterMigrateServedType(ctx, keyspace, sourceShards, destinationShards, filteredReplicationWaitTime, reverseReplication); err != nil { return err } } else { @@ -187,43 +282,70 @@ func (wr *Wrangler) MigrateServedTypes(ctx context.Context, keyspace, shard stri return err } - // Send a refresh to the tablets we just disabled, iff: - // - we're not migrating a master - // - we don't have any errors - // - we're not told to skip the refresh - if servedType != topodatapb.TabletType_MASTER && !skipReFreshState { - rec := concurrency.AllErrorRecorder{} - var refreshShards []*topo.ShardInfo - if reverse { - // For a backwards migration, we just disabled query service on the destination shards - refreshShards = destinationShards - } else { - // For a forwards migration, we just disabled query service on the source shards - refreshShards = sourceShards - } + // Master migrate performs its own refresh. + // Otherwise, honor skipRefreshState if requested. + if servedType == topodatapb.TabletType_MASTER || skipReFreshState { + return nil + } - // TODO(b/26388813): Integrate vtctl WaitForDrain here instead of just sleeping. - var waitForDrainSleep time.Duration - switch servedType { - case topodatapb.TabletType_RDONLY: - waitForDrainSleep = *waitForDrainSleepRdonly - case topodatapb.TabletType_REPLICA: - waitForDrainSleep = *waitForDrainSleepReplica - default: - wr.Logger().Warningf("invalid TabletType: %v for MigrateServedTypes command", servedType) - } + // refresh + // TODO(b/26388813): Integrate vtctl WaitForDrain here instead of just sleeping. + // Anything that's not a replica will use the RDONLY sleep time. + waitForDrainSleep := *waitForDrainSleepRdonly + if servedType == topodatapb.TabletType_REPLICA { + waitForDrainSleep = *waitForDrainSleepReplica + } + wr.Logger().Infof("WaitForDrain: Sleeping for %.0f seconds before shutting down query service on old tablets...", waitForDrainSleep.Seconds()) + time.Sleep(waitForDrainSleep) + wr.Logger().Infof("WaitForDrain: Sleeping finished. Shutting down queryservice on old tablets now.") - wr.Logger().Infof("WaitForDrain: Sleeping for %.0f seconds before shutting down query service on old tablets...", waitForDrainSleep.Seconds()) - time.Sleep(waitForDrainSleep) - wr.Logger().Infof("WaitForDrain: Sleeping finished. Shutting down queryservice on old tablets now.") + rec := concurrency.AllErrorRecorder{} + refreshShards := sourceShards + if reverse { + // For a backwards migration, we should refresh (disable) destination shards instead. + refreshShards = destinationShards + } + for _, si := range refreshShards { + rec.RecordError(wr.RefreshTabletsByShard(ctx, si, []topodatapb.TabletType{servedType}, cells)) + } + return rec.Error() +} - for _, si := range refreshShards { - rec.RecordError(wr.RefreshTabletsByShard(ctx, si, []topodatapb.TabletType{servedType}, cells)) +// findSourceDest derives the source and destination from the overlapping shards. +// Whichever side has SourceShards is a destination. +func (wr *Wrangler) findSourceDest(ctx context.Context, os *topotools.OverlappingShards) (sourceShards, destinationShards []*topo.ShardInfo, err error) { + // It's possible that both source and destination have source shards because of reversible replication. + // If so, the Frozen flag in the tablet control record dictates the direction. + // So, check that first. + for _, left := range os.Left { + tc := left.GetTabletControl(topodatapb.TabletType_MASTER) + if tc == nil { + continue + } + if tc.Frozen { + return os.Left, os.Right, nil } - return rec.Error() } - - return nil + for _, right := range os.Right { + tc := right.GetTabletControl(topodatapb.TabletType_MASTER) + if tc == nil { + continue + } + if tc.Frozen { + return os.Right, os.Left, nil + } + } + for _, left := range os.Left { + if len(left.SourceShards) != 0 { + return os.Right, os.Left, nil + } + } + for _, right := range os.Right { + if len(right.SourceShards) != 0 { + return os.Left, os.Right, nil + } + } + return nil, nil, fmt.Errorf("neither Shard '%v' nor Shard '%v' have a 'SourceShards' entry. Did you successfully run vtworker SplitClone before? Or did you already migrate the MASTER type?", os.Left[0].ShardName(), os.Right[0].ShardName()) } func (wr *Wrangler) getMastersPosition(ctx context.Context, shards []*topo.ShardInfo) (map[*topo.ShardInfo]string, error) { @@ -288,7 +410,11 @@ func (wr *Wrangler) waitForFilteredReplication(ctx context.Context, sourcePositi } if err := wr.tmc.VReplicationWaitForPos(ctx, ti.Tablet, int(sourceShard.Uid), pos); err != nil { - rec.RecordError(err) + if strings.Contains(err.Error(), "not found") { + wr.Logger().Infof("%v stream %d was not found. Skipping wait.", topoproto.TabletAliasString(si.MasterAlias), sourceShard.Uid) + } else { + rec.RecordError(err) + } } else { wr.Logger().Infof("%v caught up", topoproto.TabletAliasString(si.MasterAlias)) } @@ -364,7 +490,17 @@ func (wr *Wrangler) replicaMigrateServedType(ctx context.Context, keyspace strin } // masterMigrateServedType operates with the keyspace locked -func (wr *Wrangler) masterMigrateServedType(ctx context.Context, keyspace string, sourceShards, destinationShards []*topo.ShardInfo, filteredReplicationWaitTime time.Duration) (err error) { +func (wr *Wrangler) masterMigrateServedType(ctx context.Context, keyspace string, sourceShards, destinationShards []*topo.ShardInfo, filteredReplicationWaitTime time.Duration, reverseReplication bool) (err error) { + // Ensure other served types have migrated. + if si := sourceShards[0]; len(si.ServedTypes) > 1 { + var types []string + for _, servedType := range si.ServedTypes { + if servedType.TabletType != topodatapb.TabletType_MASTER { + types = append(types, servedType.TabletType.String()) + } + } + return fmt.Errorf("cannot migrate MASTER away from %v/%v until everything else is migrated. Make sure that the following types are migrated first: %v", si.Keyspace(), si.ShardName(), strings.Join(types, ", ")) + } ev := &events.MigrateServedTypes{ KeyspaceName: keyspace, @@ -379,42 +515,61 @@ func (wr *Wrangler) masterMigrateServedType(ctx context.Context, keyspace string } }() - // For master type migration, need to: + // Phase 1 // - switch the source shards to read-only by disabling query service // - gather all replication points - // - wait for filtered replication to catch up before we continue + // - wait for filtered replication to catch up + // - mark source shards as frozen event.DispatchUpdate(ev, "disabling query service on all source masters") - if err = wr.updateShardRecords(ctx, sourceShards, nil, topodatapb.TabletType_MASTER, true); err != nil { + if err := wr.updateShardRecords(ctx, sourceShards, nil, topodatapb.TabletType_MASTER, true); err != nil { + wr.cancelMasterMigrateServedTypes(ctx, sourceShards) return err } if err := wr.refreshMasters(ctx, sourceShards); err != nil { + wr.cancelMasterMigrateServedTypes(ctx, sourceShards) return err } event.DispatchUpdate(ev, "getting positions of source masters") masterPositions, err := wr.getMastersPosition(ctx, sourceShards) if err != nil { + wr.cancelMasterMigrateServedTypes(ctx, sourceShards) return err } event.DispatchUpdate(ev, "waiting for destination masters to catch up") if err := wr.waitForFilteredReplication(ctx, masterPositions, destinationShards, filteredReplicationWaitTime); err != nil { + wr.cancelMasterMigrateServedTypes(ctx, sourceShards) + return err + } + + // We've reached the point of no return. Freeze the tablet control records in the source masters. + if err := wr.updateFrozenFlag(ctx, sourceShards, true); err != nil { + wr.cancelMasterMigrateServedTypes(ctx, sourceShards) + return err + } + + // Phase 2 + // Always setup reverse replication. We'll start it later if reverseReplication was specified. + // This will allow someone to reverse the replication later if they change their mind. + if err := wr.setupReverseReplication(ctx, sourceShards, destinationShards); err != nil { return err } // Destination shards need different handling than what updateShardRecords does. event.DispatchUpdate(ev, "updating destination shards") for i, si := range destinationShards { - // Stop VReplication streams if we're migrating master (forward only). ti, err := wr.ts.GetTablet(ctx, si.MasterAlias) if err != nil { return err } + // Stop VReplication streams. for _, sourceShard := range si.SourceShards { if _, err := wr.tmc.VReplicationExec(ctx, ti.Tablet, binlogplayer.DeleteVReplication(sourceShard.Uid)); err != nil { return err } } + // Similar to updateShardRecords, but we also remove SourceShards. destinationShards[i], err = wr.ts.UpdateShardFields(ctx, si.Keyspace(), si.ShardName(), func(si *topo.ShardInfo) error { if err := si.UpdateServedTypesMap(topodatapb.TabletType_MASTER, nil, false); err != nil { return err @@ -423,7 +578,6 @@ func (wr *Wrangler) masterMigrateServedType(ctx context.Context, keyspace string return err } - // Final migration. Remove source shards. si.SourceShards = nil return nil }) @@ -432,18 +586,111 @@ func (wr *Wrangler) masterMigrateServedType(ctx context.Context, keyspace string } } - // And tell the new shards masters they can now be read-write. - // Invoking a remote action will also make the tablet stop filtered - // replication. event.DispatchUpdate(ev, "setting destination masters read-write") if err := wr.refreshMasters(ctx, destinationShards); err != nil { return err } + if reverseReplication { + if err := wr.startReverseReplication(ctx, sourceShards); err != nil { + return err + } + // We also have to remove the frozen flag as final step. + if err := wr.updateFrozenFlag(ctx, sourceShards, false); err != nil { + return err + } + } + event.DispatchUpdate(ev, "finished") return nil } +func (wr *Wrangler) cancelMasterMigrateServedTypes(ctx context.Context, sourceShards []*topo.ShardInfo) { + if err := wr.updateShardRecords(ctx, sourceShards, nil, topodatapb.TabletType_MASTER, false); err != nil { + wr.Logger().Errorf("failed to re-enable source masters: %v", err) + return + } + if err := wr.refreshMasters(ctx, sourceShards); err != nil { + wr.Logger().Errorf("failed to refresh source masters: %v", err) + } +} + +func (wr *Wrangler) setupReverseReplication(ctx context.Context, sourceShards, destinationShards []*topo.ShardInfo) error { + // Retrieve master positions of all destinations. + masterPositions := make([]string, len(destinationShards)) + for i, dest := range destinationShards { + ti, err := wr.ts.GetTablet(ctx, dest.MasterAlias) + if err != nil { + return err + } + + wr.Logger().Infof("Gathering master position for %v", topoproto.TabletAliasString(dest.MasterAlias)) + masterPositions[i], err = wr.tmc.MasterPosition(ctx, ti.Tablet) + if err != nil { + return err + } + } + + // Create reverse replication for each source. + for i, sourceShard := range sourceShards { + if len(sourceShard.SourceShards) != 0 { + continue + } + // Handle the case where the source is "unsharded". + kr := sourceShard.KeyRange + if kr == nil { + kr = &topodatapb.KeyRange{} + } + // Create replications streams first using the retrieved master positions. + uids := make([]uint32, len(destinationShards)) + for j, dest := range destinationShards { + bls := &binlogdatapb.BinlogSource{ + Keyspace: dest.Keyspace(), + Shard: dest.ShardName(), + KeyRange: kr, + } + qr, err := wr.VReplicationExec(ctx, sourceShard.MasterAlias, binlogplayer.CreateVReplicationStopped("ReversedResharding", bls, masterPositions[j])) + if err != nil { + return err + } + uids[j] = uint32(qr.InsertId) + wr.Logger().Infof("Created reverse replication for tablet %v/%v: %v, pos: %v, uid: %v", sourceShard.Keyspace(), sourceShard.ShardName(), bls, masterPositions[j], uids[j]) + } + // Source shards have to be atomically added to ensure idempotence. + // If this fails, there's no harm because the unstarted vreplication streams will just be abandoned. + var err error + sourceShards[i], err = wr.ts.UpdateShardFields(ctx, sourceShard.Keyspace(), sourceShard.ShardName(), func(si *topo.ShardInfo) error { + for j, dest := range destinationShards { + si.SourceShards = append(si.SourceShards, &topodatapb.Shard_SourceShard{ + Uid: uids[j], + Keyspace: dest.Keyspace(), + Shard: dest.ShardName(), + KeyRange: dest.KeyRange, + }) + } + return nil + }) + if err != nil { + wr.Logger().Errorf("Unstarted vreplication streams for %v/%v need to be deleted: %v", sourceShard.Keyspace(), sourceShard.ShardName(), uids) + return fmt.Errorf("failed to setup reverse replication: %v, unstarted vreplication streams for %v/%v need to be deleted: %v", err, sourceShard.Keyspace(), sourceShard.ShardName(), uids) + } + } + return nil +} + +func (wr *Wrangler) startReverseReplication(ctx context.Context, sourceShards []*topo.ShardInfo) error { + for _, sourceShard := range sourceShards { + for _, dest := range sourceShard.SourceShards { + wr.Logger().Infof("Starting reverse replication for tablet %v/%v, uid: %v", sourceShard.Keyspace(), sourceShard.ShardName(), dest.Uid) + _, err := wr.VReplicationExec(ctx, sourceShard.MasterAlias, binlogplayer.StartVReplication(dest.Uid)) + if err != nil { + return err + } + } + } + return nil +} + // updateShardRecords updates the shard records based on 'from' or 'to' direction. func (wr *Wrangler) updateShardRecords(ctx context.Context, shards []*topo.ShardInfo, cells []string, servedType topodatapb.TabletType, isFrom bool) (err error) { for i, si := range shards { @@ -465,6 +712,25 @@ func (wr *Wrangler) updateShardRecords(ctx context.Context, shards []*topo.Shard return nil } +// updateFrozenFlag sets or unsets the Frozen flag for master migration. This is performed +// for all master tablet control records. +func (wr *Wrangler) updateFrozenFlag(ctx context.Context, shards []*topo.ShardInfo, value bool) (err error) { + for i, si := range shards { + shards[i], err = wr.ts.UpdateShardFields(ctx, si.Keyspace(), si.ShardName(), func(si *topo.ShardInfo) error { + tc := si.GetTabletControl(topodatapb.TabletType_MASTER) + if tc == nil { + return fmt.Errorf("unexpected: missing tablet control record for source %v/%v", si.Keyspace(), si.ShardName()) + } + tc.Frozen = value + return nil + }) + if err != nil { + return err + } + } + return nil +} + // WaitForDrain blocks until the selected tablets (cells/keyspace/shard/tablet_type) // have reported a QPS rate of 0.0. // NOTE: This is just an observation of one point in time and no guarantee that @@ -580,6 +846,62 @@ func formatTabletStats(ts *discovery.TabletStats) string { return fmt.Sprintf("%v: %v stats: %v", topoproto.TabletAliasString(ts.Tablet.Alias), webURL, ts.Stats) } +func (wr *Wrangler) showVerticalResharding(ctx context.Context, keyspace, shard string) error { + ki, err := wr.ts.GetKeyspace(ctx, keyspace) + if err != nil { + return err + } + destinationShard, err := wr.ts.GetShard(ctx, keyspace, shard) + if err != nil { + return err + } + if len(destinationShard.SourceShards) != 1 || len(destinationShard.SourceShards[0].Tables) == 0 { + wr.Logger().Printf("No resharding in progress\n") + return nil + } + sourceShard, err := wr.ts.GetShard(ctx, destinationShard.SourceShards[0].Keyspace, destinationShard.SourceShards[0].Shard) + if err != nil { + return err + } + wr.Logger().Printf("Vertical Resharding:\n") + wr.Logger().Printf(" Served From: %v\n", ki.ServedFroms) + wr.Logger().Printf(" Source:\n") + if err := wr.printShards(ctx, []*topo.ShardInfo{sourceShard}); err != nil { + return err + } + wr.Logger().Printf(" Destination:\n") + return wr.printShards(ctx, []*topo.ShardInfo{destinationShard}) +} + +func (wr *Wrangler) cancelVerticalResharding(ctx context.Context, keyspace, shard string) error { + destinationShard, err := wr.ts.GetShard(ctx, keyspace, shard) + if err != nil { + return err + } + if len(destinationShard.SourceShards) != 1 || len(destinationShard.SourceShards[0].Tables) == 0 { + return fmt.Errorf("destination shard %v/%v is not a vertical split target", keyspace, shard) + } + sourceShard, err := wr.ts.GetShard(ctx, destinationShard.SourceShards[0].Keyspace, destinationShard.SourceShards[0].Shard) + if err != nil { + return err + } + if len(sourceShard.TabletControls) != 0 { + return fmt.Errorf("some served types have migrated for %v/%v, please undo them before canceling", keyspace, shard) + } + destinationMasterTabletInfo, err := wr.ts.GetTablet(ctx, destinationShard.MasterAlias) + if err != nil { + return err + } + if _, err := wr.tmc.VReplicationExec(ctx, destinationMasterTabletInfo.Tablet, binlogplayer.DeleteVReplication(destinationShard.SourceShards[0].Uid)); err != nil { + return err + } + _, err = wr.ts.UpdateShardFields(ctx, destinationShard.Keyspace(), destinationShard.ShardName(), func(si *topo.ShardInfo) error { + si.SourceShards = nil + return nil + }) + return err +} + // MigrateServedFrom is used during vertical splits to migrate a // served type from a keyspace to another. func (wr *Wrangler) MigrateServedFrom(ctx context.Context, keyspace, shard string, servedType topodatapb.TabletType, cells []string, reverse bool, filteredReplicationWaitTime time.Duration) (err error) { diff --git a/go/vt/wrangler/testlib/migrate_served_from_test.go b/go/vt/wrangler/testlib/migrate_served_from_test.go index f4eba888103..bd51f1fdf0c 100644 --- a/go/vt/wrangler/testlib/migrate_served_from_test.go +++ b/go/vt/wrangler/testlib/migrate_served_from_test.go @@ -113,6 +113,7 @@ func TestMigrateServedFrom(t *testing.T) { dbClient.ExpectRequest("select pos from _vt.vreplication where id=1", &sqltypes.Result{Rows: [][]sqltypes.Value{{ sqltypes.NewVarBinary("MariaDB/5-456-892"), }}}, nil) + dbClient.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient.ExpectRequest("delete from _vt.vreplication where id = 1", &sqltypes.Result{RowsAffected: 1}, nil) // simulate the clone, by fixing the dest shard record diff --git a/go/vt/wrangler/testlib/migrate_served_types_test.go b/go/vt/wrangler/testlib/migrate_served_types_test.go index b1778fb3e63..eb8a872eb68 100644 --- a/go/vt/wrangler/testlib/migrate_served_types_test.go +++ b/go/vt/wrangler/testlib/migrate_served_types_test.go @@ -149,6 +149,7 @@ func TestMigrateServedTypes(t *testing.T) { dbClient1.ExpectRequest("select pos from _vt.vreplication where id=1", &sqltypes.Result{Rows: [][]sqltypes.Value{{ sqltypes.NewVarBinary("MariaDB/5-456-892"), }}}, nil) + dbClient1.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient1.ExpectRequest("delete from _vt.vreplication where id = 1", &sqltypes.Result{RowsAffected: 1}, nil) // dest2Rdonly will see the refresh @@ -175,6 +176,7 @@ func TestMigrateServedTypes(t *testing.T) { dbClient2.ExpectRequest("select pos from _vt.vreplication where id=1", &sqltypes.Result{Rows: [][]sqltypes.Value{{ sqltypes.NewVarBinary("MariaDB/5-456-892"), }}}, nil) + dbClient2.ExpectRequest("use _vt", &sqltypes.Result{}, nil) dbClient2.ExpectRequest("delete from _vt.vreplication where id = 1", &sqltypes.Result{RowsAffected: 1}, nil) // migrate will error if the overlapping shards have no "SourceShard" entry diff --git a/go/vtbench/client.go b/go/vtbench/client.go index e4cffe90641..e7672f1fff4 100644 --- a/go/vtbench/client.go +++ b/go/vtbench/client.go @@ -46,11 +46,12 @@ type mysqlClientConn struct { func (c *mysqlClientConn) connect(ctx context.Context, cp ConnParams) error { conn, err := mysql.Connect(ctx, &mysql.ConnParams{ - Host: cp.Hosts[0], - Port: cp.Port, - DbName: cp.DB, - Uname: cp.Username, - Pass: cp.Password, + Host: cp.Hosts[0], + Port: cp.Port, + DbName: cp.DB, + Uname: cp.Username, + Pass: cp.Password, + UnixSocket: cp.UnixSocket, }) if err != nil { diff --git a/go/vtbench/vtbench.go b/go/vtbench/vtbench.go index 8b0ad44f466..5dad800899b 100644 --- a/go/vtbench/vtbench.go +++ b/go/vtbench/vtbench.go @@ -59,12 +59,13 @@ func (cp ClientProtocol) String() string { // ConnParams specifies how to connect to the vtgate(s) type ConnParams struct { - Hosts []string - Port int - DB string - Username string - Password string - Protocol ClientProtocol + Hosts []string + Port int + DB string + Username string + Password string + UnixSocket string + Protocol ClientProtocol } // Bench controls the test diff --git a/helm/vitess/README.md b/helm/vitess/README.md index 86a52784925..52d5a6bab4b 100644 --- a/helm/vitess/README.md +++ b/helm/vitess/README.md @@ -11,8 +11,7 @@ This chart creates a Vitess cluster on Kubernetes in a single It currently includes all dependencies (e.g. etcd) and Vitess components (vtctld, vtgate, vttablet) inline (in `templates/`) rather than as sub-charts. -**WARNING: This chart should be considered Alpha. -Upgrading a release of this chart may or may not delete all your data.** +**WARNING: This chart should be considered Beta.** ## Prerequisites @@ -119,6 +118,28 @@ topology: replicas: 2 ``` +### Append custom my.cnf to default Vitess settings + +Create a config map with one or more standard `my.cnf` formatted files. Any settings +provided here will overwrite any colliding values from Vitess defaults. + +`kubectl create configmap shared-my-cnf --from-file=shared.my.cnf` + +*NOTE:* if using MySQL 8.0.x, this file must contain +`default_authentication_plugin = mysql_native_password` + +``` +topology: + cells: + ... + +vttablet: + + # The name of a config map with N files inside of it. Each file will be added + # to $EXTRA_MY_CNF, overriding any default my.cnf settings + extraMyCnf: shared-my-cnf +``` + ### Use a custom database image and a specific Vitess release ``` @@ -227,7 +248,7 @@ topology: pmm: enabled: true - pmmTag: "1.6.1" + pmmTag: "1.15.0" client: resources: requests: diff --git a/helm/vitess/templates/_helpers.tpl b/helm/vitess/templates/_helpers.tpl index 6a03c9677c5..e5aec6cfa32 100644 --- a/helm/vitess/templates/_helpers.tpl +++ b/helm/vitess/templates/_helpers.tpl @@ -87,7 +87,7 @@ nodeAffinity: {{- end -}} ############################# -# mycnf exec +# mycnf exec - expects extraMyCnf config map name ############################# {{- define "mycnf-exec" -}} @@ -97,13 +97,28 @@ if [ "$VT_DB_FLAVOR" = "percona" ]; then elif [ "$VT_DB_FLAVOR" = "mysql" ]; then FLAVOR_MYCNF=/vt/config/mycnf/master_mysql56.cnf +elif [ "$VT_DB_FLAVOR" = "mysql56" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mysql56.cnf + elif [ "$VT_DB_FLAVOR" = "maria" ]; then FLAVOR_MYCNF=/vt/config/mycnf/master_mariadb.cnf +elif [ "$VT_DB_FLAVOR" = "mariadb" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mariadb.cnf + +elif [ "$VT_DB_FLAVOR" = "mariadb103" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mariadb103.cnf + fi export EXTRA_MY_CNF="$FLAVOR_MYCNF:/vtdataroot/tabletdata/report-host.cnf:/vt/config/mycnf/rbr.cnf" +{{ if . }} +for filename in /vt/userconfig/*; do + export EXTRA_MY_CNF="$EXTRA_MY_CNF:$filename" +done +{{ end }} + {{- end -}} ############################# @@ -285,4 +300,33 @@ cat $AWS_SHARED_CREDENTIALS_FILE {{ end }} +{{- end -}} + +############################# +# user config volume - expects config map name +############################# +{{- define "user-config-volume" -}} + +{{ if . }} + +- name: user-config + configMap: + name: {{ . }} + +{{ end }} + +{{- end -}} + +############################# +# user config volumeMount - expects config map name +############################# +{{- define "user-config-volumeMount" -}} + +{{ if . }} + +- name: user-config + mountPath: /vt/userconfig + +{{ end }} + {{- end -}} \ No newline at end of file diff --git a/helm/vitess/templates/_vttablet.tpl b/helm/vitess/templates/_vttablet.tpl index 04edcedde9f..357845198ea 100644 --- a/helm/vitess/templates/_vttablet.tpl +++ b/helm/vitess/templates/_vttablet.tpl @@ -114,6 +114,7 @@ spec: - name: vt emptyDir: {} {{ include "backup-volume" $config.backup | indent 8 }} +{{ include "user-config-volume" $defaultVttablet.extraMyCnf | indent 8 }} volumeClaimTemplates: - metadata: @@ -152,7 +153,7 @@ kind: Job metadata: name: {{ $shardName }}-init-shard-master spec: - backoffLimit: 0 + backoffLimit: 1 template: spec: restartPolicy: OnFailure @@ -359,6 +360,7 @@ spec: - name: vtdataroot mountPath: "/vtdataroot" {{ include "backup-volumeMount" $config.backup | indent 4 }} +{{ include "user-config-volumeMount" $defaultVttablet.extraMyCnf | indent 4 }} resources: {{ toYaml (.resources | default $defaultVttablet.resources) | indent 6 }} @@ -383,7 +385,7 @@ spec: - | set -ex -{{ include "mycnf-exec" . | indent 6 }} +{{ include "mycnf-exec" $defaultVttablet.extraMyCnf | indent 6 }} {{ include "backup-exec" $config.backup | indent 6 }} eval exec /vt/bin/vttablet $(cat <= 10.3) # the flavor determines the base my.cnf file for vitess to function - flavor: "percona" + flavor: "mysql56" mysqlImage: "percona:5.7.20" # mysqlImage: "mysql:5.7.20" @@ -137,6 +140,11 @@ vttablet: # will block forever. "rdonly" tablets do not ACK. enableSemisync: false + # The name of a config map with N files inside of it. Each file will be added + # to $EXTRA_MY_CNF, overriding any default my.cnf settings + extraMyCnf: "" + # extraMyCnf: extra-my-cnf + resources: # common production values 2-4CPU/4-8Gi RAM limits: @@ -163,7 +171,7 @@ vttablet: # Default values for pmm pmm: enabled: false - pmmTag: "1.10.0" + pmmTag: "1.15.0" client: resources: requests: @@ -219,7 +227,7 @@ pmm: # Default values for orchestrator resources orchestrator: enabled: false - image: "vitess/orchestrator:3.0.11" + image: "vitess/orchestrator:3.0.13" replicas: 3 resources: requests: diff --git a/java/client/pom.xml b/java/client/pom.xml index 7927612a7ad..773ee366f13 100644 --- a/java/client/pom.xml +++ b/java/client/pom.xml @@ -72,9 +72,11 @@ org.apache.maven.plugins maven-surefire-plugin - 2.17 + 2.22.1 - ${surefireArgLine} + + false + true diff --git a/java/grpc-client/pom.xml b/java/grpc-client/pom.xml index e776bb73878..c8bb78dcbf3 100644 --- a/java/grpc-client/pom.xml +++ b/java/grpc-client/pom.xml @@ -85,6 +85,16 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + false + true + + org.xolstice.maven.plugins protobuf-maven-plugin diff --git a/java/grpc-client/src/main/java/io/vitess/client/grpc/GrpcClient.java b/java/grpc-client/src/main/java/io/vitess/client/grpc/GrpcClient.java index 5ad84c572c8..9927068b9e1 100644 --- a/java/grpc-client/src/main/java/io/vitess/client/grpc/GrpcClient.java +++ b/java/grpc-client/src/main/java/io/vitess/client/grpc/GrpcClient.java @@ -1,12 +1,12 @@ /* * Copyright 2017 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import io.grpc.ManagedChannel; import io.grpc.StatusRuntimeException; import io.grpc.internal.WithLogId; @@ -104,54 +105,56 @@ public void close() throws IOException { public ListenableFuture execute(Context ctx, ExecuteRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).execute(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeShards(Context ctx, ExecuteShardsRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeShards(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeKeyspaceIds(Context ctx, ExecuteKeyspaceIdsRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeKeyspaceIds(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeKeyRanges(Context ctx, ExecuteKeyRangesRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeKeyRanges(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeEntityIds(Context ctx, ExecuteEntityIdsRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeEntityIds(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeBatch(Context ctx, Vtgate.ExecuteBatchRequest request) throws SQLException { - return Futures.catchingAsync(getFutureStub(ctx).executeBatch(request), Exception.class, new ExceptionConverter()); + return Futures.catchingAsync(getFutureStub(ctx).executeBatch(request), Exception.class, + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeBatchShards(Context ctx, ExecuteBatchShardsRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeBatchShards(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture executeBatchKeyspaceIds(Context ctx, ExecuteBatchKeyspaceIdsRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).executeBatchKeyspaceIds(request), - Exception.class, new ExceptionConverter()); + Exception.class, new ExceptionConverter(), + MoreExecutors.directExecutor()); } @Override @@ -214,35 +217,35 @@ QueryResult getResult(StreamExecuteKeyRangesResponse response) throws SQLExcepti public ListenableFuture begin(Context ctx, BeginRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).begin(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture commit(Context ctx, CommitRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).commit(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture rollback(Context ctx, RollbackRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).rollback(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture splitQuery(Context ctx, SplitQueryRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).splitQuery(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } @Override public ListenableFuture getSrvKeyspace(Context ctx, GetSrvKeyspaceRequest request) throws SQLException { return Futures.catchingAsync(getFutureStub(ctx).getSrvKeyspace(request), Exception.class, - new ExceptionConverter()); + new ExceptionConverter(), MoreExecutors.directExecutor()); } /** diff --git a/java/hadoop/pom.xml b/java/hadoop/pom.xml index ffa22f09b2c..3d21d204afd 100644 --- a/java/hadoop/pom.xml +++ b/java/hadoop/pom.xml @@ -76,6 +76,16 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + false + true + + org.apache.maven.plugins maven-failsafe-plugin diff --git a/java/jdbc/pom.xml b/java/jdbc/pom.xml index 8df6df557ad..9019aaa72fe 100644 --- a/java/jdbc/pom.xml +++ b/java/jdbc/pom.xml @@ -56,23 +56,29 @@ org.powermock powermock-api-mockito - 1.6.4 + 1.7.4 test org.powermock powermock-core - 1.6.4 + 1.7.4 test org.powermock powermock-module-junit4 - 1.6.4 + 1.7.4 test + + org.powermock + powermock-api-mockito-common + 1.7.4 + test + - + @@ -84,7 +90,16 @@ 7 - + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + false + true + + org.apache.maven.plugins maven-shade-plugin diff --git a/java/pom.xml b/java/pom.xml index 3a226fbbed7..d111a8324de 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -16,8 +16,8 @@ client example - grpc-client - hadoop + grpc-client + jdbc @@ -60,8 +60,8 @@ UTF-8 - 1.11.0 - 3.0.0 + 1.15.0 + 3.5.1 @@ -70,28 +70,28 @@ com.google.code.findbugs jsr305 - 3.0.0 + 3.0.2 com.google.code.gson gson - 2.8.0 + 2.8.5 com.google.guava guava - 20.0 + 26.0-jre com.google.protobuf protobuf-java - 3.0.0 + ${protobuf.java.version} commons-io commons-io - 2.5 + 2.6 @@ -122,14 +122,14 @@ io.netty netty-handler - 4.1.22.Final + 4.1.27.Final io.netty netty-tcnative-boringssl-static - 2.0.7.Final + 2.0.17.Final @@ -157,7 +157,7 @@ joda-time joda-time - 2.5 + 2.10 @@ -175,7 +175,7 @@ org.apache.commons commons-collections4 - 4.1 + 4.2 org.apache.hadoop diff --git a/proto/query.proto b/proto/query.proto index 5413fedd1a3..e55c95674b9 100644 --- a/proto/query.proto +++ b/proto/query.proto @@ -366,6 +366,13 @@ message QueryResult { ResultExtras extras = 5; } +// QueryWarning is used to convey out of band query execution warnings +// by storing in the vtgate.Session +message QueryWarning { + uint32 code = 1; + string message = 2; +} + // StreamEvent describes a set of transformations that happened as a // single transactional unit on a server. It is streamed back by the // Update Stream calls. diff --git a/proto/topodata.proto b/proto/topodata.proto index 116fd3e6627..4fe5584f57f 100644 --- a/proto/topodata.proto +++ b/proto/topodata.proto @@ -221,6 +221,10 @@ message Shard { // what to do bool disable_query_service = 3; repeated string blacklisted_tables = 4; + + // frozen is set if we've started failing over traffic for + // the master. If set, this record should not be removed. + bool frozen = 5; } // tablet_controls has at most one entry per TabletType. diff --git a/proto/vtgate.proto b/proto/vtgate.proto index 8d7f5009a6d..823f4f4d07a 100644 --- a/proto/vtgate.proto +++ b/proto/vtgate.proto @@ -81,6 +81,9 @@ message Session { // transaction_mode specifies the current transaction mode. TransactionMode transaction_mode = 7; + + // warnings contains non-fatal warnings from the previous query + repeated query.QueryWarning warnings = 8; } // ExecuteRequest is the payload to Execute. diff --git a/py/vtdb/grpc_vtgate_client.py b/py/vtdb/grpc_vtgate_client.py index cc320436bc3..2886229cf84 100644 --- a/py/vtdb/grpc_vtgate_client.py +++ b/py/vtdb/grpc_vtgate_client.py @@ -323,6 +323,10 @@ def message_ack( return response.result.rows_affected + def get_warnings(self): + if self.session: + return self.session.warnings + return [] def _convert_exception(exc, *args, **kwargs): """This parses the protocol exceptions to the api interface exceptions. diff --git a/py/vtdb/vtgate_client.py b/py/vtdb/vtgate_client.py index cd8a2a7040f..38437598946 100644 --- a/py/vtdb/vtgate_client.py +++ b/py/vtdb/vtgate_client.py @@ -1,11 +1,11 @@ # Copyright 2017 Google Inc. -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -71,6 +71,9 @@ def __init__(self, principal=None, component=None, subcomponent=None): self.component = component self.subcomponent = subcomponent + def __repr__(self): + return repr((self.principal, self.component, self.subcomponent)) + class VTGateClient(object): """VTGateClient is the interface for the vtgate client implementations. @@ -454,3 +457,13 @@ def message_ack(self, dbexceptions.FatalError: this query should not be retried. """ raise NotImplementedError('Child class needs to implement this') + + def get_warnings(self): + """Get warnings from the previous query + + Returns: + The list of warnings. + + """ + raise NotImplementedError('Child class needs to implement this') + diff --git a/py/vtproto/query_pb2.py b/py/vtproto/query_pb2.py index 9cdaa2e52e6..fa74a6018bd 100644 --- a/py/vtproto/query_pb2.py +++ b/py/vtproto/query_pb2.py @@ -22,7 +22,7 @@ name='query.proto', package='query', syntax='proto3', - serialized_pb=_b('\n\x0bquery.proto\x12\x05query\x1a\x0etopodata.proto\x1a\x0bvtrpc.proto\"b\n\x06Target\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12\r\n\x05shard\x18\x02 \x01(\t\x12)\n\x0btablet_type\x18\x03 \x01(\x0e\x32\x14.topodata.TabletType\x12\x0c\n\x04\x63\x65ll\x18\x04 \x01(\t\"2\n\x0eVTGateCallerID\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0e\n\x06groups\x18\x02 \x03(\t\"@\n\nEventToken\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\r\n\x05shard\x18\x02 \x01(\t\x12\x10\n\x08position\x18\x03 \x01(\t\"1\n\x05Value\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\"V\n\x0c\x42indVariable\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.query.Value\"\xa2\x01\n\nBoundQuery\x12\x0b\n\x03sql\x18\x01 \x01(\t\x12<\n\x0e\x62ind_variables\x18\x02 \x03(\x0b\x32$.query.BoundQuery.BindVariablesEntry\x1aI\n\x12\x42indVariablesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.query.BindVariable:\x02\x38\x01\"\xe0\x04\n\x0e\x45xecuteOptions\x12\x1b\n\x13include_event_token\x18\x02 \x01(\x08\x12.\n\x13\x63ompare_event_token\x18\x03 \x01(\x0b\x32\x11.query.EventToken\x12=\n\x0fincluded_fields\x18\x04 \x01(\x0e\x32$.query.ExecuteOptions.IncludedFields\x12\x19\n\x11\x63lient_found_rows\x18\x05 \x01(\x08\x12\x30\n\x08workload\x18\x06 \x01(\x0e\x32\x1e.query.ExecuteOptions.Workload\x12\x18\n\x10sql_select_limit\x18\x08 \x01(\x03\x12I\n\x15transaction_isolation\x18\t \x01(\x0e\x32*.query.ExecuteOptions.TransactionIsolation\x12\x1d\n\x15skip_query_plan_cache\x18\n \x01(\x08\";\n\x0eIncludedFields\x12\x11\n\rTYPE_AND_NAME\x10\x00\x12\r\n\tTYPE_ONLY\x10\x01\x12\x07\n\x03\x41LL\x10\x02\"8\n\x08Workload\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x08\n\x04OLTP\x10\x01\x12\x08\n\x04OLAP\x10\x02\x12\x07\n\x03\x44\x42\x41\x10\x03\"t\n\x14TransactionIsolation\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x13\n\x0fREPEATABLE_READ\x10\x01\x12\x12\n\x0eREAD_COMMITTED\x10\x02\x12\x14\n\x10READ_UNCOMMITTED\x10\x03\x12\x10\n\x0cSERIALIZABLE\x10\x04J\x04\x08\x01\x10\x02\"\xbf\x01\n\x05\x46ield\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x19\n\x04type\x18\x02 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05table\x18\x03 \x01(\t\x12\x11\n\torg_table\x18\x04 \x01(\t\x12\x10\n\x08\x64\x61tabase\x18\x05 \x01(\t\x12\x10\n\x08org_name\x18\x06 \x01(\t\x12\x15\n\rcolumn_length\x18\x07 \x01(\r\x12\x0f\n\x07\x63harset\x18\x08 \x01(\r\x12\x10\n\x08\x64\x65\x63imals\x18\t \x01(\r\x12\r\n\x05\x66lags\x18\n \x01(\r\"&\n\x03Row\x12\x0f\n\x07lengths\x18\x01 \x03(\x12\x12\x0e\n\x06values\x18\x02 \x01(\x0c\"G\n\x0cResultExtras\x12&\n\x0b\x65vent_token\x18\x01 \x01(\x0b\x32\x11.query.EventToken\x12\x0f\n\x07\x66resher\x18\x02 \x01(\x08\"\x94\x01\n\x0bQueryResult\x12\x1c\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x0c.query.Field\x12\x15\n\rrows_affected\x18\x02 \x01(\x04\x12\x11\n\tinsert_id\x18\x03 \x01(\x04\x12\x18\n\x04rows\x18\x04 \x03(\x0b\x32\n.query.Row\x12#\n\x06\x65xtras\x18\x05 \x01(\x0b\x32\x13.query.ResultExtras\"\xca\x02\n\x0bStreamEvent\x12\x30\n\nstatements\x18\x01 \x03(\x0b\x32\x1c.query.StreamEvent.Statement\x12&\n\x0b\x65vent_token\x18\x02 \x01(\x0b\x32\x11.query.EventToken\x1a\xe0\x01\n\tStatement\x12\x37\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32%.query.StreamEvent.Statement.Category\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12(\n\x12primary_key_fields\x18\x03 \x03(\x0b\x32\x0c.query.Field\x12&\n\x12primary_key_values\x18\x04 \x03(\x0b\x32\n.query.Row\x12\x0b\n\x03sql\x18\x05 \x01(\x0c\"\'\n\x08\x43\x61tegory\x12\t\n\x05\x45rror\x10\x00\x12\x07\n\x03\x44ML\x10\x01\x12\x07\n\x03\x44\x44L\x10\x02\"\xf3\x01\n\x0e\x45xecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0etransaction_id\x18\x05 \x01(\x03\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"5\n\x0f\x45xecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"U\n\x0fResultWithError\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12\"\n\x06result\x18\x02 \x01(\x0b\x32\x12.query.QueryResult\"\x92\x02\n\x13\x45xecuteBatchRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\"\n\x07queries\x18\x04 \x03(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12\x16\n\x0etransaction_id\x18\x06 \x01(\x03\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\";\n\x14\x45xecuteBatchResponse\x12#\n\x07results\x18\x01 \x03(\x0b\x32\x12.query.QueryResult\"\xe1\x01\n\x14StreamExecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\";\n\x15StreamExecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xb7\x01\n\x0c\x42\x65ginRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12&\n\x07options\x18\x04 \x01(\x0b\x32\x15.query.ExecuteOptions\"\'\n\rBeginResponse\x12\x16\n\x0etransaction_id\x18\x01 \x01(\x03\"\xa8\x01\n\rCommitRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\"\x10\n\x0e\x43ommitResponse\"\xaa\x01\n\x0fRollbackRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\"\x12\n\x10RollbackResponse\"\xb7\x01\n\x0ePrepareRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x11\n\x0fPrepareResponse\"\xa6\x01\n\x15\x43ommitPreparedRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"\x18\n\x16\x43ommitPreparedResponse\"\xc0\x01\n\x17RollbackPreparedRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x1a\n\x18RollbackPreparedResponse\"\xce\x01\n\x18\x43reateTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\x12#\n\x0cparticipants\x18\x05 \x03(\x0b\x32\r.query.Target\"\x1b\n\x19\x43reateTransactionResponse\"\xbb\x01\n\x12StartCommitRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x15\n\x13StartCommitResponse\"\xbb\x01\n\x12SetRollbackRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x15\n\x13SetRollbackResponse\"\xab\x01\n\x1a\x43oncludeTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"\x1d\n\x1b\x43oncludeTransactionResponse\"\xa7\x01\n\x16ReadTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"G\n\x17ReadTransactionResponse\x12,\n\x08metadata\x18\x01 \x01(\x0b\x32\x1a.query.TransactionMetadata\"\xe0\x01\n\x13\x42\x65ginExecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\"r\n\x14\x42\x65ginExecuteResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12\"\n\x06result\x18\x02 \x01(\x0b\x32\x12.query.QueryResult\x12\x16\n\x0etransaction_id\x18\x03 \x01(\x03\"\xff\x01\n\x18\x42\x65ginExecuteBatchRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\"\n\x07queries\x18\x04 \x03(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"x\n\x19\x42\x65ginExecuteBatchResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12#\n\x07results\x18\x02 \x03(\x0b\x32\x12.query.QueryResult\x12\x16\n\x0etransaction_id\x18\x03 \x01(\x03\"\xa5\x01\n\x14MessageStreamRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04name\x18\x04 \x01(\t\";\n\x15MessageStreamResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xbd\x01\n\x11MessageAckRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x19\n\x03ids\x18\x05 \x03(\x0b\x32\x0c.query.Value\"8\n\x12MessageAckResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xe7\x02\n\x11SplitQueryRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12\x14\n\x0csplit_column\x18\x05 \x03(\t\x12\x13\n\x0bsplit_count\x18\x06 \x01(\x03\x12\x1f\n\x17num_rows_per_query_part\x18\x08 \x01(\x03\x12\x35\n\talgorithm\x18\t \x01(\x0e\x32\".query.SplitQueryRequest.Algorithm\",\n\tAlgorithm\x12\x10\n\x0c\x45QUAL_SPLITS\x10\x00\x12\r\n\tFULL_SCAN\x10\x01\"A\n\nQuerySplit\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x11\n\trow_count\x18\x02 \x01(\x03\"8\n\x12SplitQueryResponse\x12\"\n\x07queries\x18\x01 \x03(\x0b\x32\x11.query.QuerySplit\"\x15\n\x13StreamHealthRequest\"\xb6\x01\n\rRealtimeStats\x12\x14\n\x0chealth_error\x18\x01 \x01(\t\x12\x1d\n\x15seconds_behind_master\x18\x02 \x01(\r\x12\x1c\n\x14\x62inlog_players_count\x18\x03 \x01(\x05\x12\x32\n*seconds_behind_master_filtered_replication\x18\x04 \x01(\x03\x12\x11\n\tcpu_usage\x18\x05 \x01(\x01\x12\x0b\n\x03qps\x18\x06 \x01(\x01\"\x94\x01\n\x0e\x41ggregateStats\x12\x1c\n\x14healthy_tablet_count\x18\x01 \x01(\x05\x12\x1e\n\x16unhealthy_tablet_count\x18\x02 \x01(\x05\x12!\n\x19seconds_behind_master_min\x18\x03 \x01(\r\x12!\n\x19seconds_behind_master_max\x18\x04 \x01(\r\"\x81\x02\n\x14StreamHealthResponse\x12\x1d\n\x06target\x18\x01 \x01(\x0b\x32\r.query.Target\x12\x0f\n\x07serving\x18\x02 \x01(\x08\x12.\n&tablet_externally_reparented_timestamp\x18\x03 \x01(\x03\x12,\n\x0erealtime_stats\x18\x04 \x01(\x0b\x32\x14.query.RealtimeStats\x12.\n\x0f\x61ggregate_stats\x18\x06 \x01(\x0b\x32\x15.query.AggregateStats\x12+\n\x0ctablet_alias\x18\x05 \x01(\x0b\x32\x15.topodata.TabletAlias\"\xbb\x01\n\x13UpdateStreamRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x10\n\x08position\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\"9\n\x14UpdateStreamResponse\x12!\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x12.query.StreamEvent\"\x86\x01\n\x13TransactionMetadata\x12\x0c\n\x04\x64tid\x18\x01 \x01(\t\x12&\n\x05state\x18\x02 \x01(\x0e\x32\x17.query.TransactionState\x12\x14\n\x0ctime_created\x18\x03 \x01(\x03\x12#\n\x0cparticipants\x18\x04 \x03(\x0b\x32\r.query.Target*\x92\x03\n\tMySqlFlag\x12\t\n\x05\x45MPTY\x10\x00\x12\x11\n\rNOT_NULL_FLAG\x10\x01\x12\x10\n\x0cPRI_KEY_FLAG\x10\x02\x12\x13\n\x0fUNIQUE_KEY_FLAG\x10\x04\x12\x15\n\x11MULTIPLE_KEY_FLAG\x10\x08\x12\r\n\tBLOB_FLAG\x10\x10\x12\x11\n\rUNSIGNED_FLAG\x10 \x12\x11\n\rZEROFILL_FLAG\x10@\x12\x10\n\x0b\x42INARY_FLAG\x10\x80\x01\x12\x0e\n\tENUM_FLAG\x10\x80\x02\x12\x18\n\x13\x41UTO_INCREMENT_FLAG\x10\x80\x04\x12\x13\n\x0eTIMESTAMP_FLAG\x10\x80\x08\x12\r\n\x08SET_FLAG\x10\x80\x10\x12\x1a\n\x15NO_DEFAULT_VALUE_FLAG\x10\x80 \x12\x17\n\x12ON_UPDATE_NOW_FLAG\x10\x80@\x12\x0e\n\x08NUM_FLAG\x10\x80\x80\x02\x12\x13\n\rPART_KEY_FLAG\x10\x80\x80\x01\x12\x10\n\nGROUP_FLAG\x10\x80\x80\x02\x12\x11\n\x0bUNIQUE_FLAG\x10\x80\x80\x04\x12\x11\n\x0b\x42INCMP_FLAG\x10\x80\x80\x08\x1a\x02\x10\x01*k\n\x04\x46lag\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\nISINTEGRAL\x10\x80\x02\x12\x0f\n\nISUNSIGNED\x10\x80\x04\x12\x0c\n\x07ISFLOAT\x10\x80\x08\x12\r\n\x08ISQUOTED\x10\x80\x10\x12\x0b\n\x06ISTEXT\x10\x80 \x12\r\n\x08ISBINARY\x10\x80@*\x99\x03\n\x04Type\x12\r\n\tNULL_TYPE\x10\x00\x12\t\n\x04INT8\x10\x81\x02\x12\n\n\x05UINT8\x10\x82\x06\x12\n\n\x05INT16\x10\x83\x02\x12\x0b\n\x06UINT16\x10\x84\x06\x12\n\n\x05INT24\x10\x85\x02\x12\x0b\n\x06UINT24\x10\x86\x06\x12\n\n\x05INT32\x10\x87\x02\x12\x0b\n\x06UINT32\x10\x88\x06\x12\n\n\x05INT64\x10\x89\x02\x12\x0b\n\x06UINT64\x10\x8a\x06\x12\x0c\n\x07\x46LOAT32\x10\x8b\x08\x12\x0c\n\x07\x46LOAT64\x10\x8c\x08\x12\x0e\n\tTIMESTAMP\x10\x8d\x10\x12\t\n\x04\x44\x41TE\x10\x8e\x10\x12\t\n\x04TIME\x10\x8f\x10\x12\r\n\x08\x44\x41TETIME\x10\x90\x10\x12\t\n\x04YEAR\x10\x91\x06\x12\x0b\n\x07\x44\x45\x43IMAL\x10\x12\x12\t\n\x04TEXT\x10\x93\x30\x12\t\n\x04\x42LOB\x10\x94P\x12\x0c\n\x07VARCHAR\x10\x95\x30\x12\x0e\n\tVARBINARY\x10\x96P\x12\t\n\x04\x43HAR\x10\x97\x30\x12\x0b\n\x06\x42INARY\x10\x98P\x12\x08\n\x03\x42IT\x10\x99\x10\x12\t\n\x04\x45NUM\x10\x9a\x10\x12\x08\n\x03SET\x10\x9b\x10\x12\t\n\x05TUPLE\x10\x1c\x12\r\n\x08GEOMETRY\x10\x9d\x10\x12\t\n\x04JSON\x10\x9e\x10\x12\x0e\n\nEXPRESSION\x10\x1f*F\n\x10TransactionState\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07PREPARE\x10\x01\x12\n\n\x06\x43OMMIT\x10\x02\x12\x0c\n\x08ROLLBACK\x10\x03\x42\x35\n\x0fio.vitess.protoZ\"vitess.io/vitess/go/vt/proto/queryb\x06proto3') + serialized_pb=_b('\n\x0bquery.proto\x12\x05query\x1a\x0etopodata.proto\x1a\x0bvtrpc.proto\"b\n\x06Target\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12\r\n\x05shard\x18\x02 \x01(\t\x12)\n\x0btablet_type\x18\x03 \x01(\x0e\x32\x14.topodata.TabletType\x12\x0c\n\x04\x63\x65ll\x18\x04 \x01(\t\"2\n\x0eVTGateCallerID\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0e\n\x06groups\x18\x02 \x03(\t\"@\n\nEventToken\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\r\n\x05shard\x18\x02 \x01(\t\x12\x10\n\x08position\x18\x03 \x01(\t\"1\n\x05Value\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\"V\n\x0c\x42indVariable\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.query.Value\"\xa2\x01\n\nBoundQuery\x12\x0b\n\x03sql\x18\x01 \x01(\t\x12<\n\x0e\x62ind_variables\x18\x02 \x03(\x0b\x32$.query.BoundQuery.BindVariablesEntry\x1aI\n\x12\x42indVariablesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.query.BindVariable:\x02\x38\x01\"\xe0\x04\n\x0e\x45xecuteOptions\x12\x1b\n\x13include_event_token\x18\x02 \x01(\x08\x12.\n\x13\x63ompare_event_token\x18\x03 \x01(\x0b\x32\x11.query.EventToken\x12=\n\x0fincluded_fields\x18\x04 \x01(\x0e\x32$.query.ExecuteOptions.IncludedFields\x12\x19\n\x11\x63lient_found_rows\x18\x05 \x01(\x08\x12\x30\n\x08workload\x18\x06 \x01(\x0e\x32\x1e.query.ExecuteOptions.Workload\x12\x18\n\x10sql_select_limit\x18\x08 \x01(\x03\x12I\n\x15transaction_isolation\x18\t \x01(\x0e\x32*.query.ExecuteOptions.TransactionIsolation\x12\x1d\n\x15skip_query_plan_cache\x18\n \x01(\x08\";\n\x0eIncludedFields\x12\x11\n\rTYPE_AND_NAME\x10\x00\x12\r\n\tTYPE_ONLY\x10\x01\x12\x07\n\x03\x41LL\x10\x02\"8\n\x08Workload\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x08\n\x04OLTP\x10\x01\x12\x08\n\x04OLAP\x10\x02\x12\x07\n\x03\x44\x42\x41\x10\x03\"t\n\x14TransactionIsolation\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x13\n\x0fREPEATABLE_READ\x10\x01\x12\x12\n\x0eREAD_COMMITTED\x10\x02\x12\x14\n\x10READ_UNCOMMITTED\x10\x03\x12\x10\n\x0cSERIALIZABLE\x10\x04J\x04\x08\x01\x10\x02\"\xbf\x01\n\x05\x46ield\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x19\n\x04type\x18\x02 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05table\x18\x03 \x01(\t\x12\x11\n\torg_table\x18\x04 \x01(\t\x12\x10\n\x08\x64\x61tabase\x18\x05 \x01(\t\x12\x10\n\x08org_name\x18\x06 \x01(\t\x12\x15\n\rcolumn_length\x18\x07 \x01(\r\x12\x0f\n\x07\x63harset\x18\x08 \x01(\r\x12\x10\n\x08\x64\x65\x63imals\x18\t \x01(\r\x12\r\n\x05\x66lags\x18\n \x01(\r\"&\n\x03Row\x12\x0f\n\x07lengths\x18\x01 \x03(\x12\x12\x0e\n\x06values\x18\x02 \x01(\x0c\"G\n\x0cResultExtras\x12&\n\x0b\x65vent_token\x18\x01 \x01(\x0b\x32\x11.query.EventToken\x12\x0f\n\x07\x66resher\x18\x02 \x01(\x08\"\x94\x01\n\x0bQueryResult\x12\x1c\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x0c.query.Field\x12\x15\n\rrows_affected\x18\x02 \x01(\x04\x12\x11\n\tinsert_id\x18\x03 \x01(\x04\x12\x18\n\x04rows\x18\x04 \x03(\x0b\x32\n.query.Row\x12#\n\x06\x65xtras\x18\x05 \x01(\x0b\x32\x13.query.ResultExtras\"-\n\x0cQueryWarning\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xca\x02\n\x0bStreamEvent\x12\x30\n\nstatements\x18\x01 \x03(\x0b\x32\x1c.query.StreamEvent.Statement\x12&\n\x0b\x65vent_token\x18\x02 \x01(\x0b\x32\x11.query.EventToken\x1a\xe0\x01\n\tStatement\x12\x37\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32%.query.StreamEvent.Statement.Category\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12(\n\x12primary_key_fields\x18\x03 \x03(\x0b\x32\x0c.query.Field\x12&\n\x12primary_key_values\x18\x04 \x03(\x0b\x32\n.query.Row\x12\x0b\n\x03sql\x18\x05 \x01(\x0c\"\'\n\x08\x43\x61tegory\x12\t\n\x05\x45rror\x10\x00\x12\x07\n\x03\x44ML\x10\x01\x12\x07\n\x03\x44\x44L\x10\x02\"\xf3\x01\n\x0e\x45xecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0etransaction_id\x18\x05 \x01(\x03\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"5\n\x0f\x45xecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"U\n\x0fResultWithError\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12\"\n\x06result\x18\x02 \x01(\x0b\x32\x12.query.QueryResult\"\x92\x02\n\x13\x45xecuteBatchRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\"\n\x07queries\x18\x04 \x03(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12\x16\n\x0etransaction_id\x18\x06 \x01(\x03\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\";\n\x14\x45xecuteBatchResponse\x12#\n\x07results\x18\x01 \x03(\x0b\x32\x12.query.QueryResult\"\xe1\x01\n\x14StreamExecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\";\n\x15StreamExecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xb7\x01\n\x0c\x42\x65ginRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12&\n\x07options\x18\x04 \x01(\x0b\x32\x15.query.ExecuteOptions\"\'\n\rBeginResponse\x12\x16\n\x0etransaction_id\x18\x01 \x01(\x03\"\xa8\x01\n\rCommitRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\"\x10\n\x0e\x43ommitResponse\"\xaa\x01\n\x0fRollbackRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\"\x12\n\x10RollbackResponse\"\xb7\x01\n\x0ePrepareRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x11\n\x0fPrepareResponse\"\xa6\x01\n\x15\x43ommitPreparedRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"\x18\n\x16\x43ommitPreparedResponse\"\xc0\x01\n\x17RollbackPreparedRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x1a\n\x18RollbackPreparedResponse\"\xce\x01\n\x18\x43reateTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\x12#\n\x0cparticipants\x18\x05 \x03(\x0b\x32\r.query.Target\"\x1b\n\x19\x43reateTransactionResponse\"\xbb\x01\n\x12StartCommitRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x15\n\x13StartCommitResponse\"\xbb\x01\n\x12SetRollbackRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x04 \x01(\x03\x12\x0c\n\x04\x64tid\x18\x05 \x01(\t\"\x15\n\x13SetRollbackResponse\"\xab\x01\n\x1a\x43oncludeTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"\x1d\n\x1b\x43oncludeTransactionResponse\"\xa7\x01\n\x16ReadTransactionRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04\x64tid\x18\x04 \x01(\t\"G\n\x17ReadTransactionResponse\x12,\n\x08metadata\x18\x01 \x01(\x0b\x32\x1a.query.TransactionMetadata\"\xe0\x01\n\x13\x42\x65ginExecuteRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\"r\n\x14\x42\x65ginExecuteResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12\"\n\x06result\x18\x02 \x01(\x0b\x32\x12.query.QueryResult\x12\x16\n\x0etransaction_id\x18\x03 \x01(\x03\"\xff\x01\n\x18\x42\x65ginExecuteBatchRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\"\n\x07queries\x18\x04 \x03(\x0b\x32\x11.query.BoundQuery\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"x\n\x19\x42\x65ginExecuteBatchResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12#\n\x07results\x18\x02 \x03(\x0b\x32\x12.query.QueryResult\x12\x16\n\x0etransaction_id\x18\x03 \x01(\x03\"\xa5\x01\n\x14MessageStreamRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04name\x18\x04 \x01(\t\";\n\x15MessageStreamResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xbd\x01\n\x11MessageAckRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x19\n\x03ids\x18\x05 \x03(\x0b\x32\x0c.query.Value\"8\n\x12MessageAckResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xe7\x02\n\x11SplitQueryRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12 \n\x05query\x18\x04 \x01(\x0b\x32\x11.query.BoundQuery\x12\x14\n\x0csplit_column\x18\x05 \x03(\t\x12\x13\n\x0bsplit_count\x18\x06 \x01(\x03\x12\x1f\n\x17num_rows_per_query_part\x18\x08 \x01(\x03\x12\x35\n\talgorithm\x18\t \x01(\x0e\x32\".query.SplitQueryRequest.Algorithm\",\n\tAlgorithm\x12\x10\n\x0c\x45QUAL_SPLITS\x10\x00\x12\r\n\tFULL_SCAN\x10\x01\"A\n\nQuerySplit\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x11\n\trow_count\x18\x02 \x01(\x03\"8\n\x12SplitQueryResponse\x12\"\n\x07queries\x18\x01 \x03(\x0b\x32\x11.query.QuerySplit\"\x15\n\x13StreamHealthRequest\"\xb6\x01\n\rRealtimeStats\x12\x14\n\x0chealth_error\x18\x01 \x01(\t\x12\x1d\n\x15seconds_behind_master\x18\x02 \x01(\r\x12\x1c\n\x14\x62inlog_players_count\x18\x03 \x01(\x05\x12\x32\n*seconds_behind_master_filtered_replication\x18\x04 \x01(\x03\x12\x11\n\tcpu_usage\x18\x05 \x01(\x01\x12\x0b\n\x03qps\x18\x06 \x01(\x01\"\x94\x01\n\x0e\x41ggregateStats\x12\x1c\n\x14healthy_tablet_count\x18\x01 \x01(\x05\x12\x1e\n\x16unhealthy_tablet_count\x18\x02 \x01(\x05\x12!\n\x19seconds_behind_master_min\x18\x03 \x01(\r\x12!\n\x19seconds_behind_master_max\x18\x04 \x01(\r\"\x81\x02\n\x14StreamHealthResponse\x12\x1d\n\x06target\x18\x01 \x01(\x0b\x32\r.query.Target\x12\x0f\n\x07serving\x18\x02 \x01(\x08\x12.\n&tablet_externally_reparented_timestamp\x18\x03 \x01(\x03\x12,\n\x0erealtime_stats\x18\x04 \x01(\x0b\x32\x14.query.RealtimeStats\x12.\n\x0f\x61ggregate_stats\x18\x06 \x01(\x0b\x32\x15.query.AggregateStats\x12+\n\x0ctablet_alias\x18\x05 \x01(\x0b\x32\x15.topodata.TabletAlias\"\xbb\x01\n\x13UpdateStreamRequest\x12,\n\x13\x65\x66\x66\x65\x63tive_caller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x32\n\x13immediate_caller_id\x18\x02 \x01(\x0b\x32\x15.query.VTGateCallerID\x12\x1d\n\x06target\x18\x03 \x01(\x0b\x32\r.query.Target\x12\x10\n\x08position\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\"9\n\x14UpdateStreamResponse\x12!\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x12.query.StreamEvent\"\x86\x01\n\x13TransactionMetadata\x12\x0c\n\x04\x64tid\x18\x01 \x01(\t\x12&\n\x05state\x18\x02 \x01(\x0e\x32\x17.query.TransactionState\x12\x14\n\x0ctime_created\x18\x03 \x01(\x03\x12#\n\x0cparticipants\x18\x04 \x03(\x0b\x32\r.query.Target*\x92\x03\n\tMySqlFlag\x12\t\n\x05\x45MPTY\x10\x00\x12\x11\n\rNOT_NULL_FLAG\x10\x01\x12\x10\n\x0cPRI_KEY_FLAG\x10\x02\x12\x13\n\x0fUNIQUE_KEY_FLAG\x10\x04\x12\x15\n\x11MULTIPLE_KEY_FLAG\x10\x08\x12\r\n\tBLOB_FLAG\x10\x10\x12\x11\n\rUNSIGNED_FLAG\x10 \x12\x11\n\rZEROFILL_FLAG\x10@\x12\x10\n\x0b\x42INARY_FLAG\x10\x80\x01\x12\x0e\n\tENUM_FLAG\x10\x80\x02\x12\x18\n\x13\x41UTO_INCREMENT_FLAG\x10\x80\x04\x12\x13\n\x0eTIMESTAMP_FLAG\x10\x80\x08\x12\r\n\x08SET_FLAG\x10\x80\x10\x12\x1a\n\x15NO_DEFAULT_VALUE_FLAG\x10\x80 \x12\x17\n\x12ON_UPDATE_NOW_FLAG\x10\x80@\x12\x0e\n\x08NUM_FLAG\x10\x80\x80\x02\x12\x13\n\rPART_KEY_FLAG\x10\x80\x80\x01\x12\x10\n\nGROUP_FLAG\x10\x80\x80\x02\x12\x11\n\x0bUNIQUE_FLAG\x10\x80\x80\x04\x12\x11\n\x0b\x42INCMP_FLAG\x10\x80\x80\x08\x1a\x02\x10\x01*k\n\x04\x46lag\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\nISINTEGRAL\x10\x80\x02\x12\x0f\n\nISUNSIGNED\x10\x80\x04\x12\x0c\n\x07ISFLOAT\x10\x80\x08\x12\r\n\x08ISQUOTED\x10\x80\x10\x12\x0b\n\x06ISTEXT\x10\x80 \x12\r\n\x08ISBINARY\x10\x80@*\x99\x03\n\x04Type\x12\r\n\tNULL_TYPE\x10\x00\x12\t\n\x04INT8\x10\x81\x02\x12\n\n\x05UINT8\x10\x82\x06\x12\n\n\x05INT16\x10\x83\x02\x12\x0b\n\x06UINT16\x10\x84\x06\x12\n\n\x05INT24\x10\x85\x02\x12\x0b\n\x06UINT24\x10\x86\x06\x12\n\n\x05INT32\x10\x87\x02\x12\x0b\n\x06UINT32\x10\x88\x06\x12\n\n\x05INT64\x10\x89\x02\x12\x0b\n\x06UINT64\x10\x8a\x06\x12\x0c\n\x07\x46LOAT32\x10\x8b\x08\x12\x0c\n\x07\x46LOAT64\x10\x8c\x08\x12\x0e\n\tTIMESTAMP\x10\x8d\x10\x12\t\n\x04\x44\x41TE\x10\x8e\x10\x12\t\n\x04TIME\x10\x8f\x10\x12\r\n\x08\x44\x41TETIME\x10\x90\x10\x12\t\n\x04YEAR\x10\x91\x06\x12\x0b\n\x07\x44\x45\x43IMAL\x10\x12\x12\t\n\x04TEXT\x10\x93\x30\x12\t\n\x04\x42LOB\x10\x94P\x12\x0c\n\x07VARCHAR\x10\x95\x30\x12\x0e\n\tVARBINARY\x10\x96P\x12\t\n\x04\x43HAR\x10\x97\x30\x12\x0b\n\x06\x42INARY\x10\x98P\x12\x08\n\x03\x42IT\x10\x99\x10\x12\t\n\x04\x45NUM\x10\x9a\x10\x12\x08\n\x03SET\x10\x9b\x10\x12\t\n\x05TUPLE\x10\x1c\x12\r\n\x08GEOMETRY\x10\x9d\x10\x12\t\n\x04JSON\x10\x9e\x10\x12\x0e\n\nEXPRESSION\x10\x1f*F\n\x10TransactionState\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07PREPARE\x10\x01\x12\n\n\x06\x43OMMIT\x10\x02\x12\x0c\n\x08ROLLBACK\x10\x03\x42\x35\n\x0fio.vitess.protoZ\"vitess.io/vitess/go/vt/proto/queryb\x06proto3') , dependencies=[topodata__pb2.DESCRIPTOR,vtrpc__pb2.DESCRIPTOR,]) @@ -115,8 +115,8 @@ ], containing_type=None, options=_descriptor._ParseOptions(descriptor_pb2.EnumOptions(), _b('\020\001')), - serialized_start=8029, - serialized_end=8431, + serialized_start=8076, + serialized_end=8478, ) _sym_db.RegisterEnumDescriptor(_MYSQLFLAG) @@ -158,8 +158,8 @@ ], containing_type=None, options=None, - serialized_start=8433, - serialized_end=8540, + serialized_start=8480, + serialized_end=8587, ) _sym_db.RegisterEnumDescriptor(_FLAG) @@ -301,8 +301,8 @@ ], containing_type=None, options=None, - serialized_start=8543, - serialized_end=8952, + serialized_start=8590, + serialized_end=8999, ) _sym_db.RegisterEnumDescriptor(_TYPE) @@ -332,8 +332,8 @@ ], containing_type=None, options=None, - serialized_start=8954, - serialized_end=9024, + serialized_start=9001, + serialized_end=9071, ) _sym_db.RegisterEnumDescriptor(_TRANSACTIONSTATE) @@ -514,8 +514,8 @@ ], containing_type=None, options=None, - serialized_start=1934, - serialized_end=1973, + serialized_start=1981, + serialized_end=2020, ) _sym_db.RegisterEnumDescriptor(_STREAMEVENT_STATEMENT_CATEGORY) @@ -536,8 +536,8 @@ ], containing_type=None, options=None, - serialized_start=6852, - serialized_end=6896, + serialized_start=6899, + serialized_end=6943, ) _sym_db.RegisterEnumDescriptor(_SPLITQUERYREQUEST_ALGORITHM) @@ -1147,6 +1147,44 @@ ) +_QUERYWARNING = _descriptor.Descriptor( + name='QueryWarning', + full_name='query.QueryWarning', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='code', full_name='query.QueryWarning.code', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='query.QueryWarning.message', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1642, + serialized_end=1687, +) + + _STREAMEVENT_STATEMENT = _descriptor.Descriptor( name='Statement', full_name='query.StreamEvent.Statement', @@ -1202,8 +1240,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1749, - serialized_end=1973, + serialized_start=1796, + serialized_end=2020, ) _STREAMEVENT = _descriptor.Descriptor( @@ -1239,8 +1277,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1643, - serialized_end=1973, + serialized_start=1690, + serialized_end=2020, ) @@ -1305,8 +1343,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1976, - serialized_end=2219, + serialized_start=2023, + serialized_end=2266, ) @@ -1336,8 +1374,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2221, - serialized_end=2274, + serialized_start=2268, + serialized_end=2321, ) @@ -1374,8 +1412,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2276, - serialized_end=2361, + serialized_start=2323, + serialized_end=2408, ) @@ -1447,8 +1485,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2364, - serialized_end=2638, + serialized_start=2411, + serialized_end=2685, ) @@ -1478,8 +1516,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2640, - serialized_end=2699, + serialized_start=2687, + serialized_end=2746, ) @@ -1537,8 +1575,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2702, - serialized_end=2927, + serialized_start=2749, + serialized_end=2974, ) @@ -1568,8 +1606,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2929, - serialized_end=2988, + serialized_start=2976, + serialized_end=3035, ) @@ -1620,8 +1658,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2991, - serialized_end=3174, + serialized_start=3038, + serialized_end=3221, ) @@ -1651,8 +1689,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3176, - serialized_end=3215, + serialized_start=3223, + serialized_end=3262, ) @@ -1703,8 +1741,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3218, - serialized_end=3386, + serialized_start=3265, + serialized_end=3433, ) @@ -1727,8 +1765,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3388, - serialized_end=3404, + serialized_start=3435, + serialized_end=3451, ) @@ -1779,8 +1817,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3407, - serialized_end=3577, + serialized_start=3454, + serialized_end=3624, ) @@ -1803,8 +1841,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3579, - serialized_end=3597, + serialized_start=3626, + serialized_end=3644, ) @@ -1862,8 +1900,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3600, - serialized_end=3783, + serialized_start=3647, + serialized_end=3830, ) @@ -1886,8 +1924,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3785, - serialized_end=3802, + serialized_start=3832, + serialized_end=3849, ) @@ -1938,8 +1976,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3805, - serialized_end=3971, + serialized_start=3852, + serialized_end=4018, ) @@ -1962,8 +2000,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3973, - serialized_end=3997, + serialized_start=4020, + serialized_end=4044, ) @@ -2021,8 +2059,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4000, - serialized_end=4192, + serialized_start=4047, + serialized_end=4239, ) @@ -2045,8 +2083,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4194, - serialized_end=4220, + serialized_start=4241, + serialized_end=4267, ) @@ -2104,8 +2142,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4223, - serialized_end=4429, + serialized_start=4270, + serialized_end=4476, ) @@ -2128,8 +2166,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4431, - serialized_end=4458, + serialized_start=4478, + serialized_end=4505, ) @@ -2187,8 +2225,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4461, - serialized_end=4648, + serialized_start=4508, + serialized_end=4695, ) @@ -2211,8 +2249,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4650, - serialized_end=4671, + serialized_start=4697, + serialized_end=4718, ) @@ -2270,8 +2308,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4674, - serialized_end=4861, + serialized_start=4721, + serialized_end=4908, ) @@ -2294,8 +2332,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4863, - serialized_end=4884, + serialized_start=4910, + serialized_end=4931, ) @@ -2346,8 +2384,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4887, - serialized_end=5058, + serialized_start=4934, + serialized_end=5105, ) @@ -2370,8 +2408,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5060, - serialized_end=5089, + serialized_start=5107, + serialized_end=5136, ) @@ -2422,8 +2460,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5092, - serialized_end=5259, + serialized_start=5139, + serialized_end=5306, ) @@ -2453,8 +2491,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5261, - serialized_end=5332, + serialized_start=5308, + serialized_end=5379, ) @@ -2512,8 +2550,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5335, - serialized_end=5559, + serialized_start=5382, + serialized_end=5606, ) @@ -2557,8 +2595,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5561, - serialized_end=5675, + serialized_start=5608, + serialized_end=5722, ) @@ -2623,8 +2661,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5678, - serialized_end=5933, + serialized_start=5725, + serialized_end=5980, ) @@ -2668,8 +2706,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5935, - serialized_end=6055, + serialized_start=5982, + serialized_end=6102, ) @@ -2720,8 +2758,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6058, - serialized_end=6223, + serialized_start=6105, + serialized_end=6270, ) @@ -2751,8 +2789,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6225, - serialized_end=6284, + serialized_start=6272, + serialized_end=6331, ) @@ -2810,8 +2848,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6287, - serialized_end=6476, + serialized_start=6334, + serialized_end=6523, ) @@ -2841,8 +2879,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6478, - serialized_end=6534, + serialized_start=6525, + serialized_end=6581, ) @@ -2922,8 +2960,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6537, - serialized_end=6896, + serialized_start=6584, + serialized_end=6943, ) @@ -2960,8 +2998,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6898, - serialized_end=6963, + serialized_start=6945, + serialized_end=7010, ) @@ -2991,8 +3029,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6965, - serialized_end=7021, + serialized_start=7012, + serialized_end=7068, ) @@ -3015,8 +3053,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7023, - serialized_end=7044, + serialized_start=7070, + serialized_end=7091, ) @@ -3081,8 +3119,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7047, - serialized_end=7229, + serialized_start=7094, + serialized_end=7276, ) @@ -3133,8 +3171,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7232, - serialized_end=7380, + serialized_start=7279, + serialized_end=7427, ) @@ -3199,8 +3237,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7383, - serialized_end=7640, + serialized_start=7430, + serialized_end=7687, ) @@ -3258,8 +3296,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7643, - serialized_end=7830, + serialized_start=7690, + serialized_end=7877, ) @@ -3289,8 +3327,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7832, - serialized_end=7889, + serialized_start=7879, + serialized_end=7936, ) @@ -3341,8 +3379,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7892, - serialized_end=8026, + serialized_start=7939, + serialized_end=8073, ) _TARGET.fields_by_name['tablet_type'].enum_type = topodata__pb2._TABLETTYPE @@ -3479,6 +3517,7 @@ DESCRIPTOR.message_types_by_name['Row'] = _ROW DESCRIPTOR.message_types_by_name['ResultExtras'] = _RESULTEXTRAS DESCRIPTOR.message_types_by_name['QueryResult'] = _QUERYRESULT +DESCRIPTOR.message_types_by_name['QueryWarning'] = _QUERYWARNING DESCRIPTOR.message_types_by_name['StreamEvent'] = _STREAMEVENT DESCRIPTOR.message_types_by_name['ExecuteRequest'] = _EXECUTEREQUEST DESCRIPTOR.message_types_by_name['ExecuteResponse'] = _EXECUTERESPONSE @@ -3618,6 +3657,13 @@ )) _sym_db.RegisterMessage(QueryResult) +QueryWarning = _reflection.GeneratedProtocolMessageType('QueryWarning', (_message.Message,), dict( + DESCRIPTOR = _QUERYWARNING, + __module__ = 'query_pb2' + # @@protoc_insertion_point(class_scope:query.QueryWarning) + )) +_sym_db.RegisterMessage(QueryWarning) + StreamEvent = _reflection.GeneratedProtocolMessageType('StreamEvent', (_message.Message,), dict( Statement = _reflection.GeneratedProtocolMessageType('Statement', (_message.Message,), dict( diff --git a/py/vtproto/topodata_pb2.py b/py/vtproto/topodata_pb2.py index 019f81a5683..e74204fad56 100644 --- a/py/vtproto/topodata_pb2.py +++ b/py/vtproto/topodata_pb2.py @@ -20,7 +20,7 @@ name='topodata.proto', package='topodata', syntax='proto3', - serialized_pb=_b('\n\x0etopodata.proto\x12\x08topodata\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xb6\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x16\n\x0emysql_hostname\x18\x0c \x01(\t\x12\x12\n\nmysql_port\x18\r \x01(\x05\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x0b\x10\x0c\"\xcb\x04\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\r\n\x05\x63\x65lls\x18\x05 \x03(\t\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a\x84\x01\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1d\n\x15\x64isable_query_service\x18\x03 \x01(\x08\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\"\xf5\x01\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\tJ\x04\x08\x03\x10\x04\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"\x9c\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x1ar\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\tJ\x04\x08\x05\x10\x06\"@\n\x08\x43\x65llInfo\x12\x16\n\x0eserver_address\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\x90\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06MASTER\x10\x01\x12\x0b\n\x07REPLICA\x10\x02\x12\n\n\x06RDONLY\x10\x03\x12\t\n\x05\x42\x41TCH\x10\x03\x12\t\n\x05SPARE\x10\x04\x12\x10\n\x0c\x45XPERIMENTAL\x10\x05\x12\n\n\x06\x42\x41\x43KUP\x10\x06\x12\x0b\n\x07RESTORE\x10\x07\x12\x0b\n\x07\x44RAINED\x10\x08\x1a\x02\x10\x01\x42\x38\n\x0fio.vitess.protoZ%vitess.io/vitess/go/vt/proto/topodatab\x06proto3') + serialized_pb=_b('\n\x0etopodata.proto\x12\x08topodata\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xb6\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x16\n\x0emysql_hostname\x18\x0c \x01(\t\x12\x12\n\nmysql_port\x18\r \x01(\x05\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x0b\x10\x0c\"\xdb\x04\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\r\n\x05\x63\x65lls\x18\x05 \x03(\t\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a\x94\x01\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1d\n\x15\x64isable_query_service\x18\x03 \x01(\x08\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\x12\x0e\n\x06\x66rozen\x18\x05 \x01(\x08\"\xf5\x01\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\tJ\x04\x08\x03\x10\x04\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"\x9c\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x1ar\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\tJ\x04\x08\x05\x10\x06\"@\n\x08\x43\x65llInfo\x12\x16\n\x0eserver_address\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\x90\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06MASTER\x10\x01\x12\x0b\n\x07REPLICA\x10\x02\x12\n\n\x06RDONLY\x10\x03\x12\t\n\x05\x42\x41TCH\x10\x03\x12\t\n\x05SPARE\x10\x04\x12\x10\n\x0c\x45XPERIMENTAL\x10\x05\x12\n\n\x06\x42\x41\x43KUP\x10\x06\x12\x0b\n\x07RESTORE\x10\x07\x12\x0b\n\x07\x44RAINED\x10\x08\x1a\x02\x10\x01\x42\x38\n\x0fio.vitess.protoZ%vitess.io/vitess/go/vt/proto/topodatab\x06proto3') ) _KEYSPACEIDTYPE = _descriptor.EnumDescriptor( @@ -44,8 +44,8 @@ ], containing_type=None, options=None, - serialized_start=2062, - serialized_end=2112, + serialized_start=2078, + serialized_end=2128, ) _sym_db.RegisterEnumDescriptor(_KEYSPACEIDTYPE) @@ -99,8 +99,8 @@ ], containing_type=None, options=_descriptor._ParseOptions(descriptor_pb2.EnumOptions(), _b('\020\001')), - serialized_start=2115, - serialized_end=2259, + serialized_start=2131, + serialized_end=2275, ) _sym_db.RegisterEnumDescriptor(_TABLETTYPE) @@ -502,6 +502,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='frozen', full_name='topodata.Shard.TabletControl.frozen', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -515,7 +522,7 @@ oneofs=[ ], serialized_start=1007, - serialized_end=1139, + serialized_end=1155, ) _SHARD = _descriptor.Descriptor( @@ -580,7 +587,7 @@ oneofs=[ ], serialized_start=552, - serialized_end=1139, + serialized_end=1155, ) @@ -624,8 +631,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1293, - serialized_end=1381, + serialized_start=1309, + serialized_end=1397, ) _KEYSPACE = _descriptor.Descriptor( @@ -668,8 +675,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1142, - serialized_end=1387, + serialized_start=1158, + serialized_end=1403, ) @@ -699,8 +706,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1457, - serialized_end=1508, + serialized_start=1473, + serialized_end=1524, ) _SHARDREPLICATION = _descriptor.Descriptor( @@ -729,8 +736,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1389, - serialized_end=1508, + serialized_start=1405, + serialized_end=1524, ) @@ -767,8 +774,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1510, - serialized_end=1579, + serialized_start=1526, + serialized_end=1595, ) @@ -805,8 +812,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1799, - serialized_end=1913, + serialized_start=1815, + serialized_end=1929, ) _SRVKEYSPACE_SERVEDFROM = _descriptor.Descriptor( @@ -842,8 +849,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1915, - serialized_end=1988, + serialized_start=1931, + serialized_end=2004, ) _SRVKEYSPACE = _descriptor.Descriptor( @@ -893,8 +900,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1582, - serialized_end=1994, + serialized_start=1598, + serialized_end=2010, ) @@ -938,8 +945,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1996, - serialized_end=2060, + serialized_start=2012, + serialized_end=2076, ) _TABLET_PORTMAPENTRY.containing_type = _TABLET diff --git a/py/vtproto/vtgate_pb2.py b/py/vtproto/vtgate_pb2.py index 1bac1d2f560..aeba2d1fb31 100644 --- a/py/vtproto/vtgate_pb2.py +++ b/py/vtproto/vtgate_pb2.py @@ -23,7 +23,7 @@ name='vtgate.proto', package='vtgate', syntax='proto3', - serialized_pb=_b('\n\x0cvtgate.proto\x12\x06vtgate\x1a\x0bquery.proto\x1a\x0etopodata.proto\x1a\x0bvtrpc.proto\"\xb7\x02\n\x07Session\x12\x16\n\x0ein_transaction\x18\x01 \x01(\x08\x12\x34\n\x0eshard_sessions\x18\x02 \x03(\x0b\x32\x1c.vtgate.Session.ShardSession\x12\x11\n\tsingle_db\x18\x03 \x01(\x08\x12\x12\n\nautocommit\x18\x04 \x01(\x08\x12\x15\n\rtarget_string\x18\x05 \x01(\t\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\x12\x31\n\x10transaction_mode\x18\x07 \x01(\x0e\x32\x17.vtgate.TransactionMode\x1a\x45\n\x0cShardSession\x12\x1d\n\x06target\x18\x01 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x02 \x01(\x03\"\xff\x01\n\x0e\x45xecuteRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x05 \x01(\x08\x12\x16\n\x0ekeyspace_shard\x18\x06 \x01(\t\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\"w\n\x0f\x45xecuteResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x8f\x02\n\x14\x45xecuteShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x0e\n\x06shards\x18\x05 \x03(\t\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"}\n\x15\x45xecuteShardsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x9a\x02\n\x19\x45xecuteKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x05 \x03(\x0c\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x82\x01\n\x1a\x45xecuteKeyspaceIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\xaa\x02\n\x17\x45xecuteKeyRangesRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12&\n\nkey_ranges\x18\x05 \x03(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x80\x01\n\x18\x45xecuteKeyRangesResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\xb0\x03\n\x17\x45xecuteEntityIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x1a\n\x12\x65ntity_column_name\x18\x05 \x01(\t\x12\x45\n\x13\x65ntity_keyspace_ids\x18\x06 \x03(\x0b\x32(.vtgate.ExecuteEntityIdsRequest.EntityId\x12)\n\x0btablet_type\x18\x07 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x08 \x01(\x08\x12&\n\x07options\x18\t \x01(\x0b\x32\x15.query.ExecuteOptions\x1aI\n\x08\x45ntityId\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x13\n\x0bkeyspace_id\x18\x03 \x01(\x0c\"\x80\x01\n\x18\x45xecuteEntityIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x82\x02\n\x13\x45xecuteBatchRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x07queries\x18\x03 \x03(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12\x16\n\x0ekeyspace_shard\x18\x06 \x01(\t\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x81\x01\n\x14\x45xecuteBatchResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\'\n\x07results\x18\x03 \x03(\x0b\x32\x16.query.ResultWithError\"U\n\x0f\x42oundShardQuery\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0e\n\x06shards\x18\x03 \x03(\t\"\xf6\x01\n\x19\x45xecuteBatchShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12(\n\x07queries\x18\x03 \x03(\x0b\x32\x17.vtgate.BoundShardQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x83\x01\n\x1a\x45xecuteBatchShardsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12#\n\x07results\x18\x03 \x03(\x0b\x32\x12.query.QueryResult\"`\n\x14\x42oundKeyspaceIdQuery\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x03 \x03(\x0c\"\x80\x02\n\x1e\x45xecuteBatchKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12-\n\x07queries\x18\x03 \x03(\x0b\x32\x1c.vtgate.BoundKeyspaceIdQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x88\x01\n\x1f\x45xecuteBatchKeyspaceIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12#\n\x07results\x18\x03 \x03(\x0b\x32\x12.query.QueryResult\"\xe9\x01\n\x14StreamExecuteRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x03 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0ekeyspace_shard\x18\x04 \x01(\t\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\x12 \n\x07session\x18\x06 \x01(\x0b\x32\x0f.vtgate.Session\";\n\x15StreamExecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xd7\x01\n\x1aStreamExecuteShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12\x0e\n\x06shards\x18\x04 \x03(\t\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"A\n\x1bStreamExecuteShardsResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xe2\x01\n\x1fStreamExecuteKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x04 \x03(\x0c\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"F\n StreamExecuteKeyspaceIdsResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xf2\x01\n\x1dStreamExecuteKeyRangesRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12&\n\nkey_ranges\x18\x04 \x03(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"D\n\x1eStreamExecuteKeyRangesResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"E\n\x0c\x42\x65ginRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x11\n\tsingle_db\x18\x02 \x01(\x08\"1\n\rBeginResponse\x12 \n\x07session\x18\x01 \x01(\x0b\x32\x0f.vtgate.Session\"e\n\rCommitRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\x0e\n\x06\x61tomic\x18\x03 \x01(\x08\"\x10\n\x0e\x43ommitResponse\"W\n\x0fRollbackRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\"\x12\n\x10RollbackResponse\"M\n\x19ResolveTransactionRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x0c\n\x04\x64tid\x18\x02 \x01(\t\"\x90\x01\n\x14MessageStreamRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0c\n\x04name\x18\x05 \x01(\t\"r\n\x11MessageAckRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x19\n\x03ids\x18\x04 \x03(\x0b\x32\x0c.query.Value\"=\n\x0cIdKeyspaceId\x12\x18\n\x02id\x18\x01 \x01(\x0b\x32\x0c.query.Value\x12\x13\n\x0bkeyspace_id\x18\x02 \x01(\x0c\"\x91\x01\n\x1cMessageAckKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12-\n\x0fid_keyspace_ids\x18\x04 \x03(\x0b\x32\x14.vtgate.IdKeyspaceId\"\x1c\n\x1aResolveTransactionResponse\"\x8a\x02\n\x11SplitQueryRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x14\n\x0csplit_column\x18\x04 \x03(\t\x12\x13\n\x0bsplit_count\x18\x05 \x01(\x03\x12\x1f\n\x17num_rows_per_query_part\x18\x06 \x01(\x03\x12\x35\n\talgorithm\x18\x07 \x01(\x0e\x32\".query.SplitQueryRequest.Algorithm\x12\x1a\n\x12use_split_query_v2\x18\x08 \x01(\x08\"\xf2\x02\n\x12SplitQueryResponse\x12/\n\x06splits\x18\x01 \x03(\x0b\x32\x1f.vtgate.SplitQueryResponse.Part\x1aH\n\x0cKeyRangePart\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12&\n\nkey_ranges\x18\x02 \x03(\x0b\x32\x12.topodata.KeyRange\x1a-\n\tShardPart\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12\x0e\n\x06shards\x18\x02 \x03(\t\x1a\xb1\x01\n\x04Part\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12?\n\x0ekey_range_part\x18\x02 \x01(\x0b\x32\'.vtgate.SplitQueryResponse.KeyRangePart\x12\x38\n\nshard_part\x18\x03 \x01(\x0b\x32$.vtgate.SplitQueryResponse.ShardPart\x12\x0c\n\x04size\x18\x04 \x01(\x03\")\n\x15GetSrvKeyspaceRequest\x12\x10\n\x08keyspace\x18\x01 \x01(\t\"E\n\x16GetSrvKeyspaceResponse\x12+\n\x0csrv_keyspace\x18\x01 \x01(\x0b\x32\x15.topodata.SrvKeyspace\"\xe1\x01\n\x13UpdateStreamRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12\x11\n\ttimestamp\x18\x06 \x01(\x03\x12 \n\x05\x65vent\x18\x07 \x01(\x0b\x32\x11.query.EventToken\"S\n\x14UpdateStreamResponse\x12!\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x12.query.StreamEvent\x12\x18\n\x10resume_timestamp\x18\x02 \x01(\x03*D\n\x0fTransactionMode\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\n\n\x06SINGLE\x10\x01\x12\t\n\x05MULTI\x10\x02\x12\t\n\x05TWOPC\x10\x03\x42\x36\n\x0fio.vitess.protoZ#vitess.io/vitess/go/vt/proto/vtgateb\x06proto3') + serialized_pb=_b('\n\x0cvtgate.proto\x12\x06vtgate\x1a\x0bquery.proto\x1a\x0etopodata.proto\x1a\x0bvtrpc.proto\"\xde\x02\n\x07Session\x12\x16\n\x0ein_transaction\x18\x01 \x01(\x08\x12\x34\n\x0eshard_sessions\x18\x02 \x03(\x0b\x32\x1c.vtgate.Session.ShardSession\x12\x11\n\tsingle_db\x18\x03 \x01(\x08\x12\x12\n\nautocommit\x18\x04 \x01(\x08\x12\x15\n\rtarget_string\x18\x05 \x01(\t\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\x12\x31\n\x10transaction_mode\x18\x07 \x01(\x0e\x32\x17.vtgate.TransactionMode\x12%\n\x08warnings\x18\x08 \x03(\x0b\x32\x13.query.QueryWarning\x1a\x45\n\x0cShardSession\x12\x1d\n\x06target\x18\x01 \x01(\x0b\x32\r.query.Target\x12\x16\n\x0etransaction_id\x18\x02 \x01(\x03\"\xff\x01\n\x0e\x45xecuteRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x05 \x01(\x08\x12\x16\n\x0ekeyspace_shard\x18\x06 \x01(\t\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\"w\n\x0f\x45xecuteResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x8f\x02\n\x14\x45xecuteShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x0e\n\x06shards\x18\x05 \x03(\t\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"}\n\x15\x45xecuteShardsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x9a\x02\n\x19\x45xecuteKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x05 \x03(\x0c\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x82\x01\n\x1a\x45xecuteKeyspaceIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\xaa\x02\n\x17\x45xecuteKeyRangesRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12&\n\nkey_ranges\x18\x05 \x03(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x06 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x07 \x01(\x08\x12&\n\x07options\x18\x08 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x80\x01\n\x18\x45xecuteKeyRangesResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\xb0\x03\n\x17\x45xecuteEntityIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x04 \x01(\t\x12\x1a\n\x12\x65ntity_column_name\x18\x05 \x01(\t\x12\x45\n\x13\x65ntity_keyspace_ids\x18\x06 \x03(\x0b\x32(.vtgate.ExecuteEntityIdsRequest.EntityId\x12)\n\x0btablet_type\x18\x07 \x01(\x0e\x32\x14.topodata.TabletType\x12\x1a\n\x12not_in_transaction\x18\x08 \x01(\x08\x12&\n\x07options\x18\t \x01(\x0b\x32\x15.query.ExecuteOptions\x1aI\n\x08\x45ntityId\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.query.Type\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x13\n\x0bkeyspace_id\x18\x03 \x01(\x0c\"\x80\x01\n\x18\x45xecuteEntityIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x06result\x18\x03 \x01(\x0b\x32\x12.query.QueryResult\"\x82\x02\n\x13\x45xecuteBatchRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\"\n\x07queries\x18\x03 \x03(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12\x16\n\x0ekeyspace_shard\x18\x06 \x01(\t\x12&\n\x07options\x18\x07 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x81\x01\n\x14\x45xecuteBatchResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\'\n\x07results\x18\x03 \x03(\x0b\x32\x16.query.ResultWithError\"U\n\x0f\x42oundShardQuery\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0e\n\x06shards\x18\x03 \x03(\t\"\xf6\x01\n\x19\x45xecuteBatchShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12(\n\x07queries\x18\x03 \x03(\x0b\x32\x17.vtgate.BoundShardQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x83\x01\n\x1a\x45xecuteBatchShardsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12#\n\x07results\x18\x03 \x03(\x0b\x32\x12.query.QueryResult\"`\n\x14\x42oundKeyspaceIdQuery\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x03 \x03(\x0c\"\x80\x02\n\x1e\x45xecuteBatchKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12-\n\x07queries\x18\x03 \x03(\x0b\x32\x1c.vtgate.BoundKeyspaceIdQuery\x12)\n\x0btablet_type\x18\x04 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0e\x61s_transaction\x18\x05 \x01(\x08\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"\x88\x01\n\x1f\x45xecuteBatchKeyspaceIdsResponse\x12\x1e\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x0f.vtrpc.RPCError\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12#\n\x07results\x18\x03 \x03(\x0b\x32\x12.query.QueryResult\"\xe9\x01\n\x14StreamExecuteRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12)\n\x0btablet_type\x18\x03 \x01(\x0e\x32\x14.topodata.TabletType\x12\x16\n\x0ekeyspace_shard\x18\x04 \x01(\t\x12&\n\x07options\x18\x05 \x01(\x0b\x32\x15.query.ExecuteOptions\x12 \n\x07session\x18\x06 \x01(\x0b\x32\x0f.vtgate.Session\";\n\x15StreamExecuteResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xd7\x01\n\x1aStreamExecuteShardsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12\x0e\n\x06shards\x18\x04 \x03(\t\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"A\n\x1bStreamExecuteShardsResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xe2\x01\n\x1fStreamExecuteKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12\x14\n\x0ckeyspace_ids\x18\x04 \x03(\x0c\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"F\n StreamExecuteKeyspaceIdsResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"\xf2\x01\n\x1dStreamExecuteKeyRangesRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x05query\x18\x02 \x01(\x0b\x32\x11.query.BoundQuery\x12\x10\n\x08keyspace\x18\x03 \x01(\t\x12&\n\nkey_ranges\x18\x04 \x03(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12&\n\x07options\x18\x06 \x01(\x0b\x32\x15.query.ExecuteOptions\"D\n\x1eStreamExecuteKeyRangesResponse\x12\"\n\x06result\x18\x01 \x01(\x0b\x32\x12.query.QueryResult\"E\n\x0c\x42\x65ginRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x11\n\tsingle_db\x18\x02 \x01(\x08\"1\n\rBeginResponse\x12 \n\x07session\x18\x01 \x01(\x0b\x32\x0f.vtgate.Session\"e\n\rCommitRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\x12\x0e\n\x06\x61tomic\x18\x03 \x01(\x08\"\x10\n\x0e\x43ommitResponse\"W\n\x0fRollbackRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12 \n\x07session\x18\x02 \x01(\x0b\x32\x0f.vtgate.Session\"\x12\n\x10RollbackResponse\"M\n\x19ResolveTransactionRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x0c\n\x04\x64tid\x18\x02 \x01(\t\"\x90\x01\n\x14MessageStreamRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0c\n\x04name\x18\x05 \x01(\t\"r\n\x11MessageAckRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x19\n\x03ids\x18\x04 \x03(\x0b\x32\x0c.query.Value\"=\n\x0cIdKeyspaceId\x12\x18\n\x02id\x18\x01 \x01(\x0b\x32\x0c.query.Value\x12\x13\n\x0bkeyspace_id\x18\x02 \x01(\x0c\"\x91\x01\n\x1cMessageAckKeyspaceIdsRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12-\n\x0fid_keyspace_ids\x18\x04 \x03(\x0b\x32\x14.vtgate.IdKeyspaceId\"\x1c\n\x1aResolveTransactionResponse\"\x8a\x02\n\x11SplitQueryRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12 \n\x05query\x18\x03 \x01(\x0b\x32\x11.query.BoundQuery\x12\x14\n\x0csplit_column\x18\x04 \x03(\t\x12\x13\n\x0bsplit_count\x18\x05 \x01(\x03\x12\x1f\n\x17num_rows_per_query_part\x18\x06 \x01(\x03\x12\x35\n\talgorithm\x18\x07 \x01(\x0e\x32\".query.SplitQueryRequest.Algorithm\x12\x1a\n\x12use_split_query_v2\x18\x08 \x01(\x08\"\xf2\x02\n\x12SplitQueryResponse\x12/\n\x06splits\x18\x01 \x03(\x0b\x32\x1f.vtgate.SplitQueryResponse.Part\x1aH\n\x0cKeyRangePart\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12&\n\nkey_ranges\x18\x02 \x03(\x0b\x32\x12.topodata.KeyRange\x1a-\n\tShardPart\x12\x10\n\x08keyspace\x18\x01 \x01(\t\x12\x0e\n\x06shards\x18\x02 \x03(\t\x1a\xb1\x01\n\x04Part\x12 \n\x05query\x18\x01 \x01(\x0b\x32\x11.query.BoundQuery\x12?\n\x0ekey_range_part\x18\x02 \x01(\x0b\x32\'.vtgate.SplitQueryResponse.KeyRangePart\x12\x38\n\nshard_part\x18\x03 \x01(\x0b\x32$.vtgate.SplitQueryResponse.ShardPart\x12\x0c\n\x04size\x18\x04 \x01(\x03\")\n\x15GetSrvKeyspaceRequest\x12\x10\n\x08keyspace\x18\x01 \x01(\t\"E\n\x16GetSrvKeyspaceResponse\x12+\n\x0csrv_keyspace\x18\x01 \x01(\x0b\x32\x15.topodata.SrvKeyspace\"\xe1\x01\n\x13UpdateStreamRequest\x12\"\n\tcaller_id\x18\x01 \x01(\x0b\x32\x0f.vtrpc.CallerID\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12)\n\x0btablet_type\x18\x05 \x01(\x0e\x32\x14.topodata.TabletType\x12\x11\n\ttimestamp\x18\x06 \x01(\x03\x12 \n\x05\x65vent\x18\x07 \x01(\x0b\x32\x11.query.EventToken\"S\n\x14UpdateStreamResponse\x12!\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x12.query.StreamEvent\x12\x18\n\x10resume_timestamp\x18\x02 \x01(\x03*D\n\x0fTransactionMode\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\n\n\x06SINGLE\x10\x01\x12\t\n\x05MULTI\x10\x02\x12\t\n\x05TWOPC\x10\x03\x42\x36\n\x0fio.vitess.protoZ#vitess.io/vitess/go/vt/proto/vtgateb\x06proto3') , dependencies=[query__pb2.DESCRIPTOR,topodata__pb2.DESCRIPTOR,vtrpc__pb2.DESCRIPTOR,]) @@ -52,8 +52,8 @@ ], containing_type=None, options=None, - serialized_start=7137, - serialized_end=7205, + serialized_start=7176, + serialized_end=7244, ) _sym_db.RegisterEnumDescriptor(_TRANSACTIONMODE) @@ -98,8 +98,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=309, - serialized_end=378, + serialized_start=348, + serialized_end=417, ) _SESSION = _descriptor.Descriptor( @@ -158,6 +158,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='warnings', full_name='vtgate.Session.warnings', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -171,7 +178,7 @@ oneofs=[ ], serialized_start=67, - serialized_end=378, + serialized_end=417, ) @@ -243,8 +250,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=381, - serialized_end=636, + serialized_start=420, + serialized_end=675, ) @@ -288,8 +295,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=638, - serialized_end=757, + serialized_start=677, + serialized_end=796, ) @@ -368,8 +375,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=760, - serialized_end=1031, + serialized_start=799, + serialized_end=1070, ) @@ -413,8 +420,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1033, - serialized_end=1158, + serialized_start=1072, + serialized_end=1197, ) @@ -493,8 +500,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1161, - serialized_end=1443, + serialized_start=1200, + serialized_end=1482, ) @@ -538,8 +545,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1446, - serialized_end=1576, + serialized_start=1485, + serialized_end=1615, ) @@ -618,8 +625,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1579, - serialized_end=1877, + serialized_start=1618, + serialized_end=1916, ) @@ -663,8 +670,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1880, - serialized_end=2008, + serialized_start=1919, + serialized_end=2047, ) @@ -708,8 +715,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2370, - serialized_end=2443, + serialized_start=2409, + serialized_end=2482, ) _EXECUTEENTITYIDSREQUEST = _descriptor.Descriptor( @@ -794,8 +801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2011, - serialized_end=2443, + serialized_start=2050, + serialized_end=2482, ) @@ -839,8 +846,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2446, - serialized_end=2574, + serialized_start=2485, + serialized_end=2613, ) @@ -912,8 +919,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2577, - serialized_end=2835, + serialized_start=2616, + serialized_end=2874, ) @@ -957,8 +964,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2838, - serialized_end=2967, + serialized_start=2877, + serialized_end=3006, ) @@ -1002,8 +1009,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2969, - serialized_end=3054, + serialized_start=3008, + serialized_end=3093, ) @@ -1068,8 +1075,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3057, - serialized_end=3303, + serialized_start=3096, + serialized_end=3342, ) @@ -1113,8 +1120,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3306, - serialized_end=3437, + serialized_start=3345, + serialized_end=3476, ) @@ -1158,8 +1165,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3439, - serialized_end=3535, + serialized_start=3478, + serialized_end=3574, ) @@ -1224,8 +1231,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3538, - serialized_end=3794, + serialized_start=3577, + serialized_end=3833, ) @@ -1269,8 +1276,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3797, - serialized_end=3933, + serialized_start=3836, + serialized_end=3972, ) @@ -1335,8 +1342,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3936, - serialized_end=4169, + serialized_start=3975, + serialized_end=4208, ) @@ -1366,8 +1373,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4171, - serialized_end=4230, + serialized_start=4210, + serialized_end=4269, ) @@ -1432,8 +1439,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4233, - serialized_end=4448, + serialized_start=4272, + serialized_end=4487, ) @@ -1463,8 +1470,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4450, - serialized_end=4515, + serialized_start=4489, + serialized_end=4554, ) @@ -1529,8 +1536,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4518, - serialized_end=4744, + serialized_start=4557, + serialized_end=4783, ) @@ -1560,8 +1567,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4746, - serialized_end=4816, + serialized_start=4785, + serialized_end=4855, ) @@ -1626,8 +1633,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4819, - serialized_end=5061, + serialized_start=4858, + serialized_end=5100, ) @@ -1657,8 +1664,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5063, - serialized_end=5131, + serialized_start=5102, + serialized_end=5170, ) @@ -1695,8 +1702,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5133, - serialized_end=5202, + serialized_start=5172, + serialized_end=5241, ) @@ -1726,8 +1733,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5204, - serialized_end=5253, + serialized_start=5243, + serialized_end=5292, ) @@ -1771,8 +1778,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5255, - serialized_end=5356, + serialized_start=5294, + serialized_end=5395, ) @@ -1795,8 +1802,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5358, - serialized_end=5374, + serialized_start=5397, + serialized_end=5413, ) @@ -1833,8 +1840,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5376, - serialized_end=5463, + serialized_start=5415, + serialized_end=5502, ) @@ -1857,8 +1864,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5465, - serialized_end=5483, + serialized_start=5504, + serialized_end=5522, ) @@ -1895,8 +1902,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5485, - serialized_end=5562, + serialized_start=5524, + serialized_end=5601, ) @@ -1954,8 +1961,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5565, - serialized_end=5709, + serialized_start=5604, + serialized_end=5748, ) @@ -2006,8 +2013,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5711, - serialized_end=5825, + serialized_start=5750, + serialized_end=5864, ) @@ -2044,8 +2051,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5827, - serialized_end=5888, + serialized_start=5866, + serialized_end=5927, ) @@ -2096,8 +2103,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5891, - serialized_end=6036, + serialized_start=5930, + serialized_end=6075, ) @@ -2120,8 +2127,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6038, - serialized_end=6066, + serialized_start=6077, + serialized_end=6105, ) @@ -2200,8 +2207,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6069, - serialized_end=6335, + serialized_start=6108, + serialized_end=6374, ) @@ -2238,8 +2245,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6409, - serialized_end=6481, + serialized_start=6448, + serialized_end=6520, ) _SPLITQUERYRESPONSE_SHARDPART = _descriptor.Descriptor( @@ -2275,8 +2282,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6483, - serialized_end=6528, + serialized_start=6522, + serialized_end=6567, ) _SPLITQUERYRESPONSE_PART = _descriptor.Descriptor( @@ -2326,8 +2333,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6531, - serialized_end=6708, + serialized_start=6570, + serialized_end=6747, ) _SPLITQUERYRESPONSE = _descriptor.Descriptor( @@ -2356,8 +2363,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6338, - serialized_end=6708, + serialized_start=6377, + serialized_end=6747, ) @@ -2387,8 +2394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6710, - serialized_end=6751, + serialized_start=6749, + serialized_end=6790, ) @@ -2418,8 +2425,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6753, - serialized_end=6822, + serialized_start=6792, + serialized_end=6861, ) @@ -2491,8 +2498,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6825, - serialized_end=7050, + serialized_start=6864, + serialized_end=7089, ) @@ -2529,8 +2536,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7052, - serialized_end=7135, + serialized_start=7091, + serialized_end=7174, ) _SESSION_SHARDSESSION.fields_by_name['target'].message_type = query__pb2._TARGET @@ -2538,6 +2545,7 @@ _SESSION.fields_by_name['shard_sessions'].message_type = _SESSION_SHARDSESSION _SESSION.fields_by_name['options'].message_type = query__pb2._EXECUTEOPTIONS _SESSION.fields_by_name['transaction_mode'].enum_type = _TRANSACTIONMODE +_SESSION.fields_by_name['warnings'].message_type = query__pb2._QUERYWARNING _EXECUTEREQUEST.fields_by_name['caller_id'].message_type = vtrpc__pb2._CALLERID _EXECUTEREQUEST.fields_by_name['session'].message_type = _SESSION _EXECUTEREQUEST.fields_by_name['query'].message_type = query__pb2._BOUNDQUERY diff --git a/py/vttest/mysql_flavor.py b/py/vttest/mysql_flavor.py index e0e8969ea80..2e9e3f95ff3 100644 --- a/py/vttest/mysql_flavor.py +++ b/py/vttest/mysql_flavor.py @@ -53,6 +53,15 @@ def my_cnf(self): ] return ":".join(files) +class MariaDB103(MysqlFlavor): + """Overrides specific to MariaDB 10.3""" + + def my_cnf(self): + files = [ + os.path.join(vttop, "config/mycnf/default-fast.cnf"), + os.path.join(vttop, "config/mycnf/master_mariadb103.cnf"), + ] + return ":".join(files) class MySQL56(MysqlFlavor): """Overrides specific to MySQL 5.6.""" @@ -89,6 +98,8 @@ def set_mysql_flavor(flavor): if flavor == "MariaDB": __mysql_flavor = MariaDB() + elif flavor == "MariaDB103": + __mysql_flavor = MariaDB103() elif flavor == "MySQL56": __mysql_flavor = MySQL56() else: diff --git a/test/cluster/keytar/config/vitess_config.yaml b/test/cluster/keytar/config/vitess_config.yaml index ad85cbe4692..f800793a01c 100644 --- a/test/cluster/keytar/config/vitess_config.yaml +++ b/test/cluster/keytar/config/vitess_config.yaml @@ -3,8 +3,8 @@ install: - python-mysqldb extra: - apt-get update - - wget https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz - - tar -C /usr/local -xzf go1.9.linux-amd64.tar.gz + - wget https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz + - tar -C /usr/local -xzf go1.11.1.linux-amd64.tar.gz - wget https://storage.googleapis.com/kubernetes-helm/helm-v2.1.3-linux-amd64.tar.gz - tar -zxvf helm-v2.1.3-linux-amd64.tar.gz - pip install numpy diff --git a/test/cluster/keytar/requirements.txt b/test/cluster/keytar/requirements.txt index b02181264fe..76649d9b728 100644 --- a/test/cluster/keytar/requirements.txt +++ b/test/cluster/keytar/requirements.txt @@ -1,2 +1,2 @@ -Flask==0.10 +Flask==0.12.3 pyyaml==3.10 diff --git a/test/environment.py b/test/environment.py index 0cf14691335..2d615ddaace 100644 --- a/test/environment.py +++ b/test/environment.py @@ -47,7 +47,7 @@ # sanity check the environment -if os.environ['USER'] == 'root': +if os.getuid() == 1: sys.stderr.write( 'ERROR: Vitess and mysqld ' 'should not be run as root.\n') diff --git a/test/mysql_flavor.py b/test/mysql_flavor.py index 33d13705c7d..dc14073a06e 100644 --- a/test/mysql_flavor.py +++ b/test/mysql_flavor.py @@ -230,4 +230,5 @@ def register_flavor(flavor, cls, env): flavor_map[flavor] = {"cls": cls, "env": env} register_flavor("MariaDB", MariaDB, "MariaDB") +register_flavor("MariaDB103", MariaDB, "MariaDB103") register_flavor("MySQL56", MySQL56, "MySQL56") diff --git a/test/mysql_server_test.py b/test/mysql_server_test.py index 3cd11cf148d..b723eb33ec7 100755 --- a/test/mysql_server_test.py +++ b/test/mysql_server_test.py @@ -29,6 +29,7 @@ import environment import utils import tablet +import warnings # single shard / 2 tablets shard_0_master = tablet.Tablet() @@ -202,6 +203,63 @@ def test_mysql_connector(self): self.assertIn('1317', s) conn.close() + # this query should fail due to the bogus field + conn = MySQLdb.Connect(**params) + try: + cursor = conn.cursor() + cursor.execute('SELECT invalid_field from vt_insert_test', {}) + self.fail('Execute went through') + except MySQLdb.OperationalError, e: + s = str(e) + # 1054 is BadFieldError code + self.assertIn('1054', s) + + # this query should trigger a warning not an error + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + + cursor.execute('SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS */ invalid_field from vt_insert_test', {}) + if cursor.rowcount != 0: + self.fail('expected 0 rows got ' + str(cursor.rowcount)) + + if len(w) != 1: + print 'unexpected warnings: ', w + + # and the next query should get the warnings + cursor.execute('SHOW WARNINGS', {}) + if cursor.rowcount != 1: + print 'expected 1 warning row, got ' + str(cursor.rowcount) + + for (_, code, message) in cursor: + self.assertEqual(code, 1054) + self.assertIn('errno 1054', message) + self.assertIn('Unknown column', message) + + # test with a query timeout error + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + + cursor.execute('SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS QUERY_TIMEOUT_MS=1 */ sleep(1) from vt_insert_test', {}) + if cursor.rowcount != 0: + self.fail('expected 0 rows got ' + str(cursor.rowcount)) + + if len(w) != 1: + print 'unexpected warnings: ', w + + cursor.execute('SHOW WARNINGS', {}) + if cursor.rowcount != 1: + print 'expected 1 warning row, got ' + str(cursor.rowcount) + + for (_, code, message) in cursor: + self.assertEqual(code, 1317) + self.assertIn('context deadline exceeded', message) + + # any non-show query clears the warnings + cursor.execute('SELECT 1 from vt_insert_test limit 1', {}) + cursor.execute('SHOW WARNINGS', {}) + if cursor.rowcount != 0: + print 'expected 0 warnings row, got ' + str(cursor.rowcount) + # 'vtgate client 2' is not authorized to access vt_insert_test params['user'] = 'testuser2' params['passwd'] = 'testpassword2' diff --git a/test/resharding.py b/test/resharding.py index 8d1379855f0..86c55480a7b 100755 --- a/test/resharding.py +++ b/test/resharding.py @@ -973,6 +973,12 @@ def test_resharding(self): utils.check_tablet_query_service(self, shard_1_ny_rdonly, True, False) utils.check_tablet_query_service(self, shard_1_rdonly1, False, True) + # rerun migrate to ensure it doesn't fail + # skip refresh to make it go faster + utils.run_vtctl(['MigrateServedTypes', '--cells=test_nj', + '-skip-refresh-state=true', + 'test_keyspace/80-', 'rdonly'], auto_log=True) + # now serve rdonly from the split shards, everywhere utils.run_vtctl(['MigrateServedTypes', 'test_keyspace/80-', 'rdonly'], auto_log=True) @@ -992,6 +998,11 @@ def test_resharding(self): utils.check_tablet_query_service(self, shard_1_ny_rdonly, False, True) utils.check_tablet_query_service(self, shard_1_rdonly1, False, True) + # rerun migrate to ensure it doesn't fail + # skip refresh to make it go faster + utils.run_vtctl(['MigrateServedTypes', '-skip-refresh-state=true', + 'test_keyspace/80-', 'rdonly'], auto_log=True) + # then serve replica from the split shards destination_shards = ['test_keyspace/80-c0', 'test_keyspace/c0-'] @@ -1091,8 +1102,43 @@ def test_resharding(self): 'test_keyspace/c0-', '1', 'test_keyspace/80-'], auto_log=True) - # then serve master from the split shards, make sure the source master's - # query service is now turned off + # CancelResharding should fail because migration has started. + utils.run_vtctl(['CancelResharding', 'test_keyspace/80-'], + auto_log=True, expect_fail=True) + + # do a Migrate that will fail waiting for replication + # which should cause the Migrate to be canceled and the source + # master to be serving again. + utils.run_vtctl(['MigrateServedTypes', + '-filtered_replication_wait_time', '0s', + 'test_keyspace/80-', 'master'], + auto_log=True, expect_fail=True) + utils.check_srv_keyspace('test_nj', 'test_keyspace', + 'Partitions(master): -80 80-\n' + 'Partitions(rdonly): -80 80-c0 c0-\n' + 'Partitions(replica): -80 80-c0 c0-\n', + keyspace_id_type=base_sharding.keyspace_id_type, + sharding_column_name='custom_ksid_col') + utils.check_tablet_query_service(self, shard_1_master, True, False) + + # sabotage master migration and make it fail in an unfinished state + utils.run_vtctl(['SetShardTabletControl', '-blacklisted_tables=t', + 'test_keyspace/c0-', 'master'], auto_log=True) + utils.run_vtctl(['MigrateServedTypes', 'test_keyspace/80-', 'master'], + auto_log=True, expect_fail=True) + + # remove sabotage, but make it fail early. This should not result + # in the source master serving, because this failure is past the + # point of no return. + utils.run_vtctl(['SetShardTabletControl', '-blacklisted_tables=t', + '-remove', 'test_keyspace/c0-', 'master'], auto_log=True) + utils.run_vtctl(['MigrateServedTypes', + '-filtered_replication_wait_time', '0s', + 'test_keyspace/80-', 'master'], + auto_log=True, expect_fail=True) + utils.check_tablet_query_service(self, shard_1_master, False, True) + + # do the migration that's expected to succeed utils.run_vtctl(['MigrateServedTypes', 'test_keyspace/80-', 'master'], auto_log=True) utils.check_srv_keyspace('test_nj', 'test_keyspace', @@ -1107,6 +1153,36 @@ def test_resharding(self): self.check_no_binlog_player(shard_2_master) self.check_no_binlog_player(shard_3_master) + # test reverse_replication + # start with inserting a row in each destination shard + self._insert_value(shard_2_master, 'resharding2', 2, 'msg2', + 0x9000000000000000) + self._insert_value(shard_3_master, 'resharding2', 3, 'msg3', + 0xD000000000000000) + # ensure the rows are not present yet + self._check_value(shard_1_master, 'resharding2', 2, 'msg2', + 0x9000000000000000, should_be_here=False) + self._check_value(shard_1_master, 'resharding2', 3, 'msg3', + 0xD000000000000000, should_be_here=False) + # repeat the migration with reverse_replication + utils.run_vtctl(['MigrateServedTypes', '-reverse_replication=true', + 'test_keyspace/80-', 'master'], auto_log=True) + # look for the rows in the original master after a short wait + time.sleep(1.0) + self._check_value(shard_1_master, 'resharding2', 2, 'msg2', + 0x9000000000000000) + self._check_value(shard_1_master, 'resharding2', 3, 'msg3', + 0xD000000000000000) + + # retry the migration to ensure it now fails + utils.run_vtctl(['MigrateServedTypes', '-reverse_replication=true', + 'test_keyspace/80-', 'master'], + auto_log=True, expect_fail=True) + + # CancelResharding should now succeed + utils.run_vtctl(['CancelResharding', 'test_keyspace/80-'], auto_log=True) + self.check_no_binlog_player(shard_1_master) + # delete the original tablets in the original shard tablet.kill_tablets([shard_1_master, shard_1_slave1, shard_1_slave2, shard_1_ny_rdonly, shard_1_rdonly1]) diff --git a/test/utils.py b/test/utils.py index 045bfcf86c3..d7e65ff23dc 100644 --- a/test/utils.py +++ b/test/utils.py @@ -302,8 +302,9 @@ def run_fail(cmd, **kargs): proc = subprocess.Popen(args, **kargs) proc.args = args stdout, stderr = proc.communicate() - if proc.returncode == 0: + if proc.returncode == 0 or options.verbose == 2: logging.info('stdout:\n%sstderr:\n%s', stdout, stderr) + if proc.returncode == 0: raise TestError('expected fail:', args, stdout, stderr) return stdout, stderr @@ -1217,6 +1218,8 @@ def start(self, enable_schema_change_dir=False, extra_flags=None): '-workflow_manager_init', '-workflow_manager_use_election', '-schema_swap_delay_between_errors', '1s', + '-wait_for_drain_sleep_rdonly', '1s', + '-wait_for_drain_sleep_replica', '1s', ] + environment.topo_server().flags() if extra_flags: args += extra_flags diff --git a/test/vertical_split.py b/test/vertical_split.py index e895cf22f07..7b33c7923fb 100755 --- a/test/vertical_split.py +++ b/test/vertical_split.py @@ -424,6 +424,22 @@ def test_vertical_split(self): 'destination_keyspace/0'], auto_log=True) + # test Cancel first + utils.run_vtctl(['CancelResharding', 'destination_keyspace/0'], auto_log=True) + self.check_no_binlog_player(destination_master) + + # redo VerticalSplitClone + utils.run_vtworker(['--cell', 'test_nj', + '--command_display_interval', '10ms', + '--use_v3_resharding_mode=false', + 'VerticalSplitClone', + '--tables', '/moving/,view1', + '--chunk_count', '10', + '--min_rows_per_chunk', '1', + '--min_healthy_rdonly_tablets', '1', + 'destination_keyspace/0'], + auto_log=True) + # check values are present self._check_values(destination_master, 'vt_destination_keyspace', 'moving1', self.moving1_first, 100) @@ -574,6 +590,10 @@ def test_vertical_split(self): 'destination_keyspace', ['master'], ['moving1', 'moving2']) + # Cancel should fail now + utils.run_vtctl(['CancelResharding', 'destination_keyspace/0'], + auto_log=True, expect_fail=True) + # then serve master from the destination shards utils.run_vtctl(['MigrateServedFrom', 'destination_keyspace/0', 'master'], auto_log=True) diff --git a/test/vtgatev3_test.py b/test/vtgatev3_test.py index a4c6dec5560..2de9e869777 100755 --- a/test/vtgatev3_test.py +++ b/test/vtgatev3_test.py @@ -680,6 +680,33 @@ def test_user(self): ([(0,)], 1L, 0, [(u'SLEEP(1)', self.int_type)])) + # test shard errors as warnings directive + cursor.execute('SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS */ bad from vt_user', {}) + print vtgate_conn.get_warnings() + warnings = vtgate_conn.get_warnings() + self.assertEqual(len(warnings), 2) + for warning in warnings: + self.assertEqual(warning.code, 1054) + self.assertIn('errno 1054', warning.message) + self.assertIn('Unknown column', warning.message) + self.assertEqual( + (cursor.fetchall(), cursor.rowcount, cursor.lastrowid, + cursor.description), + ([], 0L, 0, [])) + + # test shard errors as warnings directive with timeout + cursor.execute('SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS QUERY_TIMEOUT_MS=10 */ SLEEP(1)', {}) + print vtgate_conn.get_warnings() + warnings = vtgate_conn.get_warnings() + self.assertEqual(len(warnings), 1) + for warning in warnings: + self.assertEqual(warning.code, 1317) + self.assertIn('context deadline exceeded', warning.message) + self.assertEqual( + (cursor.fetchall(), cursor.rowcount, cursor.lastrowid, + cursor.description), + ([], 0L, 0, [])) + # Test insert with no auto-inc vtgate_conn.begin() result = self.execute_on_master( diff --git a/vagrant-scripts/bootstrap_vm.sh b/vagrant-scripts/bootstrap_vm.sh index 4ba8265d892..5515e80dc16 100755 --- a/vagrant-scripts/bootstrap_vm.sh +++ b/vagrant-scripts/bootstrap_vm.sh @@ -35,7 +35,7 @@ apt-get install -y make \ unzip # Install golang -GO_VER='1.9.1' +GO_VER='1.11.1' GO_DOWNLOAD_URL='https://storage.googleapis.com/golang' GO_FILENAME="go${GO_VER}.linux-amd64.tar.gz" wget "${GO_DOWNLOAD_URL}/${GO_FILENAME}" -O "${TMP_DIR}/${GO_FILENAME}" @@ -69,6 +69,9 @@ printf "\nSetting higher limit for max number of open files\n" echo "fs.file-max = 10000" >> /etc/sysctl.conf sysctl -p +# Set vitess env in .bashrc +cat /vagrant/src/vitess.io/vitess/vagrant-scripts/vagrant-bashrc >> /home/vagrant/.bashrc + # Provisioning completed touch $SEED_FILE printf "\nProvisioning completed!\n\n" diff --git a/vagrant-scripts/vagrant-bashrc b/vagrant-scripts/vagrant-bashrc new file mode 100644 index 00000000000..adff78e8c54 --- /dev/null +++ b/vagrant-scripts/vagrant-bashrc @@ -0,0 +1,18 @@ +cd $VITESS_WORKSPACE || exit +seed_file=$HOME/.vitess_bootstrap_done + +if [ ! -f $seed_file ]; +then + printf "\nVM Vitess hasn't been build in this VM. Downloading and setting up vitess deps. \n" + ./vagrant-scripts/vitess/build.sh + touch $seed_file +fi + +ulimit -n 10000 +export MYSQL_FLAVOR=MySQL56 +export VT_MYSQL_ROOT=/usr +# This is just to make sure the vm can write into these directories +sudo chown "$(whoami)":"$(whoami)" /vagrant +sudo chown "$(whoami)":"$(whoami)" /vagrant/src +source dev.env +source /vagrant/dist/grpc/usr/local/bin/activate diff --git a/vagrant-scripts/vitess/build.sh b/vagrant-scripts/vitess/build.sh index 428b1f6a963..b920f55c3a2 100755 --- a/vagrant-scripts/vitess/build.sh +++ b/vagrant-scripts/vitess/build.sh @@ -3,7 +3,6 @@ # See http://vitess.io/getting-started/local-instance.html#manual-build # for more info # -set -ex ulimit -n 10000 export MYSQL_FLAVOR=MySQL56 @@ -23,4 +22,4 @@ source /vagrant/dist/grpc/usr/local/bin/activate pip install mysqlclient make build -printf "\Build completed\n\n." +printf "\Build completed\n\n" diff --git a/vitess.io/Gemfile.lock b/vitess.io/Gemfile.lock index 578184042bf..49a4a6e3af8 100644 --- a/vitess.io/Gemfile.lock +++ b/vitess.io/Gemfile.lock @@ -19,7 +19,7 @@ GEM colorator (1.1.0) concurrent-ruby (1.0.5) execjs (2.7.0) - ffi (1.9.18) + ffi (1.9.25) forwardable-extended (2.6.0) gemoji (2.1.0) html-pipeline (1.11.0) diff --git a/vitess.io/_includes/left-nav-menu.html b/vitess.io/_includes/left-nav-menu.html index 16df1f9897a..9375ce81bc1 100644 --- a/vitess.io/_includes/left-nav-menu.html +++ b/vitess.io/_includes/left-nav-menu.html @@ -21,6 +21,9 @@

Getting Started

User Guide

  • Introduction +
  • Frequently Asked Questions +
  • VTTablet Modes +
  • VTExplain
  • Backing Up Data
  • Reparenting
  • Schema Management
  • diff --git a/vitess.io/user-guide/faq.md b/vitess.io/user-guide/faq.md new file mode 100644 index 00000000000..f913653ca18 --- /dev/null +++ b/vitess.io/user-guide/faq.md @@ -0,0 +1,16 @@ +--- +layout: doc +title: "Frequently Asked Questions" +description: +modified: +excerpt: +tags: [] +image: + feature: + teaser: + thumb: +toc: true +share: false +--- + +{% include doc/FAQ.md %} diff --git a/vitess.io/user-guide/vtexplain.md b/vitess.io/user-guide/vtexplain.md new file mode 100644 index 00000000000..351e2a84082 --- /dev/null +++ b/vitess.io/user-guide/vtexplain.md @@ -0,0 +1,16 @@ +--- +layout: doc +title: "VTExplain" +description: +modified: +excerpt: +tags: [] +image: + feature: + teaser: + thumb: +toc: true +share: false +--- + +{% include doc/VtExplain.md %} diff --git a/vitess.io/user-guide/vttablet-modes.md b/vitess.io/user-guide/vttablet-modes.md new file mode 100644 index 00000000000..9a13d499660 --- /dev/null +++ b/vitess.io/user-guide/vttablet-modes.md @@ -0,0 +1,16 @@ +--- +layout: doc +title: "VTTablet Modes" +description: +modified: +excerpt: +tags: [] +image: + feature: + teaser: + thumb: +toc: true +share: false +--- + +{% include doc/VTTabletModes.md %}