diff --git a/.github/licenserc.yml b/.github/licenserc.yml index 97565bdc1c476..9f4890a3a1329 100644 --- a/.github/licenserc.yml +++ b/.github/licenserc.yml @@ -13,13 +13,13 @@ header: - '**/*.key' - '**/*.md' - '**/*.json' + - '**/*.toml' - '**/*.pem' - '**/*.crt' - '**/*.test' - '**/*.result' - '**/*.example' - '.codecov.yml' - - 'errors.toml' - 'Jenkinsfile' - '.editorconfig' - 'hooks/pre-commit' diff --git a/.github/workflows/br_compatible_test.yml b/.github/workflows/integration-test-br-compatibility.yml similarity index 83% rename from .github/workflows/br_compatible_test.yml rename to .github/workflows/integration-test-br-compatibility.yml index 149b70db1b068..25cfbeaa99b4c 100644 --- a/.github/workflows/br_compatible_test.yml +++ b/.github/workflows/integration-test-br-compatibility.yml @@ -17,20 +17,7 @@ on: - '!br/docker/**' # disable pull request only keep the merge action since it is very costly to run those tests # pull_request: - # branches: - # - master - # - 'release-[0-9].[0-9]*' - # paths: - # - 'br/**' - # - '!**.html' - # - '!**.md' - # - '!CNAME' - # - '!LICENSE' - # - '!br/docs/**' - # - '!br/tests/**' - # - '!br/docker/**' -# See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency. concurrency: group: ${{ github.ref }}-${{ github.workflow }} cancel-in-progress: true @@ -57,6 +44,7 @@ jobs: TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml rm -s -v TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml build TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml up --remove-orphans -d + TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml exec -T control go mod tidy TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml exec -T control make build_br TAG=nightly PORT_SUFFIX=1 docker-compose -f br/compatibility/backup_cluster.yaml exec -T control br/tests/run_compatible.sh run diff --git a/.github/workflows/compile_br.yaml b/.github/workflows/integration-test-compile-br.yml similarity index 95% rename from .github/workflows/compile_br.yaml rename to .github/workflows/integration-test-compile-br.yml index 3d6ae87beea7c..74d0689e98819 100644 --- a/.github/workflows/compile_br.yaml +++ b/.github/workflows/integration-test-compile-br.yml @@ -32,7 +32,6 @@ on: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency. concurrency: group: ${{ github.ref }}-${{ github.workflow }} cancel-in-progress: true diff --git a/.github/workflows/dumpling_integration_test.yml b/.github/workflows/integration-test-dumpling.yml similarity index 97% rename from .github/workflows/dumpling_integration_test.yml rename to .github/workflows/integration-test-dumpling.yml index 75395b9e271ef..a60703a50836e 100644 --- a/.github/workflows/dumpling_integration_test.yml +++ b/.github/workflows/integration-test-dumpling.yml @@ -27,7 +27,6 @@ on: - 'util/codec/**' - 'parser/model/**' -# See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency. concurrency: group: ${{ github.ref }}-${{ github.workflow }} cancel-in-progress: true diff --git a/.github/workflows/integration-test-with-real-tikv.yml b/.github/workflows/integration-test-with-real-tikv.yml new file mode 100644 index 0000000000000..10109899a9bcc --- /dev/null +++ b/.github/workflows/integration-test-with-real-tikv.yml @@ -0,0 +1,35 @@ +name: Real TiKV Tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + pessimistic-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.18 + - name: Setup TiKV cluster + run: | + # Disable pipelined pessimistic lock temporarily until tikv#11649 is resolved + echo -e "[pessimistic-txn]\npipelined = false\n" > tikv.toml + echo -e "[raftdb]\nmax-open-files = 10240\n" >> tikv.toml + echo -e "[rocksdb]\nmax-open-files = 10240\n" >> tikv.toml + curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh + $HOME/.tiup/bin/tiup playground nightly --mode tikv-slim --kv 3 --pd 3 --without-monitor --kv.config tikv.toml & + curl --retry-connrefused --retry 5 --retry-delay 5 http://127.0.0.1:2379 + + - name: Run Tests + run: | + export log_level=error + make failpoint-enable + go test ./tests/pessimistictest -v -with-real-tikv -timeout 20m diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index cf10e53fa9d49..0000000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,1267 +0,0 @@ -# TiDB Changelog -All notable changes to this project will be documented in this file. See also [Release Notes](https://github.com/pingcap/docs/blob/master/releases/release-notes.md), [TiKV Changelog](https://github.com/tikv/tikv/blob/master/CHANGELOG.md) and [PD Changelog](https://github.com/tikv/pd/blob/master/CHANGELOG.md). - -## [3.0.4] 2019-10-08 -## New features -* Add system table `performance_schema.events_statements_summary_by_digest` to troubleshoot performance issues at SQL level -* Add the `WHERE` clause in TiDB’s `SHOW TABLE REGIONS` syntax -* Add the `worker-count` and `txn-batch` configuration items in Reparo to control the recovery speed - -## Improvements -* Support `Split` commands in batches and the empty `Split` command in TiKV to split Regions in batches -* Support double linked list for RocksDB in TiKV to improve performance of reverse scan -* Add two perf tools -`iosnoop` and `funcslower` in TiDB Ansible to better diagnose the cluster state -* Optimize the output of slow query logs in TiDB by deleting redundant fields - -## Changed behaviors -* Update the default value of `txn-local-latches.enable` to `false` to disable the default behaviour of checking conflicts of local transactions in TiDB -* Add the `tidb_txn_mode` system variable of global scope in TiDB and allow using pessimistic lock by default. Note that TiDB still adopts optimistic lock by default. -* Replace the `Index_ids` field in TiDB slow query logs with `Index_names` to improve the usability of slow query logs -* Add the `split-region-max-num` parameter in the TiDB configuration file to modify the maximum number of Regions allowed in the `SPLIT TABLE` syntax -* Return the `Out Of Memory Quota` error instead of disconnect links in TiDB when a SQL execution exceeds the memory limit -* Disallow dropping the `AUTO INCREMENT` attribute of columns in TiDB to avoid misoperations. To drop this attribute, change the `tidb_allow_remove_auto_inc` system * variable. - -## Fixed Issues -* Fix the issue in TiDB that the special syntax `PRE_SPLIT_REGIONS` does not replicate data to the downstream by using notes -* Fix the issue in TiDB that the slow query logs are incorrect when getting the result of `PREPARE` + `EXECUTE` by using the cursor -* Fix the issue in PD that adjacent small Regions cannot be merged -* Fix the issue that too many file descriptors are opened in idle clusters -* Fix the issue that - -## Contributors -Our thanks go to the following contributors from the community for helping this release: -* [sduzh](https://github.com/sduzh) -* [lizhenda](https://github.com/lizhenda) - -## SQL Optimizer -* Fix the issue that invalid query ranges might be resulted when splitted by feedback [#12170](https://github.com/pingcap/tidb/pull/12170) -* Display the returned error of the `SHOW STATS_BUCKETS` statement in hexadecimal when the result contains invalid Keys [#12094](https://github.com/pingcap/tidb/pull/12094) -* Fix the issue that when a query contains the `SLEEP` function (for example, `select 1 from (select sleep(1)) t;)`), column pruning causes invalid `sleep(1)` during query [#11953](https://github.com/pingcap/tidb/pull/11953) -* Use index scan to lower IO when a query only concerns the number of columns rather than the table data [#12112](https://github.com/pingcap/tidb/pull/12112) -* Do not use any index when no index is specified in `use index()` to becompatible with MySQL [#12100](https://github.com/pingcap/tidb/pull/12100) -* Strictly limit the number of `TopN` records in the `CMSketch` statistics to fix the issue that the `ANALYZE` statement fails because the statement count exceeds TiDB’s limit on the size of a transaction [#11914](https://github.com/pingcap/tidb/pull/11914) -* Fix the error occurred when converting the subqueries contained in the `Update` statement [#12483](https://github.com/pingcap/tidb/pull/12483) -* Optimize execution performance of the `select ... limit ... offset ...` statement by pushing the Limit operator down to the `IndexLookUpReader` execution logic [#12378](https://github.com/pingcap/tidb/pull/12378) - -## SQL Execution Engine -* Print the SQL statement in the log when the `PREPARED` statement is incorrectly executed [#12191](https://github.com/pingcap/tidb/pull/12191) -* Support partition pruning when the `UNIX_TIMPESTAMP` function is used to implement partitioning [#12169](https://github.com/pingcap/tidb/pull/12169) -* Fix the issue that no error is reported when `AUTO INCREMENT` incorrectly allocates `MAX int64` and `MAX uint64` [#12162](https://github.com/pingcap/tidb/pull/12162) -* Add the `WHERE` clause in the `SHOW TABLE … REGIONS` and `SHOW TABLE .. INDEX … REGIONS` syntaxes [#12123](https://github.com/pingcap/tidb/pull/12123) -* Return the `Out Of Memory Quota` error instead of disconnect the link when a SQL execution exceeds the memory limit [#12127](https://github.com/pingcap/tidb/pull/12127) -* Fix the issue that incorrect result is returned when `JSON_UNQUOTE` function handles JSON text [#11955](https://github.com/pingcap/tidb/pull/11955) -* Fix the issue that `LAST INSERT ID` is incorrect when assigning values to the `AUTO_INCREMENT` column in the first row (for example, `insert into t (pk, c) values (1, 2), (NULL, 3)`) [#12002](https://github.com/pingcap/tidb/pull/12002) -* Fix the issue that the `GROUPBY` parsing rule is incorrect in the `PREPARE` statement [#12351](https://github.com/pingcap/tidb/pull/12351) -* Fix the issue that the privilege check is incorrect in point queries [#12340](https://github.com/pingcap/tidb/pull/12340) -* Fix the issue that the duration by sql_type for the `PREPARE` statement is not shown in the monitoring record [#12331](https://github.com/pingcap/tidb/pull/12331) -* Support using aliases for tables in the point queries (for example, `select * from t tmp where a = "aa"`) [#12282](https://github.com/pingcap/tidb/pull/12282) -* Fix the error occurred when not handling negative values as unsigned when inserting negative numbers into BIT type columns [#12423](https://github.com/pingcap/tidb/pull/12423) -* Fix the incorrectly rounding of time (for example, `2019-09-11 11:17:47.999999666` should be rounded to `2019-09-11 11:17:48`.) [#12258](https://github.com/pingcap/tidb/pull/12258) -* Refine the usage of expression blacklist (for example, `<` is equivalent to `lt`.) [#11975](https://github.com/pingcap/tidb/pull/11975) -* Add the database prefix to the function name in the error message of non-existing functions (for example, `[expression:1305]FUNCTION test.std_samp does not exist`) [#12111](https://github.com/pingcap/tidb/pull/12111) - -## Server -* Add the `Prev_stmt` field in slow query logs to output the previous statement when the last statement is `COMMIT` [#12180](https://github.com/pingcap/tidb/pull/12180) -* Optimize the output of slow query logs by deleting redundant fields [#12144](https://github.com/pingcap/tidb/pull/12144) -* Modify the default value of `txn-local-latches.enable` to `false` to disable the check for conflicts of local transactions in TiDB [#12095](https://github.com/pingcap/tidb/pull/12095) -* Replace the `Index_ids` field in TiDB slow query logs with `Index_names` to improve the usability of slow query logs [#12061](https://github.com/pingcap/tidb/pull/12061) -* Add the global system variable `tidb_txn_mode` in TiDB and allow using pessimistic lock by default [#12049](https://github.com/pingcap/tidb/pull/12049) -* Add the `Backoff` field in the slow query logs to record the Backoff information in the commit phase of 2PC [#12335](https://github.com/pingcap/tidb/pull/12335) -* Fix the issue that the slow query logs are incorrect when getting the result of `PREPARE` + `EXECUTE` by using the cursor (for example, `PREPARE stmt1FROM SELECT * FROM t WHERE a > ?; EXECUTE stmt1 USING @variable`) [#12392](https://github.com/pingcap/tidb/pull/12392) -* Support `tidb_enable_stmt_summary`. When this feature is enabled, TiDB counts the SQL statements and the result can be queried by using the system table `performance_schema.events_statements_summary_by_digest`. [#12308](https://github.com/pingcap/tidb/pull/12308) -* Adjust the level of some logs in tikv-client (for example, change the log level of `batchRecvLoop fails` from `ERROR` to `INFO`) [#12383](https://github.com/pingcap/tidb/pull/12383) - -## DDL -* Add the variable of `tidb_allow_remove_auto_inc`. Dropping the `AUTO INCREMENT` attribute of the column is disabled by default [#12145](https://github.com/pingcap/tidb/pull/12145) -* Fix the issue that the uncommented TiDB-specific syntax `PRE_SPLIT_REGIONS` might cause t errors in the downstream database during data replication [#12120](https://github.com/pingcap/tidb/pull/12120) -* Add the `split-region-max-num` variable in the configuration file so that the maximum allowable number of Regions is adjustable [#12097](https://github.com/pingcap/tidb/pull/12079) -* Support splitting a Region into multiple Regions and fix the timeout issue during Region scattering [#12343](https://github.com/pingcap/tidb/pull/12343) -* Fix the issue that the `drop index` statement fails when the index that contains an `auto_increment` column referenced byanother two indexes [#12344](https://github.com/pingcap/tidb/pull/12344) - -## Monitor -* Add the `connection_transient_failure_count` monitoring metric to count the number of gRPC connection errors in `tikvclient` [#12093](https://github.com/pingcap/tidb/pull/12093) - -## [3.0.3] 2019-08-29 -### SQL Optimizer -* Add the `opt_rule_blacklist` table to disable logic optimization rules such as `aggregation_eliminate` and `column_prune` [#11658](https://github.com/pingcap/tidb/pull/11658) -* Fix the issue that incorrect results might be returned for `Index Join` when the join key uses a prefix index or an unsigned index column that is equal to a negative value [#11759](https://github.com/pingcap/tidb/pull/11759) -* Fix the issue that `"` or `\` in the `SELECT` statements of `create ... binding ...` might result in parsing errors [#11726](https://github.com/pingcap/tidb/pull/11726) - -### SQL Execution Engine -* Fix the issue that type errors in the return value might occur when the `Quote` function handles a null value [#11619](https://github.com/pingcap/tidb/pull/11619) -* Fix the issue that incorrect results for `Ifnull` might be returned when `Max`/`min` is used for type inferring with `NotNullFlag` retained [#11641](https://github.com/pingcap/tidb/pull/11641) -* Fix the potential error that occurs when comparing bit type data in string form [#11660](https://github.com/pingcap/tidb/pull/11660) -* Decrease the concurrency for data that requires sequential read to reduce the possibility of OOM [#11679](https://github.com/pingcap/tidb/pull/11679) -* Fix the issue that incorrect type inferring might be caused when multiple parameters are unsigned for some built-in functions (e.g. `If`, `Coalesce`) [#11621](https://github.com/pingcap/tidb/pull/11621) -* Fix the incompatibility with MySQL when the `Div` function handles unsigned decimal types [#11813](https://github.com/pingcap/tidb/pull/11813) -* Fix the issue that panic might occur when executing SQL statements that modify the status of Pump/Drainer [#11827](https://github.com/pingcap/tidb/pull/11827) -* Fix the issue that panic might occur for `select ... for update` when Autocommit = 1 and there is no `begin` statement [#11736](https://github.com/pingcap/tidb/pull/11736) -* Fix the permission check error that might occur when the `set default role` statement is executed [#11777](https://github.com/pingcap/tidb/pull/11777) -* Fix the permission check error that might occur when `create user` or `drop user` is executed [#11814](https://github.com/pingcap/tidb/pull/11814) -* Fix the issue that the `select ... for update` statement might auto retry when it is constructed into the `PointGetExecutor` function [#11718](https://github.com/pingcap/tidb/pull/11718) -* Fix the boundary error that might occur when the Window function handles partition [#11825](https://github.com/pingcap/tidb/pull/11825) -* Fix the issue that the `Time` function hits EOF errors when handling an incorrectly formatted argument [#11893](https://github.com/pingcap/tidb/pull/11893) -* Fix the issue that the Window function does not check the passed-in parameters [#11705](https://github.com/pingcap/tidb/pull/11705) -* Fix the issue that the plan result viewed via `Explain` is inconsistent with the actually executed plan [#11186](https://github.com/pingcap/tidb/pull/11186) -* Fix the issue that duplicate memory referenced by the Window function might result in a crash or incorrect results [#11823](https://github.com/pingcap/tidb/pull/11823) -* Update the incorrect information in the `Succ` field in the slow log [#11887](https://github.com/pingcap/tidb/pull/11887) - -### Server -* Rename the `tidb_back_off_wexight` variable to `tidb_backoff_weight` [#11665](https://github.com/pingcap/tidb/pull/11665) -* Update the minimum TiKV version compatible with the current TiDB to v3.0.0 [#11618](https://github.com/pingcap/tidb/pull/11618) -* Support `make testSuite` to ensure the suites in the test are correctly used [#11685](https://github.com/pingcap/tidb/pull/11685) - -### DDL -* Skip the execution of unsupported partition-related DDL statements, including statements that modify the partition type while deleting multiple partitions [#11373](https://github.com/pingcap/tidb/pull/11373) -* Disallow a Generated Column to be placed before its dependent columns [#11686](https://github.com/pingcap/tidb/pull/11686) -* Modify the default values of `tidb_ddl_reorg_worker_cnt` and `tidb_ddl_reorg_batch_size` [#11874](https://github.com/pingcap/tidb/pull/11874) - -### Monitor -* Add new backoff monitoring types to record duration for each backoff type; add more backoff metrics to cover previously uncounted types such as commit backoff [#11728](https://github.com/pingcap/tidb/pull/11728) - - -## [3.0.2] 2019-08-06 -### SQL Optimizer -* Fix the issue that the "Can't find column in schema" message is reported when the same table occurs multiple times in a query and logically the query result is always empty [#11247](https://github.com/pingcap/tidb/pull/11247) -* Fix the issue that the query plan does not meet the expectation caused by the `TIDB_INLJ` hint not working correctly in some cases (like `explain select /*+ TIDB_INLJ(t1) */ t1.b, t2.a from t t1, t t2 where t1.b = t2.a`) [#11362](https://github.com/pingcap/tidb/pull/11362) -* Fix the issue that the column name in the query result is wrong in some cases (like `SELECT IF(1,c,c) FROM t`) [#11379](https://github.com/pingcap/tidb/pull/11379) -* Fix the issue that some queries like `SELECT 0 LIKE 'a string'` return `TRUE` becausethe `LIKE` expression is implicitly converted to 0 in some cases [#11411](https://github.com/pingcap/tidb/pull/11411) -* Support sub-queries in the `SHOW` statement, like `SHOW COLUMNS FROM tbl WHERE FIELDS IN (SELECT 'a')` [#11459](https://github.com/pingcap/tidb/pull/11459) -* Fix the issue that the related column of the aggregate function cannot be found and an error is reported caused by the `outerJoinElimination` optimizing rule not correctly handling the column alias; improve alias parsing in the optimizing process to make optimization cover more query types [#11377](https://github.com/pingcap/tidb/pull/11377) -* Fix the issue that no error is reported when the syntax restriction is violated in the Window function (for example, `UNBOUNDED PRECEDING` is not allowed to appear at the end of the Frame definition) [#11543](https://github.com/pingcap/tidb/pull/11543) -* Fix the issue that `FUNCTION_NAME` is in uppercase in the `ERROR 3593 (HY000): You cannot use the window function FUNCTION_NAME in this context` error message, which causes incompatibility with MySQL [#11535](https://github.com/pingcap/tidb/pull/11535) -* Fix the issue that the unimplemented `IGNORE NULLS` syntax in the Window function is used but no error is reported [#11593](https://github.com/pingcap/tidb/pull/11593) -* Fix the issue that the Optimizer does not correctly estimate time equal conditions [#11512](https://github.com/pingcap/tidb/pull/11512) -* Support updating the Top-N statistics based on the feedback information [#11507](https://github.com/pingcap/tidb/pull/11507) - -### SQL Execution Engine -* Fix the issue that the returned value is not `NULL` when the `INSERT` function contains `NULL` in parameters [#11248](https://github.com/pingcap/tidb/pull/11248) -* Fix the issue that the computing result might be wrong when the partitioned table is checked by the `ADMIN CHECKSUM` operation [#11266](https://github.com/pingcap/tidb/pull/11266) -* Fix the issue that the result might be wrong when INDEX JOIN uses the prefix index [#11246](https://github.com/pingcap/tidb/pull/11246) -* Fix the issue that result might be wrong caused by incorrectly aligning fractions when the `DATE_ADD` function does subtraction on date numbers involving microseconds [#11288](https://github.com/pingcap/tidb/pull/11288) -* Fix the wrong result caused by the `DATE_ADD` function incorrectly processing the negative numbers in `INTERVAL` [#11325](https://github.com/pingcap/tidb/pull/11325) -* Fix the issue that the number of fractional digits returned by `Mod`(`%`), `Multiple`(`*`) or `Minus`(`-`) is different from that in MySQL when `Mod`, `Multiple` or `Minus` returns 0 and the number of fractional digits is large (like -`select 0.000 % 0.11234500000000000000`) [#11251](https://github.com/pingcap/tidb/pull/11251) -* Fix the issue that `NULL` with a warning is incorrectly returned when the length of the result returned by `CONCAT` and `CONCAT_WS` functions exceeds `max_allowed_packet` [#11275](https://github.com/pingcap/tidb/pull/11275) -* Fix the issue that `NULL` with a warning is incorrectly returned when parameters in the `SUBTIME` and `ADDTIME` functions are invalid [#11337](https://github.com/pingcap/tidb/pull/11337) -* Fix the issue that `NULL` is incorrectly returned when parameters in the `CONVERT_TZ` function are invalid [#11359](https://github.com/pingcap/tidb/pull/11359) -* Add the `MEMORY` column to the result returned by `EXPLAIN ANALYZE` to show the memory usage of this query [#11418](https://github.com/pingcap/tidb/pull/11418) -* Add `CARTESIAN JOIN` to the result of `EXPLAIN` [#11429](https://github.com/pingcap/tidb/pull/11429) -* Fix the incorrect data of auto-increment columns of the float and double types [#11385](https://github.com/pingcap/tidb/pull/11385) -* Fix the panic issue caused by some `nil` information when pseudo statistics are dumped [#11460](https://github.com/pingcap/tidb/pull/11460) -* Fix the incorrect query result of `SELECT … CASE WHEN … ELSE NULL ...` caused by constant folding optimization [#11441](https://github.com/pingcap/tidb/pull/11441) -* Fix the issue that `floatStrToIntStr` does not correctly parse the input such as `+999.9999e2` [#11473](https://github.com/pingcap/tidb/pull/11473) -* Fix the issue that `NULL` is not returned in some cases when the result of the `DATE_ADD` and `DATE_SUB` function overflows [#11476](https://github.com/pingcap/tidb/pull/11476) -* Fix the issue that the conversion result is different from that in MySQL if the string contains an invalid character when a long string is converted to an integer [#11469](https://github.com/pingcap/tidb/pull/11469) -* Fix the issue that the result of the `REGEXP BINARY` function is incompatible with MySQL caused by case sensitiveness of this function [#11504](https://github.com/pingcap/tidb/pull/11504) -* Fix the issue that an error is reported when the `GRANT ROLE` statement receives `CURRENT_ROLE`; fix the issue that the `REVOKE ROLE` statement does not correctly revoke the `mysql.default_role` privilege [#11356](https://github.com/pingcap/tidb/pull/11356) -* Fix the display format issue of the `Incorrect datetime value` warning information when executing statements like `SELECT ADDDATE('2008-01-34', -1)` [#11447](https://github.com/pingcap/tidb/pull/11447) -* Fix the issue that the error message reports `constant … overflows float` rather than `constant … overflows bigint` if the result overflows when a float field of the JSON data is converted to an integer [#11534](https://github.com/pingcap/tidb/pull/11534) -* Fix the issue that the result might be wrong caused by incorrect type conversion when the `DATE_ADD` function receives `FLOAT`, `DOUBLE` and `DECIMAL` column parameters [#11527](https://github.com/pingcap/tidb/pull/11527) -* Fix the wrong result caused by incorrectly processing the sign of the INTERVAL fraction in the `DATE_ADD` function [#11615](https://github.com/pingcap/tidb/pull/11615) -* Fix the incorrect query result when Index Lookup Join contains the prefix index caused by `Ranger` not correctly handling the prefix index [#11565](https://github.com/pingcap/tidb/pull/11565) -* Fix the issue that the "Incorrect arguments to NAME_CONST" message is reported if the `NAME_CONST` function is executed when the second parameter of `NAME_CONST` is a negative number [#11268](https://github.com/pingcap/tidb/pull/11268) -* Fix the issue that the result is incompatible with MySQL when an SQL statement involves computing the current time and the value is fetched multiple times; use the same value when fetching the current time for the same SQL statement [#11394](https://github.com/pingcap/tidb/pull/11394) -* Fix the issue that `Close` is not called for ChildExecutor when the `Close` of baseExecutor reports an error. This issue might lead to Goroutine leaks when the `KILL` statements do not take effect and ChildExecutor is not closed [#11576](https://github.com/pingcap/tidb/pull/11576) - -### Server -* Fix the issue that the auto-added value is 0 instead of the current timestamp when `LOAD DATA` processes the missing `TIMESTAMP` field in the CSV file [#11250](https://github.com/pingcap/tidb/pull/11250) -* Fix issues that the `SHOW CREATE USER` statement does not correctly check related privileges, and `USER` and `HOST` returned by `SHOW CREATE USER CURRENT_USER()` might be wrong [#11229](https://github.com/pingcap/tidb/pull/11229) -* Fix the issue that the returned result might be wrong when `executeBatch` is used in JDBC [#11290](https://github.com/pingcap/tidb/pull/11290) -* Reduce printing the log information of the streaming client when changing the TiKV server's port [#11370](https://github.com/pingcap/tidb/pull/11370) -* Optimize the logic of reconnecting the streaming client to the TiKV server so that the streaming client will not be blocked for a long time [#11372](https://github.com/pingcap/tidb/pull/11372) -* Add `REGION_ID` in `INFORMATION_SCHEMA.TIDB_HOT_REGIONS` [#11350](https://github.com/pingcap/tidb/pull/11350) -* Cancel the timeout duration of obtaining Region information from the PD API to ensure that obtaining Region information will not end in a failure when TiDB API http://{TiDBIP}:10080/regions/hot is called due to PD timeout when the number of Regions is large [#11383](https://github.com/pingcap/tidb/pull/11383) -* Fix the issue that Region related requests do not return partitioned table-related Regions in the HTTP API [#11466](https://github.com/pingcap/tidb/pull/11466) -* Modify some default parameters related to pessimistic locks, these modifications reduce the probability of locking timeout caused by slow operations when the user manually validates pessimistic locking [#11521](https://github.com/pingcap/tidb/pull/11521) - * Increase the default TTL of pessimistic locking from 30 seconds to 40 seconds - * Increase the maximum TTL from 60 seconds to 120 seconds - * Calculate the pessimistic locking duration from the first `LockKeys` request -* Change the `SendRequest` function logic in the TiKV client: try to immediately connect to another peer instead of keeping waiting when the connect cannot be built [#11531](https://github.com/pingcap/tidb/pull/11531) -* Optimize the Region cache: label the removed store as invalid when a store is moved while another store goes online with a same address, to update the store information in the cache as soon as possible [#11567](https://github.com/pingcap/tidb/pull/11567) -* Add the Region ID to the result returned by the `http://{TiDB_ADDRESS:TIDB_IP}/mvcc/key/{db}/{table}/{handle}` API [#11557](https://github.com/pingcap/tidb/pull/11557) -* Fix the issue that Scatter Table does not work caused by the Scatter Table API not escaping the Range key [#11298](https://github.com/pingcap/tidb/pull/11298) -* Optimize the Region cache: label the store where the Region exists as invalid when the correspondent store is inaccessible to avoid reduced query performance caused by accessing this store [#11498](https://github.com/pingcap/tidb/pull/11498) -* Fix the error that the table schema can still be obtained through the HTTP API after dropping the database with the same name multiple times [#11585](https://github.com/pingcap/tidb/pull/11585) - -### DDL -* Fix the issue that an error occurs when a non-string column with a zero length is being indexed [#11214](https://github.com/pingcap/tidb/pull/11214) -* Disallow modifying the columns with foreign key constraints and full-text indexes (Note: TiDB still supports foreign key constraints and full-text indexes in syntax only) [#11274](https://github.com/pingcap/tidb/pull/11274) -* Fix the issue that the index offset of the column might be wrong because the position changed by the `ALTER TABLE` statement and the default value of the column are used concurrently [#11346](https://github.com/pingcap/tidb/pull/11346) -* Fix two issues that occur when parsing JSON files: - * `int64` is used as the intermediate parsing result of `uint64` in `ConvertJSONToFloat`, which leads to the precision overflow error [#11433](https://github.com/pingcap/tidb/pull/11433) - * `int64` is used as the intermediate parsing result of `uint64` in `ConvertJSONToInt`, which leads to the precision overflow error [#11551](https://github.com/pingcap/tidb/pull/11551) -* Disallow dropping indexes on the auto-increment column to avoid that the auto-increment column might get an incorrect result [#11399](https://github.com/pingcap/tidb/pull/11399) -* Fix the following issues [#11492](https://github.com/pingcap/tidb/pull/11492): - * The character set and the collation of the column are not consistent when explicitly specifying the collation but not the character set - * The error is not correctly reported when there is a conflict between the character set and the collation that are specified by `ALTER TABLE … MODIFY COLUMN` - * Incompatibility with MySQL when using `ALTER TABLE … MODIFY COLUMN` to specify character sets and collations multiple times -* Add the trace details of the subquery to the result of the `TRACE` query [#11458](https://github.com/pingcap/tidb/pull/11458) -* Optimize the performance of executing `ADMIN CHECK TABLE` and greatly reduce its execution time [#11547](https://github.com/pingcap/tidb/pull/11547) -* Add the result returned by `SPLIT TABLE … REGIONS/INDEX` and make `TOTAL_SPLIT_REGION` and `SCATTER_FINISH_RATIO` display the number of Regions that have been split successfully before timeout in the result [#11484](https://github.com/pingcap/tidb/pull/11484) -* Fix the issue that the precision displayed by statements like `SHOW CREATE TABLE` is incomplete when `ON UPDATE CURRENT_TIMESTAMP` is the column attribute and the float precision is specified [#11591](https://github.com/pingcap/tidb/pull/11591) -* Fix the issue that the index result of the column cannot be correctly calculated when the expression of a virtual generated column contains another virtual generated column [#11475](https://github.com/pingcap/tidb/pull/11475) -* Fix the issue that the minus sign cannot be added after `VALUE LESS THAN` in the `ALTER TABLE … ADD PARTITION … ` statement [#11581](https://github.com/pingcap/tidb/pull/11581) - -### Monitor -* Fix the issue that data is not collected and reported because the `TiKVTxnCmdCounter` monitoring metric is not registered [#11316](https://github.com/pingcap/tidb/pull/11316) -* Add the `BindUsageCounter`, `BindTotalGauge` and `BindMemoryUsage` monitoring metrics for the Bind Info [#11467](https://github.com/pingcap/tidb/pull/11467) - - -## [3.0.1] 2019-07-16 -* Add the `tidb_wait_split_region_finish_backoff` session variable to control the backoff time of splitting Regions [#11166](https://github.com/pingcap/tidb/pull/11166) -* Support automatically adjusting the auto-incremental ID allocation step based on the load, and the auto-adjustment scope of the step is 1000~2000000 [#11006](https://github.com/pingcap/tidb/pull/11006) -* Add the `ADMIN PLUGINS ENABLE`/`ADMIN PLUGINS DISABLE` SQL statement to dynamically enable or disable plugins [#11157](https://github.com/pingcap/tidb/pull/11157) -* Add the session connection information in the audit plugin [#11013](https://github.com/pingcap/tidb/pull/11013) -* Add optimizer hint `MAX_EXECUTION_TIME`, which places a limit N (a timeout value in milliseconds) on how long a `SELECT` statement is permitted to execute before the server terminates it: [#11026](https://github.com/pingcap/tidb/pull/11026) -* Change the default behavior during the period of splitting Regions to wait for PD to finish scheduling [#11166](https://github.com/pingcap/tidb/pull/11166) -* Prohibit Window Functions from being cached in Prepare Plan Cache to avoid incorrect results in some cases [#11048](https://github.com/pingcap/tidb/pull/11048) -* Prohibit `ALTER` statements from modifying the definition of stored generated columns [#11068](https://github.com/pingcap/tidb/pull/11068) -* Disallow changing virtual generated columns to stored generated columns [#11068](https://github.com/pingcap/tidb/pull/11068) -* Disallow changing the generated column expression with indexes [#11068](https://github.com/pingcap/tidb/pull/11068) -* Support compiling TiDB on the ARM64 architecture [#11150](https://github.com/pingcap/tidb/pull/11150) -* Support modifying the collation of a database or a table, but the character set of the database/table has to be UTF-8 or utf8mb4 [#11086](https://github.com/pingcap/tidb/pull/11086) -* Fix the issue that an error is reported when the `SELECT` subquery in the `UPDATE … SELECT` statement fails to resolve the column in the `UPDATE` expression [#11252](https://github.com/pingcap/tidb/pull/11252) -* Fix the panic issue that happens when a column is queried on multiple times and the returned result is NULL during point queries [#11226](https://github.com/pingcap/tidb/pull/11226) -* Fix the data race issue caused by non-thread safe `rand.Rand` when using the `RAND` function [#11169](https://github.com/pingcap/tidb/pull/11169) -* Fix the bug that the memory usage of a SQL statement exceeds the threshold but the execution of this statement is not canceled in some cases when `oom-action="cancel"` is configured [#11004](https://github.com/pingcap/tidb/pull/11004) -* Fix the issue that when a query ends, `SHOW PROCESSLIST` shows that the memory usage is not `0` because the memory usage of MemTracker was not correctly cleaned [#10970](https://github.com/pingcap/tidb/pull/10970) -* Fix the bug that the result of comparing integers and non-integers is not correct in some cases [#11194](https://github.com/pingcap/tidb/pull/11194) -* Fix the bug that the query result is not correct when the query on table partitions contains a predicate in explicit transactions [#11196](https://github.com/pingcap/tidb/pull/11196) -* Fix the DDL job panic issue because `infoHandle` might be `NULL` [#11022](https://github.com/pingcap/tidb/pull/11022) -* Fix the issue that the query result is not correct because the queried column is not referenced in the subquery and is then wrongly pruned when running a nested aggregation query [#11020](https://github.com/pingcap/tidb/pull/11020) -* Fix the issue that the `Sleep` function does not respond to the `KILL` statement in time [#11028](https://github.com/pingcap/tidb/pull/11028) -* Fix the issue that the `DB` and `INFO` columns shown by the `SHOW PROCESSLIST` command are incompatible with MySQL [#11003](https://github.com/pingcap/tidb/pull/11003) -* Fix the system panic issue caused by the `FLUSH PRIVILEGES` statement when `skip-grant-table=true` is configured [#11027](https://github.com/pingcap/tidb/pull/11027) -* Fix the issue that the primary key statistics collected by `FAST ANALYZE` are not correct when the table primary key is an `UNSIGNED` integer [#11099](https://github.com/pingcap/tidb/pull/11099) -* Fix the issue that the "invalid key" error is reported by the `FAST ANALYZE` statement in some cases [#11098](https://github.com/pingcap/tidb/pull/11098) -* Fix the issue that the precision shown by the `SHOW CREATE TABLE` statement is incomplete when `CURRENT_TIMESTAMP` is used as the default value of the column and the decimal precision is specified [#11088](https://github.com/pingcap/tidb/pull/11088) -* Fix the issue that the function name is not in lowercase when window functions report an error to make it compatible with MySQL [#11118](https://github.com/pingcap/tidb/pull/11118) -* Fix the issue that TiDB fails to connect to TiKV and thus cannot provide service after the background thread of TiKV Client Batch gRPC panics [#11101](https://github.com/pingcap/tidb/pull/11101) -* Fix the issue that the variable is set incorrectly by `SetVar` because of the shallow copy of the string [#11044](https://github.com/pingcap/tidb/pull/11044) -* Fix the issue that the execution fails and an error is reported when the `INSERT … ON DUPLICATE` statement is applied on table partitions [#11231](https://github.com/pingcap/tidb/pull/11231) -* Pessimistic locking (experimental feature) - - Fix the issue that an incorrect result is returned because of the invalid lock on the row when point queries are run using the pessimistic locking and the returned data is empty [#10976](https://github.com/pingcap/tidb/pull/10976) - - Fix the issue that the query result is not correct because `SELECT … FOR UPDATE` does not use the correct TSO when using the pessimistic locking in the query [#11015](https://github.com/pingcap/tidb/pull/11015) -* Change the detection behavior from immediate conflict detection to waiting when an optimistic transaction meets a pessimistic lock to avoid worsening the lock conflict [#11051](https://github.com/pingcap/tidb/pull/11051) - -## [2.1.14] 2019-07-04 -* Fix wrong query results caused by column pruning in some cases [#11019](https://github.com/pingcap/tidb/pull/11019) -* Fix the wrongly displayed information in `db` and `info` columns of `show processlist` [#11000](https://github.com/pingcap/tidb/pull/11000) -* Fix the issue that `MAX_EXECUTION_TIME` as a SQL hint and global variable does not work in some cases [#10999](https://github.com/pingcap/tidb/pull/10999) -* Support automatically adjust the incremental step allocated by auto-increment ID based on the load [#10997](https://github.com/pingcap/tidb/pull/10997) -* Fix the issue that the `Distsql` memory information of `MemTracker` is not correctly cleaned when a query ends [#10971](https://github.com/pingcap/tidb/pull/10971) -* Add the `MEM` column in the `information_schema.processlist` table to describe the memory usage of a query [#10896](https://github.com/pingcap/tidb/pull/10896) -* Add the `max_execution_time` global system variable to control the maximum execution time of a query [#10940](https://github.com/pingcap/tidb/pull/10940) -* Fix the panic caused by using unsupported aggregate functions [#10911](https://github.com/pingcap/tidb/pull/10911) -* Add an automatic rollback feature for the last transaction when the `load data` statement fails [#10862](https://github.com/pingcap/tidb/pull/10862) -* Fix the issue that TiDB returns a wrong result in some cases when the `OOMAction` configuration item is set to `Cancel` [#11016](https://github.com/pingcap/tidb/pull/11016) -* Disable the `TRACE` statement to avoid the TiDB panic issue [#11039](https://github.com/pingcap/tidb/pull/11039) -* Add the `mysql.expr_pushdown_blacklist` system table that dynamically enables/disables pushing down specific functions to Coprocessor [#10998](https://github.com/pingcap/tidb/pull/10998) -* Fix the issue that the `ANY_VALUE` function does not work in the `ONLY_FULL_GROUP_BY` mode [#10994](https://github.com/pingcap/tidb/pull/10994) -* Fix the incorrect evaluation caused by not doing a deep copy when evaluating the user variable of the string type [#11043](https://github.com/pingcap/tidb/pull/11043) - -## [3.0.0] 2019-06-28 -## New Features -* Support Window Functions; compatible with all window functions in MySQL 8.0, including `NTILE`, `LEAD`, `LAG`, `PERCENT_RANK`, `NTH_VALUE`, `CUME_DIST`, `FIRST_VALUE` , `LAST_VALUE`, `RANK`, `DENSE_RANK`, and `ROW_NUMBER` -* Support Views (Experimental) -* Improve Table Partition - - Support Range Partition - - Support Hash Partition -* Add the plug-in framework, supporting plugins such as IP Whitelist (Enterprise feature) and Audit Log (Enterprise feature). -* Support the SQL Plan Management function to create SQL execution plan binding to ensure query stability (Experimental) - -## SQL Optimizer -* Optimize the `NOT EXISTS` subquery and convert it to `Anti Semi Join` to improve performance -* Optimize the constant propagation on the `Outer Join`, and add the optimization rule of `Outer Join` elimination to reduce non-effective computations and improve performance -* Optimize the `IN` subquery to execute `Inner Join` after aggregation to improve performance -* Optimize `Index Join` to adapt to more scenarios -* Improve the Partition Pruning optimization rule of Range Partition -* Optimize the query logic for `_tidb_rowid`to avoid full table scan and improve performance -* Match more prefix columns of the indexes when extracting access conditions of composite indexes if there are relevant columns in the filter to improve performance -* Improve the accuracy of cost estimates by using order correlation between columns -* Optimize `Join Reorder` based on the Greedy algorithm and the dynamic planning algorithm to improve accuracy for index selection using `Join` -* Support Skyline Pruning, with some rules to prevent the execution plan from relying too heavily on statistics to improve query stability -* Improve the accuracy of row count estimation for single-column indexes with NULL values -* Support `FAST ANALYZE` that randomly samples in each Region to avoid full table scan and improve performance with statistics collection -* Support the incremental Analyze operation on monotonically increasing index columns to improve performance with statistics collection -* Support using subqueries in the `DO` statement -* Support using `Index Join` in transactions -* Optimize `prepare`/`execute` to support DDL statements with no parameters -* Modify the system behaviour to auto load statistics when the `stats-lease` variable value is 0 -* Support exporting historical statistics -* Support the `dump`/`load` correlation of histograms - -## SQL Execution Engine -* Optimize log output: `EXECUTE` outputs user variables and `COMMIT` outputs slow query logs to facilitate troubleshooting -* Support the `EXPLAIN ANALYZE` function to improve SQL tuning usability -* Support the `admin show next_row_id` command to get the ID of the next row -* Add six built-in functions: `JSON_QUOTE`, `JSON_ARRAY_APPEND`, `JSON_MERGE_PRESERVE`, `BENCHMARK` ,`COALESCE`, and `NAME_CONST` -* Optimize control logics on the chunk size to dynamically adjust based on the query context, to reduce the SQL execution time and resource consumption -* Support tracking and controlling memory usage in three operators - `TableReader`, `IndexReader` and `IndexLookupReader` -* Optimize the Merge Join operator to support an empty `ON` condition -* Optimize write performance for single tables that contains too many columns -* Improve the performance of `admin show ddl jobs` by supporting scanning data in reverse order -* Add the `split table region` statement to manually split the table Region to alleviate the hotspot issue -* Add the `split index region` statement to manually split the index Region to alleviate the hotspot issue -* Add a blacklist to prohibit pushing down expressions to Coprocessor -* Optimize the `Expensive Query` log to print the SQL query in the log when it exceeds the configured limit of execution time or memory - -## DDL -* Support migrating from character set `utf8` to `utf8mb4` -* Change the default character set from`utf8` to `utf8mb4` -* Add the `alter schema` statement to modify the character set and the collation of the database -* Support ALTER algorithm `INPLACE`/`INSTANT` -* Support `SHOW CREATE VIEW` -* Support `SHOW CREATE USER` -* Support fast recovery of mistakenly deleted tables -* Support adjusting the number of concurrencies of ADD INDEX dynamically -* Add the `pre_split_regions` option that pre-allocates Regions when creating the table using the `CREATE TABLE` statement, to relieve write hot Regions caused by lots of writes after the table creation -* Support splitting Regions by the index and range of the table specified using SQL statements to relieve hotspot issues -* Add the `ddl_error_count_limit` global variable to limit the number of DDL task retries -* Add a feature to use `SHARD_ROW_ID_BITS` to scatter row IDs when the column contains an AUTO_INCREMENT attribute to relieve the hotspot issue -* Optimize the lifetime of invalid DDL metadata to speed up recovering the normal execution of DDL operations after upgrading the TiDB cluster - -## Transactions -* Support the pessimistic transaction model (Experimental) -* Optimize transaction processing logics to adapt to more scenarios: - - Change the default value `tidb_disable_txn_auto_retry` to `on`, which means non-auto committed transactions will not be retried - - Add the `tidb_batch_commit` system variable to split a transaction into multiple ones to be executed concurrently - - Add the `tidb_low_resolution_tso` system variable to control the number of TSOs to obtain in batches and reduce the number of times that transactions request for TSOs, to improve performance in scenarios with relatively low requirement of consistency - - Add the `tidb_skip_isolation_level_check` variable to control whether to report errors when the isolation level is set to SERIALIZABLE - - Modify the `tidb_disable_txn_auto_retry` system variable to make it work on all retryable errors - -## Permission Management -* Perform permission check on the `ANALYZE`, `USE`, `SET GLOBAL`, and `SHOW PROCESSLIST` statements -* Support Role Based Access Control (RBAC) (Experimental) - -## Server -* Optimize slow query logs - - Restructure the log format - - Optimize the log content - - Optimize the log query method to support using the `INFORMATION_SCHEMA.SLOW_QUERY` and `ADMIN SHOW SLOW` statements of the memory table to query slow query logs -* Develop a unified log format specification with restructured log system to facilitate collection and analysis by tools -* Support using SQL statements to manage Binlog services, including querying status, enabling Binlog, maintaining and sending Binlog strategies. -* Support using `unix_socket` to connect to the database -* Support `Trace` for SQL statements -* Support getting information for a TiDB instance via the `/debug/zip` HTTP interface to facilitate troubleshooting. -* Optimize monitoring items to facilitate troubleshooting: - - Add the `high_error_rate_feedback_total` monitoring item to monitor the difference between the actual data volume and the estimated data volume based on statistics - - Add a QPS monitoring item in the database dimension -* Optimize the system initialization process to only allow the DDL owner to perform the initialization. This reduces the startup time for initialization or upgrading. -* Optimize the execution logic of `kill query` to improve performance and ensure resource is release properly -* Add a startup option `config-check` to check the validity of the configuration file -* Add the `tidb_back_off_weight` system variable to control the backoff time of internal error retries -* Add the `wait_timeout`and `interactive_timeout` system variables to control the maximum idle connections allowed -* Add the connection pool for TiKV to shorten the connection establishing time - -## Compatibility -* Support the `ALLOW_INVALID_DATES` SQL mode -* Support the MySQL 320 Handshake protocol -* Support manifesting unsigned BIGINT columns as auto-increment columns -* Support the `SHOW CREATE DATABASE IF NOT EXISTS` syntax -* Optimize the fault tolerance of `load data` for CSV files -* Abandon the predicate pushdown operation when the filtering condition contains a user variable to improve the compatibility with MySQL's behavior of using user variables to simulate Window Functions - - -## [3.0.0-rc.3] 2019-06-21 -## SQL Optimizer -* Remove the feature of collecting virtual generated column statistics[#10629](https://github.com/pingcap/tidb/pull/10629) -* Fix the issue that the primary key constant overflows during point queries [#10699](https://github.com/pingcap/tidb/pull/10699) -* Fix the issue that using uninitialized information in `fast analyze` causes panic [#10691](https://github.com/pingcap/tidb/pull/10691) -* Fix the issue that executing the `create view` statement using `prepare` causes panic because of wrong column information [#10713](https://github.com/pingcap/tidb/pull/10713) -* Fix the issue that the column information is not cloned when handling window functions [#10720](https://github.com/pingcap/tidb/pull/10720) -* Fix the wrong estimation for the selectivity rate of the inner table selection in index join [#10854](https://github.com/pingcap/tidb/pull/10854) -* Support automatic loading statistics when the `stats-lease` variable value is 0 [#10811](https://github.com/pingcap/tidb/pull/10811) - -## Execution Engine -* Fix the issue that resources are not correctly released when calling the `Close` function in `StreamAggExec` [#10636](https://github.com/pingcap/tidb/pull/10636) -* Fix the issue that the order of `table_option` and `partition_options` is incorrect in the result of executing the `show create table` statement for partitioned tables [#10689](https://github.com/pingcap/tidb/pull/10689) -* Improve the performance of `admin show ddl jobs` by supporting scanning data in reverse order [#10687](https://github.com/pingcap/tidb/pull/10687) -* Fix the issue that the result of the `show grants` statement in RBAC is incompatible with that of MySQL when this statement has the `current_user` field [#10684](https://github.com/pingcap/tidb/pull/10684) -* Fix the issue that UUIDs might generate duplicate values ​​on multiple nodes [#10712](https://github.com/pingcap/tidb/pull/10712) -* Fix the issue that the `show view` privilege is not considered in `explain` [#10635](https://github.com/pingcap/tidb/pull/10635) -* Add the `split table region` statement to manually split the table Region to alleviate the hotspot issue [#10765](https://github.com/pingcap/tidb/pull/10765) -* Add the `split index region` statement to manually split the index Region to alleviate the hotspot issue [#10764](https://github.com/pingcap/tidb/pull/10764) -* Fix the incorrect execution issue when you execute multiple statements such as `create user`, `grant`, or `revoke` consecutively [#10737](https://github.com/pingcap/tidb/pull/10737) -* Add a blacklist to prohibit pushing down expressions to Coprocessor [#10791](https://github.com/pingcap/tidb/pull/10791) -* Add the feature of printing the `expensive query` log when a query exceeds the memory configuration limit [#10849](https://github.com/pingcap/tidb/pull/10849) -* Add the `bind-info-lease` configuration item to control the update time of the modified binding execution plan [#10727](https://github.com/pingcap/tidb/pull/10727) -* Fix the OOM issue in high concurrent scenarios caused by the failure to quickly release Coprocessor resources, resulted from the `execdetails.ExecDetails` pointer [#10832](https://github.com/pingcap/tidb/pull/10832) -* Fix the panic issue caused by the `kill` statement in some cases [#10876](https://github.com/pingcap/tidb/pull/10876) -## Server -* Fix the issue that goroutine might leak when repairing GC [#10683](https://github.com/pingcap/tidb/pull/10683) -* Support displaying the `host` information in slow queries [#10693](https://github.com/pingcap/tidb/pull/10693) -* Support reusing idle links that interact with TiKV [#10632](https://github.com/pingcap/tidb/pull/10632) -* Fix the support for enabling the `skip-grant-table` option in RBAC [#10738](https://github.com/pingcap/tidb/pull/10738) -* Fix the issue that `pessimistic-txn` configuration goes invalid [#10825](https://github.com/pingcap/tidb/pull/10825) -* Fix the issue that the actively cancelled ticlient requests are still retried [#10850](https://github.com/pingcap/tidb/pull/10850) -* Improve performance in the case where pessimistic transactions conflict with optimistic transactions [#10881](https://github.com/pingcap/tidb/pull/10881) -## DDL -* Fix the issue that modifying charset using `alter table` causes the `blob` type change [#10698](https://github.com/pingcap/tidb/pull/10698) -* Add a feature to use `SHARD_ROW_ID_BITS` to scatter row IDs when the column contains an `AUTO_INCREMENT` attribute to alleviate the hotspot issue [#10794](https://github.com/pingcap/tidb/pull/10794) -* Prohibit adding stored generated columns by using the `alter table` statement [#10808](https://github.com/pingcap/tidb/pull/10808) -* Optimize the invalid survival time of DDL metadata to shorten the period during which the DDL operation is slower after cluster upgrade [#10795](https://github.com/pingcap/tidb/pull/10795) - -## [2.1.13] 2019-06-21 -* Add a feature to use `SHARD_ROW_ID_BITS` to scatter row IDs when the column contains an `AUTO_INCREMENT` attribute to relieve the hotspot issue [#10788](https://github.com/pingcap/tidb/pull/10788) -* Optimize the lifetime of invalid DDL metadata to speed up recovering the normal execution of DDL operations after upgrading the TiDB cluster [#10789](https://github.com/pingcap/tidb/pull/10789) -* Fix the OOM issue in high concurrent scenarios caused by the failure to quickly release Coprocessor resources, resulted from the `execdetails.ExecDetails` pointer [#10833](https://github.com/pingcap/tidb/pull/10833) -* Add the `update-stats` configuration item to control whether to update statistics [#10772](https://github.com/pingcap/tidb/pull/10772) -* Add the following TiDB-specific syntax to support Region presplit to solve the hotspot issue: - - Add the `PRE_SPLIT_REGIONS` table option [#10863](https://github.com/pingcap/tidb/pull/10863) - - Add the `SPLIT TABLE table_name INDEX index_name` syntax [#10865](https://github.com/pingcap/tidb/pull/10865) - - Add the `SPLIT TABLE [table_name] BETWEEN (min_value...) AND (max_value...) REGIONS [region_num]` syntax [#10882](https://github.com/pingcap/tidb/pull/10882) -* Fix the panic issue caused by the `KILL` syntax in some cases [#10879](https://github.com/pingcap/tidb/pull/10879) -* Improve the compatibility with MySQL for `ADD_DATE` in some cases [#10718](https://github.com/pingcap/tidb/pull/10718) -* Fix the wrong estimation for the selectivity rate of the inner table selection in index join [#10856](https://github.com/pingcap/tidb/pull/10856) - -## [2.1.12] 2019-06-13 -* Fix the issue caused by unmatched data types when using the index query feedback [#10755](https://github.com/pingcap/tidb/pull/10755) -* Fix the issue that the blob column is changed to the text column caused by charset altering in some cases [#10745](https://github.com/pingcap/tidb/pull/10745) -* Fix the issue that the `GRANT` operation in the transaction mistakenly reports “Duplicate Entry” in some cases [#10739](https://github.com/pingcap/tidb/pull/10739) -* Improve the compatibility with MySQL of the following features - - The `DAYNAME` function [#10732](https://github.com/pingcap/tidb/pull/10732) - - The `MONTHNAME` function [#10733](https://github.com/pingcap/tidb/pull/10733) - - Support the 0 value for the `EXTRACT` function when processing `MONTH` [#10702](https://github.com/pingcap/tidb/pull/10702) - - The `DECIMAL` type can be converted to `TIMESTAMP` or `DATETIME` [#10734](https://github.com/pingcap/tidb/pull/10734) -* Change the column charset while changing the table charset [#10714](https://github.com/pingcap/tidb/pull/10714) -* Fix the overflow issue when converting a decimal to a float in some cases [#10730](https://github.com/pingcap/tidb/pull/10730) -* Fix the issue that some extremely large messages report the “grpc: received message larger than max” error caused by inconsistent maximum sizes of messages sent/received by gRPC of TiDB and TiKV [#10710](https://github.com/pingcap/tidb/pull/10710) -* Fix the panic issue caused by `ORDER BY` not filtering NULL in some cases [#10488](https://github.com/pingcap/tidb/pull/10488) -* Fix the issue that values returned by the `UUID` function might be duplicate when multiple nodes exist [#10711](https://github.com/pingcap/tidb/pull/10711) -* Change the value returned by `CAST(-num as datetime)` from `error` to NULL [#10703](https://github.com/pingcap/tidb/pull/10703) -* Fix the issue that an unsigned histogram meets signed ranges in some cases [#10695](https://github.com/pingcap/tidb/pull/10695) -* Fix the issue that an error is reported mistakenly for reading data when the statistics feedback meets the bigint unsigned primary key [#10307](https://github.com/pingcap/tidb/pull/10307) -* Fix the issue that the result of `Show Create Table` for partitioned tables is not correctly displayed in some cases [#10690](https://github.com/pingcap/tidb/pull/10690) -* Fix the issue that the calculation result of the `GROUP_CONCAT` aggregate function is not correct for some correlated subqueries [#10670](https://github.com/pingcap/tidb/pull/10670) -* Fix the issue that the result of `Show Create Table` for partitioned tables is not correctly displayed in some cases [#10690](https://github.com/pingcap/tidb/pull/10690) - -## [2.1.11] 2019-05-31 - -* Fix the issue that incorrect schema is used for `delete from join` [#10595](https://github.com/pingcap/tidb/pull/10595) -* Fix the issue that the built-in `CONVERT()` may return incorrect field type [#10263](https://github.com/pingcap/tidb/pull/10263) -* Merge non-overlapped feedback when updating bucket count [#10569](https://github.com/pingcap/tidb/pull/10569) -* Fix calculation errors of `unix_timestamp()-unix_timestamp(now())` [#10491](https://github.com/pingcap/tidb/pull/10491) -* Fix the incompatibility issue of `period_diff` with MySQL 8.0 [#10501](https://github.com/pingcap/tidb/pull/10501) -* Skip `Virtual Column` when collecting statistics to avoid exceptions [#10628](https://github.com/pingcap/tidb/pull/10628) -* Support the `SHOW OPEN TABLES` statement [#10374](https://github.com/pingcap/tidb/pull/10374) -* Fix the issue that goroutine leak may happen in some cases [#10656](https://github.com/pingcap/tidb/pull/10656) -* Fix the issue that setting the `tidb_snapshot` variable in some cases may cause incorrect parsing of time format [#10637](https://github.com/pingcap/tidb/pull/10637) - -## [3.0.0-rc.2] 2019-05-28 -### SQL Optimizer -* Support Index Join in more scenarios -[#10540](https://github.com/pingcap/tidb/pull/10540) -* Support exporting historical statistics [#10291](https://github.com/pingcap/tidb/pull/10291) -* Support the incremental `Analyze` operation on monotonically increasing index columns -[#10355](https://github.com/pingcap/tidb/pull/10355) -* Neglect the NULL value in the `Order By` clause [#10488](https://github.com/pingcap/tidb/pull/10488) -* Fix the wrong schema information calculation of the `UnionAll` logical operator when simplifying the column information [#10384](https://github.com/pingcap/tidb/pull/10384) -* Avoid modifying the original expression when pushing down the `Not` operator [#10363](https://github.com/pingcap/tidb/pull/10363/files) -* Support the `dump`/`load` correlation of histograms [#10573](https://github.com/pingcap/tidb/pull/10573) -### Execution Engine -* Handle virtual columns with a unique index properly when fetching duplicate rows in `batchChecker` [#10370](https://github.com/pingcap/tidb/pull/10370) -* Fix the scanning range calculation issue for the `CHAR` column [#10124](https://github.com/pingcap/tidb/pull/10124) -* Fix the issue of `PointGet` incorrectly processing negative numbers [#10113](https://github.com/pingcap/tidb/pull/10113) -* Merge `Window` functions with the same name to improve execution efficiency [#9866](https://github.com/pingcap/tidb/pull/9866) -* Allow the `RANGE` frame in a `Window` function to contain no `OrderBy` clause [#10496](https://github.com/pingcap/tidb/pull/10496) - -### Server -Fix the issue that TiDB continuously creates a new connection to TiKV when a fault occurs in TiKV [#10301](https://github.com/pingcap/tidb/pull/10301) -Make `tidb_disable_txn_auto_retry` affect all retryable errors instead of only write conflict errors [#10339](https://github.com/pingcap/tidb/pull/10339) -Allow DDL statements without parameters to be executed using `prepare`/`execute` [#10144](https://github.com/pingcap/tidb/pull/10144) -Add the `tidb_back_off_weight` variable to control the backoff time [#10266](https://github.com/pingcap/tidb/pull/10266) -Prohibit TiDB retrying non-automatically committed transactions in default conditions by setting the default value of `tidb_disable_txn_auto_retry` to `on` [#10266](https://github.com/pingcap/tidb/pull/10266) -Fix the database privilege judgment of `role` in `RBAC` [#10261](https://github.com/pingcap/tidb/pull/10261) -Support the pessimistic transaction model (experimental) [#10297](https://github.com/pingcap/tidb/pull/10297) -Reduce the wait time for handling lock conflicts in some cases [#10006](https://github.com/pingcap/tidb/pull/10006) -Make the Region cache able to visit follower nodes when a fault occurs in the leader node [#10256](https://github.com/pingcap/tidb/pull/10256) -Add the `tidb_low_resolution_tso` variable to control the number of TSOs obtained in batches and reduce the times of transactions obtaining TSO to adapt for scenarios where data consistency is not so strictly required [#10428](https://github.com/pingcap/tidb/pull/10428) - -### DDL -Fix the uppercase issue of the charset name in the storage of the old version of TiDB -[#10272](https://github.com/pingcap/tidb/pull/10272) -Support `preSplit` of table partition, which pre-allocates table Regions when creating a table to avoid write hotspots after the table is created -[#10221](https://github.com/pingcap/tidb/pull/10221) -Fix the issue that TiDB incorrectly updates the version information in PD in some cases [#10324](https://github.com/pingcap/tidb/pull/10324) -Support modifying the charset and collation using the `ALTER DATABASE` statement -[#10393](https://github.com/pingcap/tidb/pull/10393) -Support splitting Regions based on the index and range of the specified table to relieve hotspot issues -[#10203](https://github.com/pingcap/tidb/pull/10203) -Prohibit modifying the precision of the decimal column using the `alter table` statement -[#10433](https://github.com/pingcap/tidb/pull/10433) -Fix the restriction for expressions and functions in hash partition -[#10273](https://github.com/pingcap/tidb/pull/10273) -Fix the issue that adding indexes in a table that contains partitions will in some cases cause TiDB panic -[#10475](https://github.com/pingcap/tidb/pull/10475) -Validate table information before executing the DDL to avoid invalid table schemas -[#10464](https://github.com/pingcap/tidb/pull/10464) -Enable hash partition by default; and enable range columns partition when there is only one column in the partition definition -[#9936](https://github.com/pingcap/tidb/pull/9936) - - -## [2.1.10] 2019-05-21 -* Fix the issue that some abnormalities cause incorrect table schema when using `tidb_snapshot` to read the history data [#10359](https://github.com/pingcap/tidb/pull/10359) -* Fix the issue that the `NOT` function causes wrong read results in some cases [#10363](https://github.com/pingcap/tidb/pull/10363) -* Fix the wrong behavior of `Generated Column` in the `Replace` or `Insert on duplicate update` statement [#10385](https://github.com/pingcap/tidb/pull/10385) -* Fix a bug of the `BETWEEN` function in the `DATE`/`DATETIME` comparison [#10407](https://github.com/pingcap/tidb/pull/10407) -* Fix the issue that a single line of a slow log that is too long causes an error report when using the `SLOW_QUERY` table to query a slow log [#10412](https://github.com/pingcap/tidb/pull/10412) -* Fix the issue that the result of `DATETIME ` plus `INTERVAL` is not the same with that of MySQL in some cases [#10416](https://github.com/pingcap/tidb/pull/10416), [#10418](https://github.com/pingcap/tidb/pull/10418) -* Add the check for the invalid time of February in a leap year [#10417](https://github.com/pingcap/tidb/pull/10417) -* Execute the internal initialization operation limitation only in the DDL owner to avoid a large number of conflict error reports when initializing the cluster [#10426](https://github.com/pingcap/tidb/pull/10426) -* Fix the issue that `DESC` is incompatible with MySQL when the default value of the output timestamp column is `default current_timestamp on update current_timestamp` [#10337](https://github.com/pingcap/tidb/issues/10337) -* Fix the issue that an error occurs during the privilege check in the `Update` statement [#10439](https://github.com/pingcap/tidb/pull/10439) -* Fix the issue that wrong calculation of `RANGE` causes a wrong result in the `CHAR` column in some cases [#10455](https://github.com/pingcap/tidb/pull/10455) -* Fix the issue that the data might be overwritten after decreasing `SHARD_ROW_ID_BITS` [#9868](https://github.com/pingcap/tidb/pull/9868) -* Fix the issue that `ORDER BY RAND()` does not return random numbers [#10064](https://github.com/pingcap/tidb/pull/10064) -* Prohibit the `ALTER` statement modifying the precision of decimals [#10458](https://github.com/pingcap/tidb/pull/10458) -* Fix the compatibility issue of the `TIME_FORMAT` function with MySQL [#10474](https://github.com/pingcap/tidb/pull/10474) -* Check the parameter validity of `PERIOD_ADD` [#10430](https://github.com/pingcap/tidb/pull/10430) -* Fix the issue that the behavior of the invalid `YEAR` string in TiDB is incompatible with that in MySQL [#10493](https://github.com/pingcap/tidb/pull/10493) -* Support the `ALTER DATABASE` syntax [#10503](https://github.com/pingcap/tidb/pull/10503) -* Fix the issue that the `SLOW_QUERY` memory engine reports an error when no `;` exists in the slow query statement [#10536](https://github.com/pingcap/tidb/pull/10536) -* Fix the issue that the `Add index` operation in partitioned tables cannot be canceled in some cases [#10533](https://github.com/pingcap/tidb/pull/10533) -* Fix the issue that the OOM panic cannot be recovered in some cases [#10545](https://github.com/pingcap/tidb/pull/10545) -* Improve the security of the DDL operation rewriting the table metadata [#10547](https://github.com/pingcap/tidb/pull/10547) - -## [3.0.0-rc.1] 2019-05-10 - -### SQL Optimizer -* Improve the accuracy of cost estimates by using order correlation between columns; introduce a heuristic parameter `tidb_opt_correlation_exp_factor` to control the preference for index scans for scenarios when correlation cannot be directly used for estimation. [#9839](https://github.com/pingcap/tidb/pull/9839) -* Match more prefix columns of the indexes when extracting access conditions of composite indexes if there are relevant columns in the filter [#10053](https://github.com/pingcap/tidb/pull/10053) -* Use the dynamic programming algorithm to specify the execution order of join operations when the number of tables participating in the join is less than the value of `tidb_opt_join_reorder_threshold`. [#8816](https://github.com/pingcap/tidb/pull/8816) -* Match more prefix columns of the indexes in the inner tables that build the index join when using composite indexes as the access conditions [#8471](https://github.com/pingcap/tidb/pull/8471) -* Improve the accuracy of row count estimation for single-column indexes with NULL values [#9474](https://github.com/pingcap/tidb/pull/9474) -* Specially handle `GROUP_CONCAT` when eliminating aggregate functions during the logical optimization phase to prevent incorrect executions [#9967](https://github.com/pingcap/tidb/pull/9967) -* Properly push the filter down to child nodes of the join operator if the filter is a constant [#9848](https://github.com/pingcap/tidb/pull/9848) -* Specially handle some functions such as `RAND()` when pruning columns during the logical optimization phase to prevent incompatibilities with MySQL [#10064](https://github.com/pingcap/tidb/pull/10064) -* Support `FAST ANALYZE`, which speeds up statistics collection by sampling the region instead of scanning the entire region. This feature is controlled by the variable `tidb_enable_fast_analyze`. [#10258](https://github.com/pingcap/tidb/pull/10258) -* Support SQL Plan Management, which ensures execution stability by performing execution plan binding for SQL statements. This feature is currently in beta and only supports bound execution plans for SELECT statements. It is not recommended to use it in the production environment. [#10284](https://github.com/pingcap/tidb/pull/10284) -### Execution Engine -* Support tracking and controlling memory usage in three operators - `TableReader`, `IndexReader` and `IndexLookupReader` -[#10003](https://github.com/pingcap/tidb/pull/10003) -* Support showing more information about coprocessor tasks in the slow log such as the number of tasks in coprocessor, the average/longest/90% of execution/waiting time and the addresses of the TiKVs which take the longest execution time or waiting time [#10165](https://github.com/pingcap/tidb/pull/10165) -* Support the prepared DDL statements with no placeholders [#10144](https://github.com/pingcap/tidb/pull/10144) -### Server -* Only allow the DDL owner to execute bootstrap when TiDB is started [#10029](https://github.com/pingcap/tidb/pull/10029) -* Add the variable `tidb_skip_isolation_level_check` to prevent TiDB from reporting errors when setting the transaction isolation level to SERIALIZABLE [#10065](https://github.com/pingcap/tidb/pull/10065) -* Merge the implicit commit time and the SQL execution time in the slow log [#10294](https://github.com/pingcap/tidb/pull/10294) -* Support for SQL Roles (RBAC Privilege Management) - - Support `SHOW GRANT` [#10016](https://github.com/pingcap/tidb/pull/10016) - - Support `SET DEFAULT ROLE` [#9949](https://github.com/pingcap/tidb/pull/9949) - - Support `GRANT ROLE` [#9721](https://github.com/pingcap/tidb/pull/9721) -* Fix the `ConnectionEvent` error from the `whitelist` plugin that makes TiDB exit [#9889](https://github.com/pingcap/tidb/pull/9889) -* Fix the issue of mistakenly adding read-only statements to the transaction history [#9723](https://github.com/pingcap/tidb/pull/9723) -* Improve `kill` statements to stop SQL execution and release resources more quickly [#9844](https://github.com/pingcap/tidb/pull/9844) -* Add a startup option `config-check` to check the validity of the configuration file [#9855](https://github.com/pingcap/tidb/pull/9855) -* Fix the validity check of inserting NULL fields when the strict SQL mode is disabled [#10161](https://github.com/pingcap/tidb/pull/10161) -### DDL -* Add the `pre_split_regions` option for `CREATE TABLE` statements; this option supports pre-splitting the Table Region when creating a table to avoid write hot spots caused by lots of writes after the table creation [#10138](https://github.com/pingcap/tidb/pull/10138) -* Optimize the execution performance of some DDL statements [#10170](https://github.com/pingcap/tidb/pull/10170) -* Add the warning that full-text indexes are not supported for `FULLTEXT KEY` [#9821](https://github.com/pingcap/tidb/pull/9821) -* Fix the compatibility issue for the UTF8 and UTF8MB4 charsets in the old versions of TiDB [#9820](https://github.com/pingcap/tidb/pull/9820) -* Fix the potential bug in `shard_row_id_bits` of a table [#9868](https://github.com/pingcap/tidb/pull/9868) -* Fix the bug that the column charset is not changed after the table charset is changed [#9790](https://github.com/pingcap/tidb/pull/9790) -* Fix a potential bug in `SHOW COLUMN` when using `BINARY`/`BIT` as the column default value [#9897](https://github.com/pingcap/tidb/pull/9897) -* Fix the compatibility issue in displaying `CHARSET`/`COLLATION` descriptions in the `SHOW FULL COLUMNS` statement [#10007](https://github.com/pingcap/tidb/pull/10007) -* Fix the issue that the `SHOW COLLATIONS` statement only lists collations supported by TiDB [#10186](https://github.com/pingcap/tidb/pull/10186) - - -## [2.1.9] 2019-05-06 -* Fix compatibility of the `MAKETIME` function when unsigned type overflows [#10089](https://github.com/pingcap/tidb/pull/10089) -* Fix the stack overflow caused by constant folding in some cases [#10189](https://github.com/pingcap/tidb/pull/10189) -* Fix the privilege check issue for `Update` when an alias exists in some cases [#10157](https://github.com/pingcap/tidb/pull/10157), [#10326](https://github.com/pingcap/tidb/pull/10326) -* Track and control memory usage in DistSQL [#10197](https://github.com/pingcap/tidb/pull/10197) -* Support specifying collation as `utf8mb4_0900_ai_ci` [#10201](https://github.com/pingcap/tidb/pull/10201) -* Fix the wrong result issue of the `MAX` function when the primary key is of the Unsigned type [#10209](https://github.com/pingcap/tidb/pull/10209) -* Fix the issue that NULL values can be inserted into NOT NULL columns in the non-strict SQL mode [#10254](https://github.com/pingcap/tidb/pull/10254) -* Fix the wrong result issue of the `COUNT` function when multiple columns exist in `DISTINCT` [#10270](https://github.com/pingcap/tidb/pull/10270) -* Fix the panic issue occurred when `LOAD DATA` parses irregular CSV files [#10269](https://github.com/pingcap/tidb/pull/10269) -* Ignore the overflow error when the outer and inner join key types are inconsistent in `Index Lookup Join` [#10244](https://github.com/pingcap/tidb/pull/10244) -* Fix the issue that a statement is wrongly judged as point-get in some cases [#10299](https://github.com/pingcap/tidb/pull/10299) -* Fix the wrong result issue when the time type does not convert the time zone in some cases [#10345](https://github.com/pingcap/tidb/pull/10345) -* Fix the issue that TiDB character set cases are inconsistent in some cases [#10354](https://github.com/pingcap/tidb/pull/10354) -* Support controlling the number of rows returned by operator [#9166](https://github.com/pingcap/tidb/issues/9166) - - `Selection` & `Projection` [#10110](https://github.com/pingcap/tidb/pull/10110) - - `StreamAgg` & `HashAgg` [#10133](https://github.com/pingcap/tidb/pull/10133) - - `TableReader` & `IndexReader` & `IndexLookup` [#10169](https://github.com/pingcap/tidb/pull/10169) -* Improve the slow query log: - - Add `SQL Digest` to distinguish similar SQL [#10093](https://github.com/pingcap/tidb/pull/10093) - - Add version information of statistics used by slow query statements [#10220](https://github.com/pingcap/tidb/pull/10220) - - Show memory consumption of a statement in slow query log [#10246](https://github.com/pingcap/tidb/pull/10246) - - Adjust the output format of Coprocessor related information so it can be parsed by pt-query-digest [#10300](https://github.com/pingcap/tidb/pull/10300) - - Fix the `#` character issue in slow query statements [#10275](https://github.com/pingcap/tidb/pull/10275) - - Add some information columns to the memory table of slow query statements [#10317](https://github.com/pingcap/tidb/pull/10317) - - Add the transaction commit time to slow query log [#10310](https://github.com/pingcap/tidb/pull/10310) - - Fix the issue some time formats cannot be parsed by pt-query-digest [#10323](https://github.com/pingcap/tidb/pull/10323) - -## [2.1.8] 2019-04-12 - -* Fix the issue that the processing logic of `GROUP_CONCAT` function is incompatible with MySQL when there is a NULL-valued parameter [#9930](https://github.com/pingcap/tidb/pull/9930) -* Fix the equality check issue of decimal values in the `Distinct` mode [#9931](https://github.com/pingcap/tidb/pull/9931) -* Fix the collation compatibility issue of the date, datetime, and timestamp types for the `SHOW FULL COLUMNS` statement - - [#9938](https://github.com/pingcap/tidb/pull/9938) - - [#10114](https://github.com/pingcap/tidb/pull/10114) -* Fix the issue that the row count estimation is inaccurate when the filtering condition contains correlated columns [#9937](https://github.com/pingcap/tidb/pull/9937) -* Fix the compatibility issue between the `DATE_ADD` and `DATE_SUB` functions - - [#9963](https://github.com/pingcap/tidb/pull/9963) - - [#9966](https://github.com/pingcap/tidb/pull/9966) -* Support the `%H` format for the `STR_TO_DATE` function to improve compatibility [#9964](https://github.com/pingcap/tidb/pull/9964) -* Fix the issue that the result is wrong when the `GROUP_CONCAT` function groups by a unique index [#9969](https://github.com/pingcap/tidb/pull/9969) -* Return a warning when the Optimizer Hints contains an unmatched table name [#9970](https://github.com/pingcap/tidb/pull/9970) -* Unify the log format to facilitate collecting logs using tools for analysis Unified Log Format -* Fix the issue that a lot of NULL values cause inaccurate statistics estimation [#9979](https://github.com/pingcap/tidb/pull/9979) -* Fix the issue that an error is reported when the default value of the TIMESTAMP type is the boundary value [#9987](https://github.com/pingcap/tidb/pull/9987) -* Validate the value of `time_zone` [#10000](https://github.com/pingcap/tidb/pull/10000) -* Support the `2019.01.01` time format [#10001](https://github.com/pingcap/tidb/pull/10001) -* Fix the issue that the row count estimation is displayed incorrectly in the result returned by the `EXPLAIN` statement in some cases [#10044](https://github.com/pingcap/tidb/pull/10044) -* Fix the issue that `KILL TIDB [session id]` cannot instantly stop the execution of a statement in some cases [#9976](https://github.com/pingcap/tidb/pull/9976) -* Fix the predicate pushdown issue of constant filtering conditions in some cases [#10049](https://github.com/pingcap/tidb/pull/10049) -* Fix the issue that a read-only statement is not processed correctly in some cases [#10048](https://github.com/pingcap/tidb/pull/10048) - -## [2.1.7] 2019-03-27 - -* Fix the issue of longer startup time when upgrading the program caused by canceling DDL operations [#9768](https://github.com/pingcap/tidb/pull/9768) -* Fix the issue that the `check-mb4-value-in-utf8` configuration item is in the wrong position in the `config.example.toml` file [#9852](https://github.com/pingcap/tidb/pull/9852) -* Improve the compatibility of the `str_to_date` built-in function with MySQL [#9817](https://github.com/pingcap/tidb/pull/9817) -* Fix the compatibility issue of the `last_day` built-in function [#9750](https://github.com/pingcap/tidb/pull/9750) -* Add the `tidb_table_id` column for `infoschema.tables` to facilitate getting `table_id` by using SQL statements and add the `tidb_indexes` system table to manage the relationship between Table and Index [#9862](https://github.com/pingcap/tidb/pull/9862) -* Add a check about the null definition of Table Partition [#9663](https://github.com/pingcap/tidb/pull/9663) -* Change the privileges required by `Truncate Table` from `Delete` to `Drop` to make it consistent with MySQL [#9876](https://github.com/pingcap/tidb/pull/9876) -* Support using subqueries in the `DO` statement [#9877](https://github.com/pingcap/tidb/pull/9877) -* Fix the issue that the `default_week_format` variable does not take effect in the `week` function [#9753](https://github.com/pingcap/tidb/pull/9753) -* Support the plugin framework [#9880](https://github.com/pingcap/tidb/pull/9880), [#9888](https://github.com/pingcap/tidb/pull/9888) -* Support checking the enabling state of binlog by using the `log_bin` system variable [#9634](https://github.com/pingcap/tidb/pull/9634) -* Support checking the Pump/Drainer status by using SQL statements [#9896](https://github.com/pingcap/tidb/pull/9896) -* Fix the compatibility issue about checking mb4 character on utf8 when upgrading TiDB [#9887](https://github.com/pingcap/tidb/pull/9887) - -## [3.0.0-beta.1] - 2019-03-26 - -### SQL Optimizer -* Support calculating the Cartesian product by using `Sort Merge Join` [#9032](https://github.com/pingcap/tidb/pull/9037) -* Support Skyline Pruning, with some rules to prevent the execution plan from relying too heavily on statistics [#9337](https://github.com/pingcap/tidb/pull/9337) -* Support Window Functions - - `NTILE` [#9682](https://github.com/pingcap/tidb/pull/9682) - - `LEAD` and `LAG` [#9672](https://github.com/pingcap/tidb/pull/9672) - - `PERCENT_RANK` [#9671](https://github.com/pingcap/tidb/pull/9671) - - `NTH_VALUE` [#9596](https://github.com/pingcap/tidb/pull/9596) - - `CUME_DIST` [#9619](https://github.com/pingcap/tidb/pull/9619) - - `FIRST_VALUE` and `LAST_VALUE` [#9560](https://github.com/pingcap/tidb/pull/9560) - - `RANK` and `DENSE_RANK` [#9500](https://github.com/pingcap/tidb/pull/9500) - - `RANGE FRAMED` [#9450](https://github.com/pingcap/tidb/pull/9450) - - `ROW FRAMED` [#9358](https://github.com/pingcap/tidb/pull/9358) - - `ROW NUMBER` [#9098](https://github.com/pingcap/tidb/pull/9098) -* Add a type of statistic that indicates the order correlation between columns and the handle column [#9315](https://github.com/pingcap/tidb/pull/9315) -### SQL Execution Engine -* Add built-in functions: - - `JSON_QUOTE` [#7832](https://github.com/pingcap/tidb/pull/7832) - - `JSON_ARRAY_APPEND` [#9609](https://github.com/pingcap/tidb/pull/9609) - - `JSON_MERGE_PRESERVE` [#8931](https://github.com/pingcap/tidb/pull/8931) - - `BENCHMARK` [#9252](https://github.com/pingcap/tidb/pull/9252) - - `COALESCE` [#9087](https://github.com/pingcap/tidb/pull/9087) - - `NAME_CONST` [#9261](https://github.com/pingcap/tidb/pull/9261) -* Optimize the Chunk size based on the query context, to reduce the execution time of SQL statements and resources consumption of the cluster [#6489](https://github.com/pingcap/tidb/issues/6489) -### Privilege management -* Support `SET ROLE` and `CURRENT_ROLE` [#9581](https://github.com/pingcap/tidb/pull/9581) -* Support `DROP ROLE` [#9616](https://github.com/pingcap/tidb/pull/9616) -* Support `CREATE ROLE` [#9461](https://github.com/pingcap/tidb/pull/9461) -### Server -* Add the `/debug/zip` HTTP interface to get information of the current TiDB instance [#9651](https://github.com/pingcap/tidb/pull/9651) -* Support the `show pump status` and `show drainer status` SQL statements to check the Pump or Drainer status [9456](https://github.com/pingcap/tidb/pull/9456) -* Support modifying the Pump or Drainer status by using SQL statements [#9789](https://github.com/pingcap/tidb/pull/9789) -* Support adding HASH fingerprints to SQL text for easy tracking of slow SQL statements [#9662](https://github.com/pingcap/tidb/pull/9662) -* Add the `log_bin` system variable ("0" by default) to control the enabling state of binlog; only support checking the state currently [#9343](https://github.com/pingcap/tidb/pull/9343) -* Support managing the sending binlog strategy by using the configuration file [#9864](https://github.com/pingcap/tidb/pull/9864) -* Support querying the slow log by using the `INFORMATION_SCHEMA.SLOW_QUERY` memory table [#9290](https://github.com/pingcap/tidb/pull/9290) -* Change the MySQL version displayed in TiDB from 5.7.10 to 5.7.25 [#9553](https://github.com/pingcap/tidb/pull/9553) -* Unify the log format for easy collection and analysis by tools -* Add the `high_error_rate_feedback_total` monitoring item to record the difference between the actual data volume and the estimated data volume based on statistics [#9209](https://github.com/pingcap/tidb/pull/9209) -* Add the QPS monitoring item in the database dimension, which can be enabled by using a configuration item [#9151](https://github.com/pingcap/tidb/pull/9151) -### DDL -* Add the `ddl_error_count_limit` global variable ("512" by default) to limit the number of DDL task retries (If this number exceeds the limit, the DDL task is canceled) [#9295](https://github.com/pingcap/tidb/pull/9295) -* Support ALTER ALGORITHM `INPLACE`/`INSTANT` [#8811](https://github.com/pingcap/tidb/pull/8811) -* Support the `SHOW CREATE VIEW` statement [#9309](https://github.com/pingcap/tidb/pull/9309) -* Support the `SHOW CREATE USER` statement [#9240](https://github.com/pingcap/tidb/pull/9240) - -## [2.1.6] 2019-03-15 - -### SQL Optimizer/Executor -* Optimize planner to select the outer table based on cost when both tables are specified in Hint of `TIDB_INLJ` [#9615](https://github.com/pingcap/tidb/pull/9615) -* Fix the issue that `IndexScan` cannot be selected correctly in some cases -[#9587](https://github.com/pingcap/tidb/pull/9587) -* Fix incompatibility with MySQL of check in the `agg` function in subqueries [#9551](https://github.com/pingcap/tidb/pull/9551) -* Make `show stats_histograms` only output valid columns to avoid panics - [#9502](https://github.com/pingcap/tidb/pull/9502) -### Server -* Support the `log_bin` variable to enable/disable Binlog [#9634](https://github.com/pingcap/tidb/pull/9634) -* Add a sanity check for transactions to avoid false transaction commit [#9559](https://github.com/pingcap/tidb/pull/9559) -* Fix the issue that setting variables may lead to panic [#9539](https://github.com/pingcap/tidb/pull/9539) - -### DDL -* Fix the issue that the `Create Table Like` statement causes panic in some cases [#9652](https://github.com/pingcap/tidb/pull/9652) -* Enable the `AutoSync` feature of etcd clients to avoid connection issues between TiDB and etcd in some cases [#9600](https://github.com/pingcap/tidb/pull/9600) - - -## [2.1.5] 2019-02-28 - -### SQL Optimizer/Executor -* Make `SHOW CREATE TABLE` do not print the column charset information when the charset information of a column is the same with that of a table, to improve the compatibility of `SHOW CREATE TABLE` with MySQL [#9306](https://github.com/pingcap/tidb/pull/9306) -* Fix the panic or the wrong result of the `Sort` operator in some cases by extracting `ScalarFunc` from `Sort` to a `Projection` operator for computing to simplify the computing logic of `Sort` [#9319](https://github.com/pingcap/tidb/pull/9319) -* Remove the sorting field with constant values in the `Sort` operator [#9335](https://github.com/pingcap/tidb/pull/9335), [#9440](https://github.com/pingcap/tidb/pull/9440) -* Fix the data overflow issue when inserting data into an unsigned integer column [#9339](https://github.com/pingcap/tidb/pull/9339) -* Set `cast_as_binary` to `NULL` when the length of the target binary exceeds `max_allowed_packet` [#9349](https://github.com/pingcap/tidb/pull/9349) -* Optimize the constant folding process of `IF` and `IFNULL` [#9351](https://github.com/pingcap/tidb/pull/9351) -* Optimize the index selection of TiDB using skyline pruning to improve the stability of simple queries [#9356](https://github.com/pingcap/tidb/pull/9356) -* Support computing the selectivity of the `DNF` expression [#9405](https://github.com/pingcap/tidb/pull/9405) -* Fix the wrong SQL query result of `!=ANY()` and `=ALL()` in some cases [#9403](https://github.com/pingcap/tidb/pull/9403) -* Fix the panic or the wrong result when the Join Key types of two tables on which the `Merge Join` operation is performed are different [#9438](https://github.com/pingcap/tidb/pull/9438) -* Fix the issue that the result of the `RAND()` function is not compatible with MySQL [#9446](https://github.com/pingcap/tidb/pull/9446) -* Refactor the logic of `Semi Join` processing `NULL` and the empty result set to get the correct result and improve the compatibility with MySQL [#9449](https://github.com/pingcap/tidb/pull/9449) - -### Server -* Add the `tidb_constraint_check_in_place` system variable to check the data uniqueness constraint when executing the `INSERT` statement [#9401](https://github.com/pingcap/tidb/pull/9401) -* Fix the issue that the value of the `tidb_force_priority` system variable is different from that set in the configuration file [#9347](https://github.com/pingcap/tidb/pull/9347) -* Add the `current_db` field in general logs to print the name of the currently used database [#9346](https://github.com/pingcap/tidb/pull/9346) -* Add an HTTP API of obtaining the table information with the table ID [#9408](https://github.com/pingcap/tidb/pull/9408) -* Fix the issue that `LOAD DATA` loads incorrect data in some cases [#9414](https://github.com/pingcap/tidb/pull/9414) -* Fix the issue that it takes a long time to build a connection between the MySQL client and TiDB in some cases [#9451](https://github.com/pingcap/tidb/pull/9451) - -### DDL -* Fix some issues when canceling the `DROP COLUMN` operation [#9352](https://github.com/pingcap/tidb/pull/9352) -* Fix some issues when canceling the `DROP` or `ADD` partitioned table operation [#9376](https://github.com/pingcap/tidb/pull/9376) -* Fix the issue that `ADMIN CHECK TABLE` mistakenly reports the data index inconsistency in some cases [#9399](https://github.com/pingcap/tidb/pull/9399) -* Fix the time zone issue of the `TIMESTAMP` default value [#9108](https://github.com/pingcap/tidb/pull/9108) - -## [2.1.4] 2019-02-15 - -### SQL Optimizer/Executor - -* Fix the issue that the `VALUES` function does not handle the FLOAT type correctly [#9223](https://github.com/pingcap/tidb/pull/9223) -* Fix the wrong result issue when casting Float to String in some cases [#9227](https://github.com/pingcap/tidb/pull/9227) -* Fix the wrong result issue of the `FORMAT` function in some cases [#9235](https://github.com/pingcap/tidb/pull/9235) -* Fix the panic issue when handling the Join query in some cases [#9264](https://github.com/pingcap/tidb/pull/9264) -* Fix the issue that the `VALUES` function does not handle the ENUM type correctly [#9280](https://github.com/pingcap/tidb/pull/9280) -* Fix the wrong result issue of `DATE_ADD` / `DATE_SUB` in some cases [#9284](https://github.com/pingcap/tidb/pull/9284) - -### Server - -* Optimize the "reload privilege success" log and change it to the DEBUG level [#9274](https://github.com/pingcap/tidb/pull/9274) - -### DDL - -* Change `tidb_ddl_reorg_worker_cnt` and `tidb_ddl_reorg_batch_size` to global variables [#9134](https://github.com/pingcap/tidb/pull/9134) -* Fix the bug caused by adding an index to a generated column in some abnormal conditions [#9289](https://github.com/pingcap/tidb/pull/9289) - -## [2.1.3] 2019-01-25 - -### SQL Optimizer/Executor -* Fix the panic issue of Prepared Plan Cache in some cases [#8826](https://github.com/pingcap/tidb/pull/8826) -* Fix the issue that Range computing is wrong when the index is a prefix index [#8851](https://github.com/pingcap/tidb/pull/8851) -* Make `CAST(str AS TIME(N))` return null if the string is in the illegal `TIME` format when `SQL_MODE` is not strict [#8966](https://github.com/pingcap/tidb/pull/8966) -* Fix the panic issue of Generated Column during the process of `UPDATE` in some cases [#8980](https://github.com/pingcap/tidb/pull/8980) -* Fix the upper bound overflow issue of the statistics histogram in some cases [#8989](https://github.com/pingcap/tidb/pull/8989) -* Support Range for `_tidb_rowid` construction queries, to avoid full table scan and reduce cluster stress [#9059](https://github.com/pingcap/tidb/pull/9059) -* Return an error when the `CAST(AS TIME)` precision is too big [#9058](https://github.com/pingcap/tidb/pull/9058) -* Allow using `Sort Merge Join` in the Cartesian product [#9037](https://github.com/pingcap/tidb/pull/9037) -* Fix the issue that the statistics worker cannot resume after the panic in some cases [#9085](https://github.com/pingcap/tidb/pull/9085) -* Fix the issue that `Sort Merge Join` returns the wrong result in some cases [#9046](https://github.com/pingcap/tidb/pull/9046) -* Support returning the JSON type in the `CASE` clause [#8355](https://github.com/pingcap/tidb/pull/8355) -### Server -* Return a warning instead of an error when the non-TiDB hint exists in the comment [#8766](https://github.com/pingcap/tidb/pull/8766) -* Verify the validity of the configured TIMEZONE value [#8879](https://github.com/pingcap/tidb/pull/8879) -* Optimize the `QueryDurationHistogram` metrics item to display more statement types [#8875](https://github.com/pingcap/tidb/pull/8875) -* Fix the lower bound overflow issue of bigint in some cases [#8544](https://github.com/pingcap/tidb/pull/8544) -* Support the `ALLOW_INVALID_DATES` SQL mode [#9110](https://github.com/pingcap/tidb/pull/9110) -### DDL -* Fix a `RENAME TABLE` compatibility issue to keep the behavior consistent with that of MySQL [#8808](https://github.com/pingcap/tidb/pull/8808) -* Support making concurrent changes of `ADD INDEX` take effect immediately [#8786](https://github.com/pingcap/tidb/pull/8786) -* Fix the `UPDATE` panic issue during the process of `ADD COLUMN` in some cases [#8906](https://github.com/pingcap/tidb/pull/8906) -* Fix the issue of concurrently creating Table Partition in some cases [#8902](https://github.com/pingcap/tidb/pull/8902) -* Support converting the `utf8` character set to `utf8mb4` [#8951](https://github.com/pingcap/tidb/pull/8951) [#9152](https://github.com/pingcap/tidb/pull/9152) -* Fix the issue of Shard Bits overflow [#8976](https://github.com/pingcap/tidb/pull/8976) -* Support outputting the column character sets in `SHOW CREATE TABLE` [#9053](https://github.com/pingcap/tidb/pull/9053) -* Fix the issue of the maximum length limit of the varchar type column in `utf8mb4` [#8818](https://github.com/pingcap/tidb/pull/8818) -* Support `ALTER TABLE TRUNCATE TABLE PARTITION` [#9093](https://github.com/pingcap/tidb/pull/9093) -* Resolve the charset when the charset is not provided [#9147](https://github.com/pingcap/tidb/pull/9147) - -## [3.0.0-beta] - 2019-01-18 - -### New Features - -* Support View -* Support Window Function -* Support Range Partition -* Support Hash Partition - -### SQL Optimizer - -* Re-support the optimization rule of `AggregationElimination` [#7676](https://github.com/pingcap/tidb/pull/7676) -* Optimize the `NOT EXISTS` subquery and convert it to Anti Semi Join [#7842](https://github.com/pingcap/tidb/pull/7842) -* Add the `tidb_enable_cascades_planner` variable to support the new Cascades optimizer. Currently, the Cascades optimizer is not yet fully implemented and is turned off by default [#7879](https://github.com/pingcap/tidb/pull/7879) -* Support using Index Join in transactions [#7877](https://github.com/pingcap/tidb/pull/7877) -* Optimize the constant propagation on the Outer Join, so that the filtering conditions related to the Outer table in the Join result can be pushed down through the Outer Join to the Outer table, reducing the useless calculation of the Outer Join and improving the execution performance [#7794](https://github.com/pingcap/tidb/pull/7794) -* Adjust the optimization rule of Projection Elimination to the position after the Aggregation Elimination, to avoid redundant `Project` operators [#7909](https://github.com/pingcap/tidb/pull/7909) -* Optimize the `IFNULL` function and eliminate this function when the input parameter has a non-NULL attribute [#7924](https://github.com/pingcap/tidb/pull/7924) -* Support building range for `_tidb_rowid`, to avoid full table scan and reduce cluster stress [#8047](https://github.com/pingcap/tidb/pull/8047) -* Optimize the `IN` subquery to do the Inner Join after the aggregation, and add the `tidb_opt_insubq_to_join_and_agg` variable to control whether to enable this optimization rule and open it by default [#7531](https://github.com/pingcap/tidb/pull/7531) -* Support using subqueries in the `DO` statement [#8343](https://github.com/pingcap/tidb/pull/8343) -* Add the optimization rule of Outer Join elimination to reduce unnecessary table scan and Join operations and improve execution performance [#8021](https://github.com/pingcap/tidb/pull/8021) -* Modify the Hint behavior of the `TIDB_INLJ` optimizer, and the optimizer will use the table specified in Hint as the Inner table of Index Join [#8243](https://github.com/pingcap/tidb/pull/8243) -* Use `PointGet` in a wide range so that it can be used when the execution plan cache of the `Prepare` statement takes effect [#8108](https://github.com/pingcap/tidb/pull/8108) -* Introduce the greedy `Join Reorder` algorithm to optimize the join order selection when joining multiple tables [#8394](https://github.com/pingcap/tidb/pull/8394) -* Support View [#8757](https://github.com/pingcap/tidb/pull/8757) -* Support Window Function [#8630](https://github.com/pingcap/tidb/pull/8630) -* Return warning to the client when `TIDB_INLJ` is not in effect, to enhance usability [#9037](https://github.com/pingcap/tidb/pull/9037) -* Support deducing the statistics for filtered data based on filtering conditions and table statistics [#7921](https://github.com/pingcap/tidb/pull/7921) -* Improve the Partition Pruning optimization rule of Range Partition [#8885](https://github.com/pingcap/tidb/pull/8885) - -### SQL Executor - -* Optimize the `Merge Join` operator to support the empty `ON` condition [#9037](https://github.com/pingcap/tidb/pull/9037) -* Optimize the log and print the user variables used when executing the `EXECUTE` statement [#7684](https://github.com/pingcap/tidb/pull/7684) -* Optimize the log to print slow query information for the `COMMIT` statement [#7951](https://github.com/pingcap/tidb/pull/7951) -* Support the `EXPLAIN ANALYZE` feature to make the SQL tuning process easier [#7827](https://github.com/pingcap/tidb/pull/7827) -* Optimize the write performance of wide tables with many columns [#7935](https://github.com/pingcap/tidb/pull/7935) -* Support `admin show next_row_id` [#8242](https://github.com/pingcap/tidb/pull/8242) -* Add the `tidb_init_chunk_size` variable to control the size of the initial Chunk used by the execution engine [#8480](https://github.com/pingcap/tidb/pull/8480) -* Improve `shard_row_id_bits` and cross-check the auto-increment ID [#8936](https://github.com/pingcap/tidb/pull/8936) - -### `Prepare` Statement - -* Prohibit adding the `Prepare` statement containing subqueries to the query plan cache to guarantee the query plan is correct when different user variables are input [#8064](https://github.com/pingcap/tidb/pull/8064) -* Optimize the query plan cache to guarantee the plan can be cached when the statement contains non-deterministic functions [#8105](https://github.com/pingcap/tidb/pull/8105) -* Optimize the query plan cache to guarantee the query plan of `DELETE`/`UPDATE`/`INSERT` can be cached [#8107](https://github.com/pingcap/tidb/pull/8107) -* Optimize the query plan cache to remove the corresponding plan when executing the `DEALLOCATE` statement [#8332](https://github.com/pingcap/tidb/pull/8332) -* Optimize the query plan cache to avoid the TiDB OOM issue caused by caching too many plans by limiting the memory usage [#8339](https://github.com/pingcap/tidb/pull/8339) -* Optimize the `Prepare` statement to support using the `?` placeholder in the `ORDER BY`/`GROUP BY`/`LIMIT` clause [#8206](https://github.com/pingcap/tidb/pull/8206) - -### Privilege Management - -* Add the privilege check for the `ANALYZE` statement [#8486](https://github.com/pingcap/tidb/pull/8486) -* Add the privilege check for the `USE` statement [#8414](https://github.com/pingcap/tidb/pull/8418) -* Add the privilege check for the `SET GLOBAL` statement [#8837](https://github.com/pingcap/tidb/pull/8837) -* Add the privilege check for the `SHOW PROCESSLIST` statement [#7858](https://github.com/pingcap/tidb/pull/7858) - -### Server - -* Support the `Trace` feature [#9029](https://github.com/pingcap/tidb/pull/9029) -* Support the plugin framework [#8788](https://github.com/pingcap/tidb/pull/8788) -* Support using `unix_socket` and TCP simultaneously to connect to the database [#8836](https://github.com/pingcap/tidb/pull/8836) -* Support the `interactive_timeout` system variable [#8573](https://github.com/pingcap/tidb/pull/8573) -* Support the `wait_timeout` system variable [#8346](https://github.com/pingcap/tidb/pull/8346) -* Support splitting a transaction into multiple transactions based on the number of statements using the `tidb_batch_commit` variable [#8293](https://github.com/pingcap/tidb/pull/8293) -* Support using the `ADMIN SHOW SLOW` statement to check slow logs [#7785](https://github.com/pingcap/tidb/pull/7785) - -### Compatibility - -* Support the `ALLOW_INVALID_DATES` SQL mode [#9027](https://github.com/pingcap/tidb/pull/9027) -* Improve `LoadData` fault-tolerance for the CSV file [#9005](https://github.com/pingcap/tidb/pull/9005) -* Support the MySQL 320 handshake protocol [#8812](https://github.com/pingcap/tidb/pull/8812) -* Support using the unsigned bigint column as the auto-increment column [#8181](https://github.com/pingcap/tidb/pull/8181) -* Support the `SHOW CREATE DATABASE IF NOT EXISTS` syntax [#8926](https://github.com/pingcap/tidb/pull/8926) -* Abandon the predicate pushdown operation when the filtering condition contains a user variable to improve the compatibility with MySQL's behavior of using user variables to mock the Window Function behavior [#8412](https://github.com/pingcap/tidb/pull/8412) - -### DDL - -* Support fast recovery of mistakenly deleted tables [#7937](https://github.com/pingcap/tidb/pull/7937) -* Support adjusting the number of concurrencies of `ADD INDEX` dynamically [#8295](https://github.com/pingcap/tidb/pull/8295) -* Support changing the character set of tables or columns to `utf8`/`utf8mb4` [#8037](https://github.com/pingcap/tidb/pull/8037) -* Change the default character set from `utf8` to `utf8mb4` [#7965](https://github.com/pingcap/tidb/pull/7965) -* Support Range Partition [#8011](https://github.com/pingcap/tidb/pull/8011) - - -## [2.1.2] 2018-12-21 -* Make TiDB compatible with TiDB-Binlog of the Kafka version [#8747](https://github.com/pingcap/tidb/pull/8747) -* Improve the exit mechanism of TiDB in a rolling update [#8707](https://github.com/pingcap/tidb/pull/8707) -* Fix the panic issue caused by adding the index for the generated column in some cases [#8676](https://github.com/pingcap/tidb/pull/8676) -* Fix the issue that the optimizer cannot find the optimal query plan when `TIDB_SMJ Hint` exists in the SQL statement in some cases [#8729](https://github.com/pingcap/tidb/pull/8729) -* Fix the issue that `AntiSemiJoin` returns an incorrect result in some cases [#8730](https://github.com/pingcap/tidb/pull/8730) -* Improve the valid character check of the `utf8` character set [#8754](https://github.com/pingcap/tidb/pull/8754) -* Fix the issue that the field of the time type might return an incorrect result when the write operation is performed before the read operation in a transaction [#8746](https://github.com/pingcap/tidb/pull/8746) - - -## [2.1.1] 2018-12-12 - -### SQL Optimizer/Executor - -* Fix the round error of the negative date [#8574](https://github.com/pingcap/tidb/pull/8574) -* Fix the issue that the `uncompress` function does not check the data length [#8606](https://github.com/pingcap/tidb/pull/8606) -* Reset bind arguments of the `prepare` statement after the `execute` command is executed [#8652](https://github.com/pingcap/tidb/pull/8652) -* Support automatically collecting the statistics information of a partition table [#8649](https://github.com/pingcap/tidb/pull/8649) -* Fix the wrongly configured integer type when pushing down the `abs` function [#8628](https://github.com/pingcap/tidb/pull/8628) -* Fix the data race on the JSON column [#8660](https://github.com/pingcap/tidb/pull/8660) - -### Server - -* Fix the issue that the transaction obtained TSO is incorrect when PD breaks down [#8567](https://github.com/pingcap/tidb/pull/8567) -* Fix the bootstrap failure caused by the statement that does not conform to ANSI standards [#8576](https://github.com/pingcap/tidb/pull/8576) -* Fix the issue that incorrect parameters are used in transaction retries [#8638](https://github.com/pingcap/tidb/pull/8638) - -### DDL - -* Change the default character set and collation of tables into `utf8mb4` [#8590](https://github.com/pingcap/tidb/pull/8590) -* Add the `ddl_reorg_batch_size` variable to control the speed of adding indexes [#8614](https://github.com/pingcap/tidb/pull/8614) -* Make the character set and collation options content in DDL case-insensitive [#8611](https://github.com/pingcap/tidb/pull/8611) -* Fix the issue of adding indexes for generated columns [#8655](https://github.com/pingcap/tidb/pull/8655) - -## [2.1.0-GA] 2018-11-30 - -### Upgrade caveat -* TiDB 2.1 does not support downgrading to v2.0.x or earlier due to the adoption of the new storage engine -* Parallel DDL is enabled in TiDB 2.1, so the clusters with TiDB version earlier than 2.0.1 cannot upgrade to 2.1 using rolling update. You can choose either of the following two options: - - Stop the cluster and upgrade to 2.1 directly - - Roll update to 2.0.1 or later 2.0.x versions, and then roll update to the 2.1 version -* `raft learner` is enabled in TiDB 2.1 by default. If you upgrade the TiDB platform from 1.x to 2.1, stop the cluster before the upgrade. You can also roll update TiKV to 2.1 and then roll update PD to 2.1. -* If you upgrade from TiDB 2.0.6 or earlier to TiDB 2.1, make sure if there is any ongoing DDL operation, especially the time consuming `Add Index` operation, because the DDL operations slow down the upgrading process. - -### SQL Optimizer -* Optimize the selection range of `Index Join` to improve the execution performance -* Optimize the selection of outer table for `Index Join` and use the table with smaller estimated value of Row Count as the outer table -* Optimize Join Hint `TIDB_SMJ` so that Merge Join can be used even without proper index available -* Optimize Join Hint `TIDB_INLJ` to specify the Inner table to Join -* Optimize correlated subquery, push down Filter, and extend the index selection range, to improve the efficiency of some queries by orders of magnitude -* Support using Index Hint and Join Hint in the `UPDATE` and `DELETE` statement -* Support pushing down more functions:`ABS` / `CEIL` / `FLOOR` / `IS TRUE` / `IS FALSE` -* Optimize the constant folding algorithm for the `IF` and `IFNULL` built-in functions -* Optimize the output of the `EXPLAIN` statement and use hierarchy structure to show the relationship between operators - -### SQL executor -* Refactor all the aggregation functions and improve execution efficiency of the `Stream` and `Hash` aggregation operators -* Implement the parallel `Hash Aggregate` operators and improve the computing performance by 350% in some scenarios -* Implement the parallel `Project` operators and improve the performance by 74% in some scenarios -* Read the data of the Inner table and Outer table of `Hash Join` concurrently to improve the execution performance -* Optimize the execution speed of the `REPLACE INTO` statement and increase the performance nearly by 10 times -* Optimize the memory usage of the time data type and decrease the memory usage of the time data type by fifty percent -* Optimize the point select performance and improve the point select efficiency result of Sysbench by 60% -* Improve the performance of TiDB on inserting or updating wide tables by 20 times -* Support configuring the memory upper limit of a single statement in the configuration file -* Optimize the execution of Hash Join, if the Join type is Inner Join or Semi Join and the inner table is empty, return the result without reading data from the outer table -* Support using the [`EXPLAIN ANALYZE` statement](https://www.pingcap.com/docs/sql/understanding-the-query-execution-plan/#explain-analyze-output-format) to check the runtime statistics including the execution time and the number of returned rows of each operator - -### Statistics -* Support enabling auto ANALYZE statistics only during certain period of the day -* Support updating the table statistics automatically according to the feedback of the queries -* Support configuring the number of buckets in the histogram using the `ANALYZE TABLE WITH BUCKETS` statement -* Optimize the Row Count estimation algorithm using histogram for mixed queries of equality query and range queries - -### Expressions -* Support following built-in function: - - `json_contains` - - `json_contains_path` - - `encode/decode` - -### Server -* Support queuing the locally conflicted transactions within tidb-server instance to optimize the performance of conflicted transactions -* Support Server Side Cursor -* Add the [HTTP API](https://github.com/pingcap/tidb/blob/master/docs/tidb_http_api.md) - - Scatter the distribution of table Regions in the TiKV cluster - - Control whether to open the `general log` - - Support modifying the log level online - - Check the TiDB cluster information -* [Add the `auto_analyze_ratio` system variables to contorl the ratio of Analyze](https://docs.pingcap.com/tidb/stable/sql-faq#whats-the-trigger-strategy-for-auto-analyze-in-tidb) -* [Add the `tidb_retry_limit` system variable to control the automatic retry times of transactions](https://docs.pingcap.com/tidb/stable/system-variables#tidb_retry_limit) -* [Add the `tidb_disable_txn_auto_retry` system variable to control whether the transaction retries automatically](https://docs.pingcap.com/tidb/stable/system-variables/#tidb_disable_txn_auto_retry) -* [Support using `admin show slow` statement to obtain the slow queries ](https://docs.pingcap.com/tidb/stable/identify-slow-queries/#admin-show-slow-command) -* [Add the `tidb_slow_log_threshold` environment variable to set the threshold of slow log automatically](https://docs.pingcap.com/tidb/stable/system-variables#tidb_slow_log_threshold) -* [Add the `tidb_query_log_max_len` environment variable to set the length of the SQL statement to be truncated in the log dynamically](https://docs.pingcap.com/tidb/stable/system-variables#tidb_query_log_max_len) - -### DDL -* Support the parallel execution of the add index statement and other statements to avoid the time consuming add index operation blocking other operations -* Optimize the execution speed of `ADD INDEX` and improve it greatly in some scenarios -* Support the `select tidb_is_ddl_owner()` statement to facilitate deciding whether TiDB is `DDL Owner` -* Support the `ALTER TABLE FORCE` syntax -* Support the `ALTER TABLE RENAME KEY TO` syntax -* Add the table name and database name in the output information of `admin show ddl jobs` -* [Support using the `ddl/owner/resign` HTTP interface to release the DDL owner and start electing a new DDL owner](https://github.com/pingcap/tidb/blob/master/docs/tidb_http_api.md) - -### Compatibility -* Support more MySQL syntaxes -* Make the `BIT` aggregate function support the `ALL` parameter -* Support the `SHOW PRIVILEGES` statement -* Support the `CHARACTER SET` syntax in the `LOAD DATA` statement -* Support the `IDENTIFIED WITH` syntax in the `CREATE USER` statement -* Support the `LOAD DATA IGNORE LINES` statement -* The `Show ProcessList` statement returns more accurate information - -## [2.1.0-rc.5] - 2018-11-12 -### SQL Optimizer -* Fix the issue that `IndexReader` reads the wrong handle in some cases [#8132](https://github.com/pingcap/tidb/pull/8132) -* Fix the issue occurred while the `IndexScan Prepared` statement uses `Plan Cache` [#8055](https://github.com/pingcap/tidb/pull/8055) -* Fix the issue that the result of the `Union` statement is unstable [#8165](https://github.com/pingcap/tidb/pull/8165) -### SQL Execution Engine -* Improve the performance of TiDB on inserting or updating wide tables [#8024](https://github.com/pingcap/tidb/pull/8024) -* Support the unsigned `int` flag in the `Truncate` built-in function [#8068](https://github.com/pingcap/tidb/pull/8068) -* Fix the error occurred while converting JSON data to the decimal type [#8109](https://github.com/pingcap/tidb/pull/8109) -* Fix the error occurred when you `Update` the float type [#8170](https://github.com/pingcap/tidb/pull/8170) -### Statistics -* Fix the incorrect statistics issue during point queries in some cases [#8035](https://github.com/pingcap/tidb/pull/8035) -* Fix the selectivity estimation of statistics for primary key in some cases [#8149](https://github.com/pingcap/tidb/pull/8149) -* Fix the issue that the statistics of deleted tables are not cleared up for a long period of time [#8182](https://github.com/pingcap/tidb/pull/8182) -### Server -* Improve the readability of logs and make logs better - - [#8063](https://github.com/pingcap/tidb/pull/8063) - - [#8053](https://github.com/pingcap/tidb/pull/8053) - - [#8224](https://github.com/pingcap/tidb/pull/8224) -* Fix the error occurred when obtaining the table data of `infoschema.profiling` [#8096](https://github.com/pingcap/tidb/pull/8096) -* Replace the unix socket with the pumps client to write binlogs [#8098](https://github.com/pingcap/tidb/pull/8098) -* Add the threshold value for the `tidb_slow_log_threshold` environment variable, which dynamically sets the slow log [#8094](https://github.com/pingcap/tidb/pull/8094) -* Add the original length of a SQL statement truncated while the `tidb_query_log_max_len` environment variable dynamically sets logs [8200](https://github.com/pingcap/tidb/pull/8200) -* Add the `tidb_opt_write_row_id` environment variable to control whether to allow writing `_tidb_rowid` [#8218](https://github.com/pingcap/tidb/pull/8218) -* Add an upper bound to the `Scan` command of ticlient, to avoid overbound scan [#8081](https://github.com/pingcap/tidb/pull/8081), [#8247](https://github.com/pingcap/tidb/pull/8247) -### DDL -* Fix the issue that executing DDL statements in transactions encounters an error in some cases [#8056](https://github.com/pingcap/tidb/pull/8056) -* Fix the issue that executing `truncate table` in partition tables does not take effect [#8103](https://github.com/pingcap/tidb/pull/8103) -* Fix the issue that the DDL operation does not roll back correctly after being cancelled in some cases [#8057](https://github.com/pingcap/tidb/pull/8057) -* Add the `admin show next_row_id` command to return the next available row ID [#8268](https://github.com/pingcap/tidb/pull/8268) - - -## [2.1.0-rc.4] - 2018-10-23 -### SQL Optimizer -* Fix the issue that column pruning of `UnionAll` is incorrect in some cases [#7941](https://github.com/pingcap/tidb/pull/7941) -* Fix the issue that the result of the `UnionAll` operator is incorrect in some cases [#8007](https://github.com/pingcap/tidb/pull/8007) -### SQL Execution Engine -* Fix the precision issue of the `AVG` function [#7874](https://github.com/pingcap/tidb/pull/7874) -* Support using the `EXPLAIN ANALYZE` statement to check the runtime statistics including the execution time and the number of returned rows of each operator during the query execution process [#7925](https://github.com/pingcap/tidb/pull/7925) -* Fix the panic issue of the `PointGet` operator when a column of a table appears multiple times in the result set [#7943](https://github.com/pingcap/tidb/pull/7943) -* Fix the panic issue caused by too large values in the `Limit` subclause [#8002](https://github.com/pingcap/tidb/pull/8002) -* Fix the panic issue during the execution process of the `AddDate`/`SubDate` statement in some cases [#8009](https://github.com/pingcap/tidb/pull/8009) -### Statistics -* Fix the issue of judging the prefix of the histogram low-bound of the combined index as out of range [#7856](https://github.com/pingcap/tidb/pull/7856) -* Fix the memory leak issue caused by statistics collecting [#7873](https://github.com/pingcap/tidb/pull/7873) -* Fix the panic issue when the histogram is empty [#7928](https://github.com/pingcap/tidb/pull/7928) -* Fix the issue that the histogram bound is out of range when the statistics is being uploaded [#7944](https://github.com/pingcap/tidb/pull/7944) -* Limit the maximum length of values in the statistics sampling process [#7982](https://github.com/pingcap/tidb/pull/7982) -### Server -* Refactor Latch to avoid misjudgment of transaction conflicts and improve the execution performance of concurrent transactions [#7711](https://github.com/pingcap/tidb/pull/7711) -* Fix the panic issue caused by collecting slow queries in some cases [#7874](https://github.com/pingcap/tidb/pull/7847) -* Fix the panic issue when `ESCAPED BY` is an empty string in the `LOAD DATA` statement [#8005](https://github.com/pingcap/tidb/pull/8005) -* Complete the "coprocessor error" log information [#8006](https://github.com/pingcap/tidb/pull/8006) -### Compatibility -* Set the `Command` field of the `SHOW PROCESSLIST` result to `Sleep` when the query is empty [#7839](https://github.com/pingcap/tidb/pull/7839) -### Expressions -* Fix the constant folding issue of the `SYSDATE` function [#7895](https://github.com/pingcap/tidb/pull/7895) -* Fix the issue that `SUBSTRING_INDEX` panics in some cases [#7897](https://github.com/pingcap/tidb/pull/7897) -### DDL -* Fix the stack overflow issue caused by throwing the `invalid ddl job type` error [#7958](https://github.com/pingcap/tidb/pull/7958) -* Fix the issue that the result of `ADMIN CHECK TABLE` is incorrect in some cases [#7975](https://github.com/pingcap/tidb/pull/7975) - - -## [2.1.0-rc.2] - 2018-09-14 -### SQL Optimizer -* Put forward a proposal of the next generation Planner [#7543](https://github.com/pingcap/tidb/pull/7543) -* Improve the optimization rules of constant propagation [#7276](https://github.com/pingcap/tidb/pull/7276) -* Enhance the computing logic of `Range` to enable it to handle multiple `IN` or `EQUAL` conditions simultaneously [#7577](https://github.com/pingcap/tidb/pull/7577) -* Fix the issue that the estimation result of `TableScan` is incorrect when `Range` is empty [#7583](https://github.com/pingcap/tidb/pull/7583) -* Support the `PointGet` operator for the `UPDATE` statement [#7586](https://github.com/pingcap/tidb/pull/7586) -* Fix the panic issue during the process of executing the `FirstRow` aggregate function in some conditions [#7624](https://github.com/pingcap/tidb/pull/7624) -### SQL Execution Engine -* Fix the potential `DataRace` issue when the `HashJoin` operator encounters an error [#7554](https://github.com/pingcap/tidb/pull/7554) -* Make the `HashJoin` operator read the inner table and build the hash table simultaneously [#7544](https://github.com/pingcap/tidb/pull/7544) -* Optimize the performance of Hash aggregate operators [#7541](https://github.com/pingcap/tidb/pull/7541) -* Optimize the performance of Join operators [#7493](https://github.com/pingcap/tidb/pull/7493), [#7433](https://github.com/pingcap/tidb/pull/7433) -* Fix the issue that the result of `UPDATE JOIN` is incorrect when the Join order is changed [#7571](https://github.com/pingcap/tidb/pull/7571) -* Improve the performance of Chunk's iterator [#7585](https://github.com/pingcap/tidb/pull/7585) -### Statistics -* Fix the issue that the auto Analyze work repeatedly analyzes the statistics [#7550](https://github.com/pingcap/tidb/pull/7550) -* Fix the statistics update error that occurs when there is no statistics change [#7530](https://github.com/pingcap/tidb/pull/7530) -* Use the RC isolation level and low priority when building `Analyze` requests [#7496](https://github.com/pingcap/tidb/pull/7496) -* Support enabling statistics auto-analyze on certain period of a day [#7570](https://github.com/pingcap/tidb/pull/7570) -* Fix the panic issue when logging the statistics information [#7588](https://github.com/pingcap/tidb/pull/7588) -* Support configuring the number of buckets in the histogram using the `ANALYZE TABLE WITH BUCKETS` statement [#7619](https://github.com/pingcap/tidb/pull/7619) -* Fix the panic issue when updating an empty histogram [#7640](https://github.com/pingcap/tidb/pull/7640) -* Update `information_schema.tables.data_length` using the statistics information [#7657](https://github.com/pingcap/tidb/pull/7657) -### Server -* Add Trace related dependencies [#7532](https://github.com/pingcap/tidb/pull/7532) -* Enable the `mutex profile` feature of Golang [#7512](https://github.com/pingcap/tidb/pull/7512) -* The `Admin` statement requires the `Super_priv` privilege [#7486](https://github.com/pingcap/tidb/pull/7486) -* Forbid users to `Drop` crucial system tables [#7471](https://github.com/pingcap/tidb/pull/7471) -* Switch from `juju/errors` to `pkg/errors` [#7151](https://github.com/pingcap/tidb/pull/7151) -* Complete the functional prototype of SQL Tracing [#7016](https://github.com/pingcap/tidb/pull/7016) -* Remove the goroutine pool [#7564](https://github.com/pingcap/tidb/pull/7564) -* Support viewing the goroutine information using the `USER1` signal [#7587](https://github.com/pingcap/tidb/pull/7587) -* Set the internal SQL to high priority while TiDB is started [#7616](https://github.com/pingcap/tidb/pull/7616) -* Use different labels to filter internal SQL and user SQL in monitoring metrics [#7631](https://github.com/pingcap/tidb/pull/7631) -* Store the top 30 slow queries in the last week to the TiDB server [#7646](https://github.com/pingcap/tidb/pull/7646) -* Put forward a proposal of setting the global system time zone for the TiDB cluster [#7656](https://github.com/pingcap/tidb/pull/7656) -* Enrich the error message of "GC life time is shorter than transaction duration" [#7658](https://github.com/pingcap/tidb/pull/7658) -* Set the global system time zone when starting the TiDB cluster [#7638](https://github.com/pingcap/tidb/pull/7638) -### Compatibility -* Add the unsigned flag for the `Year` type [#7542](https://github.com/pingcap/tidb/pull/7542) -* Fix the issue of configuring the result length of the `Year` type in the `Prepare`/`Execute` mode [#7525](https://github.com/pingcap/tidb/pull/7525) -* Fix the issue of inserting zero timestamp in the `Prepare`/`Execute` mode [#7506](https://github.com/pingcap/tidb/pull/7506) -* Fix the error handling issue of the integer division [#7492](https://github.com/pingcap/tidb/pull/7492) -* Fix the compatibility issue when processing `ComStmtSendLongData` [#7485](https://github.com/pingcap/tidb/pull/7485) -* Fix the error handling issue during the process of converting string to integer [#7483](https://github.com/pingcap/tidb/pull/7483) -* Optimize the accuracy of values in the `information_schema.columns_in_table` table [#7463](https://github.com/pingcap/tidb/pull/7463) -* Fix the compatibility issue when writing or updating the string type of data using the MariaDB client [#7573](https://github.com/pingcap/tidb/pull/7573) -* Fix the compatibility issue of aliases of the returned value [#7600](https://github.com/pingcap/tidb/pull/7600) -* Fix the issue that the `NUMERIC_SCALE` value of the float type is incorrect in the `information_schema.COLUMNS` table [#7602](https://github.com/pingcap/tidb/pull/7602) -* Fix the issue that Parser reports an error when the single line comment is empty [#7612](https://github.com/pingcap/tidb/pull/7612) -### Expressions -* Check the value of `max_allowed_packet` in the `insert` function [#7528](https://github.com/pingcap/tidb/pull/7528) -* Support the built-in function `json_contains` [#7443](https://github.com/pingcap/tidb/pull/7443) -* Support the built-in function `json_contains_path` [#7596](https://github.com/pingcap/tidb/pull/7596) -* Support the built-in function `encode/decode` [#7622](https://github.com/pingcap/tidb/pull/7622) -* Fix the issue that some time related functions are not compatible with the MySQL behaviors in some cases [#7636](https://github.com/pingcap/tidb/pull/7636) -* Fix the compatibility issue of parsing the time type of data in string [#7654](https://github.com/pingcap/tidb/pull/7654) -* Fix the issue that the time zone is not considered when computing the default value of the `DateTime` data [#7655](https://github.com/pingcap/tidb/pull/7655) -### DML -* Set correct `last_insert_id` in the `InsertOnDuplicateUpdate` statement [#7534](https://github.com/pingcap/tidb/pull/7534) -* Reduce the cases of updating the `auto_increment_id` counter [#7515](https://github.com/pingcap/tidb/pull/7515) -* Optimize the error message of `Duplicate Key` [#7495](https://github.com/pingcap/tidb/pull/7495) -* Fix the `insert...select...on duplicate key update` issue [#7406](https://github.com/pingcap/tidb/pull/7406) -* Support the `LOAD DATA IGNORE LINES` statement [#7576](https://github.com/pingcap/tidb/pull/7576) -### DDL -* Add the DDL job type and the current schema version information in the monitor [#7472](https://github.com/pingcap/tidb/pull/7472) -* Complete the design of the `Admin Restore Table` feature [#7383](https://github.com/pingcap/tidb/pull/7383) -* Fix the issue that the default value of the `Bit` type exceeds 128 [#7249](https://github.com/pingcap/tidb/pull/7249) -* Fix the issue that the default value of the `Bit` type cannot be `NULL` [#7604](https://github.com/pingcap/tidb/pull/7604) -* Reduce the interval of checking `CREATE TABLE/DATABASE` in the DDL queue [#7608](https://github.com/pingcap/tidb/pull/7608) -* Use the `ddl/owner/resign` HTTP interface ro release the DDL owner and start electing a new owner [#7649](https://github.com/pingcap/tidb/pull/7649) -### TiKV Go Client -* Support the issue that the `Seek` operation only obtains `Key` [#7419](https://github.com/pingcap/tidb/pull/7419) -### [Table Partition](https://github.com/pingcap/tidb/projects/6) (Experimental) -* Fix the issue that the `Bigint` type cannot be used as the partition key [#7520](https://github.com/pingcap/tidb/pull/7520) -* Support the rollback operation when an issue occurs during adding an index in the partitioned table [#7437](https://github.com/pingcap/tidb/pull/7437) - - -## [2.0.0-rc.5] - 2018-04-17 -### New Features -* Support showing memory usage of the executing statements in the `SHOW PROCESSLIST` statement -* Support setting the table comment using the `Alter` statement -### Improvements -* Clean up the written data while rolling back the `Add Index` operation, to reduce consumed space -* Optimize the insert on duplicate key update statement to improve the performance by 10 times -### Bug Fixes -* Fix the issue about applying the Top-N pushdown rule -* Fix the issue that `Alter Table Modify Column` reports an error in extreme conditions -* Fix the issue about the type of the results returned by the `UNIX_TIMESTAMP` function -* Fix the issue that the NULL value is inserted while adding NOT NULL columns -* Fix the estimation of the number of rows for the columns that contain NULL values -* Fix the zero value of the Binary type -* Fix the BatchGet issue within a transaction - -## [2.0.0-rc.4] - 2018-04-01 -### New Features -* Support `SHOW GRANTS FOR CURRENT_USER();` -* Support the `SET TRANSACTION` syntax -* Support displaying floating point numbers using scientific notation -### Improvements -* Improve the execution performance of `DecodeBytes` -* Optimize `LIMIT 0` to `TableDual`, to avoid building useless execution plans -### Bug Fixes -* Fix the issue that the `Expression` in `UnionScan` is not cloned -* Fix the potential goroutine leak issue in `copIterator` -* Fix the issue that admin check table misjudges the unique index including null -* Fix the type inference issue during binary literal computing -* Fix the issue in parsing the `CREATE VIEW` statement -* Fix the panic issue when one statement contains both `ORDER BY` and `LIMIT 0` - -## [2.0.0-rc.3] - 2018-03-23 -### New Features -* Support closing the `Join Reorder` optimization in the optimizer using `STRAIGHT_JOIN` -* Output more detailed status information of DDL jobs in `ADMIN SHOW DDL JOBS` -* Support querying the original statements of currently running DDL jobs using `ADMIN SHOW DDL JOB QUERIES` -* Support recovering the index data using `ADMIN RECOVER INDEX` for disaster recovery -* Attach a lower priority to the `ADD INDEX` operation to reduce the impact on online business -* Support aggregation functions with JSON type parameters, such as `SUM/AVG` -* Support modifying the `lower_case_table_names` system variable in the configuration file, to support the OGG data synchronization tool -* Support using implicit `RowID` in CRUD operations -### Improvements -* Improve compatibility with the Navicat management tool -* Use the Stream Aggregation operator when the `GROUP BY` clause is empty, to increase the speed -* Optimize the execution speed of `ADD INDEX` to greatly increase the speed in some scenarios -* Optimize checks on length and precision of the floating point type, to improve compatibility with MySQL -* Improve the parsing error log of time type and add more error information -* Improve memory control and add statistics about `IndexLookupExecutor` memory -### Bug Fixes -* Fix the wrong result issue of `MAX/MIN` in some scenarios -* Fix the issue that the result of `Sort Merge Join` does not show in order of `Join Key` in some scenarios -* Fix the error of comparison between uint and int in boundary conditions - -## [2.0.0-rc.2] - 2018-03-15 -Only TiKV has this release - -## [2.0.0-rc.1] - 2018-03-09 -### New Features -* Support limiting the memory usage by a single SQL statement, to reduce the risk of OOM -* Support pushing the Stream Aggregate operator down to TiKV -* Support validating the configuration file -* Support obtaining the information of TiDB configuration through HTTP API -### Improvements -* Improve the compatibility with Navicat -* Improve the optimizer and extract common expressions with multiple OR conditions, to choose better query plan -* Improve the optimizer and convert subqueries to Join operators in more scenarios, to choose better query plan -* Compatible with more MySQL syntax in Parser -* Resolve Lock in the Batch mode to increase the garbage collection speed -* Optimize the `Add Index` operation and give lower priority to all write and read operations, to reduce the impact on online business -### Bug Fixes -* Fix the length of Boolean field to improve compatibility - -## [1.1.0-beta] - 2018-02-24 -### New Features -* Add more monitoring metrics and refine the log -* Add the `tidb_config` session variable to output the current TiDB configuration -* Support displaying the table creating time in `information_schema` -### Improvements -* Compatible with more MySQL syntax -* Optimize queries containing the `MaxOneRow` operator -* Configure the size of intermediate result sets generated by Join, to further reduce the memory used by Join -* Optimize the query performance of the SQL engine to improve the test result of the Sysbench Select/OLTP by 10% -* Improve the computing speed of subqueries in the optimizer using the new execution engine; compared with TiDB 1.0, TiDB 1.1 Beta has great improvement in tests like TPC-H and TPC-DS -### Bug Fixes -* Fix the panic issue in the `Union` and `Index Join` operators -* Fix the wrong result issue of the `Sort Merge Join` operator in some scenarios -* Fix the issue that the `Show Index` statement shows indexes that are in the process of adding -* Fix the failure of the `Drop Stats` statement - -## [1.0.8] - 2018-02-11 -### New Features -* Add limitation (Configurable, the default value is 5000) to the DML statements number within a transaction -### Improvements -* Improve the stability of the GC process by ignoring the regions with GC errors -* Run GC concurrently to accelerate the GC process -* Provide syntax support for the `CREATE INDEX` statement -* Optimize the performance of the `InsertIntoIgnore` statement -### Bug Fixes -* Fix issues in the `Outer Join` result in some scenarios -* Fix the issue in the `ShardRowID` option -* Fix an issue in the `Table/Column` aliases returned by the Prepare statement -* Fix an issue in updating statistics delta -* Fix a panic error in the `Drop Column` statement -* Fix an DML issue when running the `Add Column After` statement - -## [1.0.7] - 2018-01-22 -### Improvements -* Optimize the `FIELD_LIST` command -* Fix data race of the information schema -* Avoid adding read-only statements to history -* Add the session variable to control the log query -* Add schema info API for the http status server -* Update the behavior when `RunWorker` is false in DDL -* Improve the stability of test results in statistics -* Support `PACK_KEYS` syntax for the `CREATE TABLE` statement -* Add `row_id` column for the null pushdown schema to optimize performance -### Bug Fixes -* Fix the resource leak issue in statistics -* Fix the goroutine leak issue -* Fix an issue about `IndexJoin` - -## [1.1.0-alpha] - 2018-01-19 -### New Features -* Support the PROXY protocol -### Improvements -* Support more syntax -* Reduce memory usage of statistics info using more compact structure -* Speed up loading statistics info when starting tidb-server -* Provide more accurate query cost evaluation -* Use `Count-Min Sketch` to estimate the cost of queries using unique index more accurately -* Support more complex conditions to make full use of index -* Refactor all executor operators using Chunk architecture, improve the execution performance of analytical statements and reduce memory usage -* Optimize performance of the `INSERT IGNORE` statement -* Push down more types and functions to TiKV -* Support more `SQL_MODE` -* Optimize the `Load Data` performance to increase the speed by 10 times -* Optimize the `Use Database` performance -* Support statistics on the memory usage of physical operators diff --git a/bindinfo/bind_cache.go b/bindinfo/bind_cache.go index aa9f0079a2903..f1f58f43dae4a 100644 --- a/bindinfo/bind_cache.go +++ b/bindinfo/bind_cache.go @@ -18,10 +18,10 @@ import ( "errors" "sync" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/kvcache" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" ) diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 1aaf349d5490e..896c56471edb3 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -16,7 +16,6 @@ package bindinfo_test import ( "context" - "crypto/tls" "fmt" "strconv" "testing" @@ -29,61 +28,11 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/terror" plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) -// mockSessionManager is a mocked session manager which is used for test. -type mockSessionManager1 struct { - PS []*util.ProcessInfo -} - -func (msm *mockSessionManager1) ShowTxnList() []*txninfo.TxnInfo { - return nil -} - -// ShowProcessList implements the SessionManager.ShowProcessList interface. -func (msm *mockSessionManager1) ShowProcessList() map[uint64]*util.ProcessInfo { - ret := make(map[uint64]*util.ProcessInfo) - for _, item := range msm.PS { - ret[item.ID] = item - } - return ret -} - -func (msm *mockSessionManager1) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) { - for _, item := range msm.PS { - if item.ID == id { - return item, true - } - } - return &util.ProcessInfo{}, false -} - -// Kill implements the SessionManager.Kill interface. -func (msm *mockSessionManager1) Kill(cid uint64, query bool) { -} - -func (msm *mockSessionManager1) KillAllConnections() { -} - -func (msm *mockSessionManager1) UpdateTLSConfig(cfg *tls.Config) { -} - -func (msm *mockSessionManager1) ServerID() uint64 { - return 1 -} - -func (msm *mockSessionManager1) StoreInternalSession(se interface{}) {} - -func (msm *mockSessionManager1) DeleteInternalSession(se interface{}) {} - -func (msm *mockSessionManager1) GetInternalSessionStartTSList() []uint64 { - return nil -} - func TestPrepareCacheWithBinding(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -105,7 +54,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t1:idx_b", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_b(b)"), res.Rows()) tk.MustExec("execute stmt1;") @@ -117,7 +66,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t1:idx_c", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_c(c)"), res.Rows()) @@ -125,7 +74,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt2;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "HashJoin"), res.Rows()) tk.MustExec("execute stmt2;") @@ -136,7 +85,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt2;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "IndexJoin"), res.Rows()) @@ -145,7 +94,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t1:idx_b", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_b(b)"), res.Rows()) tk.MustExec("execute stmt3;") @@ -157,7 +106,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t1:idx_c", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_c(c)"), res.Rows()) @@ -165,7 +114,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt4;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "HashJoin"), res.Rows()) tk.MustExec("execute stmt4;") @@ -176,7 +125,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt4;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "IndexJoin"), res.Rows()) @@ -185,7 +134,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t2:idx_b", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_b(b)"), res.Rows()) tk.MustExec("execute stmt5;") @@ -197,7 +146,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t2:idx_b", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_b(b)"), res.Rows()) @@ -208,7 +157,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t2:idx_c", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_c(c)"), res.Rows()) @@ -217,7 +166,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t2:idx_b", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_b(b)"), res.Rows()) tk.MustExec("execute stmt6;") @@ -229,7 +178,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t2:idx_c", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "idx_c(c)"), res.Rows()) @@ -243,7 +192,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "HashJoin")) tk.MustExec("execute stmt1;") @@ -253,7 +202,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt2;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "MergeJoin")) tk.MustExec("execute stmt2;") @@ -264,7 +213,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "MergeJoin")) @@ -275,7 +224,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "IndexReader")) tk.MustExec("execute stmt1;") @@ -285,7 +234,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.False(t, tk.HasPlan4ExplainFor(res, "IndexReader")) tk.MustExec("execute stmt1;") @@ -296,7 +245,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.False(t, tk.HasPlan4ExplainFor(res, "IndexReader")) tk.MustExec("execute stmt1;") @@ -306,7 +255,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt2;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "IndexReader")) tk.MustExec("execute stmt2;") @@ -317,7 +266,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { tk.MustExec("execute stmt1;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.HasPlan4ExplainFor(res, "IndexReader")) @@ -332,7 +281,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t:ia", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "ia(a)"), res.Rows()) tk.MustExec("execute stmt1;") @@ -345,7 +294,7 @@ func TestPrepareCacheWithBinding(t *testing.T) { require.Equal(t, "t:ib", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.True(t, tk.MustUseIndex4ExplainFor(res, "ib(b)"), res.Rows()) } diff --git a/bindinfo/handle.go b/bindinfo/handle.go index dc25baff5250e..6166dcfb3f7b7 100644 --- a/bindinfo/handle.go +++ b/bindinfo/handle.go @@ -961,8 +961,7 @@ func GenerateBindSQL(ctx context.Context, stmtNode ast.StmtNode, planHint string withIdx := strings.Index(bindSQL, "WITH") restoreCtx := format.NewRestoreCtx(format.RestoreStringSingleQuotes|format.RestoreSpacesAroundBinaryOperation|format.RestoreStringWithoutCharset|format.RestoreNameBackQuotes, &withSb) restoreCtx.DefaultDB = defaultDB - err := n.With.Restore(restoreCtx) - if err != nil { + if err := n.With.Restore(restoreCtx); err != nil { logutil.BgLogger().Debug("[sql-bind] restore SQL failed", zap.Error(err)) return "" } diff --git a/br/cmd/br/cmd.go b/br/cmd/br/cmd.go index 81e2093381b0a..3c5bf674da430 100644 --- a/br/cmd/br/cmd.go +++ b/br/cmd/br/cmd.go @@ -113,7 +113,7 @@ func Init(cmd *cobra.Command) (err error) { tidbLogCfg.File.Filename = timestampLogFileName() } else { // Don't print slow log in br - config.GetGlobalConfig().Log.EnableSlowLog.Store(false) + config.GetGlobalConfig().Instance.EnableSlowLog.Store(false) } e = logutil.InitLogger(&tidbLogCfg) if e != nil { diff --git a/br/cmd/tidb-lightning-ctl/main.go b/br/cmd/tidb-lightning-ctl/main.go index b877fecb2f3c9..77dd52541470c 100644 --- a/br/cmd/tidb-lightning-ctl/main.go +++ b/br/cmd/tidb-lightning-ctl/main.go @@ -24,7 +24,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning" "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" "github.com/pingcap/tidb/br/pkg/lightning/backend/local" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" @@ -46,7 +45,7 @@ var exit = os.Exit func run() error { var ( compact, flagFetchMode *bool - mode, flagImportEngine, flagCleanupEngine *string + mode *string cpRemove, cpErrIgnore, cpErrDestroy, cpDump *string localStoringTables *bool @@ -65,9 +64,6 @@ func run() error { mode = fs.String("switch-mode", "", "switch tikv into import mode or normal mode, values can be ['import', 'normal']") flagFetchMode = fs.Bool("fetch-mode", false, "obtain the current mode of every tikv in the cluster") - flagImportEngine = fs.String("import-engine", "", "manually import a closed engine (value can be '`db`.`table`:123' or a UUID") - flagCleanupEngine = fs.String("cleanup-engine", "", "manually delete a closed engine") - cpRemove = fs.String("checkpoint-remove", "", "remove the checkpoint associated with the given table (value can be 'all' or '`db`.`table`')") cpErrIgnore = fs.String("checkpoint-error-ignore", "", "ignore errors encoutered previously on the given table (value can be 'all' or '`db`.`table`'); may corrupt this table if used incorrectly") cpErrDestroy = fs.String("checkpoint-error-destroy", "", "deletes imported data with table which has an error before (value can be 'all' or '`db`.`table`')") @@ -102,15 +98,9 @@ func run() error { if *flagFetchMode { return errors.Trace(fetchMode(ctx, cfg, tls)) } - if len(*flagImportEngine) != 0 { - return errors.Trace(importEngine(ctx, cfg, tls, *flagImportEngine)) - } if len(*mode) != 0 { return errors.Trace(lightning.SwitchMode(ctx, cfg, tls, *mode)) } - if len(*flagCleanupEngine) != 0 { - return errors.Trace(lightning.CleanupEngine(ctx, cfg, tls, *flagCleanupEngine)) - } if len(*cpRemove) != 0 { return errors.Trace(lightning.CheckpointRemove(ctx, cfg, *cpRemove)) @@ -199,26 +189,6 @@ func checkpointErrorDestroy(ctx context.Context, cfg *config.Config, tls *common } } - if cfg.TikvImporter.Backend == "importer" { - importer, err := importer.NewImporter(ctx, tls, cfg.TikvImporter.Addr, cfg.TiDB.PdAddr) - if err != nil { - return errors.Trace(err) - } - defer importer.Close() - - for _, table := range targetTables { - for engineID := table.MinEngineID; engineID <= table.MaxEngineID; engineID++ { - fmt.Fprintln(os.Stderr, "Closing and cleaning up engine:", table.TableName, engineID) - closedEngine, err := importer.UnsafeCloseEngine(ctx, nil, table.TableName, engineID) - if err != nil { - fmt.Fprintln(os.Stderr, "* Encountered error while closing engine:", err) - lastErr = err - } else if err := closedEngine.Cleanup(ctx); err != nil { - lastErr = err - } - } - } - } // For importer backend, engine was stored in importer's memory, we can retrieve it from alive importer process. // But in local backend, if we want to use common API `UnsafeCloseEngine` and `Cleanup`, // we need either lightning process alive or engine map persistent. @@ -331,21 +301,3 @@ func getLocalStoringTables(ctx context.Context, cfg *config.Config) (err2 error) return nil } - -func importEngine(ctx context.Context, cfg *config.Config, tls *common.TLS, engine string) error { - importer, err := importer.NewImporter(ctx, tls, cfg.TikvImporter.Addr, cfg.TiDB.PdAddr) - if err != nil { - return errors.Trace(err) - } - - ce, err := lightning.UnsafeCloseEngine(ctx, importer, engine) - if err != nil { - return errors.Trace(err) - } - - regionSplitSize := int64(cfg.TikvImporter.RegionSplitSize) - if regionSplitSize == 0 { - regionSplitSize = int64(config.SplitRegionSize) - } - return errors.Trace(ce.Import(ctx, regionSplitSize)) -} diff --git a/br/pkg/backup/client.go b/br/pkg/backup/client.go index 72730293c230f..9b07f22324d40 100644 --- a/br/pkg/backup/client.go +++ b/br/pkg/backup/client.go @@ -934,9 +934,17 @@ func doSendBackup( }) bCli, err := client.Backup(ctx, &req) failpoint.Inject("reset-retryable-error", func(val failpoint.Value) { - if val.(bool) { - logutil.CL(ctx).Debug("failpoint reset-retryable-error injected.") - err = status.Error(codes.Unavailable, "Unavailable error") + switch val.(string) { + case "Unavaiable": + { + logutil.CL(ctx).Debug("failpoint reset-retryable-error unavailable injected.") + err = status.Error(codes.Unavailable, "Unavailable error") + } + case "Internal": + { + logutil.CL(ctx).Debug("failpoint reset-retryable-error internal injected.") + err = status.Error(codes.Internal, "Internal error") + } } }) failpoint.Inject("reset-not-retryable-error", func(val failpoint.Value) { @@ -1030,9 +1038,15 @@ const ( // isRetryableError represents whether we should retry reset grpc connection. func isRetryableError(err error) bool { - - if status.Code(err) == codes.Unavailable { - return true + // some errors can be retried + // https://github.com/pingcap/tidb/issues/34350 + switch status.Code(err) { + case codes.Unavailable, codes.DeadlineExceeded, + codes.ResourceExhausted, codes.Aborted, codes.Internal: + { + log.Warn("backup met some errors, these errors can be retry 5 times", zap.Error(err)) + return true + } } // At least, there are two possible cancel() call, @@ -1040,6 +1054,7 @@ func isRetryableError(err error) bool { if status.Code(err) == codes.Canceled { if s, ok := status.FromError(err); ok { if strings.Contains(s.Message(), gRPC_Cancel) { + log.Warn("backup met grpc cancel error, this errors can be retry 5 times", zap.Error(err)) return true } } diff --git a/br/pkg/lightning/backend/backend.go b/br/pkg/lightning/backend/backend.go index a28e80b30215a..e6c14728ae9aa 100644 --- a/br/pkg/lightning/backend/backend.go +++ b/br/pkg/lightning/backend/backend.go @@ -25,11 +25,11 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/metric" "github.com/pingcap/tidb/br/pkg/lightning/mydump" - "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/table" "go.uber.org/zap" @@ -451,7 +451,7 @@ func (engine *ClosedEngine) Import(ctx context.Context, regionSplitSize int64) e for i := 0; i < importMaxRetryTimes; i++ { task := engine.logger.With(zap.Int("retryCnt", i)).Begin(zap.InfoLevel, "import") err = engine.backend.ImportEngine(ctx, engine.uuid, regionSplitSize) - if !utils.IsRetryableError(err) { + if !common.IsRetryableError(err) { task.End(zap.ErrorLevel, err) return err } diff --git a/br/pkg/lightning/backend/backend_test.go b/br/pkg/lightning/backend/backend_test.go index d1a6f4e41a58d..b42ce1815b70b 100644 --- a/br/pkg/lightning/backend/backend_test.go +++ b/br/pkg/lightning/backend/backend_test.go @@ -2,9 +2,11 @@ package backend_test import ( "context" + "database/sql/driver" "testing" "time" + gmysql "github.com/go-sql-driver/mysql" "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/pingcap/errors" @@ -267,7 +269,7 @@ func TestImportFailedWithRetry(t *testing.T) { s.mockBackend.EXPECT().CloseEngine(ctx, nil, gomock.Any()).Return(nil) s.mockBackend.EXPECT(). ImportEngine(ctx, gomock.Any(), gomock.Any()). - Return(errors.New("fake recoverable import error")). + Return(errors.Annotate(driver.ErrBadConn, "fake recoverable import error")). MinTimes(2) s.mockBackend.EXPECT().RetryImportDelay().Return(time.Duration(0)).AnyTimes() @@ -275,7 +277,7 @@ func TestImportFailedWithRetry(t *testing.T) { require.NoError(t, err) err = closedEngine.Import(ctx, 1) require.Error(t, err) - require.Regexp(t, "fake recoverable import error$", err.Error()) + require.Contains(t, err.Error(), "fake recoverable import error") } func TestImportFailedRecovered(t *testing.T) { @@ -287,7 +289,7 @@ func TestImportFailedRecovered(t *testing.T) { s.mockBackend.EXPECT().CloseEngine(ctx, nil, gomock.Any()).Return(nil) s.mockBackend.EXPECT(). ImportEngine(ctx, gomock.Any(), gomock.Any()). - Return(errors.New("fake recoverable import error")) + Return(gmysql.ErrInvalidConn) s.mockBackend.EXPECT(). ImportEngine(ctx, gomock.Any(), gomock.Any()). Return(nil) diff --git a/br/pkg/lightning/backend/importer/importer.go b/br/pkg/lightning/backend/importer/importer.go deleted file mode 100644 index 4b2c3dd5b9128..0000000000000 --- a/br/pkg/lightning/backend/importer/importer.go +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package importer - -import ( - "context" - "strings" - "sync" - "time" - - "github.com/coreos/go-semver/semver" - "github.com/google/uuid" - "github.com/pingcap/errors" - "github.com/pingcap/kvproto/pkg/import_kvpb" - "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" - "github.com/pingcap/tidb/br/pkg/lightning/common" - "github.com/pingcap/tidb/br/pkg/lightning/config" - "github.com/pingcap/tidb/br/pkg/lightning/log" - "github.com/pingcap/tidb/br/pkg/lightning/tikv" - "github.com/pingcap/tidb/br/pkg/utils" - "github.com/pingcap/tidb/br/pkg/version" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/table" - "github.com/tikv/client-go/v2/oracle" - pd "github.com/tikv/pd/client" - "go.uber.org/zap" - "google.golang.org/grpc" -) - -const ( - defaultRetryBackoffTime = time.Second * 3 - writeRowsMaxRetryTimes = 3 -) - -var ( - // Importer backend is compatible with TiDB [2.1.0, NextMajorVersion). - requiredMinTiDBVersion = *semver.New("2.1.0") - requiredMinPDVersion = *semver.New("2.1.0") - requiredMinTiKVVersion = *semver.New("2.1.0") - requiredMaxTiDBVersion = version.NextMajorVersion() - requiredMaxPDVersion = version.NextMajorVersion() - requiredMaxTiKVVersion = version.NextMajorVersion() -) - -// importer represents a gRPC connection to tikv-importer. This type is -// goroutine safe: you can share this instance and execute any method anywhere. -type importer struct { - conn *grpc.ClientConn - cli import_kvpb.ImportKVClient - pdAddr string - tls *common.TLS - - mutationPool sync.Pool - // lock ensures ImportEngine are runs serially - lock sync.Mutex - - tsMap sync.Map // engineUUID -> commitTS - // For testing convenience. - getTSFunc func(ctx context.Context) (uint64, error) -} - -// NewImporter creates a new connection to tikv-importer. A single connection -// per tidb-lightning instance is enough. -func NewImporter(ctx context.Context, tls *common.TLS, importServerAddr string, pdAddr string) (backend.Backend, error) { - conn, err := grpc.DialContext(ctx, importServerAddr, tls.ToGRPCDialOption()) - if err != nil { - return backend.MakeBackend(nil), errors.Trace(err) - } - - getTSFunc := func(ctx context.Context) (uint64, error) { - pdCli, err := pd.NewClientWithContext(ctx, []string{pdAddr}, tls.ToPDSecurityOption()) - if err != nil { - return 0, err - } - defer pdCli.Close() - - physical, logical, err := pdCli.GetTS(ctx) - if err != nil { - return 0, err - } - return oracle.ComposeTS(physical, logical), nil - } - - return backend.MakeBackend(&importer{ - conn: conn, - cli: import_kvpb.NewImportKVClient(conn), - pdAddr: pdAddr, - tls: tls, - mutationPool: sync.Pool{New: func() interface{} { return &import_kvpb.Mutation{} }}, - getTSFunc: getTSFunc, - }), nil -} - -// NewMockImporter creates an *unconnected* importer based on a custom -// ImportKVClient. This is provided for testing only. Do not use this function -// outside of tests. -func NewMockImporter(cli import_kvpb.ImportKVClient, pdAddr string) backend.Backend { - return backend.MakeBackend(&importer{ - conn: nil, - cli: cli, - pdAddr: pdAddr, - mutationPool: sync.Pool{New: func() interface{} { return &import_kvpb.Mutation{} }}, - getTSFunc: func(ctx context.Context) (uint64, error) { - return uint64(time.Now().UnixNano()), nil - }, - }) -} - -// Close the importer connection. -func (importer *importer) Close() { - if importer.conn != nil { - if err := importer.conn.Close(); err != nil { - log.L().Warn("close importer gRPC connection failed", zap.Error(err)) - } - } -} - -func (*importer) RetryImportDelay() time.Duration { - return defaultRetryBackoffTime -} - -func (*importer) MaxChunkSize() int { - // 31 MB. hardcoded by importer, so do we - return 31 << 10 -} - -func (*importer) ShouldPostProcess() bool { - return true -} - -// isIgnorableOpenCloseEngineError checks if the error from -// CloseEngine can be safely ignored. -func isIgnorableOpenCloseEngineError(err error) bool { - // We allow "FileExists" error. This happens when the engine has been - // closed before. This error typically arise when resuming from a - // checkpoint with a partially-imported engine. - // - // If the error is legit in a no-checkpoints settings, the later WriteEngine - // API will bail us out to keep us safe. - return err == nil || strings.Contains(err.Error(), "FileExists") -} - -func (importer *importer) OpenEngine(ctx context.Context, cfg *backend.EngineConfig, engineUUID uuid.UUID) error { - req := &import_kvpb.OpenEngineRequest{ - Uuid: engineUUID[:], - } - - _, err := importer.cli.OpenEngine(ctx, req) - if err != nil { - return errors.Trace(err) - } - if err = importer.allocateTSIfNotExists(ctx, engineUUID); err != nil { - return errors.Trace(err) - } - return nil -} - -func (importer *importer) getEngineTS(engineUUID uuid.UUID) uint64 { - if v, ok := importer.tsMap.Load(engineUUID); ok { - return v.(uint64) - } - return 0 -} - -func (importer *importer) allocateTSIfNotExists(ctx context.Context, engineUUID uuid.UUID) error { - if importer.getEngineTS(engineUUID) > 0 { - return nil - } - ts, err := importer.getTSFunc(ctx) - if err != nil { - return errors.Trace(err) - } - importer.tsMap.LoadOrStore(engineUUID, ts) - return nil -} - -func (importer *importer) CloseEngine(ctx context.Context, cfg *backend.EngineConfig, engineUUID uuid.UUID) error { - req := &import_kvpb.CloseEngineRequest{ - Uuid: engineUUID[:], - } - - _, err := importer.cli.CloseEngine(ctx, req) - if !isIgnorableOpenCloseEngineError(err) { - return errors.Trace(err) - } - return nil -} - -func (importer *importer) Flush(_ context.Context, _ uuid.UUID) error { - return nil -} - -func (importer *importer) ImportEngine(ctx context.Context, engineUUID uuid.UUID, _ int64) error { - importer.lock.Lock() - defer importer.lock.Unlock() - req := &import_kvpb.ImportEngineRequest{ - Uuid: engineUUID[:], - PdAddr: importer.pdAddr, - } - - _, err := importer.cli.ImportEngine(ctx, req) - return errors.Trace(err) -} - -func (importer *importer) CleanupEngine(ctx context.Context, engineUUID uuid.UUID) error { - req := &import_kvpb.CleanupEngineRequest{ - Uuid: engineUUID[:], - } - - _, err := importer.cli.CleanupEngine(ctx, req) - if err == nil { - importer.tsMap.Delete(engineUUID) - } - return errors.Trace(err) -} - -func (importer *importer) CollectLocalDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (bool, error) { - panic("Unsupported Operation") -} - -func (importer *importer) CollectRemoteDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (bool, error) { - panic("Unsupported Operation") -} - -func (importer *importer) ResolveDuplicateRows(ctx context.Context, tbl table.Table, tableName string, algorithm config.DuplicateResolutionAlgorithm) error { - return nil -} - -func (importer *importer) WriteRows( - ctx context.Context, - engineUUID uuid.UUID, - tableName string, - _ []string, - rows kv.Rows, -) (finalErr error) { - var err error - ts := importer.getEngineTS(engineUUID) -outside: - for _, r := range rows.SplitIntoChunks(importer.MaxChunkSize()) { - for i := 0; i < writeRowsMaxRetryTimes; i++ { - err = importer.WriteRowsToImporter(ctx, engineUUID, ts, r) - switch { - case err == nil: - continue outside - case utils.IsRetryableError(err): - // retry next loop - default: - return err - } - } - return errors.Annotatef(err, "[%s] write rows reach max retry %d and still failed", tableName, writeRowsMaxRetryTimes) - } - return nil -} - -func (importer *importer) WriteRowsToImporter( - ctx context.Context, - //nolint:interfacer // false positive - engineUUID uuid.UUID, - ts uint64, - rows kv.Rows, -) (finalErr error) { - kvs := kv.KvPairsFromRows(rows) - if len(kvs) == 0 { - return nil - } - - wstream, err := importer.cli.WriteEngine(ctx) - if err != nil { - return errors.Trace(err) - } - - logger := log.With(zap.Stringer("engineUUID", engineUUID)) - - defer func() { - resp, closeErr := wstream.CloseAndRecv() - if closeErr == nil && resp != nil && resp.Error != nil { - closeErr = errors.Errorf("Engine '%s' not found", resp.Error.EngineNotFound.Uuid) - } - if closeErr != nil { - if finalErr == nil { - finalErr = errors.Trace(closeErr) - } else { - // just log the close error, we need to propagate the earlier error instead - logger.Warn("close write stream failed", log.ShortError(closeErr)) - } - } - }() - - // Bind uuid for this write request - req := &import_kvpb.WriteEngineRequest{ - Chunk: &import_kvpb.WriteEngineRequest_Head{ - Head: &import_kvpb.WriteHead{ - Uuid: engineUUID[:], - }, - }, - } - if err := wstream.Send(req); err != nil { - return errors.Trace(err) - } - - // Send kv paris as write request content - mutations := make([]*import_kvpb.Mutation, len(kvs)) - for i, pair := range kvs { - mutations[i] = importer.mutationPool.Get().(*import_kvpb.Mutation) - mutations[i].Op = import_kvpb.Mutation_Put - mutations[i].Key = pair.Key - mutations[i].Value = pair.Val - } - - req.Reset() - req.Chunk = &import_kvpb.WriteEngineRequest_Batch{ - Batch: &import_kvpb.WriteBatch{ - CommitTs: ts, - Mutations: mutations, - }, - } - - err = wstream.Send(req) - for _, mutation := range mutations { - importer.mutationPool.Put(mutation) - } - - if err != nil { - return errors.Trace(err) - } - - return nil -} - -func (*importer) MakeEmptyRows() kv.Rows { - return kv.MakeRowsFromKvPairs(nil) -} - -func (*importer) NewEncoder(tbl table.Table, options *kv.SessionOptions) (kv.Encoder, error) { - return kv.NewTableKVEncoder(tbl, options) -} - -func (importer *importer) CheckRequirements(ctx context.Context, _ *backend.CheckCtx) error { - if err := checkTiDBVersionByTLS(ctx, importer.tls, requiredMinTiDBVersion, requiredMaxTiDBVersion); err != nil { - return err - } - if err := tikv.CheckPDVersion(ctx, importer.tls, importer.pdAddr, requiredMinPDVersion, requiredMaxPDVersion); err != nil { - return err - } - if err := tikv.CheckTiKVVersion(ctx, importer.tls, importer.pdAddr, requiredMinTiKVVersion, requiredMaxTiKVVersion); err != nil { - return err - } - return nil -} - -func checkTiDBVersionByTLS(ctx context.Context, tls *common.TLS, requiredMinVersion, requiredMaxVersion semver.Version) error { - var status struct{ Version string } - err := tls.GetJSON(ctx, "/status", &status) - if err != nil { - return err - } - - return version.CheckTiDBVersion(status.Version, requiredMinVersion, requiredMaxVersion) -} - -func (importer *importer) FetchRemoteTableModels(ctx context.Context, schema string) ([]*model.TableInfo, error) { - return tikv.FetchRemoteTableModelsFromTLS(ctx, importer.tls, schema) -} - -func (importer *importer) EngineFileSizes() []backend.EngineFileSize { - return nil -} - -func (importer *importer) FlushEngine(context.Context, uuid.UUID) error { - return nil -} - -func (importer *importer) FlushAllEngines(context.Context) error { - return nil -} - -func (importer *importer) ResetEngine(context.Context, uuid.UUID) error { - return errors.New("cannot reset an engine in importer backend") -} - -func (importer *importer) LocalWriter(_ context.Context, _ *backend.LocalWriterConfig, engineUUID uuid.UUID) (backend.EngineWriter, error) { - return &Writer{importer: importer, engineUUID: engineUUID}, nil -} - -type Writer struct { - importer *importer - engineUUID uuid.UUID -} - -func (w *Writer) Close(ctx context.Context) (backend.ChunkFlushStatus, error) { - return nil, nil -} - -func (w *Writer) AppendRows(ctx context.Context, tableName string, columnNames []string, rows kv.Rows) error { - return w.importer.WriteRows(ctx, w.engineUUID, tableName, columnNames, rows) -} - -func (w *Writer) IsSynced() bool { - return true -} diff --git a/br/pkg/lightning/backend/importer/importer_test.go b/br/pkg/lightning/backend/importer/importer_test.go deleted file mode 100644 index b73128d186e44..0000000000000 --- a/br/pkg/lightning/backend/importer/importer_test.go +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package importer - -import ( - "context" - "encoding/json" - "net/http" - "net/http/httptest" - "sync" - "testing" - - "github.com/golang/mock/gomock" - "github.com/google/uuid" - "github.com/pingcap/errors" - kvpb "github.com/pingcap/kvproto/pkg/import_kvpb" - "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" - "github.com/pingcap/tidb/br/pkg/lightning/common" - "github.com/pingcap/tidb/br/pkg/mock" - "github.com/stretchr/testify/require" -) - -type importerSuite struct { - controller *gomock.Controller - mockClient *mock.MockImportKVClient - mockWriter *mock.MockImportKV_WriteEngineClient - ctx context.Context - engineUUID []byte - engine *backend.OpenedEngine - kvPairs kv.Rows -} - -const testPDAddr = "pd-addr:2379" - -func createImportSuite(t *testing.T) *importerSuite { - controller := gomock.NewController(t) - mockClient := mock.NewMockImportKVClient(controller) - mockWriter := mock.NewMockImportKV_WriteEngineClient(controller) - importer := NewMockImporter(mockClient, testPDAddr) - s := &importerSuite{controller: controller, mockClient: mockClient, mockWriter: mockWriter, ctx: context.Background()} - engineUUID := uuid.MustParse("7e3f3a3c-67ce-506d-af34-417ec138fbcb") - s.engineUUID = engineUUID[:] - s.kvPairs = kv.MakeRowsFromKvPairs([]common.KvPair{ - { - Key: []byte("k1"), - Val: []byte("v1"), - }, - { - Key: []byte("k2"), - Val: []byte("v2"), - }, - }) - - s.mockClient.EXPECT(). - OpenEngine(s.ctx, &kvpb.OpenEngineRequest{Uuid: s.engineUUID}). - Return(nil, nil) - - var err error - s.engine, err = importer.OpenEngine(s.ctx, &backend.EngineConfig{}, "`db`.`table`", -1) - require.NoError(t, err) - return s -} - -func (s *importerSuite) tearDownTest() { - s.controller.Finish() -} - -func TestWriteRows(t *testing.T) { - s := createImportSuite(t) - defer s.tearDownTest() - - s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) - - headSendCall := s.mockWriter.EXPECT(). - Send(&kvpb.WriteEngineRequest{ - Chunk: &kvpb.WriteEngineRequest_Head{ - Head: &kvpb.WriteHead{Uuid: s.engineUUID}, - }, - }). - Return(nil) - batchSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.Equal(t, []*kvpb.Mutation{ - {Op: kvpb.Mutation_Put, Key: []byte("k1"), Value: []byte("v1")}, - {Op: kvpb.Mutation_Put, Key: []byte("k2"), Value: []byte("v2")}, - }, x.GetBatch().GetMutations()) - return nil - }). - After(headSendCall) - s.mockWriter.EXPECT(). - CloseAndRecv(). - Return(nil, nil). - After(batchSendCall) - - writer, err := s.engine.LocalWriter(s.ctx, nil) - require.NoError(t, err) - err = writer.WriteRows(s.ctx, nil, s.kvPairs) - require.NoError(t, err) - st, err := writer.Close(s.ctx) - require.NoError(t, err) - require.Nil(t, st) -} - -func TestWriteHeadSendFailed(t *testing.T) { - s := createImportSuite(t) - defer s.tearDownTest() - - s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) - - headSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.NotNil(t, x.GetHead()) - return errors.Annotate(context.Canceled, "fake unrecoverable write head error") - }) - s.mockWriter.EXPECT(). - CloseAndRecv(). - Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). - After(headSendCall) - - writer, err := s.engine.LocalWriter(s.ctx, nil) - require.NoError(t, err) - err = writer.WriteRows(s.ctx, nil, s.kvPairs) - require.Error(t, err) - require.Regexp(t, "^fake unrecoverable write head error", err.Error()) -} - -func TestWriteBatchSendFailed(t *testing.T) { - s := createImportSuite(t) - defer s.tearDownTest() - - s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) - - headSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.NotNil(t, x.GetHead()) - return nil - }) - batchSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.NotNil(t, x.GetBatch()) - return errors.Annotate(context.Canceled, "fake unrecoverable write batch error") - }). - After(headSendCall) - s.mockWriter.EXPECT(). - CloseAndRecv(). - Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). - After(batchSendCall) - - writer, err := s.engine.LocalWriter(s.ctx, nil) - require.NoError(t, err) - err = writer.WriteRows(s.ctx, nil, s.kvPairs) - require.Error(t, err) - require.Regexp(t, "^fake unrecoverable write batch error", err.Error()) -} - -func TestWriteCloseFailed(t *testing.T) { - s := createImportSuite(t) - defer s.tearDownTest() - - s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) - - headSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.NotNil(t, x.GetHead()) - return nil - }) - batchSendCall := s.mockWriter.EXPECT(). - Send(gomock.Any()). - DoAndReturn(func(x *kvpb.WriteEngineRequest) error { - require.NotNil(t, x.GetBatch()) - return nil - }). - After(headSendCall) - s.mockWriter.EXPECT(). - CloseAndRecv(). - Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). - After(batchSendCall) - - writer, err := s.engine.LocalWriter(s.ctx, nil) - require.NoError(t, err) - err = writer.WriteRows(s.ctx, nil, s.kvPairs) - require.Error(t, err) - require.Regexp(t, "^fake unrecoverable close stream error", err.Error()) -} - -func TestCloseImportCleanupEngine(t *testing.T) { - s := createImportSuite(t) - defer s.tearDownTest() - - s.mockClient.EXPECT(). - CloseEngine(s.ctx, &kvpb.CloseEngineRequest{Uuid: s.engineUUID}). - Return(nil, nil) - s.mockClient.EXPECT(). - ImportEngine(s.ctx, &kvpb.ImportEngineRequest{Uuid: s.engineUUID, PdAddr: testPDAddr}). - Return(nil, nil) - s.mockClient.EXPECT(). - CleanupEngine(s.ctx, &kvpb.CleanupEngineRequest{Uuid: s.engineUUID}). - Return(nil, nil) - - engine, err := s.engine.Close(s.ctx, nil) - require.NoError(t, err) - err = engine.Import(s.ctx, 1) - require.NoError(t, err) - err = engine.Cleanup(s.ctx) - require.NoError(t, err) -} - -func BenchmarkMutationAlloc(b *testing.B) { - var g *kvpb.Mutation - for i := 0; i < b.N; i++ { - m := &kvpb.Mutation{ - Op: kvpb.Mutation_Put, - Key: nil, - Value: nil, - } - g = m - } - - _ = g -} - -func BenchmarkMutationPool(b *testing.B) { - p := sync.Pool{ - New: func() interface{} { - return &kvpb.Mutation{} - }, - } - var g *kvpb.Mutation - - for i := 0; i < b.N; i++ { - m := p.Get().(*kvpb.Mutation) - m.Op = kvpb.Mutation_Put - m.Key = nil - m.Value = nil - - g = m - - p.Put(m) - } - - _ = g -} - -func TestCheckTiDBVersion(t *testing.T) { - var version string - ctx := context.Background() - - mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - require.Equal(t, "/status", req.URL.Path) - w.WriteHeader(http.StatusOK) - err := json.NewEncoder(w).Encode(map[string]interface{}{ - "version": version, - }) - require.NoError(t, err) - })) - - tls := common.NewTLSFromMockServer(mockServer) - - version = "5.7.25-TiDB-v4.0.0" - require.Nil(t, checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion)) - - version = "5.7.25-TiDB-v9999.0.0" - err := checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) - require.Error(t, err) - require.Regexp(t, "^TiDB version too new", err.Error()) - - version = "5.7.25-TiDB-v7.0.0" - err = checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) - require.Error(t, err) - require.Regexp(t, "^TiDB version too new", err.Error()) - - version = "5.7.25-TiDB-v7.0.0-beta" - err = checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) - require.Error(t, err) - require.Regexp(t, "^TiDB version too new", err.Error()) - - version = "5.7.25-TiDB-v1.0.0" - err = checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) - require.Error(t, err) - require.Regexp(t, "^TiDB version too old", err.Error()) -} diff --git a/br/pkg/lightning/backend/kv/session.go b/br/pkg/lightning/backend/kv/session.go index 2756cc23b70d0..0e2751135c061 100644 --- a/br/pkg/lightning/backend/kv/session.go +++ b/br/pkg/lightning/backend/kv/session.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/topsql/stmtstats" "go.uber.org/zap" ) @@ -97,7 +98,7 @@ func (mb *kvMemBuf) Recycle(buf *bytesBuf) { func (mb *kvMemBuf) AllocateBuf(size int) { mb.Lock() - size = utils.MaxInt(units.MiB, int(utils.NextPowerOfTwo(int64(size)))*2) + size = mathutil.Max(units.MiB, int(utils.NextPowerOfTwo(int64(size)))*2) if len(mb.availableBufs) > 0 && mb.availableBufs[0].cap >= size { mb.buf = mb.availableBufs[0] mb.availableBufs = mb.availableBufs[1:] diff --git a/br/pkg/lightning/backend/kv/sql2kv.go b/br/pkg/lightning/backend/kv/sql2kv.go index 62eba924575d9..cfee7eceaea7a 100644 --- a/br/pkg/lightning/backend/kv/sql2kv.go +++ b/br/pkg/lightning/backend/kv/sql2kv.go @@ -77,7 +77,7 @@ func NewTableKVEncoder(tbl table.Table, options *SessionOptions) (Encoder, error autoIDFn := func(id int64) int64 { return id } if meta.PKIsHandle && meta.ContainsAutoRandomBits() { for _, col := range cols { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { incrementalBits := autoRandomIncrementBits(col, int(meta.AutoRandomBits)) autoRandomBits := rand.New(rand.NewSource(options.AutoRandomSeed)).Int63n(1<= 0 && j < len(row): value, err = table.CastValue(kvcodec.se, row[j], col.ToInfo(), false, false) @@ -373,7 +373,7 @@ func (kvcodec *tableKVEncoder) Encode( case isAutoRandom && isPk: var val types.Datum realRowID := kvcodec.autoIDFn(rowID) - if mysql.HasUnsignedFlag(col.Flag) { + if mysql.HasUnsignedFlag(col.GetFlag()) { val = types.NewUintDatum(uint64(realRowID)) } else { val = types.NewIntDatum(realRowID) @@ -454,13 +454,13 @@ func (kvcodec *tableKVEncoder) Encode( // // See: https://github.com/pingcap/tidb/blob/47f0f15b14ed54fc2222f3e304e29df7b05e6805/executor/insert_common.go#L781-L852 func getAutoRecordID(d types.Datum, target *types.FieldType) int64 { - switch target.Tp { + switch target.GetType() { case mysql.TypeFloat, mysql.TypeDouble: return int64(math.Round(d.GetFloat64())) case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: return d.GetInt64() default: - panic(fmt.Sprintf("unsupported auto-increment field type '%d'", target.Tp)) + panic(fmt.Sprintf("unsupported auto-increment field type '%d'", target.GetType())) } } diff --git a/br/pkg/lightning/backend/kv/sql2kv_test.go b/br/pkg/lightning/backend/kv/sql2kv_test.go index 56d9c6b32b249..db749e7dfd5eb 100644 --- a/br/pkg/lightning/backend/kv/sql2kv_test.go +++ b/br/pkg/lightning/backend/kv/sql2kv_test.go @@ -271,7 +271,7 @@ func TestEncodeRowFormatV2(t *testing.T) { func TestEncodeTimestamp(t *testing.T) { ty := *types.NewFieldType(mysql.TypeDatetime) - ty.Flag |= mysql.NotNullFlag + ty.AddFlag(mysql.NotNullFlag) c1 := &model.ColumnInfo{ ID: 1, Name: model.NewCIStr("c1"), diff --git a/br/pkg/lightning/backend/local/local.go b/br/pkg/lightning/backend/local/local.go index ae5d292d04dc7..be55fc7eb9cef 100644 --- a/br/pkg/lightning/backend/local/local.go +++ b/br/pkg/lightning/backend/local/local.go @@ -57,6 +57,7 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/mathutil" tikverror "github.com/tikv/client-go/v2/error" "github.com/tikv/client-go/v2/oracle" tikvclient "github.com/tikv/client-go/v2/tikv" @@ -91,6 +92,8 @@ const ( // lower the max-key-count to avoid tikv trigger region auto split regionMaxKeyCount = 1_280_000 defaultRegionSplitSize = 96 * units.MiB + // The max ranges count in a batch to split and scatter. + maxBatchSplitRanges = 4096 propRangeIndex = "tikv.range_index" @@ -322,7 +325,7 @@ func NewLocalBackend( dupeConcurrency: rangeConcurrency * 2, batchWriteKVPairs: cfg.TikvImporter.SendKVPairs, checkpointEnabled: cfg.Checkpoint.Enable, - maxOpenFiles: utils.MaxInt(maxOpenFiles, openFilesLowerThreshold), + maxOpenFiles: mathutil.Max(maxOpenFiles, openFilesLowerThreshold), engineMemCacheSize: int(cfg.TikvImporter.EngineMemCacheSize), localWriterMemCacheSize: int64(cfg.TikvImporter.LocalWriterMemCacheSize), @@ -714,6 +717,10 @@ func (local *local) WriteToTiKV( regionSplitSize int64, regionSplitKeys int64, ) ([]*sst.SSTMeta, Range, rangeStats, error) { + failpoint.Inject("WriteToTiKVNotEnoughDiskSpace", func(_ failpoint.Value) { + failpoint.Return(nil, Range{}, rangeStats{}, + errors.Errorf("The available disk of TiKV (%s) only left %d, and capacity is %d", "", 0, 0)) + }) if local.checkTiKVAvaliable { for _, peer := range region.Region.GetPeers() { var e error @@ -1099,7 +1106,7 @@ WriteAndIngest: err = local.writeAndIngestPairs(ctx, engine, region, pairStart, end, regionSplitSize, regionSplitKeys) local.ingestConcurrency.Recycle(w) if err != nil { - if common.IsContextCanceledError(err) { + if !common.IsRetryableError(err) { return err } _, regionStart, _ := codec.DecodeBytes(region.Region.StartKey, []byte{}) @@ -1146,7 +1153,7 @@ loopWrite: var rangeStats rangeStats metas, finishedRange, rangeStats, err = local.WriteToTiKV(ctx, engine, region, start, end, regionSplitSize, regionSplitKeys) if err != nil { - if common.IsContextCanceledError(err) { + if !common.IsRetryableError(err) { return err } @@ -1165,7 +1172,7 @@ loopWrite: for i := 0; i < len(metas); i += batch { start := i * batch - end := utils.MinInt((i+1)*batch, len(metas)) + end := mathutil.Min((i+1)*batch, len(metas)) ingestMetas := metas[start:end] errCnt := 0 for errCnt < maxRetryTimes { @@ -1243,7 +1250,7 @@ loopWrite: engine.importedKVSize.Add(rangeStats.totalBytes) engine.importedKVCount.Add(rangeStats.count) engine.finishedRanges.add(finishedRange) - metric.BytesCounter.WithLabelValues(metric.TableStateImported).Add(float64(rangeStats.totalBytes)) + metric.BytesCounter.WithLabelValues(metric.BytesStateImported).Add(float64(rangeStats.totalBytes)) } return errors.Trace(err) } @@ -1287,6 +1294,9 @@ func (local *local) writeAndIngestByRanges(ctx context.Context, engine *Engine, if err == nil || common.IsContextCanceledError(err) { return } + if !common.IsRetryableError(err) { + break + } log.L().Warn("write and ingest by range failed", zap.Int("retry time", i+1), log.ShortError(err)) backOffTime *= 2 @@ -1357,7 +1367,7 @@ func (local *local) ImportEngine(ctx context.Context, engineUUID uuid.UUID, regi needSplit := len(unfinishedRanges) > 1 || lfTotalSize > regionSplitSize || lfLength > regionSplitKeys // split region by given ranges for i := 0; i < maxRetryTimes; i++ { - err = local.SplitAndScatterRegionByRanges(ctx, unfinishedRanges, lf.tableInfo, needSplit, regionSplitSize) + err = local.SplitAndScatterRegionInBatches(ctx, unfinishedRanges, lf.tableInfo, needSplit, regionSplitSize, maxBatchSplitRanges) if err == nil || common.IsContextCanceledError(err) { break } @@ -1752,7 +1762,7 @@ func (local *local) isIngestRetryable( // Thus directly retry ingest may cause TiKV panic. So always return retryWrite here to avoid // this issue. // See: https://github.com/tikv/tikv/issues/9496 - return retryWrite, newRegion, errors.Errorf("not leader: %s", errPb.GetMessage()) + return retryWrite, newRegion, common.ErrKVNotLeader.GenWithStack(errPb.GetMessage()) case errPb.EpochNotMatch != nil: if currentRegions := errPb.GetEpochNotMatch().GetCurrentRegions(); currentRegions != nil { var currentRegion *metapb.Region @@ -1782,7 +1792,7 @@ func (local *local) isIngestRetryable( if newRegion != nil { retryTy = retryWrite } - return retryTy, newRegion, errors.Errorf("epoch not match: %s", errPb.GetMessage()) + return retryTy, newRegion, common.ErrKVEpochNotMatch.GenWithStack(errPb.GetMessage()) case strings.Contains(errPb.Message, "raft: proposal dropped"): // TODO: we should change 'Raft raft: proposal dropped' to a error type like 'NotLeader' newRegion, err = getRegion() @@ -1790,6 +1800,10 @@ func (local *local) isIngestRetryable( return retryNone, nil, errors.Trace(err) } return retryWrite, newRegion, errors.New(errPb.GetMessage()) + case errPb.ServerIsBusy != nil: + return retryNone, nil, common.ErrKVServerIsBusy.GenWithStack(errPb.GetMessage()) + case errPb.RegionNotFound != nil: + return retryNone, nil, common.ErrKVRegionNotFound.GenWithStack(errPb.GetMessage()) } return retryNone, nil, errors.Errorf("non-retryable error: %s", resp.GetError().GetMessage()) } diff --git a/br/pkg/lightning/backend/local/local_freebsd.go b/br/pkg/lightning/backend/local/local_freebsd.go index 3221052f43904..cb4aab3ee0766 100644 --- a/br/pkg/lightning/backend/local/local_freebsd.go +++ b/br/pkg/lightning/backend/local/local_freebsd.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build freebsd -// +build freebsd package local diff --git a/br/pkg/lightning/backend/local/local_test.go b/br/pkg/lightning/backend/local/local_test.go index 179ae09e1023c..07619c0f3075b 100644 --- a/br/pkg/lightning/backend/local/local_test.go +++ b/br/pkg/lightning/backend/local/local_test.go @@ -33,6 +33,7 @@ import ( "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/errorpb" sst "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/metapb" @@ -1188,3 +1189,14 @@ func TestMultiIngest(t *testing.T) { } } } + +func TestLocalWriteAndIngestPairsFailFast(t *testing.T) { + bak := local{} + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/backend/local/WriteToTiKVNotEnoughDiskSpace", "return(true)")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/backend/local/WriteToTiKVNotEnoughDiskSpace")) + }() + err := bak.writeAndIngestPairs(context.Background(), nil, nil, nil, nil, 0, 0) + require.Error(t, err) + require.Regexp(t, "The available disk of TiKV.*", err.Error()) +} diff --git a/br/pkg/lightning/backend/local/local_unix.go b/br/pkg/lightning/backend/local/local_unix.go index 05dc7a08bb6da..794e5e23ebb92 100644 --- a/br/pkg/lightning/backend/local/local_unix.go +++ b/br/pkg/lightning/backend/local/local_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows -// +build !windows package local diff --git a/br/pkg/lightning/backend/local/local_unix_generic.go b/br/pkg/lightning/backend/local/local_unix_generic.go index 4c4dadf0adca2..3c0114c18a846 100644 --- a/br/pkg/lightning/backend/local/local_unix_generic.go +++ b/br/pkg/lightning/backend/local/local_unix_generic.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !freebsd && !windows -// +build !freebsd,!windows package local diff --git a/br/pkg/lightning/backend/local/local_windows.go b/br/pkg/lightning/backend/local/local_windows.go index 9133c4403a13f..ec43b06c18f59 100644 --- a/br/pkg/lightning/backend/local/local_windows.go +++ b/br/pkg/lightning/backend/local/local_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows package local diff --git a/br/pkg/lightning/backend/local/localhelper.go b/br/pkg/lightning/backend/local/localhelper.go index d2ea78c6a80b0..98413b20e71e0 100644 --- a/br/pkg/lightning/backend/local/localhelper.go +++ b/br/pkg/lightning/backend/local/localhelper.go @@ -35,8 +35,8 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/logutil" split "github.com/pingcap/tidb/br/pkg/restore" - "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/multierr" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -59,10 +59,32 @@ var ( splitRetryTimes = 8 ) -// TODO remove this file and use br internal functions -// This File include region split & scatter operation just like br. +// SplitAndScatterRegionInBatches splits&scatter regions in batches. +// Too many split&scatter requests may put a lot of pressure on TiKV and PD. +func (local *local) SplitAndScatterRegionInBatches( + ctx context.Context, + ranges []Range, + tableInfo *checkpoints.TidbTableInfo, + needSplit bool, + regionSplitSize int64, + batchCnt int, +) error { + for i := 0; i < len(ranges); i += batchCnt { + batch := ranges[i:] + if len(batch) > batchCnt { + batch = batch[:batchCnt] + } + if err := local.SplitAndScatterRegionByRanges(ctx, batch, tableInfo, needSplit, regionSplitSize); err != nil { + return errors.Trace(err) + } + } + return nil +} + +// SplitAndScatterRegionByRanges include region split & scatter operation just like br. // we can simply call br function, but we need to change some function signature of br // When the ranges total size is small, we can skip the split to avoid generate empty regions. +// TODO: remove this file and use br internal functions func (local *local) SplitAndScatterRegionByRanges( ctx context.Context, ranges []Range, @@ -186,7 +208,7 @@ func (local *local) SplitAndScatterRegionByRanges( var syncLock sync.Mutex // TODO, make this size configurable - size := utils.MinInt(len(splitKeyMap), runtime.GOMAXPROCS(0)) + size := mathutil.Min(len(splitKeyMap), runtime.GOMAXPROCS(0)) ch := make(chan *splitInfo, size) eg, splitCtx := errgroup.WithContext(ctx) @@ -424,16 +446,17 @@ func (local *local) waitForSplit(ctx context.Context, regionID uint64) { } func (local *local) waitForScatterRegion(ctx context.Context, regionInfo *split.RegionInfo) { - regionID := regionInfo.Region.GetId() for i := 0; i < split.ScatterWaitMaxRetryTimes; i++ { - ok, err := local.isScatterRegionFinished(ctx, regionID) - if err != nil { - log.L().Warn("scatter region failed: do not have the region", - logutil.Region(regionInfo.Region)) + ok, err := local.checkScatterRegionFinishedOrReScatter(ctx, regionInfo) + if ok { return } - if ok { - break + if err != nil { + if !common.IsRetryableError(err) { + log.L().Warn("wait for scatter region encountered non-retryable error", logutil.Region(regionInfo.Region), zap.Error(err)) + return + } + log.L().Warn("wait for scatter region encountered error, will retry again", logutil.Region(regionInfo.Region), zap.Error(err)) } select { case <-time.After(time.Second): @@ -443,8 +466,8 @@ func (local *local) waitForScatterRegion(ctx context.Context, regionInfo *split. } } -func (local *local) isScatterRegionFinished(ctx context.Context, regionID uint64) (bool, error) { - resp, err := local.splitCli.GetOperator(ctx, regionID) +func (local *local) checkScatterRegionFinishedOrReScatter(ctx context.Context, regionInfo *split.RegionInfo) (bool, error) { + resp, err := local.splitCli.GetOperator(ctx, regionInfo.Region.GetId()) if err != nil { return false, err } @@ -462,9 +485,20 @@ func (local *local) isScatterRegionFinished(ctx context.Context, regionID uint64 return false, errors.Errorf("get operator error: %s", respErr.GetType()) } // If the current operator of the region is not 'scatter-region', we could assume - // that 'scatter-operator' has finished or timeout - ok := string(resp.GetDesc()) != "scatter-region" || resp.GetStatus() != pdpb.OperatorStatus_RUNNING - return ok, nil + // that 'scatter-operator' has finished. + if string(resp.GetDesc()) != "scatter-region" { + return true, nil + } + switch resp.GetStatus() { + case pdpb.OperatorStatus_RUNNING: + return false, nil + case pdpb.OperatorStatus_SUCCESS: + return true, nil + default: + log.L().Warn("scatter-region operator status is abnormal, will scatter region again", + logutil.Region(regionInfo.Region), zap.Stringer("status", resp.GetStatus())) + return false, local.splitCli.ScatterRegion(ctx, regionInfo) + } } func getSplitKeysByRanges(ranges []Range, regions []*split.RegionInfo) map[uint64][][]byte { diff --git a/br/pkg/lightning/backend/local/localhelper_test.go b/br/pkg/lightning/backend/local/localhelper_test.go index dd52b71493507..48ce64da5e3b6 100644 --- a/br/pkg/lightning/backend/local/localhelper_test.go +++ b/br/pkg/lightning/backend/local/localhelper_test.go @@ -17,6 +17,7 @@ package local import ( "bytes" "context" + "fmt" "math" "math/rand" "sort" @@ -302,7 +303,8 @@ func cloneRegion(region *restore.RegionInfo) *restore.RegionInfo { return &restore.RegionInfo{Region: r, Leader: l} } -// region: [, aay), [aay, bba), [bba, bbh), [bbh, cca), [cca, ) +// For keys ["", "aay", "bba", "bbh", "cca", ""], the key ranges of +// regions are [, aay), [aay, bba), [bba, bbh), [bbh, cca), [cca, ). func initTestClient(keys [][]byte, hook clientHook) *testClient { peers := make([]*metapb.Peer, 1) peers[0] = &metapb.Peer{ @@ -574,6 +576,44 @@ func TestBatchSplitByRangesNoValidKeys(t *testing.T) { doTestBatchSplitRegionByRanges(context.Background(), t, &splitRegionNoValidKeyHook{returnErrTimes: math.MaxInt32}, "no valid key", defaultHook{}) } +func TestSplitAndScatterRegionInBatches(t *testing.T) { + splitHook := defaultHook{} + deferFunc := splitHook.setup(t) + defer deferFunc() + + keys := [][]byte{[]byte(""), []byte("a"), []byte("b"), []byte("")} + client := initTestClient(keys, nil) + local := &local{ + splitCli: client, + g: glue.NewExternalTiDBGlue(nil, mysql.ModeNone), + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var ranges []Range + for i := 0; i < 20; i++ { + ranges = append(ranges, Range{ + start: []byte(fmt.Sprintf("a%02d", i)), + end: []byte(fmt.Sprintf("a%02d", i+1)), + }) + } + + err := local.SplitAndScatterRegionInBatches(ctx, ranges, nil, true, 1000, 4) + require.NoError(t, err) + + rangeStart := codec.EncodeBytes([]byte{}, []byte("a")) + rangeEnd := codec.EncodeBytes([]byte{}, []byte("b")) + regions, err := restore.PaginateScanRegion(ctx, client, rangeStart, rangeEnd, 5) + require.NoError(t, err) + result := [][]byte{[]byte("a"), []byte("a00"), []byte("a01"), []byte("a02"), []byte("a03"), []byte("a04"), + []byte("a05"), []byte("a06"), []byte("a07"), []byte("a08"), []byte("a09"), []byte("a10"), []byte("a11"), + []byte("a12"), []byte("a13"), []byte("a14"), []byte("a15"), []byte("a16"), []byte("a17"), []byte("a18"), + []byte("a19"), []byte("a20"), []byte("b"), + } + checkRegionRanges(t, regions, result) +} + type reportAfterSplitHook struct { noopHook ch chan<- struct{} diff --git a/br/pkg/lightning/backend/tidb/tidb.go b/br/pkg/lightning/backend/tidb/tidb.go index 73d8c3ecd25d6..fe93c84c249db 100644 --- a/br/pkg/lightning/backend/tidb/tidb.go +++ b/br/pkg/lightning/backend/tidb/tidb.go @@ -446,7 +446,7 @@ rowLoop: switch { case err == nil: continue rowLoop - case utils.IsRetryableError(err): + case common.IsRetryableError(err): // retry next loop case be.errorMgr.TypeErrorsRemain() > 0: // WriteBatchRowsToDB failed in the batch mode and can not be retried, @@ -562,7 +562,7 @@ func (be *tidbBackend) execStmts(ctx context.Context, stmtTasks []stmtTask, tabl return errors.Trace(err) } // Retry the non-batch insert here if this is not the last retry. - if utils.IsRetryableError(err) && i != writeRowsMaxRetryTimes-1 { + if common.IsRetryableError(err) && i != writeRowsMaxRetryTimes-1 { continue } firstRow := stmtTask.rows[0] @@ -637,13 +637,14 @@ func (be *tidbBackend) FetchRemoteTableModels(ctx context.Context, schemaName st if strings.Contains(columnExtra, "auto_increment") { flag |= mysql.AutoIncrementFlag } + + ft := types.FieldType{} + ft.SetFlag(flag) curTable.Columns = append(curTable.Columns, &model.ColumnInfo{ - Name: model.NewCIStr(columnName), - Offset: curColOffset, - State: model.StatePublic, - FieldType: types.FieldType{ - Flag: flag, - }, + Name: model.NewCIStr(columnName), + Offset: curColOffset, + State: model.StatePublic, + FieldType: ft, GeneratedExprString: generationExpr, }) curColOffset++ @@ -669,9 +670,9 @@ func (be *tidbBackend) FetchRemoteTableModels(ctx context.Context, schemaName st if col.Name.O == info.Column { switch info.Type { case "AUTO_INCREMENT": - col.Flag |= mysql.AutoIncrementFlag + col.AddFlag(mysql.AutoIncrementFlag) case "AUTO_RANDOM": - col.Flag |= mysql.PriKeyFlag + col.AddFlag(mysql.PriKeyFlag) tbl.PKIsHandle = true // set a stub here, since we don't really need the real value tbl.AutoRandomBits = 1 diff --git a/br/pkg/lightning/backend/tidb/tidb_test.go b/br/pkg/lightning/backend/tidb/tidb_test.go index 5b3d06a88c0f2..b7de642a26746 100644 --- a/br/pkg/lightning/backend/tidb/tidb_test.go +++ b/br/pkg/lightning/backend/tidb/tidb_test.go @@ -25,11 +25,11 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/backend" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/errormanager" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/verification" - "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -219,10 +219,10 @@ func testStrictMode(t *testing.T) { s := createMysqlSuite(t) defer s.TearDownTest(t) ft := *types.NewFieldType(mysql.TypeVarchar) - ft.Charset = charset.CharsetUTF8MB4 + ft.SetCharset(charset.CharsetUTF8MB4) col0 := &model.ColumnInfo{ID: 1, Name: model.NewCIStr("s0"), State: model.StatePublic, Offset: 0, FieldType: ft} ft = *types.NewFieldType(mysql.TypeString) - ft.Charset = charset.CharsetASCII + ft.SetCharset(charset.CharsetASCII) col1 := &model.ColumnInfo{ID: 2, Name: model.NewCIStr("s1"), State: model.StatePublic, Offset: 1, FieldType: ft} tblInfo := &model.TableInfo{ID: 1, Columns: []*model.ColumnInfo{col0, col1}, PKIsHandle: false, State: model.StatePublic} tbl, err := tables.TableFromMeta(kv.NewPanickingAllocators(0), tblInfo) @@ -270,6 +270,8 @@ func TestFetchRemoteTableModels_3_x(t *testing.T) { bk := tidb.NewTiDBBackend(s.dbHandle, config.ErrorOnDup, errormanager.New(nil, config.NewConfig())) tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") require.NoError(t, err) + ft := types.FieldType{} + ft.SetFlag(mysql.AutoIncrementFlag) require.Equal(t, []*model.TableInfo{ { Name: model.NewCIStr("t"), @@ -277,12 +279,10 @@ func TestFetchRemoteTableModels_3_x(t *testing.T) { PKIsHandle: true, Columns: []*model.ColumnInfo{ { - Name: model.NewCIStr("id"), - Offset: 0, - State: model.StatePublic, - FieldType: types.FieldType{ - Flag: mysql.AutoIncrementFlag, - }, + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: ft, }, }, }, @@ -307,6 +307,8 @@ func TestFetchRemoteTableModels_4_0(t *testing.T) { bk := tidb.NewTiDBBackend(s.dbHandle, config.ErrorOnDup, errormanager.New(nil, config.NewConfig())) tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") require.NoError(t, err) + ft := types.FieldType{} + ft.SetFlag(mysql.AutoIncrementFlag | mysql.UnsignedFlag) require.Equal(t, []*model.TableInfo{ { Name: model.NewCIStr("t"), @@ -314,12 +316,10 @@ func TestFetchRemoteTableModels_4_0(t *testing.T) { PKIsHandle: true, Columns: []*model.ColumnInfo{ { - Name: model.NewCIStr("id"), - Offset: 0, - State: model.StatePublic, - FieldType: types.FieldType{ - Flag: mysql.AutoIncrementFlag | mysql.UnsignedFlag, - }, + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: ft, }, }, }, @@ -344,6 +344,8 @@ func TestFetchRemoteTableModels_4_x_auto_increment(t *testing.T) { bk := tidb.NewTiDBBackend(s.dbHandle, config.ErrorOnDup, errormanager.New(nil, config.NewConfig())) tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") require.NoError(t, err) + ft := types.FieldType{} + ft.SetFlag(mysql.AutoIncrementFlag) require.Equal(t, []*model.TableInfo{ { Name: model.NewCIStr("t"), @@ -351,12 +353,10 @@ func TestFetchRemoteTableModels_4_x_auto_increment(t *testing.T) { PKIsHandle: true, Columns: []*model.ColumnInfo{ { - Name: model.NewCIStr("id"), - Offset: 0, - State: model.StatePublic, - FieldType: types.FieldType{ - Flag: mysql.AutoIncrementFlag, - }, + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: ft, }, }, }, @@ -381,6 +381,8 @@ func TestFetchRemoteTableModels_4_x_auto_random(t *testing.T) { bk := tidb.NewTiDBBackend(s.dbHandle, config.ErrorOnDup, errormanager.New(nil, config.NewConfig())) tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") require.NoError(t, err) + ft := types.FieldType{} + ft.SetFlag(mysql.PriKeyFlag) require.Equal(t, []*model.TableInfo{ { Name: model.NewCIStr("t"), @@ -389,12 +391,10 @@ func TestFetchRemoteTableModels_4_x_auto_random(t *testing.T) { AutoRandomBits: 1, Columns: []*model.ColumnInfo{ { - Name: model.NewCIStr("id"), - Offset: 0, - State: model.StatePublic, - FieldType: types.FieldType{ - Flag: mysql.PriKeyFlag, - }, + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: ft, GeneratedExprString: "1 + 2", }, }, @@ -424,7 +424,7 @@ func TestWriteRowsErrorNoRetry(t *testing.T) { require.NoError(t, err) err = writer.WriteRows(ctx, []string{"a"}, dataRows) require.Error(t, err) - require.False(t, utils.IsRetryableError(err), "err: %v", err) + require.False(t, common.IsRetryableError(err), "err: %v", err) } func TestWriteRowsErrorDowngradingAll(t *testing.T) { diff --git a/br/pkg/lightning/checkpoints/checkpoints.go b/br/pkg/lightning/checkpoints/checkpoints.go index d2d5320595999..36cefed180ae3 100644 --- a/br/pkg/lightning/checkpoints/checkpoints.go +++ b/br/pkg/lightning/checkpoints/checkpoints.go @@ -36,8 +36,8 @@ import ( verify "github.com/pingcap/tidb/br/pkg/lightning/verification" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/version/build" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/zap" - "modernc.org/mathutil" ) type CheckpointStatus uint8 @@ -432,6 +432,7 @@ type ChunkCheckpointMerger struct { Pos int64 RowID int64 ColumnPermutation []int + EndOffset int64 // For test only. } func (merger *ChunkCheckpointMerger) MergeInto(cpd *TableCheckpointDiff) { @@ -462,7 +463,7 @@ type RebaseCheckpointMerger struct { func (merger *RebaseCheckpointMerger) MergeInto(cpd *TableCheckpointDiff) { cpd.hasRebase = true - cpd.allocBase = mathutil.MaxInt64(cpd.allocBase, merger.AllocBase) + cpd.allocBase = mathutil.Max(cpd.allocBase, merger.AllocBase) } type DestroyedTableCheckpoint struct { diff --git a/br/pkg/lightning/common/errors.go b/br/pkg/lightning/common/errors.go index da9efab5b3087..ccb465ec4b86a 100644 --- a/br/pkg/lightning/common/errors.go +++ b/br/pkg/lightning/common/errors.go @@ -73,6 +73,10 @@ var ( ErrCheckKVVersion = errors.Normalize("check tikv version error", errors.RFCCodeText("Lightning:KV:ErrCheckKVVersion")) ErrCreateKVClient = errors.Normalize("create kv client error", errors.RFCCodeText("Lightning:KV:ErrCreateKVClient")) ErrCheckMultiIngest = errors.Normalize("check multi-ingest support error", errors.RFCCodeText("Lightning:KV:ErrCheckMultiIngest")) + ErrKVEpochNotMatch = errors.Normalize("epoch not match", errors.RFCCodeText("Lightning:KV:EpochNotMatch")) + ErrKVNotLeader = errors.Normalize("not leader", errors.RFCCodeText("Lightning:KV:NotLeader")) + ErrKVServerIsBusy = errors.Normalize("server is busy", errors.RFCCodeText("Lightning:KV:ServerIsBusy")) + ErrKVRegionNotFound = errors.Normalize("region not found", errors.RFCCodeText("Lightning:KV:RegionNotFound")) ErrUnknownBackend = errors.Normalize("unknown backend %s", errors.RFCCodeText("Lightning:Restore:ErrUnknownBackend")) ErrCheckLocalFile = errors.Normalize("cannot find local file for table: %s engineDir: %s", errors.RFCCodeText("Lightning:Restore:ErrCheckLocalFile")) diff --git a/br/pkg/lightning/common/retry.go b/br/pkg/lightning/common/retry.go new file mode 100644 index 0000000000000..accf7423414b4 --- /dev/null +++ b/br/pkg/lightning/common/retry.go @@ -0,0 +1,100 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "context" + "database/sql" + "database/sql/driver" + "io" + "net" + "os" + "syscall" + + "github.com/go-sql-driver/mysql" + "github.com/pingcap/errors" + berrors "github.com/pingcap/tidb/br/pkg/errors" + tmysql "github.com/pingcap/tidb/errno" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// IsRetryableError returns whether the error is transient (e.g. network +// connection dropped) or irrecoverable (e.g. user pressing Ctrl+C). This +// function returns `false` (irrecoverable) if `err == nil`. +// +// If the error is a multierr, returns true only if all suberrors are retryable. +func IsRetryableError(err error) bool { + for _, singleError := range errors.Errors(err) { + if !isSingleRetryableError(singleError) { + return false + } + } + return true +} + +func isSingleRetryableError(err error) bool { + err = errors.Cause(err) + + switch err { + case nil, context.Canceled, context.DeadlineExceeded, io.EOF, sql.ErrNoRows: + return false + case mysql.ErrInvalidConn, driver.ErrBadConn: + return true + } + + switch nerr := err.(type) { + case net.Error: + if nerr.Timeout() { + return true + } + switch cause := nerr.(type) { + case *net.OpError: + syscallErr, ok := cause.Unwrap().(*os.SyscallError) + if ok { + return syscallErr.Err == syscall.ECONNREFUSED || syscallErr.Err == syscall.ECONNRESET + } + } + return false + case *mysql.MySQLError: + switch nerr.Number { + // ErrLockDeadlock can retry to commit while meet deadlock + case tmysql.ErrUnknown, tmysql.ErrLockDeadlock, tmysql.ErrWriteConflict, tmysql.ErrWriteConflictInTiDB, + tmysql.ErrPDServerTimeout, tmysql.ErrTiKVServerTimeout, tmysql.ErrTiKVServerBusy, tmysql.ErrResolveLockTimeout, + tmysql.ErrRegionUnavailable, tmysql.ErrInfoSchemaExpired, tmysql.ErrInfoSchemaChanged, tmysql.ErrTxnRetryable: + return true + default: + return false + } + case *errors.Error: + switch { + case berrors.Is(nerr, ErrKVEpochNotMatch), berrors.Is(nerr, ErrKVNotLeader), + berrors.Is(nerr, ErrKVRegionNotFound), berrors.Is(nerr, ErrKVServerIsBusy): + // common.ErrKVServerIsBusy is a little duplication with tmysql.ErrTiKVServerBusy + // it's because the response of sst.ingest gives us a sst.IngestResponse which doesn't contain error code, + // so we have to transform it into a defined code + return true + } + return false + default: + switch status.Code(err) { + case codes.DeadlineExceeded, codes.NotFound, codes.AlreadyExists, codes.PermissionDenied, codes.ResourceExhausted, codes.Aborted, codes.OutOfRange, codes.Unavailable, codes.DataLoss: + return true + case codes.Unknown: + return false + default: + return false + } + } +} diff --git a/br/pkg/utils/retry_test.go b/br/pkg/lightning/common/retry_test.go similarity index 65% rename from br/pkg/utils/retry_test.go rename to br/pkg/lightning/common/retry_test.go index eafe233b7d49e..670004260f5a1 100644 --- a/br/pkg/utils/retry_test.go +++ b/br/pkg/lightning/common/retry_test.go @@ -1,7 +1,21 @@ -package utils +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package common import ( "context" + "database/sql/driver" "fmt" "io" "net" @@ -24,6 +38,21 @@ func TestIsRetryableError(t *testing.T) { require.False(t, IsRetryableError(&net.DNSError{})) require.True(t, IsRetryableError(&net.DNSError{IsTimeout: true})) + // kv errors + require.True(t, IsRetryableError(ErrKVNotLeader)) + require.True(t, IsRetryableError(ErrKVEpochNotMatch)) + require.True(t, IsRetryableError(ErrKVServerIsBusy)) + require.True(t, IsRetryableError(ErrKVRegionNotFound)) + require.True(t, IsRetryableError(ErrKVNotLeader.GenWithStack("test"))) + require.True(t, IsRetryableError(ErrKVEpochNotMatch.GenWithStack("test"))) + require.True(t, IsRetryableError(ErrKVServerIsBusy.GenWithStack("test"))) + require.True(t, IsRetryableError(ErrKVRegionNotFound.GenWithStack("test"))) + + // net: connection refused + _, err := net.Dial("tcp", "localhost:65533") + require.Error(t, err) + require.True(t, IsRetryableError(err)) + // MySQL Errors require.False(t, IsRetryableError(&mysql.MySQLError{})) require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrUnknown})) @@ -41,7 +70,7 @@ func TestIsRetryableError(t *testing.T) { // gRPC Errors require.False(t, IsRetryableError(status.Error(codes.Canceled, ""))) - require.True(t, IsRetryableError(status.Error(codes.Unknown, ""))) + require.False(t, IsRetryableError(status.Error(codes.Unknown, ""))) require.True(t, IsRetryableError(status.Error(codes.DeadlineExceeded, ""))) require.True(t, IsRetryableError(status.Error(codes.NotFound, ""))) require.True(t, IsRetryableError(status.Error(codes.AlreadyExists, ""))) @@ -54,7 +83,12 @@ func TestIsRetryableError(t *testing.T) { // sqlmock errors require.False(t, IsRetryableError(fmt.Errorf("call to database Close was not expected"))) - require.True(t, IsRetryableError(errors.New("call to database Close was not expected"))) + require.False(t, IsRetryableError(errors.New("call to database Close was not expected"))) + + // stderr + require.True(t, IsRetryableError(mysql.ErrInvalidConn)) + require.True(t, IsRetryableError(driver.ErrBadConn)) + require.False(t, IsRetryableError(fmt.Errorf("error"))) // multierr require.False(t, IsRetryableError(multierr.Combine(context.Canceled, context.Canceled))) diff --git a/br/pkg/lightning/common/security.go b/br/pkg/lightning/common/security.go index 9db53f78a5115..7f55c07603919 100644 --- a/br/pkg/lightning/common/security.go +++ b/br/pkg/lightning/common/security.go @@ -31,7 +31,6 @@ import ( "google.golang.org/grpc/credentials" ) -// TLS type TLS struct { caPath string certPath string @@ -50,16 +49,6 @@ func ToTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) { return nil, nil } - // Load the client certificates from disk - var certificates []tls.Certificate - if len(certPath) != 0 && len(keyPath) != 0 { - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - return nil, errors.Annotate(err, "could not load client key pair") - } - certificates = []tls.Certificate{cert} - } - // Create a certificate pool from CA certPool := x509.NewCertPool() ca, err := os.ReadFile(caPath) @@ -72,12 +61,28 @@ func ToTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) { return nil, errors.New("failed to append ca certs") } - return &tls.Config{ - Certificates: certificates, - RootCAs: certPool, - NextProtos: []string{"h2", "http/1.1"}, // specify `h2` to let Go use HTTP/2. - MinVersion: tls.VersionTLS12, - }, nil + tlsConfig := &tls.Config{ + RootCAs: certPool, + NextProtos: []string{"h2", "http/1.1"}, // specify `h2` to let Go use HTTP/2. + MinVersion: tls.VersionTLS12, + } + + if len(certPath) != 0 && len(keyPath) != 0 { + loadCert := func() (*tls.Certificate, error) { + cert, err := tls.LoadX509KeyPair(certPath, keyPath) + if err != nil { + return nil, errors.Annotate(err, "could not load client key pair") + } + return &cert, nil + } + tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + return loadCert() + } + tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + return loadCert() + } + } + return tlsConfig, nil } // NewTLS constructs a new HTTP client with TLS configured with the CA, diff --git a/br/pkg/lightning/common/security_test.go b/br/pkg/lightning/common/security_test.go index a68b8e1f4437a..3359935b73bf0 100644 --- a/br/pkg/lightning/common/security_test.go +++ b/br/pkg/lightning/common/security_test.go @@ -81,15 +81,29 @@ func TestInvalidTLS(t *testing.T) { _, err = common.NewTLS(caPath, "", "", "localhost") require.Regexp(t, "failed to append ca certs", err.Error()) + err = os.WriteFile(caPath, []byte(`-----BEGIN CERTIFICATE----- +MIIBITCBxwIUf04/Hucshr7AynmgF8JeuFUEf9EwCgYIKoZIzj0EAwIwEzERMA8G +A1UEAwwIYnJfdGVzdHMwHhcNMjIwNDEzMDcyNDQxWhcNMjIwNDE1MDcyNDQxWjAT +MREwDwYDVQQDDAhicl90ZXN0czBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL+X +wczUg0AbaFFaCI+FAk3K9vbB9JeIORgGKS+F1TKip5tvm96g7S5lq8SgY38SXVc3 +0yS3YqWZqnRjWi+sLwIwCgYIKoZIzj0EAwIDSQAwRgIhAJcpSwsUhqkM08LK1gYC +ze4ZnCkwJdP2VdpI3WZsoI7zAiEAjP8X1c0iFwYxdAbQAveX+9msVrzyUpZOohi4 +RtgQTNI= +-----END CERTIFICATE----- +`), 0o644) + require.NoError(t, err) + certPath := filepath.Join(tempDir, "test.pem") keyPath := filepath.Join(tempDir, "test.key") - _, err = common.NewTLS(caPath, certPath, keyPath, "localhost") + tls, err := common.NewTLS(caPath, certPath, keyPath, "localhost") + _, err = tls.TLSConfig().GetCertificate(nil) require.Regexp(t, "could not load client key pair: open.*", err.Error()) err = os.WriteFile(certPath, []byte("invalid cert content"), 0o644) require.NoError(t, err) err = os.WriteFile(keyPath, []byte("invalid key content"), 0o600) require.NoError(t, err) - _, err = common.NewTLS(caPath, certPath, keyPath, "localhost") + tls, err = common.NewTLS(caPath, certPath, keyPath, "localhost") + _, err = tls.TLSConfig().GetCertificate(nil) require.Regexp(t, "could not load client key pair: tls.*", err.Error()) } diff --git a/br/pkg/lightning/common/storage_unix.go b/br/pkg/lightning/common/storage_unix.go index e779aeb2ea57c..6c4ab4cbeb666 100644 --- a/br/pkg/lightning/common/storage_unix.go +++ b/br/pkg/lightning/common/storage_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows -// +build !windows // TODO: Deduplicate this implementation with DM! diff --git a/br/pkg/lightning/common/storage_windows.go b/br/pkg/lightning/common/storage_windows.go index 8617e28d30893..89b9483592f94 100644 --- a/br/pkg/lightning/common/storage_windows.go +++ b/br/pkg/lightning/common/storage_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows // TODO: Deduplicate this implementation with DM! diff --git a/br/pkg/lightning/common/util.go b/br/pkg/lightning/common/util.go index 054edcbb17d90..40b7160ed5e30 100644 --- a/br/pkg/lightning/common/util.go +++ b/br/pkg/lightning/common/util.go @@ -168,7 +168,7 @@ outside: // do not retry NotFound error case errors.IsNotFound(err): break outside - case utils.IsRetryableError(err): + case IsRetryableError(err): logger.Warn(purpose+" failed but going to try again", log.ShortError(err)) continue default: diff --git a/br/pkg/lightning/common/util_test.go b/br/pkg/lightning/common/util_test.go index 3b6ff5f92ef62..cb13a10db9d5d 100644 --- a/br/pkg/lightning/common/util_test.go +++ b/br/pkg/lightning/common/util_test.go @@ -187,7 +187,7 @@ func TestSQLWithRetry(t *testing.T) { // retry defaultMaxRetry times and still failed for i := 0; i < 3; i++ { - mock.ExpectQuery("select a from test.t1").WillReturnError(errors.New("mock error")) + mock.ExpectQuery("select a from test.t1").WillReturnError(errors.Annotate(mysql.ErrInvalidConn, "mock error")) } err = sqlWithRetry.QueryRow(context.Background(), "", "select a from test.t1", aValue) require.Regexp(t, ".*mock error", err.Error()) diff --git a/br/pkg/lightning/config/config.go b/br/pkg/lightning/config/config.go index 7af314d55950d..1955e11c7e067 100644 --- a/br/pkg/lightning/config/config.go +++ b/br/pkg/lightning/config/config.go @@ -51,8 +51,6 @@ const ( // BackendTiDB is a constant for choosing the "TiDB" backend in the configuration. BackendTiDB = "tidb" - // BackendImporter is a constant for choosing the "Importer" backend in the configuration. - BackendImporter = "importer" // BackendLocal is a constant for choosing the "Local" backup in the configuration. // In this mode, we write & sort kv pairs with local storage and directly write them to tikv. BackendLocal = "local" @@ -518,6 +516,7 @@ type FileRouteRule struct { } type TikvImporter struct { + // Deprecated: only used to keep the compatibility. Addr string `toml:"addr" json:"addr"` Backend string `toml:"backend" json:"backend"` OnDuplicate string `toml:"on-duplicate" json:"on-duplicate"` @@ -729,7 +728,6 @@ func (cfg *Config) LoadFromGlobal(global *GlobalConfig) error { cfg.Mydumper.NoSchema = global.Mydumper.NoSchema cfg.Mydumper.SourceDir = global.Mydumper.SourceDir cfg.Mydumper.Filter = global.Mydumper.Filter - cfg.TikvImporter.Addr = global.TikvImporter.Addr cfg.TikvImporter.Backend = global.TikvImporter.Backend cfg.TikvImporter.SortedKVDir = global.TikvImporter.SortedKVDir cfg.Checkpoint.Enable = global.Checkpoint.Enable @@ -873,7 +871,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { cfg.PostRestore.Checksum = OpLevelOff cfg.PostRestore.Analyze = OpLevelOff cfg.PostRestore.Compact = false - case BackendImporter, BackendLocal: + case BackendLocal: // RegionConcurrency > NumCPU is meaningless. cpuCount := runtime.NumCPU() if cfg.App.RegionConcurrency > cpuCount { diff --git a/br/pkg/lightning/config/config_test.go b/br/pkg/lightning/config/config_test.go index ce2d910102db4..881f89de3d380 100644 --- a/br/pkg/lightning/config/config_test.go +++ b/br/pkg/lightning/config/config_test.go @@ -636,7 +636,7 @@ func TestLoadConfig(t *testing.T) { func TestDefaultImporterBackendValue(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) - cfg.TikvImporter.Backend = "importer" + cfg.TikvImporter.Backend = "local" cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) require.NoError(t, err) @@ -658,7 +658,7 @@ func TestDefaultTidbBackendValue(t *testing.T) { func TestDefaultCouldBeOverwritten(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) - cfg.TikvImporter.Backend = "importer" + cfg.TikvImporter.Backend = "local" cfg.App.IndexConcurrency = 20 cfg.App.TableConcurrency = 60 cfg.TiDB.DistSQLScanConcurrency = 1 diff --git a/br/pkg/lightning/config/configlist_test.go b/br/pkg/lightning/config/configlist_test.go index c5b3e449b2759..bdc875f4dc83e 100644 --- a/br/pkg/lightning/config/configlist_test.go +++ b/br/pkg/lightning/config/configlist_test.go @@ -26,32 +26,32 @@ import ( func TestNormalPushPop(t *testing.T) { cl := config.NewConfigList() - cl.Push(&config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}}) - cl.Push(&config.Config{TikvImporter: config.TikvImporter{Addr: "2.2.2.2:2222"}}) + cl.Push(&config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted1"}}) + cl.Push(&config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted2"}}) startTime := time.Now() cfg, err := cl.Pop(context.Background()) // these two should never block. require.Less(t, time.Since(startTime), 100*time.Millisecond) require.NoError(t, err) - require.Equal(t, "1.1.1.1:1111", cfg.TikvImporter.Addr) + require.Equal(t, "/tmp/sorted1", cfg.TikvImporter.SortedKVDir) startTime = time.Now() cfg, err = cl.Pop(context.Background()) require.Less(t, time.Since(startTime), 100*time.Millisecond) require.NoError(t, err) - require.Equal(t, "2.2.2.2:2222", cfg.TikvImporter.Addr) + require.Equal(t, "/tmp/sorted2", cfg.TikvImporter.SortedKVDir) startTime = time.Now() go func() { time.Sleep(400 * time.Millisecond) - cl.Push(&config.Config{TikvImporter: config.TikvImporter{Addr: "3.3.3.3:3333"}}) + cl.Push(&config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted3"}}) }() cfg, err = cl.Pop(context.Background()) // this should block for ≥400ms require.GreaterOrEqual(t, time.Since(startTime), 400*time.Millisecond) require.NoError(t, err) - require.Equal(t, "3.3.3.3:3333", cfg.TikvImporter.Addr) + require.Equal(t, "/tmp/sorted3", cfg.TikvImporter.SortedKVDir) } func TestContextCancel(t *testing.T) { @@ -72,11 +72,11 @@ func TestContextCancel(t *testing.T) { func TestGetRemove(t *testing.T) { cl := config.NewConfigList() - cfg1 := &config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}} + cfg1 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted1"}} cl.Push(cfg1) - cfg2 := &config.Config{TikvImporter: config.TikvImporter{Addr: "2.2.2.2:2222"}} + cfg2 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted2"}} cl.Push(cfg2) - cfg3 := &config.Config{TikvImporter: config.TikvImporter{Addr: "3.3.3.3:3333"}} + cfg3 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted3"}} cl.Push(cfg3) cfg, ok := cl.Get(cfg2.TaskID) @@ -105,11 +105,11 @@ func TestGetRemove(t *testing.T) { func TestMoveFrontBack(t *testing.T) { cl := config.NewConfigList() - cfg1 := &config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}} + cfg1 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted1"}} cl.Push(cfg1) - cfg2 := &config.Config{TikvImporter: config.TikvImporter{Addr: "2.2.2.2:2222"}} + cfg2 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted2"}} cl.Push(cfg2) - cfg3 := &config.Config{TikvImporter: config.TikvImporter{Addr: "3.3.3.3:3333"}} + cfg3 := &config.Config{TikvImporter: config.TikvImporter{SortedKVDir: "/tmp/sorted3"}} cl.Push(cfg3) require.Equal(t, []int64{cfg1.TaskID, cfg2.TaskID, cfg3.TaskID}, cl.AllIDs()) diff --git a/br/pkg/lightning/config/global.go b/br/pkg/lightning/config/global.go index 5bba95ae3d4d4..6a5572b6e544f 100644 --- a/br/pkg/lightning/config/global.go +++ b/br/pkg/lightning/config/global.go @@ -59,7 +59,6 @@ type GlobalMydumper struct { } type GlobalImporter struct { - Addr string `toml:"addr" json:"addr"` Backend string `toml:"backend" json:"backend"` SortedKVDir string `toml:"sorted-kv-dir" json:"sorted-kv-dir"` } @@ -153,8 +152,7 @@ func LoadGlobalConfig(args []string, extraFlags func(*flag.FlagSet)) (*GlobalCon tidbStatusPort := fs.Int("tidb-status", 0, "TiDB server status port (default 10080)") pdAddr := fs.String("pd-urls", "", "PD endpoint address") dataSrcPath := fs.String("d", "", "Directory of the dump to import") - importerAddr := fs.String("importer", "", "address (host:port) to connect to tikv-importer") - backend := flagext.ChoiceVar(fs, "backend", "", `delivery backend: local, importer, tidb`, "", "local", "importer", "tidb") + backend := flagext.ChoiceVar(fs, "backend", "", `delivery backend: local, tidb`, "", "local", "tidb") sortedKVDir := fs.String("sorted-kv-dir", "", "path for KV pairs when local backend enabled") enableCheckpoint := fs.Bool("enable-checkpoint", true, "whether to enable checkpoints") noSchema := fs.Bool("no-schema", false, "ignore schema files, get schema directly from TiDB instead") @@ -225,9 +223,6 @@ func LoadGlobalConfig(args []string, extraFlags func(*flag.FlagSet)) (*GlobalCon if *dataSrcPath != "" { cfg.Mydumper.SourceDir = *dataSrcPath } - if *importerAddr != "" { - cfg.TikvImporter.Addr = *importerAddr - } if *serverMode { cfg.App.ServerMode = true } diff --git a/br/pkg/lightning/lightning.go b/br/pkg/lightning/lightning.go index 4ad8622c8d5fb..3c6f0256a740c 100644 --- a/br/pkg/lightning/lightning.go +++ b/br/pkg/lightning/lightning.go @@ -17,7 +17,11 @@ package lightning import ( "compress/gzip" "context" + "crypto/ecdsa" + "crypto/rand" + "crypto/x509" "encoding/json" + "encoding/pem" "fmt" "io" "net" @@ -30,12 +34,9 @@ import ( "sync" "time" - "github.com/google/uuid" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/import_sstpb" - "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" "github.com/pingcap/tidb/br/pkg/lightning/backend/local" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" @@ -133,6 +134,50 @@ func (l *Lightning) GoServe() error { return l.goServe(statusAddr, io.Discard) } +// TODO: maybe handle http request using gin +type loggingResponseWriter struct { + http.ResponseWriter + statusCode int + body string +} + +func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { + return &loggingResponseWriter{ResponseWriter: w, statusCode: http.StatusOK} +} + +func (lrw *loggingResponseWriter) WriteHeader(code int) { + lrw.statusCode = code + lrw.ResponseWriter.WriteHeader(code) +} + +func (lrw *loggingResponseWriter) Write(d []byte) (int, error) { + // keep first part of the response for logging, max 1K + if lrw.body == "" && len(d) > 0 { + length := len(d) + if length > 1024 { + length = 1024 + } + lrw.body = string(d[:length]) + } + return lrw.ResponseWriter.Write(d) +} + +func httpHandleWrapper(h http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + logger := log.L().With(zap.String("method", r.Method), zap.Stringer("url", r.URL)). + Begin(zapcore.InfoLevel, "process http request") + + newWriter := newLoggingResponseWriter(w) + h.ServeHTTP(newWriter, r) + + bodyField := zap.Skip() + if newWriter.Header().Get("Content-Encoding") != "gzip" { + bodyField = zap.String("body", newWriter.body) + } + logger.End(zapcore.InfoLevel, nil, zap.Int("status", newWriter.statusCode), bodyField) + } +} + func (l *Lightning) goServe(statusAddr string, realAddrWriter io.Writer) error { mux := http.NewServeMux() mux.Handle("/", http.RedirectHandler("/web/", http.StatusFound)) @@ -145,13 +190,13 @@ func (l *Lightning) goServe(statusAddr string, realAddrWriter io.Writer) error { mux.HandleFunc("/debug/pprof/trace", pprof.Trace) handleTasks := http.StripPrefix("/tasks", http.HandlerFunc(l.handleTask)) - mux.Handle("/tasks", handleTasks) - mux.Handle("/tasks/", handleTasks) - mux.HandleFunc("/progress/task", handleProgressTask) - mux.HandleFunc("/progress/table", handleProgressTable) - mux.HandleFunc("/pause", handlePause) - mux.HandleFunc("/resume", handleResume) - mux.HandleFunc("/loglevel", handleLogLevel) + mux.Handle("/tasks", httpHandleWrapper(handleTasks.ServeHTTP)) + mux.Handle("/tasks/", httpHandleWrapper(handleTasks.ServeHTTP)) + mux.HandleFunc("/progress/task", httpHandleWrapper(handleProgressTask)) + mux.HandleFunc("/progress/table", httpHandleWrapper(handleProgressTable)) + mux.HandleFunc("/pause", httpHandleWrapper(handlePause)) + mux.HandleFunc("/resume", httpHandleWrapper(handleResume)) + mux.HandleFunc("/loglevel", httpHandleWrapper(handleLogLevel)) mux.Handle("/web/", http.StripPrefix("/web", httpgzip.FileServer(web.Res, httpgzip.FileServerOptions{ IndexHTML: true, @@ -215,7 +260,8 @@ func (l *Lightning) RunServer() error { if err != nil { return err } - err = l.run(context.Background(), task, nil) + o := &options{} + err = l.run(context.Background(), task, o) if err != nil && !common.IsContextCanceledError(err) { restore.DeliverPauser.Pause() // force pause the progress on error log.L().Error("tidb lightning encountered error", zap.Error(err)) @@ -317,6 +363,16 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, o *opti failpoint.Return(nil) }) + failpoint.Inject("SetCertExpiredSoon", func(val failpoint.Value) { + rootKeyPath := val.(string) + rootCaPath := taskCfg.Security.CAPath + keyPath := taskCfg.Security.KeyPath + certPath := taskCfg.Security.CertPath + if err := updateCertExpiry(rootKeyPath, rootCaPath, keyPath, certPath, time.Second*10); err != nil { + panic(err) + } + }) + if err := taskCfg.TiDB.Security.RegisterMySQL(); err != nil { return common.ErrInvalidTLSConfig.Wrap(err) } @@ -559,7 +615,7 @@ func (l *Lightning) handlePostTask(w http.ResponseWriter, req *http.Request) { writeJSONError(w, http.StatusBadRequest, "cannot read request", err) return } - log.L().Debug("received task config", zap.ByteString("content", data)) + log.L().Info("received task config", zap.ByteString("content", data)) cfg := config.NewConfig() if err = cfg.LoadFromGlobal(l.globalCfg); err != nil { @@ -851,40 +907,6 @@ func CleanupMetas(ctx context.Context, cfg *config.Config, tableName string) err return errors.Trace(restore.MaybeCleanupAllMetas(ctx, db, cfg.App.MetaSchemaName, tableMetaExist)) } -func UnsafeCloseEngine(ctx context.Context, importer backend.Backend, engine string) (*backend.ClosedEngine, error) { - if index := strings.LastIndexByte(engine, ':'); index >= 0 { - tableName := engine[:index] - engineID, err := strconv.Atoi(engine[index+1:]) - if err != nil { - return nil, errors.Trace(err) - } - ce, err := importer.UnsafeCloseEngine(ctx, nil, tableName, int32(engineID)) // #nosec G109 - return ce, errors.Trace(err) - } - - engineUUID, err := uuid.Parse(engine) - if err != nil { - return nil, errors.Trace(err) - } - - ce, err := importer.UnsafeCloseEngineWithUUID(ctx, nil, "", engineUUID) - return ce, errors.Trace(err) -} - -func CleanupEngine(ctx context.Context, cfg *config.Config, tls *common.TLS, engine string) error { - importer, err := importer.NewImporter(ctx, tls, cfg.TikvImporter.Addr, cfg.TiDB.PdAddr) - if err != nil { - return errors.Trace(err) - } - - ce, err := UnsafeCloseEngine(ctx, importer, engine) - if err != nil { - return errors.Trace(err) - } - - return errors.Trace(ce.Cleanup(ctx)) -} - func SwitchMode(ctx context.Context, cfg *config.Config, tls *common.TLS, mode string) error { var m import_sstpb.SwitchMode switch mode { @@ -905,3 +927,57 @@ func SwitchMode(ctx context.Context, cfg *config.Config, tls *common.TLS, mode s }, ) } + +func updateCertExpiry(rootKeyPath, rootCaPath, keyPath, certPath string, expiry time.Duration) error { + rootKey, err := parsePrivateKey(rootKeyPath) + if err != nil { + return err + } + rootCaPem, err := os.ReadFile(rootCaPath) + if err != nil { + return err + } + rootCaDer, _ := pem.Decode(rootCaPem) + rootCa, err := x509.ParseCertificate(rootCaDer.Bytes) + if err != nil { + return err + } + key, err := parsePrivateKey(keyPath) + if err != nil { + return err + } + certPem, err := os.ReadFile(certPath) + if err != nil { + panic(err) + } + certDer, _ := pem.Decode(certPem) + cert, err := x509.ParseCertificate(certDer.Bytes) + if err != nil { + return err + } + cert.NotBefore = time.Now() + cert.NotAfter = time.Now().Add(expiry) + derBytes, err := x509.CreateCertificate(rand.Reader, cert, rootCa, &key.PublicKey, rootKey) + if err != nil { + return err + } + return os.WriteFile(certPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), 0o600) +} + +func parsePrivateKey(keyPath string) (*ecdsa.PrivateKey, error) { + keyPemBlock, err := os.ReadFile(keyPath) + if err != nil { + return nil, err + } + var keyDERBlock *pem.Block + for { + keyDERBlock, keyPemBlock = pem.Decode(keyPemBlock) + if keyDERBlock == nil { + return nil, errors.New("failed to find PEM block with type ending in \"PRIVATE KEY\"") + } + if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { + break + } + } + return x509.ParseECPrivateKey(keyDERBlock.Bytes) +} diff --git a/br/pkg/lightning/manual/manual_nocgo.go b/br/pkg/lightning/manual/manual_nocgo.go index 74befbd116e6a..bfd30cd3fb6f6 100644 --- a/br/pkg/lightning/manual/manual_nocgo.go +++ b/br/pkg/lightning/manual/manual_nocgo.go @@ -3,7 +3,6 @@ // the LICENSE file. //go:build !cgo -// +build !cgo package manual diff --git a/br/pkg/lightning/metric/metric.go b/br/pkg/lightning/metric/metric.go index 984b14c8460f6..6121ea69358b2 100644 --- a/br/pkg/lightning/metric/metric.go +++ b/br/pkg/lightning/metric/metric.go @@ -24,10 +24,18 @@ import ( const ( // states used for the TableCounter labels TableStatePending = "pending" - TableStateWritten = "written" TableStateImported = "imported" TableStateCompleted = "completed" + BytesStateTotalRestore = "total_restore" // total source data bytes needs to restore + BytesStateRestored = "restored" // source data bytes restored during restore engine + BytesStateRestoreWritten = "written" // bytes written during restore engine + BytesStateImported = "imported" // bytes imported during import engine + + ProgressPhaseTotal = "total" // total restore progress(not include post-process, like checksum and analyze) + ProgressPhaseRestore = "restore" // restore engine progress + ProgressPhaseImport = "import" // import engine progress + // results used for the TableCounter labels TableResultSuccess = "success" TableResultFailure = "failure" @@ -193,6 +201,14 @@ var ( Help: "disk/memory size currently occupied by intermediate files in local backend", }, []string{"medium"}, ) + + ProgressGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "lightning", + Name: "progress", + Help: "progress of lightning phase", + }, []string{"phase"}, + ) ) //nolint:gochecknoinits // TODO: refactor @@ -216,6 +232,7 @@ func init() { prometheus.MustRegister(ChunkParserReadBlockSecondsHistogram) prometheus.MustRegister(ApplyWorkerSecondsHistogram) prometheus.MustRegister(LocalStorageUsageBytesGauge) + prometheus.MustRegister(ProgressGauge) } func RecordTableCount(status string, err error) { diff --git a/br/pkg/lightning/mydump/csv_parser.go b/br/pkg/lightning/mydump/csv_parser.go index 9f6ae18a07c59..bc10acd999343 100644 --- a/br/pkg/lightning/mydump/csv_parser.go +++ b/br/pkg/lightning/mydump/csv_parser.go @@ -22,8 +22,8 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/worker" - "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/mathutil" ) var ( @@ -213,7 +213,7 @@ func (parser *CSVParser) peekBytes(cnt int) ([]byte, error) { if len(parser.buf) == 0 { return nil, io.EOF } - cnt = utils.MinInt(cnt, len(parser.buf)) + cnt = mathutil.Min(cnt, len(parser.buf)) return parser.buf[:cnt], nil } diff --git a/br/pkg/lightning/mydump/region.go b/br/pkg/lightning/mydump/region.go index 73456d461bb0b..640bb7b4e8791 100644 --- a/br/pkg/lightning/mydump/region.go +++ b/br/pkg/lightning/mydump/region.go @@ -26,7 +26,7 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/br/pkg/storage" - "github.com/pingcap/tidb/br/pkg/utils" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/zap" ) @@ -154,7 +154,7 @@ func MakeTableRegions( execCtx, cancel := context.WithCancel(ctx) defer cancel() - concurrency := utils.MaxInt(cfg.App.RegionConcurrency, 2) + concurrency := mathutil.Max(cfg.App.RegionConcurrency, 2) fileChan := make(chan FileInfo, concurrency) resultChan := make(chan fileRegionRes, concurrency) var wg sync.WaitGroup diff --git a/br/pkg/lightning/mydump/router.go b/br/pkg/lightning/mydump/router.go index 519644a8b9421..223d82edb90e9 100644 --- a/br/pkg/lightning/mydump/router.go +++ b/br/pkg/lightning/mydump/router.go @@ -121,7 +121,7 @@ var defaultFileRouteRules = []*config.FileRouteRule{ // // RouteRule is a rule to route file path to target schema/table type FileRouter interface { - // Route apply rule to path. Return nil if path doesn't math route rule; + // Route apply rule to path. Return nil if path doesn't match route rule; // return error if path match route rule but the captured value for field is invalid Route(path string) (*RouteResult, error) } diff --git a/br/pkg/lightning/mydump/router_test.go b/br/pkg/lightning/mydump/router_test.go index fd239688e72db..4df92b74f45c5 100644 --- a/br/pkg/lightning/mydump/router_test.go +++ b/br/pkg/lightning/mydump/router_test.go @@ -160,7 +160,7 @@ func TestMultiRouteRule(t *testing.T) { } // multi rule don't intersect with each other - // add another rule that math same pattern with the third rule, the result should be no different + // add another rule that match same pattern with the third rule, the result should be no different p := &config.FileRouteRule{Pattern: `^(?P[^/.]+)\.(?P[^./]+)(?:\.(?P[0-9]+))?\.(?Pcsv|sql)(?:\.(?P[A-Za-z0-9]+))?$`, Schema: "test_schema", Table: "test_table", Type: "$type", Key: "$key", Compression: "$cp"} rules = append(rules, p) r, err = NewFileRouter(rules) diff --git a/br/pkg/lightning/restore/check_info.go b/br/pkg/lightning/restore/check_info.go index 98c2c3b720fc0..6d2504919ab99 100644 --- a/br/pkg/lightning/restore/check_info.go +++ b/br/pkg/lightning/restore/check_info.go @@ -48,9 +48,9 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/zap" "golang.org/x/sync/errgroup" - "modernc.org/mathutil" ) const ( @@ -590,8 +590,8 @@ func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.M // hasDefault represents col has default value. func hasDefault(col *model.ColumnInfo) bool { - return col.DefaultIsExpr || col.DefaultValue != nil || !mysql.HasNotNullFlag(col.Flag) || - col.IsGenerated() || mysql.HasAutoIncrementFlag(col.Flag) + return col.DefaultIsExpr || col.DefaultValue != nil || !mysql.HasNotNullFlag(col.GetFlag()) || + col.IsGenerated() || mysql.HasAutoIncrementFlag(col.GetFlag()) } func (rc *Controller) readFirstRow(ctx context.Context, dataFileMeta mydump.SourceFileMeta) (cols []string, row []types.Datum, err error) { @@ -663,7 +663,7 @@ func (rc *Controller) SchemaIsValid(ctx context.Context, tableInfo *mydump.MDTab core := info.Core defaultCols := make(map[string]struct{}) for _, col := range core.Columns { - if hasDefault(col) || (info.Core.ContainsAutoRandomBits() && mysql.HasPriKeyFlag(col.Flag)) { + if hasDefault(col) || (info.Core.ContainsAutoRandomBits() && mysql.HasPriKeyFlag(col.GetFlag())) { // this column has default value or it's auto random id, so we can ignore it defaultCols[col.Name.L] = struct{}{} } @@ -1092,7 +1092,7 @@ func (rc *Controller) checkTableEmpty(ctx context.Context) error { var lock sync.Mutex tableNames := make([]string, 0) - concurrency := utils.MinInt(tableCount, rc.cfg.App.RegionConcurrency) + concurrency := mathutil.Min(tableCount, rc.cfg.App.RegionConcurrency) ch := make(chan string, concurrency) eg, gCtx := errgroup.WithContext(ctx) diff --git a/br/pkg/lightning/restore/check_info_test.go b/br/pkg/lightning/restore/check_info_test.go index cfd9a00adc53a..42772b64ea6ab 100644 --- a/br/pkg/lightning/restore/check_info_test.go +++ b/br/pkg/lightning/restore/check_info_test.go @@ -23,9 +23,8 @@ import ( "testing" "github.com/DATA-DOG/go-sqlmock" + gmysql "github.com/go-sql-driver/mysql" "github.com/pingcap/failpoint" - "github.com/stretchr/testify/require" - "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/glue" @@ -39,6 +38,7 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" tmock "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) const passed CheckType = "pass" @@ -478,7 +478,7 @@ func TestCheckTableEmpty(t *testing.T) { mock.MatchExpectationsInOrder(false) // test auto retry retryable error mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). - WillReturnError(mysql.NewErr(errno.ErrPDServerTimeout)) + WillReturnError(&gmysql.MySQLError{Number: errno.ErrPDServerTimeout}) mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) mock.ExpectQuery("select 1 from `test1`.`tbl2` limit 1"). diff --git a/br/pkg/lightning/restore/checksum.go b/br/pkg/lightning/restore/checksum.go index 2bac40505cdc0..e3719f2f7e413 100644 --- a/br/pkg/lightning/restore/checksum.go +++ b/br/pkg/lightning/restore/checksum.go @@ -32,10 +32,10 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/metric" "github.com/pingcap/tidb/br/pkg/pdutil" - "github.com/pingcap/tidb/br/pkg/utils" tidbcfg "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/store/driver" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" @@ -310,11 +310,11 @@ func (e *tikvChecksumManager) checksumDB(ctx context.Context, tableInfo *checkpo zap.Int("concurrency", distSQLScanConcurrency), zap.Int("retry", i)) // do not retry context.Canceled error - if !utils.IsRetryableError(err) { + if !common.IsRetryableError(err) { break } if distSQLScanConcurrency > minDistSQLScanConcurrency { - distSQLScanConcurrency = utils.MaxInt(distSQLScanConcurrency/2, minDistSQLScanConcurrency) + distSQLScanConcurrency = mathutil.Max(distSQLScanConcurrency/2, minDistSQLScanConcurrency) } } diff --git a/br/pkg/lightning/restore/checksum_test.go b/br/pkg/lightning/restore/checksum_test.go index 3954c12672c4f..d9961a34b43a5 100644 --- a/br/pkg/lightning/restore/checksum_test.go +++ b/br/pkg/lightning/restore/checksum_test.go @@ -11,9 +11,11 @@ import ( "time" "github.com/DATA-DOG/go-sqlmock" + "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" . "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/ddl" + tmysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" @@ -181,7 +183,7 @@ func TestDoChecksumWithTikv(t *testing.T) { _, err = DoChecksum(subCtx, &TidbTableInfo{DB: "test", Name: "t", Core: tableInfo}) // with max error retry < maxErrorRetryCount, the checksum can success if i >= maxErrorRetryCount { - require.Equal(t, "tikv timeout", err.Error()) + require.Equal(t, mockChecksumKVClientErr, errors.Cause(err)) continue } else { require.NoError(t, err) @@ -362,11 +364,11 @@ func (r *mockResponse) Close() error { } type mockErrorResponse struct { - err string + err error } func (r *mockErrorResponse) Next(ctx context.Context) (resultSubset kv.ResultSubset, err error) { - return nil, errors.New(r.err) + return nil, r.err } func (r *mockErrorResponse) Close() error { @@ -393,6 +395,8 @@ func (r *mockResultSubset) RespTime() time.Duration { return time.Millisecond } +var mockChecksumKVClientErr = &mysql.MySQLError{Number: tmysql.ErrPDServerTimeout} + type mockChecksumKVClient struct { kv.Client checksum tipb.ChecksumResponse @@ -410,7 +414,7 @@ func (c *mockChecksumKVClient) Send(ctx context.Context, req *kv.Request, vars i } if c.curErrCount < c.maxErrCount { c.curErrCount++ - return &mockErrorResponse{err: "tikv timeout"} + return &mockErrorResponse{err: mockChecksumKVClientErr} } data, _ := c.checksum.Marshal() time.Sleep(c.respDur) diff --git a/br/pkg/lightning/restore/chunk_restore_test.go b/br/pkg/lightning/restore/chunk_restore_test.go index bc683e8a1c36e..005c3b4ddbafd 100644 --- a/br/pkg/lightning/restore/chunk_restore_test.go +++ b/br/pkg/lightning/restore/chunk_restore_test.go @@ -18,24 +18,25 @@ import ( "context" "os" "path/filepath" + "sync" "testing" "github.com/golang/mock/gomock" "github.com/pingcap/errors" "github.com/pingcap/failpoint" - "github.com/pingcap/kvproto/pkg/import_kvpb" "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/errormanager" + "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/br/pkg/mock" "github.com/pingcap/tidb/br/pkg/storage" + "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) @@ -81,8 +82,12 @@ func (s *chunkRestoreSuite) TearDownTest() { } func (s *chunkRestoreSuite) TestDeliverLoopCancel() { - rc := &Controller{backend: importer.NewMockImporter(nil, "")} + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).AnyTimes() + rc := &Controller{backend: backend.MakeBackend(mockBackend)} ctx, cancel := context.WithCancel(context.Background()) kvsCh := make(chan []deliveredKVs) go cancel() @@ -107,6 +112,7 @@ func (s *chunkRestoreSuite) TestDeliverLoopEmptyData() { mockWriter.EXPECT(). AppendRows(ctx, gomock.Any(), gomock.Any(), gomock.Any()). Return(nil).AnyTimes() + mockWriter.EXPECT().IsSynced().Return(true).AnyTimes() dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) require.NoError(s.T(), err) @@ -120,12 +126,26 @@ func (s *chunkRestoreSuite) TestDeliverLoopEmptyData() { // Deliver nothing. cfg := &config.Config{} - rc := &Controller{cfg: cfg, backend: importer, diskQuotaLock: newDiskQuotaLock()} + saveCpCh := make(chan saveCp, 16) + rc := &Controller{cfg: cfg, backend: importer, saveCpCh: saveCpCh} + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + for scp := range saveCpCh { + if scp.waitCh != nil { + scp.waitCh <- nil + } + } + }() kvsCh := make(chan []deliveredKVs, 1) kvsCh <- []deliveredKVs{} _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) require.NoError(s.T(), err) + close(saveCpCh) + wg.Wait() } func (s *chunkRestoreSuite) TestDeliverLoop() { @@ -211,17 +231,17 @@ func (s *chunkRestoreSuite) TestDeliverLoop() { rowID: 76, }, } - kvsCh <- []deliveredKVs{} + kvsCh <- []deliveredKVs{{offset: 37}} close(kvsCh) }() cfg := &config.Config{} - rc := &Controller{cfg: cfg, saveCpCh: saveCpCh, backend: importer, diskQuotaLock: newDiskQuotaLock()} + rc := &Controller{cfg: cfg, saveCpCh: saveCpCh, backend: importer} _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) require.NoError(s.T(), err) require.Len(s.T(), saveCpCh, 2) - require.Equal(s.T(), int64(12), s.cr.chunk.Chunk.Offset) + require.Equal(s.T(), s.cr.chunk.Chunk.EndOffset, s.cr.chunk.Chunk.Offset) require.Equal(s.T(), int64(76), s.cr.chunk.Chunk.PrevRowIDMax) require.Equal(s.T(), uint64(3), s.cr.chunk.Checksum.SumKVS()) } @@ -248,7 +268,9 @@ func (s *chunkRestoreSuite) TestEncodeLoop() { require.Equal(s.T(), []string(nil), kvs[0].columns) kvs = <-kvsCh - require.Equal(s.T(), 0, len(kvs)) + require.Equal(s.T(), 1, len(kvs)) + require.Nil(s.T(), kvs[0].kvs) + require.Equal(s.T(), s.cr.chunk.Chunk.EndOffset, kvs[0].offset) } func (s *chunkRestoreSuite) TestEncodeLoopCanceled() { @@ -338,7 +360,9 @@ func (s *chunkRestoreSuite) TestEncodeLoopDeliverLimit() { if count == 4 { // we will send empty kvs before encodeLoop exists // so, we can receive 4 batch and 1 is empty - require.Len(s.T(), kvs, 0) + require.Len(s.T(), kvs, 1) + require.Nil(s.T(), kvs[0].kvs) + require.Equal(s.T(), s.cr.chunk.Chunk.EndOffset, kvs[0].offset) break } } @@ -507,61 +531,53 @@ func (s *chunkRestoreSuite) testEncodeLoopIgnoreColumnsCSV( require.Equal(s.T(), deliverKV.columns, kvs[0].columns) kvs = <-kvsCh - require.Equal(s.T(), 0, len(kvs)) + require.Equal(s.T(), 1, len(kvs)) + require.Nil(s.T(), kvs[0].kvs) + require.Equal(s.T(), s.cr.chunk.Chunk.EndOffset, kvs[0].offset) +} + +type mockEncoder struct{} + +func (mockEncoder) Encode(_ log.Logger, _ []types.Datum, rowID int64, _ []int, _ string, _ int64) (kv.Row, error) { + return &kv.KvPairs{}, nil } +func (mockEncoder) Close() {} + func (s *chunkRestoreSuite) TestRestore() { ctx := context.Background() - // Open two mock engines - controller := gomock.NewController(s.T()) defer controller.Finish() - mockClient := mock.NewMockImportKVClient(controller) - mockDataWriter := mock.NewMockImportKV_WriteEngineClient(controller) - mockIndexWriter := mock.NewMockImportKV_WriteEngineClient(controller) - importer := importer.NewMockImporter(mockClient, "127.0.0.1:2379") + mockBackend := mock.NewMockBackend(controller) + importer := backend.MakeBackend(mockBackend) - mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) - mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) + mockBackend.EXPECT().OpenEngine(ctx, gomock.Any(), gomock.Any()).Return(nil).Times(2) + // avoid return the same object at each call + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) + mockWriter := mock.NewMockEngineWriter(controller) + mockBackend.EXPECT().LocalWriter(ctx, gomock.Any(), gomock.Any()).Return(mockWriter, nil).AnyTimes() + mockBackend.EXPECT().NewEncoder(gomock.Any(), gomock.Any()).Return(mockEncoder{}, nil).Times(1) + mockWriter.EXPECT().IsSynced().Return(true).AnyTimes() + mockWriter.EXPECT().AppendRows(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) require.NoError(s.T(), err) indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) require.NoError(s.T(), err) + dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) require.NoError(s.T(), err) indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) require.NoError(s.T(), err) - // Expected API sequence - // (we don't care about the actual content, this would be checked in the integrated tests) - - mockClient.EXPECT().WriteEngine(ctx).Return(mockDataWriter, nil) - mockDataWriter.EXPECT().Send(gomock.Any()).Return(nil) - mockDataWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { - require.Len(s.T(), req.GetBatch().GetMutations(), 1) - return nil - }) - mockDataWriter.EXPECT().CloseAndRecv().Return(nil, nil) - - mockClient.EXPECT().WriteEngine(ctx).Return(mockIndexWriter, nil) - mockIndexWriter.EXPECT().Send(gomock.Any()).Return(nil) - mockIndexWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { - require.Len(s.T(), req.GetBatch().GetMutations(), 1) - return nil - }) - mockIndexWriter.EXPECT().CloseAndRecv().Return(nil, nil) - - // Now actually start the restore loop. - - saveCpCh := make(chan saveCp, 2) + saveCpCh := make(chan saveCp, 16) err = s.cr.restore(ctx, s.tr, 0, dataWriter, indexWriter, &Controller{ - cfg: s.cfg, - saveCpCh: saveCpCh, - backend: importer, - pauser: DeliverPauser, - diskQuotaLock: newDiskQuotaLock(), + cfg: s.cfg, + saveCpCh: saveCpCh, + backend: importer, + pauser: DeliverPauser, }) require.NoError(s.T(), err) require.Len(s.T(), saveCpCh, 2) diff --git a/br/pkg/lightning/restore/meta_manager.go b/br/pkg/lightning/restore/meta_manager.go index 6c009279e9e0f..8eace8c5f979d 100644 --- a/br/pkg/lightning/restore/meta_manager.go +++ b/br/pkg/lightning/restore/meta_manager.go @@ -248,10 +248,10 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 // the `show table next_row_id` will returns the unique key field only. var autoIDField string for _, col := range m.tr.tableInfo.Core.Columns { - if mysql.HasAutoIncrementFlag(col.Flag) { + if mysql.HasAutoIncrementFlag(col.GetFlag()) { autoIDField = col.Name.L break - } else if mysql.HasPriKeyFlag(col.Flag) && m.tr.tableInfo.Core.AutoRandomBits > 0 { + } else if mysql.HasPriKeyFlag(col.GetFlag()) && m.tr.tableInfo.Core.AutoRandomBits > 0 { autoIDField = col.Name.L break } @@ -1051,7 +1051,9 @@ func (m noopTableMetaMgr) FinishTable(ctx context.Context) error { return nil } -type singleMgrBuilder struct{} +type singleMgrBuilder struct { + taskID int64 +} func (b singleMgrBuilder) Init(context.Context) error { return nil @@ -1059,7 +1061,8 @@ func (b singleMgrBuilder) Init(context.Context) error { func (b singleMgrBuilder) TaskMetaMgr(pd *pdutil.PdController) taskMetaMgr { return &singleTaskMetaMgr{ - pd: pd, + pd: pd, + taskID: b.taskID, } } @@ -1068,15 +1071,34 @@ func (b singleMgrBuilder) TableMetaMgr(tr *TableRestore) tableMetaMgr { } type singleTaskMetaMgr struct { - pd *pdutil.PdController + pd *pdutil.PdController + taskID int64 + initialized bool + sourceBytes uint64 + clusterAvail uint64 } func (m *singleTaskMetaMgr) InitTask(ctx context.Context, source int64) error { + m.sourceBytes = uint64(source) + m.initialized = true return nil } func (m *singleTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(tasks []taskMeta) ([]taskMeta, error)) error { - _, err := action(nil) + newTasks, err := action([]taskMeta{ + { + taskID: m.taskID, + status: taskMetaStatusInitial, + sourceBytes: m.sourceBytes, + clusterAvail: m.clusterAvail, + }, + }) + for _, t := range newTasks { + if m.taskID == t.taskID { + m.sourceBytes = t.sourceBytes + m.clusterAvail = t.clusterAvail + } + } return err } @@ -1085,7 +1107,7 @@ func (m *singleTaskMetaMgr) CheckAndPausePdSchedulers(ctx context.Context) (pdut } func (m *singleTaskMetaMgr) CheckTaskExist(ctx context.Context) (bool, error) { - return true, nil + return m.initialized, nil } func (m *singleTaskMetaMgr) CheckAndFinishRestore(context.Context, bool) (shouldSwitchBack bool, shouldCleanupMeta bool, err error) { diff --git a/br/pkg/lightning/restore/meta_manager_test.go b/br/pkg/lightning/restore/meta_manager_test.go index 571a9d6cd5844..8480bf077d6de 100644 --- a/br/pkg/lightning/restore/meta_manager_test.go +++ b/br/pkg/lightning/restore/meta_manager_test.go @@ -7,6 +7,7 @@ import ( "database/sql/driver" "sort" "testing" + "time" "github.com/DATA-DOG/go-sqlmock" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" @@ -358,3 +359,28 @@ func (t *testChecksumMgr) Checksum(ctx context.Context, tableInfo *checkpoints.T t.callCnt++ return &t.checksum, nil } + +func TestSingleTaskMetaMgr(t *testing.T) { + metaBuilder := singleMgrBuilder{ + taskID: time.Now().UnixNano(), + } + metaMgr := metaBuilder.TaskMetaMgr(nil) + + ok, err := metaMgr.CheckTaskExist(context.Background()) + require.NoError(t, err) + require.False(t, ok) + + err = metaMgr.InitTask(context.Background(), 1<<30) + require.NoError(t, err) + + ok, err = metaMgr.CheckTaskExist(context.Background()) + require.NoError(t, err) + require.True(t, ok) + + err = metaMgr.CheckTasksExclusively(context.Background(), func(tasks []taskMeta) ([]taskMeta, error) { + require.Len(t, tasks, 1) + require.Equal(t, uint64(1<<30), tasks[0].sourceBytes) + return nil, nil + }) + require.NoError(t, err) +} diff --git a/br/pkg/lightning/restore/restore.go b/br/pkg/lightning/restore/restore.go index d181b0882f209..073a7cdf3639c 100644 --- a/br/pkg/lightning/restore/restore.go +++ b/br/pkg/lightning/restore/restore.go @@ -33,7 +33,6 @@ import ( sstpb "github.com/pingcap/kvproto/pkg/import_sstpb" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/backend/local" "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" @@ -57,11 +56,11 @@ import ( "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/mathutil" pd "github.com/tikv/pd/client" "go.uber.org/atomic" "go.uber.org/multierr" "go.uber.org/zap" - "modernc.org/mathutil" ) const ( @@ -184,58 +183,8 @@ const ( diskQuotaStateIdle int32 = iota diskQuotaStateChecking diskQuotaStateImporting - - diskQuotaMaxReaders = 1 << 30 ) -// diskQuotaLock is essentially a read/write lock. The implement here is inspired by sync.RWMutex. -// diskQuotaLock removed the unnecessary blocking `RLock` method and add a non-blocking `TryRLock` method. -type diskQuotaLock struct { - w sync.Mutex // held if there are pending writers - writerSem chan struct{} // semaphore for writers to wait for completing readers - readerCount atomic.Int32 // number of pending readers - readerWait atomic.Int32 // number of departing readers -} - -func newDiskQuotaLock() *diskQuotaLock { - return &diskQuotaLock{writerSem: make(chan struct{})} -} - -func (d *diskQuotaLock) Lock() { - d.w.Lock() - // Announce to readers there is a pending writer. - r := d.readerCount.Sub(diskQuotaMaxReaders) + diskQuotaMaxReaders - if r != 0 && d.readerWait.Add(r) != 0 { - // Wait for active readers. - <-d.writerSem - } -} - -func (d *diskQuotaLock) Unlock() { - d.readerCount.Add(diskQuotaMaxReaders) - d.w.Unlock() -} - -func (d *diskQuotaLock) TryRLock() (locked bool) { - r := d.readerCount.Load() - for r >= 0 { - if d.readerCount.CAS(r, r+1) { - return true - } - r = d.readerCount.Load() - } - return false -} - -func (d *diskQuotaLock) RUnlock() { - if d.readerCount.Dec() < 0 { - if d.readerWait.Dec() == 0 { - // The last reader unblocks the writer. - d.writerSem <- struct{}{} - } - } -} - type Controller struct { cfg *config.Config dbMetas []*mydump.MDDatabaseMeta @@ -267,7 +216,7 @@ type Controller struct { errorMgr *errormanager.ErrorManager taskMgr taskMetaMgr - diskQuotaLock *diskQuotaLock + diskQuotaLock sync.RWMutex diskQuotaState atomic.Int32 compactState atomic.Int32 status *LightningStatus @@ -358,12 +307,6 @@ func NewRestoreControllerWithPauser( var backend backend.Backend switch cfg.TikvImporter.Backend { - case config.BackendImporter: - var err error - backend, err = importer.NewImporter(ctx, tls, cfg.TikvImporter.Addr, cfg.TiDB.PdAddr) - if err != nil { - return nil, errors.Annotate(err, "open importer backend failed") - } case config.BackendTiDB: backend = tidb.NewTiDBBackend(db, cfg.TikvImporter.OnDuplicate, errorMgr) case config.BackendLocal: @@ -402,7 +345,7 @@ func NewRestoreControllerWithPauser( } var metaBuilder metaMgrBuilder - isSSTImport := cfg.TikvImporter.Backend == config.BackendLocal || cfg.TikvImporter.Backend == config.BackendImporter + isSSTImport := cfg.TikvImporter.Backend == config.BackendLocal switch { case isSSTImport && cfg.TikvImporter.IncrementalImport: metaBuilder = &dbMetaMgrBuilder{ @@ -412,7 +355,9 @@ func NewRestoreControllerWithPauser( needChecksum: cfg.PostRestore.Checksum != config.OpLevelOff, } case isSSTImport: - metaBuilder = singleMgrBuilder{} + metaBuilder = singleMgrBuilder{ + taskID: cfg.TaskID, + } default: metaBuilder = noopMetaMgrBuilder{} } @@ -441,7 +386,6 @@ func NewRestoreControllerWithPauser( ownStore: p.OwnExtStorage, metaMgrBuilder: metaBuilder, errorMgr: errorMgr, - diskQuotaLock: newDiskQuotaLock(), status: p.Status, taskMgr: nil, } @@ -750,7 +694,7 @@ func (rc *Controller) restoreSchema(ctx context.Context) error { // we can handle the duplicated created with createIfNotExist statement // and we will check the schema in TiDB is valid with the datafile in DataCheck later. logTask := log.L().Begin(zap.InfoLevel, "restore all schema") - concurrency := utils.MinInt(rc.cfg.App.RegionConcurrency, 8) + concurrency := mathutil.Min(rc.cfg.App.RegionConcurrency, 8) childCtx, cancel := context.WithCancel(ctx) worker := restoreSchemaWorker{ ctx: childCtx, @@ -844,10 +788,6 @@ func verifyCheckpoint(cfg *config.Config, taskCp *checkpoints.TaskCheckpoint) er return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "mydumper.sorted-kv-dir", cfg.TikvImporter.SortedKVDir, taskCp.SortedKVDir) } - if cfg.TikvImporter.Backend == config.BackendImporter && cfg.TikvImporter.Addr != taskCp.ImporterAddr { - return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tikv-importer.addr", cfg.TikvImporter.Backend, taskCp.Backend) - } - if cfg.TiDB.Host != taskCp.TiDBHost { return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tidb.host", cfg.TiDB.Host, taskCp.TiDBHost) } @@ -1004,8 +944,6 @@ func (rc *Controller) saveStatusCheckpoint(ctx context.Context, tableName string // listenCheckpointUpdates will combine several checkpoints together to reduce database load. func (rc *Controller) listenCheckpointUpdates() { - defer rc.checkpointsWg.Done() - var lock sync.Mutex coalesed := make(map[string]*checkpoints.TableCheckpointDiff) var waiters []chan<- error @@ -1056,8 +994,8 @@ func (rc *Controller) listenCheckpointUpdates() { lock.Unlock() //nolint:scopelint // This would be either INLINED or ERASED, at compile time. - failpoint.Inject("FailIfImportedChunk", func(val failpoint.Value) { - if merger, ok := scp.merger.(*checkpoints.ChunkCheckpointMerger); ok && merger.Checksum.SumKVS() >= uint64(val.(int)) { + failpoint.Inject("FailIfImportedChunk", func() { + if merger, ok := scp.merger.(*checkpoints.ChunkCheckpointMerger); ok && merger.Pos >= merger.EndOffset { rc.checkpointsWg.Done() rc.checkpointsWg.Wait() panic("forcing failure due to FailIfImportedChunk") @@ -1085,14 +1023,24 @@ func (rc *Controller) listenCheckpointUpdates() { }) //nolint:scopelint // This would be either INLINED or ERASED, at compile time. - failpoint.Inject("KillIfImportedChunk", func(val failpoint.Value) { - if merger, ok := scp.merger.(*checkpoints.ChunkCheckpointMerger); ok && merger.Checksum.SumKVS() >= uint64(val.(int)) { + failpoint.Inject("KillIfImportedChunk", func() { + if merger, ok := scp.merger.(*checkpoints.ChunkCheckpointMerger); ok && merger.Pos >= merger.EndOffset { + rc.checkpointsWg.Done() + rc.checkpointsWg.Wait() if err := common.KillMySelf(); err != nil { log.L().Warn("KillMySelf() failed to kill itself", log.ShortError(err)) } + for scp := range rc.saveCpCh { + if scp.waitCh != nil { + scp.waitCh <- context.Canceled + } + } + failpoint.Return() } }) } + // Don't put this statement in defer function at the beginning. failpoint function may call it manually. + rc.checkpointsWg.Done() } // buildRunPeriodicActionAndCancelFunc build the runPeriodicAction func and a cancel func @@ -1162,6 +1110,8 @@ func (rc *Controller) buildRunPeriodicActionAndCancelFunc(ctx context.Context, s case <-logProgressChan: // log the current progress periodically, so OPS will know that we're still working nanoseconds := float64(time.Since(start).Nanoseconds()) + totalRestoreBytes := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.BytesStateTotalRestore)) + restoredBytes := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.BytesStateRestored)) // the estimated chunk is not accurate(likely under estimated), but the actual count is not accurate // before the last table start, so use the bigger of the two should be a workaround estimated := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStateEstimated)) @@ -1179,8 +1129,8 @@ func (rc *Controller) buildRunPeriodicActionAndCancelFunc(ctx context.Context, s engineEstimated = enginePending } engineFinished := metric.ReadCounter(metric.ProcessedEngineCounter.WithLabelValues(metric.TableStateImported, metric.TableResultSuccess)) - bytesWritten := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.TableStateWritten)) - bytesImported := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.TableStateImported)) + bytesWritten := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.BytesStateRestoreWritten)) + bytesImported := metric.ReadCounter(metric.BytesCounter.WithLabelValues(metric.BytesStateImported)) var state string var remaining zap.Field @@ -1197,37 +1147,64 @@ func (rc *Controller) buildRunPeriodicActionAndCancelFunc(ctx context.Context, s state = "preparing" } - // since we can't accurately estimate the extra time cost by import after all writing are finished, - // so here we use estimatedWritingProgress * 0.8 + estimatedImportingProgress * 0.2 as the total - // progress. + // lightning restore is separated into restore engine and import engine, they are both parallelized + // and pipelined between engines, so we can only weight the progress of those 2 phase to get the + // total progress. + // + // for local & importer backend: + // in most case import engine is faster since there's little computations, but inside one engine + // restore and import is serialized, the progress of those two will not differ too much, and + // import engine determines the end time of the whole restore, so we average them for now. + // the result progress may fall behind the real progress if import is faster. + // + // for tidb backend, we do nothing during import engine, so we use restore engine progress as the + // total progress. + restoreBytesField := zap.Skip() + importBytesField := zap.Skip() remaining = zap.Skip() totalPercent := 0.0 - if finished > 0 { - writePercent := math.Min(finished/estimated, 1.0) - importPercent := 1.0 - if bytesWritten > 0 { - totalBytes := bytesWritten / writePercent - importPercent = math.Min(bytesImported/totalBytes, 1.0) + if restoredBytes > 0 { + restorePercent := math.Min(restoredBytes/totalRestoreBytes, 1.0) + metric.ProgressGauge.WithLabelValues(metric.ProgressPhaseRestore).Set(restorePercent) + if rc.cfg.TikvImporter.Backend != config.BackendTiDB { + var importPercent float64 + if bytesWritten > 0 { + // estimate total import bytes from written bytes + // when importPercent = 1, totalImportBytes = bytesWritten, but there's case + // bytesImported may bigger or smaller than bytesWritten such as when deduplicate + // we calculate progress using engines then use the bigger one in case bytesImported is + // smaller. + totalImportBytes := bytesWritten / restorePercent + biggerPercent := math.Max(bytesImported/totalImportBytes, engineFinished/engineEstimated) + importPercent = math.Min(biggerPercent, 1.0) + importBytesField = zap.String("import-bytes", fmt.Sprintf("%s/%s(estimated)", + units.BytesSize(bytesImported), units.BytesSize(totalImportBytes))) + } + metric.ProgressGauge.WithLabelValues(metric.ProgressPhaseImport).Set(importPercent) + totalPercent = (restorePercent + importPercent) / 2 + } else { + totalPercent = restorePercent } - totalPercent = writePercent*0.8 + importPercent*0.2 if totalPercent < 1.0 { remainNanoseconds := (1.0 - totalPercent) / totalPercent * nanoseconds remaining = zap.Duration("remaining", time.Duration(remainNanoseconds).Round(time.Second)) } + restoreBytesField = zap.String("restore-bytes", fmt.Sprintf("%s/%s", + units.BytesSize(restoredBytes), units.BytesSize(totalRestoreBytes))) } + metric.ProgressGauge.WithLabelValues(metric.ProgressPhaseTotal).Set(totalPercent) - formatPercent := func(finish, estimate float64) string { - speed := "" - if estimated > 0 { - speed = fmt.Sprintf(" (%.1f%%)", finish/estimate*100) + formatPercent := func(num, denom float64) string { + if denom > 0 { + return fmt.Sprintf(" (%.1f%%)", num/denom*100) } - return speed + return "" } // avoid output bytes speed if there are no unfinished chunks - chunkSpeed := zap.Skip() + encodeSpeedField := zap.Skip() if bytesRead > 0 { - chunkSpeed = zap.Float64("speed(MiB/s)", bytesRead/(1048576e-9*nanoseconds)) + encodeSpeedField = zap.Float64("encode speed(MiB/s)", bytesRead/(1048576e-9*nanoseconds)) } // Note: a speed of 28 MiB/s roughly corresponds to 100 GiB/hour. @@ -1237,7 +1214,8 @@ func (rc *Controller) buildRunPeriodicActionAndCancelFunc(ctx context.Context, s zap.String("tables", fmt.Sprintf("%.0f/%.0f%s", completedTables, totalTables, formatPercent(completedTables, totalTables))), zap.String("chunks", fmt.Sprintf("%.0f/%.0f%s", finished, estimated, formatPercent(finished, estimated))), zap.String("engines", fmt.Sprintf("%.f/%.f%s", engineFinished, engineEstimated, formatPercent(engineFinished, engineEstimated))), - chunkSpeed, + restoreBytesField, importBytesField, + encodeSpeedField, zap.String("state", state), remaining, ) @@ -1447,6 +1425,7 @@ func (rc *Controller) restoreTables(ctx context.Context) (finalErr error) { finalErr = err return } + logTask.End(zap.ErrorLevel, nil) // clean up task metas if cleanup { logTask.Info("cleanup task metas") @@ -1473,11 +1452,13 @@ func (rc *Controller) restoreTables(ctx context.Context) (finalErr error) { for task := range taskCh { tableLogTask := task.tr.logger.Begin(zap.InfoLevel, "restore table") web.BroadcastTableCheckpoint(task.tr.tableName, task.cp) + needPostProcess, err := task.tr.restoreTable(ctx2, rc, task.cp) + err = common.NormalizeOrWrapErr(common.ErrRestoreTable, err, task.tr.tableName) tableLogTask.End(zap.ErrorLevel, err) web.BroadcastError(task.tr.tableName, err) - metric.RecordTableCount("completed", err) + metric.RecordTableCount(metric.TableStateCompleted, err) restoreErr.Set(err) if needPostProcess { postProcessTaskChan <- task @@ -1487,6 +1468,8 @@ func (rc *Controller) restoreTables(ctx context.Context) (finalErr error) { }() } + var allTasks []task + var totalDataSizeToRestore int64 for _, dbMeta := range rc.dbMetas { dbInfo := rc.dbInfos[dbMeta.Name] for _, tableMeta := range dbMeta.Tables { @@ -1508,15 +1491,33 @@ func (rc *Controller) restoreTables(ctx context.Context) (finalErr error) { return errors.Trace(err) } - wg.Add(1) - select { - case taskCh <- task{tr: tr, cp: cp}: - case <-ctx.Done(): - return ctx.Err() + allTasks = append(allTasks, task{tr: tr, cp: cp}) + + if len(cp.Engines) == 0 { + for _, fi := range tableMeta.DataFiles { + totalDataSizeToRestore += fi.FileMeta.FileSize + } + } else { + for _, eng := range cp.Engines { + for _, chunk := range eng.Chunks { + totalDataSizeToRestore += chunk.Chunk.EndOffset - chunk.Chunk.Offset + } + } } } } + metric.BytesCounter.WithLabelValues(metric.BytesStateTotalRestore).Add(float64(totalDataSizeToRestore)) + + for i := range allTasks { + wg.Add(1) + select { + case taskCh <- allTasks[i]: + case <-ctx.Done(): + return ctx.Err() + } + } + wg.Wait() // if context is done, should return directly select { @@ -1592,8 +1593,7 @@ func (tr *TableRestore) restoreTable( versionInfo := version.ParseServerInfo(versionStr) // "show table next_row_id" is only available after tidb v4.0.0 - if versionInfo.ServerVersion.Major >= 4 && - (rc.cfg.TikvImporter.Backend == config.BackendLocal || rc.cfg.TikvImporter.Backend == config.BackendImporter) { + if versionInfo.ServerVersion.Major >= 4 && rc.isLocalBackend() { // first, insert a new-line into meta table if err = metaMgr.InitTableMeta(ctx); err != nil { return false, err @@ -1625,12 +1625,12 @@ func (tr *TableRestore) restoreTable( // rebase the allocator so it exceeds the number of rows. if tr.tableInfo.Core.PKIsHandle && tr.tableInfo.Core.ContainsAutoRandomBits() { - cp.AllocBase = mathutil.MaxInt64(cp.AllocBase, tr.tableInfo.Core.AutoRandID) + cp.AllocBase = mathutil.Max(cp.AllocBase, tr.tableInfo.Core.AutoRandID) if err := tr.alloc.Get(autoid.AutoRandomType).Rebase(context.Background(), cp.AllocBase, false); err != nil { return false, err } } else { - cp.AllocBase = mathutil.MaxInt64(cp.AllocBase, tr.tableInfo.Core.AutoIncID) + cp.AllocBase = mathutil.Max(cp.AllocBase, tr.tableInfo.Core.AutoIncID) if err := tr.alloc.Get(autoid.RowIDAllocType).Rebase(context.Background(), cp.AllocBase, false); err != nil { return false, err } @@ -1785,7 +1785,7 @@ func (rc *Controller) enforceDiskQuota(ctx context.Context) { if locker == nil { // blocks all writers when we detected disk quota being exceeded. rc.diskQuotaLock.Lock() - locker = rc.diskQuotaLock + locker = &rc.diskQuotaLock } logger.Warn("disk quota exceeded") @@ -1926,7 +1926,19 @@ func (rc *Controller) preCheckRequirements(ctx context.Context) error { if err = rc.taskMgr.InitTask(ctx, source); err != nil { return common.ErrMetaMgrUnknown.Wrap(err).GenWithStackByArgs() } - if rc.cfg.App.CheckRequirements { + } + if rc.cfg.App.CheckRequirements { + needCheck := true + if rc.cfg.Checkpoint.Enable { + taskCheckpoints, err := rc.checkpointsDB.TaskCheckpoint(ctx) + if err != nil { + return common.ErrReadCheckpoint.Wrap(err).GenWithStack("get task checkpoint failed") + } + // If task checkpoint is initialized, it means check has been performed before. + // We don't need and shouldn't check again, because lightning may have already imported some data. + needCheck = taskCheckpoints == nil + } + if needCheck { err = rc.localResource(source) if err != nil { return common.ErrCheckLocalResource.Wrap(err).GenWithStackByArgs() @@ -2135,8 +2147,6 @@ func (cr *chunkRestore) deliverLoop( dataEngine, indexEngine *backend.LocalEngineWriter, rc *Controller, ) (deliverTotalDur time.Duration, err error) { - var channelClosed bool - deliverLogger := t.logger.With( zap.Int32("engineNumber", engineID), zap.Int("fileIndex", cr.index), @@ -2148,13 +2158,15 @@ func (cr *chunkRestore) deliverLoop( indexKVs := rc.backend.MakeEmptyRows() dataSynced := true - for !channelClosed { + hasMoreKVs := true + for hasMoreKVs { var dataChecksum, indexChecksum verify.KVChecksum var columns []string var kvPacket []deliveredKVs // init these two field as checkpoint current value, so even if there are no kv pairs delivered, // chunk checkpoint should stay the same - offset := cr.chunk.Chunk.Offset + startOffset := cr.chunk.Chunk.Offset + currOffset := startOffset rowID := cr.chunk.Chunk.PrevRowIDMax populate: @@ -2162,13 +2174,19 @@ func (cr *chunkRestore) deliverLoop( select { case kvPacket = <-kvsCh: if len(kvPacket) == 0 { - channelClosed = true + hasMoreKVs = false break populate } for _, p := range kvPacket { + if p.kvs == nil { + // This is the last message. + currOffset = p.offset + hasMoreKVs = false + break populate + } p.kvs.ClassifyAndAppend(&dataKVs, &dataChecksum, &indexKVs, &indexChecksum) columns = p.columns - offset = p.offset + currOffset = p.offset rowID = p.rowID } case <-ctx.Done(): @@ -2228,13 +2246,16 @@ func (cr *chunkRestore) deliverLoop( // Update the table, and save a checkpoint. // (the write to the importer is effective immediately, thus update these here) // No need to apply a lock since this is the only thread updating `cr.chunk.**`. - // In local mode, we should write these checkpoint after engine flushed. + // In local mode, we should write these checkpoints after engine flushed. + lastOffset := cr.chunk.Chunk.Offset cr.chunk.Checksum.Add(&dataChecksum) cr.chunk.Checksum.Add(&indexChecksum) - cr.chunk.Chunk.Offset = offset + cr.chunk.Chunk.Offset = currOffset cr.chunk.Chunk.PrevRowIDMax = rowID - if dataChecksum.SumKVS() != 0 || indexChecksum.SumKVS() != 0 { + metric.BytesCounter.WithLabelValues(metric.BytesStateRestored).Add(float64(currOffset - startOffset)) + + if currOffset > lastOffset || dataChecksum.SumKVS() != 0 || indexChecksum.SumKVS() != 0 { // No need to save checkpoint if nothing was delivered. dataSynced = cr.maybeSaveCheckpoint(rc, t, engineID, cr.chunk, dataEngine, indexEngine) } @@ -2297,6 +2318,7 @@ func saveCheckpoint(rc *Controller, t *TableRestore, engineID int32, chunk *chec Pos: chunk.Chunk.Offset, RowID: chunk.Chunk.PrevRowIDMax, ColumnPermutation: chunk.ColumnPermutation, + EndOffset: chunk.Chunk.EndOffset, }, } } @@ -2311,6 +2333,8 @@ func (cr *chunkRestore) encodeLoop( deliverCompleteCh <-chan deliverResult, rc *Controller, ) (readTotalDur time.Duration, encodeTotalDur time.Duration, err error) { + defer close(kvsCh) + send := func(kvs []deliveredKVs) error { select { case kvsCh <- kvs: @@ -2454,7 +2478,7 @@ func (cr *chunkRestore) encodeLoop( } } - err = send([]deliveredKVs{}) + err = send([]deliveredKVs{{offset: cr.chunk.Chunk.EndOffset}}) return } @@ -2476,16 +2500,11 @@ func (cr *chunkRestore) restore( if err != nil { return err } + defer kvEncoder.Close() kvsCh := make(chan []deliveredKVs, maxKVQueueSize) deliverCompleteCh := make(chan deliverResult) - defer func() { - kvEncoder.Close() - kvEncoder = nil - close(kvsCh) - }() - go func() { defer close(deliverCompleteCh) dur, err := cr.deliverLoop(ctx, kvsCh, t, engineID, dataEngine, indexEngine, rc) @@ -2501,11 +2520,8 @@ func (cr *chunkRestore) restore( zap.Stringer("path", &cr.chunk.Key), ).Begin(zap.InfoLevel, "restore file") - readTotalDur, encodeTotalDur, err := cr.encodeLoop(ctx, kvsCh, t, logTask.Logger, kvEncoder, deliverCompleteCh, rc) - if err != nil { - return err - } - + readTotalDur, encodeTotalDur, encodeErr := cr.encodeLoop(ctx, kvsCh, t, logTask.Logger, kvEncoder, deliverCompleteCh, rc) + var deliverErr error select { case deliverResult, ok := <-deliverCompleteCh: if ok { @@ -2515,11 +2531,13 @@ func (cr *chunkRestore) restore( zap.Duration("deliverDur", deliverResult.totalDur), zap.Object("checksum", &cr.chunk.Checksum), ) - return errors.Trace(deliverResult.err) + deliverErr = deliverResult.err + } else { + // else, this must cause by ctx cancel + deliverErr = ctx.Err() } - // else, this must cause by ctx cancel - return ctx.Err() case <-ctx.Done(): - return ctx.Err() + deliverErr = ctx.Err() } + return errors.Trace(firstErr(encodeErr, deliverErr)) } diff --git a/br/pkg/lightning/restore/restore_test.go b/br/pkg/lightning/restore/restore_test.go index a879ac43934f3..852a3a4831e73 100644 --- a/br/pkg/lightning/restore/restore_test.go +++ b/br/pkg/lightning/restore/restore_test.go @@ -19,9 +19,7 @@ import ( "fmt" "path/filepath" "sort" - "sync/atomic" "testing" - "time" "github.com/DATA-DOG/go-sqlmock" "github.com/pingcap/errors" @@ -129,8 +127,7 @@ func TestVerifyCheckpoint(t *testing.T) { cfg.TaskID = 123 cfg.TiDB.Port = 4000 cfg.TiDB.PdAddr = "127.0.0.1:2379" - cfg.TikvImporter.Backend = config.BackendImporter - cfg.TikvImporter.Addr = "127.0.0.1:8287" + cfg.TikvImporter.Backend = config.BackendTiDB cfg.TikvImporter.SortedKVDir = "/tmp/sorted-kv" return cfg @@ -143,9 +140,6 @@ func TestVerifyCheckpoint(t *testing.T) { "tikv-importer.backend": func(cfg *config.Config) { cfg.TikvImporter.Backend = config.BackendLocal }, - "tikv-importer.addr": func(cfg *config.Config) { - cfg.TikvImporter.Addr = "128.0.0.1:8287" - }, "mydumper.data-source-dir": func(cfg *config.Config) { cfg.Mydumper.SourceDir = "/tmp/test" }, @@ -170,6 +164,7 @@ func TestVerifyCheckpoint(t *testing.T) { cfg := newCfg() fn(cfg) err := verifyCheckpoint(cfg, taskCp) + require.Error(t, err) if conf == "version" { build.ReleaseVersion = actualReleaseVersion require.Regexp(t, "lightning version is 'some newer version', but checkpoint was created at '"+actualReleaseVersion+"'.*", err.Error()) @@ -190,85 +185,6 @@ func TestVerifyCheckpoint(t *testing.T) { } } -func TestDiskQuotaLock(t *testing.T) { - lock := newDiskQuotaLock() - - lock.Lock() - require.False(t, lock.TryRLock()) - lock.Unlock() - require.True(t, lock.TryRLock()) - require.True(t, lock.TryRLock()) - - rLocked := 2 - lockHeld := make(chan struct{}) - go func() { - lock.Lock() - lockHeld <- struct{}{} - }() - for lock.TryRLock() { - rLocked++ - time.Sleep(time.Millisecond) - } - select { - case <-lockHeld: - t.Fatal("write lock is held before all read locks are released") - case <-time.NewTimer(10 * time.Millisecond).C: - } - for ; rLocked > 0; rLocked-- { - lock.RUnlock() - } - <-lockHeld - lock.Unlock() - - done := make(chan struct{}) - count := int32(0) - reader := func() { - for i := 0; i < 1000; i++ { - if lock.TryRLock() { - n := atomic.AddInt32(&count, 1) - if n < 1 || n >= 10000 { - lock.RUnlock() - panic(fmt.Sprintf("unexpected count(%d)", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(&count, -1) - lock.RUnlock() - } - time.Sleep(time.Microsecond) - } - done <- struct{}{} - } - writer := func() { - for i := 0; i < 1000; i++ { - lock.Lock() - n := atomic.AddInt32(&count, 10000) - if n != 10000 { - lock.RUnlock() - panic(fmt.Sprintf("unexpected count(%d)", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(&count, -10000) - lock.Unlock() - time.Sleep(time.Microsecond) - } - done <- struct{}{} - } - for i := 0; i < 5; i++ { - go reader() - } - for i := 0; i < 2; i++ { - go writer() - } - for i := 0; i < 5; i++ { - go reader() - } - for i := 0; i < 12; i++ { - <-done - } -} - // failMetaMgrBuilder mocks meta manager init failure type failMetaMgrBuilder struct { metaMgrBuilder diff --git a/br/pkg/lightning/restore/table_restore.go b/br/pkg/lightning/restore/table_restore.go index 9c3048d9518d6..48057c0f17607 100644 --- a/br/pkg/lightning/restore/table_restore.go +++ b/br/pkg/lightning/restore/table_restore.go @@ -40,6 +40,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/multierr" "go.uber.org/zap" ) @@ -538,7 +539,7 @@ func (tr *TableRestore) restoreEngine( } if err == nil { metric.ChunkCounter.WithLabelValues(metric.ChunkStateFinished).Add(remainChunkCnt) - metric.BytesCounter.WithLabelValues(metric.TableStateWritten).Add(float64(cr.chunk.Checksum.SumSize())) + metric.BytesCounter.WithLabelValues(metric.BytesStateRestoreWritten).Add(float64(cr.chunk.Checksum.SumSize())) if dataFlushStatus != nil && indexFlushStaus != nil { if dataFlushStatus.Flushed() && indexFlushStaus.Flushed() { saveCheckpoint(rc, tr, engineID, cr.chunk) @@ -683,10 +684,18 @@ func (tr *TableRestore) postProcess( tblInfo := tr.tableInfo.Core var err error if tblInfo.PKIsHandle && tblInfo.ContainsAutoRandomBits() { - err = AlterAutoRandom(ctx, rc.tidbGlue.GetSQLExecutor(), tr.tableName, tr.alloc.Get(autoid.AutoRandomType).Base()+1) + var maxAutoRandom, autoRandomTotalBits uint64 + autoRandomTotalBits = 64 + autoRandomBits := tblInfo.AutoRandomBits // range from (0, 15] + if !tblInfo.IsAutoRandomBitColUnsigned() { + // if auto_random is signed, leave one extra bit + autoRandomTotalBits = 63 + } + maxAutoRandom = 1<<(autoRandomTotalBits-autoRandomBits) - 1 + err = AlterAutoRandom(ctx, rc.tidbGlue.GetSQLExecutor(), tr.tableName, uint64(tr.alloc.Get(autoid.AutoRandomType).Base())+1, maxAutoRandom) } else if common.TableHasAutoRowID(tblInfo) || tblInfo.GetAutoIncrementColInfo() != nil { // only alter auto increment id iff table contains auto-increment column or generated handle - err = AlterAutoIncrement(ctx, rc.tidbGlue.GetSQLExecutor(), tr.tableName, tr.alloc.Get(autoid.RowIDAllocType).Base()+1) + err = AlterAutoIncrement(ctx, rc.tidbGlue.GetSQLExecutor(), tr.tableName, uint64(tr.alloc.Get(autoid.RowIDAllocType).Base())+1) } rc.alterTableLock.Unlock() saveCpErr := rc.saveStatusCheckpoint(ctx, tr.tableName, checkpoints.WholeTableEngineID, err, checkpoints.CheckpointStatusAlteredAutoInc) @@ -916,7 +925,7 @@ func (tr *TableRestore) importKV( regionSplitSize = int64(config.SplitRegionSize) if err := rc.taskMgr.CheckTasksExclusively(ctx, func(tasks []taskMeta) ([]taskMeta, error) { if len(tasks) > 0 { - regionSplitSize = int64(config.SplitRegionSize) * int64(utils.MinInt(len(tasks), config.MaxSplitRegionSizeRatio)) + regionSplitSize = int64(config.SplitRegionSize) * int64(mathutil.Min(len(tasks), config.MaxSplitRegionSizeRatio)) } return nil, nil }); err != nil { diff --git a/br/pkg/lightning/restore/table_restore_test.go b/br/pkg/lightning/restore/table_restore_test.go index 77ae288ab3e30..4885efc652769 100644 --- a/br/pkg/lightning/restore/table_restore_test.go +++ b/br/pkg/lightning/restore/table_restore_test.go @@ -338,7 +338,6 @@ func (s *tableRestoreSuite) TestRestoreEngineFailed() { backend: backend.MakeBackend(mockBackend), errorSummaries: makeErrorSummaries(log.L()), saveCpCh: make(chan saveCp, 1), - diskQuotaLock: newDiskQuotaLock(), } defer close(rc.saveCpCh) go func() { @@ -900,7 +899,8 @@ func (s *tableRestoreSuite) TestTableRestoreMetrics() { cfg.Mydumper.SourceDir = "." cfg.Mydumper.CSV.Header = false - cfg.TikvImporter.Backend = config.BackendImporter + cfg.TikvImporter.Backend = config.BackendLocal + cfg.TikvImporter.SortedKVDir = "/tmp/sorted" tls, err := cfg.ToTLS() require.NoError(s.T(), err) @@ -935,8 +935,8 @@ func (s *tableRestoreSuite) TestTableRestoreMetrics() { closedEngineLimit: worker.NewPool(ctx, 1, "closed_engine"), store: s.store, metaMgrBuilder: noopMetaMgrBuilder{}, - diskQuotaLock: newDiskQuotaLock(), errorMgr: errormanager.New(nil, cfg), + taskMgr: noopTaskMetaMgr{}, } go func() { for scp := range chptCh { @@ -1413,11 +1413,8 @@ func (s *tableRestoreSuite) TestSchemaIsValid() { }, { // colB doesn't have the default value - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - // not null flag - Flag: 1, - }, + Name: model.NewCIStr("colB"), + FieldType: types.NewFieldTypeBuilderP().SetType(0).SetFlag(1).Build(), }, }, }, @@ -1568,10 +1565,8 @@ func (s *tableRestoreSuite) TestSchemaIsValid() { }, { // colC doesn't have the default value - Name: model.NewCIStr("colC"), - FieldType: types.FieldType{ - Flag: 1, - }, + Name: model.NewCIStr("colC"), + FieldType: types.NewFieldTypeBuilderP().SetType(0).SetFlag(1).Build(), }, }, }, @@ -1621,10 +1616,8 @@ func (s *tableRestoreSuite) TestSchemaIsValid() { Columns: []*model.ColumnInfo{ { // colB doesn't have the default value - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - Flag: 1, - }, + Name: model.NewCIStr("colB"), + FieldType: types.NewFieldTypeBuilderP().SetType(0).SetFlag(1).Build(), }, { // colC has the default value @@ -1826,16 +1819,12 @@ func (s *tableRestoreSuite) TestGBKEncodedSchemaIsValid() { Core: &model.TableInfo{ Columns: []*model.ColumnInfo{ { - Name: model.NewCIStr("colA"), - FieldType: types.FieldType{ - Flag: 1, - }, + Name: model.NewCIStr("colA"), + FieldType: types.NewFieldTypeBuilderP().SetType(0).SetFlag(1).Build(), }, { - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - Flag: 1, - }, + Name: model.NewCIStr("colB"), + FieldType: types.NewFieldTypeBuilderP().SetType(0).SetFlag(1).Build(), }, }, }, diff --git a/br/pkg/lightning/restore/tidb.go b/br/pkg/lightning/restore/tidb.go index e530f8be604a4..a6f831ef0aa14 100644 --- a/br/pkg/lightning/restore/tidb.go +++ b/br/pkg/lightning/restore/tidb.go @@ -18,6 +18,7 @@ import ( "context" "database/sql" "fmt" + "math" "strconv" "strings" @@ -373,9 +374,17 @@ func ObtainNewCollationEnabled(ctx context.Context, g glue.SQLExecutor) (bool, e // NOTE: since tidb can make sure the auto id is always be rebase even if the `incr` value is smaller // the the auto incremanet base in tidb side, we needn't fetch currently auto increment value here. // See: https://github.com/pingcap/tidb/blob/64698ef9a3358bfd0fdc323996bb7928a56cadca/ddl/ddl_api.go#L2528-L2533 -func AlterAutoIncrement(ctx context.Context, g glue.SQLExecutor, tableName string, incr int64) error { - logger := log.With(zap.String("table", tableName), zap.Int64("auto_increment", incr)) - query := fmt.Sprintf("ALTER TABLE %s AUTO_INCREMENT=%d", tableName, incr) +func AlterAutoIncrement(ctx context.Context, g glue.SQLExecutor, tableName string, incr uint64) error { + var query string + logger := log.With(zap.String("table", tableName), zap.Uint64("auto_increment", incr)) + if incr > math.MaxInt64 { + // automatically set max value + logger.Warn("auto_increment out of the maximum value TiDB supports, automatically set to the max", zap.Uint64("auto_increment", incr)) + incr = math.MaxInt64 + query = fmt.Sprintf("ALTER TABLE %s FORCE AUTO_INCREMENT=%d", tableName, incr) + } else { + query = fmt.Sprintf("ALTER TABLE %s AUTO_INCREMENT=%d", tableName, incr) + } task := logger.Begin(zap.InfoLevel, "alter table auto_increment") err := g.ExecuteWithLog(ctx, query, "alter table auto_increment", logger) task.End(zap.ErrorLevel, err) @@ -388,8 +397,16 @@ func AlterAutoIncrement(ctx context.Context, g glue.SQLExecutor, tableName strin return errors.Annotatef(err, "%s", query) } -func AlterAutoRandom(ctx context.Context, g glue.SQLExecutor, tableName string, randomBase int64) error { - logger := log.With(zap.String("table", tableName), zap.Int64("auto_random", randomBase)) +func AlterAutoRandom(ctx context.Context, g glue.SQLExecutor, tableName string, randomBase uint64, maxAutoRandom uint64) error { + logger := log.With(zap.String("table", tableName), zap.Uint64("auto_random", randomBase)) + if randomBase == maxAutoRandom+1 { + // insert a tuple with key maxAutoRandom + randomBase = maxAutoRandom + } else if randomBase > maxAutoRandom { + // TiDB does nothing when inserting an overflow value + logger.Warn("auto_random out of the maximum value TiDB supports") + return nil + } query := fmt.Sprintf("ALTER TABLE %s AUTO_RANDOM_BASE=%d", tableName, randomBase) task := logger.Begin(zap.InfoLevel, "alter table auto_random") err := g.ExecuteWithLog(ctx, query, "alter table auto_random_base", logger) diff --git a/br/pkg/lightning/restore/tidb_test.go b/br/pkg/lightning/restore/tidb_test.go index 89a5b40433797..5d05b041e6fdb 100644 --- a/br/pkg/lightning/restore/tidb_test.go +++ b/br/pkg/lightning/restore/tidb_test.go @@ -17,6 +17,7 @@ package restore import ( "context" "database/sql" + "math" "testing" "github.com/DATA-DOG/go-sqlmock" @@ -27,6 +28,7 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/metric" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" tmysql "github.com/pingcap/tidb/parser/mysql" @@ -403,11 +405,17 @@ func TestAlterAutoInc(t *testing.T) { s.mockDB. ExpectExec("\\QALTER TABLE `db`.`table` AUTO_INCREMENT=12345\\E"). WillReturnResult(sqlmock.NewResult(1, 1)) + s.mockDB. + ExpectExec("\\QALTER TABLE `db`.`table` FORCE AUTO_INCREMENT=9223372036854775807\\E"). + WillReturnResult(sqlmock.NewResult(1, 1)) s.mockDB. ExpectClose() err := AlterAutoIncrement(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345) require.NoError(t, err) + + err = AlterAutoIncrement(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", uint64(math.MaxInt64)+1) + require.NoError(t, err) } func TestAlterAutoRandom(t *testing.T) { @@ -418,10 +426,20 @@ func TestAlterAutoRandom(t *testing.T) { s.mockDB. ExpectExec("\\QALTER TABLE `db`.`table` AUTO_RANDOM_BASE=12345\\E"). WillReturnResult(sqlmock.NewResult(1, 1)) + s.mockDB. + ExpectExec("\\QALTER TABLE `db`.`table` AUTO_RANDOM_BASE=288230376151711743\\E"). + WillReturnResult(sqlmock.NewResult(1, 1)) s.mockDB. ExpectClose() - err := AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345) + err := AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345, 288230376151711743) + require.NoError(t, err) + + // insert 288230376151711743 and try rebase to 288230376151711744 + err = AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 288230376151711744, 288230376151711743) + require.NoError(t, err) + + err = AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", uint64(math.MaxInt64)+1, 288230376151711743) require.NoError(t, err) } @@ -494,18 +512,18 @@ func TestObtainNewCollationEnabled(t *testing.T) { defer clean() ctx := context.Background() + // cannot retry on this err + permErr := &mysql.MySQLError{Number: errno.ErrAccessDenied} s.mockDB. ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). - WillReturnError(errors.New("mock permission deny")) - s.mockDB. - ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). - WillReturnError(errors.New("mock permission deny")) - s.mockDB. - ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). - WillReturnError(errors.New("mock permission deny")) + WillReturnError(permErr) _, err := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) - require.Equal(t, "obtain new collation enabled failed: mock permission deny", err.Error()) + require.Equal(t, permErr, errors.Cause(err)) + // this error can retry + s.mockDB. + ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). + WillReturnError(&mysql.MySQLError{Number: errno.ErrTiKVServerBusy}) s.mockDB. ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). WillReturnRows(sqlmock.NewRows([]string{"variable_value"}).RowError(0, sql.ErrNoRows)) diff --git a/br/pkg/lightning/sigusr1_other.go b/br/pkg/lightning/sigusr1_other.go index 0e0a050e2c2fd..05ab9529b353c 100644 --- a/br/pkg/lightning/sigusr1_other.go +++ b/br/pkg/lightning/sigusr1_other.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux && !darwin && !freebsd && !unix -// +build !linux,!darwin,!freebsd,!unix package lightning diff --git a/br/pkg/lightning/sigusr1_unix.go b/br/pkg/lightning/sigusr1_unix.go index ac01998b5e51d..b1340c8968111 100644 --- a/br/pkg/lightning/sigusr1_unix.go +++ b/br/pkg/lightning/sigusr1_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build linux || darwin || freebsd || unix -// +build linux darwin freebsd unix package lightning diff --git a/br/pkg/lightning/web/res.go b/br/pkg/lightning/web/res.go index c45bd5229a5d5..4bcad1ca16385 100644 --- a/br/pkg/lightning/web/res.go +++ b/br/pkg/lightning/web/res.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build dev -// +build dev package web diff --git a/br/pkg/lightning/web/res_vfsdata.go b/br/pkg/lightning/web/res_vfsdata.go index e96e92e007120..4a0019b96e570 100644 --- a/br/pkg/lightning/web/res_vfsdata.go +++ b/br/pkg/lightning/web/res_vfsdata.go @@ -1,7 +1,6 @@ // Code generated by vfsgen; DO NOT EDIT. //go:build !dev -// +build !dev package web @@ -22,28 +21,28 @@ var Res = func() http.FileSystem { fs := vfsgen۰FS{ "/": &vfsgen۰DirInfo{ name: "/", - modTime: time.Date(2021, 9, 1, 11, 28, 27, 808837259, time.UTC), + modTime: time.Date(2022, 3, 24, 7, 23, 19, 946380638, time.UTC), }, "/index.html": &vfsgen۰CompressedFileInfo{ name: "index.html", - modTime: time.Date(2021, 9, 1, 11, 28, 9, 926935026, time.UTC), + modTime: time.Date(2022, 3, 24, 7, 23, 19, 946380638, time.UTC), uncompressedSize: 369, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x90\xc1\x4e\xfb\x30\x0c\xc6\x5f\x25\x7f\x9f\xd7\x45\xff\x1b\x07\x27\x07\x84\x38\x20\x6e\x8c\x07\xc8\x12\xaf\x35\x34\x4e\x49\xbc\x96\xbd\x3d\x5a\x3b\x40\xe2\x62\xeb\xfb\xe4\xcf\x3f\xd9\xf8\x2f\x95\xa8\x97\x89\xcc\xa0\x79\xf4\x78\xad\x66\x0c\xd2\x3b\x20\x01\x8f\x03\x85\xe4\x31\x93\x06\x13\x87\x50\x1b\xa9\x83\xd7\xc3\x63\x77\x07\x37\x57\x42\x26\x07\x33\xd3\x32\x95\xaa\x60\x62\x11\x25\x51\x07\x99\x85\xf3\x39\x77\x2d\x86\x91\xdc\xff\x1d\x0b\x2b\x87\xf1\x47\x2f\x9c\x74\x70\x89\x66\x8e\xd4\xad\x62\xd7\x86\xca\xf2\xde\x69\xe9\x4e\xac\x4e\x0a\x58\x8f\xca\x3a\x92\x3f\xf0\xc3\xbd\x79\xe6\x7e\x50\x61\xe9\xd1\x6e\x2e\xb6\x58\x79\x52\x93\xe8\x44\xd5\xc1\xda\xc0\xb4\x1a\x1d\xb0\x24\xfa\xdc\xbf\x35\xf0\x68\xb7\x29\x8f\x76\x3b\xe6\x58\xd2\xc5\xa3\x94\x6f\xbb\x69\x2d\xd2\xff\x41\x98\x85\x8e\x86\x45\xa9\x9e\x42\x24\x53\xe9\xe3\xcc\x95\x9a\x79\x0a\x73\x78\x59\x83\x7b\xb4\xb7\x24\xda\xdf\x65\x89\x67\xc3\xc9\x41\x98\xa6\x2b\x3a\xf1\xec\xd1\x6e\x44\xbb\x7e\xf8\x2b\x00\x00\xff\xff\xc7\x4f\xce\xce\x71\x01\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\x5c\x90\xc1\x4e\xfb\x30\x0c\xc6\x5f\x25\x7f\x9f\xd7\x45\xff\x1b\x07\x27\x07\x84\x38\x20\x6e\x8c\x07\xc8\x12\xaf\x35\x34\x4e\x49\xbc\x96\xbd\x3d\x5a\x3b\x40\xe2\x62\xeb\xfb\xe4\xcf\x3f\xd9\xf8\x2f\x95\xa8\x97\x89\xcc\xa0\x79\xf4\x78\xad\x66\x0c\xd2\x3b\x20\x01\x8f\x03\x85\xe4\x31\x93\x06\x13\x87\x50\x1b\xa9\x83\xd7\xc3\x63\x77\x07\x37\x57\x42\x26\x07\x33\xd3\x32\x95\xaa\x60\x62\x11\x25\x51\x07\x99\x85\xf3\x39\x77\x2d\x86\x91\xdc\xff\x1d\x0b\x2b\x87\xf1\x47\x2f\x9c\x74\x70\x89\x66\x8e\xd4\xad\x62\xd7\x86\xca\xf2\xde\x69\xe9\x4e\xac\x4e\x0a\x58\x8f\xca\x3a\x92\x3f\xf0\xc3\xbd\x79\xe6\x7e\x50\x61\xe9\xd1\x6e\x2e\xb6\x58\x79\x52\x93\xe8\x44\xd5\xc1\xda\xc0\xb4\x1a\x1d\xb0\x24\xfa\xdc\xbf\x35\xf0\x68\xb7\x29\x8f\x76\x3b\xe6\x58\xd2\xc5\xa3\x94\x6f\xbb\x69\x2d\xd2\xff\x41\x98\x85\x8e\x86\x45\xa9\x9e\x42\x24\x53\xe9\xe3\xcc\x95\x9a\x79\x0a\x73\x78\x59\x83\x7b\xb4\xb7\x24\xda\xdf\x65\x89\x67\xc3\xc9\x41\x98\xa6\x2b\x3a\xf1\xec\xd1\x6e\x44\xbb\x7e\xf8\x2b\x00\x00\xff\xff\xc7\x4f\xce\xce\x71\x01\x00\x00"), }, "/index.js": &vfsgen۰CompressedFileInfo{ name: "index.js", - modTime: time.Date(2021, 10, 11, 4, 35, 32, 822026137, time.UTC), + modTime: time.Date(2022, 3, 24, 7, 23, 19, 946380638, time.UTC), uncompressedSize: 425195, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\xbd\x7b\x9f\xdb\xb6\xb1\x00\xfa\xff\xfd\x14\x5a\x34\x47\x25\xa2\x11\x97\xd4\x7b\xb9\x45\x54\xc7\x71\x1a\xa7\xb1\x9d\xda\x89\x93\x58\x51\x7d\xb9\x22\xb4\x62\x4c\x81\x0a\x09\xed\xc3\x12\xef\x67\xbf\x3f\xbc\x48\x50\xa2\xd6\xdb\xb4\xa7\xa7\x4e\x57\x20\xde\x18\x0c\x06\x33\x83\xc1\xe0\xfc\xf3\xb3\xd6\xd7\x69\xd6\x4a\xe2\x05\x65\x39\x6d\xc5\x6c\x99\x66\xeb\x90\xc7\x29\x6b\x6d\x12\x1a\xe6\xb4\x95\x53\x11\x1d\xd1\x3b\xf7\xb7\xdc\xfd\xee\xf9\xd3\x67\x2f\xdf\x3c\x73\xf9\x1d\x6f\x7d\x7e\xfe\xff\x38\x0e\x26\x5f\xec\x6e\xc2\xac\x45\xc9\x6e\xd8\xf7\x27\x01\x25\x5f\xec\xa8\x4b\xef\x36\x69\xc6\x73\xb2\xdc\xb2\x85\xa8\xcb\xa1\x78\x97\x51\xbe\xcd\x58\x8b\xb6\xdb\xd4\x7d\xff\x9e\xe6\x2f\xd2\x68\x9b\xd0\x29\x0d\x76\x11\x5d\x86\xdb\x84\x07\xb4\x28\xa0\x2c\xeb\xea\x58\x52\xc6\x58\x69\x55\x79\x72\xe6\x15\x30\x19\xf5\x02\x87\x02\x07\x66\xba\x93\x11\xe6\x4c\xb0\xa9\xe3\xd2\xf4\xa3\x95\x8a\x9e\xc4\x4b\x07\x99\x18\x74\x46\xf8\xfd\x86\xa6\xcb\xd6\x4f\x34\xfc\xf0\x22\xdc\x60\xdd\x4f\xb6\x4d\x92\x4b\x51\x15\x27\x8c\xde\x9a\x54\x60\xf6\xd7\xa5\xca\xeb\xa4\x8d\x03\x9d\xb2\x80\x17\xd8\xa1\xb8\x68\x02\x08\x70\xd9\x91\x33\xde\x6e\x1f\x80\xc4\xf4\x80\x5e\xc6\x4b\x47\x74\x83\x10\x42\xf7\x7b\x94\x5e\xfd\x46\x17\x1c\x9d\x11\x92\x39\x14\xb7\xdb\x0d\x63\x30\x65\x2d\x90\xca\x31\x30\x92\x3a\x1c\xcb\xfa\xda\x6d\xe6\xae\xc2\xdc\xa1\xb8\x1c\xa9\x7b\x4d\xb9\x43\xb1\xcc\x19\x92\x5d\x01\x31\x79\x25\xdb\x12\xf0\x8b\x19\xfd\x3e\x4b\x37\x34\xe3\xf7\xed\xb6\x8e\xbe\xa6\xfc\xd5\x2d\x33\xd1\x5f\xd1\x7c\x91\xc5\x1b\x9e\x66\x97\xcb\x34\x73\x44\x2d\x49\x2b\x66\x2d\x8a\x05\xa0\x75\x4f\x44\xb7\x93\xb2\x82\x4d\x96\xf2\x54\xf4\x59\x74\xc5\xaa\xca\x5d\x84\x49\xe2\x50\x48\x30\x96\xd3\x98\x93\x78\xfa\x89\x36\x65\xee\x40\xce\x56\xde\x6e\x3b\xb9\xc8\xb8\xdf\xe7\x6e\x4e\x39\x9e\x36\x0e\xc3\x09\x21\x81\x1c\x07\xe1\x2c\x99\x13\x3a\x4b\xe6\x85\x06\x44\x58\xe1\x1c\x48\x38\xe5\x02\x2e\x10\x62\x08\xff\x28\x62\xca\xf5\x50\x62\x1f\x77\x98\x41\x8f\x6a\xf2\x88\x99\xbc\x37\xf7\xeb\xab\x34\x69\xb7\x51\x2e\x03\x87\x09\x6e\xcc\x69\x16\xf2\x34\x9b\x3a\x15\x3e\xf1\x26\xcc\x33\xc8\xf0\x87\x3a\x8d\x83\x4f\x55\x4f\x6d\xd4\x3b\xea\x3d\x75\x17\x29\xcb\x79\xb6\x5d\xf0\x34\x23\x84\x94\xf1\x67\x26\x5c\xcd\xfe\xd4\x0c\x35\xf8\xf7\xba\x0c\x02\xb0\xd6\x2a\xe3\x7f\x70\xb6\xfa\xfd\x81\x45\x47\xd0\x56\x50\x3f\x9e\xc5\x0b\x8e\x2e\x99\x1b\x39\x1c\x76\xef\x02\x41\xf1\xb2\x02\x5f\xca\x51\xb6\x32\xb2\x1b\x7a\x01\xfa\x13\x9d\x2c\x87\xf4\x02\x81\xef\x89\xaf\xc5\x84\x8e\x16\x17\x08\x7a\xf2\x2b\x1c\x46\xa3\x70\x8c\xa0\x2f\xbf\x26\xfe\x62\x3c\x19\x20\x18\xc8\xaf\xd1\xe8\xea\x6a\x14\x22\x18\xca\xaf\xc1\x22\x5c\x0e\x3d\x04\x23\xf5\xd5\x0f\xbd\xc1\x18\xc1\x58\x7e\xf5\x27\x13\xda\x5f\x20\x98\xc8\xaf\x1e\x1d\x47\xfd\x1e\x82\x0b\xf9\xe5\x5f\x0d\x69\xcf\x43\xf0\x44\x35\x7f\x75\xb1\x1c\x2d\x42\x04\x4f\x54\xfb\xa3\x8b\xa5\x17\x52\x04\x4f\x54\x93\x9e\x47\x47\xe3\x11\x82\x27\x63\xfd\xb9\x98\x0c\xfb\xa8\x28\xa0\x3f\x9c\xf8\x7f\x70\xf8\xcb\x25\xbd\xa2\xd4\x0c\x7f\xb9\x5c\x44\x51\xcf\x0c\x9f\x2e\x2f\xc2\x8b\xd0\x0c\x9f\x0e\xc7\xfd\x71\xdf\x0c\x9f\x2e\x87\x7d\x31\x60\x35\xfc\xe5\x60\xd0\xef\x8f\xcc\xf0\xe9\xb0\x7f\xd1\x1f\x9a\xe1\x47\xfd\xde\xb2\xb7\x34\xc3\x5f\x8c\x7a\x93\xde\xc4\x0c\xff\x6a\xec\x2f\xfc\x45\x39\xfc\xe5\x72\x12\x4e\xbc\x72\xf8\xcb\xe5\xb0\x37\xec\x95\xc3\x5f\x2e\xfd\xf1\x60\x50\x0e\x3f\x1a\x7a\x9e\xe7\x89\xe1\x5f\x8c\x2e\xfa\x9f\x18\xfe\x3a\x96\xe3\x4f\xe0\xfd\x40\x06\xb6\xf0\xf5\xef\x32\xb0\x80\xf7\xbf\xc9\x40\x04\x9f\x31\x19\x58\x16\x8a\x9e\x8a\x8d\xa8\x37\x99\xe0\x83\x2d\x48\x6d\x2c\x61\x76\xbd\x5d\x53\xc6\x73\x37\xa1\xec\x9a\xaf\xbe\xf0\xdb\xed\x9b\x34\x8e\x5a\xde\x19\xa9\x12\x67\xfe\x7c\x6a\x7f\x04\x1e\xb0\xe3\xa2\xbd\xc6\xa2\x3d\xbb\x68\x6f\x1e\xf8\x7a\xcb\x6a\xbd\x08\xf9\xca\x5d\xc7\xcc\x51\x81\xf0\xce\xe1\x40\x31\x30\x5c\x94\x1d\x0d\xf5\x5e\x49\x5d\xb1\x3a\x6b\xbb\x12\xfa\x13\x12\x9b\x92\xbb\x58\x85\xd9\x13\xee\x78\xe5\x5e\x12\x3a\x36\xc1\xa0\x84\xba\xf9\xf6\x2a\xe7\x99\xe3\x63\x6b\x33\x7d\x4d\xaf\x9f\xdd\x6d\x1c\xe4\xee\x7c\x40\x82\x5e\x2c\x42\xee\x50\x33\x12\x32\x9a\xf6\x02\x1f\x50\x81\x30\xa0\x6b\x84\x81\x11\xea\xae\x43\xbe\x58\x89\x3d\xcc\x6c\x5a\xed\xb6\x4f\x08\x61\x33\x6f\xae\xcb\xb5\xdb\x0e\x23\xcc\x5d\x87\x1b\xc7\x69\xa2\x5a\x1d\x5a\x60\x8c\x81\x4d\x51\x76\x7d\x55\xb6\x3a\x10\x95\xe8\x1a\xa6\x28\x44\x01\x42\x80\x1c\x84\x4d\xfa\x51\x85\x62\xdf\x36\x74\xf6\x2f\xfd\xe9\x26\xcc\x72\xfa\x9c\x89\x7d\xc2\x1f\xe1\x40\x42\x33\x4b\xb7\x2c\x72\xea\x29\xe7\xbd\xe1\xf0\x73\x9f\xf6\xf1\xb9\x4f\xfb\x05\xc6\xee\x6f\x69\xcc\x1c\x04\x2d\x31\x48\x8c\x70\x80\x50\x21\xf6\x64\x0d\x25\xea\x4a\x96\xeb\xd5\xd2\x11\x9d\x91\x10\x50\x80\x8c\xd9\xb5\xe3\x81\xda\xcb\xbb\x02\x02\x33\x39\x1c\x10\x7f\x43\x04\x68\x95\x27\xea\x6f\x88\xe6\x65\x1d\x0c\x63\xbe\xca\xd2\xdb\x96\x00\xfe\xb3\x2c\x4b\x33\xc7\xf1\x20\x73\xdf\x61\xa7\x0f\xa6\xd1\xb4\xd6\x06\xef\xf8\x60\x66\xa4\xeb\x63\x37\xdf\x24\x31\x77\x10\x20\x33\x03\x3b\x81\x14\x01\x83\x9b\x30\xd9\xd2\x3c\x48\x49\x7a\x12\xf4\x12\x12\x5f\x27\xa9\x98\x64\x5c\x60\x5c\x54\x38\x16\x57\x8b\x41\xa1\x99\x1c\xaa\xaa\x53\x37\xd4\xf5\xcf\x08\xe1\x15\x3c\xc4\x70\xf1\xb4\x61\xaa\x1f\x98\x19\x0f\x07\x62\xf6\x83\xc3\xba\x04\xb4\xb0\x40\x9c\x99\x3f\x27\xa8\x44\x0a\xf1\x09\xe8\x7f\x04\xe0\x67\xbd\x7a\x42\x4f\x25\x60\xa8\x22\xf9\x01\xc2\x1c\xcc\x6c\x35\xd8\x44\xf5\x51\x31\x64\x82\x03\x83\x8c\xe4\x15\x4e\x57\x4b\x91\x41\x86\x3b\xae\x37\xc4\xe7\x4e\xb9\x4e\xcb\xb8\xaa\xbe\xbc\x02\x9e\x1c\x09\x21\xc4\xa1\x44\x2c\x5b\x2c\x61\x39\xad\xaf\x46\x95\xb3\xcc\xa1\x80\x0c\x8c\xf0\x99\x37\x87\x8c\xf0\x99\x3f\x3f\xf7\x3d\x0f\x52\xc2\x67\x3d\x15\x4c\x48\xf6\x79\xd9\x83\x14\xfc\x6e\x8a\xa1\xce\xd5\xff\x5b\x84\xcc\xa1\x1d\x76\xde\xf7\xf0\xff\xf8\x3d\xb3\xae\xd3\x6e\xf2\x79\x09\x87\xb2\x69\xde\xed\xc3\x45\x97\x83\x8f\xa1\xeb\xe3\x02\xb6\x44\x61\xfd\x82\xcc\xac\x15\x27\x96\x58\x2e\x88\x11\x1c\x45\x4e\x9a\x22\x07\x18\xcf\x75\xbb\x6a\xc5\x48\x9a\x26\x20\xd7\x6e\x3b\xdb\x0e\x41\x21\x82\x85\xbb\xd9\xe6\x2b\x87\xcf\xfa\x73\x8c\x21\x76\x14\xda\x6f\x0d\xda\x2f\x0a\x5c\x58\xd0\x0c\x0e\x70\xb7\xc5\x09\x3f\xb5\x2c\x1c\x7a\x4e\x7a\xc3\x21\xfe\x0b\x71\xbd\xfe\x45\x6f\x32\xa5\xe7\x7e\xcf\xbd\xe8\x29\x1a\xb2\x49\x6f\x1d\x87\x8a\x09\x1f\xe2\x73\x5f\xfc\x40\xcf\x1d\x88\xd5\x03\x2f\xb7\xeb\x2b\x9a\x39\x8e\xdb\xf3\x7b\xa3\xcf\xc5\xec\x75\xdc\xb1\x3f\xec\x7d\x2e\x66\xb0\xe3\x7a\xe3\x9e\x08\xf6\xe6\xd8\xe5\xe9\xd7\xf1\x1d\x8d\x9c\x3e\xb6\xb0\x66\xfb\x6f\x4f\x9b\xeb\x0f\xcd\xf8\x04\x0a\x7e\xe1\x0e\xa7\x91\x44\xed\x60\x29\x7f\xaa\xb6\x16\xb5\x55\xa9\x30\x0f\xb8\x14\x46\x24\xc5\x12\x52\x81\x81\xb8\x44\xe1\xf2\x7b\xbf\xd7\xfb\x8e\x9c\x06\x0c\x06\xb0\xb3\xfe\x9c\x70\x10\x64\xa3\x6a\x25\x2a\xa5\xa9\x7a\x0b\x72\xb5\xab\x5a\x0e\x96\x3c\x2e\xab\xeb\xcd\x3f\x27\x7e\x97\x5f\xd2\x44\x48\xbf\x82\xa6\x36\x94\x91\x24\x07\x1b\xe1\x86\x11\xef\x92\xfd\xa5\x7f\xc9\x3a\xc4\xaf\x2a\x62\xba\x22\x3d\xd6\x7a\x0f\x97\xff\x56\x0f\x3b\xc4\xf1\x3d\xaf\x6b\xc5\xe0\xcf\xff\x23\x3d\xee\x10\xb1\x12\xba\x56\x8c\xa8\xd8\x1e\x41\x01\xfd\xf1\xf0\x71\x4c\x21\xb5\x38\x9e\xe1\xc5\x64\x8c\x21\x95\xa1\x61\x1f\x43\x48\x98\x33\x1e\x8c\x7a\x18\x62\x32\x43\x77\x39\x02\x94\xaf\x11\xa0\x75\x84\x00\x25\xd7\x08\xd0\x5d\x82\xe6\x97\x36\xa5\xac\xb6\x85\x92\x50\x29\xd4\x24\x84\xf0\xe9\xee\x2e\x0f\x3c\xc8\xd7\xc1\xc8\xf3\x60\x1d\x05\x17\x23\x0f\x92\xeb\xc0\xef\x4d\x3c\xb8\x4b\x02\xff\xa2\xe7\x15\x01\x07\xb1\xa7\x6d\x59\xcc\x21\xa9\x0a\xa7\x53\xb4\xb9\x43\x41\x0a\xb9\xd8\xf0\x38\xdd\xc0\xb6\x4a\xcc\xa7\xc3\x20\x87\x05\x31\xdb\x23\x85\x19\x52\xed\x23\x40\xa2\x26\xd1\x73\x4e\x37\x68\x6e\x71\x74\x91\x45\x87\x99\x5c\x9c\x95\x58\xc4\x66\x74\x3e\x15\x7f\x02\x6a\x48\xcd\x5f\xd7\x34\x8a\xc3\x96\xb3\x8e\x59\xf7\x36\x8e\xf8\x2a\xa8\xb6\x92\x72\x1b\x49\x0e\xf6\x8e\x65\xb5\x77\x64\x24\x2e\x27\xba\x62\x88\x84\xac\x15\x97\x1b\xb6\x58\x90\x38\x78\xa8\xa9\x87\x7a\x5a\xeb\x45\x2b\x64\x51\x0b\xe1\x0e\x72\xd6\xe1\xdd\x61\x2d\x0a\xfb\xb2\x76\xbb\xa1\xba\x78\x96\x75\xfc\xb9\xa8\x53\x87\x02\x8e\xbb\x5b\xb1\xaf\x1c\x8e\x52\x13\x44\x0f\x42\x01\xf3\xdd\x07\x7a\x9f\x07\xb1\x21\xb1\x0c\xb6\x9b\x20\x82\x28\xbd\x65\xc1\xf1\xce\x53\x81\x82\xe2\x8e\x0f\x19\x11\xad\xf1\xf9\xbc\x22\xc0\x15\x58\xa6\x91\x23\x70\xcf\x86\x4b\xc3\x88\x8e\x46\x92\xb5\xdb\xfc\x0b\x6f\x9a\x05\xf4\x44\xf7\xe1\x8a\xf2\x5b\x4a\x59\xb0\x84\x94\x25\xf7\x41\x03\x0b\x24\xa6\x8f\xe2\x02\x54\x63\x0d\x19\x04\xe0\x8b\x02\x16\xb8\x50\x7a\x0f\xe6\x0c\x2e\x06\x3d\x0b\xc9\xb6\x7a\x11\x2a\x14\xb8\x3c\x00\xd9\xf5\x96\x73\x9a\xe5\x55\xcd\x86\xcd\x38\x22\xf1\x5e\x23\x89\xf7\x6c\x12\xef\xcd\x83\x5d\x61\x00\x28\x04\xbd\x34\xa1\xee\x6d\x98\x31\x67\x86\x5e\x84\x9c\x66\x71\x98\x74\x7f\x7c\x1e\xb4\xf8\x8a\xae\xa9\xbb\x8e\xef\x62\x96\xbb\xba\x0b\x0e\x6e\xc5\x79\x2b\xa2\x9b\x8c\x2e\x42\x4e\x23\x17\x01\xfa\x25\xdd\xb6\x16\x21\x6b\x09\xe2\xc1\x57\xb4\x95\xa7\xdb\x6c\x41\x5b\xe9\x52\x7e\xc9\xf2\xad\x28\xce\xe8\x82\x27\xf7\x01\x02\xf4\x2b\x6b\xc9\xff\x6d\xc2\x28\x8a\xd9\xf5\x77\x74\xc9\x4d\x63\xf9\x26\x5c\x08\xfe\xb4\x87\xe1\x20\xd7\xeb\xf8\x7a\xf5\x50\xb6\x99\x4a\xb9\xca\x68\xf8\x61\x93\xc6\x02\x24\xdb\x8d\xf3\xe7\x7c\xfd\x67\x3c\x0f\x5a\x3b\x93\xed\xc1\x56\xfb\x55\x75\x0f\xb7\x6b\x65\x2c\xca\x10\x9a\x6b\xde\xf0\x57\x26\x38\xc8\x72\xf2\xec\x06\xb9\xe8\x72\xad\x66\x11\x53\x00\x13\xd9\x73\x99\xbd\x00\x2a\x7a\x2e\x28\xe8\xc9\x4a\xfa\x47\x95\xf4\x45\x25\xb3\xaa\xe4\x1c\x63\x5c\x00\x4f\xd3\xe4\x2a\xcc\x02\x27\x23\xbb\x75\xcc\xbe\xa1\x32\xf7\x70\x54\x94\xcd\x65\x16\xa7\xab\x4a\x8b\x25\x04\x48\x92\x05\x27\xcd\x62\xca\xb8\xd4\x17\x07\xad\x24\x64\x51\xbe\x08\x37\x14\x23\x0c\x56\x75\x83\x49\x81\xad\xfa\xac\xde\x5b\x99\x46\x83\x02\x43\x26\x3a\xa9\x96\xc0\xc2\x08\xce\x4a\xd3\x10\x91\xdd\x55\x12\x2e\x3e\x48\x8d\x85\x87\xe0\x76\x15\x73\x2a\xc5\xf9\x25\x2a\x60\x69\xf4\x10\xa1\xf8\x57\xea\x21\x86\xe2\x5f\xa9\x87\x90\xff\x2b\xf5\x10\x9e\xf8\x67\xf4\x10\x57\x91\xf8\x67\xf4\x10\x17\x54\xfc\x33\x7a\x88\xf1\x50\xfc\x33\x7a\x88\x91\x2f\xfe\x19\x3d\xc4\xa0\x27\xfe\x19\x3d\x44\xcf\x17\xff\x4a\x3d\x44\x34\x14\xff\x4a\x3d\x44\x28\xff\x57\xea\x21\xfa\x9e\xf8\x57\xea\x21\x74\xbd\x05\x6c\x08\xfa\xd3\xf8\x62\x32\x5a\x5c\x21\x58\x11\xf4\xa7\xfe\x72\xe8\x5f\x0d\x11\xac\x89\x2c\xb3\xbc\x58\x22\xb8\x21\x62\xe0\x03\x6f\xe2\x23\xb8\x16\xe1\xa1\xe7\x0d\xc7\x08\xee\x09\xfa\xd3\x62\xe8\xfb\xa3\x1e\x92\x5b\xf1\x15\x61\x4e\x7f\x38\xf1\x0d\x10\x6f\x65\xb9\xab\xf1\x20\x42\x70\x27\xc3\x17\x13\x01\xcc\x67\xb2\x8e\xf1\x42\x84\x3f\x10\xf4\xa7\xd1\xe0\x6a\xb8\x1c\x21\x78\x43\xc4\xa0\x2e\x46\xcb\x3e\x82\xa7\x04\xfd\xc9\xbf\x18\x8f\x22\x5d\xf7\x3b\xc2\x9c\x49\xbf\x3f\xc0\xf0\x3d\x61\xce\xc5\xe8\xa2\x8f\xe1\x35\xd9\x71\x7a\xc7\x83\xdd\x26\x8b\xd7\x61\x76\x1f\x48\xa9\xd4\xf1\xa0\xa5\xff\x73\x27\x63\x8c\x20\xa7\x8b\x94\x45\x8d\xe9\xc3\x01\x46\x10\xc5\x79\x78\x95\xd0\xe8\x38\xb9\x3f\xc1\x08\x56\x31\xe3\xcd\x49\x05\x44\xf1\x4d\x1c\xd1\xec\x38\xd9\xef\x61\x04\x57\xe1\xe2\xc3\xb5\x94\x00\x82\xdd\x26\xdc\xd0\x2c\x88\x5c\x89\x48\x60\xf4\xe5\xcb\xd9\xd0\x9b\x17\x10\x4a\x22\x1a\xec\xc4\xef\x0d\x3d\xd1\xcd\x55\x7a\xd3\xd4\x92\x57\xa6\xbd\x12\xc4\x80\xdf\x07\xae\x37\x80\x9c\x26\x74\xc1\x9b\xc6\xe4\x4d\x24\x48\x54\x72\x55\x64\xf2\x00\x18\x7a\x23\x0b\x4a\x5f\x56\x83\x6a\x1e\xb5\xc9\x58\xd6\xdd\x9f\xc0\x32\x5d\x6c\xf3\x13\xf9\x65\x5a\x99\xd9\xef\x49\x68\xdc\x84\x76\xef\xfc\x5e\x51\xc0\xab\xc3\xd9\x36\xc0\x3c\x9c\xdf\xde\x70\x08\xad\xea\x8f\xe7\x8e\x8f\x27\xf9\x28\xcf\xb0\x3e\xd3\x8d\xe9\xf1\x22\x65\x0f\xa4\x1f\xa2\xc3\x51\x9e\x13\x48\xb1\x9c\x4d\x3c\x6f\x5e\xe2\x44\xb9\x56\x8f\xf0\xc2\x0c\xd8\xc6\x84\xa3\x46\xe4\xfc\x1e\xe0\xc3\xe4\x10\x1f\x8e\xbb\x36\x6a\xc2\x0a\x7f\xf4\x49\xb8\xf5\x1f\x42\x8d\x66\x08\x7c\x0a\x41\x9a\x4b\x3d\x02\x4d\x7a\x83\xa2\xa8\x38\x98\x1f\x14\x07\x03\x99\xe2\x4d\x52\x92\xb9\x89\x20\xfd\xfb\x7d\x06\x21\xc9\xdc\x28\xcc\x3e\xec\xf7\xbe\x3b\xfc\x3c\xbb\xa4\x33\x3e\x97\x22\x60\xfd\x7c\xc8\x61\x78\x2a\x92\x08\x9d\xb1\x79\x80\x64\x71\x24\x05\x02\xaa\xea\x12\x8c\xfb\xf7\xee\x67\x0c\x3b\xd4\x5d\x87\x31\x83\x14\x07\x48\x54\x2c\x73\xb5\xdb\x0e\x95\xcd\xa8\x6c\xef\x7f\x2b\xb3\x85\xd8\x16\x91\x5f\xda\xe2\x87\xc6\xee\x03\xf9\x43\xb6\x16\x6c\x40\x94\x0e\x56\x20\x2a\x0d\xd6\x42\xe4\x88\x85\x54\x61\x16\x80\x2d\x77\xc4\xa6\xd0\x8d\x2a\x74\xad\x0a\xdd\x17\x41\x2c\x45\x11\x9a\x65\x69\x56\x97\x45\x74\x81\x2b\xf7\xdd\xac\x2f\x30\x52\x96\x13\x5f\x43\x89\x9f\xa2\xb8\xf8\x1a\x7b\xde\xbc\x08\x72\x78\x49\x14\x9b\x16\xb3\x6b\x78\x5f\xd5\xf3\xd2\xd4\x73\xab\x2a\xb8\x53\x25\x9f\x15\xc1\x4b\x78\x21\x35\x8d\xcb\x14\x9e\x57\xf9\x5f\x98\xfc\x1f\x54\xfe\x37\x2a\xff\xd3\x22\x78\x01\x4f\xa4\x92\x70\xb1\xa0\x79\x0e\xdf\x55\x45\x9e\x98\x22\xef\x6a\x5d\x7d\x57\xeb\xea\xbb\xb2\xab\x4f\xe0\xa3\x51\xf7\x7d\x55\x55\xf2\x71\xaa\x27\x34\xf8\x08\x5f\x13\x79\x8e\xc4\xb3\x30\xe7\x3f\xac\x32\x9a\xaf\xd2\x24\x82\x2f\xab\xcc\x5f\x4f\xfb\xc1\xd7\xf0\x9b\xa8\x26\x65\x61\xf2\x6a\xb9\xcc\x29\x87\x9f\xaa\x0c\xbf\x4d\xdd\x5e\xf0\x1b\x7c\x56\x13\xe5\xf4\x5c\x0a\x21\xce\x4c\x11\x02\x24\x21\x8f\x00\x69\xd8\x21\x40\x02\x24\x22\x93\x1a\x29\x02\x24\xfa\x8a\x00\x1d\x75\x49\x24\x55\xed\xd7\xa4\xc2\x1f\x2d\x55\x8f\xc0\xb6\x75\x2c\xfa\xf0\xca\x15\x34\xd3\x20\x15\xfe\x82\x7c\x39\xad\x47\x05\xaf\x6b\x9f\x92\x17\x7a\xfb\x9f\x53\xb9\x0d\xbd\x7f\xe3\xf4\xa0\xef\x79\x90\x1d\x17\xee\x37\x16\xee\xdb\x85\xfb\xf3\x60\xec\x79\x97\xf1\xd2\x39\x73\x28\x29\x99\xd6\x02\x28\xc6\x72\x05\xb6\xdb\x62\x5d\xcb\x05\x2a\x3e\x89\xf8\xc2\x70\xa6\xbe\x9a\xb4\xd7\x0b\x51\xc1\x00\x38\x96\xaa\x70\xa4\xd4\xd6\xd6\x49\xf8\xc3\x05\x87\xf0\xed\x9b\x57\x2f\x5d\x55\x2a\x5e\xde\xeb\x66\x31\x2e\xe5\x69\x41\xad\x34\x3e\x02\x83\x9f\x30\xc8\x08\x49\x4a\x20\x13\xdf\x16\x82\xd2\x3b\x2e\x89\x95\x1d\x41\x7e\x2c\xeb\x04\x5a\xc0\x37\x64\x27\x17\xc1\x2b\x50\x0b\xe5\x75\x51\x89\x70\xa9\xe8\x51\x09\x93\x45\xba\x5e\xa7\x2c\x88\x40\x6a\x1a\xbf\x02\x83\x17\x6f\x1d\x86\xad\xad\xf5\xad\x90\x3e\x05\x2f\x89\x00\x09\x0e\x53\xfc\x8c\x3d\x0f\x61\x90\xe8\x1c\xbc\x75\xb6\x18\x34\x46\x07\x6f\x9d\xf7\x18\x04\x52\x07\x6f\x9d\xe7\x18\x34\x5e\x07\x6f\x9d\xef\x30\x5c\x67\xf4\x3e\x58\xc2\x11\x6a\x07\x5f\xc2\x35\xe5\x4f\xad\x21\x05\x3f\x42\xb8\xbd\x16\x13\xfa\x34\x4d\x44\x13\x60\xe1\x7e\xf0\x53\x01\xdf\xcc\xbe\x9a\x63\xf8\xcc\xa2\xa4\xef\x2d\x11\xd7\xd2\xbf\xfa\x74\xf8\x39\xc5\xe7\x3e\x1d\x56\x59\x5f\x58\x59\x45\x31\x89\xf9\xcf\x15\x8f\xf1\x43\x16\xb2\x7c\x99\x66\xeb\x00\x6d\x37\x1b\x9a\x2d\xc2\x9c\xa2\x02\x9e\x90\x3f\xa3\xd7\xe9\x55\xca\x53\x04\x2d\xf4\x0d\x4d\x6e\x28\x8f\x17\xa1\xf8\x78\x22\x84\x54\x04\xad\x3c\x64\x79\x37\xa7\x59\xbc\xfc\x73\xb5\x34\xbf\xb3\x15\xf1\x0d\x67\xd9\x7c\xca\x1d\x8a\x25\x31\x67\xee\x32\x65\xfc\xeb\x70\x1d\x27\x07\xd4\xfc\x89\xa4\xdb\x2a\xfd\x4d\xfc\x91\xd6\x49\xb7\x3f\x90\x7a\x24\x95\xfc\x93\x14\x71\xbe\x13\x7f\x20\xaa\x72\x2d\xa6\x42\x16\x59\xc0\xb2\x96\xed\x35\xbd\xde\x26\x61\x06\x9b\x2a\xe3\x72\x2a\x64\x86\x25\xac\x6a\x19\x5f\xd0\x28\xde\xae\x61\x5d\xe5\x5b\x4d\x85\x00\xb3\x82\x9b\x5a\xbe\x2f\x05\xe9\xbc\xae\x72\xdd\x4c\x85\xc8\x71\x03\xf7\x84\xb9\x2b\xbe\x4e\xbe\x36\x03\xb8\xaa\xf2\xdc\x4f\xfd\x51\x70\x0f\xb7\x84\xb9\x61\x92\xbc\x0d\xb3\x38\x64\x3c\x87\x3b\xc2\xdc\xcd\xdd\x0f\xe9\x6b\xba\x86\x67\x25\x65\x65\x30\x43\x15\x94\x10\x20\x03\x12\x1d\xb4\x86\x5f\x8b\xd1\x23\xad\xc5\xa9\x41\xd5\xa2\xbe\x54\x74\xd6\xee\x2a\x02\x64\x75\x0b\x01\xd2\x9d\x42\x73\x0c\x1f\xc8\xf6\xdc\x1f\xc0\x1b\x72\xb7\xdf\x1f\x2b\x5a\x2c\x61\xf6\xfc\xea\xf3\x0f\x80\x32\xba\x46\xb8\x80\xa7\x35\xd3\x1c\xc1\xa5\x40\x6a\x91\x6f\xb5\x34\xab\x41\x06\x09\x54\x1d\x0c\x28\x98\x11\x07\x6f\x1c\x8e\x21\x89\x19\xd5\x62\x2d\x2b\x20\xd1\x1b\x24\xe5\x9c\x66\x6f\x94\x82\x20\xa8\xfa\xf1\xde\xc9\xce\x39\x06\x24\xfb\x11\xec\x0a\x48\xe1\x16\x17\xf0\x8e\xec\x56\x7e\xf0\xd4\x89\xe0\x62\x04\xbe\xeb\x8f\xc6\xd0\xf5\xdd\x21\x86\x55\x4f\xc6\x8e\x3c\xf0\xdd\x1e\x74\x65\x54\x3f\x78\xea\x6c\x60\x30\xd1\x19\x3d\x0c\xab\x81\x8c\xea\x0f\x44\xae\xfe\x10\xdc\x9e\xc8\x37\x94\x91\x3d\x11\xd9\xef\x0f\x64\xbe\x51\xf0\xd4\x59\x43\x4f\xd4\x36\x02\xd7\x1f\x0a\xea\x70\xc5\x63\x9e\x50\x5f\x66\xf6\x45\xeb\xe3\x61\x3d\xa9\x27\x0b\xf9\xa2\x9e\xe1\x18\x5c\x1f\xc3\x55\x1a\xdd\x5b\x05\x74\x7e\x11\xdb\x53\xb1\x22\xef\xa0\xaf\xa3\xb7\x9c\xa7\xac\xaa\x43\x54\x3f\x80\xe7\x18\x16\xe1\x46\x32\xd8\xb2\x44\x4f\x74\x69\x04\xee\x00\x83\xe0\x9e\x05\x50\x4d\x42\x4f\x24\xf8\xf0\x1c\x9f\xa4\xa2\x36\xb6\x04\x57\xa0\xf1\x23\x78\x03\x8a\x1d\x7e\x01\x47\x73\x29\x73\x6e\xe1\x00\x61\x83\x08\x8e\x10\x36\xd8\xc0\x21\xc2\x06\x6b\xa8\x23\x6c\x70\x5d\xc0\x3b\x0c\xcf\x60\xb7\x48\x52\x46\x83\x33\xbf\xb0\xc8\xe2\x47\xc7\xe0\xd6\xac\x42\x84\xc3\x7d\xf5\x2f\xc4\x9b\xaa\x05\x19\xd8\xba\x39\x81\xec\xad\xea\xbc\xf1\xb8\x94\x7f\x5c\xca\xff\x74\xa9\xde\x71\xa9\xde\xa7\x4b\xf5\x8f\x4b\xf5\x55\x29\x2d\x5a\x8a\x7f\x55\x05\x6e\x4f\x6a\x4c\xe1\xa1\x41\x0f\x8e\xab\x1c\x7c\xba\x23\xc3\xe3\x52\xc3\x4f\x97\x1a\x1d\x97\x1a\x7d\xba\xd4\xf8\xb8\xd4\xf8\xa1\x41\xfb\x83\x4f\x8f\x7a\x72\x5c\xe7\xe4\xd3\x3d\xb9\x38\x2e\x75\xf1\x08\x04\x69\xc0\x2b\xff\x31\x88\xd5\x84\x59\xfe\x83\x23\x57\xf3\x6d\xf4\x9e\x80\x70\xa1\x34\x51\x5f\x91\x19\x62\x29\xa3\x08\x3e\x3a\x1e\xf4\xc0\x87\xae\x0f\x1e\xf8\xe0\xcb\x2a\x7c\xe8\x0b\xe2\x24\xd2\xfa\x22\xad\x07\x22\x53\x4f\xa7\x0d\xab\xb4\xbe\x4a\xeb\xc3\x40\xa7\x4d\x4c\x5a\x0f\x06\xaa\xce\x81\xc8\xaf\xea\xf6\xaa\x82\x43\x95\x38\x14\x05\x54\xe2\xe0\x28\x71\x24\x4b\xa8\xd4\xb2\x5e\x51\x9d\x6c\x73\x2c\x52\x7d\xd9\x31\x41\xf2\x54\xea\x50\xa4\xf6\xc1\x83\x89\x49\xed\x8b\x9a\x7b\x26\x75\xa4\x52\x2f\x24\x75\x53\xa9\x23\x93\x3a\x32\xa9\xa2\xe4\x00\x54\xdf\xfd\x09\xf4\x4d\xf2\x18\xba\x62\x98\xbe\x0f\xfe\x50\x27\xf7\x3c\x93\x3c\x86\x89\x4e\xee\x81\x3f\x96\xb0\x1a\x42\xaf\x07\x83\xc3\xe4\x3e\xf8\x17\x26\x79\x50\x25\x5f\xe8\xe4\x01\xf4\x7c\x93\x3c\x32\xc9\x13\x91\x2c\xc0\xe8\xcb\x3a\x7b\x12\x38\xbd\x09\x0c\x4d\xb2\xef\xe9\xf4\x91\xa8\x54\xa5\xf7\x3d\x2b\xdd\xd7\xe9\x63\x51\xab\x4e\xef\x99\xf4\x8b\x2a\x7d\x22\xaa\x55\xe0\xed\x0f\x60\x54\xa6\xf7\xa0\x3b\x12\xe9\x17\xd0\xbb\x30\xe9\x23\x93\xee\xcb\x61\xc9\x0c\x02\x20\x12\x7b\x60\x02\xfd\x09\x8c\x8f\x33\xf8\xd0\xef\xeb\x0c\x03\xcf\xce\x30\xd0\x19\x7a\xd0\x1f\x9a\x0c\xbd\x32\x83\xc4\x90\xee\x58\x64\xe8\x8b\xa6\xd5\x34\x0e\x06\x30\xa9\x32\x0c\x75\x86\x81\x68\x5a\x67\x18\xc1\x04\xcf\xe1\x6b\xb2\xbb\x4a\xb3\x88\x66\xaf\xc3\x28\xde\xe6\xc1\x40\xd9\xe5\x7e\x49\x98\x73\x31\xe8\x5f\x60\xf8\x8d\x30\xc7\xf7\xbc\x1e\x86\x9f\x88\xc3\x9c\xe1\xe8\x62\x8c\xe1\x31\xa7\x9c\x18\x3e\x23\xea\xc4\xec\xf4\xc1\x2a\x6c\x37\x0d\x67\x4e\x0f\x9d\x0e\xfe\x34\xa3\x72\x5d\x63\x84\x8b\x42\x6b\x8f\x7f\x24\xcd\xb6\x36\x53\xb3\xf9\x0a\xc6\xc9\xda\xee\x8c\xf1\xf1\x5b\xf8\x06\x7e\x27\xbb\x75\x80\xd6\x61\x76\x1d\x33\x04\x9b\x00\xe9\xd3\x09\x54\xc0\xdf\xc9\x8e\x07\xe8\x87\x74\x83\x20\x0b\xd0\x6b\xc5\x25\x5e\x05\xe8\xcb\x94\xf3\x74\x8d\x20\x09\xd0\x77\x74\xc9\x11\xdc\x05\x33\x1d\xd2\xb9\xe6\x70\x1f\xcc\x54\x49\x93\x7b\x5e\xc0\x3f\xc8\x4e\xb5\xf3\x73\x80\xd6\x77\x08\xd4\xc7\x2f\x01\x5a\xdf\x23\x73\x28\xf2\x73\x80\x36\x77\xe5\xd7\x2f\x01\xda\xdc\xa3\x02\xfe\x46\x9c\xba\xa4\x2d\x8d\xdf\x8c\x84\xac\xcc\xb5\xff\x31\xa3\x73\x6d\xec\x36\xa3\xf3\x4b\x4a\x44\x44\x61\x74\x45\xda\x4a\x4a\x5a\x6c\x39\x1e\x7c\x29\xa0\xc2\xc5\xfa\xce\xa4\xa5\x1a\xa4\x44\x9a\x16\x85\xe4\xf7\x59\x36\x87\x98\xfc\x7d\x96\xce\xf7\x7b\x84\x8c\xd0\xf9\x24\xcb\xc2\x7b\x37\xce\xe5\xaf\x13\xe3\x69\x7c\xd2\xa8\x2a\x94\xf6\x6c\xc1\x2c\xec\xc4\x73\x29\x5e\x16\xd0\x90\xab\x64\xe8\xbf\x99\x51\x21\x5d\x8b\x1f\xf2\xd6\xa1\x18\x83\x08\x16\x18\x7e\x21\x33\x24\x31\x46\xc0\x75\x2d\x98\xf1\xf5\x95\xf8\x93\x88\x3f\x77\xe2\x8f\xe0\xe8\x05\x88\x37\x22\xc7\x46\xe4\xd8\x88\x1c\x9b\x44\xf2\xdd\xe2\x8f\xc8\x61\xe6\x56\x07\xd4\xac\xa8\xb0\x9e\x53\xfd\x65\xe6\x55\x7f\xea\x19\xd5\x53\x56\x86\x7e\x11\xf5\x6a\x1c\x29\x43\xaa\x52\xfb\x60\xab\xfa\x2c\xab\xb5\x0e\xc2\xaa\xaf\x9f\xab\xe0\x2f\xb6\xa1\xc1\xcf\xb6\xa6\x4f\x1f\xde\xed\xf7\x13\x73\x54\x7f\x78\x14\xcc\xa7\x4d\xe6\xd6\x9f\xd3\x22\xa8\xcf\x1c\xc7\x8d\x19\x05\xc4\x83\x66\x79\xd3\x3e\xb9\xb5\xec\xe3\xbe\xad\xfa\xf7\xb3\x43\x5d\x79\xc8\x58\xaa\x28\xb4\x75\xbb\x58\xfc\x0e\xc5\x07\x98\xc2\x24\xbe\x4a\x13\xc1\x5f\x6c\x43\xc0\xc3\xeb\x0d\x59\xf3\xaa\xb6\xeb\x31\xe6\x3b\x6e\x46\xa3\xed\x82\xd6\x6c\xee\xb2\x2a\x79\x96\xcd\x8f\xef\x37\x18\xc5\x4c\x35\xd6\xfd\x5e\xdd\x69\xe0\xa6\x2b\x5c\x5f\x51\xa0\xca\xde\x2b\xbc\xca\x1d\x5e\xe9\x61\xf8\x17\xc4\x9b\xb2\xe0\xd8\xbe\x60\xda\x65\x01\xea\x56\xa6\x79\xb8\x70\x38\x30\x0c\xb4\xc0\xb0\x2b\x70\x51\x38\x7f\x73\x18\x06\x8e\x21\x95\xea\xe2\xcb\xc3\x91\xe9\xf3\xf4\x78\xe9\x1c\x4e\x9e\xb1\xb3\xd0\x00\xb7\xcf\x8c\xf7\xfb\xcf\xca\x9e\x35\xc1\x23\x85\xd0\x86\x88\xbb\xdd\x38\x99\x9c\xa1\x59\x38\xc7\x73\xc2\x1c\x2e\x02\x65\x27\x05\x84\xf4\xbd\x0e\x42\x04\xc9\xf8\x4d\x92\x0c\x6c\x54\xe4\x0f\xf7\xc0\x46\x00\x8e\x3f\x35\x3d\xa9\xec\x8c\xee\x44\x66\x75\xc2\xa0\x84\xc3\x71\x21\x87\x90\xe1\x02\x97\xd5\xfd\x28\xf3\x94\x18\x49\xa9\xb6\x2d\xa0\x7f\xd4\xb6\x60\x72\x29\xe9\xea\x7a\x1b\x57\x36\xc5\x06\xc5\x77\x7a\x0d\x06\xa2\x6f\x8c\x58\x8b\xc2\xd8\x32\x1d\x37\xab\xef\xe4\xa8\xc9\x93\x46\x95\xde\x65\xf6\x17\x7a\x99\x75\x3a\x98\x09\xa4\xac\x5a\xcf\x4a\x2c\xf0\x6c\xbb\x5f\xee\xf8\x38\xf0\xeb\x31\x82\x5e\xe3\xa0\xc1\x9e\xb8\x09\xa9\x69\x7d\x24\x8c\xc8\xfb\x34\x27\x88\x08\x9b\x5a\x06\xa5\x92\x84\xe2\x80\x55\x26\xc1\x2d\x54\x4a\xb5\xad\xe6\xfb\x2b\xcc\x98\x22\xed\xae\x69\x8d\x70\x98\x4e\x14\x02\x78\x02\xc0\xe4\xcc\x03\x56\x7c\xeb\x6e\xb2\x74\xf3\xc3\xfd\x86\xe6\x62\x9b\xf8\xd6\x5d\xc6\x09\xa7\x99\xa8\x2f\x27\xbf\x28\xd8\x53\xc2\x9c\x7e\xef\xc2\xc7\xc0\x44\xb0\x37\xae\x4e\x8d\x33\xfa\xb8\x79\x78\xb4\x69\x09\x08\x62\x6b\x61\xf4\xc1\xd1\x4a\x11\x70\x08\x89\xb1\x2b\x81\xb8\x4a\x0c\x45\x62\x28\x4f\x4b\x36\xa1\xd4\xa7\xc0\xa2\x76\x5e\x52\x04\x39\x44\x15\x25\x87\xa5\x3a\x66\x48\xaf\xb3\x70\xb3\xba\xaf\xab\xd4\x76\x85\xd4\xa8\xd9\xc7\x03\x56\x9f\xc4\x46\x24\xdb\x97\x1b\x87\x6c\x4b\xf0\x56\xaa\x5e\x75\x20\xa0\x6b\x45\x73\x0c\x6b\xf2\xd2\x59\x60\xb8\x21\x89\x20\x39\xd7\x84\x52\x27\xc2\x70\x4f\x0c\x67\xb4\xb3\x6a\x0e\x6e\x40\xd9\xba\xc4\x29\x0b\x50\xc2\x33\x04\xaa\xa5\x60\xeb\xdc\xc0\x35\xc4\x4a\xdd\x91\xc5\x11\xcd\x05\xb0\x74\xeb\xc1\x1a\xc4\x2c\xca\xa8\x7c\x15\x46\xe9\x6d\x1e\x7c\x05\x55\x37\x82\xef\x9c\x35\x6c\x30\x98\x05\x74\x2d\x72\x6d\x68\xf0\x35\xf0\x2c\x64\x79\x2c\x9a\xcb\x03\x4e\xdd\x77\xdf\xc3\xc7\xe7\x62\x3f\x08\x18\x75\xdf\x15\xb0\xc2\x70\x75\xbc\xa6\x6e\xad\x35\x75\xf5\x85\x3f\xbd\xea\xfa\x81\x87\xe1\x8e\xf8\x97\x77\x7f\xb9\xba\xbc\xeb\x74\xf0\xed\xec\xae\xeb\xdb\xab\xeb\xae\x5c\x5d\xb7\x4d\xb4\x88\x5b\xfa\x34\xc3\x2f\xe2\x02\xc3\x3d\x2e\x1c\x5c\x80\xc0\xbe\x4f\x58\x1a\xde\x5d\x48\x53\xc3\x10\xde\x7d\xaf\x2e\x62\x34\x98\x1c\xee\x68\x98\xd3\xe7\xec\xd5\x96\x07\x68\xb1\xbd\x8a\x17\xdd\x2b\xfa\x31\xa6\x99\xe3\xb9\x03\x73\x7c\x0e\x2d\x1f\x23\x10\x19\x9b\xb2\x79\xc7\xd9\x9e\xb3\x13\x95\xf9\x2a\x4f\xbe\x0a\xb3\xcd\xc9\xf6\x46\x32\x53\x01\x21\xd9\xe5\xab\x34\xe3\x34\xe7\x81\x3f\xf4\x40\x7d\x64\x41\xcf\xd3\xe1\xa0\x27\x62\x79\xc8\xa2\x30\x8b\xe4\x69\xcb\x22\x5d\x6f\x12\x7a\x17\xf4\xc7\x43\xa0\x8c\x53\x41\x76\xde\x2c\x32\x4a\x59\xd0\xeb\x0d\x21\xa1\xe1\x4d\x15\xe3\x5f\x0c\xad\xe3\xd6\xb8\x49\xe9\x69\xe9\xe0\x29\x06\xb4\xce\x4b\x89\x3c\x91\x90\x13\x98\x93\x42\xb4\xcd\x94\x49\x4f\x08\x8b\x8c\x86\x9c\x1e\xda\x95\xfd\xe1\xc5\x3f\x43\x61\x22\x04\x92\x3f\x7c\x7e\xb5\x2b\x80\x11\xee\x9a\x1e\xda\x2a\x79\x36\x0d\xdd\x12\x78\x0c\x72\xc2\x5d\x35\xa2\xba\x66\x3e\x75\x2b\x0c\xc9\x61\x21\x2a\xa3\x49\x78\x5f\x57\xcc\x7b\xc1\xa2\xd2\x2c\x66\x8a\x8d\x9f\x21\xd3\x2a\x02\xa4\x6a\x46\x80\x64\x61\x41\x03\x0e\xb8\x08\x8a\xa7\x34\x10\xc2\xc2\x29\x0e\xde\xd2\x44\x03\xb2\xf4\x2e\x47\x9b\x4b\x32\x4d\x82\xd8\x49\x70\x2d\xd7\xf6\xe1\x32\xd1\x34\x0a\x62\x27\xc2\xd8\xba\x6a\x82\x70\x01\xd7\x94\x3f\xd9\xf2\x54\x29\xa7\xbf\x32\xd3\x7c\xb0\xbd\x9d\x95\xdb\x99\x67\xae\xa3\x9c\xf7\x47\x97\x0d\xc7\x38\xde\xe7\xce\xa0\xe3\x0f\x3f\x2f\x4d\xd6\xb9\x54\x34\x77\xf8\xf9\x10\xe3\xa2\x28\x60\x38\x1c\x3d\xce\x7c\xf8\x86\x59\x6b\x59\x99\x0a\xa7\xe5\xaa\x96\xe6\xc3\xbd\x8b\x01\x86\xb8\x12\x8e\x99\x33\x19\x8d\x2f\x30\x86\x84\x30\x97\x39\x31\x86\xbc\xe9\x2c\xe7\xd1\xb7\x2a\x1f\xba\x48\xd9\x64\xb1\xf9\xbf\x7a\x0d\x52\x6f\xbd\x5b\x62\x73\x87\x68\xcb\x14\x27\x10\x55\xed\xdd\xc6\x2c\x4a\x6f\xa7\x56\x52\x90\x3b\x2a\x12\xe3\x76\xfb\x53\xc5\xa3\x74\x21\xd7\xd6\x41\x05\x26\x5a\x54\x71\x41\x08\x31\xdf\x2e\x4b\x23\x2a\x18\x89\x4b\x63\xa2\xd7\xf7\x07\x03\x0c\x11\x61\x8e\x3f\xee\xf9\x18\x96\x62\xaa\xfa\xbd\x11\x86\x8d\x48\xed\x8f\x46\x18\x56\x64\x57\xd8\xe0\xa8\x68\xd4\x5a\x63\x9c\x92\x08\x6a\x97\x9c\x8f\x39\xab\x23\x46\xbd\xba\xc2\x4c\xe5\x22\x5b\x63\xc5\x59\x5a\x4d\x9d\x11\xb2\x3a\xe4\x32\x77\x45\x79\x4f\x99\xa9\x7b\xca\x7c\xc6\xe6\x64\xed\x08\x29\xa1\x92\x3b\x2a\x96\xf7\xa6\x34\xbd\x35\x04\x82\xb6\xdb\x0e\x25\x68\xcb\x58\xb8\xa6\x11\x2a\x31\xd7\xfd\x2d\xcf\x21\x25\x6b\xdb\x2e\xdb\xdd\x24\xdb\xeb\x98\xe5\x6e\xca\x9e\x4a\x62\xfa\x7a\x9b\x50\xc9\x66\x33\xbc\xdf\x3b\x74\xe6\xcd\x41\x8c\x5f\x1d\x78\x5e\x1f\x88\x50\x95\x09\x3f\x42\x86\xb3\x2d\x2f\xbc\xa1\xb3\x78\xbd\x49\x33\x1e\x32\x79\xbf\x9a\x4a\xfe\x56\x70\xbd\xed\xb6\xc3\x3a\x84\x63\x60\x1d\x1d\xab\x59\xfc\x02\xee\x8f\x65\xb4\x8a\xf9\x6a\xb7\x1d\x4e\xce\x7c\x0c\x67\x27\x21\x7d\x69\x7a\xd3\x30\x1f\x82\x65\x2e\x2f\x1d\xfc\x8b\x9d\x55\x17\xa6\x58\x87\x5c\x3b\x22\x49\x92\x37\x75\xc7\x81\x89\x28\x90\xe9\xe5\xe4\xec\xf7\x47\xd5\x55\xb7\xd5\xe6\xfb\xbd\xac\xb1\x65\x65\xc1\xc0\xac\xbd\xf1\xaa\xbe\x8e\xcf\x7c\x79\xf3\x47\xb9\x3e\x98\xee\x92\x98\x51\xc9\xb0\x05\x08\x49\x7e\x8a\x06\x08\x15\x81\x1d\xff\x2b\x2b\x53\x5a\xc8\x92\xd7\x6f\x4f\xce\x1a\x57\x83\x15\xdd\x6a\x95\xfa\x1e\xd6\xa1\x55\xd9\xbb\x23\x34\x93\xa0\x21\xbb\x92\x32\x2a\xa0\x9f\x95\x92\x73\xa6\x2f\xee\x31\x29\xe0\x33\xc1\x36\x5b\xd7\x1c\xbc\x20\x85\x98\x70\x77\x19\x26\xc9\x55\xb8\xf8\x90\x5f\x9e\x29\x19\x47\x8d\xb3\xdd\x76\x42\xd2\xf5\xcf\x3d\x55\x7b\x42\xae\xa4\x81\x01\x49\xdc\x72\x9c\xb0\x25\x89\xe4\xa5\xe5\xe2\xa3\xed\x76\xd8\xe9\x40\x8c\x8f\x26\x3e\xae\x66\x7d\x41\xbc\xcb\xc5\x5f\x8c\xc5\xfd\xe5\xa2\xd3\x51\x1c\x43\x44\xe2\xd9\x62\x5e\x2e\xbc\xa5\x58\x78\x91\x4a\xda\x90\x68\xb6\x9c\x5f\x8a\x35\x70\x46\x36\xed\xb6\x93\x89\xff\x77\x48\x8e\x21\xeb\x90\x5b\x67\xd9\x41\x01\xea\x6c\x3b\xf7\xce\x06\x77\xd0\x25\x82\x50\xec\x2d\x12\x35\x4c\x75\x2b\x51\x5d\xac\xaa\x5b\x93\x78\xb6\x32\xd5\xad\x8f\xab\x5b\x95\xd5\xad\xab\xea\x4c\x45\x37\xa2\x22\x6d\x1a\x70\x4d\xf8\xec\xc6\x54\x74\x2d\xa8\xbd\x01\xa4\x40\xb8\x9b\xe3\x9a\x6f\xca\x9a\xaf\xab\x9a\x35\x17\x91\xed\xf7\xf2\x28\x3d\xbd\x7d\xb6\xde\xf0\x7b\xdc\x6e\xd3\xa9\x2a\x4f\x10\xea\xe4\x9d\xac\x93\x63\xb8\x75\x10\xea\xd0\xce\xb6\x83\x76\xa8\x93\x41\xb7\x1b\xe2\xce\xad\x83\x0a\x59\x53\x90\x49\x02\xf1\x8c\x9c\x3b\xb3\xd9\xaf\x73\xf7\x4f\x9f\x7f\xf6\xc5\x5f\x3a\xff\x1f\xd9\xff\x33\x70\x30\xa0\x3f\xff\xbf\xbf\xe6\x73\x7c\x7e\x0d\x1f\x88\x45\xcb\x4b\x3a\xfa\xf4\xcd\x9b\x76\xfb\xe9\x9b\x37\x2e\x95\x16\xda\xf0\xa6\xe9\x66\xff\x87\xe9\x07\x87\xe2\x80\xba\x19\xdd\x24\xe1\x82\x3a\xcf\x00\xfd\xfa\xeb\x67\xfe\xc1\x01\x39\xae\x3c\x1a\x50\x83\xb3\x7c\x15\xe7\xd2\xa2\x8b\xa0\x9c\xdf\x27\x14\x81\x8c\x89\xf3\xef\xb3\x74\x41\xf3\x9c\x46\xe4\xcc\x2f\xc9\x64\xbe\xa2\x94\x8b\x0d\xde\x7d\x4d\x59\x44\x33\x9a\x5d\xca\xec\x1f\xe8\x3d\xa1\xaa\x64\x2a\x4f\x82\x73\xc2\xd4\xa7\xac\x94\x70\xc8\xa6\xf2\x33\xd3\xc5\x48\x56\x06\x83\x54\x50\xaf\x5a\xa2\x10\x61\xd2\x52\xbf\x41\x2d\xb7\x13\x42\x94\x22\x0d\x9a\xa0\x8a\x14\x96\xda\xa9\xb2\xf5\x19\x9d\xeb\x01\x9c\x9d\x49\xf7\x10\xcb\x34\x53\x2b\xe3\x2c\x6b\xb7\x6b\xf9\x0e\x2b\xd0\xeb\x94\x5f\x32\x4d\x6c\x98\xe8\x81\x80\xcb\x7e\xef\xa4\xc4\x1e\xb0\xd8\x42\xec\x2d\x63\x15\xb2\x6b\xfa\x36\x4c\xb6\xd4\xe1\xa0\x60\x83\x8d\xab\x0e\xb5\x6d\xa6\xfb\xbd\xac\x53\xac\x76\x2a\xf1\xb7\xec\x8a\xe8\x5c\xd8\x6e\x9f\xc5\xed\xf6\x59\x76\xd4\xa1\x84\x84\xed\x76\x2c\xf2\x24\xd3\x88\x26\x94\xd3\xfa\x68\x83\xfa\x98\x52\xb0\xa0\x1b\x5e\x25\x54\x0f\xda\x80\xdb\xd4\x9f\xd4\xa7\xc8\xcd\xe8\x3a\xbd\xa9\xb4\x17\x07\x95\x00\xc5\x41\x3d\x7f\x4e\xf9\xe9\xcc\x90\x62\x28\x07\x90\xd7\x21\x27\xb1\xaa\xbc\x99\xd8\x6e\xe7\x6e\xc8\x79\xb8\x58\xd1\x48\x16\x29\x80\x16\x0e\x86\x77\x35\xcc\xb7\x7c\x73\xd8\xb6\xa9\x97\x29\xa1\xca\x19\x89\x28\xa9\xcd\x56\xf7\xfb\xb2\xe5\x90\x88\x7e\x26\x54\xf0\x18\x10\x8b\x8f\x45\xba\xa1\x11\x24\x22\x28\x91\x3b\x27\x99\x7b\x4d\x99\x60\x2e\xe9\xf3\xc8\xf4\x2a\x9c\xa6\x65\x39\x69\x25\x16\x06\x67\xfe\x19\x21\x71\xbb\xed\xa4\x6e\x1c\x91\xdc\x71\x3c\x58\x6a\x53\x06\xf9\x9b\x0a\x16\x17\xc3\x41\x39\xe4\xa2\xce\x1b\x59\x04\x63\x48\x0b\xc7\x83\x48\x49\x29\xda\x8f\x8b\x10\x92\x4a\x74\x2f\xb7\x1b\x37\xdc\x6c\x92\xfb\x1f\xd2\x06\x7b\xc2\xda\x1c\x08\x9c\x28\x0d\xa4\xd4\xd2\x4e\xbf\x7d\xf3\xea\xa5\x83\x4b\x0a\x9e\x09\x4c\x63\x98\xd7\xa6\x8b\x42\x06\x6c\x96\xcd\xcb\x35\xa7\xe0\xce\x74\x71\x72\x24\x46\x5a\xbc\x18\xaf\xa3\x6e\xad\x75\x85\x83\x7c\x7e\x79\xc4\x1f\x32\x65\x0f\xcc\x0e\x14\xf0\x0c\x0b\x0e\x4d\xa4\x88\x70\x45\x02\x54\x5f\xde\x48\x69\xe9\x14\x10\x6a\xe8\x24\xa4\xcd\x76\x9b\x97\x91\x49\xcc\x3e\x4c\x8d\x4c\xb8\x2b\x80\xc2\xae\xa2\xea\xc1\x99\x57\xe0\xf2\xa2\x5f\xeb\x4e\xa1\xaf\x3d\x6f\x16\x31\x03\x86\xe5\x2d\x9b\x85\x96\x2e\x77\x1f\xe8\x7d\x80\x4c\x66\x04\xb9\xad\xdb\xd3\x87\x51\x67\x84\x1c\x55\xa9\x69\x6f\x0d\x3b\x0c\xab\x5b\x9b\x54\x60\xe4\x60\x39\x09\x72\x24\x79\x3e\x31\x89\x6f\x74\x05\x0e\x03\x2a\x50\xdd\x6c\x02\x92\x5d\x65\x9a\xf0\x14\x52\x84\x6c\xd0\x39\x1e\xf5\xa1\x28\xe6\x18\x78\xe1\x3c\xc5\xf0\x3d\xd9\xd9\xbc\x6f\x70\x48\x77\xcd\x71\xa4\xbc\x7f\x3d\xf3\xe6\x62\xab\xdc\x84\x19\x65\xbc\xdd\x46\x1f\xe8\xfd\x32\x0b\xd7\x34\x47\x8a\x6c\xca\x78\x75\xbd\x5d\x90\xbf\x40\xd0\xf8\x77\xba\xa6\xa2\x80\xd7\x64\xa7\x78\xa1\xc0\x87\xc5\x2a\x4e\xa2\x8c\x32\x31\x2d\xf0\x8a\x9c\xff\xd5\x99\xfd\x7a\xdb\x9d\x77\xf0\x39\xfc\xf0\xe8\xdd\x6c\x91\xb2\x48\x2a\xcf\xc2\xa4\x71\x4f\x83\x6a\xe3\x2a\xdd\x28\x28\x67\x15\xaf\xaa\xc5\x12\x96\xb8\x1d\x72\x92\x4e\xd3\x99\x3f\x0f\xd0\x96\x7d\x60\xe9\x2d\xd3\xb5\xfe\xbe\xa5\xd9\xbd\x90\x64\xc3\xb5\x90\x83\xfe\x8a\x3a\x3a\x7f\xe3\x76\x98\x6d\x13\x9a\xcb\xfd\x8d\x52\xc7\x42\x47\x06\x3b\x05\x21\x49\x53\x0b\x8c\x81\xe3\xaa\x80\x1b\x46\x91\x13\x82\x3c\x82\xb8\xb4\xa2\xf5\x5e\xe4\xe0\xa2\x32\x7a\x3f\x20\x1d\xd2\x01\x93\x98\xbd\x46\x87\x43\x55\x55\xca\x95\x54\x01\xa5\x93\x85\x4f\xe4\xaf\x6e\x6f\x8a\x32\x61\x14\x1d\xb4\x61\xdd\x79\x24\x07\x03\x51\x69\xa5\x9c\x35\x75\x1e\xd8\x46\xf5\x8c\x49\x5c\xce\x30\x64\xca\x63\x94\x68\xb2\x99\x1a\xd4\x05\xbd\xd7\xc6\x2d\x87\x90\x1b\x2a\xf6\xb8\xf2\xcf\x45\x35\x03\x2e\xed\x97\x55\x90\xbc\xd6\x01\x0c\x26\x8f\xc1\x47\x99\xcb\x7c\x90\xd7\x65\x10\x83\x16\x44\xca\x08\x1b\x5e\x12\x41\x3a\xa8\xb5\x2b\xd0\xa5\x45\x1a\x15\x3c\xcc\x28\xaa\x63\x87\x16\x9b\xd6\x8b\xa1\x0e\xef\xb0\x0e\xef\xa0\x02\x09\x71\x46\x6d\x86\x2f\xc9\xb9\xb2\x02\xd8\xff\x35\xdf\x6e\xa4\x57\xa4\x5f\xf3\xce\x39\xbc\x7f\xd4\x92\x6d\xbd\x74\x39\xcd\xc5\x84\x4f\x05\x2a\xea\x0b\x1e\x1a\xb6\x05\xbc\x38\xb5\x16\x9f\x93\xf3\xbf\x96\xeb\xfa\xd7\xbc\x53\xad\xcb\x27\x8f\x5e\x97\x15\x5d\x00\xb3\xb0\xd0\x5f\x0f\x23\x1b\xd8\xcf\x6a\x7d\x3e\xc7\x97\x69\xbb\x2d\xd6\xa2\x82\x94\x58\x79\x44\x2e\xcd\xea\x13\xb1\x54\xfc\xa2\x6a\x95\x97\x5d\xe8\xa0\xae\x5e\xa3\x22\xc7\xc1\x2a\x35\x0c\x9a\xe1\x0b\xe2\x92\xe9\x4d\x08\xb3\xf9\x02\x43\x21\xf2\x92\x42\xc4\xa2\xab\xf2\xb0\xa3\xac\x3c\x78\xe3\x68\x46\x24\xc6\xf8\xdf\x26\x00\x39\xf0\x59\x3e\x87\x87\x0a\x35\x13\x87\x06\x3e\xfa\x31\xab\xe7\xc5\x1f\x59\x3d\x2f\x1e\xb9\x7a\x5e\x3c\x72\xf5\x84\xbc\x83\x5a\x7a\xbe\xe2\xe8\x5f\x59\x46\x52\x06\x47\x7a\xf5\x60\x38\x51\x1b\xea\x30\xb1\xb2\xf4\xb2\xfa\xee\x00\xc1\xcf\xe1\x23\x39\xff\xf5\xb3\x12\xcf\xaf\xe1\xab\xc6\x63\xf7\xe3\x83\xc5\x69\x25\x8c\x7d\x04\xfb\x34\xa5\x5a\x84\x52\x89\xc5\xa7\x7c\xc6\xe6\xca\xcb\x0d\x2d\xe0\xeb\x13\x24\x54\xb0\x44\x90\x92\xaf\x9c\x4c\x90\xce\x54\xdd\xdd\x57\x8c\x52\x8a\x0b\xf8\xf2\x71\x3b\xf5\x51\x2f\xdb\xed\xef\x6a\x94\xe0\x49\x8d\x12\x40\x49\x7f\xdf\x08\xc6\xe7\x74\xad\x42\x6e\x14\xa2\x93\xf6\x08\xc2\xa6\x0e\x0a\x59\xac\xdc\x51\x76\xe5\x3a\x8c\xa5\xbe\xe6\x6b\x87\xc2\x61\x0a\x30\xb7\x84\x38\xb6\x52\x1b\x8b\x1c\xe4\xa6\x12\x66\x35\x61\xeb\xa8\x93\x46\x74\xad\x0b\x1b\x52\xf8\xab\x74\x63\xf9\x6d\xac\xdc\x54\xed\xe4\x0d\x85\xaa\xbd\xa0\xfe\xad\xba\x1c\xe8\x72\x5f\x09\xbe\xd9\xea\xcf\xa5\xb9\x79\x58\x9d\xe7\x16\xf0\xdb\x29\xb1\xc5\xb2\xcf\x90\xdc\xbd\x22\x14\xe5\xa1\x89\x96\x5a\x2a\x1f\x0b\xa5\x9c\x00\xfc\x93\x0b\xf9\x7f\x8f\x29\xfe\x40\xef\x0f\x79\x61\xc5\x2c\xfe\xf4\xb8\x9d\xe7\x91\x1c\x22\xbd\x6d\xfd\x76\xb0\x2b\x7d\xf6\xe8\x2d\x66\x99\x32\xde\x5d\x86\x0b\x6a\x6f\x31\x87\x91\x27\xb9\xc1\xba\xde\xa2\xbe\x3d\x3c\x9e\x94\x9e\x20\x9c\x07\x16\x2b\x95\xd4\xd4\xac\x7b\x2c\xd3\x8d\x5e\x4e\xeb\x22\xf5\x64\x84\xb6\x5c\x22\x4d\x43\xec\xcf\x8e\x3f\x37\xfa\xe4\x4a\x8f\x5c\x9f\xcd\x5a\x05\xd2\xd1\x85\x24\x83\x3f\x92\xf3\x0a\x5e\xe7\xf0\xf6\x71\x53\xfb\x63\x8d\x94\x7c\x76\x30\x7d\xdf\x3c\x7a\xfa\x6e\x62\x7a\x2b\x38\x1a\x7b\xf6\x0e\xe2\xfe\x77\x27\xef\x41\x8c\x2f\x81\xf4\xfb\x23\xa5\xa3\xb2\xeb\xda\x1d\xec\x5f\xbb\xeb\xbc\x5b\x8b\x94\xf0\xfa\xe6\x00\x5e\x7f\x7f\xbc\xde\x2e\x5e\x6f\x4e\x28\xee\x8e\x20\x23\x7d\xb3\xfc\x71\xc8\x34\x63\xb0\xac\xd4\xc2\x60\x2e\x30\x58\xf9\x2e\xaa\xd2\x0d\x06\xb3\x4e\x07\xf3\x0e\x31\x1d\xab\xf6\x63\x99\x6b\xc6\xe6\x52\x03\x6b\xc7\x28\x3c\xe6\x1d\x22\xfd\x6f\x54\xe7\x3c\x36\x9b\x70\x5c\x93\xa8\x46\xcf\xd4\x3f\xc8\x0e\xfd\x75\xb1\x0a\xb3\x9c\x72\x14\x9c\x79\x80\xfe\xaa\x0e\x18\xf4\x87\x20\xea\x52\x5b\x8e\x24\x97\xfb\xb7\xc7\xa1\xbb\x54\xd9\xfd\x43\xce\xdd\xdf\x0f\xe6\xee\x17\x32\xfb\x1e\xde\xc3\x97\xf0\x13\xbc\x85\xdf\xe1\x6f\x73\xf8\x99\xec\x34\x3f\x26\x9b\xf8\x96\xec\xa4\x12\x52\xb4\x6f\xc7\x53\x7a\x6a\xd6\xf5\x8c\xaf\xc3\x0d\xd9\x15\x9a\x95\x0c\x6f\xcb\xb0\x14\xc7\xc8\x6c\xae\xbe\x16\xe9\x96\x71\x9a\x11\xaf\x3e\xcf\x1a\x07\x16\x49\x98\xe7\x34\x17\x1c\x97\x0a\x95\x58\xa2\xc8\x31\xa1\x55\xf8\x21\xc1\x32\x8c\xa2\x46\x6e\xa5\xae\x17\x85\x90\xa4\x9a\xb6\x43\x4c\xd2\x92\x9b\x4e\xe5\x99\x5b\x4e\xd2\x52\x95\x0c\x5b\x92\x5a\x2c\x36\x2c\x44\x6e\xc5\x86\x47\xa5\xb9\xcf\x4e\xf7\x39\xb0\x87\x02\x9a\x0b\x0e\x41\xd6\x1e\xc4\xf0\x5b\x9e\x07\x09\x98\x9a\x83\x1c\xaa\x7a\x83\x2d\xa8\x5a\x83\x05\x48\x26\x9d\x42\x39\xdc\xa0\x0e\x09\x30\x8a\x91\x40\xb1\xc6\x05\x30\x0c\x4b\x42\x2f\x2b\x75\x6d\x16\xde\xb6\xdb\xce\x92\x08\xb1\x22\xd2\xf8\xa7\xc1\xdf\xe9\xe0\x72\xa2\x66\xcb\x39\xe1\xb0\x2c\x8b\xe9\x8e\xb7\xdb\x4e\x54\x6a\x5f\xb4\x6e\xd0\x4e\x9f\x2d\xe7\x5a\x69\xbc\x21\x37\xce\x12\x38\x44\xf2\xac\xf4\xac\xee\xee\x5a\xab\x87\xae\xe3\x9c\xd3\xcc\xd9\xa8\x12\xab\xea\x4c\x29\x52\xf8\x31\xad\x50\x45\xaf\xc6\x40\xa7\x5c\xda\x6b\x49\x65\xc8\x37\x49\xbc\xa0\xce\x0a\x3c\xd8\x60\xd8\x08\x91\xfb\x9a\x36\xbb\x2d\xd6\x88\x39\xa3\x73\x91\x4b\xa9\x8d\x6b\x19\x65\x8e\x2d\x2b\x7b\x48\x31\xd8\x7a\x6b\x01\x1f\x89\x73\x73\x38\xee\x80\x15\x53\xe9\x1c\xc0\x7f\x94\xaa\xe2\xb0\x58\xa1\x58\x27\xb1\xdc\x8e\x55\x9a\xa7\xb4\x10\x97\x76\x9f\x64\x97\x3c\xec\x2e\xd3\xec\x59\xb8\x58\x39\xb4\xae\xa3\x00\xd5\x86\x19\xe8\x31\x10\x24\x98\xe4\x50\x09\x05\x81\x45\x39\x0f\xd9\x42\xf0\xe2\xef\xb4\x1e\x44\xe5\x30\x38\x21\xb3\xb9\x71\x64\x8e\x48\x0c\x5e\x98\x3a\xa4\x1e\x39\xa8\x55\xf4\x44\xab\xf7\x4b\x2c\x36\x65\xcb\x88\x19\x95\xd2\xa9\x2e\x2e\x3a\x5c\xcd\x4d\xad\xcb\xf6\x24\x55\x3d\x3f\xea\xf7\x71\xb6\xb2\xfb\xb5\x79\xae\x77\xfe\xb8\xdb\x76\xde\xa3\xce\xca\x6e\x6e\xa2\x90\xd3\xa3\xa9\x13\xa4\xe7\xb2\xc1\xbc\xf3\xb1\x37\xf3\xf0\xd4\x39\x36\x8c\x3a\x75\x8b\xef\xd8\x02\xea\xd4\xcd\xbd\xe3\xeb\xfa\x27\x6e\xeb\xe1\xc0\x69\xaa\xb5\xb9\xfd\xa6\x5a\x9b\xdb\xa7\xf2\x9c\x49\x48\x49\x6a\xfd\x49\xe0\xbd\x62\xd4\xc2\xb3\xb9\x52\xc5\xd5\xce\x64\x2d\xd6\xd3\x26\x15\x92\xf5\x6c\xaa\x48\x66\x9a\x65\xaa\xaa\x6a\x96\x5e\x31\x6b\xa2\xcc\x11\x8d\x21\x48\xea\x00\xf5\x67\xe3\xc0\xf6\x68\xbf\xb0\x96\x5f\xb5\x69\xc8\xc3\x0d\x25\xf0\xdb\x88\x43\xb1\x8e\xd4\x0d\x4b\x8f\xab\x72\x48\x3b\x75\x58\xc6\xad\x33\x35\x37\x65\x3f\x9a\x5c\x1c\x62\xc8\x30\x64\x86\x24\xb4\xdb\x49\xbb\x9d\x48\x47\xb3\xfa\x24\xa3\xa6\xe4\x09\xdd\xba\x38\xec\xe8\x6c\xa2\x1e\x21\x93\x59\xa7\x1f\x5b\x53\xc5\x2c\x9f\x5f\x6e\xcf\x08\x49\x66\xf9\x5c\x08\x5e\x9b\x2c\xdd\x38\x39\x6c\xe1\xdb\xea\xe8\x7a\x21\x2a\x4f\xcc\x69\xbb\x29\xb8\x98\xc3\x92\x24\xb3\x85\x3a\xc7\x26\x24\x6a\xb7\xa3\x33\x42\x96\x65\x2d\x0b\xa9\x60\x11\x15\x09\x29\xf3\x84\x3e\xf4\x80\x23\x6b\x90\x08\xcb\x43\x51\x5b\x26\x84\xf4\x40\x74\x81\x90\x78\x97\x61\x03\x52\x84\xc6\x4e\x20\x26\x16\x32\x84\xf3\x9a\x46\xc6\x89\xf7\xfb\x0c\x0b\x32\xa4\xf8\xb8\x14\x03\xef\x90\xb8\x3a\x6c\xd2\x7c\x1a\x3f\xc9\xfd\xd4\x6c\x33\x2c\x9d\xbc\x3a\x25\x2c\x19\xdd\x88\x6e\x92\xf4\xde\x8a\x30\xac\x8e\x61\x93\x2a\x1e\xc7\xc4\x18\xde\xc8\x92\x82\x39\xec\x14\x1b\x21\x05\x72\x4b\xc1\x06\x8d\xbc\xc7\x29\xe6\xa1\x10\x48\x61\x38\x90\xc6\x23\xee\x2a\x59\x26\x36\xaa\x08\xed\x4e\x96\x4b\xb9\xd2\x09\x32\x50\xc6\x4f\xff\xea\xa1\x80\x02\x1d\x39\x71\x1e\x64\x00\xbb\xdf\xd7\x7b\x7d\x70\x70\xac\xf3\x39\xa5\x72\xcd\x4c\x87\x57\x9f\x0e\xa5\xc9\xd0\x9f\x8e\x1e\xa6\xc0\xd9\x88\x3e\xa6\x17\xd3\x87\x3b\xa1\x2a\x39\xee\x84\x42\x01\x75\x48\xfd\xc8\x33\x8a\xdf\xb7\x74\x4b\x2f\x6b\xf5\xb4\xdb\x67\xe5\xe4\xc9\x64\x32\x9b\xd7\xc8\xd6\xa9\x73\x8d\xf4\xd1\xe7\x1a\xe9\x41\xd7\xa7\x35\xe0\x4d\x9d\x6c\x9a\x29\x67\xc6\xa9\xd8\x28\xd4\x2a\xcb\x69\xc6\x6b\x85\x65\xdf\x6a\x1d\x2d\x79\x94\x83\x22\x0a\x2c\x56\x29\xcd\x27\x62\x0c\x29\x0e\x52\xdd\x84\xbd\x94\x52\x5c\x1d\xbb\x54\xf5\x1c\x33\x37\xa7\x66\xc8\xea\x6e\xed\xb8\xe8\xf0\x59\x15\xa5\xfd\x98\xcd\xeb\x67\xd5\xb4\x26\x55\xe8\xa2\x4e\x06\xd2\xda\x8c\xcb\xb3\x00\x66\xe0\x53\x54\xf6\x72\xff\xfa\xc1\x97\x62\x3f\x8e\x8a\x68\xfa\x59\x1a\x64\x56\x1a\xde\xe0\xa8\x1a\x3d\xf9\x67\xce\x19\xd7\x48\x6f\xe1\x11\xb7\x4e\x70\x71\x49\x10\x64\x69\xc5\x33\x3b\x1c\xc3\x99\x73\x50\x8c\x3f\x60\xb8\xa1\xdb\xb0\x96\x82\x19\x81\x53\x6b\xec\x0f\x9f\xeb\x29\x2c\x38\xb5\x40\x4f\xaf\x48\xb5\xd0\x0f\x89\xb2\x57\x2e\xfc\x13\x8c\x9c\x31\xdd\xa6\xd6\xd2\xc2\x3a\xb3\x56\x92\x52\x4b\x43\x7a\x50\x5d\x8d\xe3\xa8\xcb\xea\xd6\x00\x2b\xee\x45\x65\x29\x2b\x79\x48\x15\x64\x95\xb7\x36\x36\xbd\x6d\xb1\x53\xdb\x96\x5e\x16\x7a\xd5\x93\x5d\x2c\xa4\x42\x16\x26\xc1\x6c\x0e\xf4\xae\x0c\x1b\x71\x5e\x72\xe0\xd9\x3d\xd9\x15\x0f\x51\x6e\x5b\x35\x71\x34\xdc\x06\x1e\xce\x54\x5b\x2b\x68\xf3\x74\xf6\xea\x6a\xcc\x3c\xcb\xe6\x86\xb6\xc5\x4b\x27\x35\x92\x67\x5a\x58\x22\xa8\x00\x60\x8d\xaa\x1d\xaa\x8d\xce\xa8\xad\x9a\xb2\x39\x13\x7a\xa4\xa3\x2e\x15\x47\x56\x77\xac\xaa\x6b\x9a\xa4\xd3\xd9\x66\x4c\x76\x1b\x5f\x52\xc5\x52\x69\x2c\x3d\x60\xe2\xa8\x51\xeb\x01\xc7\x40\xeb\xea\x33\xaf\xa8\x0d\x4b\x16\xf8\x17\x41\x6e\x17\xad\x31\xd2\x46\x47\xf9\x40\x7e\x01\xf7\x8a\xc7\x54\xbc\x75\x95\x43\xc0\xea\x04\xaf\xe7\x5d\xf2\x93\x1d\x11\xc5\x4c\x47\xf8\x69\x00\xca\x7c\x33\x3e\xd7\x74\xc0\x70\xcd\x47\xce\x76\xaa\x66\x53\xe2\x5d\xa6\x47\xcd\xaa\x62\xa6\xc1\xb4\xa1\x41\x95\x63\x96\xce\xcb\x2a\x55\x83\xd6\x99\xce\x03\x30\xa7\xd0\xdc\xae\x55\xda\x6e\x3c\x3b\x46\xf3\x2a\xa3\xe8\x43\x56\xb7\x4d\x90\xc4\x25\xa7\x87\xfb\x54\xdd\xee\x7a\x27\x77\xd1\x00\x99\x25\x8d\x0a\x6c\x9f\x50\xea\xe5\x3f\xe3\x6a\xb7\x9d\x5f\x76\x95\x21\x61\x45\x69\xdb\x6d\x47\xef\x60\x14\x1f\xd0\x82\xd9\xbc\x74\x31\x6e\xd5\xe5\x9a\xa6\xa0\x16\x6b\xe8\x4b\xe3\x8d\xd2\x23\x0e\x1a\x2b\x23\xfa\x76\x5b\xac\x14\xf3\x5a\x82\x65\x48\x2f\x6f\x99\xd6\x14\xa1\xb3\x39\xd4\x56\x58\x2d\x42\x1d\x11\xd6\x62\x24\x13\x2d\x63\xec\x03\x3a\x19\xa1\x66\x5d\x10\x3f\x6c\xc8\x68\xf6\x09\x32\x6a\xc1\xe4\xf1\x5a\xc9\x03\x2b\x39\x55\x83\x7c\xab\xc4\x10\x1d\xa5\xff\x32\x57\xae\xb9\x35\x2d\x38\x5e\x3a\x72\x96\x35\x06\xed\xf7\xec\x0b\x4b\xca\xc1\xdc\xcc\x59\xa3\xfc\x6c\xaf\x76\x21\xb8\xce\xb2\x79\xbd\xcd\x2f\xca\x83\x6e\x89\x4f\xdc\x28\xbc\x32\xf0\x4a\x35\x52\x6e\xaf\xf1\x06\x38\x34\xab\xdb\x1a\x86\x6c\x0d\xeb\xb2\x9e\x60\xd4\x6c\x5a\xa5\xf6\x09\x31\xb2\x32\x11\x98\xee\x8a\x80\xca\x3b\x5d\xa5\xb1\x66\x26\xa4\xa8\x8d\xb9\x74\x65\xa2\xd1\x1c\x4b\x79\x32\xab\xcb\x93\x08\x41\x4c\xbc\xcb\xf8\x60\xe9\x6a\xa8\xc5\x66\x63\x4a\xea\xe3\x98\xc5\xc6\xb0\x9b\xb5\xdb\x49\xd9\xf4\x19\x21\x6c\xbf\x77\xc2\x76\xdb\x09\xa5\x7c\x19\x76\x48\x52\x6d\xd5\x59\x65\x49\x18\x56\xb6\x7b\xd4\xd8\xee\x49\xd8\xa0\x13\x06\x72\x12\x03\x1a\xba\x38\xf5\x82\x7a\xcf\x9a\x32\x75\xfd\x83\x49\x97\xd6\x75\x12\xdd\x53\x2a\x45\xbc\x8c\x42\x48\x1b\x2d\xbf\xaf\x93\xf4\x2a\x4c\x7e\x58\xc5\xf9\xb4\x0a\x06\x4d\x39\xd5\xb5\xa1\x76\x5b\xfd\xba\x2f\x42\xbe\x22\x84\x88\x9f\xa9\x8a\x6a\x2c\x95\xd3\x64\xd9\x6e\x8b\xbf\xb5\x12\x22\x22\xf8\xda\x80\x01\x59\x0c\x10\xc2\x0e\x86\x98\x12\xd4\x5b\xfa\xe1\x62\x31\x5a\xf4\xc3\x91\x37\xba\xf2\x26\x3d\x3a\xa4\x74\x39\xa4\xc3\xc1\xc0\x1f\x2c\x97\x57\x48\xeb\x2c\x42\x3a\x8b\xa5\xf7\x0a\x15\x20\xe6\xc6\x02\xd5\x29\x9d\x0e\xe4\xf4\x21\x0b\x14\x73\x83\x42\x6c\x69\x47\xfe\x0d\xc4\xe6\xc3\x3b\xc4\x58\x07\x21\x24\x91\xaa\x24\xdd\xed\xb6\x93\x95\xb0\x97\xb2\xfa\xcb\x70\x4d\xbf\xcf\xe8\x32\xbe\x93\x57\x28\x4e\xa6\x2a\xd3\x95\x33\x2b\x83\x90\xdd\xa4\x0e\x36\x25\x06\xa3\x0e\xd2\x30\x16\xdc\xc3\x3a\x66\xf1\xf2\x7e\x8a\x50\xc7\x09\xf7\x7b\xb4\x40\xb8\x93\xd0\x4e\xda\xe1\x41\xd8\x61\xea\x8c\xaa\x8b\x44\x94\x93\x4e\x45\x28\x0d\x10\xc2\xca\x1e\xa9\x28\x60\xdb\xb0\x8a\x8f\x86\x5d\xb1\xa4\x42\x38\x27\x54\x8a\xd3\x45\x01\x8b\xc3\x4d\x8a\x67\xf7\x96\x81\x01\xe7\x59\x7c\xb5\xe5\x54\x52\xe9\x17\xe1\x66\xda\x10\x27\x65\x18\x8e\x03\xcd\x12\x89\x4f\x63\x20\xac\xed\xd8\x71\xb1\x90\x16\x58\xd6\x5d\xc8\xa2\x80\xe8\x78\x83\x16\x8d\x6b\xc3\x8b\xe3\x53\x6f\x69\xe3\x9b\x91\x7b\x87\xc1\x99\x87\xc1\xbe\x10\x24\x5f\x06\x63\xd5\xe2\xb1\x2e\x8a\xa9\x3e\xd5\x6c\xcc\x21\x03\x64\xdf\x14\x3a\xf3\x2e\x1f\x3b\xd4\x5c\x0c\x15\xb2\x6a\xb0\x07\x15\x1f\x8d\xf4\xcc\xd7\x14\xe4\xcc\x2b\x60\xd9\x04\xec\xc7\x36\xad\x84\x34\x1b\xd0\x87\x86\xf6\x56\xe3\x45\x01\x9b\xc3\xc6\x2a\x90\xd8\xa6\xc3\x1c\x0e\x22\x08\xe1\x05\xac\x28\xd9\xda\x7c\x40\x59\xba\xbc\x19\x28\xed\x0c\x4b\x1b\x62\xb4\xa2\x61\x84\x70\xa1\x4f\x9d\xd6\x47\xc5\xd5\x59\xc9\x89\xd2\x7f\x5e\x53\x1e\xce\x36\x7a\x20\x04\x2d\xf2\x4d\x97\xa5\x6c\x41\xd1\xfc\xcf\x15\x5f\x31\x95\xa8\xf5\xc4\x00\xc6\x91\xde\x79\xa9\x98\x41\xa5\x65\xc0\x18\x6e\x9a\x51\x0a\x55\x9a\x04\x69\x1e\x34\xa5\xb6\x6e\x41\x9e\xc0\xa2\x70\xb3\xa1\x2c\x2a\xb3\xb4\xdb\x52\x72\xd4\x51\x0d\x28\x5c\x4e\x6c\x8b\xba\x0b\xc5\xd7\xe4\x33\x36\x2f\xe0\xfa\x88\xed\x53\xde\x4e\xca\x5c\xe5\x0e\x6f\xed\xe2\x72\xb7\xd8\xef\xf9\x17\x4c\xbe\x22\x0b\xf7\x9f\x3a\xd0\x3d\x5c\x64\x64\x61\x6c\x18\xaa\x04\x12\x51\xc3\x16\xda\x88\x42\x96\x55\x56\x33\x05\x64\xa3\xe3\x56\x61\xfe\x5c\x82\x86\x6a\x55\x4b\xa9\x12\xd5\xbd\x27\x42\x08\x6d\xb7\x53\xaa\x74\x57\xc6\x74\x44\x8a\x15\x35\x33\x74\x19\x35\xad\x82\x86\xf2\x99\x2b\xdd\xd2\x0c\x15\x32\x19\xe2\x21\xa4\x84\xbb\x34\xa1\x02\x3b\x14\xa7\xa1\x3f\x48\x6a\xb9\xf5\x3c\xc2\x23\x75\x5d\xfd\x99\xca\xea\x68\x93\xb2\x0a\x65\xa4\x6b\xe5\xa7\x0a\x4d\xa4\x19\x80\x56\x18\x5b\xf5\x0b\x28\x58\x38\x15\x85\x3c\xec\xfe\x26\x7d\x40\x23\x0c\x4c\x0b\x7f\xcd\x79\xe5\x08\x10\x30\x0c\xd9\x83\xf9\x64\x9d\x62\x90\x08\x32\x73\x95\x67\x4d\x1d\x7c\x19\x3e\x58\x4c\xad\x00\x08\xff\x45\x85\xac\xbc\x31\x68\xd7\xaa\x34\xd1\x2f\xd3\xc8\x88\xb2\x72\x3a\xf0\xee\xac\x09\x4d\x8d\xa6\x2e\x4e\xd9\xf7\x69\xcc\x38\x64\x0d\x2c\x62\x4a\x4b\x86\x45\x1d\xae\x18\x9f\x00\xa6\x96\x53\x77\x5a\x85\x84\x5e\x93\xc3\x4b\x33\x45\x36\x17\x35\x65\x96\x02\x2b\x3b\x60\x7b\x35\x8b\x5d\x4f\xb0\xbb\xaa\xd9\x70\x3b\xaa\xbc\x38\x59\xd3\x39\xa8\x5b\x33\xe6\x71\xe4\x83\xeb\x4c\xc6\x32\xb6\x4a\x68\x00\x24\xb0\x34\xa2\x0d\x59\x0a\x59\xeb\xc9\xe1\x57\x57\x56\x2f\xd9\x17\x02\x18\xdd\xee\x63\x21\xf0\xc7\x07\x0a\xff\xf1\x51\xba\x8c\xde\xf1\x37\xf1\x55\x12\xb3\x6b\xa5\x73\xca\x08\x3d\xe8\x90\x1c\x4b\xbb\x7d\x64\x3a\x5a\x3e\x06\xd0\x2c\x27\xac\xa8\x83\x8d\x26\x47\x19\xf6\x8a\x8e\xe4\x0d\x28\x63\x27\x6b\xd8\x4d\x08\x21\x59\x79\x65\x5d\xc0\x4f\x84\x95\x30\xcf\xb3\x78\xed\x60\xc1\x21\x9e\x00\x55\x56\xd3\x52\x19\xf8\xa4\x47\xe0\x48\xeb\xa3\x2f\x37\x03\xfd\xde\xf6\x99\x7e\x1f\x2b\xd3\x05\xb1\x09\x68\xf8\x7c\x49\x97\x69\x46\xa5\x01\xa8\xa8\x0e\x97\xcf\xba\xb1\xa6\x37\xb5\xca\xc1\x18\xa8\x31\xcb\x2c\x46\xf4\x49\x90\x90\xf0\xb0\xea\x5a\x17\xb1\xba\x39\x2b\x00\xab\x37\xb4\xa7\x02\x6e\x0e\xc5\x85\x63\x93\x09\x38\xa6\xd4\x8a\x56\x51\xf2\x65\x9a\x26\x34\x64\x4e\x95\xc3\x26\x24\xa5\xa2\x56\x4b\x88\x87\x3b\x88\x7c\xef\xdc\x79\x78\x73\x29\x8f\x78\x8a\xe6\xe3\x1d\x41\x64\x2c\xca\x65\x19\x5e\x1c\x63\xed\xa5\xdc\xbb\xd5\x96\xa7\x86\x6a\x67\xc4\x0d\xe3\x94\x67\x97\xa5\xa5\x84\xb5\xcf\xd5\x5a\x38\xdc\x4a\x4c\x5f\x0f\x35\xdd\x56\xe7\xd4\xf1\xb3\x94\x49\xea\xb6\xb3\x07\x47\x2b\xb9\x43\xb5\xd2\x3a\x78\xb0\xc9\x4e\x65\x5e\xe7\xe0\x8e\xea\x44\xed\x6c\xe5\xf0\x64\xe4\x90\xf2\xd6\xce\x60\x4b\x3d\xa8\x7d\xce\xa2\x4f\x62\xd9\x1c\x18\x70\x7c\xf2\xe4\xe6\xf8\x02\xad\xb2\x9b\xaf\x6f\x67\x72\xb6\xc0\x8c\x6d\x57\xa9\xde\x94\xd9\x85\x7d\xd5\x8a\x54\x0f\x41\xd6\x0d\x7c\xf5\x6b\xc4\x3b\xb5\x6d\x5e\xcb\x03\x78\xbd\xd2\x08\x21\x4e\x4a\x6e\xe4\xc9\x7d\x05\x98\x5d\x75\xf5\xc4\x2f\xb0\x7c\xe9\xc3\x2c\x52\xa3\xc2\x58\x3e\xd5\x47\x68\x14\x42\x48\x6b\x97\x17\x6b\xb3\x92\xa9\x9e\x43\x8a\x21\x2d\xd4\x69\xb5\x3d\x03\xb2\x17\x71\x55\xbb\xd2\x3b\xe8\x2e\x42\xae\x7a\x16\x43\x52\x1e\xef\x08\xda\x90\x9f\x5e\x0c\x1e\x1c\xf7\x2f\x81\x1c\x43\xae\xd5\x3a\x26\xfe\x68\x22\xa8\x75\x6a\x43\x18\x54\xd8\xa6\x96\x85\x6d\xf6\xc0\xe9\x21\xa6\xcb\xfb\x94\x9f\x3e\xc9\x3a\x9e\x5a\x63\x19\x60\xe9\x88\xd4\x40\xe5\x23\x81\x4c\x5e\x34\xb4\x8e\x96\xf4\x99\x49\xc5\x07\x6b\x15\x12\x03\x5f\xc8\x60\x8f\x3a\x6c\x2a\xcb\xd6\xcf\x9b\xac\xab\x8b\x8d\xcc\xf7\xa7\xba\x79\x34\xb4\x47\xf7\xfb\x70\x01\x89\xe9\xc0\xd6\x29\x62\x7e\xea\x10\xac\xde\x9c\xa9\x5b\xeb\x34\xaf\x28\xf1\xe0\xf6\x53\x32\x40\x1c\x91\x2b\xda\xe9\x68\xa3\x57\x9a\xe5\x71\xca\x08\xf2\x3d\x77\xe2\x7a\xa8\xa6\xe2\x95\x2a\x23\x76\x70\x69\x69\x17\x47\xc1\x4e\xa9\x1e\xc4\x52\xd1\xae\x9f\xfe\x56\x19\x3c\xe6\xb4\xb2\x84\xdc\x4e\xef\xa9\x14\xb3\x40\x57\x59\x1d\x40\x55\x26\x92\x24\xa7\x8e\x55\x63\x75\x1f\x52\x9d\x2d\xfc\x72\x74\x80\x60\x34\xd0\xdb\x9c\x3a\xbf\xcc\xf8\x1c\x8c\x4e\xdc\xa8\xa4\x51\xa1\x77\x95\x9c\xf2\xed\xc6\xbc\x12\x71\x82\x17\x96\x79\x9a\x50\xe7\x58\x3d\x04\xd4\x3d\x1c\xae\xc1\x83\x52\xbb\x73\x90\x4e\x8e\x8b\xe0\x9a\x8d\x5d\xc9\xac\x45\x35\xab\x90\x7a\x12\x28\xd3\x3b\x70\x8e\x6b\xdb\xef\x65\x9a\xa9\xce\x02\xeb\x83\xfd\x3a\x6c\x1c\x1b\x3d\xd4\x21\x4b\x76\xd4\xcf\x3a\x53\x79\x98\x1d\x03\x32\xb3\xaf\x25\xe2\x7a\x71\x93\x48\x68\x19\x14\xf0\xd0\x53\xaa\x39\x84\x6d\x5e\xbb\xa5\x52\x26\x57\xc7\xa7\x6a\x38\x52\xcb\x71\x78\x36\xd5\x74\x66\x52\x9d\x91\x68\x0d\xbc\x61\x9a\xaa\x1b\xe2\x72\x23\x92\x2e\x51\xf4\x6e\x36\xf5\x02\x13\xec\xf8\xc6\x08\x43\x1a\xd2\x08\x0a\x5b\xb7\xe0\xf9\x2d\x57\xf6\x38\xb6\xe1\x2f\xb7\xe6\x42\x1f\x9d\x5b\xe6\xc6\x75\xa8\x05\x0f\x80\xb8\x5a\x4d\x8d\x80\x84\x58\x79\xe9\x2b\x2c\x67\xa8\xf6\x22\xa9\x1f\x90\x38\x72\x53\x2a\x15\xf9\x8d\x00\xb4\x74\x3e\xa5\xb5\x4b\x6a\x78\x23\x23\xbb\x57\x93\xf0\xc9\x3d\xbe\x9c\x03\x38\x76\x59\x03\xc7\x96\x0e\xb5\x0b\x79\x55\x13\xba\x3e\x79\x74\xaa\x27\xa3\x7e\x37\x51\x5b\x57\x97\x53\xf1\x30\xd8\x0a\x7c\x99\xd6\x26\xc8\x49\x8f\xd6\xce\xb5\xb5\x64\x53\x63\x81\x25\x73\x56\x96\x5e\x22\xa5\xe4\x3c\x64\x9a\x6d\xf5\x65\xe4\x76\xe5\x1b\x2a\x2d\x67\xc8\x88\xf0\xcd\x26\x3a\x21\x86\xf0\xe8\x2c\xd0\xf6\xa9\x29\xc7\x77\x6c\xc4\x59\x73\x71\xca\x71\xdd\xa5\xd0\x29\x17\xa7\xac\xb4\xdc\xa9\x14\x6f\x5c\xf0\x06\x36\x95\xe5\xf2\x49\x71\x5e\xb9\xc7\xb8\x6b\x34\x74\x11\xad\xdf\x2a\xb3\x9b\x67\xf4\xd8\x88\x45\x7a\x97\x51\x54\x46\x06\xcd\x22\x8c\x99\x48\xaa\xfc\x2e\x7d\xa0\x15\xff\x20\x2d\xce\x0f\x1c\x71\x59\xc2\x2f\xa4\xa5\x88\x28\x99\x43\x53\x87\xe0\x01\x53\xac\xb4\xd6\x62\x92\xa4\xef\xae\xac\x14\x9b\x2c\x87\x67\xa9\xe9\x92\x90\xbf\x0e\x1c\x5a\x65\xd8\x70\x90\x1f\xa8\x10\xf5\x42\x81\xc9\xf5\x3a\x43\x5c\x54\x86\x85\x77\xd4\x51\x33\xfe\x86\x12\xe6\x0c\x27\xfd\x21\x86\xa7\x94\xec\xea\x4e\x1a\xea\xcf\xdb\x51\xad\x08\xbf\x4c\xa5\x93\x17\x01\xc2\x17\xe1\x46\xaa\x57\xb9\x23\x70\x46\x39\xf5\xe0\x8e\x3a\xac\xbe\x3e\xaa\xaa\x72\x43\xac\x2b\x2a\xaf\xba\x67\x32\x86\xe1\xf2\x3e\x81\x62\x4f\x8e\xca\x9b\x92\x46\x59\xcc\x2a\x6f\xee\xef\x28\x79\xaa\xf4\x73\xdf\x53\xf5\x4e\xf7\x85\x71\xf8\xfa\x9a\x3e\xe4\x48\x4f\x7b\xaf\x5b\xa6\xd9\xb4\x0a\x3a\x68\xbd\x8d\x5d\x46\x73\x4e\x23\x84\x03\xf4\xfe\xfd\x0f\xdf\x3c\x7b\xf1\xec\xfd\xcb\x67\x6f\x7e\x78\xf6\xd5\xfb\xf7\xea\xae\xed\x2b\x4a\x66\x68\xb1\xa2\x8b\x0f\x34\x42\x80\xcc\xbb\x83\xd6\x13\x6c\xf2\x51\x41\x19\x23\x43\x6f\xe3\x3c\xbe\x4a\x28\x02\x94\xd1\xdf\xb7\x71\xa6\xf2\xde\x6d\x42\x16\xc9\xa0\x79\x20\x11\xcd\xe1\x07\x4a\xbe\x0a\x39\x75\x59\x7a\xeb\x60\x78\x29\x86\xc0\xde\xaa\x97\xbb\x3b\x3f\x50\x78\x2f\x23\x24\x55\x44\x9d\x56\xa7\xf3\x83\x1a\xfb\x0b\x4a\xd0\x5f\xd5\xb1\x18\x82\xe7\xd5\x47\x0b\xc1\x93\x07\xac\x48\x6d\xe3\x81\xb4\xb4\x23\x55\xd7\xa8\x4c\x6d\xda\xfe\x8a\xbc\xa0\x8f\xba\x51\xf5\x9f\x73\xf0\x90\x02\x9f\xa5\xff\x05\x07\x0f\xff\x8e\xb3\x06\x63\x44\xf3\x28\x67\x0d\x7f\xd4\xea\xec\xf8\x0c\xfa\x41\x43\x2c\x63\x40\xf0\xdd\x27\x26\xfe\x3f\x38\xd7\xa5\x47\x82\x7c\x7b\x95\xf3\xcc\x79\x6e\x34\x82\xd6\xec\x29\xaf\x82\xf6\x7e\x99\x02\x7f\xf0\xf6\xfe\xbf\x7a\x41\xb1\x6c\x6a\x5a\x86\x6c\xf3\xb4\xca\x5b\xc4\x47\x4a\xce\x7f\xcd\x3f\x87\x5f\xf3\xcf\xcf\xaf\x2b\xaa\xfe\xd5\xa1\x65\x75\xf9\x12\xc2\x47\xe9\x8e\x1b\x21\x6d\x5d\xc3\x6a\x36\x34\x1d\xa2\x6e\xd1\xb3\x59\x3a\xd7\xfa\x38\x60\xb3\x54\x5d\xd3\xcb\xb4\x47\xc0\xca\x84\x46\xd4\xfc\xb5\xdd\x01\xf8\x92\x92\xf3\xf6\xf9\x35\xfc\x46\xeb\x97\xeb\x25\x54\x7f\xa2\xe4\x7c\xf6\xa4\xfb\x6e\x7e\x7e\x0d\x9f\x51\x72\xfe\xcf\x75\xde\x3d\x87\x1f\x95\xcb\x21\xd3\xf3\xb7\xd4\x3a\x83\xec\x2a\x7d\xca\x77\xe9\x2d\xcd\x9e\x86\x39\x75\x8c\x6b\xdc\x6f\x8e\xac\xd0\x7e\x3c\x7a\x98\xb4\xf2\x90\xf8\x63\xe9\x28\x4c\xac\x33\x73\x79\xff\x27\x0a\x6f\x2b\xa7\x02\x32\x0f\xf9\x8c\xaa\x9b\xae\x1c\xcb\x53\x5c\x1e\x70\xab\x6b\xbf\x5b\x5b\x65\x93\xc7\x4a\xaf\x66\xfc\x83\xba\x5d\x84\xa7\x2c\xf8\x46\xd0\xf8\x79\xcd\xdf\x3d\xad\x1c\x00\xb6\xdb\x87\x1e\x1b\xab\x34\x3c\xb5\x3c\x05\x12\x2b\x41\xba\xd6\xfc\x9d\xe2\xc0\x4e\x17\xbd\xb3\xca\x62\xe0\x72\x7e\xfe\x4e\xc9\x33\x2a\xfd\xcc\x4d\x9f\xbe\x79\xe3\x6e\xee\xd4\x3b\x1b\xff\xa8\x47\xaf\xf3\x00\xad\x73\x04\x7f\x3b\xc8\x4d\xb3\x85\xc0\x62\xf4\x3f\xa8\x02\xc3\x2f\x16\x18\xce\x9d\xee\x2c\xec\x7e\x94\x5e\xee\x58\x23\x5b\x3b\xf3\xe7\x2e\x4f\x7f\xdc\x6c\xca\x19\x84\xcc\x86\x5e\xaa\xa0\x97\xcd\x52\x01\xa3\x74\x0e\xd9\x2c\x2d\xa7\x48\x2c\x6e\x15\x5d\x47\xba\x9f\x29\xf9\x85\x3a\x3b\xeb\xf6\xbe\xf2\xf9\x1b\xfc\xa3\xe6\x85\xa0\x74\x0e\x2c\xe3\xab\x57\x85\xbb\x9b\x54\x79\xdf\x46\xc1\xdf\x9b\x13\xba\x77\xa7\x93\xee\x8f\x92\xf2\xf8\x23\x95\x91\xea\x41\x19\x95\x2c\x83\xdd\x2b\xf5\x06\xc6\x71\x54\x37\xa1\x4b\xde\xcd\xe4\xdb\x33\x4d\xc9\x59\x7c\xbd\x7a\x28\x5d\xbe\x0e\x53\x4b\x10\x15\x1e\x45\x34\xe4\x6b\xa8\x33\x53\x8f\xbc\x1e\xc6\x34\x14\xe6\xe9\xe6\xf0\xfb\xe4\x48\x44\xda\xc9\x61\x88\xc4\xe3\xea\x8f\x63\xae\x92\x74\xf1\xe1\x38\xa6\x4b\x59\xd4\x1c\x7b\xaa\x8e\x6e\xce\xc3\x8c\x9f\x8a\x3f\x59\xea\x38\x3e\x66\x49\xcc\x68\x43\xd4\x51\x9f\xaa\xe8\x93\xd5\x34\xf4\xca\x4e\x38\x5d\xee\x38\x41\x15\x50\x7f\x1b\x00\xae\x12\x44\x5f\x1a\x12\x45\xf4\xc9\x92\x22\xf1\xa0\x9c\x7a\x11\x46\x66\x52\xc1\x1a\xa2\xeb\xa8\x0a\x21\x75\x84\x85\x66\x3a\xa6\x44\x27\x53\x4b\x35\xdb\x76\x4c\x05\xd9\x5a\xac\x05\x3b\x1d\x6f\xcf\x4d\x2d\xea\xa8\x86\x23\xf0\xeb\xb7\x68\x64\x1e\x1d\xae\x0d\xca\xc4\x55\xa3\x32\x31\xd6\xb0\x4c\x54\x39\xae\xb2\xa6\x6a\x60\xb5\xa8\xaa\x5f\xf5\x68\x6b\x68\x26\xc1\x1e\x5b\x3d\xee\xb8\x92\x63\xe4\x5a\x87\xf9\x87\x23\xf2\x56\x8f\xbc\xb7\x22\x4b\x92\xb6\x52\x8f\x66\xfe\x9d\x82\x7a\x8f\x4a\xe6\x88\x59\x57\xc5\x9b\x12\x77\xf5\x6f\xf3\x7a\x55\x95\x5c\x7d\x2a\x98\x8a\x90\x80\xa4\xf8\xe5\xe9\x46\xfc\x64\xa6\xa1\x98\x09\x19\x4e\x94\x94\x21\x1b\x76\x56\x44\x35\x68\x3b\xd2\x1a\xb1\x8a\xb6\xa1\x66\xc7\x1c\x16\x6f\x5a\x8e\x77\x5d\xf5\xac\x83\xfa\xe6\xf4\x8e\xd7\x22\x16\x69\xb2\x5d\xb3\xee\x75\xb8\xa9\x7d\x0b\x66\xed\x28\xc2\x86\x87\x8e\xb6\x62\xa4\x47\x8e\x12\xe4\xd5\xa7\xd8\xd6\x78\xa8\x22\xd5\x63\xa5\x5d\xf3\xde\x45\xd5\xa5\x88\x2e\x52\xb5\xcf\x75\xf9\x2a\x5e\x7c\x60\x34\xcf\xad\x64\xe5\xb4\xc9\x1e\x02\xcf\xd2\x0f\xf4\x28\xc2\xee\xcf\x6d\x9a\x45\xb5\x96\xd6\xa9\xa8\x5f\xcd\xa6\x0c\x76\x53\xf5\xbc\xb6\x88\x4a\xb7\x5c\xbe\x04\x2a\x52\x75\xd8\x4e\x2e\xe3\xaa\x06\x36\x34\xcb\x37\x54\xbd\xd8\x2f\xd1\xb6\xfa\xee\xa6\x59\x2c\xd6\xe7\x1d\x0a\xfe\xd6\x9c\x72\xaf\x52\xb8\x79\x80\x58\xc7\x37\xc7\x9a\x7a\x8e\xe2\x4f\xd4\xd2\xfd\x68\xc5\xc7\x87\xac\x85\x1d\x5b\xe3\x2d\x6e\x68\xc6\xe3\x45\x98\x74\xc3\x24\xbe\xd6\x6c\xc5\x32\xa1\x77\xdd\xab\x30\x8f\xf5\x6c\xc8\xc7\x3f\xba\xfa\x51\x2e\x11\x23\x66\x58\xfc\x5e\x87\x12\xff\xaf\xb3\x38\x92\x19\x45\xa0\xc2\xaa\x2c\xbd\xad\x3e\x64\xd2\x71\xcc\x21\x26\xca\x48\x4e\xd7\x9b\x24\xe4\x54\xe4\xcf\x9b\xe2\x55\x29\x3b\x29\xdc\xf2\xf4\x30\xbb\x8c\xab\x65\xad\x16\x46\xc9\x26\x55\x31\xf7\x47\x31\x57\xc9\x36\x3b\x8a\xcc\x37\x19\x0d\x23\x0b\xdd\x25\x86\xd8\x44\xc4\x5a\x6e\xa6\x19\x3b\xea\xfe\x38\xca\x34\x54\x58\x4f\xbe\x7f\x4b\x2d\x2d\xe9\xd1\x2b\x57\x4d\x0f\x4d\x3d\x60\xec\xcd\x67\xd9\x9c\xa8\x1a\x67\xd9\xbc\xbc\x5e\x5d\xd3\x71\x99\x37\xb5\xb0\xd4\x90\x95\xee\xa9\xa5\x59\x43\x5d\x3f\x81\xb9\xe0\x79\xbf\xa5\x5a\x3b\x70\x74\x5b\x3b\x34\xb9\x42\xd5\xa8\xb4\x26\x55\xae\x22\x6b\x4d\x1f\xbd\x88\xa6\x1d\x1a\xc7\xf9\xcb\xf0\x65\xf9\x70\x55\x4c\xd8\x8c\xce\xf7\xfb\x9f\xa5\x2c\xa4\x4f\x3b\xe3\xfd\x5e\x2b\x8d\x63\x42\xc8\xdf\xe9\x94\x5b\xb2\x77\xd3\xb3\x68\xf1\x34\x76\x38\xae\x65\x42\x1d\xde\x89\x2b\xb5\x9c\x54\x9a\x72\xc2\x9c\xfe\xa0\xdf\xc7\xc0\xd5\xfd\x64\xf9\x37\x93\x7f\x53\xf9\x37\xe4\x64\xdb\x6e\xa3\x94\xf1\x74\xbb\x58\x29\xaa\x1b\x5b\xb6\x8b\x26\xa0\xed\xc6\xc4\x4c\x6d\xf5\x40\x38\xd9\xbd\x48\x3f\x06\xa8\xbb\x4e\x3f\x76\x11\x08\xd1\xa5\xbb\xce\xbb\x08\x5e\x05\xa8\x9b\x76\x11\xfc\x44\xaf\x3e\xc4\x3c\x40\xdd\x5b\x19\xe8\xa2\x02\x12\x7e\xd2\x20\x6d\x83\xb0\xbe\x45\x5e\xde\x09\x97\x7e\x6f\x63\x39\x85\x39\xef\xa0\xf2\xa9\x73\xd1\xc3\x84\xe3\x1d\xe7\x24\xe7\x62\x50\x31\x9f\xe5\x7c\x7e\x29\x0d\xdf\x0b\xa4\xda\x95\xee\xd2\x78\xbb\x8d\xd6\xf9\x37\xf7\x9b\x15\x65\xb9\x2a\xd6\x6e\x3b\x02\x18\x42\xca\x92\x25\xdd\x75\x2e\x61\x41\xa3\x6b\x8a\x30\x1c\x96\xee\x86\x9b\x4d\x42\xbb\x3c\x0b\xe3\x44\xec\xe8\x82\x24\x97\x15\x09\x48\xca\x74\xa4\xd4\x47\x5b\x4e\x38\x87\x05\x27\x8c\x43\xc4\x49\xc6\x61\xc9\x49\xca\x61\xc3\x49\xc8\x61\xc5\xc9\x8e\xa5\xd2\x02\x3a\x49\x82\x99\xb4\xa3\x0c\xb3\x50\x1a\x6f\x82\xf6\x31\x49\x23\x23\x37\x37\x3d\x4b\x69\x95\xd0\x47\x74\x62\x1c\x84\x90\x2d\x9f\x56\x60\xee\xd0\x60\xc1\x3b\x14\x17\x05\xac\x0f\x9a\x5c\xa4\x49\x9a\x75\xc3\xe8\xb7\x6d\xce\x1f\xdb\x68\xad\x8c\x69\xb6\x82\xd2\x96\x4f\x17\xbc\x83\x36\x59\xcc\x54\xdb\xb2\xe1\x1b\x4e\xce\x67\xdd\x5f\xf3\x79\xc7\x71\xf1\xd4\x56\x89\x5c\xf3\x83\x37\x32\x79\x5d\x2e\x0d\x10\xaa\x1c\xff\xdf\xf3\xda\xd1\x8c\x91\x47\x6f\x38\x5c\x73\xeb\xe5\xb5\x2b\x3b\xdb\x3d\x77\xa4\xc2\x42\x4d\xc9\x2d\x87\xbb\x03\x20\x08\xc6\xea\x13\x83\xd7\xcf\x3f\x9c\x9d\xff\x53\x64\x3e\x37\x6e\xb7\x2a\x03\x06\xb1\xe0\x6d\x18\x94\x4f\xe6\x4b\xae\x2d\x5e\x87\xd7\x54\xbe\x48\x70\xcf\x1d\x86\x25\xfd\x28\x3d\xe1\x89\x25\xc4\x3b\x57\x87\x09\x62\xca\x2a\x67\xcc\x05\x3c\x3b\xe8\xb5\xa4\xb0\x69\x16\x53\xc6\xd5\x86\xf7\xc8\xe9\x3b\x2a\x67\xa6\x50\x21\xee\x19\x21\x11\xdf\xef\x37\x7c\x5a\x61\xcd\x87\xc3\xa6\xcb\x85\xf7\x29\xa8\x59\x5e\xb9\xaa\x42\xba\x41\xe6\x96\x51\x56\x5b\x6f\x9a\xda\x8a\x1f\x31\xc0\xe3\xc6\x62\x7b\x78\xba\x35\x19\x67\x35\xf7\xf4\xa0\xb9\xdb\x2c\xe6\x62\x59\xaf\xd3\xe8\xd1\xab\xb0\x56\xa6\x69\x41\xec\xf7\xe5\xb2\x6c\xb7\x15\x61\x39\x23\x64\x29\x17\x8a\x5e\x1f\xef\x0e\xfa\xb1\xcd\x05\x4f\x29\x75\xf6\x8f\xed\x86\x5d\xc4\xf4\xe2\x45\xfa\xf1\xa8\x0b\xfb\xbd\x9e\x6a\x22\xa6\xda\xea\xc3\xf7\x9c\xec\x3e\xb5\x08\x34\xc2\x9f\x9d\xff\x53\x12\xd7\x6e\xb9\x14\x8e\x88\x80\xfe\x7a\x2a\x39\x14\xd4\x91\x4b\x52\xe0\x77\xbb\x2d\xc8\x83\xe6\x8c\x04\x7d\xa8\x3a\xd9\x6e\xa3\x8d\x58\x28\x76\x66\x19\xa3\x96\x6f\x01\xaf\x1f\xd1\x43\xb5\x4c\x1d\x25\x23\xef\x15\x5b\xb7\xd7\xf2\x17\xd6\xe2\xc4\x89\x05\x5c\x76\xe4\xf0\x09\x97\x8a\xd2\x20\x23\xb8\x00\xaa\x34\xae\xf6\xf2\x95\xc3\x63\x45\x01\xaf\x1e\x0d\x4d\x45\xd5\x54\x61\xb1\xd2\x7f\x78\x44\x49\xd5\xaf\x2b\xfb\xf1\xc4\x6e\xe5\x14\xbc\x0a\x8b\x1d\x4b\x85\xfd\xf9\x94\x06\x5b\xde\xd1\x3e\x50\xe5\xb4\x9b\x19\x3b\xd3\xd0\xd7\x9f\x3a\x8f\x28\x5b\xed\x21\x45\x01\x2f\x3f\xd1\xb1\xca\x3f\xe9\x22\x4b\x93\xa4\x9b\xb3\x70\xa3\x0c\xd1\x94\xd2\x5e\x70\x26\x1e\xf8\x3e\xae\x6f\x54\xa8\x53\xe1\xe0\xfb\xc7\x36\x91\xde\xd0\x4c\x37\x73\x45\x57\xe1\x4d\x9c\x66\xc7\x7b\xa0\xc0\x34\x9d\x69\xb1\x0a\x63\x26\xc5\x26\xd9\xce\x0b\x4e\x76\x4a\x12\xb8\xce\x84\xdc\xa8\xc2\x4a\xe4\xbe\x11\xb3\x2b\xbf\xf3\x55\x16\xb3\x0f\x26\x95\xd1\xeb\xd0\x4e\xd5\x32\x84\x2e\x9a\xd1\x25\xcd\x32\xaa\xb5\x8e\x80\xc4\xf6\x18\x2f\xef\xbb\xe6\xaa\x85\xc9\x17\x2e\x3e\x20\x50\xfa\x48\x15\x23\xc3\x08\x90\x14\x51\xba\x31\xa7\xeb\xb2\x52\x25\xb5\x98\xa4\x83\x9a\x24\x67\x2e\xab\x2b\xe0\xf9\xa3\x51\xe6\x05\xb7\xf8\xcc\x33\xd6\x6e\x37\x22\xef\x13\x4e\x76\xa2\x91\x40\xca\x06\x22\x64\x06\xad\xc1\x75\x18\x5d\xbe\xd3\x88\x82\x99\x4c\x54\x3b\x0c\x52\xc2\x45\x95\x3a\x37\x43\x57\x79\xa2\x98\x85\x89\xa8\x73\xbb\x39\x82\x80\xc8\x61\x00\x20\xdb\x58\x26\xa2\xe9\x4f\x54\xdf\x00\x77\x91\x45\xc3\xe9\x3b\x4e\xec\x97\x60\x9f\x70\x0c\x1f\x1b\xcd\x3e\xe4\xee\x0b\x5f\x7d\x12\xac\xb6\xbf\xdb\xf5\x36\xe1\xf1\x46\xb9\x3d\xfa\xce\xbe\xd6\xfa\x45\xd7\x37\x27\xdd\x4f\x24\xf8\x05\x8d\xaa\x0b\x38\x69\x79\x28\xa2\xe6\x23\xad\xe6\x23\xad\xb9\xce\x3d\xf3\x2b\x57\xf9\xd2\x43\x50\x6a\x3b\x06\x12\x39\x35\x37\x91\xce\xbc\xb9\x62\x28\xaa\x92\xc6\x8f\x80\x3c\xa8\xf8\xc8\x71\x65\x83\x5d\xc0\xd7\x9c\xcc\x56\x1c\xd6\x82\x3f\x82\x67\x1c\x3e\x70\x78\xc3\xe1\x29\x87\x77\x1c\xbe\xe7\xf0\x9a\xc3\x2b\x0e\x3f\x70\x78\xc9\xe1\x3d\x87\xe7\x1c\xbe\xe2\x73\xf8\x92\x93\xaf\xb9\x7e\x24\xb5\xf1\xed\x6d\xb1\xf4\x0f\xe0\x57\xe0\x93\x0f\xfd\x9d\xc8\x0e\xbf\x7d\xba\x99\x72\xf3\xb4\xde\xe3\x6d\x7c\x52\xb3\x45\xe5\x25\xe2\xd2\xb9\x85\xe3\x01\xe5\xf2\x06\x6d\x55\x07\x56\x2f\xfe\xce\xe6\x18\x7e\x92\x67\x4a\x4a\xcc\xb9\x7d\x50\x5a\x91\x7b\xc5\x67\x9c\xe8\x3b\xa1\xd7\x94\x3f\x4d\xd7\x9b\x2d\xa7\x91\xf2\x7b\x70\x4a\x86\x92\x3b\x89\x99\xd3\x1f\xa5\x8c\xf3\x19\xc7\x4a\x4a\xfc\x91\xe3\xfd\xde\xf9\x89\xcf\x3e\xe3\xb3\x1f\xf9\x7c\x4e\xd4\x2f\xbe\xfc\x8d\x37\x98\xac\x54\xf0\xd0\x7e\xdd\x7e\x92\xef\x68\x63\x8b\x33\x7e\xcb\x4f\xbd\x65\xb6\x2b\x30\x9c\xdd\xd6\xf9\x52\x65\x14\x22\x6b\x31\xf1\xf2\xe3\xd2\x66\xb0\xce\x24\xd5\xb5\xf8\xbb\x33\xe9\x75\xd5\x11\x19\xd5\x2b\x3b\xb7\xc6\x55\xd7\x65\xdd\xaa\xfa\x4b\x5e\x3e\x79\xe6\xc8\x7a\xc9\x97\x5c\xf9\x90\xb8\x2d\xbd\x30\x60\x38\x53\xed\x4b\xa3\xeb\x4b\x9e\xdd\xef\x4c\xa2\x28\x80\xd0\xe9\xdb\x65\x6a\xf4\xa2\xb9\x6f\x38\xfc\x2e\x46\x08\x7f\xe7\x64\x57\x75\x3d\xf0\x6b\xaa\x23\x73\x8b\x0e\x89\x78\xb3\xf3\x59\x03\x6d\x8e\xb6\x8b\x15\xf0\x0f\x4e\xce\x9d\x7f\xfe\x9a\x7f\xae\x8f\x58\xf7\xd0\x72\xaa\x2f\x67\x7a\x36\xfb\xa7\x83\xe7\x9f\xff\x8a\xb1\x2d\x03\xfd\x8d\x1f\xf0\xaf\x37\xa1\xdc\xcd\xf8\x54\x86\x02\xf9\x14\xa8\xfa\x16\xa1\xf2\x9b\x4d\x11\xb4\x64\x8c\xc3\xa7\x6f\xe5\x55\x52\x04\x2d\xd4\x79\x2b\x08\x3a\xde\xef\xf9\x7e\xcf\xaa\xb9\xff\x85\xd7\x0c\x7b\x25\x59\xf9\x46\xb0\x83\x86\x54\xda\x77\x3c\xb8\xed\xde\xaf\xb2\x10\xdc\xef\xcf\x14\x66\x6e\xc2\x2c\xa7\xcf\x19\x77\x18\xf8\x1e\xae\x1e\x4b\xd7\xef\x3e\xd1\x0e\xab\x10\xe8\x77\xf9\x88\xb6\xce\x21\x3f\xe4\x3c\x7e\x63\xcd\x23\x3b\x9c\x46\x95\x8f\x9c\xf9\x70\xe6\x17\xf1\xd2\xf9\xbb\x44\x02\x46\x58\xc9\x8a\xfd\x83\xc3\xdf\xb8\xa5\x6f\x11\xdd\xb7\xaa\x14\x8c\x40\x77\x9d\xab\x5d\x8a\x10\xe2\x30\x22\x36\x37\xc1\x7b\xd8\x0d\x97\x79\xae\xd2\x3b\x84\xa1\xd6\x27\x38\xac\x13\xe3\xe3\xce\x19\xa2\x5a\xab\x14\x81\xca\xc1\xd4\x6f\xb1\x95\xad\x3e\x44\x3d\x14\xf9\xf8\x99\xc3\xb7\x9c\xdc\x51\x67\x57\xda\x0a\x3f\xec\x19\xb7\x66\xef\x75\x56\x69\xb9\xac\x0b\x3a\x7a\x46\x6e\x1c\x0a\xbb\xc2\xb6\x2c\x99\xbd\xa7\x73\xc2\x21\x7b\xd0\xeb\xbc\x6c\xe2\xa5\xf2\xbe\xba\xdf\xbf\x57\x81\x43\xfe\xd8\x3a\x37\xae\x3b\x90\x92\x4f\x17\x36\xe8\xab\xd2\x76\xdb\xf8\xb0\x94\x4e\xa5\xa4\x65\x9e\x75\x9d\x60\xf6\x52\xc2\x5f\xba\x9a\xd7\x8e\x2b\x4e\xd9\x8e\x71\x08\x49\x2a\x86\x22\x2d\xd3\x52\xed\xe5\x25\x74\x28\xde\xef\x8d\xf1\x61\x4c\x52\x51\xa3\xc0\xc8\xb8\xd4\xf6\x25\xea\x25\xbc\x54\x39\xf7\x4b\x20\x9e\x25\x73\xf9\x28\xba\xe0\x0f\x3f\x09\xf5\xea\xe5\x57\x09\xe3\x78\xe9\x50\x42\xc8\x8b\x2a\x96\xde\xb6\x9e\x50\xcb\x8b\x4f\xf5\x68\x4f\xbb\x5d\x5a\xb1\x78\x50\xd9\xb1\x10\x42\x9e\xd7\x8a\x7f\x57\x16\x37\x1c\x86\x32\x5e\xb1\x2f\xdc\x1b\xbb\x1a\x79\x7f\x4b\x5d\x02\xc9\x0e\xae\x30\xb4\xdb\xb5\x4c\xf5\x44\x75\x45\x44\xca\xc7\xca\x45\xaf\x7a\xd3\x52\xf9\x4b\x51\x31\x2a\xd1\xdc\x76\xa5\xca\x46\xba\x38\xf0\x4b\x52\x47\x99\xea\x81\x02\xaa\x1f\x28\x10\x7b\x4c\xf3\xdd\x5e\xe3\x84\x52\xda\xf6\x48\x9a\x1f\xca\x77\x7f\x5e\xd0\x79\x60\x40\x1b\x56\x16\x33\xb1\x74\x0c\x89\x4b\x9b\x2a\x27\x86\x70\x16\x1f\xbe\xd1\x51\x7a\x11\xfe\x4a\x64\xa8\xae\x69\xcb\x6b\xd6\x1a\xf1\x64\x13\x45\x21\x7b\x03\x8f\xec\x5b\xfd\x99\xa2\x14\x97\xf3\x1a\xca\x79\x0d\xab\x79\x7d\x61\xcf\xeb\x0b\x6a\x94\xbd\x5f\x51\xa7\xcc\x54\x65\xb1\x7b\x78\x69\x0f\x2d\x9d\x85\x27\x87\x16\x0b\xce\xa8\x1c\x4b\x68\x86\x22\xb0\xf7\xa4\x51\x56\x49\x5d\xeb\x4e\x1d\x2c\x2b\x4c\x6d\x4a\xb6\xdf\xcb\x67\x0b\xaa\x88\xca\xc9\x5e\xf5\xbc\x5a\x90\x59\xef\x79\xf2\x43\xcb\x26\xae\x2d\x9b\xbe\x96\x96\x4d\xd4\xfa\xd2\xae\x23\x04\xf7\xca\x6c\xee\xb5\x9c\x63\xc2\xc4\xb8\x13\xe2\x5d\x26\x7f\xc9\x4c\x8e\xc4\xdc\x60\xcc\x49\x36\x4b\xe6\x97\x82\x86\xa4\xe6\x35\xd4\xb4\x43\xe4\x9d\x94\xca\xb0\x0d\xb5\x11\x9e\xe6\xe5\x6e\xf1\x25\x85\x18\x07\xb1\x34\xa3\x32\x4f\x3c\xb4\xd2\xaa\xfb\xf6\xda\x36\x6e\x62\xea\x80\xd7\x36\xe6\xc6\x1a\xbe\xc0\xa5\x49\x9a\x59\x52\x8c\xe6\x3c\x66\xd7\xdf\xd1\x1b\x9a\x5c\xa6\xf6\x03\xa3\x7e\x90\x76\x7c\x6d\x07\x6d\xbf\xfe\x50\x62\xd8\xce\x2e\x1b\xa4\xda\xa0\xdd\x16\x22\x64\x8b\x75\xf6\x2e\x54\xef\xe9\x84\x7a\x38\xbb\x53\x64\x3c\x85\x10\x62\xb5\x57\xa8\x85\x79\x46\x48\xa8\x56\xbe\x01\x84\xba\x81\x05\x39\x6c\x49\x08\x0b\xb2\x3d\x20\x13\x25\xde\x47\x0a\xef\xe5\x3c\x2c\x15\xc8\xa3\x1a\xc8\x61\x43\xd4\x8a\x88\x66\x9e\x24\xb8\xcb\xfd\x7e\x23\xdb\x4e\x08\x73\xb6\xb0\x80\x04\xc3\x52\x55\xb0\x22\xdc\x89\x60\x6b\xe1\x7e\xbe\xdf\x3b\x39\xa1\xce\x42\x3e\xdf\xb3\x22\xab\x72\xfe\x7e\xa3\x90\x63\x58\x94\x6b\x63\x05\xe9\x2c\xaa\xad\x8d\xc4\x5a\x1b\x2b\xc1\xf4\x4a\xce\x60\xd3\x6e\x57\x85\x22\xb1\x03\x26\xb8\xfc\xde\xca\xa7\x06\x64\x45\x55\xd9\xaa\x3f\x85\x45\x2b\xa2\x79\x51\x61\x4d\x51\x38\xd2\x53\xd3\x89\x5d\xb3\xc1\x6b\x7f\xdd\x59\xbf\x77\xc9\xab\xcb\xdc\xbc\xd3\xc1\xf2\x59\x99\xdf\xa9\x7c\x5e\xc6\x72\x07\x65\xb8\x0d\x65\x4e\xfe\xf0\xab\x2b\xa5\xeb\xa4\x9a\xa1\x5b\x7d\xa7\xce\xc8\x37\xd4\xb2\x8e\xe6\x62\x43\x98\xd2\xc0\x61\x6a\x0f\xcc\x40\x53\xf7\x1a\x0d\x79\xc8\x49\x8c\xb4\x39\xbb\xfc\x04\xfa\x51\xc3\xa8\x94\xc8\xc7\x6a\xc8\x47\x0f\x99\x07\xaa\xcf\xf3\x2a\x8f\x93\x25\x44\x4e\x03\xa1\x72\x3d\xf8\x2d\x75\x98\xbc\x22\xa1\xe6\xe9\x81\xb7\xc0\xe5\xb3\x78\xcd\xc4\xf2\xd8\x79\x97\xb1\xd6\xd5\x57\xa6\xeb\x87\x88\xac\xdd\x3e\x32\x9b\x57\xf6\xf6\x52\xd6\xa5\x96\x7b\xe4\x54\xf0\x8d\x21\x91\x3c\xba\xbc\x84\xac\xaf\xd2\xa5\xe4\xcc\x33\xec\xca\x99\x0f\x09\xf9\x85\x3b\x21\xc8\x9a\x2e\xb5\x9b\x64\xb1\xe3\xc7\x22\x1b\x38\xe9\x7e\x1f\x8b\x7d\x3b\xad\x9c\x78\xcf\xd8\x1c\xf8\x2c\xdc\xef\xd9\x9c\x24\xfb\x7d\x66\x5b\xe5\x1f\x4e\xd1\xc1\xa6\xad\xe6\xe7\xe4\xed\x51\x4e\xa8\xd8\x96\x9a\x34\x25\x95\x7a\xd1\x52\x31\x4f\x69\x80\xfe\x2a\xd5\x7a\x56\x9d\x9d\x92\xeb\xf1\x3d\x5c\x38\xa2\x3e\x81\x67\xa7\xb0\xe6\xf8\xbd\xa3\x12\x71\xa6\x3c\x90\xd7\x31\x1e\x58\x11\x25\x32\xfc\xc2\x1d\x0e\x72\xfd\xed\xf7\x54\x21\x84\xf3\xf3\xe1\x55\xa9\x52\x33\xa0\x96\xa4\xe5\x81\x6c\x4a\xbf\xe0\x53\x3f\xe8\xfa\x41\xe9\x81\xc0\x24\x15\x0f\x50\x00\xcd\x37\x57\x1d\xe7\x27\x30\x5e\xf0\xce\x90\xd5\x94\x52\x14\xbb\x79\x9a\x71\xe7\x67\x8e\xb5\x31\x70\x66\x1b\x03\xb3\x59\x36\x4b\xe7\x73\xc1\x5a\x8b\xdf\xea\x9d\x99\x02\xcf\x0b\x0c\x94\x91\x9d\xbe\x2d\xa0\x2f\xba\x09\x41\xf7\xcc\x2f\x6f\x65\x3d\x35\xae\x97\x82\xa3\x9b\xd7\x87\x77\x69\xbe\xf0\xda\x6d\xb5\xf4\xc5\x86\x61\xb9\x44\x9f\xda\x1f\xc1\xae\x00\x4e\xa8\x6b\x5a\x95\xbc\x26\x30\x52\x96\x14\x9c\x84\xe4\x00\x36\x59\x1a\x6d\x65\x93\xca\xed\x13\x58\x7b\x64\x36\x45\xbf\xe5\x39\x0a\x32\x08\x05\xaf\x40\xe5\x4b\x70\x65\x6a\x38\x45\x28\x08\x21\x21\x52\x22\x8b\xc5\x17\x42\xc6\x4f\x5f\x0c\xa8\x8b\x30\xe4\xc4\x83\x6d\x83\x01\x7b\xde\x21\x7e\x71\xe4\xd5\xa9\xe4\xf3\x32\x52\xdd\x66\x17\xdb\xa9\x76\xbf\x20\xfb\x54\xd1\xd2\x17\xdb\x18\x61\xe9\x51\xb6\x7e\xf3\xfd\x4c\x91\x36\xb9\x11\xbe\xa2\xd5\x76\x2d\xa6\xd2\x10\x5f\x51\xb8\x5b\xf6\x56\x25\x69\x5e\xa0\x1a\x44\x82\x4d\x28\x93\xc3\x39\xc8\x5e\x5e\x3d\x30\xcd\xf3\x15\x5d\xd3\xd9\x6b\x21\xe7\x96\x30\x31\x65\xc2\x5a\x0d\x5b\x07\xe3\xc0\xf0\x08\x4d\x0d\xa6\xb5\xac\x72\x89\xfc\x96\xe7\xc1\xb7\x5c\xbd\xed\x91\x3f\x0d\x17\x2b\x7d\x83\x55\x45\xbc\x08\x59\x78\x4d\xb3\xc0\xdc\xd3\x51\xb1\xaf\xb5\x5f\x13\xe3\xb8\x98\x91\x50\xcb\xb9\xf2\x22\xfe\x1d\x77\x28\xc3\xc0\x18\xe9\xfa\xf4\xa2\xd2\x7d\x64\xd6\x54\x31\x26\xe6\x4a\x12\x49\xa6\x6e\xda\xf4\x2d\x9b\x91\xd0\x76\x0e\x7c\x2c\x53\x9a\xfb\x19\x3b\xd5\x68\x60\xb1\xb8\x9a\x61\x09\xa5\xda\x21\x24\x7c\x4a\x1d\x86\x03\x5a\xe9\x1c\xf8\x2a\x4b\x6f\x5b\xb4\x10\x82\x5d\xba\xdf\x9f\x31\x37\xbd\xa1\x59\x16\x47\x34\xaf\x7f\xcd\xd2\x52\x91\x11\x6a\x5a\x5d\x4f\x85\xc4\x66\xf0\xc2\x72\xe6\xec\x15\x1e\xe3\x66\xe5\x5d\x32\xa3\x73\x51\x3a\x65\xa2\xb8\xf8\x82\x78\x46\xe7\xf2\xde\x99\x90\xb8\x4a\x2f\x40\x85\x36\xb7\x4f\x58\xcd\x46\x3f\x3f\xba\x0d\x95\xf3\x90\xab\x17\xe9\x95\xfc\x92\xbf\xd2\xe8\x73\x44\x22\x4a\xbd\x8f\x90\x9a\x2f\x33\x77\x21\x26\xfd\x69\x79\xdd\xaf\x1e\x41\x76\xf2\xc1\x1f\x85\x13\x49\x98\x4b\xbf\x49\xd5\xd7\xb7\x6f\xde\x88\x4e\x1a\x06\xb9\xd2\x91\x64\xe6\xd2\xa0\xd8\xcb\x6a\x35\xba\xba\x9c\xf4\x21\xd7\x94\x40\xca\xb2\x20\x37\x4a\xe0\xcd\x75\x88\x9e\x34\x57\x22\x52\x08\xd7\xa5\xd3\xe3\x3c\xea\xa1\x26\xc7\x83\x37\x54\xce\xde\x55\x98\x9b\xb4\xa0\xb9\x4f\xc0\xe8\xad\xc9\xc1\xe1\x69\xba\xde\xa4\x4c\xba\x86\x11\x13\xd6\x54\x7b\x25\x6e\x6c\x0f\x24\x4d\x39\x51\x52\xce\x94\x0b\x5b\x11\x41\x7b\xc6\x20\x2e\x63\xa4\x62\x22\xcd\x20\x21\xb4\xa4\x58\x67\x61\xc3\x94\x6a\x69\xe9\x9d\xba\xdb\x16\xba\xb5\xd5\x0b\x31\xa4\x86\xe1\xde\x65\x74\x99\x07\x1e\x88\x5e\xc4\x0b\xe5\x45\x54\xce\x66\x74\xcf\xc2\x75\xbc\x90\xdb\x5b\xae\x17\xf6\x3b\x75\x2d\xaf\xa1\x3a\x30\xef\xad\x6f\xed\x35\x10\x57\xef\x4c\xc0\x4e\x8e\x2e\x48\x61\x99\xc4\x9b\x00\x5d\x29\xf7\x28\xd5\x1a\x0e\x5d\x91\x30\x55\x3f\x01\xca\xb8\x54\x5a\xa4\x6e\x79\xc2\x53\xe0\xcb\xad\x7d\x47\x55\x30\xeb\xd9\x0d\xcd\xfe\x76\xb8\xbb\xed\xf7\x55\xbe\x32\x52\x76\x6e\x41\x4c\xd7\x5f\x5b\x9e\x98\x04\xbd\x97\x0e\x24\xb4\xb7\x8d\xe8\xd2\xe4\x92\xe4\xaf\xdd\x76\xa2\x43\x40\xca\x04\x09\x46\x35\xea\x25\x89\x35\xc1\x73\x52\x48\xf0\x65\xb4\xdf\x3b\x4e\x44\x42\xeb\x52\x52\x75\xd7\xd8\x59\x56\xb2\x8b\xd8\x4a\xa4\x1f\x81\x2d\xc6\xb8\x72\xf1\x7f\xd0\x81\x03\xb8\x97\xad\x43\x84\x31\x2c\xb4\x98\xe3\x44\x18\x72\xd7\x9a\x47\x12\x41\xee\xd6\xa6\x91\x7c\xa0\xce\x12\x0b\x52\x77\x90\xa0\x06\xbe\x39\xd5\xe1\x83\xdc\x87\xdd\xf7\x64\xf7\x2f\x37\xe6\x4d\x10\x8e\x61\x53\x8d\x85\x95\x85\x65\xa7\x36\xc0\xca\xfb\xc3\xcd\x2b\xae\x36\x88\x72\xe9\x5b\x0b\x6e\x63\x22\x0b\x6b\xf4\x1b\x2d\xf5\x55\xb5\x37\xd6\x73\xa9\x66\x5a\x6c\x36\xd5\x92\x5c\x34\x2d\xc9\xcb\x7a\xc7\xdb\xed\xfa\x77\x35\xd8\xaa\x9e\xc8\xda\xa6\xcc\xc2\x66\xe5\xc2\xce\x8e\x16\x76\x7a\xb8\xb0\xd5\x79\xdf\xa9\xf5\x1c\x1a\x34\xcc\x0e\x16\x60\x0a\x42\x9e\x90\x03\xeb\x6a\x1f\x9d\xb1\x79\x63\xbf\x42\x75\xc9\x4d\xc9\x4c\xed\xb6\xf3\x8e\x9a\xeb\xae\x4d\x95\x41\x26\x11\xe1\xf0\x96\xbc\xc0\xc0\x0a\xa4\x18\xe2\x76\x3b\x36\x17\xe3\xeb\x49\x18\xf8\x01\xf4\x9c\x13\x55\xd6\xf3\xd5\xeb\x3c\x48\xc3\xd6\x94\x2d\xed\x29\x83\x8c\x84\xee\x36\xa7\xaf\xe9\xd2\x99\x49\x0f\xb8\xf2\xf3\x05\x5d\xa7\x0d\xee\x18\xc5\xfe\x24\x25\x4b\x77\xb1\xcd\x32\xca\xc4\x76\xa2\x37\x05\xf5\x4d\x52\x31\x6b\x0e\x16\xeb\x70\x9b\xd3\x67\xcb\x25\x5d\xf0\x26\xbf\x8e\x56\x0c\x6b\xb7\x99\x83\x45\xcd\x82\x4f\xa8\xfa\xb9\xb1\x50\xe2\x88\xc9\xf6\x1b\x99\x6c\xdf\x66\xb2\xfd\xb9\x71\xfd\x27\x15\x3e\x31\xe1\x87\x1e\x54\x21\x21\xdc\x2d\x77\x20\xc8\x09\x77\xf5\xd3\xa8\x3f\x48\xb4\xdb\x56\xbc\x74\x3e\x4d\x58\x90\xc3\x42\x72\x1a\xc6\x75\xb0\x7a\x18\x16\x1d\xd4\x8a\x00\x95\x75\x22\x40\x76\x8d\x68\x8e\x21\x22\x92\x25\x83\x25\x61\xfb\x7d\x2c\xe4\xbf\xf0\x83\x9a\xd5\x1c\x5d\x46\x96\xb7\x14\xa9\xcc\x12\x8c\x9e\x7a\xfe\x8d\xc1\x9a\xf2\x30\x58\xc2\x41\x73\xc1\xb2\xd0\x2f\xaf\xfd\x47\x45\x13\xc7\x83\xef\x25\x81\xc1\xfb\xfd\x16\x6a\x2e\x13\xe4\xd4\x1a\xf6\x94\x33\x0c\x0b\x0c\x71\x85\x46\x42\xa8\xa8\x3e\x2e\x97\xec\xc8\x31\x67\x46\x76\x7a\x48\x72\xa1\x8b\x06\x6b\x6b\x39\x88\xa0\xb6\xda\x83\x14\xd4\x16\xc8\x4b\x91\x64\xcb\x94\xe2\x25\x2f\x31\xef\xcc\x87\xb8\xfc\xc8\x6c\x6d\x6e\xc4\x9c\x4c\xe1\x17\x87\x68\x7e\x1a\x35\xcb\xba\xda\xed\x05\x73\xca\xca\x0e\x9a\xf1\x8a\x72\xe7\xca\x6b\xb9\x4a\x7a\x5b\x3a\x60\x6a\x2d\xcb\xfe\x6e\x24\x83\xbe\x12\x0c\x7a\x7f\x32\xba\xd0\x6e\x4b\xe5\xe7\x78\x68\x2e\xc6\xdf\x1c\xba\xf2\x3b\x92\xbf\xfe\xed\xf5\x70\xec\x9f\xb8\x7c\x17\xa9\x8e\xfb\x62\x31\xdc\xc6\x7c\x55\x5f\x09\xca\xa1\x94\x58\x07\x7a\x55\x45\xb5\x05\x51\xc3\x75\x40\x65\x79\x04\x6a\xad\xcc\x05\xda\x2f\x60\x43\xc4\xda\xae\xf6\x42\xbb\x58\x10\xdb\x3c\xa1\x42\xfd\xc5\x7e\xcf\x04\x65\xdf\x24\xe1\xbd\x40\xfc\x86\x25\x20\xf7\xf3\x15\x09\x85\x8c\x70\x1b\x66\x91\xc0\xbd\x83\xb3\x93\x72\x82\x8c\xda\x56\xba\xa0\x61\x34\x7b\x4d\x97\xd6\x38\x28\xcc\x90\xce\x88\x00\x99\x0c\xaa\xeb\x9b\xda\x55\x79\x03\x30\xc1\x23\xe7\x40\x65\x07\x22\xf3\x36\xc8\x91\x27\xc2\xc5\x7e\xbf\xc5\xed\xb6\x93\xd4\x96\x56\x2c\xb6\x61\x67\x25\xe2\x56\x52\x80\xd1\xcc\x5e\xa2\x47\x0e\x1b\x51\x79\x10\x09\xe6\x78\xdb\x6e\x9f\xad\xd4\x8e\x28\xca\xa8\x10\x49\x24\xb1\xad\x9f\x8d\xb2\x0a\xb6\x19\x5d\x06\xf9\x7e\xcf\xcb\x47\xa1\x96\x05\xac\x30\xb6\x9c\xbe\x24\x0e\x76\x56\x62\xe7\x5a\xc9\xc3\x90\xe6\x59\x59\x33\xf7\x5d\xa1\x0f\x4a\x7a\xe3\x89\x1f\x68\xa1\x89\x7c\xb1\x43\xdb\x9c\xb6\xc4\x68\x17\x1c\x89\x9d\xdf\xe1\xb0\x7b\x17\x38\x98\x7c\x91\x15\x06\xb3\x33\xb2\x5b\xa7\x57\x71\x42\xdf\x70\xba\xd9\xd0\x2c\xf0\x69\x1f\xf2\x0d\xa5\xd1\x57\x71\x98\x04\xbe\x37\xf4\x20\xdc\x6c\xbe\x0c\xb3\xc0\xf7\x3d\x0f\xa2\x2c\xbc\x15\xb9\x7a\x9e\x07\xeb\x34\x12\x59\xfa\x9e\x07\x39\x0b\x17\x1f\xae\x44\xa6\x81\xe7\x01\x4f\xd3\x84\xc7\x9b\xc0\x1f\x7a\x5e\x51\x40\x7f\x32\x7e\x5c\xb7\xd2\xa2\x3c\x1c\x74\x7a\x93\x89\x25\x2c\xa7\x46\xa9\x77\x78\x84\x4f\xb1\x12\x76\x85\xf0\xfe\x2c\xcb\xd2\xac\x44\x84\x31\xb6\xdc\xbf\x2e\x56\x61\xf6\x84\x3b\x1e\xae\x5b\x63\x77\xa8\x7e\x91\xd1\x97\xe0\x1b\x8e\x26\xa7\xfa\x59\x09\xf8\x35\xb7\x2d\x47\xfe\x5a\xb8\xe5\xaf\x85\x1a\x0f\x96\x54\xb9\xd8\x93\xce\x45\xca\x55\x5f\x5d\xd4\xe6\x0f\x5b\xf8\xe8\xfb\x24\xd3\x9a\x8a\xab\xd2\xb8\x1d\x75\x21\xb3\xba\xc0\x8c\xd2\x8d\xa9\xab\xf7\xb3\xd4\xee\x42\x3a\xbf\xac\x79\x65\xca\x04\x8b\x53\xfb\x16\xc4\xd9\xa6\xc4\x05\xc6\xc5\x21\x26\x15\x30\xec\x79\x17\x8f\x9a\xe0\xc8\x9a\xe0\xf1\x60\xd4\x13\xbd\x63\xce\xb8\x77\x31\xc0\x10\x4a\x15\xc9\x64\x2c\xb6\x2c\x87\x39\xc3\xd1\xc5\x18\x03\x73\x46\x9e\xef\x61\x0c\x89\x48\x1d\x8e\x86\x62\x0f\x13\x94\x7a\xec\x63\xf9\xdc\xeb\x69\xaa\x62\x18\x5f\xe3\x05\x50\x0a\x98\x66\x27\xd8\x9a\xb0\xa2\x5a\xe2\x2b\x4d\xd2\x0c\xa2\x8a\xb1\x58\x4c\x51\xcc\x56\x34\x8b\x39\x0a\x16\xb0\x94\x59\x0c\x43\xb2\xa9\xb2\x2d\xa7\x28\xbf\xb9\x46\xc1\x12\x56\x84\xba\xcb\x94\xf1\x37\xf1\x47\x0a\xeb\x2a\xc7\x6a\x2a\x1d\x04\x6f\xd7\x28\x58\xc1\x0d\xa1\xee\x8a\xaf\x93\xa7\xb2\xb9\x6b\xc1\x48\xc7\x3c\xa1\x4f\x16\x0b\x9a\xe7\x70\x4f\xa8\x7b\x13\xd3\xdb\x2f\xd3\x3b\xb8\xaa\x6a\xb8\x9f\x22\xaf\xe5\xb5\x7a\x83\x56\x6f\x80\x82\x7b\xb8\x15\x54\x29\x2c\x69\xa2\x1e\xa0\x61\x78\x24\x79\x2c\x07\x87\x40\x5d\x71\x90\xbf\x15\xf3\x63\x3a\x8a\x00\x95\xdd\x41\x80\xac\xce\x20\x40\xba\x2b\xa8\x3a\xc4\x49\x0f\xe8\xd9\x06\xea\xef\xea\x4a\x4d\xac\xe3\x41\x2c\x55\x3e\x6e\x96\xa6\x1c\xb6\x50\x02\xf2\x4c\xbe\x43\x98\xe8\x9b\x1a\xa5\xf2\xce\xf1\x20\x17\x05\x22\x8c\xe7\x25\x5f\x26\x32\xaf\xdb\x6d\x03\x3b\xf5\x95\xcc\xaa\x9e\x1f\x96\x5e\x63\x2c\xf6\x82\x74\xb1\x95\x92\x46\x80\x96\x61\x92\x53\x04\x7a\x14\xc1\x15\xc8\x56\x83\x1b\x40\x61\x16\x87\xdd\x55\x1c\x45\x94\xa1\xe0\xec\x7a\xbf\xd7\x9e\xa8\xb2\x34\xa1\xc1\xf5\x14\xc5\xeb\x6b\x14\x98\x38\xba\x0c\x78\x01\xb7\x18\x18\x5c\x4f\x0f\x01\xa0\x20\x86\xd4\x5b\x8a\xd7\xca\x01\xb9\xa4\xe1\x5b\x77\xbd\x8d\x05\x38\x08\x7a\x73\x73\xfd\x7c\x91\x32\xa4\x49\xae\x64\x55\x13\xd1\xe3\x06\x5b\xb7\x9d\x00\x59\xb0\xdb\xe6\x34\x53\x2e\xb9\x03\xc4\x52\x46\x91\xbe\x17\x8b\x7c\xba\x46\xe6\xb6\xac\xfa\xd0\xdb\x6f\x80\xf4\xdd\x52\x75\x8f\x15\xa4\xe5\x3d\xd2\x3c\x90\x9e\xde\x65\x42\xef\xde\x48\x23\xe0\xc0\x03\x03\xc7\x40\x1e\x8d\xa4\xd7\x59\xb8\x59\xdd\xbb\x9b\xbb\x1f\xd2\xd7\x74\xed\xf4\x06\x18\x2c\xd3\x32\x6a\xdd\x37\x30\xc2\xb4\x83\x44\x1b\x08\x76\xe6\x92\xe2\x41\x2e\x13\xed\xe6\xab\x34\xe3\x54\x52\x0a\x39\x03\xdf\x67\xf1\x3a\xcc\xee\x83\x9d\x9a\x0f\xea\x6e\x42\x79\xed\xd4\xdd\xa8\x04\x77\x1d\xc6\x4c\xe7\x7d\x43\x17\x29\x8b\x1a\x73\xe7\x26\xc9\xce\xff\x44\xc2\xf3\x38\x73\x28\xe3\xe5\xcf\x0d\xd5\x79\xe5\x7e\x71\x9c\x55\xba\x24\xb2\xeb\xfc\x4a\xbb\x2b\x3a\x59\xab\xf1\x67\x54\x94\x40\x7d\xae\x10\x3e\xd8\x95\x50\x2e\xd7\x40\x95\xe9\xcd\x3a\x4c\x12\x2b\x4b\xf3\x44\x78\xb8\x2a\xf1\x5d\x98\x5d\xd3\x4f\x95\xe8\x0f\x71\x21\xe8\xb6\x62\xe5\xd1\x8b\x6d\x6c\x10\xb0\xc0\xce\xd6\xda\x54\x23\x9b\x50\x36\x9d\x54\x1d\x2d\xf7\x45\x9d\x7d\x61\x85\x7c\xf4\x0a\x17\x95\xe7\x31\x83\xf4\x0b\x13\x82\xd4\x5d\x0b\x99\xb5\x46\xaa\x99\x64\x57\x2e\x06\xfd\xf1\x23\xf6\x5b\xc3\x5b\x37\xbc\x5c\xfb\x48\xee\xda\x1f\x8d\x9a\x37\xf0\xec\x78\xf7\x4c\xad\xdd\x33\xc3\xda\xae\x23\x93\x06\x1d\xe9\x2c\xb4\x77\xcf\x70\xae\xb5\x12\x72\xaf\x4c\x6c\x29\xcf\xec\xaa\x31\xa4\xb8\xb8\x5c\x24\x34\xcc\x7e\x88\xd7\x34\xdd\x72\x87\x63\xe0\x24\xa7\xdc\x7c\x27\xc0\x4a\x43\xb1\xcc\x95\x59\xed\x9a\x0e\xca\x16\x90\x35\xec\xbf\x93\x71\xff\x01\x06\x2b\x13\x6d\xea\x42\x8b\x70\x13\xf3\x30\x11\xb8\x23\x4b\xbb\xef\xb4\xb7\xcf\xa7\xab\x30\x66\x34\x32\xef\xb6\x28\x76\xac\x4c\xd5\x08\x24\x63\x43\xf7\x1d\x44\xf4\x2a\xdd\xb2\x85\xaa\x24\x96\x11\x9b\x8c\x2e\x42\x6d\xe8\xfc\xc3\xfd\x46\x25\x25\x10\xe7\x2f\xb6\xb1\x46\x1f\x19\x95\xbb\xef\x20\xbd\x65\x34\xfb\x4a\x5b\x0f\xca\xd8\xad\x89\xfd\x49\xbd\x37\x23\xe2\x16\xee\x3b\xd0\xde\xbf\x44\xa5\x5f\x87\x0b\x9e\x66\xf7\x8a\x8f\x80\x9c\xf2\xd7\x74\x29\x3f\x96\xee\x3b\xd8\xb2\x9c\x8b\x25\xf8\x7e\x9b\xd3\xe7\x91\x8c\xbe\x17\x91\xb6\xf9\xb5\x8c\xdd\x80\x16\x91\xb3\x34\x11\x4b\x5a\xc4\xad\x44\x05\x39\x7d\x76\x23\x28\xa5\x3e\x06\x97\x09\x6b\x95\xf0\x75\x9a\x7d\x30\x8d\xdd\xa8\xa8\xe7\xf9\xd7\x96\x9b\x32\x99\x72\xe5\xbe\xb3\xb8\x1b\xc5\xa1\x08\xee\x46\x70\x95\x9a\xbb\xe9\x79\x17\x82\xbb\x61\x8e\xc0\x7c\x6b\x21\x26\xcd\x42\x65\x8d\x03\x54\xfe\xd5\x25\xf3\x33\xf6\x25\xf3\xc3\x9c\x51\x6f\x84\x61\x21\x38\x28\xbf\x5f\x5f\xd7\x8f\xaa\x6c\x49\x98\x33\xe8\xf5\x47\x56\xd1\x8d\xb1\x47\x84\xb4\x5e\x40\x19\xb8\x30\xa7\x37\x1e\x0f\x31\xac\xc5\x68\xfc\x8b\x1e\x86\x1b\x39\xd6\xfe\x00\xc3\xb5\xe1\xe4\xaa\xda\xee\x2b\xb9\xf8\x5a\x88\xf6\x6f\xb8\xd8\x36\x24\x5b\xcc\x67\xde\x1c\x32\xc2\x67\xfe\x1c\x52\x42\xf7\x7b\x66\x68\xc8\xf5\x09\x25\x80\x62\x83\x59\xbb\xad\x7c\xce\x55\x47\x90\x2f\x42\xbe\x72\xa5\x8b\x1c\xc7\xa7\xc3\xcf\xd5\x67\xc8\xa2\x74\xed\x60\x2c\x04\x2a\x98\xb1\xb9\x71\xdc\x7c\x25\xc6\x3c\xb9\x18\xe1\x02\x04\x1c\xff\x65\xb1\xe4\x60\x84\x69\x6d\xe6\x32\x37\xce\xdf\x86\x49\x1c\x19\x7a\x49\x71\xbb\x2d\x0f\x53\x2d\xd3\x27\x79\x74\x6e\xa8\xa3\x20\x83\xa3\xde\xe8\x71\x54\xd0\x48\x33\xed\x36\x75\x6b\x4b\x68\xbf\x37\xa6\xb8\x0d\xc4\x61\xec\xf7\xff\xe5\x51\x0a\xc4\x3a\x10\xbe\xea\x36\x64\x14\x1b\x19\xfb\x6d\x4c\x6f\xf7\x7b\x65\x81\x52\x14\x20\xf0\xe9\x31\xa3\x91\x76\x95\x0d\xa7\x9e\x53\xf5\xb0\x8d\xf4\x94\x6e\x34\x3b\xbc\x49\xe6\x10\x88\xf8\x1f\x98\xbd\x4a\xb5\xbd\x28\x89\x82\xd4\x6f\xeb\xe1\x41\x4a\x1c\x75\x2e\x05\x46\xfb\x9d\x19\x15\x5a\x65\x12\x80\x4d\x5f\xc5\x42\xcf\x2a\x54\x67\x52\xff\x26\x50\x3d\x21\xe1\xcc\x37\x12\xdf\x2c\x9d\xf2\x20\x56\x15\x19\x82\x53\x67\x06\xd3\xfd\x3e\x71\x28\x56\xb7\x36\xe6\x45\x01\x62\xb5\x3d\x6a\xb8\xe1\xe1\x70\x21\x6d\x7c\x1d\x4c\xdb\x0c\xc9\x3e\x7c\x17\xde\xa7\x5b\xae\xd6\x5c\x90\x55\xeb\xcf\x3a\xac\xae\x20\x55\x0e\xbf\xf2\x6a\x56\xd7\x48\xf3\x72\xe2\xa8\x3a\x39\x6c\x1e\x65\x75\x47\xda\xe4\xd7\x9b\xa6\xe6\xbb\xab\x67\x5a\x15\x14\xa4\x22\xa1\x3f\xf8\xc3\x40\x38\xa2\x75\xe1\xc1\xda\x3d\xad\x5d\xd7\x22\x38\x55\x7e\x45\x85\x2c\x5e\x37\xb5\x62\x78\x57\x29\xa9\x18\x86\x4a\xf3\xc6\x94\x7a\x93\x02\x97\x03\x10\x94\xe7\x51\x03\x58\x35\x0e\xa0\x7f\xd1\x1f\x0a\x0c\x3b\xf3\x40\x1b\x55\x29\x33\x06\xb2\xe3\xf4\x8e\x07\x67\x1e\xe4\x34\xcc\x16\x2b\x11\xda\x66\x89\xf8\xe1\x54\xfe\xd0\x75\x18\xcb\xc0\x26\xcc\xf3\xdb\x34\x8b\x44\x58\xb9\x74\x10\x21\x69\x92\x7e\xe6\xc1\x3a\x65\x5c\x96\xbe\xa5\xf4\x83\x2c\x1e\xaf\xa9\xc9\x60\xc2\xc8\x7c\x74\x93\x74\x11\x26\x28\x38\xf3\xac\x53\xfb\xad\xc0\x14\x2a\x9f\xf2\xf9\x3b\xbd\xdf\xef\xa9\x1b\x26\x5c\x87\x16\x3c\x4b\x64\xd0\x11\x63\xb0\x4e\x14\x16\x0e\xde\x85\xe4\xcc\xb7\x8e\x9d\x1c\xbc\x43\x5a\x42\x33\x0f\xe8\xdd\x88\xdd\x36\x4e\x62\x7e\x2f\x57\x57\xbb\x1d\xcb\x77\xd8\x6a\x35\x2d\x2d\x76\x51\xec\x62\x42\xc0\x16\x4c\x33\xbf\xb4\xde\x33\x4b\xdd\x75\xc8\x17\x2b\x9a\x3b\x28\x90\xf2\x62\xf7\x46\xfb\x1b\xb5\x5f\xce\x32\x86\x11\xfb\xbd\xc3\x88\xc3\x49\x8a\x25\xe9\x86\x33\x07\x3d\x7f\xf9\xfd\x8f\x3f\x08\x91\xd4\xc9\x08\x77\x79\x78\x2d\x69\xf9\x7e\x7f\x96\xcf\xd8\x7c\xbf\xe7\x6e\x46\xc3\xe8\x15\x4b\xee\xf1\x7e\x8f\x7e\x78\xf6\xf3\x0f\x4f\x5e\x3f\x7b\x22\x0d\xd6\xf5\x33\xce\x2a\x75\xbf\x3f\x3b\xe3\x6e\x9c\xeb\xa7\x1d\x9e\x45\xb1\x64\x62\xec\xa3\x16\x07\xef\x62\x31\xdf\xfa\x1a\x56\x8d\x1d\x4c\x30\x24\xe6\x7e\x96\xc5\x51\xda\xf8\x2b\xd0\xa4\xc0\xe0\x7b\x36\x8c\x56\xd5\xb1\x51\x5c\xe7\x63\x96\x90\xb2\x2f\x93\x6d\x66\xbe\x37\x52\xfa\x7d\x80\x4e\x19\xc6\x3c\x75\x97\x31\x8b\xbe\x7a\xf5\xe2\x65\x1a\x49\x23\xca\xf2\x8d\x45\xc7\xe1\x84\xd5\xb7\x2b\x69\xb1\x2a\xb9\xad\xef\xe2\x9c\x53\x46\x33\x69\xac\x17\xa5\xb7\x0c\xc1\x56\xbe\xe9\xc6\x1b\xb2\xac\xd3\x6d\x4e\x55\xa6\xc5\xc9\x4c\x9b\x54\x7a\x8c\xff\x54\x36\xcb\x1f\xc8\x03\xb9\x2a\x84\x5b\x48\xc3\x3c\x04\x91\xc8\x5b\x12\xa4\x02\xfa\x17\xc3\x93\x22\x8c\x59\xbf\xc3\xbe\x3f\x51\xeb\x77\x32\xea\xe1\x4b\xee\xbe\xd3\x9a\x1d\x6d\x35\x95\x3a\x7a\x8d\x4b\xcd\x97\x07\x99\xc3\x9c\x9e\xef\x4d\x70\xb9\xc7\x62\xe7\x50\x8f\x8c\x36\x21\x5f\x09\xd1\x3b\x40\x2f\xfc\x8b\x96\xdf\x5f\x75\x47\x37\xa3\x55\xb7\x77\xd3\x1d\x7d\x33\xbc\xe9\xf6\x56\xa3\xb7\xc3\x55\xef\x66\xb4\x1a\xdd\xf4\x3e\xa2\x02\x03\x7a\x12\x45\x48\xb5\x1e\x17\xe0\x8f\xc6\x27\xb9\x82\xff\x56\xbf\x7b\x5e\xcb\xef\x25\x5d\xdf\x1d\xf8\xf2\xcf\x77\x7e\xbf\xe5\x8f\x5c\x7f\xfc\x76\x20\x06\xe2\xf7\x5c\x7f\x9c\x74\x87\xee\x70\x22\xfe\x5c\x7c\x37\x10\xd9\x27\xad\x49\x6b\xd2\x9d\xe8\x21\x65\x59\x7a\xfb\x55\x7a\xcb\x84\x5c\x59\x0d\xee\x62\x78\x71\x72\x9b\xf8\x6f\x0d\x4e\x76\x56\x8c\xaa\xa5\x86\xe6\xb7\xc6\xee\xa4\xff\xb6\xe7\xad\x7a\x6f\x45\x28\x11\xe3\x6a\xc9\x71\x69\x38\x4c\xc4\xbf\x96\x3d\xb2\x1f\x37\xf5\x71\x8d\x7b\x17\x27\xf5\xd3\xff\x35\x64\xeb\xb5\x7a\x4f\x47\xee\x60\xdc\xea\xb5\x7a\x2d\x1d\xf0\x7b\xf9\x40\x84\x7c\xaf\xfc\xaf\xab\x23\xba\xbe\xf7\xc6\x1f\xbb\xc3\xbe\xcc\xd6\xea\x7d\x5c\x0f\x5b\x7e\x5f\x0c\xdb\x17\x83\x6f\xf9\x63\x11\xed\xf7\x05\xa4\x26\x12\x5c\xe3\xd6\xb8\xa5\xd3\x3c\xf9\xb7\xd7\x1a\xab\x24\xf9\x47\xe5\x57\x29\x32\xd7\x58\x14\x51\x45\x65\x2d\x22\x59\xd7\xa0\x60\xf9\x34\x64\x0b\x9a\x54\x60\x1c\x8d\xfb\x27\x39\xc7\xff\x1a\x18\xbd\xd6\xe8\xbb\x89\xec\xbe\xee\xb9\x04\x44\xd2\x1d\x08\xb4\x18\x48\xf8\x78\x2d\x7f\x92\x8c\xba\x23\x3d\x8a\x15\xbd\xc9\x52\xf6\x5a\xba\xae\x2a\xc7\xd2\x1f\x9d\xe4\x27\xfe\x8b\xe4\x67\x24\x51\x7c\x2c\x86\x33\xac\xa6\x47\xc4\xb6\x86\xad\xa1\x0a\x94\x93\x39\x6c\xa9\x9c\x2a\xf6\xa2\x9a\x7e\x15\xed\xab\xff\x54\x58\x4f\xa8\x86\x40\x92\xe6\xb4\x1a\x7a\x6f\x30\x3c\x79\xe8\xf0\xdf\x1b\xbb\xdb\x1f\x8a\xa1\x79\x83\xa7\xfe\xc4\x1d\x8d\x5b\x23\x8d\x98\xa3\x41\x4b\x90\x80\xd6\xa0\x75\xe1\xfa\x7e\x6b\xd0\x1a\xb9\xa3\x96\x8c\x1e\x8a\x22\x13\xd7\x1b\xb4\x7a\x6e\x7f\xd0\x9a\xb8\xfd\x51\x4b\xac\x18\xf7\xc2\x17\xbf\x83\x85\xd7\xea\xbb\x7d\xbf\xd5\x73\x47\x17\xad\x91\xf8\xb7\xf2\xfb\x8b\x9e\x3b\x16\xd9\x86\xdd\x9e\xdb\x1b\xb4\x86\xdd\x61\xcb\xeb\xf6\xdc\xd1\xa0\xdb\x73\xbd\x61\x77\xe0\x8e\x27\xdd\x81\x3b\x12\xa1\x8b\xd1\xc7\x17\xfe\xa0\xe5\xf7\x6f\x06\xab\xee\xe0\xa6\x3b\xf8\x66\x9c\x88\xfc\xc3\xd6\x70\xd5\xed\x97\xa0\xdc\x46\x3f\x6e\x92\x34\xb4\xc8\xcb\x70\xd0\x3f\x29\x62\xfc\xd7\x00\xea\xb7\xc6\xab\xde\x4d\x6f\xd5\xed\x7d\x5c\x7b\xad\x81\xdc\xc2\x44\xd8\xef\x5e\x08\xb2\x33\x31\x64\x67\x52\x92\x9d\xc9\x21\xd9\x99\x58\x64\xa7\x57\x92\x1d\xb1\x9a\x16\x22\xd9\x6f\x79\xdd\x49\x57\x90\x20\x41\x70\x73\x15\x68\x49\xda\xdb\x12\x1f\x72\x83\x51\x81\x8a\x1e\x3f\x67\xcb\xf4\x95\x72\x30\x68\x41\x6c\x32\x3c\x2d\x5b\xff\x17\x09\xf2\x64\xe1\xbb\x02\x77\x7a\x5d\xf7\xa2\xd5\xeb\xf6\xf2\xae\x7b\xd1\xed\xa9\x7f\x2d\x11\x6c\x89\x1f\x09\x39\x09\x88\xde\xa2\x2b\x0b\x94\xa9\xb9\x49\x2d\xab\x28\x6b\x10\xf9\x47\xff\x4a\x7e\x09\xae\x17\x69\x46\xdf\xd2\xcc\x26\x54\xe3\xb1\xf7\x7f\x0d\xaa\x51\xcb\xbf\x58\x0d\xde\x0e\xbf\x19\xdd\xf8\x83\x8f\xeb\x49\xd7\x1f\xdc\xf8\x03\x11\xb3\xea\x0e\x54\xc7\xbf\x0f\xb7\x36\x8d\x19\x8d\x86\xff\xe7\x4b\x62\xd2\x1a\xde\xf8\x83\xc4\xf7\xbb\x63\xdd\xc7\x24\xbc\x97\xfc\x81\xd5\xcf\x9e\xff\x7f\x0e\x5d\x7f\xec\x8e\x04\xad\xef\x0f\x9f\xfa\x23\xb7\xd7\x1a\xb8\x17\x2d\x7f\xe0\xf6\x7c\x4d\x08\xe5\xe2\xeb\xb5\xbc\xee\xd8\xbd\xb8\x10\x2b\x6d\xa2\x42\x72\x09\x8e\x5b\x93\x96\xfa\x5a\xf4\xdd\x71\xbf\xe5\xb5\x46\xee\x44\x10\xb7\xe1\xb0\x35\x76\xc7\xfd\xae\xa0\x02\xae\x37\x59\x74\xdd\x49\x4f\x10\xce\x7e\xb7\x2f\x48\xe8\xa0\x3b\x14\xad\x0e\xba\x92\x64\x7a\xdd\x91\x20\x8a\x17\xdd\x51\x77\x94\xab\x40\x6b\xd4\x1d\x2d\x7c\x77\x24\x88\x67\xdf\xf5\x07\x82\xa8\x0e\xdc\x5e\xaf\xe5\xbb\xe3\x89\xe4\x38\xfd\xd5\xf8\xed\x20\xe9\xf6\x04\x59\x16\x7f\x14\x90\x5f\xd3\x65\x46\xf3\x95\xc5\x31\x8f\x7b\xff\xf7\x9c\x7e\xab\xe7\xaf\x7a\xbd\xef\x7c\x49\xd6\x5a\x3d\xff\xe3\xda\xef\x75\xfb\x92\xed\xef\x09\xb2\xf9\x71\xed\x75\x25\xf3\xdc\x15\x94\x53\xe3\xf4\x4f\x61\x26\x5d\x05\x55\x3b\xa7\xef\x9d\xe4\x23\xb5\x61\xbf\x52\x17\x59\x0f\x5a\xa3\xf7\xef\x69\xfe\x22\x8d\xb6\x09\x45\xa0\xed\xe5\xcf\xbc\x02\xc3\xc9\x02\xe6\x18\x17\x76\x94\x6d\xd7\xea\x49\xba\xe0\xcc\x3b\xf1\x4a\x7e\xe6\xd6\x4e\x1a\x0a\x4b\xff\x31\x19\xf7\x7d\x5c\x40\x7f\x32\x3a\xb9\xdf\x37\x9c\x16\x95\x26\xaa\x4c\xdb\x95\x9b\x3b\x3b\x9b\x5c\x5a\xa4\xf2\xfd\xfe\x8c\xab\xef\x2a\x34\x63\xe5\x7d\x88\x4c\x99\xfb\x43\x48\xaa\x34\x79\xcf\x29\x55\x57\xb6\xab\xab\x3e\xb3\x54\xbe\x5b\x20\x4d\x2b\xe4\xfb\x1b\xa5\x13\xf9\x06\x4b\x89\xc9\x69\xde\xf3\xb4\xd6\x72\x20\xb0\xc9\xd2\x5a\xfe\x67\x6e\x38\x59\xf6\xc9\x0a\x48\xa5\x35\xb2\xba\x62\x51\xd9\x5f\x9e\x55\xf7\x29\x8e\xdf\x69\xe2\x8d\x97\x42\xd8\x89\x4b\x21\x4c\xf9\xb2\x48\x95\x5f\x09\xa3\xc2\xe7\x33\x3a\x07\xd4\xaa\x6e\xf9\x30\xe9\x9e\xa2\xc0\x18\xd2\xa2\x80\xe1\xc5\x69\x56\xef\x61\xbd\x9f\x3e\x72\x4f\x49\x76\x70\x79\x47\x9e\xd3\xdb\xba\xc0\xba\x22\xd0\x64\x4b\xb1\x6a\xfe\x71\x2a\xf4\xb8\xd1\xbc\xc5\xf7\xbc\x1e\x3e\x50\xa5\x56\xaa\x7c\xeb\xdd\xa2\x52\x87\x88\xdb\x6d\xa9\x8f\xce\x79\xb6\x95\x6e\x0a\x88\xbe\x52\x57\xe9\x70\x62\xfb\xec\xf6\x08\x0f\x7a\x8d\x78\xd0\xb3\xf1\xa0\x37\x0f\x76\x8b\x24\x65\x72\x19\x8b\x7e\xba\xf2\x6b\x6a\xdf\xe7\xc6\x41\xf9\x4a\x4c\x28\x7b\x15\x3a\x1c\xb7\xdb\xf6\x3c\xf3\xa6\x79\xce\xf0\x0e\xbd\x7f\x2f\xdf\x20\x79\xff\x1e\xe9\x9b\x9e\xa1\x23\xfd\xa6\xb4\xdb\xea\x5a\xec\x34\x9d\x65\x73\x12\x3b\xea\x4e\xac\x72\x74\x1b\xc8\x38\x99\xcd\x4c\x7d\x6f\xf2\x18\x93\xac\xda\xd3\xc1\x68\xc5\xf9\x26\x0f\xce\xcf\xd7\x21\xa7\x59\x1c\x26\xdd\x6d\xec\x2e\xd2\xf5\x79\x75\x61\xaf\x2b\xcf\xf8\xcf\xa7\x8b\x34\xa2\x04\x75\x04\x91\xf0\x2f\xd9\x5f\x0e\xe1\x78\xc9\x3a\xc4\xc7\xbc\x43\x50\x3b\xcc\xae\xf3\xd9\x5c\xe4\x65\xa2\xd0\x8f\xaf\x9f\x97\xcb\xc3\xb1\x6d\xba\x4a\xff\x75\x2f\x62\x16\x2f\x63\x1a\xb5\x5e\x98\x5e\xfc\xf8\xbc\x25\x9b\x6d\xfd\x09\x75\x68\x07\x5d\xb6\x6e\xe2\x3c\xe6\x2d\xd4\xe1\x1d\xd4\x5a\xa6\x59\x8b\xaf\x68\x6b\xb9\x4d\x92\xd6\x9a\xe6\x79\x78\x4d\x5d\xd4\x40\x41\x06\x83\xbe\xdf\xec\xb3\xeb\xb2\x7a\xc7\x3b\xc5\xc7\x1b\x54\x08\x31\x39\xff\x67\x77\xea\x4c\x83\x5f\xa3\x8e\xf8\xeb\xfe\x1a\x7d\x8e\xa7\x7b\xf1\xdb\xc1\xce\x34\xa0\xb3\x4e\x77\x3e\x15\x1f\xd3\xcf\xce\x63\x48\x88\x3c\x4a\x5b\xd0\x38\x81\x5c\x85\x97\x49\x9a\x66\xb0\x25\x68\xf6\x65\x7c\xfd\x52\xaa\x8f\x95\xd5\xdd\xbc\x85\x60\x41\xb6\x1d\xa4\x23\x37\x59\xbc\x96\xbe\xe7\x5a\xab\x30\x6f\xad\xd3\x8c\xb6\xf8\x2a\x64\x2d\x7f\xd8\xca\xe3\x6b\x01\x99\x45\xc8\x78\x2b\x8a\xaf\x63\xfe\xff\x33\xf7\xa6\xeb\x6d\xe3\xda\x82\xe8\xab\x48\xe8\x84\x01\x4c\x90\x26\x6d\x27\x4e\x28\xc3\xea\x0c\xce\xde\xe9\x9d\xd8\x3e\x89\xb3\xeb\xec\x92\x55\xde\x30\x09\x49\x2c\x53\xa4\x8a\x04\x3d\xc4\x54\x3f\xcb\x7d\x96\xfb\x64\xf7\xc3\x02\x38\x68\x70\xaa\xce\x3d\xfd\xa3\xeb\xab\x58\xc4\x3c\x2d\x2c\x2c\x2c\xac\xa1\x08\x7a\x88\x46\xcc\x17\xfe\x01\x9d\x30\xff\x80\x2e\xd8\x1b\xcf\x3b\xf4\xdf\xbc\xd9\x7b\x79\x70\x78\xe0\xbd\x79\xe3\xd3\x19\x1b\xf9\xd4\xf7\xa8\xef\x79\xd4\x17\xfb\xd4\x17\x07\xd4\x17\x2f\xa9\x2f\x5e\x51\x5f\x1c\x52\x5f\xbc\xa6\xbe\x78\x43\x7d\xa1\x32\x09\xdf\x57\x7f\xf6\xd4\x9f\xfd\x31\x9d\x33\x95\xe5\x96\xad\x28\xea\x4d\xdb\x93\xc2\xab\x1a\x30\x17\xc7\x5e\x55\x09\xb0\x4d\x24\x03\xe9\x74\x18\xd2\x0f\x2b\x40\x46\x53\x9a\x33\x1f\xd8\xcb\x46\x6e\x80\x83\x31\x14\x1b\xa1\x41\x7e\x94\x0d\x74\x56\xc9\xc4\x28\xb7\x6d\x15\x4b\x53\x36\x69\x74\x6d\x07\xa9\xe3\x0c\x24\x43\x1e\xb2\x25\x19\x70\x9b\xc9\x25\x9c\x2c\x8c\xd7\x19\x0e\x5e\x83\x62\x43\x38\xe3\xf9\xfb\x2c\x12\x6f\x25\x76\x9c\x8c\x0c\x5a\x6f\x73\x46\x6e\xd1\xa3\x99\xed\x57\x95\xdf\xb5\x16\xbb\xa2\x44\x00\x5d\x0c\xe1\x14\x0b\xb5\xd2\x15\xc8\xd6\x17\x20\x64\x2b\x68\xc9\xa4\xab\x35\xae\xe2\xaa\xea\x27\xeb\x46\x60\x52\x96\x59\x56\x3f\xd3\x6f\xb5\xdc\xb2\xfa\xf0\x96\x95\x56\x55\xde\xe4\x1c\xe6\x43\x2f\x70\x92\x20\x06\x73\x34\x7d\xd6\xd4\x11\xeb\x0a\xe2\x23\x8f\xe6\xac\x60\xac\xa4\xa0\x8b\xc8\x9b\x03\x76\xe8\x05\xfd\xec\xb7\x14\xf4\x91\x57\x8c\xc2\xf5\x8a\xe3\xb2\x8e\x57\xf3\x92\x30\x5c\xb0\xda\x30\x1c\x39\xc2\x65\x33\x4f\x64\x58\x04\x25\x8d\x99\x37\x88\x8f\x92\x41\xac\x4d\xc6\x65\xa3\x78\xdc\x67\x7c\x14\x37\x67\xb9\x8a\x39\x56\x11\x75\xad\x75\x3b\x8c\x95\x43\x2f\x68\x9b\x6b\x67\xf1\xae\x35\xcc\xa3\x0e\xc3\x23\x59\x55\xe2\x38\xad\x2a\xd1\x67\xac\xc0\x82\x18\xb1\x53\x2d\x72\x5a\xda\x38\xaf\x2a\xf4\xd6\xe0\x01\x44\xec\x4d\x7b\xd9\x62\x58\x57\x32\x44\xbd\xac\x94\xbd\x6c\xd2\xcb\x79\x3a\x15\x41\x0f\x05\xa8\x97\x66\xb2\xc7\xd3\x5e\x9c\x4a\x31\x15\x79\x27\xae\xb3\x95\xcc\x7b\x4d\x0f\x11\xbb\xf1\xd1\xd4\x59\xf8\xfb\x95\xd7\xcc\xd6\xc3\x7c\xfd\xae\x8e\x85\x2b\x76\x27\x04\x34\x98\x85\x1b\x8e\xe4\xf8\xf9\x5e\x9f\x79\x6d\x05\x27\xdd\x07\x31\x2c\x1a\x19\x9b\x61\x47\x7e\xd6\x46\x2e\xea\x48\xcd\x06\x82\xd8\x58\x1e\x79\x43\x24\x50\x80\x84\x8d\x88\xdd\x39\xa4\x6e\x56\xf0\x13\x05\xd3\x7f\xf2\xc8\xd3\x9b\x23\x63\xa9\xaa\x6c\x60\xdb\x72\x90\xd9\x2c\x25\x03\xc1\x32\x5b\x2c\x6b\x0b\x58\xb6\x2d\x8f\x71\xde\x6c\x30\xd2\x94\xa2\xd2\x61\xf9\xc0\x71\x9a\x62\x36\xcb\x74\x29\x79\x94\x83\x45\x07\xd1\xec\x0e\xb9\xda\x61\xd9\x91\x09\x5e\x72\xb6\x6a\x20\xa1\xd9\x31\x94\xd3\x6f\xf4\x3d\xfd\x95\x9e\xd3\xaf\xf4\x8c\x5e\xb0\x67\xad\x3f\x2d\xf6\xd8\x39\x97\x83\x67\xb4\xb6\x51\xae\x15\x0c\x81\x2e\x3e\x9b\x18\xd5\xc2\x53\x10\x25\x7a\x86\x7d\x42\xaf\xd8\x9e\x47\xbf\xb0\x03\xfa\x89\x39\x87\xf4\x2d\xdb\xf3\xe9\x67\xe6\x28\xb4\xf4\x03\x90\xd3\x07\xd6\xf7\xe9\x47\xe6\xd3\x77\xcc\xa3\xbf\xb3\xc7\x85\x16\x9f\x47\x88\x82\x35\x49\x10\xf6\xda\xa7\x8d\xc4\xdb\xdf\x9a\x48\xcf\x64\x10\x0b\x9e\x83\x86\x06\xa2\x88\x46\x22\x8c\xe7\x3c\xe9\x44\xba\x88\x4e\x72\x2d\xad\xd6\x2d\xbb\x1a\xd7\x66\xff\x7f\xff\x1f\x44\x8b\x72\xa2\xbb\xb0\xa4\xbf\x30\xe4\xf9\x7b\xfb\x07\x2f\x5f\x1d\xbe\x7e\xc3\xaf\xc3\x48\x4c\xa6\xb3\xf8\xf7\x9b\x64\x9e\x66\x8b\x3f\xf2\x42\x96\xb7\x77\xf7\x0f\x3f\x3a\x47\xf2\xb3\x2e\x12\xe2\x34\xa1\x25\x8d\xe8\x8c\xce\xe9\x2d\x9d\xc2\x63\x1e\x6c\x78\x3c\xed\x3a\xa4\x7e\x46\xba\xe6\xa2\x74\x0d\x83\x8e\x3d\x7d\xd8\x88\x96\xd5\x07\xcb\x1d\xee\x55\x5c\x34\x67\x10\x69\x44\x47\x0a\xc0\x70\x8a\xf6\xc1\x7d\xe1\x86\x55\x25\x5c\x71\xfc\x63\x38\x75\x43\x36\x75\x05\x3c\x97\x06\xc2\x15\x47\x9f\x21\x6a\xa4\xe2\xbc\x71\x80\xd5\xaf\x42\x87\x2a\x52\xed\x1d\x0d\x2d\x84\x40\xfb\x78\xc6\x36\x77\x33\xb1\x2c\x6f\x47\x30\xe6\x41\xb7\x54\xc3\xfe\xae\x38\xf2\x86\x58\x30\x47\x50\xc7\x27\x81\x4f\xd5\x39\xf2\xbf\xff\xb7\x39\x36\x4a\xe6\xd1\x88\x89\x41\x74\xcc\x7c\x6f\x10\xed\x32\xdf\xa3\xa5\x6d\x37\xf0\x08\x7d\x2e\xd7\xfb\x0a\x3d\x2b\xa1\x5f\x9a\x22\xbe\x65\xcd\xd6\x07\x98\x07\xe3\x5d\xb1\x36\x00\xdc\x49\x6b\xa6\x32\xc3\x53\x7a\x4b\x67\x64\xa0\xba\x78\xf0\x92\xb1\xdb\xee\xa1\xe2\x91\x21\xbe\x65\xb7\xcd\x76\xd6\x1d\x5f\xe2\x92\xdd\xb6\xc6\x02\x5c\x44\xc8\xb1\xe3\x5b\x16\x64\x6d\x4c\x07\xbb\x60\x34\x98\x50\x1c\xa9\x0a\xe0\xdd\x19\xef\x8a\xdd\x98\x90\x63\x6f\x88\xcb\x23\xcf\xb2\x70\xc9\x22\x42\x4b\x9b\xd9\x75\x13\x91\xed\x13\x0a\x2d\x76\x4c\xe8\x46\x84\x04\x75\xfe\xdb\x7a\xbb\x37\xa3\xbb\xc3\x92\xee\xd1\x5f\xea\x73\x16\xbd\xe3\x85\x40\x84\xfa\x5e\xc7\xc7\xc2\x1f\x78\x6a\xf6\x9a\x20\xf4\xca\x9e\xba\xc2\xf6\xe9\x17\x58\xbd\xce\xa4\xd0\xad\x0b\x09\xa6\x66\x76\x44\x9f\x79\x6b\x73\x66\xc0\xaf\xb3\xb6\x9b\x53\x45\x9f\xb9\x1f\x4e\xde\x7d\xff\x9b\x65\xb5\x33\xb3\xfb\x9b\x77\xe9\x7a\x3b\xd5\xa5\xbb\xab\x66\xa8\x41\xa3\x2f\x57\xce\x8c\xd0\x36\x2b\xd8\xab\x57\xe6\xaf\x2c\x0d\x9c\x87\x29\xfb\xa5\x83\xe0\x68\xc9\x22\xe6\xd1\x79\x33\x75\x83\xe8\x68\x3e\x88\xf4\x59\xd8\x3a\x8a\xe3\xa6\xfa\xb7\x12\x47\x84\x1c\x69\xb8\x45\x2e\x62\x8c\xc3\x67\x74\x5c\x92\xc7\x92\xcd\xd5\x8d\x49\xc6\x69\x29\x96\x0d\x26\xee\x27\xb0\xf6\xec\x76\x55\x79\xc2\x00\xc4\x8a\xe3\x3c\x52\x55\x26\x63\x27\xb2\xc9\xd8\x29\x4c\x08\x79\x4c\x58\x5f\xed\x09\xc7\xa7\x25\xf3\xda\x76\x3b\xab\xd0\x59\x3a\x2a\xc9\x72\xa6\xb0\x24\x2e\x19\xbe\x65\x39\xbe\xa5\x52\x51\x84\x53\xb7\x20\x64\x03\x58\x87\x5b\x40\x35\x68\xa1\x0b\xc8\xad\x88\x79\x9a\xce\x5a\x99\xf7\x88\xc0\xdc\xc1\x44\x77\xe6\x74\x33\xa3\xe3\xcc\x15\x41\x06\x20\xd6\x80\x37\xb5\xed\x39\x81\xf9\x9c\x3b\x2c\xa2\x33\xcb\x6a\x00\x64\x7e\xec\xbf\x54\xa7\xd3\xf1\xa2\x43\x45\xac\x81\xc4\xd4\x2d\x76\x84\x46\x3a\x25\x2b\x9d\xc8\xf1\xc9\xf1\x0f\xd2\xc5\x08\x8d\x81\xc8\xf2\xe8\x33\xe9\xe0\xb0\x41\xbd\x5d\x3a\x08\x63\x4c\x23\x86\x4b\xdb\x27\xcf\x27\x54\xef\xaf\xc8\x66\x13\x42\xa3\xa3\xb9\xc6\x49\x91\x65\x4d\xdd\x10\x0c\xc8\xe2\x66\x8b\xc2\x7e\xa4\x73\x87\x4d\x00\x90\xc8\x66\x8e\x88\x42\x3d\x64\x10\xb1\x89\xd3\x1d\x3d\xa9\x81\x5d\x83\x4e\xe4\xb0\x39\xcc\xe3\x20\x72\x9c\xc1\xad\xad\x08\x5e\x85\x88\x9a\xfa\xc8\xb2\xde\x01\xcd\x38\x5a\xe2\xe1\xfb\x9a\x69\x44\xca\x69\x4c\x13\x5a\xb4\x47\x42\x3a\x4c\xd9\x97\xe0\x0e\xa7\xd4\xa3\xaf\x09\x55\x08\xbf\x31\x49\xd3\x71\x1e\xa2\x0a\x00\x15\xac\x68\xd7\x18\xf0\x7c\x7d\xa4\x14\xec\x01\xab\x52\xb4\x60\x3e\x63\x79\x55\xed\x19\xab\x44\x47\xec\x53\x55\xc5\xc7\xec\x2d\x19\x9e\xe0\x82\xc6\x24\xb8\x51\x3f\x14\x46\x50\x2f\x01\x67\x58\xb0\x3f\x70\x83\x78\xc0\xe5\xbf\x2b\x28\xd0\xab\xba\xe2\x7a\x42\xe8\x4a\xf5\xf2\x88\xf1\xaa\xe2\x47\xec\x93\xa1\x6a\x06\xc9\x91\x1c\x14\x30\x41\x34\x51\xd0\x57\x30\xd5\x2c\x27\xcd\x1e\x94\x0e\x8b\x69\xc1\x54\x2f\x38\xf4\x82\x72\xdb\x3f\x4e\xb4\xb9\x16\x47\x1e\x7b\x60\x6e\x4e\x55\xe1\xa2\x81\x74\x1c\x53\x1b\x19\x34\x35\x60\x69\x33\xee\x24\xc4\x64\xe5\xb6\xcf\x98\xda\xd8\xba\x0c\x59\x29\xd4\xda\x2f\x56\x60\x93\x81\x97\xca\x22\x28\x3a\x86\x77\xd7\xcc\xe3\x99\xdb\x90\x99\x8a\x91\xa7\xee\xc1\xad\x4d\xb0\xdc\xb6\xb5\x95\x49\x9c\x36\x59\xf2\x31\x21\x6e\x41\x1e\x33\x96\x1a\xcf\x26\xd2\x0d\x79\x92\xe0\x8c\x82\x55\xd3\x8c\xb5\x72\xd1\x1d\xc3\x76\x7f\x5f\xf7\xc2\xab\x1b\x6e\x6e\x56\x7d\x39\x72\x9c\x6c\x3c\x90\xee\x22\x5b\x60\xa2\xf7\x71\x06\xe2\xa6\x83\x0c\x8e\xde\x0c\x8e\xde\xbc\x3d\x7a\x71\xca\x72\x3b\xdd\x99\xc0\x66\x53\xb4\xae\x02\x11\x7d\xfc\xa6\x47\x9f\x21\x62\x24\x0c\xa1\x00\x29\x54\x45\x49\x42\x3b\x06\x30\xfe\xd8\x06\xac\x25\x0d\xe9\x42\xd1\x3c\x70\x05\x9b\xb2\x19\x20\x0b\xf2\x08\x12\xfc\xaa\x57\x0a\xf1\xdd\xaa\x9e\x95\xd0\xb3\x12\x7a\x96\xa9\x9e\xa9\xf5\xe2\x4c\x3a\x99\xc2\xd4\xdc\x66\x13\x1a\x33\x49\xe7\x0c\x87\xec\x76\xb4\x60\xde\x98\xec\x4e\x47\x99\x13\x3b\xfe\xf8\xb9\xef\x55\x5e\x03\x93\x78\xc1\x12\xac\x16\x97\xec\x4e\x08\x39\x6e\xcf\xd3\x47\x7d\xc3\x82\xa9\x36\x16\x9b\x06\x75\xe2\x11\x5b\x0c\x6e\xf5\xa6\xf4\x08\x19\x84\x6c\xce\x3c\xaa\xba\x17\x33\xcc\x9f\xb3\x09\x71\x26\xb6\xaf\x0f\x64\x55\x2e\x64\xaa\xdb\x8b\xb1\xca\xb2\xd9\xf5\x39\xc3\x9d\x62\x6a\x00\x43\x2f\x08\x57\xbb\xbb\x8c\x27\x38\x57\x1b\x42\x1e\x79\x55\xa5\x65\x85\x6e\x47\x0b\xdb\x1f\x57\x15\x8e\x8f\xbc\x61\x18\x84\xcf\xeb\x12\x84\xe6\x2c\x3d\x3a\x18\xe2\xb9\xba\x77\x5a\x16\xf6\x18\x4b\xab\x2a\x65\x0c\x03\x80\x0e\xf7\x83\x3d\x42\x82\xf9\xf1\xcb\xaa\x7a\x09\x5a\x42\xf8\x00\x72\xe4\x55\xf5\x4a\x1b\x23\xe3\xc7\xde\x30\x3e\xf6\x86\xa6\x1b\xe3\xc0\x0b\x6e\x47\x0b\x55\xf7\x73\xdf\xb3\xfc\x6e\x65\xaf\x83\x43\x42\xa8\x3c\xf2\xab\xaa\xaf\xd6\xa6\xc6\x28\xf5\x5c\x31\x8f\xe6\x43\xb5\x1d\x05\x10\x19\x2a\x0b\x9b\x8e\xf0\xc4\x91\xcf\x27\xe4\xf9\x64\x4c\x15\x88\x38\xb2\xaa\x3c\x12\x40\x22\x80\x0e\x15\xc6\x2a\x07\x1f\xe2\xa6\xa6\x05\x2d\x99\x4f\x17\x8e\x43\x82\x4e\xa4\xad\xa0\x62\x3a\x9a\x38\x7c\x4c\xd5\x2c\x33\xd5\xf1\x02\xd7\x5d\x7f\x3e\x55\x17\xdb\x9d\x32\xf0\x08\xcd\x61\x27\x0f\x06\xb5\xb9\xbc\x85\xde\x16\x1c\x56\x0e\x00\x2b\x86\xd5\x89\x61\x75\x78\x7d\xac\xe9\x34\x9b\x95\xaa\xfd\x95\x2c\x40\x90\xf2\x3e\x2b\x41\xfe\x56\xd8\xb6\x1e\x1f\x8b\xd4\x11\xae\xbe\x7c\x42\xcc\x6e\x55\xa0\x3c\x5a\x40\x2d\xea\xb7\xcf\x22\x0d\x5b\x03\x35\xb1\xce\x18\xac\x57\xf9\x4b\xdd\x9d\xe6\x14\x55\xa4\xfb\xed\xc8\x71\xf8\x58\xc1\x9b\xde\xa0\x4b\x4d\xa2\xaf\xec\x3b\x20\xd1\xb5\x0c\x70\xbd\xf7\x5a\xe7\xc6\xed\xae\xfb\x47\x57\x04\x4d\xb8\x0d\x17\x47\xa3\x77\x96\x0e\xbb\xc7\x40\x80\x65\x8d\xed\x25\x4b\x01\xc1\xa7\xc7\xec\xed\xf0\x04\xc4\x34\x83\x1b\xf5\xa3\x31\xab\x06\x04\xe3\x99\xb7\x69\xf7\x99\x66\x90\x32\x41\x9f\xb9\x5f\xcf\xbe\x9f\x7e\xb8\xfa\x7e\xce\xbc\x26\xf0\xe1\xec\x97\x53\xe6\x37\xc1\xf7\x27\x9f\x3e\xb3\xbd\x26\xf8\xf1\xf3\xd9\xd9\x57\xb6\xdf\x84\xff\xfe\xf6\xf3\x47\x55\xfe\x60\x35\x06\x2a\x79\xb9\x1a\x77\xf2\xcf\x93\x53\xf6\x6a\x35\x0e\x6a\x3f\x5c\x8d\xd3\x4d\xbc\xa6\xcf\xdc\x93\xef\xef\x3f\x7f\xfa\xc0\xde\xd0\x67\x6e\x98\xa5\x93\x78\xca\x9e\xb9\x85\x58\x35\x77\x67\x66\xad\xb5\x6a\x6d\xf4\x6b\x0d\x37\x7a\x43\xbf\xb6\x66\x74\x20\xcd\xfc\xed\x89\xfb\x05\x38\x60\x0f\x7a\xc8\xd6\x14\xcb\x86\x67\x64\xc9\xd0\x87\x93\xf7\x9f\xbe\xbc\xfd\x7c\x75\xfe\xf9\xed\xfb\x93\x6f\x48\x6d\xde\x3b\x9c\x32\x31\x92\x63\xea\xd1\x5b\x45\xbd\x5e\xb1\x54\xcd\xf8\x66\x59\x18\xda\xa7\xd3\xbf\x5d\x7d\x39\xfb\x70\xb2\x5e\xf4\xb5\x2a\xfa\xe5\xa9\xa2\x27\xff\x79\x7e\x76\x7a\x72\x7a\xf1\xe9\xed\xe7\xab\xb7\x17\x50\xd6\x14\x25\x96\x95\x2a\xc0\x1b\xaa\xca\x14\x3d\xe0\xdc\x52\x20\xa2\x55\xd0\x6f\x3a\xf5\x89\x41\xe2\x5b\xa6\x22\x49\xa0\x32\xab\x9c\x26\xcd\xc1\x6f\x59\x7a\xe4\x0d\x9d\x34\x48\x09\x79\xa2\xf7\x6f\x4f\xff\x76\x82\x88\xa2\xc1\xd7\x9a\x26\x6d\xcb\x8e\xdf\x69\xda\xd7\xd5\x7f\xd6\x4d\xff\x80\xa6\x07\xed\x25\xa8\xed\x40\x3f\x5d\x5b\x13\x69\xa3\x5e\xc8\xd3\x34\x93\xbd\x6b\xd1\xfb\x21\xf2\x4c\xad\x4a\x4a\x06\x9f\x99\x83\x7f\xb4\x5d\x5d\x3e\xb1\x4a\xef\xbf\xfe\xeb\xfc\xe2\x0c\x69\xba\xb5\xee\x6d\x9f\xb1\xfe\xd6\x96\x54\x33\x32\x2f\x45\x2f\xcb\x7b\xa0\x61\x69\x1a\x03\x4b\xb3\x00\x43\x5b\x2c\x54\x86\xf9\xc3\x42\x66\x55\xd5\x5f\xfb\x00\x93\xbc\xa0\xab\xa1\x5d\xf6\x5b\x56\x9d\xa0\x35\x38\xde\x3d\x48\x51\x98\x4e\x7c\x60\xfd\x94\x36\x70\xa8\xb3\xf5\xca\x94\xdf\xf2\x38\xe1\x20\xbc\x3b\xf8\xc0\x52\x4d\xef\xa8\x8f\x27\x46\xfb\xe5\xec\xc3\xf7\xcf\x67\x5b\xa1\xea\x8d\x9a\xde\x8f\x4f\x41\xd5\xf9\xd9\x2f\x57\xe7\x5f\x4f\xde\x7f\xfa\xf6\xe9\xec\x74\x2b\x2c\xbf\x7b\xaa\xe8\xc7\xb3\xaf\x5f\x14\x20\x6e\xdd\x63\xf5\x8c\x3f\x31\xd7\x3c\xed\xe9\x02\x66\x9e\x7f\x7f\x7a\x68\x6f\x3f\x9f\xff\xfd\xed\xbb\x93\xa6\xa1\x35\x65\xf9\xba\xa1\xaa\xda\xfd\xcd\x1d\x3e\xab\x46\xf6\xa5\xe3\x5e\x16\xe3\x0a\xbb\xc4\xdd\xb9\xf4\x8d\x1f\xa1\x74\x5b\x4f\xe2\xf4\x96\x27\x71\x64\xfa\xf0\x0b\x4b\x6b\x6b\x9c\x8f\xab\x7b\x3c\xb8\xa2\x2b\x1b\x37\xf8\x42\x57\x77\x63\x30\xfa\x44\xdf\x8e\x29\xec\x8f\x60\xf4\x99\xfe\x18\x53\x0d\x7f\xc1\x07\xda\x59\x9a\xe0\x23\x5d\x99\xef\xe0\x1d\xd5\x93\x18\xfc\x4e\xeb\x61\x06\xbf\x2c\x97\xf4\x99\xdb\x61\x04\xad\xbb\x6b\xef\x8b\xaa\xea\x7b\xfd\x27\xf8\x45\xda\x4f\x52\xdf\xdc\xd0\xea\x48\xfd\x58\xaf\x39\xfc\x8a\x6e\xcb\xe0\xc6\x00\x16\xcc\x06\x22\x50\xd3\x3a\xd2\xeb\xa1\x95\x04\xc7\x88\xb1\xc7\x65\x73\xce\x68\x1a\x36\x37\x7b\xc9\x67\x4c\x51\xfa\x0e\xfc\x12\xcb\xca\x8e\x99\x73\x6b\x59\xd9\x11\x53\x7f\x99\xba\x04\x66\xa4\x31\x76\x9b\x2b\x72\xa3\x0e\x64\x96\xe5\x83\xd1\x46\x43\xbf\x35\xbd\x33\x14\xdc\x12\x48\x7a\x86\x33\xb8\xdf\x91\x23\x5f\xdd\x2b\xe0\x7a\x67\x0e\x3c\xa8\xad\x31\x01\x2a\xeb\x17\x09\x6f\x20\x5b\x0b\x9c\x52\x73\x09\x14\x05\xac\x00\x03\x88\xb1\x63\x16\x55\x55\x0a\x17\xd4\x94\x34\xf4\xa2\xea\x55\x9f\xb1\xb4\xe9\xc7\xb2\xe5\x0f\x98\xe3\x36\xaf\xd5\x23\xc0\xf2\x90\xf9\xe4\x55\xb5\x3a\x09\xed\x40\xd6\x0e\x96\x4f\x1a\xc2\x7a\xcd\x2a\xe9\xa3\x45\xad\xf0\x9c\xdf\xc7\xf3\x72\xce\xe0\x6b\x8b\x4d\xcc\x7f\xb6\x4f\x70\xf4\xc2\x4d\xa4\x2e\x14\xa7\x75\xa1\x38\xfd\xd3\x42\x53\x5d\x48\x63\x1d\x86\xf9\xfa\x13\xd4\x1e\xfd\xc6\x56\x34\xcb\x76\xb8\xb5\xe7\xbd\x39\xf4\x5f\xfa\xc3\x2d\x46\x3a\xf1\x5a\x5e\xb2\xdc\x22\xf3\xf0\x7a\xff\xf5\xeb\x57\xde\xeb\x1d\xec\x7b\x87\xfb\x87\x07\xfe\xeb\xbd\x83\x55\xed\xb5\xca\x23\x36\xae\x73\xad\xa7\xac\xd9\x34\x6e\x55\x1e\xd4\xdd\x83\x79\xd4\x30\x00\xf4\x7d\xeb\xb4\xc3\x49\x15\x43\xc1\xae\x82\x3b\x2c\x14\xda\x22\x34\x63\x09\x16\xbb\x13\x42\x3f\x28\x50\xd8\x8e\x96\x6b\xe0\xd9\x9e\x0a\x37\xe0\xef\x71\x2a\xf7\xf7\x8c\xfb\x9f\x1d\xb6\x47\xc8\x20\x3e\xca\x06\x44\x51\xa3\xfb\xbe\x77\xb8\xb7\x23\x47\xf1\xd8\xc6\x72\x14\xdb\xfe\xf8\xf8\xf8\xd8\xf7\xd5\xfd\xe4\x8d\xf0\x5f\x0e\x71\xfa\x57\x6b\xde\x53\xb4\xf9\x28\x1e\xeb\x43\x52\xd7\x55\x1f\xd2\x86\xad\xc0\x9f\xfb\xc2\x3f\x20\x34\xb6\xd9\x1e\x19\xc4\x2c\xdb\xdd\x6b\x39\xa5\x3f\x3b\x5c\xfc\x3f\x39\x5c\x56\xa6\xa0\x53\x83\x1a\xee\x61\x3b\xda\xbd\xd7\xfe\xc1\xe1\xc1\x9b\xc3\x57\x87\xbe\xf7\xea\xe5\xab\x1d\xbc\xef\x5b\xaa\xcb\xc4\xf6\xbd\x37\x6f\x5e\xfa\xfe\xab\xbd\xc3\xc3\xc3\x57\x3b\xba\xf3\xf6\xc1\xde\x9b\x83\x37\xaf\x0e\xf7\xde\xe8\x98\xbd\xb1\xed\xbf\x3a\x3c\x3c\xdc\xf3\x75\x78\xdf\x4c\xd9\xc1\xf8\xe8\xc8\x7f\x45\x74\xe0\xe5\xf8\xe8\xe8\x35\xb1\xd5\xe7\xab\x71\x3d\x89\x5b\x3a\x76\x48\xdc\x30\x5b\x3c\x60\x49\xe3\xad\xf3\x73\xa8\xe7\xe7\x10\x0c\x85\x7e\xd0\x97\x89\x7a\x18\xdf\x30\x21\x47\xaa\x62\xcb\xc2\xe1\x28\xb6\xed\x31\x33\x25\xcd\x95\x3a\x1c\x39\x4e\x3c\xa6\xe2\x39\x9b\xd0\xcc\xb2\x04\xe8\xe2\xcc\x46\x13\x47\x8c\x69\xa8\x96\xa8\xc0\xd9\x2e\x57\xb0\x0f\x64\xbf\x8a\x1a\x84\x9a\xe8\xa7\xb1\xe3\x00\x40\xc6\x47\x1e\x09\xd9\x28\x6f\x18\x58\xaa\xea\x9c\x39\xbe\x29\xe2\xa9\x22\xc5\xc2\xf0\xa5\x7c\x42\x73\x87\x4d\xea\x4b\x8c\x4f\xb9\xce\xc2\xe1\x06\xc3\xe1\x06\x13\xc3\xed\xf9\x68\x62\x59\x58\xe5\x75\xe2\x86\x7e\x8f\x5c\xc1\x72\x1a\xb9\x21\x0b\x69\xb4\x24\xf4\x99\x5b\x94\x73\xb6\xc5\xa4\x8a\x60\x3e\xed\x18\x72\xa2\x35\xcf\x42\x02\x5b\x43\xb4\xce\x7a\xc1\x7f\xcb\x22\x29\x0b\x2c\x47\xc2\xb6\x5b\xc9\x9f\x74\x49\xf3\x4d\xa3\x5f\x9d\x37\x94\xce\x4b\x89\x6c\x39\x07\x8d\xe3\x5e\xd8\xc1\x5a\x6b\xd0\x83\x87\xda\xda\x67\xc0\x51\x31\xa8\xaf\x78\x71\xe3\x6a\xc0\x71\x06\xf1\x88\x8f\x77\x98\x34\x33\x03\x97\xbb\xbc\xa3\x71\x6a\xf8\xbe\x89\x6d\x93\xda\x1e\x4c\xdc\x35\xc2\x1c\x8f\xb2\xf1\x71\x0a\x2c\x7e\x8d\x22\xe2\x51\x66\xfb\x63\xcb\xc2\xfa\x83\x79\x84\xea\x2f\x5b\x25\x8d\x77\xd3\xca\x53\x11\xe3\xe7\x1d\x26\x4d\xec\xe6\xe2\x56\xe4\x85\xc0\x4d\x54\x2b\x10\x42\x0d\xfb\xce\x18\xf1\x04\xd6\x48\x44\x27\x74\xa1\x1f\x85\xba\xb6\x89\x5d\x44\xe8\x94\x5d\xd1\x6b\xf6\x45\xdb\x95\x3e\x66\xc0\xba\x64\xef\xe0\x71\x2c\x67\xf9\x3a\x63\x97\x2e\x18\x9e\x9b\x45\xca\x08\x71\x17\xd9\x1d\xae\x8f\x38\xe7\x56\x91\x65\x11\x9d\xbb\x21\x93\xf8\x06\x3f\xe0\x85\xba\x01\x2e\x5c\xa1\xef\x7a\xea\x5e\x4c\x05\xa1\x73\x57\xb0\x79\xf3\x6a\x4a\x68\xc8\x22\x86\x67\x4c\x9a\xae\x27\x43\x5c\xb0\x5f\xa8\x20\x01\x2e\x98\xa0\xbf\x90\x86\xb3\xa7\x20\x75\x36\x72\x9c\x68\x3c\x98\xd5\x57\x5a\xb5\x9d\x66\x1d\xde\x41\xd1\xbe\x9f\x02\x0b\x48\x11\xe4\x4e\x18\xa8\xae\xb0\x99\xea\x0b\x0b\xe9\xc2\x2d\x58\x4c\x67\x0c\x2f\x58\x8a\x17\x74\x4e\xa7\xf4\x9a\x72\x42\xdc\x90\x4e\xd8\xc2\xcd\x69\xc8\x16\xae\x20\xf4\x96\xcd\x46\x25\x0b\xed\xa9\xed\x2b\xf4\xce\x77\xf7\xe8\x84\x4d\xaa\xaa\x6c\x39\x29\xb3\x51\xa9\x12\x27\xec\xfa\xe8\x60\x68\xae\x77\xb7\x55\x35\x31\xbc\x93\xeb\xaa\xba\x66\x0c\x2f\x3a\xbc\x93\xdb\xe3\x08\x18\xf7\x91\xe6\x9d\x5c\x57\xd5\x04\x78\x27\xd7\x96\xe5\x5b\xb3\x51\xe9\xf8\xe3\x6e\x21\xcd\x23\x29\x81\x47\xa2\xc7\xc9\x26\xc3\x1b\xdc\x0c\xd3\x27\xd4\x99\xd2\xce\xa8\x49\xd0\x9d\x82\x1a\x1b\xcf\x6a\xea\xa4\xa4\x13\x40\x3e\x8e\xc3\x07\xb6\xad\x66\xb3\x1c\x1f\xf3\x01\x99\x8d\x4a\x60\x24\x54\x15\xb6\xed\x10\x84\x40\xc6\xb5\x84\xd8\xcc\xf0\xf6\x22\x36\x6b\x78\x7f\x66\x1d\x8c\x63\x2e\x00\x16\x84\x06\xb7\x47\x2c\x1a\xe4\x36\x6b\xba\x30\x1b\xdd\xaa\xdd\x4a\x06\x39\xbb\xc1\x39\x0d\x57\x7a\xda\xd8\x62\x00\xcb\xd1\x2b\x84\xc3\xaa\xf3\x91\xce\xbb\xb6\x86\xed\x95\xbd\x4a\x4b\x26\x9f\xcf\x69\xc8\xe4\xee\xbc\xf2\xa0\x43\xed\xbb\x34\x19\x14\x8e\x33\x20\x09\xc3\x38\x63\xe5\x0e\xe6\x4c\x8c\x8a\xf1\xf3\x39\xb1\x71\xce\xc2\x1d\x6e\xe3\x18\x62\x54\x51\xb2\x53\x92\xe7\xf3\x9d\xb9\x9d\x10\xb5\xed\x54\x16\x88\xb6\xc3\x9d\x98\xaa\x4c\x2c\x7b\xde\xe8\xce\x27\xf0\xfc\x3d\x4a\x9a\x59\x12\x64\x85\x4d\x29\x37\xd8\x94\x40\x16\xf4\x59\x4e\x38\x4b\x8f\x73\x2d\x1d\xd1\xf8\x07\xcf\x18\xef\x18\x8f\x52\x97\x8e\x51\x36\xee\x33\x39\xca\xc6\xe4\x51\x75\x3a\x1b\x1f\xab\x80\x2e\xa6\xf9\x42\xb5\x80\xca\x86\x2f\x92\x15\x0c\xc7\x3c\x90\x81\x21\x62\x94\x8e\x1d\x96\x29\x22\x7b\x94\x8e\x8f\xe4\x28\x55\x95\x79\x54\x85\x58\xb6\x93\xdb\x90\x41\xd6\xb2\x97\x83\x7e\xed\x71\xa8\x7e\x54\x1b\x88\xee\xf9\x40\x06\x7f\x86\x7a\x34\x4f\x56\xbf\x44\x3f\xd0\x6b\x7a\x47\xef\xe9\x09\xbd\xe9\x3e\xf8\xb3\xdc\x2d\x18\xcb\xdc\x02\x86\x45\x2f\x58\xee\x86\xf4\x94\x65\x6e\xa8\x1f\xad\x2f\x2c\xeb\x02\x7a\x71\x6a\x59\xa7\x0a\xfa\x57\x9f\xad\x73\xb7\xb0\xac\x4c\xfd\xc1\x17\xc3\xfe\x69\x55\xa9\xcc\x7d\xa6\x72\x06\xa7\x64\x78\x01\xc6\xd8\x2f\xc0\xb1\x69\xff\x74\xe8\xed\x9c\x05\x67\xbb\x5e\x70\xca\x4f\x35\xd8\xde\x31\x7c\x6d\x70\xd9\x99\xda\xfd\x8a\x8a\x3b\x63\xdc\xc6\x21\xcb\x5d\xe1\x64\xae\x20\xb6\x4f\x93\xaa\xc2\x09\x8b\x68\xc8\xa6\x38\x07\xb1\x0e\x67\x8a\x33\xf8\xa0\x67\xec\x6c\x77\x52\x79\x0a\x2d\x7a\x83\xd3\xd1\x62\xcc\x18\xbe\x18\x2d\xc6\x55\xe5\x91\xc1\xc2\x70\x97\x55\xfc\x71\x13\x6d\x59\xa1\xe3\xd0\xb3\x23\x8f\xdc\x69\x22\xc1\x27\x74\xc6\xfa\x5e\x7b\x28\xbf\x67\x17\x35\x64\x9f\xb3\xd3\xfa\x73\xc1\x3c\x7a\x66\xb3\x3d\x8a\xe7\xac\xc0\xc9\x2e\x56\xa3\xb4\x7d\x42\xc8\xb1\x3a\x4c\x4e\x99\xc0\xa7\x74\x4e\x13\x42\x2f\x98\xc0\x17\xfa\xb3\x53\xbe\xad\x95\xd0\x6f\xec\x9c\x9e\x30\x7c\xcf\x2e\x9a\x87\xa8\xf3\x16\xcb\x9e\x1c\x9d\x0f\xee\x47\x27\x8a\x0c\xf1\xc8\xe0\x2b\x3b\xad\xb7\x12\xfd\xaa\x4e\xca\x1a\xde\xbf\x12\xfa\x2b\x4c\x35\x3d\x1d\xf9\xe3\x63\x96\xec\xee\x59\xd6\xaf\xb6\x3d\x88\x32\x78\x94\x63\x1e\xc5\x25\x93\xf8\x94\xde\xd3\x73\x7a\xd2\x3c\x84\xde\xb0\x7b\x55\xe8\xbc\xcf\x4e\x2c\x0b\xdf\xb0\x9b\x9d\xc4\xc6\xf7\xe0\x06\xc2\x23\x44\x0f\xef\x66\xf7\x57\x35\x2e\xc0\x54\xf3\x63\x78\x3b\x99\xb3\xc4\xf1\x09\x7d\x60\xf8\xb6\x19\x6a\xf3\xe4\x73\xc2\xee\xeb\xde\xfb\x8c\x49\x7c\x4b\xef\xe9\x03\x3d\x21\x03\x32\x77\x1c\x9a\xe2\x5b\x7a\x7e\xf4\x30\xfc\x1a\x9c\xd2\x07\x35\x2d\x0f\x0d\x9b\x14\xd8\xb2\xb0\x09\x3d\xcd\xce\x2e\xd9\x9c\xd5\xcd\x34\x03\x6f\xa6\x26\x9e\xe0\x87\xa3\x13\x78\x64\xed\xcc\xc4\x2d\x21\x34\xc5\xf7\xf4\x96\x9e\xa8\xda\xdb\xce\x50\x75\x11\x2b\x35\xb1\xd7\x4e\xc4\x91\x3f\x20\x73\xdb\x86\x22\xe7\x47\x27\xd0\xad\xb5\x82\xcb\xba\x4b\xc0\x1e\x56\x99\xef\x19\x90\x44\x77\xa3\x85\x5a\x97\x39\x55\x73\x38\x34\xab\x74\x31\xfa\xa6\x26\x2f\xc0\xf7\x6c\xa4\xbe\xc7\xf4\x84\xf9\x64\x79\x37\x8b\x13\x81\xf1\x37\xdb\x3e\x7a\x5f\x9f\x57\xaa\x18\xb1\xac\x33\x45\x14\xce\x58\x1b\x47\xef\x60\x97\xdc\x75\x77\xf8\x12\x5c\xef\xb0\x48\xe3\x92\x05\xf3\xe9\x19\x53\xd9\x06\x67\x40\x04\x9e\x01\x11\x08\x40\xfe\x07\xbe\xa6\xdc\xc6\xd7\xae\x60\x0b\x3b\x84\xe7\x1d\xdb\xa7\x31\x35\xa2\x05\xbd\x6b\x38\x76\xaf\xdd\x9c\xd9\xb3\x1a\x7f\x5e\x03\xd2\x7f\xcf\x76\x7f\xc3\xce\x90\x78\x78\x74\x7f\x9d\x8d\x09\x1e\xb2\xcb\xbb\xd1\xe5\x9d\x3b\xde\x79\x46\x76\x63\xfa\xab\x4a\x1f\xfd\xe6\x8e\x6d\x72\xe9\x3e\xdb\xa5\xe7\x6c\xf7\xb7\x4b\xd7\xc4\x3c\xdb\xa5\x5f\xb5\x9c\xe5\xa7\x74\x12\xa7\xb1\x7c\xa8\xd4\xde\x7e\xb6\x4b\xcf\x54\xb6\x62\xe7\xd2\xc6\x43\x06\xb5\x91\xea\xb7\xcb\xc2\xae\x2e\x0b\xfb\xd9\xee\x94\x66\x6c\x55\xaa\xb3\x83\xa4\x59\x3a\x94\x81\x6c\xc8\x9e\x33\xf0\xb1\x19\x4f\xf0\x57\xcd\xb0\xe1\x84\x08\x45\x3d\x80\x27\x43\x4e\xb4\x71\x02\xae\x88\x0c\x3f\xf0\x9b\xd3\xb6\x0f\x0f\x21\x60\x2d\x59\x57\xf3\x9e\xe2\x75\x39\xd2\xfa\xbd\x8d\xa1\x7b\x04\x3e\x06\xd3\xb5\xe7\xfd\xa1\xff\x2a\x40\xd7\x88\xb1\x74\xb8\x17\xbc\xa6\xb9\x65\xe5\x7d\x96\x0d\x45\x20\xc1\xd4\x03\xbc\xdb\xe5\xb4\xdb\xca\xaf\x14\x3d\xf3\x11\x69\xc2\xe7\x14\x79\xae\x8a\x01\x9b\xf7\x7c\x0d\x79\x72\x9a\xc1\xc8\x6a\x9e\xcc\x1a\x8f\xe0\x34\x93\x3d\x8e\x6c\x9c\x0f\x51\xef\x9a\x17\xa2\x87\xec\x3c\x40\x88\xd8\xa8\x15\x8e\xb3\x25\x51\x87\x02\xc0\xd1\xb2\xfb\xaa\xb0\xa4\x17\x2e\xbf\x2e\xb2\xa4\x94\xda\xc5\x0a\x83\xf0\x26\xa1\x6e\xc8\xfd\x59\x5c\xac\xbf\x84\x62\x55\xb1\xaf\x8e\x54\x7a\x01\xe6\x00\x79\x2e\xa2\x8b\x6c\xbb\x71\xd8\x6b\x6d\x44\xb1\x15\x66\x22\xaa\x94\x91\xcd\x3a\x57\x93\x51\xb0\x0b\x37\x5a\xb0\x2d\x76\x0b\xf5\x3d\xbe\x91\x94\xaa\x59\xf4\xa6\xe6\xe6\xee\x5e\x9b\xa3\x90\xf0\x0e\x2e\xf5\x3b\x78\xfd\x22\xcd\x09\x15\x36\x87\x57\x2a\x2d\xc9\xd2\xc7\xe0\xc4\x82\xac\x4b\x79\xe6\x40\x87\xa4\x8d\xc4\xa0\x3a\x4b\xc0\xe0\x82\x3a\x4e\xc8\xce\x84\x66\x2c\x55\x47\x3e\xa0\x8c\xec\xb9\xef\x31\xd6\x3c\xa3\xaa\x3d\x5b\x53\x4c\x30\x43\xb9\xba\x2c\xe4\x30\xd2\xf8\x36\x8e\x44\xf4\xee\x81\xc1\xf7\xf6\x49\x4a\xd7\x27\x89\x5e\xd1\x2f\xa4\x53\xfc\x22\xfb\xa4\x65\x22\xa1\x9e\xf8\xbf\x50\x11\xa0\x0b\x7a\xe1\x8a\x7b\x2d\xa7\x1d\x73\x69\x7a\xb3\xc8\xee\x9e\x9e\x74\x1a\xc3\xdd\x64\x41\x67\xcd\xf4\x63\xd1\x48\x17\x11\x37\xb4\xac\xbe\x70\xe3\xc2\x74\x0b\xaf\x73\x4b\xd1\x89\x69\x6f\x53\xa6\xd3\xfe\x87\xaa\xa1\x5d\x50\xed\xaa\xd6\x80\x1b\x28\x05\x09\x57\x1c\xfb\x07\xb4\x3f\x73\x43\x45\x5b\x83\xcc\x02\x70\xd0\xf4\x27\xd8\x99\x15\xc0\x19\x9c\x35\x97\x95\xaa\xd2\xa2\x6e\x7d\x2d\xe2\x50\xaf\xee\xc2\x54\x0c\x7c\x23\x75\x25\xb2\xff\x81\x67\x84\xc6\xc3\x3d\xe7\x1e\x0b\x12\xe8\xce\x10\x2a\x87\x0b\x77\x9e\x45\x58\x92\x60\xa1\xba\xa6\x36\x4c\x71\xe4\x19\x9f\x3f\xd2\x0d\x87\x7d\x09\x15\x07\x7d\xe9\x16\xab\xdb\x15\xa8\x16\x9c\xb3\x7e\x68\x59\xb3\xee\x9c\x58\x96\x5c\x99\x22\x30\xa5\x3b\x33\xed\xb4\xb2\x5d\x6a\xb8\x6f\xc0\x64\x2e\x08\x5e\xcf\x5c\x71\xe4\xf8\x55\xa5\x6e\x29\x33\x57\x0c\xf5\xa0\x8f\xfd\xaa\x8a\x55\xfd\x21\x1c\xe9\x7b\x07\xe2\x30\xd0\x29\x47\xaf\x85\xbf\xdf\x24\x7a\xe3\x23\xf6\x46\xfd\x77\xf8\x52\x1c\xb6\x12\x70\x9c\xcd\xf4\xe6\x55\xa3\x1e\x3a\x5e\xe0\x51\xd5\x1c\xdc\x76\x39\xf3\x77\x39\x31\x40\x13\x0e\xfd\x5d\x1e\x70\x32\x78\x07\x29\x09\x7e\xb7\x3b\xb1\xf7\x08\x81\x47\xcc\x78\xd8\xc8\x2e\xb8\x2f\xc1\x44\x7f\x8d\x0b\x22\xa6\x2a\x26\x41\xc4\x70\xa6\x59\x84\xfc\xba\xc0\x66\x76\x9f\xef\xd1\x45\xcb\x82\xd3\x0f\xb5\x91\x91\x85\x58\xb0\x85\x2b\xe3\xb9\x28\xd4\x5d\xc6\x0d\xcd\xf3\x29\x1f\x2e\x9a\x95\x3d\xe6\x96\x85\xdb\x20\xe3\x24\x50\x28\x56\x15\xac\x67\x32\x9e\xe0\xac\xe1\x19\xe3\x0c\x98\x2e\x7b\xc4\xf0\x6d\x07\x11\xcb\x9e\xef\x35\x7c\xda\x3f\xe0\x0a\xa2\x9b\x84\x87\x0a\x85\x1a\x7c\xf8\x38\xf6\x0f\x88\x1e\x48\x73\x5e\x78\x50\x9f\x19\x47\xb7\x3a\xb5\x90\x75\xbf\x29\x57\x8b\x04\xf3\xdf\xed\xf3\x6c\xa3\xcf\xdd\xd5\x6f\x04\xc0\x17\x01\x0e\x61\x3c\xa7\x6a\xb7\xe3\xc5\x2a\x34\xf2\xe1\x1f\x78\x41\xdf\xd1\x2f\x54\xeb\xb2\x90\x60\x01\xfb\xd9\xec\x27\x8d\xc2\x37\x2d\x70\x6f\xc1\xde\x2d\xdf\xf3\x8b\xe1\x7b\x02\x9a\x94\x54\xc2\x14\x08\x5d\x6d\x71\xf2\x47\xc9\x93\x8b\x8c\x5d\xb8\xe2\x8f\xed\x48\x46\x4d\xf2\x76\xb4\x1e\x17\x1f\xd5\x61\x2f\x36\x19\xcd\xfd\x3e\xe0\xd2\x50\xe7\xfa\x1b\x68\x21\xe5\x17\x33\x9e\xb2\x0b\x77\xfa\x84\xeb\xae\xcd\x36\x8e\xbd\x8d\xf2\x67\x79\xdb\xe1\x69\xb7\xe5\x6e\x4d\xbe\x02\x0b\xb9\xa5\xd3\xa4\xaa\xc0\xc1\x9e\xae\xd6\xec\xd4\xa7\x7b\x6f\x59\x9d\x33\xe1\x58\xc7\xd5\x07\xc6\x9e\xae\xe3\xb3\x28\x0a\x33\xae\xe4\x2f\x8f\xeb\xc8\x5b\x2d\xdc\x1d\x54\xf2\xc4\xa0\x9c\xbf\x38\xa8\x53\x7e\xba\x65\x40\xd0\xf7\xc2\xe4\x10\x53\x2e\xe3\xdb\x2d\xab\xd6\xd3\xd9\xea\xee\x9d\x67\x45\xfc\xd3\x8c\xf5\xfa\xfc\x2a\xf2\xec\x67\xb3\xe8\x19\x5b\x46\x0a\x5d\xa9\x12\xf3\x38\x2d\x8b\x9f\x1d\x46\xb5\x75\xc9\xd8\x85\xa3\x48\xb2\xf6\x30\x52\x23\x76\x0b\xda\x4f\xaa\xaa\x2f\xb7\x20\x66\x45\x2a\xf7\x5b\x21\x59\x85\xaf\x1c\x49\x63\xcd\xb2\x14\x5a\x55\xad\x60\xb1\x5a\x52\x30\x88\xac\x7e\x43\x16\xbb\x21\x5d\x30\x61\x6e\xbb\x45\x55\xf5\x4b\x8d\xb0\xd4\x11\xb3\xa8\x2b\x0b\x87\xd8\xd4\x27\x48\xa0\xdb\x5c\x0c\xe3\xa0\x6e\xb7\xaf\x0f\xae\xfe\xa2\x7b\x20\xa9\xdb\xc1\x46\x29\x95\x71\x18\x07\xfb\x8c\x7d\x01\xe4\xac\x5d\xb9\xb0\x29\x2e\x08\x2d\xd9\x14\x97\x84\x86\xac\x91\xc8\xa6\x09\x2b\x9c\x52\x13\xff\x0a\x47\x1f\x79\x64\x88\x13\xe6\x24\x34\x63\x21\x09\x70\xc9\x0a\x9a\xb1\x05\xa1\x59\xcb\x8d\xa4\x92\x25\x20\xdd\x96\xb5\x22\x4e\x9d\xe4\x65\xc3\xee\xc8\x19\xe6\x0c\x27\x2c\x6c\x55\x4d\x24\x5b\x34\xfa\x07\xc3\x24\x90\x34\x61\xe6\x09\xad\x7e\x3b\x0b\x47\x72\xdc\x67\x8b\x91\x04\x96\x88\x0a\x1d\xa9\x40\x2b\x25\x03\x7e\x9c\x59\x48\x43\xb6\xa0\x0b\x96\x51\x98\x00\xe1\x16\x84\xaa\xc5\xcc\xdb\x06\x1c\x9c\xb6\x4d\xd7\x62\x7a\xd0\xf1\x70\x94\x9a\x8b\xaf\x7e\x83\x88\x1c\x7f\x90\x1f\x27\xfa\x38\x09\x47\x8e\x93\xab\x46\xf3\xb1\x9e\x97\x94\xe5\x83\xd4\xb2\xfa\x2a\x21\x1d\xab\xc2\x63\x26\xc9\xc0\x71\xd4\x17\x0d\x47\xf9\xd8\x66\xd1\x52\xfd\x3a\x4c\x95\x82\xf3\x6d\xe0\x6d\xe5\xb7\x3b\x4e\xd9\x60\x51\x58\xa9\xbf\x63\x41\x43\x5a\x92\x00\x16\x52\xaf\x9a\x1f\xf8\xb4\x23\xa9\x63\xf0\xe9\x3c\x8b\xca\x44\x6d\xe3\x79\x16\x6d\x01\xf0\x0e\x81\x5b\xc3\x67\x07\xae\x69\x9f\x1b\x92\xa6\x00\xc3\x61\x40\x73\x41\x07\x5a\xf8\x0e\x34\xd9\xc3\x21\x95\x77\x53\x39\x09\xf0\x1b\xc6\x3e\x0e\x41\xee\xb3\x80\x29\xf7\x69\xce\x52\xcc\xa9\xc2\xfe\xfb\x20\xe3\xc3\x32\x9a\xbb\xc5\x0e\xcb\x48\xd0\x26\x7d\x24\x14\x0b\xc6\xf5\xbe\xc4\xb9\x39\xe8\xd4\x11\x58\xd3\x62\x7d\xf6\xb1\xaa\x60\xf4\x5c\x2d\xa2\x19\x6c\x99\xc8\x78\x91\xc4\x86\xc0\x84\x52\x3f\x25\x31\xc1\x39\xad\xe1\x45\x35\x9c\x28\xbd\xd7\xd5\x8d\x3b\xa4\x37\xeb\x1b\xdd\x70\x9f\x4e\x2c\xeb\xc6\xb2\x4e\x80\x18\xbc\xe9\x70\x9f\xfa\xf7\x6a\xaa\xf4\x84\x9d\x58\x56\x5f\xe7\xe8\xdf\x54\xd5\x8d\xfa\xd1\xa1\x93\x46\xcc\xaa\xbe\x21\xc1\x3a\xee\xb0\x7b\xb7\xa0\xaa\xe6\xa1\x16\xb9\xf2\xb4\x18\x9b\x47\x82\xee\x05\x8a\x50\x2d\x37\x98\xb3\x29\xbe\x87\x83\xc0\xae\x95\x8a\x68\x53\x0b\x2e\xd8\x49\xbb\x7f\x16\xec\xa6\x0e\x58\x16\x7e\x60\x27\xf4\x84\xdd\xd0\x1b\xf6\x40\x33\x56\xd0\x42\x6f\x09\xa2\x02\xf6\x82\x3e\xb0\xd1\x78\x90\x39\xce\xe0\xa1\xdd\xa8\xaa\xbd\x6b\x16\xd1\x3b\x36\x57\x1b\x7b\xe0\x38\xd9\x31\xf3\x06\x35\xa4\x7b\x74\xc6\x6e\x46\xd9\xf8\xf9\x1d\xbd\x85\x8f\xdd\xbb\xca\xa3\x9c\x65\x36\x8e\x59\x41\x06\xfc\x38\x1b\x90\x94\x61\x5c\xb2\xd9\x0e\x2e\xd9\x09\x3c\x5a\x3d\xbf\x23\x36\x4e\xd8\xed\x4e\x69\xe3\x90\x9d\x8c\x62\x28\x46\x76\x66\xe4\xf9\xdd\xce\x9d\xfd\x30\xe2\x63\x3b\x25\xbb\xd7\xc0\x6e\x4d\x20\xcd\xbe\xdd\x09\xe9\xc3\x88\x3b\xce\x98\x95\xcf\xaf\x07\x2a\x0f\x4b\x97\x8d\x16\x9c\x6d\xe7\xc1\xc3\xca\xd6\x51\x3b\xe5\x81\xe6\x00\x1e\xa9\x3a\x67\x44\xf4\x57\xaf\x9a\x80\x1f\x34\x77\x44\x5f\x35\x15\xc6\xde\x0e\x4e\x1a\x64\x32\x96\x3f\x7d\x3c\x64\x4f\x1f\x0f\xd9\xe6\xf1\x90\x1b\xd0\x17\xb5\x53\x47\x60\x2f\xea\xab\xc9\xee\x84\x26\xc0\x0d\x2d\x9a\xf3\x81\x57\x55\x5f\x3b\x63\x86\x63\x68\xed\x7e\x90\xed\xea\x17\x8f\x7e\xa2\x8f\x83\xa2\xfb\x28\xa2\xf6\xab\x30\xa7\x80\x4a\x1f\xe6\x81\xb7\x93\x01\xfe\xe7\x6c\xaa\xae\xaf\x31\x9b\xe2\x58\xe1\xfc\xa4\xc1\xff\x19\xe3\x4e\x6c\x54\xc1\x8e\xbd\x21\x8e\x19\xa7\x29\x2b\x48\x80\x33\xe6\x64\x34\x65\x09\xa1\x69\x8b\xdc\x01\x9c\xd2\x16\x9c\x3a\x49\x80\xf6\x70\xc6\x92\x16\xff\x4a\x56\x34\xa0\xab\xee\xb2\x29\xc0\x68\x42\x13\x96\x52\xa9\xe1\xd4\x1b\xc8\x01\xc9\x18\x4e\x46\x8e\x23\xc7\x2c\x19\xc9\xb1\x5d\xa8\x3f\x19\xd9\x8d\x2a\x8f\xaa\x08\x16\x31\x06\x29\x43\x2f\x50\x3f\xcf\xa3\xc6\x50\x26\xb8\x19\x19\x65\xe3\xd6\x6d\x25\xb5\xed\x58\x03\x4b\x42\x63\x00\x96\x45\x2e\xc2\xb8\x88\x33\x45\x48\x15\xdb\x50\xe7\x13\xdc\x01\xcb\x12\x20\xb4\xb5\xc2\x26\xf0\xff\x12\x9b\xe0\xcf\x19\x04\x2b\xfc\x81\x9d\x89\xed\xd7\x4c\x81\xc7\xa7\xb8\x02\x46\x5b\x6f\xab\xe0\xf5\xb2\xd5\x7f\x07\x06\xc5\x71\x0e\x9c\x03\xf8\x36\xdc\x83\x62\x16\x4f\xf4\x7d\x7d\xd3\x48\x3e\x8c\xcc\xd9\x50\x12\x5e\x10\x0a\xb4\x95\xc6\xd9\xc8\x17\x5a\x7e\xe4\xc2\x2d\xfe\x28\x79\x2e\xbe\x66\x99\x54\x53\xfa\x47\x2e\x37\x36\x22\x95\x9b\xf4\x96\x02\xf3\xd8\x2d\x68\xa9\x48\x24\x1a\xb2\x2b\xfb\xa0\x91\xa7\x40\x9e\xfb\x52\xf3\xe0\xc0\x4d\x7b\x55\x01\xf4\x27\x1d\xf0\xd6\xf9\x14\xfd\xa4\x39\x47\x2a\x03\xa4\x0f\x4f\xf9\x69\x90\x0c\xe3\xc0\x37\x9b\x43\x5d\xb4\x8c\x7e\xb5\xea\x9b\xba\x3a\xc6\x40\xca\x16\x8c\xf9\xbb\xde\x10\x63\x90\x5c\x6d\x39\xcb\x76\x49\x9e\xef\x31\x78\x15\x95\x5a\x60\x9f\xae\x94\x97\x9a\x72\x02\xd5\x8f\xdd\x3d\xe2\x60\x78\x1b\x2c\x9f\xef\x11\xe3\x1b\xe4\x99\x82\x74\x5d\x39\x7a\x29\x90\x5d\x06\x00\xfa\x32\x3b\x69\x58\x25\x09\x56\xc8\xa3\x56\x32\x6a\x5f\x67\x05\x22\xb6\x4f\xec\x92\xc0\xa1\x09\x75\x15\x36\x42\xe0\x20\x52\x8d\x0e\x36\x55\xc1\x70\xa9\xf0\x06\xb1\x43\x72\xb4\x6f\x59\xb8\x50\xb4\xcb\x80\xc0\xce\xce\x69\xce\x22\xb3\x46\x5c\xd3\xa2\x29\x8e\x29\xa7\x21\xf5\x09\x21\xf4\x01\x2b\x10\x6c\xda\x2e\x88\x26\xf6\x1f\x70\x0e\xfa\x14\x6d\x3c\x60\x9d\xdc\x15\x47\xa5\x65\x39\x4e\x41\x91\xba\xfb\xa3\xbe\xca\x2c\x4d\xb6\xc2\xd9\xa7\x85\xed\x03\xff\x21\xab\x2a\x74\xa0\x73\x48\x42\x1e\x6d\x69\x59\xd8\x96\x8d\x7e\x55\x55\xa1\x97\x2a\xa9\xf3\x14\x58\x55\xf8\x0f\x9c\xd3\xdc\x15\xf6\x95\xbd\x07\x37\x65\xd6\xaf\x49\x82\x9c\xb8\xe2\x0f\xb5\x50\x2d\xa5\xd7\x57\xdb\xfb\x0f\xcc\x29\x37\x25\x3c\x42\x79\x3d\xd2\x3a\x3b\x79\xcc\x19\x37\x65\x42\x9b\x1d\xd0\x42\xfd\xc9\x98\xdf\xb8\x47\x6f\x9a\xf4\xe9\x17\x43\x5e\xac\xac\xcc\x13\xfc\xaf\x1a\x09\xe0\x86\x3b\x28\x6c\x9b\xd0\xef\xfa\x92\xa4\x20\xdc\x37\x75\x7d\x8c\xef\xc5\x3a\x5e\xf9\x49\x2d\x4c\xd8\xfa\xe6\xa7\xf6\x66\x5b\x5d\x5d\x59\x96\xcf\xb9\x64\x5b\x2d\x12\xd0\x6c\x05\x47\x31\x96\x92\xa6\x01\xd9\x35\x7d\x61\xa4\x44\xe5\x10\xa7\x4c\x52\xa9\xa9\x8d\x40\x6c\xc9\x22\x54\x16\x41\x05\xab\x33\xa5\xec\xf7\x46\xf9\x61\x43\x7a\x79\x5d\x7e\xb5\x51\xd1\xde\x2a\x59\x09\x98\x2e\xab\x27\x48\xd3\xa1\x99\x1b\x1a\x47\x85\x14\xdc\x0f\x2e\x92\x58\x6a\x19\x85\x84\xd9\xa9\xdb\x68\xe7\xd2\x42\x05\x37\x15\x74\x69\xc8\xea\x5c\xb5\x7a\x6d\x55\x21\x44\x23\x16\x2b\x2a\x6b\xc2\xe2\x91\x3f\x56\x44\x10\xf0\xdc\x66\x6c\x31\x8c\x5a\xe5\xea\x88\xce\xdb\xd7\x6d\x75\x2d\xd2\x8c\x29\x75\x09\xa2\x05\xe3\x74\xee\x30\x4e\x68\x72\xec\x59\xd6\xfc\xd8\xab\x25\x43\xe6\xcf\x15\xaa\xa1\x11\x9b\xd5\x1e\xca\x3d\xca\xc9\x80\x1f\xcd\x07\xdc\x66\x09\x89\x6c\x16\xda\x4d\x1a\xa7\x09\x19\x14\xc7\x46\x3b\x0c\x12\xa0\x79\x4e\x08\x5d\x80\xdc\x05\x72\x90\x1d\x91\x65\xce\x26\xc3\xc8\xc6\xa9\xbb\xae\x5d\xac\xc6\x43\x6c\xb5\xeb\xed\xd4\xdd\xd0\x32\x26\xc3\x49\xc3\xfb\x57\xf8\xe2\xab\x98\x9e\xdc\x2f\x30\xba\xbc\x8c\x1e\x91\x5d\xd8\x68\x79\x79\xf9\x0e\x51\x34\x45\x84\xa2\x67\x16\x52\x2d\x6c\x57\x4b\x86\x76\x48\x30\x21\x41\xb4\xac\x35\x77\x5c\xad\x28\xad\xbb\x90\xab\xb2\x5a\x6d\x19\x22\x0c\x80\x9a\xca\xb6\x88\xbf\x77\x89\x71\xcd\xf3\x6d\x15\x94\xe9\x35\x9b\x6a\x1a\xa7\xdd\x13\x7d\x5c\x74\x18\xc1\x2b\xec\x4e\x5c\xa8\xbb\x08\x1c\x06\x6e\xa1\x70\xb7\x9b\x48\x7c\x4a\x36\x98\xc3\x0d\x00\x22\x1b\x17\xdd\x2a\x86\x68\xc3\x28\xc0\x06\xff\x98\xd8\xff\xc0\x85\x91\x2f\xb9\x5e\x3d\x68\xa6\xf5\xdd\xb0\x66\x36\xd2\x88\xe5\x6d\x20\x63\x61\x1b\xb8\x65\x0f\xf8\x9a\x80\xdf\x45\xd1\x3c\x3a\x3a\x53\x57\x38\x3e\xd5\xac\x5e\x36\x1b\xe1\x84\xc5\xcf\x27\xe4\xc8\x1b\x4e\xec\x24\x48\xc6\x0a\xf7\x09\x35\xae\xf6\xd9\x03\x4b\x62\xf4\x6a\x64\x10\x05\xea\xd0\xfc\x41\x7f\xa8\x53\x85\xd6\xd3\x74\x4b\x68\xa8\x2b\xf4\x06\x0b\x96\xe2\x82\x4a\x60\xcb\x53\xbf\xaf\xee\xda\xb9\x46\xff\x35\x1b\x34\x83\x5b\x56\x5b\xbd\x20\x03\x92\x83\x70\x00\xa7\x11\x0b\x57\x33\x73\x06\x8e\x62\x19\xa7\xea\xe8\xd2\x34\x6b\x9b\x26\x09\x38\x3b\x6c\xcc\x65\xb0\x14\x8b\xfa\x4e\x47\x68\xa6\x3b\x11\xd6\x75\xd6\x48\x5a\xd5\x98\xd7\xbd\xe2\x6d\xaf\x68\xe8\x16\x2c\x72\x0b\x36\x75\x0b\xf0\x7d\x10\xd1\x8c\xc6\x3b\x6c\x8f\x7e\x21\xa6\xd6\x29\x01\xb6\xef\x4a\xff\x53\x1c\xd2\x9c\xc6\x9b\x99\xc8\x91\x3f\x1c\x45\x34\x1b\x07\xa3\x90\xe6\x63\xfa\x83\x25\x74\xae\xa1\x75\x5d\x8e\xb9\xc6\xcc\xf6\x3f\xf4\x2d\x41\xe7\x3a\x6f\x48\xc4\x9f\x63\xf1\x86\x02\xec\x9c\x02\x7b\xa6\x0e\x2d\x26\xbc\x4d\x29\xa4\xbe\x53\xa4\x6e\x41\x39\x4b\x37\xf4\x6a\xf8\x30\x1b\x62\xc9\x50\xfd\xc0\x89\x68\x06\x24\x8e\x04\x54\x21\x09\x09\x24\x43\xa7\xfc\x14\x05\x8d\xc4\xa9\x64\x1c\x34\x6e\xb8\xd6\xb8\x79\xc0\xa9\x1b\x12\xca\x49\x70\xd3\x7c\x83\x3c\x56\xe0\x83\x76\xff\x50\x32\x95\x80\xd3\x46\xbd\x32\x25\xf4\xca\xe6\xa0\xd5\x4d\x54\xf6\xd4\x08\x70\x05\x70\x50\x6d\xd1\x0f\x97\x2c\xc7\x6b\x95\x53\xdf\xa3\x82\x66\x60\xc2\x59\x77\x39\x35\xaf\x2a\x6d\xd7\x29\xf0\x0e\x8d\x1d\x07\x75\x93\xcf\xfe\xd7\xb7\xb3\x2d\x6c\xc4\x5e\x67\x3d\xba\xa2\xe5\x0c\xec\xaa\x9b\xc7\x1d\x50\xbb\xc1\x92\xd0\x67\x4b\x70\x80\x6c\x4c\xa2\x31\xee\xb6\xf9\x39\x6d\x2c\x89\xe1\x2d\xeb\xde\xe3\x4b\x2d\x52\x2e\x69\x4a\x25\x15\x40\x95\x08\x78\xd3\xca\x65\xc1\x72\xb2\xc4\x64\x49\x5f\x79\x4f\xdb\xff\xdb\xea\x49\x87\x66\x0c\xa1\x41\x47\x47\xa0\x3d\x60\xab\x6a\x8b\x92\x7c\x66\x33\xb1\x71\xcc\x76\xd2\xe3\x09\x06\x01\x5d\x37\x2e\x6a\xdf\x77\xa4\x95\x37\x17\x5d\x79\x73\x31\x92\x63\xb8\x5b\xe5\x58\xab\x3d\x28\xda\x4c\xfd\xb3\x19\xea\x21\x42\x8d\x51\x8f\x9a\x29\x27\xc1\x5a\x54\x5d\x6a\x2d\x63\x6b\x7b\xac\xa3\x22\x9a\x75\x65\x39\xd5\x94\x80\x32\x23\x42\xdb\x0c\x3c\x11\x2c\xba\x2e\xf9\x6c\x7b\x4c\x00\x1a\xd4\x5c\x6d\xe9\x58\xb7\xbd\x75\x73\x6d\x4b\xfa\xea\xf0\xe5\xcb\xa0\xbb\x9f\xda\x75\xea\xac\xeb\x86\x61\x26\xc1\x76\x7f\xc3\xd7\xd5\x3b\xf2\x6c\x97\x4a\xf6\x18\x8b\x30\x78\xbc\x8e\x65\x11\x8c\xd0\x35\xa2\xe8\x1f\xb1\xfa\xfb\x05\xfe\xfe\x0d\xfe\x5e\xc0\xdf\x73\xf8\x7b\x02\x7f\x7f\x85\xbf\xff\x8a\xaf\xd1\x98\x5e\x3f\x48\xa1\xca\xbe\x83\xb2\xef\xa0\xec\x3b\x28\xfb\x0e\xca\xbe\x83\xb2\xef\xa0\xec\x3b\x28\xfb\x0e\xca\xbe\x43\xe3\x25\xfd\x5d\x44\xeb\xcd\x43\xeb\xd0\x38\xb4\x0d\x4d\x43\xcb\xd0\x30\xb4\xbb\xd1\x2c\xb4\x0a\x8d\x42\x9b\xd0\x24\xb4\x08\x0d\x42\x7b\xaa\xb9\x25\x4d\xf5\x78\x47\x08\x51\x74\x13\x5f\xc7\x88\xa2\xb9\x80\x9f\xa9\x0e\x49\x1d\x5a\xe8\x1f\x71\x0f\x3f\x3f\x74\xe8\x21\xbb\x8e\xd1\xd8\xf4\xd9\x54\x91\x64\x50\xc5\x94\x43\x15\xf0\x23\x45\xce\xa1\x0a\xc9\xa1\x0a\x0e\x35\x48\x08\x3d\x64\xea\x77\xbc\xa4\x39\x7b\x04\xe3\x56\x41\xc7\xce\x55\x28\xe2\x24\x68\x6c\x60\x2d\xbb\x16\xf8\xb2\x86\x28\x6c\x38\x79\x1d\x71\x56\x3a\xdd\x94\x2d\xfb\x6f\x78\x4a\x3e\x67\xa3\x31\xfd\xca\x3c\x90\x98\x06\x21\x8f\x8c\x74\xdc\x5e\x5e\x3c\x2c\x84\xa6\x2f\x1a\x1d\x0a\xb3\x81\xf5\x13\x00\x03\x8b\x29\xbf\xba\x6a\x51\xe9\x75\x1d\x2a\xd3\xf8\x9e\xde\xd6\xa1\x05\x8f\x68\xac\xf2\xf0\x42\x54\xd5\x1e\x9d\xb6\x6e\x65\x7f\xd5\xbe\x75\x86\xe6\x37\xb8\x1e\xfa\xc1\x5e\xe3\x28\x11\x32\x80\x1f\x08\x31\xac\x3f\x02\x84\xe8\xa4\x89\x36\xae\x82\xab\xea\x71\x49\xef\xba\xa5\x8a\x9a\xb0\x1b\x76\xbe\x55\xd9\xfb\x95\x5c\x0b\x1e\x0a\xc8\x02\x1f\xc1\xf5\x10\xa1\x00\xf5\x10\xbd\x51\x89\x0f\xf3\xeb\x2c\xd1\x75\x9f\xb0\x3d\xc6\x58\x6c\x59\xbf\xba\x85\xe4\x8a\x0a\x8f\xaa\x0a\x01\x70\x20\x3a\x67\xbf\xba\x59\x29\x17\xa5\xac\xaa\x1a\xe5\xd1\xb2\x1e\xfd\xa4\x4c\x92\x49\x96\xcf\x69\xd8\x09\x14\x5d\xdb\x34\x80\xd4\x86\x9d\xc4\x60\x34\xa6\xbc\xdb\xcf\x5a\xca\x60\xd8\x7e\x06\x8e\x4f\xbf\xb1\x7c\x64\x66\x2e\x4e\xa7\x5f\x84\x9c\x65\xd1\xb8\xaa\x5a\x9f\x45\x74\xc1\xf0\x8c\xe9\xc3\x40\xad\xeb\x91\xa2\x9e\xe2\xe3\xbd\xa1\x2f\xf6\x03\xdf\xdb\x3b\xa0\xef\x59\xdf\x57\x23\x83\x95\xff\xb5\x65\x0f\x91\xe1\x82\xe7\x85\xf8\x94\xca\x6e\x2c\xf5\x3d\x12\x78\x40\xba\xcf\x98\x33\x23\x14\x3b\x46\x01\xa7\x96\x0f\x22\x70\x8b\x68\xe1\x5c\x4b\x08\x24\xd9\x14\xcf\xc8\x6e\xf3\x5d\x10\xa2\x99\x60\x9c\xa9\x6b\xec\xf1\x6b\xcb\xc2\xef\xe1\x9a\xf0\xde\x66\xaf\x1d\x4e\x28\x67\xaf\x89\xda\x4f\xc6\xa7\x24\x63\x6c\xde\xbc\xb9\x1b\xbe\x06\x9b\x91\x73\xa0\xfe\xe8\x03\x3b\x1f\xf9\x63\x06\xab\x27\x47\x27\xe3\x51\x32\x44\x0a\x20\x51\x80\x00\x73\xa0\xf1\x88\x1b\x1d\x80\xaf\x6c\xb6\x8b\x61\x2d\x87\x8d\xec\xc2\x1e\xf5\xbd\x1d\x4e\x82\x26\xc2\x17\xfb\x54\x5d\x51\x12\xcb\xc2\x5f\x77\xd8\x6b\x72\xcc\x0a\xcb\xe2\x47\xaa\x9b\x5f\x77\x59\xa1\xb5\x9d\xd5\x1e\x3d\x63\x6d\x21\x8f\xf2\x63\x6f\x38\x0d\x3c\x32\x80\x7e\x7d\xc3\x5f\x77\xce\xc8\xee\x19\x85\x10\x6b\xaa\x68\x8e\xe4\x76\x31\x2d\x0b\x43\x26\x1f\x6a\xae\xc7\x03\xe4\x4a\xac\x55\xb5\xf8\x30\x19\xa2\x9b\x6b\x14\xa0\x9b\x77\x3f\x19\x24\xbd\x86\xaa\xfc\x31\x33\xc0\xc9\x18\x3b\x19\x9e\x83\x68\x73\xcd\x7a\x08\x54\x37\x21\xaa\x31\x2a\xf3\xee\x19\x58\x93\x09\x54\x2c\x15\x5a\xf0\x4b\x7d\x93\xba\x63\x9d\x05\x55\x61\x42\x75\x1b\x48\x0b\x09\x2c\xea\x6c\x8e\x4e\xd4\x4b\x09\x31\xea\x4f\x97\xa6\xc4\xef\x89\x29\x7c\x33\x52\x3f\xe3\xaa\x82\x46\x61\xb3\x44\xc3\x6e\x99\xcf\xb0\xc3\x1b\x0d\xeb\xa8\xb1\x43\xfa\x74\xae\x88\x4e\x48\x70\xd7\x31\x58\xba\xd2\x89\xba\xaa\x15\x11\xff\x3b\x42\xe8\xad\x65\xc1\x2e\xd0\x1b\xa5\x73\x71\x3a\xd7\xc2\x83\x53\x75\xff\x55\xcb\x7d\xc1\xee\xaa\x4a\x95\x3a\xdd\xa8\x53\x5f\xde\x2f\x08\xbd\x62\xa7\x20\xda\x89\x10\xfd\xc2\xae\x6a\xca\xf1\x13\x9b\x3a\x5f\x34\x5c\xb4\x96\x49\x41\xc0\xb7\x0e\x5c\x34\x5f\x57\x0a\x63\x9e\xa4\x11\xfe\x62\x7f\x02\xda\xb2\x91\x6a\x28\xeb\xd5\x0d\x47\x7c\x3c\x54\x7f\x82\x54\x81\x02\x1f\xdb\x58\x83\x83\x81\x06\x75\x67\x56\x23\x52\x0d\x02\x4e\x2b\x10\x21\x14\x71\x85\x69\x60\x33\x0d\xcf\x83\x8e\x71\xd0\xf9\xd0\x58\xdd\x55\xf9\xa9\x46\x7c\x06\x18\x6a\x74\xc3\x69\x99\xc6\x32\x78\x58\x06\xe7\xee\xef\x59\x9c\xe2\xfb\xd6\x82\x86\xbb\xe0\xf9\x1a\xf3\x68\xd3\x47\x5c\x7b\x83\xc8\xb0\xa2\x35\x97\x4b\x9a\x01\x7d\xf9\xfa\xd5\xe1\x9f\xda\xda\xf7\xf7\xde\xbc\x52\x17\xcd\x47\xf0\x47\x6b\x0c\xa8\xaa\xb3\xa9\x08\xfa\x1e\x0d\xdb\xf0\x5a\x10\x92\xbb\x0e\xbb\x21\xdc\xfa\x14\x37\x36\x83\x3f\xac\xe5\x80\xa8\x3c\xbe\x15\x11\x38\x03\xfa\x98\x67\x73\xed\xcf\x73\x7b\x5a\x53\x6e\x1e\xdf\xc7\x29\x7c\x2d\x8c\xa7\x42\x08\x48\xdd\xb1\x25\xe5\xc6\x05\x7e\xdf\xa3\x1a\x2e\x4c\x56\x6d\xfe\x0d\xfa\xce\x93\x44\xbb\x4d\x82\x2f\x88\x6b\x8e\x6c\x1d\x88\xe5\x03\x54\x16\xb3\xc7\x67\xcf\x34\x91\xac\x47\x0d\x77\xc3\xbf\x30\xe0\xed\x7d\x4b\xd8\x63\x87\x0a\x29\x3a\x4b\xa8\x76\x04\x38\xaf\x12\x64\x18\x07\xc9\x48\xb8\x75\xbb\xe3\xaa\xca\x96\xc9\x28\x77\x3f\x36\xee\x37\xc7\xab\xbd\xca\x45\x1a\x19\x37\x50\x7f\xbd\x53\x4b\xaa\xea\x54\x4d\x8e\x59\x0c\x30\x50\xb2\xad\xa6\xa0\x69\x58\xc7\x4f\x85\xec\xe8\x2b\xab\x4a\x0b\x1a\x6d\x4f\xfc\xa6\xcf\x75\x3a\xd9\x9e\xfc\x41\x14\x61\x1e\x2f\x64\x96\xd3\x45\x27\xc7\x79\xbd\x4a\x67\x13\x3a\xab\xe3\x9b\xa5\x1b\x6c\x52\xe3\x3d\x81\x5b\x1b\x8f\x1b\xae\xc5\xb5\x36\xfb\xcc\x48\xe1\xb2\x05\x4e\xc9\x20\xb3\xac\xac\xcf\xd8\xcc\xb2\x54\xd1\x8c\xe6\x64\xa9\x7d\x80\x86\x2a\x35\xb2\x2c\x1c\xb3\xb8\x46\x12\x11\x4e\x89\x79\xc2\x04\xc7\xf6\xac\x50\x77\xc1\x39\x28\xd6\xd2\x5b\xe6\x0d\x6e\x5b\x35\x2c\xdb\xbe\xd5\x0d\x4d\x59\x3c\xba\x1d\xeb\xd7\x18\x3e\x9a\x8e\xab\x2a\xb7\xac\x1c\x3e\xe6\x96\x35\x87\x8f\xc4\xb2\x92\xd1\x74\x4c\x74\x89\x07\x36\xc1\x29\x9d\x12\xf0\x70\x55\x62\xa9\xa8\xcf\xae\x1f\xab\x65\xad\xaa\xdd\x93\xcb\x25\x7d\xe5\x7b\xda\x98\xf1\xd6\x8d\x9c\xb2\x2d\x4e\xf9\xf4\x6a\x58\x96\xfe\x75\x27\x59\x4e\x73\x96\x0e\xdb\x20\x46\xb9\xe0\xa1\x74\x85\xb6\x59\x8e\x48\xa0\x2e\xa4\xfb\x34\xdb\x9a\x4b\xad\x01\x4f\x4c\xa6\x57\x20\xdd\xbc\x99\x69\x92\xf3\x69\xa7\xae\x43\x1a\x6f\xcd\xa6\xfb\x7e\x35\xcf\x22\x61\x72\xbe\xa6\xc9\xf6\x56\xf3\x6c\x12\x27\x8a\x28\x56\xd9\xfc\x03\x5a\x3c\x95\xed\x36\x8e\xea\x6c\xde\x1b\x5a\x6e\xcd\x66\xf0\x97\xa9\xcc\xa3\xe1\xd6\x5c\xbc\x78\x48\xc3\x4e\xe7\x7c\x9f\x46\x4f\x55\x67\x7c\xe0\xad\xe6\x9e\x6c\x9f\x1b\xbd\x93\xaf\x72\x31\x31\x39\x41\xca\x70\xdb\xf4\x94\xc5\x42\xa4\x45\x5d\xe1\x3e\x9d\xfd\x34\xdb\x55\x12\x17\x66\x4c\x7b\x1e\x9d\x6f\xcd\x3b\x17\xf3\xcc\x54\xf7\x92\xde\x6e\xcd\x92\xf0\x1f\x0f\x26\xcb\x2b\x3a\xdd\x9a\x45\x3b\xa9\xd6\x2d\xf9\xf4\x61\xfb\x30\xcb\x34\xe2\x0a\x06\x6a\x60\xf1\x0f\xe9\xf5\xd6\x9c\xb9\x28\x16\x59\xda\xac\x9a\xff\x9a\xde\x6d\x1f\x67\x98\x2d\xea\xb9\xe8\x98\x02\xbe\xc7\xab\xc6\x4f\x5a\xbe\x86\xd6\x68\xef\x33\xd6\xb1\xac\x5a\xa3\xce\x41\x71\x17\xab\x2d\x26\xc9\x63\xc8\x0b\xd1\xcb\x03\x13\x01\x42\x96\x0f\x0b\x61\xe2\xc3\x00\x7e\x22\xfd\xc3\xf5\x4f\xa2\x7f\x62\xfd\xb3\x08\xea\xf7\xd0\x81\x41\xc1\x9d\xba\x2c\xab\x6d\xd3\x54\x59\xea\x62\x13\xfd\x73\xab\x7f\xe6\xfa\xa7\xd8\xac\xab\xdd\xfd\x90\x23\xeb\x44\xac\x18\x7f\x6d\x4e\x13\x35\x21\x8a\xd6\x5b\x4a\xf7\xad\x02\xe1\x2f\x59\x24\x58\x48\xa5\xfb\xbe\x81\x53\x88\x8a\x74\x94\xda\x09\xef\xb3\xb4\x28\xe7\x22\x67\x65\x1b\x77\x6e\xf6\x12\x2b\xa8\x74\x8d\x3f\x03\x96\x53\xd9\x39\x8a\xd8\x44\x05\xcd\x5e\x67\x9c\x4a\xf7\x33\xff\xf1\xc0\x6e\xa9\x84\xb3\x85\xcd\xa9\x74\xcf\x01\x5f\xb0\x4c\x7d\x9a\x4d\xcc\x12\x2a\xdd\x6f\xb0\xf7\xa1\x23\xb1\x0a\x1a\x20\x66\x0b\x2a\xdd\xb8\x68\x3b\xbe\x85\xe2\x51\x83\xad\x2a\x33\xcc\x70\x49\x8d\x13\xbe\xee\xd8\x4e\x68\xe3\x99\xaf\x33\xba\x2d\x75\x99\x5a\xca\x65\xb7\x40\x33\xf4\xa7\x0b\x14\xba\x40\x3d\x2f\x9b\x19\x7f\x06\x8e\x5d\xa0\x60\x8c\xe5\xba\xae\xee\xbc\x3e\xd9\xee\xc4\xe4\xad\x27\xfd\xe9\x9c\x5c\xe7\x84\x15\x79\x3a\xd7\xad\xce\x05\xcb\xf5\x74\xae\xb9\xce\x65\xd6\xf2\xe9\x7c\x99\xc9\x57\x2f\xf4\xd3\x39\x13\x9d\xb3\x03\x05\x4f\xe7\x8d\x4d\xde\x1a\x44\x9e\xce\xb9\xd0\x39\xbb\x5e\x7c\x15\xc9\xb3\x6d\x79\xb6\x71\x4e\xb7\x78\xb4\xd5\xf6\xc4\xb9\xfe\x89\xf4\x4f\xa2\x7f\x62\xfd\xb3\xd0\x3f\xb3\xaa\xfa\xf9\x92\xe3\x95\x35\xbf\xad\xaa\x95\xf0\x7c\x2d\x5c\xac\x85\xcb\xb5\xf0\x64\x2d\xfc\xb0\x16\xbe\x5e\x0b\xdf\xad\x85\xa7\x44\x4d\x95\x26\xb7\xd8\xfd\x92\x2a\xfa\xff\xa9\x3b\x42\x4b\x7a\xa5\x58\x11\x20\xe0\x09\x63\xef\x55\x20\xd8\x71\x87\x49\xba\xc2\x41\xae\xaa\x2d\x53\xbe\x61\x79\x65\x9d\xc8\x5b\xb3\xc3\x02\x57\x98\x83\x03\xaf\xcb\x1c\xaf\xef\x2b\x07\xfe\xde\x3e\x71\xf5\x22\xc6\x93\x07\x70\xd5\xf0\xea\xb5\xbf\x4f\xb6\x10\x8a\x6d\x17\x1e\x81\xe7\x12\x28\x42\x9b\x36\x65\x83\x7c\xb9\xa4\x4d\x29\x17\xb2\xb0\x0c\x93\x4e\x5c\x93\x57\xed\x55\xd5\xcc\x66\x8f\xca\x24\x69\xdc\x55\xec\xe2\x61\x70\x55\x5d\x5e\x96\x9e\xf7\x72\xf4\x71\x32\x26\x5b\xc2\x0b\x1d\x3e\xf4\x54\x20\x37\x81\x3d\x15\xc8\x74\xe0\x55\x9d\x53\x9a\xc4\x83\x6d\x89\x3f\x6d\x66\x97\x72\xe8\x4b\x68\x0a\xed\x6f\xab\x21\xad\xc3\x27\x02\xc2\x85\x69\x6e\x7f\xa3\xed\x95\x5e\x96\x26\xf0\x92\xac\x37\xf0\xd3\xfe\xb6\x75\xec\x3e\xb1\x52\x1b\x54\xad\x64\x8f\x3a\x18\xf4\x7d\x5a\xc8\x2c\x17\x6f\x0b\x63\xb6\xbb\xef\x53\x9e\xdc\xf1\x87\xe2\x5c\x2d\xda\xdb\xe2\x5d\x0c\x71\x65\x21\x4e\x41\x32\xfc\x5d\x3c\xfd\x94\x42\x39\x80\xb1\xb7\xd0\x48\x80\xc0\x91\x03\xa2\x1d\x5b\xe0\xab\x29\xcb\x75\xc3\x6a\xc6\x6a\xb5\xee\x86\x65\xe1\x9a\x74\x65\x7d\x8f\xd0\x26\xb1\xd3\x33\x93\xa7\x13\xc3\x8c\x9b\xd2\xb5\xee\x32\x53\x7a\x3d\x5e\x1d\x11\xeb\x71\x54\xba\x6b\x23\xab\x4b\xaf\x45\xab\xc2\x6b\x51\xb4\x61\x76\xae\xf8\x26\xd1\xe3\xd6\xf4\x93\x1e\xfb\xf6\x1c\x96\x85\xe2\x69\x9a\xe5\xe2\xe9\xf4\x45\x2e\x0a\x91\xdf\x3e\x95\xa3\xc3\xf2\xd6\xec\xee\x7f\x7f\x4a\xc3\x2c\xcf\x15\x42\x00\xd6\x08\x38\xd1\xd8\x28\xd6\xcb\x80\x01\x4d\x7b\xf3\xb2\x00\x03\x69\xf5\xe2\xf5\xea\x0e\xf5\xb2\xbc\xd7\xd8\x2c\xeb\x5d\x97\xb2\xb7\xe0\x45\x21\xa2\xde\xb3\xc7\x2d\xdd\x58\xfe\x9b\x0c\xe4\x66\xf4\xb6\x1e\x83\x91\xc4\x76\xd6\x3a\x10\xb4\x31\x5f\x9d\xb4\xb5\x99\x5a\x4d\x59\x9d\xa3\x6e\x8d\x7f\x69\x76\x3a\x05\xfe\x9b\xf3\xd2\xa9\x49\xcf\x48\x27\x62\xb5\x67\x4b\x7d\x45\xae\x1f\x4a\xd8\xe3\x0b\xf4\x22\x78\x81\x5e\x50\x74\x79\x89\x02\xf5\x87\xa2\x5d\x14\xa0\x5d\x44\xaf\x03\x74\x79\x8d\xe8\x24\x40\x97\x13\x44\xd3\x00\x5d\xa6\x88\xe6\x01\xba\xcc\x11\x95\x01\xba\x94\x68\x49\xa3\x95\xbd\x0e\xa3\xd6\x1c\x1b\xf4\xed\x21\x95\xfc\xfe\x44\x8f\xc2\xf8\x50\x09\x04\xe5\x32\x88\x29\x38\xc8\x2e\x96\x4b\xba\x95\x34\x32\xb2\x93\x89\x65\x45\x18\x9d\x18\xd3\x86\xbd\x17\xe0\xa7\xe5\x05\xbc\x03\x08\x1e\xf5\xb2\x89\x8a\x4a\x6c\xf4\x02\xc4\x7f\x1a\xab\x11\x31\x18\xd3\xf1\x69\xb2\xa4\x8b\x4d\xc9\x42\x78\x7a\x84\x4b\x88\x83\x98\x36\xb9\x9b\x31\xe4\x20\x3a\x51\x31\x84\x0c\x92\x63\x86\x3c\x64\x59\xc9\x11\x43\x6f\xd0\x80\x64\x36\x4b\xe8\x44\xdb\x2d\x06\x03\xdd\x2c\x81\xb7\xd4\x4c\x1b\xf7\x9d\x60\x62\x59\xdb\xca\x40\x7e\x81\x34\x79\x81\x4e\x56\x0a\x42\x85\x14\x39\x48\x8f\x12\xd9\xf0\x51\x55\x4d\xda\xcf\xbb\x21\x98\x9d\xd1\x5a\xc5\x09\x8b\x15\x01\x51\x6d\xd2\x18\x4e\xd4\x83\x7d\x9f\x10\x9a\xb5\x16\xcf\x87\x6b\x28\x6c\x98\x05\x1b\x18\x68\xa8\x7f\x70\xa6\x35\x42\x72\xf5\xb1\x89\xe5\x86\x4f\x96\x13\x75\x39\x70\x57\x14\x61\xf4\x8e\xb7\x0f\x60\x4b\x3a\xdb\x26\xeb\x99\x6a\xcb\x20\xf1\x04\xbf\x40\x2f\x9a\x79\xd2\x7c\x9e\x58\xcd\xb0\x56\xad\xa8\x13\x6b\x0b\x37\x8e\x7f\x9c\xa9\xb1\xda\xac\xe8\x18\xb0\xcf\x68\xec\xa8\x71\xab\x19\xce\x61\x11\x2e\x2f\xf5\xe4\xab\x3a\xfe\x42\x21\x54\x9a\xec\xb5\x4c\xbb\x7e\x35\x3f\x00\x63\x1e\xcd\x1b\x8f\xca\xe9\xbf\x22\x2b\xcb\x30\x90\x36\xf3\x49\xca\xfc\x57\x3b\xa9\x2d\x06\xb9\x6d\x8c\xdd\xbb\x93\x3c\x9b\xbf\x37\xb6\xca\x71\xda\x2a\x5c\x6e\x30\xb9\xc2\x51\x32\x36\xda\x7d\xb9\xcd\x54\x68\x99\xb1\x78\xb9\x34\xf3\x68\xb2\x93\x25\xdd\x30\x95\x34\x48\x34\xac\xf4\xd0\x80\x4c\x30\x59\xd6\x2f\xe3\x65\x37\xa3\xb9\xc6\xce\x31\xa1\x89\xbe\xbc\xa2\x47\x14\xac\xf3\x9d\xeb\x85\x49\x6b\x7a\x4e\xfb\xea\x32\x4e\xba\x54\xb7\x1f\xdb\x09\x85\x10\xa1\xaa\x4a\xb4\x44\xdd\xf5\x99\x60\xb4\x44\x84\xa6\xda\x54\x88\x51\x8f\x11\x6c\x86\x75\xee\x09\x46\x01\x32\x87\xad\x6c\x4e\x62\xd3\xe2\xaa\x31\x45\x4d\x3d\xa6\x54\x10\x85\x11\x5e\x7c\x28\x17\x49\x1c\x72\x29\x7a\x37\xe2\xa1\x87\x5e\xd8\xc2\x7e\x81\x5e\x98\xaa\x32\xfd\x16\x23\xc8\xd0\x20\x50\xa8\xbe\x83\xff\x86\x11\xae\xad\xa6\x86\x59\x2a\x79\x9c\x16\x0a\x17\x5f\x83\x73\xfb\x5e\x43\xba\xaa\x2f\x68\x1c\x91\xa0\xc6\xc0\x1b\x55\x95\x98\x04\xe9\x48\x8c\x99\xfa\x80\xe6\xf9\xd6\xe6\x37\x8e\xa2\x9f\x77\xa2\x93\xfd\xc9\x6e\x6c\x56\xb9\xd2\x99\xfa\xe3\xe7\x0b\x83\x11\xd5\x6b\xd7\x40\x98\xb9\xf1\x90\x25\x26\x03\x80\x8f\xd1\x93\xf0\xc1\x46\xc0\x17\x45\xa3\x15\x60\x18\xd5\xc0\x30\x5e\x6f\x73\x8c\x6a\x8d\x95\x06\x18\xb4\x26\x40\x89\xc9\x9f\x94\xd9\xec\xa7\x7e\x97\x69\xba\xa9\xce\x30\x53\x6a\x56\xf7\xdc\x69\x7a\xbe\xc0\x64\x9d\xfb\xb2\x8a\x5e\x87\x0b\x4c\x82\xcd\x7d\x52\xef\x11\xd9\xce\x01\x46\x12\x01\xec\xe6\xfa\xa7\xd4\x3f\x02\x20\x59\xb7\x3b\xe9\xe6\x9e\xe8\x74\xae\x7f\x12\xfd\x53\x74\x0a\xf9\xba\x50\xda\x2d\x94\xae\xd4\x9d\xb4\x3f\x60\x37\x21\xc2\xe8\x7b\x2a\x3a\xa7\xa2\x3e\x02\x97\x6a\x76\xe8\x16\xf5\x84\xd6\xbd\x92\xb0\x11\x02\x63\x84\x89\xc2\x13\x34\x6d\x00\x44\x9f\xb4\xfa\xc0\xd6\x5e\xd1\x10\xa1\x5b\x6e\xcf\x72\xd8\xe1\xd5\xaf\x9a\xc4\x18\xe5\xe3\x46\xbc\x6f\x8b\xa0\x30\x5f\xf5\x53\xc7\xb7\xf9\xa9\x53\x1d\xae\xc9\x33\x9c\x31\x81\x39\x95\x84\x0c\xf9\x48\x8e\x59\x16\x44\x22\x11\x52\xf4\x54\x68\x49\x14\xe5\x6d\x90\x42\x4e\x39\x59\xe2\x47\x84\x82\x74\x09\x4f\xb2\xe9\x52\xdd\x32\xfd\xbd\x2d\x77\x3a\x7d\x26\x6a\x1b\xa2\xfa\xa6\xd2\xf1\xd2\xb6\x4d\x16\x08\x0e\x27\xce\x76\x47\x97\x97\x97\xe8\xf2\xde\xf3\x9c\xcb\x7b\x7f\x72\x79\x7f\x38\x71\x2e\xef\xdf\x4c\xd4\xcd\x87\x47\x97\xa5\xf7\x4a\xa5\xa8\x9f\x83\xcb\xd2\x3b\xf4\x26\x97\xa5\x7f\x78\x7d\x00\x7f\x5f\x5e\x96\x7b\x9e\x17\x3a\xf0\x33\x51\x7f\xf7\x5e\x43\x60\x0f\x02\xaf\x3c\x08\xbc\x9a\x5c\x96\x13\x31\x51\x7f\x27\x13\x15\x35\x99\x4c\x26\xe3\xdd\x29\x8d\xd9\xa3\x22\xc2\x14\x61\x76\x8d\xa8\xa2\xb9\xd4\xa7\x54\x9f\x29\x7c\xa6\xea\x73\x02\x9f\x13\xf5\x99\xc3\x67\x8e\x28\xd0\x75\x97\x97\x1d\xca\xee\xf2\x12\x75\x1e\xac\x92\x0e\xc5\xc5\xdd\x84\x17\xf2\x53\x1a\x89\x7b\xe6\xd1\x16\x89\xbd\x50\xd8\xb5\x79\xfd\xe5\x14\x6f\x2a\x78\xc7\x23\x51\xaf\xfc\x06\x0f\x46\x0e\x15\x99\x78\x59\x22\x1b\x23\xcf\xf3\x3c\x64\x8b\x55\xa7\x2a\xed\x7b\xb0\xff\xaa\xd1\x26\x70\x0e\xc8\x92\x10\xdb\xd0\xa5\x1a\xbb\x2f\x3b\xef\x6c\x19\xe5\xba\xf1\xb8\x95\xf4\x61\x82\xce\xc0\xdf\x27\x9d\x1b\x93\x35\x33\xcb\xc2\xb3\xae\xd0\x48\x5e\x55\x79\xd7\x3a\x2d\xd8\x2c\x33\x3b\x7d\xb6\x05\x64\x55\xdc\xe6\x16\x98\x19\x19\x44\xa3\x44\xaf\x03\x20\x95\xba\x25\x73\x0a\xb9\x52\x0d\xaa\x9c\x66\x74\xa6\x20\xd7\x54\x64\x90\x8b\x99\xb3\x7a\xfb\xcf\x87\xb3\x20\xc1\x33\x83\xc3\x0c\xe1\x54\x27\x36\xc4\xc6\x8c\x0c\xcd\xbc\xcd\x48\x80\xd4\x80\x91\x2e\x70\x9d\x65\x89\xe0\x29\x0a\x4c\xf1\x24\x31\x9f\xd7\xf1\x34\x4e\x5b\x44\xd6\x94\xd6\xc5\xcc\xd8\x03\x30\x95\x67\xf0\xaf\xa9\x56\xe1\x69\x9b\x49\x3a\x61\xa3\x31\xdd\x64\xf9\xfc\x84\xe7\xc3\x17\x8b\xe4\x01\xd7\xae\xc2\x5a\xcb\x70\xc6\x43\x5c\x34\x50\x64\x3a\x99\x68\xe3\x94\x31\x9d\x11\x90\x75\x54\x6d\xd6\x2a\xae\x4c\x1d\xa9\x13\x53\x6c\x88\x46\x63\x14\x88\x21\x1a\x5d\xa6\xea\x2a\x30\xd1\xaf\xea\x88\x42\x90\xd8\x6a\x43\xd8\x0b\x1b\x8d\x51\x80\x46\xa8\x4d\x46\x44\xc5\x51\xc1\x16\x34\x54\x57\xc0\x74\xcb\x5a\xa7\x44\x77\x31\xdd\xda\xc5\x0d\xb8\x4e\x47\xf1\xd8\xb2\x70\xc8\x0a\x5c\x32\x15\x50\x0b\x6b\x59\x13\x7d\x9e\x25\xb8\x24\x36\x16\x43\x04\x62\xe3\x01\x22\x76\x68\x24\x28\xbb\x28\x70\xf6\x14\x0a\x84\x77\xbf\x02\x4b\x3a\x23\x83\xb4\x53\xa9\x5c\xab\x34\x55\xbb\xe4\xa9\xa9\x7a\x5c\xc2\x54\x3d\xfe\x7c\xaa\x96\x28\x40\x8f\x6b\x53\xb5\xac\xa7\x6a\xd9\x02\x74\x43\x9f\x66\x2d\xe7\x4c\x5d\x9c\x3a\x7c\xb4\x55\x0b\x6f\x66\x7f\xea\xcb\x0a\x42\x54\xaa\x3f\x1b\x82\xac\x9c\x68\xd3\xa1\x6a\xaa\xb9\x9e\x6a\x09\xd2\x9d\x30\x5b\x1b\xb3\xce\x41\x16\x94\x13\xe3\x0a\x91\x66\xdd\x0d\xda\x76\xd1\xb2\x36\x35\x4f\xb2\x56\x8c\xb6\x33\x96\x5a\xb9\x7b\xfd\xae\x8e\xd4\x9e\x6e\xc7\xd6\x7a\x60\x29\x30\x42\x54\x1d\x35\xf9\x92\x2c\xb5\xac\xef\xe1\x81\xff\x1a\x18\xa7\x5b\xd8\x5c\x3f\x7d\x4c\x4f\x37\x77\xce\x2a\xd5\x4b\xf3\xcd\x1c\x35\x35\xf8\xa9\x38\x69\xbc\x38\x77\x05\x21\x35\x77\xcb\x88\x79\x6f\x17\x4a\x34\x75\xf2\xa2\x88\xa7\x69\xc7\x50\x3d\x48\x4f\x44\xbd\xbb\x58\xce\xe0\x22\xb9\xc2\x6e\x40\x6b\x5e\x85\xc1\xdf\xd9\x36\x71\x5a\x99\x3f\x00\x7f\x6d\xa5\x95\xd6\xc0\x77\xab\x66\x6b\x10\x10\xe2\xd7\xa1\x16\x8c\x14\xa3\x97\x63\x86\x22\x81\x28\x7a\xd9\xc1\x2b\x5b\xc4\x14\xb0\x20\xad\x66\x5f\xdf\x1f\xb4\xbe\x66\x1f\x97\x34\x65\xde\x20\x3d\xf2\xbd\x41\x6a\xdb\x44\x8e\xd0\x15\xb2\xb7\x5f\xc2\xc6\x0c\xdc\x2d\x74\xcd\xc0\xf6\x7f\xda\xaa\x24\xee\x9c\x2f\x56\xfd\x27\xd7\x4f\x77\x23\xa1\x88\x12\xb3\x8d\x10\x59\x1d\x70\xce\x1e\xeb\xeb\x18\xda\xe6\xae\x0f\xd5\x7a\x4c\xe8\x09\x2f\xcd\xb9\x22\xe6\xc5\x12\xe4\x91\xb6\x95\x6f\x67\x0b\x30\xcb\xca\xdc\xe3\xc7\x25\xcd\x3b\x5d\x6b\x25\x11\xea\x3e\x2e\x97\x98\x0c\x57\xca\x74\x1d\xda\xf2\x56\x7a\x1b\x78\x46\x0c\x78\xed\x25\xf3\x07\xe5\xa6\xfc\x76\x69\xdb\x6d\xf6\xb0\x17\xa7\xbd\xd8\xf4\xac\xe3\x95\xb7\x1c\x13\x62\x8e\xc4\x98\x86\xa0\xac\x33\x0a\xc7\x2c\x1e\x85\x63\x00\x04\x49\x1e\x13\x26\x71\xdc\x8a\x6a\x44\xcc\x1b\x44\x47\x49\xe3\x50\xcd\xb6\x49\x5e\x57\x90\x8c\xa2\xb1\xae\x43\x7d\xa9\x6a\xe0\x97\x34\x52\x16\x85\xa2\x06\x0f\x57\x04\xa6\x1a\x07\xf1\xaf\xf7\x5e\x6d\x7b\x5f\x30\x82\x28\x59\x2b\xcf\x83\x53\x52\x55\x38\x63\x69\x55\x65\x34\x65\xa3\xb1\x22\x22\x33\x10\x74\x95\x5d\x1a\x43\xab\x53\x0d\xb7\x50\xe1\x4c\xb8\x45\x56\xe6\xa1\x70\xe7\xb0\x00\xbb\x97\x18\x0f\xfb\x97\x43\xb2\x3b\x35\xce\x1a\x5a\x17\x4a\xde\x20\x3f\x4a\xbb\xde\x9a\xa4\x3e\x03\x34\x63\x2d\xa7\xc6\x1d\x25\x28\xa4\x47\x22\x89\xe7\xb1\x14\xb9\x0e\x6a\x2e\x22\x4f\x82\xbe\x4f\x73\xb1\x10\x5c\x33\xcb\xb5\xb4\x19\xb0\xd7\x0b\x29\xf2\xb8\xb8\xd1\xd1\x52\x8a\x3c\xd5\xfe\x31\xdb\xa3\x04\x7a\xbd\xd4\x7e\x58\x72\x2c\x49\x3b\x9c\x0d\xbb\xa1\x20\x76\xeb\x0d\x78\x6b\x85\x99\xdb\x36\x31\x96\x3d\x04\x96\x23\x3e\x86\x22\x66\xec\x9d\x36\xba\xca\x67\x78\x18\x20\x3b\x33\x20\x5a\xa9\x43\x88\x20\x1a\xe1\x9c\x10\x9a\xea\x8e\xd0\x8c\x6c\x78\x59\x6e\xee\x4b\x1c\x0b\x9a\x6a\x7f\x5f\x75\xe6\xcd\xf7\x1f\xde\x89\x09\xb3\xf9\x22\x4e\x9e\x30\xd1\x93\x40\x7d\x92\x80\x4a\x65\x5b\x46\x66\x37\x22\x2d\x2e\xb2\x8f\xa6\x0c\x4b\xb6\x24\xea\x01\xb1\x89\x71\xcb\xde\x19\xe3\x08\x61\x45\x7f\xbb\x04\x51\x84\x47\x97\x97\xbb\xee\x98\x0c\xf1\x30\xc0\xc3\xe0\xf2\x32\xc0\x97\x97\x77\xe0\xf3\xf9\xf2\x12\x63\xf8\xb9\xbc\x74\xab\xd1\x6f\xea\x17\x93\x31\xb1\xc9\xe5\x25\x21\xc3\xea\xa7\xc9\x78\x64\xef\x0c\xc7\x64\x58\xe1\xcb\xcb\x1d\x42\xd0\xb8\x9d\x50\xd0\xe7\x5b\xf1\x79\xbe\xee\x2e\x4c\x2f\x64\x7d\x39\x44\x34\x64\xd2\xb2\xa4\xdb\x40\x57\x55\xa1\x5d\x34\xd0\x94\xb5\x3a\x7c\x5d\x71\x2f\x42\xe0\x79\x69\xf8\x8e\xb4\x09\xf8\x09\x58\x7f\xa7\x0b\x66\x3c\x1d\x82\xc4\xbb\xdd\x58\xda\x8d\xe9\x82\xd0\x98\x2d\xec\x5a\x34\x95\x4e\x48\x62\xb3\x49\xe3\x5b\x45\x55\x35\x63\x42\x51\x54\x73\x96\x8e\xf6\xc6\xf4\x96\xa5\xa3\xfd\x31\x9d\xb2\x74\x74\x30\xa6\x0f\x2c\x1d\xbd\x1c\xd3\x6b\x96\x8e\x5e\x8d\xe9\x1d\x4b\x47\x87\xe3\x41\x62\x59\x38\x37\x54\x12\x81\xee\x6b\x51\xe3\x7b\x73\x13\x98\xd7\xaf\xb6\x33\xcb\x9a\xf5\x19\x9b\xd3\x13\x86\x6c\xa4\x1f\x55\xd1\x0e\x7c\xd0\x1b\x86\x86\x6b\x51\xdf\xa0\x07\x55\x15\xd2\xf7\x6c\x5a\x55\x0f\x83\xbc\xbb\x0d\x6f\xab\x8a\xdb\x76\xbd\x17\xe7\x5a\x8d\xb4\xd9\x8c\xdf\xda\x9d\x78\x53\x6f\xc4\x93\x66\x1f\xde\x77\xb6\x61\xff\xae\xd9\x87\xef\x87\x25\x7e\x4f\x82\xbb\x21\x72\x77\x14\x11\xfb\x1b\xb2\x0b\xfc\x4d\x91\xaf\xf6\x10\x2d\x5b\x94\x16\x37\x2a\x3c\x96\x65\xa6\x57\x6b\x8f\xc6\x5a\x04\xbb\x9d\x8c\x7c\xc5\x45\x7d\xcb\x60\xaf\xbd\xa6\x63\xd1\xca\xf6\xee\x8e\x2e\x77\x87\xff\x43\xdd\x39\xb7\x1c\x71\xe8\xf9\xcf\xef\x6e\xab\xee\x24\x97\x5d\x47\xc8\xc9\x1a\xb4\xc1\xb6\x30\x6a\x49\x8d\xb9\x59\x6d\x06\x5d\x74\xcd\xa0\x6f\xbe\xbe\x8f\x32\x50\x55\x1a\x65\xe3\xee\xd6\x42\xbf\x01\xfe\x50\xa9\xae\x99\x49\x1b\x91\x67\x0a\x83\x48\xd2\x52\xc8\x1d\x24\x96\xb5\xbd\xe1\x0a\xd8\x13\x26\x01\x95\x17\x0c\x03\x4e\x27\xee\x22\x17\x52\x3e\x0c\xe3\x60\xd3\xbf\x3c\x78\xc7\x2c\xdb\xae\xc2\x99\x07\xe7\x1d\x13\xa3\x72\x3c\xd8\xca\xd6\x35\x9b\x84\x4e\x58\x32\x0a\x5d\x05\x3f\xe3\x56\x0d\x7b\xa2\x0d\x07\xb9\x35\xc4\x90\xc7\xb0\x96\x0f\xb6\x2c\xcc\x6d\x16\x1a\xbd\x5a\xd2\x7a\xe5\xdc\x46\xda\xbd\x68\x9e\x4a\xd0\x0b\x5b\xb7\x62\xbf\x40\x3d\x99\x29\xf2\xce\x10\x72\x2f\x40\xfc\x3c\xc7\x13\x62\xac\x48\xb9\x1a\x38\xb7\xd2\x8a\x4f\x57\xa8\x68\x46\x5d\x90\xc2\x4b\x54\x2e\x42\x11\xdf\x8a\xa8\xf7\xef\x17\xf6\x2a\xf1\x8c\x27\xc4\x46\xff\x46\xb5\x69\x85\xe6\x8a\xb2\x3e\xe6\x7a\x64\x83\xff\x7a\x47\xae\x45\x4f\xcc\x17\xf2\xe1\x85\x36\x22\xa2\x66\x7a\xc1\xbc\xc1\xe2\xa8\x6e\x0b\xcc\x2c\x83\xad\x3f\x56\xe0\xc9\x68\x31\x26\xb4\x9f\x8e\xca\xb1\x66\x73\x44\xdb\xb5\x77\xda\x36\x79\x92\x6c\xb4\x0b\x87\xb8\x8e\xad\x61\xee\x05\xfa\xd3\xb9\x88\xcc\x5c\x70\x9b\xc1\x64\x2c\x86\xf5\xd2\x06\x61\x8b\x6b\x89\x1d\x2d\x9b\x27\x82\x88\x85\x6e\x8d\x2c\x86\xed\xbe\x9d\x74\xf7\xed\xff\xb9\x5d\x1b\x14\x78\xf2\x5f\x9b\x9c\xff\x3f\x13\x83\x5e\xd8\x11\xb0\xec\x07\x1d\xe0\xae\x07\xdd\x53\x71\xad\xdd\xf2\xe5\x56\x01\xeb\x96\x27\xb5\x8b\x47\xae\xbd\x33\x64\xbf\xf5\x83\x67\x8f\x4b\x4c\x46\x97\xe3\xea\x72\xf7\xf2\x72\x4c\x76\xa7\x14\x5d\x5e\x3e\xf3\x51\x07\x17\x95\x4f\xd5\xc1\xfa\xc1\xb3\xcb\x5d\x75\x98\x6e\x2b\x16\xae\x50\x08\x02\xc8\x6c\x26\xbb\xa6\xdc\xa3\xb5\xe7\x4b\xb7\x10\xa9\xb6\x51\x07\xca\x04\x31\x6a\xb3\x4e\x1a\x02\x06\x4b\x45\x55\xa6\x0a\xfb\xa4\x54\x2a\xaa\x72\xd0\x92\x56\x38\x55\xd4\xa6\x42\x46\xfa\x52\x49\x39\xeb\xfb\x7d\xc6\x52\x57\xa4\x11\x8d\x35\xde\xf2\x06\x49\x8b\x89\x92\x1a\x13\x95\x4c\x8c\x92\xf1\x56\x7d\xd2\x92\xc4\x36\x2b\x70\x49\xda\xf3\x76\xa2\xc2\x35\x86\xa1\x0b\xa6\xc9\xb1\xb2\x83\x4b\xd1\xc0\x10\xa0\x25\xa1\xa5\x41\x18\x96\x85\x17\xb6\xc9\x3b\xb1\x17\x36\x22\x3b\x08\x1e\x5e\x17\xac\x6c\x76\xf5\xb0\xac\x11\xd9\x70\x62\x23\x0c\x3c\x07\x32\x44\x41\x5d\xac\x8e\x52\x71\x6d\x08\xe9\x27\xea\x19\x2b\xc0\xbc\x41\x97\x02\x21\x74\xce\xe2\x9a\x4d\x58\xf3\x93\x08\x63\xac\xb1\x19\x9d\x55\x15\x8e\x19\x9e\x0f\xe3\xc6\x36\x49\x9b\x31\x88\x89\xad\xdb\x9e\xa9\x5f\xf6\x4c\xb5\x0c\xbd\xe6\x43\xf4\x0c\x05\x99\x65\xcd\x61\xbd\xf0\x90\x41\x9e\xea\x19\x41\x74\x95\x58\xfd\x0d\xd9\x31\x05\x59\x72\x45\x21\x2e\xe9\xde\xa1\xb7\xff\x67\xca\x18\x07\xe0\xa7\xa5\xab\x11\xbb\xec\x10\x63\xe4\x71\xc9\xdd\x5c\x14\x42\xfe\xc2\xf3\x34\x4e\xa7\xef\x79\x38\x13\x60\x9b\x6e\xcb\x0d\x7b\xdd\xed\x81\x36\x9a\xa0\x1f\x37\xfb\x8c\x19\x9e\x7c\xc2\x3a\xec\x8c\xf7\x3c\x49\xe2\x74\xda\x3b\xaf\x35\x06\x7a\xa0\x97\xc8\x65\x96\x17\xbd\x28\xce\x45\x28\x93\x87\x5e\x5c\x00\x36\x2d\xca\x85\x6a\x53\x44\xbd\xeb\x87\x9e\x9c\x89\xde\xbf\x17\x79\xb6\x70\x14\xfc\x14\xff\xee\x2d\x78\x78\xc3\xa7\xc2\xed\x7d\x2f\x44\x5b\x9f\x1b\xce\x44\x78\xd3\x04\x31\x51\x98\x40\x5d\xd0\x54\x05\x73\xb7\xf7\x55\xf0\xa8\x37\xcf\x72\xd1\xe3\xb2\x37\x93\x72\x11\xec\xee\x4e\xae\xdd\xb9\xd8\x2d\x0b\xe1\x40\x61\xa7\x6d\x05\x11\x73\x08\x24\x80\x58\x18\xe8\x51\xe6\x31\x4f\x65\xef\x9f\x71\x96\x70\xe0\xf7\xd0\x64\xd9\x75\xa4\xd0\x6e\xbe\xa5\x70\xe3\xe2\xab\xf8\xa3\x8c\x73\x11\x31\x61\xe4\xe8\x1f\xe1\xc1\x28\x10\xf4\x3a\xcb\x92\x40\xc0\x3b\x49\x20\xa8\x31\x53\x2d\xa8\xb1\x3c\x22\x8c\x14\x99\xfa\xd0\x3a\x3d\x82\xf2\x54\x95\x83\xf2\x67\x93\x40\x52\x23\x56\x1f\x88\xfa\x0b\xb4\x68\x04\xad\xaf\x81\x90\x29\xcd\x22\xd1\x54\x0b\x31\x59\x2a\xda\x5f\x28\x22\x69\x31\xe3\xf0\x2b\xee\x79\x28\x03\x49\x57\xa7\x31\xe0\x74\x03\x2a\x82\xac\x79\xd9\x4d\xdd\x26\x27\x4b\x69\xba\x5c\xd2\x97\xaf\xde\x1c\x76\x40\xb1\x2b\xe6\xa7\xa0\x94\x60\xb2\xa4\x07\xfe\xc1\x26\xbb\xaa\xcd\x89\xbe\x9d\xbc\xff\x7a\x72\x71\xf5\xe1\xec\xea\xf4\xec\xe2\xea\xfc\xed\xb7\x6f\x57\x17\x7f\xff\xf4\xed\xea\xec\xeb\xd5\xbf\xce\xbe\x5f\xfd\xf2\xe9\xf3\xe7\xab\x77\x27\x57\x1f\x3f\x7d\x3d\xf9\x80\x96\xf4\xe0\xe0\xe0\xf5\x9f\x41\xff\xe1\xde\x9b\x03\x02\x02\x7d\x87\x07\xfe\x6b\x42\x39\x4b\xf1\xfe\xeb\x03\xaf\xb3\x25\x80\x38\x6d\xf9\x38\x48\xc1\x48\x11\xec\xee\x82\xa0\xf8\xef\x85\x9b\xe5\xd3\xdd\x28\x0b\x8b\x5d\x78\x9c\x72\x22\xa1\xce\xc1\xdc\x9d\xc9\x79\x32\x8c\x6b\xe8\x60\xc8\x16\x34\x65\xfe\x36\xcd\x72\xe0\x06\xd9\x0c\x59\x3c\x9f\x16\xa3\xb1\xca\xba\x41\xd9\x75\x78\x14\x69\xe3\x3d\x08\x7d\x89\xd3\x78\x12\x8b\x48\x01\x71\x28\xf5\xeb\x58\xef\x7f\x80\x2c\xca\xa0\x77\x1b\x17\xb1\xec\x21\xf0\xc9\x37\xc9\x72\xd8\x2f\x93\x32\x49\x7a\x46\xde\x05\x98\x68\x85\x80\xf8\x34\x4b\x9d\x79\x5d\x59\x24\x6e\x7b\x22\xbd\x8d\xf3\x2c\x05\xfb\x23\xaa\x30\x14\x84\xfa\x8b\x1e\x4f\xa3\x1e\x8f\xa2\x58\xe3\xd1\xde\x4c\x24\x8b\x49\x99\xf4\xee\x34\x28\x14\x2e\x5a\x6a\x07\xc2\x5d\x7b\x26\x31\xde\xdb\x3b\x24\xfa\xee\xa3\xf7\xff\x37\x21\x69\xb1\xa2\xa5\x54\xea\x93\x4c\x1f\x68\x34\xc4\xc2\x46\xef\xf9\x42\x96\xb9\x40\x0a\x9d\xad\x9f\x78\xe0\xc5\x7a\x24\xc6\xea\xb0\x63\x5e\xd7\xdb\x92\xb0\x6d\x92\xb8\x3c\x8a\xb0\x1c\x89\xb1\xd6\xbb\x89\x58\x7f\xab\xbb\xc9\xbb\x38\x8d\xb2\xbb\xaa\x6a\xf4\x38\x75\x84\x1b\x65\x21\xcc\xf7\xd3\x29\x46\xf4\xc0\x88\xfe\x12\x3a\x61\xbb\xbf\x8d\x82\xb7\xce\xaf\x57\xdc\xf9\x71\x59\x7a\xde\x7b\x78\x77\xf3\x3e\xbc\x82\xbf\xaf\x21\xf0\x11\x02\x1f\x21\xb0\xf7\xf1\xe3\x65\xe9\xed\x1f\x42\xb6\xfd\xc3\x0f\xf0\xf7\xa3\x73\x59\xfa\x1f\x55\xca\x9e\xe7\xbd\xd7\x2f\x73\x1f\xd4\x5f\xc8\xb6\xe7\xbf\x56\x29\xef\xe1\x49\x6f\xef\xe3\xc9\xc7\xcb\x72\xdf\xf3\x7c\xe7\xb2\xfc\x70\xa8\xca\x7c\x7c\x03\x29\x1f\x3f\xbc\x57\x81\x0f\x1f\x21\xf0\xf1\xe3\x87\xf1\xff\xad\x1d\xbb\x74\x5c\xcf\x79\xa3\x9a\x7e\x77\xa8\x9a\xd1\x6f\x95\xfb\xaf\xa0\x99\xfd\x8f\xd0\xcc\x81\x37\xde\x79\xb6\xdb\xea\x6f\x3d\xc9\x94\x9e\xb1\xc7\x25\x9d\xaf\xc0\xd4\x6d\xed\x21\xa1\x3e\x8a\xc0\x3e\x15\x0f\x43\xb1\x90\xc5\x3b\xfd\x20\x55\x80\x3a\xb8\xac\xaa\x7d\xfd\x73\xa0\x7e\xb4\x7d\x38\x2e\x65\x1e\x5f\x97\x52\x9c\x2a\x64\x9f\x6f\x89\x04\x5d\x73\x96\xe9\x94\x79\x59\xc8\xef\x45\xa3\xd0\xc6\x52\x1d\xbd\xe8\xf0\x6a\x99\x30\x96\xe7\x1e\x16\xa2\x6e\xa5\xe0\x69\x2c\xe3\x1f\xe2\xfb\xd7\xcf\x8c\xeb\xa8\x5c\xcc\xb3\x5b\x71\xa2\xae\x0e\x46\xa4\x33\x5e\x6a\x9d\xaf\xc7\xe5\x00\x81\xde\x64\x2e\xd2\x5e\xc4\xd3\xa9\xc8\xb3\xb2\x48\x1e\xbe\x09\xf9\x29\x4d\x45\xfe\xf7\x8b\x2f\x9f\x7b\x46\xa2\x00\x0c\x5f\xd7\x81\xf7\x0a\x81\x8b\xa8\x17\x37\xb9\xd4\x71\x9a\x8b\x42\x6b\x22\xa4\xf2\x24\x8a\x25\xbf\x4e\x84\xc1\xe9\x4d\xf2\xdf\x1f\xa2\x1c\x0e\xb6\x26\x41\x3e\x24\xa2\xe1\x0c\xf7\x9e\x62\x0d\x4f\xd5\xe6\x54\x5b\xfd\x16\x0c\x84\xf5\x7d\xaa\xdd\xe9\xab\xaf\xbe\xaf\x48\x7a\x3a\x1a\x21\xbd\x16\xef\x67\x3c\x2f\x84\x44\xd4\x84\x9d\xd0\x44\x8c\xe9\x08\x85\x09\x2f\x0a\x35\x79\x88\xea\x6f\x88\x55\x08\xf6\x63\x96\x23\x8a\x26\x59\x6e\x62\xe4\xe2\xe4\x8f\x32\xbe\x45\x14\xbe\x1d\x01\x81\xf1\x78\x7b\xff\x8c\x9a\xce\xc8\x1b\x0f\xa6\x23\x59\x77\x55\x52\x1f\xba\x3a\xf2\xc7\x1b\xbd\x45\xe1\xea\x4c\x21\x8a\xa2\x9c\x4f\xa7\xe6\xbb\x58\x88\x24\x81\x69\x46\x14\x81\x24\x25\x7a\xa2\xe9\x95\xa9\xd9\x83\xf6\x56\xdd\x67\x6c\x36\xcd\x4b\x99\x7d\xd5\x16\x29\xc1\x36\x85\xa2\x7f\x79\xf2\x55\x68\xee\x65\x43\x55\xc0\x74\x84\x65\x61\xba\x54\x0b\x81\xbe\x4d\x16\x33\xfe\x5f\xe8\xcd\x7a\xfb\x88\x27\x49\x76\xf7\xb1\x4c\x92\x6f\x61\x2e\x44\xda\x03\x85\xb5\x9e\xea\xd4\x47\xd5\x1c\x7c\x9d\x27\xfc\x01\x64\x86\xf2\x2c\x29\x6a\xb0\x53\xbf\x22\xef\x45\x31\x74\x29\xaa\x3f\xce\xe3\x50\x61\xf6\x4f\xa9\xf9\xa8\xe3\xbf\x8a\x79\x26\x85\xaa\xe9\x9a\x87\x37\xea\xec\x99\x9f\x66\xff\xd4\x24\xa1\xe8\xcd\xb4\x10\x52\x92\x65\x8b\x5e\x9a\x7d\xc9\xa2\x32\x51\x87\x57\x93\x9e\x2d\x44\xda\x5b\x24\xfc\xa1\xf8\x94\x26\x71\x2a\x7a\xb9\xe0\xd1\x59\x9a\x3c\xf4\x72\x33\x3f\x3d\x63\xd5\x33\xea\x81\x8a\x57\xd4\x2b\x04\x9f\x27\xa2\x28\x7a\xb1\x14\xf3\x6f\xa0\xf6\xf5\x5f\x83\xec\xfd\xbf\xb4\x7c\xa1\xde\x7d\x88\x22\x63\x00\x58\xc0\xa7\x84\xa8\x42\x24\x70\x63\xfd\x4b\x0b\xb4\x4f\xfb\xde\x96\x9d\x84\xc2\xfa\xac\x44\x51\x76\x97\x26\x19\xff\x6b\xd5\x1d\x6c\xdf\x98\x28\xcc\x92\x02\x51\x94\x67\x77\xea\xa7\x88\x7f\x68\x08\xe7\xe9\x5f\xaa\xf5\xd5\x13\xb5\xe6\xd9\xdd\x37\x55\x07\x45\x85\xe4\xb9\xfc\x4b\x75\xbd\xfc\xf3\x09\x1e\x68\xed\xd6\xdd\xd1\xa5\x13\x8c\xf1\x88\x3b\x3f\xd4\x65\xb9\x3d\x06\xae\xbb\x57\xe0\x91\x3f\x5e\x63\x2e\x34\xf9\xee\xd6\x1c\xea\xb0\xe9\x86\xef\x64\x32\x54\xc8\x02\xde\x25\x06\x46\x6e\x9f\x65\x43\x23\xde\x07\xea\xd7\xb9\x65\xed\x35\xc4\x08\xbc\xf8\x82\x58\x1c\xd8\xb5\x45\x67\xf5\x37\x51\x29\xa9\x0e\x81\x85\x81\xd3\xfa\x1b\x0c\x37\xad\xbe\x28\x18\xc5\x63\x63\x9d\xb5\xab\xf0\xb2\x96\xaa\x2e\xe1\x60\x3a\x9e\xa5\x5a\xb3\xb0\x79\xed\xab\x75\x10\x8d\xf4\x8b\x91\xf0\x68\xde\xa8\xb5\x24\x86\xbe\x58\xd4\x92\x18\xb5\xd4\x58\x23\xb8\x61\xa2\x73\xe3\xfd\x51\x35\x36\xec\xa7\xeb\xc7\x69\x80\x22\x2e\x39\x08\x10\x6b\x0d\xc7\xee\xc2\x35\x37\xdf\x97\x84\x58\x16\x52\xd4\x31\xe4\x14\xeb\x62\x70\xf0\xf8\x57\x0f\xaf\x75\x05\x1c\x4f\xf0\xaa\x53\xe6\xba\x23\xc4\x0c\x30\xed\x6a\x54\xee\xd7\x95\x49\x18\x49\xef\xa0\xa9\x5c\xcd\xb5\x8e\x7b\xd9\x4a\xb0\x9c\xf2\x53\x2c\xb5\xd8\x49\xef\xd5\x7a\x74\x55\xf9\xc7\x72\xd9\x74\x4e\xbf\xe6\xd0\x9c\x80\x85\x2a\x6d\xf4\x3a\xd7\x96\x98\x15\x2c\x0c\x37\x39\x5e\xfd\xfe\x42\xbf\x0c\xce\xa9\x20\x55\x55\x87\x66\x20\x3b\x8a\x27\x8d\x60\xd3\x5c\x01\x7f\xdf\x0b\xf0\x4c\x7f\x28\x18\x27\x4b\x2c\x49\xeb\x2b\x39\x1d\x0a\x43\x22\xbc\xad\x89\x11\x2c\x49\x20\xdc\x42\xc8\x4e\x0c\x45\xc8\x4e\x09\x09\xb2\x75\xca\x64\x28\x46\xd9\x0a\x59\x32\x66\x4d\xcd\xfb\xfd\x1a\x94\x2d\x0b\xa1\x20\x0d\xb0\x64\xd9\x2a\xd1\x43\xf3\xf5\x18\x20\x83\xe8\xcf\x7b\x87\x53\xb6\xaf\x5d\x8f\xe8\xea\x89\x26\xb5\x32\xcb\x02\xf1\xd4\x14\xb8\x1b\xc8\x4e\x69\x3e\x5c\x1d\xc8\xe9\x37\x9c\xc3\x2d\x6e\x73\x80\x29\x21\x84\x2c\x81\x68\x48\xa5\x33\x13\xf1\x74\x26\x7b\x3c\x89\xa7\x70\x75\x71\xae\x79\x21\xe0\x1c\xe0\x39\xbf\x8e\x43\x47\x1d\x27\xbd\x3a\xd2\x01\xc3\xc1\xbd\x90\x2f\xea\x82\x61\x12\x2f\x9c\x05\x97\x33\xfd\x95\xab\xd3\x25\xcc\x92\x2c\x77\xe2\x54\x8a\x7c\x61\x2e\xf8\xdb\xe2\x9c\x49\x9c\x48\x91\x17\x26\xcd\xe8\x90\x9b\x90\xb6\x9b\xa0\x48\xa7\x28\x9b\xc7\x29\xef\xf6\x4c\xa4\xea\xd8\x73\xd4\x69\x37\x05\x33\x3f\xbd\x49\x9c\x24\x4e\xb6\xe0\x61\x2c\x1f\x74\x00\x3a\x32\x49\xb2\x2c\x72\xa0\x42\xf3\xdd\xe4\xc9\x52\xe9\x4c\xf8\x3c\x4e\xcc\xb7\xc2\xd6\xed\x97\xc3\xa3\xdf\xcb\x42\x9a\x08\x99\x0b\x19\xce\xea\xc0\x43\x62\x32\xd6\x5c\x0c\x08\xdc\xe9\xe9\x98\x26\x0f\x8b\x99\x93\xf2\xb9\x30\x9f\x59\x1e\x8b\x54\xea\xf1\xce\xb2\x3c\xfe\x91\xa5\x92\x27\x5b\x12\x6f\x45\x2e\xe3\x50\x5d\x0e\x55\x2e\x87\x47\xb7\xce\xbd\xf9\xce\xf2\x78\x1a\xa7\xce\x7d\x2f\x9e\xf3\xa9\xe8\x4c\x4d\x22\xa4\x14\xb9\xa3\x20\x09\x82\xaa\x0b\x71\x3a\x35\x23\x9e\xf3\xfc\x46\xe4\x8e\x48\xa3\xfa\x73\x1e\x37\x9f\x70\x96\xf4\xb2\x5b\x91\xc3\xba\x2e\xc0\x05\x47\x96\xb6\x31\x72\x16\x87\x37\xa9\x3a\xe5\x17\x3c\x4e\xa5\x93\xe5\x91\xc8\x7b\x0b\x9e\x66\x85\x70\xfc\xde\x22\x83\xb5\x74\xc4\xad\xba\x61\xf7\x9a\x3e\xc1\x12\xa7\xb2\x07\xbc\x90\x4e\x57\x0b\x99\x2d\x4c\xbf\xe0\xb3\x5e\x88\x42\xe6\xf1\x8d\x50\xf7\xde\x72\x3a\x6b\xbb\xb1\x1a\xdd\xf6\xa5\x90\x79\x76\x23\x9c\x88\x17\x33\x60\xe1\x74\x23\xb2\xc9\xa4\x10\xb2\x8e\x51\x83\x08\xf9\xa2\x1b\xfc\x3d\x8b\xd3\x3a\x0c\x4c\x48\xe0\x45\xd6\x31\x9d\x1e\xa9\xe0\x5d\x1c\xc9\x59\x4f\x8a\x7b\xe9\xf0\x34\x9c\x65\xb9\xfe\x8e\x44\x98\x69\xd2\x5e\x87\xdb\x11\xaa\x9b\xf2\xda\x64\xb6\x51\xed\x08\xca\x34\x0e\xb3\x48\x38\xd7\x71\x14\x37\x01\x30\x4b\xaa\x42\xb2\x70\x16\x6a\x56\xe7\xbd\x5b\x87\x2b\x02\xf4\x5a\xc8\x38\xec\xdd\x3a\x33\x9e\x4e\x55\x2b\xb7\x4e\x1c\x89\x6c\x9a\xf3\xc5\x0c\xe2\xe7\x5c\xce\xc4\x9c\x6b\xd0\xb9\x15\xa1\xcc\x72\x47\x4c\x26\xa0\x98\x24\x72\x09\x70\xf4\xa0\x3f\x1b\x30\xea\x86\x1e\x7a\x77\x59\x1e\x35\x20\x74\x97\xc7\x00\x41\xf3\x2c\x12\xbd\xfb\x79\x92\x16\xc1\x7d\x12\xa7\x37\xbd\x7b\xb3\xe1\xff\x9c\xd2\xab\x55\xf9\x6b\x76\xfc\x03\xbd\x26\xdb\x6e\x0b\x1b\xf4\x32\x34\x14\xf0\x50\x96\x8a\x2e\x35\xa1\x3c\xcc\xb3\xa4\x0e\x75\x3e\x8b\x59\x76\x67\x3e\x65\x2c\x9b\x68\x85\x24\xff\x0f\x76\x11\x19\xee\xe6\xdd\xdd\x9d\x7b\xb7\x0f\x7c\x2b\xff\xcd\x9b\x37\xbb\xd0\x18\x5a\x21\xd3\xee\xe7\x49\xa0\x30\x14\xa2\xf0\x99\xf0\x74\x6a\x3e\x01\xd1\x3f\x45\xb6\xfd\x77\xba\xf2\x9f\x5f\x3e\xab\xee\xbc\xde\x4d\xeb\xe3\x64\xb5\x4b\x92\x5f\x83\x0c\xb0\xba\x03\xe6\x59\x51\x9c\xc1\x92\xff\x25\x02\xd2\xff\x0b\x14\xfa\xd4\x85\x69\xf8\x7b\x2e\x26\xa6\x1c\x6a\x22\x90\xae\xc1\xac\xe9\x0c\x62\xfe\x6c\x32\xe1\xd4\xa6\x23\x54\xe4\xa1\xca\xac\xcb\x68\xf3\xc2\xfa\xc6\x3a\xd7\xaa\x11\xff\xdd\x01\x78\xb4\xef\x35\x14\xf0\x3d\xcb\xdd\xab\x2b\xc3\x26\xfd\x74\x7a\x71\xf2\xf5\xf4\xed\xe7\x6f\x35\xc3\xf4\xfb\xb7\x93\xad\xac\x52\x7a\xc2\xb4\x11\x96\x1b\xa6\xed\xac\x7c\x63\xda\x90\xca\x7b\xa6\xcd\xa4\xfc\xca\xb4\x1d\x94\x73\xa6\x0d\x9d\x7c\x65\xda\x94\xc9\x19\xd3\x16\x45\x2e\x98\x36\x19\x72\xca\xb4\x39\x90\x2b\xa6\x6d\x7e\x7c\x61\xda\xb0\xc7\x27\xa6\x8d\x77\xbc\x85\xdf\xd7\xf4\x33\xfc\xbe\xa1\x3f\xd4\xef\xbe\x47\x3f\xc0\x2f\x50\x73\x7f\xc9\xa6\x8c\x06\xb4\x8f\xac\x8d\x19\x9c\xb0\x8f\x1b\xa6\x65\xe8\x4d\x1b\x59\x5b\x92\xa1\xdf\xda\xb8\xd6\x70\x0c\x7d\xdf\xc6\xae\xd8\x89\xa1\xbf\x76\xaa\x68\xcc\xc2\xd0\xf3\x95\x58\x63\x05\x86\x7e\x6d\x63\x1b\xa3\x2f\xf4\xac\xd3\x5e\xd7\x18\x0b\xbd\xe8\x34\xd9\xd8\x5e\xa1\xa7\x9b\xb1\xc6\xd4\x0a\xbd\x6a\x93\xb4\x65\x15\xfa\xa5\x8d\xd1\x86\x54\xe8\xa7\x36\xc6\xd8\x4d\xa1\x1f\xd7\x4c\x9a\xd0\xb7\x6d\x9e\x6c\xc1\xff\x28\x85\x1b\x47\x88\xd0\xcf\x6d\x74\x24\xae\xcb\xe9\x95\xcc\x79\x28\xea\x79\xf8\xd1\x29\x34\x99\x14\xc0\x03\x40\x84\x7e\xe8\xf4\x40\x4c\x79\xf8\x70\xa5\x6f\xe8\x48\x33\x5d\xdf\xd1\xdf\xff\x82\x95\x20\x75\x78\x71\x99\xe5\xed\x75\xed\x97\xce\x75\xcd\xd0\x94\xa2\x35\x79\xd0\x6f\x2d\xbc\x83\x5f\x9a\xcd\x16\xb0\x60\xbf\x5b\x96\x18\xfd\x3e\xae\x2a\x31\x42\xff\xf3\x7f\xd6\x4d\xa0\x31\x19\x0a\x2d\x53\xd6\x34\xf6\xcc\x48\xa6\x36\x7c\xde\x77\x44\xe6\x0f\x8f\x5d\xee\x75\x47\x32\xb1\x46\x71\x85\xe4\xe1\x8d\x2b\xf3\x78\x8e\x49\x23\x36\x97\xe2\xde\x0e\xe6\xb2\x47\x86\x64\x97\x0c\xde\x81\x9c\x92\x31\x1f\x67\x2e\x0e\x20\xdd\xfc\xce\x16\x30\x3d\xdf\x59\xdf\x6f\x07\xfd\x4f\xcd\xd6\x8e\x27\xb8\x2f\xaa\xea\x7b\x2d\xe9\x8e\x06\xdf\x59\xdf\x33\x4f\x45\xd0\x1d\x77\x91\x8b\x05\xcf\xc5\x37\xd5\x85\x0b\xb5\x4a\x83\x27\xe2\x8d\xd5\xc9\x81\x91\x7c\x95\x04\xfc\xbe\x74\x45\x62\x57\x06\x49\xb7\x9a\xe5\xc2\x1d\x8e\x2b\x45\xea\xd2\x50\x20\xfa\x58\x08\x19\x3c\x59\xd1\x92\xd0\x0d\x09\x99\xaf\x62\x92\x88\x50\x5a\x96\xf9\x68\xb5\xc4\xb4\x64\xee\x46\x34\x96\x74\x34\x5e\x9b\xf9\x9c\x89\xe5\x66\x46\x41\x47\x63\x2a\x8d\xea\x22\xac\x9d\xbe\x59\x75\x05\x4a\x99\x58\x0a\x63\x1e\xb9\x1d\x4e\xb7\xc8\xf6\xe5\x86\x72\x6a\x44\x4d\x4c\x3c\xc1\xc2\xb2\x72\xcb\xda\xb4\xea\xa1\x81\xa2\x2b\x83\x58\xc3\x89\x39\xc3\x2f\xd5\x9e\xe1\x2c\xdf\x12\x1b\xb3\xac\xf1\x9a\x42\x13\xc6\x9b\xc0\xc0\x3f\x62\xb1\x65\x79\x47\x2c\xb1\xac\x6c\x14\x8f\xfb\x8c\xf1\x51\x32\x1e\x90\xc4\x71\xb4\xca\x5a\x9b\x63\x10\x3b\x0e\x4d\x1c\x47\x2d\x74\x27\x2f\xf4\xda\xef\x83\x19\x11\xf5\x93\x10\xed\xe4\x5a\xe5\xf6\x8e\x1d\x27\xa9\xaa\x6e\xee\x0e\xa8\xaa\xe8\xd6\xc2\x62\x8f\x4b\x10\xb6\x40\x14\x3e\x51\xed\xa4\xb9\xed\x40\xed\xe3\x62\xb9\x9c\xc4\x29\x4f\x92\x87\x47\x05\xe4\xf4\x29\xf8\xac\xdd\x22\x61\xc1\xc4\x50\xb8\x1d\x2b\x72\x55\x25\x5c\xad\xab\x8d\xc8\x50\x6d\xd1\x00\x75\xe4\x14\xfe\xae\x56\xa2\x36\x7c\xe4\x4a\x3e\x35\xf7\xfd\xe6\x2e\xff\x0c\x1b\xcb\x4a\xfa\x32\xef\xbf\x6a\x13\xd0\x67\xc0\x95\x26\x61\xbf\x93\xf0\xad\xc1\xc3\x26\xf1\xcd\x96\xc4\xcf\x80\x8d\x75\x06\x4f\x1b\x52\xda\xd3\x3f\x7e\xd3\xfa\x3f\x4d\xeb\x8a\x06\x30\x55\xf9\xeb\x69\xae\x26\xb6\xdb\x2c\x7b\x7b\x1b\x59\xae\xd6\xf3\x6c\xd4\xa2\x4e\xff\x35\xc6\x09\x42\x9d\xd7\xe7\x3f\xd6\xc4\xee\xd7\xdc\xf5\x6c\xb3\x42\xd3\x7a\x79\xda\xb2\x1c\x9a\xc1\xb1\xdd\x1c\x78\x53\xb0\xe6\x35\xd5\x5c\x98\x6f\x75\xcf\x6a\x4b\x42\x5a\x21\xa8\x77\x53\xc7\x6b\x5b\x3f\x26\xf6\xd7\x26\xb6\x3e\x70\x75\xfc\xfb\x3a\xbe\xb5\xe3\x63\x52\x2e\x9a\x94\x7a\x01\x75\xfc\xe9\x7a\x3c\xac\xdd\x72\xbb\x5d\xf2\x06\x9a\xd6\x2c\x68\x7d\x0d\x6a\x10\x5d\x9d\x0f\xf4\xbe\x3e\xe3\x6d\xe4\xd6\x56\x9f\x4c\xc3\xe7\x6d\x99\x2b\x43\x0a\xfc\xa4\x70\x6d\x01\xca\x14\x3e\x0b\x5a\x32\x5a\xad\x7e\xfd\xa6\x2e\xd9\x5a\x25\xd2\xac\x08\x42\x74\xad\x6f\x18\xa1\x3e\x63\x72\x88\x5a\x33\x4f\x18\x1e\x82\x09\x0a\x3a\x71\x35\x18\x5f\xd5\x50\xf5\xc7\xea\xae\xf9\xd4\x8d\x37\xb0\x68\x92\xbe\x04\xaa\x83\x57\x0b\xfe\x90\x64\x3c\xa2\x42\x05\xe2\x34\x96\x70\xd4\xb4\xa5\xc0\x89\x6b\xc7\xbe\x60\x07\xfc\x5a\x18\xfd\x47\x67\x33\x37\xcb\xf1\xb8\x55\x65\x4c\x6b\x9c\xad\xa8\x85\xad\x28\xaa\x41\xa0\x7d\xe5\x7d\xca\xc0\xd9\xca\x16\xf9\x8f\xee\xb1\x0e\xe6\x1f\x5b\x9c\xe4\xa6\x59\x04\xfc\x2d\x62\x59\x28\x4e\x17\x25\x28\x34\xac\x51\xe2\x96\x85\x35\x7b\xff\x3a\xbb\x47\xfa\x09\x11\xe5\x3c\x8a\x35\xdb\xb7\xc3\x5d\xfe\x9b\xb6\xf4\x7e\x05\x4f\x43\x0a\x01\xde\x88\x1c\x6c\xf4\xaf\xc4\x6c\x71\x54\xfb\x1f\xa0\xb4\x5d\x3f\x21\x04\xe6\x6d\xa9\x55\xd3\x79\xca\xe6\x25\x5e\xb1\x34\xd2\x39\xc6\x25\x01\xb3\x06\xb6\x18\x49\x6d\x40\x72\xfd\x2d\x15\xb8\x8d\x8d\xc6\x6b\xba\x55\xdd\x30\x55\xed\x3e\x91\x52\x08\x59\xb3\xd0\x21\x1b\x78\x87\x28\x84\x5c\x55\xd5\x59\xa7\x34\x04\x95\xf4\x31\xcc\xd2\x49\x3c\x2d\x41\x7f\xc8\x98\x68\x0d\x36\x9d\x1d\x64\xe6\x30\xd7\x9e\x15\x56\xa8\x11\x38\xb6\xd5\xe0\x28\x6f\x33\x81\x8d\x5a\xf2\x04\x85\x03\xed\x8a\x46\x6b\x29\x48\xdd\x36\xb0\x24\xf4\x71\x2a\xf4\x53\xea\x96\x7e\xe4\xd0\xf8\x5a\x6a\xd3\x83\x25\x2d\x64\xb6\x80\x85\x8d\xd3\x69\xb7\xf8\xfa\xa2\xd7\x0a\x13\x42\x8a\x9e\x5a\x95\xe5\x72\xb9\xc4\xa2\x2b\xab\xfc\x2f\x83\xca\xfb\x62\x55\x85\x07\x36\x62\xb7\x2e\x58\x50\xd9\xb2\xcc\x35\xe9\x08\x50\x02\xfd\xc4\x7a\xf1\x07\xad\x48\x20\xce\x35\x88\x09\xd7\xc0\xd8\x10\xc9\xbc\x14\x28\x40\x13\x9e\x14\x02\x05\x42\xfb\xb9\x00\x8f\x97\x39\xd1\x10\x81\xa5\x5b\x8f\x1c\x0b\x02\xd7\xd0\xa6\xaf\xff\xb9\x4e\x53\xab\xcd\xa4\xf0\x52\xbb\x37\x1b\x2a\xbe\x96\xa7\x18\xd6\x1f\x81\x71\xe2\xbc\xea\x5c\xae\x83\x58\x84\xab\x2e\xd2\xb7\xb5\xe8\x85\x3a\x9b\xae\xb3\xe8\xc1\x20\x9a\xae\x30\x24\x44\xb7\xdd\xfa\x5f\x5d\xa5\x17\x59\x0f\xb6\x11\xcf\xc3\x8f\x4b\x05\x08\xab\xef\xe5\xa6\x37\xb4\xfb\xa4\x5e\xc7\xdd\x76\x03\xa6\xb6\x40\x3f\x48\xa4\xc3\x34\x10\xee\xd5\x5d\xce\x17\x0b\x91\x83\x71\x61\x57\x21\xc8\x98\x27\xa6\xe2\x65\x67\xbe\x84\xe8\xf6\xcc\x3c\xf3\xb8\xdd\x26\xc1\x1a\xfa\x4a\x0c\xcd\x8d\x0e\x41\x33\x90\x61\xf3\xd5\x66\x35\x8d\x0d\x52\xf6\x8f\xda\x95\xbc\x5e\xcb\xa1\xf9\x0d\xc0\xbf\xf7\x4a\x47\xd9\xe3\x6a\x4f\x83\x9c\x9a\x08\x3d\xfa\x94\x9a\x47\xde\x44\x44\xc1\x2a\xea\x03\x04\xba\x82\xff\x20\x66\xb8\xd6\xd3\x60\xa5\x2b\x5d\x69\x39\x33\x11\x46\x9b\x43\xb6\x45\x88\xf6\x51\xd3\x3e\xa4\x4a\x60\xdd\x34\x25\x53\x53\xd2\xd4\x60\xa0\xfe\x1f\x58\xd6\xa0\x9b\x9b\xbe\xb4\x8f\x46\x29\x69\xd5\x3e\x59\x3e\x04\xb1\x67\x85\xea\x34\x8e\x87\x62\x0a\xb6\xe0\x43\xe5\x06\xbb\x7a\x10\x62\xf0\xb0\x12\x34\x69\x10\x5e\x4f\x6e\xbd\xa0\x14\xe5\xf5\x3c\x86\xa3\x23\x57\x73\x23\x0a\xa1\x03\x35\x80\x03\x04\x6d\xbe\x99\x18\x3c\x4f\x06\xeb\x46\x47\x9a\x94\x61\x06\xa3\xd5\xa4\x60\x4a\x82\xcd\x8c\x5d\x88\x41\xc4\xb2\xba\x05\xd4\xe4\x74\xd3\x49\xe3\xff\xb1\x9e\xf4\x5a\x3b\x65\x1d\x9c\x60\xa8\xab\x51\xac\xdf\x5f\xcf\xd5\x59\x9d\x5c\xd4\x92\xc5\xea\x0a\xfa\xd4\x70\x14\x4d\xf3\xf3\x01\xd4\xd7\xc0\x76\x29\xfb\xcd\xf4\xf6\xc1\xbe\x90\x99\xde\x3e\xcc\x75\x73\x82\x19\x28\x68\x6c\x24\xd6\x50\x61\x56\x60\x20\x01\x5d\x6f\xdf\xaf\x7a\xb7\xa5\x55\x25\xbb\x70\xd1\xac\xb5\x54\xfb\xa7\xdb\x4b\x26\x97\x40\x7f\xe1\x94\x69\xa2\x59\x03\x8e\x96\x17\x45\x9d\xdc\xed\xcc\xfd\x1c\x53\x50\xa8\x2e\x6d\x6b\x49\x3b\x33\x9b\x35\x33\xdb\x01\x66\x69\x59\xff\x89\x85\x9b\xdd\xa5\x22\xff\x60\xd0\x2a\xd1\x5c\x94\xda\xbf\xde\x70\xad\xd3\x7f\x32\xfe\x60\x35\x7b\x17\xe4\xd7\xab\x49\xbb\xa7\x16\x17\xab\xf2\xe9\x2c\xc3\x8f\xb5\xf8\x92\xc1\x9c\x4b\x45\x8e\x60\xb9\x85\xee\x69\x0f\xa9\xdc\x7d\x6f\x0a\x35\xec\x52\xb1\xaa\x55\xd0\xfa\x5e\x93\x36\x13\xc0\xd3\x95\x4b\xac\x20\x59\x97\x23\x7a\x15\xea\x20\x2c\x5b\x47\x03\x49\xac\x3c\xa5\x2b\xd2\x4f\x0b\x8a\x17\x80\x53\x40\xa6\xac\xb9\xd5\x7b\x83\xac\xd5\x81\xcc\xb4\x2e\xef\x33\x64\xa7\xa3\x6c\x3c\x66\x7d\x6f\x60\x8c\x33\x0d\xd2\x56\xfe\x3d\xb5\x6d\x92\xb1\x4d\xe8\x7e\xa6\x68\xb0\x74\x5c\xe3\x28\xf8\xae\xa5\x41\xfa\xf0\x36\x8a\x57\xe2\xc0\xb5\x2c\xb0\x1f\x74\xbc\x99\xfb\x6f\x75\xb2\x3a\x85\x81\xa7\xa1\xfb\x80\x90\xfd\x0f\x9c\x12\xe3\x27\x71\x9b\x26\x13\x8c\x76\x94\x99\x1e\x28\x04\xd8\x5c\xe3\x54\x6c\xd1\x56\x0c\x56\xfd\xb0\x6e\x39\xdb\xda\x32\x19\xd4\xbb\xab\xaa\x74\x1e\x23\xf4\x53\x55\x58\x32\x15\x43\x96\x75\x0e\x43\x3f\x74\xba\xdd\xd1\xca\x12\x0d\x2b\xac\x41\x3f\xdb\x05\xdd\xd6\x64\x4c\xdf\xf8\xad\x4e\x55\x7d\x9a\xaf\x9c\xd1\xdb\x0e\xf1\x06\x1a\xff\x64\x07\x74\xcf\xeb\x42\xac\x52\x12\xd0\x48\xd7\x79\x25\xf4\x9d\xb5\xd0\x47\xe5\xda\x79\x4e\xeb\x23\xa8\x33\xca\xf5\xd1\xec\x69\x07\x7e\xab\xee\xb2\x52\xa3\x1d\x85\xfd\xe3\xc6\x24\x04\x59\x2f\xb9\xaf\xd6\x02\xd4\x1e\x97\x92\xa5\x4b\x83\xd5\xb5\xf7\x32\x44\x68\xca\xe4\xf2\xa9\x33\x5f\xcf\x8d\x82\x9a\xce\x8a\x94\x2b\xe3\x5d\x39\x54\x37\x0e\x11\x03\x04\x0a\x37\x68\x08\x4c\x49\xbf\xc1\x9b\x9d\x33\x32\x6d\x4f\x9b\x6e\x79\xcb\xda\xc0\x34\x5b\xd0\x4c\x6a\xce\xaa\x3e\x98\x94\xdb\xc4\x41\x79\x57\x5e\x58\xac\xdc\xf0\xb4\x91\x66\x29\x52\x39\xd0\x08\xfd\xe9\x25\x57\xb4\x80\x06\xd6\x0e\xd8\xb6\x78\x5f\x0b\x16\x0b\xf6\xe4\x5b\xd0\x4c\xce\x93\x8e\x5b\xb5\x89\xe8\xb2\xad\x6a\x1b\x2b\xb7\x8d\x81\x95\x2d\xf5\xec\x79\x9e\xb7\xab\xb2\x68\x49\x9c\x39\x97\xb3\x9f\xe4\x86\xf7\xb3\x2f\x5c\xce\xe0\xcf\x97\xcf\x68\xfd\xde\xfb\xd3\x8e\x76\xd6\x7b\x21\x36\xbc\x04\x6a\x16\xfc\x4f\x2b\x00\x7f\x7c\x13\x90\xf5\xf8\xd9\x50\x18\x98\x28\x46\x93\x2c\x17\xf1\x34\x3d\x6b\xfc\x96\xc8\xe1\xcf\xab\x0f\x34\xd7\x7c\x26\xe8\x5c\xd0\x5b\xc1\xf0\x7c\x5d\x4d\x5a\xd1\x5a\x3f\x69\x18\xc0\xb0\x79\x5e\xfc\xfe\xf5\x53\x55\xa1\x46\x1a\x16\x69\xe7\x71\x6e\x13\xc1\xe4\xa0\xc1\xa4\x78\x26\xd8\x4c\x54\xd5\x76\xd9\x6f\x8c\xa2\xf8\x16\x11\xd2\x29\x8b\x8e\x8a\xdb\xe9\x31\xb2\x65\xed\x20\x10\x77\xb4\xdb\x88\x8d\x8e\x76\x21\x9d\x4a\x36\x13\xee\x24\xce\x0b\x09\xe7\xdb\x60\x25\x40\x6a\x92\x10\x82\xb8\x9b\xa6\xb5\xb1\x06\x72\x2d\xbb\x82\xe3\x34\xd2\xd9\xbb\x69\x64\xb9\xa4\xdb\xee\x5e\x5f\xbe\xbd\x5d\x2c\x2c\x0b\x7e\x40\x6d\xfa\x7b\x5a\xf0\x89\x00\x37\x3c\xb5\x36\xf9\x70\x53\xd8\xec\xa7\xf9\x3b\xef\x98\x0d\x00\xcd\x35\x3c\x2d\x09\x59\x06\x73\xd1\x51\xae\x98\xb6\xa8\xbe\x63\x8d\xa0\x33\x28\x6d\x14\x27\x85\x8d\x9a\x70\x13\x6b\x59\xfb\x20\xe1\x96\x66\x91\xb8\x68\xa5\xdc\x80\x8e\xc6\x3a\xfa\x9f\xf5\x1e\x5d\xd9\xf1\x4c\x02\x08\x3d\x08\xf6\xc8\xd3\x78\x0e\xa2\x0f\x9f\xe0\x6d\x28\xce\xd2\xf7\x59\x99\xca\xa0\xef\xd1\x6b\x10\x0f\xf9\x34\xe7\x53\x71\x56\xca\x42\xac\x47\x7e\x4b\xe2\x50\xac\xc5\xfd\x12\x47\xda\x01\xcc\x75\x76\xff\x31\x11\xf7\x9d\x4f\xf0\x4d\x6b\xc2\x67\x79\x14\xa7\x3c\x69\xa2\xc2\x2c\x29\xe7\x6d\xcb\x3a\x08\x1e\x55\x26\xa6\x92\x89\xae\xe1\xae\xfe\x3e\xcf\xb4\xee\x5e\x1d\xfe\x36\xcb\xe3\xf4\xa6\x0e\x9d\x8a\x29\xef\xa6\x9e\xe5\xc6\x61\xcb\x34\x8f\xa3\xb7\xb9\xe0\xf5\xf7\x57\x5d\xa3\xf9\x3c\x49\xa3\x4e\xe8\xdb\x82\xa7\xdd\xa0\xe4\xb9\xac\xc3\xef\xa1\x87\xab\xa1\x4e\x69\x1d\xd1\xad\xc0\xc4\xd4\x75\x4c\xb2\x54\xfe\x02\xc2\x17\xe0\x37\x27\x4e\xc5\xfb\x84\xcf\x17\x75\xe0\xef\x4d\x92\x91\x60\x81\xcf\x7a\x10\x59\xbe\x98\x71\x3d\x3d\x92\x5f\x7f\x8b\x7f\xc0\x38\xef\xe2\x28\xbb\x83\xc8\x1f\x20\x21\x00\x5f\x59\x36\x87\xe6\xe2\x24\x39\x6b\x6b\x02\xb9\xa9\x4e\xb8\x90\xd9\x62\x25\x98\x67\x37\xe2\x43\x2d\x8f\xb3\x1a\xa5\x25\x72\xda\xb8\x2f\x8d\xd0\x4d\x1b\xb7\x51\x57\x0d\x16\x4b\x7a\x2d\xd8\x08\xfd\x22\xae\x6f\x62\x89\x28\x9a\x17\x88\xa2\x2f\xd9\x0f\x44\xd1\x19\x1a\xb7\xfb\xe1\x4e\xac\x99\x90\x68\x44\x3e\x1b\x5e\x68\x6b\xc1\xac\xaa\x90\xc1\x9b\x28\x48\xb7\x58\x11\x92\x55\xe5\x69\x7e\xe4\xc3\x06\x7f\x4f\x5d\x4a\x1e\xc4\x48\x8c\x87\x18\x21\x5b\x12\xf3\x94\x19\x48\x1b\x2d\xee\x3b\x2f\x2d\xf7\x62\x4d\x45\x1e\x9c\x6c\xc2\xc3\xd6\x43\xa2\x52\xb6\xdd\xe7\xd2\xe6\x9e\xa6\x25\x51\x1b\x9f\xf0\x8e\x83\x08\xcd\xd8\x9d\xc0\x29\x95\xa3\x74\x4c\x73\x32\x40\x93\x24\xe3\x70\x00\xa4\x20\x4a\x89\xc2\xa2\xf8\x08\x51\xa4\x96\x04\x6c\x2b\xa6\x19\x09\x14\xe1\xcb\xb2\xe5\xb2\x6b\x57\xe6\x41\x3c\x21\x1d\x73\x2d\xb6\x9b\xb2\x92\x4c\x1a\xf5\xe3\x5a\xf5\xb8\x23\x10\x6c\x8b\x8e\xfd\x55\x9f\xd0\x07\x31\x92\x63\x06\xd3\xa5\x50\x98\x91\xb6\x38\x81\xcb\xcc\x5c\xa4\x65\x2c\xc5\x1c\x16\xf9\x91\x9b\x2d\x76\xcd\x0b\x8d\x21\x72\xb3\xad\xd5\x8f\x98\x5f\x0b\xd8\x29\x33\x88\x8d\xe7\x53\xf8\x49\x17\x25\x80\xd0\x8d\x78\x98\x8a\xd4\xec\x04\xd8\xd1\x73\x21\xa1\xb6\x05\xcf\x39\x80\xb3\x16\xf6\x07\xf8\xcf\x79\x08\x79\xee\xa0\x89\x65\x07\xa7\xde\xac\xe0\xd4\x78\x82\x4f\x54\xc7\x1b\x99\xdd\x96\x28\xd5\x8f\x39\x3f\x23\xaf\xd7\xe8\x4a\x7f\xff\x90\x0a\x4d\x94\xfe\x59\xc9\x2e\xf1\xde\x5c\xc1\x56\x6b\x7b\xe5\xe9\xaa\x36\xde\xf5\x9f\xac\xb5\xaa\xfa\x18\x5d\x5d\x01\x35\x10\xa7\x4f\xe7\x5b\xef\xf7\x2b\x5f\xbb\xb6\xab\x3b\x04\xb0\xdb\x9a\x5a\xeb\x34\x0c\x29\xeb\xa5\xf7\x48\x97\x16\xfe\xd6\x4e\x2f\xf8\x4b\x14\x1d\xf0\x6e\xcc\x2b\x6d\x9a\x1b\x74\xe3\x62\xed\x5d\x0c\x81\x7d\x2b\x2d\x30\x79\x3f\xaf\x8d\xe1\xad\xc8\x8f\x9a\x38\x23\xe0\x19\x6e\x84\x9d\x22\x0f\x37\xe2\xca\x3c\xde\x88\x9b\x80\xef\xfd\x8d\x68\x45\x0c\x99\xc8\x79\x5c\x14\x71\x3a\x75\x40\x98\xb3\x11\xf5\xf6\xd7\xa5\xb2\xbd\xce\x4c\xbc\x17\xad\x9c\x86\x96\xf4\xe6\xf9\x54\x00\x3f\xb6\xc8\xc3\x86\x3b\xab\xf5\xe6\x88\x0b\x36\xc6\xc1\xfd\x4e\x9c\x4e\xbf\x17\x35\xf5\x04\xb6\x8b\xc5\x53\xa9\x84\xee\xc3\x1c\xd7\x47\xfd\x50\xb8\x0b\x9e\x8b\x54\x9e\x82\x16\x2b\x1c\xe7\xbf\x0a\x7d\xbd\x3d\x37\xbf\x5f\xf5\x6f\xbb\x23\xce\x44\xfd\x72\xcf\xd2\x0c\x0b\x7d\x83\xda\x62\x9f\xed\xd7\xf5\xa5\xdf\x7b\xed\x99\xcd\x6e\x64\x3e\xa4\x50\xed\x0e\xf4\x55\x2a\xcb\xb0\x24\xf4\x57\x81\x3b\x49\xd4\xbc\xcb\xca\x15\x98\xb9\x80\x0e\x9c\x8b\xe1\x57\xf5\xbf\x31\x41\x44\x82\xaf\x82\x8d\xc4\x38\x38\x17\xac\xc3\x8a\x38\x15\x18\xfa\x77\x2e\x6a\x63\xb6\xe7\x82\x4a\xf6\x15\xee\x97\x5f\x55\x48\x8f\x12\x06\x45\x25\xd8\x66\xda\xa2\x00\x79\x26\x8c\xf6\x63\x5b\xf3\xd5\x1a\x2f\x06\x77\x1f\xa7\xbe\x88\x56\x55\xae\x9b\xc5\xc4\xb4\x19\x3f\xa9\xfe\xc1\xbc\xbf\x15\xec\x4a\xd0\xcf\x82\xf5\x7d\xfa\x43\xac\x08\xb3\x7c\x50\x99\x8c\xe8\xce\xb9\x61\xbb\x31\xc6\xbe\x8a\xaa\xc2\xaa\x02\xaa\x46\xd9\xa9\xf4\xa3\x58\xb3\x47\xd5\x4c\x75\x73\xa9\x6e\x39\x13\xb0\xb8\xfa\x7c\xc9\x32\x9c\x92\x4e\x9e\x7c\x25\x4f\xca\xf2\x91\x1c\x0f\x44\xb0\xea\x80\x09\x65\xe9\xfb\x24\x0e\x6f\xea\x97\x44\x1d\xaa\x75\x4d\xeb\xc8\x0f\x59\x79\x9d\x88\xd5\x8c\x9d\xb8\xf5\xec\x5f\xb2\xb2\x10\x1f\xb2\xbb\x74\x33\x66\x6b\xd6\x2f\xd9\xed\x96\x98\xad\x59\xbf\x2f\xd6\xc3\x5b\xb3\x9d\xa4\x52\xe4\x28\xc0\x39\xeb\xe7\x0d\xeb\x85\x54\x95\x8a\xc0\xe8\xba\x94\x12\xde\xe8\x58\xeb\x76\x0a\xee\x3f\xf5\xa3\x66\x55\x19\x3d\xa4\x3a\xa4\xe8\x66\x75\x9e\x41\x98\x10\x2a\x58\x3f\xd7\xe2\x1d\x9d\x07\x55\xb5\xec\x0a\xb5\x6e\x88\x16\xa4\x5b\x2d\x20\xae\x9f\x01\x7b\xfb\x3e\x95\xb4\x49\x6c\xb8\x37\xa9\x96\x1f\x03\xa0\x8a\x27\x38\x02\x91\x2c\x15\xf5\xbb\x60\x8f\xcb\xc1\xf6\x67\xbc\xdf\x05\x45\x0b\x5e\x14\xf1\xad\x40\xf0\x68\xd7\x7d\x70\x53\x75\x79\xcb\x25\xa1\x46\x8d\x97\x47\xd1\xc9\xad\x48\xe5\xe7\xb8\x90\x22\x15\x39\x46\x52\x14\x12\xd1\xdf\x05\xfd\x5d\x34\xb9\x8c\x1e\xe6\xd3\x19\xcd\xa3\xd3\x5c\xe8\x16\xfc\x16\xa4\x7f\x11\xab\xba\xa7\x34\xa1\x45\x6d\x03\x43\xb3\x74\x5a\x45\x56\x50\x8a\x31\xa6\x58\x6b\x45\x6f\xba\xaf\xfd\xf4\x49\x63\xac\x34\xa5\x65\xe7\x2d\x1d\xb4\x44\xb3\x54\xcf\xa3\x20\xda\x2c\xc5\x33\xd8\x8a\xdf\x0d\x82\xf8\x27\x84\xfe\x6e\x42\x7f\x08\xf6\x68\xf2\xaf\x3c\x54\xaa\x32\x9e\x2a\x23\x96\x1d\xbd\xd9\x7f\x6c\xed\xfc\x6a\xfd\xbf\x08\xd3\xb3\x3f\x44\xeb\xd5\xb2\xb3\xa7\xff\xa3\xcb\x77\xa1\x29\x83\xbd\x2c\x5c\x9e\x80\xea\xa2\x14\xc4\x5c\x61\x0d\x0b\x9e\x48\xd6\x7c\xc3\xc5\x5b\x30\x39\x88\xb2\x47\xaf\xcf\xb0\xef\xed\xbd\x52\x18\x57\x51\x79\x09\x9f\x16\x5a\xe9\xa6\xce\xae\x40\xb3\xfe\x36\x12\x49\xa2\xf1\x67\xba\xaf\x1f\xa1\xf8\x74\x98\xae\x09\xfe\xfd\xad\x3e\x15\x7c\x7d\xc4\x80\x18\x51\x8d\xeb\xe7\x62\x9e\xc5\x3f\x8c\x5b\xd0\x0e\x82\x69\x79\x41\xb0\x8d\xda\xc1\xc0\x89\xb0\x56\xae\xe6\x51\xb1\xfa\x35\x56\x91\x2c\x62\x06\xfa\xb4\x22\xda\x2e\x0d\xf1\xaf\xba\x57\x30\x7d\xfd\xd6\x56\x66\x43\x84\xbd\x7e\xdd\xc5\x9c\xff\xd9\x9e\x6d\xdb\x44\xb1\x9b\x0e\x9a\x57\xe1\x56\x18\x88\x61\xc9\xa0\x8d\x0d\x2a\x4f\x35\xd0\x48\x9d\xa8\x1e\x68\x39\x4b\xb1\x6c\xed\x64\x09\x9a\x33\x39\x18\xb4\x6f\xfc\x66\xe1\xda\xda\x33\xe3\x2b\x40\x5b\xb2\xca\x56\x3b\x62\xf2\xf0\xae\xde\x1a\xce\x59\x56\x2f\x28\x79\x4c\x59\xde\x5a\x94\xd2\x32\x65\xf1\x04\x67\x9a\x96\x04\x63\xf6\xf0\xa5\x2f\x26\xaa\x7e\x08\x0e\xb8\xb6\xde\xce\xbb\xc7\xc5\xbf\x04\xce\x08\x85\x76\x79\xf7\x88\xd0\xf1\x72\xc0\x19\x77\x8b\xf8\x3a\x89\xd3\xe9\x72\xdb\x54\xab\x2e\x9a\x8e\xf5\x19\xcb\xeb\x3e\xa6\x2c\xa3\x39\xe3\x2d\x93\x48\xdb\x36\xe8\xfb\xb4\x68\xba\x53\xe8\xee\x14\xd0\x9d\xc7\x44\xed\xb4\xba\x58\x33\xa6\x02\xfa\xa4\x13\x73\x96\xd1\xb4\x49\x2c\x58\xd1\x74\x4c\xad\x9e\xf1\xfb\x50\xd4\x83\xdf\x5e\x3d\x57\xb5\x3c\x55\x3d\x57\xed\x3f\x59\xfd\xfa\xe8\xdf\x28\x22\xe6\xff\xe3\xee\x5d\x98\xdb\xb6\x95\xfe\xe1\xaf\x62\x71\x3a\x1c\xe0\x0d\xa2\x47\xf2\x2d\x09\x15\x1c\x4d\x9a\x4b\x9b\x34\x69\xd2\x5c\x4e\x2f\xfe\x7b\x32\xb0\x04\xdb\x6c\x28\x40\x05\x41\x3b\x8e\xa5\xf3\xd9\xdf\xc1\xe2\x42\x80\xa4\x9d\xf4\x3c\xe7\xf9\x3f\xef\xbc\x9d\xc6\x22\x41\x10\x04\x16\xc0\x62\xb1\xd8\xfd\x2d\x34\x3f\xf4\x1e\xc0\xb8\x74\xf2\x3d\x98\x58\x2a\xed\x01\x04\x90\x99\x46\xb7\x0c\x28\xd1\xae\xed\x63\x17\x45\xcf\xba\x8c\x15\x7a\x0b\x76\x04\xe9\x4a\xd2\x02\x6f\xf0\x99\x6d\xed\x81\x9f\xd0\x9b\xcd\xa1\xbf\x0c\xd3\x0b\x40\x3a\xdd\xd0\x70\xbf\xae\xbf\xa8\x26\xda\xef\x45\x66\x1e\xc1\x0a\x14\xc0\x6e\xa0\x02\x37\x1a\x69\x4f\x12\xfb\xb1\x91\xe7\x2b\x9b\x8d\xbf\xa2\x5d\x3b\xba\x96\x6f\x6d\xc3\xdb\xe1\xa3\xee\x02\xbe\xed\x89\x3d\x3c\xf1\x5f\x74\x77\xda\xc9\xec\xf5\x8c\xc4\x56\x4b\xdb\x25\x5a\x47\xc3\x7c\x34\x89\x2b\x12\xdc\x14\x41\x82\xd4\x44\x6b\x22\x34\x51\x9a\x48\x6d\x46\x28\xd3\xf4\xe8\x98\x94\xee\x58\xa8\x72\xbf\xb5\xfb\x6d\x34\x78\x1e\xbc\x62\x6b\xb2\x68\x2f\x97\xf0\xce\xa9\xa6\xd9\xca\x48\x1b\x4b\x79\x29\x76\xe0\xaa\x59\xef\x68\xd9\x2c\xce\x17\x4c\x2c\x78\x65\xaf\xb9\x58\xda\x0b\xeb\x9a\xc5\x9a\xcf\x0b\x23\x34\xed\x2c\x4f\x2a\x7b\xe1\x5c\xae\xdc\x3b\xee\x0e\xca\x74\xd7\xcd\x7a\x67\xa9\xd8\x99\x29\xc8\xfc\xda\x72\x96\x4a\xae\x77\x16\x72\xe5\x9d\x92\xcc\xd3\xe8\xd6\x66\xfa\xc4\xaf\xa0\xa0\x4f\xfc\x0a\xf0\x0b\xcc\x45\xb3\xde\x01\x49\x07\xfc\x9c\x9e\xc3\xd5\x42\xae\xaf\x76\x16\x36\x54\x91\xe6\x3b\xb6\x5a\x8b\x73\x70\x5e\x72\x46\x7b\x66\x6f\xbf\x03\xe7\xc9\x3b\xee\x8c\x39\xf2\xc6\x69\x17\xcb\xb5\xee\x8b\xce\xd7\x60\x7f\xcf\x97\xaf\x45\xc1\xc9\x52\xae\x40\x84\x80\xf0\xc8\x9a\x80\x9b\xd9\xbb\xab\x5a\xf3\xd5\x33\xb3\x9a\x15\xd3\xc3\x8d\x20\x02\x14\x77\x90\xaf\x90\xc4\x6e\xa5\x1e\xdb\x00\x1c\x5c\xd5\xc5\x91\x3a\x8e\x44\xf9\x73\x6d\x07\x4b\x67\x47\x09\xae\xff\xa5\x08\xfb\xbc\x45\x53\xcb\x46\x67\x85\xeb\x69\x3b\xf1\xed\x51\x82\x25\xae\x0e\xf6\x74\xe6\xbe\xe2\xcc\x08\xa5\x55\x3f\x37\x74\xb4\xbc\x08\xb9\xed\xbd\x29\xba\xee\x67\x76\x3d\x18\x65\xf7\x29\xe6\x85\x06\xa0\x3b\xb9\xe6\x48\x8f\x5d\xfa\xf3\x25\x8e\xdf\x3f\x93\x3a\x0c\x8f\x58\xce\xad\x64\xdd\x7f\x30\x58\x5a\x44\xa9\x95\x8e\x25\x99\x01\xb7\x02\x3e\x8e\x28\x3f\xa2\x94\xcd\x11\xa7\x6b\x8d\xda\x77\x48\x7b\xfa\xe3\xd7\x2a\x6d\x36\x92\x1a\xe3\x3c\xd7\xda\x6c\x02\x39\x2e\x10\x1f\x77\x3b\x76\x43\x15\xd1\x61\x5f\xdc\x76\xa6\x2f\x50\xe6\x39\xa8\x10\x74\x50\x21\x48\x53\xa2\xdd\x1f\x9a\x35\x2b\x5a\xe7\x2f\x74\xbb\xac\x6b\x89\x7c\xa1\x91\x32\x86\x86\xfd\xd3\x2f\x66\x6b\x97\x38\x47\x7b\x29\xc7\x54\x1c\x18\x66\xb2\xf2\x6a\xfa\x03\x87\x08\xd4\xad\xe1\x94\x1f\xbd\xd4\x45\x73\x53\x1a\xf1\x71\xc5\x8c\xb4\x5d\x4a\x55\xea\x2b\x12\xab\xf9\xd9\xb8\x31\x93\xef\xa4\xe2\x1f\x55\x23\x7e\x2d\xf5\xb9\xcf\x86\xf8\x78\x3d\xf4\x86\xd0\x08\x40\xe2\xcd\xff\xde\x4e\x66\xcf\xc9\x57\xd1\x0a\xe1\x64\xa5\x44\xc1\x1f\xd7\xce\x9e\x03\x80\x74\x17\xaf\x2b\x9e\xd2\xcf\xc5\xa9\x04\xa9\x0f\x6f\xe3\xb7\x52\xc6\x7b\xa6\x23\x23\x69\x38\x23\x0a\x39\x87\x80\xbc\xfb\xdd\x39\x9b\xb4\x5b\x6f\xdf\x05\xbf\x19\x7a\xc5\xf3\x9e\xf4\x87\x07\xd1\x47\x93\x63\x92\x8c\xbf\xb4\xd7\xa2\xb1\x1a\x06\x9d\x88\x06\x5d\xdc\x24\x32\x9a\xce\xf4\x18\x5c\x9a\x91\x17\x7e\x47\x93\xb6\x95\x57\xda\x6b\x96\xa1\xbd\x86\xcc\x7e\xe2\x44\xa3\xec\x44\xbb\x98\x4d\xb0\x4e\xcc\x26\x0f\x59\xa7\x65\x9c\x32\x53\xeb\xd9\x30\xb9\xae\x5b\xd9\x58\xc8\xb8\xa3\x4c\xa5\xb9\xf9\xae\x93\x3d\xfe\x57\xc8\x79\x9d\x10\xcc\xd5\xa4\xa5\x99\x67\x09\x6d\xa6\x3c\x67\xe9\xe3\x11\xa5\xa5\xce\xf3\x33\x8d\x4a\x70\xc7\x77\x7c\x35\x70\x88\xca\x3e\xac\xe0\x61\xd5\x79\x58\xdb\x87\x35\x3c\xac\xfd\xc3\x46\x07\x05\xf5\x95\xc6\x64\x91\xdc\x46\xc8\x14\x8e\xe1\xc7\x4d\xf0\xe7\xd1\xe9\xc0\x26\x52\x6f\x36\xd0\x7f\x13\x12\xcd\xcb\x7a\x71\xce\x97\x4d\xc5\x1f\xb3\xaa\x3a\x61\x8b\x4f\x28\x7a\xf6\xb3\x54\x2b\x56\x85\x99\x7d\xa2\x71\xbc\xc3\xf8\x0c\xf3\x23\x02\xb4\x6b\x55\x48\x97\x86\x4d\x72\x10\xfe\xa2\xa1\x82\xaf\x2f\x35\x62\xb6\x37\x5a\xd8\x48\x87\x7e\xa6\x63\x93\x18\x77\x4a\xc0\xf4\x91\x38\x9e\xa9\xa4\x69\x60\x96\xda\x69\x9a\xe1\xeb\x52\xa1\xa8\x27\x2e\x4d\x4f\x10\x9e\x74\xc0\xa5\xe9\x80\x28\xad\xb6\x69\x35\xa4\x45\xe4\x4e\xa9\xad\xb1\xc3\xe7\x5f\x26\x35\x44\x8a\x2e\x4d\xed\xf0\xd7\x2b\x67\x25\xc8\x49\x5b\x40\x50\x7b\x21\x61\x0a\x99\xc4\x85\xcc\xf0\x85\xe1\x80\x01\x32\x21\x1e\x74\xcb\x76\xd0\x05\xaa\x3f\xd5\xb1\x82\xec\xba\x45\xda\x3b\xea\x58\xa3\x1f\x1b\x89\x38\x75\x14\x0d\xe7\x4e\x77\xf8\x31\xcd\x2e\xdd\xb5\x36\x0f\x5e\xc9\x2f\x36\x75\x65\x2e\x34\xb1\x7a\x97\x4f\x3a\x3a\x1f\xe5\x62\x59\x3c\xd5\x28\x7b\xe4\x13\x32\xd2\x5e\x3f\x15\xcb\x0c\x93\x90\xb7\xf4\x67\xa9\x37\xbf\x11\x8e\x5b\xe3\xf7\x40\x70\xbb\xf9\x1d\x38\x3d\xcc\x30\xd1\x8a\x89\x20\xf8\x41\xf6\xf7\x21\x25\x23\xd1\x0d\x54\x6b\x4b\xde\x41\xd8\x85\xc7\x3a\x81\x04\xfb\xc3\xb3\xfb\x77\xa0\x1f\x75\x74\x84\x1b\xd8\x23\x7f\x8a\x93\x2d\x46\xa3\x26\x82\x42\x32\x74\xb1\xde\x29\xc5\x0e\x2c\xa9\x62\xc8\x6a\x1e\x1e\x3f\xd6\x49\xc1\x54\x1c\xe9\x10\x83\x8a\x6f\x97\x79\x8e\x1e\x6b\x7a\xab\x35\x81\x3b\x60\x8b\x48\x6d\x18\x5a\x56\x8a\x00\x59\x87\x9c\xb9\xf8\x27\x3d\x8e\x3b\xab\xbd\x21\x03\x19\x42\x0f\xdd\x9e\x0d\x3a\xa4\xbd\xc5\x09\x71\xbb\x15\x69\xdf\x4f\x3a\x28\xba\xb3\x3a\xf4\x37\x9a\xfe\xa1\x51\x16\x57\x36\xc3\xe4\x6d\x27\xb5\x8c\x06\xc8\xeb\xce\xb3\xda\x0d\x84\xf7\x36\x3d\xf9\x5c\x86\xc9\xcf\xed\x6e\xe5\x63\x7b\xf9\x4a\xd3\xa3\x8c\x9d\x48\x05\xf0\x62\xf6\xf7\x8d\x26\x6d\xa9\x66\xb4\x90\xb7\x71\x4a\x3b\x48\xc9\xeb\x38\xdd\x0e\x44\x92\x2d\x98\x58\x57\xec\xca\x5e\xbd\x09\x57\x26\xcd\xc1\x3c\xb4\x8f\xde\x87\x84\x65\x63\x0b\xb5\x9b\x8c\x28\xe1\xb1\x4f\xe0\xab\xb5\x2e\x01\x12\x2a\xba\x12\x0b\x75\xb5\xd6\x03\xd7\xcb\xf4\xd7\x46\x33\x0d\xbf\x7d\x29\x1a\xd2\xde\xd8\xb4\x80\xac\x98\x01\x52\x54\xf2\xc3\x97\x4b\xa6\x59\xb8\x79\x12\xdf\xac\xb8\x66\xc9\xd3\x57\x69\x42\xed\x28\x64\xae\xdf\x85\xeb\x9e\xdc\x6e\x13\x7b\x75\x31\x04\x2c\x01\x6b\x20\xba\x52\xf2\xcc\x6c\xe3\xd2\xcb\x9a\xf3\x4f\xf6\x79\x74\xa5\x21\x4e\x4c\x7a\x05\xae\x5f\xe9\x95\x2e\x57\xbc\x59\x2f\x99\xe6\xee\xe6\x83\xbb\x79\xaf\x49\x34\xa6\x60\x58\x64\x97\x0c\x40\x24\xa2\xab\xe8\xb8\xfe\xb9\xee\xee\xd9\x3b\x56\x9f\x74\x37\x38\xae\x1e\x89\x63\x22\xcd\xcf\x9d\xe9\xf1\x4c\xd2\x4c\x8a\xec\x0e\x92\x47\x93\x0e\x18\xd5\x1d\xe9\x20\x92\xa6\x18\x93\x8f\xe0\x63\x81\x14\xd1\x66\x70\xbb\x6b\x89\x49\x83\x24\x39\x52\xc7\x78\xbb\x45\xc9\x22\x2f\xe4\x25\x46\x76\xb2\x3d\xd2\xf4\x7e\x5b\xd1\x97\x9e\xe9\x81\x36\x35\x6f\xe3\xb2\x3e\xd2\x74\x7a\x40\x40\xc9\x6e\x1e\xed\x76\x1e\xed\x93\x5d\xff\x68\xbf\xf3\x68\x8f\xec\xbb\x93\xb1\xdd\xfd\xdc\x3b\x4d\x59\x63\xeb\x39\x32\x19\x76\x89\xc6\x85\x79\x73\xcf\x94\x6a\xd3\xa6\x64\x6f\xd7\x26\x6a\x3a\x7d\xd0\xa6\x4f\x7c\xde\xdd\x83\x43\x9f\xf8\x80\xec\x1e\x1c\xfa\xcc\x7b\x07\xf7\xf7\xfd\x83\xfb\x3e\xf3\xfe\xe4\x41\xc8\x7d\x8f\x98\x3b\x9f\x7d\x7f\x7a\xff\x70\x3a\x0d\xe5\x1f\xfa\x37\x34\x3d\xdc\x7d\x30\xdd\x3f\x38\x9c\xf8\x47\x07\xe6\xd1\xe1\xbd\xe9\xe4\xfe\xfd\xc3\xfd\x9c\x43\xda\x3e\xf1\x09\xf6\xad\xe9\xde\xfe\xee\xf4\xde\xbd\xdd\xfb\xfe\xa5\x3d\x12\x92\x7c\xb9\xf7\x27\x07\x7b\x93\xc3\xbd\xc3\x90\x27\x34\x7f\x3a\xb9\xb7\x77\x6f\x7f\x7a\x7f\x37\x34\x60\x4a\xda\x34\x5c\xd8\x26\xc5\x7b\xbd\x2f\x3a\x3d\x0d\x33\xe3\xb6\x14\x67\x2f\x99\xe0\xb5\x07\xab\x17\x51\x5f\x4c\xdc\x69\xd8\x84\x48\x3a\x21\xcc\x86\x10\x2c\x15\x5f\xc2\x1b\xa4\x84\x28\x0c\x30\xfa\x7d\x52\x65\x4a\x2d\xc5\x99\xbb\x77\x7d\x4c\x19\x56\x94\x11\x49\x61\x54\x04\xff\x05\xd3\x08\x46\x7d\x8b\xef\xe5\xde\xbc\xa3\xa6\x2c\xff\x57\x39\x33\x2f\xd6\x73\xa4\xe8\x4b\x8d\x6a\x0c\x6f\xdb\x86\x57\x39\x65\x18\xbc\x8b\x5e\x6a\x54\xb9\x27\x76\xb7\x67\x8b\x14\xf9\xbf\x4a\xec\xde\x64\xd1\x9b\x10\xfa\x38\x79\xcb\xb7\x3a\x28\x6f\x2d\x12\x18\x15\x39\x42\x93\x7f\x20\x45\xf7\xa6\x77\xbf\xd3\x48\x61\x3c\x9f\x14\xd3\x87\x0f\x15\x7e\xf8\x70\x8a\xef\x4e\xc9\xc4\xee\xdb\xb5\x75\x0e\x98\x98\x5d\x54\x5e\xda\xdd\xef\x4b\xd8\x44\xc9\x87\xa6\xfc\xa0\x3f\x7c\xa4\xa9\xdc\x3a\x6a\x80\x42\x9f\x0b\xcd\xc4\x59\xe5\x08\x85\xdd\x71\x6b\x9b\x6e\xcf\x6a\x74\x4e\x95\xd9\xb7\xcc\xb0\xa4\xd3\x87\x0f\x91\x70\x15\xd2\x18\x13\xb5\xb1\x93\x5f\xe7\xf4\x5f\x32\x18\xb4\xb7\xbd\xfd\x44\x47\x70\x07\x86\x30\x9c\xde\x0d\xe3\xe3\x20\x4f\xbb\x1f\xcf\x79\x11\x0f\xa8\x79\x7b\x53\x44\xbb\xbd\x67\x83\xfa\xa1\xc8\x45\x79\xea\x1c\x8a\x3d\x22\xda\xce\xae\x4b\x08\x5e\xc8\xce\x6d\xeb\x7b\x8d\x76\xf7\xf3\x7f\x69\x8c\xe7\xcf\x34\xb2\x13\x95\xbb\xbc\x93\x7e\x5e\x33\xa9\x7d\xe6\xfb\x51\xde\xfb\xfd\xac\x30\xa5\xff\x05\x4a\x94\x36\xd1\x4f\x5c\x9b\x8e\x38\x3d\x98\xee\x62\xe2\x0a\x49\xeb\xa6\x4d\xfe\x76\xda\xb9\x37\x34\xdd\x3d\xbc\xbf\xbf\x77\xb0\x7f\x70\x88\x89\xee\x28\xf4\xf7\x0e\xcc\x44\x8b\x66\xda\xf7\x3a\x01\xc7\xbf\x1b\x9d\xc3\xff\xa9\x53\xe0\xe7\xa3\x63\xd8\x20\xec\x4d\xff\x21\x2c\x64\xb3\x3f\xc6\x0f\x47\x25\xd1\xd9\x5f\xd8\x6c\xa7\xbd\xb7\xa1\xda\x4d\x55\x7d\x77\x3a\xeb\xce\xca\x9c\x2a\x92\x4c\x4b\x93\x60\x07\x9b\x11\xb9\xde\x97\x2b\x5e\xe3\x23\x1d\x86\xd6\x31\xb5\xe2\xfa\x77\x9a\xbe\x62\xfa\x7c\xbc\xa8\xbe\xec\xed\xce\xdb\xcb\xa2\x8f\x41\x07\x94\xe3\xf3\xbd\xdd\x62\x6f\x7a\x17\x7d\x30\x4d\xfc\xaf\x7f\xea\xcd\x04\x6f\x26\x5b\xf2\xc1\x95\x53\xc9\x33\xf2\x4f\x77\xfd\xf2\xe7\x5d\xf2\xa3\xa6\xd1\x1a\xf3\xa1\xe6\xea\x7b\xb3\x59\x29\xc5\x59\xd8\x32\xfe\x95\x64\xe9\xe8\x80\xc8\x4f\x1a\xdc\x22\xc2\xc1\xa0\x6e\x4d\x49\x5f\xf2\xcd\xe6\x39\x77\x6b\x96\xa4\xbf\x6b\xc2\xe8\x4b\x3e\x7b\xc9\xcd\x1b\x5a\x5d\x5d\xbf\xe2\x48\x12\x9f\x3d\xa0\x0a\xa0\x97\x9c\x32\xbc\xd9\x3c\x01\x70\x86\xf6\x48\x2f\x2a\xf9\x2f\x8d\x7e\xd4\xe4\x77\x3d\x3e\x29\xc5\x12\xf6\x8c\xa1\x98\xd8\xab\x52\x77\x20\x1f\x0d\x5f\xf9\x09\xcc\xda\x90\xa4\x86\x5f\xec\xe7\x76\x88\xb6\x5b\xd7\x3c\xbf\x3b\x7d\x78\xda\x2a\xed\x38\xc6\xa0\x31\x4c\xbe\x41\x58\x3b\x40\x42\x3c\x03\x06\x8a\x0c\x97\x23\x39\x08\x93\x79\x0e\x3a\x5d\x85\xc3\xe1\x84\x74\x36\x46\x9d\x4f\x05\x4f\x9a\xb5\x46\xac\xfd\x1c\x68\xe9\xa2\x6f\x96\xa7\x3d\x0c\x49\x22\x5b\x3f\xeb\xae\xc2\xd8\x95\x5a\x6a\xba\xb2\x5b\xea\xf0\x4a\x08\x1e\x1c\x69\x8c\x5d\xee\x0a\x72\x57\x83\xb9\x23\x8d\xb1\xcb\x5d\x43\xee\x7a\x30\x77\xa2\x32\xf6\x47\x86\x41\x9f\x1b\x02\x86\x5b\x11\x88\x91\x95\x46\x0d\x38\xb4\x22\x33\x08\x62\xba\x13\x89\xdb\x52\x07\x14\xc9\xae\xa4\xa4\x78\xb2\x88\xca\x5d\xdc\x5a\x6e\x84\xff\xd8\xd2\xde\x3b\x91\xb9\x0e\xdc\x3e\x57\x40\x71\x65\x21\x9a\x04\xde\x46\x23\xf4\xb7\xee\x78\xa3\x8f\x39\x52\xb1\x9e\x0a\x49\xaa\x25\x92\xd8\x2d\xb2\x8c\xfe\xc2\x91\xec\x0c\x16\xab\x72\x0f\xc3\xaa\xa4\x6c\xac\xd9\xd9\xcc\x6b\x79\xcb\x44\xbb\x2b\xe9\x0f\x1c\xb1\x56\xbb\x2b\x67\xf6\xfd\x44\xef\x6a\x5f\x61\x37\xab\x5e\xf7\x6c\x04\x71\x76\x36\x67\xb7\x6a\x5a\x93\xc2\x99\xf3\x61\x92\x5e\x7d\xe3\x0a\x0b\x14\x92\xc4\xe9\x40\x80\x91\xbd\x70\x07\x50\xdc\x69\xb2\xb4\xe8\x18\x72\x09\x61\x6d\xa3\x74\x90\x7e\xb4\x68\xa3\x21\x53\x2e\x88\x6a\xe3\xa4\x4a\xea\xfc\x0a\x4b\xb1\xf3\x42\xcf\x5f\x78\x87\xd7\x17\x3a\x36\x09\x27\x2c\x20\xaf\xcc\x5a\x53\x2a\x95\xe7\x10\xa6\x9c\x52\x69\xb6\xfd\xfc\xce\x1d\xcb\xa1\x4a\xaa\xee\xda\x40\xe1\x9a\x4e\x67\x1a\x70\x4f\xc4\x91\xba\xab\x6d\x56\x76\x57\x1f\xcf\xb4\xc9\x1c\xaa\x47\xbd\x3c\xcf\xc9\xf4\xa1\x9e\x4f\xef\x06\xff\xe6\xc8\x3b\x32\x39\xb2\xff\xc4\xaf\x1e\xcb\xa5\x97\xa8\x33\x1f\x22\x07\x1c\x14\xe6\xde\x99\x3a\x44\xce\xc1\x79\x3e\xdd\xf3\xaa\x40\x3a\xdd\xc3\x05\xa7\x9a\x4c\x27\x4e\x4b\x05\x49\x64\x6f\xf7\x21\xe5\x9b\x8d\x35\x74\x98\xf3\x58\x52\x88\xcc\xf4\x63\x75\x31\x8b\x92\x23\xa3\x96\x4a\x74\x75\x81\xed\xc9\x4a\x88\xc5\xb8\x53\x8a\x1d\xb0\x4f\xf9\x08\xd0\x50\x00\x7b\xee\xa0\xce\x3f\x5a\x65\xef\x73\x51\x6b\x0f\xa7\x0e\x48\xe8\x0e\x29\x3d\x52\xdd\x7a\x4c\x75\xfb\x82\xc7\x45\x77\x27\xc6\xef\x6d\xa2\x1d\x2c\xb8\x67\xdc\x5c\x3a\x6b\x8c\xa3\xf2\x18\x5e\x3b\x2a\x8f\xa9\x9e\x6b\x24\x71\x21\x8f\xca\xe3\xb6\x77\x4c\x91\x65\xfd\xc4\xda\x32\xbd\x51\xb0\xcc\xf2\x25\x75\x53\x47\x7a\xb7\xa2\xf0\x64\xde\x4f\x2a\x00\x4b\xd6\x5b\x2e\x58\x17\xa8\xb9\x14\x05\x73\x4d\x2a\x6b\x53\x2d\x76\xe6\xf4\x07\x72\xbd\xe6\x4b\xea\x1e\x6e\x83\xaf\x5a\x8c\xb1\x74\xbd\xb6\x65\xbb\x6a\xa5\x30\x4b\x65\xdd\xab\x81\x87\x87\xe2\xb4\x4b\xc3\x99\xf5\xb7\x4a\xcb\x9b\x77\x13\x10\x2e\xb2\x46\x7c\x12\xf2\x32\x32\xd4\xe2\x71\x83\xa0\x94\xe8\x9e\x8e\xa6\x98\xdc\x44\x3c\x29\xb0\x85\x3d\x88\xda\x1d\xb7\xe1\xd6\xaa\x76\xde\x9b\xf7\x52\x6e\xa8\xac\x3d\x47\xfe\xbe\x39\x39\xa9\x6c\x41\x71\x02\x1d\x4d\xf0\x2d\x9d\x01\x15\x5e\x73\x55\x97\x75\x42\xec\x2d\x29\xeb\x37\x36\x19\xce\x64\xc5\xd6\x08\x94\xb0\xf1\x11\xa4\x11\x64\x21\xc8\x52\xd0\x6b\x68\xf7\x9b\x73\x56\xf3\x62\x42\x4e\xe0\x83\x75\x31\x21\xb6\x02\x00\x27\x31\x21\xba\x5c\xf1\x77\x9a\xad\xd6\x43\x22\x19\x1f\x87\xc7\x9b\xcd\x13\xa6\xf9\x58\xc8\x4b\x84\xb7\xa4\x37\xd4\x26\xa4\xac\xdf\xab\xa6\x86\xeb\x2d\x39\x15\xb4\x12\x68\x29\x30\x59\x0b\x0a\xfe\x8e\x4b\x41\xae\x2f\x4a\x7e\x59\x4c\xc8\x92\x6b\x56\x56\xc5\x64\x8b\xc9\x39\xe4\x5b\x0b\x4c\x56\x2e\xdf\x5a\x90\x6b\x0b\xe2\xf6\x5b\x31\x21\xf6\xea\x77\x53\xe9\xaa\xe4\x42\xff\x16\xae\x4c\xda\x9a\x9d\xf1\xdf\xdc\x2f\xe4\xd1\xaa\xfa\x89\x5f\x99\xf7\xce\xcb\x53\x6d\x2f\x59\xe5\x2e\x56\x5c\x33\x7b\x75\xc6\xf5\x2b\xb9\x2c\x4f\x4b\xe7\x59\x57\xbc\x11\xc4\x1a\x21\x02\x9d\xcc\x85\xa1\x93\xe2\x15\xd3\x7c\x69\x67\xf4\x10\x79\x02\x86\x84\x19\x82\x51\xde\x39\x87\xb0\xb9\x4e\x6b\x0a\xcf\x5b\xab\xe3\x39\x1f\x6b\xf9\xd4\x47\xc3\x89\x33\x16\x9d\x62\xb6\x64\x25\x2f\xe0\xc9\x6f\x03\x5f\xcf\xc2\x43\xcb\x7e\xf9\xb8\xcd\x8d\xf8\x88\xd2\x85\xc8\x73\x64\xfe\x58\x81\xc7\x3c\x75\x10\x31\x57\x6b\x3e\x47\x35\x18\xb3\x5a\x4a\xdf\x5d\x08\x7f\x49\x9a\x36\xfd\xf7\x36\xfd\x77\x5c\x34\x82\xd6\x82\x4e\xc8\x42\x50\x8e\x49\x6d\x86\xa6\xff\xe2\xef\xb7\xd5\xef\xf7\x6e\xfd\x7e\x2f\x1a\xb1\xdd\x62\x72\x01\x9d\xbf\x12\x98\x9c\xc1\x15\xf4\xff\x4a\x90\xeb\x25\xd3\x0c\x94\xba\xa7\x5c\x99\x61\x82\xc9\x55\x9b\xc1\x0c\x90\xb4\x67\x20\xc7\x49\x9b\xc3\x0c\xb5\xa0\x17\x05\xc3\x86\x09\xe1\x15\x5b\xd7\x7c\x69\x36\x2a\x66\xc0\xd4\xbc\x59\x86\x4e\x80\xf7\x2f\xa3\x71\xba\xa8\xca\xf5\x89\x64\x0a\xf4\x8b\x43\x4d\x4b\x32\xf8\xe6\xa5\x6f\x39\x2b\xcd\x24\xd1\x34\xfa\x33\xd4\xf3\x52\x60\xf2\x34\xad\xb1\x69\xb4\xad\xca\x27\x41\xaf\x9f\xd6\x8b\x22\x7b\x5a\x2f\xd8\x9a\x67\xe4\xdd\x9a\x2d\xf8\x09\x53\x45\xb6\x93\x91\x97\xfc\x54\x17\xd9\x23\xa5\xe4\xa5\xb9\xcc\xc8\x87\xb5\xbb\xfd\xb0\xce\xc8\x5b\x70\x52\xb2\xf7\x70\x9d\x91\x27\xf2\x52\xb8\x14\x30\x02\x26\x4f\x78\x55\x64\x4f\x40\x33\x9e\x91\x5f\x4b\x51\x64\xaf\xdf\x65\xe4\x15\x17\x4d\xe1\xd1\x9f\xcc\x4d\x46\x1e\xad\xd7\x75\x27\xe9\xdd\x42\xc9\xaa\x2a\x32\xfb\xfb\x52\x2e\x3e\x65\xe4\x95\xfc\xf2\x46\x95\x02\x36\x58\x66\x82\x65\x1f\x44\xb9\xe4\x42\x43\xcc\x9e\x6c\x4b\xde\x09\x7a\x7d\xbf\xc8\xbe\x67\x8b\x4f\x0e\x3d\xf5\x41\x91\xbd\x67\x27\x19\x99\xee\x16\xd9\xe3\x8a\x33\x95\x91\xe9\x5e\x91\x59\x33\x61\x32\x3d\x2c\xb2\x77\x66\x02\x67\x64\x7a\xcf\x7e\x5f\xc9\x2a\x23\xd3\xfb\x45\xf6\xa8\x32\xa9\x0f\x8a\xec\x0d\x6b\x6a\x9e\x91\xdd\x49\x91\x3d\x66\xeb\xda\xd6\x64\xf7\x5e\x4b\xb4\xbd\x5d\x20\xd7\xde\x9e\xc9\x7b\xc6\x0d\x71\xf6\xf6\xed\xb5\x25\xc3\xde\x81\xf9\xe2\x32\x23\x7b\x87\x45\xf6\xa3\x5c\x99\x77\xee\x25\x94\xdd\xbb\x1f\x51\x76\xef\x41\x4a\xd6\xfd\x49\x42\xd4\xfd\x83\x22\x7b\x2e\x6a\xae\xcc\xa3\xc3\x96\xbe\x53\xd3\xc6\x67\x53\x73\xb1\x57\x64\xcf\x76\xcd\xc5\x7e\x91\x3d\xdb\x33\x17\x07\x45\xf6\x6c\xdf\x5c\x1c\x16\xd9\xb3\x03\x73\x71\xaf\xc8\x9e\x1d\x9a\x8b\xfb\x45\xf6\xec\x9e\xb9\x78\x50\x64\xcf\xee\x1b\x52\x4d\x8a\xec\xd9\x03\x73\x31\x35\x05\x4e\xcc\x15\x14\x6d\xca\xde\x35\x65\x4f\x4d\xe1\xfb\xfb\x45\xf6\x73\xb3\xb2\xf4\x98\x9a\x5a\xc5\x5d\xb5\xbb\xbb\x5f\x64\xaf\xb8\x66\xd9\x96\x3c\x16\xf4\xfa\x51\xa5\x8b\xcc\x72\xc8\x8c\x38\x42\x17\x99\xe3\xa3\x66\x4c\x68\x56\x64\x8e\x71\x66\x04\x3a\xa5\xc8\x3c\x73\xcd\xe2\xa3\xab\x48\x4e\xec\x2d\xa0\xc1\xc2\xb4\xcb\x78\xe7\xfd\x24\xc4\x71\x31\x1a\x21\x4e\x1f\x1b\x29\x17\xe7\xf9\x68\x04\x71\xc2\xc3\x97\xde\x44\xce\x9b\x7f\x58\x2d\xc3\xdb\x68\xed\xf8\xc4\xaf\x92\x19\x0b\x86\xbd\x9f\xf8\x95\xaf\xdc\x27\x71\x04\xf7\xc7\x9b\x0d\xfc\x82\x9b\x4f\x32\x60\x13\xa3\x58\x0f\x8e\xe9\x2d\xb6\x22\x0e\x6a\xad\x56\x38\x05\x11\x19\xcf\xdd\xe8\x2d\x86\xe2\xa6\x73\x5c\x64\xce\xf6\xab\x2d\x60\xb3\xc9\xc0\xfc\x2b\x2a\xf2\x9d\xab\x9c\x79\xe9\x78\xb3\x49\xeb\x55\x64\xd9\x96\x2c\xe4\xd2\x30\xb0\x4a\x2e\xac\xf4\xf2\xed\x8b\x9e\x0b\xa7\x6b\xdf\x85\xa5\x7f\x68\x19\xf4\xb2\xfb\x10\xd7\x1b\xa0\x01\xb4\xdd\x2c\xf8\xae\xd2\x37\xbc\xf6\xd5\x86\x87\x56\x9b\xb2\x2e\xcf\xcb\xc5\xf9\xdf\xaa\xc0\xdf\xfe\xc6\x16\x93\xd7\xc0\x7e\xdf\x0a\x4c\xde\xa7\xab\x4f\xd8\x7c\x17\xe0\xc0\xa9\xcf\x8b\x09\xb1\xa0\xdc\x66\xe5\x30\xdf\x6f\x14\x48\x4e\x4c\x9c\x99\xce\x61\xd5\x9b\x28\xb1\xac\x40\x48\x31\xbf\x46\x24\xd1\x97\x46\x74\x9b\x10\x57\x28\x44\xb0\x33\xb2\xd2\x1b\x55\xae\x98\xba\xb2\x0c\xff\xe7\x74\x75\xb3\x66\x8a\x35\x7c\xc2\x2c\x70\xef\xc3\xbd\x3d\x9e\x5b\xb6\x09\x03\xfd\x3c\x38\x1e\x06\xba\xda\x7c\xf8\x63\xba\x04\xc5\x61\x17\xbe\x65\xcd\x7c\xe5\xe6\x1d\xac\xd9\xbc\xd2\x6c\x50\x4e\xb1\x4f\xfc\x2a\xe9\xf2\x65\x97\xe7\x9c\x57\x4f\xa2\x47\x77\xf9\x38\x4a\x33\xe3\x00\xb2\x0e\x8a\x16\xf6\x49\x52\xe4\xef\x71\x91\xbf\x0f\x14\x99\x64\x18\x78\x1e\xbe\xf8\x07\x88\xa8\x95\x66\xaf\xec\x58\xc1\xe4\x39\x90\xe9\x95\xc0\xe4\x91\xa0\x47\x0f\xc8\x74\x8f\xec\xde\x23\x7b\xbb\xc7\xe4\xa5\xa0\xcb\x3c\xcf\x1e\xb7\x86\x9e\x9d\x23\x68\xf2\xc5\x29\x0a\x4c\x36\x7f\xaa\xfe\xca\xed\x99\xfd\x7d\x9e\xa3\x2f\xa2\x3d\x73\x8f\xb3\xd9\xbd\xfd\x13\xfb\x99\xf7\xfc\xb3\xee\x94\x9f\xe7\xa3\x2f\x82\x3c\x83\xe7\x68\xf4\x52\x6c\x36\x5f\x44\x9e\xdf\x7f\x68\xfe\x4e\xa7\xff\xa0\x5f\x04\x26\xdf\x0b\x3a\xc4\x94\xf6\x76\x31\xf9\x53\x24\xbe\x51\xbf\x8a\x41\xdb\x4d\x3b\x93\x9c\x82\xea\xee\x74\x44\xe9\xa3\xd6\x73\x56\xfb\x69\x65\xf1\x17\xc3\x54\x0c\xda\xfb\xdd\x07\x80\x6a\xe4\x75\x07\x3e\x93\x9d\xc9\x91\xcd\xe6\xb2\xf5\x50\x6a\xcd\x43\x83\x05\x71\x3f\x04\x4b\x0b\x93\x1c\x0f\x8d\x0e\x7c\x26\x28\x24\xec\x86\x03\x9b\x1e\x88\xe4\x35\x10\xb8\x82\x82\xe7\x83\xa1\x04\xf9\xa7\xa0\xd7\xe0\xe6\x58\x8c\x26\x64\x69\x26\x8a\xfb\x35\xfb\x20\x73\x9d\xf9\x9b\xbb\xc0\x46\x33\xeb\x3c\x6b\xb6\x33\xa3\x09\x59\x49\x61\x3d\xed\x5d\x80\x4c\xf0\x8f\xad\xeb\x4b\xa9\xc0\xb7\x16\xa2\x0f\x80\xaf\x2c\x67\x6a\x01\x19\x35\xaf\xec\xcf\x67\xf0\xb3\xf5\x5f\x69\x14\x24\x5f\x72\xfe\xa9\x18\x4d\xa2\x65\xf6\xc7\x58\x1d\x93\xe7\x2d\x0a\x64\x7c\x9d\x1a\xd9\x78\x65\x4d\x70\xa7\xd2\xf3\xd1\xe8\x9f\x60\x9c\x73\xb5\xe6\xc7\x45\xe2\x4c\x15\x1d\x14\xfc\x15\xa1\x2a\xbc\xe7\x48\x61\x32\x79\x88\x34\x7d\xa9\x90\x26\x59\x30\x0c\xc0\xb8\x8d\x26\x64\x63\x94\x9f\x0a\x94\x45\x76\x03\xde\xa2\xc0\x2a\x1c\x89\xc2\xc4\x39\x19\xda\xdd\x69\x21\x48\xe5\xbc\x97\xea\x42\x6f\xb1\x45\x2e\xf9\xc9\x69\xd9\x7e\xe9\x6a\xd9\x7e\x80\xf6\xbf\x55\x88\x93\x58\x4b\xf5\xbb\x5f\xea\x7f\x47\x0a\xbc\x28\x83\x2a\x3a\x52\x6f\x46\x48\x1c\xae\x52\xb1\xbd\xbc\xdd\x3e\xbf\x10\xc1\xad\xcb\x6a\x03\x54\x74\xa3\x15\xcd\xa4\xb0\x74\x8c\x66\xaf\x75\x5f\x71\x4a\x53\xa1\x6e\xb7\x9d\x99\x09\x95\x06\x8a\x09\x25\x92\xcc\xe9\x6a\xc1\x9a\x68\x08\x9c\x5c\xa8\xb1\xcb\xbc\xe5\x8a\x6a\x65\x15\x99\x5c\x99\x2a\xbf\x10\x94\x2b\xc3\x02\x06\xb9\xc8\x66\xf3\xe0\xe1\x30\x7b\x89\x34\x7d\x0a\xe1\xeb\x9f\xcc\x9e\xf1\x27\x01\x33\x66\x71\x0e\xbc\xc6\xd4\xd0\x2f\x0c\xbe\x33\xa5\xc2\xa6\x6f\x7e\xf2\xb6\x6f\xad\xca\x4e\xb9\x8e\x70\xfa\x4d\x58\x7d\xe3\x65\x25\xcf\x7f\x17\xe8\x17\x7f\x4c\xab\xe9\x11\x58\x36\xfd\x25\x90\x26\xbf\x08\xc2\x09\x38\xee\x62\xc2\xe9\x0f\x82\xbc\xe4\x18\xac\x85\x41\x99\xdc\x1e\xbb\x38\x5f\xd1\x70\xe0\x62\xbd\x3c\xed\x71\x4b\xc4\x15\x98\x0a\xe8\x63\xfe\x28\x01\x54\x8c\xc8\x34\x14\x46\x16\x41\x3f\x09\xaa\xf1\x98\xe9\xaf\x35\x16\x17\x2d\x4b\xb2\xda\x4b\x53\x48\x84\xd1\x15\x9a\x6d\xfd\x14\x5b\x4b\x1a\xe7\xb0\xd8\xca\x22\xf6\x26\x08\x2b\xc1\xe3\x07\xa8\x12\x69\x33\x55\x34\x5a\xc1\xd1\xb3\x93\x3b\xb6\xc0\xac\xa3\xcc\x89\xd7\xe4\xc0\x38\xb7\xaf\x82\xaf\xdf\xe0\x20\x73\xfe\x8b\x65\x3d\x0f\x57\x45\x0a\x65\x13\x4e\x79\xac\x66\x77\x32\x82\x6f\x4d\xff\x8b\x53\x3a\xfd\x2f\x8d\x37\x1b\x0e\x60\x67\x7a\x44\xf5\x96\x2c\xd4\xd7\x62\x63\xb6\x93\x7b\xd9\x36\xa3\xb1\x97\x49\x70\xad\x3e\xc8\x7e\x88\x69\x35\x04\xc1\xaf\xc3\x53\x9d\xa2\x92\x06\x6c\x5a\x80\x67\x00\xa4\xa8\x38\xc1\x59\xe6\x3a\xb6\x06\x6e\x55\xce\x76\x34\xb1\xb8\x56\x74\x32\x53\x2d\xd6\x9a\xba\x73\x07\x1b\x3e\xb0\x50\x0e\xd8\x95\x88\x23\x75\x8c\x37\x9b\x91\x69\xca\x91\xb9\x39\x26\xda\xfe\xe2\xb6\xa4\xbe\x76\xfb\x54\xf9\xb3\xdd\x19\x30\xf5\x04\x45\x27\x05\xa0\xe9\xf3\xb8\xb5\x8a\xac\x33\x88\xa2\x50\x58\x38\x3b\x50\xd6\x43\xc7\x6c\x5b\x54\x0b\x50\x63\xf1\xc0\xf8\x1d\x15\x1f\x3d\xf8\x83\x0a\xfe\x10\xcc\xde\xff\x11\x68\x78\x0d\x21\x9a\x15\x71\x90\x23\xfa\x2e\xdf\xce\x38\x15\x5b\x5e\xd8\x3a\xbb\x6f\xa8\xb1\xe0\x9f\xf5\x3b\xeb\x55\x84\xaf\x15\x4d\x12\xbc\xab\xee\xd6\xa4\xb7\x3e\xf3\x5b\xe5\xa2\x02\x6c\xa1\xe6\x2a\x3e\x3e\x3d\x57\xf1\xe0\x1b\x41\x20\x82\x91\xb6\xe7\xf0\x80\x23\x02\x29\x7b\xa3\xd8\x21\x1f\x54\xed\x16\x90\x47\xb7\x5e\xfa\xb6\xa4\xe8\xb3\xb8\xc8\xdc\x59\x51\x1d\x54\x39\xee\x1e\x69\xb3\x19\x35\xf7\x2b\x93\xdf\xe3\x15\xbe\x71\xb2\x9e\xd9\x9c\xa2\xe9\x61\x7e\x63\x06\xa4\x71\x62\xaf\xbc\x52\xa8\x3d\x8c\xe0\x2e\x6c\x2f\xd1\xf4\x37\x84\x67\x7a\xc7\x87\xc2\x06\xb5\xf1\x8f\xef\x5f\xbd\x7c\xfe\x4c\xb1\x95\x5f\x40\x66\x36\x18\x81\x1d\xc1\x03\x20\x0e\x2e\x00\xe8\xaf\x56\xef\xe4\x37\x88\xe3\x73\xc5\x4f\x5b\xdf\x5c\xe1\x7c\xa2\x47\xc2\xb9\x96\x99\x6f\x23\x4e\x3b\xaf\xe3\xb0\x48\x04\x67\xd5\x48\x32\xb8\x50\xff\xae\x10\xb2\x63\x18\x46\x24\x89\x98\x3b\x00\x1b\x8f\xf7\x6d\x56\x3a\x4a\x92\x34\xaf\x92\xfb\x46\xa5\xf7\x5e\xca\x6a\x13\x71\xc7\x4b\x5c\x9b\x7b\xe5\x57\xa4\x4e\xb0\x54\xcb\x0f\xcf\x14\xbd\x5d\x48\x37\xf2\xf4\xe0\x2a\x4a\xae\x1c\x4a\xf2\x89\xfb\xbd\x74\xbf\x9f\x55\x22\x5e\x3f\x0d\x4b\x92\x0b\xf2\x3d\xb6\x23\x00\xbc\x0c\x45\x28\xb2\x78\x90\x40\x48\xcd\x45\x21\x52\xbc\xcc\xd9\xe7\x10\xce\xef\x4a\x6d\x36\x57\x6a\x44\xe9\x6f\x48\x59\x87\xfa\x76\x09\xb2\x46\x8e\xa5\x40\x8a\x5e\x29\x9c\xe7\x17\x66\x4e\xcd\xaf\xad\x45\xb3\x1a\xa7\xf9\x08\x17\xcb\x38\xf1\xa9\x58\x6e\x8b\x6b\x1b\x92\x0b\x00\x2d\x90\xa2\x48\xa5\xf5\xc8\xf3\x4e\x42\x00\xbb\x2b\xf9\x65\x8b\xae\x71\xc6\x1d\x16\x23\x1c\x5e\xe0\x71\x5b\x28\xb1\x97\xaf\x2d\x33\x51\xe3\xf8\x96\xc0\x8a\x0b\x9f\x56\xe3\x70\x6d\x53\xc3\x0b\xd1\xdd\x96\x5c\xaa\x3c\x5f\x2a\x74\xa9\x08\x90\xe2\x52\x51\x65\x64\x56\x65\x64\xd6\x13\x65\x84\x56\x5b\x8d\x44\x68\xd5\x91\xd0\xea\x1e\xfb\xa8\xa7\x4e\x68\x35\x1d\xd6\x11\x5a\x75\x24\xb4\xaa\x2d\x26\xda\x9f\x05\x5e\x29\x33\xdf\x9f\x6b\x94\x39\xf7\x41\xff\x63\x5d\xf8\xdc\x5f\x59\x73\xff\x37\xf2\xe6\x5b\xb4\x7a\x56\xe7\x01\xe8\xdd\x00\xcd\xbf\xe0\xa7\xc8\x9a\xcf\x8f\x53\x87\xc5\x65\x0b\xfd\x90\x38\x26\x3e\xed\x38\x28\xb2\xb3\x77\xad\xab\x22\xfc\x71\x82\x91\xfd\xdd\xf1\x22\xce\xce\x49\xd5\x28\xe7\x94\xe8\xff\x5e\xb0\xaa\x5c\x86\xdf\xc8\x8f\xf1\x49\xd7\x9f\xf1\x4d\xe4\xd8\xf8\x89\x5f\x7d\x58\xef\x74\x9c\x32\x9f\xc4\xee\x99\x2b\x8b\x1a\xe1\x3c\x1d\xfd\xdf\xa6\x0e\x7f\x2b\x76\xe5\xfe\x0c\xb9\x65\x3e\xbe\xd1\x49\xf3\x49\xea\xb0\xe9\xae\x3e\xac\x77\x14\xd3\xdc\xf9\x52\x9a\xcb\xc7\xee\x12\x5c\x29\x9d\x43\x25\xe7\x9f\x20\xfc\xae\xfd\x01\xf7\x4a\xff\xd3\x73\x27\x7d\x3c\xe4\x5a\xfa\x34\xf5\x31\x85\x4b\x4b\xfb\x0b\x59\x35\x2b\xff\x7d\x7b\xe3\xb6\x4a\x91\xff\x26\x99\x60\x62\xc6\x90\xe9\xb2\x9d\xf0\x07\x0c\x5c\x5c\xc7\xfa\x2b\xfe\xb9\xb4\x3d\xfb\xd4\x5f\x80\xa3\x24\x5c\xbd\x0c\x57\xf2\xc2\x65\x7f\x6d\x2e\xc2\x69\x90\xbd\x7a\x15\xae\x4c\xd7\xc3\xc5\x6b\x7f\x21\x43\x7e\x78\xd3\x11\x11\xde\x75\xd7\xaf\xa2\x6b\xf3\xbe\xbb\x7c\xdd\x5e\xca\xe8\x4d\x28\xa5\x06\x7d\xb4\xff\xd1\xf2\xec\xac\xe2\xed\x4f\xb3\x38\x87\xf2\xe1\x0a\x4a\x07\x15\x8d\xfd\x9b\x10\x69\x0a\x44\x7a\xa5\xc9\x6e\xeb\xc9\xf3\x49\x51\x27\xf4\xee\x74\x24\xf1\xc4\xbd\xb6\xe3\x96\x7b\xb3\xdb\xae\xb3\xc5\x8e\x3f\xfb\xce\x48\x7e\xef\xd4\xc3\x4f\x5e\x2e\x9c\xbd\x33\xc2\x9f\xb3\x87\xfe\xa4\x8e\xde\xa9\x63\x32\xc1\xb3\x05\x4a\xd1\x4f\xc8\x51\xeb\x9a\x4a\x22\x1b\xa4\x63\x4c\xda\xac\xd0\x67\x5f\xcd\xea\x8c\xd3\x43\xb9\x91\x0f\x2b\x49\xec\x95\x3a\x2f\x84\xd2\x6f\x7b\xa1\x19\xd8\xbe\x3b\xce\x95\xb0\x0b\x19\xb8\x43\xc4\x0d\x9a\x75\x97\xee\x31\xed\x5c\xe1\x81\xcd\x86\x72\x62\x36\xe8\x39\x98\xff\x58\x5a\x7a\xdf\xc1\xfb\xeb\xdf\xfb\x9e\x9f\x4a\xc5\x9f\xdb\x5d\xf6\x51\x96\xf6\x76\x46\x5a\x65\x14\xc9\xc2\x20\xc9\x00\xaf\x45\xf3\x96\x22\x91\x8a\x0f\xde\xea\x0c\x9a\xd0\x96\x1b\x7c\xbc\x5b\x15\x57\xbf\x82\x51\xd9\xc1\x8d\xa3\x3b\x46\xff\x43\xe5\x7b\x7f\x82\xac\x37\xc8\xff\xcd\x2f\xc0\x96\xea\xb1\xa2\xd6\x7d\x65\xc7\xb9\x9a\xec\xa4\x2e\x27\x3b\xa9\x7f\xc9\x8e\x73\x21\xd9\x09\x4e\x23\x3b\x60\x6a\xba\x03\x0e\x22\x3b\xad\xa3\xc7\x4e\xea\xd9\xb1\x13\xdc\x38\xba\xab\x43\x29\xce\x76\xbc\x0b\x46\xcc\xe1\x23\x56\x6e\xa3\xa3\x82\xf3\xc5\x8e\x33\x6e\xdd\x69\xdd\x2d\x52\xc6\xec\xfd\x29\xe2\x79\xff\x87\x02\x49\xe1\x1d\x8f\x16\x77\x58\xc3\xfd\xa2\x68\x2a\x97\x72\xb5\x24\x42\xe6\x42\x8a\x05\xd3\xe8\xb1\xc2\x91\x7f\xfe\x9b\x8e\x44\xd8\x4a\xb8\xd6\x90\xc4\xc6\x7d\xcd\x66\xbc\x6b\x5e\x44\xfa\x16\x94\x84\x91\x8a\xd4\xa4\x81\x0d\xd8\x4f\x1e\x01\x07\x22\x8c\xb4\x18\x38\xe4\x3b\x17\xaa\xe3\xbb\x1e\x78\xcb\x83\xfb\xae\x37\x17\xf4\x03\x9f\x75\x01\x7b\x36\x1b\xf4\x4f\xc0\xe3\xf9\x91\xd3\x05\xde\x6e\x21\xee\xb1\xc3\xa9\xe6\x46\x3e\xea\xdb\x3f\xb5\x3b\x86\xb7\x6e\xf7\xa6\xa9\x75\xd7\xd0\xb1\xef\x65\x0f\x8d\x3c\x75\x4b\x51\xd6\xc4\x78\x66\xf6\x8a\x41\xea\x9a\xf1\xc2\x99\x20\xba\x38\x72\x80\x28\x18\xcc\xbc\xc2\x9e\xfd\xee\x74\x36\x79\x48\xcb\x59\x79\xf7\xae\x2d\xb6\xa2\xea\xa8\x3c\x26\x35\xad\xc6\x7e\xbb\x45\x1a\x5a\xa5\xb5\x37\xa5\x55\xb4\x0a\x9f\x23\xf5\x88\x52\x96\xe7\x72\xd0\x4a\x07\x61\xec\xa1\xa7\xde\x28\x24\x49\x45\x1a\x4c\x18\xad\xad\x7a\xce\xd4\xa9\xa4\x93\x59\xf9\x30\xac\x17\xa5\x03\x37\xaf\x29\xb2\xd5\xc1\xb7\xd4\x85\xfc\x07\x2a\x02\x48\x29\xff\xf4\x1d\xce\xe9\x8f\xbc\x83\xc0\x14\xa9\x10\x5e\xc7\x2a\x04\xca\x00\x47\x4e\x51\x7e\x27\xfb\xf8\xd1\x5a\x10\x65\x33\xf0\x2d\xb4\xdb\x8d\x57\x0a\x69\xc2\xc9\x2e\x84\x14\x15\x63\xb6\x5c\x22\xe5\x74\xb8\xef\x15\xcd\xac\x95\x9d\x85\xa7\x32\xf3\xe9\x0e\x18\x6e\x2b\x26\x96\x72\x15\xc3\x0e\xef\x1d\xfa\xe8\xeb\xbb\xd1\xe4\xf8\x19\xf6\x99\xfc\xe8\xbd\x3a\xde\x6c\x10\xfc\x9a\x01\x58\x0d\xc3\x66\xfe\xa1\xa0\x5a\x1a\x6f\x36\x1f\x4d\xad\x42\xec\x5b\x4c\xec\xfd\xc4\xdf\x6f\x93\x3d\xf9\x47\xd5\x35\x7b\xdd\x7f\x18\xe6\x4b\xd8\x27\x84\x70\x0d\xe1\xd1\xd1\xfe\xf1\x3c\xbe\x29\x26\x84\x51\x31\xbb\x49\x09\x98\xe7\x0f\x46\xf1\xae\x2e\xcf\x11\xa3\x9d\x7d\x5d\xf0\x0b\x56\x79\x3e\xd2\x79\xee\x9a\xe4\x51\x01\x2d\x6f\xb1\x21\xe9\x9d\xae\x58\x6e\xe8\x2e\x61\x54\x6d\x9d\xad\xad\x44\x0c\x93\xca\x76\x57\x76\x07\xe9\x79\x16\xcc\x8b\x33\xd7\x7d\x78\x56\x42\xa9\x95\xe9\x3f\xb3\x03\x97\x1b\xba\x8f\xc9\x2b\x05\x66\xc3\x92\x68\x4c\x4a\xe8\xc8\x2a\xa6\xd2\xab\x1e\x95\x3e\x5a\x6b\x64\x8d\x3d\x76\x64\xb0\x86\x92\xf3\xdd\x42\x3a\xb7\x8e\x49\x21\xe9\x2f\x3a\x82\xd0\xd8\x99\x16\x92\xfe\xe0\x53\xfc\xa9\x8e\xa4\xbf\xeb\xad\xa0\x32\xb2\x88\x37\x1f\xe3\x98\x48\x37\xc3\xc9\xe8\x7b\xd0\x04\x04\xa9\xda\xc1\x9f\x67\x41\x64\xf4\x09\x56\x52\xb4\x58\xff\x48\x82\x85\x9d\x9a\x87\xfe\x93\x73\xde\x07\x58\x33\xdf\xba\x76\x94\xf2\xa7\x36\xe5\x05\x2f\xe4\x16\x17\x37\x64\x1f\x4d\x70\xf1\x0d\x85\x7e\x4b\x49\x71\xac\x98\xe7\x2a\x36\x89\xb7\x2c\x4e\x39\x17\x23\x34\xcd\xb5\xf5\x48\x41\xbb\x70\xe5\x47\x0b\xe6\x05\x28\xdf\x66\x31\x86\x96\xf7\x47\xf2\xc6\xc1\xde\x0c\x1b\x4c\xaa\x6d\x7c\xfb\x32\xf0\xc4\x9b\xec\xa6\x2d\x27\xa4\x54\x6e\x36\xf7\x29\xa5\x55\x34\x7c\xab\x48\x85\x16\x81\x6a\x95\xa7\xc8\x16\x6d\x19\x9f\xc7\xa4\xf2\x28\x41\xe5\xcc\x3b\x68\x95\xbe\x42\x50\xa3\xda\xd6\x08\xe0\xd3\x90\x79\x78\x43\x85\x70\x5b\x99\x3a\xaa\x4c\xdd\xad\x8c\x6f\x7c\x49\x4b\x0f\x3c\x04\x24\xf2\xce\xf8\x09\xa9\x50\x49\xb5\x34\xe3\x1d\xb7\x58\x61\x07\x26\xdd\xd5\x12\x5b\x3c\xa7\x1a\x5f\x2b\xca\x68\x19\xd0\xbf\x76\xf8\xd6\x70\xe7\x48\x83\x09\x1a\x4d\xf7\xbd\x51\xba\x44\xc3\x07\xbf\xb4\xa1\x08\x11\x9e\x7d\x09\x67\x1a\x8f\x3c\xb8\x72\x38\xd5\xf8\x12\x9d\x6a\x24\xb8\xe5\x0e\x97\x80\x80\x79\xbe\xc0\xa4\xa4\x47\xc7\x7e\x39\xac\xe8\xcf\x76\x56\x5a\x2f\x8b\x30\x3e\x2b\x4f\xf4\x53\x41\x1a\xda\x8d\x82\x18\x9d\xc6\x7a\x5f\x36\x81\x44\xbb\x98\xa4\xc7\xba\xf1\x89\x70\x4d\x5f\x8b\x18\x1e\x27\xf8\x6c\x34\xd4\x5e\x67\xa4\xa6\x57\xfd\x2c\x16\x6d\x87\x66\x27\x55\xa3\xfa\x59\x4e\x40\x5e\x87\x67\xf6\x6b\xec\x54\x73\x65\xef\xbb\x79\xed\xd9\x88\xa9\xf7\xae\xc5\x2a\x00\xeb\xcd\xb4\xea\x5e\x75\xe2\xe1\x84\x9c\xde\xe4\x86\xb3\xe7\xd6\x58\x32\xba\x6f\xd6\x3d\x74\xa1\x41\xf0\xa1\x68\x23\x63\xea\x7a\x21\xba\xb8\x46\x11\xa4\x91\xd9\x7c\x14\x37\x02\x1e\x99\x9d\x7d\x1f\xff\x28\xdc\x47\xdf\x0c\x2a\x9e\x70\x2f\xa1\x6b\xce\x92\x8f\x47\x8a\x0b\x97\xcf\xab\x2c\xe2\xdb\xa8\xdd\x11\xa7\x2d\x6a\xfa\x73\x5c\xd8\xce\x1b\x6d\xe3\x8a\xbe\x75\xbf\xaf\x75\x51\xd3\x93\x24\xcb\x7b\x93\xf4\x31\xa9\x82\x5b\xbf\x8a\x9a\x9e\x27\xe9\x96\x61\x17\x35\x7d\x9e\x76\xad\x5c\x5f\x79\xb2\x06\x82\xdb\x4d\x59\x51\xd3\xcf\xe2\xdf\xc6\x65\x8a\xbc\x7a\x12\x82\x44\x5a\xa4\x34\x25\xa2\x4a\x0c\x17\x75\x3b\xa2\x94\x9d\x1f\xef\xad\x85\xda\x22\x08\xbe\x64\x49\x47\x8b\x3c\xf7\xc4\x30\xa2\x01\x39\xa5\x8b\xb9\x67\x4c\xf3\xea\x4e\x16\x30\x54\x01\xdc\xb0\x9a\x2d\xcc\x14\xf7\xc2\xed\x9a\x9c\x53\xe5\xf9\x98\x87\xa1\x59\x51\xb4\xa6\xe7\x38\x05\xa7\x35\x2c\x6c\x6d\xf8\x57\x58\x29\x56\x79\x8e\xd6\x74\xe5\xc5\x8c\x53\xff\x00\xad\xe8\x33\x8e\xce\xc9\x29\xc6\x79\xbe\xb0\xaa\xce\x47\x0a\x9d\x93\x15\x59\x63\x8c\xc9\xd2\x31\xf7\x73\x7a\xee\xb9\xdb\xe4\xe1\xa2\x55\xa2\x56\xb0\x35\xaa\x51\x45\x1a\x7f\xd0\x2f\x8d\x18\x11\xeb\x4c\xab\x48\x67\xba\xd8\x3a\xf8\x3e\xb3\x96\xdd\xcb\x35\x76\xf2\x70\x3b\xbd\xdc\xa1\x5e\x44\x6e\xa0\x14\x1a\xa1\x8a\x46\xb3\xae\x93\xcd\x27\xe1\xcd\x06\xdc\x9b\x0f\x73\x23\x0e\x8e\x50\x03\x30\x90\x91\xcd\xf0\x66\x23\x62\xcb\x6b\x93\x49\x4b\xd4\xe0\x3c\x1f\x35\x47\x2f\xd4\x31\xe0\xe0\x6c\x36\x15\x80\xe5\x50\xd9\xea\xe9\xe5\x5c\x16\x90\x92\x0a\x6e\xf3\x2a\x55\x7d\xfb\x45\xc1\x1e\xa7\x38\x63\x60\x52\xcf\x51\x4d\x95\xa7\x3e\x6a\xe8\x70\xc5\x82\x79\x38\x9e\x43\xa5\x2c\x4c\x54\x9e\xa3\xc6\xbc\xb5\xa4\xbf\x70\xd4\x60\xbc\xd9\x1c\x8c\x28\x6d\x6c\xff\x1e\xfa\x4b\xc8\x66\x4f\xe5\x71\x81\x6a\x87\x9a\x47\x15\x86\xad\x43\x63\x09\xbd\xa0\x17\x82\xac\x68\x47\xe9\x74\x4a\x3b\x0a\xab\x73\x47\xe9\x48\x47\xd4\x80\xd8\xc5\xf3\x3c\x21\xb9\x3d\x01\x46\x0b\xfa\xde\x15\x9b\xea\x9b\x4e\x69\x4f\x67\x75\x4e\x7d\x01\x99\x99\x11\x76\x1d\xae\xe7\x55\xa1\x24\xaa\x31\x59\xbb\x94\xc6\xa6\x34\x98\xb8\x21\xb6\x40\x2b\x72\x7e\x27\xb3\xdc\x90\xd4\x30\xce\xb0\x57\xbe\x2f\x49\x95\x12\x93\xae\xc9\xca\xb9\x6b\x49\x04\xa2\x83\x32\xe2\xc5\xc2\x15\x75\x6a\x8a\xb2\x7c\xd7\x8c\xdb\xb8\xa8\x35\x59\x74\x8a\x5a\x92\x15\x5d\x98\xba\xae\x48\x9d\xe7\x0d\x76\x07\x9e\xa7\xb4\x21\xe7\x74\x42\xd6\x74\x41\xeb\xd9\x7a\xb6\xa6\x5f\x14\x5a\x63\x7c\x7e\xe7\x0e\xcc\xd8\x35\x9d\x90\x15\x3d\x9d\xad\x66\x2b\xf3\x64\x85\xf1\xda\x3d\x99\x4d\x1e\x9e\xdf\x5d\xcf\xf0\xc2\xa4\x2f\x30\x39\xf7\x31\xb3\x27\x0f\xd7\x77\xcf\x67\xf8\xd4\xa4\x9f\x62\xb2\xf6\xe9\x26\x83\xeb\x3e\x4a\x4f\x3d\x42\xbe\x99\xc4\x90\x10\x01\xbe\x86\xd5\xcf\x15\xed\x8a\xda\x2e\x22\xff\x37\x7b\xed\xf9\x48\x9d\xe7\x4f\x14\x02\x2c\x5d\xb2\xb0\x9b\x39\xfb\xa0\x09\xbc\x63\xe9\xb2\x2c\x49\x63\xb2\x4c\x00\x5a\x29\xc2\x65\x76\xdb\xd9\xb9\x92\x48\xe1\xc2\x9f\xfd\xb4\x47\x83\xd5\x0d\x47\x83\x09\xd4\x73\x9d\xe7\x19\xa0\xcb\x83\xb0\x09\x07\x79\x86\xbd\x5d\xd0\xdf\x44\xf0\xf9\xff\x51\x18\x51\xad\x3c\x45\x2f\x04\xbe\xa0\xb5\x72\xce\x86\xb4\x54\x20\xea\x9e\x51\x66\x2d\x63\x50\x4d\xab\xe1\x28\xb9\xf5\xed\x51\x72\xab\x5e\xa8\x48\x57\x95\x3c\x47\x17\xb4\x52\xed\x8e\x07\x12\x2e\xc0\xb5\x12\xcf\xff\x12\xa8\x24\x17\x30\x8e\x0a\x74\x96\xe7\x67\x88\x93\x8a\x28\x4c\xba\xb6\x23\xe8\x8c\x56\x69\x68\x27\x9c\xe7\x67\xe3\x36\x72\x65\x9e\x47\x01\xf3\xec\xb7\x21\x3c\x62\x45\x7c\x3a\xa9\x7c\x94\x40\x72\xd6\xa1\x39\xe9\x21\x2e\x1a\x8a\x9d\xe1\xe8\x00\xf4\xac\x77\x00\x9a\xe7\xe8\x4a\xd1\x33\x72\xa2\xa8\xf2\xa7\x97\x78\x58\x6c\xbb\x54\xf4\x44\x51\x77\xe2\xd9\x03\x62\xb4\x8b\xe7\x67\x65\x04\xdb\x64\x2d\x8f\xe4\xa2\x01\xb1\x2a\xc8\x43\x70\x62\x4a\x9e\x9a\x81\x66\x08\x99\x88\x0f\x9d\x5d\xb5\x11\xfa\xce\x14\x8e\x72\x0c\xca\xa8\xa1\x2c\x1b\x5f\xc7\x2c\x8c\x2f\x85\x99\xbe\x1d\x21\xb8\xab\x71\xb5\xce\xbe\x27\x74\x48\x3f\x3b\x4b\xe4\xcb\x8e\x42\xb9\xe8\xbe\xf3\x54\x2c\x6f\x7e\xc3\x9d\x30\xf4\x5e\x72\x8a\xda\x60\x2a\x71\xe2\x6d\x23\x60\x1a\x7c\x10\x73\xb0\xd5\x84\xc8\x9f\x43\xdf\xeb\xd8\x44\xe7\xf9\xee\xae\x3d\x55\x76\x66\x98\x03\xaf\x39\x28\xab\xd9\x49\x9e\xa3\x67\x22\xcf\xb3\x4f\x12\x82\x3b\x8e\xad\xc1\x78\x9e\xa3\x0f\x62\xb3\x19\x7a\x67\x44\xe9\xc9\xbc\x5f\x07\x4a\xe9\x49\x9e\x7f\x10\x66\x70\x51\x21\x90\x59\x91\xb8\x68\x5d\x5f\xd1\x0b\x4d\x25\xbe\xd1\xfb\xf5\x83\x80\xc8\x7d\x64\xf2\x10\x9d\xd1\x97\x0a\x29\x72\x12\x1f\xdc\x9e\x00\x17\x7f\x2a\xd0\x89\xd3\xeb\x0c\x09\x1d\x27\x91\xd0\x71\xb6\xc5\x04\x5d\x05\xbe\x89\xae\xe8\x77\xb0\xcd\x01\x12\x82\x35\x28\xbd\x32\xc2\x0e\xba\xa2\x4f\xd2\xd0\x52\x3d\x83\xd8\x6e\x8f\xbb\x3d\xdd\x77\x02\x69\xdc\x35\x70\xf5\x4e\xca\xbb\x60\x05\x0b\xb6\xed\x16\xb4\x1a\xfd\x69\x1a\x48\xbe\x17\xee\x95\xf6\xec\x21\xc4\x68\x87\x28\x26\x9a\x99\x95\xeb\x7b\x91\xe7\x7f\x0a\x07\x77\xdd\xb1\x86\xb5\x70\xbd\x5b\x18\x0f\x45\x2f\xee\xd8\x07\xef\x91\xdc\xad\xb6\x15\x9e\x46\x2f\x45\x9e\x3b\xc3\xdf\x39\xe2\xd0\x51\x44\x0b\xca\x05\xf5\x4e\xcf\xd6\x36\x96\x5b\x41\x24\xda\x3c\x0e\xd4\xa2\xdb\x7a\x88\x07\xa8\xc7\xce\x28\x7d\xb3\xd1\x63\x6b\xb2\x6e\xae\x9c\xcd\x3a\xc4\x56\x75\x19\xf2\xdc\x67\x70\xe1\x58\x17\xe7\x4c\xe5\xf9\xf4\xa1\xbd\x4a\x2d\xb1\x76\x6c\xa2\x05\x56\x06\xc2\xb6\xc8\x66\x7d\x73\x67\x9f\x65\xdb\xab\xed\x0d\xbd\x19\xcd\x01\xed\xe6\x80\x25\xbf\xed\x14\x47\x6f\xc0\x5f\xb0\x36\x06\x60\x62\x10\x1f\x36\xc5\xc3\x55\xfa\xe1\xda\x3d\x90\x72\xdb\x5d\x67\x04\x7a\xd3\x40\x96\x1d\x8b\x03\xe9\x07\xec\xf6\xad\xe1\x6f\x36\x80\x59\xd0\x22\x3d\x52\x69\xac\xa6\x6b\xaf\x5f\x2e\x78\x28\xa7\xd0\x24\x51\x34\x17\x22\x32\xb7\x7a\xa9\xba\xe8\x51\xba\xdd\x96\x10\x65\xf6\x23\x1e\x63\x33\x20\xad\x73\xf0\x57\x6f\x77\x20\x07\xe0\x7c\x1c\x6f\x3f\x18\xd0\x81\x39\xd9\x02\x31\x0a\xb1\x35\x80\x86\x6a\xdc\x08\x8b\x2c\x08\x75\x67\x00\x6a\x90\xe6\xd3\x36\x9f\xdf\x9c\xb8\x4c\x18\x22\xfc\x27\xd8\xd2\x31\x82\xcd\x17\x15\x21\xa8\xf6\xf0\xb1\x97\xf2\x3a\x7a\xdb\xe1\xf3\xe7\xf9\xc1\xc8\x83\xee\x07\x1b\x3b\xcb\x36\x22\x64\x9c\x44\x4f\xe7\xc9\xc4\xa8\x8e\x3c\xcb\xad\x6a\xc6\x63\x7c\xe6\x39\x60\xb4\xcf\xbc\xce\x4d\xc0\x21\x44\x10\xda\x40\xf3\xdf\x8b\x2d\x62\x45\x33\x0b\x94\x6e\x17\xba\x03\x2b\x12\x44\x54\x6d\x60\x8f\xd2\x10\xe9\xf6\x90\xa8\x36\xf4\x12\x84\x19\x7a\x95\x31\x5d\x05\xa9\x89\xd9\x17\x48\xcf\x04\x3b\x59\x3d\x69\x5d\x3e\x4c\x44\x80\xcf\xdf\x4e\x46\x94\x96\x61\x38\xdf\x6c\x0e\x53\xc6\xc1\x48\x9f\x29\x1f\x90\xe5\x7b\x67\x11\xf5\xa7\xea\x58\x74\xff\xaa\x06\x39\xac\x8b\x09\x62\x57\x72\x3b\x37\x8a\x48\x0a\xf0\x3a\x0a\x6f\xe1\xe5\xdd\x02\x46\x7a\xcc\x1a\x2d\x9f\x19\x69\x65\xdb\xc7\x08\xf8\x2e\xb1\x22\x4c\xc3\x88\x98\xa5\x6d\xed\x6c\x61\xe1\x4e\xc8\x7a\xa1\xca\x75\x1b\x82\xa4\x6f\x72\x17\xa2\x55\xb5\xf2\xda\xd0\xc3\x8e\x4f\xc2\xcd\xd1\xa1\xa2\x20\xd0\x5f\xc9\x71\x63\x86\xb1\x0d\x42\x65\x7d\x1a\x06\x2d\x7c\x6b\x0e\x78\x3d\xb2\xd1\xf3\xf6\xd2\x87\x9c\xfd\xe7\xe0\x2b\x8b\x8a\x33\xe5\x5f\x8a\x6f\xdc\x6b\x91\x83\x02\xcc\x37\x34\x4d\x22\x23\x6d\x36\x0f\x92\xfb\xa0\x76\x30\x93\xef\x44\x2e\xaf\x5c\x04\xe4\x38\x1c\x62\x96\x45\xe3\xe8\xaf\xd6\x28\xd6\xbe\xc9\x67\xe6\xd5\xc4\xc6\xd4\x63\x54\xf8\x8f\x00\xe4\x88\xb5\xfc\x03\x0b\x50\x3b\x7f\xb6\x7d\xa3\xd9\x9f\xec\x31\x13\xb5\xe0\x03\xa5\x6c\x6a\x6f\xa6\xda\x22\x2c\x4d\x66\xdc\xee\xbd\xee\x27\x0d\x69\x71\xd0\x0c\x37\x86\xb3\x9f\xef\x20\x5c\xdc\x66\x93\x7d\x37\x0a\x57\xf3\x8c\xfa\xc8\xbb\x93\xc8\x1e\x79\x87\xcf\xf4\xdd\xbb\x20\xd0\x65\xff\xf5\x9d\x0b\x33\xa7\xef\xdc\xd9\x0e\xd4\x25\x01\xe6\x37\x1f\xfd\x45\xd1\x09\xf9\x41\xd1\x6f\x38\x51\x23\xbf\x2b\x9a\x7d\xb4\x7c\xe9\x59\x79\xc2\xd5\x77\xd9\x9d\x1f\x14\xf9\xad\x4d\x7d\xa3\xe4\xba\xb6\xa9\x2f\xda\xd4\x80\x7b\x6c\x9f\x70\x19\x9e\xc0\x21\x86\x7d\xa1\xed\x7a\x2d\x23\xb3\xd0\xa3\xdf\xd5\xb1\x3d\x94\x0d\xf8\x65\x71\xf4\x80\x56\x65\x3e\x13\x3e\x6e\x80\x38\x7a\xa1\x8e\x37\x1b\x61\x5e\x0d\x51\x8a\x5b\xfe\x18\x66\x06\x4c\xac\x20\xc6\x89\x30\x67\x84\x0b\xae\x60\xcd\x9d\xa1\x57\xe3\x45\xca\x9a\x39\x43\xe1\x9e\x96\x33\x97\xad\xb5\x71\x15\x80\x0f\x8d\x13\xa3\xe4\xa1\x88\x08\x10\xab\x2b\x18\x23\x73\x5b\xee\x66\xc3\x41\x77\x64\x35\x33\xbc\xd5\xcc\xb8\xcb\xe9\x5e\x7b\x1d\x2e\x43\x00\x93\xe0\x87\x21\xdd\x8a\x75\xe0\x43\xbf\xd8\xd3\x07\x1e\x47\x93\x48\x22\x7e\xa5\x38\x62\x7b\xb1\x20\x20\x65\x8c\xe6\x70\xf4\x1b\x10\x38\x69\x09\x4b\x7a\x8d\xcb\x80\x05\x1b\x8e\xf3\xb4\x43\x2c\xe1\xf2\xd8\x5b\x40\x78\xb4\x89\x52\xd2\xa3\x63\x52\x49\x7a\x37\xb2\x72\xad\xa3\x6f\x5e\x3b\x11\xa3\xe0\x71\xc8\x66\xc8\x30\xf9\x47\x25\x21\x56\xbd\x0f\xb5\x51\xca\xa3\x4a\x1e\x13\xfb\xe3\xc2\x3f\xc8\xbb\x77\xe3\x70\xc9\xd2\xb2\xef\x4a\xde\xb9\xe3\xf3\x85\xf7\x5b\x13\x04\x17\x4a\xf5\x54\xd2\xeb\x2d\x59\x4b\x5a\x4b\x74\x2a\x31\x39\x87\xab\xd1\x14\x93\x95\xa4\xa7\xb2\xad\xf0\x85\x4c\x31\x0d\xc1\x49\xc1\xed\x58\xcd\x2c\x07\x0c\xc2\x51\xc0\xf5\x39\x95\x33\x6f\xac\x91\xac\xd7\xca\x48\x27\x6e\x82\x3c\x17\x30\x6c\xab\x57\x2e\xe6\xce\x07\xb1\x62\xf5\x27\x6e\xe3\xdf\x3a\x87\xfa\x98\x13\xdc\xf8\xe2\xab\xde\x6b\x16\x8e\x8c\x30\x1f\xf8\x5d\x5a\xcc\x5f\x76\x24\x8f\xa9\x3e\x6a\xfb\x0f\x54\x5d\x3c\xae\x24\xfe\x5b\xb5\x33\x04\xfd\xe6\x4a\x51\x86\x09\x8b\x70\xeb\xe3\x61\xe7\x38\xb6\x9d\x9d\x8f\x23\xb2\x46\x08\xf0\x12\xe1\xeb\x46\xa2\x73\x89\x49\x23\xd1\x3a\x0e\xea\x76\x22\xa3\xf3\xb3\xb5\xf4\x9d\x3c\xa2\xf4\x54\x76\x4d\x58\x0e\xef\x63\x3c\x5b\x98\x02\x88\xc6\x64\x61\x0a\x24\xb1\x57\xcd\xa5\xec\x9a\xdb\x24\x3d\xc8\x3d\x77\x89\x6b\x49\x06\x62\x85\xa9\xf1\x19\xd7\x71\xfb\x5b\x96\x12\x44\x41\xd3\x2d\x8a\xf6\x72\x22\x50\x5d\x8d\x10\x3c\xe7\xbd\x00\x47\x93\xfb\xe4\x2f\xb0\x61\xc8\x3e\x38\x28\x19\x23\x9c\x25\x91\xe3\x2d\xda\x5c\x80\x40\x4f\x66\x38\xed\xf4\xb8\x91\xd4\x6e\xea\x44\xae\xce\xd2\x4e\xdc\x6c\x4e\xa5\x99\x1b\x2d\x91\x89\xa5\x25\xf7\xb4\x3c\x0f\x4f\x00\x71\xac\x35\x6c\xbf\x9d\xae\xa3\x5e\x5c\x9e\xc3\x07\x18\xcf\x84\xd9\x6e\xba\x2e\x59\x49\x4c\x6e\x9e\x04\xbd\xaa\x52\x4e\x92\xe1\x12\x2a\x8a\x0b\x97\x1e\x3a\x1f\xcc\x42\x2d\xca\x17\x79\xe7\x7e\x1f\xcb\xdb\x30\x01\xff\x48\x9e\x76\xd1\xe9\xc9\x9b\xe4\xb1\x3d\x41\x0a\x0f\xdf\xa6\xef\x9e\xcb\xa6\x5a\xfe\x5e\xf2\x6a\x49\x5e\xa7\xdf\xe4\x7f\x35\xbc\xd6\x6f\x58\x29\x34\x79\x9f\x3c\x12\xf2\x92\xfc\x9c\xa4\x98\x21\x64\xc9\xee\xeb\xf8\x92\x5f\xf0\x8a\x7c\x4c\x72\x3d\x5f\xad\xf8\xb2\x64\xba\x8d\x83\xf1\x4a\x7e\x15\x1d\xf1\x79\x92\xa5\x83\xb6\xff\x28\x79\xf8\x52\x5e\x86\x27\x2f\xd3\x2f\x2f\xab\xf6\xa3\x5f\x80\xed\x3e\xf1\x76\x1b\x23\x4a\x5f\xcb\xf9\x6b\x99\xc2\x17\x3d\x73\x1d\xf1\xbd\xfb\xfd\x53\xd2\xd1\x94\xfc\x2a\xe9\x7b\x89\x30\xf9\x4e\xd2\x29\xdf\xff\xc7\xaf\x72\xfe\x3e\x79\xcf\x8d\x72\x93\xe7\xee\xaf\x32\x72\x8b\xfd\x60\xf8\x87\xdb\x41\xfc\x2c\x11\x76\xc6\x27\x1f\xa5\xdf\xcb\x3f\x78\x60\x4f\x25\x5f\xb5\x29\xf7\x6d\xca\xf3\x36\xe5\x9e\x4d\x79\xd4\xa6\x1c\xda\x94\x97\x6d\xca\x41\x50\xbd\x74\x97\xdd\x34\x14\xeb\x3f\x65\x3f\xa0\xfe\xce\x83\x07\xbe\x9c\x8f\xd2\x96\xfc\x20\x80\x8f\xbe\xf2\x29\xf7\x7c\xca\x73\x9f\x72\xe8\x53\x1e\xf9\x94\x80\x95\xfa\x52\x7e\x63\x7d\x7e\x94\x1d\xe7\x3d\xa8\x20\x79\x2c\x9d\x2f\x65\x90\xb4\x65\x27\xca\xb3\xcf\xf9\x87\x0c\x16\x0a\x41\x70\x96\x28\x46\xf3\xfb\x5e\x7a\x04\xad\xef\xe5\xcc\x77\xec\x1b\xf3\xf2\xf6\x17\x19\x7b\x4b\xfe\xe2\xde\x1b\xfd\x29\x83\xf0\xf6\x4c\xe2\x6b\x33\x08\x3c\x5e\x98\x35\x8b\xb0\x62\xc9\x33\x39\xfb\x51\xa2\x07\x0f\x92\x28\x2d\xd6\x43\x2e\x0d\x2c\xea\x56\x70\x80\xc3\x5f\xca\x6b\x41\x05\x1a\x4d\xb0\xdb\xd7\x7b\x29\x11\x6f\xb7\x18\xfb\x01\xe8\x3c\xa3\x34\xbe\xb6\xe4\x0b\xb5\xc9\x73\xf4\x4c\xd2\x67\x01\x21\xef\xce\x14\x03\x0d\x3e\x4a\xf2\x93\x34\xe2\x8f\xb7\xd3\x80\x91\xbb\xb5\x41\x0e\x7f\x90\xf4\xf3\xf8\x2d\x88\xce\x76\xba\x7e\x6f\x4a\x7f\x2c\xc5\x69\x79\xd6\x0e\xd6\xdf\x65\x50\xcd\x81\xc7\x54\xc0\xd2\x92\xeb\xba\x13\xcd\x5a\x5b\x7c\x05\x6d\x95\x1c\x49\xc6\x56\x3c\x3b\x12\xc7\x46\x42\x3b\x12\xc7\x60\x32\x19\x81\xbe\x26\xae\xcd\xbf\x81\xf8\x63\x0d\xe2\x5e\xb8\xde\xe1\xcc\x1d\x8f\xb1\x2e\x9a\x21\x43\xf8\x5a\x33\xca\x19\x75\x79\x23\x01\x95\xb5\x12\xe3\x6f\x61\x41\x98\x35\x12\xfd\x26\xb1\x0b\x32\x3b\xfe\xe8\xe4\xa7\xf1\x47\xf7\xdc\x45\xbd\x8f\x44\x53\xd6\xaa\x98\xba\xca\x24\xd1\x0d\x0f\x88\x9c\xf8\x60\xb1\x67\x35\x06\xd9\x29\x52\xeb\x88\xcd\x06\x89\x81\x2c\x56\x67\x12\x3f\xd9\x50\xed\xfc\xa6\xd3\x44\xd2\xee\x27\x50\x27\x3f\x9e\x45\x4a\xa2\x48\x72\x76\x0d\x78\x21\x29\x27\x96\x56\x56\x7b\x17\x05\x61\x5c\x72\x00\xd1\x15\x8b\x92\xd7\xad\xc1\x96\xf7\xe2\xb4\x24\xb2\x3e\xb4\x2e\x86\x51\x0d\x86\x5d\xe8\x65\x09\x76\x6b\x69\xc6\xae\xb3\x75\xc9\xda\x68\xda\xcc\x1e\xcb\x8e\xa6\xd6\x08\x0e\xb0\xa5\x8d\xa0\xd1\x57\x4c\xe4\x79\xc0\x65\xde\x73\x46\x72\xa6\xf2\x44\xd3\x36\x1d\x13\x4d\xaf\x5d\x0f\x16\x9c\xc8\x93\x9a\xab\x0b\xbe\xfc\xbe\xd4\x75\xa1\x89\xd9\x76\x5b\xe0\x04\x1f\x23\x84\xb3\xb8\x33\x5e\x74\xe5\xb2\xbd\x89\x91\xcb\x38\xa3\x9a\xbc\x90\x09\x4d\xe8\x35\x34\xba\x98\x90\xb8\xa1\x85\x26\x2e\xe0\x32\x57\xb5\xfd\x92\xeb\x33\x43\x65\xd8\xf6\xd3\x80\x2a\xc4\xd3\x21\x06\x63\xbd\x62\x89\xdf\x5d\x0d\x23\x96\x8f\xed\x59\xcb\x2f\x0d\x6f\x38\xbd\x3e\x61\x35\xb7\x58\x28\x9d\xd0\x98\xb6\x2a\xdf\xb3\xda\x81\xef\x17\x76\x2b\xc2\xfa\x69\xf5\x39\x53\x7c\x59\x5c\x3b\x1c\x65\x47\x13\x7e\x7a\xca\x17\xda\xd7\xbb\xdd\xf5\xb8\xde\x32\xc3\x22\xaa\x08\xd1\x49\xb5\xec\x01\xa1\xbe\xb9\xaa\xe1\xba\x57\x4d\x37\x58\xda\x94\x6e\x9d\xcd\x08\x4b\x9e\xbb\xfa\xf3\xb1\xbd\x08\x35\xe7\x63\x77\x15\xeb\xf2\x16\x2c\x5e\x41\xae\x03\xee\x73\x61\xbe\x23\x78\xa1\x89\x66\x67\x00\xc6\x77\x55\x49\xb6\xb4\x14\x5a\x38\xb9\xc8\xde\xb5\x03\xa7\x2d\x76\xd9\x0e\xe2\x78\xe2\x44\xed\xc7\x9e\x27\x58\xd9\x16\xaa\x8a\x3d\x76\xf5\xcc\x33\x80\xb9\x76\xe3\xa2\x40\xee\x4a\xc0\x0f\x11\x2e\x1d\x7c\xf8\xec\x4b\x54\x47\x15\x38\x65\xe9\xee\x2f\xee\x1b\xd5\xe5\x43\xad\x7d\xae\xa0\x10\x17\x54\x0d\xd4\xd4\x31\x57\xc7\x53\xa3\x86\x09\x2a\xba\x7d\x84\xf1\xf5\x52\x3a\xa4\xdc\x88\xa6\xa2\xc5\xd5\xb6\xd4\x15\xc0\x1d\x80\xc4\x10\x54\xac\x25\xf3\xd8\x5d\x45\xb4\x1e\xfb\xcb\x88\xe2\x9e\x50\x6c\x2e\x29\xa3\x65\xc1\xa8\x9b\x48\x25\x68\x79\xcd\x65\x77\xa1\x4c\x5f\xd1\xed\x2b\x8e\x83\x42\x6a\x88\xf6\x13\x0f\x53\x75\xcb\x30\x95\xdd\x61\xc9\xfc\x38\x54\xdd\x71\xa8\xc2\x38\x24\x2e\xbc\x5a\x3c\x2d\x44\x88\x8b\x85\x38\x15\x9d\xb1\x8d\xe7\x3d\x52\x53\x5d\x70\x57\x7f\xd2\xcd\x1e\x2f\x4c\x6b\x96\x9a\x3a\xb3\x74\x50\xcc\x2c\x73\xf1\xe0\xc6\xbd\x39\x47\x59\x6f\x9a\x51\xe6\x5a\x16\x46\x6d\xa4\xde\xc7\xd7\xdd\xa7\x76\xdc\x00\x44\x03\xad\xc9\x82\x36\x50\xeb\x59\xe3\x86\xb5\x5f\x63\x28\xa5\xd5\xbc\xa4\x8b\xa2\xb2\x0f\x16\xa4\xa2\x0d\xbc\xb6\xbc\x61\xd8\x3a\x1c\x93\x53\x8a\x96\x74\x99\x0c\xdc\x4e\x95\x67\xa7\x2e\xd2\x81\xfb\xce\xe9\x7c\xd9\xa3\xe6\xa2\x38\xf5\xdf\x5d\x76\xa9\xd9\xb8\xe0\xac\xce\xe6\x17\x3b\x53\x19\x16\x0d\x8b\x8a\x4e\xc8\x92\x2e\xa8\x35\x56\x9a\xcd\xf0\x75\x4d\x4b\x18\xe4\xd0\x84\x35\x2d\xdb\x29\x00\x12\x80\xca\x6b\x6c\x8d\x70\x5b\x83\x14\x68\x07\x54\x22\x9a\x3b\x6b\x3b\x63\x26\x30\x59\xca\x64\xb2\x94\xfd\xc9\x52\x0e\x4d\x16\xec\x0d\x6a\xcf\x29\x27\x2b\x5a\xfa\x33\xcf\x9a\x6a\xb2\xa6\x82\xac\x6c\x44\x66\x67\xcf\x9e\x44\xec\x0f\xc0\x43\xe7\x74\xe5\xbf\x86\xf1\xf5\x29\x3d\xb7\xc0\x10\x6b\x72\x4a\x6a\x1c\x8e\xf5\x4f\xe9\x79\x62\x1a\xb0\xb3\x57\x9c\xdb\x40\xd2\xf4\xee\xfe\xe4\xc1\xbd\xdc\xdd\x6d\x0e\xf7\x67\xce\xa0\x3e\x2c\xb4\xa8\x1e\xd0\xd5\x27\xdf\x9d\x27\x1f\x2d\xce\x5b\x9b\xde\x53\x2b\x59\xc6\x75\xf1\x81\x0c\xcc\xf8\x9e\x6c\x43\x50\xb9\x40\x1f\x50\xd1\xdb\xca\xd0\xbd\x5d\x3f\x04\x21\xe6\xaf\x9b\xa6\x78\x1e\x2e\xe9\x51\x79\x5c\xd4\xf6\x94\xa8\xf4\x81\x14\xd7\x03\xdd\x54\xff\x37\xba\xc9\xd7\x61\x39\x47\x0b\xba\xa4\x6b\xd2\xd0\x53\x5c\x84\x31\xb1\x26\xd5\x86\xd6\xb3\xc4\xce\xbb\x84\x47\x38\xb1\xfe\xee\xcf\x4f\xec\x8d\xd9\x69\x6d\x17\x91\x3a\x9a\x7b\xdd\xf9\x4d\x6b\x32\x38\x83\xb7\x9e\x3d\x2d\xc1\x26\xef\x14\x93\x68\xfc\xd3\x86\xf4\x78\x07\x5d\xf4\xcb\x5e\x92\x27\xd5\x86\x56\xc4\x49\x87\x70\x95\x48\x2b\xf4\x34\x46\xc9\x60\x91\xae\x8c\x53\xed\x7b\x83\x84\xab\x44\x44\xb5\x71\xce\xb5\xd9\x6c\xb5\x1e\x58\x3a\xf6\xc0\xd2\xd6\x03\xcb\xd3\x3e\xe2\x25\xd2\xe1\x7c\xf8\x47\xb6\x60\x45\xc5\x90\xbe\xac\xa7\xa8\x7b\x30\x25\x12\xe3\x99\xb4\xc3\x53\x61\xb7\x81\x5a\x31\x8a\x04\xbf\xdc\x51\x63\x30\x25\x11\x5c\x68\x3c\x56\xfc\xb4\x8e\x94\xb5\x11\x77\x16\xce\x4c\xd0\x2c\xac\xc8\xc6\x33\x4d\x83\x9c\xe3\xb9\x2e\xec\x0e\xca\xfa\xf0\xa7\x94\x13\xc4\x62\xf7\x5a\xb9\x3b\x4f\x97\x97\xa8\xab\x9c\x12\xe9\x8c\xd1\xeb\xb2\x7e\x25\x1b\x00\x3c\xee\xa3\xd2\x01\x6a\x25\x1f\xa7\x2a\x2c\x23\xf5\x43\x28\x73\xf3\xa5\x2d\xe1\xe2\x2f\x53\xf8\x3b\xae\xed\x42\xd9\x75\x11\x18\x28\xc0\x29\x9b\x9b\x1a\x61\x22\xe9\x02\x10\x6b\x18\x5d\x30\x08\xb7\x34\x63\x7e\xaa\x84\x1d\x8c\xd9\xc0\xb0\xa8\x5b\x30\x01\x11\x8b\x61\xb2\xac\x11\x27\x92\x28\x1c\xea\xf1\x96\xaf\x2b\xb6\xe0\xff\xb1\xba\x68\x76\x46\xa7\xe4\xbf\x57\xa7\x67\x52\x2d\xbc\x68\x90\xda\xb2\xdc\x54\x21\x61\x2b\xa4\x5c\x85\xa4\xa9\x10\x44\xb1\x00\xeb\x03\xba\xeb\x2a\x01\xbe\x4e\x6d\x25\xb4\xab\x84\x74\x95\x50\x10\x0e\xa1\x1d\x68\x57\x2c\x71\xad\x2c\xc3\xa9\x71\x9f\xe5\x76\xb4\xec\x56\xeb\x17\x46\xb0\x6d\xcb\x9c\x0f\xa7\x23\x05\x85\x17\xa3\x18\x68\x1d\x22\xed\x06\xbc\xa4\xb2\x7e\xd3\x28\x6e\xf5\x0a\xfe\x65\x40\xba\x30\x8d\x84\x0b\x49\x58\x7c\xea\x73\xc2\x52\x75\xec\x68\x4a\x24\x3d\x95\x84\x79\x9c\x17\xab\xda\x9e\x0d\x43\xe6\xed\xb0\xd6\x60\x63\xce\x68\xc9\x10\xc3\x05\x92\xf4\x4c\x22\x8d\xe7\x2b\x59\x44\xfa\x61\x66\x64\x60\x77\x98\xab\xd2\xd2\x6b\x8c\xe7\x70\xb2\x22\x71\x71\x2a\xcd\x8e\xd2\xcc\x6c\x0d\xd6\x06\xfd\xa9\xe8\x0f\xf7\x80\x8c\x91\xbb\x9d\x4b\x99\xbb\x5f\xbb\x8f\xf0\xdb\x23\x45\xcf\x18\x89\x48\x4f\x35\xd1\xdd\x11\x42\x39\xf9\xef\x9e\x84\xc8\xbf\x7b\x12\x12\x09\x93\x97\x11\xbb\xe2\xbe\x35\x64\xe0\x88\x5d\x03\x86\x10\xf4\xed\xaf\x65\x55\xbd\xe5\x0b\x5e\x5e\x70\xd0\xf5\x98\xd1\x70\xe3\x43\x18\x04\xc3\x05\x7e\xf8\xf9\xdd\xa3\x67\x4f\x3f\xde\x5a\xee\xd7\xf2\xd8\xe2\x5d\xbd\xad\x8e\xe1\x8c\x8d\x07\xd8\x07\xd2\x3e\x17\xe9\xa8\x29\x3e\xb3\xae\xeb\x60\x7c\x3c\x20\x01\x1e\xae\xa6\x82\x38\xdb\xa1\x2e\x13\x27\x12\x56\x00\xba\x62\x04\xf6\xf1\x33\x6f\x68\x13\x8f\xe4\x5b\xc7\xb0\xf4\x59\xfd\x58\x66\x83\x63\xb9\xcd\x06\xc3\x96\x61\x4c\x60\x2b\x20\x80\x3f\xdd\x58\xbd\x01\x7e\x60\x6a\x77\xc6\xf5\x13\xae\xca\x0b\x97\xed\x99\x92\x2b\xab\xb8\xcb\x73\xe4\xd6\x30\x66\x16\xa5\x1b\x8a\xbd\xa1\x4b\x6f\x2a\x75\xb3\x19\xc8\x2e\x01\x79\x47\xb0\x75\x7d\x2e\xb5\xb5\x39\xb3\x3c\x27\xce\xdd\xae\xd1\x83\x63\x01\x96\xbb\x3c\x1f\xcc\xdf\xcf\xb8\xd9\x20\xed\x6d\xc0\x86\x1a\x30\xf4\x4e\x9e\x0f\xa5\xa2\x41\x02\xdc\x5a\xc7\x5b\x1e\x22\x4c\xb4\x91\x59\x3c\x7b\xb9\x61\x08\x4b\xdf\x1b\xce\x6f\xf8\x1b\xba\xff\x86\x6a\x86\x2a\x3c\x29\x97\xae\x7a\xad\xf0\xbc\x6f\xe5\x89\xa7\x8c\x3e\x52\x8a\x5d\x8d\xcb\x1a\x7e\xdb\xa5\xe7\x53\x2c\xc6\xb5\x5a\x11\x61\x26\x02\x1e\xec\x0c\x9e\xe7\x7d\x78\x3c\xfb\xfa\xf8\x23\xb8\xaa\x38\x03\x88\xe4\x76\x3a\x72\x21\xca\x7b\xfa\xba\x07\x0e\x0a\x40\xd1\x28\x78\xf9\x76\xf0\x28\x6f\xff\x1e\xe1\xd8\x07\xc9\xca\xb2\x3b\x21\xde\xa2\xe8\x86\xa6\xd7\xa6\xfe\x71\xf5\xa3\x81\x0d\x4f\xe0\x67\xfc\xd1\x1a\x5a\xbd\xe5\xa7\xe0\x6f\x03\x89\x05\xd2\x34\x96\xb8\xac\xf6\x59\x59\xd9\x50\x53\x4a\x57\x0c\xac\x14\x6c\x0a\xbd\xde\x86\xf0\xc5\x7c\xee\x62\xc0\xea\x23\x79\x5c\x98\x3f\x46\x0e\xd3\xf1\x57\x24\xd1\xce\x99\xc1\x5a\x78\x45\x14\x4c\xdb\xba\x7b\x7f\x1f\x63\x6b\x0c\xe0\xc9\xd8\xc9\xf0\x60\x02\x41\xdc\xfa\x46\x46\xef\x5a\x35\x57\x6b\x76\x36\x0a\x68\x65\x1d\xfa\x4f\x49\x76\x64\xbb\xd3\xe1\x31\x1e\x67\x94\xf6\x81\x14\xbd\xb5\x8f\x83\x1c\xc4\x73\x37\x06\x76\x2e\x4b\x7d\xbe\xf3\x89\x5f\xd5\x3b\xd7\xd9\x9d\x14\xdc\x70\xfc\xa7\x2c\x05\xca\xc8\x4e\x86\xef\x64\xdb\xac\xd0\xb1\xe0\xf0\x98\xf5\x63\xe8\xd8\xbd\x84\x17\x25\x34\x6c\x50\x9e\xc2\x66\xc2\x6b\xed\xd5\xdc\xe1\xfd\xd9\x64\x2a\x48\x9c\x8b\x0a\x5c\x68\xbb\xd5\x71\x09\xe9\x53\xa7\xa0\xf3\xb7\xb0\x3d\x71\x3b\xe0\xfb\xd1\xd6\x46\xc0\x4a\x04\xc7\x46\xa9\x0d\x67\x7c\x7e\xa0\x66\x58\xdb\x15\x4b\x51\x35\xae\x9d\x19\xd7\xa0\x05\x4f\x64\xe0\xca\x7d\x3c\x5e\x5f\x8c\x9e\xe1\x30\x64\x3f\xf1\x2b\x23\xba\x71\x6d\x81\x8e\x21\x6e\xa0\xbb\x05\x04\x64\xa2\x8d\x68\xa3\xbb\x1f\x8b\xba\x3e\x39\x79\x43\x9c\x7e\x57\x5b\x63\x56\xfb\x3e\x9d\x18\x09\xc6\xbe\xdc\x03\x63\x60\xc8\xad\x9b\xc1\xe0\xd9\xbe\xa3\x08\xf7\x0e\x83\x20\x76\xb5\xae\x3f\x73\xd0\x49\x42\x2e\xfc\x50\xcc\x91\x76\xa4\xdc\x25\x02\x17\xaa\x48\xef\x45\x84\x37\x1a\x85\x4e\xe7\x21\x3a\x78\x54\x32\x68\xa5\xdd\xbb\x89\x84\x53\xb7\xab\x7b\x44\x68\x6b\x78\x77\x08\x24\xd4\xec\x6c\x8e\x90\xa6\x7f\x19\x69\x82\x8f\x57\x72\x09\x0e\x33\xee\x44\x85\x1a\x62\x14\xe6\xb9\x84\xe1\x96\xa4\x47\xea\xf3\xc1\xcf\xb8\x10\x9a\x63\x6e\x1d\xe6\x8c\x2c\x00\x5e\x0e\x36\xc4\x09\x52\xb6\x4c\x2b\x62\x40\xc9\xa7\x34\x30\x57\xa2\xda\x2f\x29\x53\x03\x45\x3f\xd4\xc8\xbe\x4b\xc0\x51\xc2\xbf\x69\xad\xb2\x93\x9a\xdf\x58\x4e\xa4\x30\xbf\x85\x30\xfb\x9e\x30\x9b\x8d\xbe\xc9\xd5\xdd\x9a\xb4\xc5\x29\x69\xe6\x72\xb5\xb6\xad\x06\x0c\x10\xc8\x9d\x26\x01\xd1\x7f\xfa\x16\xa2\x47\xc6\xaa\x47\xc7\x37\xf5\xc0\x32\xec\x87\xd8\x40\x8b\xee\x25\x5d\xfd\xcf\xf8\xab\x46\x94\xfa\x7b\x9d\x7d\x1a\xad\x7f\x7d\xbb\xdb\x21\x73\x5b\xc7\x12\xec\x28\xcb\xb2\x3b\xda\x7f\x3d\xfd\x46\x8c\x23\x1b\x1f\x89\xf9\xb1\xd4\x46\x21\x1c\x7f\xf7\x9d\x7d\xec\xd4\x7c\x4f\xbd\x53\x86\x30\xa3\x44\xdb\x51\xe2\x58\xc2\xc0\x28\x11\xf1\x28\xb1\x9b\x16\x4c\x44\x5b\x13\x61\xb5\x6d\x9f\x8a\x50\xef\x9f\x6a\x74\x43\xa5\xcd\xda\xf4\x94\x81\x55\xd0\xaf\x28\x80\xe2\x5a\x2a\xb7\xaf\x58\x99\x25\x69\xac\x5b\x74\x86\x4d\x18\xd7\x5d\xa9\xdc\xd3\x60\x0e\xad\x2a\xfc\xe1\x45\x8f\xfe\x43\xe6\xce\x02\xa7\x93\xd2\xda\xa2\x17\x96\x37\x64\xd9\x1d\x1f\x54\xb2\x47\xfb\xc8\x7c\x33\xd0\x5e\xdc\x44\xfb\x1d\x98\x95\x20\x15\xd8\x69\x4a\x29\x7d\x37\x77\xe3\xd2\x76\x42\x18\xc9\x60\x98\x5f\xb4\x5c\xc3\xb6\x27\x21\x7a\x54\xdc\x22\xcd\xe7\x28\x2e\x80\xe2\x02\x0f\x37\xae\x9d\x0f\x40\x79\x4b\x6d\x71\x03\xb5\xcf\x63\x77\x81\x21\xaa\xaa\x01\xaa\x86\x90\xc2\xd0\xcf\x94\x03\xb4\x83\xf0\xe1\x1f\xb3\xec\x0e\xa8\x5d\x86\xc8\xaa\x22\x70\x10\x4f\x56\x75\x23\x59\x43\xd1\x0e\x39\x04\x16\x3d\x51\xc0\xaf\xff\x9a\x8a\x09\xae\x09\x27\xaa\x4b\x70\x49\xec\x0b\x45\x63\x9f\x9b\xba\xa5\xf4\x5e\xc4\xcd\xb8\xed\x5b\x44\x62\xd7\x05\x0a\xba\x20\x04\xb2\xdc\x59\x0e\x51\x02\x82\x35\xfa\x3e\xd0\x86\x09\x0f\xf6\xc1\x0a\x49\x02\x2e\xae\xad\x95\x85\x3d\x7d\x20\xd6\x19\x96\x2c\x69\x49\x56\xb4\xa4\x13\x72\x91\x78\xc7\x2e\xf3\x7c\xf5\xb0\xf2\x0a\xd2\xd5\x9d\x3b\xf8\x7a\x69\xd7\xd8\x7f\xac\xe6\xe8\x82\x2e\x9d\x0b\x33\x2e\x2e\xe8\x32\x48\x02\xd6\x19\x75\x8d\x24\x59\x92\xea\x68\x75\x4c\xea\x38\x54\xe6\x99\x3d\xc7\xa0\xfe\x1c\xe3\xc2\xe9\xe1\xb7\x3c\xcf\x97\x61\x01\x3e\x8b\x17\x60\x6d\x8a\xc2\xa4\xa4\x0c\x9d\x91\x92\xac\x82\x8c\xbb\x98\x37\xf4\xac\x58\x04\x31\xe2\x8c\x2c\xe8\x19\x59\xd2\x0b\x43\xc4\x15\x38\x8c\xa4\x8e\x53\xc2\x96\xd4\x44\xf5\x59\x3a\x4b\x8c\x4e\x43\xbd\x94\xb1\xa4\xa7\x48\xfa\x66\x98\x3d\xac\xa9\xc5\xb2\x57\x8b\x65\x54\x8b\x25\x59\xd0\x65\xb0\x46\x69\x00\x7f\x65\x49\x15\x7c\xfa\xa6\xcf\x5c\xd0\x73\xb4\x24\x92\xac\xe2\x4f\x05\x7f\x01\x7a\x11\x93\x63\x39\xb6\x92\xbd\x6f\xc1\x05\x0c\xa5\x55\x01\xbf\x96\x4c\x17\xbd\x0a\x5e\x44\x15\xbc\x20\x0b\x43\xf6\x56\xea\x59\x0e\x20\x4b\xb5\xc6\x95\x86\xfc\x1c\x6f\x31\x26\x4d\x84\x85\x0c\x38\x5b\x80\xba\x66\x71\x1e\x7e\x45\xb6\x9b\x07\x36\x69\x8b\xee\xd6\xe9\x60\x82\xa3\x21\x81\x6a\xba\xb0\x92\x7c\x8d\x7b\x76\xa1\x07\x53\xdc\x62\xa6\x2d\xa9\x1b\xb0\x2b\x5a\x91\x0b\x5a\xd1\x09\x71\xb2\xe3\x95\x3b\xb0\x40\xc1\xf4\x7d\x95\xe7\xa3\xab\xf1\x52\x0a\x3e\xbb\xb8\x73\x27\xca\x80\xaf\x57\x6e\x0c\x5f\xcc\xd1\x19\x5d\x39\x57\x79\x5c\x9c\xd1\x55\x32\x86\x4f\x60\x0c\xaf\xc8\x95\x75\xd3\x24\x4d\x3c\x8c\x4f\xc2\x30\x5e\xe5\x39\x5a\xd1\xb3\x68\x18\xaf\xc2\x30\x3e\xe9\x0e\xe3\x15\x26\x15\x65\xe8\x84\x54\xe4\x02\xb7\xc7\x38\x0b\x7a\x52\x84\x09\x44\x4f\xc8\x92\x9e\x90\x15\x3d\x33\xc3\xd8\xb6\x21\x1e\xc0\x2b\x4c\x16\x51\x4d\x56\x6e\x00\xdf\xd0\x5a\x11\xbc\x3e\xcd\x40\x6e\xdb\x62\x11\x1e\x18\xba\xea\x55\xe5\x2a\xaa\xca\x15\x59\xd2\xab\x30\x54\x16\x30\x96\x57\x30\x96\x57\xf8\xeb\x5f\x3c\x47\x2b\x22\xc9\x45\xe7\xab\xed\xb0\xbe\x8a\xc9\xb3\xea\x0c\xeb\x2b\x18\xd6\x17\xc5\x95\x1d\xd6\x7f\xb7\xae\x50\xe2\xb7\x0d\xeb\x85\x67\x9b\x91\xda\x5d\x11\x66\xf8\xa5\xe5\x95\xb7\x69\xd9\xf2\x9c\x85\x15\x22\xf4\x3b\x83\x08\x5b\x0d\x60\x9d\xb1\xce\x7a\xe1\xb1\x06\x6f\x2b\xd4\x74\xef\x02\xbb\xf5\x8b\xf5\xd7\x2f\x07\xc2\xb0\xb0\x1f\x22\x4d\x0b\x8c\xd2\x58\x8f\x8f\xc6\xad\xf0\x0b\xb8\xbb\x47\x3d\x4a\x86\x8d\x28\xec\xeb\x8b\xaf\x4d\x53\x1b\x4f\x41\x4c\x60\xe3\xd0\x90\x5e\x95\x23\xe9\x8a\x53\x15\x0e\x71\x43\xb8\xe2\xa6\xb3\x11\xb1\x9f\xf8\x4a\xf1\xb1\xa4\xd8\x10\x96\xec\x27\xe2\xaf\x40\x21\x7e\x7a\x69\xb8\x21\x0d\x0d\xc5\x6e\xdb\xf6\xc0\xce\xe7\x9f\x35\xea\xd6\xdf\xcb\x8a\x35\x01\x7a\x75\x9a\x63\xe4\xf2\xda\x08\xb7\xb6\x20\x9b\xc7\x57\x32\x11\x6e\x93\x2a\x1b\xf1\x9e\xd4\x71\x49\x75\x58\x7f\x2b\xc4\x83\x0c\xe0\xfa\xaa\x71\x83\xa2\xdd\xb1\xdb\x73\x44\xdb\x4f\x16\xbc\x72\x1f\x04\x03\xf0\x93\xb9\x11\x99\x0c\xa8\x9b\xa4\xa4\x99\xd3\xad\x10\xe4\x4e\x93\x6c\xaf\xa8\x4e\xaf\x28\xc2\x6e\xdc\x0c\x75\x3b\x43\xc5\x9d\x91\xea\x1c\xb6\x48\x19\x81\x9e\xa5\x14\x6b\xcb\x89\x09\xb4\x1d\x12\x07\xd9\x80\x38\xc8\x3c\xf7\x63\x34\xcb\xee\xb0\x08\x2c\xf0\xd0\x13\x6c\x8e\x6e\x68\x54\xbf\xaf\x6d\x0b\x4c\x86\xbf\x6e\xa9\x28\x26\x95\x03\x13\x7b\xca\x10\x0b\x62\xd8\x2a\xb0\x06\xf3\xe8\xd7\xe8\xc9\x45\xf2\x64\x91\xe7\xef\xdc\x49\x5f\x30\x58\x65\x79\x3e\x6a\xfc\xa4\xe6\x89\x25\x85\xb5\x40\xd8\x2d\x9c\xa5\x83\x4d\x75\xc9\xd3\x83\xa2\xbb\x26\xee\x92\xbf\x50\x0b\xf7\x1f\xce\xc6\xb2\x56\x03\x67\x1b\x69\x0f\x97\xff\x60\xf4\x31\x43\xa3\x09\x26\x6f\xec\xd5\x14\x93\xb7\x8c\x5e\x6f\xc9\x6b\x46\x6b\x89\xde\x32\x4c\xde\x87\xab\x9f\xfd\x55\xab\x96\xfd\xc8\x7c\x40\x41\x4a\xe9\x5b\xd6\x5d\xa2\xef\xed\xb7\x8e\x1a\x91\x0e\xe7\x15\x4b\x1c\x5c\x17\x12\xfd\xcc\x9c\x77\xca\x7b\xe6\x5c\x2b\x5e\x33\x62\xbe\xc9\xa3\x38\x15\xde\x64\x3c\x10\x41\x53\xa4\x69\x1b\x77\xa0\x85\x08\x1a\x0b\xb6\xe2\x10\x58\xf3\xc3\xdb\xe7\xc5\xda\x2e\x1c\x24\xcb\x70\x07\x63\x51\xd3\x35\x47\x9a\x22\x4e\xc1\x89\x71\x1e\xc7\xc0\x28\x34\x4e\x8a\xf1\x11\xe6\xad\xd7\x19\x00\xa8\x6c\x1b\x53\x4f\x5f\xdd\x78\xb7\xfe\x9c\x59\xef\x1d\xf3\xb4\x31\xad\x82\x9f\x9f\x59\xec\x90\x0e\xa4\xfb\xc8\xd0\xcf\x2c\x78\x90\xcc\xac\x12\xf7\x23\x43\xaf\xdb\x44\x22\xa0\x96\xce\x8c\x18\xcf\xb4\x33\xc9\xed\x50\x4b\xc4\x5a\xcb\x97\x50\xf8\xfb\x50\x88\x33\xa2\x4c\x6a\x64\x55\xee\x5f\xa0\x53\x27\x51\x9f\x3e\x61\xde\xb3\xd4\xb9\xc0\x45\x3a\xc0\x6b\x1f\xb4\x5e\xdb\x41\xea\xac\xcb\xd3\x03\x80\xc8\x24\x42\xb4\x06\x53\xa0\x69\x5f\x72\x17\xa8\x7e\x89\x5b\x2f\x50\xf0\x14\x6d\xdd\x43\x2d\xbe\x43\x1b\x84\xca\xaf\x24\xd3\x07\xfe\xbb\xc9\x61\xa8\xff\x34\x1c\xfa\x8c\x15\xbf\xe0\xac\x7a\xad\x96\x4e\x9f\x3f\x19\x51\x74\xb8\x9f\x3b\x3d\xdd\x40\xa9\x22\xf1\xa1\xc4\xd7\xee\xc2\xcf\x78\x0d\x9a\x4c\x48\x0a\x18\x87\x5b\xf0\xcd\xa4\xd4\xa1\x0a\xb5\xea\x56\xa8\x9f\x97\x13\x63\x7b\x1a\xed\x8a\xdb\x6c\xfc\x55\xcf\xef\x5e\x87\x4c\xdb\x50\x46\xa8\x84\xbb\x88\xb5\xaa\x3d\xef\xd7\x67\xce\xd6\xfa\x7b\xf7\xfb\x67\x6a\xf0\xfb\x6b\x62\xd3\xf9\x67\x8d\x0e\x48\xb0\x7b\x21\x13\x3c\x13\xc9\x3a\x9d\x3d\x79\xfa\xf2\xe9\xfb\xa7\x4f\x32\xe2\xb4\x0a\x71\x42\x7c\xb8\x1c\xeb\x6f\xbc\x8a\x3a\xd8\xd2\x44\x4a\xed\x39\x8a\xef\x52\xd5\x38\xef\xa8\xc6\x79\xa2\x1a\x4f\x9f\x46\x8e\xeb\x29\x13\x89\xb9\xe6\x41\x11\xfb\x2d\x76\x0e\x5f\x90\xa6\x60\x11\x1e\xb9\x62\x8b\x14\xfc\x28\x3c\xed\x23\x33\x39\xb4\x0b\xec\xc2\x9f\xb7\x74\x18\x4d\xdc\xaa\x7e\x58\xf4\x3e\x97\xb9\x98\x5f\xd6\x10\xca\x1d\x4e\xee\x25\x75\xb8\xb5\xdc\x5b\xe2\xfc\x7d\xf0\xfc\xf7\x4f\xe6\x4f\x80\xbe\x67\xd6\xc9\xd8\xcf\x4d\x38\x9c\x71\xc4\xb2\x87\x05\x48\xd3\xbf\x14\x12\x89\xaf\x38\xde\x6c\x42\xa6\x60\x45\xee\x8c\xee\xa6\x93\xdd\x83\xdc\x1f\xd5\xed\xda\x81\x65\xad\x4f\x9f\x31\xca\xf1\xec\x57\x86\x9e\x19\xfe\xb3\x35\xb7\x66\xfc\xfd\xa5\x90\x8e\xa2\x32\x61\xef\x5d\x70\x5b\x79\xe6\xdd\xd8\x59\x28\x30\xa1\xd6\xd1\x20\xb8\x44\x44\x70\x14\x91\xdb\x70\xec\x4d\x6c\x03\x43\xb9\xd7\xa0\xe8\xd6\xed\x27\x2c\x59\x23\x4a\x9f\xb1\x36\xf0\x14\xb8\xdf\x04\x81\x02\x2a\x00\x75\x9b\x10\x67\xdb\xaa\xfd\x80\x2a\x4f\x51\xa8\xc0\x66\x93\x9d\x73\xb6\xf4\x48\xbb\x27\x72\x79\xe5\xae\x47\xdf\x29\xab\x8b\x8c\x19\x14\x76\xf6\x65\xdf\xb3\x99\x9e\x61\x37\x29\x89\xb6\x24\x8b\x3b\xc4\x7c\xc4\xd6\x01\xf8\x2d\x0f\x32\xfa\x08\x05\xdb\x10\xd4\x3f\x7b\x85\xd8\x9f\x9e\xc7\x5a\x94\xbc\xde\x49\xda\x3d\x0c\xc6\x9c\x9e\xb8\xd1\x57\xc9\xdf\x71\xeb\x77\xfe\xf9\x91\x0f\xff\xb5\xed\xfb\x14\x85\x20\xc8\x87\xc1\xb1\xff\xbb\xcc\xae\x0c\x86\xe1\xfb\xab\x39\x5c\x6d\x36\xde\xd7\x3f\x2a\x61\xeb\x38\x9a\xdb\x53\x7c\xcf\xe8\x33\x36\x87\xcf\xb4\xa2\x6d\xfc\x41\xab\xd6\x74\xdd\x1a\x79\x64\xfe\x65\xd6\x64\x78\x3b\x62\x90\x36\xb6\x22\x03\x34\xc9\xe0\x8c\xc5\x92\x90\x54\x93\x19\x7f\xf8\x13\x8b\x9d\xaa\x7e\x62\x47\xfc\x78\xfc\xf1\x52\xaa\x4f\xcf\xc5\x1b\x87\xb1\xff\x4f\xae\xea\x52\x0a\x17\xc5\xd6\x2a\xcb\xc2\x6b\x74\x62\xbd\xa1\x58\xc7\x1b\xea\x49\x59\xaf\x99\x5e\x9c\x73\x45\x7e\xef\x3e\x8b\x3c\xa5\xc8\x6f\x8c\x4e\xc8\x0b\x57\x71\x5e\x3a\x17\x25\xf7\x2b\x4a\x33\x81\x54\x99\xf0\x7b\x59\x22\xef\xc1\x15\x7a\x7e\x77\x1a\xcb\x08\xac\x4c\xdc\x0c\xd2\xa8\x70\x29\x16\xbd\x0e\x28\x27\x1d\x5c\x7a\x33\x1e\x6d\x34\x37\x08\xe5\x76\x7b\x1c\xb7\xb2\x8c\xcd\xc7\xe0\xc3\xbf\x31\xca\x4c\xbb\x34\xd1\x03\xe6\x4f\x1d\x47\x10\x97\x64\xad\x3e\x27\xe4\x87\x56\xba\x11\x21\xe6\x9d\xbf\x4a\x4b\x9b\x7f\x2c\x8b\x57\x25\xe1\x60\x13\x29\x31\x51\x25\xbe\x66\x74\x32\x5b\x4a\xd8\x69\x01\xfd\x46\x68\xf7\xe0\x1f\xac\x37\x5b\x26\x53\x8c\x67\xec\x0e\x9d\x1a\x72\x07\xca\xf7\xeb\x15\xd5\xe6\x79\xfb\x25\xe7\x3f\xa0\x4a\xd8\xd2\x44\x79\x7e\x2e\x89\xf6\xd3\x98\x97\xad\x1b\x94\x35\xc6\xb5\xfd\x6d\x3f\xe8\x7b\xdd\xf6\xb2\xee\xd5\x6f\x32\x28\x62\x57\x25\xf2\xae\x87\xd7\x09\x29\xac\xb9\x58\xeb\x97\x10\x6e\xa1\x2d\xf6\xf6\xaf\xf6\x32\xf2\x96\xe8\x9c\x6f\x95\xf3\x17\xac\xd3\x67\xa6\xc2\x85\x2e\xa9\xb6\xad\xa0\x9c\xe8\x32\x3a\x15\x2d\x51\x02\x3b\x54\xfa\x0a\xbe\x60\x91\x69\x7e\x60\x6e\x7c\xde\xe9\x44\x5b\x0d\xbb\x94\x78\x42\x39\xbe\x7c\x73\x9d\x0a\x57\x97\x48\x26\xd5\xd8\x54\xd1\xcc\x22\x6e\x71\x12\x63\x28\xa4\x2e\xaf\x34\xd4\xed\x91\x10\x99\x77\x71\xc7\xe8\x29\xf2\x48\x2a\x23\xa3\xfe\x96\xb4\x2e\xd9\xba\xd1\xfc\xe5\x93\xe0\x62\xc0\x80\xfb\x9b\xe8\x1b\xdc\x19\x23\x32\x37\x65\x02\xe8\x33\x60\x59\x32\xd7\x88\xe3\x22\x3a\xaf\x5e\x94\xad\x01\x89\xe9\x25\x62\x44\x4e\xa8\x58\xa4\x4c\x14\x3d\xda\x98\x99\x61\xbd\x46\xde\x72\xb1\xe4\x8a\x2f\xdf\xf2\x65\xb3\xe0\x8a\x72\x0f\x07\x51\x82\xad\x74\xdb\x6c\x46\xc5\x80\xc3\x07\x8b\xad\x7a\xa4\x47\x83\x92\xb6\xe3\xec\x8f\xf3\xb3\x21\xce\xdd\xa6\xda\x46\xa5\x52\x00\xd0\x4a\x0d\xcd\x93\xf2\xa4\x2b\x0b\xd4\x11\xa1\x6b\x66\x16\xff\xbb\xa2\xcc\x43\xc2\xca\x99\x73\x3c\x5a\xd0\xc6\xfa\x5d\x94\xa7\x08\xfd\xc6\xf2\x05\x06\x85\x99\x08\xf0\x53\xa8\x76\x4a\x4d\xeb\xad\x57\x4c\x08\x03\x52\x16\xcd\xd8\x5e\x10\xce\xce\xb8\x72\xf4\x28\x9a\x71\x7c\x6b\x9f\xd9\xb1\xe2\x9e\xd8\xb1\x12\x79\x5b\x10\x45\xd3\x97\x60\x7f\x1a\xe7\x2e\x38\x52\xc4\x7f\xce\x45\x84\xb5\x9a\x70\x5b\xa5\xc5\x7f\xb8\x4a\x7e\x87\x53\xcf\x51\x45\x6b\xba\x24\x8c\x2a\x5c\x04\x3a\x2c\xc9\x0b\x66\x59\xf3\x86\x2e\xc0\x42\x7f\xb1\x6d\x9c\x9f\x4e\xea\x45\xd5\xe4\x79\x03\xfd\xd2\x96\xc8\xa8\x2a\x5c\x39\x15\x69\x14\x52\xdd\xe5\x00\x6f\x36\xde\x01\xb4\xbb\x50\x98\xbc\xad\x61\x3a\x73\x77\x76\x60\xd4\x24\x1d\x9f\xee\x0d\x37\x6d\x8e\x3a\x45\x11\x31\x5e\xba\xf5\xf8\x38\x3a\xe3\xff\x9f\x9a\x1c\xed\xd7\x88\x6c\xa7\x05\x58\x24\xdf\xb4\x9d\x96\xf8\x5a\xf4\x5d\xa2\x2a\xea\x07\xb8\x19\xbf\x8c\x72\xc4\x48\xe5\x07\x06\x04\x4b\x89\x3a\xc1\x16\x33\x6b\x14\x62\x7f\x83\xc8\x2c\xb0\xa5\x96\xba\x60\xfe\x12\x51\x1e\x0f\x12\x9b\x79\x62\x33\xa2\x22\xaa\x9e\x96\xa9\x3d\xb6\x1e\x7f\x3c\xe3\xda\xc9\x50\x33\x45\x8d\x38\xfc\xb1\x96\x8d\x5a\x70\x6f\x48\xa7\x6f\x97\xb8\x62\x32\xcd\x0d\x4f\xa0\x54\x15\x56\x42\x6e\x00\x93\xe1\x2d\x67\xd6\x7f\x99\x20\x4e\xcd\xac\xb6\x1e\x08\x10\x12\xf5\x2b\xc2\x9c\x22\x3f\x31\xeb\xb8\xa3\x01\x5e\xaf\x3d\x73\x89\x6a\x69\x47\x40\x9b\x91\x84\xc1\x70\x30\x89\xe5\xae\x75\xd9\x35\x33\x78\x5f\x45\x43\xa9\xe7\x29\xbc\xef\x2d\x0f\x59\x4a\x25\x38\xf7\x68\xbf\x4f\x6a\xda\xca\x17\xa4\xa1\xf5\xb8\x71\x5d\x93\xc4\x4a\xf0\xe7\x19\x25\x92\x16\xbb\x00\x63\xb2\xa0\xcd\xd1\xf4\x98\x2c\x69\x73\x34\x39\x9e\x35\x54\x97\x33\xeb\x14\xd7\x35\xec\x5d\xd3\x53\xb0\x26\x24\xe7\x74\x1d\x5b\xd2\x92\x15\x3d\x1d\xdb\x7a\xcc\x4e\xcd\x65\x73\x52\x2f\x54\x79\x62\x87\xfa\x05\x7d\xc1\x5a\xd7\xe4\x74\x60\x5d\x9b\xe2\x8a\x35\xb1\x2f\x17\x9a\x84\x57\x0b\xb5\x25\xd0\x06\xbb\xf5\x4f\x1a\x91\x7c\x9c\x0a\xb2\x1e\xd7\xd1\xfd\xc2\x01\x26\xc4\xd4\x99\x39\x49\xb5\x22\x1c\xe3\x6b\x23\x9e\x45\x94\x6b\x14\x5a\x12\x18\xfe\x0b\xb3\xe1\xe2\x74\x51\xa3\x0b\x4c\x64\x6f\xe4\x6c\x28\xcf\xa5\x9f\x80\x90\x62\x72\xf7\xf3\x11\x39\xe6\x42\x33\x71\x56\xf1\xf0\x62\x10\xa9\x15\x6d\x9f\x42\xa4\x1c\x62\x24\x91\xc9\xc3\x36\x0e\xc8\xde\xf4\xee\x77\x1a\x95\x98\x34\x74\xfa\xf0\x61\x3d\x53\x47\xf5\xf1\x86\x72\x52\xe6\xf4\x5f\xcd\x76\xbb\xc5\xe4\x48\x10\x4d\xd4\x31\xbe\x91\x42\x1e\xf1\xa8\x6d\x26\xe9\x46\xcc\xe0\x9d\x3e\x14\x34\x21\x23\xa0\x4d\x08\xc4\x23\x42\x79\x03\x58\x20\xcf\x6c\x88\x3c\xaa\x43\x9e\x28\xcc\x6e\x52\x3d\x17\x76\x09\x30\xef\x31\x36\x0d\xb2\xcd\x69\x14\x3a\x07\x04\xdf\x46\xa1\x15\xd1\xf6\xe2\xd4\x06\x2f\x45\x9c\x26\x6e\xe5\xc4\xb3\xcf\xd6\x1b\xbd\xc3\x6a\x8b\xa6\x24\x3d\x8e\x54\x2c\xb7\x38\x70\x5e\xba\xa0\xef\xcb\x28\xc2\xce\x0b\x50\xa8\x36\x96\xbf\x53\x4e\x9a\x68\x31\x71\xf6\x10\x61\xe6\x90\xa6\x33\x96\x9b\x88\x1b\x2e\x31\x59\x46\xa6\x2e\x65\x07\x42\x64\x5d\x22\x58\x4b\xba\xf8\x21\xab\x68\xb1\x31\x22\xfc\xec\x46\x29\x8e\x43\x9c\x67\x8e\x70\x9f\x59\xc7\x5c\x99\x13\x00\x40\x72\x2b\xd6\x7f\x86\x80\x3c\x26\xe0\x00\xf9\x7a\xeb\x2a\x8f\x18\xff\x45\xd9\xb3\x01\xe4\xf4\x5a\xb3\xb3\x82\x93\x85\xe2\x20\xb2\x93\x25\xaf\xb5\x92\x57\x85\x20\x4b\xbe\xae\x0b\x35\x20\x1f\x23\x6d\xf6\x0d\xb1\xc3\xee\x1c\x81\x34\xe6\x75\x85\x2e\x7b\x9a\x09\x36\x9a\x91\x3e\xd1\x79\x3f\x3b\x1c\x5f\xab\xa5\x8e\x33\xe0\xf9\x60\xf6\x02\xa9\x8e\x2f\x3d\x27\xee\x99\xea\x7c\x00\xc7\xc6\xab\x67\x65\x82\x4c\x15\x41\xc1\x11\xd3\xdb\x9d\x7e\x8c\x5e\xbc\x2a\xdb\x39\x5d\xf7\x72\x46\x6e\x4e\xbd\xb5\x05\x46\xd1\x0b\xe6\x0d\xed\xb9\xe1\x6a\xc9\x57\x2e\x4a\x34\xdd\x98\x57\x1c\xdc\x65\x38\x94\x52\x56\x29\x19\xdb\x6f\x5e\xf6\x8a\xaf\x61\x90\xd2\xde\x4b\x6e\xc1\x6a\x43\xd1\x85\x0d\x2e\x76\xae\xfd\xbc\xec\x8b\x39\x8c\x96\x63\xd7\xf7\xd1\x51\x1e\x2b\x91\x22\xe6\xc1\xba\x55\xe0\x43\xc1\x17\x25\x18\x03\x33\xa2\xf0\xf6\x9b\x9a\xc8\x52\x9c\xb0\x64\xa7\x64\x68\x77\x30\x3d\x24\xfb\x24\x35\xbc\x7c\x9a\xe6\xba\x1c\xce\xf5\xa9\x97\x6b\x9f\xec\x76\xf2\xbc\xfb\xfa\xce\xcc\x4e\x69\x62\x36\x68\x24\x66\x97\x16\xa4\x66\x6b\x87\xe9\x88\xb6\x19\x83\x42\x81\x27\xf9\x13\xcd\xc8\xd6\x87\xe5\x8a\xac\xda\xbb\x0c\x49\xb8\x6d\xb7\x98\x0b\x1f\x96\xf1\x88\x1f\xdb\xef\x11\xd7\x9a\x77\x65\x12\x8b\x8c\xe3\x84\x75\xfd\x61\x86\x68\x7b\xfb\xa6\x8c\xcf\x1b\x60\x98\xe8\x76\x98\x68\xa7\xf0\x0e\xa2\x70\x3a\x14\x52\x15\x7a\x6b\xb9\xa7\x61\x30\x68\xa2\x8e\xa6\xc7\x78\xae\x8e\x26\xc7\x05\xea\xbc\x4b\x8f\x38\xd1\xc7\x84\x47\x35\x7b\xfb\x7f\xab\x2a\xb6\x4f\xbe\x5e\xa1\xd7\x49\x85\x3e\x48\x84\x01\xcd\xe9\xfe\x3f\xc4\xfc\xc1\xfd\x42\x24\x2b\x35\x07\xbc\x26\x8c\x89\xc9\x71\xef\xa1\x98\x3f\xb8\xd7\xc9\x61\x4b\xf9\x9d\x8d\xb5\x62\xc2\x62\x76\xcf\x92\x3b\x3a\x85\xb5\x9c\xc3\xf1\xae\x46\x6d\x40\xad\x34\x97\xd8\x26\x80\xd9\xef\x3b\x12\x7a\xc7\xc3\xd5\x6e\x32\xa5\xdf\x64\x76\x76\x97\x56\x4f\xd9\xee\x29\x3b\xba\x24\x52\x52\xdd\xd5\x03\x50\x4a\xcb\xb9\xdb\xde\xb3\x02\x79\x28\x0e\xcb\x65\x9d\xc2\x83\x99\x11\xef\xf7\x3f\xcc\xc8\x4d\x11\x1a\x2a\xa7\x94\xbe\x60\x01\x05\xb5\xcc\xf3\x12\x52\xb0\x2a\xa9\x30\xdb\x9a\xa0\xed\x49\x7d\x9c\xfd\xc7\x37\x1b\x93\x6e\x01\x17\x22\x64\x22\x54\xba\x15\xa1\xb3\x36\x62\xec\xe1\xb8\xaa\x4e\x06\xbb\xe8\xd5\xb4\x44\x15\x11\x20\x79\xb2\x74\x2b\x5f\x12\x16\xed\xb1\x69\x6d\xc4\x1e\x80\x97\x76\x07\x80\x41\x68\xda\xb6\xbe\xc0\xa0\x3f\xfe\xb9\x34\x02\x33\xf3\x8e\x95\x45\xc9\x48\x53\x07\x18\xbe\x42\x96\x70\xeb\x1e\xda\x3b\xb7\x18\xda\x9b\xe7\xab\x35\x57\x4c\x97\x17\xfc\x47\x26\x96\x15\x77\xc9\x2f\xd9\x95\x6c\x74\x92\xf3\x15\x5f\x49\x77\xe9\xfb\xd4\xdf\x9d\xba\x2b\xdb\xb3\xf6\xfa\x09\x3f\x69\xce\x00\x6c\x28\x24\x9c\x72\xa5\xf8\x32\x4e\x7b\x1f\xc6\x9a\xff\x88\x95\x1f\xdf\x59\xd9\xdf\xa6\xbd\x5e\xb3\xbf\x1a\xfe\x7c\xc9\x85\x2e\x4f\x4b\xf7\x59\x8f\xaa\x57\xd6\x3f\xf3\xcb\xb7\xdc\x30\xa8\xb2\xe2\xaa\x18\x4d\xb7\xe4\xe3\xed\x34\x49\xfd\xa5\xbd\x8d\x49\x7f\xb1\x3d\xe2\xa4\xc7\x12\x8e\x09\xdf\xc6\x14\xb5\x45\x3b\x3a\x7d\x1e\xa6\x68\xd7\x65\xfc\x5b\xf8\xeb\xc9\x2d\xfc\xb5\xd7\x3f\x83\x0d\x3a\x89\xd6\x9b\xd0\x7d\x69\x4e\xcb\x26\x22\xa1\x72\x67\x80\x09\x92\x5b\x59\xd8\x36\x1e\x0e\xdd\x86\x5a\x2e\x31\x54\xfe\x88\x9a\x66\x23\x8d\x0b\x4d\x54\x57\x7b\x13\xc9\xaa\xda\xca\xaa\xea\xdf\x94\x55\xf9\x80\xa8\xaa\xbf\x26\xaa\xaa\xbe\xa8\xea\x47\xf9\x59\x34\xca\x57\xdd\x51\xfe\xc7\xc0\x28\xef\x7b\xe3\x81\x38\x4f\x04\xd5\x47\x93\x63\xa2\xa8\x3e\x9a\x06\x2c\xda\xcf\x65\x2f\x84\xa1\xfe\x06\x26\x0e\xd8\xcc\xc3\xfc\x5b\xc3\xc6\x90\x1f\x63\x22\xb6\x9d\xe9\xd6\xdb\xf9\xad\x4a\xbb\x18\x50\x6e\x76\xfc\xae\x4a\x46\x3a\xa5\xaf\x63\x22\x71\xb3\xb8\x99\x42\x89\xb6\x74\x49\x67\xec\xd7\x87\x40\xb7\xbb\xed\x76\xff\x3a\xda\x76\x9a\x2d\x7f\x74\x67\x97\x07\xa7\x0d\xe0\x91\x36\x40\x6c\xc9\xda\xc8\x81\x6e\xc7\x34\xc8\x2a\xa2\x66\x46\x47\xe2\x10\x35\x32\xf5\x95\x74\x80\x5d\xde\x78\xb2\x78\x44\xbc\xdf\x60\xc1\x09\x18\xa4\xbe\x3e\x2d\x78\x27\xca\xa4\xdb\xb3\x6e\x36\x08\x82\x3e\x0b\x94\xa9\x22\xbb\x83\x7e\x51\x77\xee\xa4\x28\xe3\x38\x56\xfd\x1c\x60\x58\xbd\x85\x21\xb9\xc6\xd1\x00\xb0\x31\x4b\x5f\x30\x30\x32\xc3\x79\x8e\x5a\x09\xd6\x08\x98\x17\x25\x3a\x48\x96\xf9\x5b\xbe\xb7\xf5\xa6\x64\xce\xe1\x85\x04\x9c\x43\xf3\x51\x7a\xe3\x7b\x44\x6f\x6f\xe7\xad\xaf\x6e\xe7\xad\x6f\xca\x1b\xb9\xe3\xd3\x61\xee\xf8\xb8\xbf\xde\x7c\x6a\xd7\x9b\xb7\xc9\x7a\xb3\x08\xeb\xcd\x55\x34\x13\xfb\x3a\x8e\x45\x89\x9a\xd2\x8e\x88\xbf\x3d\x41\xed\xbb\xc3\x33\xf4\xe9\xff\xea\x0c\xb5\x35\x6b\x67\xe7\x91\xd9\x02\xb6\xc0\xde\x43\xd3\xf1\x7c\x78\x01\xbd\x89\x62\x47\x93\xe3\xaf\x74\xff\xf3\xff\xcd\xee\x5f\x7e\x63\xf7\x2f\xff\x1b\xdd\xbf\xfc\xff\x6c\xf7\x2f\xff\x07\xbb\x7f\xf9\x8d\xdd\xff\xa8\xec\x58\x24\xbc\xbe\x14\x5c\x91\x97\xa9\xa1\xc1\x97\x48\x27\xe0\x2c\xe5\xc2\x79\xfc\xfc\x0d\xb8\xeb\xda\x00\x3e\x0a\x17\x7f\x30\xb0\x88\x81\x4c\x1d\xd0\xee\x27\x65\xec\x0e\x66\xa3\xac\x98\x95\x3c\x68\xbe\x15\x3f\xf5\x5d\xc3\x4c\x31\x12\x13\x45\x23\x93\x02\x66\x52\x5a\x43\x80\x97\x65\xf0\xf4\xdd\xd0\x29\x71\xb5\x84\xd3\x7f\x6f\xeb\x57\x74\x40\x25\xbb\x20\x94\xf0\x72\x4e\xef\x1e\x4c\xef\x79\xb0\xa9\x9c\xfe\x4b\x12\x51\x41\x59\x32\xde\x2d\x3d\xeb\xdb\x36\x84\x33\x65\xa7\xf0\x10\xb1\x35\xda\x80\x2f\x4c\xb9\xd9\xfc\x5a\xa3\x12\x6f\x36\x41\x6c\x2a\x13\x80\xdb\x36\xc0\x03\x80\x29\x30\xc5\xa3\xac\x22\xc9\x3a\x47\x88\xc7\xae\xbb\xd6\x25\x0c\xac\x2c\xe4\x92\x3b\xdb\xe7\x53\x4b\x55\xc2\x23\x63\x47\xd7\x81\x1c\x88\x03\xd8\x45\x07\xc4\x7a\x76\xd2\x92\x7c\x6f\x1b\x59\xba\x46\x06\x93\xe2\xd2\x43\xd9\x13\xb3\xa8\xc9\x9c\x61\x88\x6a\x54\xa6\xa6\x4f\x04\x89\x60\xb8\x24\xda\x36\xe0\xb9\x28\x96\x0a\x23\x09\xc8\x3d\x1c\xea\xe5\x80\x11\xf0\xdc\x91\x9a\xe1\x22\xee\x4c\xeb\x31\x5e\x06\xbf\xe3\x5b\x9a\xd1\xf6\xd0\xf7\xc3\x3d\x64\xed\xc9\x96\x0a\x75\x0c\xb5\x06\x6a\x63\x5e\x81\xc1\x0f\xcd\x64\xb9\x6c\xcd\x49\x9d\x51\x8a\x1b\x25\x24\x54\x7b\x66\x63\xae\xee\xdd\xdf\xf7\x06\x6f\x2d\x94\xad\xa7\xde\x77\xd1\x18\x8e\xea\xfb\x67\xef\x84\x2c\x36\x20\xb4\x18\x64\xde\x89\x81\xdd\x6e\x34\x01\xe6\x5a\xe7\xe5\x72\xc9\x21\x92\x8f\x82\x41\xb0\xd9\x64\x7e\xf6\xdf\x5d\x1a\x3e\x79\xf7\xb2\xd4\xe7\xb2\xd1\x77\xcf\xcb\xa5\x35\xbc\x77\x39\xb1\x8b\x4a\xbb\x9f\xdb\xe1\x83\x71\x57\xe3\x0c\x38\x97\x2f\x2d\x6c\xed\x96\x9c\xd4\x68\x42\xfc\x91\xb4\x8f\xd3\xee\x81\x74\xf7\xf3\xd6\x79\x34\xd8\x7a\xb0\xb9\xc5\x81\xb3\xa7\x08\xa2\x10\xc1\xcc\x47\x47\xb8\xc3\x2d\x1a\xef\x7e\x4f\xe7\x1d\xd5\x80\xbb\x1a\x70\xcb\x0e\x66\xdf\x52\xd9\x81\x6a\x14\xc2\xd9\x2d\x86\x87\x48\xd1\xa4\x9a\x83\x36\x4b\xb8\x50\x54\xd8\x52\x55\x10\x83\x1d\xf7\x91\x44\x04\xee\xd3\x76\xf4\xaf\x89\x36\xc8\x32\xba\xc0\x3c\x5a\x5f\xe0\x30\xfb\xb9\x1b\x97\xe0\x20\xdc\x62\x10\x6c\xe8\x74\xf7\x7e\x34\x7e\xbe\x2b\xfb\x61\xf3\xcf\x24\x12\x1d\x8c\x9f\xc0\x53\xe9\x85\x44\x66\xc8\x12\xcf\x5d\xc5\xdf\xe6\xae\xe2\x7f\x8a\xbb\x7e\x28\x3b\xbe\xc2\xd0\x10\xdf\xaa\xd1\x64\xf6\x59\x22\xed\xba\x0b\xcc\x9e\xcb\x53\x14\x9a\x11\x0c\xb3\x03\xd4\x55\x4b\x48\x14\x29\x90\xbc\x69\x57\x2f\xc1\x35\x73\x17\x93\x13\x8f\x3e\x41\x3e\xbb\x2b\xbb\x0c\x39\xdd\xd2\xce\x00\xd7\x8f\xbe\x4b\xaa\xae\xb9\xfa\xac\x74\x50\x4f\x95\x33\x46\x29\x3d\xe0\x12\x69\x1c\xd2\x81\x87\x73\x1a\x70\x35\x6b\x03\xd1\x36\xf3\x92\xa1\x06\x17\xd0\x85\xcd\x50\x37\x7b\xd7\x32\x71\x23\x5e\x12\x59\x0e\x86\xb9\x1a\x84\x51\x2a\x6f\x82\x51\x9a\x2d\x07\x81\x94\xca\x6f\x00\xde\x1a\x7c\xed\xc6\xfc\x9b\x0d\x58\x32\xa8\xcd\xc6\x06\x71\xce\xf3\x4b\xd3\x23\x66\x69\x6a\x30\x69\xf1\x68\x4f\xfb\xd6\x14\x0e\xb5\xe8\x94\xac\xc1\x33\x9a\x94\xa6\x0f\xeb\x6e\x3e\xe2\x8a\x37\xd3\xac\xde\x6c\xda\x30\x1f\x9b\x4d\xc5\xe6\x03\xe8\xa6\x3b\x0b\x0b\x63\x65\x86\xc5\xc2\x0c\x91\x5e\x91\x10\xb2\xb9\x62\x9b\xcd\x95\xcd\x65\x96\xe4\x53\x70\x94\xc5\x73\xf4\x77\x08\x77\x33\x02\x55\x39\x8c\x40\x35\xd8\x85\x43\x45\x0e\xa5\x0e\xe3\x4e\xdd\x5a\xb3\x5b\x1e\x22\x7c\x43\x71\x43\xf8\x50\xba\xc5\x87\xc2\xc5\x57\x5a\x31\xfc\x1a\xe9\xcc\x38\xda\x33\x2d\xa2\x35\x04\x96\x74\x0f\xfd\xe8\xa8\x49\x98\x8a\xb4\x21\x8a\x56\xff\xee\xf7\x15\x1d\x4d\x2d\x67\xba\x4e\x99\x81\x03\x3f\xef\x33\x05\xd2\x50\xed\xfd\x16\x13\x18\x97\x79\x55\xfc\x2e\x3d\xce\x46\xd5\xd6\xba\x21\xcb\xae\x74\x70\x1a\x71\x92\xba\xc7\x39\x50\x9d\x32\x97\x56\xd9\x5d\x1b\x46\x52\x3b\x46\x52\xdf\xcc\x48\xd6\xb7\x30\x92\x19\x5a\x0c\x71\x92\xf5\xdf\xe3\x24\xf8\xff\x2e\x23\x59\xba\x99\x1e\x33\x92\xda\x31\x12\xd2\x63\x22\x64\x90\x89\xcc\x2c\x3c\x72\x97\xe1\x44\xc5\x9f\x7f\x13\x23\x59\xb7\x8c\x64\x6d\x18\x49\xaf\x48\x4c\x50\x13\x33\x92\x06\x18\xc9\x39\xa9\x0d\x23\x59\xfc\x0d\xc2\x59\x52\x7f\x0b\xc9\x3c\x4a\xde\x37\xb0\x12\x5f\xe8\x60\x32\x52\x50\xcf\x6f\xe7\x28\x6d\x69\x37\x3f\x75\x85\x7e\x03\x63\xf1\xa5\x25\x53\xf4\xef\x0c\xcb\xf8\xd5\xdd\x83\xc3\x94\x2d\x0d\x11\x2f\x7c\x74\xb3\x49\x0d\xd3\xdd\x68\x3d\xed\x5b\xab\x6f\x36\x37\x54\x6f\xf4\xd5\xea\xfd\x7b\x1f\x31\x0d\xf9\x06\x46\x79\x3e\xc4\x28\xcf\x23\x46\x59\x13\x45\x9b\xff\xff\x50\xc4\xb2\x6e\xef\x0f\x94\xca\xc2\x91\xa7\x52\x67\x5f\xe9\xc4\x79\x87\x86\xdf\xf1\x3f\xb4\xa1\xbf\xf2\x7c\x54\xfa\x3d\x90\xcc\xf3\xa7\x00\xfc\x44\x46\x53\x1c\x6d\x1c\x55\xb2\x58\x3c\x2a\xdb\x48\x7e\xce\xe6\xb3\x1c\x9c\xb6\x83\x6c\x19\xb4\xd1\xce\x30\xc3\xa9\x55\xa2\x53\x9a\x56\x8c\x6f\xe5\x62\x10\xef\xed\x1e\x3a\xd5\xd9\x00\xda\x77\x10\xf2\xed\x43\x7b\x22\x43\x18\xc6\x85\xdb\x08\xb8\x3c\xdd\xa3\x1e\x0b\x24\x19\xb5\x78\x32\xb0\x1d\xfa\x31\x32\x81\x4a\x62\x3a\xfa\x15\xce\x29\x1c\xe7\x27\x12\x4d\x48\x37\xb5\x97\x60\x7d\x3b\x5d\x48\xba\x22\x5c\xe6\xb9\x7b\xdd\xaf\x92\x86\xfa\xd6\x2f\x39\x75\xa1\xb7\x5e\xb2\x7f\x95\xe4\xa7\x92\xfc\x52\x92\x1f\x4a\x7a\xdd\x71\xb0\x22\x8a\x6b\x75\xf5\x12\xcc\xc0\x23\xb0\xe4\xdf\xd3\xfd\x3b\x91\xdd\x35\x9a\xd1\x2f\xad\xbd\x26\xe8\xd4\x1c\x8a\x95\xea\x8e\x1a\xbc\xd9\x20\x45\x51\xea\xe5\x32\xea\x0d\x60\x0c\x41\x6e\xd0\x6e\xce\x30\x26\x6a\x8e\x4a\x3a\x9a\x44\x1b\xad\xc3\x03\x6f\x3e\x42\x5b\x38\xbb\xde\x1c\x08\x47\x82\x72\x7c\xea\x14\xbd\x9b\xcd\xc8\x26\x04\x6d\x21\x33\xb9\xde\x9f\x97\xf5\xb3\x90\x05\xb1\x0d\x9d\x82\x2f\xf2\x17\x46\xa6\x39\x8b\xd0\x26\x51\x50\x52\xb5\x65\xe6\xf9\x07\x86\xb4\xb5\x9e\x8c\xd4\x18\x6d\x06\x52\xce\x11\xa7\xbf\x95\x00\x9c\xc4\xa2\x8d\xf3\xcd\xbb\x79\xb1\xed\x8d\xb9\x1f\x4a\xc2\x71\xd1\x83\x0d\x88\x9a\xc2\x3f\xaf\xf9\x42\xf3\xe5\x4b\xc9\x96\xef\xcb\x15\xff\x0f\x7d\xd5\xeb\x2f\xf6\xf6\x0e\x0e\xf6\xf7\xf7\x76\x4d\x35\x10\x12\xf4\xc7\x1a\x5d\xaf\xe4\x92\x17\xd9\x45\x59\x97\x27\x15\xcf\x88\x6f\x7e\x01\x20\x9c\x83\xc8\x65\xad\x46\x4b\x98\x15\xa7\x6b\x96\x5b\xce\x91\xa4\xe9\x61\x5c\xbc\xeb\x77\x85\x06\x2d\xdd\x8c\xd3\x32\x81\xb3\xa9\xa8\xab\x93\xd3\x11\xb5\x55\x12\xdb\xf4\xb8\x8a\x61\x40\x5e\x36\x8f\x47\x94\x96\x73\x04\xf6\x72\x76\xc3\x1f\x6b\x6a\x26\xad\x3f\x86\x5d\x4d\xda\x18\x50\xa5\x0b\x4c\xe2\x0d\xec\x50\x8a\x84\x29\xe2\xbb\xd4\x96\xae\x74\x66\x20\x11\x2e\xe6\xed\x38\x9a\x90\x41\x58\x5d\x61\x85\x03\x7b\x9b\x2b\x0b\x38\xa9\x70\x61\x41\x41\x80\xa5\x7b\x92\xfb\x15\xa0\xc5\x1c\x89\xbc\x9c\xcd\xa5\x07\x95\x51\x6d\xa7\x10\xb5\xb5\x4a\x8b\x08\xfa\xab\x1d\xc9\x02\x83\xbd\x8b\xe5\xa0\xcc\xf7\x42\x4f\xa2\xec\xeb\x92\x20\xd0\x4c\x32\xd4\x8a\xe8\x2e\xd1\x45\x6d\xcd\x32\xdc\xd2\x3f\x89\x0d\xf6\xaf\xbe\xa6\xea\x07\x23\xaf\x16\x48\xf4\x46\x4d\x8b\x47\x6d\x87\x4a\xd0\xd4\x49\xdf\x6e\x02\x04\x95\xe4\xc6\x61\x2c\xb6\x98\xd8\xd1\xa2\xc3\xd9\xa6\x70\xd3\x41\xe1\x61\x5a\x8a\x38\x04\x03\xa8\x65\xba\x00\xa8\x3c\x78\x97\xdf\xd2\xe3\xbc\x5d\x99\x44\xaf\x47\x44\x7f\x49\xb2\x9f\x8d\x35\x4d\xbf\xf5\x2c\x1c\x1d\x0a\x08\xeb\x92\x44\xdf\x38\x69\xf4\xd6\xb5\x5f\xe2\x08\x72\x1b\xb1\x74\x82\xb0\x74\x82\x68\x5c\x30\xc3\x1d\x34\x91\xc4\x9d\xe3\x12\x61\x41\x23\xa5\xc7\xd3\x23\x2c\xf6\xb6\x0f\x97\xac\x25\xa3\x5f\xa8\x29\x23\x91\xab\xfc\x0b\xa7\x61\xe4\xde\x41\x47\xcf\xfa\x21\xe5\x44\x1c\xec\xcd\xe7\xc3\x44\x32\xc4\x03\xfc\x40\x44\x28\x5e\xa5\x62\x8f\x33\xea\xec\xec\x7d\x82\x61\x57\xcf\xee\xbf\xac\xbf\x67\x8b\x4f\x97\x4c\x2d\x6b\x88\x6d\x66\x84\x92\x60\xec\x11\x6e\xdf\x69\xa6\x6c\x6c\x94\x09\x58\x77\x14\x8a\x68\x56\x56\x85\x80\x9f\x57\x86\xfe\x36\x78\x92\x3b\x4d\x64\xdb\x02\x95\xe3\xa8\x6c\xaa\x49\x39\x0e\xc5\xd9\x0e\x8f\x12\x42\xf9\x74\x42\x4a\x18\x49\x20\xda\x9a\xc2\xa9\x70\x17\xe6\x2b\x54\xba\xc7\x6e\xa0\xc5\x8a\x7a\x5d\x7d\x55\x51\x1f\xa1\x52\x10\x06\xb0\x34\x25\x28\xe5\xfd\xa9\x54\x32\x48\xed\x1a\x8e\x54\x24\x1e\x60\x8c\x15\x9d\xe6\x6a\xb3\xdb\xaa\x23\x0f\xf7\x13\xef\x45\x3b\x71\x9c\xe0\xe0\xcf\x1a\x30\x2f\xac\x97\xb7\x87\xb0\x10\x49\xf0\xef\xc8\xb3\x7c\x58\xa2\xc8\x73\x18\x3a\x4e\x97\x1f\x40\x38\xec\x2b\xdd\x47\xa1\x08\x87\xa4\xc1\x53\x24\x0d\x0e\xd0\x29\x7d\x24\x0d\xde\x46\x25\xdc\xe1\x09\x96\x06\x1f\xc4\xd2\xe0\x01\x4b\x83\xb7\x58\x1a\x6d\x01\x51\x5c\x42\xde\xc5\xd1\x08\x03\x99\xb7\x65\x6f\x55\x4e\xa7\xa6\x1e\x56\x72\x51\x1d\xde\xd5\x3b\xea\x80\x23\x05\x68\xb2\x03\x9e\x90\x16\x74\x22\x3b\x95\x0a\x46\x5c\x06\x24\x0f\xcb\x22\x91\x09\x6e\xa2\x08\x38\xca\x80\x5e\xde\xa2\x14\x07\x89\x0c\xe0\x57\xe0\xfc\x4c\x60\x88\x43\xe6\x89\xd0\x5a\xa8\x4b\x6c\x16\x7c\xff\x81\xf8\xd0\x15\xa2\x52\x88\x96\x55\x27\x0c\x16\x13\x5e\x21\x23\xe9\x9a\xc5\x8e\xb0\x64\x71\xf5\xc8\x38\xd0\x94\x13\x3f\x7b\x7c\x5b\x60\xda\x0c\x7f\xd1\x37\x4c\xce\x3a\xd0\xec\xf2\xc6\xc6\xb5\xe7\xc4\xd2\x23\xe3\x45\xcb\x8b\x8c\xb8\x99\xa0\x92\x48\xca\xb7\xb6\xde\x13\x27\x17\xdd\x56\x75\x2d\xcf\xb8\x3e\xe7\x2a\x2b\x7c\x5b\xc3\xd2\xe2\x6d\x64\x86\xde\x0d\x80\x40\x03\xbd\x1d\x9c\x6c\xbb\x3b\x15\x51\xf5\x31\xe9\xad\x82\x20\x89\xe7\xd8\x09\x79\x09\xbe\x91\x4e\x3c\x84\xb9\x2e\xf2\xf8\x90\x0b\x77\x4a\x6b\xa5\x2d\x3f\xb1\xba\x90\x4f\x7b\x2d\x62\x62\x0c\x64\x63\x7b\xce\x08\x3a\xa1\xdf\x52\x0c\x92\x68\xad\x8c\x16\xe5\xc0\x22\xda\xc9\x17\xcd\x16\x38\xc3\x0d\x1d\x04\x52\x54\xa7\x50\x1c\x95\x94\x8c\xbe\x2e\x19\x07\xf1\x48\x55\x15\x30\x09\x46\x7f\xb2\x18\x11\xcb\xf2\x61\x37\xd7\xdc\x92\x5b\x00\x22\x87\xe1\xa5\x2d\x5c\x41\x3c\x26\x63\xd0\xf2\x18\xb5\x5b\xd0\x0e\x42\xb9\xf0\x11\x13\xb9\x63\xfd\x66\xab\x9c\x56\x3f\x1e\x64\x0b\x59\x55\x6c\x5d\xf3\x65\x56\x88\x6e\x0d\xd4\x0d\xd3\x5d\x24\x35\x50\x37\x4c\x6e\x35\xd7\x11\x86\x81\x29\x38\xa9\x92\xbd\x4e\xea\x55\xa8\x94\xca\x11\xc8\xfa\xad\xeb\xd2\x2c\xa0\x3a\xb7\xb8\x39\x0e\x65\x6c\x7a\x18\xe0\xc5\x86\x50\xc7\xee\xd9\x9f\xfb\x2e\xd5\xbd\xe4\x51\xb9\xf6\x63\xfc\x9b\x59\x0c\x62\x36\x0d\x61\x9c\xcf\xbc\x16\x1b\xe7\xf9\x95\x44\xee\x9c\xd6\xc5\x7a\x73\x79\x9e\x33\x84\x3b\x01\xcd\x7f\x31\x49\x28\x51\x8c\xe0\xce\x6e\xdf\x90\x36\xa8\xa3\x54\x57\x37\xd0\x4d\x70\x5c\x31\xdd\x14\xb7\x33\x6d\xb3\x41\x3f\x9a\x4d\xea\xbc\xd5\x3d\x15\x6a\xec\xf6\xfe\x5d\x6d\x51\xdc\x88\x83\xe2\xa5\x79\xcf\x99\xae\x74\x20\xbe\x20\xe6\x84\x6e\xed\x32\xe2\x2f\xc7\x2d\xfb\xa9\x95\x44\x89\x3f\xef\x75\x41\x21\xd2\x23\xdf\x20\x06\x8c\x54\x8a\x39\xd5\x96\xd5\x0d\x35\x7f\xd8\x62\x46\x08\xe7\x2d\xcf\xbb\xa8\x63\xd0\x74\x7c\x9d\xea\xa1\x7c\xcd\x67\xde\xee\x3d\x3d\xce\xf4\xb0\xca\x47\xbf\xab\x63\xaa\x89\x3a\xfa\x4d\x1d\x9b\xad\x9f\x9b\xb6\xcb\x92\x55\xf2\x2c\x2b\x5e\x2b\x94\xd9\x20\xf1\x99\x69\x1d\xdc\x56\xb2\xe6\x59\xc0\x0f\xb4\xf3\xac\x3c\x55\x6c\xc5\x33\x18\x3e\xfe\x0c\xc3\xde\xf0\xd5\x89\x99\x7d\xe6\xcd\x4a\xb2\x65\xf7\xc5\x8b\x72\xc9\xa5\xcb\xca\x9a\x65\x29\x33\x27\x07\x4d\x66\xfc\xe1\x63\x15\x63\xb9\xbc\x56\xe8\xb1\x3a\xe2\xc7\x9d\x12\xac\x05\xaa\xfd\x02\x37\x74\xeb\xd5\x6d\x75\xe6\x3e\x50\xae\xd8\x99\xaf\x64\x55\x8a\x4f\x9d\x97\xc8\x4d\x95\x5c\x72\x33\x99\x6b\x9b\x5d\xcb\xb3\xb3\xaa\x4f\x00\xb1\x6e\x74\x56\x70\x8e\x94\xd9\xc0\x9a\x8c\xa5\xb8\x60\x55\xd9\x2b\xac\xe6\x15\x50\x47\x8d\x3f\x5e\x2a\xb6\x5e\x7b\xdf\x82\xeb\x4b\x56\xbf\x6a\x2a\x5d\xae\x2b\x5e\x8c\x46\xd5\x78\xe5\x6e\xb6\xb7\x95\x16\xc2\x71\x14\xf5\xf0\xa7\xb7\x01\x2d\x7a\xa7\x14\x3b\x9f\x38\x12\x26\x93\xdb\x50\x55\xb8\x1a\x9f\xb3\xfa\xf5\xa5\x30\xa3\x82\x2b\x7d\x85\x1a\x0c\x80\xa7\xd5\x51\x73\x4c\x32\x2f\xec\x66\x94\xd2\x66\xde\xc7\x79\x9c\xab\xb1\xa9\x00\x4c\x52\xa1\x2d\x92\x2a\xe2\xf4\xa8\x7d\x91\xb0\xe3\x01\xad\x0e\xcb\xf3\xee\x9b\x59\x76\xa7\xff\xb2\x49\x3c\xc6\x45\x3d\x54\x49\x3b\x0f\x59\x9e\x67\x52\xbc\x5b\x28\x59\x55\x50\xcb\x3c\x37\x04\xa8\x6d\x02\x51\x18\xfb\xa1\xee\x87\xb6\xeb\xa9\x1f\x90\xc2\x44\x01\xcd\x00\xba\x6b\x90\xa6\x90\x69\xc1\xd1\x70\x0f\xda\xc1\xbe\x06\xb5\x6e\x91\x4a\x27\x03\x07\x15\xd5\x58\x8a\xc7\x55\x09\xa1\x28\xd5\x58\x8a\x85\xb9\xa6\xcf\x14\xde\x2a\xda\x0d\xa4\xac\x22\x9f\xba\x58\x9f\x6e\x4f\x27\x5d\x83\x1a\xfa\x00\x90\x41\x03\x32\x19\x2b\xd8\x18\x02\xbb\x3c\x71\x30\x8b\xe0\x68\xb3\xb4\xfe\xa7\xa7\x1c\x09\x8c\x5d\xca\xdc\x10\xa8\x5c\x6b\x80\x85\x02\x0b\xb4\x66\x6c\x5d\x3a\x1d\x32\x23\xca\x96\xe5\x45\x06\x61\x3e\x04\x57\x3f\xbe\x7f\xf5\x92\x66\x0f\xed\x3b\xff\x78\xf8\x7f\xfe\xcb\x5d\x65\xc4\xca\xf0\x2b\x79\xc1\x01\x3f\x0c\xf1\x18\x4c\x0c\x17\x7d\xa0\xf8\x71\x59\xcf\xfb\x5f\x13\xe4\xba\xac\x0b\xf3\x70\x8b\x8b\x81\xda\x08\x4c\x3c\xd5\xa9\xdd\xf8\x36\x94\x13\x15\xa6\xc8\xbc\x09\x97\x74\x34\x81\x85\xf6\x0b\xa0\x28\xc2\x05\xb5\xf7\x18\xe3\xa2\x57\xf4\xcf\xef\x60\x6b\x44\xb8\x63\x84\x1c\x18\xa1\x22\x7f\x95\x0e\xef\x2b\xc2\x78\xe3\xa4\xa1\xef\xb8\x0d\xd1\x72\x1b\xa3\xe4\x09\xa3\x04\x1f\x2c\xf5\x6f\x32\xcb\xfe\xcb\x37\x30\x4c\x46\x27\x33\x16\x31\x4c\x16\x18\x26\x3b\x26\x1c\xcf\x3a\xa5\x0c\x30\xcd\x81\x7a\x7e\x1b\xe3\xe4\x31\xe3\xec\x97\x32\xc8\x3c\x07\x3e\x16\x18\x28\x20\xbb\x32\xfa\xc2\x5e\x24\xec\x8c\x27\xf3\xd0\x4f\x3d\x46\x19\x8f\x10\x6d\xd3\x49\xca\x6f\x67\xb3\x2a\x62\xb3\xcc\x86\x95\x55\xe4\x1a\x1c\x0b\xbc\x2b\xe6\xad\x75\x48\xf8\xaf\xab\x79\xc5\x6f\xab\xba\x67\x11\x8c\xaa\x2d\xb0\x63\xe6\x2d\x7e\x18\x88\xa6\x95\xe1\xd3\x0b\x6c\xf6\xb9\x5d\xb6\x57\x39\x43\xaa\x25\x5d\x1c\x55\xc7\xb3\xac\xd6\x57\x15\xcf\x20\x94\xf2\x67\xf3\xcd\x25\x2e\xb2\x25\x13\x67\x5c\xc9\xa6\xae\xae\xde\x71\xfd\xdc\x4f\x5f\x9b\xcb\x72\x15\xb4\xa4\xcb\xf9\x72\xfc\xf1\xe3\xb9\x5e\x55\xae\x95\x38\xcf\x2f\x7c\x11\x31\xd7\xaf\xfa\x5c\x7f\x39\x4f\xa3\x40\x89\xcd\x26\xcb\x20\x40\x73\x9e\x9f\xf9\x32\xba\x1c\x7f\xe9\x9e\x65\xd9\x1d\xf3\xb8\x6e\xd6\x6b\xc5\xeb\xda\xf1\xff\xa7\xcb\x12\x74\xfc\xbf\x32\x25\x6c\x10\x2b\x5a\xe5\x79\xc8\xf5\x23\x08\x72\xa5\x14\x9d\xe7\xac\xd1\xf2\x99\x5c\x34\xb5\x4b\x40\xbd\x85\xa2\xc2\xae\xcd\xcb\xce\x3a\x51\xa5\xeb\x04\xf7\x07\x2e\xcb\x3c\xbf\x44\x9c\x54\x64\x49\x1a\x8c\xb7\x37\xad\x1d\x1c\xd6\x0e\x4e\x14\x19\x4d\x6f\x5c\x3b\x38\xac\x1d\xc3\x63\xd6\x7e\x4d\x59\x4c\xf5\x3c\x87\xa8\x4c\x8f\xb4\x56\xe5\x49\xa3\x39\xca\x20\x19\xd6\xbf\x9f\x90\xcb\x84\x6f\x18\xde\x2d\xe3\x8b\x06\xb3\x5b\x3f\x50\xe5\x3f\x81\xe7\xa5\xa9\x6f\x92\xa7\x32\x95\x0f\x35\x71\xe3\xf2\x9f\xb6\x42\xfd\xdc\x69\x8e\x68\xcd\xbc\x65\xcd\x63\xd1\x9a\xc7\x93\x35\xef\x57\x1f\x00\x34\x59\xde\x44\x12\x6b\xad\x63\x2f\xd9\xdb\xad\x1c\x16\x46\x1a\x1e\x92\xc8\x7f\x29\xd1\x84\xf4\x10\x1d\x0d\x87\xf0\x12\x78\x2f\x5c\x9a\x8a\xe2\x46\xdd\x2e\x8e\x8b\xce\x3e\x81\x0c\x89\xe3\x73\xd4\x17\xc7\x3b\x95\xf1\xa2\x37\x2c\xe0\x40\x54\xa7\xd4\x4d\x6d\xa9\x90\xa2\xe8\x01\xa0\xed\xb6\x10\xa4\x85\x48\x17\x7a\xec\x16\xb5\xf7\xfc\x33\x20\x22\x23\x85\xb1\x2b\x3e\x5e\xc0\xd4\x00\x11\xa7\x61\x1f\xd7\x48\xf4\x85\x61\xa2\x7a\x26\x34\x9d\x33\xce\x39\xf2\x47\x66\x02\xe2\x21\xf9\x18\xaa\x46\x6a\xa1\x4e\x8d\x03\xa7\x89\x37\x42\xff\xb6\x47\x8b\x40\xab\x22\x58\x9b\x77\x8f\xcb\x54\x9e\x8f\x84\x3f\x2b\x8d\xce\x28\x82\xc9\xed\x68\xa8\xf8\xdb\x0e\x3f\xc1\xca\x3b\x8f\xf4\xb5\xf3\x09\xa5\xf4\x91\x61\x1e\x8f\x2a\xba\x87\x0b\x64\x4a\x34\xf7\x7b\xf0\xbb\xd9\x98\xf4\xfd\x70\x46\xfa\xbe\x02\xe7\x63\x34\xdd\xdb\xdf\x9d\xde\xbb\xb7\x7b\x2f\x7f\x52\xe1\x3c\x4f\x93\x9e\x55\x78\xb3\x59\xd5\xe8\x7d\x45\x3e\x56\x18\x9b\xad\xf0\x66\x23\x3a\x83\xdd\x05\x7d\x81\x4e\xd8\x4f\xf6\xd2\x6d\xf3\x7e\x56\xe8\xc6\x08\x5b\xf1\x36\x76\x3a\xf1\x05\x28\x38\xab\x8d\x9e\x3c\x30\x93\xc4\x75\xad\xd7\x4b\xf6\xba\x38\x09\x12\x64\xf6\xbd\x55\xf7\x60\x3b\xbc\xdb\x50\xd5\x2a\xe5\xb1\x59\xa6\x2a\xac\x2a\x64\x19\x61\xb0\x23\x77\xb4\xbb\x59\xdd\x7d\x9b\xb2\xdb\x6b\x26\x1b\xa7\x84\xb4\x1a\xb2\x48\x9d\x4e\xfc\x07\xc3\x51\x65\x45\x9b\x04\x61\x04\x48\x1d\x4b\xd4\x91\x75\x70\xdb\x99\x2a\xd2\x2f\xda\xce\x89\x8f\x37\x41\xe3\x90\x1c\x5a\xc5\xf9\x21\x5a\xb8\xe8\xb6\x40\xcc\xb0\x91\xde\x51\x45\x05\xf6\xc7\xf9\xbb\xa4\xea\x9d\x91\x55\xbd\x4f\x91\xaa\x7b\x20\x1a\x91\xbc\x4a\x82\xe4\x55\xe9\xf1\x54\xe5\x5d\x1a\x48\x15\x69\x7b\x49\xd5\xb1\x12\xea\x24\x46\xc7\x6a\x55\x1f\x23\xb3\x4a\x15\xa3\x2e\xad\xe5\x24\x4e\x83\x9d\xd4\xa4\x89\x6e\x42\xa5\x1a\xa7\x3e\xf5\x55\x73\x99\x7a\xb5\x6b\x3a\xdc\xb1\x5b\xd1\xa6\x6b\xf3\x9b\xd4\x39\xe9\x7c\x52\x59\x9b\xcc\xc6\x6a\x6e\xcc\x45\xdc\x98\xa1\xb6\x01\xbb\x02\x1d\x1d\x80\x25\xd4\x85\x77\x0f\xb1\xbb\x19\xe7\x37\xe7\x37\x37\xf6\x76\x9b\xaa\x05\xbd\xc3\x9e\xb3\xaa\x68\x39\xcc\x66\xb7\x35\x9d\x89\x4f\x33\x3c\xd3\x04\x45\x61\x9e\x7f\x27\x11\xfe\xc7\x77\x55\xcc\x23\x0e\xf7\x49\x45\x47\x93\x76\xb4\x77\x4d\x15\xbc\xb5\xea\x29\x1a\x55\x38\x51\xe9\x3f\x61\xa8\xc1\x56\x41\xdd\x2b\x4e\x04\xcf\x1e\x7e\xfb\x9c\x11\xc9\x9c\xb1\xb5\x98\x44\x93\xc7\x56\x3c\x71\x57\xf1\xda\xdf\x3c\x1f\x35\xb1\x1a\x35\x82\x6b\x16\x01\x6d\xfb\xc6\xb9\x65\xab\xd2\x35\x20\x80\x0f\x5b\xcf\x81\xdd\xff\xc7\x90\xeb\xae\x1a\x38\x1e\x04\x1a\xb6\xee\x27\xdd\x25\xf5\xeb\x34\x9d\xa9\xf8\x54\x72\x8e\x42\x8c\x92\xde\xa1\x4a\x83\x0b\xd4\x12\xd3\x36\x00\xcf\x5b\x65\x74\x53\x84\x9c\xc4\x3e\xa5\x4d\xb2\x02\x87\xee\x9f\xc3\xfb\xe6\x8a\xa8\xf8\x0c\x94\x28\xa7\x52\x0e\x5a\xfd\x98\x4c\x09\x01\xc9\x10\x31\xe8\x77\xa0\xb3\x4d\x0f\xef\x75\x6c\xcd\x64\xc7\x6b\x35\x9f\xe6\x7a\xb3\x5b\x4c\x73\xb3\x78\xc4\xe1\xe6\x76\xf7\x5c\x5c\x8b\xb0\x44\x5d\xd6\x68\x50\x11\x9b\xcc\xcf\x11\x6d\x4f\x39\xba\x96\x4f\x5f\x71\x66\x1a\x79\x67\xa6\x81\xe5\x72\xdb\x3d\x51\x39\x24\x56\x2b\x1e\x83\x25\x57\x88\x0f\x62\xcd\x4f\x8b\x33\xe9\x23\x6e\x58\x6d\x76\xc0\x0a\x87\xaf\xf8\x29\xbc\x3f\x79\x70\x98\x03\x0c\xbe\x43\x41\xdf\x9f\x3c\xb8\x97\xeb\xcd\xe1\xbe\xdf\x26\x78\x05\x78\x79\x8a\x6e\x52\x7e\xbb\xf5\x0e\x85\xd2\x7b\x51\xb1\x76\xef\x1f\x44\x78\xc0\x03\xdf\xf2\x1a\x6a\x97\x05\x02\x45\x90\x5b\x04\x37\xa8\x77\xf4\xc1\xaf\xb7\x60\xfa\xa0\x53\x44\xfb\xa8\x2f\x91\x0c\x48\x1a\x49\x7d\x6e\x19\x29\x1d\x5c\xfc\x9d\xce\xf1\x47\xe9\x8e\x92\x3c\x4a\x8b\xa0\x59\x66\xc4\xd0\xd9\x52\x5e\x8b\x3b\xf4\x47\xe4\xc2\xd3\xb8\xc3\x62\x07\xd4\xec\xc1\x26\x23\x10\x16\x49\xb3\xff\x23\x80\xbe\x3b\x67\x5c\x80\x43\xb3\x38\xdb\xa9\x35\x5b\x7c\x2a\x76\xb2\x3b\x66\x8c\xd6\x35\x3b\xe3\x77\xb2\xff\x23\xcc\x2d\x3c\x71\x13\xd2\xed\xf9\x79\x84\x6f\x08\xef\xc9\xa8\xa2\x55\x54\xd1\x85\x14\xb5\xac\xf8\x18\x94\x20\x48\xbb\x5d\x56\x5b\x97\x9a\xc3\x0c\x94\x8d\xbe\x11\x4e\xef\xaf\x92\xa6\xc0\x1f\xed\xd9\x58\x5f\xac\x30\xac\xfc\x80\xba\x90\xd7\x9b\xcd\xa1\xbf\xc4\x7c\xcc\xd6\x66\x39\xb3\x0a\xb8\x28\xe6\x43\x7b\xde\xbf\xef\x43\x65\xb7\x3e\x6a\xfe\xec\x51\xa4\x47\xff\x02\xd6\xb4\xfe\xd1\x7f\x74\x72\x9f\x1c\xfc\x8b\xc1\x83\x7f\x11\x0e\xfe\x45\x7c\xf0\xef\x63\x03\x84\xe7\x5b\xd1\x3d\xf7\xf7\x4f\xe2\xa5\x75\xbb\x25\x3f\x95\x37\x98\x3f\xb1\xae\xbd\x30\xf8\x93\xd9\xc8\x91\x3c\xd9\x80\xa5\x9b\x34\x6b\xf3\x4b\xec\x61\xdd\x0d\x1a\x62\xab\x82\x82\x1d\x91\xd3\x45\x55\xf4\xe8\xf8\x16\x05\x14\x64\x75\xaa\xa8\x5e\x5e\xbf\x61\x77\x4a\x26\xd6\x53\x32\xa9\x9b\xb4\x4f\xdd\x92\x5a\x15\x83\x53\x35\xc1\x77\xab\xfe\x77\xfb\x1b\xf3\xd1\xc0\xc6\x7c\x60\xdb\xae\x6e\xdc\xb6\x43\x18\xc4\x70\x90\xa0\x40\x04\xb2\x86\xc6\x70\xaa\xd5\x55\xbf\x2c\x71\x9e\xb3\xa1\x44\xa7\xbc\x3f\x5a\x1e\x63\xbb\x19\x77\x8a\xac\xa5\x8f\xd6\x66\x1e\xc1\x48\x2b\xcd\xd7\x1a\xdc\x74\x4b\x29\x61\x23\xb8\xd9\x20\x61\x03\xa6\x1f\x95\xc7\x34\xcb\xac\x44\x74\xa3\x12\xcc\x86\xc3\x6c\x15\x5c\xee\xfe\xeb\xda\xa8\xe5\x57\xb4\x51\xcb\xae\x36\x6a\x39\xa4\x8d\x5a\xe2\xb9\xd9\x50\x9a\x2e\x32\xc2\x33\xad\x20\x48\x97\x45\xa1\x5d\x3a\xab\xc6\x59\x20\xb1\xf2\x51\x19\x95\xa1\x85\xd9\xc5\xb9\x6d\x32\x9b\x1b\xea\xb8\x01\x42\x06\x89\xbe\xb0\xe8\xcd\x6e\x11\x5e\xf8\x9d\x58\x83\xbb\xe4\x36\xc5\x5a\xc6\xe3\x08\x3d\x1a\xa0\xf4\x66\xb3\xc8\xf3\x9e\x36\xd2\xa4\x0f\xf4\x40\xdb\x6b\x0b\x3c\xf0\x4e\x9e\x37\x47\xe5\xf1\x88\xd2\xc5\x51\x79\xdc\xef\x42\x93\xea\xbd\x79\x0d\xa9\x3c\xb9\x48\x15\xc8\x04\x18\x2d\x8b\xd9\xad\x1d\x0d\x91\x05\xd1\x82\x2e\xe6\x8b\x54\xcf\x49\x1a\xda\xcc\x9b\x4e\x9a\xa3\x92\x45\xbb\x5e\x40\x4c\xc5\xb4\x6b\x16\xb8\xa3\x16\x5d\xce\x7b\x0a\xa4\x45\x9e\x7b\xad\xe7\x28\xf2\xc9\xec\x95\x95\x65\x77\x16\xdf\xa4\x01\xfd\x86\x31\x37\x38\xc4\x50\x68\x4e\xa2\xf1\x5c\x76\x35\x9e\xa4\xda\x6c\x1a\x4a\xe9\xc2\xd3\x18\x17\x3d\xc7\xd5\x45\x58\x31\x60\x04\x78\x18\x1e\x4a\xe9\xa3\xf9\xa2\x85\xa8\x19\x18\xcd\x0b\x8c\xb7\xa2\x47\x4a\x37\xf4\x88\x0b\xa0\xb8\xa4\xd5\xac\xb3\xe9\x58\x76\x75\x82\x5b\xf2\xcb\x10\xf7\x17\x03\xa7\x63\xd6\x35\xb7\x1a\xf2\x69\xfb\x95\xb3\x4f\xaf\xd8\x7a\xee\x7e\x8b\x57\x6c\xdd\x3a\x00\x34\xc1\xfe\x02\x09\xba\x60\xe8\xee\x14\x82\x58\x6b\x76\x46\xf7\x88\x18\xaf\xd9\x55\x25\xd9\x92\x5e\x3b\x0f\x3f\x87\xb2\xee\x6d\x35\x80\x5d\x87\x43\x7a\x08\x82\x7a\xc2\x16\x9f\x68\xb4\xea\xff\x65\xc6\xf1\x5f\xb0\xf1\xf8\xa9\x82\xb8\x74\x15\x9a\x00\x02\x58\x64\xfb\xb9\xb8\xa5\x16\x1e\xa5\x1f\xa4\xd7\x1b\x1d\x47\xd2\xd0\xad\x51\x24\xe6\x6b\x8f\xcb\x6d\xeb\xda\x36\xa9\x0f\x39\xe2\x6a\x46\x14\x92\x0e\xca\x8e\x25\xce\x1d\xe9\xf6\x85\x0d\xae\x1f\x2c\x71\x21\x7a\x6c\x44\x22\xb0\x55\x1d\x22\xcd\xc0\xe2\xa4\x5a\x15\xdf\x2f\xd5\xfc\x97\x8a\x0a\x7e\xb9\xf3\x8e\x6b\x74\xa4\xcf\xcb\xfa\x18\x17\xbf\x54\x63\xb6\x5c\x22\x73\x17\x48\x89\x1d\x94\xb4\xb6\x52\xdd\xcc\x3c\xec\x57\xc3\x0b\x6a\xe4\x3a\x3c\x7a\x07\x62\x9e\x08\xa8\x0c\x45\x96\x6d\xb1\x61\x47\xd0\xf8\xe5\x8d\xa3\xe9\x1d\xd7\x73\xf7\x5b\xbc\xe3\xba\x1d\x4d\xa7\x55\xec\x16\xa3\xf8\x69\x12\xd1\x62\xb8\x8b\x34\x40\x14\x7a\xf0\x50\x2b\x44\x6a\x7c\xfd\xa5\xb6\x31\xd0\x81\x1f\x76\xa0\x42\x5b\x94\xf2\x2a\x09\xaf\x15\x9b\x09\xf5\xa3\x10\x26\x41\x0a\xdd\xad\x33\x22\xda\xef\x18\xff\x78\x93\xa0\xf2\x14\xed\x1e\x1c\x7a\x4d\x60\xbb\xe3\x6b\x03\x0d\x75\x14\xdb\x3d\xdb\x62\x6d\x81\x8d\x23\x5b\xa0\x1b\x5c\xc0\x90\xee\xc4\x20\xb5\x36\x2c\x73\x11\xb9\xd3\x0a\x6c\xed\x6c\x3e\x7e\x54\x9c\x2d\xf4\x73\x01\x4a\x86\x6a\xa8\x38\xea\xd1\xb5\x3a\x16\x4b\x10\x11\x2b\x69\xd3\x8f\xb7\x29\x5a\x71\x77\xdb\x79\xb8\x17\x6f\x38\xcf\xc3\xbc\x0d\x21\xe0\xbf\xa5\x07\x22\x7d\x4d\x88\x2f\x63\xae\x52\xa4\xe4\x78\x8b\xef\x82\x44\x19\xc1\x96\xea\x10\x45\xa0\x3c\x45\x7b\x94\xa2\xbd\xdc\xee\x75\xbd\x0d\x19\x77\x47\x02\x33\xee\x71\x7a\xa9\x42\x38\x44\x6c\x72\xbb\x28\x0e\x63\x72\xfb\x9f\xaa\x8b\xb3\xc3\x9f\x29\x1f\xc6\xc3\x6c\x83\xf7\x73\x24\xa9\xb4\x95\xb3\x8a\xe0\x29\xd8\xdb\xa3\xe7\x35\x12\x66\x1d\x7a\x65\x7f\x31\xc4\x16\x4d\xea\x95\x0e\xc4\x16\x8b\x24\x92\xeb\xf7\x73\xe1\x3b\x31\xd8\x53\xcd\x79\xdf\xd9\x1b\xd9\x93\x8a\xce\xf8\xb2\xa8\x3b\xf3\xce\x09\x82\x19\x6d\x0e\x8f\xa7\xf3\xc4\x0c\xbc\xbe\x7b\x64\x3f\x0a\xc6\xb7\x8d\x4f\x8c\x2d\x1c\x1c\xba\x89\xe4\x79\x7e\xce\x90\x00\x84\x49\x1c\x29\x1d\x6e\xca\xee\xe2\x7b\x8a\xc8\x45\xc3\x6f\xf4\xc2\xd0\xb4\xdb\xbd\x38\x02\x9f\xa3\x2e\xf7\x79\x5b\xe2\x6e\xc3\xd7\x93\x9e\x38\x18\xee\x89\xd0\x12\x0a\x98\xbb\x51\xc7\xfc\xaa\x02\xbc\x51\x87\x9c\x79\xce\xc7\xa7\x46\x66\x46\x38\x44\xe5\x4b\x98\x91\x37\x74\x7c\x10\x98\x93\x9d\x3f\x6e\x5e\xed\xfa\xb0\xab\x5d\xe5\x43\x57\x47\x12\x57\x4e\x74\x4d\xe7\xc1\x54\xb6\x85\xa7\x15\x91\x7f\x45\x37\x73\xf7\x61\xeb\x61\x18\x3d\xf9\xac\x91\xc0\xe6\xbf\xdb\x19\xc7\xaa\xea\x6e\xfb\xf9\xac\xb3\xd1\xf7\xb3\x39\xa2\xb3\x8d\x19\xd8\x5f\x43\x10\x44\xf0\x35\xe2\x15\x1e\xd7\x5c\x7b\x89\x70\xae\xe2\x3b\x94\x2d\xcb\x7a\x5d\xb1\xab\x8c\x64\x42\x0a\x9e\x91\xac\x5c\xad\xa5\xd2\x4c\xe8\x0c\x17\x6a\xec\x1e\x53\xfb\xd4\x1e\xe8\xa4\x9f\x77\x5a\x97\xce\x99\x1b\x7c\x78\x26\x1d\xf3\x90\x79\x2e\xbb\x92\x69\xf8\x32\x9e\x4b\xff\x19\xe7\x43\x62\xdf\x0e\xdf\xbe\xe4\x51\x35\x8d\x14\xe2\xf5\x18\xad\xd2\x43\xc4\x11\xe5\xfc\xf1\x29\xd5\xf3\x2c\x2b\x3a\x35\x0b\x4a\x10\xb4\xbb\xd7\xaa\x41\x76\x83\x4a\x24\x18\xf1\x8a\xae\x7f\xa5\x70\x31\x47\xfe\x1b\x2a\x93\xa1\xb8\xa3\x7f\x43\x65\xc2\xff\x7d\x95\x49\x8b\xe2\xdf\xda\x69\xbf\x93\x83\xd2\xda\x3b\x69\xb6\xfb\x72\xb5\x2a\xf5\xb3\xf2\x84\xab\x0f\x62\x65\x18\x26\x48\x24\x37\x3c\x43\x9f\xa4\x11\x4b\x5a\xf4\xe3\x6f\x90\x3d\xf6\x6f\x5b\x01\x8d\x78\x90\x32\x3e\x11\x05\x4e\x8c\x4e\x06\x82\xd0\xe1\xd6\x31\xbf\xea\x28\x2a\xc0\x7f\xc7\xad\x75\x66\x92\x28\x1b\x55\x9a\xb4\x3e\xad\xd8\x85\x99\xdd\xcf\x15\xc6\xcf\x6b\xa4\x03\xf6\x95\xa2\x36\x8a\x86\x44\x51\xab\xbe\xd4\x48\x19\xde\xb7\x15\x2e\x84\x80\x8f\x8e\x04\xd2\xcf\xb6\x55\xc9\x58\x21\xe9\xb4\x42\x7a\x08\xa2\xa0\x2b\xfb\xa4\xb0\x08\x11\xb1\xb9\x73\xd9\xef\x5a\x0a\x38\xf1\xbb\x77\x2e\xcf\x07\x8b\xea\xb4\x00\xb8\x77\x54\xd5\x83\x02\xea\x19\x29\x94\x76\xf6\x8b\xa7\x76\x90\x44\xc3\xe6\x0c\x84\xd8\x1e\xe6\x12\x8f\x4f\x18\xf9\xc0\x21\x21\xef\x1f\x6c\xf2\xde\xc1\x26\x1f\x3a\x9a\xec\xfa\x9d\xb9\xc4\xc4\xf5\xce\xa5\xf9\x91\x6f\xef\xba\x87\x97\x51\x2c\x86\x2a\x0a\xe2\x70\x40\x43\x1c\xd0\xbd\xf6\x72\xdf\x5f\x46\x91\x19\x6c\xd3\x8b\x38\xb0\x72\x27\xae\xa9\x8b\xaf\x7c\x65\x28\x19\xfc\x99\xe2\xb8\xc0\x1d\xb6\x3f\x71\x21\x9c\x05\xd5\xc1\x9a\x3f\x59\x3b\x45\x2f\x26\xae\xa2\xa3\x69\xdc\x49\x7b\x7e\x5d\xd4\xb4\xe3\xf7\x6e\x51\xad\x3a\xde\x31\x9d\x0a\x4c\x31\xde\x4e\x0f\x23\x51\xe9\x8c\x23\x4d\xb2\x0c\xfb\x58\xc0\x39\xbd\x3b\xbd\x87\x67\xbc\xd0\xce\x91\x08\x96\xa2\xbf\xc3\xb7\xae\x2a\xe4\x6f\x30\xc0\x42\x06\x57\x8c\x1d\xbe\x8d\x18\x18\x14\xff\x2d\x4c\x6c\x76\xd0\xf2\xeb\xc3\xf6\x72\x7a\xdf\x5f\xdb\x8a\xec\xfa\x56\x61\xcf\x7d\x77\x74\x1c\xef\xcb\x7b\x08\xec\x87\xc5\x23\xca\x77\x33\x2f\xdf\x42\x00\xd7\xb6\x70\x8b\x74\xd9\x2e\x83\xbe\x65\x5b\x35\xbf\x34\xb3\x07\x6c\x61\x3e\xfb\xab\x28\x10\x47\xc7\xb7\x03\x06\x1b\x91\xd4\x0c\x47\x65\xf5\xf8\xb0\x6f\x97\x98\x53\x39\x8f\x76\xda\x45\x1c\x35\xb5\x14\xb5\x66\x62\xc1\x89\x9e\xdf\xef\xd8\x02\x45\x81\xd0\x4d\x36\xae\x9c\x88\x09\x33\xba\x10\x03\x69\xa8\x53\x04\x8c\xc5\xb6\x14\xdc\x7d\x45\xe0\xc2\x64\xc1\xc9\x41\x03\xf7\x87\x80\x20\x06\x59\x59\xf7\xad\x94\x70\x3a\x0e\x43\x13\x07\xf3\x0f\xed\x55\xc8\xe0\x89\x11\xa9\x93\xd3\x13\x0a\x95\x32\x7d\xbb\xda\x82\xa1\x48\xa0\x61\xec\x0e\x18\x19\x8d\x0c\x3e\x8f\xa2\x87\xfc\xa7\xbb\x60\x88\xa8\xa2\x43\x9d\x6f\x6c\xda\xe7\xaf\x34\x6d\xf0\x79\x14\xf2\xa4\x2b\x42\x12\x80\xaf\x20\x80\xaa\x66\xe7\xc7\x88\xe1\x6b\x46\xa5\xe7\x60\xd6\xcf\x74\x96\x4c\x62\xd6\xb3\x73\x9b\x44\x76\xf3\x94\x45\x8c\x8a\x25\x8c\xaa\x65\x52\x3b\xbc\xc3\xa6\x84\x03\xae\x1a\x62\x53\x3b\x7c\xcb\xa8\xf7\x90\xde\x32\x3a\x9a\x6c\x9d\xd0\x2b\xdb\xd3\x2d\xbb\x63\xbc\xb6\xf5\xb5\x4e\x2c\x9c\xd4\x54\x92\x86\xd6\xb3\x99\x59\xca\x2f\x2a\x54\x91\x26\x1c\x46\x3b\xd3\x92\x3c\xdf\x87\x1b\xf3\x76\x93\x4e\xef\x86\x34\x3e\x57\x30\x55\x6a\x28\xa5\xf5\xa0\x53\x6b\x33\xc8\xf0\x9a\xc0\xf0\x9a\x56\x50\x6b\x0b\x68\x42\x86\x6d\xd3\x65\x72\xfe\x09\xd4\x22\x38\xb5\xce\x51\x45\x85\x69\x58\x44\x65\x33\x41\xab\x76\x82\x56\xf1\x1c\x8f\xcd\xed\x6b\x5c\x54\x9d\x04\x33\x12\xe3\x94\xa8\x58\x1c\x04\xe9\xfd\x96\xbe\x51\x2c\xbe\x20\xe0\xc6\x75\x19\xe8\x44\xef\xaa\xef\xdb\x25\x89\xf4\x2f\xb7\x12\x70\xf8\x16\x08\xa0\x32\xf4\x52\xf8\xca\xb7\x14\x62\x26\xe5\x0d\x27\x8f\x72\xb0\x77\x64\xe8\x1d\x39\x70\xf2\x68\x9a\x0d\xba\x08\xb7\x4c\xd9\x05\x05\x31\x40\x0f\x92\xdd\xee\xf2\xd9\xa0\x62\x7d\xc1\xfa\xd3\xb7\xab\xdd\xfa\xa2\xaf\x3f\xe5\x8d\x64\x97\x48\x4b\xd8\xc2\xef\x8a\xb9\x18\x50\xba\x38\x81\xd7\x49\xa5\x46\x04\xb6\x1a\x20\x90\x77\x21\x32\x7d\x2b\x09\x93\x70\x45\x93\xb0\x51\x0e\x9e\x14\x61\x7b\xb6\x1e\x89\xb7\x0a\xe0\x4a\x3b\xba\x97\x74\x37\x9e\xaa\x08\x0f\x5a\x49\x1e\x1c\xe6\xda\x01\x67\x9d\xd2\xd2\xfd\x98\xdb\x3f\xf6\x51\x70\xad\xea\x45\xcd\x78\xec\xb9\xc6\xfa\x44\x1a\x08\xe9\xec\xb5\xd1\xce\x97\xd6\xf9\x70\xb8\x83\x5c\x6b\x4a\x99\x29\xb6\x2c\xa5\xb3\x52\xba\x5a\x07\xcb\x15\x35\x16\x6c\xc5\xf3\x5c\xbb\x03\xcd\x77\xdc\x0e\x57\x4d\xdf\xb9\x13\x55\x49\x27\x33\xf9\x30\x84\x15\x97\x77\xe8\xae\x0f\x7c\xcb\x8e\xe4\x31\xa9\xcd\xcf\x9d\x69\xcf\x1e\x5f\x90\xfa\x6b\xf6\xf8\x17\x3e\x57\x6a\x72\x7f\xe6\x92\x2f\x91\x20\x15\xa9\x8d\x3c\xe1\xed\x59\xd2\x23\x6a\x61\x2b\x3d\x7c\x3a\xdc\xf4\x1f\x06\xab\x71\xb3\x64\xc7\x6e\x11\xe3\xc8\x2b\x82\xdc\xf2\x6c\xd0\xc8\x9c\x25\x46\xe6\x22\x35\x1b\x67\x60\x64\xce\x47\x34\x79\x35\x1c\x4d\xa6\x56\xe5\x03\xef\xf7\xcd\xce\x8b\xa1\x4c\xc1\x13\xe8\xe8\xb8\xc8\x32\xf3\x4d\xbc\xdd\x26\x63\xf8\xb0\xf8\x36\x8f\xcb\xdd\xd6\x2a\x07\x94\x46\x7a\x58\xd5\xd0\x51\x64\x0d\x69\x98\x3b\x93\xc1\xfb\xa3\xc2\x51\x88\xbb\xa6\xa3\x29\xf9\xac\x91\xe8\x6a\x9c\x71\x57\x7f\x35\x6c\x4d\x95\xe7\xe8\xd7\xca\x1a\x79\xad\x2a\x8f\x03\x66\x68\xe4\xc2\x4c\xbc\x83\xad\x5e\xc7\xd6\xa7\xfb\xa4\x6f\xb8\x03\x39\x4c\x81\xe4\x06\x23\xae\xdb\xf5\x5a\xef\x92\x03\x90\x61\x16\x07\x18\x27\xdd\x79\x1c\xb0\x4e\x5a\x31\xdb\x4b\xf1\xa0\x6e\xe3\xb1\x05\x2a\xbf\xdc\x59\x82\x81\xee\xa9\x54\x4f\xd9\xe2\x3c\x32\xb3\xd1\x9e\x45\x3e\xab\xe3\x10\x29\x44\xe3\x99\x18\x9f\xb3\x1a\x69\x38\xba\xb6\x87\x48\xa6\x08\x7d\xce\x05\x52\x44\x41\x04\x90\x88\xc7\x3f\xae\x92\xd8\x3d\xad\xd5\x9b\x1f\x48\x36\x6a\x6d\x27\x34\x6f\x30\x89\x6b\x95\x83\x91\x42\x43\x0f\x98\xc4\x85\x61\xd9\xbe\x01\xfb\xc5\x3f\x2a\xfa\x8a\xe9\xf3\xf1\x82\x97\x15\x79\x53\x75\x40\xfe\x9f\xb8\x70\x39\x5c\x91\xb7\xdd\x67\x36\x00\xc0\xeb\x8a\x4e\xc8\x7b\x6b\xe5\x42\x7e\x76\xbf\x1f\x4d\xe2\x2b\xf3\xe7\x79\x45\x6b\x89\x26\x98\x3c\x32\x77\x2f\xdd\xf3\x2f\xe6\xe6\x89\xf9\xf3\xcc\xfc\xf9\x7f\xa9\xfb\x13\xe6\xb6\x71\xa4\x71\x1c\xfe\x2a\x12\x77\x5e\x2e\xb0\x86\x15\x4a\x76\x1c\x9b\x0a\xa2\x27\x87\xb3\xc9\x4c\x12\x67\xe3\xcc\xa9\xd5\xcf\x45\x4b\x90\xcd\x31\x0d\x68\x48\xc8\x47\x24\xee\x67\x7f\x0b\x8d\x83\x20\x45\x39\x99\xdd\xe7\xa8\xff\xd4\x54\x4c\xe1\x3e\x1a\x8d\x46\x9f\x2f\xd4\x3f\xbf\x9b\xbc\x9f\xd5\x8f\xef\x32\xda\x7f\x14\x55\x02\xaf\x1f\x33\x84\x57\xdf\x69\x38\xdc\x79\x1c\x45\x30\xf4\x9f\x32\xf2\xc6\x54\xfa\x23\x53\x60\xfe\x83\xf9\xf5\x0f\xf3\xf7\xef\x90\xfa\xab\xf9\xf5\x4b\x46\x8f\x22\xf2\x7d\x46\xc7\x13\xc2\x0a\xf5\xaf\x34\xcf\x7d\x5e\xd0\x88\xe4\xe6\x87\x28\xe8\x6e\x9f\x24\x2a\x29\x05\xdd\x67\x93\x5e\x14\xb5\x48\x07\xcb\xa2\x12\x68\x02\xc3\xe7\x30\x3c\xc9\xf0\x48\x0d\x30\xde\xed\x2b\x2a\xa4\x18\x89\x22\x16\x05\x8c\xd9\x13\xc1\x16\x0a\x72\x8d\x23\xf4\x41\xa8\x77\x17\x2e\x32\xab\xbd\x0a\x0e\xab\xb5\x8b\xf5\x4a\x6b\xfe\xe8\x88\x52\x08\x0e\x37\xea\xc7\x03\x53\x80\x26\xea\x99\x9d\x14\xf4\x4b\x06\xda\x80\xf4\xef\xc2\x8b\x30\x81\x57\x10\x34\x40\x15\x49\x0b\x7b\x19\xfe\x9e\x8d\x7e\xcf\x6a\x41\x59\xe3\x48\xd1\xfd\x49\x61\x14\x15\xf7\xfb\x87\x07\xfd\xfe\x20\xfc\x57\x5a\xf8\xce\xbe\x64\x48\x77\xa5\x31\x42\x00\x51\x9b\x2b\xc7\x70\xb8\xab\x15\x7b\xe9\x61\xff\x68\xe0\x85\x9b\x61\x30\x5e\xc2\xe8\x6b\x69\x58\x62\x27\x19\x0e\xc3\xa3\x43\x50\x85\xee\x0f\x62\x56\x0b\xc3\x53\xbf\x7e\x3a\x47\x0e\x99\xf4\x1f\x6b\x24\x72\x74\xe8\x52\x22\x93\x62\x58\xf5\x47\x07\x36\xe7\xd0\x64\x38\xf9\xc1\xa0\xa9\x18\x18\x95\x25\xc4\xac\x2b\xbc\x3d\x81\xc0\x6a\xd6\x77\xc7\xe3\xe8\x29\x2f\x0c\xca\xae\x01\x86\x43\x45\xa0\x55\x59\x61\x7a\xc4\xe8\x5c\x0b\x51\xeb\x36\x0e\x3f\xcb\xea\x5d\x45\xe9\xe7\x2c\x0c\xd1\xeb\x6c\x4d\x25\xd9\x37\xe6\x20\xd7\xaa\xd6\x59\xe6\x22\xe9\x42\xec\xbf\x3e\x48\x97\xd4\x7a\x1d\xea\xf5\x02\x48\xd0\xc0\x75\xa3\x60\x27\x46\x8b\x42\x1b\x94\x2a\x10\x38\x51\xcd\xaa\xd3\x41\x7e\x10\x08\x63\x1c\x1b\xc8\x39\xc9\xf0\x7a\x7d\x74\xa8\x1f\x86\x47\x47\xda\x7d\xb5\xbb\x9b\x8a\x91\x02\x7d\x2b\xf2\x66\x13\x1c\xcb\x02\x50\x15\xc3\x98\x98\xe6\xb1\x3a\x91\x5e\x34\x51\x33\xc7\x87\xfd\x46\x01\x6d\xd4\xee\x3b\xca\x3a\xfd\xa9\xb3\xb9\xd8\x10\xfb\xee\xc9\xd4\xf2\x70\x4f\x79\xdc\xf7\x1a\x63\x25\x4b\xef\xb6\x35\x69\x16\x7f\xcf\x72\x61\x46\x1e\x33\x25\x6e\x08\xb4\x8b\x0d\xb9\x88\x53\x1d\x80\xe7\x91\x7a\xc2\x17\xcb\x02\x78\x8f\x36\x8c\x33\x65\xbd\x45\xca\x2f\xec\xef\x84\xb2\x1e\xbb\x5b\xa4\x5a\x6b\xe6\x73\x7a\xcd\x0a\x92\x51\x56\x3b\x5d\xc3\xe8\x69\xd6\x88\xe4\x9c\xd9\x48\xce\x64\x4a\x93\x71\x01\x6a\x57\xbb\x6a\xd7\xa7\x0e\x2d\x2c\xc3\x1c\x6b\x3b\xa2\x65\x28\x30\x5e\x4d\xa9\x24\xef\x24\x5a\x5a\x8d\x96\xe7\x72\xa8\x6a\xd2\x7e\xf4\x94\xce\x46\xd3\x9d\xc1\xe3\x28\x3e\xd0\x9f\x8f\xd9\x5e\xbc\xdb\x37\x4f\xa3\xe9\x53\x2a\x41\xbf\x0e\x86\xe9\xa2\x4f\x2f\xf1\x30\x83\xe0\xd1\xc0\xc1\xfe\xa2\xc0\x54\x43\xe8\xe8\x2c\x53\xe8\x40\xd2\xe7\x12\x80\x2b\xc7\xfe\x5e\x76\x29\xfd\x22\xc2\xf0\xa3\x40\x1c\x64\x94\xde\x72\x39\xce\xad\x49\xfb\x98\xa7\x22\x4f\xe5\x3d\x8d\x70\xd3\x2f\x95\x3e\x64\x2d\x45\x7d\xf5\x4d\xbf\xab\xb2\xff\x18\x8e\x04\xe2\xf4\xa6\x76\xd7\x3a\x33\x81\xd7\x62\x84\x5e\x0b\x3a\xe6\x13\xf2\x42\xd0\xdf\x04\x3a\x13\xe4\x1f\x02\xe3\xf8\xb5\xd0\x2a\x41\xe0\x5e\xe5\x8b\xc0\x71\x7f\x5f\x87\xb7\xa3\x7f\x08\x74\x74\x44\x1a\xed\x35\x7c\xe0\x6d\xa0\x24\xfb\xb8\xaa\xdc\x9a\x1c\x1d\x39\x22\xaa\xfe\x7a\xb1\xaf\x19\xa7\xca\x7c\x64\x31\x53\xcd\x5f\xca\x93\x36\xed\x08\x87\xbb\x8e\x9e\xd4\x18\x1e\xb6\x6d\x97\x6d\xf0\x62\xd5\x47\xb4\x85\x39\xbb\xf7\xf8\x50\x4d\xaf\x2c\xc1\x70\x4b\x4d\x9e\x93\xcb\xc6\xdc\x71\xdb\xf6\xc9\x8d\x7d\xf6\x28\x97\x4b\x7b\x93\xe9\x1b\x33\x2d\x28\x5c\x9a\xd5\x65\xd8\x8c\x5d\x3f\x78\x82\x2b\x7d\x78\xbf\x59\x75\x04\xce\x0a\x04\xa2\x5a\x3f\xbd\x5b\xc1\x44\xc7\x23\xde\x36\x20\xd6\xde\x87\x7c\xa3\xb0\x96\xd9\x9c\x64\xc3\x93\x6c\x4d\xfb\x07\xe6\xbd\x77\x55\x20\xad\x43\xf8\xd9\x18\xc1\x9d\x65\x9a\x4f\xa7\x31\xe9\x9d\xf6\x07\x89\x87\x43\x90\x99\xfc\xa6\x4a\x6b\xd7\x54\x4e\x6b\xe6\xd8\x68\xcd\x28\xb8\x4e\x10\x26\x1f\x33\xa7\x39\x93\x28\x92\x48\x58\x2c\xf6\x21\x1b\xe5\x34\x8a\xd1\x67\x9f\x32\xca\xe9\x73\x7d\x63\xa3\x2f\x59\xf8\x3a\xc3\x18\x7a\x8c\x2a\x86\x5e\xa4\xd5\x8b\xd3\x39\x1a\x50\xad\x83\xa6\xc6\x7f\xb0\x4f\x98\x47\xe1\x33\x9f\xc2\x7f\x93\xa3\x0d\x9d\x12\xa0\x09\x10\xa7\xaf\xa4\xc2\xeb\xe0\x68\xe8\xd4\xe0\x76\x4c\xfa\x70\xbe\xf5\x0e\x49\xfa\x2e\x23\x66\x0c\xe4\xda\xdc\x2e\x80\x22\x15\xed\x82\x89\x93\x28\xb0\xde\x3c\xe5\x69\x71\xc9\x66\x3f\x8b\xfc\x4a\xed\xa2\x9e\xb4\x1f\x78\xd5\x15\x79\x67\x0c\x38\xf3\x06\xcb\xa2\x09\x9c\xfb\x8f\xed\x5b\xc4\xe9\x0c\x9d\x14\x75\x9b\x66\xad\x93\x60\x47\x86\x0e\x06\x47\xfd\xfd\xc7\x07\x51\xc8\xb1\x26\xdc\xfb\xd1\x53\x94\xd3\x9f\x33\x45\x1a\xee\xc2\x98\xb1\xb5\x11\x04\x60\x89\x8c\x08\x45\x01\x0a\x42\x62\x03\xb7\xe3\x90\x63\x8d\x9b\x20\xb0\x6d\x0d\xcf\xaf\x37\x4a\x87\xce\x53\x59\x4f\x6a\xfd\x7b\x1d\xd1\x8c\xfe\x98\xa3\x93\x06\x8a\xb2\x8f\xe3\x72\x63\x4a\xfb\xb5\x29\x59\x7a\x4a\xcf\xc8\x63\x46\xa9\x8b\x88\xdd\x30\x2e\xf5\x05\x23\xe8\x6e\x7f\x18\x3d\xe5\x43\xcb\x1f\xd0\x97\x0a\xc7\xc3\x44\x5d\x2a\x19\x41\x19\xcd\xc7\xd9\x04\x3f\x13\xe0\x36\x2e\xc3\x84\x87\xf4\x5f\x89\x16\x17\x0b\xa2\x56\x8a\x53\xd4\x1f\x44\xcf\x10\x07\xd2\x74\x97\xe3\x51\x7f\x10\xc5\xfb\x87\xd1\x33\x3e\xda\x3f\x8c\xe2\x7e\x04\x9f\xea\x4f\xdc\x3f\x1a\xc0\xf7\xd1\x20\x8a\xf7\xd8\xde\x33\x3e\xda\x63\x7b\xf1\xfe\x1e\xa4\xaa\x3f\x71\xff\xe8\x20\xfa\xdb\x6f\x19\xe2\x8f\xd4\x17\x56\xed\x29\x22\xe1\xab\x2b\xc3\xdb\x56\x66\x0b\xfe\x1a\x1c\x29\xec\x65\x0e\xb7\x07\x98\x0d\xec\xa4\x70\x7b\x03\xaf\x35\xee\xfd\x6b\xef\xde\x97\x21\xfd\xd7\x8b\x8c\xa8\x3f\xaf\xd5\xe5\x55\xdf\xe4\x35\x20\x3f\x0f\x0e\x42\xfa\x2f\x88\x88\xda\xbc\xf3\x87\xd1\x53\x39\xb4\x32\x63\xbd\x1b\x12\x93\x5c\xed\x06\x1f\xb2\x31\x9f\x28\xe4\xa8\x3a\xc9\x7d\x91\xb9\x7b\x05\x3c\x8c\x2d\x0d\x62\x74\x14\xa4\x2a\x5e\xbf\xce\xc3\x33\xcb\xae\x93\xf4\x2c\x23\x5c\x1f\x71\xa9\x83\x4d\x69\xf4\x02\x0f\x5b\x9d\xac\x8f\x83\xa2\x54\x8d\x02\x74\x2d\x3d\xd2\x3d\x02\xe3\xce\x28\x31\x98\x87\xf1\xbf\x8f\x7e\x64\x85\x7e\xdc\xd8\x0c\xfa\xe1\x96\xca\xde\x40\x3f\xb2\x86\x7e\xb8\x67\xc2\xf4\x67\xd1\x8f\x24\x00\x5e\xb5\xe6\x6a\x10\x71\x51\xf8\x01\x97\xec\x4d\xa1\xa3\xf7\x99\x5e\x91\xac\x82\xf8\xa9\x6b\x06\x9d\x64\x3a\xd8\x52\x45\x77\x7b\x5b\x7b\xbf\xd9\x60\x48\x77\x07\x44\xb5\x7b\xf8\x1f\xb4\x7b\x6e\xda\x9d\x0a\xf4\x36\x23\xef\x33\x4c\xde\xc3\x6b\xe2\x8b\xfa\xd7\x13\x06\xaa\x77\xe9\xfb\x8c\xbe\x75\x37\x12\x59\xaa\x1a\x7e\xa8\x7b\x47\xc9\xd7\x96\xd3\x09\xd7\xfd\xf5\x8b\x1c\x91\x5f\x3b\xd0\x9a\x68\x35\x94\x61\xf3\xb0\xef\xf6\xc9\x4f\x39\xb8\x02\x72\x97\x20\xd6\x12\xdf\x0f\x59\x83\xfc\xb7\x78\x2c\xa7\xdc\xf9\x0b\xab\xd9\xd3\x19\xfe\x5f\x6e\x58\xaa\xfa\x05\xf0\xb2\x8a\x56\x52\x58\x3b\xbb\xda\x65\xb1\xc5\x64\x6e\x58\x53\x52\x78\x97\xd4\x9d\x2e\x75\xf6\xa1\x9e\x9f\xe2\xe8\xba\xa3\x58\x9b\xaf\xd5\x32\xa3\x38\x6f\x36\xe1\x31\xba\xd4\x46\xf8\x42\xe9\xcf\x19\x65\xe4\x43\x06\x7e\x12\xdd\xd6\x00\xb7\x5d\x11\x05\xef\x33\xfa\x25\xa3\xb2\xce\x26\x79\x91\xd1\xd7\x19\x7d\x95\x51\x2f\x58\xff\xb1\x87\xc1\x86\x0e\xef\x7c\xc8\x00\xb2\x2c\x39\xf2\x77\x67\x86\x44\x3f\xa4\x84\xa7\xd5\x43\x27\xa7\xdf\x27\x2d\x6e\x79\x15\xbd\x31\xb4\x3a\xdc\x26\xe6\xb2\x73\xe6\xa9\x2e\x12\x17\x68\x5d\x8f\xd8\xf1\xf3\x79\x4a\xbb\xe0\x31\xf5\x97\x84\x46\x44\xa6\x94\xa5\xf4\x7b\x1d\x81\x8e\xe4\x10\x1e\xef\x53\x56\x53\x2a\xb6\x44\x3b\xf7\xb4\xa2\x8c\xac\x64\xf5\x3c\xa3\x7d\x35\x79\x69\x19\x49\xf6\x9e\x8d\xad\x25\x16\x49\x2b\x39\xbe\x96\x69\x81\x20\x1e\x50\x5f\xe6\x3c\xf0\x45\xfb\x87\x0d\xf3\xf7\x76\xcb\xf7\x2e\xa5\x45\x18\x6e\x58\x24\x14\xad\x3a\x4c\x05\xb0\xf0\xac\xf1\x50\x31\x74\x2c\x9c\xcc\xf0\x6f\x8c\x29\x8d\x67\x48\x3f\x9c\x8e\x50\xdd\x8a\x7c\xda\xb0\x22\xaf\xeb\xa3\x4c\x37\x2c\xd0\xb5\xe1\xf0\xd4\x84\xa1\x8f\x51\xab\x1d\x7d\x4b\xdc\x39\xad\x58\x4e\x37\x5c\x51\x90\x39\x4d\xad\x3e\xd3\x42\x4d\x61\x41\xc1\xef\xef\xbc\xd2\x04\xbc\xa4\xf3\x66\x90\x2c\xf7\x78\xbb\xc4\x0b\xcb\x49\xba\xf4\x18\x89\xfa\x8d\xa7\x2a\x5f\x7b\x95\xb5\x2c\x66\x51\xc5\xfd\xbe\xf6\xbc\x72\xa0\xae\x4e\x79\xc8\x91\x46\x77\x86\x4b\x05\x5a\x0b\x3d\xb0\x1b\x3a\x6f\xe3\xf4\x52\x4a\x6f\x74\x81\x0b\xcb\xd2\x18\x5e\x00\x33\x63\x89\x49\xad\x06\xbd\xd0\x97\xde\x8d\xc9\xad\xb6\x70\x6e\xb7\x30\x9d\xa3\xb9\x6f\xc7\xed\xbc\xc3\x1c\xec\x1d\xba\x9f\x0a\x9d\x1f\x1d\xf6\xe1\x0e\xcb\x60\xe1\xaa\xa1\xf8\x6e\x14\x32\x1d\x33\xf3\x49\xb5\x3c\xf7\xc6\xe8\xa2\x8f\x87\xf7\x90\x39\x20\xb3\x04\x65\xe4\x1e\x97\x99\x65\x95\x38\x69\x77\x59\x58\x71\x5a\x66\x78\x2d\xe7\x34\x01\x8a\xe4\x65\x32\xbd\xf4\xe7\x7f\x3e\x42\xb5\x2c\x58\x87\x22\x23\x8e\xc7\x43\xce\x7b\x05\x93\x68\x49\x0a\x8c\x63\x17\xd4\x01\x15\xf4\xbc\x77\xa1\xd2\xe1\x7a\x6e\x2d\x4d\xba\x60\xff\x03\x7e\xa1\x34\x8b\x28\xd3\x6f\xb8\x5b\xfa\xca\xa7\xb4\x12\xb2\x24\x19\x1e\x2e\x35\x9f\xfb\x96\xdc\xe2\xd2\x2d\xe4\x7e\x74\x74\x40\xe6\x36\x86\xa3\x9b\xde\x9c\xce\xeb\xf6\xb6\x06\xb2\xe6\x78\x58\x50\x4d\x06\xa1\x3f\x90\xf6\xb4\x80\xd7\xeb\xe0\x79\x07\xb8\xcf\x1d\xa7\x91\x16\xe0\x9d\xa0\xe3\xa8\xb6\x0e\x34\xd2\x71\x16\xea\xa4\x73\xbe\x94\x1d\x2e\x3a\x16\xe8\x3a\x3f\xbe\xed\xdc\x26\x45\xa7\x58\xb0\x69\x3a\x4f\xd9\xac\xf7\x4f\xfe\x4f\xfe\x7c\x36\xeb\x24\x9d\xa7\xa7\xd0\x4c\xc1\x5c\x69\xda\xeb\xf5\x9e\x55\x7d\x75\x2e\xd3\x8b\x4b\x96\x77\x52\xde\x91\x97\xac\x23\x73\xc6\x3a\x52\x74\x16\xb9\xb8\x49\x67\xac\x93\x74\x32\x91\x28\xfc\xd8\x49\xf9\x2c\x9d\x26\x52\xe4\x1d\x91\x77\x16\x59\x32\x65\x97\x22\x9b\xb1\x5c\x95\x36\x1a\xa7\xbd\x00\x97\x8f\xbb\x95\x4b\x98\x01\x26\x05\x4d\x33\x54\x90\xcc\x1d\x50\x73\x19\xce\xbd\xcb\x70\x2f\x4e\x68\x41\xea\xab\x0a\x7c\x59\xbb\xb6\x8a\x1a\x98\x27\x68\x4e\x96\x19\x8a\x48\x02\x16\x2b\x35\xcd\x89\xbe\x6a\x01\x76\xef\x4e\x9d\xf8\xfb\x05\x23\xc7\x74\x5e\xd7\xfb\x55\x07\xe2\x60\x3f\x9c\x57\x01\x4a\x5b\x70\xe1\xdd\x56\xfb\x20\x27\x9a\x38\x6e\x45\xa2\xc7\xed\x66\x3b\xd6\x12\x67\xbd\xee\xfe\x03\xdc\x45\xa2\x63\x0c\x4e\x59\xbe\x61\xb2\xd3\x0c\xcd\xeb\x93\x2d\x1f\x00\xad\xf2\x53\x81\xb8\xa7\xbe\x28\xf5\xa5\x0c\x84\x8c\xc7\xec\x52\xf7\x4f\x75\x31\x55\xda\x02\xfa\x3e\xf2\x24\xf4\x85\x0b\xd2\x5c\xb1\x00\x2c\xb9\xea\x31\x05\xd4\x2d\x6c\x9d\x80\x7c\x48\x63\x8f\xad\x7a\xda\x4a\x7f\x1e\x18\xee\x45\x3b\xa7\x42\xae\xd7\x86\x86\x33\x2c\x8a\x97\xdf\xc0\xa2\x50\xc4\xa5\xcf\xa7\xc8\x3d\xea\xac\xe1\x36\xe0\xa0\x5f\x09\x28\x6b\x8c\x8b\xe7\x1e\xe1\xac\xfa\xac\xb4\xf7\xa0\x9d\x21\xfe\x58\xa0\x0f\x3e\xa9\xf9\xdb\x66\xa1\x30\xec\x7e\x52\x04\xdb\x46\xd9\x8f\x45\x25\xd3\xfb\x29\xf3\x83\x71\x12\xa6\xe8\xdd\x61\x53\xa7\xb3\xae\xb9\xe9\x62\x7b\x8e\x3e\x01\x9b\xfc\x83\xa2\x23\x1a\xc4\x47\xd5\xd9\x27\xaf\x33\x66\x6f\x44\xee\xbb\x86\x1e\xa6\x5a\xad\xd6\x50\x1b\x70\x51\x44\xfb\x87\x55\x1c\x9e\x55\x4d\x9b\x42\x64\x60\xc7\xf0\x3e\xab\xa4\x00\x20\xa1\x55\x90\x04\x37\x0d\xe8\x83\x83\xb7\x69\xf3\xb4\xda\xfb\xba\x7e\x38\xdc\xdf\x55\xb0\xdc\xf7\x19\xd6\xae\xa1\xf6\x43\x6e\x6f\xac\x8a\xb0\x8b\x88\x70\x5a\xe2\xdc\xf9\x61\xcf\xd7\x54\x98\x13\x23\x7c\xef\x39\x9e\xc6\xc9\xd0\x67\xac\xd3\xbc\xac\x64\x90\x6e\xd2\x5e\xbc\x62\x0b\xc7\x3e\x7d\x05\x8f\x80\x7a\x20\x0e\xef\x17\xae\x64\xbc\x35\x67\x48\x4e\x88\x59\x4b\xf5\x7f\xfa\x0e\x5a\x1a\x4d\xb2\x6d\x5e\x4a\x30\xe9\x3f\x95\x35\x7b\x9d\x46\x1f\xa3\xad\x3d\xc4\x8d\x49\x34\x3a\xc1\x95\x33\x9c\x6a\xdf\x13\x50\xd0\x75\x8c\x47\xe7\x91\x29\xda\x7f\x42\x3c\x00\xf0\xe4\xba\xf5\x4e\xda\x54\x97\x3d\x3a\xb6\x61\x38\xe5\xbc\x94\x6f\x00\x99\xc4\x43\xf5\x2f\x65\x75\x8c\x27\xf1\xd0\xf7\x3e\xf6\xd8\x3b\x6f\x27\xde\x11\x00\xd1\x93\x69\xf1\x0d\xf0\xc6\x3f\x37\xe5\xda\xcd\x87\xf3\x67\x83\xb8\x66\x62\x75\xa6\x9e\x3a\xb5\x6e\x7f\xcd\x2c\x27\xe1\x6b\xbc\x60\x4e\xeb\xcf\x50\x5f\xaf\xb6\xe9\x32\xec\x9b\x1e\xac\x04\xcc\x1a\x1c\xc5\xdb\x50\x23\x78\xa2\xfa\x6d\x11\x5e\x58\x6e\xb1\x39\x2a\xbc\x7e\x54\x72\x10\xf6\xf8\x82\x9d\xf0\x5f\x62\x58\x4f\xa1\x62\x83\x87\x44\xa3\x3a\x0b\x09\x7e\xd7\x98\x37\x50\xe9\x5a\x47\xee\xff\xc4\x12\x3f\x95\x71\x99\xf0\x8b\xcc\x2b\x29\x68\x95\x7a\xcd\xb8\x2c\x86\x9e\xde\xa2\xcf\x24\x2c\x5a\xb9\x54\xc9\xd0\x3e\x5e\x34\x97\x2a\xc1\x64\x4a\xfb\x4f\x9f\x2e\x87\x62\xbc\x9c\xd0\x88\x64\xea\xcf\x6e\x9f\x14\xe6\x6f\x12\xd2\x7f\x4d\x3d\xf8\x93\x85\xc1\x08\xfb\x61\x8e\xc3\x50\x6a\xca\x90\xe9\xcf\x19\xcb\x98\x64\x88\x79\xd2\xce\x0f\x19\xf5\x6f\x0f\x75\x30\xcd\xf9\x18\xd9\xab\xd6\x3f\x96\x88\x6f\x39\x97\x9c\xe4\xf5\x48\x50\x10\x56\x3b\x6e\x24\x3a\x7f\xc6\x5a\x26\x41\x4f\x32\x60\xb9\xec\x0d\x36\x5e\xa0\x2f\x72\xfa\x83\x24\x37\x39\xca\xe8\x75\x6e\x79\xc5\x46\x71\x29\x15\x1c\x5c\x1b\x05\x29\xef\x64\xb8\xa0\xab\x42\xfd\x8a\xb3\x5e\x3d\x9b\x30\x3e\xf3\x13\x8f\xf9\xac\xd4\xdc\x7b\x16\xa7\x73\x54\x28\xda\x3a\x6b\x38\x50\x0c\xc3\xc2\x29\x1a\xa5\xec\x76\xbd\xbe\x4d\xf9\x4c\xdc\x12\x34\xa5\x05\x58\xab\xda\xc6\x54\x41\xff\x37\x32\x46\x8d\x74\xda\xcb\x13\x7e\xc1\x5e\x82\x39\xc7\x4a\xbd\x0b\x13\x3e\xbd\x14\xb9\x56\x9b\x75\x3f\x4f\xe6\xf3\x82\x49\xb2\xa4\x53\x6d\xf8\x06\xd9\x53\xfb\x4b\xe7\x02\xbb\xa0\x70\xfa\x9f\x64\xe9\x3e\x3d\xff\x32\x75\x05\x7b\xf3\xa4\x24\x73\x05\x1b\x0b\xf5\xcf\x25\x8d\xc8\x35\x8d\xc8\x0d\xcd\x88\x09\x8c\x20\x9d\xee\xaf\x85\xcd\xfb\xe1\x8d\x8e\x9a\x1c\x69\x63\x6e\x75\xed\xdd\xb8\xde\xd6\x6b\x34\xa7\xb3\x9d\x04\x13\x55\x6a\xa9\x4b\x4d\x5b\x4a\x2d\xe8\x6c\x67\x8a\x89\x7a\xac\x56\xe9\x61\x88\x66\x3b\xe6\x37\x28\x4d\x19\x0d\xba\xca\x6b\xdf\x3d\xbd\xf1\xfd\x45\x0f\xf1\x05\xbd\x21\x37\xf4\x7e\xe8\xa9\x28\xdf\xa8\x77\x9b\x51\xaf\x05\x76\xc2\x05\x05\xc6\xc0\xce\xce\x25\xd5\xfe\xc6\xe7\x74\x86\xc9\x85\xf6\xfd\xbd\xb3\x73\x4d\xb5\x0b\x87\x85\x4a\xf5\x3b\x52\x30\x7b\x6a\xf1\xb3\xe6\x0a\x5d\x50\x74\x43\x2f\xb0\xa7\x5d\x5b\xde\xd0\xfb\xb2\xa0\x20\xf2\x9d\xaf\xd7\xf0\x77\x61\x3c\xc3\x69\x60\x9b\x03\x74\x2d\x8c\x10\xd7\xec\x42\xa1\x96\xd0\x14\x88\xa0\x40\x54\x2f\xf0\x7b\x4e\x57\xb0\xc1\x6c\x76\x9c\xb1\xeb\x38\x23\x0e\x3a\x3f\x29\xa8\x89\x8b\x92\xfc\x20\x69\xb7\x5f\xd7\x68\x21\x6f\x32\x9a\x2b\x02\x48\x01\xc4\x87\xc2\x37\xed\xa9\x30\xf1\x9b\x26\x89\xb8\xb7\x17\x61\x3c\xfc\x52\xa0\x37\xc0\xcb\x7f\x93\xd1\x37\xbe\x07\xc2\xb2\x7e\x1b\xbc\xc9\xf0\xd0\x76\xea\x77\x07\xbe\x88\xa9\x63\x34\xbd\xb1\xa2\xf2\x73\xd5\x9a\x76\x98\x95\xce\x51\xff\x20\x3c\x07\xd7\xbe\x6f\x3c\xf7\x80\x60\x58\xd2\x1f\x1c\x86\xe7\xba\xca\xad\xaa\x52\xa3\xdd\x4c\xa3\xb7\x3a\xff\x8e\xde\x82\x9d\xbc\x49\xbd\xdb\xf2\xae\x19\xdd\x69\xfb\xf8\xf8\xae\x86\x32\x70\x69\xb5\x23\xfb\xd1\x1e\xf4\x69\xe4\x55\xe7\x19\x7a\x93\xa9\xf9\x3b\xce\xc0\x9e\xcf\x0e\x3c\x68\x2b\x40\xae\x54\x9a\x47\xdd\xaa\xe5\xa9\xf1\x15\x07\xfb\xb1\x57\xa1\x1f\x0d\x1e\x37\xf2\x0f\x9b\xf9\x5f\x6b\x73\x3f\xfe\x4a\x81\xc3\xf8\x38\x43\x19\x29\x60\xaf\xd4\x82\x1d\xd3\xc2\x5b\xcf\x8b\x0c\x15\x0e\xd6\x8f\xc3\xf0\x22\x43\xc7\xb8\xdc\xdc\xf6\xff\x19\xd8\x49\xe7\xe8\x8e\xfe\x9e\x93\x5b\xc0\xd7\xe4\x9c\xde\xf5\x3c\x48\x27\x19\xbd\xeb\xd5\x61\x9d\xdc\x76\x29\x3d\x0f\x15\xdc\x9c\xd7\xb1\x70\x18\x5e\xe6\xa8\x91\xd6\x9b\x99\x0f\xe3\xb0\x9d\x9c\x63\xbc\x32\xdd\x67\x61\x78\x93\xa3\x73\x45\xf8\xde\x52\x80\xbf\x5c\x92\x8a\x83\x72\x47\xb3\x1e\xe3\xe0\x50\xe4\x8e\xde\x3a\x17\xf2\xfe\x2d\x72\x3e\x42\xe7\x8d\xdb\x83\xde\x92\xf3\xda\xdd\xa1\x55\xf0\xae\x53\x8e\xee\xc8\xb9\x56\x74\xb5\x98\x0c\xc7\xe8\x8e\xa2\x5b\xda\x18\xf3\x7a\x3d\xab\xee\x95\xdb\xb6\x7b\x05\x37\xee\x14\x74\x47\xef\x1a\xd7\x0a\x29\xe8\xb9\x1f\x23\xc1\xf4\x49\x8e\xab\xf1\xd8\x29\x17\x98\x64\xd4\xcd\x1b\x26\x3d\x3a\x8e\xbd\x62\x8c\xcf\x54\xa1\xee\x5d\x8f\xdd\x49\xc6\x67\x61\x78\xfc\x0c\xfc\x65\xd3\x8c\x64\xf4\x98\x1c\xd3\x42\xf5\xb7\xc8\xd1\x39\x39\xc6\x24\xd1\x5f\x19\x26\x45\x18\x2a\x14\xdb\x57\xa7\xd2\xbb\xdf\xd6\xeb\x3b\xef\x76\x53\x37\x08\x60\xf9\x2a\x59\xdf\x63\x90\x21\xe0\x53\x65\xb9\xfb\xae\x6b\xc3\x16\xb8\x54\x57\x3e\x31\xe5\xd5\xa6\xa1\x5b\x7a\x6b\xbc\x18\x00\xe0\x20\x0c\x96\xcd\xb0\x4b\x48\xf7\x48\x6c\xfb\x98\xdc\x19\xb3\x87\xe7\x59\x06\xa5\x0b\x84\xc9\xf1\xb3\x6c\x84\xee\x7a\xc9\x6c\xa6\x1b\xb8\x55\xc5\xf4\x12\x20\x3d\x02\xe2\x3a\xc4\x31\xba\x55\xcd\x1f\xb7\xe4\x91\x5a\x1b\xea\x3f\x72\x4b\xc7\xda\x41\xd5\x1d\x3d\x1f\xaa\xdd\xab\x2e\x91\x21\x56\xd7\xc6\x9d\x77\x11\xde\x6a\x55\x17\xe7\x40\xe6\x8e\x64\x6c\x2e\xe3\xbb\x9e\xf6\xc6\xf3\x8e\xcd\x25\x91\x62\xe1\x12\x3e\x8b\x45\xa9\x59\x0b\x2d\x78\xf0\x5c\x2f\x99\x3a\x3d\xc6\x74\x9e\x9c\xd3\x68\x78\xfe\xf4\xd6\xaa\xa8\x9f\xef\xec\x60\x05\xf2\xe3\xf3\x09\xb6\x0e\x0f\xbc\xae\xe8\x5d\x4f\x75\xaf\x96\xa2\x96\xf7\x59\x2c\xe8\x5d\x4f\x8a\x45\xa9\xae\xa2\xee\x8b\x9c\xfc\x9e\xd3\x17\xb9\xd3\x1f\xb2\x38\x77\xe3\x9a\x38\x6f\xb9\x26\xae\x6a\xd7\xc4\xde\x41\x78\x15\x86\x97\x19\x3a\x27\x4d\x44\x07\x17\xc5\x15\x5e\xdd\x1a\x08\x06\x04\x77\xaa\x6a\xd7\x5d\xa7\x9c\xea\x76\x5f\x52\xff\xa6\x19\xbe\x01\x3e\x2e\xb9\xa5\x2f\xdb\x82\x83\x9f\x8e\x4e\xd1\x2d\x8e\x4f\xdd\xd8\x6f\xcb\xff\x35\xbc\x68\xb5\x5f\x5f\x09\xcd\xdf\x11\x9a\x20\xf0\xd6\x51\x4d\xee\xef\x19\x76\x8a\xb0\x8c\xfc\x92\x51\xa9\x29\x55\xb5\xac\xb0\xcc\xde\xba\xca\x7a\x9f\xe4\xcd\xa6\x5f\xe1\xc3\xd0\xdd\x3d\x21\x42\x6a\x0f\x70\xdd\xf9\xe7\x55\xd3\x89\xaf\x9a\x8a\xb4\x3a\x3a\xa0\xd0\xe0\xbf\x9b\xd4\x31\x34\x0a\xbb\x46\x2b\x65\xa4\x5e\x10\x79\x31\xe2\xc5\xce\x4e\x8c\xac\x0e\x26\xc3\x31\xd7\xcf\x3b\xdf\xaa\xf5\x1b\x0d\xce\x3f\x09\xd1\x6e\x6d\xae\x32\xd0\x95\x20\xdc\x06\x84\x3b\xd8\xd7\x0c\x50\xee\x84\xcb\x86\xdd\xe3\x99\xa2\xa7\x73\xe4\xc9\x93\xff\xb0\x1b\xa9\x95\x90\x19\xfd\x21\x73\x9a\xc8\xce\x99\x91\x53\xe8\x5c\xaf\x7f\xb0\x41\xae\xaa\xb7\xf4\x87\x26\x9b\xcc\xc1\x38\xab\xd3\x35\x45\xe1\x98\x45\x59\xb1\x5e\x23\xdd\xac\xdd\x10\x3c\xfa\x5e\x51\x49\x24\x83\x45\x55\xe4\x5d\x84\x63\x90\xef\x68\x18\x0e\x43\xd0\x36\x7f\x93\xe1\x30\xdc\x2c\x69\x75\xb3\xdc\xa1\x02\x9f\xe8\x8f\x0f\x42\x85\x29\x17\xa6\x22\xf0\xc1\x1e\xf7\x07\xa1\xc4\xeb\xf5\xdf\xb3\xf5\x1a\xfd\x1d\x7c\x4e\xfd\x21\xd0\xd1\x13\x82\x36\x9d\x3d\x9d\x59\x0f\x9d\xa5\x42\x69\x9b\x40\xed\xd6\x40\x15\x54\xc7\xe3\x48\xbd\x00\x7e\xc9\xec\xf4\x8f\x9e\x3c\xfd\x25\x1b\x1d\x3d\x89\x7f\xc9\xec\x5a\x6a\x45\xee\x37\x02\x31\xf2\xbc\xb0\x56\x44\xdd\x7e\xd5\xd4\x7b\xc3\x9a\xf8\xde\x78\x74\x93\xea\x3c\xfd\xe9\xc1\x56\xed\xbd\xb5\x02\xf3\xe2\xbf\xa7\xbd\xe7\x66\xaa\x66\x27\x7f\xcd\xb0\x9d\x83\xf1\x30\xf5\x2b\xb0\x3b\xac\xe2\xfa\x76\x2e\xca\x5e\xdf\xed\x9a\xe1\x1c\xef\x0d\x2c\x57\xa5\x18\x82\x92\xbb\x17\x8b\x2e\x1a\xe6\x4f\xb9\x45\xe0\xb9\xb3\x31\x12\x94\x8f\xf3\x09\x49\xd4\x9f\x9d\xfe\x84\x64\x54\xf8\x3e\x0e\x44\xd3\xb8\xab\x2d\xf0\x10\x9c\xad\xac\xfd\xf1\xd0\x34\xfd\x74\x78\x2e\x01\xcf\x07\x5a\x33\xe0\xfb\xcc\x68\xe6\xb7\x0e\xb3\x31\xc4\xa1\x75\xe3\x5a\x50\x61\x7d\x10\x55\xc3\xdc\xf2\x86\xf9\x86\x61\x14\x9e\x4a\x89\xc7\x59\xb0\x87\xb2\x18\x62\xa6\xc8\x90\x0a\x3d\x16\x2d\xd8\xb1\x70\xc8\xb1\xa8\xe3\xc5\x62\x03\x2f\x16\xd4\xe1\x87\x93\x8c\x4a\x50\xf9\x20\x5d\x4f\xd8\xff\xce\x29\xa6\xcf\x20\x1a\x3d\x05\xc9\x8e\xa4\x29\x30\x9b\x31\xe9\x63\xac\x12\x3d\x77\xc9\x56\x19\xbd\x0f\x22\x3d\x50\x41\xef\x3b\x75\x1a\xe9\x03\xa1\x71\xfc\x65\x9c\x3b\x99\x30\xae\xd0\x21\x08\x16\xdc\x15\x61\x99\x74\x9b\x8a\x1b\xa6\xa6\x71\x2c\xf0\x0e\x5c\x2c\x11\xeb\xf7\x41\x21\xc9\xfe\x57\x7c\xcc\xb4\x40\x12\x7f\xd8\xfd\xdc\x7a\xdd\xea\x4b\xf4\x1b\x85\x4a\x39\xc6\x16\xe4\xa7\x6a\x05\x99\x5a\x48\x38\xcc\x7d\x78\x64\xcc\x12\xc4\x89\xc0\x44\xd4\x97\x94\xab\x25\xe5\x6a\x49\xf1\xcf\x52\x7d\xa8\x32\x0b\x08\xc6\x5c\xa9\x6c\xfe\xa7\xe3\x02\xc5\xa0\x36\x6f\x72\xc4\x77\xf9\x6b\x05\x50\x9e\x5e\x49\xb5\xa3\xaf\x8a\xa6\x11\x7a\x25\x2c\xb6\xcc\xb1\x30\xcc\x2d\xab\x4e\x3a\xd8\xf9\x9a\xbe\x23\x27\x56\xfc\x84\xce\x32\xa7\x74\x89\xb4\x1d\x83\xf6\x75\x01\x0c\x66\xa7\x97\x79\x96\xa9\x32\x67\x59\x18\x3e\x8e\xa2\x67\xa0\x65\xf8\x73\x36\x32\x2a\x5e\xf1\x8b\x6c\x4d\xb9\x03\xc9\x6a\xfc\xaf\x6b\xa2\xb0\xa6\x89\x96\x96\xcc\x71\x6f\xf4\xda\x18\x25\x52\x80\x6e\x8c\x69\xa4\x33\xa6\x19\x49\xda\x8f\xb5\xa8\x44\xaa\x1f\x35\xfb\x99\x78\xd3\x7a\x86\x42\x5b\x2f\x64\x35\x87\x7f\x25\x05\xd6\x76\x2d\xfb\xfd\xa3\xfd\xbd\x68\x1f\x83\x57\xd0\xb6\xc3\x26\xab\xc3\x26\x9d\xea\x6c\x2d\x92\xf8\x8b\xa2\x72\x2b\x09\x6e\x03\x65\x72\x41\x19\x81\xcf\x2b\x76\x4f\xb9\xfe\x74\x6e\xe0\xc1\xb3\x20\xb8\x41\x81\x4f\x63\x2e\xac\xcb\x38\x24\xa2\x1b\xba\x5f\x98\x2f\xdf\xed\x18\x20\x1c\x48\x4d\xf9\x8c\xdd\xd1\x88\x98\x76\xe6\x5e\x56\x3d\xe4\xb8\x4e\xab\xb9\x5b\x81\x94\xba\x76\x09\x24\xf9\x3a\x15\xb5\x32\x9e\x0b\x15\x9d\x0e\x21\x61\xf4\xb7\xf6\x13\x6e\x06\xe2\x8b\x55\x20\xd3\x17\xbb\xa8\x84\x26\x5e\xad\x56\xc4\xe8\xf5\xe9\x56\x34\x53\x1d\x7e\xd4\xdd\xc8\x54\x4b\xff\xbb\xb7\xf4\x56\x9e\xc0\x6e\xfd\x1d\xa9\xca\xfe\x5c\x54\xde\x5c\xba\xa8\x0b\xc6\x59\x8b\x5c\x48\x61\x74\x10\xba\xac\x97\x16\xda\x06\xce\x1e\x54\xaf\xf6\x77\x0d\xf8\xad\xc8\x36\x4f\x8e\x61\xc2\xe1\x71\xaa\xc6\x05\x0f\x0b\x49\x98\x82\x01\x62\x41\xb7\xb6\x91\xcc\xff\x45\x34\x76\x34\x3e\x3a\x09\xf7\x03\xc7\xd5\x3c\xbd\x54\x6b\xc1\x48\xcd\xc1\x0e\x8e\x11\x6f\xee\x7b\xb3\x51\xbb\x51\x7c\x63\x13\xf8\xa6\xe7\x1d\xde\x14\x5f\x61\x52\x93\x26\xfa\xc6\x3d\xc4\x06\xfe\xb7\xa1\x2f\x4c\x49\x5b\xa8\xe9\xba\x6d\xc3\xed\x63\x43\x3e\xba\x11\xcb\xa7\xe6\xaa\xae\x6e\x17\x4a\x64\x23\xf4\x32\xe1\xad\x31\x3a\x64\x2d\x46\x87\x6c\x8b\xd1\x21\xeb\x31\x3a\xbc\xd8\x07\xcc\x8b\xb5\xad\xcf\x1d\xd3\x7f\x21\xa4\xf2\x5c\xbb\xea\xf4\xfd\xb1\xfe\x58\x6c\xc6\xcd\xcf\xe8\x40\xbb\x96\x62\x6d\x94\x16\xc3\x3f\x6b\x91\x0b\xca\x68\xdf\xbb\x7d\x9a\x11\xd4\x18\xce\xe8\x63\x2b\x91\x68\xd8\xb1\x9c\x5a\x83\x91\x9f\x0a\x6b\x53\x95\x33\xae\x46\x40\xac\xc1\xee\xbb\x38\xa3\x87\x44\x80\x26\x82\xc7\x25\x7c\xe9\x92\xfd\xd4\xdf\x4c\x7b\x88\x29\xa0\xee\x0f\x08\x27\x92\x1c\xae\x45\x03\x94\x7f\x23\x1a\xc4\xe0\x43\x03\x42\x62\x43\x10\x7c\xae\x37\xb1\x07\x4d\xa8\x06\xa0\xc2\x67\x52\x3b\x06\xf0\xbb\xd1\xc0\x87\x7a\x03\x47\xae\x01\xbf\xde\x87\xcd\x7a\x5f\xec\x5a\xbc\x81\xfb\xdc\x5b\x82\x57\xb5\x16\x07\xfb\xad\x2d\xbe\xaa\xb5\x68\xb5\xd7\xd5\x86\x34\x95\x0a\xbd\x38\x16\x55\x24\x6b\xeb\xec\xd8\x6c\xcc\xc7\x38\xa3\xfd\xa8\xae\xb3\xf3\x29\xce\xe8\x51\x3d\xe9\x44\x15\x6b\x38\x45\x39\x53\x69\xfb\xf5\xb4\xf7\x2a\xed\x80\xe4\x35\x31\x8e\xce\x7a\x1b\x67\x74\x30\x70\xa2\x9d\x86\x90\x74\x2f\x32\xca\x14\x6c\xc4\x62\x3b\x7e\x12\x04\xd8\x3e\xb6\x90\x54\x6b\x92\xb5\x2e\x09\x23\xda\xb7\x82\xc2\xfb\x6e\x6d\x3c\x05\xe5\x9f\x36\xf0\xb1\x5e\xe1\x27\x84\x91\x5c\x5d\xa5\x2e\xf2\x97\xa7\x25\xf3\x66\x4b\xa5\xc1\x9e\xab\xe5\x8f\xe1\x8b\xdb\x96\x5a\x2b\x7f\x38\x02\xc9\x6f\xe3\x80\x68\x37\x03\xdb\xfa\xfe\xa1\x59\x0b\x26\xbf\xef\x02\x94\xb8\x13\x34\xaa\x3e\xe3\xf1\xc4\x60\x75\xbf\x51\x3f\x50\xda\xaa\xa6\x2d\x1f\x37\x9d\xa0\xd8\xd8\xd4\xb6\x3d\x18\x60\x7a\xbd\xd0\x93\x04\xb9\x6e\xcc\x7a\xf5\x84\xd2\x5f\xe6\x7f\xb8\x51\x3b\x7a\xc3\x5c\xf1\xb5\x8e\x2c\x11\x52\x13\xac\x6b\xea\xc0\x69\x13\xea\x5a\x86\xa5\xe4\x53\x0e\x76\x74\xde\x15\xbd\xa1\x09\x5e\x2b\x6f\x22\x6d\xbb\x61\xd8\xb0\xdb\xba\x94\xb5\x27\x30\xc4\xd0\xa6\x81\x61\x2d\xb9\xb2\x31\xd4\xe9\x95\xfc\x9b\xfe\x2e\x51\x84\x4d\x6a\x5d\x0c\xae\xb2\x76\xfb\x36\xaf\x26\x61\xa7\xb5\x75\xf0\x92\x9a\xe2\x79\x5a\x35\x5c\x2b\xe7\x0b\xfa\x35\xa5\x56\x57\x06\xf0\x57\xe2\x9d\x4f\xb9\xd4\x64\xfa\xfe\xe0\x4d\xcf\xa7\x10\x2e\xe4\x38\xb9\x60\xb9\x73\xd2\xfe\x2a\x91\x49\x83\xd0\xf9\x7b\x83\xfc\xdf\x7b\x9a\xe4\x17\x20\x22\x28\xcc\x6b\x3a\x0c\x9d\x2e\xae\xcb\x1a\xef\x4d\x46\xfe\x0f\x1d\xbb\xc5\x04\x2c\xb1\xf8\x29\xbe\x22\x57\x4c\xbb\xd2\xa4\x34\xd7\x57\x64\x10\xec\xe4\xc4\xc1\x3b\x23\x75\x78\x96\x4d\x60\xf5\x1f\x2a\xbf\x16\xf5\x10\x1b\x82\x3a\xc7\xd3\x24\xd1\x14\x76\x46\xa7\x05\x52\xcf\x2b\x70\xa9\x81\x57\x32\x56\xcf\xcd\x7f\x30\xcf\x15\x98\x75\x7b\x5b\x60\x1d\x21\xb4\x6f\xf5\xa9\x36\x74\x3e\x2c\x6f\xab\xa0\xdc\xd3\xad\x2c\x6a\xba\x95\x05\x2d\x1a\x1e\x89\xd8\x9d\xd5\x55\x95\x9e\x0b\xc6\x0b\x81\x34\xd1\x8d\xf1\xaa\x5e\xa7\xe1\x8d\xf7\xbd\x21\x4d\xde\xb3\xfc\x82\x69\x9f\x5d\x2f\xeb\xad\x96\xa5\x6a\xa0\x4d\x4f\xb1\xc0\xc3\xe6\x1c\xfa\x18\xb7\x3c\xa9\x97\xc6\xbd\xf0\x50\x8f\x6c\x09\x3e\xe4\x6e\x05\xe2\x64\x49\x0a\x4f\x21\x92\xd3\xc2\x1a\xfc\xcc\x45\x83\x1c\x95\x76\xb6\x23\x59\x1d\xca\x58\x6e\x84\xc7\x27\x48\xd2\x69\x82\x12\x92\x61\xbc\xe9\xb0\x9e\x95\xee\x55\x94\x57\x82\x22\x03\x2b\x26\x0a\xa7\x73\xce\x9e\x63\x32\x4b\x90\x20\x12\x93\x59\x81\x04\xc9\x48\x82\x89\x07\xca\xbf\x78\x74\xb8\x76\x67\x66\xb4\x79\x34\x82\x1d\x21\x56\x39\x19\xb6\x0e\x23\x3d\x37\x28\x0d\xa3\xaf\xef\x2b\x4e\x07\xf7\x5c\xa4\xb5\x79\xc8\x68\xfa\xd4\x58\x79\xdc\x8f\xfc\x5e\x9d\xda\xa1\xf7\x4d\x23\xf3\x28\x7d\x2a\x47\x3c\xf6\x99\x99\x6c\x69\x38\x90\xc6\x9a\x09\x3a\xf4\x8d\xd9\xbf\x6f\x3e\x7e\xe5\xb2\x7e\x7a\xf5\x68\x9c\x56\xaa\x75\xe7\x92\x0a\x7e\x02\x21\x61\x0a\xf5\x16\x6e\xa6\xd5\x31\x86\xe1\x15\x83\x80\x03\x74\xbb\xed\x9d\x60\x9b\xee\x82\xd1\xac\xc5\xbb\x98\xc0\xc5\xb6\xa7\x2f\x43\xf8\x67\x00\x14\xf1\x93\x58\x3b\x25\xd8\x8b\x23\xa0\xee\xed\x4d\x50\xbb\xcf\x38\x29\x20\x2e\x24\x1b\x7f\x9f\x4f\xa8\x2b\x45\x3e\xe4\xe0\x0b\x90\x55\xae\xc6\x98\x27\xc7\x8a\xc1\x44\xb2\x0a\xc7\x5f\x8b\xc6\x6f\x70\x03\x92\x34\x1f\xb3\x09\xee\x9d\x5d\x30\xf9\x13\xcb\x8b\x54\xf0\xa1\xa0\x02\xc9\xde\x99\x8e\xa4\x64\x2d\xc1\xf9\xd7\x30\xe6\xe8\xab\x25\xe8\x58\x12\x31\x89\xbf\x5a\xce\x32\x82\x05\x2e\x01\x55\x9f\xa5\xe6\xd8\x7f\x12\x42\x52\x8f\xc4\xe7\xcb\xda\x93\x92\x69\x3c\xc5\x3c\xc9\xdd\x51\xe3\x77\xbf\x59\x00\x1d\xd6\x12\xd6\xeb\xa0\x03\x98\x66\x17\x9c\xb1\xee\x2e\x44\xca\xe5\xae\x35\xa4\xe8\x04\xae\xf0\x4f\x3a\xa6\x6f\x35\x96\x7c\x59\x3d\x37\x6c\x70\xa3\x56\xc7\x8a\x10\xe2\x48\x97\x48\x69\x52\x9f\xdc\x16\xc6\x9d\xb0\xaf\x17\x31\x14\x7e\xf0\x05\xcd\xd0\xfe\xa5\x40\x29\x1e\x66\x80\x01\x10\xc3\x65\xf9\x6b\x81\x24\x49\x09\x53\x0b\x68\x95\x2a\xb7\x0c\xa6\x11\xc1\x2a\x9d\x23\xb9\x5e\x23\x49\xd5\x03\x5d\x52\x36\x3a\x6a\x82\x57\x43\x9c\x1f\xfb\x11\xe3\xb5\x7f\x33\xbd\x09\xd2\x5b\xd2\xae\xec\x5d\x26\x85\x17\x1e\x79\x96\xc8\x64\x17\x06\x93\x0b\x21\x03\x8c\x31\xe9\x4a\xec\x18\xa2\x43\x6e\x34\x37\xa1\xd5\x21\xae\x3b\xcd\xe3\x4e\x99\x52\x1d\x3b\x38\xda\x11\x91\xa3\x95\x39\x69\x71\x37\x2a\x6d\x50\xec\x52\xfb\x04\xdb\x58\xe6\xb6\xc7\x9f\xb0\x9e\x24\x1e\x58\xe3\xa2\x5a\xe3\xfb\xa2\x16\x17\xcc\x5f\x72\x47\xc9\x77\xa0\x56\x05\x22\x62\xe9\xf3\x30\x06\xdf\x46\x42\x0c\x7c\x12\x62\x60\x48\x88\x74\x8e\xba\x7c\x89\xe4\x46\x50\xba\x28\xaa\xb4\xcb\xff\x5e\x61\x24\xc2\x71\xf9\x53\xd6\x08\xc3\x62\xb1\xa1\x79\x49\x78\xb2\x5a\x86\x41\x21\xb4\xc6\x20\x80\x3d\xf5\xb9\x1b\xeb\xf5\xa5\x70\x77\xc7\xbb\x94\x76\xa3\x2a\x7e\x2c\xa5\x88\x87\x39\x76\x5e\x1e\xde\x81\xb5\x9a\xac\x11\x05\x6f\x52\x85\xd2\xfe\xd8\x30\x1d\x7c\x9e\x34\xfc\x1b\x43\xe0\x3f\x69\x03\xff\xdd\x89\x0d\xf7\xc7\xef\x13\x54\xc3\x97\x0d\x63\xd9\xa6\x5d\xe1\x46\xc0\x61\x1d\x55\xc5\x12\x4b\xc0\x23\x3f\xb3\x44\xca\x54\xa0\x5f\x04\x11\xbd\x33\x33\x53\x7d\xee\x9b\x09\xb5\x58\xf8\x9d\xbe\xef\xe5\xbf\xe9\x2d\xca\x93\x59\xf2\xd0\xb8\xfc\xf2\xf8\x38\x78\xf4\x6b\x6a\xb6\x27\x46\x9b\xd1\x48\x2b\xf6\xa8\xa4\xdc\xfa\x16\xc5\x23\xa7\xba\xac\x8f\xe0\xb0\xa5\x62\x6d\x80\x10\x55\x38\xa7\xb5\x41\xe8\xee\x49\x33\xd2\xaf\xda\xcf\xdc\x8e\x5a\xda\x2e\x87\x5e\x44\x4e\x5f\x8b\x5a\xb4\x78\xc7\x42\xc2\x8f\x89\x09\x6e\xa0\x4c\x58\x4c\xfd\xbd\xc1\xe4\xd2\xa3\xf7\x27\x9d\x1b\x8d\x3f\x5f\x67\x79\x8b\xf3\x33\xe9\x38\x97\xbf\xdb\x85\x74\x31\x3b\xed\xe8\xcb\x77\xa9\x36\xdf\x3b\xd8\x3b\xac\xa6\xaa\x89\x38\x00\x55\xe7\xe5\xb9\x62\x83\x7a\xb0\x3b\xd0\xab\x67\x03\x9a\xf8\xda\xe7\x0d\x7f\xdb\x72\x33\xc1\xea\x9f\x63\xc2\x1a\x07\x8a\x08\x7a\x23\x90\x24\x8b\xea\x58\x91\x24\x01\x2f\xe7\x44\xd0\x34\xd5\xea\xe2\x92\xe4\x0a\xcd\xa8\xc4\x2a\xbe\x3a\xd9\x60\x89\x08\x47\x73\xb5\x0b\xf1\xed\x9e\x58\x9c\x03\xce\x37\x2b\x96\x09\xf8\x69\x04\x0b\xbb\x66\x68\x0c\x3b\x8f\x0d\x5b\xc9\x0b\x81\x72\x6c\x6f\xbe\x6e\x34\x84\x83\xaa\xd7\x14\xdc\xd9\xb6\xb5\x03\x0e\x45\x0b\xed\x0a\xaf\xf2\xf3\xae\x53\x46\xe6\xaf\x7e\x9e\x03\x01\x34\xd4\xb7\x60\xde\x26\xc2\xd2\x16\x91\x6d\xf2\xd3\x30\xbc\x51\xab\x98\x13\x50\xfd\x10\x66\xe4\x39\xbd\x48\x6a\x44\x16\x9c\xf2\xfa\xe3\x87\x4a\x72\xa7\xab\x82\x23\x09\x49\x7f\xf2\x36\xa1\x1b\x91\x44\xc1\x92\x09\xee\xa3\x16\x2b\x22\x5f\x5c\x01\xbd\x43\x2e\x12\xa4\x85\x4e\x73\x00\x0f\x62\x75\x52\x3c\xb6\xca\x90\xc5\x2e\xfe\xcc\x7f\x23\x40\xa1\x84\x0a\x75\xf7\xa5\x12\x23\xd1\x3b\x33\x2f\x0b\x6c\xd9\x48\x82\x24\x54\x0f\xdd\x77\xcd\xd3\x4e\x84\x38\xd4\x05\x4c\xd2\x51\x3f\x8e\xaa\x1b\x43\x57\x02\x42\xdc\xc1\x10\xa5\xf4\xc4\xb9\x5d\xeb\x6b\x8b\x1f\x4a\xcf\x5c\xd2\xbe\x3d\x96\x83\x12\x09\x35\xf8\x5f\x05\x12\x6a\x87\x12\xe7\xd3\x44\xd2\xef\xbc\xf5\x64\xce\xad\x45\x65\x73\x27\xe9\x8f\x0f\x97\x50\x45\x5e\x3d\x5c\x64\x3f\x96\xf4\xb5\x57\x44\x8d\xc3\xc4\x9e\xc6\x24\xf7\xca\x37\x58\x79\x7b\xd1\x01\x11\x3e\xe7\xce\xee\x6e\x15\x63\xd5\xe2\x08\xd1\xdc\x99\xef\x34\x6e\x02\x6f\xcf\x8d\x98\x36\xf9\x48\xc4\xbf\x0a\x94\x83\xd3\x5d\xdc\x08\x9e\xb3\xbd\xc5\x1f\xff\x5c\x8b\x70\x45\xe9\x2b\x38\xaf\xfb\x68\x75\xc6\x74\x4e\x1b\x26\xdf\x08\x7d\x3b\xd0\xce\x2c\xf2\x4d\x80\xdb\x7e\x11\x8c\x44\xcf\x0f\xc0\x46\x96\x89\x71\x46\xa1\x4f\x98\x21\x53\xc8\x66\x74\x7b\x5b\x4d\x41\x94\xc0\x8a\x60\x20\xde\xe5\xe7\x88\x0e\x94\xe8\x5e\x37\x3d\x76\xaa\x3b\xe8\x45\x42\xff\x78\x20\x48\x94\xaf\xc7\x4e\x5e\x27\xe0\x82\xfb\x77\x85\xc6\x00\x1c\x2b\xff\xb8\x8c\x8a\xaf\xbd\x5e\xb4\x63\x70\xed\x75\x96\xd5\xbc\xce\xa2\x84\xb2\xb1\x50\x8f\xad\x5b\x91\x5f\xbd\xe5\x1f\x73\x71\x91\xb3\xa2\x30\xef\xae\x8f\x79\x7a\x9d\xe4\xf7\xaa\xcc\x4e\x7f\x42\x7e\x30\xef\xa0\x44\x6b\x12\x72\xfa\x31\x31\x1e\x3d\x01\x28\x5d\x18\x6b\x3e\xe4\x43\x6c\x25\x4b\xbb\x7b\xd6\xe3\xfd\xba\x1f\x0d\xf6\x6b\x41\x45\x00\x51\x7d\xb1\x60\xc2\x0d\xed\xe5\x50\x54\x03\x88\x9d\xa7\x2c\xa0\xc7\x1c\x50\x84\xe1\x8f\x89\x05\x9a\x76\x40\x4c\xb6\x3b\x07\x86\xc1\x67\xd6\x4f\x74\xce\x38\xf9\x2e\x07\xb0\x1c\x69\x62\xc0\x86\x71\x4b\xc2\x10\x32\x92\x5a\x30\xc1\xfe\x01\x26\x3f\xa7\x1a\x68\xcc\x34\x32\x6f\x21\xac\x56\x78\x9d\x01\xe3\x06\xcc\x5b\x22\x2f\x3b\x52\xab\x11\x34\xf9\x2b\x04\x25\xd9\x80\x7b\xdb\xd9\xc8\x6e\xca\x6f\xb5\xbd\x8a\xfd\x55\xaf\x0d\xb7\xff\x0d\x27\xfb\xd5\x9f\x3b\xd9\xd6\xb9\xb3\xdd\xea\xe6\x50\x1b\x23\x38\x74\xde\xd5\x1e\xaa\x56\xed\xd8\xc6\x0c\xa2\x98\xc5\xab\xbc\x49\x38\x6f\x4e\x23\xdb\x08\x8c\xa2\xee\xa6\x8a\xf6\x2e\x36\x68\xef\x74\x8e\x34\xf9\x5d\x34\xc9\xef\x46\x02\x4d\x2c\x15\x06\x71\xf4\x0b\x9a\x99\x30\x81\xea\x21\x92\xd0\x65\x8e\x0a\x92\xe0\x51\x14\x47\xeb\x76\x5d\x92\xb3\x69\x92\x4d\x97\x59\x22\xd9\xcb\xcb\x84\x5f\xb0\xd9\x8b\x54\x16\xa3\x2d\xe9\xd0\x58\xec\x4c\x47\xf7\x8c\x91\x53\xe6\xd6\x88\x52\x0f\xc4\xc3\xb0\xeb\xbd\x93\x56\x3e\xe6\x72\x1c\x44\xa7\x0f\x64\xb1\x67\x61\x0f\x25\x68\x10\x3a\x15\x05\xec\x69\x4b\x59\x5f\x19\x35\x49\xab\xf7\x86\x5b\xe2\x55\x46\xcd\xbe\x39\x3d\xb5\x29\x5d\xd6\x04\xac\xb6\xbd\xa9\xd6\x38\x9a\x3a\x1e\x25\x68\xb3\x28\x12\x79\xda\x13\xe7\x05\xcb\x6f\xf4\xd4\xc3\x04\xe3\x55\x9f\x52\x5a\x18\xdf\xeb\x68\x6a\x43\x5d\x86\xbb\x36\xda\x25\xf8\x5d\x28\xc8\x14\xab\x7d\x32\xf6\xe4\xdc\xbd\x5b\xa6\xbe\xed\x83\x9a\xde\xd4\x95\xc1\x44\x24\x6e\xb6\x0a\xd0\x96\x2e\xcb\x1a\x60\xd3\xa9\x76\x8d\xa2\x97\x2c\xa3\xfd\xa8\x1a\x8c\xd1\xd7\xa8\xa2\x0e\x2a\x8c\x62\x57\xa0\x5a\x98\x0c\x5b\x47\x39\xb4\xa8\x34\xb1\x32\x5a\xd8\xc5\xc8\xf4\x62\x00\xfb\x56\x2d\x62\x25\xe1\xf3\x5f\x3a\x0a\xc8\x9c\xbd\xe8\xca\xed\x51\x56\x79\x50\x29\x4c\xa5\xcc\x25\x96\x05\xcd\x4a\x73\xbe\x44\xfd\x48\x6d\xc1\xc2\xce\x51\xab\x7d\x99\x92\x5c\x41\x74\xfd\x68\xe1\xaa\x29\xfb\x5e\xc8\xa9\xba\x82\xd2\x04\x09\x92\x54\x7e\x40\xfc\xad\xc4\xb5\xf7\xc3\x76\x04\xe5\x90\x62\x02\x04\x9a\x1d\x46\x63\x04\xe4\xb5\x99\x15\xd1\xc5\x74\xa1\xc4\xd0\x4f\xd6\xc3\xa3\x69\xe9\x85\xc5\x30\x2d\x2d\xf9\x15\x9e\x7c\x1d\x37\x7e\x05\x25\xfe\xbb\x94\xb4\x7d\xfb\xc0\x9b\x66\x84\x18\xed\x46\x04\xde\x33\x38\x06\x97\x5c\x76\x99\xcf\x35\xed\x22\xb0\x7d\x27\x00\xd5\xdf\x78\x25\xb0\x6a\x46\x6e\x3b\xab\x87\xf4\x96\x67\x6c\xf5\x78\x6d\x08\x2b\x1e\x1f\x98\xb7\x28\x2e\x89\x5c\x56\x1a\x34\xe6\x3d\x57\x23\xe4\xb5\x2c\x68\x83\x85\x5a\x31\xa1\x9b\x6d\x2c\x75\x0c\xaa\x4d\xfe\x57\x4b\x23\xe0\x68\xd2\xbf\x17\x87\xbf\x16\xd6\xa2\x19\xfe\xd4\xe2\xe6\x6b\xce\xb5\xd6\xd6\x2d\x09\x93\xb5\x71\xf6\x9d\x92\x64\x18\x22\x70\x18\xbc\x4f\x20\xa6\x20\x01\x5e\xff\x3e\xcc\xf5\x6b\x55\x0e\x9e\xf4\xa3\xc3\xc3\x83\x5a\x4d\x9b\xa6\x1a\xe0\xb2\xf9\xc8\xa9\xda\xb0\xa6\xda\x5a\x01\x8d\x82\x1f\xe9\x21\xb4\x0a\xaa\xa0\xd0\x16\xc7\x65\x49\x72\xd9\xe0\x98\xda\xfd\x44\xb8\x24\xbf\xb1\x0d\x0e\x9b\xe5\x23\xd4\xfd\xfe\x2b\x34\xa2\x23\xf3\x28\x4a\x16\x22\x18\x90\x2a\xc0\x01\xaf\x05\x38\x30\xee\xa8\x38\xd5\x71\x7f\x2b\x23\x15\x5e\x8b\xfa\x63\x68\x44\xde\xfb\x63\xc9\xf2\x7b\x6d\x87\x24\xf2\xe7\x59\x86\x74\xa7\x63\xd5\x09\x0d\x76\xbe\x3f\x3d\xf9\xd0\xd3\x0a\x2d\xe9\xfc\x1e\x05\xc1\x8e\xc4\x3b\x7f\x9d\x8c\x01\x75\x9a\x31\x4c\xfe\xaa\xc6\x15\x0d\x65\xa5\x2a\x2c\xad\xc8\x20\xa7\x7c\x2c\xc1\xaf\x6e\xae\x4f\x56\xde\x9b\x8b\xfc\x5a\x3b\x2d\x10\xf9\xb5\x15\x2c\x08\x75\x72\x80\x4f\x29\x1a\xaf\x87\xa3\x08\xe3\xe1\xaf\x28\xc7\x84\x33\x38\xa6\x65\x59\x6e\x0b\x80\x50\xbd\xd6\xea\x01\x10\x0c\x35\xae\x16\x4f\x47\x2e\x08\xc3\x54\x95\xee\x76\x79\x15\x55\x40\x92\x6e\x5f\xed\xd9\x19\xa3\x17\x05\x79\xdf\xdc\x1c\x9f\x51\x6f\x14\xbc\xf7\x7d\x17\x72\x6f\x04\x3a\x3a\x24\xcc\xb3\xd4\xb7\x95\x36\x3d\xcb\x25\x4d\xcf\x72\xe4\x2d\xf3\x0f\x11\x28\x4b\x1e\x69\x9f\xd3\xfe\xb1\xf0\xed\xbf\xdd\x51\x2b\x86\xb2\x8a\xc6\xb6\xe1\x1c\x1f\xc2\xba\xd5\x7d\x0e\x0f\xf6\xc3\xba\xd9\x87\xe7\x91\x4f\x1d\x37\x35\xa6\x12\x61\x72\xa6\x0e\x46\x49\x9e\xb3\x06\x0c\xd7\xdc\xa3\x0c\xfe\xbc\x1b\x3d\xed\xf9\x75\x49\x57\xc7\x37\x8c\xcb\x22\x1e\x73\x41\x72\x41\x84\x20\x9f\x19\xf9\xc0\xc8\x59\x41\x56\x86\x00\x8a\xbb\xfd\x72\x52\x92\x74\x49\x57\xf3\x94\xcf\xc0\x4c\xe4\xc5\xfd\x1b\x51\xc8\xb7\x26\x3e\x53\x2c\x05\x39\x5f\xf2\x59\x06\xc2\x83\x38\x22\x37\xfa\x75\x14\x07\xfd\x27\xbd\xa8\x37\x08\x88\x46\x74\x2c\xff\x98\x4c\xaf\x92\x0b\xf6\x21\xb9\x66\x71\xa0\x85\x36\x33\x71\x1d\x94\x24\x5b\xd2\x95\xd7\x44\xba\xec\x55\xbf\x5c\x73\xe9\xb2\x67\x3e\x5b\x1b\x4c\x97\xbd\x96\x64\x57\xf4\xa5\xe0\xf3\xf4\xc2\x2f\xa5\x53\x88\xb8\x61\x79\x9e\xce\xd8\x1b\x21\xae\x4e\x2b\xf6\xd5\x46\xf2\x2b\xd0\xb4\xfd\x98\xc8\xcb\x2d\x05\x3e\x31\x75\x62\x37\x0b\x78\x2f\xa9\x5a\xd2\xb6\x06\x21\xb3\xd9\x58\xc1\xa4\x75\xca\xa4\xb5\x49\x72\x93\x3e\xbd\x64\xb3\x65\x66\xe2\xdb\xea\xb4\x69\x33\x5a\xc1\x27\x36\x8f\xb7\x46\x32\x50\xbb\xea\x6f\xe7\x8b\x7b\xd8\xe3\xd8\x87\xdf\xfa\x0b\x0d\x31\xfa\x0b\x43\x0c\x63\x4d\xb0\x79\xca\x96\x25\xd9\x06\x23\xa9\x22\x63\x5b\xb3\xd6\xeb\x4d\x4b\x11\xb8\x76\x36\x46\x56\xbc\x16\x6a\x2a\x39\x2b\x2e\xeb\x93\x6f\x4f\x14\x42\xba\xb5\x33\x25\x6a\x4b\x77\xc1\xec\x6a\xe8\x09\x43\xa7\x20\xcf\x5b\xf2\x19\x9b\xa7\x9c\xcd\xaa\x10\xe9\x67\x67\x9f\x8e\x9f\xbf\xfc\x7c\xf6\xea\xf8\xa7\xcf\x27\x27\xef\x4e\xcf\xfe\xfe\xee\xe4\xc5\xf3\x77\x67\x6f\x4e\x4e\x7e\x38\x3b\x33\x92\xa8\x25\x7d\xb8\x18\x60\xd7\x62\xd9\x4b\x8b\x57\x69\xa1\xe8\xbb\x59\x18\x16\xcb\x5e\xb1\x5c\x2c\x44\x2e\x0b\x18\x06\xa8\xbe\x5f\x09\xaa\x8a\xf1\xdf\xd9\x54\xa2\x6c\x89\xc9\xa9\x4a\x30\x8a\xef\xd7\x0c\xaf\xca\x52\xf6\xce\xce\x4e\x8f\x5f\x7e\x3a\xfe\x7c\xf6\xf6\xc3\xe7\xe3\x4f\x1f\x9e\xbf\x3b\x3d\x7b\x75\x72\xf6\xe1\xe4\xf3\xd9\x8f\xa7\xc7\x67\x27\x9f\xce\x7e\x3d\xf9\xf1\xec\xe7\xb7\xef\xde\x9d\xbd\x38\x3e\x7b\xfd\xf6\xd3\xf1\x2b\x9a\x2c\x15\xad\x08\x26\x22\x1f\x45\x2e\x93\x8c\x0a\x95\xa2\x16\xfa\xd5\xc9\x7b\x60\xaa\x36\x6e\x5c\xa3\xf9\xd6\xf4\x3d\xd2\xaf\x49\x19\x6d\x2e\x73\xfe\xac\x1b\x6c\x59\x55\xc5\x71\xad\xe5\x56\x7e\xa5\x39\x9a\x4d\x8d\x95\xc3\x43\xdc\xd4\x00\x19\x1c\x1c\x92\x13\x60\xa0\xf7\xae\xd8\xbd\xba\xfc\x2b\x9e\x5e\x0d\x4a\x65\x2b\x94\x2a\xca\x71\x59\x5c\x9e\xde\xf3\xe9\x36\xcc\x5a\xf9\x6b\xe1\xce\xbb\x8c\x6a\xce\xf3\x88\x9a\xce\x91\x9b\xba\x76\x13\x53\xbb\x7b\xbc\x5b\x07\xbc\x4d\x01\x52\x57\x7d\x5b\xcd\xae\x26\xe9\xf1\x4d\x32\xc2\x7c\xe9\x9c\xd0\x28\x52\x95\x2b\x42\x6b\x93\x92\xfc\x77\x1b\xec\x9b\x06\x0d\x59\xe9\xf4\xba\x9f\xcb\x36\xe0\xe8\x82\x38\xbf\xd1\xf8\x7e\xd5\x76\xb7\xcb\xda\x44\xd8\x61\x88\x1a\xc2\x58\x3b\x06\x33\x90\x6e\xbf\x46\x8a\xb6\x36\x62\xee\xdb\x1a\x95\x8a\x31\xe9\x46\x66\xfc\xe6\x01\x75\x0e\x58\xce\x84\x0d\x2f\x14\x59\xe1\x65\xd6\x4e\x42\x2b\x95\xa8\x05\xc0\xe4\x3f\x90\xfc\xd6\x87\xa3\x37\xea\x74\x79\x2e\x73\xc6\xde\x72\x29\xda\xe5\xfa\x5a\x19\xcc\xac\x30\x6f\xdf\xbe\xea\x70\xae\xd7\xee\x6c\x6d\x9c\xbc\xa6\x99\xd7\x61\x6d\xe3\x75\x57\xdd\x3e\xc9\x61\x98\xe6\x7a\xa5\xf6\xe2\x2e\xc9\xde\xd1\xde\xe3\xd8\x80\x13\x7d\xb6\x0a\x96\x05\xeb\x28\x5a\x74\x2a\x83\x61\xb7\xd2\xef\xd1\x84\xd1\x9f\xc7\x9b\xad\x82\xae\x87\xab\xf4\xa6\x97\x6c\x7a\xf5\xea\xe5\x31\x20\xca\x6f\x2c\x8b\x7c\xab\xa1\xa9\xe0\x85\xc8\x58\x8f\xc1\x9a\x30\x5c\x96\x60\xf4\xc3\xee\x00\x09\x53\x8e\xf6\xf7\xf7\x0f\x71\x49\x8e\x8e\x06\x7d\x98\xfb\xc6\xcc\xdb\xd1\xd7\xe9\xfd\xf5\xb9\xc8\xc2\x50\xff\x55\x84\xa0\x45\x27\x55\xca\x90\x23\x4d\xf8\xd8\x37\x70\x80\x89\x4b\x82\xb0\xe0\x99\x9f\x32\xcf\x93\x8b\x66\x29\x3d\x88\xb3\x6b\x31\x63\xb5\xca\xb9\x98\xa7\x19\xcb\x1b\x69\x37\xe9\xac\x9e\x66\xf8\x45\xb5\x5e\x44\x7e\x9b\xe4\xb3\xb3\x9c\xcd\x6b\x1d\x19\x7a\xa3\x2d\xed\x2c\x4b\x8b\x5a\x1b\xd7\xec\x5a\xf8\xbf\xb3\xe4\xcb\xbd\xff\xfb\x3c\x13\xd3\xab\x5a\x4b\x2c\xbf\x61\xf9\x66\xfa\x7c\xc9\x67\x09\x28\x4a\xd6\x56\x62\xc6\xce\x97\x17\x67\x32\x4f\xa6\x6c\x63\xea\x19\xbb\x48\xa6\xf7\x67\x97\xe9\x6c\xc6\x78\xa0\x70\xec\xd1\xe1\xc1\xfe\x36\xb0\xe5\x48\x6d\x2c\x2e\xc9\xe1\x41\xfb\xee\xea\x3d\xfb\xa6\x0d\x1e\x72\xff\x57\xcb\xd6\xb6\x65\x57\xdb\xdc\x96\xeb\x6f\x79\x5b\x7e\x63\xfb\x5b\x3b\xf0\x40\x61\x4b\xbe\x03\x8b\xb6\x7c\x0f\x44\xda\xb2\x93\xe2\x9e\x4f\x1f\x1c\xc0\x54\x70\x43\x83\x3e\x58\xac\x01\x77\xad\xb3\xf5\x60\xf0\xa1\x7c\x07\x8f\x6d\x85\x2c\x6c\xb6\xe5\x59\x38\x6d\xcb\x73\xb0\xd9\x3a\xf8\x3a\x9c\xb6\x15\xc9\x59\xb1\x10\xfc\x81\x85\x2e\xa6\x62\xc1\x02\x5c\x92\x83\x83\xbd\xed\xe0\x7a\x78\x80\x4b\x32\xd8\x8f\x0e\xb7\x15\x31\xaf\x7c\xf4\x64\xbf\x7f\x88\x89\xa0\x07\x51\x3f\xda\x23\x09\xfc\x3d\x18\xca\xde\x6b\x03\x52\x90\xf0\x84\xc8\xde\x29\x54\x7c\xaf\x6e\x74\x95\x74\x48\x64\xef\xa3\x81\x19\x95\xd0\xdf\x1f\x6a\x5d\x37\x95\x79\x44\x32\x48\x8b\x48\x01\x7f\x07\x43\xd9\xb3\x2f\x11\x48\xd8\x1b\x6a\xbe\xb6\xfa\x7e\x4c\xa6\xf0\xf7\xe0\x4f\xa2\xc8\x99\x8f\x22\x05\x9d\x6d\x9e\xa4\xa4\x4a\x74\xe7\xc7\x9b\xd9\xac\xe5\xf8\xd4\xe6\x39\x6b\x3f\x3f\xde\xc4\x67\x2d\xc7\x27\xad\xa5\xda\x43\x93\x55\xa9\xd5\x51\x29\xbc\x31\xd4\xe0\xda\x5b\xae\x59\x0b\x58\x2f\xab\x54\x03\xa7\xd3\x2a\x45\x43\x27\xf8\x1a\x9b\x7f\x03\x46\x4a\x25\xcb\x13\x29\xf2\x2a\x2e\xdb\x42\x5d\x78\x55\x58\xf5\xe0\x52\xca\x45\x11\x3f\x7a\x04\xcd\xff\x5e\xf4\x44\x7e\xf1\x68\x26\xa6\xc5\x23\xb8\x0c\x77\x67\x6c\x2a\x66\x2c\xef\x5d\xca\xeb\x6c\x94\xf2\x9b\x24\x4f\x13\x2e\x69\xb0\xc3\x08\xa7\xfd\x21\xdf\x20\x83\x86\x7c\x67\x07\xcb\x1d\x1a\x84\x49\x7e\x51\x8c\x27\xaa\x28\x57\x6d\xfc\xf8\xe9\xad\x23\x1e\x51\x45\x14\xf1\x89\x25\x3f\x82\xf7\x29\x07\xbf\xc3\xc6\x8f\x31\x0c\xa0\xf3\x97\x60\x87\xed\x04\xc3\xce\x4d\x5a\xa4\xb2\x13\xec\xc8\x9d\xa0\x33\x17\x39\x78\x19\x9e\x2f\xb3\xac\x73\xcd\x8a\x22\xb9\x60\x1d\x91\x77\xd4\x11\x50\xe9\x5c\xf0\xdd\x6b\xdb\xd8\x8c\xdd\x74\x18\xbf\x49\x73\xc1\x55\x8f\x50\x19\x2a\x42\xfb\x45\x27\xe1\xb3\x4e\x32\x9b\x41\x4c\xb8\x24\xeb\x5c\xb2\x6c\x31\x5f\x66\x9d\xdb\x24\xe7\x29\xbf\x28\x7a\x41\xa9\xbd\x7e\xaf\xd2\xe2\xbd\xa2\x80\xd9\x2c\xde\x78\x9e\x76\xfb\x25\x61\x1c\xbc\xc2\xbf\x16\xf9\xd4\xbe\xbd\xbd\x72\x2e\xff\x13\x03\xa7\xc7\x9a\xaf\xd0\x56\xe0\x14\xdc\xeb\x34\x32\x4b\x72\x4d\x57\x65\xb5\x8b\x37\x35\xe3\x95\x85\xb6\x06\x24\x35\xbb\x11\xe9\x4c\x5a\x0b\x7a\x4d\x3c\xbb\xd4\x9c\xf2\xf5\xfa\xd2\x8b\xf0\xa0\x3a\xa8\xc2\x33\xfc\xe7\x2d\xdf\x78\xdc\xe8\xa6\x39\x28\x5d\x95\xc4\xcf\x2f\xcc\x6c\x37\x95\x58\xad\x3a\x54\xd7\xb3\x10\xab\x00\xbe\xbb\x61\x37\x56\x0f\x23\xba\x40\x10\x85\xce\x1f\x5c\xaf\xb1\xc0\x48\x65\xc2\x23\x27\xb0\xa3\x50\x98\xd7\x1f\xdd\xbc\xda\xcc\xda\x4b\xa7\xad\x59\x6f\xe3\x6d\xcb\x81\x57\x5f\x35\x7d\x51\x35\x4d\xbd\x6e\x8c\xef\xf2\x7b\x2f\x97\xb3\xdb\xce\xc5\xf0\x5c\x2d\x79\x21\xf3\xe5\x54\x8a\x9c\xde\x93\x1c\x9d\xfb\xc3\xc3\xe4\xbc\x97\x16\x1f\x97\x39\x6b\xac\x71\x37\x32\x2e\xc8\x1d\xcb\x4e\xb3\x4f\xee\xa8\x79\x21\x57\x33\xbc\x4c\x8a\x93\x5b\xfe\x31\x17\x0b\x96\xcb\x7b\x72\x4c\x57\x57\xec\x3e\xee\x46\x24\x67\x73\xf5\xe7\xec\xac\x60\x99\xfd\x02\x6d\x89\xb8\x1b\x79\x80\x78\x55\xd3\x43\x25\x89\xda\xdf\xd4\x38\xde\xa7\x4e\xbb\xde\x70\xc1\x21\x5e\x4f\x27\x35\xd1\x4d\x23\xd0\xac\xcc\xd9\x1c\x8c\x35\xe1\x0b\x13\x2f\xe7\x8a\xdd\x87\x21\x4a\x69\x10\xec\xc0\x0f\x4c\x24\xbe\xd3\xda\xbb\x92\xe4\x38\x0c\xbb\xc7\x8d\xe1\x23\xb0\xa3\x48\xc6\xf9\x84\xca\x71\x3e\xb1\x46\x2d\x4d\x14\xb5\x3b\xb0\x0c\x8b\x02\x27\x95\xc4\x97\x3b\x6b\xd1\xfe\xd3\xa2\xc2\x91\x4b\xfa\x3c\xcf\x93\x7b\x54\x28\x3c\x1c\x0d\xa7\x4f\x8b\xe1\x74\x67\x07\x2f\xc7\xd3\x89\xf7\xd0\x9b\xee\x0c\x26\x43\xaf\x31\x08\x1e\xc7\xc2\x90\x59\xd7\x63\x5a\xc6\xe6\x56\xa0\xa0\x8d\x1c\xf7\x60\x53\xc3\xb7\xb3\x28\x60\x16\x4d\x63\x23\x41\xd4\x47\xcc\xc0\xe6\x28\x85\x9d\xca\x08\x9c\xd4\x38\x21\x67\xe0\x06\x2d\xbe\xb5\xe2\x6a\xcf\xe8\xe2\xb4\x62\xdc\x3d\x64\x7e\xa9\x06\x6d\xfb\xa2\x94\x8a\x52\xfb\x7c\x7a\xf4\xcf\x47\x3b\x8f\x2e\xaa\x9d\xff\xcd\x7f\x16\x3f\xdc\x9e\x39\xa0\x6a\x13\x47\xfe\x31\xd2\x57\xd0\x2a\xa0\x41\x1c\xd0\x28\x20\x41\xac\x3e\x06\x41\x69\x6f\x84\xef\x82\x1d\xd6\xcb\x35\xc6\x44\x8f\xc6\x34\x9e\x3c\xba\x20\xa8\x85\x0f\x29\xc7\x6c\xa2\xde\xfb\x28\x50\x35\x14\xb0\xc4\xb2\x27\xc5\x29\x08\x49\xd0\xde\x81\xef\x46\xdb\x89\x0e\x52\xab\x92\x6f\xc7\x3c\xac\xbd\x57\x69\x16\x86\xc1\xb9\x10\x19\x4b\x38\xfc\x5c\xaf\x91\xf1\x4c\x62\x00\xab\xdb\xf7\xbc\xf1\x32\x5c\x58\xfd\xe9\x8e\x11\x19\x65\x46\x64\x64\x8c\x8f\x41\x3e\x18\xf0\xe5\xf5\x39\xcb\x83\xb8\x70\xb1\xf8\xb5\x5c\xc4\xac\x60\xbc\xcd\xf8\x55\x68\xf1\x62\x02\x15\x21\xee\x43\x61\x59\x4d\x29\x4d\x51\x41\xc1\xb5\x6c\x00\xe1\xb5\x47\x41\x2f\xd8\xf9\x0d\x15\x24\xc2\x71\x4e\x00\x7e\x7b\x69\xa1\xe1\x38\xc5\x23\xc4\x69\x10\x18\xc9\x2a\x33\x61\x7d\xed\x2a\xbf\x24\xc1\x77\xe1\xa3\x00\xef\x04\x8f\x02\x4c\x3e\xa2\x14\x16\x2b\x08\x5a\x97\x9d\x95\x18\x63\x23\xc9\x49\xc3\x10\x9d\xa2\x14\xc3\x99\x6d\x63\x9d\x6c\x02\xb0\x16\x08\x2b\x28\x96\x00\xc5\xda\xfe\x5b\x43\x32\xd3\x77\x8f\x85\x67\xd6\xd3\x1f\x65\x89\x52\xc2\x77\x50\x37\x55\xbb\xbc\x5e\x17\x61\xa8\x3d\x44\x50\x0a\x29\xa3\x20\x88\x15\x10\xc0\x0f\xdc\x3e\xab\x1d\x06\x82\x73\xd0\xcc\x4a\x31\x26\xb0\x8b\xe0\x45\xcb\x5b\xbe\x38\xdf\x09\xe2\xa0\xb1\x76\x0c\xe3\x0a\x2d\x44\xc3\x65\xa5\x1c\xb6\xb4\xc2\xb5\x29\xcd\x77\x7e\x43\x19\x65\xe3\xe5\x84\x2c\xf1\xb0\xd8\xa1\x1f\x91\x96\x3b\x4d\x49\x5a\xc5\xff\x9f\xd2\xed\xec\x74\xb6\x5e\x6f\xde\x7e\xc6\xaa\x70\x83\xe4\x43\x8c\xce\xc3\x90\x8d\xe7\x93\xf5\x9a\x8d\x83\xff\xfa\x2f\x4b\xf3\x05\x13\x3c\x32\x71\x3d\x11\xc3\x6d\xf6\x12\x53\x63\x59\x34\xb5\x36\x11\x44\xcd\xaa\xab\x46\x0f\x2a\x1a\x08\xe3\xde\x4c\x70\x36\xc4\x7a\x16\x4e\x27\x07\x66\xa3\x27\x4a\xd4\xcc\x49\xea\x99\xda\x3b\x54\x40\x33\x17\x3f\x4f\x1d\x4b\x62\x6f\xe6\xbd\x3e\x09\xc6\xba\x54\x47\x5f\x48\x93\x00\x0c\xa8\x4c\xd5\xce\x6d\x2a\x2f\x3b\x57\xec\xbe\xe8\xac\x82\x9d\x3a\x53\xb7\xf7\xbb\x48\x39\x0a\x48\x47\xed\x65\x19\xc4\xb2\xe2\x5e\x15\x9e\xf7\x7a\x8f\xdf\xd9\xe0\x57\x33\xf3\x38\x1a\x4f\x20\xaa\xbc\x0d\x45\x80\x18\xc9\x15\x94\x6f\x01\x74\x6d\x9b\x07\x0e\x7c\xc4\xce\x0e\xf0\x15\x73\xcf\x53\xb8\xe1\x7e\xee\x6a\x26\xf8\x59\x21\x13\xb9\x2c\xaa\xf8\xdb\x67\x39\x2b\x96\x99\x1c\x4a\x2a\x81\xb1\x64\x0a\x80\xbb\x6b\x93\x07\xd6\x62\x10\x1b\xa4\x16\x43\x3b\xf2\x1b\x04\x67\x2b\xd2\x5e\x1b\x5e\x3b\x7d\xbf\x1d\x5c\x62\xf2\x60\x1b\x55\xbd\x41\xa3\x9e\xb3\xa0\xac\xe6\xe0\x22\x8b\xb9\x39\xc0\x8e\xba\xdf\x70\x39\x7c\x6e\x10\x1a\xd5\x25\xf1\xc1\x69\x1f\x7c\x76\xd1\x1f\x7c\x94\x59\x27\xd9\xf6\x06\x5e\x60\x05\xed\x50\xf9\x8c\xae\xda\xa5\x54\xf1\x67\xe2\x67\xbc\x50\xa9\x46\xa2\xb7\xaa\x82\x3c\xc7\x51\x49\x36\x62\x72\xc7\xb7\xe4\x6d\x71\x2a\xae\xd9\x27\x23\xf7\x7b\x3e\x95\x29\xbf\x88\x7d\x01\x27\x49\x8a\x22\xbd\xe0\x71\x5e\x0e\x65\xcf\xd9\x71\xaf\xae\x93\x45\xfc\x89\x18\x89\x6e\xdc\xe4\xae\x2b\xb0\xab\x69\x4c\xf4\x92\xc5\x22\xbb\xd7\xe4\xa0\xa3\x15\xd4\x06\x71\x5c\x92\xa9\x7a\x4d\xc4\x9b\xf7\xa1\x03\xca\x8d\xe6\x76\x76\x14\xe0\xc9\x92\x48\x01\xf8\xa8\x4d\x22\x57\xaf\x54\x47\xd5\xeb\xf5\x78\x52\x12\xc1\xb3\x7a\xcd\x74\x8e\xba\xa7\x4d\xb6\xfd\x02\xf5\xf7\xf7\xfc\xdd\x28\x89\xec\x55\x24\xe6\x8d\x7a\x28\x2f\x73\x56\xa5\xdc\x93\x7f\x4b\x00\x75\x46\x64\x6f\x9a\x09\xce\x8c\x35\x5a\x9b\xc8\xc2\x1e\xe1\xfa\xf8\x06\x07\x4f\x08\x33\x96\xcb\x09\xcd\x91\x7a\x42\xe9\x4b\x43\x3d\xd3\xb5\x77\x81\xcc\xf8\x14\x51\xe4\x96\xbe\x40\x7c\x7a\x74\xe5\x84\x50\x9b\xa4\x28\x29\xe8\x6d\x65\xc3\xf1\x20\x59\xca\x8c\xb2\x87\xfe\xdb\x20\xeb\xe0\xaa\x68\xc9\x01\x65\x8f\x29\xc4\xcb\xa9\xa8\xda\x69\x2b\x55\x3b\xd5\x54\xed\x74\x52\xd9\x0d\xcb\xf1\x74\xe2\x09\x1c\x96\x23\x45\x8e\xc6\x2a\x55\xf3\x06\xa6\x0f\x10\xbd\xd3\x6d\x44\xef\x14\xaf\x2c\xb1\x3b\xc5\x4e\xdf\x70\x46\xa3\xe1\xec\xe9\x74\x38\x03\xa2\x77\xe6\x13\xbd\xb3\x0d\xa2\xf7\xeb\x37\xfd\x16\x7a\xb5\x00\xf8\xd2\xe2\x17\x6b\x51\xdd\x2a\x7f\xa9\x96\x00\xd0\xa1\xb6\x36\x42\x8c\x56\x7d\x66\xa4\x55\xe5\x33\x96\xa4\xa6\x70\x1a\xb3\xfa\xef\x81\x4a\x90\x97\x39\x4b\x66\xe0\x60\x37\x8e\xc8\x47\xc3\xe1\xd1\xd2\xe1\x97\x82\x17\xcb\x6b\x2b\x16\xc6\x3d\x9b\xeb\x75\x9d\x12\xab\xf8\x1a\x33\x05\x8d\xb6\x0a\x65\xd5\xec\x2c\x9c\x5f\xb9\x94\xd7\x89\x7a\xdf\xdd\xd3\x4d\x54\x70\x55\x8b\xd5\xe9\x0c\x50\x8c\x43\x22\xc0\x04\xd6\x3b\x2f\x9b\xd3\x0d\xb6\x44\x1d\x2b\x83\x90\x53\x33\xa2\x6a\xa5\xd9\x26\x81\x56\x18\x25\x89\x58\x1f\xfb\xb4\xf8\x29\xc9\xd2\x99\x1d\xf9\x29\xd1\x7c\xa8\x07\x9b\x98\x12\x6b\xa9\x12\xaf\xcc\x65\x12\xef\xf6\x89\xb9\x36\xd4\xf2\x80\x49\x4b\x7c\x02\x3d\x5c\xb3\x6b\xf1\x15\xa2\x71\x69\x5f\x3d\x53\x71\xbd\x48\x72\x56\xc5\xe9\x32\x3e\x89\x24\xb4\xb4\x2c\xd8\x4b\x6b\x46\xdf\x0a\x40\x1f\x10\xf6\x0b\x69\x33\x73\x53\xf1\x21\xc0\xb3\xf5\x74\x19\xbf\xda\x2b\x76\xbe\xbc\xd0\x4a\xcc\x35\x86\x0e\x64\x1a\xab\xb8\x87\x9a\xd4\x45\xfc\x16\xdf\x5e\x2f\x14\x0d\x97\xde\x18\xd5\x8e\x0d\xa4\x58\x6f\xa0\x59\xdc\xaa\x1d\xea\xc6\xde\x25\xf7\x62\x29\xbf\x61\x1c\x7e\x41\x7f\x34\xef\xb7\x6d\x8e\xad\xa8\x0a\xf8\x15\x3e\xb1\xd9\x72\xda\x22\x7d\xae\xd7\x32\xa5\xea\x83\x6d\x87\xcc\xaa\xca\x1c\x31\x5b\xb4\xc9\x37\x6a\x16\xd6\x4c\x1e\xb6\x45\x8e\xf9\x64\x70\xb4\x55\x20\xe4\x8b\xfe\x06\xfb\xd1\x21\x2e\xc9\xe3\xbd\x07\x44\x43\xda\x3d\xd5\xb0\xcd\xad\xd1\x82\xe5\x73\x91\x5f\x27\x7c\xca\x5a\x45\x9b\x5e\x7e\x8f\x8b\x5b\x6b\x53\xee\x25\x0f\x3d\x61\x31\x17\xb7\x9b\xa7\xbc\x93\xaa\x9a\x08\x6b\x85\x6a\xf3\xa4\x7d\x95\x48\x46\x0a\x9a\xe9\xac\xaf\xb7\x61\x0a\xee\x16\xf0\xb2\xf4\xde\xc1\x6e\xa4\xda\x6b\xba\xef\x60\xd2\xbd\x4d\xde\x6b\x16\xac\x42\xb6\x9c\x65\xce\xf3\x06\x68\x1e\xe9\x3f\x33\xda\xaa\x31\xb7\xc4\xd6\x53\x29\xa3\xf5\x21\x22\x3c\x5c\xa2\x6e\x44\xe0\x4d\x02\xe8\xab\x0a\x49\x06\x54\x40\xc1\xc0\x99\x8d\x58\x4a\x34\x23\x11\x26\xac\x2c\x87\xf5\xe8\xf4\xb6\x8f\x91\x57\x94\x13\xd5\x64\x8c\x96\x94\x91\x46\x0b\xb8\x24\x4d\x53\xfa\x29\xf5\xca\x68\xf8\xae\xd9\x95\x4f\x33\x96\xe4\x36\x7f\x5a\x97\xeb\x17\x97\x62\x99\xcd\x7e\x4d\x59\x36\xdb\x5c\x6e\x20\x30\xfd\x19\x03\xa3\xf0\x75\x9e\x5c\xb3\x4f\x35\xa0\xc6\x2b\x6f\x57\xe7\x54\xef\x41\xaf\x1a\x15\x59\xd8\x34\x7f\x2c\xdb\x54\x96\x8c\x9c\xdb\xc6\xb1\xb4\x35\x15\x94\x65\xcf\x79\x7a\x0d\xf6\x4f\x30\x8a\x61\xcb\x2e\x9b\xe2\x39\xfb\x63\xc9\x0a\x59\x2f\x1f\x86\x75\x19\x7a\xf0\xf9\x32\x2d\x3a\xe7\xb9\xb8\x2d\x58\xde\x99\x09\x56\xf0\xbf\xca\x8e\x51\x6b\xea\xb4\x36\xd1\xeb\xbc\x4f\xae\x58\xa7\x58\xe6\xac\x23\x2f\x13\xd9\xb9\x17\x4b\x88\x1a\xd8\x49\x3a\x0b\x91\xdd\xcf\xd3\x2c\x53\xe4\x92\x8e\x16\x68\x9a\x2e\x7a\x9d\x36\x01\x46\x96\xf2\x2b\x9d\xb0\x6b\xab\x16\x81\xff\x04\x76\x93\xba\xfc\x73\x23\x6f\x5b\xab\xff\xf9\x81\x97\x3a\x74\x68\xb7\x4f\x6e\x8c\x9d\x2e\xdd\xed\x93\x7b\xfa\x18\xbc\xce\x7f\x2b\xd0\x75\x9a\x27\xec\x19\x3d\x57\x60\xd8\xbc\xb3\xbe\x06\x93\x0c\xaf\xa2\x67\x6c\xbd\xee\x0f\x1e\x3f\x65\xa3\xc6\xea\xd5\x2b\x75\x64\x72\xc5\x0a\x58\x07\xf5\x1e\xbb\x61\x9d\x94\xcb\xce\x39\x93\xb7\x8c\xf1\x4e\x04\xb2\x97\xfe\xe0\x31\xe9\xa8\x6a\x29\xbf\xe8\xcc\x55\xcd\x4e\x9e\x48\x56\xd8\x88\x92\xf2\x32\xe1\xaa\x50\x67\xbe\x28\x3a\x69\xd1\xe1\xc2\x6d\x07\x9b\x05\x38\xbe\xa7\xd1\x53\x36\x82\x48\x0b\xf3\x4c\x88\x1c\xf5\xd9\xde\x23\x86\xe3\xc7\xa5\x61\x82\x73\x76\xdb\xc0\x50\xe4\x8e\xde\x82\xd0\x70\x30\xd4\x7f\xfb\x3d\xc1\x8d\x1c\xa9\x1d\x51\xdd\xe0\x6d\x58\xea\x9c\xb2\x9d\x7b\xed\x70\x59\xe3\xab\xd1\x5d\x6f\x21\x0a\x69\x7a\x34\xe1\x52\x90\xb7\x7b\xb8\x89\xca\x5a\x2a\x10\x6b\x51\xa4\xea\x95\xa4\x8e\xd8\x6e\x28\x23\xd7\xeb\xb5\x6a\x33\x22\x2d\x95\x9b\x98\x8c\xe3\xd5\x05\x9d\xd7\xd4\xab\x18\x6a\x4e\xc4\xbe\x4a\x6b\x08\x6e\x81\x2e\x30\x00\x9b\xc7\x45\x3e\xae\x3b\xf1\xb4\xfe\x68\x8c\xc3\x17\x3c\x64\xb1\x1f\x7a\x39\xa7\x7c\xb7\xff\xec\xd9\xb3\x3e\x11\x94\x8d\x73\xd0\x3a\xef\x56\x8f\x2e\x11\x86\xd1\xd3\x97\xe0\xe9\xc8\x44\x04\xea\xb0\x21\x03\x06\x3e\x81\xd8\xf0\x82\x70\xea\x07\x86\xbf\xf2\xee\xf9\x2a\xcc\x08\xa3\x6c\x1c\x4d\xac\x5e\x5f\x83\xe3\x6d\xb8\x30\xe3\x68\x32\xac\xbd\xf7\xaa\x39\x2c\xc4\x02\x69\xf5\x29\x9d\xae\xca\xaa\x97\x51\x5c\x0f\x1e\xe8\x26\x9b\x3f\x15\x43\xab\x76\x3e\xf8\x1b\xca\x77\xfa\x78\xb7\xaf\xde\x9c\xe3\x64\x42\x32\x9a\xec\xf4\xd5\x83\x73\x9c\xd5\x3b\x4c\xc3\x30\x7a\xf6\x12\xa5\x84\x63\xec\x12\x0b\x9d\x58\x90\x14\x8f\x10\x4c\xbc\x20\xaa\x26\x04\xf5\x52\x80\x03\x69\x29\x51\x4d\x43\x5a\x52\x59\xcb\x7a\xeb\xe8\x9a\xe1\xcd\x75\xf4\x9b\x2b\x4b\x67\x9a\xe4\xab\x46\x7a\x31\x2b\x1b\x0e\x86\x45\x2e\xdf\xf2\x19\xbb\xdb\x95\xd5\xb7\xe7\xb1\x9f\xf2\x11\x78\xd9\x9b\xed\xca\x5e\x3a\x03\x2c\xf5\x1b\x1d\x4f\xc8\x47\xf5\xcf\x27\xda\x27\x27\x1a\x5d\x7d\xa6\x7b\xe4\x83\x3a\x00\x67\xea\x9f\xf7\xb4\xdb\xaf\x38\x44\x6f\xeb\xf2\xe8\x2b\xf4\xd1\x59\xc8\xc9\xa1\xef\x9f\xbc\x72\x8f\x85\x4f\x55\xa1\x6a\x15\xa4\x8e\xc1\xa2\x2e\xbf\xa7\x94\xd9\xc8\x52\xaa\x10\xf1\xc6\x4d\x65\xc3\xd9\x1d\x39\x46\xbf\xa9\x3b\x5d\x77\xea\xc1\xd8\x73\xc3\x14\x51\x03\x25\x6a\x7c\xa4\x7b\x86\x2b\x5c\x70\x85\x7e\xc3\xf8\x4c\x9d\x3d\x8e\xde\xe1\x2a\x78\x71\x63\xf0\x61\x98\xa3\xe7\xc4\x1b\xdb\x2e\xf3\x3b\x79\xa7\x0f\xa6\x5e\x91\x30\xd4\x9d\x41\xbc\x84\x0f\x56\x7e\x97\xd0\xcf\x43\x1b\xdf\xe3\x2d\xe2\x98\x9c\x40\xdf\xb6\x87\x93\x30\x44\x5d\x74\xd2\x98\xd5\x33\x8e\xd7\x6b\x16\x86\xdd\xf6\x6b\x01\x61\x3c\xb4\x44\xe6\x89\x5b\xd1\x2d\xca\x19\x29\x5e\x55\x65\xec\x56\x9e\xf4\x16\xc6\xb3\xe0\x3b\x76\xc3\x32\xe3\xcf\x21\xdd\x18\xc8\x53\x08\xeb\xb8\x81\x30\x5b\xdd\xe3\x8f\xbc\x6e\xb2\xf8\x84\xea\x45\x0e\xc3\x53\xf4\x1b\x26\x6a\xea\x1a\x19\xaa\x9f\x43\xbd\x08\x9e\x19\xdf\x09\x36\xd2\x98\xa8\xda\x8b\x65\x6d\x2f\x96\x7a\x2f\x96\xde\x5e\x70\x4c\x0a\x85\x5a\x2b\xde\xb1\x55\xcc\xb5\xf3\x4c\x00\x64\x4b\x80\xea\x2f\x34\xf1\xaf\xd9\xb7\xb3\x8c\x39\xf7\x8a\x8f\xfd\x3b\xf3\xed\xf5\x35\x9b\xa5\x89\xac\xb2\xfb\x7e\xf6\x3b\x71\xeb\x32\xf6\xfd\x8c\x0f\x8a\xd8\xcf\x5c\xde\x9e\x9f\xa7\xf5\x51\x9c\xe3\x15\x2f\xe7\xc7\x82\xe5\x2f\x32\x31\xbd\x02\x5b\x3a\x53\x77\x50\xd3\x67\x05\x7a\xa5\xe5\x41\x8c\x57\xac\xbe\xb3\xb5\xab\xdf\xc6\xf3\x3d\xbe\x63\xd3\xa5\xaa\xe0\x5f\x0a\x67\xeb\xf5\x87\xf5\x1a\xb9\x13\x50\xa7\x7b\x2b\x1d\xfa\x8f\x3e\x98\xb4\x90\x23\x9f\x9b\xf5\x5e\x83\x55\xab\xef\xd5\x72\xb3\x12\xec\xbd\x5f\x8f\xd7\x1f\xec\xce\x5c\xeb\xb3\x11\x9b\xf5\x8d\x55\x5e\x6c\x5c\x26\xe8\x93\x6a\xa3\x90\x59\x8f\xb4\x92\x7e\x2e\x35\xd6\xfb\x3c\xfc\x4c\x65\xdd\x7e\xa6\xd2\xda\xfe\x4c\x79\x59\xeb\x7d\x91\xa8\xf7\x7b\xdb\x2a\x35\x94\x7c\x81\xe0\xfd\x98\xa4\x5c\xd2\x2f\xb5\x9c\x25\xff\x39\x95\x97\x6e\xf7\xea\x0f\x90\x86\x63\xe2\xe6\x5c\x8c\xc5\xbb\xb1\xf5\xaf\xcf\x88\xd1\x3d\x6f\x46\xcc\x9f\x91\x7c\x68\x46\xd6\x58\xa2\x8d\x89\x92\x78\x22\xd3\x26\x1d\x64\x86\x9a\xd2\x8d\x27\x70\xea\x44\xc1\x69\x18\x5a\xf1\xa7\x93\x5e\xa5\x34\xed\xcd\x58\x96\xdc\x63\x45\x0a\xa4\xa3\x6c\x27\x8d\x33\x52\xcd\x58\x9f\xed\xdd\x9a\x43\xe5\x41\x5c\xd0\xc1\xe3\xa8\xee\x73\xaa\xa0\x95\x39\x77\xdd\xb7\x54\x41\xfb\x6c\xbf\xb1\xe1\x05\x7d\xcc\xf6\xec\xe9\x67\x74\x95\xce\xe2\x4f\x3b\x3b\xc4\x1e\x89\x38\x21\x35\x2c\x17\x33\xe2\x70\x47\x9c\x92\x3a\xa6\x8b\x0b\x9a\xee\x14\xc4\xdd\x34\xf1\x6e\xbf\x24\xe9\xb3\x6c\x84\xbc\x2b\x94\xa6\xe4\x18\x7d\x24\xce\x17\x9f\xc1\x70\x0c\xbe\x3e\x62\x75\x03\x8c\x04\xc2\xf1\x7b\x75\xac\x14\xb6\x4a\x77\x33\x8c\x15\x01\xe0\xb5\x51\xc0\x9d\xc5\x30\xd9\x38\x83\x8a\x62\xf4\xb7\xf1\x36\x4f\x16\xad\xc7\x5e\xc3\xff\x67\x7b\x8b\x37\xac\x44\xdb\xe0\x7f\x8b\x10\xa3\x06\x41\x65\x49\xf6\x0e\xf7\xa3\x6f\x61\xa8\x3c\xde\xc3\x25\x39\x8a\x9e\x6c\x2b\xeb\x6e\xc8\x5c\x9f\x01\x73\xff\xcb\xf5\x5a\x3e\x73\x51\xdf\x42\x1d\xcb\xc0\xfc\x1a\x56\x71\x38\x22\x92\x03\xc1\xaf\xd9\xd8\x12\x0f\xf9\x53\x09\x2a\x69\xb9\xa2\x26\x15\x49\xe9\x94\xdd\x4b\xde\x9b\x21\x49\x56\xbf\xc5\x08\xd3\x67\x79\x89\xd5\x1c\x9e\x6c\xd5\xa9\xf4\xc7\x05\xe4\xc1\x86\x68\xd8\x89\x4a\x36\x1b\x7e\xb2\x37\x38\xf8\xe6\x86\x2b\xdd\x7d\x23\xf1\x50\x13\xfa\xc4\xe6\x2c\x67\x7c\xca\xb4\xf8\x23\x50\xdb\xd1\xb9\x4c\xe0\x75\x7a\xae\x5e\x53\x29\x4f\x65\x9a\x64\x69\xc1\x66\x9d\x5d\xf5\x42\x62\x39\xc2\xb5\x12\x0a\xb8\xd5\x93\x69\xf8\xc0\x40\xf7\xfa\xfb\x5b\xd9\x62\xcd\x9d\xf1\x56\x5d\x2d\xb3\xaf\x00\x68\xdd\xd2\xc1\x7a\xf7\x18\x5f\x5e\xb3\x5c\xc1\x25\xf5\x7f\xac\xd7\xdd\x3e\xc9\x7b\x53\x90\xda\x2d\x75\x7e\x37\x22\x01\xc8\x98\x83\x94\x77\xf2\x30\x44\x79\xef\x36\x4f\xa5\xc9\xc3\xd6\xc4\x47\xb3\x36\x9c\x84\x84\x91\x1c\xc4\x3d\xb9\x4f\x61\x89\x06\xdb\x11\x28\x32\x2f\x5e\x01\x91\xa0\x84\x9b\x6b\x23\xde\xc6\x62\x08\xb5\x18\xfb\x47\xfb\x83\x6f\x5b\x0c\xbf\x1b\xf5\xd6\x67\xa3\x6d\x03\x95\x64\x05\xf3\x8b\x39\xa9\x56\x22\xee\x46\xc4\x5f\x06\xf5\xdb\x4e\x3b\xee\x46\x25\x8e\xd9\x58\x4e\xc0\xed\x76\x0b\x6c\xed\x1f\x7c\xcb\x28\xdd\x00\x73\xab\x05\xa6\x45\x9c\x9e\xb5\x5d\x8d\x12\xef\x0f\xe5\xa6\x72\xa7\xb3\x21\xe6\x9e\x18\x48\x7a\x41\x94\xd4\xe4\x39\xfe\x8a\x9a\x99\x15\xa6\x83\xba\x16\xbc\x52\xf8\x38\x9f\x38\x73\x2d\x56\x92\x7c\x0b\xd2\xd9\x9c\x7d\xff\x89\xb1\xc9\xf8\x06\x80\x6d\x2e\x40\xc1\xe4\x47\x3b\xc4\x93\xb9\xbf\x10\x5e\x69\xd6\x3b\x3b\x83\x89\x9c\x9d\xa9\x47\x69\x49\xf2\x86\x67\x5a\x61\x82\x5f\x79\xea\x7b\xa6\x7d\x2d\x9a\x41\xd2\x57\xd9\xf3\x8a\xd5\xb4\xfb\x98\x6d\x77\x13\x0c\x8f\xfa\x47\x47\xdf\x8c\x3c\xda\xf8\x7e\x56\x29\xd8\x68\xfc\x8c\x1b\xca\xc1\x13\xed\x25\x4a\xe5\xd4\xd5\x47\xac\xf7\x20\x40\x74\xf3\x5c\x5c\x23\xd6\xb6\x05\x8f\x07\x07\xdf\x82\xcd\x2d\xbb\x43\x61\xb3\xcf\xf7\x0b\x8b\xc8\xde\xf2\x9b\x24\x4b\x67\x9d\x44\x4a\x76\xbd\x90\x1d\x29\x3a\x10\xa9\x6a\x39\x95\xcb\x5c\xeb\xf2\xc2\x90\xce\x33\xd6\x49\x8d\xdd\x67\xef\x9f\xfc\x2d\xef\x88\x7c\xc6\x72\x55\xfe\x9c\x75\x6c\x11\x02\x15\x12\x35\xe2\x8e\x26\x44\x8a\xce\xf5\xb2\x90\x9d\xcb\xe4\x86\x75\x92\xce\xc6\xdc\x11\xee\x5c\x33\x79\x29\x66\xbd\xa0\x75\x6e\x47\x87\x5b\xe7\xd6\xdc\x29\xa7\x76\xbf\xb7\x77\x70\x80\x87\x4d\x00\xd9\xd0\x45\x59\x95\x46\x7c\x20\x48\x42\x51\x44\xf2\xde\x6f\x18\x8a\xaa\xe7\x98\x01\xa1\x0b\x26\xbd\x83\xa3\x07\x5f\xb8\x07\xdc\x03\x65\x10\xd3\xd7\xa2\x76\x62\x95\x56\x4e\xac\x76\x30\xa7\xe9\x58\x4c\x88\xd4\xb1\x37\x4e\xe6\x88\xe3\x67\x34\x5a\xaf\x37\x4e\xed\xc2\x34\xf9\xb6\x38\x76\xa8\xca\xa8\x0a\x11\xae\x85\xd2\xe6\x52\x75\x67\x37\x51\x94\xc0\xde\xc1\x37\x5d\x76\x0f\x2f\x4a\x4e\x04\x5d\x95\x24\xa1\x75\x05\x20\x98\x94\x0e\x82\x96\x54\x41\xd0\xd4\xa4\x92\x71\xde\x32\x29\x24\xdc\x18\xed\xbd\x27\x5a\xf6\xf9\x68\x7f\x6f\xeb\x19\xab\x95\x4e\xfd\x7d\x3e\x7c\x02\xe6\x15\x1c\xf5\x0f\xfb\x98\x24\x8a\xba\x19\x1c\x3c\xf1\xb6\x3e\xf5\x51\x89\xdb\x62\xdc\x44\x35\x1a\xa3\x9a\x85\x30\x8a\x5e\x0f\x9c\xe3\xb6\x13\xdc\x38\xbb\x95\x9a\x83\xd3\xcd\x55\x50\x36\x9e\x90\x54\xdd\xb1\x19\x78\x73\x34\xbc\x05\x4e\xb9\x55\x00\x1b\x76\x51\x4a\x51\x4e\x79\x4d\xff\x0b\xb6\x5a\x33\xf8\x72\xe3\xac\x81\x74\xe5\x7a\x6d\x37\x00\xb8\x66\x43\xd5\x30\x1e\x56\xcc\x4d\x08\xfd\x27\x28\x73\x94\x22\x58\xc8\x5a\x8f\x74\x36\x3e\xd7\x7a\x6d\xbf\xbc\x57\x49\x3a\x47\x56\x77\x4c\x94\x1e\x68\xc1\x6a\xad\xd7\x28\x22\xc2\x9e\x15\xf8\x95\xa8\x5f\x58\x81\xde\xfe\xde\x76\xbb\x99\x6d\xdb\x78\x14\x3d\xd1\xbb\xa8\x10\xad\xde\x46\xb5\x9f\xb5\x5d\x74\xd7\x41\x43\x71\x66\x0b\x11\x58\x6d\x75\x09\xdb\xed\x46\xec\x8d\xb7\x06\x06\xdf\x8e\x1c\x8b\x45\xce\x92\xd9\xff\x2e\x5e\x84\xb5\xed\x47\xd1\x37\x51\x43\xde\x3d\xfb\x80\x81\x4a\x50\xc0\x47\x33\xc3\x0d\x60\xd4\xa6\x85\x67\x54\x21\xcb\x36\xc5\xa7\x76\xf9\xaa\x3b\x32\xb5\xcb\x96\x52\x97\xde\xb5\xdf\x15\xde\x1b\xd9\xb1\xb9\xd8\x2e\x70\xe9\xb7\x52\x1f\x87\x5b\x89\x8f\xad\xb7\x83\x02\xb7\xb6\xcb\xc1\xdc\xdf\x9b\x91\x8a\x1a\x20\x45\x8c\x13\x55\xbe\xa9\xcd\x6f\x35\x9e\xed\x71\xee\x15\x59\x3a\x65\xe8\x90\xec\xf6\x9d\x95\xcd\x89\x53\xcf\xe4\x8d\x65\x31\x9a\xc0\x5e\x0a\xb8\xb5\xc1\x24\x78\x9f\x2c\xa0\xc2\x7a\x1d\x9c\x32\x5d\x77\x54\xa3\x0a\xe2\xe0\xb9\x25\xd2\x4c\xc1\x47\xff\x0f\x8d\xe2\x1f\xd3\xf5\x5b\xcc\x25\x1a\xc5\x87\xeb\xfe\xc1\x7a\x6f\x80\xd1\x28\x7e\x99\x25\xd7\x0b\x36\xc3\xba\x85\xef\x1e\xf5\x24\x2b\x24\xe2\x78\xe4\xcf\xd0\x68\x77\xc0\xcb\x52\xd6\x4c\x5f\x38\xaa\xa2\x62\x18\x81\x42\x25\x4e\xb0\x24\x8b\xb0\x0f\x4e\xc3\x48\x55\x25\xe9\xca\xa4\xc5\xab\xb2\x74\x6f\xa0\x71\x3e\xd1\xab\x95\xd8\x2a\x24\x21\xd5\x37\xc7\xd5\x8f\x92\xf7\x38\x65\xf4\x99\x95\x28\xa8\xe5\x3b\x3b\x63\xc5\x7b\x31\x5b\x66\x6c\xa4\xf6\xd9\xe9\x78\xc1\xae\x57\x81\xcd\x34\x2c\x24\xb1\x2c\x41\x7f\x8f\xf7\x66\xd4\xaa\x13\xd4\x48\x67\x89\x79\x4f\x58\xf3\x06\xf5\xc9\xe0\x73\xeb\xab\x87\xac\xea\x8f\x88\x0b\x26\x63\x35\x57\x05\x9b\xbc\x77\xd1\x10\x66\x6d\xb0\x66\x2e\x32\x71\x9e\x64\x9f\x2f\x53\xa7\xe8\x59\xa5\xd4\x38\x46\x97\x69\xb1\x5e\x2b\xdc\xf4\xda\x36\x18\x78\x59\x01\x6e\x84\x14\xdd\xe8\xc8\x84\x5c\x37\x75\xf4\x2f\xb0\xb2\xe6\x3d\x61\x57\xe2\x9b\x1e\x0d\xfa\xd5\xd6\xcb\x61\x1f\x1e\xba\x23\xcd\xa1\xb6\x27\xe2\x73\x72\xb1\x7d\x19\x37\xcb\xda\x47\x5a\xa0\xf7\x36\x28\xb7\xbf\x3c\x83\x0a\x04\x02\x5b\x4d\x3d\xd9\x4a\x82\x50\xab\xba\x08\x03\xc3\xcc\x83\x01\x38\x8e\x42\x4f\x06\x47\xfb\x98\x28\xbc\xf0\xf8\xe0\x48\xdf\x43\x3d\x05\xe2\x9a\x9a\x78\x7c\xf0\x18\x93\x94\xae\x7e\x66\xe7\x57\xa9\x7c\x2d\xb8\x3c\xbd\x16\x42\x5e\xa6\xfc\x22\x0e\x12\x0e\x0f\xfe\xa4\x60\xb3\x80\xbc\x17\x5f\x4e\x8a\xbb\x46\x89\x8b\x3c\xb9\x2f\xa6\x89\x1a\xd9\xb9\xb8\x3b\x4d\xbf\x40\xea\x39\x5c\x10\xbb\xe7\xe2\x2e\x28\x89\xc7\x99\xf5\x09\x15\xa6\x0e\xe2\x6a\x2a\x32\x91\xc7\xb2\xb7\x48\x32\x26\x25\x83\x58\xf8\xbd\x85\xf6\x71\x5a\x6a\xe7\x6f\xe2\x22\x4f\x16\x97\xf7\xbd\x73\x31\xbb\x1f\x90\xd5\x79\x32\xbd\xba\xc8\xc5\x92\xcf\x5e\x36\xea\x56\x39\x4e\x83\x39\xf8\x2f\xe0\x96\x77\x16\x79\xca\x65\x10\x3f\x50\x79\x2a\xae\xaf\x05\xef\xdd\x5e\xa6\x92\x95\x25\x2e\x87\x80\xa4\x3a\x05\xb5\x97\x29\xda\x9c\xc5\x2a\xf8\x2f\x0d\xcd\x41\xbc\xba\x94\xd7\x59\x9c\x92\xe0\x6f\xa4\xf3\xb7\x38\x3e\x67\x73\x91\x33\xf8\x4c\xe6\x92\xe5\xaa\xeb\x6a\x79\x52\x7e\xc9\xf2\x54\x06\x25\x51\xb8\x58\xf0\x0b\xd2\x39\x0f\xe2\xd5\x5c\x70\xf9\x33\x4b\x2f\x2e\x65\x5c\x9b\x78\x95\xfe\x42\x64\xb3\x92\xa8\x85\x88\xdd\x0a\x5e\x27\xf9\x45\x0a\x6a\xc8\x19\x92\x98\xac\x82\x30\x8e\xd5\x34\x67\xb9\x58\x3c\x38\xe3\xcd\xe5\x52\xf3\x2e\x4b\x4c\x56\x1c\xbc\x25\xbd\x5f\xa6\x2f\x8b\xe2\x45\x52\xb0\x2c\xe5\x0a\x42\xeb\x0e\xa6\xac\x0c\xcf\xb9\x15\xf4\xa2\xce\x70\x4d\x62\x72\x87\x04\x7b\xd3\x2c\x29\x0a\x56\x34\x95\x14\x51\x65\x50\x6b\x3c\xa1\xe2\xd2\x68\xdc\x2e\x15\xfd\x7b\xb4\xf7\x18\x93\xa9\xa2\x97\x9e\x0c\x7c\x82\x69\xe6\x59\x1a\x3d\x0a\xa8\x0e\x02\x96\xe4\xcf\x25\x8a\xbc\x87\xf3\xbc\xc9\x46\x92\xea\x1c\xec\xf4\x9b\xa2\x56\xbe\x43\xfb\x24\xdf\xa1\x7d\xcc\x34\x2d\x9f\x4f\x86\x46\x68\x5b\xd6\xed\x5a\xdd\x7c\xe0\x18\x9e\xcc\x47\xee\x0b\xe1\x78\x03\xbf\x98\x2c\x17\x10\x42\xc3\xd4\xa5\x3b\x10\x1d\x86\xac\x06\xb2\x54\xab\x66\xa3\x50\x47\x95\x0a\xbb\x74\xe4\x6c\x15\xa2\x7a\x83\x2a\x94\xb8\xfe\x92\xb6\xe9\xea\x09\x65\xb9\x66\xe0\x33\xce\x3a\x12\x91\x3d\x76\xc3\xf2\x7b\x1f\xa8\xbd\xe8\x9c\x30\x2a\xe0\x97\x68\x9f\x1f\x1b\xc8\x56\x56\xe6\x23\x55\xdc\x60\xcb\x92\x5b\x28\x30\x14\x74\xe1\xc5\xe0\xc8\xbb\x30\x11\x01\x02\x5d\xed\xcf\x2d\xf6\x1f\x5d\x35\x76\x11\x5a\x95\x3a\x60\xc1\xc6\x18\x6b\x23\x54\x6f\x31\x3b\xc8\x2a\x02\xb9\x39\xb6\xd7\x9b\xd6\x9e\x5d\x9f\xd7\xe9\x11\xbf\x60\x6e\xdc\x99\x27\x29\x70\x2e\xeb\x16\xb0\x5b\x41\x6c\xc4\xe2\xe0\x51\xb0\xc3\x7c\x1b\x57\x9f\xa5\xd3\xca\xe7\xd1\x66\x12\x52\xbc\x13\xb7\x2c\x7f\x99\x14\x0c\x61\xf7\x96\x94\xf5\x74\x1c\x86\xbb\xfd\x2e\xa5\xc1\xa3\xd1\x5f\x02\x57\xc8\x0d\xc0\xee\x29\xc6\xfa\xc1\x32\x62\xbd\x62\x79\x5e\xc8\xbc\xca\xf1\x95\x14\xee\xb7\xce\xc4\x9e\x82\xdd\x3e\xb4\x01\xb4\x5c\xa4\x68\x39\xbf\xfa\xb9\xa7\xe3\xd0\x5b\x24\xf2\x12\x5c\x11\x82\xf8\x9e\x25\xf9\xf4\x92\xe4\x14\xae\xd2\x4b\x22\xd4\x2e\x07\x8f\x02\x47\x95\x84\x61\x30\x0a\x74\x88\x26\x24\x76\x68\x30\xd2\xae\x0b\xab\x75\xe4\x71\x30\x0a\x76\x38\x26\x79\x18\x06\x7f\x09\x74\x80\x64\x28\xfa\x17\x30\x94\xf2\x8a\xe6\x71\xf0\x97\x60\x27\xc7\x44\x54\x43\xbb\x45\x75\x1f\x7d\xc3\x0d\xe2\x56\x8e\x50\xd2\x22\x9e\x60\x30\x4e\x02\x66\x6a\xb9\xfa\x47\xd0\xea\x61\x1f\xfc\x25\xc0\x43\x58\x7f\x11\x86\xe0\x6a\xdc\xac\xae\xd0\x3e\x58\xcd\xaf\x88\x08\x67\x1c\xe0\x55\x1e\x39\xfe\x37\x34\x91\x00\xd1\xeb\x2a\x25\x8d\x26\x12\x8c\xc9\xca\x2e\x6a\x2c\x89\x5e\xd2\xd8\xac\xd4\x28\x08\x62\x4e\xd4\xda\xc6\x66\x41\x54\x4a\x5e\x96\xea\x8c\x25\xda\xbd\x14\xc4\x94\xad\x34\x55\x80\xd1\xa3\xaf\x86\x12\x62\x1f\xda\xc6\xf5\x13\xdb\xfc\xa0\x41\x00\x0d\x40\x6f\x23\xbd\x49\xf6\x67\xb5\xe6\x50\x45\x27\xaa\xbd\xdb\xb1\x3f\x70\x5c\x25\x07\x24\x81\xcd\x1f\xe9\xed\xd3\x3f\x1a\x4d\xa8\x24\xb5\xa3\x3b\xfa\x53\x55\xd7\x49\x41\x65\xf7\xc0\xbd\x20\x13\x89\x0d\xf7\x80\xaa\x39\x62\x20\x17\xbd\x19\x68\xc7\x01\x3f\x7e\x7a\xeb\x4d\x6b\x43\xf3\xa9\x7a\xb9\x8a\x79\xe7\xc7\x4f\x6f\xe1\xe0\x8f\x14\x0a\xb0\x3f\xd0\x5f\x3f\x9a\xca\x9d\xe0\xaf\x3b\x55\x53\x3b\x7f\x0d\x3a\x53\xb1\xcc\x66\xa0\x0f\x76\xce\x3a\xba\xbf\x59\xaf\x03\xfa\x7b\x69\xd1\xc9\xd2\x2b\x96\xdd\x77\xa6\xc9\xb2\x60\xb3\xce\xf9\x7d\x27\xe1\x9d\xd4\x3c\xa7\x17\x2c\x9f\x32\x2e\x77\xc1\x33\x81\x7a\x2f\xfd\x55\x1d\x29\x8b\x0e\x61\x62\x57\xec\x9e\x2a\x68\x1e\x55\x7d\x8e\x82\x47\x7a\x0d\x6d\x42\x63\x1d\xdd\xdc\x1b\xcc\x9d\xba\xc5\x42\x10\x60\xcb\xe1\xd2\x4f\x88\x62\x91\xa5\x12\x05\x8f\x02\xb0\xcf\x51\xa0\xae\x6e\x80\x46\x6a\xa2\xca\xaa\x6b\x95\xa4\x2a\x7f\xa6\x20\x2c\xa3\xc9\x7a\x9d\x0e\xb5\xa1\xb1\xca\x1b\x09\x9a\xc7\xb9\xbb\x46\x90\xd0\x97\x24\x11\x54\x80\x07\x96\x44\xa2\x1c\x63\xd2\x15\x16\x0d\x39\xac\xa3\x1a\x71\xa9\x36\x88\xd2\x58\x38\xfc\x33\x19\x72\x1a\xf4\x14\x88\x17\xeb\x75\xd0\x73\x5f\xf0\xd7\x46\xce\xeb\xf6\x87\x9e\x75\x24\x99\x52\x5b\x7f\x38\x7d\x46\xa3\xe1\x74\x77\x57\x37\xbd\xa0\x62\x3c\x9d\x0c\x75\x7b\x8b\xd1\x1c\x09\x32\xc5\xb1\x69\x75\x31\x42\x3a\x01\x0c\x0b\xe3\x65\x18\xba\xdf\xbb\xbb\xa0\xf6\xd1\xcd\xc0\x6c\x71\xb8\xdc\xdd\x1d\x2e\xb1\xe8\x2d\x79\x71\x99\xce\x25\x52\x0d\xe0\x61\x37\x33\xc3\x12\xe3\x68\xb2\x5e\xab\x7f\xd5\xe2\xa8\xbf\x78\xbd\xf6\x4a\x9b\x6d\xb8\xa4\xc2\xd8\x14\x3e\xaa\x24\x63\x0a\x33\xc2\x5e\x5f\x5a\x54\xb0\xdb\x57\x7b\x7c\xb9\x43\xc1\x2c\xf6\xb2\xf4\xb6\x9b\x88\x0a\xc0\xd5\xd9\x71\x60\x50\xa5\x7b\xa9\xeb\x75\xed\x9c\xab\xd6\x92\x0a\x63\xde\x39\x7b\x39\xad\xeb\x41\xc7\x56\x5e\xb9\xd2\xc2\x8a\xeb\x85\x67\x32\xe6\x09\x29\xa8\x24\xbe\x7a\x9f\x81\x36\x63\xae\x5c\x96\x5a\xba\x94\x5f\x7f\x76\x96\x71\x9f\x85\xd7\x8e\xc5\xd2\x7e\x30\x10\x8d\x39\xdb\x9c\xf2\x8d\x34\x5d\x14\xb3\x4d\x7c\x9e\x8c\xda\x7c\xb3\x8f\x72\x94\x28\xa2\x42\xa0\x6e\x04\xff\x02\xe6\x35\x4a\x3d\x90\x58\x92\x64\xb1\x60\x7c\xf6\x2e\x2d\x24\xe3\x0d\x5f\x93\x9a\x38\xec\x46\x75\x61\x02\x70\x2f\xb4\x94\x48\x9f\x30\x5f\x4e\xe4\x34\x5e\x35\xd3\x12\xfb\x8b\xc3\x21\x8e\x15\x95\xbd\x79\x9a\x49\x96\xa3\x56\x6b\x39\x75\xd5\x95\xe0\x05\x96\x0b\x99\xce\xef\xed\xc0\x0a\xdf\x2d\x87\x85\x76\xb6\x61\x6d\x45\xb8\x27\x85\x66\xea\x7d\x17\x0d\xf3\xa7\x4c\x73\xaa\xc7\xb9\x6f\x44\x95\x4f\x86\xb2\xdd\x47\x6c\x43\x00\x6f\x66\xc9\x81\xa4\xd2\x7a\x49\xc7\xb4\xfb\xa0\xae\x7e\xd7\xe8\x6c\xdb\x88\x6f\x9b\x29\x75\x7a\x1f\x37\x1c\x3b\xe0\x95\x44\x56\x4b\x5c\x03\x10\x62\x58\xab\x23\x9f\xd2\x60\x21\x16\x80\xfe\x03\xf2\x92\x06\xea\xc6\x98\x82\xb5\x55\xe0\xfb\x08\xc0\x2b\x8f\x8d\x60\x9a\xba\x4c\x0b\x29\xf2\x7b\x7d\x77\xac\xd7\xab\xb2\xba\x16\xac\x0c\xa0\xf4\xed\xf5\x37\x71\xe8\xaa\xc4\xe4\x78\xbd\xbe\x46\xdd\x7e\x85\x4c\xeb\xad\x13\x41\xb5\x3d\x2e\xe2\x36\x87\x27\x37\xe9\x45\x22\x45\xde\x5b\x16\x2c\x7f\x7e\x01\x01\x33\x1d\x61\xf0\x9c\xcf\x72\xd5\xcb\xa0\x17\x00\x7d\x07\xa4\xd0\x46\xee\x7e\x2f\x52\x18\xb9\x99\xfd\x5e\x9c\xa7\x19\xeb\x9c\x26\xf3\x24\x4f\x75\x81\x6e\xad\xc0\xcb\xcb\x5c\x5c\xb3\xb6\x9c\x9f\x61\x70\x45\xe7\xe3\xa5\xe0\x2c\x50\xb4\x65\x7d\x22\x61\x18\x28\x20\xd6\xfe\x49\xd2\xe6\x22\x92\x84\x76\xf5\x3c\xb7\x4f\xb2\xea\xeb\x73\x9e\xce\xc0\x15\x12\x5c\x23\x24\xa3\xa9\x76\x71\x62\x9c\xa1\x92\x82\xba\x0b\x3f\x0b\xc3\x8c\x2c\x69\xda\xbb\x60\xf2\xc7\xc2\xf8\xc6\xcd\xb5\xda\x3b\x99\x56\x6f\xc9\xe5\xe8\x2a\x5e\x92\x99\xb6\xbe\x7f\xa7\x81\x7f\x5e\x65\xcf\x46\x07\xf1\x8c\x2c\xa8\xec\x9d\x27\x05\x78\xb0\x1d\xdd\xa3\x1b\x54\xfd\xc4\x38\x0e\x3c\x88\xb9\xac\x11\x81\xab\x92\x70\x6d\x72\x09\xf1\x3a\x00\x60\x88\xb0\x53\xcd\xc4\x54\x0f\x27\xf1\x50\xed\x8e\x30\xb4\xcf\x8e\x00\x2a\xc6\xa2\xf4\x85\xba\xa2\xe9\x05\x4a\xc8\x02\x63\x72\x8b\x12\xf0\x52\xef\x83\x99\x3b\x70\xa0\x4b\x9e\x27\x7c\x26\xae\x11\xae\x79\x91\xb0\xb7\xc1\x80\xcc\xf5\x29\xf8\x44\xef\x90\x77\x68\x4e\x14\xac\x5a\x02\xef\x77\x22\x31\xf9\xdd\xbe\xef\xec\xb5\x4c\x3e\xf5\x1a\x18\x05\xfd\x5e\xcd\xe4\xf7\x5e\x02\x2d\x79\x03\xfb\xac\x56\xa4\x0d\x2f\x78\x2e\x1e\x0d\x3d\xa6\xa1\xf2\x21\x00\x78\x99\xa7\x27\xa7\x01\x2e\xb5\xf4\xe1\x3d\xba\x44\xa6\xb2\x1f\x06\xf3\x03\xc2\x2b\x95\xf5\x1b\xc2\xe6\xb0\x9f\xd5\x54\x76\xdf\xab\x41\x9c\x8d\x10\xe8\xae\x9e\x20\x8c\xe3\x4f\xbd\x96\xfb\x05\x31\x12\x7c\x3c\xf9\x18\x90\x69\xdd\x1e\x5d\x8e\x4e\xd0\x4a\x4f\x33\xd6\x05\xec\xf4\x63\x56\xe2\x16\x83\x68\x6f\x7d\x38\x7d\xee\x3d\xca\xae\xd8\xbd\x7a\x09\x68\x56\x36\xe2\x34\xb2\x4c\xf6\xe7\xde\xa3\xac\x2a\x04\xea\x24\xb6\x90\xa0\x7c\x37\x1f\xaa\x17\x04\x28\x51\x7d\x41\x02\x9e\x6b\x80\x5c\x55\xfe\x5b\xaa\x17\x80\x3c\xa7\xe3\xb7\xaa\x91\xc9\xd0\xd7\xdd\x75\xbb\xb0\xd8\x51\x0f\xb0\x6a\xf1\xbe\x40\x5e\xef\x42\xa8\x54\xd5\xd0\x2b\xea\x5d\x5c\xaf\xc1\xef\xbd\xc2\x4a\xaf\x76\x28\xc3\x61\x08\xd6\xf6\x23\x8b\x64\x93\xd9\x0c\xfc\x6f\x5b\xd8\x40\xa7\xe4\x33\x26\x89\x43\x09\x1b\xf9\x2f\xc9\x07\x8c\x63\x05\x04\xaf\xc2\x10\x39\x0b\x9d\x6b\x71\xc3\x1e\x6c\xa8\xad\x08\xb4\x05\x43\x7e\xa1\x36\xf6\x77\xba\xd2\x10\xeb\x28\x4a\xd2\xbe\x69\x6f\x89\xbe\x43\xde\xe4\x6c\x1e\xbf\x23\x0a\x59\xc5\x6d\xe2\xcd\xe0\xe3\x8f\xa7\x6f\x02\x92\xd0\x5b\x90\x98\x7c\x44\x70\x3a\x4c\x2b\x78\xd8\x0e\x43\x09\xf8\xcd\x40\x0d\xa9\x9b\x03\x8d\x77\xea\xc5\x96\xd2\xc4\x18\x7b\x9b\xf7\x08\x50\xb3\x38\x9d\xa3\xbc\xe7\x50\x27\x5a\x69\xeb\x63\x1d\x8f\x2e\x2b\x6d\x48\x7b\x52\xe0\x06\x3a\xe9\x5d\xe6\x6c\x4e\xa5\xaf\x4c\x5c\xc1\x53\x35\x62\x6d\xfb\x3d\xa5\xcf\xdd\xc3\x7c\xb9\xd3\xc7\xc3\xa9\x89\xf8\xa4\xb3\x9f\xd3\x29\xa9\xa0\x9d\x57\x8b\x96\x94\x86\xfc\x69\xef\xbc\x84\x10\x0b\xc6\x7b\x49\xfb\x6a\x7e\x3a\xfe\xf8\xee\xf9\xcb\xe3\xff\xed\x05\xcd\x3d\xff\x65\x7f\x62\x4d\xad\x23\x16\x89\xbf\x69\x5d\xf5\xfb\x5e\x11\xff\xcf\xc7\xcb\x09\x35\xab\xf9\xe7\x56\xb2\xea\x52\xaf\xe6\x85\x88\xbf\x90\x0b\xf1\x22\x99\x5e\xf9\x44\xdc\x17\x45\xdb\xab\xdc\xd7\xda\x36\xba\x9e\xa7\xb2\xc0\xeb\x63\x1d\x2f\x39\xd4\x0b\x44\xb6\xa5\x42\x24\xfd\xd4\x73\x64\x3a\xaa\x0c\xb6\x5f\xac\xd7\xe8\x35\xea\x63\xf2\x02\x74\xd8\x36\xb5\x9a\x5f\x84\x21\x82\x43\xf7\x5a\x0d\x06\x13\x09\x02\xd7\x0c\x4e\x66\x0b\x42\xfc\xd4\xab\x53\xcb\x5e\x57\xd0\x8d\xd7\xc1\x6b\x1d\xce\x5f\xb5\xe7\x64\x5e\xbf\x9b\xab\xab\xd2\x97\x25\x27\xb4\x4d\x96\x52\x09\x83\x46\xd5\x67\xab\x66\x82\x5e\xfb\x91\xfe\x13\x57\x5c\x83\xde\xc5\x88\xf7\x2e\x62\x5f\x7e\xf7\xb9\x9a\x47\xf5\xb8\x11\xf5\x69\x1a\xba\x9d\xe1\x92\x88\xf9\xbc\x9e\xd5\x46\xb8\x7b\x41\x3c\xba\x94\x32\xbd\xdd\x4c\x6e\x3a\xea\xeb\xb0\x92\x14\x7e\x06\xb8\x55\x66\x94\x93\x36\x1a\xdc\x8f\x0d\xc2\x34\xef\xdb\x10\xde\x1f\x68\xc3\x59\x41\x4d\xa3\xa3\x72\x87\x46\x52\x92\xd1\xe0\xcc\xf8\x95\xd6\xf1\x92\x77\x8d\x8b\x80\xdd\x60\x07\xa1\x93\x71\xaa\xf2\xf5\xf2\x9e\x2d\x79\xfa\xc7\x92\x9d\xa5\xb3\xb3\xb3\x60\x42\x55\xe6\x64\xbd\x8e\xf0\x4e\x1f\xef\x04\x67\x67\xe0\x53\xb2\xa6\xac\x67\xd7\x54\x9a\x67\xa3\x34\xeb\x09\xca\xb1\xad\x1a\x74\xeb\xb5\x4a\xc0\x3d\x76\x9d\x4a\xc9\x72\xfa\x59\x6b\xa7\xd9\x08\xba\x98\xc8\x12\x45\x64\xaa\xe8\x17\x49\x98\xbd\x4f\x3d\xae\xb9\x63\x1a\x2b\xc2\xd0\x8f\xda\xbf\x11\x70\xc6\x8e\x85\x29\x72\x7d\x9c\x4d\x74\x00\x1a\xd3\x31\x28\xd2\xf5\xa6\xd6\x7b\xc8\xcf\x69\x96\x7d\x62\x53\x96\xde\xe8\x60\x07\x4d\xbf\xe2\x95\x33\x42\x3d\x4e\x88\xe1\xad\x47\xac\x27\xae\xe8\xc3\x46\x19\x10\x23\xe8\xd8\x64\x08\x25\x34\xc7\xea\xda\x4d\xa9\xc0\x23\xf0\xd1\xbd\x5e\xf7\x1f\x25\x94\xf6\x1f\xa5\x71\xd2\xa5\x49\x18\xa6\x5d\x9a\xe2\x91\xa4\x51\x8c\x64\xdb\xbb\x97\x8f\xb8\xe6\x8d\x7f\x82\x00\xbb\x72\x4d\x23\x1c\x86\xfe\xa4\xd4\xe1\x47\xcc\xfa\x48\x32\x97\x69\x42\x52\x35\xd5\xa6\x43\x76\xec\xcb\x56\xcd\xb0\xad\xac\xa6\x54\xbb\xe0\x79\x5b\x81\xa8\xd5\xde\x52\x7f\xbe\x5f\xb0\x82\x22\x94\xdb\x95\x15\x08\xf7\x34\xc7\x1f\x1c\x2e\xfe\xb1\x4c\x73\x36\x23\xb9\x95\xd4\xf8\x00\xed\xc9\xd1\x37\xf6\x69\x8b\xbf\x1a\x0b\x33\x9a\xd7\x67\x44\x9c\x4c\xed\x3f\x38\x3d\x40\xb8\x24\xac\x27\x78\xd3\x4f\x22\xc8\x4e\xd4\x4a\xa1\x68\xcd\x6a\x21\xc8\x70\xc8\x31\x70\xbe\xac\x27\xc6\xb6\x36\x55\xab\x0e\x16\xb9\x55\x7a\xc8\x29\x6f\x83\xc5\x6f\x03\x24\xcb\x25\xf7\xc7\xa2\x5d\x44\xfa\x29\x46\x0f\x4b\x8e\x3e\xc5\xb2\x06\xa4\xaf\xd2\xd9\xfb\x66\x68\x25\xdf\x31\xe6\x38\x9b\x18\x78\xa8\x12\x7a\x6a\x21\xa0\x07\xb3\x3e\xd8\xc8\x80\xbd\x6d\xff\xa6\xe1\xb0\xd1\xa7\x78\xf3\xcc\xfc\xb8\x19\xec\xe9\xeb\x23\x9a\xcf\x1b\x43\x52\xcd\xda\x95\xdf\x06\xa1\x55\x03\xa3\x66\x83\x17\x4c\x22\xac\x07\xb7\x0d\xca\x51\x6d\xc2\x4e\x26\xd9\xd4\x9e\x1a\xb1\x71\x34\x89\x19\xd6\xe3\x03\x78\x33\xa7\x5c\xaf\x5a\x49\x78\xe3\x60\x98\x21\x2e\xed\x78\xec\xd1\x48\x36\x8f\x06\x49\x30\x59\x39\x97\x2e\x45\xe5\xcf\x65\x59\x5a\xc1\xd4\x19\xfd\x00\x1d\xbd\xa7\x1c\xed\x3f\x79\x72\x84\xc9\x5b\x10\xc7\xbf\x57\x94\x1c\xe2\xe8\xe0\x60\x0f\x13\xa3\xdf\x89\xc9\x3b\x95\x74\x78\xa0\x8a\x6d\x42\xd9\x19\xf2\xfc\xb5\xcc\xd2\x62\x91\x25\xf7\x1f\x92\x6b\xed\xb6\x05\x93\x2f\xf4\x1d\x0a\x3e\x89\xa5\x64\xf9\xee\x1b\xfd\x94\x0f\x30\x79\x55\xa5\x06\x98\xbc\x6e\x47\xf6\x70\x8c\x81\x08\xb4\x27\x17\xe4\xbc\xe0\x41\x48\x1d\x5c\xd9\x3c\xb0\x8e\x54\x92\x8e\xf5\x62\x93\x4a\xc2\x7b\x67\xce\xb1\xad\xa2\x40\x78\xef\xcc\x86\x21\x32\x65\xac\xd9\x99\x6a\x2d\x9d\xba\xfb\x0e\xf1\xde\x92\x6b\x12\x85\x7a\x0d\x43\x42\x9d\x8f\xe5\x77\x31\xe2\xde\xa9\xaf\xbd\xfb\x5a\x3a\x06\xf7\x82\x6a\xcb\x1d\x16\x60\x98\x70\x38\x01\x4b\x09\xe1\x5c\xde\x27\x72\x7a\xd9\xe6\x87\x66\x91\xc8\xcb\x38\x78\x14\x90\x65\x9e\xc1\xdf\x45\x92\x27\xd7\x45\xbc\x2a\x49\x5a\x1c\xdf\x25\x53\x19\x1b\x61\x9b\x89\x7d\xf4\x35\xc4\xb2\xf5\xf0\xfb\xcb\x17\x99\x48\x6d\x8d\x89\x98\x33\xd8\x32\xf1\xd6\xe2\x25\xfe\xe6\x73\x6e\x77\x20\x0c\x51\xed\x37\xc2\x64\x63\x70\xfd\xf6\xc1\x19\x16\xf1\x83\x57\x54\x43\x2b\xe0\x95\xf3\x7d\x64\x15\x5e\x56\x66\xff\x63\xef\x94\x5b\x0e\x55\x7d\xb2\xfa\x50\xbb\x07\xfd\xb5\xda\xc0\x78\x73\x4f\x51\x4b\xe1\x8a\xcd\x4e\x6a\xb0\xe8\x77\x5a\xcb\x28\x37\xbc\x2e\xa1\x2f\xde\xd0\x2d\x1a\x8a\x5b\x50\x93\x96\xeb\x13\x3d\xbb\xcd\x49\x01\x85\xd9\xc4\x45\xde\x8f\xa1\x7e\x46\x6f\x25\xd6\x1e\xb6\xad\xd2\xe7\x77\x93\x10\xe3\x6d\x84\x18\xff\x06\x18\x35\xf7\x0c\x87\x5c\x03\x8d\xb5\x34\x1f\x7d\x28\xd4\x51\x92\x7a\xb3\xdb\x7c\x20\xdb\x46\x74\x7e\xa3\x65\x9d\xd8\x68\x9a\xb0\x7a\xe3\x0f\x41\xb7\x6b\x48\xe7\x37\x9b\xd7\xa9\x6d\x43\xdf\x0a\xc9\xc6\xd2\xb5\xbe\x71\xe4\x77\xba\x2a\xc9\xcf\x3e\x9f\xe6\xbb\x76\x9f\x63\xfa\xb9\x07\x42\x9b\x16\x8e\xb4\x41\x28\x23\xd6\xf4\xae\xf7\xfb\x98\x39\x63\x0a\xf5\x6d\x1e\x8b\x6f\x11\x86\x75\x48\x33\xe6\xbd\xe0\x7e\x7e\xda\x67\xfb\x61\x08\x95\xa8\x24\x3f\xef\xec\x00\x51\xae\x2e\x45\xb2\x5a\xe4\x4c\xca\x7b\xad\x5f\xe6\x06\xfb\x23\x72\xda\x1d\xee\x20\xcd\xe0\x14\x81\x36\x99\x14\x24\x51\xc8\x6d\x59\x5c\x92\xb4\x62\xf0\x26\x61\x98\x0c\xb7\x1e\x70\x7b\x39\x36\xc3\x40\x72\xbc\xe2\x3e\xe3\x5d\xb5\xec\x0e\x3a\xe5\xf5\xf3\x47\x0a\x9a\x8e\xb4\xe2\x78\x9c\xd8\xf7\x38\x59\xd2\x5b\x94\x8f\x36\x44\x47\x62\xf4\x1d\x12\x24\xef\x69\x44\x8d\x63\x4f\x4e\x2e\x3c\x19\xfc\x77\xa8\xe2\xf5\x56\xa5\x4b\x1c\x0b\xb7\x82\xd9\x08\x15\x68\xa9\x0d\x2d\x71\xdc\x9c\xdb\x0b\xb2\x32\x40\xef\x3f\x0f\x55\x85\x92\x58\x98\x8d\xeb\x44\x6c\xa5\x3f\x7f\x8b\xd4\x7a\xe2\x61\x4e\x13\x22\x7c\x51\xfe\x92\x00\x2f\x04\x18\x15\x25\x86\x81\x19\x11\x1f\xf5\x98\xd3\x61\x98\x5b\xc9\xbc\x4a\xd6\x9f\x2a\x11\xe4\xed\x2a\x49\x7d\xa8\x04\xed\xd2\x56\x68\x6f\x83\x97\x28\xb7\xbc\x6f\xc3\xad\x5d\xaf\xf5\x80\xa5\x88\x45\xe9\x78\x96\x3f\x29\x38\x7e\xe3\xc3\xf1\x1f\xad\x22\x68\x05\xac\x9b\x8a\xc6\x72\xbd\xde\xd0\x5b\xd2\xc5\xe1\x32\x95\xa5\x43\x42\x04\x2e\xcb\x44\x6a\xf8\x62\xea\x36\x25\x09\xf5\x9d\x7a\x08\x92\x02\x30\xe4\xe9\x54\x92\x8c\xfa\x3e\x30\x52\x52\xa8\x2c\xc6\xb5\x47\x18\xb2\xa4\xbe\x17\x8b\xc2\x6c\xe2\x78\x52\x49\xac\x7b\x39\x78\x0a\xab\xa9\x43\xd9\x58\x56\x61\x18\x80\x06\x4b\x33\x1c\x99\xb4\x09\xd2\xdc\xee\xad\x3c\xb4\x60\x47\xf6\x18\x9f\xed\xd8\x20\x10\xea\xc3\x0d\x2c\xa7\x3f\x8d\xf9\x64\xbd\x46\xea\x8f\x5a\x33\x88\x98\xe9\x1d\xe5\xdc\x1e\x65\x41\x41\x42\xbf\xca\xd9\x05\xbb\x5b\xc4\x6f\x11\x46\x8c\x08\x22\x31\xb9\x62\xf7\x45\x2c\x1c\xe7\xe5\x8d\x39\xdb\xaa\x26\x4d\xc8\x1b\x75\xb6\x93\x12\x71\xb2\x62\x7c\x16\x27\x44\x8f\x22\xce\x88\x1b\x45\xbc\x2c\x31\x11\x54\x5d\xce\xaa\x6d\x92\x52\x80\x8d\x82\x14\x54\xf4\xd8\x1d\x9b\x2a\xcc\x01\x41\xe4\x6a\x2b\xa0\x7d\x40\x16\xe3\x68\x42\x66\xb4\x30\x1c\xca\x3e\x26\x73\xaa\x00\x72\x6a\xc7\x93\x84\x61\x77\xae\x95\x01\xf5\x26\x73\x4b\x2f\x69\x9e\x3a\x08\xd2\xa7\xa3\xe0\x51\x10\x4f\x1d\xdd\x34\xb7\xb4\x54\xba\xb9\x31\x75\x53\x48\x36\x96\xa0\x41\x3e\xa1\xb3\x31\x9f\x10\x56\x62\xb2\x2a\x71\x59\x9a\xa3\x09\x30\xfb\x03\xf5\x71\x4b\x9b\xbd\x22\x7f\xf0\x92\x74\x1a\xab\x70\x55\x42\xf0\xe3\xfc\x81\x88\xba\x76\xeb\x55\xdd\x3f\x8f\xfd\x72\xbc\xca\x7d\xec\x27\x34\xd1\xb8\x28\x1c\x8d\xb2\x5e\xe7\xbe\x5c\xca\x66\xd7\xb0\xf2\xa8\x35\x35\xb6\xa9\x6a\x23\x46\x7f\xf8\x68\xce\xe4\xe0\x38\xef\x01\xbd\x44\x52\x1f\xf5\xe4\xa4\xa2\x27\x85\x21\xa8\x92\x12\x03\x3a\xd6\x3e\xb4\x0b\x5a\x05\x36\x27\x4b\xf5\xc3\xde\x7d\x64\x0a\x81\xad\xd5\x1a\x0d\x5b\x75\x14\x0b\x1c\x86\x2d\xb2\x27\xc0\x25\xce\x2f\x6e\x0f\x5c\xd9\x82\xb1\x4b\x01\xd1\xce\x8d\x5b\xce\xaf\xd3\x8d\x69\x49\x52\x3d\xa7\x51\xd1\xa6\x3a\x50\x8c\x0a\x94\xe2\xb8\x88\x97\xa3\x66\x63\x4b\x92\xe2\x78\x3a\x9a\xaa\xfc\x2d\xae\xb1\x6d\x75\x0d\x6d\xc0\x51\xff\x0a\xc9\xf6\x8f\xff\x4f\x43\x23\x49\x00\xed\x6e\x87\xc8\xaa\x0f\xb7\x75\x96\xeb\xc9\x9b\x6f\xf3\xda\x9d\xef\x14\x5e\x93\x30\x6c\xfa\x03\x45\x1c\xe3\x95\xa0\xdc\x78\x82\xf1\xc1\x78\xbd\xb6\xbf\xe6\xb9\xb8\x1e\x26\x34\x1b\xfd\x81\xd2\x0a\xb0\x3d\x28\xb6\xb0\xaa\xf1\x50\x56\x62\x07\xed\x65\x89\x31\x49\x46\x75\x37\xc1\x48\x78\x50\x9f\x92\xfa\x49\x4a\x4a\x1c\xbb\x38\xd5\x9b\x5b\x5e\x79\xf1\x84\x21\xff\x7d\xdb\x33\xdb\xb3\x86\x26\x7c\x53\xc5\xc3\x77\x34\xc0\x31\xd1\x86\x96\x1c\x2c\x2c\xf3\xb1\xf0\x55\x3c\xc4\xc4\xe7\xcb\x2a\x7a\xd5\x00\x11\x23\x63\xb5\xf5\xde\x5d\xe7\xde\xee\x86\xa8\xa2\x1f\x2d\x83\x56\x51\x81\x75\xf0\x32\xcf\xe1\x87\xc0\x6b\x0b\x4c\xbd\x26\xf5\x07\x9b\xa5\xe0\x1e\x7a\x11\x95\xdf\xf0\xe2\xf9\xb5\xd5\x4d\xe8\x36\x1d\x22\xe0\x19\xfd\xd2\x5e\x65\xc3\x0a\x6a\x74\x8b\x58\x15\xf4\x9c\xe8\xca\xdf\xb7\xb9\xff\x64\x25\x61\x8c\xfa\xbe\x6e\x87\x15\x01\x0f\x14\x3c\xa3\xdf\x1b\x81\x0d\xa3\xcc\xbf\xbe\x40\x1a\x60\x11\x7b\xca\x39\x04\xca\x05\x34\x6e\xa4\xea\x0c\x0e\x98\xe0\x2f\xb3\x74\x7a\x45\x32\x85\x86\x9f\xeb\xad\x18\x07\xb6\x7c\x40\x02\x5b\x3a\x20\x81\x29\x1b\x4c\x30\xa0\x61\x99\xe4\x17\x4c\x92\xa5\x8f\xc0\x33\x45\x91\x42\xa9\xba\xa4\x23\xbf\x5f\x29\x7a\xa9\x0a\x55\x28\x9d\xde\x64\x6f\x91\xb3\x1b\xf5\x34\xd3\xa6\x01\xea\xb9\x5f\x7a\xfe\xa5\x21\x8f\xcd\xd6\xeb\x08\x18\xe5\xe7\x4b\x29\x15\x22\x28\xc2\x30\x80\x78\x2e\x8a\x64\x2a\xea\x86\xff\x46\x47\xbb\x8b\x58\xef\x9a\xc9\xe4\x07\x76\xbf\x5e\x43\xc0\x7d\xf3\x35\x95\x79\x66\x3e\x41\x81\xee\x07\x76\x6f\x6d\x1b\x5b\x46\x93\x40\x50\x69\x8f\x3d\x97\xb3\x39\xfd\xbe\xab\x37\x20\x5f\xaf\xc5\xc6\xdd\x10\x24\x01\x59\x82\x63\x7d\xfe\xd0\xa6\x54\x37\x57\x52\x29\x99\x88\x91\x64\xb1\x26\x39\xed\x23\x23\xd3\x0f\x9f\xc2\xdf\xc7\x65\x6d\xbb\x5c\x4b\x01\x09\x4c\xad\x80\x04\x52\x04\xa4\xda\xc9\x09\xfe\xcf\x5f\x48\xc2\x7b\x21\x4d\xe9\x2f\xe8\x57\x94\x11\x5e\x89\x69\x6b\xdf\x33\x3a\x1d\x89\x5e\x25\x4e\x47\x53\x1c\x07\x01\x99\x37\x5e\x1a\x97\x39\x9b\xc7\x33\x62\xa1\x2c\x6e\x4a\x5e\x68\xb3\x0f\x49\xcf\x91\xf7\x9b\x52\x7a\x8e\x7e\x41\x0c\xe3\x21\x4a\xd7\x6b\x39\x12\x76\xdd\x62\x01\xaf\x35\x30\x5c\xad\xb6\x4f\x6f\xdc\x68\x0e\xbb\x98\xaf\xd7\x45\x3c\x77\xab\x4a\x37\x8d\x46\x12\x32\xc7\x26\xf8\x6a\xde\xea\xa0\x97\x95\x44\x6c\x3b\xa1\x42\x9d\x50\xc1\x68\xce\x30\x11\xdb\xc0\x60\x1c\x24\x79\x9a\xec\x1a\xf7\xd6\xc1\xa4\x0e\x0c\xc1\x22\xb9\x60\x81\x01\x88\x64\xaa\xc8\xe8\x97\x59\x52\x14\x10\xfd\x3b\xab\x4a\xa6\xa3\x40\xe7\x06\xb1\x7e\x94\xe8\x5f\xa7\xf2\x3e\x53\xcf\x12\xae\xad\x62\xa0\xd6\xd4\xbd\x73\x66\x0a\xa2\x8a\xe7\x50\x92\xcc\x69\xb5\xaa\x64\x51\x7b\xd6\x5c\x56\xef\x9f\x1b\xf8\x54\x8d\x5e\x68\xa8\xbc\xf7\xa1\xf2\xbc\x06\x95\xb5\x79\x91\xa0\x31\x7a\x97\x02\x63\x0c\x48\x30\xf5\x72\x60\x7c\x0a\x7a\xcd\xe8\x02\x12\xd8\xb1\x05\x24\x70\x23\x0b\xc0\xac\x29\x85\xa2\x85\x69\xe6\x7f\x02\xea\xe7\xea\xf2\x77\x8b\x93\x02\xe4\x5f\x10\x81\xd5\xff\xb7\xd4\x23\x02\xee\xe8\x6d\x18\xde\x56\x61\x7e\xd0\xb8\xb7\xf3\xb7\x11\xfd\x7f\xdd\xf8\xbb\x55\x89\xf0\xf8\x9f\x93\xf5\xa3\x7f\xfe\x73\x82\x1f\x5d\x90\xe0\x9f\xff\xfc\xae\x1f\x60\x72\x4c\xef\xea\x14\xb2\xa6\x1a\xee\x08\xac\x41\x3c\xf5\xde\x4f\x0b\xfb\xa8\xba\x34\x44\x01\xb9\xa2\xdd\x2e\x9a\x8d\x66\xe8\x98\x08\x1c\x1f\x63\x72\xda\x26\xed\x5b\x8e\x96\xe8\x0a\xc7\x4b\xf2\xb2\x2d\xf7\x66\x74\xa3\x72\x6f\x86\x57\x61\x88\x4e\xe9\xb7\xe9\x84\xca\xba\x4e\xa8\x76\x9b\xc3\x74\xc0\x3c\xf5\xc4\xf4\x83\xe2\x55\x3b\xf0\x90\x96\x6a\x89\x6d\x40\x94\x4e\x80\x4b\x74\x4a\x32\x4c\x5e\xfa\xc8\xe2\x25\x29\x8c\x11\xc4\x6f\x55\x72\x1d\xc8\xe2\xab\x30\x4c\x0c\xbb\xd3\x81\x53\x7c\x4a\x00\x36\xe2\x97\x44\x0a\x45\xa5\x9f\x57\xd6\x42\x4c\x3d\xf1\xd9\xe8\x37\x8b\x0d\xee\xe3\xdf\x2a\x6c\x70\xbf\x81\x0d\x38\x23\xbf\x19\x74\xa0\x39\x46\x8c\xa4\x8c\x64\x0c\xc2\xea\x46\x11\x26\x45\xd3\xbd\xb9\x67\xeb\xc4\xd9\x2d\xe2\xeb\x35\xe2\xf4\x63\x2e\xae\xd3\x82\x61\xdf\xcc\x4d\x90\xc4\x23\xd8\x52\x7b\x69\x16\x28\xd7\xee\x0b\x18\xf6\x2c\x0e\x12\x54\xf3\xbf\x98\xf9\xa5\xe1\x56\x7d\xb0\x78\xe1\x24\x3b\x43\x06\x3e\x11\x46\xc2\x4a\x7a\x71\x0c\x64\x9d\x91\xfa\xfa\x16\x0d\x7c\x24\x63\xb5\xe5\x0d\x79\x08\xa8\xa4\x60\x8c\x75\xbc\x97\x94\x64\xb8\x2c\x10\xca\x69\xee\xa8\x42\xb9\x5e\x8f\x27\x18\x5b\x27\x0c\x40\xc7\x2e\x37\xec\x0a\x2a\xd7\xe3\x24\xa5\xab\x2c\x39\x67\x59\x1c\x29\xd0\xaf\x71\xb6\xd2\x39\xea\x87\xa0\xfe\x6e\x1c\x2a\x8c\xfb\x0e\xba\xd4\x77\x49\x64\x7e\x5f\xc4\xe3\x09\x11\x0b\xf5\xc7\x31\x2b\x12\xba\x52\xfd\xc7\x19\x8a\x30\x81\xba\x71\x86\xfa\x0a\xa7\xab\xec\x38\x43\x03\x5c\xb6\x79\x73\xb4\x16\xb8\x28\xd9\x70\x2a\xb0\x45\xb8\x58\x62\x92\x0c\xbd\x9d\x49\x36\x2d\xb5\xb2\xcd\xa4\x44\x3f\x4b\x70\xab\xe3\x84\xbf\x33\xae\xfb\xec\xa4\x45\x27\xc9\x72\x96\xcc\xee\x3b\x4c\x3b\xea\xe3\x17\xbd\x40\xfb\x11\x19\xa6\x43\x6c\xe2\xb6\x73\xda\x27\x60\xdc\x44\x07\x61\x32\x8e\x26\xa3\xdc\xb8\xa5\x88\xcd\x2f\xe8\x66\xbd\x46\x48\x73\x63\x54\x16\x0e\x43\xa1\xd9\xcf\x39\x86\x50\x5b\xb0\x61\x38\x0c\xbb\x08\x4c\x2e\x20\x87\x24\xe3\xfe\xc4\x3a\xd2\xb0\xeb\x6e\xdd\xe5\x81\x63\x59\xd0\x4c\x1d\xeb\x6e\x89\xd0\x80\x34\xc1\x44\xfd\x34\x6e\xf0\xa2\xd8\x78\xc3\x13\x34\xa9\xfb\xb6\x33\x0d\xa6\x3d\xd8\xfe\x9d\x1d\xfb\xb0\x56\x9d\x12\xd5\x65\x0c\x66\x77\xda\x45\x5e\x55\x2a\xa7\x50\x20\xa1\xe3\x68\x32\xb4\xde\x1e\x75\xb1\x27\x71\x42\xd3\x1e\xbc\xe0\xc0\x78\x24\xed\x29\xf8\x30\x3e\x72\x5d\x51\x6b\xe6\x0e\x0e\x58\x91\xa0\x48\x50\x5d\x10\x1b\x6c\xf7\x2c\x0a\xc3\x9a\x05\x09\x5e\xaf\x0f\xba\x94\x26\x60\x90\x31\x30\x5f\x18\xaf\x52\x1a\xb9\x66\xcb\x74\x8e\xf6\xa8\x2d\x84\xba\x62\xbd\x56\xe3\x7c\xa6\xad\x38\xd4\xe7\x53\x31\xde\x83\x5a\x7a\x2a\x30\x0d\xbd\x22\xaa\xee\x81\xab\x6b\xf2\x9f\x2a\x08\xaf\x4a\xab\x5f\xc4\xad\xa1\xaa\x21\xfc\xa2\x83\x5a\xd1\xc1\x84\x98\x75\x00\x85\x3e\x6c\x2a\xa9\x0c\x55\xe9\x2b\x2b\x54\x26\xc6\x63\x2d\x62\x24\xf5\xf1\x0a\x1d\x1f\x10\x36\x21\x39\x8d\x9c\xbb\x13\x4e\x05\x8d\xd4\x68\x1e\x03\x0c\x18\x88\x4e\xaa\x83\xea\x36\x35\x9a\x8c\x54\xb2\xd1\xb0\x32\x1b\x1c\x95\x25\x1a\x27\x24\x9b\x80\x92\x97\x3b\x47\x53\xe6\x47\x16\x63\xb7\x9d\x57\x89\x64\xa8\xcf\x76\x0f\xfe\xc6\x70\xd9\xad\x61\xa4\x31\xeb\x7d\x10\xf2\x54\x26\xb9\x64\x33\x1a\x4d\x68\x50\xfd\x0c\x88\xca\xfe\xb4\xe4\x3c\xe5\x17\xb4\x3f\xa1\x81\xf9\xd6\x19\xea\x05\x98\x31\x55\x6d\x30\xa1\x81\xfb\x15\x94\x28\x01\x63\x17\x50\xff\xa9\x4b\xc8\x55\xb5\xf7\x69\x51\xa8\xf6\x54\x5f\xe6\x5b\xb7\xf7\x3e\xb9\x33\x5e\x4f\xe8\xe0\xb1\xca\x74\xbf\x75\xfe\x3b\x91\xcc\xd8\x8c\xee\xa9\x8a\xfa\x5b\xa7\x3f\xcf\xb2\x9f\xf3\x54\x4a\xc6\xe9\x81\xca\xab\x7e\x9b\x71\x66\xa2\x60\x33\x7a\xa4\xf2\xf4\xb7\x4e\x7f\x7b\xad\x5d\x89\xd3\xfe\x40\x65\xd9\x9f\x26\x93\xcf\xd8\x5d\x55\x62\x1f\x4a\xf8\x69\xb6\x6f\xc9\x72\x36\x7b\xbe\x94\xe2\x2d\x9f\xd2\xfe\x63\x3d\x00\x3f\xd1\x0c\xe2\x92\x4d\xaf\x8a\xe5\xf5\xe9\x55\xba\x58\xa8\x16\x9f\xc0\x70\xea\xa9\xf5\xa2\xd7\xaa\xd8\xa1\x5f\xec\xda\x75\xcb\x93\xec\xfe\x0b\xb3\x8d\x0d\x22\xe8\xb6\x96\x58\x2b\x38\xa3\x83\xbe\x57\xc4\x5b\x50\xc0\x9a\x6a\x55\xcd\xa2\x9a\xdf\xba\x80\x5a\x46\x66\x4b\x1c\x4c\x68\xe0\x27\x78\x8b\x6b\x8b\x1c\xd9\x15\xae\x15\xd1\x2b\x66\xcb\xf4\x07\x6e\xad\xeb\xa5\xaa\xc5\x75\x45\xf7\xeb\x8b\x5e\x2b\x0f\x8b\x6c\x96\xd8\x55\x78\x6c\x57\xbf\x9e\x51\x5f\x57\x57\xfa\xd0\x5b\xda\x7a\xdb\x7a\x99\x6c\xc1\x41\xbf\x5a\x3a\x5b\xae\x44\xa9\x02\xf2\x54\x03\x39\xd0\x37\x33\x46\x57\xa7\x3a\xde\x4d\xea\xc0\x9c\x3c\xcf\x32\x31\x7d\x91\x14\x2c\x8e\xc8\x31\xbf\x48\x39\xd3\x6e\x48\xdc\x69\x9d\x33\x17\x97\x52\x54\x8e\x5f\x7b\x85\xb9\x01\x12\xff\x80\xc6\x4e\xb6\x61\xf3\xcc\x89\xb4\x19\xdc\x65\xb8\xf3\x18\x3b\x91\xf3\xf5\x48\xc4\xbe\x4b\xf5\x05\xab\x6e\xe3\xc2\xc4\xae\x35\xf8\xc5\xfc\x41\x5b\x54\xfb\x3a\x4b\x53\xbc\xa6\x32\x69\xc6\x2e\x35\x22\x75\x37\x98\x91\xeb\xec\x93\x39\x53\xd9\x41\xaf\xf7\x48\x26\xc5\x55\x11\xe0\xc9\xd0\xdc\x6e\xae\x08\x88\x61\x24\xc2\xe0\x70\x02\xd9\x02\x83\xb8\xb2\x76\x33\x05\xc8\x78\x40\x32\xd6\x5b\x24\x79\xa1\xb0\xdd\xa4\xd4\x84\x66\x35\xb9\xcb\x3f\x35\xb9\xad\xd3\x62\xde\x96\x7c\x75\x5a\x8b\x5c\x5c\xe4\xac\x28\x60\x7e\x6d\xd3\x63\x76\x7a\xbf\x17\xaa\xdb\xc6\xf4\xc6\x03\x57\x60\x73\x3e\xd7\x3e\x52\xff\xb6\xdd\x92\xdb\x77\x8b\xbb\x69\xf1\x6f\xdd\x2d\xb2\xd2\x6e\xa1\xe2\xe0\xe3\xc9\xe9\xe7\x40\xbb\xbb\x60\x65\x73\x96\x48\xea\xd7\x30\xf8\x10\x13\x57\xa3\xf1\x60\x12\xc3\xc6\x36\xa6\x6c\x88\x37\xbb\x20\x10\x45\x62\x63\xd2\x37\xff\x17\x9b\x98\x2c\x0b\xf6\x1f\x6d\x5e\x0f\x9a\x98\x6d\xee\xe1\xc5\xff\xf1\x1e\x3e\x0a\x76\x58\xcb\xc4\xf8\xc3\x87\xae\xda\xd0\xda\xa1\x93\x2d\x40\x7a\xff\xe7\x26\xf8\xdf\x88\x4c\xd4\xd4\x2a\x08\x7d\x75\xfc\xee\xf8\xf3\x71\xb0\x01\x9c\x1d\x0f\x7d\x6c\x8e\xfe\xfc\xff\x74\xf4\x3b\xc1\xa3\x79\x2e\xb8\xf4\x0f\xda\xf3\xcf\x2f\xdf\xfc\xd9\x59\xdc\xfe\x5f\xcf\xe2\x3c\x99\x5e\xfd\xa7\x93\xb8\xfb\x37\x4e\x0a\xe1\xdb\xcf\x4a\xee\x26\x93\xff\x29\x34\x7e\x9e\xb1\x91\xa4\xc1\x0e\xf8\x0b\x60\x3f\x7e\x7a\xeb\xc4\x1e\x88\xe1\x96\xa3\x84\x24\xcd\x1d\xf6\x6b\xe0\x09\x78\x6b\xda\x5c\x22\x7b\xe2\x0a\x3b\xd4\xc1\x27\x43\x8b\x10\x6b\x98\x10\x6c\x7d\x19\xe5\xe8\xf1\xd1\xe1\x13\x4c\xae\xd4\xe7\x41\xd4\x8f\x30\x39\x65\xe0\x87\x72\x6f\x1f\x93\x97\x50\xa0\x7f\x34\xc0\xe4\x37\xe0\xae\x1c\x1e\x1d\x60\xf2\x11\x0a\xec\xef\xed\x61\xf2\x09\x3c\x4f\xed\x0d\x0e\xb0\x51\x77\x3d\x61\x4d\x33\x06\x1d\x40\xc6\x33\xd6\x60\x9e\x39\x43\xc3\xad\xad\x2e\x6a\xaf\xe4\x30\xf4\x84\x8a\xd7\xc9\xe2\x81\x30\xa4\x5b\xac\x9d\xc7\x60\xab\x37\x69\x8d\x8b\x1c\x86\x28\xda\x08\x44\x88\x11\xc3\x23\x55\x2c\x66\xc6\x72\xcf\x0f\xca\xfb\x81\x35\xb4\x11\x8c\x3b\xcc\xb1\x9c\x8c\xd4\x3f\x36\xc2\xf4\x58\x4e\xaa\x4a\x67\x30\xdf\x8a\xd3\xac\xe6\xef\x24\x60\xd8\x0f\x96\xa4\x5d\x17\x55\xc2\x42\xaf\x1f\x70\xe4\x36\x92\x63\x3e\x89\xd9\x98\x4f\x4a\x66\x4c\x59\x25\x95\xea\xef\xd0\xa8\x13\xb5\x2d\x27\xb8\xe8\x74\x5e\x14\x52\x70\x25\x8d\x53\xdd\x60\xe2\x39\x76\x18\xa7\x13\x9a\x40\x61\xf0\x38\xa0\x23\x59\x1b\x01\xec\xaa\x74\x0d\x14\xda\xa7\xdc\x4a\x3d\x74\xc7\xc5\x04\x57\xbe\x53\xd5\x4f\xdf\x7d\xaa\x31\xc8\x52\xc9\xe3\x7c\x32\xcc\xc6\xe6\x6b\x42\x39\x5a\xe2\x32\x1b\x17\xea\xab\xc0\xe5\x16\xf7\xab\xd9\x38\x31\xa5\x13\x2f\x66\x7d\x27\x2b\x11\x27\x95\x66\x96\xef\x55\x28\x69\x83\x03\x17\x5f\x20\x19\xa7\xe0\xda\xaf\x75\xdb\x33\x6c\x7d\x54\xc0\xd2\x70\xb2\xd4\x1f\x82\x4c\x29\x1f\xa7\x13\x32\xa3\xad\xf5\x20\xbc\xea\xd4\xc8\x35\x53\x3e\xec\x2e\x41\x26\xd6\x9d\x8d\x96\xeb\x75\xb7\x58\xaf\x67\xa3\x65\x18\x16\x5b\x80\xcd\x84\x61\x4d\x27\xba\x71\x5f\x1a\x8d\x11\xc8\xf0\x8e\xef\x52\xa0\xb4\xbd\xa8\x9d\x19\x26\x29\x8f\xab\x3e\x09\xbb\x4b\x65\xfc\x81\xa1\x8c\x04\xea\x33\x20\x0c\x13\xc6\x25\xcb\x6d\xa2\xfa\x56\xa9\x25\xc6\xf1\x03\xbd\xa5\x3c\xee\xf6\xcb\x07\x8b\x3c\x30\xa0\x6e\xf4\x67\x06\xa2\x25\xf0\x80\x85\xde\x3b\xe7\xd6\xc0\x92\x68\x15\x22\x76\x1a\x21\xbb\x15\x36\x68\x33\xaa\x62\xea\xe8\x61\x5c\x92\xb7\x6c\x9b\xda\x85\x63\x74\xaa\xf3\x02\x7e\x69\x2b\x6d\x4f\xe6\x69\xba\x5f\x42\xdc\x4b\x3d\x5d\x3d\x59\x14\x91\x4f\xc0\xee\xce\xab\x20\xc6\xb9\xd5\x88\x37\xc6\x02\x3a\x0e\xec\xca\xe8\x48\xab\xf7\x53\x37\x2a\x89\xdf\x56\x2c\xc8\x3c\xcd\x0b\xa9\x23\x45\x43\x76\x5e\xfa\xea\x1d\x46\xd8\x91\x6f\xea\xe5\x8a\x6f\xd0\xcb\xbd\x6e\x28\x8e\x57\x1a\xe2\xdb\x47\xd8\x2f\x4b\x5c\x12\xf1\x6d\x1a\xb4\xae\x83\xbe\xb1\xf1\x78\xc5\xf2\xf4\x86\xcd\xa0\x97\xd7\xb9\xb8\x6e\x1a\xc9\xd4\xd5\x1d\x79\xa5\x0e\x92\x52\x5e\x5b\x65\xcb\x99\x72\x2a\x03\xbc\xe7\xad\xd4\x08\xe5\x94\x11\x41\x53\xf2\x99\xa1\xbc\x4d\xa9\x84\x79\xce\x06\x9b\xb0\xcb\x3c\xd8\x15\xb5\x10\xb8\x06\x76\x93\xc5\x82\x25\x00\xa8\x8c\x04\xfa\x47\x40\x72\x0f\x7e\x99\x83\x5f\x95\x6a\x20\x9d\x59\x48\xcf\x31\xe8\x4c\xe2\x18\xd0\x7d\x42\x52\x5c\xdf\xe5\x7e\xa9\x16\xd8\x9f\x2d\x6d\x51\x08\x55\x97\x43\x8b\x9e\x04\x1e\x02\xe4\x2b\x7c\x94\xaf\xd7\xce\xbc\xce\x4e\x48\xdd\x93\xf5\x14\xc4\x8d\xb2\xbe\xd9\xac\xa6\xb5\x40\x8d\xd4\xd7\x3d\xd7\xf4\x66\xaa\x8e\x0d\xe4\xcd\x98\x7a\xf1\x77\xf2\x31\x0c\x64\xe2\x29\xba\x03\x41\x01\xd0\xd3\xae\x89\xe4\x5b\xe9\x10\xed\x0b\xd6\x8a\xdb\x73\xeb\x4b\xd0\x44\x2b\xd6\xea\xaf\xcf\xb5\xbf\xd6\xba\x34\xdd\x2f\x16\x4c\xd4\x9d\xe6\x29\xf3\xfb\x80\x4d\x52\xfa\x9e\xf9\x9a\xfe\x6e\x2a\x80\x33\xf2\xe6\x8c\x44\x4f\xef\x35\x71\xbf\x61\x93\xbd\x9f\x77\xa9\xb4\xf1\x55\xf8\x86\xc6\xd8\x09\xdb\xd0\x3f\x4b\x4a\x92\x6e\xaa\x08\xb7\x17\xdc\x10\x6c\x11\x41\xd2\x36\x0d\xa3\xb7\x9a\xb2\xd0\xa6\x48\x2b\x85\xde\x6a\x91\xbf\x15\xfa\x31\x65\xe3\x60\x96\xde\x04\xc4\x5f\xb0\x56\xd7\xc6\xce\x40\xe9\x39\xa3\x6f\x19\xe0\x9c\x77\x8c\x6e\xf7\xfc\x32\xf2\x42\x0f\xc7\x1b\x41\x80\x4d\x5b\x5f\xd8\x86\x71\x1c\x6c\xb9\x71\x05\xa9\x36\x7c\xb1\xcc\x0a\xed\x72\xc3\xe9\xe8\xe6\x61\x98\x93\x84\xb2\x5e\x9e\x2e\x16\x19\xfb\x05\x42\xad\xeb\xef\x5f\x75\xb8\x75\xf8\x3e\x4d\xbf\x30\x88\xba\x9e\xaa\xdb\x99\x39\x60\xaf\xbb\x0e\xf1\xc0\xaf\x04\x2f\x22\xac\x27\x4d\x60\xd3\x39\xad\x82\xfc\xa2\x6e\x1f\x93\x05\x9d\x8f\xa3\x09\xb9\xa4\xf3\x71\x7f\x42\xae\x15\xf4\x5d\xc1\x21\xe0\xa6\x4b\x62\x3f\x7e\x4a\x8b\xf4\x3c\x63\x44\x84\xa1\x4d\xfa\xa8\x27\x82\xc9\x0d\x5d\xdd\xa6\x33\x79\x19\x67\xe4\x52\x3b\xf3\xcc\x88\x14\x8b\x78\x37\x7b\x34\xd8\x49\x49\xc6\xe6\x52\x7f\x27\x25\xb9\xf0\xfb\x80\x3d\x22\x0b\xd5\x24\x7c\xbe\x63\xc9\x4d\xca\x2f\x74\x27\x90\xe2\xfa\xb8\x57\xf5\x5e\x42\xbd\xa9\x03\xe1\x77\xac\x16\x80\x51\xab\xec\xae\x2e\x51\x37\xb2\x16\x81\x5e\xac\xd9\x7b\x32\xc3\x2d\x11\x7a\x6a\xf1\x66\x99\xf6\x06\x3a\xbe\x27\x05\x99\x4d\x36\x95\x2d\x83\x62\x91\xf0\x80\xac\x2a\x99\xee\xb5\x91\xe9\xde\x6c\xc2\xf2\x66\xe1\x0b\x75\x33\xc3\xc8\x5e\xd5\x55\x35\xb6\x6a\xe6\xe8\xb3\xd8\xa6\x07\x6e\x41\x2a\xab\xe9\x54\x80\xf3\xd6\x63\xe6\xf4\x71\x0c\xc2\x0e\x4c\xe9\x9a\x76\xc3\x04\x93\xa5\x0f\x10\xe3\x09\x26\x53\xba\xd4\xfa\xcd\x4b\x05\x10\x06\x5e\xd4\x00\x23\x0c\x0e\x67\xcc\x2f\xfd\x4c\xf1\x0e\x44\x6d\x1f\x16\x36\xc6\x7f\x18\x22\xf7\x8d\x30\x71\xdf\xc6\x3c\x0a\x93\xf1\x74\x62\x3d\x86\xb9\xb6\x15\x5c\x5e\x37\xba\x22\x37\xcd\x84\x8b\x6f\x1d\xcc\x57\x76\xfc\xda\x8e\x09\x54\xa8\xc7\x66\x38\xf7\xb4\x16\xf4\xbc\xdd\x0b\xac\x3d\xc8\xb9\x77\x70\x85\x77\x70\x93\xfa\xc1\x55\xe7\x78\x7a\x3e\x9c\xb5\x69\x1d\x54\x9a\xf9\x28\x22\x1f\x99\xf6\x64\x4f\xc6\x1b\x86\x56\x4c\x5b\x44\xcc\xed\xa0\x89\xd9\xd7\x38\x25\xe6\x8c\xc7\x8f\x1f\x47\xc4\x8c\x2c\xe6\xc4\x8c\x2b\xce\xcd\xd7\xaf\xb1\x20\xd5\x98\xe2\xa4\xc4\xe0\x4d\x94\xb8\x16\x77\x68\xdf\xdb\xa7\x4c\xad\x49\x3a\xc1\xe4\x7c\xeb\x82\xd8\x4b\xae\xa9\x99\xf1\x2c\xb2\xde\x0d\xbb\xd4\xd3\xc2\x88\x26\x23\xff\x47\x0c\x4f\xb8\x8d\xba\xfd\xd6\xba\x7d\xbf\x6e\x1f\xea\x6e\xaa\x90\x3e\x1b\x78\x85\x06\x4e\xaa\x07\xf6\xf6\x5b\x30\x6f\xaa\x5e\xec\xfa\xa4\xd5\x34\x99\x92\xf5\xda\x55\x02\x6d\x26\xd9\x9b\x27\x57\x76\x37\x36\x8c\x2c\xd2\x39\x0a\xae\xc5\xb2\x60\x33\x71\xcb\xb5\xcf\x51\x75\x81\x84\xe1\xa5\x83\x31\xf7\x45\xbb\x7d\xed\xb3\x23\x90\x62\x39\xbd\x84\x38\x68\x7e\x15\xe4\x95\x34\xc8\x6c\x4a\x66\x64\x4e\x16\x74\xa9\x6d\x0b\x2e\x1c\x0c\x9c\xd3\xc5\x68\xa1\xe8\xd0\x17\x62\x09\x56\x88\x2f\xb3\x94\x71\xf9\x49\x9d\x04\x1c\x1b\xd4\x1c\x59\xd4\x1c\x69\x7c\x1c\x01\x86\x8e\x4a\x35\xea\x6c\xbd\xd6\x2e\x8f\xa6\x50\xf1\x97\x30\xf4\x7f\xfe\xba\x5e\x77\xbd\xac\x2e\xeb\xc1\x90\x59\x81\xa7\x54\x7b\x75\x52\xdd\xa2\xf3\x1e\x74\xf4\x68\x80\xc9\xac\x9e\xae\x3b\x7e\x34\xf0\xbc\x94\xdc\x52\xd7\xca\xc8\x7d\x81\x99\x32\x84\x11\x36\x9d\x91\x63\xf7\xfd\xeb\xb0\xd6\xd9\xdd\xee\x79\x4f\x4d\xa3\xd1\xd7\xf1\xee\x79\x4f\x8a\x05\x78\x34\xcc\x30\x9a\xeb\xbc\xe2\x8f\x5c\x22\x34\xf8\x1b\xfc\x58\x88\x5b\x3b\x54\x32\xc0\x3b\x5e\x9a\x1e\x26\x19\x60\xfc\x68\x0f\xe3\xff\xdf\x80\xd2\x28\x0c\xd1\x7c\x87\xf6\xbd\x81\x5f\x51\xd3\xce\x75\x72\x87\xe0\x23\x39\x2f\x10\x52\x1b\xa0\x07\xfa\xb3\x5e\x6d\xbc\x3b\xc5\x64\x8a\x77\x06\xe4\xf4\x6b\x35\xde\x98\x7d\xc1\xbb\x33\x4c\x66\x78\x67\x30\xf4\xc7\xed\x06\x78\x55\x1b\xee\xa9\x1a\x67\x59\x2d\xa2\xa1\xcf\x6e\x3c\xcc\xeb\xbe\x7d\x82\xf4\x1e\xad\x2c\x40\x0b\x87\x1c\xa6\x0e\x39\xcc\x7c\xe4\x30\x27\xd3\xf3\x18\x54\x94\x1d\x92\xf4\xef\xd3\x1a\x0a\x68\xeb\x17\x61\x72\xb3\x81\xf1\x0f\x23\x8c\xe3\x7f\x6b\x14\x0a\x15\x25\xe4\x7e\x82\xc9\xed\x03\xc8\xe8\x5c\xd1\xef\xae\x75\xb0\xe9\xc3\x64\x7c\x3e\xc1\xe4\x6e\x3b\x4e\x37\xfe\x92\xb7\x5c\x0c\x44\x9f\x51\xf6\xff\x67\xef\x5f\x98\xdb\xc6\x95\xbc\x71\xf8\xab\x48\x7c\x33\x7c\x88\x4d\x5b\x23\xf9\x96\x84\x3e\x3c\x5a\xc7\x71\x32\x9e\x89\x63\x8f\xed\xcc\x25\x7a\xf4\xe4\xd0\x12\x24\x31\xa6\x40\x85\xa4\x7c\x89\xc4\xef\xfe\x16\xee\x00\x49\xc9\x72\x66\xce\xd6\xfe\xb7\xb6\x2a\x15\x8b\x24\x08\xe2\x8e\xee\x46\xf7\xef\x47\x86\xe6\x0c\x55\x55\x53\x14\x75\xad\x19\x4e\xb3\x28\xb3\xea\x5d\x69\x03\x66\x62\xf5\x1e\x6d\xd0\x7b\xce\x5b\x85\x10\x3a\x28\xbd\x5f\xbb\x7f\x34\xb0\x5a\x75\x15\xa8\x31\x43\x34\x46\xe6\xae\x9b\x8b\x1d\x4e\x59\x89\xe7\x19\x3e\x99\xce\x70\x1a\xe6\xd1\x2d\xfe\x89\xa9\x66\x5e\x5a\x63\xc2\x56\xed\x79\xc7\x19\x1b\xfd\x6b\xc8\xe8\xf2\x71\xcf\x3a\xe5\x0e\xae\xe1\x7e\xb5\xb0\xa4\x81\xef\x95\x1c\xa4\x44\xc0\xa8\x95\x26\x49\x0e\x31\x82\x14\x8f\xfc\x71\x01\x59\x35\x9b\x43\x0c\x86\x70\xcf\x75\x56\xaa\x7c\x36\xdb\x05\x0c\xb8\x0b\x1c\x97\xbd\xdf\xe2\x1a\xe4\x7a\x1d\xbd\x4e\xbf\xe4\x2f\x92\x5b\x9c\x8e\xe2\xe4\xce\x77\x26\xd1\x70\x88\x89\x03\xb3\x24\xa2\x4b\x3f\xc3\xed\xca\x7c\x87\x24\x04\xd3\x9b\x1c\xdc\xc9\x77\xc2\xeb\x2c\x89\xe7\x39\x76\xe0\x1b\x27\xa2\x14\x2b\x27\xa4\x62\x39\xbd\x4e\xf2\x3c\x99\xea\x75\x95\x33\x01\x5c\x84\xc3\x68\x9e\x99\xc0\xf7\x7c\x4c\xfb\x8b\x64\x16\x0e\xa2\xfc\xc1\x6f\xd7\x7d\x44\x26\x13\xe2\xb6\x4e\xdd\xda\x81\x3c\x0d\x49\x36\x4a\xd2\xa9\xef\x30\xfe\x01\xaf\x83\x1c\x08\x25\x6d\xbe\xef\x3c\x63\x5b\x58\xc3\x91\xa2\x04\x95\x04\x9c\x69\xd6\x70\x90\xbc\x83\x5b\xb9\x82\xad\xca\x5a\x38\xcc\x22\x32\xa6\x7f\xf0\x09\x39\x9b\xe7\x48\x7e\x5c\x08\xdd\xfe\x42\x65\xfe\x66\x9e\x8a\x8f\x38\xf5\x79\x0d\x45\x82\x56\x36\x49\x52\xba\x91\x3a\xd3\xcc\x41\x05\xd7\xc2\x74\x2d\x3a\x20\x50\x1b\x7c\x87\x01\x40\x39\xc0\x77\x27\xa7\xd3\x6e\xff\xe0\xc8\x2d\x4a\x5c\xd9\x0d\xb9\xc7\x6e\x95\xa0\xfd\x1d\x31\xb4\xd9\x95\x23\x3e\x27\xb4\x08\xb3\xa5\xad\x56\xba\x8f\xf2\xbf\xd4\x48\xa6\x62\xe2\x2f\xea\x46\x8a\xb9\xc3\x5a\xdf\x16\xf3\xa8\xb1\xbd\xd7\x6e\xd3\x8f\x6e\xf6\x4d\x70\x1a\xdb\x2c\x7d\x44\x46\x11\x89\x72\x4c\x5b\xd6\xf9\xcf\x1b\xfc\xc0\xa8\xfd\xb3\x06\x97\xf2\xfd\x85\xd3\xfe\xc1\xf1\x17\x95\x71\xd2\x46\x0e\xa8\x71\xd4\x29\x80\xb7\x6f\x4d\xc2\x8e\x99\x70\xa7\x28\x7d\xe4\x3e\xca\xd5\x37\x54\x87\xea\xdc\x54\x6b\x97\xde\x13\x75\x5e\x5d\xbc\x0e\x72\x0a\x60\xfd\x5b\x57\xf6\xd6\xab\x6d\xf6\x7c\x4d\x99\x0b\x4e\xe1\x30\x8a\xa3\x99\xdf\xec\x80\xa2\x72\xb8\xa2\xcb\xf6\x05\x1b\xd2\x4e\x81\xbc\xbc\x35\xc5\xd3\xc4\x7b\x83\x85\x53\xc9\xeb\xcd\x74\x30\x8e\x8e\xc6\x0c\x77\x3c\xe6\xe3\x02\x8f\xb8\x06\xc6\x9a\x9d\xe7\x5f\x1b\x8f\xab\x2c\x74\x03\x43\x5f\x1b\x5a\xfa\xda\xc8\x0a\xbf\x98\x69\xe9\x73\xd4\x75\xf8\xd7\x1c\x7f\xc4\xfc\xde\x87\x51\x16\x5e\xc7\x78\x08\x53\xfd\xa5\x89\xeb\x4e\x98\x27\xbc\x78\x28\xca\x32\xd6\x29\x6e\x5d\xf7\x96\xb9\xc6\x8b\x14\x46\x93\xc0\xb5\x4e\xf6\xe0\xba\x0f\x70\x17\x90\xd6\x28\x19\xcc\x33\xf1\xfc\x5e\x3f\xbf\x73\xdd\x3b\x38\x96\xcf\xc5\xe2\xa4\xfd\xff\x6f\x58\xfc\xce\xeb\x78\x9e\xc2\xa5\x11\xca\x73\xc4\x7e\xbf\xa5\xaf\xc0\x27\xfd\x5b\x9a\x12\xce\xd9\xad\x5f\xf0\xc3\x9b\xe4\x8e\xc0\x85\xbc\xfa\x38\x83\x33\xf6\xfb\x94\xca\xd2\xec\xd9\x95\xbe\xa6\x93\x1b\xc3\x07\x7d\xe3\xe3\x0c\x3e\xb3\x2b\x56\xb5\x63\x32\x84\x53\x7d\x79\x9a\xdc\x62\x06\x37\x23\xae\x99\xaf\x0f\x1c\xb2\x1b\x6f\xd2\x70\xcc\x73\x7b\x1f\x90\x56\x1e\x5e\xb3\xe5\x1d\xbe\xe9\x3e\x78\xdf\x6d\xfb\xef\xe1\x4d\x40\x5a\x46\xb3\x31\x73\x13\xbc\xa5\xaf\x3c\xcc\x30\xbc\xd6\xc9\xdf\xea\x2e\x7b\x0b\x5f\x6c\x45\x9c\x0f\x22\x07\x1c\x35\x84\xa8\x2a\x6e\x0c\x20\x69\xe2\x4b\xe9\x96\x54\xab\xae\x83\x65\x0f\x94\xc3\x41\xff\x54\xf9\x54\xbb\xda\x01\xc7\xe8\x58\x79\x55\xee\x46\x16\x58\x45\x3b\xd1\x88\xb0\xa2\xbf\x58\xa7\xe9\x5f\xe2\x35\x76\x43\x74\x9e\xfc\xfd\x71\xc6\x7e\xa9\x8e\xd3\x57\xac\xa1\xf5\xa5\x48\x28\xbb\x4c\x5f\xd0\x0e\xd3\x57\xac\xbb\xd8\xa5\xea\x2c\x07\x1c\xd9\x55\x0e\x38\xe5\x7e\xa1\x4f\x1f\x66\xcc\xb4\xf1\x7b\xd9\x62\xf0\xac\x7c\xe3\x63\xd9\x1a\xf6\x5b\xf0\xb1\xd7\xee\xc3\x4f\xc1\xc7\x5e\xa7\x7f\x30\x75\xdd\xdf\x5c\xf7\x27\x15\x7d\xf1\x95\xf6\xe8\x27\xd6\xa3\x08\x7e\x09\xbe\xb6\xa2\xcc\x1a\xce\xbf\x06\x5f\xc5\x24\x90\x77\xde\x05\x5f\x5b\x29\x1e\xe9\x93\xdf\x3f\xcd\x40\xf9\xaa\xe2\x5a\xab\xf4\x6e\xf7\x6d\x7d\xf6\xfa\x40\x99\xf8\xb9\x39\xac\x8e\x2c\x24\x77\xdd\xdc\x4b\x11\x34\x89\xeb\x3e\xd3\xb2\xb9\xfa\xd9\xc3\x7d\xf6\xb8\x5d\x20\x54\xd4\xcb\x81\x49\x9d\x1c\x68\x8e\x1b\xd3\x1f\xfe\x27\xaf\xd9\x46\xf0\xbb\xcc\x9e\x2f\x13\x9e\x30\xa6\x31\xd1\xb0\xde\x38\xf3\x9b\xeb\xde\xbb\x6e\x73\x6c\x14\x4d\x2a\xdc\x1e\x13\xdc\xc7\x70\x0f\xbf\x09\xa3\xcc\x1f\xc1\x9f\x9e\xc3\x35\x65\x38\x43\xf0\x33\xbf\x4c\x66\x0e\x1c\x22\xc0\x58\x5f\x7e\x40\x90\x1b\x97\x96\x30\xf8\x9b\xeb\xd6\x84\xd6\x5d\xb9\xee\x95\x38\xed\x26\xd8\xf8\xcc\x09\x8b\xb6\x52\x39\x7d\x46\x90\x18\x97\xa7\x08\xc2\x35\xdf\xf1\x7e\xf5\x30\x02\x36\x80\x10\xdc\xb8\xee\x0d\xfb\x02\xd0\x91\x16\xe1\xa0\xa6\xff\x30\x5a\xa8\x26\x5c\x2e\x3d\xf5\x9b\xaa\xe2\xfc\xd7\x15\x8b\x74\x44\xf0\x8b\xc7\xf8\x23\x79\xb3\x7f\x72\xdd\x4f\x1e\x46\x08\x8e\x5c\xf7\x48\xd4\x22\xc6\xd5\x63\x88\x79\x6b\x14\x91\xe1\x9b\xb3\xd3\x0f\xc9\x10\xeb\xdc\x91\x81\xe6\x2c\x17\xb0\x66\x10\xcc\x5c\xb7\xe9\x39\x87\x42\xe5\x09\xc7\x1f\x18\xd4\x06\x66\x58\xaa\xa8\x80\x0c\xdb\x16\xbb\xf9\xaa\x1a\xd1\xfe\xcd\xb0\x1e\x83\xbf\x59\x23\xd2\x69\xf0\x0f\x30\x48\x0e\x4f\xa7\x0b\x9a\x54\x6b\xd0\x0a\x95\x1e\x1e\xb4\xad\x2d\x3f\x08\xb4\x30\x1f\x86\x69\xce\x9b\x00\x01\x16\x81\xa1\xdc\x96\x61\x36\xa0\xeb\xc6\xd8\x43\xa5\xaf\xd7\x0c\x8b\x73\xd7\x3d\xf7\xf0\x46\x39\x1d\x33\x11\x4c\xe7\xd6\x9c\xba\x6e\x5d\x10\xe7\xa5\xeb\x5e\xb2\xa0\x18\x84\x60\xb0\xa6\xcd\xac\xa2\x3d\xb3\x9a\xaf\x59\x0d\x4a\x2d\xb5\x5d\xe7\x7b\xda\x4e\xce\x3b\xd1\x7a\x17\xae\x7b\x41\xeb\x7e\x49\x5b\xe6\x49\x0d\x59\x5b\xbe\x4b\x31\x30\x87\x38\x98\x1d\xc8\x61\x16\x04\xc1\x10\xbb\xee\x17\x36\xa8\x5c\xd7\x1b\xe2\xc0\x09\x05\x87\xc4\x08\x07\x8b\xc2\x4e\xd9\xf5\x46\x5c\xfb\x0e\x5e\xc3\x08\x2b\x89\x28\x98\x22\xdf\x73\x42\x3b\xb7\xe5\x92\x26\x4e\x93\x18\x07\x32\x0f\x04\x23\x2c\x82\x01\xd5\xee\xd9\x0f\xa6\xfc\x73\x33\xd6\x17\x97\xac\x2f\x42\x48\x11\x4c\x8c\x1b\xef\xe0\x77\x04\x53\xe3\xc6\x0c\xc3\x04\x23\xb8\xc5\xe5\x2d\x64\x8c\x83\x5b\x4c\x37\x91\x07\xf6\xa3\xd3\x5f\x69\x97\x7e\xc0\x8c\xa3\x41\xdb\x9c\xaf\x71\x30\xc6\x7c\x31\x6c\x4e\x57\x05\x0b\x0e\xf1\x5a\x7d\x7a\xc0\xf5\xe9\x21\xfc\xe6\xba\xbd\x81\x25\xad\xc1\x71\x1f\xa6\xae\x3b\x50\xcd\x86\x80\xef\x56\x7e\x88\x41\x86\x4a\x5f\x82\xd8\xe4\xfd\x88\xde\x14\xdb\xbb\x3f\x17\x17\x1f\x67\xfe\x80\xfe\x54\x1b\xbc\xff\x07\x98\x1b\xbc\x9f\xab\xa7\x1f\x67\x3e\xa6\x17\x6a\xe3\xf6\x7f\x06\xbd\xe1\xfb\x29\x06\x63\xc7\xf7\x13\x75\xc9\xb6\x7c\x9f\x60\x66\x10\x98\x62\x90\x9b\xbd\x3f\xed\x6e\x75\xfc\x6f\x05\x8c\x30\x7c\x41\x90\xc1\x35\xae\x9c\x45\xbe\x35\x1a\x87\xbe\xfe\x0c\xb8\x84\xe5\xc7\x05\xbc\x41\x1a\xb2\x42\xd8\x0b\xbe\x68\x7b\x81\x30\x0e\x28\xe5\x34\x22\x71\x44\xf0\xd6\x28\xa6\x52\x46\x18\x47\x63\x72\x92\xe3\x69\xe6\xab\x03\x95\x2f\xf3\x2c\x8f\x46\x0f\xcc\xc3\x8b\xe4\xfa\xbe\xd6\x06\x53\x1c\x87\x3c\x34\x94\xf3\x0c\x5e\x85\xb3\x9f\xa2\xf1\x24\xa6\x1a\xae\x50\x5e\x99\x2e\x33\x0b\x79\x58\x6a\x45\xb5\xb5\x9e\x26\xf3\x9c\x96\x48\x99\x17\xfc\x36\x48\x16\x3c\x5b\x4f\x6e\xc3\x2c\x1c\x0e\xa9\xfa\xdb\x86\xc1\x3c\xcd\x68\x4e\xc2\xc2\xe1\xc0\x3c\xc3\xe9\x25\x8e\xf1\x20\x97\x76\x8e\x5b\x9c\xe6\xd1\x20\x8c\x0f\x69\x1d\x7d\x67\x1a\x0d\x87\x4c\xb4\xdb\x9a\x26\xdf\xb6\xf8\xc1\x70\x48\x06\xd8\x91\xe9\x9d\xad\x3b\x56\x9b\xba\x67\x39\xbe\xcf\xdf\xe0\x41\x22\x4d\x05\xfc\x2e\xa7\x3b\x54\x76\x10\x70\x5c\xdf\x67\xb9\xb3\xc1\xb9\xc5\x82\x1c\x19\x57\x20\xad\x04\x0b\xc1\x15\x6f\x16\xe0\xb8\xcf\xd4\x44\xa5\x8a\x76\x8d\x9d\x46\x56\x51\x2c\x38\xf4\xa5\x12\xff\x21\xfb\xfe\xe1\x90\x76\x98\x2f\xc2\x79\x8b\x02\x64\xbe\xfe\xa2\x00\x4b\xa8\x59\x14\x85\x41\x06\xf8\x9a\xad\x1c\xaf\xc3\x8c\x29\x90\xaf\x05\x64\xdc\xef\xcc\xfd\xef\x45\xa7\x23\x47\xd2\xb3\xaa\xcf\xdf\x42\x20\x3b\x7d\xfc\xfe\x23\x65\xf8\x6d\x43\x05\x55\x8d\xcf\x52\xc8\xb6\x18\x94\x32\x68\x7b\x9e\x27\x5c\x17\xab\xd3\x55\xf9\x1a\xa9\x4e\x92\xc5\x99\x06\xd7\x56\xa5\x1a\x3b\x32\xd4\xd8\x99\xa5\xc6\x4e\x2c\x35\x76\x1a\x90\x16\x6d\x87\x30\x22\x38\x55\x67\xf8\x70\xab\x0b\x37\xed\x3a\x71\xe4\xf8\x53\x16\xbc\xad\x92\x72\xd5\xea\x21\xf0\xc6\x3a\xe5\xb8\xbb\x28\xfc\x31\x32\xbe\x75\xad\x35\xab\x31\xf4\xec\xf3\x4c\xaa\xc2\x0e\x31\xc9\xea\x95\x57\xa5\x42\xdf\xe8\x87\xc7\xae\x7b\xcc\x94\x56\xf1\xf0\xdd\x3c\xcf\x71\x9a\xc1\x91\x4e\x42\xb7\x6c\xa6\xbf\x0e\x23\xee\xbe\x70\xae\x9f\x51\xd9\x8b\xa9\xae\xf5\x8a\xf1\x19\xf3\xef\xa6\x13\x0e\x0f\xe1\x4a\xbf\x76\xe6\xba\x67\xf0\xa1\xa4\x22\xaa\x6e\x74\xc0\x51\x9d\xa5\x54\xc6\xa7\x2a\x88\xd5\x0e\x30\x6f\x4a\x6d\x89\x35\x56\xad\x3a\x29\x1a\x82\xdd\x60\xd5\x5e\xa3\x36\xca\x2a\xd2\x2e\xf8\x1c\x98\x60\x30\xde\x33\x8c\xe0\x34\x58\xb0\xef\xf8\xf7\xcb\xe5\x67\xde\x3f\xcb\x65\xb3\x63\x2e\xac\x61\x01\x27\xe5\x13\xdd\x8f\xf6\xe9\x7e\xec\xba\x27\x5a\x0e\x3a\xa9\xe8\x1a\x08\x7a\xb1\xd8\x4a\x0f\x4d\x1c\xa5\x3c\xe1\xd1\xe1\x43\x04\xef\x83\x43\xed\xef\xd9\x86\xdf\x59\xdb\x1f\xf6\x0e\x75\x40\x25\xf4\x9c\xf7\x51\x96\xd3\x42\x5d\xe2\x41\x42\x86\x61\xfa\x70\xc8\x75\xf7\x3e\x82\x6f\xeb\x8e\x85\x55\x89\x4a\x82\x36\x16\x9b\x3c\xbc\xd1\xf2\xc3\x37\x2a\x61\xbc\x0d\xd6\x6d\xe5\x23\xbe\x95\xcf\xe0\x94\xb7\x98\xeb\x8e\xc4\xd0\x6e\x1e\xd1\xdf\x63\x31\x50\xcf\xd9\x03\x31\x32\x6f\xf8\x85\x18\xe6\x03\x7a\x25\x26\xb6\x5c\x0c\x38\x48\xe1\xc8\x58\x34\xde\xc6\xf8\x9e\xdb\x45\xde\xd3\x07\x99\x5d\x6d\xaa\x1a\x8d\xd4\x18\x46\x7a\xe1\xbc\x29\xa8\x9e\xf5\x3a\x98\x2c\x97\x74\x2e\x4b\x81\x65\xe0\xba\xde\x5b\xbd\x16\xb0\xc7\xcc\x1f\xe7\x6d\xfd\x14\x09\x8c\x0a\x5b\xe2\xca\x05\xcd\xfc\x0b\x46\xf0\xbe\xeb\xbd\x0e\x8c\x2c\x97\xcb\x49\xf7\xb5\x70\xf2\xa1\x5f\x0e\x98\x95\xcb\x13\x3f\x5f\x77\x5f\x07\xec\x99\x2f\x6e\x18\x6f\x96\x8a\xc6\x92\xa1\xea\x81\xc3\xb3\xaa\xa7\xd2\x69\xd5\xbb\xe3\x76\xad\x20\x36\x62\x3e\x59\x6c\xaa\xc1\x03\x3f\xdd\x78\x53\xc0\x75\xf5\x63\xaf\xe1\x2d\x55\x5f\x0f\x79\xa4\x2b\x42\x55\xc7\xa9\xcd\x8a\xf3\xda\x16\x7d\xde\x14\xf0\x16\xc1\xa1\x79\x3c\xf2\xd3\x26\xc7\x23\x4a\x02\xe2\xa2\x4f\x59\xcc\xa1\x77\xb7\x84\x6e\x5c\x27\x16\xd5\x89\x3f\xf5\x62\x81\x65\xf7\xaf\xe7\x51\x66\x6f\x0a\xc1\x24\xc6\xa3\xdc\x91\xa2\xcd\x55\x32\xf3\x5f\xca\x8b\xd7\xfc\xf8\xe5\x25\x95\x16\xcc\x01\x54\x43\x04\x8c\x15\x11\x30\x37\xc7\xa9\x61\xcd\x44\x0d\xb5\x4e\x37\xf4\x6f\x7f\x92\xdc\x72\xf1\xe4\x49\x59\x19\x52\x8b\x32\xa7\xef\x71\xc2\x38\x3e\x26\xcc\x63\x03\xd5\x52\x15\x49\x04\xf8\xaa\xb9\x30\xaa\xbd\x5b\xaa\xf6\x6e\x01\x35\x33\xd9\x5f\x98\x9d\x63\x74\x9a\x2d\xf8\x88\x55\x43\x0a\x5f\x22\x4b\xa7\x33\xbb\x6f\x64\x49\x1c\x0d\xcd\xf3\x09\x59\x5d\xf1\x0e\x32\xe5\xd5\x38\x9a\xf9\x8e\x28\x97\x60\xc0\x16\xab\x93\x2a\xfb\x7b\x3c\xca\xfd\xce\xbe\x2c\xfd\x05\x3b\xe7\xe9\xec\x17\xc0\x97\x27\x61\xd7\xe7\x2d\x62\x1f\x86\x08\x4f\x7e\x47\x7f\x6f\x8b\x89\x74\x0e\x2c\xe4\xa1\x93\xbf\xf6\x2c\x2a\xcb\x0b\x44\xa5\x4e\xd9\x95\xf5\xe3\xf1\xd1\x0e\x66\xaf\x2b\xe9\xd2\x63\x97\x7e\x83\xbe\x8c\x6a\xc6\x87\x25\xbd\x17\x45\x01\xa5\x65\x55\x35\x0c\x6f\x89\xdd\x97\x34\x85\x18\x73\x8b\x12\x23\xb5\xdc\x90\xa8\x08\xfa\x9b\x10\x41\xbf\xf2\x10\x95\x17\x1d\x04\xbf\xe0\x60\x31\xe9\xf8\xce\xa4\xe3\xc0\x64\xdb\x77\x26\xdb\x0e\x4c\x76\x7c\x67\xb2\xe3\xc0\x64\xd7\x77\x26\xbb\x0e\x4c\xf6\x7c\x67\xb2\xe7\xc0\x64\xdf\x77\x26\xfb\x0e\x64\xf3\xeb\x3c\xca\x63\xdc\xb1\x2f\xb7\xf9\xe5\x75\x32\x7c\xe8\xf8\xce\x8c\xff\xda\xa6\xbf\x0a\xf8\xf5\x09\xc2\x68\x49\x0e\x95\xb2\xbf\xbf\xde\x73\x8d\x8a\x90\x71\x92\x2a\xbf\x9a\x20\x08\x32\xfa\x72\x94\x47\x61\xec\xf8\x19\x3f\x46\x51\xe2\xe4\x90\x0b\x6d\x74\xb9\xb2\xc9\xd1\xf4\x2b\x43\x26\xa6\xf2\xb1\xc8\x47\x37\x4c\xb4\x10\x36\x73\xdd\x19\x93\x55\x49\xf2\x7b\x1a\xce\x94\x7c\xda\x0c\x82\xa9\xeb\x72\xd9\x74\x16\xa6\x21\xe3\x24\x87\x07\xfd\x74\xec\xba\x63\xb8\x0e\x48\x4b\x50\x29\xc3\x9d\xfe\xfc\x75\xd7\x61\xcd\xe7\xf8\xd7\x70\xaf\x93\x9c\x86\xb3\x59\x44\xc6\x70\xac\x53\xde\x77\x7f\xc1\xfe\x3d\xdc\xd4\x48\x81\x6b\x04\x3c\x36\xf2\xcb\x27\x01\xb4\x0d\x1c\x70\xcc\x8a\x3a\xe0\xf0\x6a\x39\xe0\xa8\x4a\x38\xe0\x88\xf2\xe8\x5f\xa2\x64\x54\xbc\xb9\x0c\x06\xcb\xa5\xf7\xd0\x75\x66\x8e\x7f\xdc\xbb\xeb\x2f\x97\xbf\xe0\xde\x5d\x1f\x2d\x97\xfc\x28\x7f\x95\x51\xe2\x72\xa3\x33\x7e\x50\xe3\x80\xcb\xe4\x51\xef\xae\x0f\xaa\xaf\x38\x33\x51\xd4\x13\x55\x34\xdc\xe1\xbe\xb2\x5c\xe6\x08\xf5\xe1\xd6\x75\x23\xd9\x5b\x13\xfa\xdb\xea\xda\x07\x7a\x47\x77\x98\xf9\xb9\x90\x65\xcd\xdb\xb6\x92\x75\x48\xb3\x36\x0b\x32\x62\xa9\x65\xbb\x56\xd2\x8f\x10\xea\xf3\x2d\x3d\x2d\xe0\xc6\xdc\x62\xdf\x6d\xb2\xc5\x6a\xf6\x7a\x3e\xbb\x70\x95\xf1\x9f\x4f\xc0\xca\x83\x0e\x0c\xc2\x99\x5c\xf0\xf4\x23\x71\x53\x2e\xa5\xf6\x6b\x5c\xfa\x9b\x94\x72\x9b\x74\xe8\x52\x61\xdf\xda\xa6\xab\x86\x7d\x6b\x87\x2e\x20\xf6\xad\x5d\xba\x96\xd8\xb7\xf6\xe8\xb2\x62\xdf\xda\x37\x56\x18\xeb\x89\xba\x6d\xac\x39\xb5\x09\xb6\x81\x2e\xb0\xcc\xe6\x61\x3d\x97\x77\x21\x4b\xcf\x48\xfc\x50\x7f\xfe\x2e\xfc\x08\x3a\x42\xca\xe8\x40\xc5\xeb\x43\x6c\x9b\x6c\x5b\x5a\x94\xe5\x0c\xf1\xf0\x88\x1b\x8f\xcc\xc7\x42\xce\x11\x09\xf8\xda\x6d\x3e\x67\x3e\x21\xf2\xf1\xcf\x5c\x78\xb2\x12\x08\x81\xca\x29\x80\x0f\xe3\x3a\x87\x14\x9a\xfc\x4c\xdd\xc5\x71\x1c\xcd\xb2\x28\x73\xe0\x6e\x12\xe5\xf8\x72\x16\x0e\x98\x85\xe4\x8e\xce\x6d\xb9\xd1\x8a\xad\x5b\x8c\x2d\xb9\x91\xb7\x5b\x3b\x7b\x74\xdb\x00\x35\x29\x4a\x29\xe8\x06\xcc\xe6\xdb\x09\x9f\x2a\xc2\x5a\x62\x7a\xad\xb0\x1b\xe7\x69\x34\x0d\xd3\x07\xf9\x58\xef\x8d\x33\xfe\xa0\x35\x0d\x23\x22\xd2\x2a\xb5\xa9\x9a\x5a\xed\x81\x66\xfa\x2b\x7c\x9f\xaf\xcc\x9f\x36\x85\xfc\x88\x91\x7e\xcd\x37\xd8\x1b\xea\x43\xe2\x1d\x86\x2c\x51\x4d\xcb\xc2\x41\x45\x59\xc4\x6c\x3f\x61\x86\xbf\x8a\x25\xd0\x51\x09\x5e\x33\xde\xb2\x45\xc9\x8d\xa5\xb4\x63\x5f\xa9\xf1\x4a\xf7\xec\x5f\xc5\x9e\xfd\xe7\x86\x3e\xdf\xd2\xdc\x12\x1a\x7b\x65\x64\xed\x95\xb1\x71\xa0\xaf\x3e\x55\x43\x34\x4a\x5a\x11\xc9\x70\x6e\x5a\x75\xe6\xae\x3b\x67\x5b\xa7\x68\x55\x66\xd4\x11\xbf\x75\x5e\xdc\x12\xc3\xc1\xf7\x44\x53\x72\xf0\x3d\x79\x55\x4e\x3a\x2d\xf9\x9d\x3f\x66\xa9\xa8\x94\x9e\x61\xe5\x65\x98\x6e\x4c\xa2\x34\xfa\x57\xe9\x63\xcc\xe0\x20\xca\x61\xfe\x2e\x27\xeb\x2b\xb7\x71\xc3\x18\x21\x74\xe8\x71\xc0\x23\x57\x87\xdd\xa1\x9f\x1c\x70\xef\xc9\xf1\x72\x39\xe6\xc7\x0b\x41\xf0\x0e\x2f\x97\xd9\x72\xe9\x8d\x83\xf2\x66\xf7\xce\x30\x32\x8b\x2d\xd4\xbf\xe5\x9b\xfe\xb6\xe3\x8b\xcd\xdf\x00\x7d\x0b\x55\x4b\x1b\x11\x2a\xdc\x33\xae\x3c\x88\x60\x84\x60\x8c\xa4\x07\xfa\xec\xc0\x88\xb1\x0d\x82\x87\xe5\xf2\xa1\x5c\xba\x87\x8d\x4a\x27\xca\x66\x95\x49\x77\xab\x98\xf1\xb9\x39\xad\x6a\x8a\x36\x41\xf0\x50\xa3\x2b\x73\x35\x7c\xdd\xf6\x1f\xf2\xed\x3f\xa2\x9b\x77\x28\x5a\x7f\x40\x7f\xf2\xa1\x39\x76\xdd\x07\x7a\x35\x9d\xc7\x79\x44\xa7\x9a\xda\x59\xa7\x08\xc6\xf0\x60\xec\xae\x7f\x54\xec\xf5\x54\xb3\xf1\x9d\x4e\xa3\xd3\x08\xe7\x79\xe2\xc0\x34\x22\xc2\xff\x56\x58\xc7\xb9\xca\x64\xad\x79\xbb\x05\xa8\x6f\xc9\xe5\x90\x26\xdb\xb7\x93\xed\x2b\xed\xab\x00\x56\x52\x5b\x95\xd9\xdb\x2f\x60\x26\x57\x2d\x43\xba\x2f\xd9\x8f\xa5\xe8\x4e\x17\x2d\xba\x14\xfc\x29\x96\x82\x9f\x37\x5c\x0a\xc4\xec\x0f\xad\xd9\x1f\x95\xe6\x5a\x6d\x68\xc7\x2a\x59\xed\xf1\x0e\x4b\x78\x87\x85\xaa\x23\x22\x2e\xe2\xfc\x8c\x5b\xd3\x79\xc4\x6c\x36\x2b\x6d\x64\xa2\xa7\x70\x5e\xee\xa9\xba\x5d\x3a\x15\x4a\x20\xf3\x93\xe3\xfe\x7d\x86\x77\x17\xfb\x19\x87\x39\xfe\xd3\xdb\xda\x6b\xff\x80\x9c\xda\x86\x2d\x17\xa0\x40\xde\xcf\xa2\x8d\xf3\xfc\xef\x5c\x6e\xb5\xde\x91\x69\x11\x3e\xee\x3a\xf3\xd8\xf1\xf9\x52\x2b\x86\x76\xcd\x52\x2b\x16\xbb\x73\x3e\x7e\x94\xb2\xd2\x0c\x82\xa1\xeb\x72\x1d\x25\x9b\x5f\x4f\x70\x38\xc4\x29\x4c\x9e\xb8\x92\x5a\xaa\x80\x6d\xcd\x15\x1f\xa4\x6b\xa4\xcc\x9e\x2e\x8a\x22\xb8\xe6\x14\x4f\x93\x9a\x48\x19\x61\xaa\x1d\x14\x32\x3c\x67\xc5\x40\xaa\x31\x4b\x4d\xab\x66\xa9\x6c\xb3\xb5\x61\xa0\xd7\x86\xe6\x88\xfe\x16\x73\x0d\x66\xf4\x42\x95\x5e\x0d\xc9\x09\x82\x19\x24\xa6\xe8\x4d\x2a\x43\x2e\x8e\xb2\xdc\x3c\x4f\xd2\x07\x66\xfa\x84\xac\xd6\x0a\x23\x1f\x2f\xd6\x99\x9b\x8c\xe5\x41\x15\xcf\x7a\xa3\x5d\x19\xaf\xcc\x07\x51\x52\xee\x6d\x38\x38\x57\x2c\x00\x52\x55\xb6\x81\x77\xe5\x21\x98\x40\xde\xd5\x43\xd6\xd6\xa8\xe3\x48\x2a\xd3\xa5\x33\x8f\xa1\x1e\x98\x03\xd7\x1d\x30\xd1\x40\x24\xb9\xcc\xa3\xc1\xcd\x83\x72\x50\xe4\x4a\x12\x77\x4c\xe4\xeb\x78\xd5\x2b\xf1\xd1\x45\x6a\xa5\x3a\x5b\x3e\x7e\x30\x4a\xa0\xc4\x84\xd5\x03\x73\xbe\xd1\xea\x06\xaa\xb5\xb8\xb8\x94\xac\xd4\x3c\x63\xaa\x1e\x4e\x5d\x37\x11\x35\x6d\xce\xe8\xef\x8c\x37\x48\x73\x48\x2f\x84\xb5\x4b\x0d\xcf\x5b\x73\x64\x26\xf9\x06\x4a\xe1\x0a\x0b\x28\xdd\xa4\x44\x7c\x88\xb3\xfb\x72\xc6\xee\x94\x46\xf5\x7a\x01\x18\x46\x09\xc9\xdf\x86\xd3\x28\x7e\xb0\xf5\x28\x7d\x9f\x25\xf9\x9d\x7f\xa4\x92\x84\xdf\x3f\xc5\xc3\x68\x3e\x65\x09\x59\x4c\x86\x95\x6c\x76\x7f\x95\x5c\xe0\xa9\xd7\xd9\x45\xdf\xa1\x2e\xac\xd6\x3c\x36\x36\x21\xd6\x6c\xcf\x2f\xb6\x0b\xe0\x3d\x64\x6e\x3d\x99\x18\x42\xdc\x2f\x5b\xb8\xf3\x77\xaa\x27\xef\xaa\x0c\x55\x3b\xdc\xa5\x5a\x48\x0b\xe4\xa5\x62\x32\x87\x39\x43\x91\xd9\x7b\x85\x20\xca\x99\x5d\x6e\xff\x15\x82\x98\xfe\xdc\xdf\xde\x47\x90\xd1\x5f\xbb\xdb\x3b\xfb\x08\xe6\x79\x2d\x29\xb0\x79\x1c\x6c\x1e\x01\xfb\xc6\x01\xb1\x18\x4e\x83\x95\x2b\x87\x01\x2a\xa3\xa3\xbe\x59\x44\xa2\x3e\x8b\x08\x03\xe5\x37\x73\x9e\xa4\x79\x18\x97\xd9\xab\x58\x98\x62\x42\x78\xd4\x3e\x1e\xb2\xa0\x37\xe5\xe1\xc2\xfd\x26\x35\x07\x0e\x8f\x11\x55\xa7\x5a\x15\x12\x8b\x14\x31\xc4\xd7\x11\x8f\xda\xd0\xc1\xf4\xa5\x60\x97\x68\xb9\x1c\xd6\x06\xb5\xd4\xa1\x44\xe3\x2e\xf6\x90\x8f\xa1\x72\xc8\xe6\x25\x68\xb9\x1c\x26\x03\xe6\x2a\xc9\xec\x25\xec\xe0\x2d\x81\xa8\x4f\xdb\xbd\x1c\x29\x3c\x70\xdd\x66\x84\x94\x2f\x65\x96\xf3\xa5\x6a\x60\x31\x3d\x1b\x0f\xb8\xf3\x08\xcd\x91\xc0\xa0\x2e\xcf\xd8\x75\xbd\xc1\x72\x19\x21\xd7\x8d\xc5\x71\xa4\x48\x18\x75\xeb\x5a\xa6\xc4\xbd\x91\x02\x3b\xb8\x19\x15\xc8\x4f\xfd\x41\x77\x2e\x56\x35\xde\x4b\x5e\x0a\x03\xe4\x0f\x14\x1c\x22\x1d\x50\xdb\x7b\xfb\x2f\x11\x8c\xd8\xcf\x17\x2f\x3b\x08\x66\x6c\xec\x75\x76\x77\x0d\xac\xa1\x49\xae\xdc\xff\x54\xd3\xd4\x08\x84\xe8\x00\x73\x34\x75\x1e\x19\x17\x38\xaf\x5e\xd1\xc5\x46\xde\xe4\xf6\x94\xf2\x5d\x39\xb1\x02\x43\xa6\x93\xcf\xf2\x64\x16\x38\x5b\xaf\x5e\xd9\x6f\x48\x5b\x47\xe0\x64\x83\x34\x89\x63\x07\xac\xfe\x12\x0c\xdc\xec\xe4\xd6\x93\x52\x1c\x1d\x8e\xa3\x51\x86\x79\x64\xdd\x16\x36\xe3\xec\x14\x94\x81\x95\x0b\xe7\xe1\x97\xb9\x40\xce\x30\x56\xa6\xb4\x71\x5e\x74\x76\x8c\xb6\xb9\xcd\xb9\x3b\x6e\xde\x65\xac\xb9\x87\x79\x9e\x46\xd7\xf3\x1c\x7b\xdc\x47\x4c\x9a\x63\x9c\x3c\x9d\x63\x07\xf9\x58\x64\xbc\x22\x9d\x89\x45\x97\x1b\x83\x98\x21\xba\x9d\x90\xdc\x13\x54\xea\x63\x9c\x1f\x09\x62\x15\xb6\x8e\x7b\x18\xf5\xd4\xe1\x09\xb7\x1f\xf5\xa1\xd3\x46\xcb\x65\xdb\x00\x7f\xcb\x25\xee\x12\x9f\xdf\x15\xdf\xe1\x9d\x5a\xdf\xe1\x1d\xd3\x77\x78\xa7\xcf\xf0\xa8\xab\xef\xee\x1a\x89\x76\x55\xc0\x6c\x18\xf4\x72\x20\xd5\xb8\xe4\x14\x21\x88\x82\x9e\x73\x75\x7c\x7a\xfe\xfe\xf0\xea\xd8\x01\xe7\xf2\xe8\xe2\xe4\xfc\x8a\xfe\xb8\xfa\xf3\xfd\xb1\xd3\x3f\xe8\xf5\x25\x0c\x91\x40\xeb\x5d\x01\x56\xd2\x61\x4e\x83\x24\x19\xe2\x2b\x16\x53\xb7\x45\x6f\x84\x8a\xbf\x1e\x23\x71\x2b\xd2\xb7\xa4\x2b\x2a\x72\x5d\xd6\x7f\x49\x09\x67\x2e\x37\x5d\xac\xb7\x3a\x0a\x4a\xab\x95\x25\x53\x9b\x54\x2b\xd5\xfc\x1c\x39\x77\xa7\x25\x41\x0a\xcc\x27\x0f\x01\x61\x83\xe6\xce\x8a\x9d\x54\x1f\xc1\x1e\x5a\x34\x2b\xd1\x83\x4d\x0f\x9b\x38\xe5\x39\xaa\x07\xd1\x3e\x0a\x09\x49\xf2\x06\x6d\x97\x46\xd8\x60\x12\x4a\x23\xcc\x1a\xa1\x8a\x50\x77\x50\x21\xb0\x78\x14\x84\xc9\x30\x8c\xb3\xa0\xd7\x07\x45\x12\xcc\x16\x73\x7a\x4b\xb3\xd7\xcc\x72\x01\x1b\xc2\x22\xc4\x9d\x70\x38\x74\x04\xd3\x66\x0d\xc2\x79\x60\x64\x6c\x34\xf7\x41\x34\xf2\xb6\x3a\x16\xf5\xdb\x81\x9d\x56\xa2\xee\x1b\xb7\x04\xab\x3c\x60\x7e\xe3\x02\x8f\x78\xd7\xa8\x4b\x90\x1e\xf4\x69\x0d\x71\xb4\xa2\xab\xdf\x74\xcc\x30\x3e\x6b\x35\x07\x5d\x97\x4f\x4f\x36\x90\xc6\x2b\x27\x31\x62\x08\x31\x82\xfe\x1e\x31\xee\xc7\x1c\x1d\x3c\xe4\x5e\xce\x8a\x3d\x27\x39\xdd\x45\x8c\x2a\x00\x1b\x09\x02\x88\xe8\x3a\xf7\x4a\x2d\x5f\x0f\xc3\xa6\x13\x04\x41\x90\x17\x0a\x23\x89\x35\x69\xd2\x2d\x67\xd2\x4b\xfa\xe5\x36\x24\xc8\x2f\xa7\xe2\xcf\x16\x3c\xa1\xdf\xc3\x7d\xe3\x14\x39\x87\x14\x67\x79\x92\x62\xbe\xc1\xf2\xca\x5e\x46\xd7\x71\x44\xc6\xb4\x42\x99\x9f\x16\x34\x53\xaa\x8a\xb0\x51\xc1\xaa\xba\x6e\x5c\xac\xad\xaa\x42\x99\x62\x15\xca\xab\xe3\x87\xa1\xc5\x05\xe5\x6a\x92\xfe\x01\x95\x02\x58\x41\x97\x4b\x4f\xfd\xae\x87\xde\x0f\xd8\x22\xc5\xb8\xff\x8c\x06\x65\x74\x7c\xb9\xd2\x46\xd8\xee\xf1\x3e\x19\xdc\xb0\x99\x57\x1d\x55\x5e\x1b\x62\x3e\x1f\x0c\x35\x81\x6e\x0e\x8c\x4b\xd4\x6b\xc3\x94\x3d\xcd\x11\x27\x59\x60\x9b\xc9\x3f\xf3\x96\xdc\x47\xc4\xde\x68\x85\x74\xe3\x16\xdf\xb3\xb8\x38\xfe\x4f\x6c\x45\x6f\x17\x5e\x28\xe0\xd3\xa2\x80\x6e\xb9\x07\xa9\xe8\x36\x01\x74\x23\x77\x4c\x43\x74\x05\xd6\x21\xf6\xc2\x0f\x38\x66\x2c\x73\x22\x7d\x65\x5f\x08\x74\xf8\xe5\x38\xf7\x42\xf4\x3c\x02\x67\x76\xef\x20\x20\xba\xc6\x21\x6a\x7d\x9d\xe3\xf4\x81\xfb\x79\x26\xe9\x61\x1c\x7b\x4e\x6b\x3a\x8f\xb6\x46\xd1\x3d\x1e\x3a\x08\xca\x33\xad\x34\xc1\x12\x31\x1a\x6b\xca\x8c\xa0\xee\xae\x5d\x2a\xac\x4a\x25\x41\x16\xe3\x80\xea\xf3\xa9\x6e\x57\xc8\x02\xe7\xa7\xab\xd3\xf7\x74\xd6\xc6\x6c\xf9\xe7\xc1\x05\x52\x2a\x08\x82\x60\xd5\x66\x19\xa3\x9e\x23\xa5\x88\xad\x07\xa7\xdf\x8d\xfd\xb0\xd4\xd8\x59\x49\xd8\xe0\x0d\x2d\xaf\x58\x1b\x67\x05\x82\x72\xb2\x40\x1d\x0d\x55\x11\x43\x88\xeb\xae\x6d\x34\x3a\x7c\x93\x5e\xde\xef\xd6\x36\x4f\xc2\x81\x11\xf9\x13\x2e\x43\x9c\xa7\xc9\x0c\xa7\xf9\x83\x57\xea\x61\x3e\x83\xea\xb1\x1c\xa5\x34\xc4\x39\x31\x48\x80\x5b\x38\x66\xd8\x23\x37\xf8\xe1\x20\xef\x0a\x3a\x1c\x2a\xc9\xa8\xdc\x53\xc8\x91\x4f\xea\xbf\x9c\xb2\xfe\x29\x58\x1a\xbd\x40\xf0\x44\xd5\x15\x42\x7e\x7e\xdd\xbe\x41\x17\x3d\x9b\x21\xf4\xdf\xb6\x9e\x44\x23\x2f\x95\xc9\xb3\x19\x0b\x77\x4f\xab\xaf\x43\xc7\xda\x41\x65\xca\x9c\xde\x6f\x07\x41\x90\xda\xbb\x1a\x52\x2b\x93\xeb\xaa\x9f\xde\xda\x8d\xad\x8d\xe0\x21\xf7\x52\x43\xc1\x5a\xb5\x9d\xb4\xaa\x8b\x33\x8b\x04\x2a\xaf\xf6\xa2\x8c\x04\x4c\xd4\x89\x44\x15\xb5\x57\x2a\xf3\x56\xa7\x7f\x90\xd8\xe5\x4b\xac\x8d\x57\x8e\xe6\x5c\x75\x71\x94\x5d\x25\xb3\x53\x9a\xa4\xae\x9b\x0d\x06\x11\xfb\x4b\xff\x6c\x0b\x0c\x35\x51\x90\x6a\x8a\xad\x4e\x9f\x73\xbf\xf7\x11\xe0\xc2\x93\xf6\x8f\xfb\xbc\x1e\x12\x4b\xee\xee\xa9\x56\x49\x0f\x95\x8b\x72\x1d\x38\x96\x48\x74\x4c\x46\x49\x3a\xc0\x3c\x5d\x9d\xf6\x2a\xe3\x21\x79\x07\xf2\x74\xe5\xb3\xb1\x01\x17\x17\xde\x24\x03\x06\x90\x15\x65\xc7\x84\xfb\x4c\x8e\xa8\xbe\x31\xc3\xc4\x44\x3b\x42\x30\x29\xc7\x0e\xae\x03\x28\xaa\x82\x13\xc1\x5a\x3c\xa1\xf1\x63\x8e\xa3\xd7\x5a\xc5\x26\x54\x9d\x86\x07\x85\x81\xc1\xbe\x67\x01\x3a\xd4\x84\x9a\xdc\x69\x24\x10\x9a\xe3\xa8\x8f\xa0\x79\xa7\x5d\x69\x47\xae\xbb\xda\x26\x61\x01\x89\x0c\x3c\x24\xf8\xbc\x24\xac\xe0\xca\xc8\x3e\xba\x2d\x4b\xcd\x53\xed\x4d\x63\x1d\x73\x96\x2c\x97\xcd\xb1\x0e\x76\x53\x3f\xe5\x5c\xc8\x3c\x5c\xfa\xd4\x72\xa9\xdf\x6f\x4d\xc2\xcc\x10\xf5\x54\x44\x28\x32\x73\xb2\x75\x3a\x1d\x35\xba\xd5\x41\x30\x2e\xbb\x0f\x4b\x6d\xd3\x5c\xf5\xd9\x09\x61\x30\x36\xb0\x4d\x30\xfd\xf0\x5b\xfe\x86\xeb\x36\x23\xd7\x1d\xb2\x1f\x0a\x63\xa3\x6b\xa4\x6e\x6e\x50\x29\xd7\xad\x94\xc4\x9f\x19\x81\x5c\xa8\x00\x12\x98\x0b\xa6\xfa\xe6\x2b\xc6\x16\x7b\x83\x1f\x8e\x92\x21\x0b\xcc\xb3\x32\x0e\xec\x72\xcf\xcc\xb8\xba\x5c\x91\x0d\x76\xa7\x95\x8f\x4f\x2a\x0d\x53\x1c\xe0\x56\x38\x1c\xb2\xb8\x8b\xf7\x51\x96\x63\x82\x53\x8f\xbb\x82\x3b\x90\xb3\x35\xb0\x2e\xc1\x0d\x7e\x60\x38\x48\x40\x94\x24\x9d\x06\x19\xce\x4f\x48\x8e\xd3\xdb\x30\xb6\x46\x4b\xce\x0c\x26\x7b\xed\x95\x00\x6d\xea\xad\x94\x7e\x8d\xef\x52\xeb\x4b\x54\x9b\xc6\x2e\x14\x64\xcb\xa5\x67\x40\xd7\xdc\xda\x75\xaf\xdc\xa8\x01\xb4\x29\x84\x89\x09\x32\x18\xc2\xa8\x06\x04\x25\x6f\xbd\x4d\xc3\x31\x93\x7a\x38\xc7\x66\xed\x79\xdc\x42\x85\x39\xb5\x99\x0d\x79\x02\xce\x30\xcc\xc3\xad\x1c\x67\xb9\xe3\x3b\x19\x26\x79\x44\x70\xcc\xe3\xa1\x0b\x54\x02\xf7\xf4\x08\xb7\x1d\x5d\x17\xab\x0e\x68\xcb\xf9\x4f\xeb\xf3\x3f\x26\x43\x47\x41\xd4\x1d\xe7\x81\x30\x4e\x0b\x4b\xe9\x56\xc7\x38\x2f\xe1\xc2\x64\x15\x04\x85\xdb\x56\x25\x14\x4a\xd9\xb2\x9a\x8e\xaf\x43\xaf\x0d\x0d\xf1\xaf\xb5\x87\x36\x0c\x8f\x2a\x20\x22\xb7\xd2\x31\xf6\x11\x67\x4b\xb1\xef\xdc\x6c\x76\xc4\xa2\xf2\xad\x45\xd9\x63\x5b\x41\x6c\x9f\x65\xa8\x37\x1c\x70\xe8\x73\xe3\x2c\x22\xaa\xc4\xa4\x95\xce\x5b\x2d\xad\xd4\x6f\xb6\xe5\x89\x41\x0c\x0b\x8e\x23\x68\xa0\x90\x1e\xe7\xe2\xac\xa2\x7b\x9c\xb7\x8c\xea\x17\x10\x73\x91\x8e\xc1\x19\x0b\x4e\x5e\xd6\x65\x97\x9c\x0d\xef\x4e\xda\x8a\x8f\x36\x69\x02\xaf\x0d\x61\xce\xa3\xda\x43\x7a\x11\xb1\x0b\x6d\xf6\x16\xa2\x02\xc3\x2f\x35\x8b\xc7\x10\x56\xf1\x14\xfb\x49\x81\x20\x0a\xc2\xd6\xeb\x70\x70\x33\x4c\x93\x99\x8e\xf8\xb1\x8e\xa7\x6e\x72\x76\x2e\xa5\xd3\x71\xcf\x91\x41\x10\x6a\x59\x60\x48\x2f\xe2\x24\xc3\x87\xa3\x1c\xa7\x57\xca\xa9\xb7\xe6\xcc\x34\x34\x84\xae\x49\x10\x56\x45\x88\xea\x89\x94\x4a\xa4\x4a\xca\x60\x2a\xaa\x70\x19\x61\xad\xac\x51\xc5\xcb\xd0\xe9\xb2\x41\x38\xc3\x12\xca\xa2\x1a\x7b\x14\x96\x8c\xee\xd5\x00\xa4\xb0\x56\x6c\xa9\x46\x21\x85\x55\x1d\xb8\x26\x1e\x29\xa4\xe2\xa6\xaa\x26\x9c\xe9\x04\x17\xae\x7b\x01\x57\x41\xd8\xba\xc1\x78\x76\xca\xc1\x71\xe1\x83\x7e\x7e\xe5\xba\x57\xf0\x39\x08\x5b\xd3\x90\x84\x63\x9c\xc2\xa9\xee\xc3\xcf\xdd\xcb\xdc\xff\x0c\x27\x41\xd8\x4a\x88\xdd\x86\x87\xec\x1e\x23\x28\x82\xf7\xec\xb7\xdd\x24\xdf\xd8\x3d\x75\xaa\xf0\x86\x5e\xd2\xa9\xf5\x56\x4f\xad\x10\x7a\x4e\x65\x08\x39\xe0\x58\xc3\xa5\x1c\x05\x55\x1d\x2a\xec\x38\x51\x0c\x0c\x7d\x7a\x78\x68\xc4\x53\xd5\x0d\x02\x7d\xdb\xec\x72\xe3\xae\x59\x1b\xe3\x84\x9d\x75\xa7\x81\xc1\x61\x74\x9e\x71\x74\xa9\xba\xca\x01\xc7\xec\x18\x07\x1c\xa3\x1b\x1c\x70\x44\xa3\x73\x24\x8e\x52\xf9\x44\xf3\xb2\x5f\xe5\xe2\xe8\xa6\xd5\x6b\x12\xbc\xb6\x82\x93\xdb\x08\xbe\x04\xaf\x7b\xed\x3e\xfc\x1e\xbc\xee\x75\xfa\x26\x1e\xc6\xa2\x50\x68\x18\x5a\x66\xfd\xad\x7c\xe3\x27\x2d\x86\xfe\x06\x29\x82\xaf\x35\xac\x02\xcd\xa6\x96\xec\xa9\x50\x22\x7f\x0b\x78\xe6\x49\x98\x9d\xdd\x11\xad\xfd\x46\xcc\xda\x19\x22\xf8\xa5\xca\x62\xa8\xa4\xc6\x8f\x1a\xa2\x13\x7e\xad\x61\x3b\xd4\x21\xec\x52\xf1\x09\x7e\x53\xe0\x88\xe6\x43\xa1\x97\x05\x1f\xab\x4f\x0b\x78\x67\xe6\x7c\xca\x53\x7b\xbf\x7a\x08\x16\x95\x5e\xf4\xcf\x0b\x04\xbf\x69\x39\x93\x3d\xb8\x4a\x66\x41\xbb\x80\x3f\xeb\x42\xfa\xa5\x20\xfc\xd7\xcf\xb8\x66\x68\xb9\xfc\xc5\x43\xcc\x96\x75\x70\x4a\xc5\x2e\x56\x46\x6c\x94\xc7\x75\xdf\x79\x4c\x73\xfe\x63\x0d\x4c\x9e\xf8\xfa\x69\x4b\x6b\x83\x34\x23\xa6\x71\x9c\xf6\x11\xfc\xbc\x02\x99\xe0\xa3\xc6\xa4\x00\xec\xba\xde\x37\xd7\xfd\xe6\x21\x78\xe3\xba\x7f\x78\xa8\xfb\xce\x43\xfe\x6d\xee\xe9\xd6\x6f\xb6\x39\xd2\x01\xc6\x6b\xca\x72\x2a\x64\x35\xb3\x00\x54\xc3\xdf\x1c\xd1\x15\x63\x8f\x1f\xcd\x61\xbc\x06\x6c\xe4\x4d\xf7\x4f\x0f\xf9\x5f\x5d\x77\xb4\x5c\x62\x81\x2f\xf2\x06\x30\x86\xaf\x30\x82\x3f\xa9\x52\xf4\xc1\x75\x9b\x6f\x5c\xd7\x6b\x7e\x5d\x2e\xbf\x20\x64\xf8\xdf\x49\x66\xf3\x95\x07\xf8\x15\xc9\x48\x08\x4d\xb8\xc5\x7f\xf0\xb1\xb9\x5e\x5e\x2a\x84\x05\xd7\x5f\xb0\xbd\x3e\x8a\xa3\xfc\x41\x7b\x2c\x17\x85\x97\x2c\x97\x52\x18\x1b\xe5\xad\x4f\x05\x43\x2b\x59\x28\x72\x51\xb5\x50\x4b\x6a\x04\x29\xf5\xb9\xae\x47\xb0\xba\xaa\x3c\x5e\x2e\x9d\xad\x8e\x83\xe0\x2b\x4f\x97\x10\x06\x66\x41\x47\xc0\x30\x2f\x0f\xe4\xdf\x3d\xaa\x94\x20\x18\x68\xc0\x75\x9a\x98\x96\x44\xe1\x51\xaf\x7c\xb3\x8d\x60\xe4\xba\xa2\xed\x07\x25\xc8\xf6\x1a\xef\xc2\x41\xce\x05\xdb\x9f\x0d\x9b\xf7\x0c\xac\xb5\xd7\xbf\xa9\x01\x5e\xb6\x65\x2e\x9a\xc3\x4f\x06\x9a\x81\xd9\x87\x0e\x5f\x49\x0d\xf4\x8a\x3f\xa8\x72\xe5\xbd\x77\xdd\xf7\x1e\x46\x70\xcf\xa8\xd8\xb3\x9c\x6f\x3f\xe1\x38\xe4\x95\x81\x43\xd7\x3d\x64\xd8\xf7\xd6\x42\xcc\x70\xe0\xd3\x24\xc6\xbe\x33\x4b\x31\x95\xaa\x39\x53\x74\x01\x6f\x6b\xe4\xbb\x1c\x73\xf9\x8e\x0e\xb9\x2f\xdd\x1c\xb7\x64\xef\x17\xf0\x56\x09\x78\x70\xc6\xe1\x5e\xcb\x75\x8c\x75\xfd\xe8\x7a\xef\xbf\x81\x3a\xba\xfb\x75\xc8\x1d\xde\x89\xeb\x9e\xd0\x3a\x36\xc7\xae\x2b\xeb\x73\x6d\x6d\x3a\xcc\x30\x98\xd5\x74\xcc\x7d\xae\x96\x45\x73\xbf\xf4\xaf\xa1\xbc\xdf\xfa\x53\xa8\xd9\x1b\xfd\x23\xe0\xd6\x17\xff\x17\x50\xb6\x17\xff\x0f\xe0\x55\x29\xca\xfa\xcd\x00\x08\x46\x48\xd3\x1d\x7f\xca\x03\xe2\xbd\xda\xdd\x79\xc5\x2f\xcf\x99\x53\xc5\x54\xee\xa2\x17\x79\xc0\x38\x09\xe8\xef\x33\xfa\x9b\x0e\x50\xe6\x07\x77\x25\xaf\xe8\xa3\x0f\x22\x19\x7b\xf2\xd9\x36\x52\x19\x1c\x34\xfa\xd4\xf5\x80\xf9\x55\x28\xaa\x0c\xfa\x80\x53\x65\xf0\x63\x22\x08\x03\xe2\xba\x4d\xd2\xd2\xc4\x12\xdd\x9c\x83\xe9\xfb\xb9\x00\xd9\xd7\xa4\x19\xfc\x9a\x73\x1a\x06\x42\x33\x8c\x48\x37\xec\x7a\x49\x70\x91\x43\x29\xc1\x59\x8e\xfc\x24\xb8\xca\xfd\x84\xae\xa3\xbc\xaa\x67\x6c\xde\x2c\x97\x62\x67\x3b\xe3\x13\xb1\x7b\x9e\xfb\xec\x7d\xc1\xca\x91\x71\xd6\xc4\xa4\x00\x4e\xa4\x2b\x57\x60\xfe\x4d\xcd\xbb\x41\xe8\x1e\x42\x36\x62\xb3\x30\xc8\x46\x5a\x11\x71\x5d\x06\xbb\x43\x4b\x19\x04\xe7\x79\x57\x7e\xf1\x22\x2f\xb8\x6e\x22\x54\x7f\x52\x65\xf3\x48\x37\x60\xf3\x98\xcf\x86\x61\x8e\x79\x33\x78\x92\xd2\xc3\x6c\x1b\x3a\xe3\xac\x7c\x3e\xb2\x37\x6a\x8e\x1a\xd9\x3a\x1e\x8d\x3c\xdc\x0c\x0c\x4a\x06\xeb\x44\x94\x33\x26\xf0\x1a\x1c\x18\x3c\x14\x11\xe9\x92\x66\x10\x9c\xe5\xae\x4b\xff\x5e\xd1\xe9\x93\xb3\x5e\xb1\x6f\x2f\x97\x5e\x1e\x7c\xc8\x51\x51\x53\xf6\x0e\xe4\x76\x59\xd7\x71\x8c\x0c\x42\x32\xc0\xf1\x07\xa3\xc3\x3c\x24\xd8\x46\x04\x5c\x6c\x56\x01\x78\xe2\x4c\x97\x46\xd5\x24\xee\xff\x81\xa6\x78\x0c\x48\xc0\x69\xe6\x9b\x41\xea\xba\x0e\x99\x4f\xaf\x59\x50\xb8\x10\x3c\x52\xd7\xf5\x70\x90\x72\xce\x87\x9c\xfe\x60\xa8\xd8\xc4\xb0\xc6\x8a\xc6\xef\xca\x1f\x7e\x8e\x60\xc1\x00\x59\xb1\xa0\x0a\xc9\x25\x95\x08\x29\x68\x91\xcd\x56\x28\x1f\xf9\xc9\x0d\x0b\xb3\xef\x36\x3b\x48\x94\x2d\xc8\xe5\x69\x69\x4d\x3b\x00\x5d\xce\xce\xf2\x2e\xaf\x28\x4e\x47\x49\x3a\x65\x63\xdf\xc3\xc8\xb7\x6e\xde\x47\xb9\x87\xe4\x3d\xd6\x22\xd6\xdc\x91\xa4\x20\x46\xa7\x07\x41\x70\x91\x97\xc9\x42\xe4\x90\x3e\xcf\x0b\xd6\x09\xe6\x37\x6b\xc6\x19\x5b\x1d\x88\xd9\x0f\xbc\x15\x8d\x93\x0c\x7c\x2f\x8a\x2f\x2e\x8c\x35\xc3\xc7\x90\x98\xef\x92\x64\x48\x65\xf0\x6e\x2f\xed\xfb\x3d\x5b\x20\x64\x34\x3d\x90\xf6\x21\x0c\x12\x2a\xd8\x47\x9c\x8b\x39\xe6\xaf\x1b\x43\xc5\x43\x90\x05\x69\x37\x96\x5d\x16\xf3\x12\x1d\xe0\xe5\x92\x74\x4d\xbe\x15\xb1\x9b\x7b\x8c\xbe\x85\x37\x42\x38\xc2\x97\xe5\x86\x38\xcb\x0b\x0b\x44\x2a\xb7\x5f\x8f\xc8\x58\xe4\xd0\x4a\x88\xd6\xcc\x8e\xc9\xd0\xcb\x4a\xef\xd5\x66\x7f\xb5\x3e\x7b\x3c\x64\xb9\x0b\x1a\x37\x24\x3b\xf8\x7b\xb3\xe2\x4c\xf0\xa9\x39\x68\xea\x29\x5c\x20\xb7\xfa\x94\xd1\xa2\xd4\x35\x75\x5a\xd7\x7d\x7c\xa8\xfb\x35\x1d\x78\x90\x97\xbb\x80\x0e\xdb\x74\x5d\xfb\x7f\x28\xd5\x0a\x5b\xef\xd2\xe6\x67\x66\xd2\x72\xe3\x13\x5e\x68\xfb\xcd\xda\x0f\x5c\xac\xfd\x00\x1e\x8a\xd3\xc3\x47\x9b\x7f\xc3\x7c\xe8\xaa\x58\x99\xe8\x35\xa6\x78\xf6\x21\x73\x17\xa3\xcb\x70\xf9\x9e\xc8\xca\x13\x0d\x58\xd9\xf4\xd8\xe7\xcc\xd2\x96\x16\x25\xd1\xcb\x19\xce\xad\x65\x27\x47\x25\x3a\x29\x2c\xd6\xf3\x52\xc2\xd5\x0b\x42\xb3\x7d\x60\x9e\xae\x91\xda\x97\x52\x76\xda\xec\x91\x80\xee\x17\x35\x3b\x36\xf6\x52\xda\x60\xab\x6a\x6d\x35\x1a\x63\xa8\xaa\xa4\xa4\x65\x2e\x8d\x8c\x72\x0b\xd4\xd7\xff\xc0\xd8\x28\xed\xc1\x5d\xbd\x25\x85\xcd\xba\x01\x0f\x69\xc0\x43\x9a\xb0\xeb\x36\x8d\x57\xc3\xe1\xf0\x98\x0c\xa5\xb1\x9e\xee\xd4\x54\x9e\x4a\xd9\x59\xd2\xca\x64\xd2\x8a\x59\xb7\x62\x56\xaa\xde\xf7\x7b\xa4\xda\x20\xa5\xf5\xf3\x60\xe5\xb7\xf8\xb2\xc3\xc7\x22\x76\x5d\x03\xba\xbd\x92\x27\x60\x54\xe0\x38\xc3\x8d\xb5\x89\xda\x6c\x00\xad\xa5\x8d\xb2\x24\x12\x2a\xbc\x30\x29\xab\xa2\x9a\x9a\xdd\x02\xa9\x19\xd6\x92\x04\x1e\x69\x45\x04\x88\x25\x26\x02\xb1\xb7\x42\x20\x92\x06\x8a\xc8\x3d\x5f\xac\x70\x8a\x3c\x88\x94\x5a\x03\x88\x5c\x45\xf5\xaf\x88\x8c\xf5\x05\x1e\xf2\xdf\x3c\x1b\xb5\x36\xa9\xdf\xec\xb9\xe8\x2c\x90\xbc\x57\xa5\x98\x97\x88\xfe\x67\x16\xdc\x01\xc7\x2a\xb8\xa3\xb9\xca\x24\x3b\x99\x20\x24\x73\x44\xc1\x69\x0a\xab\xe0\xdc\x82\x26\xd2\xea\x82\xeb\x0b\x6e\x45\x93\xd9\xab\x82\xab\xdf\xec\xb9\x28\xb8\xd3\x47\x2b\x23\x11\x6a\x28\xaf\x98\x44\x0c\x35\x26\x9f\xb4\x9b\x32\x6f\x46\xbf\xa4\xfa\x18\x40\x46\x09\x89\x1f\xe8\xc2\x9e\xd0\x05\x80\x94\xf8\xb1\x94\xc6\x72\x9a\x7b\x68\x51\x7c\xce\xa5\x68\x71\xf5\x30\xc3\xc1\x19\x86\xcf\xb9\x4d\xa0\xf5\x39\x2f\x11\x68\x31\xf2\x43\x30\xdb\x9a\x5e\x5b\x8d\x4d\x6f\x08\x11\xa2\xd9\x11\xd2\x9e\x64\x3d\x6c\xb6\x41\x34\x9f\x7f\x9a\x83\x6e\x56\xe3\x0a\x0f\xc5\x05\x4d\xaf\x7e\xe9\x34\x9c\x9c\xee\x34\x67\x85\xfb\xf8\xe1\xf4\xec\xe3\x87\xab\xe3\x37\xc1\x79\x4e\xaf\x8f\xff\x38\xa1\x17\x17\xfc\xe2\xc3\xd5\xf1\xc5\xc9\x87\x77\xc1\x99\xbe\x3c\x7e\x13\x5c\xa9\x94\xf4\xd9\x07\x79\x0c\x72\x92\x07\x9f\xb9\x43\xca\x21\x73\x91\xde\x7e\xd5\x41\xf0\x9e\xfd\x7c\xb1\x67\x34\xdd\xb7\xdc\x34\x3e\x8a\x43\x91\xe5\xf2\x7d\xde\xfa\xc4\x1c\x99\xde\xe4\xb5\x16\x3c\x6d\x00\x34\xa8\xe7\xdf\x5a\x8e\xa8\x9a\x82\x8b\xea\x90\x4c\xb7\x57\x2e\x0e\x41\x10\xa4\xdd\x45\xe1\x4b\xe5\x50\xc3\x9a\x24\x06\xac\x89\x44\xe0\x5f\x2e\xa5\xd0\xae\x86\x0e\xe9\x12\x9f\xf4\x98\xf5\x13\xf7\x97\xcb\x36\x0c\x71\x1c\x3e\xd8\x6f\xd3\x3b\x05\xab\xc4\xeb\x3c\x58\x48\x8d\xd8\xc2\x71\x17\x8a\xb1\x79\xaf\x80\x2f\x32\xb5\x7f\x98\xb7\xee\x5f\xb5\xe4\x9b\x97\x83\x14\x63\x41\xbc\xc9\x9f\xc4\x1c\x75\x9f\x3f\x28\xe0\xf7\xef\x88\xbe\x53\x91\x3e\x69\x34\xc8\x4f\x93\x21\xa6\xe3\x3b\xcc\x6b\x9c\x3c\xd8\x8a\x96\x05\x7a\x05\x9a\x07\xe6\xb2\x33\x08\xac\x15\x69\x18\xa8\x75\x68\x14\x18\xab\xcf\x2c\x30\x97\x25\x16\xdf\xcc\x7a\x66\x1a\x90\x96\xde\x1f\x57\x00\xd8\x9d\xe4\x02\xbe\x4e\xf6\xec\x83\x09\x5a\xf7\x25\xf7\xc7\x26\x52\x5d\x69\x59\x5b\x51\x53\xb9\xe0\x55\x96\x27\xb9\x22\x59\x4b\x95\xb9\x3c\x19\x4b\x96\x88\xf8\xa3\x35\x71\xc0\xa9\xa9\x87\xb1\x34\x32\xc8\x3c\x3a\xec\x19\xed\xce\x9c\x64\x8c\x96\xf9\x73\xa6\xca\xe5\xba\xcd\x08\x8e\xcb\x27\x01\x37\xfa\x24\x20\x61\x0e\x29\x29\x82\x4b\x7d\xef\xbe\x7b\x2c\xbd\xc8\x6f\x10\x1c\xd5\x4d\x1a\xed\xd2\x00\x84\x6d\xf0\x58\xba\xb6\xdf\x77\x7b\xc7\xca\x7e\x9c\xf7\x7d\xe6\x85\xce\x89\x11\x3f\xe5\x9c\x21\x74\x1b\x95\x76\x6c\xe3\x94\x11\x7b\x21\xf2\x31\xdf\xa9\x8b\x02\x3e\x05\x47\xde\x00\xc1\x79\x70\x54\xe6\x7b\x79\x93\xcb\x10\x03\x12\xbc\xcd\x3d\x61\x9e\x9b\x28\x1e\xad\x87\x02\x16\x74\x46\xf9\x62\x5b\x29\x8c\x18\x09\x7e\x62\xad\x5a\x36\xb8\xab\x45\x2c\x12\xf3\xc8\x01\xa2\xfd\x26\xf3\xa7\xbc\x94\xb9\x6e\x26\x79\x60\xe0\x22\x38\xf2\xe6\x08\xce\x82\x23\x6f\x86\xe0\xca\xae\x90\x94\x34\x1f\xa9\x08\x1d\x31\x7f\xa1\x1e\xf9\xf7\xd4\x23\x47\x30\x74\xdd\xa1\xf0\xe6\xfb\x10\x1c\x79\xa3\x95\x1b\xa6\x81\xa9\x26\xb7\x99\x36\x44\xc4\x8f\x41\xec\xb6\xbe\x31\xb4\xe4\x6e\x73\x6e\x6c\x2f\x17\xe6\xc6\xf3\x49\x6e\x35\x57\x7a\x73\xf9\x60\x6c\x3a\x67\x66\x13\x5d\x23\x28\x2d\x51\xba\x8c\xe6\x7e\x9c\xe8\x22\x96\x0c\xba\x9a\x6d\xc4\xb4\xde\x0b\x43\x64\x33\x08\xc8\x72\x19\x4b\x35\x50\xc3\x90\xbc\xce\x7b\xa4\x0f\x13\x48\x84\xc4\xc9\xed\xbe\xcc\x2d\xe0\xb2\x80\x54\x2a\x59\x12\x68\x34\x0f\x7e\xe7\x3b\xd9\xc7\xbf\x35\xba\x59\x3b\x41\xd4\x81\x48\xb0\x93\x5a\xba\xa6\x56\xb7\x23\xb6\xb6\xd6\xad\x95\x16\x22\xd3\xb3\x9c\x41\x31\x3d\x2d\xb0\xb9\xe2\x66\x01\x4e\xf5\xfb\x2b\x56\xb8\xd5\xd1\xa1\x23\xdd\x7f\x11\xf1\xe7\x6a\x08\x0c\x0a\x98\xad\xf4\x9e\x59\x17\xba\x9c\x71\x2c\x03\x51\x56\x04\xab\x3c\x3c\xac\x68\xe5\xdf\x2a\xd1\xca\x6b\x7c\x6c\x4a\x98\x7c\x4f\x81\x23\xfe\xef\xe8\x9e\x63\xc2\xeb\xca\x73\xf0\x02\x79\x1f\x85\x82\xf9\x93\xb0\xed\xbf\x30\x04\xb3\xaf\x96\x30\x55\x1f\x36\x90\xaf\x62\xc0\xe3\x47\x89\xa3\xf0\x06\x5f\x49\x74\x01\x44\x82\xd2\x1d\xd3\xd7\x76\x95\xef\x79\x8e\x0e\x48\x90\xd0\xfb\xf2\x00\x9b\x11\xee\x7a\x0a\x13\x59\xa1\x17\x38\x68\xb9\xac\x4b\x68\x24\x60\xb2\x58\x18\xb4\x21\x0a\xda\x42\xd5\xe5\x01\xbd\x74\xa5\x70\x5d\x87\x6e\xc1\x64\x6c\x08\x79\x92\xc4\x9d\x30\x17\xe1\xdc\x73\x3c\x07\xf5\x3a\x7d\x79\x85\x1c\xd4\x6b\xab\x2b\x70\xd0\x41\x18\xa8\xd0\xb3\xb8\xb7\xcb\x62\xca\x20\x32\xef\xed\xb1\x7b\xc2\x41\x98\x23\x1f\xb1\xf0\x08\x0d\xbd\xf0\x87\xa7\x3c\xfb\x45\xa3\xe8\x70\x09\x70\x66\xf7\xa8\x61\x26\x55\x0c\x4a\xe1\x56\xca\xd8\xf9\x58\x12\x07\x49\x58\xa4\x4a\xe6\x5b\x2a\x77\x9e\xfe\x79\xca\xc3\x0f\xb7\x42\xf5\xe6\x7c\x56\x7e\xed\xcf\xfa\x32\xf1\x38\x8c\x52\xa1\xfe\x34\x0a\x15\x6d\xa5\xad\x3c\x99\xa9\x9c\x4d\x7c\x09\xa3\x1c\x79\x32\x7b\x9e\x8a\x80\xc7\xad\x48\xa4\x2e\xd8\x50\x3b\x20\xae\xeb\xe5\xd5\xbd\x93\x76\x68\x40\x20\x37\xb7\x46\x7e\x8f\xf7\xf2\x2f\xdf\x29\x43\x8b\xb5\xe2\xd7\xef\x92\xa4\x53\xcc\xe1\x5b\x23\xbd\x0e\x87\x5d\x87\x39\x3f\xfa\xb5\x12\xf4\xc0\x92\xa0\x87\xb6\x04\xad\xc5\x66\x43\x68\xc6\x43\x26\x33\x6b\x09\x7a\xaa\x24\xe8\x5b\x43\x2e\x36\xc0\x9c\x6f\xbb\xbf\xe4\x3e\xe7\x23\xaa\xdb\x33\xae\x75\xca\x07\x2a\x5f\x3f\xc0\xdd\x1a\x09\x5a\xd4\xf0\xdf\x20\x33\x6b\xc3\x41\xfd\xde\x02\xf7\x5c\x66\xae\x91\x8b\xd7\xb8\x79\x1f\x3f\xe6\xe6\x7d\x59\x96\xaa\x99\xf0\xac\xee\x5d\x52\x29\xfb\xd3\x7a\x61\x1a\x2d\xb0\xeb\x7a\xaa\x15\xf3\x2e\xf6\xd4\x67\xa9\x58\x6c\x48\xd6\xec\x6c\xf7\x3c\xf8\x54\x96\x8b\xbf\xe6\x5e\x04\x18\x01\x93\x8f\xcb\x22\xa8\x99\xda\x08\x47\xa5\x62\xa7\xdc\x48\xc7\x82\x10\x79\x5a\x95\x9f\x6b\xe6\x0e\x17\x21\xef\x6b\x45\xc8\xea\xb2\x0a\xc6\xe9\x79\x0a\x0b\xce\x93\xe6\xdf\xaf\x22\x4f\x3b\x9b\xe7\x2c\xd8\xaf\x2a\xb3\xd6\x7f\xf0\xef\xfa\x50\x79\x6d\x90\xf8\xf8\x95\x05\x42\x3c\x60\xf2\x31\x6d\x4e\x9a\xc9\x59\xf0\x89\x6a\x2c\x57\xc1\x27\x6f\x42\xe5\x65\xab\xc9\xe5\x16\xf8\x48\x83\x0b\x39\xff\x6f\x6d\x6f\xb2\xbe\x19\xb2\x49\x98\xce\xfe\x86\xd6\xde\xf4\x33\x6c\x98\xe6\xcc\x9f\x64\xe4\xf1\xe1\xf9\xd9\x1e\xcc\xec\x70\xa3\xbe\xfe\x8e\x53\xa7\xc8\x38\x0e\xcc\x5c\x77\x26\x34\x95\xd3\x35\x1e\x4b\xc7\xda\xd7\x8a\x95\x43\xcf\x31\xc1\x97\xfc\x58\x44\x46\x34\xf2\x9a\xb1\xeb\xf2\xf5\x98\xc3\xf0\x8b\x4d\x92\x5e\x18\x71\x13\x3f\x55\xdc\x68\xd6\x7d\x5b\x7d\x57\xec\x8c\x55\xaf\xfc\x14\x67\xd1\x37\xec\xd0\x09\x6e\x1d\xcb\x30\x27\x7b\x0f\x81\x78\xb1\xd6\x79\x5e\xbf\xcb\xdd\xde\x23\x88\xd7\x78\x5b\xc5\xcb\xe5\xa9\x84\x41\x38\xad\x71\x8c\xbf\xd6\xbd\x2e\x95\xbb\xe3\x5a\x9d\xee\xcc\xd4\xe9\x2e\xa4\x4e\xf7\x41\xeb\x74\x9f\x0d\x9d\xee\x0a\x4a\x8a\xa3\x9a\x25\x05\xdc\x3d\x5d\xc5\xa3\xb2\xfb\x11\x94\x14\xbd\xa7\xa8\x77\xd3\x92\x62\x67\xaa\x74\xb4\x93\xdf\xfd\x75\x1c\xa0\x5a\x67\x6b\x0e\x81\xce\x71\x80\xb2\xaf\xf3\x30\xc5\x65\xba\x6a\xb6\xe1\xe3\x18\xdf\x4a\x3d\x4e\x7b\x8f\x75\x3b\x3e\x07\xff\x91\xf8\xb6\x36\x2f\xa1\x7a\x89\x53\x13\x6e\x84\xf3\xa3\x4d\x4f\xbc\x34\x0e\x18\xd9\x68\x54\xda\xd5\x7a\x5b\xbc\x21\xaa\x8f\x20\x4a\x61\x54\xbd\xb3\x6e\xd2\x92\xd7\x7e\xd2\x33\xbe\x28\xe5\xbd\x21\xea\x43\x73\xee\xba\x09\x27\x90\xc6\x43\x03\x61\xca\x50\xd7\xfe\xac\x83\xf0\x51\x8b\xb1\x76\xc0\xcb\xe9\xfa\x34\x4c\xee\xb2\xba\x08\x4e\xba\xb9\x92\xba\x42\xe4\xa8\x1f\x30\x00\x20\xf6\xae\x8f\x0b\xba\xfc\xe8\x21\xc8\xf1\x81\x4a\x3a\x55\xae\x30\x75\xf4\x93\xd6\x2c\x9c\x51\x41\xae\x94\xc0\xc4\xd0\x04\x03\x66\x3b\xaf\x87\xd9\x4e\xee\xb7\x78\x25\x1c\xe6\xcb\xc6\x5a\x45\x22\x84\x0b\x8e\x19\x56\xcd\x19\x6e\x99\x37\x0b\x50\x2d\x2d\x12\xd7\x02\x89\xe7\x15\x20\xf1\xa2\x60\x1b\x9f\xa1\x15\x9e\xd3\x6a\x50\x95\xf0\x9d\x50\x09\xff\xc8\x83\x05\x53\x59\xc5\x1a\x29\xd4\x5a\x01\x0a\xcf\xd0\xe3\x78\x54\x8f\x50\x73\xa9\xd6\x50\xc0\xcf\xdf\x6b\xba\xc6\x64\x33\xa4\x6b\x32\x98\x24\x69\x09\xea\x9a\x15\x49\xe0\x5c\xdb\x71\x0e\xb1\x29\xa3\x67\xc6\x9c\x9e\x5b\x73\x7a\xdd\xac\xdc\x17\xd3\x92\xb9\xeb\x4a\x88\x4e\x6f\x64\x4e\xce\x45\xe1\x8f\x50\xe9\xcb\xc6\x14\x1d\x19\x3e\xf6\x0a\x24\x73\x2a\x28\x3b\x93\x8c\x0b\xee\xcc\xdc\x53\xc7\x21\xca\x3a\x86\xe7\x69\x89\xea\x8b\xc2\xe7\xec\xa1\x97\x71\x34\x14\x04\x99\xf7\x2b\x64\x7c\x0b\x00\xfb\xd7\x9c\x01\x60\xd7\x1a\x96\x2e\x75\xc2\x9b\xee\xcf\xb9\xcf\xe9\x44\xe5\x8a\xf4\x49\x3f\x3d\xea\x3a\x39\x9e\xce\x92\x34\x4c\x1f\x1c\xff\x08\xce\x4b\x80\xda\xac\x9b\x1e\x8b\x23\xa8\x5b\xb5\xcc\x05\x4a\x37\xb9\xed\x89\xcf\xed\x52\xba\x61\x1c\x70\x74\x23\xac\x36\xbf\xd7\xd9\xb1\xf4\x1a\x08\x17\x5c\xbf\x38\xb3\x28\xf6\x56\x32\x89\x9d\x19\xc1\x7d\x06\x9f\xd8\x55\xad\xcf\x9e\x93\xe6\x31\xf7\x76\x55\x1a\x94\xeb\x56\x75\x0a\x16\x91\xdd\x13\x33\x4c\x4c\xbb\xbe\x19\x99\xed\xe5\xa8\xfb\x47\xde\xcb\xfb\x7e\x5e\x78\x17\x10\x52\x51\xb5\xbc\x66\xff\x99\xeb\x65\x4c\x35\xa6\x6f\xf4\x56\x10\x04\x9f\xba\x43\xbf\x0d\x7c\x53\x60\x94\xde\xd7\xb5\xe6\xb6\x4c\x2c\x6e\x59\xcf\x61\x3f\x0e\x79\xaf\x56\xc0\xda\xae\x10\xea\xc3\xb5\x31\x9f\x8c\xaf\xf1\xf0\x18\x3b\x87\x37\xc9\xe0\x06\x0f\xeb\xf3\xa1\xab\x52\xcc\xcc\x47\xce\x0c\xa7\xd3\x90\x75\x1e\x2d\x32\xfa\x6e\x6c\xcd\x8c\xef\x53\x59\x6b\xc8\xbe\x0b\x73\xb5\xdf\x9c\x23\xf8\xc0\xfb\xed\x73\xa5\x1d\x8f\x2d\x9b\xe5\x18\x54\xcf\xf9\x7f\xe4\xbd\xab\xbe\x92\x71\x2e\xa5\xf0\x73\xa6\xc3\x1a\xee\x58\xbe\xa2\xef\x05\x27\xa0\xac\xc7\x63\xc1\x6a\x4f\xad\xc0\xe7\x2a\x79\xc9\x91\x31\x04\xac\x09\x68\x3a\x42\x47\x30\x83\x45\x75\x4e\xf8\x97\x05\x82\x4a\x44\x90\xff\x5b\x0e\xeb\x0a\xc6\xfd\xec\xe7\x88\xfb\x12\x8f\x41\x4c\x56\x7f\xaa\x0a\x0a\x13\x5a\x54\xbd\xbb\xe7\x64\x03\x80\xbe\x02\x78\x8d\x25\xe8\x6c\xbb\xd1\xe6\xa0\xb3\x05\xb0\xe1\xa4\x81\xbc\xff\xf4\x1d\x8e\x46\x5b\xb2\xdb\xd2\xff\xdf\xa8\x9e\x73\x06\x49\x3c\x9f\x92\x32\xe7\xb9\x44\xb4\x15\x99\x57\xa2\x08\x86\x69\x78\x87\x53\x61\x94\x95\x20\xe1\x3c\x32\x85\x81\x07\xe6\xc9\x7c\x30\x71\xaa\x36\x64\x6e\xf7\x55\x2c\x72\xa2\xd0\x7c\x0e\x70\x10\x74\x61\x13\x16\x5b\xab\x59\x35\x9e\x4a\x80\x9d\xf3\x7d\x98\x17\x4e\x58\x97\xad\x64\x57\xc9\xcc\x5f\xd8\x56\x66\xb1\x29\x5b\xef\xa8\x6a\x0b\xe0\xde\xf0\xfe\x27\xb3\x1d\xac\x2c\x25\xb8\x39\xdb\xe8\x79\x7a\x3b\xeb\xf6\xf7\xe4\xca\x67\x3e\xaf\xbb\x10\x64\x44\xd2\x4d\xe8\x4f\x6a\xb2\x62\x35\xff\x0e\x26\x95\x9a\xac\x44\x5b\xf3\xcc\x58\x11\xbf\x3b\x2b\xd9\x78\x3c\x2f\x5a\xc6\x4d\xb3\x62\x13\xa9\x42\x46\xf2\x86\x0d\x40\x3a\x50\x19\xd9\x7a\x81\x3c\x4c\xc4\x31\x2a\x09\x88\xf7\x6a\xff\xd5\x0e\x82\x74\x33\x09\x0a\x0f\xc7\xf5\x51\xb7\x4a\x4e\x8a\x0d\x39\x29\xb3\xe4\xa4\xb9\xc2\x40\x1d\x68\x51\x60\x6e\x60\xa0\x5a\xd0\xbb\xc3\x5a\xd0\x5d\xf1\xf0\xad\xc1\x79\x5e\x47\x0f\x42\xb5\xde\x12\x79\xdd\x94\x01\x62\x72\x02\x3b\x4b\xda\xa0\x55\xda\x8c\xa9\x8d\x23\x9f\x56\x79\xd7\xde\x5a\x44\xdd\x4c\xe3\x5e\xad\x15\x7d\x59\x4f\x07\x1a\x8b\x45\xd1\x02\x3b\x1d\xb8\x6e\xbc\x12\xec\x74\x40\xf7\xcf\x91\xeb\xc6\xba\xe5\x9c\x6c\x1a\x72\x50\x9e\x5b\xf6\x26\x2b\x52\xe5\xc5\x5b\xfa\xe2\x82\xb1\x0c\xf9\x31\xeb\x59\xce\x29\x86\xc9\x50\x5c\x1f\x93\x61\xd1\x0b\xfb\x08\x4c\xda\x73\xaa\xa7\x1b\xd4\xe4\x7e\x73\xa2\x19\x8a\x46\x72\xc5\x1e\xd7\x1c\xcc\x71\x04\x75\xa3\xd2\x71\x2b\x0e\xaf\x71\xac\xe0\xaa\x05\xf8\xea\x26\x6b\x7b\x95\xe0\x01\x4a\x8b\xfc\x23\xd0\xa7\xdb\xbb\x48\xa1\x06\x77\xb6\x6d\x42\x4e\x0e\x6c\xad\x59\x1e\xd4\xa1\x66\x19\x1c\x55\xf0\x0c\x71\x18\x07\xf8\xaf\xe3\x43\x2a\xab\x96\x5e\x1b\x08\x69\xbd\xfd\x8a\xbc\x55\x65\xab\xe7\x46\x3a\xe3\xe7\xdf\xe8\x7b\x39\x92\x4a\xc4\x59\xeb\xf9\x50\x57\x34\x9e\x7c\xbf\x28\x40\x0d\x41\x09\xf2\xce\xd6\xd1\xad\xce\x36\x38\xcf\xe8\x10\xbe\xa4\xa3\xda\x75\xec\xa7\x3b\xe2\xc5\x63\x32\x94\x0f\xf8\x5a\xbc\xf2\x3d\xf1\x78\xa7\xf8\x1b\x99\x34\x9e\xda\x3b\xd6\xbb\xff\x9e\xce\x79\x2a\xb9\xc7\x53\xab\x50\x7a\xfb\xdf\x55\x09\x93\xfd\x4c\x75\xa6\x82\x0e\xf6\x77\x1e\x83\x38\x7e\x89\x0a\x60\xcb\x8c\xbf\xb0\x08\xec\xd6\x1c\xd1\x2b\xe2\xdb\xf2\x19\xfd\x0a\x94\xe1\x93\x41\x42\x38\xed\x2c\x83\x18\x16\x9b\x6b\xb8\xd9\x8e\xfa\x17\x08\x03\x20\xae\x70\x65\xfc\x75\x0e\x01\x30\xc9\xe7\x18\xda\x9b\x6e\x1a\xd7\x4d\xea\x58\x28\xcb\xb4\x03\x7c\x1d\x8f\x37\x59\xc7\x15\xfd\xc3\xde\xfe\x23\xab\x2b\x2d\xd5\xe5\x24\x8d\xc8\x8d\xdf\x86\x5a\xd6\xe7\x15\xbc\x7a\x9a\x2f\xe2\xe5\x0a\x96\x36\xda\x7f\xb4\xe7\x42\x62\x38\x30\x64\x46\x61\x9d\x6c\x10\xc6\x58\x9f\x62\x63\x70\xa0\xa1\xcf\xa9\x4f\xc3\x7c\xd2\x9a\x25\x77\x1e\x86\x6d\x04\x0e\x72\x50\x41\xbc\x57\x2f\xf7\x77\xf9\x40\x98\x93\x5a\xf7\x4d\x83\x39\x21\x23\x5e\x07\xd5\xb9\x73\x9a\xec\x0a\x9c\x61\xb9\x80\xc1\x86\xe3\xea\xbf\xab\x9b\xa6\x3c\x64\xb6\xc5\x33\xb6\x67\x0b\xf7\xcc\x3a\x23\x94\xe5\xaa\x79\xf2\xdf\xc5\x55\xf3\xd1\x63\x67\x13\xf3\x0b\xee\xcd\x8b\x63\x6e\x30\xba\x09\x8e\x57\x3a\x71\x5e\x96\x0f\xab\x8f\x6a\x9c\x38\x3f\xe9\x7b\x37\xdd\x4b\xe9\x69\x77\x84\xe0\xfc\x69\x4e\x9c\x37\xdd\xde\xe5\xdf\xe7\xc4\x79\x11\x9c\x7b\x03\x04\x67\xc1\xf9\x1a\x27\x4e\x48\x6b\xbd\x1f\x6f\x2b\xc7\xd0\x90\x04\xa9\x92\x89\x20\xa4\x17\x38\x0e\x1f\x0e\xf8\xa8\x61\x5e\x0a\x1e\x09\x8e\x2d\x11\x6a\x8c\xf3\xc3\x79\x9e\x70\x6d\x52\xda\x27\x3c\x1b\x03\x14\xc1\xbd\x06\x87\x42\x3e\x09\x92\xba\x43\xc6\xde\xf1\x7a\x77\x49\x2d\xc4\x11\xe1\xc7\x1d\x16\x08\xea\x5f\x32\x4e\x50\xf5\x6b\xad\xfd\xfd\xfd\xff\x30\xde\xed\xb7\xbe\x24\x11\x61\x2e\x41\xf6\x69\xfe\x55\x70\xee\xcd\x11\x7c\x08\xce\xbd\x19\x82\xcf\x76\xe3\x0a\x87\x52\xa8\xf7\x8d\xbd\x2d\x1f\x35\xb3\x90\x13\xd5\xa6\x09\x63\x43\x29\xb7\x69\xfe\x17\xdb\x34\x47\x7e\x1e\xa4\x7f\xad\x4d\x73\xe9\x1b\xff\x1d\x6d\xaa\xde\x5d\x2e\x5b\x3b\x3b\x3b\xff\x91\xdb\x6d\xab\x30\xce\xf9\x57\x03\xa7\x5d\x3a\x64\x66\x27\xfe\x19\xf1\x5a\x2f\xf6\x2c\x97\xd8\xd3\xe0\xdc\x72\x89\xdd\x14\xf4\x82\x1d\xd9\xca\xd8\xa2\x3b\x7d\x0a\x2c\xbc\x49\xca\x9b\xf6\xc3\xa3\xbe\xb5\xc6\x8c\x97\xe7\xb0\x67\xc6\x39\xec\x55\xed\x39\xec\x67\x23\x70\xc3\x38\x87\xfd\x00\x76\xcc\x4d\x2d\xd8\xf0\x4d\x17\xfb\xb9\x31\x46\x5c\x57\xd7\x23\x30\x02\xa7\x88\x1e\x05\xcb\x65\x9b\x85\xbf\x89\x81\x68\x8c\x2f\x86\x92\x70\xfb\xf7\x3a\xf2\x5a\x9b\x2a\xeb\xb7\xa7\x9c\xfd\xce\xc9\x4a\xd7\xde\x4f\x96\x6b\x2f\x69\x4d\xe7\xd1\xe5\x7c\x36\x4b\x52\x36\x25\x82\x66\x5b\x88\x3d\x43\x12\x0c\x88\x16\x23\x46\x56\xf3\xc9\x70\xc2\x4a\x40\x48\xde\x25\x81\x76\x02\x65\x7e\x40\x24\x90\x28\xfe\x3f\x6e\xfb\x0e\xb7\x9b\xb1\x27\x2c\xd6\x50\x3e\x43\x40\x34\x94\xfa\xec\x2f\x7d\x8c\x89\xc7\xf4\x5b\xca\xf7\x4f\x7e\x8a\x3d\xb1\xbe\x34\x31\x36\x95\x1e\x6e\x4d\x92\x34\xfa\x96\x90\x3c\x8c\x01\xb7\x6e\x71\x9a\x47\x83\x30\xee\xb7\xa6\xe1\xac\x4e\xf6\xab\x14\x08\x77\x1d\x53\xb6\x9a\xdd\x3b\xc8\xc7\x05\x42\x62\xae\x36\x4c\xa4\xfe\xa9\x99\xd1\x4a\x1c\x1e\xe6\xc5\x77\xbb\xe1\xa9\xe0\x40\x6c\x2b\xf2\x80\xf0\x38\x66\x26\x2d\x7e\x71\x96\x46\xe3\x88\xd8\x47\xf5\x0b\x59\x45\xdf\xc9\x93\x99\x03\xba\xfa\x92\x8e\x52\x9c\xe3\xf3\x2c\xce\x85\x69\x97\x49\x4f\xfc\xd6\x05\x1e\xe1\x14\x93\x01\xb6\xcf\x0b\x1d\x59\x00\x47\x9c\x1b\x2a\x29\x6e\x66\xa8\x0a\x13\x4b\x55\x98\x32\xb3\x9a\xc4\x55\xbb\xb5\x0e\x23\x2d\x47\xbe\x97\xc2\x8f\x8f\x79\xc9\x32\x8d\xe6\x50\x56\xf7\x3a\x20\x2d\x21\x27\x4f\x52\x9c\x4d\x92\x78\x68\x33\xe4\x76\xf6\x05\x39\xae\x14\x0b\x8f\x2d\xb1\xf0\xc6\x16\x0b\x2f\xb5\x58\x78\x64\x8a\x85\x9f\x2c\xb1\xf0\x5c\x1e\x5c\x5e\xd8\x07\x95\x67\xfa\xc3\x17\xdd\x45\xe1\x5f\xc0\x95\x3c\x6f\xa4\x13\x5b\x74\xc8\x07\x9d\xea\x6a\x93\x0e\xb9\x82\xcf\x2b\x44\x4b\x0b\x2e\x6d\x48\x18\x5c\x5a\xed\xf9\xe6\xa1\x4e\x78\x22\x25\xd6\x13\x78\x6f\x65\xcb\xab\xf0\x4d\xa7\x7c\x4f\xab\xf0\x1e\xde\x94\x8e\x38\xa5\x23\xa4\xea\x70\xf9\x93\x57\x4f\x5d\xca\xb1\xa3\x6e\xa8\x91\xb3\x99\xcd\x52\xc3\xaa\x99\x67\xa3\xd5\x21\xc0\x90\xcc\xac\x01\xf0\xf7\x48\xca\x75\xc7\xad\xa5\xae\x7c\xda\x99\x6b\xa9\xa9\xa9\x90\xfd\xd6\x94\xab\x5f\xaf\x73\xe8\x8c\x46\x5e\xb9\x5d\x83\x20\x18\xca\xd3\xc1\x4c\x20\xca\x4e\x89\x17\x32\x84\xf6\xdc\x75\x19\x46\xb6\x22\xbc\xe8\xe6\xbe\x02\x39\x7b\xab\x36\x70\x4e\x5d\xb3\xca\x9b\x1d\xd2\x80\x01\x66\x74\xe3\x96\x1e\xa6\x62\xf1\x95\x01\x84\x79\x32\xf3\x09\xf3\x64\x1e\xf1\xd5\x89\x9f\x97\x10\xee\x64\x3d\xa3\xf7\x62\x63\x95\xe5\x22\x43\x68\xdd\x03\x9d\x3d\x64\x30\xec\x23\xf8\xb2\xae\x29\x78\x4d\x99\x23\xfb\x83\xeb\xea\x71\xc8\xda\x43\xec\x20\x0f\x02\x28\x9c\xe3\xc2\x49\x40\x5c\x82\xa4\xce\x60\x4b\x08\xa3\x24\xf5\x44\x60\x33\xad\xf2\x01\xe1\x10\x2b\xf8\x00\xa5\xcf\x03\x8f\x70\x6a\x6e\x0d\x29\x8f\x74\x10\xa6\x42\x97\x29\x18\x23\xd2\x41\x4e\x57\x06\xc6\x20\x73\x95\xcc\x9e\x13\x4b\xbe\xfc\x71\x7b\x2b\x5d\x2e\xdb\x85\x46\xc9\x46\xd0\x33\xaa\x3e\x84\x87\x3e\x82\xdf\x1f\xaf\x7a\x85\x54\xa5\x53\x4b\xc8\xd2\x31\x09\x59\x3a\x7d\x5f\xee\xaa\x7a\xc9\x61\x5b\xfc\x07\x55\x02\xf4\x3c\x37\xd7\x9f\x19\x7f\x5a\xee\x3b\xf3\x8e\xf1\x72\x1f\x49\x90\xbf\x75\x45\xff\xc2\x88\x27\x02\x61\xd0\xb2\xd8\x76\xe4\x79\x9a\xbc\x29\xc8\x0e\x20\x0d\x7e\xf7\x08\xe4\xfc\x6c\x9c\x99\x12\x8c\x81\xcf\x87\xdf\x3c\x8e\xc5\xa8\x63\xd8\x46\xf6\x24\xf5\x27\xc4\x4b\x05\xcc\x6c\x12\xbc\xf6\x72\x44\x95\x40\x3a\x62\xb7\x52\xdd\xf8\x71\x90\xb0\x11\xbb\x95\x9a\xd5\xcb\x82\xe8\x39\x11\xf2\x0a\xcc\x83\xf8\x39\xe1\x12\x05\x0c\x02\xc5\xeb\xc0\xa6\x1c\x82\x51\x30\x30\x83\x03\xb6\xee\x60\x26\xef\x70\x32\xa1\x3b\x5a\x81\xe8\x1f\x77\xbc\x29\x26\x41\x44\xef\x6c\x05\x13\xd0\xa5\x78\x1e\x4c\x78\x20\x7f\x34\xf2\xb2\x7f\x0a\x48\xeb\x69\x90\x6d\x8d\x68\xca\xa9\x95\x72\x5a\x44\x23\x2f\x96\xd9\xdd\x06\xf1\xd6\xdd\x41\xbc\x15\xdc\x82\x59\x81\xe7\xc1\xad\xca\x70\xfe\xcf\x19\x4f\x3b\x0e\xe6\x5b\x33\x9a\x76\x5c\x4a\x3b\x2e\x8c\x46\xd5\x72\x0d\x33\x12\x31\x43\xa7\x17\x21\xc1\x01\xc1\x4f\x66\xeb\x92\xc4\x32\x49\x7d\x37\xf0\xd9\x3f\x84\xd7\xf0\x05\x7e\x87\xbb\xbe\xc2\x82\xac\xf5\x7d\xe5\xae\xa9\x6a\xb9\x3a\xd0\x6a\x7f\x1e\x3c\xa3\x53\x5c\x62\x75\xd0\xee\x64\x90\xd9\x9a\x11\x8a\xdd\xd3\x18\x3f\xac\x77\x8d\x24\xf4\x52\xdc\x45\x55\xdd\x89\x97\x39\xc8\xcb\x77\x58\xf9\x9f\xf5\x15\x60\x65\xfd\x58\x7f\xfb\x88\xf7\xfd\x4a\xef\x9a\x73\xd7\xfd\xc8\xf1\x14\x59\x8a\x93\xe9\x0c\xa7\x8c\x29\xf2\xa7\x90\x0c\x63\x4c\xf5\x88\xaa\x9a\x76\xde\x5d\x70\xd8\x23\xb9\x33\xf8\x46\x1a\x9a\x9d\xc0\xc6\x42\xd0\x3b\x87\x8f\x6b\xbc\x68\xa3\x91\x77\xbe\xd6\x1d\x98\x97\xed\xbf\xd4\xef\x97\x95\x98\xc7\x6a\x05\x87\x42\x7d\x6b\x06\xc1\xe1\x72\x79\x5a\x52\x64\x96\x4b\xef\x27\x21\xbc\xf0\x17\xbe\x06\xd3\xe5\xd2\x0b\xbb\x6a\xdb\xe3\x33\x95\x6d\x79\xbe\x4c\xb8\xc2\xea\x6c\xba\x92\x68\x38\xc0\xaf\xdc\xcf\xe3\x9c\x5b\x8d\xc1\xf6\x31\x59\xe8\xa8\xb4\x66\xbb\xa8\x73\x1b\x99\x71\x43\xf5\x04\x15\xf0\xa6\xaa\x33\x9f\xae\xd0\x99\x95\x7b\xb2\x7f\x6f\x28\xc8\xc7\x52\x27\xbe\xd4\x3a\xf1\x91\xa1\x13\x7f\x52\x6a\xeb\x4f\x05\x7c\x83\x85\xa1\x4e\xd7\x00\x26\xb2\x5d\xf0\xc6\x75\x6f\xd8\x2f\x60\xfd\x0c\xdf\x0c\xc1\x18\xd5\xa0\x7d\xd7\x7b\x5c\x8d\x59\xe3\xfc\x56\xc0\x59\xad\x6f\xd5\x4c\xf8\x56\x9d\x69\x3d\x80\xe6\x3d\x42\xa6\x01\x7e\x4c\xca\x11\x8b\xca\xf1\xa5\x8e\xdb\xb7\xe2\x0c\x23\x6f\xfc\xa1\x79\xee\x95\xb9\xbe\xb3\x4f\x7f\x0b\x57\x0d\x7a\x11\xde\xf3\x07\xce\x20\x8c\x07\x5e\xa7\xdd\xfe\xa1\xb1\xd5\xd8\xd9\x9e\xdd\x23\xcb\xa9\xa3\xe6\xa9\xf6\x70\x31\xe3\x0c\xcf\x93\x19\x3b\x8b\x2a\x90\x77\x6b\x9a\xe5\x1f\x88\xa4\x55\x53\x08\x69\x2c\x68\xa6\x35\x8a\xd2\x2c\x67\xc0\x1b\x7e\xee\xba\x1c\x87\x47\xb4\xb1\x60\xf0\xe8\xd6\xdd\xf4\x09\x37\x43\x98\x19\x18\xdc\x64\xf5\x5f\x23\xf6\xf7\x70\x2b\x0e\xad\x6f\xcf\x52\x7c\x1b\x25\xf3\xac\xf2\xfd\xfa\x07\xba\x0c\x2a\x1f\x5d\x84\x3b\x4d\x57\xa6\x83\x84\xc4\xbe\xdd\x6c\x1f\x48\xb0\x0a\xb6\x45\x5e\xe1\xfb\xbc\x82\x2c\x4a\x84\x12\x9f\xe3\x7b\x29\xf4\x23\xa0\x32\x0e\x13\xc9\xf2\x34\x9a\x7a\xa8\x95\x27\xef\x93\x3b\x9c\x1e\x85\x19\xf6\x10\x12\x12\x11\x8b\x9d\x4b\xf1\x0c\x87\x0c\x19\x91\xf4\xda\x7d\xc9\x60\x90\xf5\xda\x7d\x9f\xe5\xae\x3c\x0c\xf9\x7d\xa1\xb2\x33\x5c\x4d\x55\x87\x7b\xd1\x8c\x90\x42\x02\xa1\x96\x14\xa3\xa0\xd9\xa1\x32\x03\x7b\xda\x6c\xe6\xae\x4b\xd0\x41\x7c\xc0\x2a\x1b\x33\x8f\x47\xdd\xca\xec\xa6\x64\x7f\x3c\x88\x82\x66\x9b\xe9\xf8\x59\xd0\x4c\x5d\xd7\xd3\xce\x0f\xcb\xa5\xa2\x17\x8b\xeb\xe8\xc5\xd4\x79\x35\x62\xb2\x50\x5c\xe5\xa5\x88\x38\x2f\x85\xeb\xde\x11\x2f\x86\x10\xb9\x6e\x33\x43\x66\xab\xc6\x92\x5b\xe0\x80\x97\x3d\x66\x7c\x5d\x0c\x80\x9f\x98\x5c\xa1\x41\x1d\x57\xa8\xc9\x12\x6a\xf2\x86\xc2\xcd\x53\xac\x15\xfc\xbc\x30\x54\xc8\xe9\x75\x07\x39\xea\xe9\x49\x8e\xa7\x35\x74\x2a\xc4\x04\x71\x37\x2d\x0a\x06\x89\xf0\x90\x9f\xa6\xd1\x5c\xe8\x65\x2d\x9b\xb0\x48\x4a\x77\x9f\xdf\xd3\x70\x56\x83\xe2\x4e\xb5\x7e\x09\x2b\x3e\x36\x5c\x82\xad\x43\x1d\x27\x63\xf4\x57\x78\x78\x8a\xc9\xdc\xa9\x1e\xf0\x88\x8a\x53\x45\xd8\x40\x06\xb7\x2a\x59\xa3\x12\x0b\x45\xb8\xbe\x3a\xfa\x81\x2c\x3c\xd3\x5e\x35\x48\xb7\xe1\xe0\x7b\x57\x3e\x8c\x31\x4e\x73\x16\x74\xe4\xfb\xbd\x3e\xa8\xc9\x42\x77\x1d\x39\xd9\x7f\xc1\x0f\xa7\x61\x3e\x98\xe0\x21\xbd\x4b\xa7\xf8\x55\x34\x15\xb8\x42\xe8\xe0\x98\xd8\xd2\x83\xeb\xde\x95\x29\x2c\x44\x84\xd2\x13\xa4\x99\x45\x38\xfc\x32\x17\xac\xc3\x6f\x93\x94\x7b\x1b\x5e\x87\xf5\x36\x5d\x4d\x2c\x63\x12\x8a\x32\x29\xd1\xd2\xbc\xfe\xa1\xd3\x99\xb7\xe9\xa4\x15\xfa\xa0\x16\x65\x27\x54\xef\x65\x12\xec\x41\x29\xf7\x9e\x74\x67\xce\xb5\x3b\x73\xd7\x31\x98\x80\x1d\x45\xb1\x76\x21\x28\xd4\x52\xa8\x2d\x61\x60\xec\x26\xcf\xb5\x63\x5c\xca\x4f\x60\xa5\x78\xa5\xfc\x6a\x0b\xc3\xd1\xfa\x78\x9d\xdc\x79\xf7\x58\xd4\xa7\x81\xa5\x72\xcc\x71\x54\xb6\x3a\x07\x06\xea\x93\x8c\x24\x19\x40\x89\xe9\xb7\xc2\x29\xcb\x38\x2c\x25\xc2\x9e\x5e\xc1\x3c\x7b\x2e\x04\x8c\xbd\x40\x26\x93\x8f\x96\x4b\xc6\xdf\x75\x49\xb3\xb8\x0c\x88\x0e\x50\x3a\x0a\x8c\xb2\x4c\xc3\x59\xb5\x1c\x54\xa5\x67\xaf\x8a\x7e\xd3\xe1\x30\x99\xeb\x7a\xa9\x5e\x39\x82\x66\x1b\x81\x86\xfc\xac\x60\x54\xd7\x95\xd3\x4b\x35\x6c\x75\xbb\xc2\x7b\x82\x21\x55\x7d\x83\x8b\xd5\x40\x5c\x24\x37\xe3\x69\x62\xec\x3b\x53\xfa\x09\x26\x16\xdd\x18\x62\xe1\x70\x05\x4a\x34\xd7\x6e\x54\x57\x32\xf2\xb5\x1b\xfc\x00\xa9\xa6\x36\xca\x4b\xcc\x48\x4c\x35\x3e\x4c\xd3\xe4\x8e\xcd\x7e\xba\xb9\x21\xcc\xb6\x6c\x4c\xf2\x37\xdc\x1b\xcf\x43\x70\x4f\xbc\x1c\x52\x98\xc2\x0c\x1e\x08\x67\xfc\x6a\xa8\x37\x3f\xce\x36\x79\xef\xda\x7c\xef\xa7\x64\x8a\xd7\xbf\xc4\xf4\xf1\xca\xf7\x8e\xc9\x70\xc3\xd7\xcc\xcf\x75\xd8\x9e\x2d\xd8\xd3\xc4\xa6\xa2\x8e\x6a\xd8\xa6\x62\x89\x02\x10\x05\x02\x64\x33\x24\x03\xdc\x22\xc9\x9d\x87\x0e\x12\xbe\xd3\x6b\x92\x31\x2f\xda\x4a\x5a\x72\x61\xfb\xe7\x5e\xbb\xdd\xf5\x78\x1a\xc6\x0c\xa9\x45\x88\xa0\xd9\x66\x47\x2b\xe5\x75\x91\x0e\x33\xdf\x48\xe7\xba\x61\x33\x08\x12\x29\x68\xb8\xae\x67\x65\xd2\x41\x08\xf4\xf7\x82\x08\x44\x81\x18\xa5\x60\xc8\x27\x41\x1c\xa4\xae\xdb\xb4\xf2\xbc\x23\x5e\x0a\x09\x2d\x7e\xb5\x04\x54\x84\x58\x2e\x45\x17\x35\x3b\xac\xad\x21\x41\xa8\x5b\x6d\x5c\xbf\xbe\x06\x9d\xe2\xd6\x75\x6f\xe9\x22\x01\x8a\xb9\x27\xea\xb6\xfd\xad\x0e\x3b\xe0\x3a\x32\x04\xf3\x4b\x12\xdc\x10\x3e\x55\x49\xb0\xce\x74\xcd\x0f\x62\x0a\xf8\xb4\x3e\x19\xb7\x70\xc3\xf9\x86\x02\x84\x12\x1a\xcc\x38\xa8\xe5\xf2\x11\x3f\xde\x32\x4a\x38\x13\x2a\x06\xa5\x00\x45\x2a\x47\xd0\xa5\x80\x6e\xa7\xdc\x12\x6e\x81\xca\x2c\x0a\x5f\xfa\x86\xf0\xd8\xa5\x89\x7d\x6e\x30\x95\x27\x02\xb7\xf6\x89\x80\x75\x8c\xb1\x28\xc4\x39\x86\x50\x11\x8e\x44\x21\xaf\xeb\x8d\xf6\xd6\x31\x86\x30\xda\x5f\x97\x62\x9d\xf8\x57\x8e\x03\xef\xde\x0c\x75\x5a\x14\xfe\x3d\x32\x8b\x77\xa3\x05\x92\x7b\xe8\x99\x76\x70\x06\x05\xa0\xe5\x9a\x23\x9d\xcd\x65\x59\xae\xb9\xe4\x1e\x1b\x86\x5c\x63\x48\x33\xb5\x06\xfd\xba\x96\x77\xc0\xb1\xda\xb9\x4c\x36\x62\x18\xe8\x6b\x0c\xf0\x76\xcb\x6d\x6a\x69\xb7\xc4\xa1\x73\xee\xbe\x72\x41\xc5\xcd\xe6\xc0\x75\xa7\x66\xe8\x13\x17\x90\xae\xca\x37\x3e\x94\xf6\x49\xba\x37\x45\xdf\xbf\x47\xb2\x0d\xa1\x19\x04\x47\x2b\xf7\xc6\x0f\xf4\xd5\x0f\xe6\xde\xf8\xb9\xbc\x37\x56\xbe\x2f\x61\x3a\xe9\xeb\x65\xc2\x77\x2c\x08\xdf\x8d\x78\xd2\xab\x15\xc2\x42\xce\xe2\x41\x39\x13\x3d\x66\xbe\x3a\xec\x9c\xdf\x5f\xb7\xe7\x8d\x89\xde\xf3\xaa\x27\x34\x7e\xd5\x66\x75\xa5\x83\x86\xc4\x70\xf1\x1f\x54\xf4\xcc\x0c\x4a\x1d\x68\x1c\x97\x6b\x33\x86\x2d\x10\x9e\xe9\x48\x75\xf5\xb3\xb5\x42\x96\xf4\x30\x9c\x23\xa0\x12\x3e\x37\x77\x1c\xbb\xee\x31\xf7\x54\x29\xe0\x06\x81\x79\x9a\xe5\x4b\x99\xef\xdc\x90\xf9\x8e\x88\xff\x89\x54\xec\x9b\xab\x53\xea\x11\x6c\x06\x22\x8d\x85\x7d\x04\xdb\x77\xd5\xd2\xc5\x2d\x1f\x31\xb7\x97\x14\x54\x82\x63\xc6\x27\x11\x5a\x04\x35\x21\x4c\x77\x05\x7c\xaa\x9a\x69\x2e\x8d\xbe\x59\xc1\x4b\x71\x15\x5e\x1b\xa4\x14\x5e\xcd\xb6\xcc\xb1\x0a\x80\x2a\x99\x9a\x7f\xa2\x00\xa1\xd9\xf8\x67\xa0\xd6\x02\x3f\x74\x5d\xce\xcf\xfa\x61\xb9\x1c\x20\xb0\xd4\x1c\xff\x02\xc4\x4c\xf4\x8f\x0a\x18\xd5\x5a\x88\xe2\x56\x1c\x65\x39\x8c\x6c\x03\xd1\x67\xd3\x3e\x74\x61\xd8\x87\x84\x5d\x68\x85\xa5\xe6\xd5\x3e\xb3\xd4\x3c\x12\xc2\x54\x00\xfd\xa4\xbf\xa8\x37\xe8\xb0\xd5\xaf\x40\xde\xb9\x70\x8f\x3d\x23\x01\xf1\x76\x5f\xed\x6e\x23\xb8\xda\x60\xe3\x7a\x04\x0d\x4d\xc7\xd4\x67\x7a\xed\x8d\xbb\x4e\x1c\x39\x3e\x47\x44\x13\x2b\xc7\xbb\x79\x9e\xe3\x34\x33\x77\xae\xb9\xeb\xf2\xc8\x13\xe9\x0f\x2a\x77\x14\xaa\x07\x53\xd9\xb3\x14\x4c\x4f\xd7\x9d\x88\xae\xc1\x3e\xd7\x7f\xe5\xa2\xc3\xbd\x1b\xc5\xde\x0f\xb7\x4f\x8d\xb2\xb7\x0b\xe8\x80\x53\x2a\x8e\x03\x0e\x2d\x8c\x03\x6a\x43\x71\x40\x53\x64\xea\x80\x13\x62\x2e\x92\x06\x29\xeb\xb4\x3b\xf5\xb7\x3a\xd5\x91\xfd\x93\x11\x90\x72\xcd\xbc\x98\x19\x04\x1a\x95\xb9\x67\x5a\x94\x49\x40\x95\xd5\xcf\x40\x96\xc0\x57\xb1\x1f\xa2\xd8\xfe\x00\x2a\xd3\x71\x88\x49\x86\xfd\xb0\xc5\xfe\x16\x30\x44\x75\x56\x5d\x05\xce\x36\x71\xdd\x50\x37\x29\xdd\x5a\xc2\xd6\x98\x67\xae\xfc\x8c\x6f\xcd\x61\xfc\xa1\xce\xcf\x38\xb7\xfd\x8c\x4d\x0a\x17\xd3\x4b\xfc\x3a\x19\x3e\x74\x68\xf5\xcf\x08\x7b\xac\x6d\x9a\xbb\x2f\x65\x78\xc8\x55\x32\xf3\xf7\xe5\x85\x88\xcd\xda\x87\xeb\xe4\xfe\x32\xfa\xc6\x46\x3f\x8f\x1d\xd9\xba\x4e\xee\x1d\x10\x2e\xe6\xb6\x01\x55\xdb\x4f\xef\x26\x51\x8e\x2f\x67\xe1\x00\xfb\x0e\x49\xee\xd2\x70\xe6\xd0\x12\x5d\xa7\x38\xbc\x99\x25\x11\xc9\xb3\xd6\x7c\xe6\x39\xd9\xd4\x41\x60\x14\x46\xc4\xf6\x21\x04\xa2\x25\x98\x33\xbc\xec\x83\x45\x01\xbc\x89\xd7\xd5\x72\xbb\x2e\x3f\xdb\x1d\x9a\xce\x50\x26\x5b\x14\xc8\xbb\x12\xb3\xf4\x33\x81\x53\x3a\x51\x3b\xfb\x2f\x76\x10\x9c\xb0\x78\xb1\xbd\x57\xbb\x08\x0e\xe9\xcf\x17\xdb\xaf\x5e\x22\x78\x4f\x7f\xbe\xdc\xeb\xec\x20\xf8\x46\x02\xef\x73\x19\xee\x4d\x8c\xcb\xcf\x24\x38\xbb\xfe\x82\x07\xb9\xe0\xbb\xe6\xc4\x22\x67\xa3\xe5\x72\xf1\xf9\x33\x23\x1a\xf9\xfc\xd9\xef\xf5\x8b\x88\x64\x39\x55\x36\x92\x51\xe3\x30\x4d\xc3\x07\x33\xd6\x99\x66\x87\x5b\x2a\x79\x90\x17\xcb\xe5\x8a\x43\xe8\x46\x44\x1a\x39\x12\x5f\x54\x3c\x26\x25\x3a\x33\xc1\x0d\x03\x84\xc9\x18\x3d\xd2\x0f\xf2\x1e\xe9\xa3\x02\x3e\x13\x01\x16\x6f\xe7\x4e\xf5\x2e\xe5\x73\xa4\x28\x38\x72\xd7\x95\xe7\x63\x28\x9f\xa4\xc9\x5d\x83\xe0\xbb\xc6\xd5\xc3\x0c\x1f\xa7\x69\x92\x7a\x0e\x9b\xc1\x0d\x7c\x9f\x63\x32\xcc\x1a\x0c\x56\xba\xe1\x3c\xbf\x64\x78\x71\x5e\x8e\x9e\x3b\x8d\x28\x6b\x90\x24\x6f\x84\x0d\x36\xa6\xd3\xf9\x20\x4f\xd2\x46\x92\x32\xb4\x70\xc7\x30\x7f\x6b\xb6\x11\x9d\x2e\xc0\x85\x28\x2e\x60\x5d\x53\x01\xd8\x1e\xe4\x5d\xd1\x06\xc2\x5d\x32\x47\xbe\x67\x10\xbb\x04\x46\xe3\x00\x2d\x36\x41\x85\x9c\x59\x6f\xc8\x2a\x86\x1d\x65\xf1\x31\xd9\x75\x14\xb7\x8e\xe2\x8a\x99\x30\x0b\xd5\x55\x32\x1e\xc7\x98\x8e\x2e\x8b\x09\x4e\xc3\xf2\xd7\x85\x07\xd0\x45\xf6\x6c\x86\x09\x1e\xfa\x4d\xdc\xd2\x57\x85\x20\x1f\xe0\x59\x33\x49\x67\x4d\xce\x56\x36\x9d\xc2\x78\xf3\x32\x4f\x66\x57\x61\x76\x53\xc5\x70\x4f\x95\x95\x23\xbb\x39\x79\x03\x79\x30\xc0\x1e\xe6\x16\xf2\x41\xc8\xbd\xca\xc9\x98\x53\x65\x8f\xa2\x74\xea\x39\x6f\x92\xc6\x43\x32\x6f\xa4\x38\x8c\xe3\x87\xc6\x5d\x48\xf2\x46\x9e\x34\xb2\x3c\x99\x35\x42\x32\x6c\x0c\x71\x8c\x73\xdc\xa0\xd9\x35\xbe\xce\xf1\x1c\x0f\x1b\x61\xde\x70\x9e\xe7\xcf\x9d\xae\x83\x98\xbd\x44\x32\x2c\xbc\x61\x49\x3d\x8c\xaa\x15\xf4\xcc\x6a\x9f\x26\xb7\x98\x16\xfe\x2a\x79\x9b\x26\x36\x15\x8d\xce\x8c\x25\xe2\x09\x3c\xbb\x4e\xb5\xd9\xd7\xe5\xfe\xba\xc4\xe9\x50\xce\x9c\x3e\xdf\x34\xef\x14\x8f\x54\x94\x3c\xf7\xd4\x51\x84\x47\x76\x27\x41\x2a\xed\x43\xdf\x88\xe4\x38\xd2\xf3\xb7\x8a\xbc\xbf\x36\xe2\xa5\x96\xc0\x37\x21\xb0\xc0\xc3\x31\x73\x30\x1f\x72\x93\x12\x9b\x53\x54\x4a\x97\x94\x5c\xec\x46\x79\xfc\x56\x79\xcb\xde\x93\xd6\x27\xf6\x91\x1a\xc6\xad\x0b\x02\x0b\xe9\x56\xa3\x3e\xa0\x4c\x2d\x4c\x0c\x35\xf8\x02\x74\x23\x28\x09\xde\x28\x83\x6a\xcc\x6a\x11\x2e\x49\x7d\x2d\x3f\x10\x58\xd4\xd4\x46\x0e\x7c\x10\x61\xc3\x26\xd5\xce\x34\xb9\xa5\x7b\x79\xf5\x1b\xf1\x8a\x6f\x1c\xd2\xea\xcb\xb8\x39\x15\x10\xe6\x14\x35\xad\xf1\x07\x86\x85\x88\x7a\xbb\x52\x5b\x93\x38\xf3\xad\x66\x20\x48\x30\xac\x62\x75\x1d\x3e\x3f\x1c\xdf\xa1\x95\x70\x10\xaa\x49\xe4\xba\x4f\xa5\x73\x5e\xd1\x4e\xa5\x39\xb6\x79\x9b\x9c\xac\x19\x12\x7f\x60\xfe\x8e\x43\x73\xa7\xab\xc4\x88\xe6\xed\xd4\xa4\x7c\xb4\x54\xaf\x19\x2f\xc8\xa6\x85\x3a\x7d\x4a\xa1\xae\x43\x46\x24\xc7\xe8\xdb\x2a\xac\x05\x74\x91\x7c\x4b\xaa\xcb\xa6\x1d\x59\xa2\x8e\x4b\xff\xbf\xb3\xe5\x63\x8e\xe7\x57\xa1\x33\x97\x91\x32\x35\x1b\x3f\x51\x1b\x3f\xf9\x8e\x8d\x9f\x3c\x65\xe3\x4f\xeb\x36\xfe\xbc\xe0\x85\x86\xbc\xba\xef\x93\xd2\xbe\x4f\x90\xcf\x97\x6a\x99\xac\xb4\xef\xa7\xa8\x28\x3c\x04\xaf\x49\xcd\xda\xfa\x5a\x89\x6e\x61\x96\x45\x63\x62\xf6\x80\x6e\xff\x1c\x48\xd0\x81\xb4\xe2\x58\x77\x40\xfe\x91\x1e\x90\xe7\xcf\x91\x4c\x98\xb0\x8e\x32\x7c\xec\x48\x7f\xd3\x5e\x4b\x78\xaf\x25\xb4\xd7\x12\xad\xf3\xe0\x02\x5e\x33\x3a\x94\xf8\x81\xcb\x22\x2a\x6f\x54\xc0\x17\x5b\x20\x05\x33\xc2\x80\xe0\x3b\x8f\x2c\x97\x1e\x09\xce\xd3\x64\x1a\x65\x18\x99\x5a\x04\x3f\xac\x96\x5d\x10\xd1\xca\xe6\xe9\xc3\x22\xf3\x38\x31\x9f\x87\x11\x2a\x06\x61\x3e\x98\xd0\x27\xa1\x87\x51\xa1\xcf\xbc\x63\x33\x35\x1b\x1c\x6b\x93\x67\xea\xd0\xe2\x00\xb7\x86\x09\xc1\xdd\xc4\xc3\x2d\x36\x62\x90\xef\xe5\x81\xf8\x0d\x79\xc3\x98\x2c\xa4\x9b\xfb\x4c\x66\x2b\x81\x28\x72\x74\x45\xd4\xca\x27\x98\x78\x11\xc4\xa8\xc8\x3c\x2f\xe5\x44\x70\xf1\x03\x6d\x84\xe5\xb2\xd7\x47\x88\xd7\x82\x47\x35\xc0\xef\x2b\x60\x9a\x21\x81\x10\xa2\x60\xc1\x83\x68\xdb\x90\x51\x15\xd0\xf6\x77\xea\xb8\x49\xaf\xdd\x17\x53\x80\x45\x86\x89\xe6\xa5\xbf\x0b\xc8\x53\x7e\x3a\x4a\xd7\xfa\x5e\x5f\xcd\xb0\x30\x58\xd0\xef\xfb\xb1\xd7\xa6\x2b\x79\x9a\xdc\xf9\xb1\xd7\xa1\x4a\x1e\x7d\xec\xc7\xde\x36\xaa\xe5\x5d\xb9\x7c\x98\x5e\x27\xb1\xeb\x7a\x61\x8f\xff\x6c\x45\x39\x4e\xc3\x3c\x49\xfb\x75\x72\xc1\x24\xca\x0a\x04\xe1\x81\xd1\x33\x61\x35\x38\x27\xae\xde\x0a\xf9\x41\x59\xfd\xcc\x7e\x87\x09\xff\x26\x9d\xc1\x61\x9c\xe2\x70\xf8\xd0\xc0\xf7\x78\x30\xcf\x23\x32\x6e\xd1\xa9\x9b\xa4\xde\x41\x74\x80\xe8\x18\x60\x07\x6e\x1d\x48\x5d\xd7\x4b\x82\x6d\x37\xec\xb5\xfb\x5d\x2a\x12\xb1\x8a\x8a\x2b\xf6\x99\xe5\xd2\xf3\x92\x40\x3e\x42\xae\x9b\xf0\x91\x9f\x22\x68\x23\x9f\x0f\x3b\xe4\xba\x4d\x2f\x09\xe4\x13\x08\x7b\x1d\xda\x97\x74\xd0\x48\x37\x85\xe4\x20\xbb\x8b\xe8\x40\x4b\x83\x36\x24\xb4\xa9\x82\x1e\xff\x2c\x24\x7c\x20\xf5\x11\xd0\x4b\xb4\x18\x84\x19\x6e\xb4\x7d\xf6\xa7\xe3\x27\x41\x78\xc0\xb4\xd1\x03\x76\x63\xd7\x97\x2c\xf9\x1c\xaa\xe1\xf9\x73\xc9\x8a\x43\x3f\x0a\xf4\x93\x54\x64\xe3\x89\xf7\x7c\x9d\x2a\x0d\x58\x82\x30\xe8\xb5\xfb\x54\x52\xce\x23\x32\xc7\x3c\xd9\x0b\x3f\x0c\xa2\x16\xdd\xb2\x67\xc9\xcc\x43\x10\xb5\xe8\xf8\xe0\x17\x3a\xa9\x40\xbf\xf0\xa3\x91\xd7\xa4\x4d\xe2\x25\x01\x4f\x88\x8c\x73\xa7\xa4\x97\x88\xab\xad\x4e\x1f\x2d\x97\xfb\xcd\x20\x08\xd9\x81\xd1\xb6\xf8\x85\xd0\x22\x0a\xda\x2a\xdb\x22\x1a\x79\x3b\x81\x4c\xe4\x35\x93\xe5\x92\x96\xf3\x9f\x09\xbb\xa6\x3f\xff\x91\xf4\x76\xd8\x5b\xbc\x2a\xac\x1a\xbc\x45\xe8\xbb\xfb\xea\x5d\xf1\xfc\x1f\x74\x84\xeb\xd4\x8c\xcc\x4f\xb5\x21\x7d\x23\x31\x93\x6e\x5b\x49\xb7\xfb\x20\xda\x41\x9c\x5b\xf1\x97\xe8\x03\xfa\xd2\x23\x2d\x54\x84\x54\x9c\xa6\x23\x00\x43\x64\xae\x2b\x41\x6f\x1f\x70\x1f\xd2\xa0\x5d\x8c\x22\x42\x75\x92\x05\x09\x92\xa0\x4d\x4b\xb3\xc7\xc6\x80\x18\xd1\xa1\x9e\xa8\xaa\x53\xdb\xfd\x2e\xbd\x2d\x83\xca\x78\x07\xb7\x8b\xc2\xeb\x85\x10\xf7\x59\x68\xe7\xb3\x95\x5a\xa1\xc1\x9d\x63\x70\xae\x96\xb4\x42\x22\xa5\xfe\x28\x7b\x9f\x84\x2c\x86\xbf\xd9\x01\xaa\x3c\x1c\x8d\xc6\x82\x6c\x89\x48\x0d\xe0\x6d\x8d\x06\x20\xc4\x58\x66\xfd\xb8\x62\x3a\x47\x5d\xa0\xeb\x17\xc2\x3f\x2f\x2a\x22\xfe\x94\xbd\x62\x95\xb7\xd4\xef\x22\xb9\x61\x7a\x44\x0b\x31\x87\x08\xef\x31\x35\x55\x4c\x46\x38\xad\x69\x1a\xd5\x61\x90\x6e\xbb\xa6\x70\x3a\xc6\xac\xa8\x47\xa3\xb1\x87\x51\xff\x40\x4c\x36\x99\x11\xb3\x21\x92\xdc\x2b\xd3\xd5\xd5\x37\x11\x73\x78\xdf\xee\x17\x82\xcd\xcf\x6a\x9b\xb5\xe4\xac\x1b\xb7\xcc\xca\x36\xc1\xaa\x4d\x70\x7d\x9b\x48\x9b\x83\xc1\x67\x1a\x66\x37\xbf\x52\xad\x57\x2a\x3e\xdd\xde\x0e\x6c\xf7\x7d\xd9\x3e\xd5\xde\xf4\xd6\xbd\xad\x1b\x0f\xcb\x36\x13\x45\x09\xb6\xf9\x93\x6d\x51\x96\x55\x4d\xc4\x15\x48\x69\x5b\x0d\xec\xc3\x1f\x6e\xd4\x60\xb5\x4e\xb8\xde\xbf\xea\xac\xe6\x27\x0c\x86\xb5\xf4\x06\x3f\xf8\x8e\xf3\x1c\x57\x19\x9d\x55\x6b\xa6\x75\x55\xc5\xc8\x00\xb8\x30\x94\x41\xd5\xf1\x55\x09\xdf\xd0\xa3\xfc\x44\x59\x25\xde\x30\xbe\x56\x6e\x99\x00\xa5\x47\x19\x09\xae\xa2\xa9\x4a\x50\xe3\x85\x8a\x57\x28\x47\x6f\x08\xbc\x26\xde\x82\xeb\xf6\x3e\x06\xa1\x65\xf9\xc4\x54\xd0\x84\xa2\xb0\x56\x4b\x37\x38\x39\x2d\x3e\x42\x61\x2d\x5e\x8f\x5b\x51\x5b\xb4\x9c\x98\x07\x1f\x44\xe2\xac\x49\xf3\xb3\x38\xd2\x90\xf7\xd9\xe9\x51\xc1\xb5\xee\x66\x5b\x9d\x9f\x18\x30\x81\xab\x48\xc9\xad\x8f\xe4\x49\x12\x5f\x87\x69\x4d\x0b\xae\x52\x2f\x13\x71\xdf\x39\xe2\x23\xd8\xd1\xce\xf4\x6b\xc6\xb9\xe0\xb3\xb5\x07\xeb\xda\x99\x01\xcd\x1a\xdb\xbe\xfa\x38\x4b\xea\x58\x0a\xb3\xce\x81\x59\xa5\x4a\xc1\x9a\x26\x63\x74\xb9\x14\xd0\x6c\x33\xf9\xb2\xfa\xbd\x77\xd8\x6e\xae\x01\x3f\xc2\x84\x59\x98\x86\x4c\xe3\x67\x4e\xdd\x31\x6e\x71\xae\x8c\x68\xc4\xc5\x75\x31\xea\xc5\x0a\x27\x97\xa4\xed\x5a\xfd\x93\x9b\x26\x3f\xae\x07\x17\x11\xdd\xe4\xe3\xd6\x34\xba\x8f\x48\x26\xfb\x0d\xf8\x60\x90\x50\x30\x9d\x97\x6d\x0b\x57\xa4\x00\x63\xb0\x18\x89\x0a\x10\x15\xe1\x50\x82\xef\xa8\xa8\xda\x51\xf0\x51\xb8\x95\xcd\xc2\x01\x9d\x59\x3b\x08\x0c\x68\x22\x9a\xbb\x69\xf0\x9f\xa5\x98\x21\xc7\x20\xef\x99\xb0\xae\xff\x46\x02\xe2\xed\x6d\xb7\x5f\xc9\x6a\xfd\xc4\xaa\xf5\x1b\x3b\x8c\xa8\x8c\xc6\x59\x98\x4f\x1c\x58\x0c\x7d\xe7\xb4\xb3\xdd\xd8\x3e\xda\x6f\xed\xbe\x68\x6c\x37\xb6\x1b\xe2\x47\x67\x3b\xdb\xa5\xbf\x3a\x6d\xf5\x6f\x4b\xdc\xd8\xea\xb4\x2f\x3b\x2f\x5a\x7b\x3b\x2c\x59\x63\xfb\xdb\x74\xaf\xd1\xd9\x69\xed\xbd\x7a\xdf\xd9\x6b\xed\xbd\x6a\x74\x5e\xd0\xdb\x9d\x9d\xd6\x6e\xa7\xf1\x92\xfe\xd7\x79\xd1\x78\xd1\x10\xcf\xda\xec\xff\xed\xc6\x0b\xfe\x88\xfd\xc7\xd3\xf3\x27\x2c\xd5\x0b\xfa\x0a\x7f\x95\xe5\x42\x1f\x8b\x1c\xbe\x39\x05\x02\xe7\x88\x91\x9d\x9a\x2a\xed\x57\x33\x92\xf7\x75\x38\xb8\xa1\xcd\xa8\x79\xfd\x97\x4b\x69\xef\x91\x77\x38\x35\xc7\x86\x5e\x2e\xb7\x61\x1e\xa6\x8f\x9d\x1a\xd2\xb5\x3a\xe4\x1c\x4a\x12\x9b\x6e\xae\xcf\xfa\x32\x03\x9b\x8e\x83\x6f\xeb\x63\xc6\x21\x07\x4c\xc0\x39\x3e\x19\x24\xc4\x72\x99\xad\x75\x92\x8d\x68\xaa\x69\x20\x64\x09\xe1\x13\xcb\xf6\x0a\xe6\x11\x2b\x6d\xbf\xcc\xb1\x45\x3b\xcb\x5e\xcb\xab\x8f\x33\x86\xd6\xcb\x70\xed\x0c\x27\x95\x3b\x8d\x6b\x77\xc7\x42\x72\xa5\x07\xca\x8d\x4e\x73\x6c\xd4\xe2\x98\x33\x56\x18\xce\x27\xac\x99\x56\xc7\x8f\xca\x06\x32\xf0\xef\xac\x33\x4b\xd5\x02\x36\x30\x5e\xc4\xef\xb0\xba\x0a\xd7\x94\x68\x70\xc3\x7e\x89\x3e\xb5\xfd\x6c\x45\x1d\x25\x7a\x9e\xe5\x69\x72\x54\x76\x23\x31\x10\x4f\x8e\x20\x2d\x03\x9d\xd0\xb5\x85\x07\x93\x84\x63\x8e\x4f\x81\x60\xec\xba\x63\xb6\xd7\x5e\x04\x4d\xaf\xd9\x09\x82\x20\x5e\x2e\x9b\xb7\x68\xb9\x8c\xe1\x2c\xd0\x68\x79\xf7\x70\x15\x0c\x96\x4b\xef\xa2\xfb\x05\xfb\x6c\xf5\x47\xf0\x21\xb8\x0a\x82\xe0\x0b\xee\x2e\xf4\x01\x28\x7b\x54\xf8\x8b\x02\x3e\x2b\x8a\xfa\x31\x1f\x7b\xa7\x81\x3a\xd2\x34\x11\xfc\xe6\xae\xab\xaf\x19\x3e\x72\xd8\x33\x5a\xef\xa8\x1e\xda\x6f\x8e\x50\xdf\xb7\x12\x9e\x09\xc4\xee\x35\x2f\x20\x38\x73\xdd\xd0\x18\x9c\x0c\x31\x0b\x1d\x7c\x0e\x86\xae\x5b\xf1\xae\x19\xa2\xb2\x93\xcb\xb0\xd6\x9f\x60\x68\xee\xd7\x6c\x02\x99\x9f\x80\x53\xa4\x44\x9f\xf3\xa2\x8a\x29\xfb\x13\x59\xc1\xc8\xb5\x32\x0b\x36\xd7\x4f\x78\xeb\x26\x35\xe5\x66\x86\xa0\x93\xa0\x82\x10\x51\xff\x19\xb1\x1a\x24\x95\x4a\xb0\xa6\xe2\x4f\x59\x33\x41\xa9\xd3\x42\x39\x45\xd6\x35\xb8\x74\x2e\x3a\xe4\xc5\x15\xfb\xe6\xa4\xa6\xd4\x13\x5a\xea\xc3\x72\xa9\x27\x2b\x4a\xcd\xd6\x8c\x49\x7d\x99\x23\xd9\xb1\x35\x25\x8e\xd6\x8f\x28\x54\x67\x9e\xbf\x2a\xb9\xdb\x5e\x2c\x97\xe3\xae\xc3\x25\x5c\x47\xaa\x83\xeb\xce\xed\x4b\xc5\xe8\x85\x2b\x01\x2b\x69\x19\xe0\x82\x95\x54\xad\x2f\x6b\x8a\x4b\x67\xaf\x9c\x03\x8f\x24\xed\x5b\xa5\xb8\xa1\xa5\x50\x6c\x02\x5a\x6a\xd6\xf7\x04\xb4\x9f\x21\x30\xeb\x67\x0a\x37\xaf\xe8\xcd\xfb\x7d\x98\xb1\x39\x25\x57\x78\xd6\x05\x0a\x8d\x8e\x55\xc6\xd8\x4c\xc6\x6a\xfe\x85\x06\xbf\x9c\x06\x4a\x6c\x36\x67\xcb\xa5\x68\x52\xe5\x60\xc1\x1a\xbc\xad\xd1\x5c\xf8\x4c\xb8\x5d\xe1\xde\xac\xc4\xbe\xab\x30\x1d\xe3\x9c\xed\x90\x39\xfb\xe9\xba\x6c\x5f\xe5\x3e\x71\x25\xff\xa3\x07\xd7\x7d\x60\xeb\xa0\x58\x6f\x37\xce\xd2\x1b\x8b\x6c\xbb\x74\x1d\xf5\x9d\xe3\x6c\x10\xce\xb0\xe1\xed\x74\xa4\x05\x57\xf5\xb3\x75\x1d\xcf\x53\x0f\x21\xb8\x76\xdd\x6b\xf6\x59\x81\xa3\xf2\x01\x2e\x11\x9c\x2c\x97\x87\x1b\x60\x84\x1a\x03\x8d\xef\x9c\xac\xe9\xd9\x4f\xbe\xae\x15\x30\xb5\xb1\xa1\x7f\x5d\x21\x1a\x72\x8f\x70\x27\x56\xc4\x66\x9a\x6e\xe1\x61\x86\xbb\xfa\x72\x9c\xe2\x87\xde\x4e\xbb\xdd\xf7\x4b\xf7\x5e\xb4\xdb\x7d\x60\xb9\x57\xc0\x10\x2d\xc6\x86\xd6\xf6\xbe\xd4\x1b\x45\xe0\xdd\x28\x21\xf9\xdb\x70\x1a\xc5\x0f\x36\x4a\xa1\xbe\xff\x18\x8c\xe1\x0e\xaa\x07\xbd\x7b\x12\xb7\xa0\x88\x0d\xdf\xd9\xae\x60\xed\x09\x77\xc3\x34\xcc\xf2\x2b\x7c\x9f\x7b\x39\xaa\x50\x0d\xe6\x36\x48\x6a\x67\xbf\xce\x9b\xe5\x51\x10\xd4\x5e\x0d\x0a\xaa\xc9\x60\xd1\x47\x30\x98\xa7\x59\x92\xfa\x6a\x2a\xeb\x08\x41\xa0\xcd\xfc\x06\x0f\x12\xe1\xaa\x27\xc8\x98\x24\x79\x05\xbf\x92\x62\x79\x1b\xa4\xcb\xb4\x00\x8a\x9d\x46\xc3\x61\xcc\x92\xd7\xba\xee\xd8\x58\xa6\x12\x51\xa8\xb5\x07\xcc\x31\x07\xa7\x2c\xc4\x36\x93\x38\x7c\xe0\xb8\x8d\x67\x42\x7a\xb2\x00\x49\xf7\xc0\x42\x19\xdd\x17\x2e\x41\xdb\xbb\xb2\xf5\xb7\x77\x45\xeb\x6f\x3a\x14\x5f\xd4\x0c\x45\x3a\x3c\x1f\x1b\x32\xcc\x7c\xae\x4a\x79\x64\x60\x99\x3a\xab\xc1\x4c\x07\xc6\x28\xa8\x0c\x81\x6a\xf2\x61\x98\xde\x54\xbe\xa2\x96\xce\x9a\xef\x68\xd4\xd0\x0d\xbf\xa4\x5f\x28\x7f\x8b\xcd\x7f\xbb\xf1\x77\xed\xc6\xdf\x05\xa9\xc2\xc9\xc6\xef\xbc\x7c\xac\xd5\xda\xa8\xb0\x80\x46\x55\xaf\x95\xe1\x60\x1f\x6f\x1c\x86\x8b\xba\x49\x43\x57\xa1\x5a\x37\x69\x8f\xda\xec\xeb\xdb\xd7\x86\x51\x55\x3b\x95\xbf\x98\x67\x38\xe5\x16\x29\x39\x7d\x36\x22\x0f\x55\x73\x54\xcc\x0d\x47\x81\xc7\x42\xc3\xf5\x59\xd8\xda\x4a\x14\xd9\xcf\xbb\xc8\xcb\xa1\xd5\x7e\xc9\x86\xa7\xcf\x43\x70\x68\x6a\x4d\xa7\x23\x39\x79\x7a\x9d\x7e\x61\x14\xf7\xc8\x6a\xff\xa7\x7d\x71\x45\xef\xb0\x62\x94\x3f\x61\xf4\xc3\xf7\x7e\xa4\xd4\x4b\xe2\x33\x4a\x26\x60\x19\x6f\xdc\x4c\xc6\x8b\x95\x26\xf8\xfe\x9a\x6f\x57\x33\xb6\x2b\xfe\x57\xea\xcb\x32\x37\xe8\x85\xd6\x22\x43\xaf\x21\x1f\x5a\xb9\x46\x56\x88\x6f\xb7\x77\x90\x23\xe8\x70\xb7\xf7\xf6\xa0\xa1\xff\xe3\xcf\x10\x38\xcf\x54\x37\xab\x5e\x35\x6f\xb1\xfa\x42\xe3\x99\x6a\x93\xc7\x9a\x60\x8d\x08\xb0\x1e\x0d\x79\xf5\xee\xb1\xfb\xc8\x02\xb7\xcd\x9f\x33\xfd\xba\xee\x45\xa5\x16\xd4\xbe\x66\xa8\xeb\x36\x18\xf6\x5e\xf9\xb9\x9d\x07\x4f\xb4\x63\x74\xe9\x66\xa0\xd8\x6b\x3a\xb6\xfe\x8d\x7f\x7b\x27\x3d\x01\x77\xdb\xa8\xed\xe6\x18\xda\x1b\xd5\xd8\x7e\xe7\xdf\x5e\xe7\x27\x01\x75\x17\x05\xf0\xc1\x47\x37\x0a\x63\x18\xea\x4b\x7b\x09\xb2\xee\x1a\xed\x54\x00\x1d\x8a\xca\xb5\xeb\xaf\x8a\x3a\x6b\x04\x2c\xfe\x25\x51\xc8\x9a\xfd\x7e\x8d\x78\xc0\x5f\x3d\xaa\x41\x79\x37\x40\xe0\x55\x92\xca\x28\x30\x12\x09\x84\xf1\xaa\xc7\x37\x5d\x15\xce\xd4\x5d\x1c\xc7\xd1\x2c\x8b\x32\x25\xa5\x72\x43\xf1\x36\x98\x11\xcf\xf4\xba\xd6\x51\x5c\x6b\x3d\x0a\xff\x9c\xbd\xff\xd2\x7e\xfd\xa5\x58\xd6\xd9\x44\xf6\x17\x1b\x6e\xe8\xec\x1e\x51\x42\xea\xb6\x94\x5b\xb7\xab\x7b\x3d\x6f\x44\xdf\x69\x37\xf6\x66\xf7\x8d\x76\x63\x6b\x7f\x76\xef\x98\xf0\xf1\x83\xd2\x58\x24\xd0\xda\x55\xbb\x8d\x5e\x5f\x94\x70\xd5\x91\x52\x32\x43\x12\xd1\x3d\xb4\x6b\x76\x1e\xed\xae\x92\xc5\xac\xd4\x69\xeb\x26\xbc\x25\x6d\xb6\x5e\x20\x4b\x60\x51\x32\xc8\x46\xc2\x5a\xa5\x18\x95\x81\xb1\x7e\x16\x7e\x5f\x51\x56\x08\x76\x66\x61\x2c\xe3\xe0\x13\xda\x86\x6f\xd9\x4f\x6d\x13\xfa\xd6\xea\xcf\x3f\xb1\x4d\x9e\x56\x04\xfb\xbd\xa2\x04\xeb\x7e\x34\x89\x18\x3d\xfd\x2f\xe2\x94\xe5\x1d\x09\x88\xb7\xf3\xf2\xc5\x4b\x04\x7f\xb2\x00\x86\xce\xab\x57\x08\xfe\x60\x61\x0d\x2f\x3b\x08\x7e\xe6\xa7\x30\xfb\x2f\x10\xe0\xf4\xe9\xd8\xea\xeb\x82\x92\xe2\x38\x9c\x65\x78\x28\x98\xce\x33\xf3\x1e\x55\x41\x4a\x87\x0d\xed\xd9\x7d\xdd\x41\x83\x89\x0f\xca\x38\x42\x07\xe6\x71\x43\x05\xd3\xbd\xf6\xf4\x81\x08\xca\x40\x0e\xde\x79\x6b\x81\x77\x8e\xed\x20\xdc\x07\x0d\xde\x79\x6d\x82\x77\xde\x59\xe0\x9d\xf7\x0a\xd3\xfd\xd8\xc0\x74\xb7\x8e\x1d\x38\x53\x63\x96\x87\xb4\xab\x86\xec\xec\xa1\x1e\x80\xd3\x0a\x97\x3d\xc9\xab\x21\xb2\x9b\x70\xf3\x98\x2d\x6d\xde\xb9\xe4\x07\x0a\x35\x91\x56\xff\x1d\xf0\xe1\x55\x18\xad\x81\x60\xb9\x2e\x90\x16\xc1\x87\xa0\x0c\x9f\xeb\xc5\xcb\xe5\x1c\x19\x10\xba\xf4\x5a\xa0\xe8\xd2\x9f\x2b\x71\xd2\x1e\x01\xa8\xbe\x28\x03\x54\x8b\x08\xda\xf3\x15\x80\xf5\x33\x49\xc0\xac\x4b\x7e\xa2\x8f\x6a\x52\xf8\xdc\x3d\x95\x80\x61\x70\xf8\x34\x70\xfa\xcf\xdd\xde\xe9\xdf\x07\x4e\xff\x3e\x38\x2c\xa3\x76\x49\xe8\x3a\xbe\x21\x05\x1f\x60\xea\xba\x53\x85\xbb\xfe\xad\xfa\x02\x77\x74\x52\x41\xb2\xdd\xb3\x5a\x6c\x14\xbf\x6d\x61\xdc\xdf\x2b\x38\xb1\x9b\x0a\xc6\xbd\xc2\x62\x67\x30\x14\x12\x24\xfb\x46\x2e\x3a\xe7\x1b\x00\xb1\x13\x74\x50\x85\x5a\x97\x4f\x0d\x70\x96\x04\x9c\x69\xe6\x20\xd0\xb1\xcb\x09\xc7\x37\x5c\xf7\x36\x3f\xb1\xd7\x5e\x98\x69\x37\x35\xa0\x0b\x53\x9e\xe5\x41\xa9\x1d\x75\x02\x22\xf0\x0c\xf9\x51\x9c\x68\xd7\x37\x8f\x76\x84\x88\xa4\xe3\xd0\x0a\xe2\xad\xb7\xf6\x5b\xd2\xb2\xfb\x78\x5f\xac\x2e\x5d\x2e\x4a\x27\x0d\xe4\x08\xc1\xeb\xe0\xd0\xbb\x46\xf0\xe5\x7b\x3f\x66\xe1\xf0\xd7\x76\x3c\xc7\xe1\x5f\xdb\xef\xe9\x46\xfd\x9e\x6f\xd8\xef\x69\xa5\xdf\xd3\xa7\xf7\x3b\xe9\x12\xdf\xea\xd6\xba\x7e\xff\x00\x77\xae\x7b\xc7\x5b\x72\x25\x38\xa0\x45\x91\x39\x51\xf8\x7c\xef\x0d\x7c\xbe\x37\x26\x80\xfd\x37\x09\xd6\xf7\x56\x83\xf5\xbd\x36\xc0\xfa\xbe\x6c\x02\x60\xff\xd9\x06\xb0\xbf\x71\x5d\xbd\xce\xd9\x00\xf6\x57\x25\x00\x7b\x89\xb9\xaf\x97\xb1\x2a\xa6\xfd\x0d\x07\x72\xbb\x61\x21\xe4\x2b\x31\xed\xad\x66\x18\xae\x65\xe5\x11\xc7\x6b\xa1\x81\xf0\x1d\xc1\x42\x12\xc5\x84\x2d\xf1\x0b\x38\xb0\xbd\xdf\x9c\xb8\x2e\x13\x23\x82\x20\xf8\xe0\xba\x61\x8b\xab\x21\x45\x8f\xf4\x51\x99\x13\x5d\x87\x83\x7e\x28\xe0\x9e\xc7\xd6\x9e\x14\x90\xd6\x30\xb7\x95\xfd\xa0\xc2\x16\xd5\x48\x66\x38\x65\x2f\x9d\x6d\xe0\x39\xa5\xde\x38\x21\x84\xf9\x61\x21\x85\xa5\x8f\xd3\x95\x58\xfa\x79\xba\x01\x85\xd0\x44\x4e\xb8\x1a\xe5\xeb\x31\x46\x36\xfe\xae\x63\x72\xef\xd8\x7c\x94\x55\x12\xb8\x02\x78\xee\xbe\x45\x2a\xaf\x18\x04\x44\x35\xfd\x85\xcd\x2f\xa5\x1e\xb0\xfa\xdb\x54\x54\x65\xf1\x55\x48\x2e\x54\x84\xc5\x29\x02\x92\xaa\xb8\x39\x49\xf4\xb4\x28\xf8\x5e\x9c\xa6\x01\xf1\xb6\x5f\xbc\xd8\x43\x90\x6c\x20\xb9\x72\x71\x55\xca\xae\x91\x21\xbb\xc6\x96\xec\xca\xe0\x5e\xf8\xe1\xcb\xf1\xfd\x2c\x24\x43\x3c\xac\xa5\xa2\x57\xc7\xa1\x43\xfd\x70\xe0\xba\x5c\x3c\xc5\xf2\x4d\x81\xf7\x32\x09\xc9\x98\x03\xbe\x08\x72\xfb\x3a\x98\xb8\x3a\xe9\xd0\x02\x7f\xc9\x53\x01\xfe\x52\x06\x6f\x59\xcd\x06\x54\x2f\x31\x96\xea\x67\xbb\xaf\x60\x7d\x57\x96\xdc\xa4\xc1\xaf\x47\x2b\xaf\x01\x26\xbf\xa3\x85\x4a\x53\x85\x7f\x9a\x26\x31\x67\x49\x94\xde\xed\x73\xe0\xdd\xce\x8a\x91\xd1\x57\x43\x82\x63\x07\x98\x3f\x9c\xaf\xcb\x51\x20\xb8\xd7\xc2\xce\x1d\x15\x76\x8e\x83\x7b\x2a\xec\xdc\x04\xf7\xbd\x4e\x5f\x52\x05\xd5\x03\x9a\xdd\x78\xcd\x63\x05\x3e\xd1\x3c\x66\x30\x66\xc7\x30\x83\x1b\xe6\x5d\xe3\x25\x26\x26\x4a\x9e\xb0\x08\x2c\x2f\x64\xf8\x25\xef\x98\x27\x5a\x82\x96\x4b\xaf\x0d\x7f\x9a\x17\x7f\x98\x17\x3f\xb3\x0b\x84\xe0\x53\x70\x44\x0b\x75\x1e\x1c\xb5\xb2\x38\x1a\x60\xaf\xa3\x64\xdb\x53\x3c\x4d\x6a\xa4\xcf\x85\xac\xa3\x7f\xac\xcf\x28\x86\x90\xb3\x98\x4b\xff\xb2\xe0\x65\x1d\xc2\xe5\x6a\x46\x4d\x13\x41\xb5\x66\x09\x8d\xf8\x12\x1a\xc3\xb1\xeb\x46\x7a\x58\x0e\xe9\x95\x1a\xc1\xcd\x29\xbd\x14\xdc\xf9\x02\x67\x40\x52\x5c\x4f\x19\x80\x53\xc5\xdf\x33\x6d\x9d\xa7\x09\x0b\xa1\x94\x31\x11\x17\xb5\xc8\x21\x63\x6b\x9f\x3b\x2e\x6d\x1a\x05\x3c\xac\x5c\x70\xb9\xdf\x00\xb3\xfa\xc4\x78\x78\xfd\xe0\xf8\x9f\x84\x33\x48\x34\x84\x68\x28\xaf\x7a\x3c\x9d\x18\x60\x99\xd3\xe7\xe0\x0d\x4e\x8a\xc7\x51\x42\xd7\xa4\x73\x0b\x16\x36\x5c\xb1\xa8\x72\xc1\x66\x73\x46\x4a\xfb\x84\x5b\x23\xca\xa6\x38\x66\xf0\x84\x9b\x9c\x05\x73\xf3\x8e\xd3\x87\x9c\x69\xfe\xd7\x78\x94\xa4\x54\xe1\xaf\xc3\xa7\x15\x04\xc2\x79\x32\xf3\xb7\x3a\x65\xfa\xe0\x8e\xf2\xd0\xfc\x3f\x8e\xf3\x7f\x40\x13\xa8\xad\x3e\x48\x13\xf1\xaf\x1b\x94\x52\xb1\x12\x55\xcf\xae\xfb\x0c\x24\xc0\x71\x7d\x06\x54\xba\xc5\x96\x1d\x87\x9d\x9e\xa8\xba\xa8\x8d\x40\x12\xb8\x39\xee\x33\x35\xb1\xa5\x85\xdd\x77\x3a\xfb\xb3\xfb\x46\xdb\xa9\xe6\xa5\xf9\xeb\xda\xec\x4b\x71\x58\x79\x28\x50\x29\xf8\x73\xf5\x61\x45\x8a\x63\x7f\xb3\xf1\xbc\xe1\x6e\x50\xc4\x35\xbc\x9e\x2b\x39\x3c\x5f\xab\x84\x45\x01\x62\x32\x29\xaa\x66\xee\x36\xd0\xae\x56\x50\xf1\x1c\xbf\xc7\xa3\x5c\x24\x63\x47\x80\x33\xdc\x32\xdf\x05\x95\x90\x59\x07\xd7\xa4\xac\xb6\x93\x49\xf2\xbc\xd9\x67\x78\xda\xc7\xbe\x04\xce\x7f\x66\x5c\x72\xc9\x1a\xde\xd6\x34\xdb\x8a\xa6\x78\x8b\xb9\x64\xf8\x8c\x86\x16\xad\xfe\x76\x7b\xe5\x87\xda\x54\x49\x55\xeb\xe2\xc2\x3a\xbc\xb5\x65\x85\xd2\xbe\x51\x20\x2f\x49\xb9\x68\x10\x6d\x68\xc9\xfa\x7e\xf6\xc9\xbf\x4e\x35\xb9\x82\x37\x72\x13\xa1\xaf\xc4\xde\x59\x75\xc5\xee\xc0\x36\x6c\xa3\xb5\xcd\xf5\x06\xe7\x61\x14\x67\xb4\xd5\x22\xd1\x6a\xd9\xdf\x6a\xff\xe3\x5d\xc8\x9c\x1b\xa9\x48\xa5\x69\x42\xb9\xc8\xc2\x99\x15\x5f\xc7\xf3\x54\xd0\x2a\x72\x77\x60\xce\xa9\xc8\xc0\x9e\x7e\xe3\x32\x27\x8c\x9e\x28\xdc\xe8\x0f\x3b\xe0\x94\x3e\xcb\x64\x1a\xfa\xd1\x92\x5f\xae\xf9\x41\x2a\xbb\xcc\xf8\xb6\xcd\x23\x91\x9a\x1d\x04\x93\x60\x46\xf7\xf6\x69\x30\xa3\x02\xc7\xad\x4d\x3d\x4a\x52\x44\x05\x35\xbd\xa1\x3e\x68\xe9\x8e\xaa\xfc\x70\x1d\xdc\xea\xbd\xf7\x2e\xb8\x6d\xf1\x1d\x7e\x13\x96\x6c\x8b\x6c\xba\x23\x27\x83\x26\xa3\x56\xb3\xe3\x01\x4a\x2e\xba\xc2\xf3\x4e\xaf\xb6\xd7\x6b\x5d\x18\x1f\x2c\x1f\xbf\x6b\x7a\xa5\x8a\xcc\x60\x89\x58\x49\xa8\x7c\x60\x37\x97\xe5\x46\x37\xf5\x9a\x6d\x4d\x16\x07\xbc\xad\xcb\x29\x3a\x08\xe6\xae\x3b\x17\x29\x4a\x21\x43\x18\x2d\x84\xf6\x0c\x54\x9a\x56\x9e\x73\x69\x01\xa3\x0d\x94\x33\xa3\x5e\x32\xfc\xc2\xaa\x0a\xfd\x24\x82\xb8\x0a\x94\x90\x90\x47\x54\x51\x63\x3c\xdb\x39\x82\x81\xa6\x51\xee\x02\xe5\xe0\xc8\x02\x51\x98\x64\xc2\x43\x52\x58\xd7\x08\xbd\x89\x85\x85\x64\x08\x62\x73\x21\x98\xff\x5b\x04\x95\xd2\xca\x61\x21\x3e\x6d\x20\xb0\x44\x64\x6b\x22\x6d\xcc\xb5\xd2\x40\xcd\x5a\xd4\x66\xb4\xb0\xe2\x60\xc3\x27\x49\xee\xa9\xdd\x95\xee\x0f\xe5\xf3\xb5\x8a\x84\xa0\x8a\xb8\xcf\x4e\xf9\x9f\x89\x61\xb8\xc9\xce\xcc\x92\x96\xf7\x73\x29\x18\xac\xdc\xc7\xc5\x61\x70\x69\x17\x12\x9f\x2d\x6d\x48\x3a\x34\xa6\xd4\xb2\x46\xa4\xcc\xd3\x04\x41\x25\x11\x6d\x4b\x89\xa8\x4e\x5e\xda\x6e\xb3\xa7\xaa\x8c\xfc\xb0\xd3\xe0\xcb\x4d\x13\xb6\x74\xb5\x87\x78\x8c\x36\x30\x05\x18\x2c\x92\xf9\x5a\xb2\x75\x9b\xa1\xba\x54\xba\xea\xf7\x3b\x2f\x79\x09\xca\xa7\x54\xf6\x5e\x74\x39\x9f\x4e\x39\x72\x8a\x97\x89\xbd\x68\xb0\xe1\x5e\x84\xe3\x58\x9c\x2f\x99\x78\xae\xdd\xce\xcb\xb6\xff\x08\xa4\xab\xde\xad\xe6\xfc\x64\x4a\xc3\xe2\x05\x41\x30\xef\x6e\xfb\x1c\x17\x4f\x1f\x46\x59\x68\xae\xce\x3c\x76\x04\x9e\xab\x18\xe9\x30\xd1\xcf\x67\xdd\x5d\x7f\xc6\x4e\x9d\xf8\x31\x51\x19\x0f\x4f\x15\x7b\x33\x1e\xb3\x38\x2b\x1d\xe2\x88\x4f\xaa\xc3\x96\xd5\x02\xc9\x68\xed\xb2\x16\xf3\xd5\x3f\x53\x4a\x5f\xc9\x4a\xc6\x87\xdb\xd6\xe4\xc7\xed\x02\xa6\xa8\x80\x5b\xba\x04\xaf\x84\x10\xe5\xe7\x16\xcd\x8a\xe3\x3f\x41\xc8\x08\x91\xe5\xc6\x1b\x0e\xc1\x31\xcb\x58\xcb\x2f\x97\x1d\x46\xc2\xca\xef\xa4\xc9\x1d\xbd\x73\x50\xcf\x83\x49\xa0\xcc\x7f\x29\xcc\x49\xca\x2c\xdb\x69\xb7\x7f\x1c\xfc\x47\x0a\xce\x0f\x0e\x02\xcb\xa2\x15\x04\x41\x28\x61\x70\xc3\xff\x48\x9e\x4f\xd4\x7a\xc5\x6a\x48\x2c\xe2\xcb\x82\x85\xf9\xe9\x15\x79\x98\x96\x19\x45\x6a\xe6\xfc\xef\x69\x38\xf3\x1d\xee\x0d\x5c\xe1\x14\x89\x23\x81\x24\x5a\xf5\xd6\x7d\x0c\x5d\xd2\x04\x93\x7c\x97\x46\xcc\xcc\x4b\xe7\xcb\x40\xcc\x97\x51\x99\x8f\xcc\xc0\xaf\x38\xc0\x9c\xc1\x6c\x3a\x8b\x71\x8e\x19\x38\x27\x67\xbb\x94\x16\xeb\x7f\x62\x9b\x9c\xcc\xa4\xd4\xfa\xb1\xfe\x19\x1f\xbd\x5d\x8f\x91\x6b\xb0\x81\x45\x4b\x84\x04\x21\x8f\x80\xda\x60\x5b\xea\x39\xe6\xf1\x7c\xd1\x74\xfc\x76\x1e\xc7\x2c\xd3\x56\x36\x8b\xa3\x9c\x71\x5b\x22\x04\x5e\x6a\xe7\x11\x0e\x87\x22\x83\xb4\x26\x03\xfe\x65\x2b\x07\xe4\x7b\x5e\xb2\xa6\x1c\xc9\x66\xd9\x80\x17\xae\x2a\x48\xb8\x51\x4d\x10\x2a\x60\xf6\x37\x0a\xd1\x9e\x58\x97\x8c\x45\x08\xad\x80\xf8\xf4\x08\x9b\x36\xf0\xe4\x93\xe3\xf2\xca\x42\x73\x71\xfa\x08\xc1\xa0\x74\x9c\xf9\x18\xe1\x6f\xb3\x74\x94\xc5\xc6\x99\x1c\x74\xdd\x51\xca\x6e\xfb\xb8\x86\xeb\x29\x4e\xc2\xa1\x63\xc5\xe0\x8b\xd4\x6c\xfe\x79\x03\x0d\xd0\xae\x69\xad\x6a\x0a\xb0\x86\x74\x6a\x94\x96\x73\xf9\x2f\x23\xa0\x42\xd0\x0b\x6b\xd8\x8d\xb3\x4d\x0e\x3e\x22\xa5\x23\xce\x37\x3a\x97\xc8\x23\x0e\x5f\x66\x2d\xd0\x09\xd4\x28\x92\x8d\x1a\xa0\xe9\xae\x13\x4d\xc7\xdc\x4b\x2d\x7f\x98\x61\x66\xdb\xfc\x9d\x15\x07\x43\xcf\x39\x99\x86\x63\xba\xcf\xac\x40\x85\x1e\x14\xc8\x97\xac\x1e\xd6\xaa\x39\xa9\xac\x9a\x2b\x22\x10\xec\x50\x64\x5a\x95\x7a\xbb\x9a\x5a\x74\xaf\xe3\x84\x6a\x6f\x72\x81\x67\xa7\x09\xd5\x63\x90\x02\xac\x09\xaf\x8f\x38\x78\x7a\x43\x64\x61\x3f\xe3\x30\xc7\x7f\x78\x5b\x7b\xed\x1f\x90\x03\x75\x9f\xe7\xac\x75\x7b\xed\x1f\x74\xce\x9c\xfb\xc9\x3a\xd5\xa8\x7d\xb5\xee\x5b\x7f\xca\x6f\x31\xbe\x3c\x96\x6d\xdd\x52\x7f\x15\xc5\xec\x48\x64\x26\x96\xfb\xe9\x5f\x33\x70\x90\x56\x1a\x46\x19\x1e\x2a\x62\xdf\x66\x10\x44\xae\x1b\x41\xb6\x09\x6e\x2f\x7f\x77\x8d\xcc\xf1\x88\x4d\x5a\x5b\x40\x34\xe5\x57\xdc\x7d\xe9\x77\xe4\x68\xcf\xcc\x01\x74\x5b\x19\x40\xd5\x3e\x36\x9b\xec\x28\x4c\x87\xb4\xa9\xa6\xa2\xa9\xc6\x7f\xb5\xa9\xb4\x00\x68\xd1\x20\x73\x6f\xa4\x0d\x9b\x6c\x60\xb8\xbd\xac\x6a\xb5\xf8\x69\x66\x23\xab\x91\x1e\x2a\x8d\x24\x45\x8b\xce\x7e\xc5\x1c\x68\xa3\xf9\x6e\xef\x16\x95\xf6\x13\xb1\x53\xb4\x19\xc7\xa2\x19\xaf\x37\x6b\x46\x93\x4e\x9a\x87\x9d\xae\x3f\x69\xd3\x8d\x5b\x0a\x3d\xa7\x8d\x6b\x1d\xb4\x69\xdc\xc4\xda\x13\xb7\x6c\x7e\x3d\xc1\xe1\x10\xa7\x5c\x24\x97\x57\x25\xb4\x45\x76\x04\x97\x47\x79\xcc\x99\xa3\xd9\xaf\x72\x92\xdb\x55\x64\xc5\x8f\x44\x8b\x57\x7d\xac\x74\xce\x54\x50\x97\x45\x32\x7f\x97\xbe\xcd\x9c\xa6\x72\xe1\x3c\x55\x2d\x9a\xd3\x47\x30\x0e\x26\x07\x1c\x68\x66\xbc\x5c\x8e\xd9\x4a\x1d\x04\xc1\x3b\xbc\x5c\x0e\x97\x4b\x6f\x1c\xd4\x80\x52\xa8\x61\x25\x71\x3f\xc2\xae\xc3\x50\x91\x1d\xdf\x99\xec\x39\x86\x55\x28\x12\x6d\x63\x98\x31\x78\x4c\x62\x69\xd1\x65\x61\x87\x63\x11\xf8\xfb\x10\x8c\x0e\x2c\x04\x9c\x87\xe5\xf2\xa1\x5c\xb0\x87\xa7\x16\x8c\x81\x53\xdb\x65\xd3\x5d\x2c\x3c\x90\x73\x7c\x9f\xeb\x70\xab\x0d\x4a\x3d\x43\xf0\x50\x13\xfe\x3b\xdf\xe8\x08\xcd\x00\xe0\x86\xb0\x6a\x40\xaa\xec\xc7\x91\x98\x01\x05\x9d\xb4\x1b\xa4\x16\xa6\x84\x02\xc6\xf0\x80\x20\xd9\xec\x0b\x6c\x70\x32\x8f\x02\xbd\x18\xdc\x3d\xa6\xa8\xd4\x45\x4d\xea\xf5\x42\xfb\xc0\xd3\xd4\xbe\xd3\x6e\xb4\x1b\x5c\x7f\x31\xbd\x93\x59\x3a\xf6\xf5\x6a\x3a\x96\xff\x25\x8e\x47\xfc\x83\x5b\x59\x1e\xa6\xb9\x7c\xfd\x2a\x99\xf9\x5b\x2f\x6d\x5f\xf4\x97\x25\x8c\x11\xdf\xe9\x34\x3a\x0d\x71\x44\xc8\x86\x24\xc3\xfc\x96\xfd\xef\x2f\x2a\x2b\xd6\x4f\x7c\x6a\x15\xc8\xbb\x4e\x11\xdc\xa7\x81\xf3\xff\xc3\x03\x3c\x1a\x75\x1c\x38\xa6\x17\xbb\x7b\x7b\xe1\xfe\xae\x03\x37\xf4\x62\xf4\x6a\x74\x8d\x5f\x38\x70\x49\x2f\xc2\xd1\xf5\xee\xf6\xb5\xc3\x19\x69\xd2\x80\x78\x2f\x77\x76\x76\x11\x7c\xa2\x3f\x77\xf6\x5e\x76\x10\x9c\xff\xf5\x1d\x24\x4e\xd2\xd2\xee\x31\x93\xc1\x88\x9c\x2b\x9f\xe3\x1b\xce\xe5\xaf\xd7\xf3\xd1\x08\x73\xcb\xb8\x04\xb5\xb0\x5d\x61\x23\x32\xc4\x39\x4e\xa7\x11\x09\x73\xcc\x9d\x62\x37\xda\x86\x78\xc8\x29\xfb\x86\xfc\xcb\xbf\x65\xc3\x4e\xcc\xb8\x67\xe6\x24\x58\x14\x30\x0d\x16\xd7\x61\xda\xa1\x3d\x70\x1d\xa6\xdb\xb4\xf1\x0f\xa2\x91\xe7\x39\x66\x09\x82\x20\x18\x2e\x97\xce\x35\xcf\x8b\xb1\x2b\x1b\x84\xd2\x19\x5a\x4c\xc4\x41\x2d\xfb\x24\x49\xee\x9c\x7e\x60\x30\xfe\x66\x08\xac\x04\xd3\x88\x38\xfd\xa0\x5d\xba\x19\xde\x3b\xfd\xa0\xd3\xe6\xbc\x8f\xb7\x41\xb6\x45\x7f\x4b\xce\x8c\x99\xe6\xcc\x70\x5d\xef\x36\xd8\xba\x45\x30\x6d\xd1\x92\x6b\x02\xde\xc0\x14\xf2\x94\xbd\xe0\x16\x9c\x1f\x90\x83\x8a\x68\xe4\x99\x15\x30\xca\x3f\x97\xac\xc7\xde\x7c\xb9\x6c\xa3\x35\xdf\x1d\x07\x5b\x63\xf1\xdd\xed\xc7\xbe\x3b\x16\xdf\xfd\xab\x47\x49\xc9\x4a\xb0\x81\x18\xa1\x3e\x84\xb0\x30\x7a\xca\x4f\x5a\xc6\x15\x58\xe3\xc8\x4f\x5a\xd6\x35\xf0\xd6\xf0\x93\x16\xff\x01\x5f\xe7\x98\xe1\x6a\xb1\xbf\x45\x6f\xd8\x47\xe2\xb4\x7d\x96\x26\xe3\x14\x67\xd9\x75\x98\x3a\x05\x4c\xb8\x4e\xc0\x4d\xf6\x66\x93\x76\x37\xb7\xdf\x27\xad\x61\x98\x4d\xf0\x90\xd6\x8e\xff\x5a\x01\x7d\x10\x73\x50\x07\xbf\x16\x7f\x6a\x5d\xfe\xd7\x61\x4a\x33\xbf\x5e\x09\x6f\xc1\x5a\xcf\x2b\x4d\x35\x31\xd0\x59\x0b\xc8\x71\xce\xf2\xea\x9c\x58\x4d\x57\x6a\x73\x9a\xe0\x4d\x6d\xcb\x86\x69\x87\xcf\x40\xde\x9e\xdc\xb6\xc5\x07\x6e\x81\xa0\x32\xc9\xb8\x8f\xdd\x53\xeb\xb9\x71\x2d\xb6\xed\x5a\x58\x9d\xd7\x7b\x64\xa0\xf1\x0c\x78\x65\xfa\xfe\xa3\x4d\x6b\xd5\x75\xbb\xb0\xc8\x59\xd6\x1e\x7e\x54\x61\xba\x56\x46\x58\xf1\xb8\x8b\x67\x84\x45\x93\xee\x6f\x23\x19\xbe\xf9\x85\xdd\xd8\x43\x05\x90\x60\x75\x38\x5e\x1a\xac\x09\x5c\x7b\xdc\x03\xa4\xea\x92\x27\x74\xcf\x5d\x70\xfe\x73\x8a\x87\x51\xd8\x98\xa5\x11\xc9\x65\x8c\xc7\x21\xa3\x1a\xf2\x1d\x7c\x1f\x0e\x72\xaa\xd4\xac\x0f\xb9\x26\x8f\x07\x4e\xa7\x05\x98\xc3\x70\x51\x94\xe6\x3b\x5d\xd2\xf9\x40\x7c\xcc\xd0\xcf\x67\xfe\x3a\x0b\x3f\xf0\x59\x5a\xef\xbe\x62\xb8\x71\x94\x14\x76\x4b\x6b\x0e\x49\x34\x15\xe0\x06\xcf\x78\xc1\x1a\x3b\x59\x23\x22\xa3\x88\x44\x39\x6e\xc4\x11\xc1\x6c\x81\x31\x16\x84\x9a\xe6\x61\xa6\x0a\xdf\x49\xc3\x61\x14\xc6\x5b\x63\xfa\x97\xcd\x11\xc3\x6d\xb7\xd1\xfe\x01\x1a\x0e\x32\xef\x74\xf6\x7f\x80\x86\x51\xe9\xc6\xee\x36\x5d\x9d\x0d\x1f\x1a\x16\x37\xef\x74\xda\xb3\xfb\x06\xfd\xcf\x31\x1e\x29\xda\x74\xa7\xdd\xd8\xda\xde\x99\xdd\xdb\x85\xac\xed\xa2\xc7\x8a\x99\x56\x8a\x99\xfe\x3b\x8a\x79\x1d\xa6\x2b\x6d\x17\x15\xff\xa3\x6b\xe1\x6b\xc3\xcc\x15\x6d\xf3\x5c\x49\x1f\x21\x35\xda\xad\xed\x4c\xf6\x55\x95\xe2\x4a\xf0\xf5\x5d\x97\x63\x29\x37\x43\x14\xd0\x2f\x7e\x07\x5e\x00\x7b\xd9\x5e\xa7\x55\xd5\x85\xe4\x6a\x0c\x40\x6b\xaa\x74\x1a\xdb\xad\x4e\xd6\x18\xcc\xaf\xa3\xc1\xd6\x35\xfe\x16\xe1\xd4\x6b\xb7\xf6\x59\x80\xf5\xcb\x0e\xfb\xf3\x62\x87\xfd\xd9\x79\xb5\x87\xd4\x90\xe5\x15\x35\x57\x7e\x31\x87\x2a\x8d\xd6\x52\xfd\xbe\x0b\x8e\x6a\x3e\xc4\xdf\x7f\x2d\x26\xe9\x37\x7e\x98\xdc\x59\xd1\xf0\xeb\xf2\xd8\xfe\xae\x6a\x6f\xd7\x56\xbb\x23\xea\xbd\x4b\xff\xdf\xdd\x85\x46\x07\x35\x3a\xad\xce\x5e\x56\xaa\xf7\xb6\x2c\xf7\x13\x8b\xeb\xfc\xe7\x0d\x7e\x18\xa5\xe1\x14\xd3\x1c\xcd\x5e\x70\xfc\x85\xd3\xfe\xc1\xf1\x17\xdc\x0c\xb7\xb5\xb3\xf7\x83\x23\xbc\xe1\x84\x3b\x31\x38\xfb\x46\x02\x3e\xa0\x45\x82\xad\x57\x3c\x01\xbb\xb9\x26\xc5\x9a\x02\x6c\x97\x0b\xb0\x6d\xbe\x5e\x5f\x82\x17\x46\xfe\x2f\xeb\x0a\x50\x4e\x60\x7f\x5f\xec\xc0\xf2\xbb\x75\xce\x7d\x75\xd3\x9a\xd9\x12\x0d\x37\xb8\xc7\x92\x8b\x32\xad\xcf\x9e\x56\x77\x76\x2f\x5f\x2a\x9d\xe9\xbe\x67\xfd\x77\x2e\x24\x41\xc6\x76\x26\x6c\x47\x67\x54\x97\xda\x7f\xb1\xb3\x87\xe0\x8a\xff\xdc\xdb\x43\xf0\x21\x0d\xb8\x2f\xbf\xcf\x63\xe5\xb0\x08\x75\xb8\x1c\xa4\x18\x13\xe6\xd4\x2f\x9e\xc4\x38\xbc\x55\x0f\x0a\xf8\xbc\x99\x3e\xf6\x3a\x1c\xdc\x0c\x53\x8e\x86\x97\x3d\xc9\xfb\x9b\x5b\x6f\xe4\xfb\xdc\x31\x69\x8d\x0b\x38\xc7\x83\x92\xa8\x85\x75\xc6\xa9\xd1\x3c\x8e\x45\xb5\xea\x02\x14\x47\xd2\x88\x5c\xeb\x16\x3e\x0d\xef\xf9\x43\xcb\x17\xdc\xc9\xa6\x8e\xf0\x06\x4f\x88\x5d\xd4\x6b\x83\x63\xf4\xce\x08\x7c\xbc\xb7\x02\x1f\x8f\xed\xc0\xc7\x1b\x7e\x69\x55\xe5\x52\x07\x43\x1e\x99\xc1\x90\x9f\xac\x60\xc8\x73\xc9\x5b\x7a\x21\x79\x4b\xb5\xfb\xfa\x99\x2e\xf2\x45\xf7\xcf\xdc\xbf\x80\x2b\x9b\xdc\xf4\x83\x4e\x70\xd5\x5d\x14\xfe\x15\x7c\x0e\x48\x2b\x63\xe7\x9f\x70\xaa\x1f\x7e\xee\x3a\x0c\xd2\xd6\xf1\x3f\xc3\xc9\x0a\x5f\xf9\x43\x9d\xfc\xa4\xfb\x2c\xf7\x4f\xe0\x7d\x3d\x2b\xea\x37\x9d\xf0\x7d\xf7\x43\xea\xbf\x87\x37\x35\x4e\xf5\x6f\x03\x22\xb4\xcf\x21\xce\x06\x69\x74\xcd\xbc\x90\xfb\xf0\x5a\xdd\x37\x9c\x93\xfb\xf0\xc5\x56\xc0\xad\xd1\xb7\xc9\x29\x7f\xdd\xa8\xd3\xb7\xad\x8e\x71\xc0\xd1\x23\x4a\x5c\xb0\x21\xe2\x80\x23\x47\x0b\xf7\x74\x2b\x65\x56\x61\x49\x7d\x24\xcc\xb3\xf4\xd1\xc7\x02\x3f\x4d\xb6\x55\x33\x38\xc0\xa2\x5f\xe5\x7d\xbb\x32\x90\x60\x43\x32\xd6\x4a\xbf\x40\xb5\x4b\x10\xfc\x6e\xc4\x8e\xae\x8c\xc4\xda\xcc\x81\x1e\x81\x6a\x4c\x65\x66\xfc\x2d\x07\xab\x9b\xb5\x4b\x42\x0d\xb3\xe6\x37\xe6\x79\x36\xa0\xed\x7f\x38\xca\x71\xaa\xeb\xc4\xfc\xbf\xe6\xdd\x45\xdd\x08\xf0\xe7\x0c\x69\x73\x51\x37\x0c\x18\xfd\xb7\x7d\xe7\x46\xd1\x27\x5d\x73\xb4\xe7\x73\x69\xb4\xfc\x52\xb5\x41\x1e\xea\x8a\x87\xb3\x19\x0e\x53\xbf\xd9\x86\x88\xbe\x23\xbd\xf4\xbf\xa9\xb8\xb4\x3b\x33\x16\xed\xd8\x08\x52\xbb\x97\x71\x69\x97\x46\x30\xda\x27\x1d\xa3\x76\x24\x2c\x04\x24\x21\xb8\x31\x4b\x71\x86\x49\xce\xbb\xb5\x80\x37\x4f\x71\xe8\x8b\xcc\x28\xb0\x9e\x1c\x46\x15\xcd\xf2\x94\x69\x96\x09\x39\x4d\xe6\x19\xae\x80\xfc\xe5\x1a\xdd\xcf\xc2\xfb\x73\x5d\xe3\xd9\xef\x1a\xce\xcf\x53\xbf\x19\xba\xa5\x0c\x91\x84\xe6\xdc\x75\x39\xb0\x1f\x77\x84\xd3\x93\x0c\x31\xa7\x46\xf6\xf5\x0a\x6e\xa1\xce\x4c\x7e\xad\xa8\x46\x8f\x9d\xe9\x5e\xd1\xc7\x63\xdb\xbb\xa2\x19\xa9\xae\x90\x8c\xeb\x26\x80\xff\xb6\x3a\x05\xfc\xd7\x05\x7c\x58\xd1\x9a\x6c\x39\xa5\x2d\xc9\x7e\x5c\xae\x69\x4e\x95\x88\x2f\x2c\x95\x34\x02\x59\x7d\x8c\x68\xda\x0f\xc6\x66\x3a\x73\x5d\xf1\x9d\xb7\x7a\x03\x9c\x5a\x37\x59\x96\xa8\x40\x10\xda\xc7\xc6\xa7\x9b\xf8\x41\x97\xb5\xe8\xaa\xe2\xd2\x68\x46\xd3\x59\x92\xe6\x21\x61\x0a\x35\x1f\x34\x02\xe0\xba\x64\x14\x5f\x05\x1b\x58\x63\x2c\x97\x19\xbd\x4e\x86\x0f\xfa\x38\xf2\xcf\x72\xd8\xdc\x1f\x36\x10\x8a\x00\xe2\x93\xf9\x3a\xae\x1f\xd2\x75\x80\x69\xff\x46\xf4\x46\x19\xe8\x50\x1c\x73\xaf\x80\xf3\xab\x55\xa6\xdb\xdc\x78\x20\x66\x4b\xf9\xc8\xbb\xdc\x6a\x96\x87\x54\xa1\xf1\x06\x0b\x50\xbc\xb8\xcc\x0b\x6c\x67\xbb\xf6\x54\xbb\x52\xfd\x72\xfe\x46\x02\x19\x46\x08\x1a\xee\x4c\x45\x5d\x18\xc3\xb0\xbe\x83\xe8\xff\x6f\xa4\xa9\xd5\x77\x06\x49\x3c\x9f\x12\x07\x56\xb0\xf6\xee\xef\xce\xee\x91\x63\x65\xcb\xbb\xeb\x69\xed\x6b\x74\x9c\x50\x5c\xf5\x4c\x78\x1b\xc6\x19\x66\xb4\xc1\xdc\x03\x60\xf5\xf7\xd9\xf3\x3f\x32\x23\x2d\xb3\x7d\x4f\xc3\x7b\x0f\x5b\xfc\xa7\xcc\xce\x9d\xb5\xee\x33\xd8\xdd\xdd\x45\xe0\xb8\xcf\x4a\xe5\x77\x7c\xcd\xd7\x5a\x80\xfd\xf2\x30\xb9\x23\xde\x46\x19\x3f\xdf\xdf\x45\xb0\xbe\xe0\xc8\x2c\xfa\xe5\xd4\x28\x7a\x6d\xc6\xd9\xf4\x7b\x0a\xbb\x22\xab\xa7\x16\xef\x74\xf8\x58\xf1\xa6\xc3\xbf\xad\x78\xd3\xe1\x53\x8b\xf7\x7e\xfc\x58\xf1\xe2\xf1\xdf\x56\xbc\x78\xfc\xd4\xe2\xfd\x11\x3f\x56\xbc\xfb\xf8\x6f\x2b\xde\x7d\xfc\x84\xe2\x55\x9d\x6b\x56\xce\x30\xbd\xc1\xa8\xf5\xaa\x6d\xdb\x16\xf5\x17\xf9\xb5\xbd\x28\x1a\xab\x88\x09\xab\x6a\xc4\x6d\x55\xeb\xaf\x3f\x54\xca\xbb\xac\x19\xbf\xe1\x9b\x76\x81\xbc\xcf\x42\x23\x3e\xf9\xab\x47\x8a\x22\x7e\x2f\xfb\x3e\x0f\x1e\xf9\xf6\xdf\x12\xc8\x04\xb1\xeb\x26\xaa\x40\xf5\xfe\x29\x87\x9b\x6c\xe7\xa5\x93\xdf\xc7\x7c\x62\xab\x3b\x8f\x3c\xc3\x76\x5e\xce\xee\x1b\xdb\xbb\x02\x97\xcb\x8e\xb7\x33\x78\xad\xb7\xdb\x45\x21\x89\x40\x33\xed\x31\xc3\x83\x11\xf9\xeb\x2a\xe8\xee\x11\x50\x3b\x91\x0b\xb2\xa2\xda\x36\x7c\xa7\x76\xb0\x18\x1e\x38\x27\x62\xcc\xbc\x5f\x3f\x66\x56\xf4\xa3\xe9\x66\x61\x38\x48\xcc\x1c\xcd\x02\x23\x5d\x2d\x6a\x9d\x2a\x44\x6f\x12\xb3\x37\xbf\x55\x1c\x0c\xac\x48\xcc\xce\xb6\x75\x3c\x6f\x55\xe8\x0a\xdf\xb3\x4a\xbd\x17\x95\x7a\xf3\xb7\xc6\x9c\x55\x5d\x85\x32\x3d\x3d\x62\xd7\x65\x9e\xb2\x4f\x8b\x94\xaf\x78\xf2\xfc\x95\x29\x53\xe7\xd7\x99\x75\x93\xca\x71\x1e\x63\x92\xd1\x9d\x35\xd9\x36\x7a\x6b\xb2\xef\x94\xfc\x3d\xde\xae\xe8\x0e\xbf\x0d\x75\x63\xba\xe4\xad\x51\xd3\x57\x57\xcc\x07\xa9\x40\xde\x1b\xd1\x4b\xaf\xd3\x80\x78\x9d\x17\xdb\x2f\x10\x7c\xa9\x21\x36\xfa\x5f\xf6\xd3\xff\x11\xec\xa7\xbf\xa7\x7f\x91\xdb\x8e\x73\x7c\x9d\xcd\x30\xe1\xe3\xa8\x86\x7f\x8d\x18\x04\x6f\x5c\x97\x95\xdc\xd7\xed\x82\xd1\x68\x19\x8c\xcf\xdf\x91\x49\x87\x67\x22\x48\xf6\xca\xcf\x34\xb5\xde\x97\x74\x13\x72\x6d\x36\xba\x81\x40\x5a\xc3\xd9\x05\x89\x79\x33\x0e\xb3\x9c\xf5\x3b\x73\xa0\xb8\x3f\x1b\x79\xce\xff\x25\x8e\x5a\x29\x92\x7f\x06\xed\xae\x87\xeb\xdf\xc8\xe6\xd7\x59\x9e\x7a\x6d\x48\x90\xcd\x0e\x56\x49\x92\x3c\xef\x20\xe4\xaf\xc8\x07\x48\xe0\x38\x55\x83\xca\x63\x04\xd0\x49\x3d\xd5\xb2\xee\x44\xb1\x2f\x98\x2d\xc0\xdc\x99\xb8\x5b\x96\x73\x39\x49\xee\x1a\xb4\x10\x0d\x4c\x4b\xd1\x98\xe2\x2c\x0b\xc7\xb8\x86\x50\xec\x75\xba\x9a\x85\xf9\x34\x85\x45\x99\x13\xdc\xec\xbd\x95\xac\xe0\xa2\x8c\x5a\x00\x8b\xc7\x35\x9f\x7e\x9b\xf2\xca\xe3\x1a\x23\x58\x5a\xdf\x2e\xdf\x52\xd3\x6e\xc2\xd8\xda\x07\x37\x57\x69\x38\xc0\x6c\x33\x5c\x4d\xce\xf5\x6c\xbd\xa8\xa3\xf3\xf1\x17\x65\x7e\xac\x15\xe8\xec\x83\x70\x26\xc2\x19\xf9\x53\x4e\xa3\xf5\xbb\x58\x9b\x3f\xfe\xef\x82\xfc\x3f\x75\x41\xfe\x2d\x0d\x16\x03\xe5\xdc\x28\x2d\x53\x35\xfe\xef\x40\x53\x7d\x26\x09\x5d\x14\xd3\xbc\x0e\x73\xfc\x3e\x15\x89\xd2\x39\x21\x54\x22\xa8\xa4\xb8\x91\x29\xb2\xf9\x60\x80\xeb\xf2\x38\x4a\x5b\x9f\x7a\x7b\xed\xbe\x48\x37\x0a\xa3\xb8\x2e\xd9\x27\x95\x4c\x7a\x85\xbd\x0e\x4d\x23\x14\xbe\xa7\x32\xc7\x4f\x69\xf0\xe3\xff\xfb\x97\xe7\x75\xfd\xde\xff\xfb\x57\x7f\xf9\xaf\x7f\xa1\xe7\xe8\x5f\xff\xb7\x55\xbe\xf3\xec\x47\xf8\xba\x72\x5b\xd2\x1b\x02\xef\x78\x16\xe7\x56\xcb\x83\xcd\x77\x2a\xb9\xfa\x7f\xfc\x3b\x56\xff\x11\xb6\x19\x09\xaf\x63\x7c\x42\x46\x09\xa4\xad\x52\x67\xc8\x3b\xa2\xe5\xe5\xa5\x68\x66\x79\xc9\x5b\x13\x41\x18\x94\x73\xa5\x0b\x50\x6b\xca\x18\x6e\x7f\x4a\xd1\x41\xd8\xf5\x08\x23\xe6\x6d\xa5\x78\x16\x87\x03\xec\xfd\xf8\xaf\x7f\xfd\x38\x06\xe7\x5f\x0e\x02\x1c\x84\xbd\xed\xba\x27\xc8\xf7\xe8\xfe\x00\xb8\x36\x7b\x81\x9a\x11\x74\xda\xed\xff\xa8\xab\x54\xeb\xee\xc7\xda\xdb\xdf\x20\x0e\xf8\xe1\xcc\x08\xa7\x29\x1e\x36\xf2\xa4\x71\xc2\x0c\xae\x38\xf5\x1b\xce\xf3\xab\xb4\xb6\x8d\x5a\x77\x74\xb6\xfd\xb8\x26\xc1\xb7\x95\x42\xf6\xad\xb5\x2e\x27\x62\x1b\xaa\xab\x54\x75\x1b\xb8\x93\xef\xe2\x4c\x1b\x5d\x79\xfb\x5b\x53\x4c\xfa\x1c\x63\xc3\xe5\x98\x40\x9d\x47\xbe\xbf\x28\x6b\x51\x24\x61\x21\xa0\x2c\xa4\x7f\x85\x97\x7f\xe9\xa5\x6d\xeb\x25\xe1\x53\xfd\xe8\x36\x5e\xd7\x6a\xd3\xaa\xcf\xf8\xb3\x14\x16\x4a\x44\xa8\x34\x13\x7f\xab\x86\xcf\x93\x4a\x05\x5a\x01\x21\x18\xf2\xc4\x77\x7e\x64\xef\x74\xf3\xc0\x79\x8e\xc9\x20\x19\xe2\x8f\x17\x27\x6a\xfb\xab\xf4\x23\x1b\x57\x35\xc7\x1b\x5a\x0a\xa8\xa3\x62\x7d\x58\xb1\x1d\x5f\x94\xb6\x63\x63\x69\xd1\xaa\x91\xe9\xe1\x08\x1c\x95\x2a\x12\x5d\xc9\xc2\xd2\x56\x6d\xd9\xbf\xe8\x2d\xfb\xb7\x14\x79\x5f\xc5\xce\xfa\xeb\xff\xee\xac\xff\x53\x77\xd6\x77\x69\x8d\x5a\xf1\x2e\x95\xfd\x18\x66\x59\x34\x26\x66\x0f\xe8\xf6\xcf\x81\x91\xd9\x07\x6a\x73\x11\x24\xec\x07\xe4\x1f\xe9\x01\x79\xfe\x1c\xc9\x84\x09\xeb\x28\x9d\x8e\xb6\xff\x86\xbd\x96\xf0\x5e\x4b\x68\xaf\x25\xda\xe0\x80\x0b\x78\x97\xd6\x6f\x70\x05\xfc\xf9\xb7\x6f\x93\xbf\x6e\xbe\x4d\xd6\x6d\x91\x24\xe8\xf5\x21\x0d\x9a\x9d\x03\xbb\x45\x6c\x12\x5e\xe9\x2f\xd4\x12\x3a\x66\x58\x66\x06\xd6\x09\x7a\x49\xff\x20\x6c\x65\x36\xc5\x36\xd5\x15\xe6\x99\xeb\x7a\x84\x33\xc9\xf7\x12\x08\xfb\x08\x42\xba\x18\x7a\x69\xd0\x6c\x23\x54\x90\x56\x96\xa4\x79\x19\x6c\x57\x36\x2a\xdd\x4a\xa7\xae\xdb\xcc\xd9\x8f\xee\x56\xc7\xcf\xe5\x2d\xfe\xac\xdb\xf1\x71\xaf\xdd\xff\x47\xde\x6b\xf7\xe9\xe3\xe7\x1e\xbd\xfc\x27\xbd\x54\xec\x87\x11\x8f\x66\x18\xe0\x28\xf6\x44\x68\x70\x44\x88\xb0\xb0\xff\xb8\xd3\x6e\xaf\xdc\xd0\xc2\x14\x16\x25\x3c\x46\x73\x9d\x2e\x3d\xaa\x2e\xa8\xf3\x15\x2b\xa6\xcd\x46\x8c\x5b\xb3\x90\xe0\x98\x59\x76\x0c\x5b\xd2\x9e\x53\x58\x5b\x09\x7d\x5c\x5d\x94\x7f\x25\x74\x13\xb9\xc6\xb1\x4f\xc4\x60\x17\x4a\x61\xda\x75\x32\x4d\x77\xa5\x38\xcb\xea\x28\x16\xe3\x15\xc5\x1c\xa6\x76\x31\xc7\x22\xe2\x95\x7e\x21\xf3\x23\xd0\x50\x19\x7e\x67\x87\x61\x34\xd8\x54\xcd\x58\x99\x26\x7a\x6d\x3a\xdc\xb0\xe6\xf5\xaf\x34\xf5\x24\x85\xc5\x0d\x7e\x60\xfc\xdd\xa5\x47\xbf\xa4\xb0\x50\xdb\x16\xdd\xec\xe5\xf6\xe8\xa7\xdc\x33\xbd\x6e\xfb\x80\x3f\xfe\x9b\xcd\xb9\xf5\x96\x49\xab\x9d\xd3\x24\xc9\xab\xcd\xf0\x67\x0a\xef\x52\xaf\x32\x1e\x9b\x6d\xe0\xf3\xcc\x0f\x71\xeb\x42\xc8\xb1\xc2\x00\x70\xc8\x79\x0a\x6c\x4a\xf4\xef\xca\xf8\x48\x80\x05\x0c\x65\xd6\xea\xc6\x86\xb9\xeb\xac\x3e\x68\xe9\x5b\xe4\x75\x8e\xc9\x30\x22\xe3\x52\x4e\x2b\x45\x82\x9f\x37\x39\xb0\xa8\xe3\xc0\x2e\x40\x8e\xe0\x12\xce\x2d\xe8\x09\x68\x12\x69\x73\x65\xfe\x0f\x21\x72\xe0\x24\xe8\xb5\xa1\x03\xdb\xb0\x03\xbb\xb0\x07\xfb\xf0\x02\x5e\xc2\x2b\xe8\xb4\xfb\x90\x27\x41\x4f\x1c\x74\x34\xeb\xd3\x40\xa7\x03\x9d\xed\xbe\xde\x4e\x49\xa2\xa3\x26\xca\xfb\xd5\x3f\x3b\x46\x80\x93\xde\xa4\x3a\xfd\xae\x79\xe1\x77\x80\x04\xb3\x30\xcd\xf0\xdb\x38\x09\x73\x0f\xcb\x75\xcc\x40\xc1\xfe\x31\x57\x1e\xea\x62\xcf\xc7\x48\xa9\x20\x4a\x0a\x00\xc7\x41\xcb\x25\x43\x1a\x67\xf4\xb6\x69\xb2\x59\x40\x71\x1c\x8d\x89\x90\xcb\x6d\x8c\x1f\x27\xcb\x53\x9c\x0f\x26\x8e\x40\xfa\xd1\x8e\x1a\xa5\x50\x3b\x95\x2e\xd2\xc0\x3f\x98\x23\xd0\xe9\xe3\x83\x0d\x79\x27\xb4\x0f\x52\x9d\x23\xa7\x8a\x04\x53\x8e\x9c\x41\x10\x4c\xba\x4e\x9a\xdc\x39\x3e\xf7\xe6\x8c\x72\x3c\x55\x9e\x9c\xcd\x20\xb8\x75\x5d\xee\xc5\x29\xfc\x4f\x98\xf7\xa6\xed\x8b\x02\x77\x3a\xb3\xeb\xae\x19\x52\xe9\x5f\x33\xa7\xce\x78\x0c\xc7\x3a\xc7\x7b\xd7\xbd\x67\xee\x9c\xd3\x21\x5c\xea\xdb\x37\xae\x7b\xc3\xdc\x38\xb3\x29\x7c\xd2\xb7\x8f\x5c\xf7\x88\xb9\x70\x4a\x14\xa3\x0b\xfd\xb1\xf3\x6e\xdb\x3f\x87\xb3\x80\x30\xfc\x6a\xb8\xd2\x4f\xce\xba\x1c\xe3\xc6\x3f\x83\x0f\x01\x69\xdd\xc7\xf0\x59\x67\xf9\xc1\x75\x3f\xc0\x29\xbd\x9d\xc1\x89\xbe\x7d\xea\xba\xa7\x70\x18\x90\xd6\x37\x9c\x26\xa7\x11\xe1\x4e\xad\xef\x75\x82\x43\xd7\x3d\x84\x6f\xa5\xe8\x6b\xa3\xfb\x1d\x70\x74\x1f\x6f\x14\x87\xad\x7a\x8b\x9d\xe4\x88\xbe\x71\xc0\xa1\x9d\xe0\x80\x23\x9a\x59\xff\xd2\x1f\x8a\xc7\x0e\x38\xd3\xa1\x03\x4e\x36\xb5\xf0\x96\x38\xb4\x8f\x73\x1f\xd3\xff\xe8\xb7\xcd\xda\x38\x7d\x04\x6f\x34\x07\x76\xc6\x8f\x7b\xe6\x30\x73\xdd\x5e\x66\x8c\x1d\x5a\xdb\x0b\xd7\xcd\x7a\xff\x7f\xf6\xde\x75\xb9\x6d\x23\x6d\x18\xbc\x15\x0a\xaf\x5f\x7c\xe8\x71\x8b\x03\xca\x96\xed\x40\x41\xf8\xd9\xb2\x6c\xcb\xf1\x29\x92\x1c\x3b\xe6\xcb\x72\x41\x44\x53\x84\x05\xa2\x19\x00\x94\x44\x93\xa8\xda\xbf\x7b\x17\x7b\x2d\x7b\x29\x7b\x25\x5b\x7d\xee\x06\x1a\x24\xe5\x38\x33\xf3\xa5\x52\x33\xb1\x40\xa0\xcf\xfd\xf4\x73\xea\xe7\x20\x1a\xde\xbd\x29\x76\x9d\xda\x21\x3a\xa1\x39\x7d\x2f\x5c\xb7\x60\x40\xf3\x8a\x3c\x19\x6b\x47\xe1\x6a\x27\x0c\xa7\xb4\x29\x39\x41\x5b\x63\x53\x00\x86\x7c\xf0\x3b\x61\x78\x46\x2b\x90\x5f\xb6\xb2\x67\xb4\xac\x38\x35\xec\xe6\xac\xe0\x5b\xb1\x4b\x86\x52\xd8\x6a\xa5\xf5\x5a\x91\x56\x8b\x0b\xdb\xb6\x7a\x11\xad\xa7\x01\xf5\x4e\x18\x7a\x8b\xd5\xea\x1a\xd0\xfa\x7c\x67\xd6\xb5\x40\x0b\x83\x21\xdc\xe9\xed\x84\xe1\x31\xad\x45\x70\xb0\xad\xe8\xb1\x2c\xf7\x49\x95\x2b\xa6\x8d\x72\x9f\x64\xb9\x53\x55\x6e\x1a\x37\xca\x9d\xca\x72\x47\xaa\x5c\x7a\xd1\x28\x77\x24\xcb\x7d\xd6\xc6\x97\x36\xca\x7d\x06\xa0\xfd\x7e\xd1\x1a\x2c\xff\xa9\xb8\x4a\xfc\xaa\x5f\x09\x62\x6c\x21\x5f\x92\xe7\xd5\x92\x5d\x13\x32\x66\xd8\x8a\xb5\x44\x67\xd9\x10\xea\xca\xa4\x74\x04\x46\x5a\x5b\x92\xf9\xb3\x9c\x0a\xea\xd0\x4c\x43\xfd\xb1\x27\xbf\x82\x26\x34\x73\x5b\x2f\x46\x37\x9b\x36\x60\xf6\xe2\xbb\x39\xba\x42\x79\x81\xda\xaa\xc9\xef\xf5\xea\x39\xbe\x6e\xaf\xab\x7f\xac\xa0\x3c\x43\x3c\x4d\x19\x2b\xce\x56\x46\x66\x2e\x93\x85\xe8\x5f\xb3\x65\xb5\x88\x7a\xab\xb5\xa3\xc6\x4d\x06\x83\xa5\xd5\x16\xb1\x5e\x5a\xa7\x0f\x46\x0d\xed\x43\x4b\x2d\x94\xc5\xb6\x3a\xe4\x75\xb3\xc6\x79\x54\xa0\x34\xc9\x50\xad\x86\x7c\x2d\x6b\x68\x47\xd7\x9c\x49\xdd\xd6\xd2\x56\xa3\x39\x1b\x59\xcb\x36\x9f\x7a\x4d\x6d\x46\x66\x3d\x63\x4e\x5a\x2d\x82\x90\xd1\xee\x39\x2a\xaf\x11\xca\x1a\x55\xcd\xaf\xed\xf5\x23\xaa\x0f\x6f\xa9\xce\x3f\x56\xd0\x86\xdc\xe4\x0a\xb5\xd8\xa3\xda\x6b\x69\x73\xad\xd7\xd3\x67\x6b\xa9\x59\x9f\x6f\xbd\x7a\x63\xc6\xad\x6d\xc8\x39\xdb\x9b\x58\x3b\x6b\x56\x04\x5d\xa1\x2c\x5d\xb4\xb6\xc0\x3f\x57\x15\xb4\xe5\x36\x59\x4a\x9d\x16\xc2\x84\xaf\x3c\x8a\x46\x13\x13\xf9\xb1\xb8\x83\x8a\x59\x2f\xc1\x01\x21\xc4\xb9\xeb\x7a\x99\xa2\xc4\x2a\xfb\x2a\x25\xef\xbb\xca\xfd\xb2\x04\xc3\x50\x46\xe0\x54\xe5\x32\x4c\x13\x30\x01\xd8\xb0\x51\xbb\xdb\x31\x0a\x01\xe8\xd0\x4c\xac\x6e\xe7\xa7\xce\x1d\xca\x82\x28\x11\x82\x37\x52\xd1\xa0\x83\x54\x26\x21\x52\x8e\x6e\x40\x77\x89\x16\x45\x37\x47\xf1\x7c\x84\x5a\x4c\x7f\x74\x5d\x9e\x62\xa1\x97\xd5\x41\x69\x5b\x10\x95\x14\x9e\x12\x23\xdd\xed\x54\x9b\x33\x02\x07\xc9\xd8\xdb\x21\xeb\x84\x80\xcc\xd1\x43\x7f\xf1\x75\x57\x82\x80\x16\xcf\x01\xfd\xb3\xb7\xf7\x8f\x1e\x7a\x04\xfe\xd9\x43\x0f\x68\x20\xc6\x03\x3c\x28\x87\x21\xc5\x79\x4f\xa2\x22\x29\x82\x4c\xc5\x48\xd5\x0c\xe8\xb2\x8a\x25\xe5\xa9\x97\xe6\x82\x8f\xad\x0a\xb7\x20\x3e\xb0\xd6\xf3\xf5\x48\xac\x0d\x33\x3d\x00\x28\x13\x17\x86\x61\xde\x17\x44\xb1\x84\x18\x04\xe5\x20\x33\x16\x7f\x3e\xf3\x72\x30\x0c\x71\xe5\x65\xb0\x84\x39\xd9\x21\x00\x97\x54\x33\x50\x8b\xd6\xe5\x54\xc0\xcb\x31\x80\x11\x6e\x24\x2e\xe1\x9a\x22\x1c\x3a\x54\xbb\xe0\xc0\x74\x3b\x11\xe8\xd6\xa1\xa9\x12\xcc\x45\x1d\x0e\x5d\xb5\xd8\x4a\x19\xce\xa7\x51\x2a\xc2\x2b\x15\xc9\x57\x54\x93\x77\xa6\x28\x4e\xe6\x53\x21\xf2\x14\x65\x32\xba\x5c\xbc\x10\xc1\x95\xea\x52\xcf\xad\xa2\x5f\x41\x87\x0f\x89\xf0\xd4\x2c\x37\x9d\xde\x3c\xe1\x9f\xa7\xeb\x33\x66\x88\x03\x33\xa7\x69\xca\x83\x18\xea\xf5\x83\x19\x0d\xb8\x37\x87\x31\x9c\xb5\xf3\x51\x11\x6e\x24\xaf\x98\x36\x55\x21\x5a\x38\x2e\xea\x7a\x91\x92\xa5\xc5\x2c\xfc\x82\xd8\x40\x16\x34\x75\x9d\x6d\xe4\xcc\x75\xb1\xb1\x82\xa0\x82\x13\xc3\xd3\xa1\x58\xcb\xaa\xd5\x03\xf8\xf0\x8e\x0d\xcb\x56\xc6\x5d\x89\xcc\x39\x81\xcc\xfe\x27\xbe\x9c\x32\xcc\x46\xad\x58\x3b\xdc\x98\xc0\x51\xbe\x4a\x64\xea\x9a\xb5\x01\xbd\x92\x82\x72\x9d\x4b\x89\x2e\xf7\x80\x30\x05\x31\xb3\x3e\x4b\x0d\x60\xc3\x58\x1e\xf2\xce\x4e\x93\x18\x11\x26\xb0\x2c\xf1\x94\x5a\xf7\x1a\x7b\xb6\xac\x8f\xbf\x40\xb3\x28\x8f\x4a\x54\xcf\x0d\x74\x46\xe7\x5e\x01\x2f\xc5\x00\xce\xdb\xce\xd7\x08\x87\xe6\xfd\x9a\x53\xc1\x31\x39\x73\xf4\x19\xce\xfe\xa4\x33\x37\xc6\xdf\x33\x16\xdc\xbc\x09\xa2\x23\xbc\x16\x46\x37\x87\x8c\x83\x12\x8c\xc7\x02\x8c\x73\x7c\x7d\x91\xe3\x39\x61\x52\x0b\x33\x6a\x23\x6e\x0d\x21\x45\x21\x90\xf2\xc8\xbc\x6a\x55\xdf\x22\x6a\x1d\x5d\x01\x6f\x86\x79\xb0\xc2\x2d\x96\x1c\x46\x4a\x87\x53\x53\xdf\x88\x3c\xc3\xb7\x52\xdf\x28\xdc\x47\x51\xd8\x08\xcf\x10\x0b\x0c\x47\xb0\x1d\xcd\xc3\x84\xf3\xf2\xa9\xa6\xae\x51\x81\x96\xea\xf1\xdf\xc8\x90\xb6\xd2\x36\x68\xa8\x8d\xf4\xa7\xa1\x38\xbd\x2f\x33\xd0\xd2\x85\x99\x49\x20\xc2\x00\x2e\xcc\x57\x73\x0c\xe0\x79\xb8\x70\x5d\x67\x82\xa2\x98\xd0\xaa\x85\x18\xea\xc1\xa8\xef\x45\xe1\x08\xe2\xf0\xbc\xcf\x85\x1a\x1e\x62\x2e\xa0\x21\xa6\x1d\x10\x44\xe4\x53\x39\x71\x02\xa7\x8c\x59\x8c\xab\xeb\x70\x7c\xb0\x73\x4d\xdd\xd7\xbc\xeb\x90\x54\x73\xd8\x36\xdd\x84\x34\x82\x9c\xeb\x5e\x88\xb5\xeb\xcb\xa7\x40\x10\x0d\x00\x8f\xc2\x99\x28\x46\xa6\xd7\x67\x7f\x02\x41\x34\x00\xbc\x0c\xa7\xab\xd5\xc2\x75\xe5\x30\xe1\x29\xbd\xad\x13\xb0\x3e\x71\x5d\xef\x34\x74\xa2\x62\xe4\x30\xed\x58\x54\x8c\xb8\x72\x36\x70\x62\x24\x7f\x34\xd5\xbc\x91\x86\x92\xdb\x30\x2f\xd7\xb9\x14\x83\xcb\x21\x9c\x43\x09\x3c\xa6\x16\xa3\x25\x80\x8d\x98\x24\x53\xa2\x15\x03\xb9\xa3\x8d\xe2\x37\xb4\x38\x9f\xb2\x94\xfe\xe9\x76\x37\xca\x52\xd9\x5f\x6e\xde\xa5\xeb\xb2\xb5\xd3\x50\xa0\xeb\x16\x26\x8d\xe0\x9e\x7c\x04\x6e\x9c\xe0\x94\x1d\x5c\x0c\x29\x54\x05\xd7\x15\xbc\x32\xe2\x63\x6e\x41\x3f\x36\xe0\xfa\xda\xd9\xa6\xa0\x53\x77\x88\x12\x0b\xd9\x66\xe1\xfe\x3f\x59\xa7\xd3\x51\xfc\xae\x8a\xc8\x53\xb6\x45\xe4\x51\x39\x91\xcb\x46\x5a\xa2\x1e\x80\xdd\x47\x8f\xf4\x70\x3d\x9b\x4a\x3f\x78\x04\x40\x93\x00\x69\x51\xed\x00\x24\x5b\x20\xd2\x29\xd7\x68\x18\x0f\x31\x02\x89\xe0\xca\x6f\x9b\x8c\x85\x9a\xdd\x9c\xe1\x13\x34\xf5\xf6\xee\x03\x6a\xa4\xf7\xc1\x52\x46\xbd\x7f\x4d\xe1\xa2\x82\xe7\xd4\xe1\x6c\x5d\x87\x84\x34\xe1\x92\x10\xc1\x0d\xa4\x75\xe3\xc0\x7a\x40\x59\x0f\x5a\x4b\xf4\xf6\x08\xe1\x4d\xbe\x22\x33\x87\x7a\xe0\x08\xcb\xf0\x0e\x79\xe8\x89\x6c\xe6\xb6\x88\xa1\x2a\xf2\x1f\x75\x87\xa1\xef\x0e\x27\x68\x74\x79\x8e\x6f\x1c\x71\xdd\xb1\x77\x5f\x59\x9d\xfb\x1d\x96\xc6\x60\x7d\xb3\xf6\x34\xf0\xb4\x97\xce\x4f\x9d\x7f\x68\x52\x12\xcd\x0d\x54\xeb\x58\xf4\x7b\xff\x91\xde\x2f\xf9\xdf\xfd\x4d\x7d\xfa\x66\x97\xf7\x55\xe3\x6f\x70\x86\xb4\x6e\xdb\x5a\xa1\xd9\xa5\x28\x46\xa1\xed\x2d\x9b\xde\x82\x4c\xfe\x67\x61\x2e\x96\x4d\x2f\x50\x5e\x80\xf5\xaf\x7f\xcf\x59\x72\x80\xb5\xca\x27\x5a\xf5\x25\x13\x95\x8d\xca\x42\xaf\x5d\x67\xb4\x94\xfb\x26\x7b\xef\xf0\x30\x3e\x3c\xb8\x0f\x8f\x2e\xb3\xd7\x48\x1b\xa6\xa0\x52\x7d\x11\x17\xd3\x36\x1e\xed\x90\x20\x90\x0a\x78\x53\xce\x00\x5c\xe8\x2c\x19\x45\x84\x15\x5c\x10\x96\x8c\x3e\xc3\xf3\x3f\x89\x25\x5b\xfc\xd9\x2c\xd9\xc5\xf7\x63\xc9\x16\x1b\x59\xb2\xeb\x4d\x2c\x19\x23\xfd\xad\x5c\xd9\x0b\xba\xee\xc0\x3b\xe7\x9b\x72\xf3\x27\xad\xba\x53\xe6\x82\x55\x63\xb9\xec\x6d\x91\x53\x0a\x94\xa2\x51\x69\x4d\x9e\x79\x4b\x79\x92\x25\x2a\x81\x8e\x68\x51\xcb\xde\xa4\x71\x50\x5b\xc4\x5c\xde\x4a\x96\x5b\x52\x1a\x82\xbb\xe4\x8f\x40\xdd\xb8\xcb\x1e\xaa\xc1\x4c\x70\x3c\x43\x38\x27\x72\x1f\x9b\x7f\x4c\x45\x40\x3e\x3c\x11\x30\xb1\xa4\x31\xf5\x52\xb5\xe9\x44\x4a\xd1\xb7\xfb\xc8\x46\xd6\xeb\x17\xd0\xdc\x65\x4b\xd2\xe6\x26\x93\xde\xea\xd8\x2c\xdd\xbc\x09\x2e\x67\xb9\x79\xda\x72\xbe\x34\x32\xe5\xd0\x82\x94\x08\xc8\x7d\xec\xa8\xe7\xd6\x76\x14\x09\x6f\x0b\xd0\x05\x1b\x5d\x89\x46\x79\x52\x1e\x50\x55\x50\xf6\xb3\xac\x20\x1b\x38\x79\xa0\xb4\x5d\x91\x53\x1b\x5a\x3a\x21\xab\x0c\xbc\x1b\x7e\x00\x2e\xf1\xdf\xe6\x7d\x7f\x4d\xf3\x3e\xd5\xe1\x29\xd6\x72\x1e\xa0\x6e\x8e\xa2\xf8\x27\xdf\x75\xd9\xd3\x8f\xa8\x5b\xe2\x32\x4a\xfb\xec\xe7\x3f\xf9\xcf\x80\x7f\x0d\xfd\xfe\x5e\x70\xaf\x62\xc7\xf1\x10\x7f\x6f\x4b\x9f\x4b\xbc\xbd\xa5\xcf\x60\x78\x60\xc2\x47\xcd\xd6\x56\xda\xc8\x1d\x65\x17\x49\x86\x0a\x69\x83\x98\x87\xbe\xe9\xa8\x64\x2d\x3e\xc8\x86\xdd\xc3\xc9\x3c\xbb\x2c\x0e\xf2\x1f\xb1\xb0\x67\xcc\xef\xde\x15\x26\x79\x78\x90\x0f\x0f\x10\x33\xb0\xa3\x16\x54\x51\xf7\x67\xb4\xe8\xbe\x8b\xca\xc9\x5d\x27\x70\xee\xb2\x9f\x6f\x69\x66\x18\x88\x68\xa3\xc7\x4f\x83\xbb\x19\x24\x0b\x19\x44\xac\x71\xfe\x7d\xd7\x28\xcc\x56\x5c\x94\x38\xca\x62\x4b\xa1\x4a\x86\xc8\x45\x56\x43\x3e\xa6\x87\xa6\x5b\x0d\x73\xf2\xb7\x94\xf8\x3e\xfb\x31\xef\xef\xf6\x82\xec\xa7\xbc\xdf\x0b\x50\xf7\x12\x2d\x7e\x2c\xc9\xbf\xdc\x8c\x8f\x3c\xfe\x44\x5f\x00\x9b\xcd\x5a\xd4\x62\xb3\x26\x4c\xee\x9c\x67\x49\x8a\x0a\x8b\xa0\xda\x66\xec\x56\x60\xfb\xfb\xeb\x96\xf7\x47\x2d\xef\xaf\xf8\x7b\x87\x2e\x9b\x65\x00\xb2\x00\xdb\xe1\x75\x25\x64\xc0\x36\x60\x59\x81\x09\x2f\x85\x9a\x56\x77\x2d\x14\xf5\x08\x33\x1b\x3b\xba\xb6\x4d\xf6\xe8\x0a\x1b\x9e\xad\xe5\xc4\xe1\x62\x2d\xa7\x81\xb4\xda\x9a\xd1\x06\x0e\x44\x5d\x01\x61\xed\xe5\x6c\xe6\xe3\x8c\x67\xeb\xf9\xfe\x3f\xcc\xf3\x6e\xb7\x1f\xe7\xb9\x9f\xec\x9e\x5e\x04\xe2\x3e\xfd\x4d\x3e\xfe\xa2\xe4\x03\xbe\xfb\xee\xc8\xfe\xd3\x2d\x90\xbd\xd5\x94\xba\x61\xf1\x0c\xf3\x30\xfb\x31\x4c\x50\xf7\x75\x74\x73\x9c\x5d\x45\x69\x12\xf7\x51\x97\xfa\x60\x06\x32\x64\x2a\x34\x27\x52\x5c\x27\xe5\x68\x42\x9e\x46\x51\x81\x3a\x09\xea\xbe\xc2\x51\x4c\xb7\x09\xc5\x01\x1f\xaa\x7f\xa0\x7f\x44\x71\x20\x7e\x7e\xc8\x93\x12\xd5\x0a\xf7\x64\xe1\xc7\x69\x4a\x0a\x94\x28\x93\x15\xa8\x83\x66\xad\xc2\xde\x81\xf1\x55\xb5\xce\xdc\x86\x6a\xa5\xef\x1d\x98\x9f\xf5\xf2\x44\x56\xb5\x56\xba\x7f\x60\x29\xa3\xd5\x7c\x9c\x96\x28\x7f\x3c\x2f\xf1\x71\x36\xaa\x55\xdd\x3f\x30\x0a\xa1\x98\x17\x53\x53\x9a\xa0\xd1\x65\x31\x9f\xd6\xea\x3d\x38\xa8\x17\x98\x6a\x1d\x8a\x77\xa7\x97\xc9\x6c\xa6\x0f\x24\x8b\xd2\xc5\xd7\xfa\x0a\x3d\x3c\xa8\x7d\x6f\x54\x10\xed\xf0\x0a\x8f\x0e\x44\x42\x7d\xb1\x83\x55\xe5\x65\x1b\xa2\x14\x50\x2c\x49\xf1\x4c\x77\x9c\xe3\xa9\xb7\x64\x44\xdf\xf0\x10\x22\xc8\xb1\x02\x35\xcc\x9f\xc1\xa8\x15\xf7\x73\x33\x63\xca\x20\x40\xc3\xf6\x9c\xd3\x98\xa7\xb8\xbc\xeb\x74\x9c\xbb\x39\xfd\xd7\x8b\x7e\xc4\x7d\xd4\x1d\x27\x69\x8a\xe2\x00\x75\xd1\x74\x46\x38\x7c\x4a\x8a\xd7\x83\xed\xeb\xa4\x28\x92\xec\x82\x4f\xd8\x99\xb2\x9f\x4e\x1d\x72\xf9\xe7\xeb\x9c\x05\x28\xb4\xc1\x2a\x2f\x32\x4a\xb1\xd9\x02\x87\x4e\xfe\x99\x05\x11\x33\x0a\x48\xb0\x32\x8a\xa0\xd8\x69\x81\x3e\x51\x8c\xbc\xec\x34\x0b\xd7\xe0\x8d\x97\x8e\x71\x92\x5d\x74\x46\x1c\x7e\x9c\x5b\x41\x19\x6f\x22\xa2\x30\x63\x4e\x7f\x2b\xb8\x72\xc6\x49\x96\x14\x13\x7d\x90\x4d\x6c\x41\x73\xb7\x91\x31\x7a\x88\xbd\x07\xaa\xb4\x05\x5f\x88\xad\xb0\x15\xb7\x60\x0b\xb1\x2d\xb6\xe2\xb6\xa3\xaf\xf6\xc9\x5a\xa3\x0d\x63\x18\x9b\xd2\x52\xb9\x1d\x69\x38\x11\xf9\x44\x63\x69\x74\x92\x6c\x64\x9d\x9a\x15\x6b\x38\x62\x5f\xad\xfd\xd9\x70\x83\xda\x4c\xbd\x8a\x79\xfa\x9d\x79\x76\x99\xe1\xeb\xcc\xa1\x48\xa0\xd5\xbe\xfd\x64\xbd\x7a\x41\x3b\xb0\x42\xbf\xfa\x48\x44\x4c\x7a\xd4\x16\xa2\x4e\x4f\xe9\xf2\xc8\x0c\xa0\xc4\x13\xa6\xf1\xa3\xbe\xac\x20\x3d\xeb\xe4\x61\x26\xe2\x7f\x3b\xee\x1d\xf6\x79\xad\x06\xc2\x8c\x05\xee\xb8\x77\x68\x43\xad\xca\x86\x3b\x19\x68\x89\xee\x0f\xbb\x0f\x40\x55\x41\x46\x30\xb7\xec\x9c\x16\xfe\xb6\xae\x55\x55\xd6\x31\xb5\xfa\x7f\xc7\x35\x11\x6f\xff\x66\x25\xff\xa2\xac\x24\x3f\x6d\x67\xdf\x9d\xa1\x7c\x7b\x4b\x86\x12\x66\x02\x74\x2e\xd1\xa2\x68\x38\xeb\x36\x14\x08\x35\xaa\x2f\xef\x13\x07\x25\x44\x6b\x55\x09\xe5\x70\xa8\xa5\xd7\xdc\xe0\x79\xe7\x0f\x77\xcb\x81\x3f\x6c\x91\xbd\x2d\xde\x42\xed\xee\x6f\x5c\xd2\xfd\xb7\x4a\xe3\x6c\x08\x9d\xe3\xa7\xeb\xe4\xed\x53\xca\xbe\xaf\x2b\xc1\xb5\x0a\x6b\xc4\xf1\x3f\xe2\x04\x27\x04\x74\x8b\x13\xdc\x26\xe1\x9c\x48\xdf\xd9\x2d\x84\x6e\x0c\x97\x4c\xbf\x73\x5f\x78\x79\xe5\x5d\x36\x7d\xdb\x8e\x93\xde\x23\xfd\xf6\xab\x82\x39\x57\x4b\x71\x95\xd4\x06\x89\xfc\xcd\xdf\x68\xf4\x2f\x8a\x46\xe1\xe7\xef\x8e\x40\xdf\x58\x10\xa8\x84\xfd\xa7\x49\xfc\x1a\xcf\xb3\x52\x87\x27\x0d\x65\xe2\xec\x70\x12\x65\x17\x88\xb9\x3e\x9e\xe9\x78\xb0\x2d\x0c\x82\xb5\x9b\x0f\x49\x9a\xbe\xcf\xa6\xdf\xd8\x13\xbb\x38\xab\xb5\xfd\x2f\xf4\x15\xc5\x14\x5b\x08\xc7\x91\x1d\x5f\x44\x50\xae\xdb\x8c\x43\xab\x77\x80\x21\x1f\x52\x1f\xcd\xe7\x79\x62\x71\x6f\x26\xbd\x50\x7f\x12\x1b\xf2\x7f\x8e\xa0\x76\xb1\x7c\xaf\xe6\xcc\x2c\x97\xdf\x12\xdf\x42\xb5\x6a\x0e\x84\xd4\x79\x8a\xcb\x12\xc5\x62\x9d\x9b\xbd\x2a\xbc\xf6\x48\xe0\xb5\x56\x7a\x2a\xd1\x5d\x73\x0c\x67\x98\xbb\x1c\x8b\xc2\xad\xad\x58\xe2\x64\x1c\xde\xa2\x72\xab\x10\xf0\x7a\x9b\x3b\x46\xbb\x93\xab\xdc\xb1\x5a\xec\x47\xa4\x99\x8b\x56\xd0\xb2\x9c\x42\x9c\xb8\xf7\xc0\x67\x4c\xf0\x67\xce\x04\x1f\xff\xf1\xfb\xe8\x8d\x59\x16\x85\x01\x44\xcd\x20\x7a\x9c\xdc\x10\xce\xbf\x80\xa3\xdb\x24\x51\x14\x8d\x6d\x99\x08\xb9\xf8\x7d\x1e\xe5\x88\x02\x9c\x16\xd9\x91\x67\x84\x55\x91\xde\xef\xaf\xb9\x82\xc6\x03\xd5\x69\xc3\xcc\x6c\x4e\x53\xb0\x6d\x4a\x05\xc8\xe7\x1a\x86\xe1\xdc\x75\x9d\xe9\x3c\xd9\x65\x2f\x64\x44\xca\x91\x11\xb6\xb5\x05\x40\xb8\xe3\x40\x5b\xd6\x35\xf5\xf3\x22\x47\x8b\x41\xcf\xf7\x87\x41\xed\xdd\x0f\xbe\x3f\x3c\xb0\x9b\x38\xaf\x8d\xf6\x5d\x33\x7c\xb6\x7a\x98\x71\x3b\x16\xd4\x65\x0f\x84\x1a\x3c\x89\xf2\x5a\x82\x71\xb1\x90\xcf\xc8\xf4\x75\xd3\x18\xb6\x1e\xba\x65\x0c\xf7\x3d\x60\x29\x7a\xfc\x46\x7c\x73\x4b\xba\xac\x4a\xb5\xff\x98\xbf\xb3\xe7\x45\x6b\xed\x45\x35\x70\x4a\x4d\x75\x36\x18\xef\xb4\x57\x8e\xca\x64\x64\x56\x26\x6f\x1c\x55\xe4\x84\x47\x72\xb7\xe6\xb0\xe3\x29\xe6\x9e\x72\x15\x43\x43\xd4\x2d\xb9\x49\xb8\xb6\xbb\xa8\x3c\xc4\x59\x99\x47\x05\x8d\xf5\xea\x95\x60\x53\x1e\xbb\x16\xf9\xbc\xde\xb0\xf8\x38\xd2\x5a\xdf\x9c\x01\xaf\xd5\xd2\xa0\xde\xbc\xfa\x6c\xe9\xe0\x98\x19\x58\x34\x0c\x2e\xf8\xe7\x33\x95\x8e\x6d\x43\x22\x3d\x58\x6f\xc0\x34\x53\x78\x4c\x21\x95\x06\xfd\xe5\x58\xf1\xd5\x9f\x65\xa5\x23\xb3\x97\xcb\xa8\xb9\xcf\xe7\x65\x89\xf2\xc2\x6a\xaf\x63\x4f\x42\x9b\xa3\x8b\x79\x1a\xe5\xb7\x48\x3f\xdb\x48\x91\xcd\x3b\x35\x8c\xa2\xff\x50\x82\x74\x3c\x88\x09\x9e\xdb\xa1\x06\x38\x17\xac\x75\x89\xdc\x0c\x0b\x9b\xaf\x5b\x51\x3f\x4b\xc6\x83\xcd\xd9\x94\x2b\xc8\x7b\xd6\x62\xa4\xeb\x86\x87\x3a\x95\x34\x6d\x10\x4d\xfa\x89\xea\x4e\x48\x4e\x31\x75\x00\x6c\x69\xeb\x5e\x6b\x5b\xf7\x40\x45\xd6\x80\xee\x56\x80\xba\xd3\xe4\x26\xc9\x8a\x6e\x89\x71\x7a\x1e\xe5\x30\x46\x19\xcd\x63\x90\x64\xdc\xc2\xf4\xfe\xa3\xba\xf9\x0c\x2b\x49\x03\x37\x73\xc0\x7c\xba\x65\xf8\x86\x6c\x34\xc1\x39\xcb\xfd\x67\x86\x6f\x58\x0a\xc3\xa4\xc0\x29\xf1\xcc\x81\x13\x9c\x27\x5f\x09\x3b\x99\x4a\xf9\x8f\x07\x76\x38\x8f\xe2\x0b\x24\x62\x21\xa4\x7a\x34\xe8\x4d\xfe\x00\x84\x21\xa8\x85\x72\xe0\x21\x6a\x64\x38\x07\x71\x3a\x66\xaa\xd8\xb8\xcf\xf2\x87\x07\x2c\xa8\x43\x92\xf1\xb4\x15\xd4\x4b\x60\x1a\xdd\xc0\x2b\x55\x76\xda\xff\xe1\x87\x60\x0a\x2f\xc2\xac\x8b\xaf\x50\x9e\x46\x33\xb8\x50\x5f\x2f\xc8\x19\x19\x95\x51\x76\x91\x22\x27\xb8\xa0\xb1\x1d\x8a\x09\xbe\xfe\x84\x72\x2c\xa3\x3a\xec\x84\xe1\xb9\xeb\xb2\x48\x0e\xe2\x9c\x1d\xa9\x36\x6e\xfa\x04\x67\x13\xd4\x14\x3b\xc1\x0d\xbc\xac\x79\x27\x68\xeb\xeb\x40\x47\x5f\xaa\x6d\x92\x4e\x09\x5e\x46\x3f\x99\x72\xbe\x2c\x9b\x94\x03\x1d\x3e\x33\x07\x3a\x62\xf0\xa6\x13\xc3\xa9\xcc\x49\x3f\x71\x5d\x8f\x22\x18\xd7\xdd\xb9\x5e\xad\xd8\xcb\xc4\x75\x9d\x18\x53\x1b\xfc\x23\x40\x8d\xff\x77\x7c\x06\x44\x87\xa1\xe3\x1c\xc8\xbb\x8e\x92\x5b\xd2\x7b\x87\x61\xf2\xd3\x55\xdf\xd1\x13\x34\xdf\x75\x40\x90\x34\xd9\xe0\xd9\x5a\x94\x20\xe2\x2f\xc8\xf3\x7f\x09\xa0\x25\x47\x30\x4b\x16\x6f\x6f\x80\x2e\x28\x2c\x06\x6a\x30\x51\x57\x41\x2a\x68\xb0\x59\x51\x57\x80\x35\x80\x4e\xe5\x80\x21\xa9\x6b\x6c\xd2\xba\x2a\xb6\xf6\xb4\xde\x9a\x9f\x17\xd4\xb7\x40\x00\xf5\x0e\xcd\x5a\x5d\xb4\xf2\x80\x31\x29\x7d\x4a\x03\x4a\x48\x98\xa6\xeb\x1e\x32\x0f\x86\x6e\x8c\x09\xb9\x3e\x34\x82\x8b\xff\x61\x2c\xc9\x2f\x09\x18\xb2\x6c\xb1\x46\x34\x79\x33\xba\xe8\x9b\x38\x42\x6a\xdc\x58\x8f\x43\xb0\x36\x89\xcf\x36\xa9\x7d\xac\xc9\x4f\x5b\xf8\xcc\x31\xce\xca\x67\xd1\x34\x49\x17\x66\xbc\x5e\xf5\x5e\xf7\x15\x68\x14\xd1\x7d\x05\x5a\x22\xff\x6a\xb6\xfb\x50\x46\x47\xd8\xf3\x75\x6f\x80\x9e\x6e\xf5\x4e\xad\xec\xf9\x35\xcd\x9e\x6f\x5e\xc1\xf4\xa4\x81\xb7\x91\x3e\x14\x69\x09\xf2\x0a\xa1\x95\x51\x49\x3a\x1d\xb8\x44\x51\xc1\xe4\x3f\xbd\x20\x7b\x49\xfe\xa0\xe3\xec\xed\xbc\x84\xb1\xc8\x73\x66\x96\x13\xaf\x6b\xd9\x1d\xab\xbf\x02\x57\xc8\x62\x6a\x6e\x75\x5f\xd4\x68\x98\x7d\x32\x1b\x8d\xc9\x51\x32\xf6\xec\xbe\xba\x73\x93\xdb\xaf\xdc\x1c\xfc\x0a\xea\x98\xe5\x0c\xcf\x28\xdd\x3f\x11\x14\x27\x58\x32\x09\x41\x08\x2e\x5a\xf2\xe6\x62\x14\xa5\xc8\xeb\x81\x8e\xcc\x4b\xef\xed\xfb\xff\x0d\x3b\xbb\xfb\xfe\x7f\x03\x4b\xd2\x5e\xea\xce\x4e\x93\x47\xb9\x77\x14\x7d\x30\xf2\x41\xb3\x26\xfd\x96\x26\xab\xb5\x63\xa5\x7c\xc9\x7f\xee\x68\x99\x6e\xa3\xbe\xb8\x32\x17\xf2\x2d\x46\xbc\x6e\xc0\x3c\x3b\xd7\xad\x87\xbc\xdd\x88\xd9\x12\xff\x27\x8f\xf9\x0c\xcf\x08\x43\xdb\x00\x5f\xee\x9d\xb2\x7e\xa4\xbb\x6b\x01\xe2\x5b\xc0\x61\x77\x2d\xf4\x6a\x23\xd5\x81\xf7\x3f\x6f\xac\x0c\x12\x6a\x0b\x2b\xc1\xe0\x16\xe3\x6d\x1f\xee\x37\x00\xc1\xee\x06\xc8\x6d\x2c\xef\x7f\xf0\x88\x05\x2e\x3b\x4c\xf2\x91\x80\x5a\xa7\x77\x5f\x4b\x0b\x4d\x9e\xff\x83\xd0\x99\x3e\x60\x05\xbc\xff\xd1\x43\xd6\xf0\x99\x58\xe6\x73\xe1\x81\xfa\x0d\xc3\xfe\x37\xa0\x61\xb5\xd8\xff\x27\x0c\x9c\x63\xb8\x26\x48\xf3\x9c\xe5\x9b\x87\xfb\xef\x40\xc8\x36\x80\xfe\xcf\x1c\xb0\xc2\x72\x56\x70\xbe\xe5\xa0\xff\xe5\xa8\xb9\x05\x98\xff\x73\x86\x2d\xeb\x05\xcb\x7f\x83\xac\x63\xe6\xab\xaf\x27\x78\x7b\x42\xa4\x5b\x9a\x5d\x8b\xab\xd2\x9e\xe0\x30\xf3\xf6\xef\xdf\xdb\x03\xf0\xcb\xdf\x26\x0c\x7f\x51\x13\x06\xae\x4e\xf9\xf0\xdd\x0d\x19\xbe\x6c\x65\x09\xb6\xd9\x18\xdc\x9e\x02\xc2\xf4\x2f\xe5\xb1\x94\xcf\xa2\xe2\xb2\x93\x64\x63\xec\x40\x5b\x92\x88\xe2\xb2\xb0\xe5\x60\xc2\x70\xa9\xab\x27\x83\x5a\x9c\xf7\x5f\xe6\x68\x8e\xba\xbf\xd3\x7f\x8d\x20\xe3\xf2\x12\xd7\x92\x52\x0a\xab\x64\x12\x2d\x46\x41\x77\xc8\xe1\xba\xf7\xf0\xa1\x0f\xe0\x7b\xf2\xf8\xe0\xc1\xfe\x1e\x80\xbf\xfe\x7d\xce\xfe\xda\xe7\xec\xc5\x77\x3f\x67\xbf\xfe\x91\x73\xd6\x7e\x98\xb4\x53\x30\x8b\xe6\x05\x8a\xfb\xce\x09\x2a\xe6\x53\xe4\x04\xce\x3b\xf2\xc2\x81\x46\x7a\x36\x61\x17\x74\x86\x2f\x2e\x52\x44\x4b\xc4\x50\x64\xa9\xc4\xf3\xd1\xe4\x24\x99\xcd\x52\xc4\xcc\x65\x1a\x6d\xd7\xc7\xf5\x5e\x1e\xa0\x46\xc6\x99\x3b\xea\x6c\xd9\x4f\xd6\xef\xf4\x38\xed\xf5\x7c\x00\x7f\xfe\xfb\x38\xfd\x45\x8f\x13\xfc\x45\x3f\x48\x90\x47\x96\x14\x27\x08\x5d\x7b\xd9\x6a\xe5\x65\xe1\xbb\x1c\x4f\x93\x02\x01\xfd\x92\x00\xc3\x48\x3b\x78\x09\x39\x86\x65\xbe\x58\x16\x5e\xde\xcd\xd0\x4d\xe9\x21\x00\xaa\x51\xc4\x3d\x7b\x22\x0f\x81\xaa\x92\xa5\x53\xbd\x34\x5d\xc9\xb5\xc5\x0b\x69\x94\x72\x80\xba\x31\xce\x50\x1f\x7b\x88\xa5\x9c\x06\x81\x57\x86\xfc\x19\x96\x1d\x0d\xb2\xb2\x3e\x21\x5a\xd7\x9d\xcc\xbc\xd8\x40\x5e\x49\xcd\x4c\xbb\xe5\x04\x65\x5e\x02\x53\x50\x15\x9e\x97\x87\x22\xf1\x0a\x82\xe5\x6a\x35\x18\x02\xc0\x66\x41\xef\x4a\x2a\xf8\xdc\x5c\x26\x6e\x8f\x0b\x73\xc8\x22\x9b\xf1\xf4\x19\x3e\x2c\x08\xe5\xd3\xce\x4a\x32\xf6\x7a\x2e\x1e\xf8\x43\x0e\x2f\x58\xb3\xdc\x25\xcf\x15\x2c\xf3\x45\x11\x0c\x86\x10\xcf\xc8\x1f\x09\x8e\x51\xb8\x24\xfd\x07\xa9\xe7\x03\x48\xeb\x06\xa9\xd7\x03\x90\x7d\x0e\x52\x7a\x7f\xac\x40\x34\x14\x20\x7a\xba\x98\x9e\xe3\xd4\x75\xbd\x68\xc0\x1e\xbb\x49\x89\xf2\xa8\xc4\xf9\xd0\x86\xc7\x08\x02\x04\x30\x3a\xd0\x76\x26\x6a\x06\x1c\x4d\x9b\xaf\x22\x3a\xb7\x96\x63\xf0\x1c\x65\xac\x4f\x02\xee\x51\x9a\xa3\x28\x5e\x74\xd0\x0d\x1a\xcd\x4b\xc2\x69\x13\x38\xc7\xb9\x77\x90\x1c\x00\x02\x03\xa4\x9d\xb0\x07\x73\xd7\xf5\x70\xb8\xe7\x46\x03\x7f\xd8\xcf\xbb\x7c\xa2\xfc\x17\xed\x66\xb5\xf2\x3c\x1c\x8a\x4f\xc0\x75\x31\x3b\xdc\x39\x80\x3e\x08\x18\xd8\x01\xd7\xdd\xf1\x70\x28\xbe\xc0\x68\xd0\x23\x7b\x49\x80\x06\x88\x75\x3f\xe0\x1e\x67\xd4\x7b\x9e\x2c\x55\x38\x60\xdd\x42\xcc\x00\x69\x08\x20\xf9\xc9\x1d\xd2\x7c\xe6\x48\xd5\x0b\x70\x18\x1d\xd0\x0b\x7b\xe6\xc6\x73\x5f\x38\xe4\x25\x5d\xba\xfd\x77\xef\x0a\x27\x64\xd2\x29\x24\x5d\x06\x3b\xbd\x8a\x15\xde\x0f\x54\xa9\x9c\xe6\x77\x83\x51\x38\xf0\x87\x84\x9e\x95\x49\x36\x47\xac\xd8\xc3\x20\x0a\x93\x2e\xc5\xe8\x78\xe6\x01\x98\x74\x09\x7c\xb0\x1f\xaa\xa8\x70\x09\x4a\xc6\xde\x0e\x59\x12\x0f\x87\xac\x20\x10\xc9\x1f\x7c\xd7\xc5\x03\xe1\xea\xbf\xdb\x1b\x82\xd5\xea\xc1\x4e\x18\x92\x59\xb9\xee\x1e\x7f\x02\x60\x99\x84\xbe\x6c\xb6\x4a\xc6\xde\xbd\x50\x14\xf2\x76\xf0\x6a\x45\xc6\xf9\x13\xa6\xbf\xc9\xe3\x8f\x78\x70\x8f\xd6\x62\x53\xa1\xd3\x60\x2b\x42\xea\x3e\x90\x75\xf9\xf7\x1f\x09\x84\xab\xd2\xe4\x17\x94\x6b\x48\x6a\x60\xbd\xe8\x9e\x51\x74\x6f\x08\xf9\x3a\xcc\x8b\x89\x17\x01\x5e\x89\x7c\x20\x95\x36\xac\x50\x15\x85\x25\x83\x00\x04\x13\x1d\xaf\x84\x83\x07\x10\x0d\x61\x1e\xfa\xd5\x38\xc9\xa2\x34\x5d\x2c\xb3\x10\x87\x3e\x19\xcd\x3e\x85\x01\x0e\xd1\x91\x3a\xa8\x72\x53\xfd\x61\x9f\xbc\x0e\xd8\xdd\x3d\xdf\x60\xbf\xaa\xbc\x41\x04\xd3\x21\x91\x03\xe1\x6f\x38\xa4\xb6\x5a\x27\x68\x9c\xa3\x62\x72\x9c\x95\x28\xbf\x8a\x52\x87\xb3\x2d\x1f\x5b\xd9\x96\x4c\xc5\x2f\x56\x29\x78\xb3\x5a\x0a\xde\x5c\x4f\x8d\xfa\x1a\x65\x73\xe3\x48\x6b\x59\x73\xa7\x28\x9b\x1b\x39\x73\x45\x4d\x3e\x2e\xb3\x5e\xad\x51\x0f\x40\x72\xc6\x68\x41\x4f\xab\xcb\x58\x92\x35\xdd\xda\x2e\x90\xf5\x91\xa0\xae\xfa\x55\x51\xb4\x2a\xfb\xa6\x56\xd0\x62\xb5\x42\x4b\x1c\x82\x8d\x03\x1e\x19\x4d\x50\xfa\xc1\xa6\x21\xe3\x88\x9e\xa0\x31\x2d\xc9\xb3\x07\x27\x05\x5f\x8c\x24\xbb\x08\x76\x7a\xd0\x58\x33\x68\xd9\xc4\xc0\xaf\x60\x2e\xd8\xc5\x9f\xad\xec\x62\x73\x71\x79\xda\x1f\xcc\x36\x94\x43\x0e\xff\xd3\x0c\x7f\xdb\x79\xce\x0b\x7a\x36\x07\x59\x76\x38\x24\x56\xd2\x70\xb8\xb6\xf5\xe6\xb4\xfc\x0a\xc0\xc1\x7d\x68\xb0\x96\x27\x62\x6b\x87\x07\x1c\xb1\xa9\xf0\x1b\x84\x33\x04\x70\x6d\x93\x3d\xd2\xe4\xde\xb0\xaa\x38\x69\x34\x4c\xdf\xdb\xf7\x91\xd9\x94\x52\x68\xae\x35\x6f\x5b\x6a\x54\x01\x98\xe2\x51\x94\x9e\x96\x38\x8f\x2e\xc8\xc8\xca\xe3\x12\x4d\xbd\xdf\x30\x74\x9c\xbb\x08\xc0\x51\x8a\xa2\x5c\x6e\x37\x6d\x52\x6b\xe8\x2c\x99\xa2\x9c\x4f\xa4\xfe\x3a\x44\x3f\xf9\x7d\x9e\xc4\x8b\x34\x2b\xda\xb0\x6c\x47\xa9\x9d\x03\x00\x7b\xe8\xde\x3f\x10\xe0\xc7\xbf\xc5\xe6\xdf\xe6\x5a\xb0\x35\x10\x50\xce\xfa\xa0\x15\x14\x4a\x09\x0a\xa5\x15\x14\xc4\x46\xe7\x6d\x1b\x5c\x8a\x0d\x46\xa1\xbf\x32\x96\xf7\x42\x2e\x2f\x5f\xb4\xc6\x71\x6a\xdf\xf3\x0d\xee\x0e\xdb\x6c\xd4\x26\x27\x87\x6f\x53\x6f\xe4\x68\x1c\x88\x05\x11\xba\x0d\xde\x6d\xc3\x52\x13\x5a\x92\x64\x2b\x84\xd7\x54\x4d\xfc\x8e\xdb\xb3\x5d\x9f\x64\x70\xc9\x14\xab\x47\xa9\x1c\x40\x77\x34\xcf\x73\x94\x95\xb0\x9e\x07\x5b\xe1\x9d\xd6\x2c\xd8\xf6\x21\x9c\x66\xf6\xa9\xbf\xc9\x68\xc8\x4f\x22\x31\xc6\x7a\x47\xfa\x31\xb6\x4d\x97\x7f\x85\x3c\xec\x26\x15\x31\xc5\x7a\x75\x32\x7c\x6d\xf1\x69\xc3\x3c\x5d\xa9\xf3\x78\x5e\xe2\x0e\x87\x3b\x4b\xb9\x37\xf6\x2c\xe4\x26\xda\xf7\xf6\x80\x0a\xfe\xb5\x27\xd2\x00\xb2\xb1\x5b\x70\x44\x05\x9d\xbd\x0e\x33\xe0\xb0\xb9\xdb\x6d\xd7\xe5\x3d\xdf\xd7\x3a\xbd\xe7\xfb\xdb\x74\xbb\xdf\x99\x26\xd9\xbc\xb4\x3a\x23\x6e\xd7\xad\xde\xe9\x56\x5d\xbe\x1d\x8f\x9d\x76\x25\xd8\xcb\x2d\xad\x88\x85\x5d\x65\xa4\xd9\x55\x26\x86\x5d\x65\x2a\xed\x2a\x0b\x65\xa2\x98\x6a\x76\x95\x29\x33\xc4\x94\x76\x95\x23\x55\x6c\xde\x77\xce\xe7\x65\x89\x33\x27\x98\xd3\x10\xcd\x02\x08\xe1\x58\x99\x42\xc6\xae\x1b\xd3\x48\xcd\xfc\xe3\x91\xf0\x8c\x80\x13\x55\x68\xe6\xba\x33\x6a\x8d\xc9\x0b\x3d\xc3\xa3\x79\xc1\x14\x1f\xd2\x38\x93\xe5\x45\x62\xa6\x99\x28\x8b\x8f\x47\x38\xa3\x79\xb6\xc6\xa4\xec\xaf\xec\x76\xe0\x50\xce\xeb\x9c\x7c\x99\xa7\x29\x4b\xac\x64\x33\xcd\xa4\x91\xa3\x4d\xbb\x4c\x11\x27\x9f\xa5\xdb\xa2\x99\x48\x68\x37\xa7\x61\x46\x1d\x21\xe0\xa1\x2a\x7e\xaa\x26\x7f\x0a\x3f\x69\xa6\x9e\xef\x54\x99\x4f\x7d\xa7\x44\x37\xa5\x13\x7c\x82\x27\x35\x7b\xea\x6f\x31\xe4\x14\xcb\xab\x1e\xe5\x62\xaa\x57\xda\xd2\x39\xd0\xe1\x0b\xe5\x40\xc7\xba\x4c\xe4\xbd\x58\x24\x3d\x82\x3f\x9f\xb8\x03\x1d\x32\x6d\xd3\x38\xf4\x6d\x78\xd9\x4c\x4b\xbc\xc6\xe6\x32\xd2\x16\x32\x1a\x38\xc9\x08\x67\xa7\xad\x71\x95\x01\xb5\xe9\x3c\x0b\x2f\x6e\xd9\x85\x00\x88\x6d\x3a\xb8\x68\x35\x48\xff\x82\xd6\x9a\x9f\x46\x3c\x70\xe4\xe0\xdd\x10\x26\x2a\x14\x35\xf5\x39\x8a\xba\x86\x63\x81\x6e\xc2\x59\x10\x59\x4a\xd9\x9b\xbe\x6b\x5a\x7d\x16\xcd\xe8\xd3\x03\xa3\x0a\x74\xe8\x8c\x9a\x35\x69\x2c\xea\x68\x5d\xa4\xea\x21\x9c\xb8\x6e\xd4\x3c\x7d\x63\xed\x6d\x0c\xaf\xc9\x2f\x09\x0a\x40\xbb\x06\x18\x41\x49\x5a\xc6\x70\xac\x80\x2b\xd8\xb9\x82\x56\x98\xd2\xd7\x4b\x2f\x00\x17\x22\x48\x2a\x81\xa9\xe0\xb0\x82\x27\x4d\x6c\xda\xdc\xe4\x88\x71\x3e\x15\x7c\x0b\x31\x3c\xd3\x2d\x59\x51\xf4\x07\x02\x65\xd3\xa3\x0b\x5b\x73\x5a\x09\xe3\xbc\x07\x5a\xf0\x63\x15\x4e\xd9\xb0\xe9\x2b\xbb\xc5\x24\x9a\xa1\xae\xfe\xd2\x9e\x58\x41\x04\x71\xd2\x6e\x30\x4b\xdb\x0d\xe6\xc0\x51\x26\x88\xbb\x02\x11\x9c\xe3\x9b\xdd\x62\x12\xc5\xf8\x9a\xfe\xc8\x69\x76\x0d\xb8\x94\x57\x97\xa5\xfd\xea\xb2\x98\xe0\xbc\xac\x00\x74\x5c\x19\xc6\x93\x8c\xe5\x29\x1a\x61\x5e\x91\xa5\x5b\x69\xc4\x08\xb6\xc5\xe7\x36\x67\x61\x8d\x22\x2a\xe2\x7a\x4a\xaf\x2a\x8f\x85\xf4\xec\x90\x5e\x80\x25\xb8\x86\xe1\x4e\x43\xc3\x70\x48\x34\xb7\xa9\x70\xbd\x74\x7d\xd1\xf9\xb8\x44\x89\x8a\x88\x18\x54\x6d\x67\x24\xf2\xd4\x0d\x9b\x39\x6b\xa8\xdb\x11\xcb\x97\x75\x53\x64\xe5\x33\x44\x96\xa5\x16\x7f\xfb\xd1\xec\x86\x7f\x90\x06\xb1\xf5\xd1\x19\x66\xb0\xda\xf6\x6c\xb3\x11\x46\xdd\x3f\x65\x23\x2a\x36\x7a\xcd\xe6\xb6\x3e\xfe\x9a\xa5\xed\x2d\x67\x50\xab\xfd\x67\xcd\x81\x47\xc5\x8d\xb5\xed\xd9\x27\xc7\x78\x5f\x1d\x63\x2d\xe6\xfd\x16\xe1\xee\x9d\xfc\xe2\x3c\xf2\x7c\xd8\xe1\xff\xef\xee\xdd\x03\x4e\xc0\xde\xee\xed\xef\xc3\x8e\xfa\x87\x7d\x03\x75\x90\x6e\xef\xb4\x15\x72\x9f\xc8\x69\x02\x6d\x4e\xdb\x41\xd6\x9a\xfe\x36\x42\x56\x77\x1f\x18\x98\x63\xab\xb1\xeb\x2d\x80\xad\xd0\xca\xbf\x04\x9a\xc5\xaa\x6d\x0f\xd1\xb7\x5c\xb9\x5a\xed\x6f\x5a\x3b\xb3\x8d\xed\x56\xef\x5f\x72\x92\xbe\x03\x10\x13\xd0\x15\xe1\x05\x2c\x69\x1b\x1a\x7e\xa6\xa6\x7f\xf1\x3d\xdf\x1f\x36\xd7\xc3\x52\x88\x3a\x77\x50\x3a\xc9\x28\x73\x8c\xaf\x8b\xc1\xde\x70\x1d\x7e\x32\x5b\xe9\x3e\xee\xf9\xbe\xb5\x95\xfb\xc3\xf6\xe5\xb3\x77\xba\xc5\x78\x37\x91\xbc\x2d\x90\x02\xdb\x1e\x9d\xd7\x6a\x19\xd1\x03\xda\x5b\x10\xb1\x0c\xdf\xf6\x32\x8f\x1a\x23\xda\x40\x56\xad\x4b\xe5\xaf\x9b\xfb\xba\x89\x48\x08\xd9\x88\xdd\x74\x5f\x8b\x35\x9d\x6d\x4b\x66\x9b\x35\xe2\x28\xbf\xdc\xfa\xbc\xd8\x3b\xac\xf4\x19\x6d\x85\x79\xb6\x9c\xd5\xf6\xc4\xd7\x56\xe7\x1b\x67\x66\x76\x4a\xe6\x56\x97\x2a\x74\x90\xe2\x7c\xa5\x81\x02\xcd\x6f\xeb\xc1\x56\x95\xb1\x01\xac\xd6\x82\x81\x97\x6a\xdf\x2b\x43\x46\x09\x96\x95\x92\x66\x96\x1b\x7c\xc1\x55\x1a\x36\xf2\x96\x2b\xf3\xe8\x2f\xce\xd9\x9d\x5a\x72\xaf\xdc\x9f\xdd\x74\x28\x6f\xb1\x21\x77\x0b\x0d\xb9\xc1\xdb\x78\x15\xe5\x17\x5a\x72\x12\xe7\x11\x61\x50\x7a\x5b\x34\xb2\x0f\x34\xb2\x66\x19\xcc\xbd\xd9\x4d\xe7\x87\x2d\x07\xa3\xb7\x53\x1f\xd0\xc3\xd9\x4d\x67\x6f\xdb\x01\x29\x70\x6f\x59\x9e\x9e\xbf\xe5\x90\x8c\x96\x6c\x8b\xb4\xb7\xb7\xe5\x98\xb4\x2c\x39\xec\x07\x6f\xad\x82\x52\xe4\xad\x27\xf7\x97\x3a\x0b\xcd\x6d\x51\x42\x86\x19\x18\x91\xfd\xa2\xbe\xdb\xbb\xf7\xa9\x91\x2b\xd7\x40\xd0\x2e\x1d\x11\x50\x85\x15\xd8\xab\x2a\xc8\x95\x15\x9b\x5a\xde\xbd\xaf\x37\xfd\xa8\xbd\x65\x5e\x9c\x34\x6d\x14\x08\x96\x2c\xe1\x4e\x30\x4e\x72\x2d\xd7\x8d\x5c\xb0\xde\x23\xad\x06\xf3\x5b\xdc\x54\x65\xcf\xd7\xaa\xf0\x55\xdc\x50\x63\xaf\xaa\xdb\xcb\x32\xb5\x59\x05\xbc\x97\xdc\x60\xb6\x8c\xb6\x52\x67\xf2\xa3\xcb\xd3\x1f\x4a\xef\xf3\x9d\x30\xc4\xae\x8b\x95\x62\x13\x15\x4c\xad\x29\x95\x81\xb5\x9c\x31\x66\x3b\x2d\x2a\xb8\xf6\xb0\x05\xec\x12\x62\x9d\xa2\x28\x61\x8a\xa2\x14\xee\x44\xae\x9b\x08\xaf\x7d\xe9\xb5\x5c\xe8\x5a\x8c\x2c\x6a\x4d\x03\xd3\x1a\x8e\x40\xea\x24\x1e\x35\xa4\x52\x99\x1d\x98\xba\xd2\xb2\xcc\x49\x34\x96\x48\x05\xf9\x30\xf8\x86\x05\x19\x2e\x3d\x7d\xd3\x80\x09\xa9\x8f\x2a\x23\xe5\xcc\xd3\x24\x4a\xf1\xc5\x63\xba\x2b\x05\xd9\xbb\x32\xd2\x8d\x97\x22\x23\x2d\x43\x31\x3f\x2f\x98\x09\xd4\x1e\xe8\x96\xf8\x15\xbe\x46\xf9\x61\x54\x20\x0f\xf0\xec\x0b\x38\x6a\x5c\x15\x66\x21\x52\xfa\xea\x3c\x44\x62\xb7\x4f\x50\x34\x2a\xcf\x72\x84\x20\x56\xfb\x9d\xbb\x6e\x0e\xa3\x10\x75\xa7\x78\x5e\xa0\xa3\x2b\x94\x95\x30\x51\x7a\xd7\xa8\xef\x70\x95\xbc\x13\x44\x30\x0d\x51\x97\xff\x7c\x7c\x1d\x2d\x60\x11\xa2\x6e\x89\xe7\xa3\x09\xab\x37\x32\x42\x07\xe1\x8c\x1a\xdd\x1d\x65\x34\x7e\x50\xcc\x12\xcf\x10\x98\xdc\xe9\x01\x38\x56\x3f\xe9\x4d\x90\x48\x4c\x23\xbe\x4f\x8c\x9f\x07\xf4\xc7\xd1\x78\x8c\x46\xa5\xed\xae\xb1\x40\xe5\x59\x32\x45\x78\x6e\x7e\x9d\x89\x8b\xa3\x90\x5e\xe6\xfa\x5a\xec\x64\xe3\x63\x8f\xa6\x46\x1d\xf2\x94\x8c\x3c\x43\x4e\x94\xa6\x84\x7e\x9b\x37\xf3\xf2\x2a\x2a\x9c\x77\xc7\x49\x16\x3f\x7d\xfb\xfa\x0d\x8e\x91\x87\x00\x6b\x81\x65\x48\x3c\x65\xe7\x83\xde\x9d\x4d\x01\xbc\x20\xef\x0e\x51\x4b\xa8\xa0\x89\x68\xf2\x20\x19\x7b\x13\x6d\x50\x50\x8e\xd0\x75\xc7\xea\x71\xc7\x72\xc3\x1f\xe3\x11\x35\xcc\xec\x8a\x07\x7e\xc0\xba\xa3\x34\xa1\xb7\x8b\x71\x39\xf9\x11\xf1\x5f\x1f\x57\xab\x0d\xe5\x99\xff\xb4\xac\xf0\x5b\xe5\x21\x00\x92\xb1\x17\x8b\x51\x80\x58\x1b\x27\xcd\x2e\xbc\xf4\xf8\x6d\x66\x81\xe2\x77\x51\x39\xe9\x9b\x3f\x3d\xd0\xa5\x91\x84\xdf\x8e\x3d\x39\x15\xf0\xd3\x6e\x2f\xd8\xf1\x7c\x98\x96\x64\x69\xd4\xfb\xe6\xa8\x18\xf9\x2a\x3c\xd4\x2d\x09\xa2\x2c\xc1\x6a\x25\x8b\x5b\xbe\x82\xd5\x6a\x07\xbb\x6e\xb9\x5a\x31\x63\x06\x00\xe0\x62\xad\x61\x44\x09\x96\xda\xca\xfb\x07\xcc\x9c\x24\x63\xd7\xfe\x03\x34\x3c\x20\xa7\xc4\x2b\x89\xdc\x75\x1e\xd2\xbb\xd1\x2b\x61\x6d\xb6\xd3\x63\xf9\x99\xbc\xf3\xc1\x68\x18\x2e\xbc\x11\xbd\xd4\xb4\x43\x6b\x42\x80\x99\x14\x17\x86\xa0\x79\xe4\x8d\x00\x2c\x43\xcb\x22\xc0\x4c\xbf\xc4\x8d\x75\x48\x56\xd8\x34\x8a\x63\x7a\xf2\x5e\x25\x45\x89\x32\x94\x7b\x08\x5e\x90\xee\x1b\xef\x1d\x7a\x4a\xa7\xf8\x0a\xd1\x30\x95\x7a\x44\xbd\x6e\x8e\xc8\x7b\x6b\x3b\xb6\x4f\x66\x53\x94\x20\x0d\x2e\xe0\x68\x08\x20\x9d\x5b\x42\x97\x22\x21\x4b\x91\x6c\xb1\x14\x89\xb6\x14\x49\xcb\x52\x6c\x9a\xef\x56\xb3\x11\x03\x4d\x86\x4d\x55\x79\xd9\x7d\x96\x47\x17\xe4\x51\xde\x0a\xa7\x38\x93\x9f\x33\x78\x0e\x40\x45\x81\x22\xda\x8e\xbc\x32\xb1\x6c\xc3\x5d\xe1\x14\x15\x45\x74\x81\x68\xa4\x96\x1c\xa7\xa8\x16\x79\x2d\x4a\x51\x5e\x5a\x22\xaf\xb1\xb6\x5b\x6f\xbb\x78\xab\x0e\x74\x48\x9b\x5b\x06\x60\xa3\x89\xb7\xe6\x50\xc5\x61\x53\x41\xd7\x1e\xd8\x82\xae\xf1\xeb\x9b\x44\x0b\x8d\xd6\xbc\x7f\xa8\x07\x4b\x8c\xc4\x8c\x2b\x98\x02\x88\x1b\x06\xd7\x96\x0a\x6c\xae\x15\xc4\x20\xa0\x54\x42\xd1\xfa\xa4\xe5\xc6\x82\x27\x5e\x6f\xd3\x39\x76\x1f\x05\xdd\x1f\x1e\xc1\x3c\xe4\xd9\x33\xef\xeb\xea\x9f\x66\x06\x3f\x28\x73\x05\x6c\x93\x2c\x54\x05\x34\xda\xa4\x91\xc9\x9b\xfa\x97\x7c\x8b\xd8\x49\x8d\x98\x1e\xdf\x74\xa1\xa2\xb2\xbe\x57\xb5\x3c\xfa\x2a\x8a\x92\x2c\xe3\x24\x59\x52\x26\x51\xaa\x5d\xe4\xec\x3d\x7a\x44\x30\x2a\xdf\xcc\x9a\x20\xe1\x3b\x15\x64\xbb\xb6\x15\xf7\xa5\x71\x49\x3c\x4e\x9b\x91\xf8\xf2\x81\xc9\xc5\xd7\x63\x2f\x9d\x66\xd1\xe8\xf2\x3c\xca\x45\x54\x9f\x0a\x78\x51\xc4\xa8\x78\x7a\xeb\x83\x6a\x84\x63\x4a\x42\x2f\xd2\x99\x20\x2d\x22\x13\xcf\xd5\x6d\x04\x65\x12\xb1\xad\x82\x08\xc8\x88\x35\x30\x0d\xf5\x08\x35\xf4\x98\x93\x29\xbe\x48\x62\xf4\x94\xdf\x29\x99\x47\x9e\x26\xbc\x63\x41\xc5\x24\xfb\x16\x6b\x28\x64\x6c\xa0\x90\x59\x98\x75\x25\x27\x26\x50\xdd\x3b\x42\xb0\x68\x68\x26\xbe\x26\xec\x85\x66\x0f\xf0\x81\x1a\x6f\x3d\x49\xe7\xb9\xa8\x63\x35\x0b\x10\xc8\x69\x11\x66\x5d\x6e\x5a\x43\x0d\x01\x70\x76\x44\xa6\x0a\xaf\xd5\x33\x8a\xa9\x11\x00\xff\x45\xc4\x89\x23\xf6\xf3\x26\x29\xe9\xed\x3f\x7b\x44\x31\xbd\xfc\x67\x3f\x48\xa9\x43\xfa\xeb\x35\x65\x3b\x69\x9b\x9f\xd4\x8b\x57\x28\xba\x42\xf0\x1d\x79\x31\x43\x19\x3c\x21\x28\x92\xba\x7e\x18\xab\xf7\x36\xcc\xba\x67\xf2\xaa\x4e\x1a\x76\xc0\x33\xb5\xaa\x6f\xfb\x71\x16\xbc\x85\x6f\xc2\x4c\xbb\xd4\x93\x0d\x7c\x56\x05\xdf\xf4\x97\x2c\x15\xe9\xe3\xb2\x7b\xf3\x43\x2d\x26\x0b\x44\x37\x49\xc9\xbf\x98\x1e\x8c\xc1\x1b\xf8\xda\x18\x05\x5b\xf0\xe3\x16\x9c\x5d\x8b\x49\x55\x87\x87\x6d\xe2\x52\xd9\xf7\x9c\x7c\xd0\x76\x5c\x19\x31\x34\xf7\xdb\x20\x12\x7c\x6f\xe9\xd3\x11\x3b\x93\x8e\xdc\x57\xf5\xcc\x84\x3b\xb6\x77\xf2\x41\x14\x60\xfb\x49\x9f\xd5\x6e\xaa\x9f\x74\x2f\xc9\xcf\x19\x9d\x55\x73\x1f\x1d\xe8\x58\x76\xd1\x81\x4e\x73\xc7\x8c\xa2\x6c\xa6\x43\x00\x1f\x2b\x61\x01\xc0\x57\xec\x07\x33\x90\xdc\xf1\x01\xfc\x1a\xbe\x1a\xf8\x43\xf8\x34\x7c\x35\xe8\x0d\xe1\x33\x1b\x33\x0e\x96\x34\x29\x37\xf3\x62\xe0\xc6\x85\xca\xd9\x89\x60\xbb\x27\x2d\x3c\xfc\x42\xb8\xb5\x20\xd7\xf5\xa8\xb9\x9e\x10\x44\x1e\x2b\x56\x4e\x3e\x86\x2d\x82\xca\x33\x8f\x99\x82\x95\xec\x9b\x43\xa4\x09\xc4\x44\xdb\x0d\x92\xcf\x3b\xd7\x7d\xe2\xcd\x0d\x1e\xa8\x65\x14\x94\xff\x79\x07\xe7\xf0\x09\x17\x74\xbe\x34\x2c\x0d\x2d\x95\xe0\x87\x56\x71\x08\x2c\xd9\xcc\xe7\x64\x08\xec\xf1\xa4\x7f\x12\x74\xf7\xff\x31\xa7\xd2\xd0\x1c\x9e\xd0\xbe\x24\xff\xd1\xce\x09\x5e\xb9\xee\x3b\xe1\x62\xc0\xad\x4b\x9b\x2c\x2c\x55\x3f\x3a\xf0\x03\x80\xad\x45\xce\xd3\x79\xee\xc0\x2f\xc6\x72\xf0\xc2\x56\x56\xb6\xd1\xa4\xb5\x94\x68\x95\xae\xe0\x15\xfc\x00\xdf\x11\x66\xf7\x9d\xeb\x7e\x65\x28\xbb\x61\xd9\xa7\x25\x63\xd7\xa4\xe5\xa0\x06\x37\x0b\x0f\x91\x93\x9d\x8c\x2e\xa3\xeb\x68\xe1\x10\xe1\x62\xd6\xc6\x46\xad\x53\x91\xc4\x8c\x19\x8b\x37\x05\x53\x4b\x2c\x41\xd2\x68\xe8\xdb\x31\x80\xfa\xc9\x35\xc6\x79\xe8\xba\x87\x1e\x02\xf0\x8b\x07\x2a\xa8\x1f\x68\xa3\xd4\x27\xd7\xfd\x44\x4a\x7d\xa0\x36\xef\x8c\x25\x3c\xb6\x84\x75\x56\xf3\x88\x66\x33\x14\xd1\xd0\xd8\x49\x16\xbc\x83\x1c\xcd\x90\x49\xc5\x65\xfd\x6c\x3e\xf5\x76\x7a\x04\xa2\xce\x01\x94\xa8\x29\xb8\x86\x0a\x35\x05\x37\x90\xa1\xa1\xe0\x08\x0a\xd4\xd4\xda\x94\x4f\x9a\xba\x04\x50\x22\xae\xe0\x14\xf2\x73\x17\x7c\x86\xb1\x8a\xa2\x56\xe2\x99\xc3\x03\x82\xe2\xeb\xcc\x09\x1c\x9a\x79\xf8\x35\x80\xa3\xd5\xaa\x3e\xb3\x44\xdb\x72\xc1\x18\x5d\x08\x46\x08\x57\x70\xc2\x62\xf3\x4b\xf6\xb5\x58\xcb\xbe\xd2\x18\x0d\x8f\x2a\x98\x87\x22\x88\xc0\xa3\x0a\xe2\x70\xd9\xaa\xa1\xaa\x60\xd4\xf2\x95\x2a\x5f\x9d\x0a\x26\xac\xd1\xbd\xfb\x15\x4c\x65\xab\xe4\x57\x11\x2e\x59\xa0\x0d\xf2\x63\x1e\x2e\x69\xa0\x02\xf2\x3c\xe2\xcf\x34\x3f\x8d\x08\xc6\xc1\x78\x34\x2d\xdc\x80\x8c\x32\xf0\xd1\xe3\xd1\x1c\xcc\xd0\xc5\x3c\xae\x5a\x29\x02\x0e\x17\x9c\x65\x83\x8d\xa8\xc2\x35\x6e\x31\x65\x9a\xda\x9c\x6b\x86\xd7\x46\xaf\xab\x47\x18\xad\xc5\xbf\xe0\x39\xc6\x35\xe6\x3d\xd3\x78\xf5\x56\x26\x58\x2b\x9f\xc0\x11\x00\xc0\x12\xf1\xa1\xd9\x74\x7e\xcb\xa6\xd3\x66\xd3\x22\x08\x8d\x39\x62\x7c\xab\x86\xb5\xd0\xc7\x64\xf8\x85\x7d\xf8\x8d\x6e\xf2\x3f\xd2\x4d\xda\xec\x86\x47\x1f\x31\x67\x12\xdd\xaa\x0b\x1d\xf2\xc8\x54\xe6\xf6\xa9\xd4\xbb\xc9\xff\x50\x37\x29\xed\x86\x4a\x1b\xe3\x34\x99\x05\x3b\x3d\xd8\x90\x3a\x88\xb8\x91\x72\x71\x63\x1e\x85\x99\xb7\xf7\xe8\x91\xa6\xc8\x1d\x45\x4a\xc7\xc7\xf3\xc2\xc0\x2c\x44\xcc\x54\xb9\xa0\x7a\xd9\xe9\x3c\x79\x86\xf3\x29\x15\x0d\x71\xaa\x12\xc3\xe4\x28\x9e\x8f\x0c\x9f\x20\xdd\x4f\x58\xf8\xe1\xc2\xdc\x75\x25\xfb\x4a\x5e\x08\x27\xdd\x7c\x90\x0d\x01\x44\x64\xf0\x15\xa8\xc8\x08\xe2\x48\x7a\xf2\x88\xcc\xdf\x02\x13\x8d\xa3\x30\xd6\x7c\x18\x67\x91\x91\x87\x66\x16\xe5\x05\x3a\xce\x4a\x0f\x0d\xca\x21\xec\xf9\x60\xb5\xf2\x69\x8b\x93\x28\x74\xe6\x59\x8c\xc6\x49\x86\x62\xe5\xe5\xcb\xc8\x68\x9f\xd2\xfa\x57\xd1\x02\xcf\x4b\x46\xf1\x03\x8d\xfa\xc3\x69\x14\x2e\x69\x0c\x92\x24\x4d\xca\x45\xe0\x4c\x92\x38\x26\xac\xa1\x2d\xbe\x24\xbe\x42\xf9\x38\x25\x82\xa8\x28\xc5\xc3\xfe\xf9\xb0\x2d\xac\x98\x44\x49\x9f\x3c\x9f\xe0\x23\x36\xcf\xab\xed\x04\x42\x91\x55\x82\x8a\x84\x39\xbe\x66\x8a\x1b\xf2\xf0\x3a\xba\xa1\x6a\x1b\xfa\x9c\xb0\x00\xbb\xd3\xe8\xe6\x84\x94\x99\x93\xe7\x24\xa3\xcf\x86\x55\x77\x8f\x9b\x73\x17\xe5\x22\x45\x54\x80\x63\xde\xb6\x33\x53\x3e\x10\xbd\x52\xad\xcd\x75\xc1\xff\xbc\xa6\x11\x66\x79\x7f\x2c\xe2\xec\x09\xfb\xca\xfb\xa2\x06\xc6\x8b\x94\x59\x15\xa7\x73\x44\x78\xe1\x49\x58\xac\x56\x09\x9c\x86\xd1\x6a\x95\xae\x56\x23\x78\x65\x6a\xda\x77\xc2\x31\x90\xfe\x14\x17\x75\x2d\xfc\x42\xa9\xaf\x73\x78\x01\xe0\x79\xbd\xc0\xb5\x7a\xe1\x03\x78\xa3\xf3\xda\xcb\x0a\xc0\xa3\xf0\x86\xf0\xda\x97\xe1\x0d\xe1\xb5\x4f\xd7\xf0\x8e\x4c\xeb\x77\x21\x87\x52\x86\x9c\x05\xa3\xba\x92\xe9\x6c\x5e\xa2\xf8\x94\x4c\x8e\xa5\x2e\x3e\x97\x5a\xf2\x9c\x2d\x66\x97\x5e\x32\x86\x25\xfb\x0b\x73\xb6\xb0\xc2\x9d\x79\xb5\xca\xba\xb3\x34\x1a\xa1\x09\x4e\x63\x94\xaf\x56\x0e\x59\xca\xff\xc9\x08\x41\xe7\x45\xbb\x45\x9a\x8c\x90\xb7\xdb\x03\xae\xeb\xf1\x77\x77\x43\xa7\xe3\xb0\x13\x8d\xc3\x72\xc0\x2c\x45\xa9\x51\xab\x33\x84\x51\x38\x8b\xbc\x12\x3a\x5c\x43\xb1\xcb\x15\x01\xe0\xae\xf9\x9a\xb0\x0d\x00\x26\xbc\xb0\x34\x85\x25\x65\x77\xe9\x58\x65\x0d\xfe\xad\xc4\x33\xf1\x01\xa6\x61\xde\x2d\x46\x39\x4e\x53\xa6\x83\xdf\x8d\x0e\xc4\xcc\x9c\x1b\x87\x0e\xac\x68\x14\x81\xf3\x30\x3d\x98\xba\xae\x37\x0f\x5f\x47\xe5\x84\x40\xa5\xf7\x66\x3e\x3d\x47\xb9\x37\x05\xff\x28\x08\x2a\x83\x13\xed\x73\x92\x89\xcf\x13\xfe\x99\x36\x3c\x0a\xf5\x06\xe6\x04\x99\xdf\xf5\x74\x5b\x5e\x1a\x9b\x3a\xba\x9b\x04\x3e\x80\x31\x2b\x19\x9d\x17\xde\x7c\x37\x05\x3f\x86\xbd\x83\x4b\x6b\x12\xe4\x6b\xb1\x71\x3f\xee\xf9\x44\x44\xfa\xc9\x77\x5d\x59\xd5\x43\x5d\x3c\x2f\x51\xce\x66\x42\xb7\x7b\xb5\xf2\xc1\xee\x08\xfc\xd4\x5b\xad\x50\x57\x9c\xfe\x9d\x30\x8c\x41\xdf\x93\x6d\xdd\x0d\x7b\x70\x29\x51\x43\x0c\xeb\x8d\x04\xa3\x0a\x04\x88\x7a\x5c\xc1\xc1\x04\x4e\xa1\x01\x0d\x9b\x65\x12\x06\x9c\x9e\x0f\x5f\x34\x38\x48\x39\x86\xd0\x87\xa7\x1e\xd0\x12\x7a\xb5\x4a\x25\x39\x62\xde\x00\xc8\x90\x4b\x50\x97\xca\x5c\xde\x7a\xd9\x43\xd5\xa5\xd2\xc7\x29\x39\xe1\x91\x31\x20\x36\x88\x56\x45\xbb\x36\x5e\xd2\xc0\x78\x3b\xf5\xb7\x29\x82\x10\x82\x11\xe5\x28\xd2\xe4\x10\xe6\xd7\x3b\x86\x02\x73\x19\xe2\x80\xbe\x46\x57\xab\xd5\xa9\x07\x20\x76\x5d\xec\x21\x2e\x1d\x2c\x20\x41\x6a\xc1\x14\xd2\x93\xac\xa8\x36\x47\xed\x47\x0d\xa0\x50\x64\xe0\x48\xc2\x44\x5f\x50\x04\xaa\x1a\xae\x60\x0c\x88\xfc\x64\x11\xa0\xd4\xe8\x97\x4e\x94\x27\xd1\xae\xa8\x67\x24\xb8\xd1\x55\x6b\x39\x8a\xe2\xb7\x59\xba\x20\x25\xc8\x78\xcf\x61\x19\x9d\x33\x46\x76\xb7\x57\x1f\x74\x05\xa7\x11\xe9\x9c\xb1\xf7\x92\x90\x5e\xe8\xf7\xb8\x52\x45\xb0\xe3\xb1\xc4\xb2\x49\x41\xff\x7a\x08\xb8\xae\x4f\xb3\x84\xf0\x34\x5e\x2a\x70\xc3\x42\xe3\x1f\xa4\x2e\x42\xf8\xa8\xf7\x04\xe9\xdf\x09\xd5\xc7\x41\x6f\xe8\xba\xfa\x2f\x01\x99\xc8\x75\x3d\x32\x1e\x1e\xf6\xc1\x75\x1d\x67\x27\x54\xa8\xb2\x74\x5d\xfa\x95\x2b\xbd\x7f\x35\x0b\x19\x6f\x29\xed\x3f\x37\x68\x7f\x68\xa3\xfd\x3a\xd5\xd7\xf9\x00\x78\xbd\x15\x19\x1e\xb0\x8d\x8a\x51\x31\xca\x93\x73\x14\x9f\x2f\x28\xfe\x65\x0a\x54\x42\x1d\x52\x54\xb2\x1c\x0e\xe4\x05\xf5\xd3\x51\x76\x0a\xa8\x50\xc1\xef\xe9\x76\xce\x43\x4f\x78\x66\x65\xe6\x74\xa8\xae\x55\x5a\xdf\xc5\xcc\x1d\xea\x71\x8c\xf3\x8c\x9e\x86\x31\xa9\x48\xc3\x11\xc3\x4c\x77\xe9\x98\x29\x85\xe9\xd8\x75\x79\x28\xfc\x98\x6a\x59\x93\x6c\x36\x2f\x95\x26\xd2\x08\x87\xef\xd0\x8f\x0e\x8f\x89\x4f\x7f\x30\x6d\xa1\x11\x16\x7f\x59\xf1\x68\xf8\xb4\xc0\x09\x1a\xc3\x6b\x32\x0c\xa6\x08\x87\x59\x77\x3a\x4f\xcb\x24\x4d\x32\x44\xc8\xaf\x1c\xc7\xb5\xeb\x5e\x53\xbd\x2b\x61\x53\xb9\xd6\xf5\x49\x3a\xcf\xb9\xce\x95\x33\x35\x87\x5c\x9b\x9b\x8c\x2e\xb9\xb6\x95\xad\x1d\x55\xb4\x66\x3f\xa3\xc5\x53\x7c\xcd\xb4\xad\xf4\xd7\xfb\x19\x55\xb1\x6a\xa8\x13\x9e\x51\x4d\x2c\x3b\x1e\x54\xab\xca\x1c\x4e\x4f\xe7\xe3\x71\x72\x03\x3f\x0b\xa6\xe9\xb5\xc6\x34\x1d\x6b\x4c\xd3\x63\x8d\x69\x7a\xa5\x31\x4d\x5f\x85\x93\x98\x5a\xfc\xa7\xc2\x53\xec\x99\x5a\x9d\xa7\xc2\x0b\xec\x29\x7c\x22\x79\xa9\x2f\x35\x5d\x6b\x1d\x72\x98\x9a\x55\x40\x0d\xff\xf9\x8c\x69\x7e\x36\xb8\x8c\xe9\xc0\x62\x7a\x8d\xe9\x70\x42\x7e\x12\x20\xa9\xb9\x80\x25\x31\xcd\x18\xa0\xc3\x83\x78\x21\x74\xb4\x62\x8b\x29\x73\x97\x33\x9d\xb0\xdc\x5f\x07\x3a\x19\x1b\x0e\xdb\x4a\xa6\xad\x15\x7c\xa2\xb0\xca\x20\x4f\x62\x32\x72\x0b\xc5\xf3\xfb\x99\x03\x1d\x6d\xfb\xa8\xfa\x95\x6d\x1e\x7d\x54\x5b\xf7\x2d\x9c\xa7\xbe\x5d\xba\x7f\x1b\xe7\x44\x3f\x84\x0c\xed\x2d\xd8\x3e\xf5\xf9\xdf\xe0\x09\xbc\x53\x67\x49\x3f\x28\x96\xf4\xbd\xae\xcb\xfd\x75\x9d\x2d\x06\xb7\xb8\x78\xa1\x58\xd6\x05\xb5\xb8\xf8\x15\xc0\xdf\xd5\xbb\x73\xf8\x02\xc0\x9f\xd5\xef\xf7\xf0\x77\x00\x7f\x31\x74\xc4\x3d\x00\x9f\x87\xbf\x10\xbe\xf5\xb7\xf0\x17\xc2\xb7\x7e\xe4\xdd\x72\x51\x29\x8e\x00\x7c\x19\x8e\x22\x6f\x49\xa5\xb8\x20\x83\xa6\xe0\x16\x7c\x84\x4c\xa8\x0b\x06\x0a\x72\x34\x50\xe1\xb0\xc1\xc8\xce\xab\xe8\x1c\xa5\xfa\x7e\xe7\xe8\xf7\x79\xc2\x94\xed\x3c\xcf\xee\xb0\x02\x07\x2f\x99\xc3\x17\x8a\xc3\x8f\xfd\x8f\xe2\x39\x78\xde\x4a\xe6\x77\x3e\xba\xee\xc8\x75\x9f\xbb\xae\xf7\x1b\x9d\xd1\xa5\xeb\x5e\x7a\x8c\x01\xfa\x08\x47\xf0\x39\xbc\xe4\x6a\x5f\x84\xc2\x8f\xae\xfb\x91\x9c\x7d\xda\x1d\x2c\xe5\x8b\xa3\xe9\xac\x5c\xc0\x0c\xad\x5b\x75\x4a\x96\xfa\x08\xb9\x2e\x42\x1e\x08\x4a\xe4\xba\x25\xa2\x2e\xfe\x03\x84\x60\x89\x86\xe0\xe0\xdc\x64\x50\xee\xb8\x6e\x86\x04\xc7\xf0\xa1\xa2\x45\x3f\xc0\x0c\xc1\x3b\xc3\x76\xb6\x25\x43\xde\x7b\xa5\x85\x56\xd6\x39\x39\x0a\xaf\x20\xa6\xbc\x99\x20\xbf\x0b\xe6\xad\xfe\x73\x25\x38\x31\x87\x59\x4c\x29\xa9\x34\x47\x7d\xbd\x8a\x38\x75\xc1\xcf\xcc\x7f\xee\x59\x05\x31\x62\x8d\x50\x56\x02\x04\x37\xfd\x9d\xcf\xab\xd5\xe3\xd5\xea\xd5\x6a\xf5\x7a\xb5\x3a\xee\x7b\x7a\x7d\x7e\x06\x82\xcf\xab\xd5\x2b\xc8\x8f\x4b\xf0\x1a\xf2\x43\x12\x3c\x26\xcd\x01\x48\x46\x1a\x81\x20\x47\xa1\xe2\x40\x02\xbd\x19\xd5\x77\xfb\x32\xd0\x8d\x29\x10\x3b\x67\x44\x20\x8a\xf2\xd2\x7b\x82\x71\x8a\xa2\xcc\xfb\x2a\xb6\xf7\xab\x85\xa9\xdb\xac\x37\x4e\xb9\x69\x5d\x6b\x4e\x8c\x97\x8c\x68\xae\x56\x32\xcc\x20\x00\x43\x58\xc0\x97\x92\x64\xba\x6e\xaa\xc8\xe7\x4b\x46\x2a\xc9\x3b\x46\x33\x67\xe4\x51\x79\x0e\x4b\x90\xa6\xaf\xd9\x23\xfc\xc8\x7e\xc8\xb3\x04\x6f\xc8\x0b\x89\x03\xe1\x57\xf2\x33\xd2\x66\x0f\x63\xed\xcd\x51\x16\x13\x24\x9d\x15\x88\x08\x27\x2f\x39\x91\xa4\x2d\xd0\xa7\xa7\xe4\x13\x90\x0e\xfb\x3a\x1c\xbf\x57\x16\x55\x48\x3c\x9e\x51\xf3\x21\xca\x8e\x31\x4b\x22\xd7\x95\xc5\xd8\x88\x3d\x00\xb9\x46\x5c\xea\xb9\xbf\x00\xf8\xb5\xb1\xfa\xe3\xa8\xfb\x2e\xc7\x34\x16\x80\x08\x6c\xc4\xb8\xd4\x7a\xc1\x5c\xf3\x93\x65\xa4\x2b\xc9\xae\xa2\x34\x89\x9d\x80\xaf\x27\x6c\x52\xb4\x00\x43\x9d\xa4\x05\x11\x94\x24\x2d\x48\xa0\x4e\xb4\x82\xb9\xb2\xd2\x56\xdb\x06\x93\x38\x98\x40\x9c\x3d\xce\x92\x29\xbd\x56\xa3\x2b\x6b\x2c\x4f\x86\x3c\x9a\x02\x8f\x34\xbc\x4b\xf0\xd2\xee\x28\xca\x46\x28\x65\x29\xed\x22\x51\x91\x40\x54\x5f\xae\x51\xc0\xa7\xea\xdc\x38\x15\xa8\x98\xc6\xec\x08\x6a\xf4\x27\x78\xab\x78\xeb\x33\x28\x30\x5f\xf0\xb2\x2b\x1e\x99\x60\xf0\x19\x72\x64\x01\x25\x45\xa3\x77\x04\x94\xa2\x05\x27\xec\xb8\x5a\x21\x9a\x1e\x6d\xb8\xd0\x98\xbf\x16\x60\xa5\x60\x46\x4b\xbf\x96\xb0\xf6\xb2\xab\xa1\x68\xf9\xfd\x85\x7a\xc7\xa0\x91\xbe\x7d\xdc\x00\x49\xfd\x35\x85\xcb\x02\x45\xf9\x68\x42\x16\xec\x99\xfc\x7e\xb6\x98\xa1\x53\xfa\xbe\x05\x6e\xd9\x90\x4c\xe0\x25\xc4\xdf\xd8\x1c\x8a\xdb\x11\x80\x0b\xce\xe4\xb9\xae\x78\x22\x6f\x39\x32\x27\x3f\xfb\x1f\xd5\xfb\x80\xd2\x85\xca\x2e\xb1\x25\x63\x6f\xe7\x8e\xd2\x56\x32\xe8\x5f\xad\xde\xeb\xb6\x89\x2c\x58\x5e\xa9\x85\x2d\x63\x21\xcb\x3c\x1f\xce\xe9\x4d\x46\x0f\x80\x03\x85\xe9\x4b\x46\xee\x2b\x50\xc9\xa0\x83\x0d\x39\x06\xe6\x21\x69\x87\xc9\x42\xd9\x4f\xbd\x7e\xb6\xdb\x0b\x7c\x00\x71\xd8\x3b\xc0\x3f\x66\x07\xf8\xee\x5d\x90\x0f\xf0\x6e\x6f\xa8\x49\x39\x78\x78\xb0\x90\x2c\x2d\x9b\x3a\x7b\xe6\xf7\xb7\x0b\x38\x40\x43\x81\xcc\x72\x00\xe0\xa9\xeb\x9e\x9a\x77\xbb\x66\x01\xb2\x26\xec\xf0\xe8\x4b\xa2\x00\xa7\x8f\xba\x45\x89\x67\x84\x69\x8b\x2e\x22\x86\x99\x03\x4f\xdc\x79\x2d\x04\x17\xcd\x86\x42\x1f\xb5\x6d\xa0\xbf\xfb\x1f\xb5\x2f\x64\x23\x7c\xaa\x5c\x06\x00\xc6\xf0\x4d\xff\x8d\xa7\x51\xb3\x97\x70\x69\x72\x56\xc1\xd7\x0a\x34\xcc\x9f\x6e\xbe\xc9\xfc\x09\xe6\xa1\x70\xcd\x30\x9c\x30\x20\x66\x3e\x6d\x41\xd6\xef\xde\xdf\x0b\xba\xfb\x1b\xfd\xaa\x1d\x5e\xc3\xd9\xd2\x6d\x1a\xe5\x04\x21\xe0\x70\x29\x7a\x72\xfc\xce\x4e\x32\x9d\xe1\xbc\x8c\xa8\xb3\x72\xa4\x3e\x89\x41\xc8\x9b\x24\xe7\x7f\x5f\xa4\xf8\x3c\x4a\x9d\x60\xe9\xfc\xef\x4b\xb4\x18\xe7\xd1\x14\x15\x1d\x03\x3d\x39\xc1\xb2\x82\xad\x5f\x05\xf2\x0a\x96\x55\x05\x37\x5a\x72\xf5\x60\xc3\x80\xcb\x70\xd7\xd6\x52\x0c\x39\xbd\x6e\xef\xd1\xc3\x07\x68\xda\x9a\x09\xc9\x96\xff\x69\x34\xcf\x0b\xea\x18\x48\x64\x99\x96\x6c\x50\x36\x6b\xa9\xf5\xce\x64\x74\x8c\x12\xc1\x89\x3e\x44\xf4\x84\xaa\x02\x50\xa3\xb3\xd4\x63\x83\x73\x95\x35\x57\x1e\x9d\xda\x6a\xbf\x8f\x32\xfa\x15\xb1\xcc\x3e\x15\xd4\x28\x2c\xfd\x29\xd0\xa8\x66\x10\x26\x59\x8a\x07\xd0\x99\xdd\x74\xfc\x8e\x0a\xbb\xf0\x90\xbc\x61\x1e\xbd\x5a\x43\x8e\xac\x7c\x86\x67\xc1\xbd\xaa\x99\xae\x68\x8d\x9f\x09\x45\x9d\xcc\x5d\x42\x73\x03\xa1\x6b\x93\x73\x07\x05\xed\xbd\xf5\x1c\xdc\x66\xe4\xdc\x71\xd3\xd7\x37\x7e\xc4\xae\x27\xd9\xce\x2b\x0b\x3f\xe1\xc0\x35\x69\x00\x0d\x9b\x7b\xe0\xc3\x0f\xe8\xfc\x32\x29\xcf\xa2\xd9\x8b\xe4\x62\x42\x8f\xaf\x2d\x45\xa6\x04\x95\xf3\x14\x13\xd9\x4f\xda\xe4\xf9\x66\xf6\x57\x83\x3e\x07\x76\x42\xae\x0a\x09\xe3\x1a\x52\x7b\x5a\x50\x3f\xb3\x60\xf7\x9a\x0e\x68\x97\x2e\xea\xae\x2e\x42\x06\x39\x2b\x30\xc5\x5f\x2d\xef\x77\xa7\xc5\xba\x3a\xed\x1f\x99\x29\x46\xb0\xe4\xde\x53\x81\x4f\xdd\xd5\x24\x33\x64\xf7\x66\x93\xc3\x64\xb4\x76\x37\x96\xb1\x18\x08\xae\x10\x1f\x99\xad\x01\x99\xb5\xa3\x2a\xd3\xf0\x05\x83\x38\x2a\xa3\xdd\x82\x66\x57\x0b\xc7\x51\x5a\xa0\x61\xe7\x6e\xe7\x8e\x76\x4e\x3a\x2e\x69\x69\xfd\x82\xe0\x96\x05\xc1\x6b\x16\x04\xaf\x5b\x10\x2c\x17\x64\x6d\xbf\x91\x5e\xac\xd1\xbb\xf6\xb5\xa5\x1b\xb3\xbe\xbd\x48\xdd\x2d\x50\x20\xe9\x1e\x5d\x7f\xb9\xc2\xf3\x12\x73\x2c\x6c\x81\xaa\x7d\xdf\xf7\x8b\xf5\x40\xc9\x12\x13\x98\xac\x4f\x0d\x17\x40\x93\x5b\x0b\x84\xb6\x58\xe4\xf7\xa5\x8a\x72\x71\xd2\xb4\x3c\x60\x35\xbe\x8b\xc0\x05\x59\x2b\x03\x28\x08\xea\x1c\x27\x28\x25\x42\xb8\x15\x6a\x54\x01\xde\xe0\xe3\x1a\x92\xac\x71\x7f\xf2\x95\xc6\x3d\x12\xe2\x63\x98\xaf\x1e\x93\x02\x4f\xa2\x82\x66\x3c\xb8\xe6\x37\xc9\x47\xb7\x72\xe0\x7a\x9f\xc5\x28\xa7\xcc\x6b\xdd\xd6\x5c\xc9\x5d\xa9\xd2\x12\x26\xae\xcb\xf2\xda\xd6\xd4\x94\xa6\xe5\x39\x57\x53\x32\x4b\x54\x25\x8a\xc5\xaa\x9d\x91\xeb\xb2\x24\xa1\x94\xab\x30\xf3\x83\x32\x05\xdd\x18\x4e\xac\x9e\x62\x72\xc0\x86\xee\xcd\x50\x9b\xd5\x35\x66\xba\x42\x8c\xea\x98\xda\x6d\xda\x6f\xa2\x9a\xc4\x8b\x0a\x9d\xd2\x47\x50\x9a\x71\x1b\x76\xec\x3b\xd8\x75\xa3\xee\x5c\x0c\x0d\x40\xf9\xc8\x15\x02\x1a\xd1\x49\xa1\x39\xc0\x60\xae\x91\xbe\x58\x0f\xcb\x33\xa3\x66\x3f\x84\x67\x3b\x8a\xba\xd3\x79\x42\xc0\x3e\x74\xe8\xa6\x8b\x98\xa6\x97\x36\x36\x6e\x73\x12\xf1\x46\xe4\x8c\xfb\x7b\xed\x91\x33\x1e\x02\xe7\x60\x53\x46\xca\xca\x64\x0d\x18\x72\xec\xdc\xa5\xc8\x8f\x91\x28\x72\x06\x7b\x0f\xaa\x56\xa6\xa1\x4e\xa7\x1d\xf7\x8e\x5a\xc4\x68\x5c\x6a\x81\x1b\xb8\xe5\xcc\xda\x6c\x83\x55\xa5\xed\x01\xc1\xbf\xb6\x26\x02\x67\xaf\x19\x34\xc1\x9e\x1c\x11\x08\x3b\x01\x99\x2c\x8b\x93\xea\xe0\x7f\x39\xce\xff\xb2\x5a\x1e\xb4\xa5\x81\xfb\xe8\xf9\x22\x35\xcb\xb6\xa9\x53\x36\x25\x45\xe1\x2c\x32\xdc\x94\x62\xe5\xed\xbc\xac\x00\xa4\x26\x2c\x28\xa7\x17\x85\x45\xc3\xff\x1b\xc5\x72\xad\x9a\x23\xef\x01\x56\x92\x31\x71\xdb\x6c\x8b\x96\xa7\xb1\xb5\xb9\xe0\x1c\x8d\x71\x8e\x1a\xbb\x63\x0b\x69\xb1\x6e\x23\xfe\xe7\x7f\x7c\x3f\xf2\xb7\xd9\x8e\x75\x0b\x6f\xde\xb8\x73\x7d\xec\xb6\x5b\xb0\x66\x79\x99\xef\x3d\xf5\xf5\x94\x04\x11\xb4\x4d\x7d\x2d\x60\xea\xc2\xc4\x9a\x30\x22\x9b\xd7\xd2\x0c\x26\x62\x1f\x0b\xbb\x0f\x77\x62\x5c\x96\x28\x26\x64\x76\x0b\x06\xde\x60\xb2\x25\x63\x6d\xa3\xd0\x4d\xaa\x6c\x21\xb8\x36\xb2\x47\x48\xde\x11\x27\x79\xa7\x7f\x93\xbc\xbf\x1c\xc9\x3b\x6d\x23\x79\x87\xdf\x44\xf2\x60\x16\x96\xb7\x26\x7b\x30\xb7\x55\xf2\x7f\x68\xaf\x44\xbe\x6d\x24\x96\x16\xd7\x2d\x76\xe0\x44\xee\x4b\xe6\x7b\x85\x6c\xbe\x57\xb2\x20\xcb\x3f\xba\xa6\xe4\x66\x3c\xd7\x08\x6c\xf7\x9d\xe9\xcc\xba\x48\x28\xcd\x65\xed\xad\x09\xde\x45\xbe\x6d\x1d\x24\x25\xaf\x74\x62\xb6\x5d\xe7\x9b\xf6\x74\x63\x64\x20\xcb\x7c\xd6\xc0\x16\xf9\x66\xd1\x4d\xfc\xcd\xf3\xfc\xcd\xf3\x58\xe8\xf4\xda\x8d\xf8\x3f\x82\xe7\xd9\x7e\xae\x2d\x4c\xce\xb7\xf0\x29\x5b\x69\x27\x0d\x6f\xd1\x3d\x53\x57\xc9\xbf\x31\x1b\x77\xf2\xf1\x36\xaa\xcb\xbd\x87\xb3\x9b\x4e\x6f\x4f\x06\xd9\x59\xa7\xa7\xdc\xbb\x27\xf4\x0d\x7c\x65\x1e\x54\x92\x69\x5a\xd3\xa0\x4d\x7b\xc2\xd4\x80\x4f\x94\xae\xab\x4d\x04\xa4\x8e\x47\x34\x24\x89\xdf\xe9\xf9\xfe\xec\xa6\xf3\x5f\x7b\x0f\x1e\x3c\xfc\xe1\x51\x27\xc9\x0a\x54\x3a\x42\xa1\x88\x6e\xca\x67\x49\x9a\x72\x65\xe2\xfa\xd6\xfe\x6b\x3c\x1e\x3b\x70\x14\xe5\xa8\xbc\x45\x79\x1b\xed\xab\x47\x7e\xaa\x11\x3c\x15\xf0\x73\x83\xd6\xc7\xb2\xb2\x16\xb5\x8a\x56\xa1\xf7\xa8\x56\xa1\xf7\x03\xcb\x95\x69\x76\x62\xee\x5f\xcf\xaf\x57\xea\x55\x4d\xc6\xb6\xae\x52\x7a\xdc\x0a\x88\xbe\x45\x1d\x64\x00\xa3\x5f\xe3\x88\x99\x21\x86\xe4\x8b\x4f\x39\x5f\xfc\x69\x3d\x5f\xac\xbc\x84\x0f\x64\x94\x72\xce\x0d\x47\x86\xfd\x1b\xe1\x8d\xa9\x44\x4f\x6d\xe4\xe8\x13\x63\x93\x09\x5b\x9c\xe1\x72\x34\x41\x31\x35\x61\x67\x56\xea\xa3\x5b\xc6\xd7\x4e\xb9\x45\x8b\x6a\xd8\x81\x0e\x6f\x56\x5a\xa8\x0f\x01\x8c\x43\x27\x2f\xe9\x05\xf2\xd7\xd2\x03\x5d\xe9\x69\xd5\x77\x28\x9e\x73\x02\x87\xa0\x49\xe7\x20\x19\x7b\x8a\x7b\x07\x6d\x91\x83\xa8\x36\x8e\x42\x7a\xed\xfe\xdc\x6a\xdd\x29\xd9\x5f\xcc\x03\x4f\x8b\x00\xca\xcc\x98\x73\x6e\x8f\x60\x90\xa2\x0b\x1a\xff\xc7\x76\xd7\x8c\xbb\xec\x2b\x85\xc1\x14\xc5\xb0\x70\x5d\xf1\xee\x0d\x9b\x3c\xa8\x60\xd2\x8c\x72\xc0\xc2\x32\x53\x43\xdb\xa4\x99\x5a\x4e\x44\x6d\x8e\xa3\xec\x02\xe5\x78\x5e\xa4\x8b\x53\x54\x1e\x67\x19\xca\x5f\x9c\xbd\x7e\x15\x2c\x3f\x7f\x9e\x94\xd3\x34\x70\xdc\xff\x7a\xb4\xe7\xdf\x3b\x70\xe8\x35\x22\x05\x80\x71\x98\xfe\xe4\xf7\xbb\x0f\xf7\xff\x91\xde\x7d\x14\x74\xfd\x5e\x6b\xd4\xa5\x6d\xd6\xce\xb4\x72\xd5\x3d\x69\x84\xa5\x7b\xd3\x60\x24\x06\x00\x3e\x02\x70\x0e\xb6\x58\xf9\xad\x57\x5c\x2c\x2a\x1f\x11\xbf\xf4\x29\xfa\x63\x32\xc5\xaa\x69\x51\xf1\x6d\x2b\xa8\xae\x56\xdf\xb5\x08\x28\x2d\x62\x81\xa2\xd6\x92\xba\xe7\x9a\x83\xca\xee\xbe\x20\xfe\xf2\xaa\x47\x92\x04\x9f\xc6\x36\xb6\x12\x5f\x33\x8c\x43\x1d\x9d\x72\x5a\x49\x69\xaf\x78\xc7\x44\xb5\x5e\xd3\x61\xa6\x82\x6c\xfd\x58\xb4\xea\xc7\x69\x72\x91\xf1\x93\xa6\xb4\xe4\xe6\x95\x26\x8d\x4f\xb7\x91\xe7\x60\x2e\x0b\x1a\x97\xd1\xdb\xf7\xb7\xe3\xe6\xc4\x88\xc4\xd1\xd1\x22\x45\xf0\x7b\x2d\x7e\x99\xc5\xbd\x0d\xdb\x87\xcd\xaf\x00\x7a\x3d\x15\xba\xce\xf1\xbb\x0f\xf7\xd1\xd4\x81\x36\x0f\xa3\x69\x74\xc3\xd6\xa9\xeb\xf7\x36\xcf\x70\x1a\xdd\xec\x36\x66\xb9\xed\x24\x21\x0d\x0d\x46\x61\xd1\xa4\x0e\xfb\xd0\xa0\x05\xfb\x8d\xfb\x5f\xb6\x06\x95\x58\x25\x8e\x4c\x82\xa5\x1c\x7c\x0f\xdd\xfb\xc6\xc1\xf7\xfc\xad\x46\x0f\x63\x44\x06\xb4\xef\x9b\x09\x9a\xdf\xe5\xc9\x55\x54\x22\x3e\xa0\xb7\xec\xa2\x8e\x10\xac\x4f\x9c\x60\x9d\x6c\xa7\xc8\xd1\xa9\x94\xd2\xd9\x24\x4a\xd7\x12\xb9\x6e\x44\x69\x55\x4d\x67\x63\xe6\xd5\xe0\x3a\x1b\x96\x55\x83\xd1\xb7\x91\x49\xdf\x62\x55\x7e\xd4\xf7\x03\xa6\xbf\x51\xda\x1d\x9b\x19\xb7\x20\x87\x53\xa1\xe9\x31\x2d\xb8\x99\xa6\x67\xca\x42\x7a\x69\x34\x72\x3b\xb5\x8e\x95\x52\x1a\xf6\xbe\x92\x6a\xde\x42\xeb\xa3\x9b\xf1\x06\x16\x0f\x9c\x7a\xdd\x77\x91\x89\x5e\x33\x63\x3f\x79\x5c\xf7\x39\x54\x83\x0c\x62\xc8\xcb\x04\x72\xc1\x26\xfd\x49\x20\xec\x10\x51\xcd\x74\x7b\xb5\x42\x5d\x66\xca\x4a\x9f\x18\x1f\x0f\xc8\xb9\xb7\x28\xa8\x70\x5d\x41\xc5\xe9\x04\xd6\x95\x53\xe6\x10\x9b\x1a\xaa\xa4\xae\xa1\x2a\x34\xa6\x7e\xa6\x6b\xa8\xae\x2a\x78\xc1\xb0\xfd\x49\x9b\x86\xea\xed\x77\xba\x94\xd9\x14\xce\x7c\x0b\x45\x93\x4e\x04\xac\x5a\x22\x21\xa2\x75\xee\x98\x4b\x24\x85\xab\xba\x6c\xab\x8b\x65\x55\xab\x4e\x66\xcb\x66\x4b\x43\x55\xb3\xf5\x18\x2c\x41\xd5\x79\x64\x21\x25\xa8\x6f\xdd\x98\x12\xd6\x0d\x21\x73\xeb\xfa\x8d\xcc\x06\x36\xb5\xce\x6d\x67\xd8\x50\xec\xdc\x5e\x98\xbd\xbf\x4e\x98\xbd\x7f\x3b\x61\xb6\xf7\xa8\x4b\x43\xf5\xdf\xdf\x24\xc9\xf6\xfc\xee\x7e\x5d\x16\xf2\xbb\xfb\x55\x55\x3f\x81\x35\x30\x68\x48\xbb\xb5\x1e\xff\x52\xa2\xee\x6d\x85\xd8\xb6\x45\xfd\x57\x4a\x98\x7c\xdf\x94\x8c\x79\xa2\xc7\x1c\x3d\x8b\xf4\x3c\x71\x9a\xe7\xc3\x38\x62\x1e\x5f\x6f\xb6\x24\xec\xdb\x24\xc9\xd2\x7c\xb1\x64\x6a\x1c\x50\x23\xed\x8c\x50\x52\xd2\xee\x69\x0e\x5a\x9a\x33\x16\x73\x5d\xc8\xa4\x1d\x79\xa6\x4c\x88\xbf\x6b\x76\x28\xe9\xd8\xc3\x5c\x33\x78\xf2\x27\xfa\x24\x1d\x37\x86\x00\xc0\xd1\x3a\xff\x10\xb2\xbe\x4d\x17\x11\xdd\xf1\x43\x36\xda\xde\xf5\xb0\x6a\xe5\x06\x8a\xed\x72\x2d\xb5\xd9\xf9\x8f\xac\x76\xfe\x09\x1c\x69\xa6\xd3\x5a\x82\xa3\x91\xb0\xf3\x8f\xf8\x76\x8c\xf8\x76\xd0\xc4\x47\x6c\x63\x46\xca\xd6\x3f\x92\x7b\x34\x92\x7b\x44\xde\x8a\x67\x29\x0f\xce\x01\xc4\x46\x99\x36\xc9\x6e\x1b\x39\x3f\xea\x46\x45\x89\xf2\xa4\xb8\x6c\x8c\x17\x54\xd0\xf9\xff\xfe\xaf\xff\xdb\x81\xce\x3f\x1c\x5d\xf0\xfb\x7c\x9b\x24\x48\x56\xe3\x4b\x89\xf6\xed\x46\xa5\x9a\x90\xd5\xd3\x84\x18\xe3\xb2\x63\x5d\x02\x92\x4d\xd9\x04\x0c\x03\x50\x45\x4a\x2d\x25\x35\xa2\x59\x81\x35\x04\xcf\x52\x75\x5b\xd2\x26\xe9\x13\x83\x08\xf2\x24\xed\xfd\x09\xe5\xe3\xbb\x43\x7b\xdb\x66\x98\x35\x8d\x19\xce\xa7\xcc\x93\xaa\x02\xde\x1b\x2e\x7e\xbc\xbe\xbd\xf8\x61\x2a\xc9\xf8\xf8\xa5\x5b\x84\xe5\x1e\x59\xf7\xc4\x64\x76\x83\x80\x21\x29\x91\xb3\xae\x45\x2e\xd0\x51\x4e\xbd\x1b\xdd\x1b\x8c\xb5\x69\xa4\x89\x23\xc8\x85\x62\x90\x38\x2c\x0e\x24\x96\x8c\xa9\xbf\x97\x17\x87\x23\xc9\x6b\xcb\x43\x47\x1e\x75\xd6\x42\xe8\x87\xd6\xa0\xa8\x91\xc2\x4f\x72\x2c\x72\x08\xed\x98\xe7\xb3\x26\x87\x38\x9a\x31\xa5\x13\xc4\xeb\x74\x40\x70\xe4\xba\xd8\x70\xfb\xd9\x49\xc9\x1b\x66\x22\x88\x62\x18\x93\x5f\xac\x29\xcd\x51\x62\x2c\x1d\x25\xb0\xee\xe0\x03\x97\x1c\xc6\xb0\x40\x3f\x32\x57\x11\xee\x8a\xc7\x6a\x30\x16\x7b\x34\x04\x52\x10\x59\x0a\xe8\xc5\x12\x4b\x49\x20\xc6\x0a\xe5\x31\x60\xc6\x1c\xdf\x49\x38\xc6\x8a\xe8\x48\x78\xc6\x12\xf1\x54\x0a\xb1\x69\x58\xe6\x78\x1b\xf5\x52\x5d\x1f\x22\xaf\xa1\x58\xc4\x1b\x1a\x9b\xaa\x43\x95\x21\x9b\xcf\x9f\xfd\xd4\xd5\x2c\xbe\x6c\xfa\x2c\x11\x59\x85\x86\x59\xb1\xc5\x57\x21\xc2\xce\xde\xfd\xd9\x0d\xe8\xd0\xbb\x31\x76\x35\x66\xb0\xa3\xad\xb5\x7a\xb5\x5a\x6c\xab\xdb\x2b\xf4\x08\x3b\x29\x6a\xf8\xdd\x87\xfb\x60\xfd\xa2\x08\x40\xe2\x2d\xae\x51\x94\x28\x7a\xac\x6e\x2f\x87\xdf\xf9\xfa\x52\x21\x41\x1e\x0e\xab\x67\x57\xfa\x59\x67\xdf\xdb\x9b\xdd\xc0\xce\x9e\x6f\xac\x58\x93\x8b\x5f\x53\xb7\xf7\xb0\xb6\xda\x8e\x7b\x47\x1c\xd3\xb5\xf5\xfc\xc6\x9a\xdf\xa6\xdb\x87\xf5\xda\x66\x16\xb1\x6f\x59\x8a\xfb\x7f\x60\x29\x68\x5d\x32\xb2\x5b\x2e\x05\xad\xb7\xfb\xc0\x32\x99\xa6\x55\x93\x24\x49\xaf\x39\x49\x7a\xfc\x1d\x19\x67\x7b\x76\x59\xc1\xb2\x6d\xc8\x2e\x1b\x27\x57\x5b\xa5\x96\x65\x18\xce\x96\x4f\x56\x69\xea\x6c\xf1\x62\x05\xf6\x5c\x84\x99\xee\x45\x07\xcf\x55\xd9\x85\xeb\x2e\x68\xdc\x58\x4e\x40\x6f\xd4\x00\xaf\xfb\x6c\xdb\x03\x16\xc3\x40\x62\xd5\x4b\x55\xfb\xc8\x75\x8f\x68\x30\x03\x9a\x6c\xf6\x50\xcb\x12\xfb\x49\xb5\x73\xd8\x77\x8a\x32\x22\xec\x49\xec\x04\x87\xf0\xdd\xf7\xcd\x14\x6b\x73\xf2\x57\x9c\xfb\x66\xf7\x6e\x9e\x13\x56\x4b\x00\x7b\xa2\xfb\xa1\x37\x03\xd0\xec\xc8\x2b\x1c\x4c\xb8\xe1\x43\x3e\x7e\x02\x50\x47\xd1\x68\xe2\x61\x33\xc1\x79\x32\x26\x3c\xfd\x07\x3a\xdf\x12\x0e\xb8\x56\x0b\x3a\xa7\x34\x5d\x32\xe1\x24\xb8\x7f\x98\x51\x4a\x7e\xed\x97\x3c\xcd\x3d\x13\xe6\xcb\x83\xcc\x75\x79\x08\xfc\x9a\x82\xcf\x75\x3d\x14\xee\xf8\x2c\xb2\x3e\x22\xff\xbc\x0d\x4f\x06\xfe\x10\x9e\x85\x27\x83\xde\x10\xbe\xf9\xae\xd3\x5a\x3f\x27\xd7\x5d\x44\x1e\x1f\x39\xdc\xf1\x81\x1c\x9b\x18\xda\xe7\xf0\x0d\x19\xda\xeb\xf0\x0d\x19\xda\x71\xdd\xf3\xff\x71\x78\x4c\x3e\xbf\x0a\x8f\xc9\xe7\xaf\x0a\xe0\x2e\xfa\x17\xc1\xe3\x83\xb1\xeb\x7e\x75\xdd\x57\x34\x09\x05\x19\xfd\xd3\x35\x21\xad\x5e\xf3\xe0\x92\x83\x21\x80\xcf\xc2\xa5\xa1\xdc\x79\x0b\x6b\x5e\xdc\xc1\x19\x77\x41\x2a\xf4\xac\xb0\x8c\x6a\x4f\x04\xbd\xf8\x2c\xa9\xfb\x57\x4d\xdb\x79\x05\x35\x58\x0b\xce\xc5\xcd\x92\xe7\x14\x34\x97\x0d\xcb\xa8\xcc\x98\x26\xae\xb0\x05\xab\xd5\x4d\xc3\x91\x14\x2c\x5f\x09\x8f\x50\xea\xf8\x1f\xac\x9d\x59\x4f\xcc\x4c\xc4\x0d\x08\x9e\x36\xdd\x26\x69\x93\x3e\xf5\x8d\xbe\x48\x08\xaf\xc1\xe3\xc0\x70\xb7\x4b\xc9\x8a\x5c\x42\x7e\x08\x82\x4f\x55\x1b\x6b\x69\x71\xa1\x7e\xd6\xbc\xed\x1b\x6d\x23\xfa\x26\x90\xa1\x97\x9d\x30\xbc\xa1\x19\x84\xf9\xe9\x6c\x48\xc2\x37\x44\xf0\xbd\xaa\x25\xf0\xe5\x5c\xdc\x3b\x00\xb1\xce\xc8\xbd\x6a\xcf\x36\x63\x38\xf2\x91\x7f\x9f\xaa\xa8\xa2\x23\x9c\xce\xa7\x99\xdd\x2f\x50\x73\xe7\x52\xe2\xa1\xbc\x37\x94\x0e\x67\x22\xc2\x38\xbf\x14\x2b\xf1\x4c\xf2\x5d\x6f\x70\x3e\x8d\x52\xd3\x68\x9f\x7f\x7a\x22\x23\x89\x1a\x2c\x9a\x2a\xf9\xc8\x2c\x78\xbf\xdd\xd5\xae\xaa\x49\x62\x9c\x8d\x24\x84\xef\x31\x27\x7c\x5f\xbf\x33\xe1\xb3\x5f\x01\xcd\x6e\xa9\x23\x92\xa2\x9b\xa4\x30\x6d\x82\xdb\x66\x52\x71\x5b\x75\x91\x8d\x22\x98\x42\xde\xd6\x1a\x24\x51\x4d\x6b\xf4\xb6\x2a\xab\x3f\xa8\x4c\xf2\x44\xeb\x61\x18\x8e\xc4\x12\xae\x56\x8e\x60\xef\x8c\xf7\x80\x1c\x28\x99\x82\xec\x5f\xa6\x58\xd2\x04\xc7\x91\x14\x1c\x23\x33\x32\x84\x52\x3d\x39\x1d\x16\xdf\xee\x7b\x98\x13\x04\x58\xc3\x13\x4f\xff\x34\xb5\xd2\x28\x9a\x51\x2d\x45\xf3\x62\x5f\x1d\xea\x7b\x0a\x7f\xfc\x39\xca\x23\x29\x67\xea\xc2\x67\x0b\x86\xb9\x6f\xa4\x2d\xd5\x72\x3f\xf4\xee\x1b\x89\x1e\x7a\xf7\x0d\xb1\xd6\xaa\x41\x6a\xea\x83\x5e\xa0\x74\x86\xf2\x33\x74\x43\x15\xdc\x5f\x39\x22\x7a\x16\x85\x99\xb7\xff\xe8\xde\x3e\x80\x4f\xc8\x63\xcf\xf7\xf7\x34\xd5\xf7\x17\x23\xde\xa9\x83\xcf\xbf\x10\xb6\x22\x0c\xc9\x9e\x3d\xa1\x9b\x46\xc0\x97\x45\x29\x0a\xcb\x3e\x0a\xc3\xb0\x0c\x4e\x59\x46\x2e\x04\x08\xa9\x65\xcf\x25\x53\x94\x7f\xb8\x4d\x78\x33\xa6\xe5\x56\x81\xcd\x58\x2c\x2e\x11\xd5\x4c\x78\x32\x68\x48\xb2\xd0\x90\xe4\xdc\x40\x92\x34\x8e\x99\x16\xf7\xa3\xce\xe8\xd3\x1f\x84\x38\xb1\x10\x3f\x84\xd3\x3f\x1e\xe9\x29\x13\x26\x7a\xc0\xb1\xa9\xb8\x46\x3f\x8e\xe1\x55\x98\x75\x5f\xa3\x6c\xce\x22\x95\x5d\x28\xf4\x7b\xd5\x5f\x56\xc1\x15\x65\xf8\xe9\x9d\xd3\x2c\x65\x19\x22\x68\x00\xb2\x6b\x15\x80\xec\x46\x0f\x40\x76\xa4\xa5\x93\xb8\xd4\x02\x90\xb1\x28\x65\x6f\x67\x28\x63\x31\xca\xc8\xc3\x27\x3d\xd4\xd8\x3b\x19\x6a\x8c\xcd\xef\x24\xcc\xba\x8c\x07\x7c\xca\x26\xc6\xc6\xf7\x56\x8d\xef\x84\x8c\xef\x84\x06\x2c\x13\xd1\xfb\xe0\x1b\x42\x2a\x98\x3f\x01\x8f\x85\x47\x43\x96\x09\x12\xf0\x5a\xd5\xfe\xac\x4b\x12\x9f\x1b\xf9\x1c\xd4\xf6\x99\xe1\xc4\xe4\xc6\x6d\x93\xc9\xa1\x3d\xba\x98\xbe\x59\x0e\x74\x8c\xad\x32\xc3\x86\xf1\x6d\x72\xa0\x23\x37\x49\xd8\x14\xcc\xd2\x2d\x42\x88\x89\xdc\x0f\x2a\x84\xd8\x5b\x96\xa6\x41\x66\x6b\xa8\x85\x0b\x13\xa3\x6d\x2e\xbe\x03\x1d\xb1\xd0\xf5\x68\x60\x86\xd0\xf3\x98\xac\x65\x9e\x73\x7c\x47\xe9\x1b\x39\xde\x6f\x44\xe0\x9a\x60\xc4\x63\x2d\x73\x1e\xbf\x02\xf0\x15\xa9\xf2\x89\xc6\xe2\x7c\x0c\xf7\x9a\x29\x1d\x6a\x41\x6a\x9f\xe8\x4c\x3e\x7b\xf5\x25\x7c\x42\x6a\x7c\x08\x9f\x90\x1a\x8d\x00\x64\x87\x8d\x00\x64\xac\x32\x80\xbf\x86\xef\x49\xc5\x17\xe1\x7b\x52\xf1\xf7\xba\xf8\xf0\x73\xf8\x3b\xf9\xfc\x4b\xf8\x3b\xf9\xfc\x5c\x0f\x9f\x3b\xe1\xc9\x1b\x8e\xa7\x33\x94\x53\x0e\xef\x45\x94\xc5\x29\xf2\x9e\xc3\x66\x22\x07\xa6\x88\xd4\x39\xe9\x2f\x22\xe2\x50\x05\x33\x1c\xa3\xe0\x99\x1c\x21\x63\x86\xbf\xd2\x80\xa0\x5f\x78\xf0\x27\x7b\xf8\xa8\xc8\x75\xbf\xb8\xae\x6a\x09\xc0\x41\x04\xbf\xac\xa9\x90\x8c\xbd\x2f\x5a\xf8\x53\x96\x89\xeb\x0b\xe8\x5e\x20\x91\x8c\xed\xc9\xe2\x38\xf6\xa6\xe0\x20\x19\x2b\x9b\x08\xad\x81\x0b\x54\xb2\x6d\xa3\x3f\xbb\x49\x71\x88\xd3\x34\x9a\x51\x82\xad\xc6\x21\x03\x53\x5a\xa2\xa5\x8e\x58\x58\xbb\xb2\x16\x2c\xd5\x1a\x1d\x55\x96\x65\xda\x98\xc1\x94\x4c\x8e\xa2\xfd\xdf\xe0\x47\xf8\x52\xcb\xf9\x46\x70\x3c\xea\x9f\xba\xee\xa9\x57\x82\xe0\xc8\x75\x8f\xbc\x12\xc0\x3b\xab\x95\xf7\xc2\x4b\xd8\x25\xef\x17\x3d\x5b\x1e\x80\xbf\x78\x08\x80\x0a\x22\x14\x6a\x22\x6a\x89\x59\xac\x9a\x14\xc0\x12\x6d\x4a\x29\x47\x85\x6d\xb2\x50\x8b\xd5\xea\xa5\xb7\xd3\x23\x73\x5a\x80\x65\x16\x9a\x31\x40\xbf\x82\xfe\x57\x1e\x8c\x18\x04\x83\x21\x4f\x3e\xf7\x55\x26\xcc\xe3\xc1\xc3\x39\xc2\x3a\xd8\xed\x85\x61\x98\xf7\xb3\xee\x6c\x5e\x4c\x6a\x1f\x83\xac\x5b\xcc\x68\x4b\x39\xec\x81\x0a\xa5\x05\xa2\xd9\x20\xb5\x32\x07\xe2\x17\x0f\x8a\xe5\xba\xb5\x17\x64\x5d\xbe\xee\x84\x61\xe6\xba\xde\x53\x2f\x03\xf0\xc6\x75\x89\x80\x8d\xf2\x22\x29\x4a\x0f\xc0\xb7\x94\x46\x76\x59\xfc\x4f\x72\xf2\x51\x5e\x2e\xbc\x92\x9c\xfe\xfc\x02\x95\x0e\x5c\x5e\xe7\x49\x49\x50\x59\xb0\xe3\x73\x60\x15\x31\xb0\xd8\xc9\x3e\x27\x9b\x75\xe3\x95\x10\xd1\x20\xeb\x30\x43\x3c\x54\x60\xf8\xc5\x75\xbd\x3b\xfd\xc3\xe0\x67\x70\x10\xa3\x14\x95\xa8\x73\x3c\x30\xc3\x62\x0d\x45\x18\xb8\xc1\x10\x62\xaa\x4b\xf0\x16\x91\x88\x39\xf4\xb5\x02\xab\xd5\x18\xb8\xae\xf7\xae\xff\x5b\xf8\xce\xfb\x0a\x02\x4c\xb5\x01\x2c\x79\x1b\x0a\x11\xea\x4e\xa3\x99\xa9\x79\x4f\xc6\xde\x4e\xd9\x4d\x8a\x5f\x49\xfb\x82\xed\x43\x00\x68\xb1\x5b\x0f\xd4\x56\xb2\xf2\xf5\x1d\x6c\x0f\x8a\xb4\x07\xc0\x81\x97\x85\x5f\xbb\x05\x9e\x22\x1b\x07\x48\x58\x90\x12\x9a\xfb\x58\x01\x00\x5c\x17\x23\xd7\xcd\x91\xb9\xcf\x82\xa8\xb0\xcd\xf5\xb2\xf0\x4b\xe4\x7d\xad\xd5\xe6\x55\xbd\x8f\x61\xa3\x96\xc6\xf4\xeb\x19\xee\x90\xb8\x54\x2d\xe8\xd9\x25\x0c\x62\xd6\x77\xca\x7c\x2e\x35\x08\x32\x86\x5a\x49\x03\x72\x8b\x58\x5c\xfa\x74\x18\x07\x5d\x76\x2f\xd1\xc2\x75\xcb\xee\x2c\x47\xe4\xb0\x3e\x65\x48\xdd\x03\x50\xc1\x19\xad\xab\x03\x1e\x7d\x41\x78\x28\x48\x33\xd1\x39\x78\xc6\xee\xc5\xc4\x70\x82\x8c\xc3\x11\x1f\x0c\xbb\x6a\x62\xb4\x25\x30\x26\x5f\x51\xce\x9b\x4e\xff\xb7\x70\xd1\xcf\x51\xf7\x0b\x4e\x32\xcf\x81\x1d\x07\x04\x1f\x19\x1c\x24\x08\xa6\x28\xfc\xf5\x60\x27\x71\xdd\x3b\x14\x43\x7a\x29\x0a\x6b\xc7\x3f\x41\x4a\x15\x74\xd6\x3f\x0b\x62\x86\x24\x58\x6e\xc8\x02\x85\x6f\xbb\x49\xbc\x5a\x79\xe7\x7d\x1a\xc8\x42\x8a\x83\x7c\x05\x77\xa5\x6e\xe1\x1c\x08\x1d\x4c\x9b\xc0\xb5\x31\xfc\xf2\xc6\x48\x7e\x05\x13\xca\x8a\x2e\xeb\x5c\x3e\x10\x96\x00\x16\x83\xd7\x43\x38\x87\xb1\xeb\x16\x92\x23\x64\x82\xcf\x07\x15\xd6\x38\x41\x7c\xe5\xcf\x59\x46\x61\x11\x74\x4e\xca\x0b\x71\x0d\x1c\xd8\x77\x74\x33\x8b\xb2\x98\x82\x0b\xb2\x16\x98\x44\xc5\x0c\xcf\xe6\x33\x27\x70\xd2\xa4\x28\x69\x5c\x1c\x9d\x7b\x0a\xb0\xfe\x33\x65\xd1\xed\x06\x53\x58\xa0\x21\x91\xf8\x4a\x94\x8b\x68\x87\x80\x6f\x64\xc7\x01\xab\x95\x84\x49\x11\x1d\xce\x48\x46\xb3\x5a\xed\xf6\x76\xc2\x70\xe0\x74\x1c\xe8\x3c\xce\x73\x7c\x4d\xe3\xa0\xd2\x27\x1e\x1d\x95\xa5\xa8\x1a\x6a\x38\xf6\x12\x2d\xa8\xee\xb0\x09\xb7\x2f\xbd\x1d\x9f\x66\x63\x12\xf9\x6f\x68\x8f\xf1\x6a\xf5\x89\x81\x84\xde\x37\x8b\xe5\xcc\x16\xd1\xde\x9a\x24\x82\x46\xbb\x8d\x10\x6f\x3b\x19\x72\xdd\x6b\xd6\xc4\x06\xcc\x8b\xb6\xc1\xbc\x5f\x35\xcc\x7b\xed\x21\x3d\xe8\xd9\x65\x05\xdf\xc2\x65\x12\x07\x05\xaa\x34\xa2\x6b\x46\xaf\x0e\x43\xb4\x5a\x89\xc0\x9a\x32\xe4\x33\x72\xdd\x1d\xd4\x2d\xf3\x64\xea\x81\xca\xfb\x0d\x7c\x1f\xe9\xf9\x37\x8b\x63\x00\x33\xf6\xad\xc7\x1f\xb7\x10\x52\x7e\xdc\x1d\x20\xa7\x4c\x61\xfd\x19\x6c\x58\x8d\x58\x03\xe1\xf1\x08\x78\x16\x32\x21\x59\x16\x03\xdb\x00\x0d\x84\xd8\x2e\x08\x3a\x9d\x8c\x3d\x0a\x86\x32\x2a\x1b\x42\x83\x72\x78\xf0\xd4\xcb\x0c\x64\x4d\xc8\xeb\x0d\x4d\xf0\x51\x55\x46\x98\x71\x75\xce\x8b\x6e\x46\xd9\x47\xaa\xfb\xd6\x42\x3d\x46\x15\x3c\xb6\x04\x3c\x9f\x59\xfd\x55\x8a\x6e\x32\xc2\x19\x2c\x06\x0e\xf9\xdb\x54\x7d\xbe\x06\x60\x08\x09\xd0\xb1\x82\x54\x14\x33\x71\x46\xd5\xec\xea\x24\x53\x3b\x92\xc4\x81\x33\x45\xd9\x5c\x43\x7d\xab\x95\xe3\x88\x5c\x2d\x47\x69\xf0\x05\x12\xa1\x22\xc8\x10\xe4\x92\x87\x19\x6f\x8f\x70\x48\x88\xac\xc2\x05\x5c\x12\xcc\x45\xd8\x3c\x2a\x58\x04\x35\x2f\x15\x1d\x57\x4c\x39\xde\x92\xd8\x85\x0f\x97\x54\xa6\x99\x32\x77\xfc\x0a\x5e\x74\x8d\xf6\x00\x7c\x17\xcd\x78\xde\x3c\xdd\x14\xf9\xa2\xab\xde\xc3\x65\x2d\xcc\xbb\xd4\xcd\xa6\xa8\x82\x8c\x5b\xd1\xcb\xf7\xf5\x1f\xcc\x91\x4a\xc4\xec\xab\x00\x8c\x90\xae\x39\xbe\x13\x85\x1f\x22\xf8\x9e\xea\x85\x7e\xa5\x5e\x35\x0d\x70\x9f\x45\xcc\x70\x3f\x70\x5e\x3f\xec\xf4\xfc\x74\xbf\xb3\xdf\xd9\xdf\xdd\xff\x4a\x84\x21\x8e\xc8\x72\x3c\xa3\xc8\x0c\xc0\x5f\xbf\x93\xdd\x4b\x4c\xb5\x0d\xa6\x5e\xa0\xd0\xf5\x02\x73\x4d\x56\x36\xaf\x17\x95\xac\x3c\x87\x71\x9b\x6d\xbc\xc5\x06\x26\x5e\x2f\xdd\x2a\xa9\xf1\x9b\x89\x27\xa3\x84\xeb\xe9\xa7\x34\x39\xe7\xf4\x13\x0f\x46\x43\x18\xc1\xc4\x75\xb1\x46\x32\xa5\x82\x2b\xa1\x18\xa5\x58\xad\xf2\x0a\xc6\x00\x40\xa5\x00\xb1\xe7\x83\x4b\x5b\x1c\xc8\xe8\x81\xc4\x6d\x07\x72\x44\x8d\xf0\x8c\x21\xf0\x1c\x03\x64\x43\x5f\x44\x16\xe9\x83\xdf\x43\x54\x9c\x6f\xb2\x86\xba\x62\xd7\xeb\x6b\x62\xa3\xc1\x79\x81\x72\x26\xc3\x59\x9d\x91\x7c\x75\x4d\xd1\x7b\x20\xc3\x0c\xf2\x4b\x7c\x47\x0f\xe5\x56\xf7\xb2\xdf\xde\x74\xde\xdf\x5f\xe3\xcf\xbf\x0f\xea\x23\xaa\x64\x30\x35\xc6\x90\x38\xda\x5d\x8c\x72\x15\xd7\x95\x9f\xf5\xe0\x88\xd0\x71\x07\x62\x13\x87\x4e\x2d\xb6\x18\x6d\x3e\xc3\xa5\xa7\x8a\x80\x0e\x63\x51\x61\xc7\xfa\x85\xcc\x7a\x66\x59\x01\x64\xcb\x35\x3c\x23\x78\x83\xf4\xe1\x3a\x35\x2b\xde\xbd\xfb\x95\xd2\x7e\x5a\xbe\xdf\xdb\x33\x2c\x2a\xb6\x71\x17\xb0\xb7\xa1\xd8\xc5\x7a\x58\xb5\x69\x92\x35\x43\x5d\x96\xe8\xa6\x7c\x2b\xfd\xcc\x50\x9a\x26\xb3\x22\x29\x1c\x78\x3d\x49\x4a\x74\x3a\x8b\x46\x34\x0e\x1b\x4b\x51\x6c\xf1\x47\xd3\x35\xc5\x04\xf6\xed\xe6\x47\xba\x17\x9d\x33\x8a\xd2\x91\xb7\xef\xff\x77\x67\x97\x99\x70\xb4\x78\xcd\x8d\xec\xc6\xfd\xe4\xcf\x15\xb2\x2a\xc0\xd7\x39\x02\x08\x3a\x68\x58\x86\xe4\x98\xea\x7e\x7a\x8f\xfc\x18\x5d\x00\x87\x95\xe2\x37\xa2\x3c\x89\xd8\x43\x5e\x55\x6e\x8c\x7c\xad\xd1\xf1\x60\x29\xfd\x05\xb9\xa1\x95\x35\xfd\x15\x0f\xb7\xe7\xdb\xe7\x6b\xde\xca\x55\xf0\x77\x95\xe7\x4b\x20\x9f\xcb\x08\x32\x0d\xd8\xcf\x7f\xf0\x46\xce\xa4\x0b\xa9\x42\xff\x49\xff\x7d\x14\x68\x31\x76\xcc\xd0\x3a\xbf\x47\x3c\xaa\x8e\x96\xef\x22\x6e\x37\x98\xb4\xe9\x4c\xad\x04\xa2\x9e\x4a\x41\xbf\x4a\x5b\x6b\xe9\x68\xbf\x4a\x33\x2f\xc4\x74\xd9\x78\x0e\xcd\xc0\xf1\xca\xc9\xe8\xd7\x08\xaa\x21\x68\x77\x38\x7c\x0e\x01\x96\x66\x86\x11\x34\xe6\x10\xa4\xf2\xfe\x5b\x1a\x25\x72\xf7\x24\xba\x70\x15\x1c\xc1\x79\x7f\xae\x9b\x63\xb0\x3e\x96\x95\xbc\xb2\x8a\x19\x2d\xf8\x59\xf3\x62\x3a\x55\xa4\x8e\xaa\x1e\x5e\x44\xda\x0d\xc9\x1b\x0a\x7a\x52\xa5\xea\xfd\xcc\xef\x47\x7e\x89\xc2\x17\x11\x7c\xbe\x06\x70\x7e\x6b\x7e\x3b\x14\xdf\x3e\xb6\x01\x55\x27\xf3\x72\x88\x19\x58\x45\x61\xae\xdd\x68\x34\xfd\xfc\x72\xfd\x86\x23\xd7\x6e\x38\x72\xf3\xd6\x62\xa4\x6a\xce\x5d\x97\x30\x1a\x79\x0d\x2a\xc7\x0a\xf2\x62\x02\x95\x31\x9c\x85\x79\x37\x89\xe1\x84\xfc\xa1\xc0\x39\x15\x4f\x0c\x14\xaf\xc2\x9c\xfb\x0e\x5e\x88\xa7\xe3\x18\x2e\xc4\x33\x1b\xf2\xb9\x6a\x76\xd1\xf7\x83\x05\xbc\x0e\x73\xed\x52\xe4\x26\xcc\xd5\x15\xc8\x91\x1a\x24\xe1\xec\xe1\x65\x98\x73\xf6\x1d\x9e\xaa\x4f\x97\xae\x7b\x09\x0f\xc3\x5c\x5e\x86\x7c\xa2\xcf\x94\xeb\x7e\x47\x1e\x59\xd6\xeb\xdc\xb8\xf3\x78\x1b\xe6\xb6\x3b\x8f\x33\x9a\xd1\x8c\x01\xd1\x1b\x35\xd2\x33\x9d\x2b\x3b\x83\x9f\x15\x57\x96\xc3\xc1\xe6\x8b\x8a\x4d\x57\x10\x71\xdb\x41\x34\x9c\x1c\xe9\xcd\x84\xe1\xee\xd8\x7a\x4d\xc1\x4c\x20\x8c\x4b\x89\xfa\x55\xc4\xc6\xfb\x07\xed\x96\xe1\x75\x78\xda\xff\x35\x0a\xee\x44\xf0\x58\xc3\x06\xf9\xd6\xd8\x40\x5d\x6a\xbf\x81\x8f\xc3\xc9\x6a\xb5\x14\xab\x19\x3c\x8f\x14\xd1\xad\x9f\x8c\xb7\x11\x5c\x32\x0f\xca\x2b\xdd\x83\xf2\x9c\x48\xd6\x8c\x48\xfc\x16\x55\x83\xe3\x61\x0b\xb2\x79\xdc\x8a\x6c\x5e\xaf\xc7\x35\x69\x0d\xc3\x8c\x25\x86\x39\xd6\x31\x0b\x14\x4b\x1e\x1c\x55\xf0\xb4\x4f\x84\xb6\x59\x15\x2c\x25\x34\x04\x09\xd4\x37\x3e\x18\x41\xbe\x8d\xc1\x05\x94\x3b\x47\x73\xef\x32\x01\xee\x10\x72\x12\xf9\x89\xc9\x76\xef\xa0\xb6\x4b\xc1\x09\x6c\xee\x52\xa0\x0b\x8c\xb3\x0a\xbe\x05\x15\x9c\x42\x19\xba\x6c\xda\xf7\x7c\xf8\x8c\x59\xd5\x9c\x47\x05\x3a\xe4\xef\x0b\x98\xa1\x6b\xf1\x63\x2a\x71\x84\x9a\x70\x56\x81\xa0\xa8\xe0\xa4\x3f\x69\x47\x9b\xb8\x82\x9f\x19\xda\xfc\xd8\x44\x9b\x5c\x38\x7b\xa9\xae\xeb\x7f\xd1\xf1\xa7\xc2\x9c\x1f\x39\xe6\x44\x49\xa8\x60\xe2\x32\x12\xfb\x7b\xa8\x41\xc7\xdb\xa8\x82\x65\xb2\x15\xdd\x35\x32\x5b\xd5\x6f\x84\x9b\x9e\xd1\x5b\xde\x09\x33\x8b\x51\xc3\x0f\x5a\x59\x8c\x32\x7f\x68\xe3\xda\x78\xa6\x4b\x83\x36\x2b\x50\x66\x98\x61\xb3\x00\x35\xaf\xe0\x45\x62\x2b\xdd\x6e\xd4\x66\x0b\x3a\x91\x35\xe8\x45\xb1\x6e\x3a\x7a\xc4\xb2\x6a\x5d\x12\xde\x43\x1a\xd7\xb2\x76\x4f\x4d\x7e\xe2\x50\x14\x61\x3f\x3f\xe9\x32\xeb\x3b\xe9\x1c\x7e\x62\x38\x7f\xbf\x55\x83\x39\x71\x5d\x76\x4f\x4c\xaf\xae\xdf\xa8\xab\xeb\xcf\xfa\xd5\xf5\x6b\xed\xba\xfa\xb8\x96\x15\xeb\xb1\x6e\xb4\xfa\x4a\xb5\xfc\xd8\x75\x1f\xd3\xdc\x56\x34\x29\xd6\x53\x2d\x29\xd6\x33\x2d\x11\xd6\x13\x2d\x11\xd6\x97\x30\x13\x52\xe8\x07\xd5\xce\x17\xd7\xfd\x02\xef\xc8\x2b\x6f\x36\xcd\xf7\xc2\x45\xfd\x57\x99\x0a\xeb\x85\x26\xa0\xff\xae\x36\xfd\x85\x4e\x0a\x5e\xb0\x6c\x48\xda\x65\xf6\x9a\xec\x58\xdb\x5a\xcc\xae\x49\x94\xc5\xad\x91\x2c\xe0\x51\x33\xa5\x55\xa0\xd0\xb0\xa6\xa5\xd4\xa6\x06\x04\x75\xba\x73\xdc\x92\x58\x4b\xd0\xa3\xad\xf3\x6a\x89\xc9\xd7\xf3\x66\x49\xab\xad\x46\xa2\x2c\x6b\x7a\x2c\xce\x8c\x39\xda\x96\xad\xbd\x16\xff\x25\x5c\x56\x07\xc9\xd8\x33\x6c\xa8\x7e\x77\x5d\xef\x52\xcb\xf5\x77\xc9\x9d\x62\x5c\xd7\xfb\x45\x38\xee\xcb\x97\x00\xbe\xe3\x26\xbe\xcf\xe1\x6f\xe2\x46\xcd\x7b\x1e\x32\xfd\xed\x65\x9f\xb5\x12\x5c\x2a\xd7\x3b\xad\xe5\xe7\xfd\xe7\xc1\xab\x83\x5f\xd8\x59\x69\x30\x7c\x75\x35\xcb\x3b\xf8\x9b\xeb\x3a\xff\xef\xff\xf3\x0f\x07\x54\x1f\x5c\xd7\xbb\xe3\xba\x77\x38\x9b\xb3\x5a\x79\xbf\x74\x13\x81\x72\x00\xfc\xc5\x96\xcc\x4f\x7c\xa5\x88\xf4\x63\x78\xed\xba\x47\x7d\x15\x74\xff\x08\x3a\xbb\x0c\x1a\x76\x69\xc0\x05\x71\x85\x02\x5f\x86\xef\x9a\x25\xd9\x06\xcb\x32\x08\x85\x28\x19\xfc\x3e\x84\x25\x6a\x4c\x03\x35\xb2\xed\x18\x69\x75\x3e\x9a\x69\x75\x70\x7b\x5a\x9d\xb1\x66\x1b\x79\xae\xf9\x5c\xbf\x65\x3a\xe7\x33\x96\xc7\xe6\xab\xcc\x0e\xf5\x54\x66\x87\x7a\x06\x45\xfa\xa8\x27\x8c\x30\xbf\xe7\x8a\xfa\x5f\x61\x12\x07\x47\x50\x26\xa7\xfa\x24\xae\x05\xde\x28\x4d\xf5\x67\xa9\xb4\x7f\x6d\xa4\xd5\x39\xd6\x99\x83\xd3\x0a\xfe\x02\x0f\x41\xab\xca\xec\x55\x3d\x62\xa8\xf5\x32\x69\xae\x29\xbc\x26\xdc\xca\xeb\xca\x98\xb5\x6e\x84\x7c\xc3\x63\x2c\x48\x03\xad\x57\x5c\x16\x8f\x25\x1f\xf2\x7b\x05\x7f\x06\xf0\x5d\xd3\xad\xf3\x58\x1b\xcf\xa4\x9c\xa6\xcf\x70\x4e\xd6\x21\x0e\x5e\x56\x90\xc2\x34\xfc\xd0\xb8\x57\x78\x19\x6d\xd8\x48\xba\x96\x82\x77\x79\xa9\x96\x98\x99\xb6\xa3\x0a\xde\x01\x30\x05\x41\x89\xe0\x75\x73\x44\x4f\x23\x43\xad\xfd\xb1\x82\x17\x00\x5e\xeb\x2a\xdc\x2c\xa9\x1b\xff\x1a\x46\xb1\xcc\x17\x9d\x86\x8b\x07\x5e\x99\xf0\xd4\x65\x49\x98\x79\xf7\x7e\xd8\x7f\x08\x20\xa6\x8f\x0f\x1e\x00\x18\x91\xa7\xbd\xfb\xfb\x3f\x00\x98\x24\x61\xc3\x54\x5e\xdd\xaf\xea\x19\xc0\x43\x7e\x11\x54\x20\xb2\xe5\x25\x26\x70\xf4\x76\xbc\x5a\x2d\x3f\x7f\x9e\x91\xdf\x9f\x3f\x07\x83\x61\x95\x64\x04\xe9\x8f\x10\x1e\xb3\x04\x3b\xae\x5b\x33\x87\xe8\xca\xe2\x61\x59\xad\x56\xe6\x57\x99\xb4\xa7\x93\x64\x9d\x12\xf0\x1e\x67\xa2\xbb\xee\x24\x2a\xde\x5e\x67\xe2\x12\xaa\x3b\x8a\xd2\x94\x0e\x52\x24\x21\x2f\x07\xd9\x10\x54\x10\xd1\x97\xd2\xe0\xc3\x9c\x0f\xc1\x76\xe2\x8d\xca\xd6\x96\x49\x7b\xbb\x4c\xbb\x56\x3f\x5b\xcc\x10\xbb\x5a\x77\x28\x1b\xd8\x41\x37\x25\xca\xe2\xa2\x43\xb7\xb6\xe3\xdc\xe5\x86\x78\x19\xb8\xeb\x74\x92\xa2\x93\xe1\xb2\x13\x75\xe8\x6e\xe5\xf3\x51\x89\xf3\x0e\xce\xe9\x4d\x96\xa3\x59\xff\xe5\x1e\x58\x96\x93\xa4\xe8\x6a\xe5\xc2\xb2\x62\x83\x86\xda\x74\x39\x0e\x0d\xb3\x3e\x5f\x08\xee\x3d\x96\x81\xc0\xcb\xf5\x62\xea\x99\x30\xac\x9d\x1c\x54\x95\x07\x60\x9a\x18\xda\x5a\x4d\x48\x56\xb7\x43\x7c\x09\x27\x49\x01\x4b\xb0\x5a\x91\x07\x95\x11\x7e\x42\x2d\x87\x08\xa7\xfd\x34\x89\x52\x7c\x11\x36\x0c\x88\x3a\x84\x6f\x28\x79\x26\xee\x98\x16\x22\xc5\x51\x1c\xec\xf8\x34\x19\x17\x6f\x83\xf2\xed\xdf\xd0\x48\xaf\xd1\x08\xdd\x8d\x0d\x6d\x50\xbc\x61\x6d\xe2\xfd\x2c\xc5\x51\xfc\x2c\x49\x4d\x33\x1a\x91\x81\xca\xc8\xc8\xd6\x1d\x27\x29\x2a\x44\x0e\x2a\x75\xa7\xc6\xb2\x47\x91\x36\x4e\x50\x14\xa3\xfc\x80\xc8\xd0\xa4\x59\x9b\x65\x8e\x3e\xac\x32\x2a\x2e\x0f\x71\x36\x4e\xa8\xe7\x1e\xeb\x23\x47\xc5\x3c\xa5\xce\x7a\x39\x35\x3b\x7c\x5c\x90\x53\xec\x95\x03\x7f\x48\x6d\x54\xc4\xd4\x29\x26\xfe\x96\x0e\x84\x7d\x82\x6c\xea\x74\x7e\x3e\x4d\xca\xb3\xa8\xb8\xb4\xac\x22\x0a\x33\x58\x86\xe2\xa2\xbb\x81\x19\x1a\x07\x8a\x1e\x5a\x0a\x4a\x30\x87\x18\x46\x30\x09\xb9\x20\xea\xc3\x82\x4a\x84\x86\x95\x57\xcf\xc5\x64\x62\xec\x7c\x61\x2d\x57\x30\x79\xae\x60\x99\x2f\x8a\x60\x30\x84\x84\x9e\x0c\x86\xf2\xf8\x46\xe1\x32\x43\x37\x65\x90\x7a\x3e\x80\xb4\x6e\x90\x7a\x3d\x22\x5c\x91\xcf\x41\xea\xed\x81\x0a\xaa\x23\x2d\xef\x89\x4f\x17\xd3\x73\x9c\xba\xae\x17\x0d\xd8\x63\x37\x29\x51\x1e\x95\x38\x1f\x5a\xa6\x4e\x40\xbf\x02\x30\x52\xe7\x34\xf5\xa2\xa6\x85\x55\xda\x7c\x15\xd1\xb9\xb5\xa0\x8d\xe7\x28\x63\x7d\x12\xf4\x10\xa5\x64\x8f\x17\x1d\x74\x83\x46\xf3\x32\xc9\x2e\xba\x04\x2f\xe0\xdc\x3b\x48\x0e\x40\x99\x2f\x68\x3b\x61\x0f\xe6\xae\xeb\xe1\x70\xcf\x8d\x06\xfe\xb0\x4f\x00\x83\x4e\x94\xff\xa2\xdd\xac\x56\x9e\x87\x43\xf1\x09\xb8\x2e\x66\x27\x39\x07\xd0\x07\x41\xde\x25\x0b\x06\x5c\x77\xc7\xc3\xa1\xf8\x02\xa3\x41\x6f\x08\x40\x37\xc6\x19\x12\x66\x46\xf8\xa0\xb8\x4e\xca\xd1\xc4\xcb\x43\x1f\x62\xb2\x54\xe1\x80\x75\x0b\x31\x03\x9d\x21\x80\xe4\x27\x58\x8e\xa2\x02\x75\xfc\x80\xfe\xe9\x05\x38\x8c\x0e\xce\x73\x14\x5d\x1e\xd0\x17\xf7\x03\xde\x60\xc2\x58\xb9\xbb\x77\x85\xf7\x0c\xe9\x14\x92\x2e\xc9\x49\x64\x85\xf7\x03\x55\x2a\x0f\x69\x81\x28\x1c\xf8\x43\x42\xe5\xca\x24\x9b\x23\x56\xec\x61\x10\x85\x49\x97\x08\xd5\x33\x3c\xf3\x00\x4c\xba\x04\x3e\xd8\x0f\x55\x54\x98\x6f\x26\x63\x6f\x87\x2c\x89\x87\x43\x56\x10\x88\xac\xd5\xbe\xeb\xe2\x01\xe6\xbf\x76\x7b\x43\xb0\x5a\x3d\x20\x42\xed\xc0\x1f\xba\xee\x1e\x7f\x02\x60\x99\x84\xbe\x6c\xb6\x4a\xc6\xde\xbd\x50\x14\xf2\x76\xf0\x6a\x45\xc6\xf9\x13\xa6\xbf\xc9\xe3\x8f\x78\x70\x8f\xd6\xe2\xbc\x2b\x79\xc7\x56\x84\xd4\x7d\x20\xeb\xf2\xef\x3f\x12\x08\x57\xa5\xc9\x2f\x28\xd7\x90\xd4\xc0\x7a\xd1\x3d\xa3\xe8\xde\x10\xf2\x75\x98\x17\x13\x2f\x02\xbc\x12\xf9\x40\x2a\x6d\x58\xa1\x8a\x2a\x52\x09\x04\x20\x98\x80\x6a\x14\x91\xed\x46\x60\x19\x85\x83\x07\x10\x0d\x61\x1e\xfa\xd5\x38\xc9\xa2\x34\x5d\x2c\xb3\x10\x87\x3e\x19\xcd\x3e\x85\x01\x0e\xd1\x91\x3a\xa8\x72\x53\xfd\x61\x9f\xbc\x16\xec\x2f\xdb\x60\xbf\xaa\xbc\x41\x04\x53\x82\xba\x2a\x46\x54\x0c\xd3\x33\x0e\x6b\x25\x9b\x99\x04\x29\xc9\x31\xb2\xd1\x93\x49\x0e\x7c\xb8\x07\xe1\xbd\x21\x80\x83\xfb\x90\xd2\x4a\x61\xb4\xa5\xd0\x17\xed\xa0\x4b\xb5\x68\x5d\x85\xf9\xc0\xf0\x80\x83\xa8\x6c\x96\x20\x22\x0f\xb0\x66\x1a\xe4\xc8\x03\x70\x70\x0f\xde\xe3\xb5\xf6\x02\x89\x08\xcd\x7a\x2d\xc4\xc5\x67\x3c\xea\x6b\x54\x14\xd1\x05\x0a\x1c\xe7\x2e\xaa\x8c\x06\xef\xf1\x06\x07\x7b\xc3\xaa\x02\x04\x0d\xa3\x6b\xcf\xcb\x43\xe9\x21\xe7\xe5\xe1\xbb\x1c\x4f\x93\x02\x01\x60\x68\x69\x22\x8d\x62\x27\x64\xc3\x08\x7e\x28\x3c\x4c\x8f\x36\xb5\xa5\x51\x5b\xe9\x21\x50\x55\x1a\xde\xd2\x4a\xd3\x2d\x5c\x5b\xbc\x90\x14\xf0\x00\x51\xe4\xd0\xcf\x64\xd2\xf6\xc0\x2b\x45\xc6\x76\x58\x76\x34\xde\x2e\xef\x97\x01\x65\x35\x4c\x73\x15\xe4\x95\xd4\x8c\xb0\x5b\x4e\x50\xe6\x25\x30\x05\x55\xe1\x51\x1c\xc4\x32\x21\x22\x58\xae\x56\x03\x82\x85\xe8\x2c\xd4\xcd\x32\x82\x25\xa1\x20\x84\x4c\xd1\x1d\x0d\xeb\x8c\x00\x34\x89\x7a\x7d\xdd\xa1\x46\xfb\x1c\xa7\x82\x59\x25\x10\x52\xe2\x65\x10\x01\xa8\xf1\x48\x5c\xbd\xdd\xe4\x7b\x35\x40\xe3\x8a\x87\xd6\x60\xa6\xd4\x3a\xce\x7a\xf7\x8f\x33\xb8\x94\x66\x8b\x0a\xe4\x14\x17\x25\x92\xc0\xc9\xf0\x9a\x65\x52\xa6\x28\x70\x18\x64\x53\xfa\x41\x26\xe3\x58\xd2\xb6\x26\xdd\x4f\xec\x0a\xa4\x69\x14\xf3\x3a\x87\x4b\xaa\x0c\xd5\x4e\x85\xbe\x84\x52\x79\x6a\x3f\x06\x9a\x8c\xb5\xe3\xab\x88\x95\x4e\x31\x95\xc6\x2d\x4f\xa2\xd1\x65\x9c\xe3\x19\x9b\xda\x8e\xdf\x1c\xdf\xb3\x9c\x2d\x89\x98\x0a\x9d\x46\x73\xa8\x8f\xf3\x75\x26\x87\x9a\x74\x88\xba\x73\xca\xaf\x3d\xa1\x96\x6d\x96\xa0\xab\xfc\x2a\x60\x19\x8d\x46\x68\x56\x06\x4e\xb7\xc4\xd3\xd4\xe1\x32\x22\x99\x48\x12\x07\x0e\x6b\x63\x97\x0c\x66\x77\x44\x21\xc4\x61\x32\xb0\x43\x18\x3c\x47\xc9\xb9\xda\xca\x28\x3e\xd1\x62\x7f\x24\x94\x3b\x52\x6e\xb4\x75\xd1\x1c\x2d\x8a\xe0\x52\x5a\x6c\x06\xdc\x46\x4d\xc8\xa9\x8e\x74\x51\xb2\xd4\x8c\xc8\xbe\x1b\xeb\x92\xa2\x71\x79\x3c\xc2\x59\x05\xa0\xc3\xc6\xea\x00\x0b\x50\x64\x89\xb8\x17\x70\x08\xc6\xec\xb0\xb1\xf1\x68\x12\x8e\xa6\x41\xd8\xf1\x4d\x00\xa0\x8a\x04\x67\xcf\x77\xb8\x0c\x6b\x45\xb5\xd6\x95\x63\x6f\x2a\xdb\x60\x22\xfb\xb6\x93\x75\xb1\x1c\x18\x1d\x38\xf9\x89\x11\x3a\xe4\x0a\x3a\x87\x2c\x9d\x60\xb3\x97\x96\xd6\x14\xd9\x10\x8d\x49\xff\x36\x47\xa9\x1c\xfc\x30\x0c\xad\x53\xe5\xdc\x43\x25\x40\xdb\xba\xda\x23\xae\xa6\x72\x3a\x4e\xe3\x5b\x11\x35\x8f\xa7\x86\xd1\xa8\xce\xe7\x45\x12\x23\x99\xbf\x6e\x1f\xdd\x6b\x3d\xb2\x94\xb5\x6c\x82\x49\x12\x99\x40\x42\xdb\x3f\xcd\xa2\xd1\xe5\x93\x28\x87\x53\x8e\x2b\xeb\x03\xe0\x38\x14\x32\x4b\x84\xc6\xd5\x12\x41\x67\x75\x84\xd5\xb6\x5b\x2d\xe3\xc2\x0a\x6d\x11\xda\x40\x88\x60\xe5\x95\x5d\x79\x8b\x22\xd4\x1b\x45\xb2\x36\x48\x8d\x80\x79\xe1\xc3\xc7\x2c\x49\x50\xb7\x60\x59\x36\xbd\x1e\xa8\xa0\x8e\x2f\x44\x39\xee\x59\xac\x0a\xde\x03\x3c\x50\x8d\x58\x1b\xdd\x64\xa6\x11\xe4\x31\x8e\xf2\xcb\x8a\xd0\x6e\x2f\xe5\x2a\x95\xf9\x76\x77\x2b\xed\x96\x6f\xec\x7e\xc4\x30\x66\x50\xf7\x23\xcc\xa6\x61\xd4\x92\x32\x28\x12\xe9\x82\xf8\x65\x41\xac\xdd\x0f\x8c\xc3\xac\x7b\x26\x1d\x35\xf9\xb5\x15\xbd\x5c\x91\x41\x4d\xe5\xed\x4a\x18\x86\xb3\xbe\xc3\x33\xad\xb0\x4b\x16\xa1\xc2\x37\x63\xcf\x8a\x4d\x5f\x17\x7e\x76\x53\x34\x0b\x4d\xe3\x2d\xd4\xdc\x8d\x71\x3a\xd0\x99\x6b\x29\x8b\x34\x15\xf5\x82\xba\x61\xd1\x6e\x01\x3c\x0f\x17\xdd\xa4\xa0\xad\xfc\x9a\x14\xc9\x79\x8a\xe0\x75\x28\xf2\x50\x8b\x37\x37\xe1\xa2\x9b\xa3\x31\x3c\xaa\xfb\x4d\x5d\x86\x47\x44\xb4\x39\x0d\x8f\x08\xff\x7d\xa8\xfb\x4d\xdd\xb4\x6a\x2e\x9f\xa3\xad\xcc\xf8\x06\xda\xf8\x1b\x66\x75\x13\x00\x86\x30\x82\x97\x2c\x00\x95\x36\x78\x61\xfa\x1e\x52\xeb\x02\xcc\x8d\xb8\x55\xa8\xa8\x31\x47\x57\x29\x1c\x69\x89\x90\xec\xd9\xb9\xbd\x6b\x0f\xc0\x53\x32\x51\x00\x47\xae\x3b\xa2\xf9\xe2\x6d\x49\xa6\xcf\x3d\x04\x5c\xf7\xd4\xdb\xf1\x01\x8c\x5d\x37\x96\x89\xe5\x0f\x25\x3d\x52\x11\x6b\xd9\xd9\x1c\x35\x55\x8f\x2a\x6f\xcc\x1b\xc2\xfd\x53\x7f\xe0\xa7\x32\x15\xaa\xb4\x81\x93\xa5\x5e\xd0\x68\xaf\xf6\x62\x7a\xda\x9f\x7a\x01\xb5\xac\x7a\xae\x9a\xc7\xe9\x75\xb4\x28\xd6\x96\x86\xe7\x1c\x0f\xd8\xa2\x1e\x6c\x97\xfa\xb6\x61\x4c\x68\x7c\x95\x59\x63\x55\x94\x84\x5a\xdc\x04\x69\xbd\xa8\x22\x2b\x34\x6c\x17\x9b\x96\x8f\xb5\x50\x0b\xd3\x24\x8e\xa9\xb9\xc2\xb7\xd8\x55\xca\x24\xb1\x14\xec\x76\x93\x2c\xd3\x32\xd1\xf0\x90\xee\xb5\xc4\x36\x1c\x36\xb5\xb4\xb8\xdc\x22\x91\xfb\x47\xf3\xef\x35\xed\xf3\xab\x24\xbb\x74\x2a\xe0\xcd\x39\x96\x8c\xff\x56\x2c\xff\x45\x15\xcb\x1c\x25\x8c\x5b\xd5\xcb\x86\x0f\xc7\x4e\x18\x22\xd7\x15\x69\xf2\xa9\x52\x40\x66\xd5\xe7\x1a\x67\x21\xab\xc5\x5b\xc9\x6a\x6b\x45\x32\x0d\x43\xd7\xa5\x39\xf2\xd2\x12\xca\x25\x69\xf2\x37\x92\x29\x9f\x3c\x70\x34\xbc\x9b\x21\x58\x62\xc2\x85\xe2\x8b\x1c\x15\x05\x39\x31\x67\xc9\xd3\x27\x9d\x57\x04\x7b\x64\x49\x76\xe1\xd8\x78\x1b\x02\x75\xb3\xbf\xcf\xc2\x5f\xf4\x2c\xc0\xc9\x77\x3f\x05\xb3\x3f\xa4\xb1\x80\x59\x48\x7b\x79\x12\xe5\x77\x9d\x8e\x73\x77\x8c\x3c\xad\x10\x91\x68\xde\x71\xf8\x85\xa2\xdc\xe7\x0c\x97\x34\x3a\x14\x8a\xd5\xbb\x7c\x9e\x11\x90\x56\x2f\x8a\xf9\x68\x84\xf4\x12\xe3\x28\x49\x51\xdc\xca\x36\x59\xa4\x79\xc2\x38\x34\x4f\xe0\x63\x0c\x35\x0a\x3d\x4e\x6e\x50\xec\x68\x7e\x48\x16\xb9\xff\x2b\xb6\x4b\x92\xe3\xc4\xec\x8f\x2a\x56\x2a\x00\x5b\x16\xa0\x3b\x6d\x5e\xc2\xde\xc9\x89\xc4\x5c\x94\x14\x1e\x83\xd6\x8a\x75\x1d\x8e\x45\x4b\xf0\x01\x43\x7a\x21\xf3\xcb\x1c\xcd\x51\xbd\x25\xfa\xd2\x52\xa9\x48\x88\xf4\xaa\x84\xd5\xa0\x45\xf7\x69\xa9\xfa\x82\x2c\x63\x44\xa3\x97\x68\x95\xd8\x1b\x88\xb3\x33\x7c\x71\x91\xa2\x77\x8d\x02\xe6\x17\x4b\xbb\x1f\x31\x19\xd2\x09\x1a\xe7\xa8\x98\x98\x35\xf9\xcb\xb5\x42\xdd\x74\xbd\x50\xc7\x78\xc9\x71\x8a\x6e\x9e\xe7\xf8\x3a\xe8\x55\x5c\x1b\x66\xbc\x62\x00\xa7\x47\xd5\x14\xc8\x29\xb0\x24\xa4\x54\xa5\x54\x32\x78\xbf\x7b\xaf\x70\x20\x0f\xfe\x88\xba\xec\xa1\x1b\xe7\xd1\x35\xca\xef\xca\x1e\xb4\x83\xd0\xf4\xa2\x38\xca\x65\x31\x7e\x36\x9a\x65\x4e\x55\x19\x7e\x5c\x9a\x65\x0e\xf3\xee\xa7\xc1\x43\xdf\x1f\xca\xa2\xec\x20\x35\x4b\x7e\x92\x25\xa9\xf8\x39\xe1\x8c\xd5\xd5\xdf\xc4\xe4\xaf\x4a\x4c\x2e\x12\x23\x78\x04\xa4\xfa\x04\x41\x45\xd0\xb5\x97\xad\x56\x5e\x66\xbd\x2f\xc0\x6d\xf7\x05\xf9\xad\xee\x0b\xf2\x6f\xba\x2f\xc0\x9b\xef\x0b\x32\x7e\x5f\x90\x6d\x73\x5f\x90\x87\xf9\x9a\xfb\x82\x0a\x2e\x92\xf0\xef\x1b\xe8\xbf\x6f\xa0\xff\xbe\x81\xfe\xfb\x06\x7a\xdd\x0d\x34\x3c\xff\x3e\x06\x50\x9c\xcd\xb1\x9c\xd8\x0b\xc2\xaa\xf3\x01\xf0\x3f\x8d\xc0\xb3\x0c\x8d\x43\x2c\x5a\x5d\x24\xf5\x9b\xf1\x48\xde\x8c\x47\xd6\x9b\xf1\xc1\x7d\xc8\x51\x7e\x97\x8c\x75\x30\x43\x44\xee\x20\xff\x5c\x21\x79\x3f\x4d\x15\xfa\x93\xa8\x78\x4c\xbd\x0e\xcf\xa2\xf3\x14\x11\x2e\xb8\x7f\x83\xf4\x7b\xf2\xc8\xfc\x0a\xba\x6c\x33\x9a\x91\xa1\x3a\x31\xaa\x00\x08\x44\xbf\x39\x2a\x70\x7a\x85\xbc\x18\x81\x61\xe3\x86\x1d\x85\x91\xbc\x2b\x0f\x11\x39\xb9\x59\x88\x08\x78\xe5\x21\x22\xa0\x83\x43\x34\xb8\x37\xac\xdf\xa3\x6b\xbc\x31\xd4\x99\xeb\x20\x83\x9c\x8d\xcd\xa1\x36\x5c\xf9\x19\x57\x00\x8a\xdb\x74\xa0\xd9\x35\xe9\x6c\xac\xbe\x55\x9a\x81\x54\x4b\x64\x05\x5a\xa5\xaf\x55\x29\xd8\x9a\xad\xd9\x59\x5e\x79\x8e\xea\x7b\x89\xe4\x5e\xa2\xb6\xbd\x1c\x23\xf2\xd9\xe9\x76\xff\x99\xa3\x62\x3e\x45\x0e\x5c\x4e\x51\x39\xc1\x71\xe0\xbc\x7b\x7f\xe6\x54\xcd\xf5\x15\xab\xab\x4d\xdb\x03\xc1\xbf\x61\xc0\x74\xa9\xbe\x71\xbc\x52\x3a\xd9\x11\x4b\x5e\x19\xfb\x67\xb3\x4b\x43\xdb\x9e\xb4\xd6\xb3\xb5\xc9\xea\x64\x70\x1f\x4e\x91\x87\xda\xad\x46\x0a\x54\x9e\x25\x53\x84\xe7\xa5\xa7\x5d\x77\x71\x94\x00\xf7\x7d\xdf\x0e\x8d\x4f\x69\x1c\xa9\x7f\xc3\x6c\x16\x7f\xc6\x6c\x5e\xe3\x2b\x3a\x97\x33\xfc\x2c\xc7\x59\xf9\x0d\x53\xa2\xfc\x22\xcc\xda\x91\x60\x2e\xa7\x96\xb7\x4d\xed\xdc\x36\xb5\x5c\xa1\x1e\x03\xc1\xc0\x2c\x5c\x56\x70\x70\x1f\x12\x6c\x59\xb7\xee\x29\x75\x3d\xcc\xc0\xcb\x94\x4c\x1e\xca\xf6\x32\x30\xdc\xb4\x18\x4f\xa2\xd1\xb7\x6c\xef\xf7\x58\x8b\xeb\xff\x8c\xb5\x60\xb7\xfd\x8f\x9b\x68\xfa\xdb\x97\x25\xd4\x49\xb0\x75\x6d\xc4\xc0\xc3\x9d\x5e\x8d\xa8\x68\x37\xb1\x5a\x31\x44\x44\xc4\x3a\xe9\x83\xcb\x26\xb1\x24\x0c\x62\x05\x6c\x47\x71\x8b\xa1\xff\x81\xfd\xec\x94\xae\x8b\xfa\x83\xfb\xf0\x86\xee\x6a\x30\xd8\xab\xef\x6c\xa6\xf6\xa2\x46\x46\x6d\xb3\xf0\x61\x6d\xb2\x01\xb2\x92\xd2\xcc\x24\xa5\x80\xfd\x92\x5b\xcc\x0d\xb1\x14\xa1\x5e\x72\xfb\x68\x1a\x63\x06\xfe\x4e\xdf\x0d\x88\xd4\xa4\x93\xef\x65\x11\x44\xa8\xfb\x46\xa9\x14\xe9\x5d\xe1\x54\x3a\x99\x5b\x97\xbd\x31\x60\xc7\xb1\x8e\x38\x46\x82\x39\xd8\xe9\x69\x46\x5e\x57\xb7\x54\x99\x72\x28\xdb\xce\xd6\xeb\x39\xa4\x3e\xa1\xec\xa2\xeb\x9f\xd7\xe8\xdc\x62\xa1\x53\x70\xcf\xf4\xfa\xfb\x69\xd2\x50\x02\x2a\xd3\x12\xfa\xd2\x5c\xbc\x5a\x09\xa9\xaa\xd5\x15\x7b\xec\xb3\x54\xec\x19\x9a\x39\x13\x9f\x37\x35\x89\x0d\x63\x18\x9b\x62\xb0\xc9\x4f\xd9\x8c\xa0\xa6\x51\x92\xb5\x98\xc0\x35\x54\xbf\x59\xb7\xc4\x38\x3d\x8f\x72\x4b\x43\xbf\xd8\xdb\xf8\x99\xf0\x0b\xe5\x24\x70\xfe\xa9\xdd\xb7\x34\x1c\x72\x72\xb6\xbc\x9b\xd6\xcf\x66\x8e\xa4\x3a\x20\x25\x6d\xad\xbf\xcf\x36\x6e\xde\x05\xa2\xcb\x78\x38\xbe\x08\x2e\x10\xc4\x19\x23\xfb\xfa\x32\x2a\x46\x80\x06\x72\xbb\x42\x9c\x86\xea\x65\x6a\xe4\x55\x16\x24\xf4\xc5\x5e\x8e\x7c\xd9\x34\xa9\xf3\x14\x39\x15\x34\x50\x22\x77\x5f\xe8\xa6\x78\x44\x15\xa3\x6d\x20\xff\x9a\xea\xae\xc5\x59\x8c\xd1\x08\xc7\xe8\xfd\xc9\xb1\x54\xee\x7a\x04\x1b\x45\xf9\x68\xd2\x2d\xe6\xe7\x45\x99\x7b\xf7\xc8\x58\x8c\x93\x8a\x9a\x12\x87\x84\x66\x61\x37\x66\xa1\x1b\x01\xda\x44\x59\x68\xac\xc5\xe6\x5e\xc1\x65\x89\x0d\x60\xb1\x2a\xa5\xe1\xf5\x7a\x75\x34\x07\xd3\x00\x75\xa7\xc9\x4d\x92\x15\x12\x6e\x2b\x00\xbc\xf3\x04\x1c\x78\x3e\x9c\x73\xd4\xd2\x0c\xa0\x75\x9d\x70\x34\x10\xe3\x11\xbd\xda\xa9\x47\xb0\x75\xa2\xd9\x8c\x66\xff\xf3\xe8\x7f\x07\xff\x7f\x00\x00\x00\xff\xff\x5d\x5c\xd5\xa7\xeb\x7c\x06\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xcc\xbd\x7b\x9f\xdb\xb6\xd1\x30\xfa\xff\xf9\x14\x5a\x34\x8f\x4a\x44\x23\x2e\xa9\xfb\x72\x8b\xa8\x8e\xe3\x34\x4e\x63\x3b\xb5\x13\x27\xb1\xa2\xfa\x70\x45\x68\xc5\x98\x02\x15\x12\xda\x8b\x25\x9e\xcf\x7e\x7e\xb8\x91\xa0\x44\xad\xb7\x69\xdf\xb7\x4f\x9d\xae\x40\xdc\x31\x18\x0c\x66\x06\x83\xc1\xf9\xe7\x67\xad\xaf\xd3\xac\x95\xc4\x0b\xca\x72\xda\x8a\xd9\x32\xcd\xd6\x21\x8f\x53\xd6\xda\x24\x34\xcc\x69\x2b\xa7\x22\x3a\xa2\x77\xee\x6f\xb9\xfb\xdd\xf3\xa7\xcf\x5e\xbe\x79\xe6\xf2\x3b\xde\xfa\xfc\xfc\xff\x71\x1c\x4c\xbe\xd8\xdd\x84\x59\x8b\x92\xdd\xb0\xef\x4f\x02\x4a\xbe\xd8\x51\x97\xde\x6d\xd2\x8c\xe7\x64\xb9\x65\x0b\x51\x97\x43\xf1\x2e\xa3\x7c\x9b\xb1\x16\x6d\xb7\xa9\xfb\xfe\x3d\xcd\x5f\xa4\xd1\x36\xa1\x53\x1a\xec\x22\xba\x0c\xb7\x09\x0f\x68\x51\x40\x59\xd6\xd5\xb1\xa4\x8c\xb1\xd2\xaa\xf2\xe4\xcc\x2b\x60\x32\xea\x05\x0e\x05\x0e\xcc\x74\x27\x23\xcc\x99\x60\x53\xc7\xa5\xe9\x47\x2b\x15\x3d\x89\x97\x0e\x32\x31\xe8\x8c\xf0\xfb\x0d\x4d\x97\xad\x9f\x68\xf8\xe1\x45\xb8\xc1\xba\x9f\x6c\x9b\x24\x97\xa2\x2a\x4e\x18\xbd\x35\xa9\xc0\xec\xaf\x4b\x95\xd7\x49\x1b\x07\x3a\x65\x01\x2f\xb0\x43\x71\xd1\x04\x10\xe0\xb2\x23\x67\xbc\xdd\x3e\x00\x89\xe9\x01\xbd\x8c\x97\x8e\xe8\x06\x21\x84\xee\xf7\x28\xbd\xfa\x8d\x2e\x38\x3a\x23\x24\x73\x28\x6e\xb7\x1b\xc6\x60\xca\x5a\x20\x95\x63\x60\x24\x75\x38\x96\xf5\xb5\xdb\xcc\x5d\x85\xb9\x43\x71\x39\x52\xf7\x9a\x72\x87\x62\x99\x33\x24\xbb\x02\x62\xf2\x4a\xb6\x25\xe0\x17\x33\xfa\x7d\x96\x6e\x68\xc6\xef\xdb\x6d\x1d\x7d\x4d\xf9\xab\x5b\x66\xa2\xbf\xa2\xf9\x22\x8b\x37\x3c\xcd\x2e\x97\x69\xe6\x88\x5a\x92\x56\xcc\x5a\x14\x0b\x40\xeb\x9e\x88\x6e\x27\x65\x05\x9b\x2c\xe5\xa9\xe8\xb3\xe8\x8a\x55\x95\xbb\x08\x93\xc4\xa1\x90\x60\x2c\xa7\x31\x27\xf1\xf4\x13\x6d\xca\xdc\x81\x9c\xad\xbc\xdd\x76\x72\x91\x71\xbf\xcf\xdd\x9c\x72\x3c\x6d\x1c\x86\x13\x42\x02\x39\x0e\xc2\x59\x32\x27\x74\x96\xcc\x0b\x0d\x88\xb0\xc2\x39\x90\x70\xca\x05\x5c\x20\xc4\x10\xfe\x51\xc4\x94\xeb\xa1\xc4\x3e\xee\x30\x83\x1e\xd5\xe4\x11\x33\x79\x6f\xee\xd7\x57\x69\xd2\x6e\xa3\x5c\x06\x0e\x13\xdc\x98\xd3\x2c\xe4\x69\x36\x75\x2a\x7c\xe2\x4d\x98\x67\x90\xe1\x0f\x75\x1a\x07\x9f\xaa\x9e\xda\xa8\x77\xd4\x7b\xea\x2e\x52\x96\xf3\x6c\xbb\xe0\x69\x46\x08\x29\xe3\xcf\x4c\xb8\x9a\xfd\xa9\x19\x6a\xf0\xef\x75\x19\x04\x60\xad\x55\xc6\xff\xe0\x6c\xf5\xfb\x03\x8b\x8e\xa0\xad\xa0\x7e\x3c\x8b\x17\x1c\x5d\x32\x37\x72\x38\xec\xde\x05\x82\xe2\x65\x05\xbe\x94\xa3\x6c\x65\x64\x37\xf4\x02\xf4\x27\x3a\x59\x0e\xe9\x05\x02\xdf\x13\x5f\x8b\x09\x1d\x2d\x2e\x10\xf4\xe4\x57\x38\x8c\x46\xe1\x18\x41\x5f\x7e\x4d\xfc\xc5\x78\x32\x40\x30\x90\x5f\xa3\xd1\xd5\xd5\x28\x44\x30\x94\x5f\x83\x45\xb8\x1c\x7a\x08\x46\xea\xab\x1f\x7a\x83\x31\x82\xb1\xfc\xea\x4f\x26\xb4\xbf\x40\x30\x91\x5f\x3d\x3a\x8e\xfa\x3d\x04\x17\xf2\xcb\xbf\x1a\xd2\x9e\x87\xe0\x89\x6a\xfe\xea\x62\x39\x5a\x84\x08\x9e\xa8\xf6\x47\x17\x4b\x2f\xa4\x08\x9e\xa8\x26\x3d\x8f\x8e\xc6\x23\x04\x4f\xc6\xfa\x73\x31\x19\xf6\x51\x51\x40\x7f\x38\xf1\xff\xe0\xf0\x97\x4b\x7a\x45\xa9\x19\xfe\x72\xb9\x88\xa2\x9e\x19\x3e\x5d\x5e\x84\x17\xa1\x19\x3e\x1d\x8e\xfb\xe3\xbe\x19\x3e\x5d\x0e\xfb\x62\xc0\x6a\xf8\xcb\xc1\xa0\xdf\x1f\x99\xe1\xd3\x61\xff\xa2\x3f\x34\xc3\x8f\xfa\xbd\x65\x6f\x69\x86\xbf\x18\xf5\x26\xbd\x89\x19\xfe\xd5\xd8\x5f\xf8\x8b\x72\xf8\xcb\xe5\x24\x9c\x78\xe5\xf0\x97\xcb\x61\x6f\xd8\x2b\x87\xbf\x5c\xfa\xe3\xc1\xa0\x1c\x7e\x34\xf4\x3c\xcf\x13\xc3\xbf\x18\x5d\xf4\x3f\x31\xfc\x75\x2c\xc7\x9f\xc0\xfb\x81\x0c\x6c\xe1\xeb\xdf\x65\x60\x01\xef\x7f\x93\x81\x08\x3e\x63\x32\xb0\x2c\x14\x3d\x15\x1b\x51\x6f\x32\xc1\x07\x5b\x90\xda\x58\xc2\xec\x7a\xbb\xa6\x8c\xe7\x6e\x42\xd9\x35\x5f\x7d\xe1\xb7\xdb\x37\x69\x1c\xb5\xbc\x33\x52\x25\xce\xfc\xf9\xd4\xfe\x08\x3c\x60\xc7\x45\x7b\x8d\x45\x7b\x76\xd1\xde\x3c\xf0\xf5\x96\xd5\x7a\x11\xf2\x95\xbb\x8e\x99\xa3\x02\xe1\x9d\xc3\x81\x62\x60\xb8\x28\x3b\x1a\xea\xbd\x92\xba\x62\x75\xd6\x76\x25\xf4\x27\x24\x36\x25\x77\xb1\x0a\xb3\x27\xdc\xf1\xca\xbd\x24\x74\x6c\x82\x41\x09\x75\xf3\xed\x55\xce\x33\xc7\xc7\xd6\x66\xfa\x9a\x5e\x3f\xbb\xdb\x38\xc8\xdd\xf9\x80\x04\xbd\x58\x84\xdc\xa1\x66\x24\x64\x34\xed\x05\x3e\xa0\x02\x61\x40\xd7\x08\x03\x23\xd4\x5d\x87\x7c\xb1\x12\x7b\x98\xd9\xb4\xda\x6d\x9f\x10\xc2\x66\xde\x5c\x97\x6b\xb7\x1d\x46\x98\xbb\x0e\x37\x8e\xd3\x44\xb5\x3a\xb4\xc0\x18\x03\x9b\xa2\xec\xfa\xaa\x6c\x75\x20\x2a\xd1\x35\x4c\x51\x88\x02\x84\x00\x39\x08\x9b\xf4\xa3\x0a\xc5\xbe\x6d\xe8\xec\x5f\xfa\xd3\x4d\x98\xe5\xf4\x39\x13\xfb\x84\x3f\xc2\x81\x84\x66\x96\x6e\x59\xe4\xd4\x53\xce\x7b\xc3\xe1\xe7\x3e\xed\xe3\x73\x9f\xf6\x0b\x8c\xdd\xdf\xd2\x98\x39\x08\x5a\x62\x90\x18\xe1\x00\xa1\x42\xec\xc9\x1a\x4a\xd4\x95\x2c\xd7\xab\xa5\x23\x3a\x23\x21\xa0\x00\x19\xb3\x6b\xc7\x03\xb5\x97\x77\x05\x04\x66\x72\x38\x20\xfe\x86\x08\xd0\x2a\x4f\xd4\xdf\x10\xcd\xcb\x3a\x18\xc6\x7c\x95\xa5\xb7\x2d\x01\xfc\x67\x59\x96\x66\x8e\xe3\x41\xe6\xbe\xc3\x4e\x1f\x4c\xa3\x69\xad\x0d\xde\xf1\xc1\xcc\x48\xd7\xc7\x6e\xbe\x49\x62\xee\x20\x40\x66\x06\x76\x02\x29\x02\x06\x37\x61\xb2\xa5\x79\x90\x92\xf4\x24\xe8\x25\x24\xbe\x4e\x52\x31\xc9\xb8\xc0\xb8\xa8\x70\x2c\xae\x16\x83\x42\x33\x39\x54\x55\xa7\x6e\xa8\xeb\x9f\x11\xc2\x2b\x78\x88\xe1\xe2\x69\xc3\x54\x3f\x30\x33\x1e\x0e\xc4\xec\x07\x87\x75\x09\x68\x61\x81\x38\x33\x7f\x4e\x50\x89\x14\xe2\x13\xd0\xff\x08\xc0\xcf\x7a\xf5\x84\x9e\x4a\xc0\x50\x45\xf2\x03\x84\x39\x98\xd9\x6a\xb0\x89\xea\xa3\x62\xc8\x04\x07\x06\x19\xc9\x2b\x9c\xae\x96\x22\x83\x0c\x77\x5c\x6f\x88\xcf\x9d\x72\x9d\x96\x71\x55\x7d\x79\x05\x3c\x39\x12\x42\x88\x43\x89\x58\xb6\x58\xc2\x72\x5a\x5f\x8d\x2a\x67\x99\x43\x01\x19\x18\xe1\x33\x6f\x0e\x19\xe1\x33\x7f\x7e\xee\x7b\x1e\xa4\x84\xcf\x7a\x2a\x98\x90\xec\xf3\xb2\x07\x29\xf8\xdd\x14\x43\x9d\xab\xff\xb7\x08\x99\x43\x3b\xec\xbc\xef\xe1\xff\xf1\x7b\x66\x5d\xa7\xdd\xe4\xf3\x12\x0e\x65\xd3\xbc\xdb\x87\x8b\x2e\x07\x1f\x43\xd7\xc7\x05\x6c\x89\xc2\xfa\x05\x99\x59\x2b\x4e\x2c\xb1\x5c\x10\x23\x38\x8a\x9c\x34\x45\x0e\x30\x9e\xeb\x76\xd5\x8a\x91\x34\x4d\x40\xae\xdd\x76\xb6\x1d\x82\x42\x04\x0b\x77\xb3\xcd\x57\x0e\x9f\xf5\xe7\x18\x43\xec\x28\xb4\xdf\x1a\xb4\x5f\x14\xb8\xb0\xa0\x19\x1c\xe0\x6e\x8b\x13\x7e\x6a\x59\x38\xf4\x9c\xf4\x86\x43\xfc\x17\xe2\x7a\xfd\x8b\xde\x64\x4a\xcf\xfd\x9e\x7b\xd1\x53\x34\x64\x93\xde\x3a\x0e\x15\x13\x3e\xc4\xe7\xbe\xf8\x81\x9e\x3b\x10\xab\x07\x5e\x6e\xd7\x57\x34\x73\x1c\xb7\xe7\xf7\x46\x9f\x8b\xd9\xeb\xb8\x63\x7f\xd8\xfb\x5c\xcc\x60\xc7\xf5\xc6\x3d\x11\xec\xcd\xb1\xcb\xd3\xaf\xe3\x3b\x1a\x39\x7d\x6c\x61\xcd\xf6\xdf\x9e\x36\xd7\x1f\x9a\xf1\x09\x14\xfc\xc2\x1d\x4e\x23\x89\xda\xc1\x52\xfe\x54\x6d\x2d\x6a\xab\x52\x61\x1e\x70\x29\x8c\x48\x8a\x25\xa4\x02\x03\x71\x89\xc2\xe5\xf7\x7e\xaf\xf7\x1d\x39\x0d\x18\x0c\x60\x67\xfd\x39\xe1\x20\xc8\x46\xd5\x4a\x54\x4a\x53\xf5\x16\xe4\x6a\x57\xb5\x1c\x2c\x79\x5c\x56\xd7\x9b\x7f\x4e\xfc\x2e\xbf\xa4\x89\x90\x7e\x05\x4d\x6d\x28\x23\x49\x0e\x36\xc2\x0d\x23\xde\x25\xfb\x4b\xff\x92\x75\x88\x5f\x55\xc4\x74\x45\x7a\xac\xf5\x1e\x2e\xff\xad\x1e\x76\x88\xe3\x7b\x5e\xd7\x8a\xc1\x9f\xff\x47\x7a\xdc\x21\x62\x25\x74\xad\x18\x51\xb1\x3d\x82\x02\xfa\xe3\xe1\xe3\x98\x42\x6a\x71\x3c\xc3\x8b\xc9\x18\x43\x2a\x43\xc3\x3e\x86\x90\x30\x67\x3c\x18\xf5\x30\xc4\x64\x86\xee\x72\x04\x28\x5f\x23\x40\xeb\x08\x01\x4a\xae\x11\xa0\xbb\x04\xcd\x2f\x6d\x4a\x59\x6d\x0b\x25\xa1\x52\xa8\x49\x08\xe1\xd3\xdd\x5d\x1e\x78\x90\xaf\x83\x91\xe7\xc1\x3a\x0a\x2e\x46\x1e\x24\xd7\x81\xdf\x9b\x78\x70\x97\x04\xfe\x45\xcf\x2b\x02\x0e\x62\x4f\xdb\xb2\x98\x43\x52\x15\x4e\xa7\x68\x73\x87\x82\x14\x72\xb1\xe1\x71\xba\x81\x6d\x95\x98\x4f\x87\x41\x0e\x0b\x62\xb6\x47\x0a\x33\xa4\xda\x47\x80\x44\x4d\xa2\xe7\x9c\x6e\xd0\xdc\xe2\xe8\x22\x8b\x0e\x33\xb9\x38\x2b\xb1\x88\xcd\xe8\x7c\x2a\xfe\x04\xd4\x90\x9a\xbf\xae\x69\x14\x87\x2d\x67\x1d\xb3\xee\x6d\x1c\xf1\x55\x50\x6d\x25\xe5\x36\x92\x1c\xec\x1d\xcb\x6a\xef\xc8\x48\x5c\x4e\x74\xc5\x10\x09\x59\x2b\x2e\x37\x6c\xb1\x20\x71\xf0\x50\x53\x0f\xf5\xb4\xd6\x8b\x56\xc8\xa2\x16\xc2\x1d\xe4\xac\xc3\xbb\xc3\x5a\x14\xf6\x65\xed\x76\x43\x75\xf1\x2c\xeb\xf8\x73\x51\xa7\x0e\x05\x1c\x77\xb7\x62\x5f\x39\x1c\xa5\x26\x88\x1e\x84\x02\xe6\xbb\x0f\xf4\x3e\x0f\x62\x43\x62\x19\x6c\x37\x41\x04\x51\x7a\xcb\x82\xe3\x9d\xa7\x02\x05\xc5\x1d\x1f\x32\x22\x5a\xe3\xf3\x79\x45\x80\x2b\xb0\x4c\x23\x47\xe0\x9e\x0d\x97\x86\x11\x1d\x8d\x24\x6b\xb7\xf9\x17\xde\x34\x0b\xe8\x89\xee\xc3\x15\xe5\xb7\x94\xb2\x60\x09\x29\x4b\xee\x83\x06\x16\x48\x4c\x1f\xc5\x05\xa8\xc6\x1a\x32\x08\xc0\x17\x05\x2c\x70\xa1\xf4\x1e\xcc\x19\x5c\x0c\x7a\x16\x92\x6d\xf5\x22\x54\x28\x70\x79\x00\xb2\xeb\x2d\xe7\x34\xcb\xab\x9a\x0d\x9b\x71\x44\xe2\xbd\x46\x12\xef\xd9\x24\xde\x9b\x07\xbb\xc2\x00\x50\x08\x7a\x69\x42\xdd\xdb\x30\x63\xce\x0c\xbd\x08\x39\xcd\xe2\x30\xe9\xfe\xf8\x3c\x68\xf1\x15\x5d\x53\x77\x1d\xdf\xc5\x2c\x77\x75\x17\x1c\xdc\x8a\xf3\x56\x44\x37\x19\x5d\x84\x9c\x46\x2e\x02\xf4\x4b\xba\x6d\x2d\x42\xd6\x12\xc4\x83\xaf\x68\x2b\x4f\xb7\xd9\x82\xb6\xd2\xa5\xfc\x92\xe5\x5b\x51\x9c\xd1\x05\x4f\xee\x03\x04\xe8\x57\xd6\x92\xff\xdb\x84\x51\x14\xb3\xeb\xef\xe8\x92\x9b\xc6\xf2\x4d\xb8\x10\xfc\x69\x0f\xc3\x41\xae\xd7\xf1\xf5\xea\xa1\x6c\x33\x95\x72\x95\xd1\xf0\xc3\x26\x8d\x05\x48\xb6\x1b\xe7\xcf\xf9\xfa\xcf\x78\x1e\xb4\x76\x26\xdb\x83\xad\xf6\xab\xea\x1e\x6e\xd7\xca\x58\x94\x21\x34\xd7\xbc\xe1\xaf\x4c\x70\x90\xe5\xe4\xd9\x0d\x72\xd1\xe5\x5a\xcd\x22\xa6\x00\x26\xb2\xe7\x32\x7b\x01\x54\xf4\x5c\x50\xd0\x93\x95\xf4\x8f\x2a\xe9\x8b\x4a\x66\x55\xc9\x39\xc6\xb8\x00\x9e\xa6\xc9\x55\x98\x05\x4e\x46\x76\xeb\x98\x7d\x43\x65\xee\xe1\xa8\x28\x9b\xcb\x2c\x4e\x57\x95\x16\x4b\x08\x90\x24\x0b\x4e\x9a\xc5\x94\x71\xa9\x2f\x0e\x5a\x49\xc8\xa2\x7c\x11\x6e\x28\x46\x18\xac\xea\x06\x93\x02\x5b\xf5\x59\xbd\xb7\x32\x8d\x06\x05\x86\x4c\x74\x52\x2d\x81\x85\x11\x9c\x95\xa6\x21\x22\xbb\xab\x24\x5c\x7c\x90\x1a\x0b\x0f\xc1\xed\x2a\xe6\x54\x8a\xf3\x4b\x54\xc0\xd2\xe8\x21\x42\xf1\xaf\xd4\x43\x0c\xc5\xbf\x52\x0f\x21\xff\x57\xea\x21\x3c\xf1\xcf\xe8\x21\xae\x22\xf1\xcf\xe8\x21\x2e\xa8\xf8\x67\xf4\x10\xe3\xa1\xf8\x67\xf4\x10\x23\x5f\xfc\x33\x7a\x88\x41\x4f\xfc\x33\x7a\x88\x9e\x2f\xfe\x95\x7a\x88\x68\x28\xfe\x95\x7a\x88\x50\xfe\xaf\xd4\x43\xf4\x3d\xf1\xaf\xd4\x43\xe8\x7a\x0b\xd8\x10\xf4\xa7\xf1\xc5\x64\xb4\xb8\x42\xb0\x22\xe8\x4f\xfd\xe5\xd0\xbf\x1a\x22\x58\x13\x59\x66\x79\xb1\x44\x70\x43\xc4\xc0\x07\xde\xc4\x47\x70\x2d\xc2\x43\xcf\x1b\x8e\x11\xdc\x13\xf4\xa7\xc5\xd0\xf7\x47\x3d\x24\xb7\xe2\x2b\xc2\x9c\xfe\x70\xe2\x1b\x20\xde\xca\x72\x57\xe3\x41\x84\xe0\x4e\x86\x2f\x26\x02\x98\xcf\x64\x1d\xe3\x85\x08\x7f\x20\xe8\x4f\xa3\xc1\xd5\x70\x39\x42\xf0\x86\x88\x41\x5d\x8c\x96\x7d\x04\x4f\x09\xfa\x93\x7f\x31\x1e\x45\xba\xee\x77\x84\x39\x93\x7e\x7f\x80\xe1\x7b\xc2\x9c\x8b\xd1\x45\x1f\xc3\x6b\xb2\xe3\xf4\x8e\x07\xbb\x4d\x16\xaf\xc3\xec\x3e\x90\x52\xa9\xe3\x41\x4b\xff\xe7\x4e\xc6\x18\x41\x4e\x17\x29\x8b\x1a\xd3\x87\x03\x8c\x20\x8a\xf3\xf0\x2a\xa1\xd1\x71\x72\x7f\x82\x11\xac\x62\xc6\x9b\x93\x0a\x88\xe2\x9b\x38\xa2\xd9\x71\xb2\xdf\xc3\x08\xae\xc2\xc5\x87\x6b\x29\x01\x04\xbb\x4d\xb8\xa1\x59\x10\xb9\x12\x91\xc0\xe8\xcb\x97\xb3\xa1\x37\x2f\x20\x94\x44\x34\xd8\x89\xdf\x1b\x7a\xa2\x9b\xab\xf4\xa6\xa9\x25\xaf\x4c\x7b\x25\x88\x01\xbf\x0f\x5c\x6f\x00\x39\x4d\xe8\x82\x37\x8d\xc9\x9b\x48\x90\xa8\xe4\xaa\xc8\xe4\x01\x30\xf4\x46\x16\x94\xbe\xac\x06\xd5\x3c\x6a\x93\xb1\xac\xbb\x3f\x81\x65\xba\xd8\xe6\x27\xf2\xcb\xb4\x32\xb3\xdf\x93\xd0\xb8\x09\xed\xde\xf9\xbd\xa2\x80\x57\x87\xb3\x6d\x80\x79\x38\xbf\xbd\xe1\x10\x5a\xd5\x1f\xcf\x1d\x1f\x4f\xf2\x51\x9e\x61\x7d\xa6\x1b\xd3\xe3\x45\xca\x1e\x48\x3f\x44\x87\xa3\x3c\x27\x90\x62\x39\x9b\x78\xde\xbc\xc4\x89\x72\xad\x1e\xe1\x85\x19\xb0\x8d\x09\x47\x8d\xc8\xf9\x3d\xc0\x87\xc9\x21\x3e\x1c\x77\x6d\xd4\x84\x15\xfe\xe8\x93\x70\xeb\x3f\x84\x1a\xcd\x10\xf8\x14\x82\x34\x97\x7a\x04\x9a\xf4\x06\x45\x51\x71\x30\x3f\x28\x0e\x06\x32\xc5\x9b\xa4\x24\x73\x13\x41\xfa\xf7\xfb\x0c\x42\x92\xb9\x51\x98\x7d\xd8\xef\x7d\x77\xf8\x79\x76\x49\x67\x7c\x2e\x45\xc0\xfa\xf9\x90\xc3\xf0\x54\x24\x11\x3a\x63\xf3\x00\xc9\xe2\x48\x0a\x04\x54\xd5\x25\x18\xf7\xef\xdd\xcf\x18\x76\xa8\xbb\x0e\x63\x06\x29\x0e\x90\xa8\x58\xe6\x6a\xb7\x1d\x2a\x9b\x51\xd9\xde\xff\x56\x66\x0b\xb1\x2d\x22\xbf\xb4\xc5\x0f\x8d\xdd\x07\xf2\x87\x6c\x2d\xd8\x80\x28\x1d\xac\x40\x54\x1a\xac\x85\xc8\x11\x0b\xa9\xc2\x2c\x00\x5b\xee\x88\x4d\xa1\x1b\x55\xe8\x5a\x15\xba\x2f\x82\x58\x8a\x22\x34\xcb\xd2\xac\x2e\x8b\xe8\x02\x57\xee\xbb\x59\x5f\x60\xa4\x2c\x27\xbe\x86\x12\x3f\x45\x71\xf1\x35\xf6\xbc\x79\x11\xe4\xf0\x92\x28\x36\x2d\x66\xd7\xf0\xbe\xaa\xe7\xa5\xa9\xe7\x56\x55\x70\xa7\x4a\x3e\x2b\x82\x97\xf0\x42\x6a\x1a\x97\x29\x3c\xaf\xf2\xbf\x30\xf9\x3f\xa8\xfc\x6f\x54\xfe\xa7\x45\xf0\x02\x9e\x48\x25\xe1\x62\x41\xf3\x1c\xbe\xab\x8a\x3c\x31\x45\xde\xd5\xba\xfa\xae\xd6\xd5\x77\x65\x57\x9f\xc0\x47\xa3\xee\xfb\xaa\xaa\xe4\xe3\x54\x4f\x68\xf0\x11\xbe\x26\xf2\x1c\x89\x67\x61\xce\x7f\x58\x65\x34\x5f\xa5\x49\x04\x5f\x56\x99\xbf\x9e\xf6\x83\xaf\xe1\x37\x51\x4d\xca\xc2\xe4\xd5\x72\x99\x53\x0e\x3f\x55\x19\x7e\x9b\xba\xbd\xe0\x37\xf8\xac\x26\xca\xe9\xb9\x14\x42\x9c\x99\x22\x04\x48\x42\x1e\x01\xd2\xb0\x43\x80\x04\x48\x44\x26\x35\x52\x04\x48\xf4\x15\x01\x3a\xea\x92\x48\xaa\xda\xaf\x49\x85\x3f\x5a\xaa\x1e\x81\x6d\xeb\x58\xf4\xe1\x95\x2b\x68\xa6\x41\x2a\xfc\x05\xf9\x72\x5a\x8f\x0a\x5e\xd7\x3e\x25\x2f\xf4\xf6\x3f\xa7\x72\x1b\x7a\xff\xc6\xe9\x41\xdf\xf3\x20\x3b\x2e\xdc\x6f\x2c\xdc\xb7\x0b\xf7\xe7\xc1\xd8\xf3\x2e\xe3\xa5\x73\xe6\x50\x52\x32\xad\x05\x50\x8c\xe5\x0a\x6c\xb7\xc5\xba\x96\x0b\x54\x7c\x12\xf1\x85\xe1\x4c\x7d\x35\x69\xaf\x17\xa2\x82\x01\x70\x2c\x55\xe1\x48\xa9\xad\xad\x93\xf0\x87\x0b\x0e\xe1\xdb\x37\xaf\x5e\xba\xaa\x54\xbc\xbc\xd7\xcd\x62\x5c\xca\xd3\x82\x5a\x69\x7c\x04\x06\x3f\x61\x90\x11\x92\x94\x40\x26\xbe\x2d\x04\xa5\x77\x5c\x12\x2b\x3b\x82\xfc\x58\xd6\x09\xb4\x80\x6f\xc8\x4e\x2e\x82\x57\xa0\x16\xca\xeb\xa2\x12\xe1\x52\xd1\xa3\x12\x26\x8b\x74\xbd\x4e\x59\x10\x81\xd4\x34\x7e\x05\x06\x2f\xde\x3a\x0c\x5b\x5b\xeb\x5b\x21\x7d\x0a\x5e\x12\x01\x12\x1c\xa6\xf8\x19\x7b\x1e\xc2\x20\xd1\x39\x78\xeb\x6c\x31\x68\x8c\x0e\xde\x3a\xef\x31\x08\xa4\x0e\xde\x3a\xcf\x31\x68\xbc\x0e\xde\x3a\xdf\x61\xb8\xce\xe8\x7d\xb0\x84\x23\xd4\x0e\xbe\x84\x6b\xca\x9f\x5a\x43\x0a\x7e\x84\x70\x7b\x2d\x26\xf4\x69\x9a\x88\x26\xc0\xc2\xfd\xe0\xa7\x02\xbe\x99\x7d\x35\xc7\xf0\x99\x45\x49\xdf\x5b\x22\xae\xa5\x7f\xf5\xe9\xf0\x73\x8a\xcf\x7d\x3a\xac\xb2\xbe\xb0\xb2\x8a\x62\x12\xf3\x9f\x2b\x1e\xe3\x87\x2c\x64\xf9\x32\xcd\xd6\x01\xda\x6e\x36\x34\x5b\x84\x39\x45\x05\x3c\x21\x7f\x46\xaf\xd3\xab\x94\xa7\x08\x5a\xe8\x1b\x9a\xdc\x50\x1e\x2f\x42\xf1\xf1\x44\x08\xa9\x08\x5a\x79\xc8\xf2\x6e\x4e\xb3\x78\xf9\xe7\x6a\x69\x7e\x67\x2b\xe2\x1b\xce\xb2\xf9\x94\x3b\x14\x4b\x62\xce\xdc\x65\xca\xf8\xd7\xe1\x3a\x4e\x0e\xa8\xf9\x13\x49\xb7\x55\xfa\x9b\xf8\x23\xad\x93\x6e\x7f\x20\xf5\x48\x2a\xf9\x27\x29\xe2\x7c\x27\xfe\x40\x54\xe5\x5a\x4c\x85\x2c\xb2\x80\x65\x2d\xdb\x6b\x7a\xbd\x4d\xc2\x0c\x36\x55\xc6\xe5\x54\xc8\x0c\x4b\x58\xd5\x32\xbe\xa0\x51\xbc\x5d\xc3\xba\xca\xb7\x9a\x0a\x01\x66\x05\x37\xb5\x7c\x5f\x0a\xd2\x79\x5d\xe5\xba\x99\x0a\x91\xe3\x06\xee\x09\x73\x57\x7c\x9d\x7c\x6d\x06\x70\x55\xe5\xb9\x9f\xfa\xa3\xe0\x1e\x6e\x09\x73\xc3\x24\x79\x1b\x66\x71\xc8\x78\x0e\x77\x84\xb9\x9b\xbb\x1f\xd2\xd7\x74\x0d\xcf\x4a\xca\xca\x60\x86\x2a\x28\x21\x40\x06\x24\x3a\x68\x0d\xbf\x16\xa3\x47\x5a\x8b\x53\x83\xaa\x45\x7d\xa9\xe8\xac\xdd\x55\x04\xc8\xea\x16\x02\xa4\x3b\x85\xe6\x18\x3e\x90\xed\xb9\x3f\x80\x37\xe4\x6e\xbf\x3f\x56\xb4\x58\xc2\xec\xf9\xd5\xe7\x1f\x00\x65\x74\x8d\x70\x01\x4f\x6b\xa6\x39\x82\x4b\x81\xd4\x22\xdf\x6a\x69\x56\x83\x0c\x12\xa8\x3a\x18\x50\x30\x23\x0e\xde\x38\x1c\x43\x12\x33\xaa\xc5\x5a\x56\x40\xa2\x37\x48\xca\x39\xcd\xde\x28\x05\x41\x50\xf5\xe3\xbd\x93\x9d\x73\x0c\x48\xf6\x23\xd8\x15\x90\xc2\x2d\x2e\xe0\x1d\xd9\xad\xfc\xe0\xa9\x13\xc1\xc5\x08\x7c\xd7\x1f\x8d\xa1\xeb\xbb\x43\x0c\xab\x9e\x8c\x1d\x79\xe0\xbb\x3d\xe8\xca\xa8\x7e\xf0\xd4\xd9\xc0\x60\xa2\x33\x7a\x18\x56\x03\x19\xd5\x1f\x88\x5c\xfd\x21\xb8\x3d\x91\x6f\x28\x23\x7b\x22\xb2\xdf\x1f\xc8\x7c\xa3\xe0\xa9\xb3\x86\x9e\xa8\x6d\x04\xae\x3f\x14\xd4\xe1\x8a\xc7\x3c\xa1\xbe\xcc\xec\x8b\xd6\xc7\xc3\x7a\x52\x4f\x16\xf2\x45\x3d\xc3\x31\xb8\x3e\x86\xab\x34\xba\xb7\x0a\xe8\xfc\x22\xb6\xa7\x62\x45\xde\x41\x5f\x47\x6f\x39\x4f\x59\x55\x87\xa8\x7e\x00\xcf\x31\x2c\xc2\x8d\x64\xb0\x65\x89\x9e\xe8\xd2\x08\xdc\x01\x06\xc1\x3d\x0b\xa0\x9a\x84\x9e\x48\xf0\xe1\x39\x3e\x49\x45\x6d\x6c\x09\xae\x40\xe3\x47\xf0\x06\x14\x3b\xfc\x02\x8e\xe6\x52\xe6\xdc\xc2\x01\xc2\x06\x11\x1c\x21\x6c\xb0\x81\x43\x84\x0d\xd6\x50\x47\xd8\xe0\xba\x80\x77\x18\x9e\xc1\x6e\x91\xa4\x8c\x06\x67\x7e\x61\x91\xc5\x8f\x8e\xc1\xad\x59\x85\x08\x87\xfb\xea\x5f\x88\x37\x55\x0b\x32\xb0\x75\x73\x02\xd9\x5b\xd5\x79\xe3\x71\x29\xff\xb8\x94\xff\xe9\x52\xbd\xe3\x52\xbd\x4f\x97\xea\x1f\x97\xea\xab\x52\x5a\xb4\x14\xff\xaa\x0a\xdc\x9e\xd4\x98\xc2\x43\x83\x1e\x1c\x57\x39\xf8\x74\x47\x86\xc7\xa5\x86\x9f\x2e\x35\x3a\x2e\x35\xfa\x74\xa9\xf1\x71\xa9\xf1\x43\x83\xf6\x07\x9f\x1e\xf5\xe4\xb8\xce\xc9\xa7\x7b\x72\x71\x5c\xea\xe2\x11\x08\xd2\x80\x57\xfe\x63\x10\xab\x09\xb3\xfc\x07\x47\xae\xe6\xdb\xe8\x3d\x01\xe1\x42\x69\xa2\xbe\x22\x33\xc4\x52\x46\x11\x7c\x74\x3c\xe8\x81\x0f\x5d\x1f\x3c\xf0\xc1\x97\x55\xf8\xd0\x17\xc4\x49\xa4\xf5\x45\x5a\x0f\x44\xa6\x9e\x4e\x1b\x56\x69\x7d\x95\xd6\x87\x81\x4e\x9b\x98\xb4\x1e\x0c\x54\x9d\x03\x91\x5f\xd5\xed\x55\x05\x87\x2a\x71\x28\x0a\xa8\xc4\xc1\x51\xe2\x48\x96\x50\xa9\x65\xbd\xa2\x3a\xd9\xe6\x58\xa4\xfa\xb2\x63\x82\xe4\xa9\xd4\xa1\x48\xed\x83\x07\x13\x93\xda\x17\x35\xf7\x4c\xea\x48\xa5\x5e\x48\xea\xa6\x52\x47\x26\x75\x64\x52\x45\xc9\x01\xa8\xbe\xfb\x13\xe8\x9b\xe4\x31\x74\xc5\x30\x7d\x1f\xfc\xa1\x4e\xee\x79\x26\x79\x0c\x13\x9d\xdc\x03\x7f\x2c\x61\x35\x84\x5e\x0f\x06\x87\xc9\x7d\xf0\x2f\x4c\xf2\xa0\x4a\xbe\xd0\xc9\x03\xe8\xf9\x26\x79\x64\x92\x27\x22\x59\x80\xd1\x97\x75\xf6\x24\x70\x7a\x13\x18\x9a\x64\xdf\xd3\xe9\x23\x51\xa9\x4a\xef\x7b\x56\xba\xaf\xd3\xc7\xa2\x56\x9d\xde\x33\xe9\x17\x55\xfa\x44\x54\xab\xc0\xdb\x1f\xc0\xa8\x4c\xef\x41\x77\x24\xd2\x2f\xa0\x77\x61\xd2\x47\x26\xdd\x97\xc3\x92\x19\x04\x40\x24\xf6\xc0\x04\xfa\x13\x18\x1f\x67\xf0\xa1\xdf\xd7\x19\x06\x9e\x9d\x61\xa0\x33\xf4\xa0\x3f\x34\x19\x7a\x65\x06\x89\x21\xdd\xb1\xc8\xd0\x17\x4d\xab\x69\x1c\x0c\x60\x52\x65\x18\xea\x0c\x03\xd1\xb4\xce\x30\x82\x09\x9e\xc3\xd7\x64\x77\x95\x66\x11\xcd\x5e\x87\x51\xbc\xcd\x83\x81\xb2\xcb\xfd\x92\x30\xe7\x62\xd0\xbf\xc0\xf0\x1b\x61\x8e\xef\x79\x3d\x0c\x3f\x11\x87\x39\xc3\xd1\xc5\x18\xc3\x63\x4e\x39\x31\x7c\x46\xd4\x89\xd9\xe9\x83\x55\xd8\x6e\x1a\xce\x9c\x1e\x3a\x1d\xfc\x69\x46\xe5\xba\xc6\x08\x17\x85\xd6\x1e\xff\x48\x9a\x6d\x6d\xa6\x66\xf3\x15\x8c\x93\xb5\xdd\x19\xe3\xe3\xb7\xf0\x0d\xfc\x4e\x76\xeb\x00\xad\xc3\xec\x3a\x66\x08\x36\x01\xd2\xa7\x13\xa8\x80\xbf\x93\x1d\x0f\xd0\x0f\xe9\x06\x41\x16\xa0\xd7\x8a\x4b\xbc\x0a\xd0\x97\x29\xe7\xe9\x1a\x41\x12\xa0\xef\xe8\x92\x23\xb8\x0b\x66\x3a\xa4\x73\xcd\xe1\x3e\x98\xa9\x92\x26\xf7\xbc\x80\x7f\x90\x9d\x6a\xe7\xe7\x00\xad\xef\x10\xa8\x8f\x5f\x02\xb4\xbe\x47\xe6\x50\xe4\xe7\x00\x6d\xee\xca\xaf\x5f\x02\xb4\xb9\x47\x05\xfc\x8d\x38\x75\x49\x5b\x1a\xbf\x19\x09\x59\x99\x6b\xff\x63\x46\xe7\xda\xd8\x6d\x46\xe7\x97\x94\x88\x88\xc2\xe8\x8a\xb4\x95\x94\xb4\xd8\x72\x3c\xf8\x52\x40\x85\x8b\xf5\x9d\x49\x4b\x35\x48\x89\x34\x2d\x0a\xc9\xef\xb3\x6c\x0e\x31\xf9\xfb\x2c\x9d\xef\xf7\x08\x19\xa1\xf3\x49\x96\x85\xf7\x6e\x9c\xcb\x5f\x27\xc6\xd3\xf8\xa4\x51\x55\x28\xed\xd9\x82\x59\xd8\x89\xe7\x52\xbc\x2c\xa0\x21\x57\xc9\xd0\x7f\x33\xa3\x42\xba\x16\x3f\xe4\xad\x43\x31\x06\x11\x2c\x30\xfc\x42\x66\x48\x62\x8c\x80\xeb\x5a\x30\xe3\xeb\x2b\xf1\x27\x11\x7f\xee\xc4\x1f\xc1\xd1\x0b\x10\x6f\x44\x8e\x8d\xc8\xb1\x11\x39\x36\x89\xe4\xbb\xc5\x1f\x91\xc3\xcc\xad\x0e\xa8\x59\x51\x61\x3d\xa7\xfa\xcb\xcc\xab\xfe\xd4\x33\xaa\xa7\xac\x0c\xfd\x22\xea\xd5\x38\x52\x86\x54\xa5\xf6\xc1\x56\xf5\x59\x56\x6b\x1d\x84\x55\x5f\x3f\x57\xc1\x5f\x6c\x43\x83\x9f\x6d\x4d\x9f\x3e\xbc\xdb\xef\x27\xe6\xa8\xfe\xf0\x28\x98\x4f\x9b\xcc\xad\x3f\xa7\x45\x50\x9f\x39\x8e\x1b\x33\x0a\x88\x07\xcd\xf2\xa6\x7d\x72\x6b\xd9\xc7\x7d\x5b\xf5\xef\x67\x87\xba\xf2\x90\xb1\x54\x51\x68\xeb\x76\xb1\xf8\x1d\x8a\x0f\x30\x85\x49\x7c\x95\x26\x82\xbf\xd8\x86\x80\x87\xd7\x1b\xb2\xe6\x55\x6d\xd7\x63\xcc\x77\xdc\x8c\x46\xdb\x05\xad\xd9\xdc\x65\x55\xf2\x2c\x9b\x1f\xdf\x6f\x30\x8a\x99\x6a\xac\xfb\xbd\xba\xd3\xc0\x4d\x57\xb8\xbe\xa2\x40\x95\xbd\x57\x78\x95\x3b\xbc\xd2\xc3\xf0\x2f\x88\x37\x65\xc1\xb1\x7d\xc1\xb4\xcb\x02\xd4\xad\x4c\xf3\x70\xe1\x70\x60\x18\x68\x81\x61\x57\xe0\xa2\x70\xfe\xe6\x30\x0c\x1c\x43\x2a\xd5\xc5\x97\x87\x23\xd3\xe7\xe9\xf1\xd2\x39\x9c\x3c\x63\x67\xa1\x01\x6e\x9f\x19\xef\xf7\x9f\x95\x3d\x6b\x82\x47\x0a\xa1\x0d\x11\x77\xbb\x71\x32\x39\x43\xb3\x70\x8e\xe7\x84\x39\x5c\x04\xca\x4e\x0a\x08\xe9\x7b\x1d\x84\x08\x92\xf1\x9b\x24\x19\xd8\xa8\xc8\x1f\xee\x81\x8d\x00\x1c\x7f\x6a\x7a\x52\xd9\x19\xdd\x89\xcc\xea\x84\x41\x09\x87\xe3\x42\x0e\x21\xc3\x05\x2e\xab\xfb\x51\xe6\x29\x31\x92\x52\x6d\x5b\x40\xff\xa8\x6d\xc1\xe4\x52\xd2\xd5\xf5\x36\xae\x6c\x8a\x0d\x8a\xef\xf4\x1a\x0c\x44\xdf\x18\xb1\x16\x85\xb1\x65\x3a\x6e\x56\xdf\xc9\x51\x93\x27\x8d\x2a\xbd\xcb\xec\x2f\xf4\x32\xeb\x74\x30\x13\x48\x59\xb5\x9e\x95\x58\xe0\xd9\x76\xbf\xdc\xf1\x71\xe0\xd7\x63\x04\xbd\xc6\x41\x83\x3d\x71\x13\x52\xd3\xfa\x48\x18\x91\xf7\x69\x4e\x10\x11\x36\xb5\x0c\x4a\x25\x09\xc5\x01\xab\x4c\x82\x5b\xa8\x94\x6a\x5b\xcd\xf7\x57\x98\x31\x45\xda\x5d\xd3\x1a\xe1\x30\x9d\x28\x04\xf0\x04\x80\xc9\x99\x07\xac\xf8\xd6\xdd\x64\xe9\xe6\x87\xfb\x0d\xcd\xc5\x36\xf1\xad\xbb\x8c\x13\x4e\x33\x51\x5f\x4e\x7e\x51\xb0\xa7\x84\x39\xfd\xde\x85\x8f\x81\x89\x60\x6f\x5c\x9d\x1a\x67\xf4\x71\xf3\xf0\x68\xd3\x12\x10\xc4\xd6\xc2\xe8\x83\xa3\x95\x22\xe0\x10\x12\x63\x57\x02\x71\x95\x18\x8a\xc4\x50\x9e\x96\x6c\x42\xa9\x4f\x81\x45\xed\xbc\xa4\x08\x72\x88\x2a\x4a\x0e\x4b\x75\xcc\x90\x5e\x67\xe1\x66\x75\x5f\x57\xa9\xed\x0a\xa9\x51\xb3\x8f\x07\xac\x3e\x89\x8d\x48\xb6\x2f\x37\x0e\xd9\x96\xe0\xad\x54\xbd\xea\x40\x40\xd7\x8a\xe6\x18\xd6\xe4\xa5\xb3\xc0\x70\x43\x12\x41\x72\xae\x09\xa5\x4e\x84\xe1\x9e\x18\xce\x68\x67\xd5\x1c\xdc\x80\xb2\x75\x89\x53\x16\xa0\x84\x67\x08\x54\x4b\xc1\xd6\xb9\x81\x6b\x88\x95\xba\x23\x8b\x23\x9a\x0b\x60\xe9\xd6\x83\x35\x88\x59\x94\x51\xf9\x2a\x8c\xd2\xdb\x3c\xf8\x0a\xaa\x6e\x04\xdf\x39\x6b\xd8\x60\x30\x0b\xe8\x5a\xe4\xda\xd0\xe0\x6b\xe0\x59\xc8\xf2\x58\x34\x97\x07\x9c\xba\xef\xbe\x87\x8f\xcf\xc5\x7e\x10\x30\xea\xbe\x2b\x60\x85\xe1\xea\x78\x4d\xdd\x5a\x6b\xea\xea\x0b\x7f\x7a\xd5\xf5\x03\x0f\xc3\x1d\xf1\x2f\xef\xfe\x72\x75\x79\xd7\xe9\xe0\xdb\xd9\x5d\xd7\xb7\x57\xd7\x5d\xb9\xba\x6e\x9b\x68\x11\xb7\xf4\x69\x86\x5f\xc4\x05\x86\x7b\x5c\x38\xb8\x00\x81\x7d\x9f\xb0\x34\xbc\xbb\x90\xa6\x86\x21\xbc\xfb\x5e\x5d\xc4\x68\x30\x39\xdc\xd1\x30\xa7\xcf\xd9\xab\x2d\x0f\xd0\x62\x7b\x15\x2f\xba\x57\xf4\x63\x4c\x33\xc7\x73\x07\xe6\xf8\x1c\x5a\x3e\x46\x20\x32\x36\x65\xf3\x8e\xb3\x3d\x67\x27\x2a\xf3\x55\x9e\x7c\x15\x66\x9b\x93\xed\x8d\x64\xa6\x02\x42\xb2\xcb\x57\x69\xc6\x69\xce\x03\x7f\xe8\x81\xfa\xc8\x82\x9e\xa7\xc3\x41\x4f\xc4\xf2\x90\x45\x61\x16\xc9\xd3\x96\x45\xba\xde\x24\xf4\x2e\xe8\x8f\x87\x40\x19\xa7\x82\xec\xbc\x59\x64\x94\xb2\xa0\xd7\x1b\x42\x42\xc3\x9b\x2a\xc6\xbf\x18\x5a\xc7\xad\x71\x93\xd2\xd3\xd2\xc1\x53\x0c\x68\x9d\x97\x12\x79\x22\x21\x27\x30\x27\x85\x68\x9b\x29\x93\x9e\x10\x16\x19\x0d\x39\x3d\xb4\x2b\xfb\xc3\x8b\x7f\x86\xc2\x44\x08\x24\x7f\xf8\xfc\x6a\x57\x00\x23\xdc\x35\x3d\xb4\x55\xf2\x6c\x1a\xba\x25\xf0\x18\xe4\x84\xbb\x6a\x44\x75\xcd\x7c\xea\x56\x18\x92\xc3\x42\x54\x46\x93\xf0\xbe\xae\x98\xf7\x82\x45\xa5\x59\xcc\x14\x1b\x3f\x43\xa6\x55\x04\x48\xd5\x8c\x00\xc9\xc2\x82\x06\x1c\x70\x11\x14\x4f\x69\x20\x84\x85\x53\x1c\xbc\xa5\x89\x06\x64\xe9\x5d\x8e\x36\x97\x64\x9a\x04\xb1\x93\xe0\x5a\xae\xed\xc3\x65\xa2\x69\x14\xc4\x4e\x84\xb1\x75\xd5\x04\xe1\x02\xae\x29\x7f\xb2\xe5\xa9\x52\x4e\x7f\x65\xa6\xf9\x60\x7b\x3b\x2b\xb7\x33\xcf\x5c\x47\x39\xef\x8f\x2e\x1b\x8e\x71\xbc\xcf\x9d\x41\xc7\x1f\x7e\x5e\x9a\xac\x73\xa9\x68\xee\xf0\xf3\x21\xc6\x45\x51\xc0\x70\x38\x7a\x9c\xf9\xf0\x0d\xb3\xd6\xb2\x32\x15\x4e\xcb\x55\x2d\xcd\x87\x7b\x17\x03\x0c\x71\x25\x1c\x33\x67\x32\x1a\x5f\x60\x0c\x09\x61\x2e\x73\x62\x0c\x39\xf9\x77\x6e\x55\x3e\x74\x91\x32\xf8\xbf\x7d\x0d\x52\x6f\xbd\x5b\x62\x73\x87\x68\xcb\x14\x27\x10\x55\xed\xdd\xc6\x2c\x4a\x6f\xa7\x56\x52\x90\x3b\x2a\x12\xe3\x76\xfb\x53\xc5\xa3\x74\x21\xd7\xd6\x41\x05\x26\x5a\x54\x71\x41\x08\x31\xdf\x2e\x4b\x23\x2a\x18\x89\x4b\x63\xa2\xd7\xf7\x07\x03\x0c\x11\x61\x8e\x3f\xee\xf9\x18\x96\x62\xaa\xfa\xbd\x11\x86\x8d\x48\xed\x8f\x46\x18\x56\x64\x57\xd8\xe0\xa8\x68\xd4\x5a\x63\x9c\x92\x08\x6a\x97\x9c\x8f\x39\xab\x23\x46\xbd\xba\xc2\x4c\xe5\x22\x5b\x63\xc5\x59\x5a\x4d\x9d\x11\xb2\x3a\xe4\x32\x77\x45\x79\x4f\x99\xa9\x7b\xca\x7c\xc6\xe6\x64\xed\x08\x29\xa1\x92\x3b\x2a\x96\xf7\xa6\x34\xbd\x35\x04\x82\xb6\xdb\x0e\x25\x68\xcb\x58\xb8\xa6\x11\x2a\x31\xd7\xfd\x2d\xcf\x21\x25\x6b\xdb\x2e\xdb\xdd\x24\xdb\xeb\x98\xe5\x6e\xca\x9e\x4a\x62\xfa\x7a\x9b\x50\xc9\x66\x33\xbc\xdf\x3b\x74\xe6\xcd\x41\x8c\x5f\x1d\x78\x5e\x1f\x88\x50\x95\x09\x3f\x42\x86\xb3\x2d\x2f\xbc\xa1\xb3\x78\xbd\x49\x33\x1e\x32\x79\xbf\x9a\x4a\xfe\x56\x70\xbd\xed\xb6\xc3\x3a\x84\x63\x60\x1d\x1d\xab\x59\xfc\x02\xee\x8f\x65\xb4\x8a\xf9\x6a\xb7\x1d\x4e\xce\x7c\x0c\x67\x27\x21\x7d\x69\x7a\xd3\x30\x1f\x82\x65\x2e\x2f\x1d\xfc\x8b\x9d\x55\x17\xa6\x58\x87\x5c\x3b\x22\x49\x92\x37\x75\xc7\x81\x89\x28\x90\xe9\xe5\xe4\xec\xf7\x47\xd5\x55\xb7\xd5\xe6\xfb\xbd\xac\xb1\x65\x65\xc1\xc0\xac\xbd\xf1\xaa\xbe\x8e\xcf\x7c\x79\xf3\x47\xb9\x3e\x98\xee\x92\x98\x51\xc9\xb0\x05\x08\x49\x7e\x8a\x06\x08\x15\x81\x1d\xff\x2b\x2b\x53\x5a\xc8\x92\xd7\x6f\x4f\xce\x1a\x57\x83\x15\xdd\x6a\x95\xfa\x1e\xd6\xa1\x55\xd9\xbb\x23\x34\x93\xa0\x21\xbb\x92\x32\x2a\xa0\x9f\x95\x92\x73\xa6\x2f\xee\x31\x29\xe0\x33\xc1\x36\x5b\xd7\x1c\xbc\x20\x85\x98\x70\x77\x19\x26\xc9\x55\xb8\xf8\x90\x5f\x9e\x29\x19\x47\x8d\xb3\xdd\x76\x42\xd2\xf5\xcf\x3d\x55\x7b\x42\xae\xa4\x81\x01\x49\xdc\x72\x9c\xb0\x25\x89\xe4\xa5\xe5\xe2\xa3\xed\x76\xd8\xe9\x40\x8c\x8f\x26\x3e\xae\x66\x7d\x41\xbc\xcb\xc5\x5f\x8c\xc5\xfd\xe5\xa2\xd3\x51\x1c\x43\x44\xe2\xd9\x62\x5e\x2e\xbc\xa5\x58\x78\x91\x4a\xda\x90\x68\xb6\x9c\x5f\x8a\x35\x70\x46\x36\xed\xb6\x93\x89\xff\x77\x48\x8e\x21\xeb\x90\x5b\x67\xd9\x41\x01\xea\x6c\x3b\xf7\xce\x06\x77\xd0\x25\x82\x50\xec\x2d\x12\x35\x4c\x75\x2b\x51\x5d\xac\xaa\x5b\x93\x78\xb6\x32\xd5\xad\x8f\xab\x5b\x95\xd5\xad\xab\xea\x4c\x45\x37\xa2\x22\x6d\x1a\x70\x4d\xf8\xec\xc6\x54\x74\x2d\xa8\xbd\x01\xa4\x40\xb8\x9b\xe3\x9a\x6f\xca\x9a\xaf\xab\x9a\x35\x17\x91\xed\xf7\xf2\x28\x3d\xbd\x7d\xb6\xde\xf0\x7b\xdc\x6e\xd3\xa9\x2a\x4f\x10\xea\xe4\x9d\xac\x93\x63\xb8\x75\x10\xea\xd0\xce\xb6\x83\x76\xa8\x93\x41\xb7\x1b\xe2\xce\xad\x83\x0a\x59\x53\x90\x49\x02\xf1\x8c\x9c\x3b\xb3\xd9\xaf\x73\xf7\x4f\x9f\x7f\xf6\xc5\x5f\x3a\xff\x1f\xd9\xff\x33\x70\x30\xa0\x3f\xff\xbf\xbf\xe6\x73\x7c\x7e\x0d\x1f\x88\x45\xcb\x4b\x3a\xfa\xf4\xcd\x9b\x76\xfb\xe9\x9b\x37\x2e\x95\x16\xda\xf0\xa6\xe9\x66\xff\x87\xe9\x07\x87\xe2\x80\xba\x19\xdd\x24\xe1\x82\x3a\xcf\x00\xfd\xfa\xeb\x67\xfe\xc1\x01\x39\xae\x3c\x1a\x50\x83\xb3\x7c\x15\xe7\xd2\xa2\x8b\xa0\x9c\xdf\x27\x14\x81\x8c\x89\xf3\xef\xb3\x74\x41\xf3\x9c\x46\xe4\xcc\x2f\xc9\x64\xbe\xa2\x94\x8b\x0d\xde\x7d\x4d\x59\x44\x33\x9a\x5d\xca\xec\x1f\xe8\x3d\xa1\xaa\x64\x2a\x4f\x82\x73\xc2\xd4\xa7\xac\x94\x70\xc8\xa6\xf2\x33\xd3\xc5\x48\x56\x06\x83\x54\x50\xaf\x5a\xa2\x10\x61\xd2\x52\xbf\x41\x2d\xb7\x13\x42\x94\x22\x0d\x9a\xa0\x8a\x14\x96\xda\xa9\xb2\xf5\x19\x9d\xeb\x01\x9c\x9d\x49\xf7\x10\xcb\x34\x53\x2b\xe3\x2c\x6b\xb7\x6b\xf9\x0e\x2b\xd0\xeb\x94\x5f\x32\x4d\x6c\x98\xe8\x81\x80\xcb\x7e\xef\xa4\xc4\x1e\xb0\xd8\x42\xec\x2d\x63\x15\xb2\x6b\xfa\x36\x4c\xb6\xd4\xe1\xa0\x60\x83\x8d\xab\x0e\xb5\x6d\xa6\xfb\xbd\xac\x53\xac\x76\x2a\xf1\xb7\xec\x8a\xe8\x5c\xd8\x6e\x9f\xc5\xed\xf6\x59\x76\xd4\xa1\x84\x84\xed\x76\x2c\xf2\x24\xd3\x88\x26\x94\xd3\xfa\x68\x83\xfa\x98\x52\xb0\xa0\x1b\x5e\x25\x54\x0f\xda\x80\xdb\xd4\x9f\xd4\xa7\xc8\xcd\xe8\x3a\xbd\xa9\xb4\x17\x07\x95\x00\xc5\x41\x3d\x7f\x4e\xf9\xe9\xcc\x90\x62\x28\x07\x90\xd7\x21\x27\xb1\xaa\xbc\x99\xd8\x6e\xe7\x6e\xc8\x79\xb8\x58\xd1\x48\x16\x29\x80\x16\x0e\x86\x77\x35\xcc\xb7\x7c\x73\xd8\xb6\xa9\x97\x29\xa1\xca\x19\x89\x28\xa9\xcd\x56\xf7\xfb\xb2\xe5\x90\x88\x7e\x26\x54\xf0\x18\x10\x8b\x8f\x45\xba\xa1\x11\x24\x22\x28\x91\x3b\x27\x99\x7b\x4d\x99\x60\x2e\xe9\xf3\xc8\xf4\x2a\x9c\xa6\x65\x39\x69\x25\x16\x06\x67\xfe\x19\x21\x71\xbb\xed\xa4\x6e\x1c\x91\xdc\x71\x3c\x58\x6a\x53\x06\xf9\x9b\x0a\x16\x17\xc3\x41\x39\xe4\xa2\xce\x1b\x59\x04\x63\x48\x0b\xc7\x83\x48\x49\x29\xda\x8f\x8b\x10\x92\x4a\x74\x2f\xb7\x1b\x37\xdc\x6c\x92\xfb\x1f\xd2\x06\x7b\xc2\xda\x1c\x08\x9c\x28\x0d\xa4\xd4\xd2\x4e\xbf\x7d\xf3\xea\xa5\x83\x4b\x0a\x9e\x09\x4c\x63\x98\xd7\xa6\x8b\x42\x06\x6c\x96\xcd\xcb\x35\xa7\xe0\xce\x74\x71\x72\x24\x46\x5a\xbc\x18\xaf\xa3\x6e\xad\x75\x85\x83\x7c\x7e\x79\xc4\x1f\x32\x65\x0f\xcc\x0e\x14\xf0\x0c\x0b\x0e\x4d\xa4\x88\x70\x45\x02\x54\x5f\xde\x48\x69\xe9\x14\x10\x6a\xe8\x24\xa4\xcd\x76\x9b\x97\x91\x49\xcc\x3e\x4c\x8d\x4c\xb8\x2b\x80\xc2\xae\xa2\xea\xc1\x99\x57\xe0\xf2\xa2\x5f\xeb\x4e\xa1\xaf\x3d\x6f\x16\x31\x03\x86\xe5\x2d\x9b\x85\x96\x2e\x77\x1f\xe8\x7d\x80\x4c\x66\x04\xb9\xad\xdb\xd3\x87\x51\x67\x84\x1c\x55\xa9\x69\x6f\x0d\x3b\x0c\xab\x5b\x9b\x54\x60\xe4\x60\x39\x09\x72\x24\x79\x3e\x31\x89\x6f\x74\x05\x0e\x03\x2a\x50\xdd\x6c\x02\x92\x5d\x65\x9a\xf0\x14\x52\x84\x6c\xd0\x39\x1e\xf5\xa1\x28\xe6\x18\x78\xe1\x3c\xc5\xf0\x3d\xd9\xd9\xbc\x6f\x70\x48\x77\xcd\x71\xa4\xbc\x7f\x3d\xf3\xe6\x62\xab\xdc\x84\x19\x65\xbc\xdd\x46\x1f\xe8\xfd\x32\x0b\xd7\x34\x47\x8a\x6c\xca\x78\x75\xbd\x5d\x90\xbf\x40\xd0\xf8\x77\xba\xa6\xa2\x80\xd7\x64\xa7\x78\xa1\xc0\x87\xc5\x2a\x4e\xa2\x8c\x32\x31\x2d\xf0\x8a\x9c\xff\xd5\x99\xfd\x7a\xdb\x9d\x77\xf0\x39\xfc\xf0\xe8\xdd\x6c\x91\xb2\x48\x2a\xcf\xc2\xa4\x71\x4f\x83\x6a\xe3\x2a\xdd\x28\x28\x67\x15\xaf\xaa\xc5\x12\x96\xb8\x1d\x72\x92\x4e\xd3\x99\x3f\x0f\xd0\x96\x7d\x60\xe9\x2d\xd3\xb5\xfe\xbe\xa5\xd9\xbd\x90\x64\xc3\xb5\x90\x83\xfe\x8a\x3a\x3a\x7f\xe3\x76\x98\x6d\x13\x9a\xcb\xfd\x8d\x52\xc7\x42\x47\x06\x3b\x05\x21\x49\x53\x0b\x8c\x81\xe3\xaa\x80\x1b\x46\x91\x13\x82\x3c\x82\xb8\xb4\xa2\xf5\x5e\xe4\xe0\xa2\x32\x7a\x3f\x20\x1d\xd2\x01\x93\x98\xbd\x46\x87\x43\x55\x55\xca\x95\x54\x01\xa5\x93\x85\x4f\xe4\xaf\x6e\x6f\x8a\x32\x61\x14\x1d\xb4\x61\xdd\x79\x24\x07\x03\x51\x69\xa5\x9c\x35\x75\x1e\xd8\x46\xf5\x8c\x49\x5c\xce\x30\x64\xca\x63\x94\x68\xb2\x99\x1a\xd4\x05\xbd\xd7\xc6\x2d\x87\x90\x1b\x2a\xf6\xb8\xf2\xcf\x45\x35\x03\x2e\xed\x97\x55\x90\xbc\xd6\x01\x0c\x26\x8f\xc1\x47\x99\xcb\x7c\x90\xd7\x65\x10\x83\x16\x44\xca\x08\x1b\x5e\x12\x41\x3a\xa8\xb5\x2b\xd0\xa5\x45\x1a\x15\x3c\xcc\x28\xaa\x63\x87\x16\x9b\xd6\x8b\xa1\x0e\xef\xb0\x0e\xef\xa0\x02\x09\x71\x46\x6d\x86\x2f\xc9\xb9\xb2\x02\xd8\xff\x35\xdf\x6e\xa4\x57\xa4\x5f\xf3\xce\x39\xbc\x7f\xd4\x92\x6d\xbd\x74\x39\xcd\xc5\x84\x4f\x05\x2a\xea\x0b\x1e\x1a\xb6\x05\xbc\x38\xb5\x16\x9f\x93\xf3\xbf\x96\xeb\xfa\xd7\xbc\x53\xad\xcb\x27\x8f\x5e\x97\x15\x5d\x00\xb3\xb0\xd0\x5f\x0f\x23\x1b\xd8\xcf\x6a\x7d\x3e\xc7\x97\x69\xbb\x2d\xd6\xa2\x82\x94\x58\x79\x44\x2e\xcd\xea\x13\xb1\x54\xfc\xa2\x6a\x95\x97\x5d\xe8\xa0\xae\x5e\xa3\x22\xc7\xc1\x2a\x35\x0c\x9a\xe1\x0b\xe2\x92\xe9\x4d\x08\xb3\xf9\x02\x43\x21\xf2\x92\x42\xc4\xa2\xab\xf2\xb0\xa3\xac\x3c\x78\xe3\x68\x46\x24\xc6\xf8\xdf\x26\x00\x39\xf0\x59\x3e\x87\x87\x0a\x35\x13\x87\x06\x3e\xfa\x31\xab\xe7\xc5\x1f\x59\x3d\x2f\x1e\xb9\x7a\x5e\x3c\x72\xf5\x84\xbc\x83\x5a\x7a\xbe\xe2\xe8\x5f\x59\x46\x52\x06\x47\x7a\xf5\x60\x38\x51\x1b\xea\x30\xb1\xb2\xf4\xb2\xfa\xee\x00\xc1\xcf\xe1\x23\x39\xff\xf5\xb3\x12\xcf\xaf\xe1\xab\xc6\x63\xf7\xe3\x83\xc5\x69\x25\x8c\x7d\x04\xfb\x34\xa5\x5a\x84\x52\x89\xc5\xa7\x7c\xc6\xe6\xca\xcb\x0d\x2d\xe0\xeb\x13\x24\x54\xb0\x44\x90\x92\xaf\x9c\x4c\x90\xce\x54\xdd\xdd\x57\x8c\x52\x8a\x0b\xf8\xf2\x71\x3b\xf5\x51\x2f\xdb\xed\xef\x6a\x94\xe0\x49\x8d\x12\x40\x49\x7f\xdf\x08\xc6\xe7\x74\xad\x42\x6e\x14\xa2\x93\xf6\x08\xc2\xa6\x0e\x0a\x59\xac\xdc\x51\x76\xe5\x3a\x8c\xa5\xbe\xe6\x6b\x87\xc2\x61\x0a\x30\xb7\x84\x38\xb6\x52\x1b\x8b\x1c\xe4\xa6\x12\x66\x35\x61\x2b\x68\x86\x1f\x3b\x10\x36\xa4\xf0\x57\xe9\xc6\xf2\xdb\x58\xb9\xa9\xda\xc9\x1b\x0a\x55\x7b\x41\xfd\x5b\x75\x39\xd0\xe5\xbe\x12\x7c\xb3\xd5\x9f\x4b\x73\xf3\xb0\x3a\xcf\x2d\xe0\xb7\x53\x62\x8b\x65\x9f\x21\xb9\x7b\x45\x28\xca\x43\x13\x2d\xb5\x54\x3e\x16\x4a\x39\x01\xf8\x27\x17\xf2\xff\x39\xa6\xf8\x03\xbd\x3f\xe4\x85\x15\xb3\xf8\xd3\xe3\x76\x9e\x47\x72\x88\xf4\xb6\xf5\xdb\xc1\xae\xf4\xd9\xa3\xb7\x98\x65\xca\x78\x77\x19\x2e\xa8\xbd\xc5\x1c\x46\x9e\xe4\x06\xeb\x7a\x8b\xfa\xf6\xf0\x78\x52\x7a\x82\x70\x1e\x58\xac\x54\x52\x53\xb3\xee\xb1\x4c\x37\x7a\x39\xad\x8b\xd4\x93\x11\xda\x72\x89\x34\x0d\xb1\x3f\x3b\xfe\xdc\xe8\x93\x2b\x3d\x72\x7d\x36\x6b\x15\x48\x47\x17\x92\x0c\xfe\x48\xce\x2b\x78\x9d\xc3\xdb\xc7\x4d\xed\x8f\x35\x52\xf2\xd9\xc1\xf4\x7d\xf3\xe8\xe9\xbb\x89\xe9\xad\xe0\x68\xec\xd9\x3b\x88\xfb\x3f\x3b\x79\x0f\x62\x7c\x09\xa4\xdf\x1f\x29\x1d\x95\x5d\xd7\xee\x60\xff\xda\x5d\xe7\xdd\x5a\xa4\x84\xd7\x37\x07\xf0\xfa\xfb\xe3\xf5\x76\xf1\x7a\x93\x3c\x12\xad\xa5\x6f\x96\x3f\x0e\x99\x66\x0c\x96\x95\x5a\x18\xcc\x05\x06\x2b\xdf\x45\x55\xba\xc1\x60\xd6\xe9\x60\xde\x21\xa6\x63\xd5\x7e\x2c\x73\xcd\xd8\x5c\x6a\x60\xed\x18\x85\xc7\xbc\x43\xa4\xff\x8d\xea\x9c\xc7\x66\x13\x8e\x6b\x12\xd5\xe8\x99\xfa\x07\xd9\xa1\xbf\x2e\x56\x61\x96\x53\x8e\x82\x33\x0f\xd0\x5f\xd5\x01\x83\xfe\x10\x44\x5d\x6a\xcb\x91\xe4\x72\xff\xf6\x38\x74\x97\x2a\xbb\x7f\xc8\xb9\xfb\xfb\xc1\xdc\xfd\x42\x66\xdf\xc3\x7b\xf8\x12\x7e\x82\xb7\xf0\x3b\xfc\x6d\x0e\x3f\x93\x9d\xe6\xc7\x64\x13\xdf\x92\x9d\x54\x42\x8a\xf6\xed\x78\x4a\x4f\xcd\xba\x9e\xf1\x75\xb8\x21\xbb\x42\xb3\x92\xe1\x6d\x19\x96\xe2\x18\x99\xcd\xd5\xd7\x22\xdd\x32\x4e\x33\xe2\xd5\xe7\x59\xe3\xc0\x22\x09\xf3\x9c\xe6\x82\xe3\x52\xa1\x12\x4b\x14\x39\x26\xb4\x0a\x3f\x24\x58\x86\x51\xd4\xc8\xad\xd4\xf5\xa2\x10\x92\x54\xd3\x76\x88\x49\x5a\x72\xd3\xa9\x3c\x73\xcb\x49\x5a\xaa\x92\x61\x4b\x52\x8b\xc5\x86\x85\xc8\xad\xd8\xf0\xa8\x34\xf7\xd9\xe9\x3e\x07\xf6\x50\x40\x73\xc1\x21\xc8\xda\x83\x18\x7e\xcb\xf3\x20\x01\x53\x73\x90\x43\x55\x6f\xb0\x05\x55\x6b\xb0\x00\xc9\xa4\x53\x28\x87\x1b\xd4\x21\x01\x46\x31\x12\x28\xd6\xb8\x00\x86\x61\x49\xe8\x65\xa5\xae\xcd\xc2\xdb\x76\xdb\x59\x12\x21\x56\x44\x1a\xff\x34\xf8\x3b\x1d\x5c\x4e\xd4\x6c\x39\x27\x1c\x96\x65\x31\xdd\xf1\x76\xdb\x89\x4a\xed\x8b\xd6\x0d\xda\xe9\xb3\xe5\x5c\x2b\x8d\x37\xe4\xc6\x59\x02\x87\x48\x9e\x95\x9e\xd5\xdd\x5d\x6b\xf5\xd0\x75\x9c\x73\x9a\x39\x1b\x55\x62\x55\x9d\x29\x45\x0a\x3f\xa6\x15\xaa\xe8\xd5\x18\xe8\x94\x4b\x7b\x2d\xa9\x0c\xf9\x26\x89\x17\xd4\x59\x81\x07\x1b\x0c\x1b\x21\x72\x5f\x53\x7e\x52\x2b\xb0\x0e\x37\x33\x3a\x17\xb9\x94\xda\xb8\x96\x51\xe6\xd8\xb2\xb2\x87\x14\x83\xad\xb7\x16\xf0\x91\x38\x37\x87\xe3\x0e\x58\x31\x95\xce\x01\xfc\x47\xa9\x2a\x0e\x8b\x15\x8a\x75\x12\xcb\xed\x58\xa5\x79\x4a\x0b\x71\x69\xf7\x49\x76\xc9\xc3\xee\x32\xcd\x9e\x85\x8b\x95\x43\xeb\x3a\x0a\x50\x6d\x98\x81\x1e\x03\x41\x82\x49\x0e\x95\x50\x10\x58\x94\xf3\x90\x2d\x04\x2f\xfe\x4e\xeb\x41\x54\x0e\x83\x13\x32\x9b\x1b\x47\xe6\x88\xc4\xe0\x85\xa9\x43\xea\x91\x83\x5a\x45\x4f\xb4\x7a\xbf\xc4\x62\x53\xb6\x8c\x98\x51\x29\x9d\xea\xe2\xa2\xc3\xd5\xdc\xd4\xba\x6c\x4f\x52\xd5\xf3\xa3\x7e\x1f\x67\x2b\xbb\x5f\x9b\xe7\x7a\xe7\x8f\xbb\x6d\xe7\x3d\xea\xac\xec\xe6\x26\x0a\x39\x3d\x9a\x3a\x41\x7a\x2e\x1b\xcc\x3b\x1f\x7b\x33\x0f\x4f\x9d\x63\xc3\xa8\x53\xb7\xf8\x38\x79\xec\xcd\x3d\x46\x1e\x79\x5b\x0f\x07\x0e\x7f\x74\xfb\xec\xd1\xed\x53\x79\xce\x24\xa4\x24\xb5\xfe\x24\xf0\x5e\x31\x6a\xe1\xd9\x5c\xa9\xe2\x6a\x67\xb2\x16\xeb\x69\x93\x0a\xc9\x7a\x36\x55\x24\x33\xcd\x32\x55\x55\x35\x4b\xaf\x98\x35\x51\xe6\x88\xc6\x10\x24\x75\x80\xfa\xb3\x71\x60\x7b\xb4\x5f\x58\xcb\xaf\xda\x34\xe4\xe1\x86\x12\xf8\x6d\xc4\xa1\x58\x47\xea\x86\xa5\xc7\x55\x39\xa4\x9d\x3a\x2c\xe3\xd6\x99\x9a\x9b\xb2\x1f\x4d\x2e\x0e\x31\x64\x18\x32\x43\x12\xda\xed\xa4\xdd\x4e\xa4\xa3\x59\x7d\x92\x51\x53\xf2\x84\x6e\x5d\x1c\x76\x74\x36\x51\x8f\x90\xc9\xac\xd3\x8f\xad\xa9\x62\x96\xcf\x2f\xb7\x67\x84\x24\xb3\x7c\x2e\x04\xaf\x4d\x96\x6e\x9c\x1c\xb6\xf0\x6d\x75\x74\xbd\x10\x95\x27\xe6\xb4\xdd\x14\x5c\xcc\x61\x49\x92\xd9\x42\x9d\x63\x13\x12\xb5\xdb\xd1\x19\x21\xcb\xb2\x96\x85\x54\xb0\x88\x8a\x84\x94\x79\x42\x1f\x7a\xc0\x91\x35\x48\x84\xe5\xa1\xa8\x2d\x13\x42\x7a\x20\xba\x40\x48\xbc\xcb\xb0\x01\x29\x42\x63\x27\x10\x13\x0b\x19\xc2\x79\x4d\x23\xe3\xc4\xfb\x7d\x86\x05\x19\x52\x7c\x5c\x8a\x81\x77\x48\x5c\x1d\x36\x69\x3e\x8d\xd3\xd3\x3c\xaf\x25\x1f\x59\x3a\x79\x75\x4a\x58\x32\xba\x11\xdd\x24\xe9\xbd\x15\x61\x58\x1d\xc3\x26\x55\x3c\x8e\x89\x31\xbc\x91\x25\x05\x73\xd8\x29\x36\x42\x0a\xe4\x96\x82\x0d\x1a\x79\x8f\x53\xcc\x43\x21\x90\xc2\x70\x20\x8d\x47\xdc\x55\xb2\xa3\x4e\x69\x1a\x54\x84\x76\x27\xcb\xa5\x5c\xe9\x04\x19\x28\xe3\xa7\x7f\xf5\x50\x40\x81\x8e\x9c\x38\x0f\x32\x80\xdd\xef\xeb\xbd\x3e\x38\x38\xd6\xf9\x9c\x52\xb9\x66\xa6\xc3\xab\x4f\x87\xd2\x64\xe8\x4f\x47\x0f\x53\xe0\x6c\x44\x1f\xd3\x8b\xe9\xc3\x9d\x50\x95\x1c\x77\x42\xa1\x80\x3a\xa4\x7e\xe4\x19\xc5\xef\x5b\xba\xa5\x97\xb5\x7a\xda\xed\xb3\x72\xf2\x64\x32\x99\xcd\x6b\x64\xeb\xd4\xb9\x46\xfa\xe8\x73\x8d\xf4\xa0\xeb\xd3\x1a\xf0\xa6\x4e\x36\xcd\x94\x33\xe3\x54\x6c\x14\x6a\x95\xe5\x34\xe3\xb5\xc2\xb2\x6f\xb5\x8e\x96\x3c\xca\x41\x11\x05\x16\xab\x94\xe6\x13\x31\x86\x14\x07\xa9\x6e\xc2\x5e\x4a\x29\xae\x8e\x5d\xaa\x7a\x8e\x99\x9b\x53\x33\x64\x75\xb7\x76\x5c\x74\xf8\xac\x8a\xd2\x7e\xcc\xe6\xf5\xb3\x6a\x5a\x93\x2a\x74\x51\x27\x03\x69\x6d\xc6\xe5\x59\x00\x33\xf0\x29\x2a\x7b\xb9\x7f\xfd\xe0\x4b\xb1\x1f\x47\x45\x34\xfd\x2c\x0d\x32\x2b\x0d\x6f\x70\x54\x8d\x9e\xfc\x33\xe7\x8c\x6b\xa4\xb7\xf0\x88\x5b\x27\xb8\xb8\x24\x08\xb2\xb4\xe2\x99\x1d\x8e\xe1\xcc\x39\x28\xc6\x1f\x30\xdc\xd0\x6d\x58\x4b\xc1\x8c\xc0\xa9\x35\xf6\x87\xcf\xf5\x14\x16\x9c\x5a\xa0\xa7\x57\xa4\x5a\xe8\x87\x44\xd9\x2b\x17\xfe\x09\x46\xce\x98\x6e\x53\x6b\x69\x61\x9d\x59\x2b\x49\xa9\xa5\x21\x3d\xa8\xae\xc6\x71\xd4\x65\x75\x6b\x80\x15\xf7\xa2\xb2\x94\x95\x3c\xa4\x0a\x6a\x3e\x6a\xd0\xdb\x16\x3b\xb5\x6d\xe9\x65\xa1\x57\x3d\xd9\xc5\x42\x2a\x64\x61\x12\xcc\xe6\x40\xef\xca\xb0\x11\xe7\x25\x07\x9e\xdd\x93\x5d\xf1\x10\xe5\xb6\x55\x13\x47\xc3\x6d\xe0\xe1\x4c\xb5\xb5\x82\x36\x4f\x67\xaf\xae\xc6\xcc\xb3\x6c\x6e\x68\x5b\xbc\x74\x52\x23\x79\xa6\x85\x25\x82\x0a\x00\xd6\xa8\x1a\x39\xb2\x4d\xb7\x55\x53\x36\x67\x42\x8f\x74\xd4\xa5\xe2\xc8\xea\x8e\x55\x75\x4d\x93\x74\x3a\xdb\x8c\xc9\x6e\xe3\x4b\xaa\x58\x2a\x8d\xa5\x07\x4c\x1c\x35\x6a\x3d\xe0\x18\x68\x5d\x7d\xe6\x15\xb5\x61\xc9\x02\xff\x22\xc8\xed\xa2\x35\x46\xda\xe8\x28\x1f\xc8\x2f\xe0\x5e\xf1\x98\x8a\xb7\xae\x72\x08\x58\x9d\xe0\xf5\xbc\x4b\x7e\xb2\x23\xa2\x98\xe9\x08\x3f\x0d\x40\x99\x6f\xc6\xe7\x9a\x0e\x18\xae\xf9\xc8\xd9\x4e\xd5\x6c\x4a\xbc\xcb\xf4\xa8\x59\x55\xcc\x34\x98\x36\x34\xa8\x72\xcc\xd2\x79\x59\xa5\x6a\xd0\x3a\xd3\x79\x00\xe6\x14\x9a\xdb\xb5\x4a\xdb\x8d\x67\xe4\x81\x8c\xa2\x0f\x59\xdd\x36\x41\x12\x97\x9c\x1e\xee\x53\x75\xbb\xeb\x9d\xdc\x45\x03\x64\x96\x34\x2a\xb0\x7d\x42\xa9\x97\xff\x8c\xab\xdd\x76\x7e\xd9\x55\x86\x84\x15\xa5\x6d\xb7\x1d\xbd\x83\x51\x7c\x40\x0b\x66\xf3\xd2\xc5\xb8\x55\x97\x6b\x9a\x82\x5a\xac\xa1\x2f\xf8\xc4\x2d\xae\x3a\x07\x8d\x95\x11\x7d\xbb\x2d\x56\x8a\x79\x2d\xc1\x32\xa4\x97\xb7\x4c\x6b\x8a\xd0\xd9\x1c\x6a\x2b\xac\x16\xa1\x8e\x08\x6b\x31\x92\x89\x96\x31\xf6\x01\x9d\x8c\x50\xb3\x2e\x88\x1f\x36\x64\x34\xfb\x04\x19\xb5\x60\xf2\x78\xad\xe4\x81\x95\x9c\xaa\x41\xbe\x55\x62\x88\x8e\xd2\x7f\x99\x2b\xd7\xdc\x9a\x16\x1c\x2f\x1d\x39\xcb\x1a\x83\xf6\x7b\xf6\x85\x25\xe5\x60\x6e\xe6\xac\x51\x7e\xb6\x57\xbb\x10\x5c\x67\xd9\xbc\xde\xe6\x17\xe5\x41\xb7\xc4\x27\x6e\x14\x5e\x19\x78\xa5\x1a\x29\xb7\xd7\x78\x03\x1c\x9a\xd5\x6d\x0d\x43\xb6\x86\x75\x59\x4f\x30\x6a\x36\xad\x52\xfb\x84\x18\x59\x99\x08\x4c\x77\x45\x40\xe5\x9d\xae\xd2\x58\x33\x13\x52\xd4\xc6\x5c\xba\x32\xd1\x68\x8e\xa5\x3c\x99\xd5\xe5\x49\x84\x20\x26\xde\x65\x7c\xb0\x74\x35\xd4\x62\xb3\x31\x25\xf5\x71\xcc\x62\x63\xd8\xcd\xda\xed\xa4\x6c\xfa\x8c\x10\xb6\xdf\x3b\x61\xbb\xed\x84\x52\xbe\x0c\x3b\x24\xa9\xb6\xea\xac\xb2\x24\x0c\x2b\xdb\x3d\x6a\x6c\xf7\x24\x6c\xd0\x09\x03\x39\x89\x01\x0d\x5d\x9c\x7a\x41\xbd\x67\x4d\x99\xba\xfe\xc1\xa4\x4b\xeb\x3a\x89\xee\x29\x95\x22\x5e\x46\x21\xa4\x8d\x96\xdf\xd7\x49\x7a\x15\x26\x3f\xac\xe2\x7c\x5a\x05\x83\xa6\x9c\xea\xda\x50\xbb\xad\x7e\xdd\x17\x21\x5f\x11\x42\xc4\xcf\x54\x45\x35\x96\xca\x69\xb2\x6c\xb7\xc5\xdf\x5a\x09\x11\x11\x7c\x6d\xc0\x80\x2c\x06\x08\x61\x07\x43\x4c\x09\xea\x2d\xfd\x70\xb1\x18\x2d\xfa\xe1\xc8\x1b\x5d\x79\x93\x1e\x1d\x52\xba\x1c\xd2\xe1\x60\xe0\x0f\x96\xcb\x2b\xa4\x75\x16\x21\x9d\xc5\xd2\x7b\x85\x0a\x10\x73\x63\x81\xea\x94\x4e\x07\x72\xfa\x90\x05\x8a\xb9\x41\x21\xb6\xb4\x23\xff\x06\x62\xf3\xe1\x1d\x62\xac\x83\x10\x92\x48\x55\x92\xee\x76\xdb\xc9\x4a\xd8\x4b\x59\xfd\x65\xb8\xa6\xdf\x67\x74\x19\xdf\xc9\x2b\x14\x27\x53\x95\xe9\xca\x99\x95\x41\xc8\x6e\x52\x07\x9b\x12\x83\x51\x07\x69\x18\x0b\xee\x61\x1d\xb3\x78\x79\x3f\x45\xa8\xe3\x84\xfb\x3d\x5a\x20\xdc\x49\x68\x27\xed\xf0\x20\xec\x30\x75\x46\xd5\x45\x22\xca\x49\xa7\x22\x94\x06\x08\x61\x65\x8f\x54\x14\xb0\x6d\x58\xc5\x47\xc3\xae\x58\x52\x21\x9c\x13\x2a\xc5\xe9\xa2\x80\xc5\xe1\x26\xc5\xb3\x7b\xcb\xc0\x80\xf3\x2c\xbe\xda\x72\x2a\xa9\xf4\x8b\x70\x33\x6d\x88\x93\x32\x0c\xc7\x81\x66\x89\xc4\xa7\x31\x10\xd6\x76\xec\xb8\x58\x48\x0b\x2c\xeb\x2e\x64\x51\x40\x74\xbc\x41\x8b\xc6\xb5\xe1\xc5\xf1\xa9\xb7\xb4\xf1\xcd\xc8\xbd\xc3\xe0\xcc\xc3\x60\x5f\x08\x92\x2f\x83\xb1\x6a\xf1\x58\x17\xc5\x54\x9f\x6a\x36\xe6\x90\x01\xb2\x6f\x0a\x9d\x79\x97\x8f\x1d\x6a\x2e\x86\x0a\x59\x35\xd8\x83\x8a\x8f\x46\x7a\xe6\x6b\x0a\x72\xe6\x15\xb0\x6c\x02\xf6\x63\x9b\x56\x42\x9a\x0d\xe8\x43\x43\x7b\xab\xf1\xa2\x80\x0d\x6d\xf6\xf4\x41\xeb\xa6\xc3\x1c\x0e\x22\x08\xe1\x05\xac\x28\xd9\xda\x7c\x40\x59\xba\xbc\x19\x28\xed\x0c\x4b\x1b\x62\xb4\xa2\x61\x84\x70\xa1\x4f\x9d\xd6\x47\xc5\xd5\x59\xc9\x89\xd2\x7f\x5e\x53\x1e\xce\x36\x7a\x20\x04\x2d\xf2\x4d\x97\xa5\x6c\x41\xd1\xfc\xcf\x15\x5f\x31\x95\xa8\xf5\xc4\x00\xc6\x91\xde\x79\xa9\x98\x41\xa5\x65\xc0\x18\x6e\x9a\x51\x0a\x55\x9a\x04\x69\x1e\x34\xa5\xb6\x6e\x41\x9e\xc0\xa2\x70\xb3\xa1\x2c\x2a\xb3\xb4\xdb\x52\x72\xd4\x51\x0d\x28\x5c\x4e\x6c\x8b\xba\x0b\xc5\xd7\xe4\x33\x36\x2f\xe0\x9a\x36\xaa\x27\xaa\x5c\xe5\x0e\x7f\xe0\xb2\x47\x88\xfe\x5f\x30\xf9\x8a\x2c\xdc\x7f\xea\x40\xf7\x70\x91\x91\x85\xb1\x61\xa8\x12\x48\x44\x0d\x5b\x68\x23\x0a\x59\x56\x59\xcd\x14\x90\x8d\x8e\x5b\x85\xf9\x73\x09\x1a\xaa\x55\x2d\xa5\x4a\x54\xf7\x9e\x08\x21\xb4\xdd\x4e\xa9\xd2\x5d\x19\xd3\x11\x29\x56\xd4\xcc\xd0\x65\xd4\xb4\x0a\x1a\xca\x67\xae\x74\x4b\x33\x54\xc8\x64\x88\x87\x90\x12\xee\xd2\x84\x0a\xec\x50\x9c\x86\xfe\x20\xa9\xe5\xd6\xf3\x08\x8f\xd4\x75\xf5\x67\x2a\xab\xa3\x4d\xca\x2a\x94\x91\xae\x95\x9f\x2a\x34\x91\x66\x00\x5a\x61\x6c\xd5\x2f\xa0\x60\xe1\x54\x14\xf2\xb0\xfb\x9b\xf4\x01\x8d\x30\x30\x2d\xfc\x35\xe7\x95\x23\x40\xc0\x30\x64\x0f\xe6\x93\x75\x8a\x41\x22\xc8\xcc\x55\x9e\x35\x75\xf0\x65\xf8\x60\x31\xb5\x02\x20\xfc\x17\x15\xb2\xf2\xc6\xa0\x5d\xab\xd2\x44\xbf\x4c\x23\x23\xca\xca\xe9\xc0\xbb\xb3\x26\x34\x35\x9a\xba\x38\x65\xdf\xa7\x31\xe3\x90\x35\xb0\x88\x29\x2d\x19\x16\x75\xb8\x62\x7c\x02\x98\x5a\x4e\xdd\x69\x15\x12\x7a\x4d\x0e\x2f\xcd\x14\xd9\x5c\xd4\x94\x59\x0a\xac\xec\x80\xed\xd5\x2c\x76\x3d\xc1\xee\xaa\x66\xc3\xed\xa8\xf2\xe2\x64\x4d\xe7\xa0\x6e\xcd\x98\xc7\x91\x0f\xae\x33\x19\xcb\xd8\x2a\xa1\x01\x90\xc0\xd2\x88\x36\x64\x29\x64\xad\x27\x87\x5f\x5d\x59\xbd\x64\x5f\x08\x60\x74\xbb\x8f\x85\xc0\x1f\x1f\x28\xfc\xc7\x47\xe9\x32\x7a\xc7\xdf\xc4\x57\x49\xcc\xae\x95\xce\x29\x23\xf4\xa0\x43\x72\x2c\xed\xf6\x91\xe9\x68\xf9\x18\x40\xb3\x9c\xb0\xa2\x0e\x36\x9a\x1c\x65\xd8\x2b\x3a\x92\x37\xa0\x8c\x9d\xac\x61\x37\x21\x84\x64\xe5\x95\x75\x01\x3f\x11\x56\xc2\x3c\xcf\xe2\xb5\x83\x05\x87\x78\x02\x54\x59\x4d\x4b\x65\xe0\x93\x1e\x81\x23\xad\x8f\xbe\xdc\x0c\xf4\x7b\xdb\x67\xfa\x7d\xac\x4c\x17\xc4\x26\xa0\xe1\xf3\x25\x5d\xa6\x19\x95\x06\xa0\xa2\x3a\x5c\x3e\xeb\xc6\x9a\xde\xd4\x2a\x07\x63\xa0\xc6\x2c\xb3\x18\xd1\x27\x41\x42\xc2\xc3\xaa\x6b\x5d\xc4\xea\xe6\xac\x00\xac\xde\xd0\x9e\x0a\xb8\x39\x14\x17\x8e\x4d\x26\xe0\x98\x52\x2b\x5a\x45\xc9\x97\x69\x9a\xd0\x90\x39\x55\x0e\x9b\x90\x94\x8a\x5a\x2d\x21\x1e\xee\x20\xf2\xbd\x73\xe7\xe1\xcd\xa5\x3c\xe2\x29\x9a\x8f\x77\x04\x91\xb1\x28\x97\x65\x78\x71\x8c\xb5\x97\x72\xef\x56\x5b\x9e\x1a\xaa\x9d\x11\x37\x8c\x53\x9e\x5d\x96\x96\x12\xd6\x3e\x57\x6b\xe1\x70\x2b\x31\x7d\x3d\xd4\x74\x5b\x9d\x53\xc7\xcf\x52\x26\xa9\xdb\xce\x1e\x1c\xad\xe4\x0e\xd5\x4a\xeb\xe0\xc1\x26\x3b\x95\x79\x9d\x83\x3b\xaa\x13\xb5\xb3\x95\xfc\x13\x94\xb7\x76\x06\x5b\xea\x41\xed\x73\x16\x7d\x12\xcb\xe6\xc0\x80\xe3\x93\x27\x37\xc7\x17\x68\x95\xdd\x7c\x7d\x3b\x93\xb3\x05\x66\x6c\xbb\x4a\xf5\xa6\xcc\x2e\xec\xab\x56\xa4\x7a\x08\xb2\x6e\xe0\xab\x5f\x23\xde\xa9\x6d\xf3\x5a\x1e\xc0\xeb\x95\x46\x08\x71\x52\x72\x23\x4f\xee\x2b\xc0\xec\xaa\xab\x27\x7e\x81\xe5\x4b\x1f\x66\x91\x1a\x15\xc6\xf2\xa9\x3e\x42\xa3\x10\x42\x5a\xbb\xbc\x58\x9b\x95\x4c\xf5\x1c\x52\x0c\x69\xa1\x4e\xab\xed\x19\x90\xbd\x88\xab\xda\x95\xde\x41\x77\x11\x72\xd5\xb3\x18\x92\xf2\x78\x47\xd0\x86\xfc\xf4\x62\xf0\xe0\xb8\x7f\x09\xe4\x18\x72\xad\xd6\x31\xf1\x47\x13\x41\xad\x53\x1b\xc2\xa0\xc2\x36\xb5\x2c\x6c\xb3\x07\x4e\x0f\x31\x5d\xde\xa7\xfc\xf4\x49\xd6\xf1\xd4\x1a\xcb\x00\x4b\x47\x64\x3d\xe1\xcb\xe4\x45\x43\xeb\x68\x49\x9f\x99\x54\x7c\xb0\x56\x21\x31\xf0\x85\x0c\xf6\xa8\xc3\xa6\xb2\x6c\xfd\xbc\xc9\xba\xba\xd8\xc8\x7c\x7f\xaa\x9b\x47\x43\x7b\x74\xbf\x0f\x17\x90\x98\x0e\x6c\x9d\x22\xe6\xa7\x0e\xc1\xea\xcd\x99\xba\xb5\x4e\xf3\x8a\x12\x0f\x6e\x3f\x25\x03\xc4\x11\xb9\xa2\x9d\x8e\x36\x7a\xa5\x59\x1e\xa7\x8c\x20\xdf\x73\x27\xae\x87\x6a\x2a\x5e\xa9\x32\x62\x07\x97\x96\x76\x71\x14\xec\x94\xea\x41\x2c\x15\xed\xfa\xe9\x6f\x95\xc1\x63\x4e\x2b\x4b\xc8\xed\xf4\x9e\x4a\x31\x0b\x74\x95\xd5\x01\x54\x65\x22\x49\x72\xea\x58\x35\x56\xf7\x21\xd5\xd9\xc2\x2f\x47\x07\x08\x46\x03\xbd\xcd\xa9\xf3\xcb\x8c\xcf\xc1\xe8\xc4\x8d\x4a\x1a\x15\x7a\x57\xc9\x29\xdf\x6e\xcc\x2b\x11\x27\x78\x61\x99\x87\x3c\xe4\x15\xb5\x54\x0f\x01\x75\x0f\x87\x6b\xf0\xa0\xd4\xee\x1c\xa4\x93\xe3\x22\xb8\x66\x63\x57\x32\x6b\x51\xcd\x2a\xa4\x9e\x04\xca\xf4\x0e\x9c\xe3\xda\xf6\x7b\x99\x66\xaa\xb3\xc0\xfa\x60\xbf\x0e\x1b\xc7\x46\x0f\x75\xc8\x92\x1d\xf5\xb3\xce\x54\x1e\x66\xc7\x80\xcc\xec\x6b\x89\xb8\x5e\xdc\x24\x12\x5a\x06\x05\x3c\xf4\x94\x6a\x0e\x61\x9b\xd7\x6e\xa9\x94\xc9\xd5\xf1\xa9\x1a\x8e\xd4\x72\x1c\x9e\x4d\x35\x9d\x99\x54\x67\x24\x5a\x03\x6f\x98\xa6\xea\x86\xb8\xdc\x88\xa4\x4b\x14\xbd\x9b\x4d\xbd\xc0\x04\x3b\xbe\x31\xc2\x90\x86\x34\x82\xc2\xd6\x2d\x78\x7e\xcb\x95\x3d\x8e\x6d\xf8\xcb\xad\xb9\xd0\x47\xe7\x96\xb9\x71\x1d\x6a\xc1\x03\x20\xae\x56\x53\x23\x20\x21\x56\x5e\xfa\x0a\xcb\x19\xaa\xbd\x48\xea\x07\x24\x8e\xdc\x94\x4a\x45\x7e\x23\x00\x2d\x9d\x4f\x69\xed\x92\x1a\xde\xc8\xc8\xee\xd5\x24\x7c\x72\x8f\x2f\xe7\x00\x8e\x5d\xd6\xc0\xb1\xa5\x43\xed\x42\x5e\xd5\x84\xae\x4f\x1e\x9d\xea\xc9\xa8\xdf\x4d\xd4\xd6\xd5\xe5\x54\x3c\x0c\xb6\x02\x5f\xa6\xb5\x09\x72\xd2\xa3\xb5\x73\x6d\x2d\xd9\xd4\x58\x60\xc9\x9c\x95\xa5\x97\x48\x29\x39\x0f\x99\x66\x5b\x7d\x19\xb9\x5d\xf9\x86\x4a\xcb\x19\x32\x22\x7c\xb3\x89\x4e\x88\x21\x3c\x3a\x0b\xb4\x7d\x6a\x2a\x6f\x13\x0f\xbb\x38\xe5\xb8\xee\x52\xe8\x94\x8b\x53\x56\x5a\xee\x54\x8a\x37\x2e\x78\x03\x9b\xca\x72\xf9\xa4\xb8\xe5\x1e\xe3\xae\xd1\xd0\x45\xb4\x7e\xab\xcc\x6e\x9e\xd1\x63\x23\x16\xe9\x5d\x46\x51\x19\x19\x34\x8b\x30\x66\x22\xa9\xf2\xbb\xf4\x81\x56\xfc\x83\xb4\x38\x3f\x70\xc4\x65\x09\xbf\x90\x96\x22\xa2\x64\x0e\x2d\x57\x6b\x24\xc5\x4a\x6b\x2d\x26\x49\xfa\xee\xca\x4a\xb1\xc9\x72\x78\x96\x9a\x2e\x09\xf9\xeb\xc0\xa1\x55\x86\x0d\x07\xf9\x81\x0a\x51\x2f\x14\x98\x5c\xaf\x33\xc4\x45\x65\x58\x78\x47\x1d\x35\xe3\x6f\x28\x61\xce\x70\xd2\x1f\x62\x78\x4a\xc9\xae\xee\xa4\xa1\xfe\xbc\x1d\xd5\x8a\xf0\xcb\x54\x3a\x79\x11\x20\x7c\x11\x6e\xa4\x7a\x95\x3b\x02\x67\x94\x53\x0f\xee\xa8\xc3\xea\xeb\xa3\xaa\x2a\x37\xc4\xba\xa2\xf2\xaa\x7b\x26\x63\x18\x2e\xef\x13\x28\xf6\x24\x38\xe6\x03\x55\x49\xa3\x2c\x66\x95\x37\xf7\x77\x94\x3c\x55\xfa\xb9\xef\xa9\x7a\xa7\xfb\xc2\x38\x7c\x7d\x4d\x1f\x72\xa4\xa7\xbd\xd7\x2d\xd3\x6c\x5a\x05\x1d\xb4\xde\xc6\x2e\xa3\x39\xa7\x11\xc2\x01\x7a\xff\xfe\x87\x6f\x9e\xbd\x78\xf6\xfe\xe5\xb3\x37\x3f\x3c\xfb\xea\xfd\x7b\x75\xd7\xf6\x15\x25\x33\xb4\x58\xd1\xc5\x07\x1a\x21\x40\xe6\xdd\x41\xeb\x09\x36\xf9\xa8\xa0\x8c\x91\xa1\xb7\x71\x1e\x5f\x25\x14\x01\xca\xe8\xef\xdb\x38\x53\x79\xef\x36\x21\x8b\x64\xd0\x3c\x90\x88\xe6\xf0\x03\x25\x5f\x85\x9c\xba\x2c\xbd\x75\x30\xbc\x14\x43\x60\x6f\xd5\xcb\xdd\x9d\x1f\x28\xbc\x97\x11\x92\x2a\xa2\x4e\xab\xd3\xf9\x41\x8d\xfd\x05\x25\xe8\xaf\xea\x58\x0c\xc1\xf3\xea\xa3\x85\xe0\x09\x7d\xf8\xe6\x54\x69\xb0\x50\xda\x91\xaa\x6b\x54\xa6\x36\x73\xe9\xec\x05\x7d\xd4\x8d\xaa\xff\x9c\x83\x87\x14\xf8\x2c\xfd\xbf\xe0\xe0\xe1\xdf\x71\xd6\x60\x8c\x68\x1e\xe5\xac\xe1\x8f\x5a\x9d\x1d\x9f\x41\x3f\x68\x88\x65\x0c\x08\xbe\xa3\x8f\xbe\x32\xf7\xef\xce\x75\xe9\x91\x20\xdf\x5e\xe5\x3c\x73\x9e\x1b\x8d\xa0\x35\x7b\xca\xab\xa0\xbd\x5f\xa6\xc0\x1f\xbc\xbd\xff\xaf\x5e\x50\x2c\x9b\x9a\x96\x21\xdb\x3c\xad\xf2\x16\xf1\x91\x92\xf3\x5f\xf3\xcf\xe1\xd7\xfc\xf3\xf3\xeb\x8a\xaa\x7f\x45\x8f\x15\x9b\xea\x25\x84\x8f\xd2\x1d\x37\x42\xda\xba\x86\xd5\x6c\x68\x3a\x44\xdd\xa2\x67\xb3\x74\xae\xf5\x71\xc0\x66\xa9\xba\xa6\x97\x69\x8f\x80\x95\x09\x8d\xa8\xf9\x6b\xbb\x03\xf0\x25\x25\xe7\xed\xf3\x6b\xf8\x8d\xd6\x2f\xd7\x4b\xa8\xfe\x44\xc9\xf9\xec\x49\xf7\xdd\xfc\xfc\x1a\x3e\xa3\xe4\xfc\x9f\xeb\xbc\x7b\x0e\x3f\x2a\x97\x43\xa6\xe7\x6f\xa9\x75\x06\xd9\x55\xfa\x94\xef\xd2\x5b\x9a\x3d\x0d\x73\xea\x18\xd7\xb8\xdf\x1c\x59\xa1\xfd\x78\xf4\x30\x69\xe5\x21\xf1\xc7\xd2\x51\x98\x58\x67\xe6\xf2\xfe\x4f\x14\xde\x56\x4e\x05\x64\x1e\xf2\x19\x55\x37\x5d\x39\x96\xa7\xb8\x3c\xe0\x56\xd7\x7e\xb7\xb6\xca\x26\x8f\x95\x5e\xcd\xf8\x07\x75\xbb\x08\x4f\x59\xf0\x8d\xa0\xf1\xf3\x9a\xbf\x7b\x5a\x39\x00\x6c\xb7\x0f\x3d\x36\x56\x69\x78\x6a\x79\x0a\x24\x56\x82\x74\xad\xf9\x3b\xc5\x81\x9d\x2e\x7a\x67\x95\xc5\xc0\xe5\xfc\xfc\x9d\x92\x67\x54\xfa\x99\x9b\x3e\x7d\xf3\xc6\xdd\xdc\xa9\x77\x36\xfe\x51\x8f\x5e\xe7\x01\x5a\xe7\x08\xfe\x76\x90\x9b\x66\x0b\x81\xc5\xe8\x7f\x50\x05\x86\x5f\x2c\x30\x9c\x3b\xdd\x59\xd8\xfd\x28\xbd\xdc\xb1\x46\xb6\x76\xe6\xcf\x5d\x9e\xfe\xb8\xd9\x94\x33\x08\x99\x0d\xbd\x54\x41\x2f\x9b\xa5\x02\x46\xe9\x1c\xb2\x59\x5a\x4e\x91\x58\xdc\x2a\xba\x8e\x74\x3f\x53\xf2\x0b\x75\x76\xd6\xed\x7d\xe5\xf3\x37\xf8\x47\xcd\x0b\x41\xe9\x1c\x58\xc6\x57\xaf\x0a\x77\x37\xa9\xf2\xbe\x8d\x82\xbf\x37\x27\x74\xef\x4e\x27\xdd\x1f\x25\xe5\xf1\x47\x2a\x23\xd5\x83\x32\x2a\x59\x06\xbb\x57\xea\x0d\x8c\xe3\xa8\x6e\x42\x97\xbc\x9b\xc9\xb7\x67\x9a\x92\xb3\xf8\x7a\xf5\x50\xba\x7c\x1d\xa6\x96\x20\x2a\x3c\x8a\x68\xc8\xd7\x50\x67\xa6\x1e\x79\x3d\x8c\x69\x28\xcc\xd3\xcd\xe1\xf7\xc9\x91\x88\xb4\x93\xc3\x10\x89\xc7\xd5\x1f\xc7\x5c\x25\xe9\xe2\xc3\x71\x4c\x97\xb2\xa8\x39\xf6\x54\x1d\xdd\x9c\x87\x19\x3f\x15\x7f\xb2\xd4\x71\x7c\xcc\x92\x98\xd1\x86\xa8\xa3\x3e\x55\xd1\x27\xab\x69\xe8\x95\x9d\x70\xba\xdc\x71\x82\x2a\xa0\xfe\x36\x00\x5c\x25\x88\xbe\x34\x24\x8a\xe8\x93\x25\x45\xe2\x41\x39\xf5\x22\x8c\xcc\xa4\x82\x35\x44\xd7\x51\x15\x42\xea\x08\x0b\xcd\x74\x4c\x89\x4e\xa6\x96\x6a\xb6\xed\x98\x0a\xb2\xb5\x58\x0b\x76\x3a\xde\x9e\x9b\x5a\xd4\x51\x0d\x47\xe0\xd7\x6f\xd1\xc8\x3c\x3a\x5c\x1b\x94\x89\xab\x46\x65\x62\xac\x61\x99\xa8\x72\x5c\x65\x4d\xd5\xc0\x6a\x51\x55\xbf\xea\xd1\xd6\xd0\x4c\x82\x3d\xb6\x7a\xdc\x71\x25\xc7\xc8\xb5\x0e\xf3\x0f\x47\xe4\xad\x1e\x79\x6f\x45\x96\x24\x6d\xa5\x1e\xcd\xfc\x3b\x05\xf5\x1e\x95\xcc\x11\xb3\xae\x8a\x37\x25\xee\xea\xdf\xe6\xf5\xaa\x2a\xb9\xfa\x54\x30\x15\x21\x01\x49\xf1\xcb\xd3\x8d\xf8\xc9\x4c\x43\x31\x13\x32\x9c\x28\x29\x43\x36\xec\xac\x88\x6a\xd0\x76\xa4\x35\x62\x15\x6d\x43\xcd\x8e\x39\x2c\xde\xb4\x1c\xef\xba\xea\x59\x07\xf5\xcd\xe9\x1d\xaf\x45\x2c\xd2\x64\xbb\x66\xdd\xeb\x70\x53\xfb\x16\xcc\xda\x51\x84\x0d\x0f\x1d\x6d\xc5\x48\x8f\x1c\x25\xc8\xab\x4f\xb1\xad\xf1\x50\x45\xaa\xc7\x4a\xbb\xe6\xbd\x8b\xaa\x4b\x11\x5d\xa4\x6a\x9f\xeb\xf2\x55\xbc\xf8\xc0\x68\x9e\x5b\xc9\xca\x69\x93\x3d\x04\x9e\xa5\x1f\xe8\x51\x84\xdd\x9f\xdb\x34\x8b\x6a\x2d\xad\x53\xe9\x95\x5e\xce\xa6\x0c\x76\x53\xf5\xbc\xb6\x88\x4a\xb7\x5c\xbe\x04\x2a\x52\x75\xd8\x4e\x2e\xe3\xaa\x06\x36\x34\xcb\x37\x54\xbd\xd8\x2f\xd1\xb6\xfa\xee\xa6\x59\x2c\xd6\xe7\x1d\x0a\xfe\xd6\x9c\x72\xaf\x52\xb8\x79\x80\x58\xc7\x37\xc7\x9a\x7a\x8e\xe2\x4f\xd4\xd2\xfd\x68\xc5\xc7\x87\xac\x85\x1d\x5b\xe3\x2d\x6e\x68\xc6\xe3\x45\x98\x74\xc3\x24\xbe\xd6\x6c\xc5\x32\xa1\x77\xdd\xab\x30\x8f\xf5\x6c\xc8\xc7\x3f\xba\xfa\x51\x2e\x11\x23\x66\x58\xfc\x5e\x87\x12\xff\xaf\xb3\x38\x92\x19\x45\xa0\xc2\xaa\x2c\xbd\xad\x3e\x64\xd2\x71\xcc\x21\x26\xca\x48\x4e\xd7\x9b\x24\xe4\x54\xe4\xcf\x9b\xe2\x55\x29\x3b\x29\xdc\xf2\xf4\x30\xbb\x8c\xab\x65\xad\x16\x46\xc9\x26\x55\x31\xf7\x47\x31\x57\xc9\x36\x3b\x8a\xcc\x37\x19\x0d\x23\x0b\xdd\x25\x86\xd8\x44\xc4\x5a\x6e\xa6\x19\x3b\xea\xfe\x38\xca\x34\x54\x58\x4f\xbe\x7f\x4b\x2d\x2d\xe9\xd1\x2b\x57\x4d\x0f\x4d\x3d\x60\xec\xcd\x67\xd9\x9c\xa8\x1a\x67\xd9\xbc\xbc\x5e\x5d\xd3\x71\x99\x37\xb5\xb0\xd4\x90\x95\xee\xa9\xa5\x59\x43\x5d\x3f\x81\xb9\xe0\x79\xbf\xa5\x5a\x3b\x70\x74\x5b\x3b\x34\xb9\x42\xd5\xa8\xb4\x26\x55\xae\x22\x6b\x4d\x1f\xbd\x88\xa6\x1d\x1a\xc7\xf9\xcb\xf0\x65\xf9\x70\x55\x4c\xd8\x8c\xce\xf7\xfb\x9f\xa5\x2c\xa4\x4f\x3b\xe3\xfd\x5e\x2b\x8d\x63\x42\xc8\xdf\xe9\x94\x5b\xb2\x77\xd3\xb3\x68\xf1\x34\x76\x38\xae\x65\x42\x1d\xde\x89\x2b\xb5\x9c\x54\x9a\x72\xc2\x9c\xfe\xa0\xdf\xc7\xc0\xd5\xfd\x64\xf9\x37\x93\x7f\x53\xf9\x37\xe4\x64\xdb\x6e\xa3\x94\xf1\x74\xbb\x58\x29\xaa\x1b\x5b\xb6\x8b\x26\xa0\xed\xc6\xc4\x4c\x6d\xf5\x40\x38\xd9\xbd\x48\x3f\x06\xa8\xbb\x4e\x3f\x76\x11\x08\xd1\xa5\xbb\xce\xbb\x08\x5e\x05\xa8\x9b\x76\x11\xfc\x44\xaf\x3e\xc4\x3c\x40\xdd\x5b\x19\xe8\xa2\x02\x12\x7e\xd2\x20\x6d\x83\xb0\xbe\x45\x5e\xde\x09\x97\x7e\x6f\x63\x39\x85\x39\xef\xa0\xf2\xa9\x73\xd1\xc3\x84\xe3\x1d\xe7\x24\xe7\x62\x50\x31\x9f\xe5\x7c\x7e\x29\x0d\xdf\x0b\xa4\xda\x95\xee\xd2\x78\xbb\x8d\xd6\xf9\x37\xf7\x9b\x15\x65\xb9\x2a\xd6\x6e\x3b\x02\x18\x42\xca\x92\x25\xdd\x75\x2e\x61\x41\xa3\x6b\x8a\x30\x1c\x96\xee\x86\x9b\x4d\x42\xbb\x3c\x0b\xe3\x44\xec\xe8\x82\x24\x97\x15\x09\x48\xca\x74\xa4\xd4\x47\x5b\x4e\x38\x87\x05\x27\x8c\x43\xc4\x49\xc6\x61\xc9\x49\xca\x61\xc3\x49\xc8\x61\xc5\xc9\x8e\xa5\xd2\x02\x3a\x49\x82\x99\xb4\xa3\x0c\xb3\x50\x1a\x6f\x82\xf6\x31\x49\x23\x23\x37\x37\x3d\x4b\x69\x95\xd0\x47\x74\x62\x1c\x84\x90\x2d\x9f\x56\x60\xee\xd0\x60\xc1\x3b\x14\x17\x05\xac\x0f\x9a\x5c\xa4\x49\x9a\x75\xc3\xe8\xb7\x6d\xce\x1f\xdb\x68\xad\x8c\x69\xb6\x82\xd2\x96\x4f\x17\xbc\x83\x36\x59\xcc\x54\xdb\xb2\xe1\x1b\x4e\xce\x67\xdd\x5f\xf3\x79\xc7\x71\xf1\xd4\x56\x89\x5c\xf3\x83\x37\x32\x79\x5d\x2e\x0d\x10\xaa\x1c\xff\xdf\xf3\xda\xd1\x8c\x91\x47\x6f\x38\x5c\x73\xeb\xe5\xb5\x2b\x3b\xdb\x3d\x77\xa4\xc2\x42\x4d\xc9\x2d\x87\xbb\x03\x20\x08\xc6\xea\x13\x83\xd7\xcf\x3f\x9c\x9d\xff\x53\x64\x3e\x37\x6e\xb7\x2a\x03\x06\xb1\xe0\x6d\x18\x94\x4f\xe6\x4b\xae\x2d\x5e\x87\xd7\x54\xbe\x48\x70\xcf\x1d\x86\x25\xfd\xb0\x1f\xeb\xd8\xf2\xce\xd5\x61\x82\x98\xb2\xca\x19\x73\x01\xcf\x0e\x7a\x2d\x29\x6c\x9a\xc5\x94\x71\xb5\xe1\x3d\x72\xfa\x8e\xca\x99\x29\x54\x88\x7b\x46\x48\xc4\xf7\xfb\x0d\x9f\x56\x58\xf3\xe1\xb0\xe9\x72\xe1\x7d\x0a\x6a\x96\x57\xae\xaa\x90\x6e\x90\xb9\x65\x94\xd5\xd6\x9b\xa6\xb6\xe2\x47\x0c\xf0\xb8\xb1\xd8\x1e\x9e\x6e\x4d\xc6\x59\xcd\x3d\x3d\x68\xee\x36\x8b\xb9\x58\xd6\xeb\x34\x7a\xf4\x2a\xac\x95\x69\x5a\x10\xfb\x7d\xb9\x2c\xdb\x6d\x45\x58\xce\x08\x59\xca\x85\xa2\xd7\xc7\xbb\x83\x7e\x6c\x73\xc1\x53\x4a\x9d\xfd\x63\xbb\x61\x17\x31\xbd\x78\x91\x7e\x3c\xea\xc2\x7e\xaf\xa7\x9a\x88\xa9\xb6\xfa\xf0\x3d\x27\xbb\x4f\x2d\x02\x8d\xf0\x67\xe7\xff\x94\xc4\xb5\x5b\x2e\x85\x23\x22\xa0\xbf\x9e\x4a\x0e\x05\x75\xe4\x92\x14\xf8\xdd\x6e\x0b\xf2\xa0\x39\x23\x41\x1f\xaa\x4e\xb6\xdb\x68\x23\x16\x8a\x9d\x59\xc6\xa8\xe5\x5b\xc0\xeb\x47\xf4\x50\x2d\x53\x47\xc9\xc8\x7b\xc5\xd6\xed\xb5\xfc\x85\xb5\x38\x71\x62\x01\x97\x1d\x39\x7c\xc2\xa5\xa2\x34\xc8\x08\x2e\x80\x2a\x8d\xab\xbd\x7c\xe5\xf0\x58\x51\xc0\xab\x47\x43\x53\x51\x35\x55\x58\xac\xf4\x1f\x1e\x51\x52\xf5\xeb\xca\x7e\x3c\xb1\x5b\x39\x05\xaf\xc2\x62\xc7\x52\x61\x7f\x3e\xa5\xc1\x96\x77\xb4\x0f\x54\x39\xed\x66\xc6\xce\x34\xf4\xf5\xa7\xce\x23\xca\x56\x7b\x48\x51\xc0\xcb\x4f\x74\xac\xf2\x4f\xba\xc8\xd2\x24\xe9\xe6\x2c\xdc\x28\x43\x34\xa5\xb4\x17\x9c\x89\x07\xbe\x8f\xeb\x1b\x15\xea\x54\x38\xf8\xfe\xb1\x4d\xa4\x37\x34\xd3\xcd\x5c\xd1\x55\x78\x13\xa7\xd9\xf1\x1e\x28\x30\x4d\x67\x5a\xac\xc2\x98\x49\xb1\x49\xb6\xf3\x82\x93\x9d\x92\x04\xae\x33\x21\x37\xaa\xb0\x12\xb9\x6f\xc4\xec\xca\xef\x7c\x95\xc5\xec\x83\x49\x65\xf4\x3a\xb4\x53\xb5\x0c\xa1\x8b\x66\x74\x49\xb3\x8c\x6a\xad\x23\x20\xb1\x3d\xc6\xcb\xfb\xae\xb9\x6a\x61\xf2\x85\x8b\x0f\x08\x94\x3e\x52\xc5\xc8\x30\x02\x24\x45\x94\x6e\xcc\xe9\xba\xac\x54\x49\x2d\x26\xe9\xa0\x26\xc9\x99\xcb\xea\x0a\x78\xfe\x68\x94\x79\xc1\x2d\x3e\xf3\x8c\xb5\xdb\x8d\xc8\xfb\x84\x93\x9d\x68\x24\x90\xb2\x81\x08\x99\x41\x6b\x70\x1d\x46\x97\xef\x34\xa2\x60\x26\x13\xd5\x0e\x83\x94\x70\x51\xa5\xce\xcd\xd0\x55\x9e\x28\x66\x61\x22\xea\xdc\x6e\x8e\x20\x20\x72\x18\x00\xc8\x36\x96\x89\x68\xfa\x13\xd5\x37\xc0\x5d\x64\xd1\x70\xfa\x8e\x13\xfb\x25\xd8\x27\x1c\xc3\xc7\x46\xb3\x0f\xb9\xfb\xc2\x57\x9f\x04\xab\xed\xef\x76\xbd\x4d\x78\xbc\x51\x6e\x8f\xbe\xb3\xaf\xb5\x7e\xd1\xf5\xcd\x49\xf7\x13\x09\x7e\x41\xa3\xea\x02\x4e\x5a\x1e\x8a\xa8\xf9\x48\xab\xf9\x48\x6b\xae\x73\xcf\xfc\xca\x55\xbe\xf4\x10\x94\xda\x8e\x81\x44\x4e\xcd\x4d\xa4\x33\x6f\xae\x18\x8a\xaa\xa4\xf1\x23\x20\x0f\x2a\x3e\x72\x5c\xd9\x60\x17\xf0\x35\x27\xb3\x15\x87\xb5\xe0\x8f\xe0\x19\x87\x0f\x1c\xde\x70\x78\xca\xe1\x1d\x87\xef\x39\xbc\xe6\xf0\x8a\xc3\x0f\x1c\x5e\x72\x78\xcf\xe1\x39\x87\xaf\xf8\x1c\xbe\xe4\xe4\x6b\xae\x1f\x49\x6d\x7c\x7b\x5b\x2c\xfd\x03\xf8\x15\xf8\xe4\x43\x7f\x27\xb2\xc3\x6f\x9f\x6e\xa6\xdc\x3c\xad\xf7\x78\x9d\x13\xb7\xb8\x36\xdb\x7c\x55\x3a\xb7\x70\x3c\xa0\x5c\xde\xa0\xad\xea\xc0\xea\xc5\xdf\xd9\x1c\xc3\x4f\xf2\x4c\x49\x89\x39\xb7\x0f\x4a\x2b\x72\xaf\xf8\x8c\x13\x7d\x27\xf4\x9a\xf2\xa7\xe9\x7a\xb3\xe5\x34\x52\x7e\x0f\x4e\xc9\x50\x72\x27\x31\x73\xfa\xa3\x94\x71\x3e\xe3\x58\x49\x89\x3f\x72\xbc\xdf\x3b\x3f\xf1\xd9\x67\x7c\xf6\x23\x9f\xcf\x89\xfa\xc5\x97\xbf\xf1\x06\x93\x95\x0a\x1e\xda\xaf\xdb\x4f\xf2\x1d\x6d\x6c\x71\xc6\x6f\xf9\xa9\xb7\xcc\x76\x05\x86\xb3\xdb\x3a\x5f\xaa\x8c\x42\x64\x2d\x26\x5e\x7e\x5c\xda\x0c\xd6\x99\xa4\xba\x16\x7f\x77\x26\xbd\xae\x3a\x22\xa3\x7a\x65\xe7\xd6\xb8\xea\xba\xac\x5b\x55\x7f\xc9\xcb\x27\xcf\x1c\x59\x2f\xf9\x92\x2b\x1f\x12\xb7\xa5\x17\x06\x0c\x67\xaa\x7d\x69\x74\x7d\xc9\xb3\xfb\x9d\x49\x14\x05\x10\x3a\x7d\xbb\x4c\x8d\x5e\x34\xf7\x0d\x87\xdf\xc5\x08\xe1\xef\x9c\xec\xaa\xae\x07\x7e\x4d\x75\x64\x6e\xd1\x21\x11\x6f\x76\x3e\x6b\xa0\xcd\xd1\x76\xb1\x02\xfe\xc1\xc9\xb9\xf3\xcf\x5f\xf3\xcf\xf5\x11\xeb\x1e\x5a\x4e\xf5\xe5\x4c\xcf\x66\xff\x74\xf0\xfc\xf3\x5f\x31\xb6\x65\xa0\xbf\xf1\x03\xfe\xf5\x26\x94\xbb\x19\x9f\xca\x50\x20\x9f\x02\x55\xdf\x22\x54\x7e\xb3\x29\x82\x96\x8c\x71\xf8\xf4\xad\xbc\x4a\x8a\xa0\x85\x3a\x6f\x05\x41\xc7\xfb\x3d\xdf\xef\x59\x35\xf7\xbf\xf0\x9a\x61\xaf\x24\x2b\xdf\x08\x76\xd0\x90\x4a\xfb\x8e\x07\xb7\xdd\xfb\x55\x16\x82\xfb\xfd\x99\xc2\xcc\x4d\x98\xe5\xf4\x39\xe3\x0e\x03\xdf\xc3\xd5\x63\xe9\xfa\xdd\x27\xda\x61\x15\x02\xfd\x2e\x1f\xd1\xd6\x39\xe4\x87\x9c\xc7\x6f\xac\x79\x64\x87\xd3\xa8\xf2\x91\x33\x1f\xce\xfc\x22\x5e\x3a\x7f\x97\x48\xc0\x08\x2b\x59\xb1\x7f\x70\xf8\x1b\xb7\xf4\x2d\xa2\xfb\x56\x95\x82\x11\xe8\xae\x73\xb5\x4b\x11\x42\x1c\x46\xc4\xe6\x26\x78\x0f\xbb\xe1\x32\xcf\x55\x7a\x87\x30\xd4\xfa\x04\x87\x75\x62\x7c\xdc\x39\x43\x54\x6b\x95\x22\x50\x39\x98\xfa\x2d\xb6\xb2\xd5\x87\xa8\x87\x22\x1f\x3f\x73\xf8\x96\x93\x3b\xea\xec\x4a\x5b\xe1\x87\x3d\xe3\xd6\xec\xbd\xce\x2a\x2d\xd7\xf1\xdb\xf5\x37\x0e\x85\x5d\x61\x5b\x96\xcc\xde\xd3\x39\xe1\x90\x3d\xe8\x75\x5e\x36\xf1\x52\x79\x5f\xdd\xef\xdf\xab\xc0\x21\x7f\x6c\x9d\x1b\xd7\x1d\x48\xc9\xa7\x0b\x1b\xf4\x55\x69\xbb\x6d\x7c\x58\x4a\xa7\x52\xd2\x32\xcf\xba\x4e\x30\x7b\x29\xe1\x2f\x5d\xcd\x6b\xc7\x15\xa7\x6c\xc7\x38\x84\x24\x15\x43\x91\x96\x69\xa9\xf6\xf2\x12\x3a\x14\xef\xf7\xc6\xf8\x30\x26\xa9\xa8\x51\x60\x64\x5c\x6a\xfb\x12\xf5\x12\x5e\xaa\x9c\xfb\x25\x10\xcf\x92\xb9\x7c\x14\x5d\xf0\x87\x9f\x84\x7a\xf5\xf2\xab\x84\x71\xbc\x74\x28\x21\xe4\x45\x15\x4b\x6f\x5b\x4f\xa8\xe5\xc5\xa7\x7a\xb4\xa7\xdd\x2e\xad\x58\x3c\xa8\xec\x58\x08\x21\xcf\x6b\xc5\xbf\x2b\x8b\x1b\x0e\x43\x19\xaf\xd8\x17\xee\x8d\x5d\x8d\xbc\xbf\xa5\x2e\x81\x64\x07\x57\x18\xda\xed\x5a\xa6\x7a\xa2\xba\x22\x22\xe5\x63\xe5\xa2\x57\xbd\x69\xa9\xfc\xa5\xa8\x18\x95\x68\x6e\xbb\x52\x65\x23\x5d\x1c\xf8\x25\xa9\xa3\x4c\xf5\x40\x01\xd5\x0f\x14\x88\x3d\xa6\xf9\x6e\xaf\x71\x42\x29\x6d\x7b\x24\xcd\x0f\xe5\xbb\x3f\x2f\xe8\x3c\x30\xa0\x0d\x2b\x8b\x99\x58\x3a\x86\xc4\xa5\x4d\x95\x13\x43\x38\x8b\x0f\xdf\xe8\x28\xbd\x08\x7f\x25\x32\x54\xd7\xb4\xe5\x35\x6b\x8d\x78\xb2\x89\xa2\x90\xbd\x81\x47\xf6\xad\xfe\x4c\x51\x8a\xcb\x79\x0d\xe5\xbc\x86\xd5\xbc\xbe\xb0\xe7\xf5\x05\x35\xca\xde\xaf\xa8\x53\x66\xaa\xb2\xd8\x3d\xbc\xb4\x87\x96\xce\xc2\x93\x43\x8b\x05\x67\x54\x8e\x25\x34\x43\x11\xd8\xfb\x80\x4f\xc7\x46\xa7\x0e\x96\x15\xa6\x36\x25\xdb\xef\xe5\xb3\x05\x55\x44\xe5\x64\xaf\x7a\x5e\x2d\xc8\xac\xf7\x3c\xf9\xa1\x65\x13\xd7\x96\x4d\x5f\x4b\xcb\x26\x6a\x7d\x69\xd7\x11\x82\x7b\x65\x36\xf7\x5a\xce\x31\x61\x62\xdc\x09\xf1\x2e\x93\xbf\x64\x26\x47\x62\x6e\x30\xe6\x24\x9b\x25\xf3\x4b\x41\x43\x52\xf3\x1a\x6a\xda\x21\xf2\x4e\x4a\x65\xd8\x86\xda\x08\x4f\xf3\x72\xb7\xf8\x92\x42\x8c\x83\x58\x9a\x51\x99\x27\x1e\x5a\x69\xd5\x7d\x7b\x6d\x1b\x37\x31\x75\xc0\x6b\x1b\x73\x63\x0d\x5f\xe0\xd2\x24\xcd\x2c\x29\x46\x73\x1e\xb3\xeb\xef\xe8\x0d\x4d\x2e\x53\xfb\x81\x51\x3f\x48\x3b\xbe\xb6\x83\xb6\x5f\x7f\x28\x31\x6c\x67\x97\x0d\x52\x6d\xd0\x6e\x0b\x11\xb2\xc5\x3a\x7b\x17\xaa\xf7\x74\x42\x3d\x9c\xdd\x29\x32\x9e\x42\x08\xb1\xda\x2b\xd4\xc2\x3c\x23\x24\x54\x2b\xdf\x00\x42\xdd\xc0\x82\x1c\xb6\x24\x84\x05\xd9\x1e\x90\x89\x12\xef\x23\x85\xf7\x72\x1e\x96\x0a\xe4\x51\x0d\xe4\xb0\x21\x6a\x45\x44\x33\x4f\x12\xdc\xe5\x7e\xbf\x91\x6d\x27\x84\x39\x5b\x58\x40\x82\x61\xa9\x2a\x58\x11\xee\x44\xb0\xb5\x70\x3f\xdf\xef\x9d\x9c\x50\x67\x21\x9f\xef\x59\x91\x55\x39\x7f\xbf\x51\xc8\x31\x2c\xca\xb5\xb1\x82\x74\x16\xd5\xd6\x46\x62\xad\x8d\x95\x60\x7a\x25\x67\xb0\x69\xb7\xab\x42\x91\xd8\x01\x13\x5c\x7e\x6f\xe5\x53\x03\xb2\xa2\xaa\x6c\xd5\x9f\xc2\xa2\x15\xd1\xbc\xa8\xb0\xa6\x28\x1c\xe9\xa9\xe9\xc4\xae\xd9\xe0\xb5\xbf\xee\xac\xdf\xbb\xe4\xd5\x65\x6e\xde\xe9\x60\xf9\xac\xcc\xef\x54\x3e\x2f\x63\xb9\x83\x32\xdc\x86\x32\x27\x7f\xf8\xd5\x95\xd2\x75\x52\xcd\xd0\xad\xbe\x53\x67\xe4\x1b\x6a\x59\x47\x73\xb1\x21\x4c\x69\xe0\x30\xb5\x07\x66\xa0\xa9\x7b\x8d\x86\x3c\xe4\x24\x46\xda\x9c\x5d\x7e\x02\xfd\xa8\x61\x54\x4a\xe4\x63\x35\xe4\xa3\x87\xcc\x03\xd5\xe7\x79\x95\xc7\xc9\xea\x51\xc2\x93\x40\xa8\x5c\x0f\x7e\x4b\x1d\x26\xaf\x48\xa8\x79\x7a\xe0\x2d\x70\xf9\x2c\x5e\x33\xb1\x3c\x76\xde\x65\xac\x75\xf5\x95\xe9\xfa\x21\x22\x6b\xb7\x8f\xcc\xe6\x95\xbd\xbd\x94\x75\xa9\xe5\x1e\x39\x15\x7c\x63\x48\x24\x8f\x2e\x2f\x21\xeb\xab\x74\x29\x39\xf3\x0c\xbb\x72\xe6\x43\x42\x7e\xe1\x4e\x08\xb2\xa6\x4b\xed\x26\x59\xec\xf8\xb1\xc8\x06\x4e\xba\xdf\xc7\x62\xdf\x4e\x2b\x27\xde\x33\x36\x07\x3e\x0b\xf7\x7b\x36\x27\xc9\x7e\x9f\xd9\x56\xf9\x87\x53\x74\xb0\x69\xab\xf9\x39\x79\x7b\x94\x13\x2a\xb6\xa5\x26\x4d\x49\xa5\x5e\xb4\x54\xcc\x53\x1a\xa0\xbf\x4a\xb5\x9e\x55\x67\xa7\xe4\x7a\x7c\x0f\x17\x8e\xa8\x4f\xe0\xd9\x29\xac\x39\x7e\xef\xa8\x44\x9c\x29\x0f\xe4\x75\x8c\x07\x56\x44\x89\x0c\xbf\x70\x87\x83\x5c\x7f\xfb\x3d\x55\x08\xe1\xfc\xcc\x4f\xf9\x77\x51\x4b\xd2\xf2\x40\x36\xa5\x5f\xf0\xa9\x1f\x74\xfd\xa0\xf4\x40\x60\x92\x8a\x07\x28\x80\xe6\x9b\xab\x8e\xf3\x13\x18\x2f\x78\x67\xc8\x6a\x4a\x29\x8a\xdd\x3c\xcd\xb8\xf3\x33\xc7\xda\x18\x38\xb3\x8d\x81\xd9\x2c\x9b\xa5\xf3\xb9\x60\xad\xc5\x6f\xf5\xce\x4c\x81\xe7\x05\x06\xca\xc8\x4e\xdf\x16\xd0\x17\xdd\x84\xa0\x7b\xe6\x97\xb7\xb2\x9e\x1a\xd7\x4b\xc1\xd1\xcd\xeb\xc3\xbb\x34\x5f\x78\xed\xb6\x5a\xfa\x62\xc3\xb0\x5c\xa2\x4f\xed\x8f\x60\x57\x00\x27\xd4\x35\xad\x4a\x5e\x13\x18\x29\x4b\x0a\x4e\x42\x72\x00\x9b\x2c\x8d\xb6\xb2\x49\xe5\xf6\x09\xac\x3d\x32\x9b\xa2\xdf\xf2\x1c\x05\x19\x84\x82\x57\xa0\xf2\x25\xb8\x32\x35\x9c\x22\x14\x84\x90\x10\x29\x91\xc5\xe2\x0b\x21\xe3\xa7\x2f\x06\xd4\x45\x18\x72\xe2\xc1\xb6\xc1\x80\x3d\xef\x10\xbf\x38\xf2\xea\x54\xf2\x79\x19\xa9\x6e\xb3\x8b\xed\x54\xbb\x5f\x90\x7d\xaa\x68\xe9\x8b\x6d\x8c\xb0\xf4\x28\x5b\xbf\xf9\x7e\xa6\x48\x9b\xdc\x08\x5f\xd1\x6a\xbb\x16\x53\x69\x88\xaf\x28\xdc\x2d\x7b\xab\x92\x34\x2f\x50\x0d\x22\xc1\x26\x94\xc9\xe1\x1c\x64\xaf\x9c\x91\xea\xe6\xf9\x8a\xae\xe9\xec\xb5\x90\x73\x4b\x98\x98\x32\x61\xad\x86\xad\x83\x71\x60\x78\x84\xa6\x06\xd3\x5a\x56\xb9\x44\x7e\xcb\xf3\xe0\x5b\xae\xde\xf6\xc8\x9f\x86\x8b\x95\xbe\xc1\xaa\x22\x5e\x84\x2c\xbc\xa6\x59\x60\xee\xe9\xa8\xd8\xd7\xda\xaf\x89\x71\x5c\xcc\x48\xa8\xe5\x5c\x79\x11\xff\x8e\x3b\x94\x61\x60\x8c\x74\x7d\x7a\x51\xe9\x3e\x32\x6b\xaa\x18\x13\x73\x25\x89\x24\x53\x37\x6d\xfa\x96\xcd\x48\x68\x3b\x07\x3e\x96\x29\xcd\xfd\x8c\x9d\x6a\x34\xb0\x58\x5c\xcd\xb0\x84\x52\xed\x10\x12\x3e\xa5\x0e\xc3\x01\xad\x74\x0e\x7c\x95\xa5\xb7\x2d\x5a\x08\xc1\x2e\xdd\xef\xcf\x98\x9b\xde\xd0\x2c\x8b\x23\x9a\xd7\xbf\x66\x69\xa9\xc8\x08\x35\xad\xae\xa7\x42\x62\x33\x78\x61\x39\x73\xf6\x0a\x8f\x71\xb3\xf2\x2e\x99\xd1\xb9\x28\x9d\x32\x51\x5c\x7c\x41\x3c\xa3\x73\x79\xef\x4c\x48\x5c\xa5\x17\xa0\x42\x9b\xdb\x27\xac\x66\xa3\x9f\x1f\xdd\x86\xca\x79\xc8\xd5\x8b\xf4\x4a\x7e\xc9\x5f\x69\xf4\x39\x22\x11\xb8\x72\x72\xb6\x2b\x2e\x33\x77\x21\x26\xfd\x69\x79\xdd\xaf\x1e\x41\x76\xf2\xc1\x1f\x85\x13\x49\x98\x4b\xbf\x49\xd5\xd7\xb7\x6f\xde\x88\x4e\x1a\x06\xb9\xd2\x91\x64\xe6\xd2\xa0\xd8\xcb\x6a\x35\xba\xba\x9c\xf4\x21\xd7\x94\x40\xca\xb2\x20\x37\x4a\xe0\xcd\x75\x88\x9e\x34\x57\x22\x52\x08\xd7\xa5\xd3\xe3\x3c\xea\xa1\x26\xc7\x83\x37\x54\xce\xde\x55\x98\x9b\xb4\xa0\xb9\x4f\xc0\xe8\xad\xc9\xc1\xe1\x69\xba\xde\xa4\x4c\xba\x86\x11\x13\xd6\x54\x7b\x25\x6e\x6c\x0f\x24\x4d\x39\x51\x52\xce\x94\x0b\x5b\x11\x41\x7b\xc6\x20\x2e\x63\xa4\x62\x22\xcd\x20\x21\xb4\xa4\x58\x67\x61\xc3\x94\x6a\x69\xe9\x9d\xba\xdb\x16\xba\xb5\xd5\x0b\x31\xa4\x86\xe1\xde\x65\x74\x99\x07\x1e\x88\x5e\xc4\x0b\xe5\x45\x54\xce\x66\x74\xcf\xc2\x75\xbc\x90\xdb\x5b\xae\x17\xf6\x3b\x75\x2d\xaf\xa1\x3a\x30\xef\xad\x6f\xed\x35\x10\x57\xef\x4c\xc0\x4e\x8e\x2e\x48\x61\x99\xc4\x9b\x00\x5d\x29\xf7\x28\xd5\x1a\x0e\x5d\x91\x30\x55\x3f\x01\xca\xb8\x54\x5a\xa4\x6e\x79\xc2\x53\xe0\xcb\xad\x7d\x47\x55\x30\xeb\xd9\x0d\xcd\xfe\x76\xb8\xbb\xed\xf7\x55\xbe\x32\x52\x76\x6e\x41\x4c\xd7\x5f\x5b\x9e\x98\x04\xbd\x97\x0e\x24\xb4\xb7\x8d\xe8\xd2\xe4\x92\xe4\xaf\xdd\x76\xa2\x43\x40\xca\x04\x09\x46\x35\xea\x25\x89\x35\xc1\x73\x52\x48\xf0\x65\xb4\xdf\x3b\x4e\x44\x42\xeb\x52\x52\x75\xd7\xd8\x59\x56\xb2\x8b\xd8\x4a\xa4\x1f\x81\x2d\xc6\xb8\x72\xf1\x7f\xd0\x81\x03\xb8\x97\xad\x43\x84\x31\x2c\xb4\x98\xe3\x44\x18\x72\xd7\x9a\x47\x12\x41\xee\xd6\xa6\x91\x7c\xa0\xce\x12\x0b\x52\x77\x90\xa0\x06\xbe\x39\xd5\xe1\x83\xdc\x87\xdd\xf7\x64\xf7\x2f\x37\xe6\x4d\x10\x8e\x61\x53\x8d\x85\x95\x85\x65\xa7\x36\xc0\xca\xfb\xc3\xcd\x2b\xae\x36\x88\x72\xe9\x5b\x0b\x6e\x63\x22\x0b\x6b\xf4\x1b\x2d\xf5\x55\xb5\x37\xd6\x73\xa9\x66\x5a\x6c\x36\xd5\x92\x5c\x34\x2d\xc9\xcb\x7a\xc7\xdb\xed\xfa\x77\x35\xd8\xaa\x9e\xc8\xda\xa6\xcc\xc2\x66\xe5\xc2\xce\x8e\x16\x76\x7a\xb8\xb0\xd5\x79\xdf\xa9\xf5\x1c\x1a\x34\xcc\x0e\x16\x60\x0a\x42\x9e\x90\x03\xeb\x6a\x1f\x9d\xb1\x79\x63\xbf\x42\x75\xc9\x4d\xc9\x4c\xed\xb6\xf3\x8e\x9a\xeb\xae\x4d\x95\x41\x26\x11\xe1\xf0\x96\xbc\xc0\xc0\x0a\xa4\x18\xe2\x76\x3b\x36\x17\xe3\xeb\x49\x18\xf8\x01\xf4\x9c\x13\x55\xd6\xf3\xd5\xeb\x3c\x48\xc3\xd6\x94\x2d\xed\x29\x83\x8c\x84\xee\x36\xa7\xaf\xe9\xd2\x99\x49\x0f\xb8\xf2\xf3\x05\x5d\xa7\x0d\xee\x18\xc5\xfe\x24\x25\x4b\x77\xb1\xcd\x32\xca\xc4\x76\xa2\x37\x05\xf5\x4d\x52\x31\x6b\x0e\x16\xeb\x70\x9b\xd3\x67\xcb\x25\x5d\xf0\x26\xbf\x8e\x56\x0c\x6b\xb7\x99\x83\x45\xcd\x82\x4f\xa8\xfa\xb9\xb1\x50\xe2\x88\xc9\xf6\x1b\x99\x6c\xdf\x66\xb2\xfd\xb9\x71\xfd\x27\x15\x3e\x31\xe1\x87\x1e\x54\x21\x21\xdc\x2d\x77\x20\xc8\x09\x77\xf5\xd3\xa8\x3f\x48\xb4\xdb\x56\xbc\x74\x3e\x4d\x58\x90\xc3\x42\x72\x1a\xc6\x75\xb0\x7a\x18\x16\x1d\xd4\x8a\x00\x95\x75\x22\x40\x76\x8d\x68\x8e\x21\x22\x92\x25\x83\x25\x61\xfb\x7d\x2c\xe4\xbf\xf0\x83\x9a\xd5\x1c\x5d\x46\x96\xb7\x14\xa9\xcc\x12\x8c\x9e\x7a\xfe\x8d\xc1\x9a\xf2\x30\x58\xc2\x41\x73\xc1\xb2\xd0\x2f\xaf\xfd\x47\x45\x13\xc7\x83\xef\x25\x81\xc1\xfb\xfd\x16\x6a\x2e\x13\xe4\xd4\x1a\xf6\x94\x33\x0c\x0b\x0c\x71\x85\x46\x42\xa8\xa8\x3e\x2e\x97\xec\xc8\x31\x67\x46\x76\x7a\x48\x72\xa1\x8b\x06\x6b\x6b\x39\x88\xa0\xb6\xda\x83\x14\xd4\x16\xc8\x4b\x91\x64\xcb\x94\xe2\x25\x2f\x31\xef\xcc\x87\xb8\xfc\xc8\x6c\x6d\x6e\xc4\x9c\x4c\xe1\x17\x87\x68\x7e\x1a\x35\xcb\xba\xda\xed\x05\x73\xca\xca\x0e\x9a\xf1\x8a\x72\xe7\xca\x6b\xb9\x4a\x7a\x5b\x3a\x60\x6a\x2d\xcb\xfe\x6e\x24\x83\xbe\x12\x0c\x7a\x7f\x32\xba\xd0\x6e\x4b\xe5\xe7\x78\x68\x2e\xc6\xdf\xb0\x66\x11\xfb\xd8\x39\xd2\x1f\x5e\x0f\xc7\xfe\x89\xcb\x77\x91\xea\xb8\x2f\x16\xc3\x6d\xcc\x57\xf5\x95\xa0\x1c\x4a\x89\x75\xa0\x57\x55\x54\x5b\x10\x35\x5c\x07\x54\x96\x47\xa0\xd6\xca\x5c\xa0\xfd\x02\x36\x44\xac\xed\x6a\x2f\xb4\x8b\x05\xb1\xcd\x13\x2a\xd4\x5f\xec\xf7\x4c\x50\xf6\x4d\x12\xde\x0b\xc4\x6f\x58\x02\x72\x3f\x5f\x91\x50\xc8\x08\xb7\x61\x16\x09\xdc\x3b\x38\x3b\x29\x27\xc8\xa8\x6d\xa5\x0b\x1a\x46\xb3\xd7\x74\x69\x8d\x83\xc2\x0c\xe9\x8c\x08\x90\xc9\xa0\xba\xbe\xa9\x5d\x95\x37\x00\x13\x3c\x72\x0e\x54\x76\x20\x32\x6f\x83\x1c\x79\x22\x5c\xec\xf7\x5b\xdc\x6e\x3b\x49\x6d\x69\xc5\x62\x1b\x76\x56\x22\x6e\x25\x05\x18\xcd\xec\x25\x7a\xe4\xb0\x11\x95\x07\x91\x60\x8e\xb7\xed\xf6\xd9\x4a\xed\x88\xa2\x8c\x0a\x91\x44\x12\xdb\xfa\xd9\x28\xab\x60\x9b\xd1\x65\x90\xef\xf7\xbc\x7c\x14\x6a\x59\xc0\x0a\x63\xcb\xe9\x4b\xe2\x60\x67\x25\x76\xae\x95\x3c\x0c\x69\x9e\x95\x35\x73\xdf\x15\xfa\xa0\xa4\x37\x9e\xf8\x81\x16\x9a\xc8\x17\x3b\xb4\xcd\x69\x4b\x8c\x76\xc1\x91\xd8\xf9\x1d\x0e\xbb\x77\x81\x83\xc9\x17\x59\x61\x30\x3b\x23\xbb\x75\x7a\x15\x27\xf4\x0d\xa7\x9b\x0d\xcd\x02\x9f\xf6\x21\xdf\x50\x1a\x7d\x15\x87\x49\xe0\x7b\x43\x0f\xc2\xcd\xe6\xcb\x30\x0b\x7c\xdf\xf3\x20\xca\xc2\x5b\x91\xab\xe7\x79\xb0\x4e\x23\x91\xa5\xef\x79\x90\xb3\x70\xf1\xe1\x4a\x64\x1a\x78\x1e\xf0\x34\x4d\x78\xbc\x09\xfc\xa1\xe7\x15\x05\xf4\x27\xe3\xc7\x75\x2b\x2d\xca\xc3\x41\xa7\x37\x99\x58\xc2\x72\x6a\x94\x7a\x87\x47\xf8\x14\x2b\x61\x57\x08\xef\xcf\xb2\x2c\xcd\x4a\x44\x18\x63\xcb\xfd\xeb\x62\x15\x66\x4f\xb8\xe3\xe1\xba\x35\x76\x87\xea\x17\x19\x7d\x09\xbe\xe1\x68\x72\xaa\x9f\x95\x80\x5f\x73\xdb\x72\xe4\xaf\x85\x5b\xfe\x5a\xa8\xf1\x60\x49\x95\x8b\x3d\xe9\x5c\xa4\x5c\xf5\xd5\x45\x6d\xfe\xb0\x85\x8f\xbe\x4f\x32\xad\xa9\xb8\x2a\x8d\xdb\x51\x17\x32\xab\x0b\xcc\x28\xdd\x98\xba\x7a\x3f\x4b\xed\x2e\xa4\xf3\xcb\x9a\x57\xa6\x4c\xb0\x38\xb5\x6f\x41\x9c\x6d\x4a\x5c\x60\x5c\x1c\x62\x52\x01\xc3\x9e\x77\xf1\xa8\x09\x8e\xac\x09\x1e\x0f\x46\x3d\xd1\x3b\xe6\x8c\x7b\x17\x03\x0c\xa1\x54\x91\x4c\xc6\x62\xcb\x72\x98\x33\x1c\x5d\x8c\x31\x30\x67\xe4\xf9\x1e\xc6\x90\x88\xd4\xe1\x68\x28\xf6\x30\x41\xa9\xc7\x3e\x96\xcf\xbd\x9e\xa6\x2a\xa5\xb7\x65\xed\x05\x50\x0a\x98\x66\x27\xd8\x9a\xb0\xa2\x5a\xe2\x2b\x4d\xd2\x0c\xa2\x8a\xb1\x58\x4c\x51\xcc\x56\x34\x8b\x39\x0a\x16\xb0\x94\x59\x0c\x43\xb2\xa9\xb2\x2d\xa7\x28\xbf\xb9\x46\xc1\x12\x56\x84\xba\xcb\x94\xf1\x37\xf1\x47\x0a\xeb\x2a\xc7\x6a\x2a\x1d\x04\x6f\xd7\x28\x58\xc1\x0d\xa1\xee\x8a\xaf\x93\xa7\xb2\xb9\x6b\xc1\x48\xc7\x3c\xa1\x4f\x16\x0b\x9a\xe7\x70\x4f\xa8\x7b\x13\xd3\xdb\x2f\xd3\x3b\xb8\xaa\x6a\xb8\x9f\x22\xaf\xe5\xb5\x7a\x83\x56\x6f\x80\x82\x7b\xb8\x15\x54\x29\x2c\x69\xa2\x1e\xa0\x61\x78\x24\x79\x2c\x07\x87\x40\x5d\x71\x90\xbf\x15\xf3\x63\x3a\x8a\x00\x95\xdd\x41\x80\xac\xce\x20\x40\xba\x2b\xa8\x3a\xc4\x49\x0f\xe8\xd9\x06\xea\xef\xea\x4a\x4d\xac\xe3\x41\x2c\x55\x3e\x6e\x96\xa6\x1c\xb6\x50\x02\xf2\x4c\xbe\x43\x98\xe8\x9b\x1a\xa5\xf2\xce\xf1\x20\x17\x05\x22\x8c\xe7\x25\x5f\x26\x32\xaf\xdb\x6d\x03\x3b\xf5\x95\xcc\xaa\x9e\x1f\x96\x5e\x63\x2c\xf6\x82\x74\xb1\x95\x92\x46\x80\x96\x61\x92\x53\x04\x7a\x14\xc1\x15\xc8\x56\x83\x1b\x40\x61\x16\x87\xdd\x55\x1c\x45\x94\xa1\xe0\xec\x7a\xbf\xd7\x9e\xa8\xb2\x34\xa1\xc1\xf5\x14\xc5\xeb\x6b\x14\x98\x38\xba\x0c\x78\x01\xb7\x18\x18\x5c\x4f\x0f\x01\xa0\x20\x86\xd4\x5b\x8a\xd7\xca\x01\xb9\xa4\xe1\x5b\x77\xbd\x8d\x05\x38\x08\x7a\x73\x73\xfd\x7c\x91\x32\xa4\x49\xae\x64\x55\x13\xd1\xe3\x06\x5b\xb7\x9d\x00\x59\xb0\xdb\xe6\x34\x53\x2e\xb9\x03\xc4\x52\x46\x91\xbe\x17\x8b\x7c\xba\x46\xe6\xb6\xac\xfa\xd0\xdb\x6f\x80\xf4\xdd\x52\x75\x8f\x15\xa4\xe5\x3d\xd2\x3c\x90\x9e\xde\x65\x42\xef\xde\x48\x23\xe0\xc0\x03\x03\xc7\x40\x1e\x8d\xa4\xd7\x59\xb8\x59\xdd\xbb\x9b\xbb\x1f\xd2\xd7\x74\xed\xf4\x06\x18\x2c\xd3\x32\x6a\xdd\x37\x30\xc2\xb4\x83\x44\x1b\x08\x76\xe6\x92\xe2\x41\x2e\x13\xed\xe6\xab\x34\xe3\x54\x52\x0a\x39\x03\xdf\x67\xf1\x3a\xcc\xee\x83\x9d\x9a\x0f\xea\x6e\x42\x79\xed\xd4\xdd\xa8\x04\x77\x1d\xc6\x4c\xe7\x7d\x43\x17\x29\x8b\x1a\x73\xe7\x26\xc9\xce\xff\x44\xc2\xf3\x38\x73\x28\xe3\xe5\xcf\x0d\xd5\x79\xe5\x7e\x71\x9c\x55\xba\x24\xb2\xeb\xfc\x4a\xbb\x2b\x3a\x59\xab\xf1\x67\x54\x94\x40\x7d\xae\x10\x3e\xd8\x95\x50\x2e\xd7\x40\x95\xe9\xcd\x3a\x4c\x12\x2b\x4b\xf3\x44\x78\xb8\x2a\xf1\x5d\x98\x5d\xd3\x4f\x95\xe8\x0f\x71\x21\xe8\xb6\x62\xe5\xd1\x8b\x6d\x6c\x10\xb0\xc0\xce\xd6\xda\x54\x23\x9b\x50\x36\x9d\x54\x1d\x2d\xf7\x45\x9d\x7d\x61\x85\x7c\xf4\x0a\x17\x95\xe7\x31\x83\xf4\x0b\x13\x82\xd4\x5d\x0b\x99\xb5\x46\xaa\x99\x64\x57\x2e\x06\xfd\xf1\x23\xf6\x5b\xc3\x5b\x37\xbc\x5c\xfb\x48\xee\xda\x1f\x8d\x9a\x37\xf0\xec\x78\xf7\x4c\xad\xdd\x33\xc3\xda\xae\x23\x93\x06\x1d\xe9\x2c\xb4\x77\xcf\x70\x7e\x59\x3d\x5c\x0a\x89\x2d\xe5\x99\x5d\x35\x86\x14\x17\x97\x8b\x84\x86\xd9\x0f\xf1\x9a\xa6\x5b\xee\x70\x0c\x9c\xe4\x94\x9b\xef\x04\x58\x69\x28\x96\xb9\x32\xab\x5d\xd3\x41\xd9\x02\xb2\x86\xfd\x77\x32\xee\x3f\xc0\x60\x65\xa2\x4d\x5d\x68\x11\x6e\x62\x1e\x26\x02\x77\x64\x69\xf7\x9d\xf6\xf6\xf9\x74\x15\xc6\x8c\x46\xe6\xdd\x16\xc5\x8e\x95\xa9\x1a\x81\x64\x6c\xe8\xbe\x83\x88\x5e\xa5\x5b\xb6\x50\x95\xc4\x32\x62\x93\xd1\x45\xa8\x0d\x9d\x7f\xb8\xdf\xa8\xa4\x04\xe2\xfc\xc5\x36\xd6\xe8\x23\xa3\x72\xf7\x1d\xa4\xb7\x8c\x66\x5f\x69\xeb\x41\x19\xbb\x35\xb1\x3f\xa9\xf7\x66\x44\xdc\xc2\x7d\x07\xda\xfb\x97\xa8\xf4\xeb\x70\xc1\xd3\xec\x5e\xf1\x11\x90\x53\xfe\x9a\x2e\xe5\xc7\xd2\x7d\x07\x5b\x96\x73\xb1\x04\xdf\x6f\x73\xfa\x3c\x92\xd1\xf7\x22\xd2\x36\xbf\x96\xb1\x1b\xd0\x22\x72\x96\x26\x62\x49\x8b\xb8\x95\xa8\x20\xa7\xcf\x6e\x04\xa5\xd4\xc7\xe0\x32\x61\xad\x12\xbe\x4e\xb3\x0f\xa6\xb1\x1b\x15\xf5\x3c\xff\xda\x72\x53\x26\x53\xae\xdc\x77\x16\x77\xa3\x38\x14\xc1\xdd\x08\xae\x52\x73\x37\x3d\xef\x42\x70\x37\xcc\x11\x98\x6f\x2d\xc4\xa4\x59\xa8\xac\x71\x80\xca\xbf\xba\x64\x7e\xc6\xbe\x64\x7e\x98\x33\xea\x8d\x30\x2c\x04\x07\xe5\xf7\xeb\xeb\xfa\x51\x95\x2d\x09\x73\x06\xbd\xfe\xc8\x2a\xba\x31\xf6\x88\x90\xd6\x0b\x28\x03\x17\xe6\xf4\xc6\xe3\x21\x86\xb5\x18\x8d\x7f\xd1\xc3\x70\x23\xc7\xda\x1f\x60\xb8\x36\x9c\x5c\x55\xdb\x7d\x25\x17\x5f\x0b\xd1\xfe\x0d\x17\xdb\x86\x64\x8b\xf9\xcc\x9b\x43\x46\xf8\xcc\x9f\x43\x4a\xe8\x7e\xcf\x0c\x0d\xb9\x3e\xa1\x04\x50\x6c\x30\x6b\xb7\x95\xcf\xb9\xea\x08\xf2\x45\xc8\x57\xae\x74\x91\xe3\xf8\x74\xf8\xb9\xfa\x0c\x59\x94\xae\x1d\x8c\x85\x40\x05\x33\x36\x37\x8e\x9b\xaf\xc4\x98\x27\x17\x23\x5c\x80\x80\xe3\xbf\x2c\x96\x1c\x8c\x30\xad\xcd\x5c\xe6\xc6\xf9\xdb\x30\x89\x23\x43\x2f\x29\x6e\xb7\xe5\x61\xaa\x65\xfa\x24\x8f\xce\x0d\x75\x14\x64\x70\xd4\x1b\x3d\x8e\x0a\x1a\x69\xa6\xdd\xa6\x6e\x6d\x09\xed\xf7\xc6\x14\xb7\x81\x38\x8c\xfd\xfe\xbf\x3c\x4a\x81\x58\x07\xc2\x57\xdd\x86\x8c\x62\x23\x63\xbf\x8d\xe9\xed\x7e\xaf\x2c\x50\x8a\x02\x04\x3e\x3d\x66\x34\xd2\xae\xb2\xe1\xd4\x73\xaa\x1e\xb6\x91\x9e\xd2\x8d\x66\x87\x37\xc9\x1c\x02\x11\xff\x03\xb3\x57\xa9\xb6\x17\x25\x51\x90\xfa\x6d\x3d\x3c\x48\x89\xa3\xce\xa5\xc0\x68\xbf\x33\xa3\x42\xab\x4c\x02\xb0\xe9\xab\x58\xe8\x59\x85\xea\x4c\xea\xdf\x04\xaa\x27\x24\x9c\xf9\x46\xe2\x9b\xa5\x53\x1e\xc4\xaa\x22\x43\x70\xea\xcc\x60\xba\xdf\x27\x0e\xc5\xea\xd6\xc6\xbc\x28\x40\xac\xb6\x47\x0d\x37\x3c\x1c\x2e\xa4\xe4\xf4\x9b\x5f\x53\xd9\x87\xef\xc2\xfb\x74\xcb\xd5\x9a\x0b\xb2\x6a\xfd\x59\x87\xd5\x15\xa4\xca\xe1\x57\x5e\xcd\xea\x1a\x69\x5e\x4e\x1c\x55\x27\x87\xcd\xa3\xac\xee\x48\x9b\xfc\x7a\xd3\xd4\x7c\x77\xf5\x4c\xab\x82\x82\x54\x24\xf4\x07\x7f\x18\x08\x47\xb4\x2e\x3c\x58\xbb\xa7\xb5\xeb\x5a\x04\xa7\xca\xaf\xa8\x90\xc5\xeb\xa6\x56\x0c\xef\x2a\x25\x15\xc3\x50\x69\xde\x98\x52\x6f\x52\xe0\x72\x00\x82\xf2\x3c\x6a\x00\xab\xc6\x01\xf4\x2f\xfa\x43\x81\x61\x67\x1e\x68\xa3\x2a\x65\xc6\x40\x76\x9c\xde\xf1\xe0\xcc\x83\x9c\x86\xd9\x62\x25\x42\xdb\x2c\x11\x3f\x9c\xca\x1f\xba\x0e\x63\x19\xd8\x84\x79\x7e\x9b\x66\x91\x08\x2b\x97\x0e\x22\x24\x4d\xd2\xcf\x3c\x58\xa7\x8c\xcb\xd2\xb7\x94\x7e\x90\xc5\xe3\x35\x35\x19\x4c\x18\x99\x8f\x6e\x92\x2e\xc2\x04\x05\x67\x9e\x75\x6a\xbf\x15\x98\x42\xe5\x53\x3e\x7f\xa7\xf7\xfb\x3d\x75\xc3\x84\xeb\xd0\x82\x67\x89\x0c\x3a\x62\x0c\xd6\x89\xc2\xc2\xc1\xbb\x90\x9c\xf9\xd6\xb1\x93\x83\x77\x48\x4b\x68\xe6\x01\xbd\x1b\xb1\xdb\xc6\x49\xcc\xef\xe5\xea\x6a\xb7\x63\xf9\x0e\x5b\xad\xa6\xa5\xc5\x2e\x8a\x5d\x4c\x08\xd8\x82\x69\xe6\x97\xd6\x7b\x66\xa9\xbb\x0e\xf9\x62\x45\x73\x07\x05\x52\x5e\xec\xde\x68\x7f\xa3\xf6\xcb\x59\xc6\x30\x62\xbf\x77\x18\x71\x38\x49\xb1\x24\xdd\x70\xe6\xa0\xe7\x2f\xbf\xff\xf1\x07\x21\x92\x3a\x19\xe1\x2e\x0f\xaf\x25\x2d\xdf\xef\xcf\xf2\x19\x9b\xef\xf7\xdc\xcd\x68\x18\xbd\x62\xc9\x3d\xde\xef\xd1\x0f\xcf\x7e\xfe\xe1\xc9\xeb\x67\x4f\xa4\xc1\xba\x7e\xc6\x59\xa5\xee\xf7\x67\x67\xdc\x8d\x73\xfd\xb4\xc3\xb3\x28\x96\x4c\x8c\x7d\xd4\xe2\xe0\x5d\x2c\xe6\x5b\x5f\xc3\xaa\xb1\x83\x09\x86\xc4\xdc\xcf\xb2\x38\x4a\x1b\x7f\x05\x9a\x14\x18\x7c\xcf\x86\xd1\xaa\x3a\x36\x8a\xeb\x7c\xcc\x12\x52\xf6\x65\xb2\xcd\xcc\xf7\x46\x4a\xbf\x0f\xd0\x29\xc3\x98\xa7\xee\x32\x66\xd1\x57\xaf\x5e\xbc\x4c\x23\x69\x44\x59\xbe\xb1\xe8\x38\x9c\xb0\xfa\x76\x25\x2d\x56\x25\xb7\xf5\x5d\x9c\x73\xca\x68\x26\x8d\xf5\xa2\xf4\x96\x21\xd8\xca\x37\xdd\x78\x43\x96\x75\xba\xcd\xa9\xca\xb4\x38\x99\x69\x93\x4a\x8f\xf1\x9f\xca\x66\xf9\x03\x79\x20\x57\x85\x70\x0b\x69\x98\x87\x20\x12\x79\x4b\x82\x54\x40\xff\x62\x78\x52\x84\x31\xeb\x77\xd8\xf7\x27\x6a\xfd\x4e\x46\x3d\x7c\xc9\xdd\x77\x5a\xb3\xa3\xad\xa6\x52\x47\xaf\x71\xa9\xf9\xf2\x20\x73\x98\xd3\xf3\xbd\x09\x2e\xf7\x58\xec\x84\x47\x77\x6c\x42\xbe\x12\xa2\x77\x80\x5e\xf8\x17\x2d\xbf\xbf\xea\x8e\x6e\x46\xab\x6e\xef\xa6\x3b\xfa\x66\x78\xd3\xed\xad\x46\x6f\x87\xab\xde\xcd\x68\x35\xba\xe9\x7d\x44\x05\x06\xf4\x24\x8a\x90\x6a\x3d\x2e\xc0\x1f\x8d\xfb\xff\xed\x7e\xf7\xbc\x96\xdf\x4b\xba\xbe\x3b\xf0\xe5\x9f\xef\xfc\x7e\xcb\x1f\xb9\xfe\xf8\xed\x40\x0c\xc4\xef\xb9\xfe\x38\xe9\x0e\xdd\xe1\x44\xfc\xb9\xf8\x6e\x20\xb2\x4f\x5a\x93\xd6\xa4\x3b\xd1\x43\xca\xb2\xf4\xf6\xab\xf4\x96\x09\xb9\xb2\x1a\xdc\xc5\xf0\x62\xf0\xdf\x1e\x9c\xec\xac\x18\x55\x4b\x0d\xcd\x6f\x8d\xdd\x49\xff\x6d\xcf\x5b\xf5\xde\x8a\x50\x22\xc6\xd5\x92\xe3\xd2\x70\x98\x88\x7f\x2d\x7b\x64\x3f\x6e\xea\xe3\x1a\xf7\x2e\x26\xff\x75\x64\xeb\xb5\x7a\x4f\x47\xee\x60\xdc\xea\xb5\x7a\x2d\x1d\xf0\x7b\xf9\x40\x84\x7c\xaf\xfc\xaf\xab\x23\xba\xbe\xf7\xc6\x1f\xbb\xc3\xbe\xcc\xd6\xea\x7d\x5c\x0f\x5b\x7e\x5f\x0c\xdb\x17\x83\x6f\xf9\x63\x11\xed\xf7\x05\xa4\x26\x12\x5c\xe3\xd6\xb8\xa5\xd3\x3c\xf9\xb7\xd7\x1a\xab\x24\xf9\x47\xe5\x57\x29\x32\xd7\x58\x14\x51\x45\x65\x2d\x22\x59\xd7\xa0\x60\xf9\x34\x64\x0b\x9a\x54\x60\x1c\x8d\xfb\xc3\xff\x3a\x18\xbd\xd6\xe8\xbb\x89\xec\xbe\xee\xb9\x04\x44\xd2\x1d\x08\xb4\x18\x48\xf8\x78\x2d\x7f\x92\x8c\xba\x23\x3d\x8a\x15\xbd\xc9\x52\xf6\x5a\xba\xae\x2a\xc7\xd2\x1f\x8d\xfe\x17\x90\x9f\x91\x44\xf1\xb1\x18\xce\xb0\x9a\x1e\x11\xdb\x1a\xb6\x86\x2a\x50\x4e\xe6\xb0\xa5\x72\xaa\xd8\x8b\x6a\xfa\x55\xb4\xaf\xfe\x53\x61\x3d\xa1\x1a\x02\x49\x9a\xd3\x6a\xe8\xbd\xc1\xf0\xe2\xbf\x3f\x76\xb7\x3f\x14\x43\xf3\x06\x4f\xfd\x89\x3b\x1a\xb7\x46\x1a\x31\x47\x83\x96\x20\x01\xad\x41\xeb\xc2\xf5\xfd\xd6\xa0\x35\x72\x47\x2d\x19\x3d\x14\x45\x26\xae\x37\x68\xf5\xdc\xfe\xa0\x35\x71\xfb\xa3\x96\x58\x31\xee\x85\x2f\x7e\x07\x0b\xaf\xd5\x77\xfb\x7e\xab\xe7\x8e\x2e\x5a\x23\xf1\x6f\xe5\xf7\x17\x3d\x77\x2c\xb2\x0d\xbb\x3d\xb7\x37\x68\x0d\xbb\xc3\x96\xd7\xed\xb9\xa3\x41\xb7\xe7\x7a\xc3\xee\xc0\x1d\x4f\xba\x03\x77\x24\x42\x17\xa3\x8f\x2f\xfc\x41\xcb\xef\xdf\x0c\x56\xdd\xc1\x4d\x77\xf0\xcd\x38\x11\xf9\x87\xad\xe1\xaa\xdb\x2f\x41\xb9\x8d\x7e\xdc\x24\x69\x68\x91\x97\xe1\xa0\xdf\xfb\xaf\x03\xd4\x6f\x8d\x57\xbd\x9b\xde\xaa\xdb\xfb\xb8\xf6\x5a\x03\xb9\x85\x89\xb0\xdf\xbd\x10\x64\x67\x62\xc8\xce\xa4\x24\x3b\x93\x43\xb2\x33\xb1\xc8\x4e\xaf\x24\x3b\x62\x35\x2d\x44\xb2\xdf\xf2\xba\x93\xae\x20\x41\x82\xe0\xe6\x2a\xd0\x92\xb4\xb7\x25\x3e\xe4\x06\xa3\x02\x15\x3d\x7e\xce\x96\xe9\x2b\xe5\x60\xd0\x82\xd8\x64\xe8\xf7\xff\x17\x10\xe4\xc9\xc2\x77\x05\xee\xf4\xba\xee\x45\xab\xd7\xed\xe5\x5d\xf7\xa2\xdb\x53\xff\x5a\x22\xd8\x12\x3f\x12\x72\x12\x10\xbd\x45\x57\x16\x28\x53\x73\x93\x5a\x56\x51\xd6\x20\xf2\x8f\xfe\x95\xfc\x12\x5c\x2f\xd2\x8c\xbe\xa5\x99\x4d\xa8\xc6\x63\xef\xbf\x0d\xaa\x51\xcb\xbf\x58\x0d\xde\x0e\xbf\x19\xdd\xf8\x83\x8f\xeb\x49\xd7\x1f\xdc\xf8\x03\x11\xb3\xea\x0e\x54\xc7\xbf\x0f\xb7\x36\x8d\x19\x8d\x86\xff\xf5\x25\x31\x69\x0d\x6f\xfc\x41\xe2\xfb\xdd\xb1\xee\x63\x12\xde\x4b\xfe\xc0\xea\x67\xcf\xff\xaf\x43\xd7\x1f\xbb\x23\x41\xeb\xfb\xc3\xa7\xfe\xc8\xed\xb5\x06\xee\x45\xcb\x1f\xb8\x3d\x5f\x13\x42\xb9\xf8\x7a\x2d\xaf\x3b\x76\x2f\x2e\xc4\x4a\x9b\xa8\x90\x5c\x82\xe3\xd6\xa4\xa5\xbe\x16\x7d\x77\xdc\x6f\x79\xad\x91\x3b\x11\xc4\x6d\x38\x6c\x8d\xdd\x71\xbf\x2b\xa8\x80\xeb\x4d\x16\x5d\x77\xd2\x13\x84\xb3\xdf\xed\x0b\x12\x3a\xe8\x0e\x45\xab\x83\xae\x24\x99\x5e\x77\x24\x88\xe2\x45\x77\xd4\x1d\xe5\x2a\xd0\x1a\x75\x47\x0b\xdf\x1d\x09\xe2\xd9\x77\xfd\x81\x20\xaa\x03\xb7\xd7\x6b\xf9\xee\x78\x22\x39\x4e\x7f\x35\x7e\x3b\x48\xba\x3d\x41\x96\xc5\x1f\x05\xe4\xd7\x74\x99\xd1\x7c\x65\x71\xcc\xe3\xde\x7f\x9f\xd3\x6f\xf5\xfc\x55\xaf\xf7\x9d\x2f\xc9\x5a\xab\xe7\x7f\x5c\xfb\xbd\x6e\x5f\xb2\xfd\x3d\x41\x36\x3f\xae\xbd\xae\x64\x9e\xbb\x82\x72\x6a\x9c\xfe\x29\xcc\xa4\xab\xa0\x6a\xe7\xf4\xbd\x93\x7c\xa4\x36\xec\x57\xea\x22\xeb\x41\x6b\xf4\xfe\x3d\xcd\x5f\xa4\xd1\x36\xa1\x08\xb4\xbd\xfc\x99\x57\x60\x38\x59\xc0\x1c\xe3\xc2\x8e\xb2\xed\x5a\x3d\x49\x17\x9c\x79\x27\x5e\xc9\xcf\xdc\xda\x49\x43\x61\xe9\x3f\x26\xe3\xbe\x8f\x0b\xe8\x4f\x46\x17\xff\xc2\x69\x51\x69\xa2\xca\xb4\x5d\xb9\xb9\xb3\xb3\xc9\xa5\x45\x2a\xdf\xef\xcf\xb8\xfa\xae\x42\x33\x56\xde\x87\xc8\x94\xb9\x3f\x84\xa4\x4a\x93\xf7\x9c\x52\x75\x65\xbb\xba\xea\x33\x4b\xe5\xbb\x05\xd2\xb4\x42\xbe\xbf\x51\x3a\x91\x6f\xb0\x94\x98\xf4\xff\x80\xd6\x72\x20\xb0\xc9\xd2\x5a\xfe\x67\x6e\x38\x59\xf6\xc9\x0a\x48\xa5\x35\xb2\xba\x62\x51\xd9\x5f\x9e\x55\xf7\x29\x8e\xdf\x69\xe2\x8d\x97\x42\xd8\x89\x4b\x21\x4c\xf9\xb2\x48\x95\x5f\x09\xa3\xc2\xe7\x33\x3a\x07\xd4\xaa\x6e\xf9\x30\xe9\x9e\xa2\xc0\x18\xd2\xa2\x80\xe1\xc5\xf0\xe2\x8f\xe9\xfd\xf4\x91\x7b\x4a\xb2\x83\xcb\x3b\xf2\x9c\xde\xd6\x05\xd6\x15\x81\x26\x5b\x8a\x55\xf3\x8f\x53\xa1\xc7\x8d\xe6\x2d\xbe\xe7\xf5\xf0\x81\x2a\xb5\x52\xe5\x5b\xef\x16\x95\x3a\x44\xdc\x6e\x4b\x7d\x74\xce\xb3\xad\x74\x53\x40\xf4\x95\xba\x4a\x87\x13\xdb\x67\xb7\x47\x78\xd0\x6b\xc4\x83\x9e\x8d\x07\xbd\x79\xb0\x5b\x24\x29\x93\xcb\x58\xf4\xd3\x95\x5f\x53\xfb\x3e\x37\x0e\xca\x57\x62\x42\xd9\xab\xd0\xe1\xb8\xdd\xb6\xe7\x99\x37\xcd\x73\x86\x77\xe8\xfd\x7b\xf9\x06\xc9\xfb\xf7\x48\xdf\xf4\x0c\x1d\xe9\x37\xa5\xdd\x56\xd7\x62\xa7\xe9\x2c\x9b\x93\xd8\x51\x77\x62\x95\xa3\xdb\x40\xc6\xc9\x6c\x66\xea\x7b\x93\xc9\xe3\x16\x7d\x75\x1d\x19\xad\x38\xdf\xe4\xc1\xf9\xf9\x3a\xe4\x34\x8b\xc3\xa4\xbb\x8d\xdd\x45\xba\x3e\xaf\x2e\xec\x75\xe5\x19\xff\xf9\x74\x91\x46\x94\xa0\x8e\x20\x12\xfe\x25\xfb\xcb\x21\x1c\x2f\x59\x87\xf8\x98\x77\x08\x6a\x87\xd9\x75\x3e\x9b\x8b\xbc\x4c\x14\xfa\xf1\xf5\xf3\x72\x79\x38\xb6\x4d\x57\xe9\xbf\xee\x45\xcc\xe2\x65\x4c\xa3\xd6\x0b\xd3\x8b\x1f\x9f\xb7\x64\xb3\xad\x3f\xa1\x0e\xed\xa0\xcb\xd6\x4d\x9c\xc7\xbc\x85\x3a\xbc\x83\x5a\xcb\x34\x6b\xf1\x15\x6d\x2d\xb7\x49\xd2\x5a\xd3\x3c\x0f\xaf\xa9\x8b\x1a\x28\xc8\x60\xd0\xf7\x9b\x7d\x76\x5d\x56\xef\x78\xa7\xf8\x78\x83\x0a\x21\x26\xe7\xff\xec\x4e\x9d\x69\xf0\x6b\xd4\x11\x7f\xdd\x5f\xa3\xcf\xf1\x74\x2f\x7e\x3b\xd8\x99\x06\x74\xd6\xe9\xce\xa7\xe2\x63\xfa\xd9\x79\x0c\x09\x91\x47\x69\x0b\x1a\x27\x90\xab\xf0\x32\x49\xd3\x0c\xb6\x04\xcd\xbe\x8c\xaf\x5f\x4a\xf5\xb1\xb2\xba\x9b\xb7\x10\x2c\xc8\xb6\x83\x74\xe4\x26\x8b\xd7\xd2\xf7\x5c\x6b\x15\xe6\xad\x75\x9a\xd1\x16\x5f\x85\xac\xe5\x0f\x5b\x79\xfc\xff\x33\xf7\xe7\xfb\x6d\xe3\x58\x83\x30\x7c\x2b\x12\x26\x61\x01\x26\x48\x93\xb6\x13\x27\x94\x61\x4d\x16\xa7\x3b\xd3\x89\xed\x49\x9c\xae\xa7\x4b\x56\xb9\x61\x12\x92\x58\xa6\x48\x15\x09\x7a\x89\xa9\xb9\x96\xef\x5a\xbe\x2b\x7b\x7f\x38\x00\x17\x2d\x4e\xa5\xdf\x79\xfe\x78\xeb\x57\xb1\x88\x7d\x3b\x38\x38\x38\x38\xcb\x54\xcd\x4c\xc8\x53\xd9\x8b\xe2\x69\x2c\x8b\xa0\x87\x68\xc4\x7c\xe1\x1f\xd0\x09\xf3\x0f\xe8\x82\xbd\xf6\xbc\x43\xff\xf5\xeb\xbd\x17\x07\x87\x07\xde\xeb\xd7\x3e\x9d\xb1\x91\x4f\x7d\x8f\xfa\x9e\x47\x7d\xb1\x4f\x7d\x71\x40\x7d\xf1\x82\xfa\xe2\x25\xf5\xc5\x21\xf5\xc5\x2b\xea\x8b\xd7\xd4\x17\x2a\x93\xf0\x7d\xf5\x67\x4f\xfd\xd9\x1f\xd3\x39\x53\x59\x6e\xd9\x8a\xa2\xde\xb4\x3d\x29\xbc\xaa\x01\x73\x71\xec\x55\x95\x00\xdb\x44\x32\x90\x4e\x87\x21\xfd\xb0\x02\x64\x34\xa5\x39\xf3\x81\xbd\x6c\xe4\x06\x38\x18\x43\xb1\x11\x1a\xe4\x47\xd9\x40\x67\x95\x4c\x8c\x72\xdb\x56\xb1\x34\x65\x93\x46\xd7\x76\x90\x3a\xce\x40\x32\xe4\x21\x5b\x92\x01\xb7\x99\x5c\xc2\xc9\xc2\x78\x9d\xe1\xe0\x15\x28\x36\x84\x33\x9e\xbf\xcb\x22\xf1\x46\x62\xc7\xc9\xc8\xa0\xf5\x36\x67\xe4\x16\x3d\x9a\xd9\x7e\x55\xf9\x5d\x6b\xb1\x2b\x4a\x04\xd0\xc5\x10\x4e\xb1\x50\x2b\x5d\x81\x6c\x7d\x01\x42\xb6\x82\x96\x4c\xba\x5a\xe3\x2a\xae\xaa\x7e\xb2\x6e\x04\x26\x65\x99\x65\xf5\x33\xfd\x56\xcb\x2d\xab\x0f\x6f\x59\x69\x55\xe5\x4d\xce\x61\x3e\xf4\x02\x27\x09\x62\x30\x47\xd3\x67\x4d\x1d\xb1\xae\x20\x3e\xf2\x68\xce\x0a\xc6\x4a\x0a\xba\x88\xbc\x39\x60\x87\x5e\xd0\xcf\x7e\x4f\x41\x1f\x79\xc5\x28\x5c\xaf\x38\x2e\xeb\x78\x35\x2f\x09\xc3\x05\xab\x0d\xc3\x91\x23\x5c\x36\xf3\x44\x86\x45\x50\xd2\x98\x79\x83\xf8\x28\x19\xc4\xda\x64\x5c\x36\x8a\xc7\x7d\xc6\x47\x71\x73\x96\xab\x98\x63\x15\x51\xd7\x5a\xb7\xc3\x58\x39\xf4\x82\xb6\xb9\x76\x16\xef\x5a\xc3\x3c\xea\x30\x3c\x92\x55\x25\x8e\xd3\xaa\x12\x7d\xc6\x0a\x2c\x88\x11\x3b\xd5\x22\xa7\xa5\x8d\xf3\xaa\x42\x6f\x0c\x1e\x40\xc4\xde\xb4\x97\x2d\x86\x75\x25\x43\xd4\xcb\x4a\xd9\xcb\x26\xbd\x9c\xa7\x53\x11\xf4\x50\x80\x7a\x69\x26\x7b\x3c\xed\xc5\xa9\x14\x53\x91\x77\xe2\x3a\x5b\xc9\xbc\xd7\xf4\x10\xb1\x1b\x1f\x4d\x9d\x85\xbf\x5f\x79\xcd\x6c\x3d\xcc\xd7\xef\xea\x58\xb8\x62\x77\x42\x40\x83\x59\xb8\xe1\x48\x8e\x9f\xef\xf5\x99\xd7\x56\x70\xd2\x7d\x10\xc3\xa2\x91\xb1\x19\x76\xe4\x67\x6d\xe4\xa2\x8e\xd4\x6c\x20\x88\x8d\xe5\x91\x37\x44\x02\x05\x48\xd8\x88\xd8\x9d\x43\xea\x66\x05\x3f\x51\x30\xfd\x27\x8f\x3c\xbd\x39\x32\x96\xaa\xca\x06\xb6\x2d\x07\x99\xcd\x52\x32\x10\x2c\xb3\xc5\xb2\xb6\x80\x65\xdb\xf2\x18\xe7\xcd\x06\x23\x4d\x29\x2a\x1d\x96\x0f\x1c\xa7\x29\x66\xb3\x4c\x97\x92\x47\x39\x58\x74\x10\xcd\xee\x90\xab\x1d\x96\x1d\x99\xe0\x25\x67\xab\x06\x12\x9a\x1d\x43\x39\xfd\x4a\xdf\xd1\xdf\xe8\x39\xfd\x42\xcf\xe8\x05\x7b\xd6\xfa\xd3\x62\x8f\x9d\x73\x39\x78\x46\x6b\x1b\xe5\x5a\xc1\x10\xe8\xe2\xb3\x89\x51\x2d\x3c\x05\x51\xa2\x67\xd8\x27\xf4\x8a\xed\x79\xf4\x33\x3b\xa0\x1f\x99\x73\x48\xdf\xb0\x3d\x9f\x7e\x62\x8e\x42\x4b\xdf\x01\x39\xbd\x67\x7d\x9f\x7e\x60\x3e\x7d\xcb\x3c\xfa\x07\x7b\x5c\x68\xf1\x79\x84\x28\x58\x93\x04\x61\xaf\x7d\xda\x48\xbc\xfd\xad\x89\xf4\x4c\x06\xb1\xe0\x39\x68\x68\x20\x8a\x68\x24\xc2\x78\xce\x93\x4e\xa4\x8b\xe8\x24\xd7\xd2\x6a\xdd\xb2\xab\x71\x6d\xf6\xff\xff\xff\x0f\xd1\xa2\x9c\xe8\x2e\x2c\xe9\xaf\x0c\x79\xfe\xde\xfe\xc1\x8b\x97\x87\xaf\x5e\xf3\xeb\x30\x12\x93\xe9\x2c\xfe\xe3\x26\x99\xa7\xd9\xe2\xcf\xbc\x90\xe5\xed\xdd\xfd\xc3\xf7\xce\x91\xfc\xac\x8b\x84\x38\x4d\x68\x49\x23\x3a\xa3\x73\x7a\x4b\xa7\xf0\x98\x07\x1b\x1e\x4f\xbb\x0e\xa9\x9f\x91\xae\xb9\x28\x5d\xc3\xa0\x63\x4f\x1f\x36\xa2\x65\xf5\xc1\x72\x87\x7b\x15\x17\xcd\x19\x44\x1a\xd1\x91\x02\x30\x9c\xa2\x7d\x70\x5f\xb8\x61\x55\x09\x57\x1c\x7f\x1f\x4e\xdd\x90\x4d\x5d\x01\xcf\xa5\x81\x70\xc5\xd1\x27\x88\x1a\xa9\x38\x6f\x1c\x60\xf5\xab\xd0\xa1\x8a\x54\x7b\x47\x43\x0b\x21\xd0\x3e\x9e\xb1\xcd\xdd\x4c\x2c\xcb\xdb\x11\x8c\x79\xd0\x2d\xd5\xb0\xbf\x2b\x8e\xbc\x21\x16\xcc\x11\xd4\xf1\x49\xe0\x53\x75\x8e\xfc\x9f\xff\x63\x8e\x8d\x92\x79\x34\x62\x62\x10\x1d\x33\xdf\x1b\x44\xbb\xcc\xf7\x68\x69\xdb\x0d\x3c\x42\x9f\xcb\xf5\xbe\x42\xcf\x4a\xe8\x97\xa6\x88\x6f\x59\xb3\xf5\x01\xe6\xc1\x78\x57\xac\x0d\x00\x77\xd2\x9a\xa9\xcc\xf0\x94\xde\xd2\x19\x19\xa8\x2e\x1e\xbc\x60\xec\xb6\x7b\xa8\x78\x64\x88\x6f\xd9\x6d\xb3\x9d\x75\xc7\x97\xb8\x64\xb7\xad\xb1\x00\x17\x11\x72\xec\xf8\x96\x05\x59\x1b\xd3\xc1\x2e\x18\x0d\x26\x14\x47\xaa\x02\x78\x77\xc6\xbb\x62\x37\x26\xe4\xd8\x1b\xe2\xf2\xc8\xb3\x2c\x5c\xb2\x88\xd0\xd2\x66\x76\xdd\x44\x64\xfb\x84\x42\x8b\x1d\x13\xba\x11\x21\x41\x9d\xff\xb6\xde\xee\xcd\xe8\xee\xb0\xa4\x7b\xf4\xd7\xfa\x9c\x45\x6f\x79\x21\x10\xa1\xbe\xd7\xf1\xb1\xf0\x27\x9e\x9a\xbd\x26\x08\xbd\xb2\xa7\xae\xb0\x7d\xfa\x19\x56\xaf\x33\x29\x74\xeb\x42\x82\xa9\x99\x1d\xd1\x67\xde\xda\x9c\x19\xf0\xeb\xac\xed\xe6\x54\xd1\x67\xee\xfb\x93\xb7\xdf\xfe\x66\x59\xed\xcc\xec\xfe\xee\x5d\xba\xde\x4e\x75\xe9\xee\xaa\x19\x6a\xd0\xe8\x8b\x95\x33\x23\xb4\xcd\x0a\xf6\xea\x95\xf9\x99\xa5\x81\xf3\x30\x65\xbf\x76\x10\x1c\x2d\x59\xc4\x3c\x3a\x6f\xa6\x6e\x10\x1d\xcd\x07\x91\x3e\x0b\x5b\x47\x71\xdc\x54\xff\x46\xe2\x88\x90\x23\x0d\xb7\xc8\x45\x8c\x71\xf8\x8c\x8e\x4b\xf2\x58\xb2\xb9\xba\x31\xc9\x38\x2d\xc5\xb2\xc1\xc4\xfd\x04\xd6\x9e\xdd\xae\x2a\x4f\x18\x80\x58\x71\x9c\x47\xaa\xca\x64\xec\x44\x36\x19\x3b\x85\x09\x21\x8f\x09\xeb\xab\x3d\xe1\xf8\xb4\x64\x5e\xdb\x6e\x67\x15\x3a\x4b\x47\x25\x59\xce\x14\x96\xc4\x25\xc3\xb7\x2c\xc7\xb7\x54\x2a\x8a\x70\xea\x16\x84\x6c\x00\xeb\x70\x0b\xa8\x06\x2d\x74\x01\xb9\x15\x31\x4f\xd3\x59\x2b\xf3\x1e\x11\x98\x3b\x98\xe8\xce\x9c\x6e\x66\x74\x9c\xb9\x22\xc8\x00\xc4\x1a\xf0\xa6\xb6\x3d\x27\x30\x9f\x73\x87\x45\x74\x66\x59\x0d\x80\xcc\x8f\xfd\x17\xea\x74\x3a\x5e\x74\xa8\x88\x35\x90\x98\xba\xc5\x8e\xd0\x48\xa7\x64\xa5\x13\x39\x3e\x39\xfe\x4e\xba\x18\xa1\x31\x10\x59\x1e\x7d\x22\x1d\x1c\x36\xa8\xb7\x4b\x07\x61\x8c\x69\xc4\x70\x69\xfb\xe4\xf9\x84\xea\xfd\x15\xd9\x6c\x42\x68\x74\x34\xd7\x38\x29\xb2\xac\xa9\x1b\x82\x01\x59\xdc\x6c\x51\xd8\x8f\x74\xee\xb0\x09\x00\x12\xd9\xcc\x11\x51\xa8\x87\x0c\x22\x36\x71\xba\xa3\x27\x35\xb0\x6b\xd0\x89\x1c\x36\x87\x79\x1c\x44\x8e\x33\xb8\xb5\x15\xc1\xab\x10\x51\x53\x1f\x59\xd6\x3b\xa0\x19\x47\x4b\x3c\x7c\x5b\x33\x8d\x48\x39\x8d\x69\x42\x8b\xf6\x48\x48\x87\x29\xfb\x1c\xdc\xe1\x94\x7a\xf4\x15\xa1\x0a\xe1\x37\x26\x69\x3a\xce\x43\x54\x01\xa0\x82\x15\xed\x1a\x03\x9e\xaf\x8f\x94\x82\x3d\x60\x55\x8a\x16\xcc\x67\x2c\xaf\xaa\x3d\x63\x95\xe8\x88\x7d\xac\xaa\xf8\x98\xbd\x21\xc3\x13\x5c\xd0\x98\x04\x37\xea\x87\xc2\x08\xea\x25\xe0\x0c\x0b\xf6\x27\x6e\x10\x0f\xb8\xfc\x77\x05\x05\x7a\x55\x57\x5c\x4f\x08\x5d\xa9\x5e\x1e\x31\x5e\x55\xfc\x88\x7d\x34\x54\xcd\x20\x39\x92\x83\x02\x26\x88\x26\x0a\xfa\x0a\xa6\x9a\xe5\xa4\xd9\x83\xd2\x61\x31\x2d\x98\xea\x05\x87\x5e\x50\x6e\xfb\xc7\x89\x36\xd7\xe2\xc8\x63\x0f\xcc\xcd\xa9\x2a\x5c\x34\x90\x8e\x63\x6a\x23\x83\xa6\x06\x2c\x6d\xc6\x9d\x84\x98\xac\xdc\xf6\x19\x53\x1b\x5b\x97\x21\x2b\x85\x5a\xfb\xc5\x0a\x6c\x32\xf0\x52\x59\x04\x45\xc7\xf0\xee\x9a\x79\x3c\x73\x1b\x32\x53\x31\xf2\xd4\x3d\xb8\xb5\x09\x96\xdb\xb6\xb6\x32\x89\xd3\x26\x4b\x3e\x26\xc4\x2d\xc8\x63\xc6\x52\xe3\xd9\x44\xba\x21\x4f\x12\x9c\x51\xb0\x6a\x9a\xb1\x56\x2e\xba\x63\xd8\xee\xef\xeb\x5e\x78\x75\xc3\xcd\xcd\xaa\x2f\x47\x8e\x93\x8d\x07\xd2\x5d\x64\x0b\x4c\xf4\x3e\xce\x40\xdc\x74\x90\xc1\xd1\x9b\xc1\xd1\x9b\xb7\x47\x2f\x4e\x59\x6e\xa7\x3b\x13\xd8\x6c\x8a\xd6\x55\x20\xa2\x8f\xdf\xf4\xe8\x13\x44\x8c\x84\x21\x14\x20\x85\xaa\x28\x49\x68\xc7\x00\xc6\x9f\xdb\x80\xb5\xa4\x21\x5d\x28\x9a\x07\xae\x60\x53\x36\x03\x64\x41\x1e\x41\x82\x5f\xf5\x4a\x21\xbe\x5b\xd5\xb3\x12\x7a\x56\x42\xcf\x32\xd5\x33\xb5\x5e\x9c\x49\x27\x53\x98\x9a\xdb\x6c\x42\x63\x26\xe9\x9c\xe1\x90\xdd\x8e\x16\xcc\x1b\x93\xdd\xe9\x28\x73\x62\xc7\x1f\x3f\xf7\xbd\xca\x6b\x60\x12\x2f\x58\x82\xd5\xe2\x92\xdd\x09\x21\xc7\xed\x79\xfa\xa8\x6f\x58\x30\xd5\xc6\x62\xd3\xa0\x4e\x3c\x62\x8b\xc1\xad\xde\x94\x1e\x21\x83\x90\xcd\x99\x47\x55\xf7\x62\x86\xf9\x73\x36\x21\xce\xc4\xf6\xf5\x81\xac\xca\x85\x4c\x75\x7b\x31\x56\x59\x36\xbb\x3e\x67\xb8\x53\x4c\x0d\x60\xe8\x05\xe1\x6a\x77\x97\xf1\x04\xe7\x6a\x43\xc8\x23\xaf\xaa\xb4\xac\xd0\xed\x68\x61\xfb\xe3\xaa\xc2\xf1\x91\x37\x0c\x83\xf0\x79\x5d\x82\xd0\x9c\xa5\x47\x07\x43\x3c\x57\xf7\x4e\xcb\xc2\x1e\x63\x69\x55\xa5\x8c\x61\x00\xd0\xe1\x7e\xb0\x47\x48\x30\x3f\x7e\x51\x55\x2f\x40\x4b\x08\x1f\x40\x8e\xbc\xaa\x5e\x6a\x63\x64\xfc\xd8\x1b\xc6\xc7\xde\xd0\x74\x63\x1c\x78\xc1\xed\x68\xa1\xea\x7e\xee\x7b\x96\xdf\xad\xec\x55\x70\x48\x08\x95\x47\x7e\x55\xf5\xd5\xda\xd4\x18\xa5\x9e\x2b\xe6\xd1\x7c\xa8\xb6\xa3\x00\x22\x43\x65\x61\xd3\x11\x9e\x38\xf2\xf9\x84\x3c\x9f\x8c\xa9\x02\x11\x47\x56\x95\x47\x02\x48\x04\xd0\xa1\xc2\x58\xe5\xe0\x43\xdc\xd4\xb4\xa0\x25\xf3\xe9\xc2\x71\x48\xd0\x89\xb4\x15\x54\x4c\x47\x13\x87\x8f\xa9\x9a\x65\xa6\x3a\x5e\xe0\xba\xeb\xcf\xa7\xea\x62\xbb\x53\x06\x1e\xa1\x39\xec\xe4\xc1\xa0\x36\x97\xb7\xd0\xdb\x82\xc3\xca\x01\x60\xc5\xb0\x3a\x31\xac\x0e\xaf\x8f\x35\x9d\x66\xb3\x52\xb5\xbf\x92\x05\x08\x52\xde\x67\x25\xc8\xdf\x0a\xdb\xd6\xe3\x63\x91\x3a\xc2\xd5\x97\x4f\x88\xd9\xad\x0a\x94\x47\x0b\xa8\x45\xfd\xf6\x59\xa4\x61\x6b\xa0\x26\xd6\x19\x83\xf5\x2a\x7f\xa9\xbb\xd3\x9c\xa2\x8a\x74\xbf\x1d\x39\x0e\x1f\x2b\x78\xd3\x1b\x74\xa9\x49\xf4\x95\x7d\x07\x24\xba\x96\x01\xae\xf7\x5e\xeb\xdc\xb8\xdd\x75\xff\xe8\x8a\xa0\x09\xb7\xe1\xe2\x68\xf4\xce\xd2\x61\xf7\x18\x08\xb0\xac\xb1\xbd\x64\x29\x20\xf8\xf4\x98\xbd\x19\x9e\x80\x98\x66\x70\xa3\x7e\x34\x66\xd5\x80\x60\x3c\xf3\x36\xed\x3e\xd3\x0c\x52\x26\xe8\x33\xf7\xcb\xd9\xb7\xd3\xf7\x57\xdf\xce\x99\xd7\x04\xde\x9f\xfd\x7a\xca\xfc\x26\xf8\xee\xe4\xe3\x27\xb6\xd7\x04\x3f\x7c\x3a\x3b\xfb\xc2\xf6\x9b\xf0\xdf\xdf\x7c\xfa\xa0\xca\x1f\xac\xc6\x40\x25\x2f\x56\xe3\x4e\xfe\x79\x72\xca\x5e\xae\xc6\x41\xed\x87\xab\x71\xba\x89\x57\xf4\x99\x7b\xf2\xed\xdd\xa7\x8f\xef\xd9\x6b\xfa\xcc\x0d\xb3\x74\x12\x4f\xd9\x33\xb7\x10\xab\xe6\xee\xcc\xac\xb5\x56\xad\x8d\x7e\xad\xe1\x46\x6f\xe8\xd7\xd6\x8c\x0e\xa4\x99\xbf\x3d\x71\xbf\x00\x07\xec\x41\x0f\xd9\x9a\x62\xd9\xf0\x8c\x2c\x19\x7a\x7f\xf2\xee\xe3\xe7\x37\x9f\xae\xce\x3f\xbd\x79\x77\xf2\x15\xa9\xcd\x7b\x87\x53\x26\x46\x72\x4c\x3d\x7a\xab\xa8\xd7\x2b\x96\xaa\x19\xdf\x2c\x0b\x43\xfb\x78\xfa\xb7\xab\xcf\x67\xef\x4f\xd6\x8b\xbe\x52\x45\x3f\x3f\x55\xf4\xe4\xbf\xce\xcf\x4e\x4f\x4e\x2f\x3e\xbe\xf9\x74\xf5\xe6\x02\xca\x9a\xa2\xc4\xb2\x52\x05\x78\x43\x55\x99\xa2\x07\x9c\x5b\x0a\x44\xb4\x0a\xfa\x4d\xa7\x3e\x32\x48\x7c\xc3\x54\x24\x09\x54\x66\x95\xd3\xa4\x39\xf8\x0d\x4b\x8f\xbc\xa1\x93\x06\x29\x21\x4f\xf4\xfe\xcd\xe9\xdf\x4e\x10\x51\x34\xf8\x5a\xd3\xa4\x6d\xd9\xf1\x3b\x4d\xfb\xba\xfa\x4f\xba\xe9\xef\xd0\xf4\xa0\xbd\x04\xb5\x1d\xe8\xa7\x6b\x6b\x22\x6d\xd4\x0b\x79\x9a\x66\xb2\x77\x2d\x7a\xdf\x45\x9e\xa9\x55\x49\xc9\xe0\x13\x73\xf0\xf7\xb6\xab\xcb\x27\x56\xe9\xdd\x97\x7f\x9d\x5f\x9c\x21\x4d\xb7\xd6\xbd\xed\x33\xd6\xdf\xda\x92\x6a\x46\xe6\xa5\xe8\x65\x79\x0f\x34\x2c\x4d\x63\x60\x69\x16\x60\x68\x8b\x85\xca\x30\x7f\x58\xc8\xac\xaa\xfa\x6b\x1f\x60\x92\x17\x74\x35\xb4\xcb\x7e\xcb\xaa\x13\xb4\x06\xc7\xdb\x07\x29\x0a\xd3\x89\xf7\xac\x9f\xd2\x06\x0e\x75\xb6\x5e\x99\xf2\x5b\x1e\x27\x1c\x84\x77\x07\xef\x59\xaa\xe9\x1d\xf5\xf1\xc4\x68\x3f\x9f\xbd\xff\xf6\xe9\x6c\x2b\x54\xbd\x56\xd3\xfb\xe1\x29\xa8\x3a\x3f\xfb\xf5\xea\xfc\xcb\xc9\xbb\x8f\x5f\x3f\x9e\x9d\x6e\x85\xe5\xb7\x4f\x15\xfd\x70\xf6\xe5\xb3\x02\xc4\xad\x7b\xac\x9e\xf1\x27\xe6\x9a\xa7\x3d\x5d\xc0\xcc\xf3\x1f\x4f\x0f\xed\xcd\xa7\xf3\xbf\xbf\x79\x7b\xd2\x34\xb4\xa6\x2c\x5f\x37\x54\x55\xbb\xbf\xbb\xc3\x67\xd5\xc8\xbe\x74\xdc\xcb\x62\x5c\x61\x97\xb8\x3b\x97\xbe\xf1\x23\x94\x6e\xeb\x49\x9c\xde\xf2\x24\x8e\x4c\x1f\x7e\x65\x69\x6d\x8d\xf3\x71\x75\x8f\x07\x57\x74\x65\xe3\x06\x9f\xe9\xea\x6e\x0c\x46\x1f\xe9\x9b\x31\x85\xfd\x11\x8c\x3e\xd1\xef\x63\xaa\xe1\x2f\x78\x4f\x3b\x4b\x13\x7c\xa0\x2b\xf3\x1d\xbc\xa5\x7a\x12\x83\x3f\x68\x3d\xcc\xe0\xd7\xe5\x92\x3e\x73\x3b\x8c\xa0\x75\x77\xed\x7d\x51\x55\x7d\xaf\xff\x04\xbf\x48\xfb\x49\xea\x9b\x1b\x5a\x1d\xa9\x1f\xeb\x35\x87\x5f\xd1\x6d\x19\xdc\x18\xc0\x82\xd9\x40\x04\x6a\x5a\x47\x7a\x3d\xb4\x92\xe0\x18\x31\xf6\xb8\x6c\xce\x19\x4d\xc3\xe6\x66\x2f\xf9\x8c\x29\x4a\xdf\x81\x5f\x62\x59\xd9\x31\x73\x6e\x2d\x2b\x3b\x62\xea\x2f\x53\x97\xc0\x8c\x34\xc6\x6e\x73\x45\x6e\xd4\x81\xcc\xb2\x7c\x30\xda\x68\xe8\xb7\xa6\x77\x86\x82\x5b\x02\x49\xcf\x70\x06\xf7\x3b\x72\xe4\xab\x7b\x05\x5c\xef\xcc\x81\x07\xb5\x35\x26\x40\x65\xfd\x22\xe1\x0d\x64\x6b\x81\x53\x6a\x2e\x81\xa2\x80\x15\x60\x00\x31\x76\xcc\xa2\xaa\x4a\xe1\x82\x9a\x92\x86\x5e\x54\xbd\xea\x33\x96\x36\xfd\x58\xb6\xfc\x01\x73\xdc\xe6\xb5\x7a\x04\x58\x1e\x32\x9f\xbc\xaa\x56\x27\xa1\x1d\xc8\xda\xc1\xf2\x51\x43\x58\xaf\x59\x25\x7d\xb4\xa8\x15\x9e\xf3\xfb\x78\x5e\xce\x19\x7c\x6d\xb1\x89\xf9\xcf\xf6\x09\x8e\x5e\xb8\x89\xd4\x85\xe2\xb4\x2e\x14\xa7\x7f\x59\x68\xaa\x0b\x69\xac\xc3\x30\x5f\x7f\x82\xda\xa3\x5f\xd9\x8a\x66\xd9\x0e\xb7\xf6\xbc\xd7\x87\xfe\x0b\x7f\xb8\xc5\x48\x27\x5e\xcb\x4b\x96\x5b\x64\x1e\x5e\xed\xbf\x7a\xf5\xd2\x7b\xb5\x83\x7d\xef\x70\xff\xf0\xc0\x7f\xb5\x77\xb0\xaa\xbd\x56\x79\xc4\xc6\x75\xae\xf5\x94\x35\x9b\xc6\xad\xca\x83\xba\x7b\x30\x8f\x1a\x06\x80\xbe\x6f\x9d\x76\x38\xa9\x62\x28\xd8\x55\x70\x87\x85\x42\x5b\x84\x66\x2c\xc1\x62\x77\x42\xe8\x7b\x05\x0a\xdb\xd1\x72\x0d\x3c\xdb\x53\xe1\x06\xfc\x2d\x4e\xe5\xfe\x9e\x71\xff\xb3\xc3\xf6\x08\x19\xc4\x47\xd9\x80\x28\x6a\x74\xdf\xf7\x0e\xf7\x76\xe4\x28\x1e\xdb\x58\x8e\x62\xdb\x1f\x1f\x1f\x1f\xfb\xbe\xba\x9f\xbc\x16\xfe\x8b\x21\x4e\x7f\xb6\xe6\x3d\x45\x9b\x8f\xe2\xb1\x3e\x24\x75\x5d\xf5\x21\x6d\xd8\x0a\xfc\xb9\x2f\xfc\x03\x42\x63\x9b\xed\x91\x41\xcc\xb2\xdd\xbd\x96\x53\xfa\xa3\xc3\xc5\xff\x8b\xc3\x65\x65\x0a\x3a\x35\xa8\xe1\x1e\xb6\xa3\xdd\x7b\xe5\x1f\x1c\x1e\xbc\x3e\x7c\x79\xe8\x7b\x2f\x5f\xbc\xdc\xc1\xfb\xbe\xa5\xba\x4c\x6c\xdf\x7b\xfd\xfa\x85\xef\xbf\xdc\x3b\x3c\x3c\x7c\xb9\xa3\x3b\x6f\x1f\xec\xbd\x3e\x78\xfd\xf2\x70\xef\xb5\x8e\xd9\x1b\xdb\xfe\xcb\xc3\xc3\xc3\x3d\x5f\x87\xf7\xcd\x94\x1d\x8c\x8f\x8e\xfc\x97\x44\x07\x5e\x8c\x8f\x8e\x5e\x11\x5b\x7d\xbe\x1c\xd7\x93\xb8\xa5\x63\x87\xc4\x0d\xb3\xc5\x03\x96\x34\xde\x3a\x3f\x87\x7a\x7e\x0e\xc1\x50\xe8\x7b\x7d\x99\xa8\x87\xf1\x15\x13\x72\xa4\x2a\xb6\x2c\x1c\x8e\x62\xdb\x1e\x33\x53\xd2\x5c\xa9\xc3\x91\xe3\xc4\x63\x2a\x9e\xb3\x09\xcd\x2c\x4b\x80\x2e\xce\x6c\x34\x71\xc4\x98\x86\x6a\x89\x0a\x9c\xed\x72\x05\xfb\x40\xf6\xab\xa8\x41\xa8\x89\x7e\x1a\x3b\x0e\x00\x64\x7c\xe4\x91\x90\x8d\xf2\x86\x81\xa5\xaa\xce\x99\xe3\x9b\x22\x9e\x2a\x52\x2c\x0c\x5f\xca\x27\x34\x77\xd8\xa4\xbe\xc4\xf8\x94\xeb\x2c\x1c\x6e\x30\x1c\x6e\x30\x31\xdc\x9e\x8f\x26\x96\x85\x55\x5e\x27\x6e\xe8\xf7\xc8\x15\x2c\xa7\x91\x1b\xb2\x90\x46\x4b\x42\x9f\xb9\x45\x39\x67\x5b\x4c\xaa\x08\xe6\xd3\x8e\x21\x27\x5a\xf3\x2c\x24\xb0\x35\x44\xeb\xac\x17\xfc\xb7\x2c\x92\xb2\xc0\x72\x24\x6c\xbb\x95\xfc\x49\x97\x34\xdf\x34\xfa\xd5\x79\x43\xe9\xbc\x94\xc8\x96\x73\xd0\x38\xee\x85\x1d\xac\xb5\x06\x3d\x78\xa8\xad\x7d\x06\x1c\x15\x83\xfa\x8a\x17\x37\xae\x06\x1c\x67\x10\x8f\xf8\x78\x87\x49\x33\x33\x70\xb9\xcb\x3b\x1a\xa7\x86\xef\x9b\xd8\x36\xa9\xed\xc1\xc4\x5d\x23\xcc\xf1\x28\x1b\x1f\xa7\xc0\xe2\xd7\x28\x22\x1e\x65\xb6\x3f\xb6\x2c\xac\x3f\x98\x47\xa8\xfe\xb2\x55\xd2\x78\x37\xad\x3c\x15\x31\x7e\xde\x61\xd2\xc4\x6e\x2e\x6e\x45\x5e\x08\xdc\x44\xb5\x02\x21\xd4\xb0\xef\x8c\x11\x4f\x60\x8d\x44\x74\x42\x17\xfa\x51\xa8\x6b\x9b\xd8\x45\x84\x4e\xd9\x15\xbd\x66\x9f\xb5\x5d\xe9\x63\x06\xac\x4b\xf6\x16\x1e\xc7\x72\x96\xaf\x33\x76\xe9\x82\xe1\xb9\x59\xa4\x8c\x10\x77\x91\xdd\xe1\xfa\x88\x73\x6e\x15\x59\x16\xd1\xb9\x1b\x32\x89\x6f\xf0\x03\x5e\xa8\x1b\xe0\xc2\x15\xfa\xae\xa7\xee\xc5\x54\x10\x3a\x77\x05\x9b\x37\xaf\xa6\x84\x86\x2c\x62\x78\xc6\xa4\xe9\x7a\x32\xc4\x05\xfb\x95\x0a\x12\xe0\x82\x09\xfa\x2b\x69\x38\x7b\x0a\x52\x67\x23\xc7\x89\xc6\x83\x59\x7d\xa5\x55\xdb\x69\xd6\xe1\x1d\x14\xed\xfb\x29\xb0\x80\x14\x41\xee\x84\x81\xea\x0a\x9b\xa9\xbe\xb0\x90\x2e\xdc\x82\xc5\x74\xc6\xf0\x82\xa5\x78\x41\xe7\x74\x4a\xaf\x29\x27\xc4\x0d\xe9\x84\x2d\xdc\x9c\x86\x6c\xe1\x0a\x42\x6f\xd9\x6c\x54\xb2\xd0\x9e\xda\xbe\x42\xef\x7c\x77\x8f\x4e\xd8\xa4\xaa\xca\x96\x93\x32\x1b\x95\x2a\x71\xc2\xae\x8f\x0e\x86\xe6\x7a\x77\x5b\x55\x13\xc3\x3b\xb9\xae\xaa\x6b\xc6\xf0\xa2\xc3\x3b\xb9\x3d\x8e\x80\x71\x1f\x69\xde\xc9\x75\x55\x4d\x80\x77\x72\x6d\x59\xbe\x35\x1b\x95\x8e\x3f\xee\x16\xd2\x3c\x92\x12\x78\x24\x7a\x9c\x6c\x32\xbc\xc1\xcd\x30\x7d\x42\x9d\x29\xed\x8c\x9a\x04\xdd\x29\xa8\xb1\xf1\xac\xa6\x4e\x4a\x3a\x01\xe4\xe3\x38\x7c\x60\xdb\x6a\x36\xcb\xf1\x31\x1f\x90\xd9\xa8\x04\x46\x42\x55\x61\xdb\x0e\x41\x08\x64\x5c\x4b\x88\xcd\x0c\x6f\x2f\x62\xb3\x86\xf7\x67\xd6\xc1\x38\xe6\x02\x60\x41\x68\x70\x7b\xc4\xa2\x41\x6e\xb3\xa6\x0b\xb3\xd1\xad\xda\xad\x64\x90\xb3\x1b\x9c\xd3\x70\xa5\xa7\x8d\x2d\x06\xb0\x1c\xbd\x42\x38\xac\x3a\x1f\xe9\xbc\x6b\x6b\xd8\x5e\xd9\xab\xb4\x64\xf2\xf9\x9c\x86\x4c\xee\xce\x2b\x0f\x3a\xd4\xbe\x4b\x93\x41\xe1\x38\x03\x92\x30\x8c\x33\x56\xee\x60\xce\xc4\xa8\x18\x3f\x9f\x13\x1b\xe7\x2c\xdc\xe1\x36\x8e\x21\x46\x15\x25\x3b\x25\x79\x3e\xdf\x99\xdb\x09\x51\xdb\x4e\x65\x81\x68\x3b\xdc\x89\xa9\xca\xc4\xb2\xe7\x8d\xee\x7c\x02\xcf\xdf\xa3\xa4\x99\x25\x41\x56\xd8\x94\x72\x83\x4d\x09\x64\x41\x9f\xe5\x84\xb3\xf4\x38\xd7\xd2\x11\x8d\x7f\xf0\x8c\xf1\x8e\xf1\x28\x75\xe9\x18\x65\xe3\x3e\x93\xa3\x6c\x4c\x1e\x55\xa7\xb3\xf1\xb1\x0a\xe8\x62\x9a\x2f\x54\x0b\xa8\x6c\xf8\x22\x59\xc1\x70\xcc\x03\x19\x18\x22\x46\xe9\xd8\x61\x99\x22\xb2\x47\xe9\xf8\x48\x8e\x52\x55\x99\x47\x55\x88\x65\x3b\xb9\x0d\x19\x64\x2d\x7b\x39\xe8\xd7\x1e\x87\xea\x47\xb5\x81\xe8\x9e\x0f\x64\xf0\x57\xa8\x47\xf3\x64\xf5\x4b\xf4\x03\xbd\xa6\x77\xf4\x9e\x9e\xd0\x9b\xee\x83\x3f\xcb\xdd\x82\xb1\xcc\x2d\x60\x58\xf4\x82\xe5\x6e\x48\x4f\x59\xe6\x86\xfa\xd1\xfa\xc2\xb2\x2e\xa0\x17\xa7\x96\x75\xaa\xa0\x7f\xf5\xd9\x3a\x77\x0b\xcb\xca\xd4\x1f\x7c\x31\xec\x9f\x56\x95\xca\xdc\x67\x2a\x67\x70\x4a\x86\x17\x60\x8c\xfd\x02\x1c\x9b\xf6\x4f\x87\xde\xce\x59\x70\xb6\xeb\x05\xa7\xfc\x54\x83\xed\x1d\xc3\xd7\x06\x97\x9d\xa9\xdd\xaf\xa8\xb8\x33\xc6\x6d\x1c\xb2\xdc\x15\x4e\xe6\x0a\x62\xfb\x34\xa9\x2a\x9c\xb0\x88\x86\x6c\x8a\x73\x10\xeb\x70\xa6\x38\x83\x0f\x7a\xc6\xce\x76\x27\x95\xa7\xd0\xa2\x37\x38\x1d\x2d\xc6\x8c\xe1\x8b\xd1\x62\x5c\x55\x1e\x19\x2c\x0c\x77\x59\xc5\x1f\x37\xd1\x96\x15\x3a\x0e\x3d\x3b\xf2\xc8\x9d\x26\x12\x7c\x42\x67\xac\xef\xb5\x87\xf2\x3b\x76\x51\x43\xf6\x39\x3b\xad\x3f\x17\xcc\xa3\x67\x36\xdb\xa3\x78\xce\x0a\x9c\xec\x62\x35\x4a\xdb\x27\x84\x1c\xab\xc3\xe4\x94\x09\x7c\x4a\xe7\x34\x21\xf4\x82\x09\x7c\xa1\x3f\x3b\xe5\xdb\x5a\x09\xfd\xca\xce\xe9\x09\xc3\xf7\xec\xa2\x79\x88\x3a\x6f\xb1\xec\xc9\xd1\xf9\xe0\x7e\x74\xa2\xc8\x10\x8f\x0c\xbe\xb0\xd3\x7a\x2b\xd1\x2f\xea\xa4\xac\xe1\xfd\x0b\xa1\xbf\xc1\x54\xd3\xd3\x91\x3f\x3e\x66\xc9\xee\x9e\x65\xfd\x66\xdb\x83\x28\x83\x47\x39\xe6\x51\x5c\x32\x89\x4f\xe9\x3d\x3d\xa7\x27\xcd\x43\xe8\x0d\xbb\x57\x85\xce\xfb\xec\xc4\xb2\xf0\x0d\xbb\xd9\x49\x6c\x7c\x0f\x6e\x20\x3c\x42\xf4\xf0\x6e\x76\x7f\x53\xe3\x02\x4c\x35\x3f\x86\xb7\x93\x39\x4b\x1c\x9f\xd0\x07\x86\x6f\x9b\xa1\x36\x4f\x3e\x27\xec\xbe\xee\xbd\xcf\x98\xc4\xb7\xf4\x9e\x3e\xd0\x13\x32\x20\x73\xc7\xa1\x29\xbe\xa5\xe7\x47\x0f\xc3\x2f\xc1\x29\x7d\x50\xd3\xf2\xd0\xb0\x49\x81\x2d\x0b\x9b\xd0\xd3\xec\xec\x92\xcd\x59\xdd\x4c\x33\xf0\x66\x6a\xe2\x09\x7e\x38\x3a\x81\x47\xd6\xce\x4c\xdc\x12\x42\x53\x7c\x4f\x6f\xe9\x89\xaa\xbd\xed\x0c\x55\x17\xb1\x52\x13\x7b\xed\x44\x1c\xf9\x03\x32\xb7\x6d\x28\x72\x7e\x74\x02\xdd\x5a\x2b\xb8\xac\xbb\x04\xec\x61\x95\xf9\x9e\x01\x49\x74\x37\x5a\xa8\x75\x99\x53\x35\x87\x43\xb3\x4a\x17\xa3\xaf\x6a\xf2\x02\x7c\xcf\x46\xea\x7b\x4c\x4f\x98\x4f\x96\x77\xb3\x38\x11\x18\x7f\xb5\xed\xa3\x77\xf5\x79\xa5\x8a\x11\xcb\x3a\x53\x44\xe1\x8c\xb5\x71\xf4\x0e\x76\xc9\x5d\x77\x87\x2f\xc1\xf5\x0e\x8b\x34\x2e\x59\x30\x9f\x9e\x31\x95\x6d\x70\x06\x44\xe0\x19\x10\x81\x00\xe4\x7f\xe2\x6b\xca\x6d\x7c\xed\x0a\xb6\xb0\x43\x78\xde\xb1\x7d\x1a\x53\x23\x5a\xd0\xbb\x86\x63\xf7\xda\xcd\x99\x3d\xab\xf1\xe7\x35\x20\xfd\x77\x6c\xf7\x77\xec\x0c\x89\x87\x47\xf7\xd7\xd9\x98\xe0\x21\xbb\xbc\x1b\x5d\xde\xb9\xe3\x9d\x67\x64\x37\xa6\xbf\xa9\xf4\xd1\xef\xee\xd8\x26\x97\xee\xb3\x5d\x7a\xce\x76\x7f\xbf\x74\x4d\xcc\xb3\x5d\xfa\x45\xcb\x59\x7e\x4c\x27\x71\x1a\xcb\x87\x4a\xed\xed\x67\xbb\xf4\x4c\x65\x2b\x76\x2e\x6d\x3c\x64\x50\x1b\xa9\x7e\xbf\x2c\xec\xea\xb2\xb0\x9f\xed\x4e\x69\xc6\x9e\xf0\x09\x47\x39\x4b\x87\x32\x90\x0d\xd9\x73\x06\x3e\x36\xe3\x09\xfe\xa2\x19\x36\x9c\x10\xa1\xa8\x07\xf0\x64\xc8\x89\x36\x4e\xc0\x15\x91\xe1\x07\x7e\x73\xda\xf6\xe1\x21\x04\xac\x25\xeb\x6a\xde\x51\xbc\xdd\xdf\x78\x2f\x63\xe8\x1e\x81\x8f\xc1\x74\xed\x79\x7f\xe8\xbf\x0c\xd0\x35\x62\x2c\x1d\xee\x05\xaf\x68\x6e\x59\x79\x9f\x65\x43\x11\x48\x30\xf5\x00\xef\x76\x39\xed\xb6\xf2\x1b\x45\xcf\x7c\x44\x9a\xf0\x39\x45\x9e\xab\x62\xc0\xe6\x3d\x5f\x43\x9e\x9c\x66\x30\xb2\x9a\x27\xb3\xc6\x23\x38\xcd\x64\x8f\x23\x1b\xe7\x43\xd4\xbb\xe6\x85\xe8\x21\x3b\x0f\x10\x22\x36\x6a\x85\xe3\x6c\x49\xd4\xa1\x00\x70\xb4\xec\xbe\x2a\x2c\xe9\x85\xcb\xaf\x8b\x2c\x29\xa5\x76\xb1\xc2\x20\xbc\x49\xa8\x1b\x72\x7f\x16\x17\xeb\x2f\xa1\x58\x55\xec\xab\x23\x95\x5e\x80\x39\x40\x9e\x8b\xe8\x22\xdb\x6e\x1c\xf6\x5a\x1b\x51\x6c\x85\x99\x88\x2a\x65\x64\xb3\xce\xd5\x64\x14\xec\xc2\x8d\x16\x6c\x8b\xdd\x42\x7d\x8f\x6f\x24\xa5\x6a\x16\xbd\xa9\xb9\xb9\xbb\xd7\xe6\x28\x24\xbc\x83\x4b\xfd\x0e\x5e\xbf\x48\x73\x42\x85\xcd\xe1\x95\x4a\x4b\xb2\xf4\x31\x38\xb1\x20\xeb\x52\x9e\x39\xd0\x21\x69\x23\x31\xa8\xce\x12\x30\xb8\xa0\x8e\x13\xb2\x33\xa1\x19\x4b\xd5\x91\x0f\x28\x23\x7b\xee\x7b\x8c\x35\xcf\xa8\x6a\xcf\xd6\x14\x13\xcc\x50\xae\x2e\x0b\x39\x8c\x34\xbe\x8d\x23\x11\xbd\x7d\x60\xf0\xbd\x7d\x92\xd2\xf5\x49\xa2\x57\xf4\x33\xe9\x14\xbf\xc8\x3e\x6a\x99\x48\xa8\x27\xfe\x0f\x2a\x02\x74\x41\x2f\x5c\x71\xaf\xe5\xb4\x63\x2e\x4d\x6f\x16\xd9\xdd\xd3\x93\x4e\x63\xb8\x9b\x2c\xe8\xac\x99\x7e\x2c\x1a\xe9\x22\xe2\x86\x96\xd5\x17\x6e\x5c\x98\x6e\xe1\x75\x6e\x29\x3a\x31\xed\x6d\xca\x74\xda\xff\x50\x35\xb4\x0b\xaa\x5d\xd5\x1a\x70\x03\xa5\x20\xe1\x8a\x63\xff\x80\xf6\x67\x6e\xa8\x68\x6b\x90\x59\x00\x0e\x9a\xfe\x04\x3b\xb3\x02\x38\x83\xb3\xe6\xb2\x52\x55\x5a\xd4\xad\xaf\x45\x1c\xea\xd5\x5d\x98\x8a\x81\x6f\xa4\xae\x44\xf6\x3f\xf0\x8c\xd0\x78\xb8\xe7\xdc\x63\x41\x02\xdd\x19\x42\xe5\x70\xe1\xce\xb3\x08\x4b\x12\x2c\x54\xd7\xd4\x86\x29\x8e\x3c\xe3\xf3\x47\xba\xe1\xb0\x2f\xa1\xe2\xa0\x2f\xdd\x62\x75\xbb\x02\xd5\x82\x73\xd6\x0f\x2d\x6b\xd6\x9d\x13\xcb\x92\x2b\x53\x04\xa6\x74\x67\xa6\x9d\x56\xb6\x4b\x0d\xf7\x35\x98\xcc\x05\xc1\xeb\x99\x2b\x8e\x1c\xbf\xaa\xd4\x2d\x65\xe6\x8a\xa1\x1e\xf4\xb1\x5f\x55\xb1\xaa\x3f\x84\x23\x7d\xef\x40\x1c\x06\x3a\xe5\xe8\x95\xf0\xf7\x9b\x44\x6f\x7c\xc4\x5e\xab\xff\x0e\x5f\x88\xc3\x56\x02\x8e\xb3\x99\xde\xbc\x6a\xd4\x43\xc7\x0b\x3c\xaa\x9a\x83\xdb\x2e\x67\xfe\x2e\x27\x06\x68\xc2\xa1\xbf\xcb\x03\x4e\x06\x6f\x21\x25\xc1\x6f\x77\x27\xf6\x1e\x21\xf0\x88\x19\x0f\x1b\xd9\x05\xf7\x05\x98\xe8\xaf\x71\x41\xc4\x54\xc5\x24\x88\x18\xce\x34\x8b\x90\x5f\x17\xd8\xcc\xee\xf3\x3d\xba\x68\x59\x70\xfa\xa1\x36\x32\xb2\x10\x0b\xb6\x70\x65\x3c\x17\x85\xba\xcb\xb8\xa1\x79\x3e\xe5\xc3\x45\xb3\xb2\xc7\xdc\xb2\x70\x1b\x64\x9c\x04\x0a\xc5\xaa\x82\xf5\x4c\xc6\x13\x9c\x35\x3c\x63\x9c\x01\xd3\x65\x8f\x18\xbe\xed\x20\x62\xd9\xf3\xbd\x86\x4f\xfb\x27\x5c\x41\x74\x93\xf0\x50\xa1\x50\x83\x0f\x1f\xc7\xfe\x01\xd1\x03\x69\xce\x0b\x0f\xea\x33\xe3\xe8\x56\xa7\x16\xb2\xee\x37\xe5\x6a\x91\x60\xfe\xbb\x7d\x9e\x6d\xf4\xb9\xbb\xfa\x8d\x00\xf8\x22\xc0\x21\x8c\xe7\x54\xed\x76\xbc\x58\x85\x46\x3e\xfc\x13\x2f\xe8\x5b\xfa\x99\x6a\x5d\x16\x12\x2c\x60\x3f\x9b\xfd\xa4\x51\xf8\xa6\x05\xee\x2d\xd8\xbb\xe5\x7b\x7e\x36\x7c\x4f\x40\x93\x92\x4a\x98\x02\xa1\xab\x2d\x4e\xfe\x2c\x79\x72\x91\xb1\x0b\x57\xfc\xb9\x1d\xc9\xa8\x49\xde\x8e\xd6\xe3\xe2\x83\x3a\xec\xc5\x26\xa3\xb9\xdf\x07\x5c\x1a\xea\x5c\x7f\x03\x2d\xa4\xfc\x62\xc6\x53\x76\xe1\x4e\xe5\xcf\x1e\x1d\xc7\xde\x46\xf9\xb3\xbc\xed\xf0\xb4\xdb\x72\xb7\x26\x5f\x81\x85\xdc\xd2\x69\x52\x55\xe0\x60\x4f\x57\x6b\x76\xea\xd3\xbd\xb7\xac\xce\x99\x70\xac\xe3\xea\x03\x63\x4f\xd7\xf1\x49\x14\x85\x19\x57\xf2\xd3\xe3\x3a\xf2\x56\x0b\x77\x07\x95\x3c\x31\x28\xe7\x27\x07\x75\xca\x4f\xb7\x0c\x08\xfa\x5e\x98\x1c\x62\xca\x65\x7c\xbb\x65\xd5\x7a\x3a\x5b\xdd\xbd\xf3\xac\x88\x7f\x98\xb1\x5e\x9f\xdf\x44\x9e\xfd\x68\x16\x3d\x63\xcb\x48\xa1\x2b\x55\x62\x1e\xa7\x65\xf1\xa3\xc3\xa8\xb6\x2e\x19\xbb\x70\x14\x49\xd6\x1e\x46\x6a\xc4\x6e\x41\xfb\x49\x55\xf5\xe5\x16\xc4\xac\x48\xe5\x7e\x2b\x24\xab\xf0\x95\x23\x69\xac\x59\x96\x42\xab\xaa\x15\x2c\x56\x4b\x0a\x06\x91\xd5\x6f\xc8\x62\x37\xa4\x0b\x26\xcc\x6d\xb7\xa8\xaa\x7e\xa9\x11\x96\x3a\x62\x16\x75\x65\xe1\x10\x9b\xfa\x04\x09\x74\x9b\x8b\x61\x1c\xd4\xed\xf6\xf5\xc1\xd5\x5f\x74\x0f\x24\x75\x3b\xd8\x28\xa5\x32\x0e\xe3\x60\x9f\xb1\xcf\x80\x9c\xb5\x2b\x17\x36\xc5\x05\xa1\x25\x9b\xe2\x92\xd0\x90\x35\x12\xd9\x34\x61\x85\x53\x6a\xe2\x5f\xe1\xe8\x23\x8f\x0c\x71\xc2\x9c\x84\x66\x2c\x24\x01\x2e\x59\x41\x33\xb6\x20\x34\x6b\xb9\x91\x54\xb2\x04\xa4\xdb\xb2\x56\xc4\xa9\x93\xbc\x6c\xd8\x1d\x39\xc3\x9c\xe1\x84\x85\xad\xaa\x89\x64\x8b\x46\xff\x60\x98\x04\x92\x26\xcc\x3c\xa1\xd5\x6f\x67\xe1\x48\x8e\xfb\x6c\x31\x92\xc0\x12\x51\xa1\x23\x15\x68\xa5\x64\xc0\x8f\x33\x0b\x69\xc8\x16\x74\xc1\x32\x0a\x13\x20\xdc\x82\x50\xb5\x98\x79\xdb\x80\x83\xd3\xb6\xe9\x5a\x4c\x0f\x3a\x1e\x8e\x52\x73\xf1\xd5\x6f\x10\x91\xe3\x0f\xf2\xe3\x44\x1f\x27\xe1\xc8\x71\x72\xd5\x68\x3e\xd6\xf3\x92\xb2\x7c\x90\x5a\x56\x5f\x25\xa4\x63\x55\x78\xcc\x24\x19\x38\x8e\xfa\xa2\xe1\x28\x1f\xdb\x2c\x5a\xaa\x5f\x87\xa9\x52\x70\xbe\x0d\xbc\xad\xfc\x76\xc7\x29\x1b\x2c\x0a\x2b\xf5\x77\x2c\x68\x48\x4b\x12\xc0\x42\xea\x55\xf3\x03\x9f\x76\x24\x75\x0c\x3e\x9d\x67\x51\x99\xa8\x6d\x3c\xcf\xa2\x2d\x00\xde\x21\x70\x6b\xf8\xec\xc0\x35\xed\x73\x43\xd2\x14\x60\x38\x0c\x68\x2e\xe8\x40\x0b\xdf\x81\x26\x7b\x38\xa4\xf2\x6e\x2a\x27\x01\x7e\xcd\xd8\x87\x21\xc8\x7d\x16\x30\xe5\x3e\xcd\x59\x8a\x39\x55\xd8\x7f\x1f\x64\x7c\x58\x46\x73\xb7\xd8\x61\x19\x09\xda\xa4\x0f\x84\x62\xc1\xb8\xde\x97\x38\x37\x07\x9d\x3a\x02\x6b\x5a\xac\xcf\x3e\x54\x15\x8c\x9e\xab\x45\x34\x83\x2d\x13\x19\x2f\x92\xd8\x10\x98\x50\xea\x87\x24\x26\x38\xa7\x35\xbc\xa8\x86\x13\xa5\xf7\xba\xba\x71\x87\xf4\x66\x7d\xa3\x1b\xee\xd3\x89\x65\xdd\x58\xd6\x09\x10\x83\x37\x1d\xee\x53\xff\x5e\x4d\x95\x9e\xb0\x13\xcb\xea\xeb\x1c\xfd\x9b\xaa\xba\x51\x3f\x3a\x74\xd2\x88\x59\xd5\x37\x24\x58\xc7\x1d\x76\xef\x16\x54\xd5\x3c\xd4\x22\x57\x9e\x16\x63\xf3\x48\xd0\xbd\x40\x11\xaa\xe5\x06\x73\x36\xc5\xf7\x70\x10\xd8\xb5\x52\x11\x6d\x6a\xc1\x05\x3b\x69\xf7\xcf\x82\xdd\xd4\x01\xcb\xc2\x0f\xec\x84\x9e\xb0\x1b\x7a\xc3\x1e\x68\xc6\x0a\x5a\xe8\x2d\x41\x54\xc0\x5e\xd0\x07\x36\x1a\x0f\x32\xc7\x19\x3c\xb4\x1b\x55\xb5\x77\xcd\x22\x7a\xc7\xe6\x6a\x63\x0f\x1c\x27\x3b\x66\xde\xa0\x86\x74\x8f\xce\xd8\xcd\x28\x1b\x3f\xbf\xa3\xb7\xf0\xb1\x7b\x57\x79\x94\xb3\xcc\xc6\x31\x2b\xc8\x80\x1f\x67\x03\x92\x32\x8c\x4b\x36\xdb\xc1\x25\x3b\x81\x47\xab\xe7\x77\xc4\xc6\x09\xbb\xdd\x29\x6d\x1c\xb2\x93\x51\x0c\xc5\xc8\xce\x8c\x3c\xbf\xdb\xb9\xb3\x1f\x46\x7c\x6c\xa7\x64\xf7\x1a\xd8\xad\x09\xa4\xd9\xb7\x3b\x21\x7d\x18\x71\xc7\x19\xb3\xf2\xf9\xf5\x40\xe5\x61\xe9\xb2\xd1\x82\xb3\xed\x3c\x78\x58\xd9\x3a\x6a\xa7\x3c\xd0\x1c\xc0\x23\x55\xe7\x8c\x88\x7e\xf6\xaa\x09\xf8\x41\x73\x47\xf4\x55\x53\x61\xec\xed\xe0\xa4\x41\x26\x63\xf9\xd3\xc7\x43\xf6\xf4\xf1\x90\x6d\x1e\x0f\xb9\x01\x7d\x51\x3b\x75\x04\xf6\xa2\xbe\x9a\xec\x4e\x68\x02\xdc\xd0\xa2\x39\x1f\x78\x55\xf5\xb5\x33\x66\x38\x86\xd6\xee\x07\xd9\xae\x7e\xf1\xe8\x27\xfa\x38\x28\xba\x8f\x22\x6a\xbf\x0a\x73\x0a\xa8\xf4\x61\x1e\x78\x3b\x19\xe0\x7f\xce\xa6\xea\xfa\x1a\xb3\x29\x8e\x15\xce\x4f\x1a\xfc\x9f\x31\xee\xc4\x46\x15\xec\xd8\x1b\xe2\x98\x71\x9a\xb2\x82\x04\x38\x63\x4e\x46\x53\x96\x10\x9a\xb6\xc8\x1d\xc0\x29\x6d\xc1\xa9\x93\x04\x68\x0f\x67\x2c\x69\xf1\xaf\x64\x45\x03\xba\xea\x2e\x9b\x02\x8c\x26\x34\x61\x29\x95\x1a\x4e\xbd\x81\x1c\x90\x8c\xe1\x64\xe4\x38\x72\xcc\x92\x91\x1c\xdb\x85\xfa\x93\x91\xdd\xa8\xf2\xa8\x8a\x60\x11\x63\x90\x32\xf4\x02\xf5\xf3\x3c\x6a\x0c\x65\x82\x9b\x91\x51\x36\x6e\xdd\x56\x52\xdb\x8e\x35\xb0\x24\x34\x06\x60\x59\xe4\x22\x8c\x8b\x38\x53\x84\x54\x11\xfd\x3c\x77\xc0\xb2\x04\x08\x6d\xad\xb0\x09\xfc\x9f\x62\x13\xfc\x35\x83\x60\x85\x3f\xb0\x33\xb1\xfd\x9a\x29\xf0\xf8\x14\x57\xc0\x68\xeb\x6d\x15\xbc\x5e\xb6\xfa\xef\xc0\xa0\x38\xce\x81\x73\x00\xdf\x86\x7b\x50\xcc\xe2\x89\xbe\xaf\x6f\x1a\xc9\x87\x91\x39\x1b\x4a\xc2\x0b\x42\x81\xb6\xd2\x38\x1b\xf9\x42\xcb\x8f\x5c\xb8\xc5\x9f\x25\xcf\xc5\x97\x2c\x93\x6a\x4a\xff\xcc\xe5\xc6\x46\xa4\x72\x93\xde\x52\x60\x1e\xbb\x05\x2d\x15\x89\x44\x43\x76\x65\x1f\x34\xf2\x14\xc8\x73\x5f\x68\x1e\x1c\xb8\x69\xaf\x2a\x80\xfe\xa4\x03\xde\x3a\x9f\xa2\x9f\x34\xe7\x48\x65\x80\xf4\xe1\x29\x3f\x0d\x92\x61\x1c\xf8\x66\x73\xa8\x8b\x96\xd1\xaf\x56\x7d\x53\x57\xc7\x18\x48\xd9\x82\x31\x7f\xd7\x1b\x62\x0c\x92\xab\x2d\x67\xd9\x2e\xc9\xf3\x3d\x06\xaf\xa2\x52\x0b\xec\xd3\x95\xf2\x52\x53\x4e\xa0\xfa\xb1\xbb\x47\x1c\x0c\x6f\x83\xe5\xf3\x3d\x62\x7c\x83\x3c\x53\x90\xae\x2b\x47\x2f\x04\xb2\xcb\x00\x40\x5f\x66\x27\x0d\xab\x24\xc1\x0a\x79\xd4\x4a\x46\xed\xeb\xac\x40\xc4\xf6\x89\x5d\x12\x38\x34\xa1\xae\xc2\x46\x08\x1c\x44\xaa\xd1\xc1\xa6\x2a\x18\x2e\x15\xde\x20\x76\x48\x8e\xf6\x2d\x0b\x17\x8a\x76\x19\x10\xd8\xd9\x39\xcd\x59\x64\xd6\x88\x6b\x5a\x34\xc5\x31\xe5\x34\xa4\x3e\x21\x84\x3e\x60\x05\x82\x4d\xdb\x05\xd1\xc4\xfe\x03\xce\x41\x9f\xa2\x8d\x07\xac\x93\xbb\xe2\xa8\xb4\x2c\xc7\x29\x28\x52\x77\x7f\xd4\x57\x99\xa5\xc9\x56\x38\xfb\xb4\xb0\x7d\xe0\x3f\x64\x55\x85\x0e\x74\x0e\x49\xc8\xa3\x2d\x2d\x0b\xdb\xb2\xd1\xaf\xaa\x2a\xf4\x42\x25\x75\x9e\x02\xab\x0a\xff\x89\x73\x9a\xbb\xc2\xbe\xb2\xf7\xe0\xa6\xcc\xfa\x35\x49\x90\x13\x57\xfc\xa9\x16\xaa\xa5\xf4\xfa\x6a\x7b\xff\x89\x39\xe5\xa6\x84\x47\x28\xaf\x47\x5a\x67\x27\x8f\x39\xe3\xa6\x4c\x68\xb3\x03\x5a\xa8\x3f\x19\xf3\x1b\xf7\xe8\x4d\x93\x3e\xfd\x6c\xc8\x8b\x95\x95\x61\x4f\x7a\x89\x01\x24\x80\x1b\xee\xa0\xb0\x6d\x42\xbf\xe9\x4b\x92\x82\x70\xdf\xd4\xf5\x21\xbe\x17\xd1\xcf\xd7\xc2\x84\xad\x6f\x7e\x6a\x6f\xb6\xd5\xd5\x95\x65\xf9\x9c\x4b\xb6\xd5\x22\x01\xcd\x56\x70\x14\x63\x29\x69\x1a\x90\x5d\xd3\x17\x46\x4a\x54\x0e\x71\xca\x24\x95\x9a\xda\x08\xc4\x96\x2c\x42\x65\x11\x54\xb0\x3a\x53\xca\xfe\x68\x94\x1f\x36\xa4\x97\xd7\xe5\x57\x1b\x15\xed\xad\x92\x95\x80\xe9\xb2\x7a\x82\x34\x1d\x9a\xb9\xa1\x71\x54\x48\xc1\xfd\xe0\x22\x89\xa5\x96\x51\x48\x98\x9d\xba\x8d\x76\x2e\x2d\x54\x70\x53\x41\x97\x86\xac\xce\x55\xab\xd7\x56\x15\x42\x34\x62\xb1\xa2\xb2\x26\x2c\x1e\xf9\x63\x45\x04\x01\xcf\x6d\xc6\x16\xc3\xa8\x55\xae\x8e\xe8\xbc\x7d\xdd\x56\xd7\x22\xcd\x98\x52\x97\x20\x5a\x30\x4e\xe7\x0e\xe3\x84\x26\xc7\x9e\x65\xcd\x8f\xbd\x5a\x32\x64\xfe\x5c\xa1\x1a\x1a\xb1\x59\xed\xa1\xdc\xa3\x9c\x0c\xf8\xd1\x7c\xc0\x6d\x96\x90\xc8\x66\xa1\xdd\xa4\x71\x9a\x90\x41\x71\x6c\xb4\xc3\x20\x01\x9a\xe7\x84\xd0\x05\xc8\x5d\x20\x07\xd9\x11\x59\xe6\x6c\x32\x8c\x6c\x9c\xba\xeb\xda\xc5\x6a\x3c\xc4\x56\xbb\xde\x4e\xdd\x0d\x2d\x63\x32\x9c\x34\xbc\x7f\x85\x2f\xbe\x88\xe9\xc9\xfd\x02\xa3\xcb\xcb\xe8\x11\xd9\x85\x8d\x96\x97\x97\x6f\x11\x45\x53\x44\x28\x7a\x66\x21\xd5\xc2\x76\xb5\x64\x68\x87\x04\x13\x12\x44\xcb\x5a\x73\xc7\xd5\x8a\xd2\xba\x0b\xb9\x2a\xab\xd5\x96\x21\xc2\x00\xa8\xa9\x6c\x8b\xf8\x7b\x97\x18\xd7\x3c\xdf\x56\x41\x99\x5e\xb3\xa9\xa6\x71\xda\x3d\xd1\xc7\x45\x87\x11\xbc\xc2\xee\xc4\x85\xba\x8b\xc0\x61\xe0\x16\x0a\x77\xbb\x89\xc4\xa7\x84\x3c\x09\x80\xc8\xc6\x45\xb7\x8a\x21\xda\x30\x0a\xb0\xc1\x3f\x26\xf6\x3f\x70\x61\xe4\x4b\xae\x57\x0f\x9a\x69\x7d\x37\xac\x99\x8d\x34\x62\x79\x1b\xc8\x58\xd8\x06\x6e\xd9\x03\xbe\x26\xe0\x77\x51\x34\x8f\x8e\xce\xd4\x15\x8e\x4f\x35\xab\x97\xcd\x46\x38\x61\xf1\xf3\x09\x39\xf2\x86\x13\x3b\x09\x92\xb1\xc2\x7d\x42\x8d\xab\x7d\xf6\xc0\x92\x18\xbd\x1a\x19\x44\x81\x3a\x34\xbf\xd3\xef\xea\x54\xa1\xf5\x34\xdd\x12\x1a\xea\x0a\xbd\xc1\x82\xa5\xb8\xa0\x12\xd8\xf2\xd4\xef\xab\xbb\x76\xae\xd1\x7f\xcd\x06\xcd\xe0\x96\xd5\x56\x2f\xc8\x80\xe4\x20\x1c\xc0\x69\xc4\xc2\xd5\xcc\x9c\x81\xa3\x58\xc6\xa9\x3a\xba\x34\xcd\xda\xa6\x49\x02\xce\x0e\x1b\x73\x19\x2c\xc5\xa2\xbe\xd3\x11\x9a\xe9\x4e\x84\x75\x9d\x35\x92\x56\x35\xe6\x75\xaf\x78\xdb\x2b\x1a\xba\x05\x8b\xdc\x82\x4d\xdd\x02\x7c\x1f\x44\x34\xa3\xf1\x0e\xdb\xa3\x9f\x89\xa9\x75\x4a\x80\xed\xbb\xd2\xff\x14\x87\x34\xa7\xf1\x66\x26\x72\xe4\x0f\x47\x11\xcd\xc6\xc1\x28\xa4\xf9\x98\x7e\x67\x09\x9d\x6b\x68\x5d\x97\x63\xae\x31\xb3\xfd\x0f\x7d\x4b\xd0\xb9\xce\x1b\x12\xf1\xc7\x58\xbc\xa1\x00\x3b\xa7\xc0\x9e\xa9\x43\x8b\x09\x6f\x53\x0a\xa9\xef\x14\xa9\x5b\x50\xce\xd2\x0d\xbd\x1a\x3e\xcc\x86\x58\x32\x54\x3f\x70\x22\x9a\x01\x89\x23\x01\x55\x48\x42\x02\xc9\xd0\x29\x3f\x45\x41\x23\x71\x2a\x19\x07\x8d\x1b\xae\x35\x6e\x1e\x70\xea\x86\x84\x72\x12\xdc\x34\xdf\x20\x8f\x15\xf8\xa0\xdd\x3f\x94\x4c\x25\xe0\xb4\x51\xaf\x4c\x09\xbd\xb2\x39\x68\x75\x13\x95\x3d\x35\x02\x5c\x01\x1c\x54\x5b\xf4\xc3\x25\xcb\xf1\x5a\xe5\xd4\xf7\xa8\xa0\x19\x98\x70\xd6\x5d\x4e\xcd\xab\x4a\xdb\x75\x0a\xbc\x43\x63\xc7\x41\xdd\xe4\xb3\xff\xf5\xf5\x6c\x0b\x1b\xb1\xd7\x59\x8f\xae\x68\x39\x03\xbb\xea\xe6\x71\x07\xd4\x6e\xb0\x24\xf4\xd9\x12\x1c\x20\x1b\x93\x68\x8c\xbb\x6d\x7e\x4e\x1b\x4b\x62\x78\xcb\xba\xf7\xf8\x52\x8b\x94\x4b\x9a\x52\x49\x05\x50\x25\x02\xde\xb4\x72\x59\xb0\x9c\x2c\x31\x59\xd2\x97\xde\xd3\xf6\xff\xb6\x7a\xd2\xa1\x19\x43\x68\xd0\xd1\x11\x68\x0f\xd8\xaa\xda\xa2\x24\x9f\xd9\x4c\x6c\x1c\xb3\x9d\xf4\x78\x82\x41\x40\xd7\x8d\x8b\xda\xf7\x1d\x69\xe5\xcd\x45\x57\xde\x5c\x8c\xe4\x18\xee\x56\x39\xd6\x6a\x0f\x8a\x36\x53\xff\x6c\x86\x7a\x88\x50\x63\xd4\xa3\x66\xca\x49\xb0\x16\x55\x97\x5a\xcb\xd8\xda\x1e\xeb\xa8\x88\x66\x5d\x59\x4e\x35\x25\xa0\xcc\x88\xd0\x36\x03\x4f\x04\x8b\xae\x4b\x3e\xdb\x1e\x13\x80\x06\x35\x57\xe4\xc7\xed\xad\x9b\x6b\x5b\xd2\x97\x87\x2f\x5e\x04\xdd\xfd\xd4\xae\x53\x67\x5d\x37\x0c\x33\x09\xb6\xfb\x3b\xbe\xae\xde\x92\x67\xbb\x54\xb2\xc7\x58\x84\xc1\xe3\x75\x2c\x8b\x60\x84\xae\x11\x45\xff\x88\xd5\xdf\xcf\xf0\xf7\x6f\xf0\xf7\x02\xfe\x9e\xc3\xdf\x13\xf8\xfb\x1b\xfc\xfd\x57\x7c\x8d\xc6\xf4\xfa\x41\x0a\x55\xf6\x2d\x94\x7d\x0b\x65\xdf\x42\xd9\xb7\x50\xf6\x2d\x94\x7d\x0b\x65\xdf\x42\xd9\xb7\x50\xf6\x2d\x1a\x2f\xe9\x1f\x22\x5a\x6f\x1e\x5a\x87\xc6\xa1\x6d\x68\x1a\x5a\x86\x86\xa1\xdd\x8d\x66\xa1\x55\x68\x14\xda\x84\x26\xa1\x45\x68\x10\xda\x53\xcd\x2d\x69\xaa\xc7\x3b\x42\x88\xa2\x9b\xf8\x3a\x46\x14\xcd\x05\xfc\x4c\x75\x48\xea\xd0\x42\xff\x88\x7b\xf8\xf9\xae\x43\x0f\xd9\x75\x8c\xc6\xa6\xcf\xa6\x8a\x24\x83\x2a\xa6\x1c\xaa\x80\x1f\x29\x72\x0e\x55\x48\x0e\x55\x70\xa8\x41\x42\xe8\x21\x53\xbf\xe3\x25\xcd\xd9\x23\x18\xb7\x0a\x3a\x76\xae\x42\x11\x27\x41\x63\x03\x6b\xd9\xb5\xc0\x97\x35\x44\x61\xc3\xc9\xeb\x88\xb3\xd2\xe9\xa6\x6c\xd9\xff\x85\xa7\xe4\x73\x36\x1a\xd3\x2f\xcc\x03\x89\x69\x10\xf2\xc8\x48\xc7\xed\xe5\xc5\xc3\x42\x68\xfa\xa2\xd1\xa1\x30\x1b\x58\x3f\x01\x30\xb0\x98\xf2\x9b\xab\x16\x95\x5e\xd7\xa1\x32\x8d\xef\xe9\x6d\x1d\x5a\xf0\x88\xc6\x2a\x0f\x2f\x44\x55\xed\xd1\x69\xeb\x56\xf6\x37\xed\x5b\x67\x68\x7e\x83\xeb\xa1\x1f\xec\x35\x8e\x12\x21\x03\xf8\x81\x10\xc3\xfa\x23\x40\x88\x4e\x9a\x68\xe3\x2a\xb8\xaa\x1e\x97\xf4\xae\x5b\xaa\xa8\x09\xbb\x61\xe7\x5b\x95\xbd\x5f\xc9\xb5\xe0\xa1\x80\x2c\xf0\x11\x5c\x0f\x11\x0a\x50\x0f\xd1\x1b\x95\xf8\x30\xbf\xce\x12\x5d\xf7\x09\xdb\x63\x8c\xc5\x96\xf5\x9b\x5b\x48\xae\xa8\xf0\xa8\xaa\x10\x00\x07\xa2\x73\xf6\x9b\x9b\x95\x72\x51\xca\xaa\xaa\x51\x1e\x2d\xeb\xd1\x4f\xca\x24\x99\x64\xf9\x9c\x86\x9d\x40\xd1\xb5\x4d\x03\x48\x6d\xd8\x49\x0c\x46\x63\xca\xbb\xfd\xac\xa5\x0c\x86\xed\x67\xe0\xf8\xf4\x2b\xcb\x47\x66\xe6\xe2\x74\xfa\x59\xc8\x59\x16\x8d\xab\xaa\xf5\x59\x44\x17\x0c\xcf\x98\x3e\x0c\xd4\xba\x1e\x29\xea\x29\x3e\xde\x1b\xfa\x62\x3f\xf0\xbd\xbd\x03\xfa\x8e\xf5\x7d\x35\x32\x58\xf9\xdf\x5a\xf6\x10\x19\x2e\x78\x5e\x88\x8f\xa9\xec\xc6\x52\xdf\x23\x81\x07\xa4\xfb\x8c\x39\x33\x42\xb1\x63\x14\x70\x6a\xf9\x20\x02\xb7\x88\x16\xce\xb5\x84\x40\x92\x4d\xf1\x8c\xec\x36\xdf\x05\x21\x9a\x09\xc6\x99\xba\xc6\x1e\xbf\xb2\x2c\xfc\x0e\xae\x09\xef\x6c\xf6\xca\xe1\x84\x72\xf6\x8a\xa8\xfd\x64\x7c\x4a\x32\xc6\xe6\xcd\x9b\xbb\xe1\x6b\xb0\x19\x39\x07\xea\x8f\x3e\xb0\xf3\x91\x3f\x66\xb0\x7a\x72\x74\x32\x1e\x25\x43\xa4\x00\x12\x05\x08\x30\x07\x1a\x8f\xb8\xd1\x01\xf8\xc2\x66\xbb\x18\xd6\x72\xd8\xc8\x2e\xec\x51\xdf\xdb\xe1\x24\x68\x22\x7c\xb1\x4f\xd5\x15\x25\xb1\x2c\xfc\x65\x87\xbd\x22\xc7\xac\xb0\x2c\x7e\xa4\xba\xf9\x65\x97\x15\x5a\xdb\x59\xed\xd1\x33\xd6\x16\xf2\x28\x3f\xf6\x86\xd3\xc0\x23\x03\xe8\xd7\x57\xfc\x65\xe7\x8c\xec\x9e\x51\x08\xb1\xa6\x8a\xe6\x48\x6e\x17\xd3\xb2\x30\x64\xf2\xa1\xe6\x7a\x3c\x40\xae\xc4\x5a\x55\x8b\x0f\x93\x21\xba\xb9\x46\x01\xba\x79\xfb\x83\x41\xd2\x6b\xa8\xca\x1f\x33\x03\x9c\x8c\xb1\x93\xe1\x39\x88\x36\xd7\xac\x87\x40\x75\x13\xa2\x1a\xa3\x32\x6f\x9f\x81\x35\x99\x40\xc5\x52\xa1\x05\xbf\xd4\x37\xa9\x3b\xd6\x59\x50\x15\x26\x54\xb7\x81\xb4\x90\xc0\xa2\xce\xe6\xe8\x44\xbd\x94\x10\xa3\xfe\x74\x69\x4a\xfc\x8e\x98\xc2\x37\x23\xf5\x33\xae\x2a\x68\x14\x36\x4b\x34\xec\x96\xf9\x04\x3b\xbc\xd1\xb0\x8e\x1a\x3b\xa4\x4f\xe7\x8a\xe8\x84\x04\x77\x1d\x83\xa5\x2b\x9d\xa8\xab\x5a\x11\xf1\xbf\x23\x84\xde\x5a\x16\xec\x02\xbd\x51\x3a\x17\xa7\x73\x2d\x3c\x38\x55\xf7\x5f\xb5\xdc\x17\xec\xae\xaa\x54\xa9\xd3\x8d\x3a\xf5\xe5\xfd\x82\xd0\x2b\x76\x0a\xa2\x9d\x08\xd1\xcf\xec\xaa\xa6\x1c\x3f\xb2\xa9\xf3\x59\xc3\x45\x6b\x99\x14\x04\x7c\xeb\xc0\x45\xf3\x75\xa5\x30\xe6\x49\x1a\xe1\xcf\xf6\x47\xa0\x2d\x1b\xa9\x86\xb2\x5e\xdd\x70\xc4\xc7\x43\xf5\x27\x48\x15\x28\xf0\xb1\x8d\x35\x38\x18\x68\x50\x77\x66\x35\x22\xd5\x20\xe0\xb4\x02\x11\x42\x11\x57\x98\x06\x36\xd3\xf0\x3c\xe8\x18\x07\x9d\x0f\x8d\xd5\x5d\x95\x9f\x6a\xc4\x67\x80\xa1\x46\x37\x9c\x96\x69\x2c\x83\x87\x65\x70\xee\xfe\x91\xc5\x29\xbe\x6f\x2d\x68\xb8\x0b\x9e\xaf\x31\x8f\x36\x7d\xc4\xb5\x37\x88\x0c\x2b\x5a\x73\xb9\xa4\x19\xd0\x97\xaf\x5e\x1e\xfe\xa5\xad\x7d\x7f\xef\xf5\x4b\x75\xd1\x7c\x04\x7f\xb4\xc6\x80\xaa\x3a\x9b\x8a\xa0\xef\xd1\xb0\x0d\xaf\x05\x21\xb9\xeb\xb0\x1b\xc2\xad\x4f\x71\x63\x33\xf8\xfd\x5a\x0e\x88\xca\xe3\x5b\x11\x81\x33\xa0\x0f\x79\x36\xd7\xfe\x3c\xb7\xa7\x35\xe5\xe6\xf1\x7d\x9c\xc2\xd7\xc2\x78\x2a\x84\x80\xd4\x1d\x5b\x52\x6e\x5c\xe0\xf7\x3d\xaa\xe1\xc2\x64\xd5\xe6\xdf\xa0\xef\x3c\x49\xb4\xdb\x24\xf8\x82\xb8\xe6\xc8\xd6\x81\x58\x3e\x40\x65\x31\x7b\x7c\xf6\x4c\x13\xc9\x7a\xd4\x70\x37\xfc\x89\x01\x6f\xef\x5b\xc2\x1e\x3b\x54\x48\xd1\x59\x42\xb5\x23\xc0\x79\x95\x20\xc3\x38\x48\x46\xc2\xad\xdb\x1d\x57\x55\xb6\x4c\x46\xb9\xfb\xa1\x71\xbf\x39\x5e\xed\x55\x2e\xd2\xc8\xb8\x81\xfa\xf9\x4e\x2d\xa9\xaa\x53\x35\x39\x66\x31\xc0\x40\xc9\xb6\x9a\x82\xa6\x61\x1d\x3f\x15\xb2\xa3\xaf\xac\x2a\x2d\x68\xb4\x3d\xf1\xab\x3e\xd7\xe9\x64\x7b\xf2\x7b\x51\x84\x79\xbc\x90\x59\x4e\x17\x9d\x1c\xe7\xf5\x2a\x9d\x4d\xe8\xac\x8e\x6f\x96\x6e\xb0\x49\x8d\xf7\x04\x6e\x6d\x3c\x6e\xb8\x16\xd7\xda\xec\x33\x23\x85\xcb\x16\x38\x25\x83\xcc\xb2\xb2\x3e\x63\x33\xcb\x52\x45\x33\x9a\x93\xa5\xf6\x01\x1a\xaa\xd4\xc8\xb2\x70\xcc\xe2\x1a\x49\x44\x38\x25\xe6\x09\x13\x1c\xdb\xb3\x42\xdd\x05\xe7\xa0\x58\x4b\x6f\x99\x37\xb8\x6d\xd5\xb0\x6c\xfb\x56\x37\x34\x65\xf1\xe8\x76\xac\x5f\x63\xf8\x68\x3a\xae\xaa\xdc\xb2\x72\xf8\x98\x5b\xd6\x1c\x3e\x12\xcb\x4a\x46\xd3\x31\xd1\x25\x1e\xd8\x04\xa7\x74\x4a\xc0\xc3\x55\x89\xa5\xa2\x3e\xbb\x7e\xac\x96\xb5\xaa\x76\x4f\x2e\x97\xf4\xa5\xef\x69\x63\xc6\x5b\x37\x72\xca\xb6\x38\xe5\xd3\xab\x61\x59\xfa\xd7\x9d\x64\x39\xcd\x59\x3a\x6c\x83\x18\xe5\x82\x87\xd2\x15\xda\x66\x39\x22\x81\xba\x90\xee\xd3\x6c\x6b\x2e\xb5\x06\x3c\x31\x99\x5e\x82\x74\xf3\x66\xa6\x49\xce\xa7\x9d\xba\x0e\x69\xbc\x35\x9b\xee\xfb\xd5\x3c\x8b\x84\xc9\xf9\x8a\x26\xdb\x5b\xcd\xb3\x49\x9c\x28\xa2\x58\x65\xf3\x0f\x68\xf1\x54\xb6\xdb\x38\xaa\xb3\x79\xaf\x69\xb9\x35\x9b\xc1\x5f\xa6\x32\x8f\x86\x5b\x73\xf1\xe2\x21\x0d\x3b\x9d\xf3\x7d\x1a\x3d\x55\x9d\xf1\x81\xb7\x9a\x7b\xb2\x7d\x6e\xf4\x4e\xbe\xca\xc5\xc4\xe4\x04\x29\xc3\x6d\xd3\x53\x16\x0b\x91\x16\x75\x85\xfb\x74\xf6\xc3\x6c\x57\x49\x5c\x98\x31\xed\x79\x74\xbe\x35\xef\x5c\xcc\x33\x53\xdd\x0b\x7a\xbb\x35\x4b\xc2\xbf\x3f\x98\x2c\x2f\xe9\x74\x6b\x16\xed\xa4\x5a\xb7\xe4\xd3\x87\xed\xc3\x2c\xd3\x88\x2b\x18\xa8\x81\xc5\x3f\xa4\xd7\x5b\x73\xe6\xa2\x58\x64\x69\xb3\x6a\xfe\x2b\x7a\xb7\x7d\x9c\x61\xb6\xa8\xe7\xa2\x63\x0a\xf8\x1e\xaf\x1a\x3f\x69\xf9\x1a\x5a\xa3\xbd\xcf\x58\xc7\xb2\x6a\x8d\x3a\x07\xc5\x5d\xac\xb6\x98\x24\x8f\x21\x2f\x44\x2f\x0f\x4c\x04\x08\x59\x3e\x2c\x84\x89\x0f\x03\xf8\x89\xf4\x0f\xd7\x3f\x89\xfe\x89\xf5\xcf\x22\xa8\xdf\x43\x07\x06\x05\x77\xea\xb2\xac\xb6\x4d\x53\x65\xa9\x8b\x4d\xf4\xcf\xad\xfe\x99\xeb\x9f\x62\xb3\xae\x76\xf7\x43\x8e\xac\x13\xb1\x62\xfc\xb5\x39\x4d\xd4\x84\x28\x5a\x6f\x29\xdd\x37\x0a\x84\x3f\x67\x91\x60\x21\x95\xee\xbb\x06\x4e\x21\x2a\xd2\x51\x6a\x27\xbc\xcb\xd2\xa2\x9c\x8b\x9c\x95\x6d\xdc\xb9\xd9\x4b\xac\xa0\xd2\x35\xfe\x0c\x58\x4e\x65\xe7\x28\x62\x13\x15\x34\x7b\x9d\x71\x2a\xdd\x4f\xfc\xfb\x03\xbb\xa5\x12\xce\x16\x36\xa7\xd2\x3d\x07\x7c\xc1\x32\xf5\x69\x36\x31\x4b\xa8\x74\xbf\xc2\xde\x87\x8e\xc4\x2a\x68\x80\x98\x2d\xa8\x74\xe3\xa2\xed\xf8\x16\x8a\x47\x0d\xb6\xaa\xcc\x30\xc3\x25\x35\x4e\xf8\xba\x63\x3b\xa1\x8d\x67\xbe\xce\xe8\xb6\xd4\x65\x6a\x29\x97\xdd\x02\xcd\xd0\x9f\x2e\x50\xe8\x02\xf5\xbc\x6c\x66\xfc\x11\x38\x76\x81\x82\x31\x96\xeb\xba\xba\xf3\xfa\x64\xbb\x13\x93\xb7\x9e\xf4\xa7\x73\x72\x9d\x13\x56\xe4\xe9\x5c\xb7\x3a\x17\x2c\xd7\xd3\xb9\xe6\x3a\x97\x59\xcb\xa7\xf3\x65\x26\x5f\xbd\xd0\x4f\xe7\x4c\x74\xce\x0e\x14\x3c\x9d\x37\x36\x79\x6b\x10\x79\x3a\xe7\x42\xe7\xec\x7a\xf1\x55\x24\xcf\xb6\xe5\xd9\xc6\x39\xdd\xe2\xd1\x56\xdb\x13\xe7\xfa\x27\xd2\x3f\x89\xfe\x89\xf5\xcf\x42\xff\xcc\xaa\xea\xc7\x4b\x8e\x57\xd6\xfc\xb6\xaa\x56\xc2\xf3\xb5\x70\xb1\x16\x2e\xd7\xc2\x93\xb5\xf0\xc3\x5a\xf8\x7a\x2d\x7c\xb7\x16\x9e\x12\x35\x55\x9a\xdc\x62\xf7\x4b\xaa\xe8\xff\xa7\xee\x08\x2d\xe9\x95\x62\x45\x80\x80\x27\x8c\xbd\x97\x81\x60\xc7\x1d\x26\xe9\x0a\x07\xb9\xaa\xb6\x4c\xf9\x86\xe5\x95\x75\x22\x6f\xcd\x0e\x0b\x5c\x61\x0e\x0e\xbc\x2e\x73\xbc\xbe\xaf\x1c\xf8\x7b\xfb\xc4\xd5\x8b\x18\x4f\x1e\xc0\x55\xc3\xcb\x57\xfe\x3e\xd9\x42\x28\xb6\x5d\x78\x04\x9e\x4b\xa0\x08\x6d\xda\x94\x0d\xf2\xe5\x92\x36\xa5\x5c\xc8\xc2\x32\x4c\x3a\x71\x4d\x5e\xb5\x57\x55\x33\x9b\x3d\x2a\x93\xa4\x71\x57\xb1\x8b\x87\xc1\x55\x75\x79\x59\x7a\xde\x8b\xd1\x87\xc9\x98\x6c\x09\x2f\x74\xf8\xd0\x53\x81\xdc\x04\xf6\x54\x20\xd3\x81\x97\x75\x4e\x69\x12\x0f\xb6\x25\xfe\xb0\x99\x5d\xca\xa1\x2f\xa1\x29\xb4\xbf\xad\x86\xb4\x0e\x9f\x08\x08\x17\xa6\xb9\xfd\x8d\xb6\x57\x7a\x59\x9a\xc0\x0b\xb2\xde\xc0\x0f\xfb\xdb\xd6\xb1\xfb\xc4\x4a\x6d\x50\xb5\x92\x3d\xea\x60\xd0\xf7\x69\x21\xb3\x5c\xbc\x29\x8c\xd9\xee\xbe\x4f\x79\x72\xc7\x1f\x8a\x73\xb5\x68\x6f\x8a\xb7\x31\xc4\x95\x85\x38\x05\xc9\xf0\xb7\xf1\xf4\x63\x0a\xe5\x00\xc6\xde\x68\xef\xf8\x08\x1c\x39\x20\xda\xb1\x05\xbe\x9a\xb2\x5c\x37\xac\x66\xac\x56\xeb\x6e\x58\x16\xae\x49\x57\xd6\xf7\x08\x6d\x12\x3b\x3d\x33\x79\x3a\x31\xcc\xb8\x29\x5d\xeb\x2e\x33\xa5\xd7\xe3\xd5\x11\xb1\x1e\x47\xa5\xbb\x36\xb2\xba\xf4\x5a\xb4\x2a\xbc\x16\x45\x1b\x66\xe7\x8a\x6f\x12\x3d\x6e\x4d\x3f\xe9\xb1\x6f\xcf\x61\x59\x28\x9e\xa6\x59\x2e\x9e\x4e\x5f\xe4\xa2\x10\xf9\xed\x53\x39\x3a\x2c\x6f\xcd\xee\xfe\xf7\xc7\x34\xcc\xf2\x5c\x21\x04\x60\x8d\x80\x13\x8d\x8d\x62\xbd\x0c\x18\xd0\xb4\x37\x2f\x0b\x30\x90\x56\x2f\x5e\xaf\xee\x50\x2f\xcb\x7b\x8d\xcd\xb2\xde\x75\x29\x7b\x0b\x5e\x14\x22\xea\x3d\x7b\xdc\xd2\x8d\xe5\xbf\xc9\x40\x6e\x46\x6f\xeb\x31\x18\x49\x6c\x67\xad\x03\x41\x1b\xf3\xd5\x49\x5b\x9b\xa9\xd5\x94\xd5\x39\xea\xd6\xf8\x53\xb3\xd3\x29\xf0\x7f\x39\x2f\x9d\x9a\xf4\x8c\x74\x22\x56\x7b\xb6\xd4\x57\xe4\xfa\xa1\x84\x3d\xfe\x82\x7e\x09\x7e\x41\xbf\x50\x74\x79\x89\x02\xf5\x87\xa2\x5d\x14\xa0\x5d\x44\xaf\x03\x74\x79\x8d\xe8\x24\x40\x97\x13\x44\xd3\x00\x5d\xa6\x88\xe6\x01\xba\xcc\x11\x95\x01\xba\x94\x68\x49\xa3\x95\xbd\x0e\xa3\xd6\x1c\x1b\xf4\xf5\x21\x95\xfc\xfe\x44\x8f\xc2\xf8\x50\x09\x04\xe5\x32\x88\x29\x38\xc8\x2e\x96\x4b\xba\x95\x34\x32\xb2\x93\x89\x65\x45\x18\x9d\x18\xd3\x86\xbd\x5f\xc0\x4f\xcb\x2f\xf0\x0e\x20\x78\xd4\xcb\x26\x2a\x2a\xb1\xd1\x2f\x20\xfe\xd3\x58\x8d\x88\xc1\x98\x8e\x4f\x93\x25\x5d\x6c\x4a\x16\xc2\xd3\x23\x5c\x42\x1c\xc4\xb4\xc9\xdd\x8c\x21\x07\xd1\x89\x8a\x21\x64\x90\x1c\x33\xe4\x21\xcb\x4a\x8e\x18\x7a\x8d\x06\x24\xb3\x59\x42\x27\xda\x6e\x31\x18\xe8\x66\x09\xbc\xa5\x66\xda\xb8\xef\x04\x13\xcb\xda\x56\x06\xf2\x0b\xa4\xc9\x0b\x74\xb2\x52\x10\x2a\xa4\xc8\x41\x7a\x94\xc8\x86\x8f\xaa\x6a\xd2\x7e\xdc\x0d\xc1\xec\x8c\xd6\x2a\x4e\x58\xac\x08\x88\x6a\x93\xc6\x70\xa2\x1e\xec\xfb\x84\xd0\xac\xb5\x78\x3e\x5c\x43\x61\xc3\x2c\xd8\xc0\x40\x43\xfd\x83\x33\xad\x11\x92\xab\x8f\x4d\x2c\x37\x7c\xb2\x9c\xa8\xcb\x81\xbb\xa2\x08\xa3\xb7\xbc\x7d\x00\x5b\xd2\xd9\x36\x59\xcf\x54\x5b\x06\x89\x27\xf8\x17\xf4\x4b\x33\x4f\x9a\xcf\x13\xab\x19\xd6\xaa\x15\x75\x62\x6d\xe1\xc6\xf1\x8f\x33\x35\x56\x9b\x15\x1d\x03\xf6\x19\x8d\x1d\x35\x6e\x35\xc3\x39\x2c\xc2\xe5\xa5\x9e\x7c\x55\xc7\x4f\x14\x42\xa5\xc9\x5e\xcb\xb4\xeb\x57\xf3\x03\x30\xe6\xd1\xbc\xf1\xa8\x9c\xfe\x4b\xb2\xb2\x0c\x03\x69\x33\x9f\xa4\xcc\x7f\xb9\x93\xda\x62\x90\xdb\xc6\xd8\xbd\x3b\xc9\xb3\xf9\x3b\x63\xab\x1c\xa7\xad\xc2\xe5\x06\x93\x2b\x1c\x25\x63\xa3\xdd\x97\xdb\x4c\x85\x96\x19\x8b\x97\x4b\x33\x8f\x26\x3b\x59\xd2\x0d\x53\x49\x83\x44\xc3\x4a\x0f\x0d\xc8\x04\x93\x65\xfd\x32\x5e\x76\x33\x9a\x6b\xec\x1c\x13\x9a\xe8\xcb\x2b\x7a\x44\xc1\x3a\xdf\xb9\x5e\x98\xb4\xa6\xe7\xb4\xaf\x2e\xe3\xa4\x4b\x75\xfb\xb1\x9d\x50\x08\x11\xaa\xaa\x44\x4b\xd4\x5d\x9f\x09\x46\x4b\x44\x68\xaa\x4d\x85\x18\xf5\x18\xc1\x66\x58\xe7\x9e\x60\x14\x20\x73\xd8\xca\xe6\x24\x36\x2d\xae\x1a\x53\xd4\xd4\x63\x4a\x05\x51\x18\xe1\x97\xf7\xe5\x22\x89\x43\x2e\x45\xef\x46\x3c\xf4\xd0\x2f\xb6\xb0\x7f\x41\xbf\x98\xaa\x32\xfd\x16\x23\xc8\xd0\x20\x50\xa8\xbe\x83\xff\x86\x11\xae\xad\xa6\x86\x59\x2a\x79\x9c\x16\x0a\x17\x5f\x83\x73\xfb\x5e\x43\xba\xaa\x2f\x68\x1c\x91\xa0\xc6\xc0\x1b\x55\x95\x98\x04\xe9\x48\x8c\x99\xfa\x80\xe6\xf9\xd6\xe6\x37\x8e\xa2\x1f\x77\xa2\x93\xfd\xc9\x6e\x6c\x56\xb9\xd2\x99\xfa\xe3\xc7\x0b\x83\x11\xd5\x6b\xd7\x40\x98\xb9\xf1\x90\x25\x26\x03\x80\x8f\xd1\x93\xf0\xc1\x46\xc0\x17\x45\xa3\x15\x60\x18\xd5\xc0\x30\x5e\x6f\x73\x8c\x6a\x8d\x95\x06\x18\xb4\x26\x40\x89\xc9\x5f\x94\xd9\xec\xa7\x7e\x97\x69\xba\xa9\xce\x30\x53\x6a\x56\xf7\xdc\x69\x7a\xbe\xc0\x64\x9d\xfb\xb2\x8a\x5e\x87\x0b\x4c\x82\xcd\x7d\x52\xef\x11\xd9\xce\x01\x46\x12\x01\xec\xe6\xfa\xa7\xd4\x3f\x02\x20\x59\xb7\x3b\xe9\xe6\x9e\xe8\x74\xae\x7f\x12\xfd\x53\x74\x0a\xf9\xba\x50\xda\x2d\x94\xae\xd4\x9d\xb4\x3f\x60\x37\x21\xc2\xe8\x5b\x2a\x3a\xa7\xa2\x3e\x02\x97\x6a\x76\xe8\x16\xf5\x84\xd6\xbd\x92\xb0\x11\x02\x63\x84\x89\xc2\x13\x34\x6d\x00\x44\x9f\xb4\xfa\xc0\xd6\x5e\xd1\x10\xa1\x5b\x6e\xcf\x72\xd8\xe1\xd5\xaf\x9a\xc4\x18\xe5\xe3\x46\xbc\x6f\x8b\xa0\x30\x5f\xf5\x53\xc7\xb7\xf9\xa9\x53\x1d\xae\xc9\x33\x9c\x31\x81\x39\x95\x84\x0c\xf9\x48\x8e\x59\x16\x44\x22\x11\x52\xf4\x54\x68\x49\x14\xe5\x6d\x90\x42\x4e\x39\x59\xe2\x47\x84\x82\x74\x09\x4f\xb2\xe9\x52\xdd\x32\xfd\xbd\xfd\x6d\xb7\x4c\x75\x26\x6a\x1b\xa2\xfa\xa6\xd2\xf1\xd2\xb6\x4d\x16\x08\x0e\x27\xce\x76\x47\x97\x97\x97\xe8\xf2\xde\xf3\x9c\xcb\x7b\x7f\x72\x79\x7f\x38\x71\x2e\xef\x5f\x4f\xd4\xcd\x87\x47\x97\xa5\xf7\x52\xa5\xa8\x9f\x83\xcb\xd2\x3b\xf4\x26\x97\xa5\x7f\x78\x7d\x00\x7f\x5f\x5c\x96\x7b\x9e\x17\x3a\xf0\x33\x51\x7f\xf7\x5e\x41\x60\x0f\x02\x2f\x3d\x08\xbc\x9c\x5c\x96\x13\x31\x51\x7f\x27\x13\x15\x35\x99\x4c\x26\xe3\xdd\x29\x8d\xd9\xa3\x22\xc2\x14\x61\x76\x8d\xa8\xa2\xb9\xd4\xa7\x54\x9f\x29\x7c\xa6\xea\x73\x02\x9f\x13\xf5\x99\xc3\x67\x8e\x28\xd0\x75\x97\x97\x1d\xca\xee\xf2\x12\x75\x1e\xac\x92\x0e\xc5\xc5\xdd\x84\x17\xf2\x63\x1a\x89\x7b\xe6\xd1\x16\x89\xfd\xa2\xb0\x6b\xf3\xfa\xcb\x29\xde\x54\xf0\x8e\x47\xa2\x5e\xf9\x0d\x1e\x8c\x1c\x2a\x32\xf1\xb2\x44\x36\x46\x9e\xe7\x79\xc8\x16\xab\x4e\x55\xda\xf7\x60\xff\x65\xa3\x4d\xe0\x1c\x90\x25\x21\xb6\xa1\x4b\x35\x76\x5f\x76\xde\xd9\x32\xca\x75\xe3\x71\x2b\xe9\xc3\x04\x9d\x81\xbf\x4f\x3a\x37\x26\x6b\x66\x96\x85\x67\x5d\xa1\x91\xbc\xaa\xf2\xae\x75\x5a\xb0\x59\x66\x76\xfa\x6c\x0b\xc8\xaa\xb8\xcd\x2d\x30\x33\x32\x88\x46\x89\x5e\x07\x40\x2a\x75\x4b\xe6\x14\x72\xa5\x1a\x54\x39\xcd\xe8\x4c\x41\xae\xa9\xc8\x20\x17\x33\x67\xf5\xf6\x9f\x0f\x67\x41\x82\x67\x06\x87\x19\xc2\xa9\x4e\x6c\x88\x8d\x19\x19\x9a\x79\x9b\x91\x00\xa9\x01\x23\x5d\xe0\x3a\xcb\x12\xc1\x53\x14\x98\xe2\x49\x62\x3e\xaf\xe3\x69\x9c\xb6\x88\xac\x29\xad\x8b\x99\xb1\x07\x60\x2a\xcf\xe0\x5f\x53\xad\xc2\xd3\x36\x93\x74\xc2\x46\x63\xba\xc9\xf2\xf9\x01\xcf\x87\x2f\x16\xc9\x03\xae\x5d\x85\xb5\x96\xe1\x8c\x87\xb8\x68\xa0\xc8\x74\x32\xd1\xc6\x29\x63\x3a\x23\x20\xeb\xa8\xda\xac\x55\x5c\x99\x3a\x52\x27\xa6\xd8\x10\x8d\xc6\x28\x10\x43\x34\xba\x4c\xd5\x55\x60\xa2\x5f\xd5\x11\x85\x20\xb1\xd5\x86\xb0\x17\x36\x1a\xa3\x00\x8d\x50\x9b\x8c\x88\x8a\xa3\x82\x2d\x68\xa8\xae\x80\xe9\x96\xb5\x4e\x89\xee\x62\xba\xb5\x8b\x1b\x70\x9d\x8e\xe2\xb1\x65\xe1\x90\x15\xb8\x64\x2a\xa0\x16\xd6\xb2\x26\xfa\x3c\x4b\x70\x49\x6c\x2c\x86\x08\xc4\xc6\x03\x44\xec\xd0\x48\x50\x76\x51\xe0\xec\x29\x14\x08\xef\x7e\x05\x96\x74\x46\x06\x69\xa7\x52\xb9\x56\x69\xaa\x76\xc9\x53\x53\xf5\xb8\x84\xa9\x7a\xfc\xf1\x54\x2d\x51\x80\x1e\xd7\xa6\x6a\x59\x4f\xd5\xb2\x05\xe8\x86\x3e\xcd\x5a\xce\x99\xba\x38\x75\xf8\x68\xab\x16\xde\xcc\xfe\xd4\x97\x15\x84\xa8\x54\x7f\x36\x04\x59\x39\xd1\xa6\x43\xd5\x54\x73\x3d\xd5\x12\xa4\x3b\x61\xb6\x36\x66\x9d\x83\x2c\x28\x27\xc6\x15\x22\xcd\xba\x1b\xb4\xed\xa2\x65\x6d\x6a\x9e\x64\xad\x18\x6d\x67\x2c\xb5\x72\xf7\xfa\x5d\x1d\xa9\x3d\xdd\x8e\xad\xf5\xc0\x52\x60\x84\xa8\x3a\x6a\xf2\x25\x59\x6a\x59\xdf\xc3\x03\xff\x15\x30\x4e\xb7\xb0\xb9\x7e\xf8\x98\x9e\x6e\xee\x9c\x55\xaa\x97\xe6\x9b\x39\x6a\x6a\xf0\x63\x71\xd2\x78\x71\xee\x0a\x42\x6a\xee\x96\x11\xf3\xde\x2e\x94\x68\xea\xe4\x45\x11\x4f\xd3\x8e\xa1\x7a\x90\x9e\x88\x7a\x77\xb1\x9c\xc1\x45\x72\x85\xdd\x80\xd6\xbc\x0a\x83\xbf\xb3\x6d\xe2\xb4\x32\x7f\x00\xfe\xda\x4a\x2b\xad\x81\xef\x56\xcd\xd6\x20\x20\xc4\xaf\x43\x2d\x18\x29\x46\x2f\xc6\x0c\x45\x02\x51\xf4\xa2\x83\x57\xb6\x88\x29\x60\x41\x5a\xcd\xbe\xbe\x3f\x68\x7d\xcd\x3e\x2e\x69\xca\xbc\x41\x7a\xe4\x7b\x83\xd4\xb6\x89\x1c\xa1\x2b\x64\x6f\xbf\x84\x8d\x19\xb8\x5b\xe8\x9a\x81\xed\xff\xb0\x55\x49\xdc\x39\x5f\xac\xfa\x4f\xae\x9f\xee\x46\x42\x11\x25\x66\x1b\x21\xb2\x3a\xe0\x9c\x3d\xd6\xd7\x31\xb4\xcd\x5d\x1f\xaa\xf5\x98\xd0\x13\x5e\x9a\x73\x45\xcc\x8b\x25\xc8\x23\x6d\x2b\xdf\xce\x16\x60\x96\x95\xb9\xc7\x8f\x4b\x9a\x77\xba\xd6\x4a\x22\xd4\x7d\x5c\x2e\x31\x19\xae\x94\xe9\x3a\xb4\xe5\xad\xf4\x36\xf0\x8c\x18\xf0\xda\x4b\xe6\x0f\xca\x4d\xf9\xed\xd2\xb6\xdb\xec\x61\x2f\x4e\x7b\xb1\xe9\x59\xc7\x2b\x6f\x39\x26\xc4\x1c\x89\x31\x0d\x41\x59\x67\x14\x8e\x59\x3c\x0a\xc7\x00\x08\x92\x3c\x26\x4c\xe2\xb8\x15\xd5\x88\x98\x37\x88\x8e\x92\xc6\xa1\x9a\x6d\x93\xbc\xae\x20\x19\x45\x63\x5d\x87\xfa\x52\xd5\xc0\x2f\x69\xa4\x2c\x0a\x45\x0d\x1e\xae\x08\x4c\x35\x0e\xe2\x5f\xed\xbd\x24\x4f\x0b\xa2\x64\xad\x3c\x0f\x4e\x49\x55\xe1\x8c\xa5\x55\x95\xd1\x94\x8d\xc6\x8a\x88\xcc\x40\xd0\x55\x76\x69\x0c\xad\x4e\x35\xdc\x42\x85\x33\xe1\x16\x59\x99\x87\xc2\x9d\xc3\x02\xec\x5e\x62\x3c\xec\x5f\x0e\xc9\xee\xd4\x38\x6b\x68\x5d\x28\x79\x83\xfc\x28\xed\x7a\x6b\x92\xfa\x0c\xd0\x8c\xb5\x9c\x1a\x77\x94\xa0\x90\x1e\x89\x24\x9e\xc7\x52\xe4\x3a\xa8\xb9\x88\x3c\x09\xfa\x3e\xcd\xc5\x42\x70\xcd\x2c\xd7\xd2\x66\xc0\x5e\x2f\xa4\xc8\xe3\xe2\x46\x47\x4b\x29\xf2\x54\xfb\xc7\x6c\x8f\x12\xe8\xf5\x52\xfb\x61\xc9\xb1\x24\xed\x70\x36\xec\x86\x82\xd8\xad\x37\xe0\xad\x15\x66\x6e\xdb\xc4\x58\xf6\x10\x58\x8e\xf8\x18\x8a\x98\xb1\x77\xda\xe8\x2a\x9f\xe1\x61\x80\xec\xcc\x80\x68\xa5\x0e\x21\x82\x68\x84\x73\x42\x68\xaa\x3b\x42\x33\x12\x3c\x61\x1d\x6f\x82\x39\x16\x34\xd5\xfe\xbe\xea\xcc\x9b\xef\x3f\xbc\x13\x13\x66\xf3\x45\x9c\x3c\x61\xa2\x27\x81\xfa\x24\x01\x95\xca\xb6\x8c\xcc\x6e\x44\x5a\x5c\x64\x1f\x4c\x19\x96\x6c\x49\xd4\x03\x62\x13\xe3\x96\xbd\x33\xc6\x11\xc2\x8a\xfe\x76\x09\xa2\x08\x8f\x2e\x2f\x77\xdd\x31\x19\xe2\x61\x80\x87\xc1\xe5\x65\x80\x2f\x2f\xef\xc0\xe7\xf3\xe5\x25\xc6\xf0\x73\x79\xe9\x56\xa3\xdf\xd5\x2f\x26\x63\x62\x93\xcb\x4b\x42\x86\xd5\x0f\x93\xf1\xc8\xde\x19\x8e\xc9\xb0\xc2\x97\x97\x3b\x84\xa0\x71\x3b\xa1\xa0\xcf\xb7\xe2\xf3\x7c\xdd\x5d\x98\x5e\xc8\xfa\x72\x88\x68\xc8\xa4\x65\x49\xb7\x81\xae\xaa\x42\xbb\x68\xa0\x29\x6b\x75\xf8\xba\xe2\x5e\x84\xc0\xf3\xd2\xf0\x1d\x69\x13\xf0\x13\xb0\xfe\x4e\x17\xcc\x78\x3a\x04\x89\x77\xbb\xb1\xb4\x1b\xd3\x05\xa1\x31\x5b\xd8\xb5\x68\x2a\x9d\x90\xc4\x66\x93\xc6\xb7\x8a\xaa\x6a\xc6\x84\xa2\xa8\xe6\x2c\x1d\xed\x8d\xe9\x2d\x4b\x47\xfb\x63\x3a\x65\xe9\xe8\x60\x4c\x1f\x58\x3a\x7a\x31\xa6\xd7\x2c\x1d\xbd\x1c\xd3\x3b\x96\x8e\x0e\xc7\x83\xc4\xb2\x70\x6e\xa8\x24\x02\xdd\xd7\xa2\xc6\xf7\xe6\x26\x30\xaf\x5f\x6d\x67\x96\x35\xeb\x33\x36\xa7\x27\x0c\xd9\x48\x3f\xaa\xa2\x1d\xf8\xa0\x37\x0c\x0d\xd7\xa2\xbe\x42\x0f\xaa\x2a\xa4\xef\xd8\xb4\xaa\x1e\x06\x79\x77\x1b\xde\x56\x15\xb7\xed\x7a\x2f\xce\xb5\x1a\x69\xb3\x19\xbf\xb6\x3b\xf1\xa6\xde\x88\x27\xcd\x3e\xbc\xef\x6c\xc3\xfe\x5d\xb3\x0f\xdf\x0d\x4b\xfc\x8e\x04\x77\x43\xe4\xee\x28\x22\xf6\x77\x64\x17\xf8\xab\x22\x5f\xed\x21\x5a\xb6\x28\x2d\x6e\x54\x78\x2c\xcb\x4c\xaf\xd6\x1e\x8d\xb5\x08\x76\x3b\x19\xf9\x8a\x8b\xfa\x96\xc1\x5e\x7b\x4d\xc7\xa2\x95\xed\xdd\x1d\x5d\xee\x0e\xff\x87\xba\x73\x6e\x39\xe2\xd0\xf3\x1f\xdf\xdd\x56\xdd\x49\x2e\xbb\x8e\x90\x93\x35\x68\x83\x6d\x61\xd4\x92\x1a\x73\xb3\xda\x0c\xba\xe8\x9a\x41\xdf\x7c\x7d\x1f\x65\xa0\xaa\x34\xca\xc6\xdd\xad\x85\x7e\x07\xfc\xa1\x52\x5d\x33\x93\x36\x22\xcf\x14\x06\x91\xa4\xa5\x90\x3b\x48\x2c\x6b\x7b\xc3\x15\xb0\x27\x4c\x02\x2a\x2f\x18\x06\x9c\x4e\xdc\x45\x2e\xa4\x7c\x18\xc6\xc1\xa6\x7f\x79\xf0\x8e\x59\xb6\x5d\x85\x33\x0f\xce\x3b\x26\x46\xe5\x78\xb0\x95\xad\x6b\x36\x09\x9d\xb0\x64\x14\xba\x0a\x7e\xc6\xad\x1a\xf6\x44\x1b\x0e\x72\x6b\x88\x21\x8f\x61\x2d\x1f\x6c\x59\x98\xdb\x2c\x34\x7a\xb5\xa4\xf5\xca\xb9\x8d\xb4\xfb\xa5\x79\x2a\x41\xbf\xd8\xba\x15\xfb\x17\xd4\x93\x99\x22\xef\x0c\x21\xf7\x0b\x88\x9f\xe7\x78\x42\x8c\x15\x29\x57\x03\x27\xf9\xcf\x2a\x54\x34\xa3\x2e\x48\xe1\x25\x2a\x17\xa1\x88\x6f\x45\xd4\xfb\xf7\x2f\xf6\x2a\xf1\x8c\x27\xc4\x46\xff\x46\xb5\x69\x85\xe6\x8a\xb2\x3e\xe6\x7a\x64\x83\xff\xbc\x23\xd7\xa2\x27\xe6\x0b\xf9\xf0\x8b\x36\x22\xa2\x66\x7a\xc1\xbc\xc1\xe2\xa8\x6e\x0b\xcc\x2c\x83\xad\x3f\x56\xe0\xc9\x68\x31\x26\xb4\x9f\x8e\xca\xb1\x66\x73\x44\xe4\x2f\x06\xcf\x93\x64\xa3\x5d\x38\xc4\x75\x6c\x0d\x73\xbf\xa0\xbf\x9c\x8b\xc8\xcc\x05\xb7\x19\x4c\xc6\x62\x58\x2f\x6d\x10\xb6\xb8\x96\xd8\xd1\xb2\x79\x22\x88\x58\xe8\xd6\xc8\x62\xd8\xee\xdb\x49\x77\xdf\xfe\xf7\xed\xda\xa0\xc0\x93\xff\x6c\x72\xfe\xdf\x4c\x0c\xfa\xc5\x8e\x80\x65\x3f\xe8\x00\x77\x3d\xe8\x9e\x8a\x6b\xed\x96\x2f\xb7\x0a\x58\xb7\x3c\xa9\x5d\x3c\x72\xed\x9d\x21\xfb\xbd\x1f\x3c\x7b\x5c\x62\x32\xba\x1c\x57\x97\xbb\x97\x97\x63\xb2\x3b\xa5\xe8\xf2\xf2\x99\x8f\x3a\xb8\xa8\x7c\xaa\x0e\xd6\x0f\x9e\x5d\xee\xaa\xc3\x74\x5b\xb1\x70\x85\x42\x10\x40\x66\x33\xd9\x35\xe5\x1e\xad\x3d\x5f\xba\x85\x48\xb5\x8d\x3a\x50\x26\x88\x51\x9b\x75\xd2\x10\x30\x58\x2a\xaa\x32\x55\xd8\x27\xa5\x52\x51\x95\x83\x96\xb4\xc2\xa9\xa2\x36\x15\x32\xd2\x97\x4a\xca\x59\xdf\xef\x33\x96\xba\x22\x8d\x68\xac\xf1\x96\x37\x48\x5a\x4c\x94\xd4\x98\xa8\x64\x62\x94\x8c\xb7\xea\x93\x96\x24\xb6\x59\x81\x4b\xd2\x9e\xb7\x13\x15\xae\x31\x0c\x5d\x30\x4d\x8e\x95\x1d\x5c\x8a\x06\x86\x00\x2d\x09\x2d\x0d\xc2\xb0\x2c\xbc\xb0\x4d\xde\x89\xbd\xb0\x11\xd9\x41\xf0\xf0\xba\x60\x65\xb3\xab\x87\x65\x8d\xc8\x86\x13\x1b\x61\xe0\x39\x90\x21\x0a\xea\x62\x75\x94\x8a\x6b\x43\x48\x3f\x51\xcf\x58\x01\xe6\x0d\xba\x14\x08\xa1\x73\x16\xd7\x6c\xc2\x9a\x9f\x44\x18\x63\x8d\xcd\xe8\xac\xaa\x70\xcc\xf0\x7c\x18\x37\xb6\x49\xda\x8c\x41\x4c\x6c\xdd\xf6\x4c\xfd\xb2\x67\xaa\x65\xe8\x35\x1f\xa2\x67\x28\xc8\x2c\x6b\x0e\xeb\x85\x87\x0c\xf2\x54\xcf\x08\xa2\xab\xc4\xea\xef\xc8\x8e\x29\xc8\x92\x2b\x0a\x71\x49\xf7\x0e\xbd\xfd\xbf\x52\xc6\x38\x00\x3f\x2d\x5d\x8d\xd8\x65\x87\x18\x23\x8f\x4b\xee\xe6\xa2\x10\xf2\x57\x9e\xa7\x71\x3a\x7d\xc7\xc3\x99\x00\xdb\x74\x5b\x6e\xd8\xeb\x6e\x0f\xb4\xd1\x04\xfd\xb8\xd9\x67\xcc\xf0\xe4\x13\xd6\x61\x67\xbc\xe3\x49\x12\xa7\xd3\xde\x79\xad\x31\xd0\x03\xbd\x44\x2e\xb3\xbc\xe8\x45\x71\x2e\x42\x99\x3c\xf4\xe2\x02\xb0\x69\x51\x2e\x54\x9b\x22\xea\x5d\x3f\xf4\xe4\x4c\xf4\xfe\xbd\xc8\xb3\x85\xa3\xe0\xa7\xf8\x77\x6f\xc1\xc3\x1b\x3e\x15\x6e\xef\x5b\x21\xda\xfa\xdc\x70\x26\xc2\x9b\x26\x88\x89\xc2\x04\xea\x82\xa6\x2a\x98\xbb\xbd\x2f\x82\x47\xbd\x79\x96\x8b\x1e\x97\xbd\x99\x94\x8b\x60\x77\x77\x72\xed\xce\xc5\x6e\x59\x08\x07\x0a\x3b\x6d\x2b\x88\x98\x43\x20\x01\xc4\xc2\x40\x8f\x32\x8f\x79\x2a\x7b\xff\x8c\xb3\x84\x03\xbf\x87\x26\xcb\xae\x23\x85\x76\xf3\x2d\x85\x1b\x17\x5f\xc4\x9f\x65\x9c\x8b\x88\x09\x23\x47\xff\x08\x0f\x46\x81\xa0\xd7\x59\x96\x04\x02\xde\x49\x02\x41\x8d\x99\x6a\x41\x8d\xe5\x11\x61\xa4\xc8\xd4\x87\xd6\xe9\x11\x94\xa7\xaa\x1c\x94\x3f\x9b\x04\x92\x1a\xb1\xfa\x40\xd4\x5f\xa0\x45\x23\x68\x7d\x0d\x84\x4c\x69\x16\x89\xa6\x5a\x88\xc9\x52\xd1\xfe\x42\x11\x49\x8b\x19\x87\x5f\x71\xcf\x43\x19\x48\xba\x3a\x8d\x01\xa7\x1b\x50\x11\x64\xcd\xcb\x6e\xea\x36\x39\x59\x4a\xd3\xe5\x92\xbe\x78\xf9\xfa\xb0\x03\x8a\x5d\x31\x3f\x05\xa5\x04\x93\x25\x3d\xf0\x0f\x36\xd9\x55\x6d\x4e\xf4\xf5\xe4\xdd\x97\x93\x8b\xab\xf7\x67\x57\xa7\x67\x17\x57\xe7\x6f\xbe\x7e\xbd\xba\xf8\xfb\xc7\xaf\x57\x67\x5f\xae\xfe\x75\xf6\xed\xea\xd7\x8f\x9f\x3e\x5d\xbd\x3d\xb9\xfa\xf0\xf1\xcb\xc9\x7b\xb4\xa4\x07\x07\x07\xaf\xfe\x0a\xfa\x0f\xf7\x5e\x1f\x10\x10\xe8\x3b\x3c\xf0\x5f\x11\xca\x59\x8a\xf7\x5f\x1d\x78\x9d\x2d\x01\xc4\x69\xcb\xc7\x41\x0a\x46\x8a\x60\x77\x17\x04\xc5\xff\x28\xdc\x2c\x9f\xee\x46\x59\x58\xec\xc2\xe3\x94\x13\x09\x75\x0e\xe6\xee\x4c\xce\x93\x61\x5c\x43\x07\x43\xb6\xa0\x29\xf3\xb7\x69\x96\x03\x37\xc8\x66\xc8\xe2\xf9\xb4\x18\x8d\x55\xd6\x0d\xca\xae\xc3\xa3\x48\x1b\xef\x41\xe8\x73\x9c\xc6\x93\x58\x44\x0a\x88\x43\xa9\x5f\xc7\x7a\xff\x03\x64\x51\x06\xbd\xdb\xb8\x88\x65\x0f\x81\x4f\xbe\x49\x96\xc3\x7e\x99\x94\x49\xd2\x33\xf2\x2e\xc0\x44\x2b\x04\xc4\xa7\x59\xea\xcc\xeb\xca\x22\x71\xdb\x13\xe9\x6d\x9c\x67\x29\xd8\x1f\x51\x85\xa1\x20\xd4\x5f\xf4\x78\x1a\xf5\x78\x14\xc5\x1a\x8f\xf6\x66\x22\x59\x4c\xca\xa4\x77\xa7\x41\xa1\x70\xd1\x52\x3b\x10\xee\xda\x33\x89\xf1\xde\xde\x21\xd1\x77\x1f\xbd\xff\xbf\x0a\x49\x8b\x15\x2d\xa5\x52\x9f\x64\xfa\x40\xa3\x21\x16\x36\x7a\xc7\x17\xb2\xcc\x05\x52\xe8\x6c\xfd\xc4\x03\x2f\xd6\x23\x31\x56\x87\x1d\xf3\xba\xde\x96\x84\x6d\x93\xc4\xe5\x51\x84\xe5\x48\x8c\xb5\xde\x4d\xc4\xfa\x5b\xdd\x4d\xde\xc5\x69\x94\xdd\x55\x55\xa3\xc7\xa9\x23\xdc\x28\x0b\x61\xbe\x9f\x4e\x31\xa2\x07\x46\xf4\x97\xd0\x09\xdb\xfd\x7d\x14\xbc\x71\x7e\xbb\xe2\xce\xf7\xcb\xd2\xf3\xde\xc1\xbb\x9b\xf7\xfe\x25\xfc\x7d\x05\x81\x0f\x10\xf8\x00\x81\xbd\x0f\x1f\x2e\x4b\x6f\xff\x10\xb2\xed\x1f\xbe\x87\xbf\x1f\x9c\xcb\xd2\xff\xa0\x52\xf6\x3c\xef\x9d\x7e\x99\x7b\xaf\xfe\x42\xb6\x3d\xff\x95\x4a\x79\x07\x4f\x7a\x7b\x1f\x4e\x3e\x5c\x96\xfb\x9e\xe7\x3b\x97\xe5\xfb\x43\x55\xe6\xc3\x6b\x48\xf9\xf0\xfe\x9d\x0a\xbc\xff\x00\x81\x0f\x1f\xde\x8f\xff\xbf\xda\xb1\x4b\xc7\xf5\x9c\xd7\xaa\xe9\xb7\x87\xaa\x19\xfd\x56\xb9\xff\x12\x9a\xd9\xff\x00\xcd\x1c\x78\xe3\x9d\x67\xbb\xad\xfe\xd6\x93\x4c\xe9\x19\x7b\x5c\xd2\xf9\x0a\x4c\xdd\xd6\x1e\x12\xea\xa3\x08\xec\x53\xf1\x30\x14\x0b\x59\xbc\xd5\x0f\x52\x05\xa8\x83\xcb\xaa\xda\xd7\x3f\x07\xea\x47\xdb\x87\xe3\x52\xe6\xf1\x75\x29\xc5\xa9\x42\xf6\xf9\x96\x48\xd0\x35\x67\x99\x4e\x99\x97\x85\xfc\x56\x34\x0a\x6d\x2c\xd5\xd1\x8b\x0e\xaf\x96\x09\x63\x79\xee\x61\x21\xea\x56\x0a\x9e\xc6\x32\xfe\x2e\xbe\x7d\xf9\xc4\xb8\x8e\xca\xc5\x3c\xbb\x15\x27\xea\xea\x60\x44\x3a\xe3\xa5\xd6\xf9\x7a\x5c\x0e\x10\xe8\x4d\xe6\x22\xed\x45\x3c\x9d\x8a\x3c\x2b\x8b\xe4\xe1\xab\x90\x1f\xd3\x54\xe4\x7f\xbf\xf8\xfc\xa9\x67\x24\x0a\xc0\xf0\x75\x1d\x78\xa7\x10\xb8\x88\x7a\x71\x93\x4b\x1d\xa7\xb9\x28\xb4\x26\x42\x2a\x4f\xa2\x58\xf2\xeb\x44\x18\x9c\xde\x24\xff\xfd\x21\xca\xe1\x60\x6b\x12\xe4\x43\x22\x1a\xce\x70\xef\x29\xd6\xf0\x54\x6d\x4e\xb5\xd5\x6f\xc1\x40\x58\xdf\xa7\xda\x9d\xbe\xfa\xea\xfb\x8a\xa4\xa7\xa3\x11\xd2\x6b\xf1\x6e\xc6\xf3\x42\x48\x44\x4d\xd8\x09\x4d\xc4\x98\x8e\x50\x98\xf0\xa2\x50\x93\x87\xa8\xfe\x86\x58\x85\x60\x3f\x64\x39\xa2\x68\x92\xe5\x26\x46\x2e\x4e\xfe\x2c\xe3\x5b\x44\xe1\xdb\x11\x10\x18\x8f\xb7\xf7\xcf\xa8\xe9\x8c\xbc\xf1\x60\x3a\x92\x75\x57\x25\xf5\xa1\xab\x23\x7f\xbc\xd1\x5b\x14\xae\xce\x14\xa2\x28\xca\xf9\x74\x6a\xbe\x8b\x85\x48\x12\x98\x66\x44\x11\x48\x52\xa2\xf1\x4f\x4c\xcd\x1e\xb4\xb7\xea\x3e\x63\xb3\x69\x5e\xca\xec\x8b\xb6\x48\x09\xb6\x29\x14\xfd\xcb\x93\x2f\x42\x73\x2f\x1b\xaa\x02\xa6\x23\x2c\x0b\xd3\xa5\x5a\x08\xf4\x4d\xb2\x98\xf1\xff\xa0\x37\xeb\xed\x23\x9e\x24\xd9\xdd\x87\x32\x49\xbe\x86\xb9\x10\x69\x0f\x14\xd6\x7a\xaa\x53\x1f\x54\x73\xf0\x75\x9e\xf0\x07\x90\x19\xca\xb3\xa4\xa8\xc1\x4e\xfd\x8a\xbc\x17\xc5\xd0\xa5\xa8\xfe\x38\x8f\x43\x85\xd9\x3f\xa6\xe6\xa3\x8e\xff\x22\xe6\x99\x14\xaa\xa6\x6b\x1e\xde\xa8\xb3\x67\x7e\x9a\xfd\x53\x93\x84\xa2\x37\xd3\x42\x48\x49\x96\x2d\x7a\x69\xf6\x39\x8b\xca\x44\x1d\x5e\x4d\x7a\xb6\x10\x69\x6f\x91\xf0\x87\xe2\x63\x9a\xc4\xa9\xe8\xe5\x82\x47\x67\x69\xf2\xd0\xcb\xcd\xfc\xf4\x8c\x55\xcf\xa8\x07\x2a\x5e\x51\xaf\x10\x7c\x9e\x88\xa2\xe8\xc5\x52\xcc\xbf\x82\xda\xd7\x7f\x06\xd9\xfb\x3f\xb5\x7c\xa1\xde\x7d\x88\x22\x63\x00\x58\xc0\xa7\x84\xa8\x42\x24\x70\x63\xfd\xa9\x05\xda\xa7\x7d\x6f\xcb\x4e\x42\x61\x7d\x56\xa2\x28\xbb\x4b\x93\x8c\xff\x5c\x75\x07\xdb\x37\x26\x0a\xb3\xa4\x40\x14\xe5\xd9\x9d\xfa\x29\xe2\xef\x1a\xc2\x79\xfa\x53\xb5\xbe\x7c\xa2\xd6\x3c\xbb\xfb\xaa\xea\xa0\xa8\x90\x3c\x97\x3f\x55\xd7\x8b\xbf\x9e\xe0\x81\xd6\x6e\xdd\x1d\x5d\x3a\xc1\x18\x8f\xb8\xf3\x5d\x5d\x96\xdb\x63\xe0\xba\x7b\x05\x1e\xf9\xe3\x35\xe6\x42\x93\xef\x6e\xcd\xa1\x0e\x9b\x6e\xf8\x4e\x26\x43\x85\x2c\xe0\x5d\x62\x60\xe4\xf6\x59\x36\x34\xe2\x7d\xa0\x7e\x9d\x5b\xd6\x5e\x43\x8c\xc0\x8b\x2f\x88\xc5\x81\x5d\x5b\x74\x56\x7f\x13\x95\x92\xea\x10\x58\x18\x38\xad\xbf\xc1\x70\xd3\xa6\x87\x9f\x86\x27\x27\xbb\x0a\x2f\x6b\xa9\xea\x12\x0e\xa6\xe3\x59\xaa\x35\x0b\x9b\xd7\xbe\x5a\x07\xd1\x48\xbf\x18\x09\x8f\xe6\x8d\x5a\x4b\x62\xe8\x8b\x45\x2d\x89\x51\x4b\x8d\x35\x82\x1b\x26\x3a\x37\xde\x1f\x55\x63\xc3\x7e\xba\x7e\x9c\x06\x28\xe2\x92\x83\x00\xb1\xd6\x70\xec\x2e\x5c\x73\xf3\x7d\x41\x88\x65\x21\x45\x1d\x43\x4e\xb1\x2e\x06\x07\x8f\x7f\xf5\xf0\x5a\x57\xc0\xf1\x04\xaf\x3a\x65\xae\x3b\x42\xcc\x00\xd3\xae\x46\xe5\x7e\x5d\x99\x84\x91\xf4\x0e\x9a\xca\xd5\x5c\xeb\xb8\x17\xad\x04\xcb\x29\x3f\xc5\x52\x8b\x9d\xf4\x5e\xae\x47\x57\x95\x7f\x2c\x97\x4d\xe7\xf4\x6b\x0e\xcd\x09\x58\xa8\xd2\x46\xaf\x73\x6d\x89\x59\xc1\xc2\x70\x93\xe3\xd5\xef\x2f\xf4\xcb\xe0\x9c\x0a\x52\x55\x75\x68\x06\xb2\xa3\x78\xd2\x08\x36\xcd\x15\xf0\xf7\xbd\x00\xcf\xf4\x87\x82\x71\xb2\xc4\x92\xb4\xbe\x92\xd3\xa1\x30\x24\xc2\x9b\x9a\x18\xc1\x92\x04\xc2\x2d\x84\xec\xc4\x50\x84\xec\x94\x90\x20\x5b\xa7\x4c\x86\x62\x94\xad\x90\x25\x63\xd6\xd4\xbc\xdf\xaf\x41\xd9\xb2\x10\x0a\xd2\x00\x4b\x96\xad\x12\x3d\x34\x5f\x8f\x01\x32\x88\xfe\xb8\x77\x38\x65\xfb\xda\xf5\x88\xae\x9e\x68\x52\x2b\xb3\x2c\x10\x4f\x4d\x81\xbb\x81\xec\x94\xe6\xc3\xd5\x81\x9c\x7e\xc5\x39\xdc\xe2\x36\x07\x98\x12\x42\xc8\x12\x88\x86\x54\x3a\x33\x11\x4f\x67\xb2\xc7\x93\x78\x0a\x57\x17\xe7\x9a\x17\x02\xce\x01\x9e\xf3\xeb\x38\x74\xd4\x71\xd2\xab\x23\x1d\x30\x1c\xdc\x0b\xf9\xa2\x2e\x18\x26\xf1\xc2\x59\x70\x39\xd3\x5f\xb9\x3a\x5d\xc2\x2c\xc9\x72\x27\x4e\xa5\xc8\x17\xe6\x82\xbf\x2d\xce\x99\xc4\x89\x14\x79\x61\xd2\x8c\x0e\xb9\x09\x69\xbb\x09\x8a\x74\x8a\xb2\x79\x9c\xf2\x6e\xcf\x44\xaa\x8e\x3d\x47\x9d\x76\x53\x30\xf3\xd3\x9b\xc4\x49\xe2\x64\x0b\x1e\xc6\xf2\x41\x07\xa0\x23\x93\x24\xcb\x22\x07\x2a\x34\xdf\x4d\x9e\x2c\x95\xce\x84\xcf\xe3\xc4\x7c\x2b\x6c\xdd\x7e\x39\x3c\xfa\xa3\x2c\xa4\x89\x90\xb9\x90\xe1\xac\x0e\x3c\x24\x26\x63\xcd\xc5\x80\xc0\x9d\x9e\x8e\x69\xf2\xb0\x98\x39\x29\x9f\x0b\xf3\x99\xe5\xb1\x48\xa5\x1e\xef\x2c\xcb\xe3\xef\x59\x2a\x79\xb2\x25\xf1\x56\xe4\x32\x0e\xd5\xe5\x50\xe5\x72\x78\x74\xeb\xdc\x9b\xef\x2c\x8f\xa7\x71\xea\xdc\xf7\xe2\x39\x9f\x8a\xce\xd4\x24\x42\x4a\x91\x3b\x0a\x92\x20\xa8\xba\x10\xa7\x53\x33\xe2\x39\xcf\x6f\x44\xee\x88\x34\xaa\x3f\xe7\x71\xf3\x09\x67\x49\x2f\xbb\x15\x39\xac\xeb\x02\x5c\x70\x64\x69\x1b\x23\x67\x71\x78\x93\xaa\x53\x7e\xc1\xe3\x54\x3a\x59\x1e\x89\xbc\xb7\xe0\x69\x56\x08\xc7\xef\x2d\x32\x58\x4b\x47\xdc\xaa\x1b\x76\xaf\xe9\x13\x2c\x71\x2a\x7b\xc0\x0b\xe9\x74\xb5\x90\xd9\xc2\xf4\x0b\x3e\xeb\x85\x28\x64\x1e\xdf\x08\x75\xef\x2d\xa7\xb3\xb6\x1b\xab\xd1\x6d\x5f\x0a\x99\x67\x37\xc2\x89\x78\x31\x03\x16\x4e\x37\x22\x9b\x4c\x0a\x21\xeb\x18\x35\x88\x90\x2f\xba\xc1\x3f\xb2\x38\xad\xc3\xc0\x84\x04\x5e\x64\x1d\xd3\xe9\x91\x0a\xde\xc5\x91\x9c\xf5\xa4\xb8\x97\x0e\x4f\xc3\x59\x96\xeb\xef\x48\x84\x99\x26\xed\x75\xb8\x1d\xa1\xba\x29\xaf\x4d\x66\x1b\xd5\x8e\xa0\x4c\xe3\x30\x8b\x84\x73\x1d\x47\x71\x13\x00\xb3\xa4\x2a\x24\x0b\x67\xa1\x66\x75\xde\xbb\x75\xb8\x22\x40\xaf\x85\x8c\xc3\xde\xad\x33\xe3\xe9\x54\xb5\x72\xeb\xc4\x91\xc8\xa6\x39\x5f\xcc\x20\x7e\xce\xe5\x4c\xcc\xb9\x06\x9d\x5b\x11\xca\x2c\x77\xc4\x64\x02\x8a\x49\x22\x97\x00\x47\x0f\xfa\xb3\x01\xa3\x6e\xe8\xa1\x77\x97\xe5\x51\x03\x42\x77\x79\x0c\x10\x34\xcf\x22\xd1\xbb\x9f\x27\x69\x11\xdc\x27\x71\x7a\xd3\xbb\x37\x1b\xfe\xaf\x29\xbd\x5a\x95\xbf\x66\xc7\x3f\xd0\x6b\xb2\xed\xb6\xb0\x41\x2f\x43\x43\x01\x0f\x65\xa9\xe8\x52\x13\xca\xc3\x3c\x4b\xea\x50\xe7\xb3\x98\x65\x77\xe6\x53\xc6\xb2\x89\x56\x48\xf2\xbf\xb1\x8b\xc8\x70\x37\xef\xee\xee\xdc\xbb\x7d\xe0\x5b\xf9\xaf\x5f\xbf\xde\x85\xc6\xd0\x0a\x99\x76\x3f\x4f\x02\x85\xa1\x10\x85\xcf\x84\xa7\x53\xf3\x09\x88\x1e\x8d\xff\xfb\xbb\xf2\x5f\x9f\x3f\xa9\xee\xbc\xda\x4d\xeb\xe3\x64\xb5\x4b\x92\x5f\x83\x0c\xb0\xba\x03\xe6\x59\x51\x9c\xc1\x92\xff\x14\x01\xe9\xff\x04\x85\x3e\x75\x61\x1a\xfe\x9e\x8b\x89\x29\x87\x9a\x08\xa4\x6b\x30\x6b\x3a\x83\x98\xbf\x9a\x4c\x38\xb5\xe9\x08\x15\x79\xa8\x32\xeb\x32\xda\xbc\xb0\xbe\xb1\xce\xb5\x6a\xc4\xff\xed\x00\x3c\xda\xf7\x1a\x0a\xf8\x9e\xe5\xee\xd5\x95\x61\x93\x7e\x3c\xbd\x38\xf9\x72\xfa\xe6\xd3\xd7\x9a\x61\xfa\xed\xeb\xc9\x56\x56\x29\x3d\x61\xda\x08\xcb\x0d\xd3\x76\x56\xbe\x32\x6d\x48\xe5\x1d\xd3\x66\x52\x7e\x63\xda\x0e\xca\x39\xd3\x86\x4e\xbe\x30\x6d\xca\xe4\x8c\x69\x8b\x22\x17\x4c\x9b\x0c\x39\x65\xda\x1c\xc8\x15\xd3\x36\x3f\x3e\x33\x6d\xd8\xe3\x23\xd3\xc6\x3b\xde\xc0\xef\x2b\xfa\x09\x7e\x5f\xd3\xef\xea\x77\xdf\xa3\xef\xe1\x17\xa8\xb9\x9f\xb2\x29\xa3\x01\xed\x03\x6b\x63\x06\x27\xec\xc3\x86\x69\x19\x7a\xd3\x46\xd6\x96\x64\xe8\xd7\x36\xae\x35\x1c\x43\xdf\xb5\xb1\x2b\x76\x62\xe8\x6f\x9d\x2a\x1a\xb3\x30\xf4\x7c\x25\xd6\x58\x81\xa1\x5f\xda\xd8\xc6\xe8\x0b\x3d\xeb\xb4\xd7\x35\xc6\x42\x2f\x3a\x4d\x36\xb6\x57\xe8\xe9\x66\xac\x31\xb5\x42\xaf\xda\x24\x6d\x59\x85\x7e\x6e\x63\xb4\x21\x15\xfa\xb1\x8d\x31\x76\x53\xe8\x87\x35\x93\x26\xf4\x4d\x9b\x27\x5b\xf0\x3f\x4b\xe1\xc6\x11\x22\xf4\x53\x1b\x1d\x89\xeb\x72\x7a\x25\x73\x1e\x8a\x7a\x1e\xbe\x77\x0a\x4d\x26\x05\xf0\x00\x10\xa1\xef\x3b\x3d\x10\x53\x1e\x3e\x5c\xe9\x1b\x3a\xd2\x4c\xd7\xb7\xf4\x8f\x9f\xb0\x12\xa4\x0e\x2f\x2e\xb3\xbc\xbd\xae\xfd\xda\xb9\xae\x19\x9a\x52\xb4\x26\x0f\xfa\xad\x85\x77\xf0\x4b\xb3\xd9\x02\x16\xec\x0f\xcb\x12\xa3\x3f\xc6\x55\x25\x46\xe8\x7f\xfe\xcf\xba\x09\x34\x26\x43\xa1\x65\xca\x9a\xc6\x9e\x19\xc9\xd4\x86\xcf\xfb\x96\xc8\xfc\xe1\xb1\xcb\xbd\xee\x48\x26\xd6\x28\xae\x90\x3c\xbc\x71\x65\x1e\xcf\x31\x69\xc4\xe6\x52\xdc\xdb\xc1\x5c\xf6\xc8\x90\xec\x92\xc1\x5b\x90\x53\x32\xe6\xe3\xcc\xc5\x01\xa4\x9b\xdf\xda\x02\xa6\xe7\x1b\xeb\xfb\xed\xa0\xff\xa9\xd9\xda\xf1\x04\xf7\x45\x55\x7d\xab\x25\xdd\xd1\xe0\x1b\xeb\x7b\xe6\xa9\x08\xba\xe3\x2e\x72\xb1\xe0\xb9\xf8\xaa\xba\x70\xa1\x56\x69\xf0\x44\xbc\xb1\x3a\x39\x30\x92\xaf\x92\x80\xdf\x97\xae\x48\xec\xca\x20\xe9\x56\xb3\x5c\xb8\xc3\x71\xa5\x48\x5d\x1a\x0a\x44\x1f\x0b\x21\x83\x27\x2b\x5a\x12\xba\x21\x21\xf3\x45\x4c\x12\x11\x4a\xcb\x32\x1f\xad\x96\x98\x96\xcc\xdd\x88\xc6\x92\x8e\xc6\x6b\x33\x9f\x33\xb1\xdc\xcc\x28\xe8\x68\x4c\xa5\x51\x5d\x84\xb5\xd3\x37\xab\xae\x40\x29\x13\x4b\x61\xcc\x23\xb7\xc3\xe9\x16\xd9\xbe\xdc\x50\x4e\x8d\xa8\x89\x89\x27\x58\x58\x56\x6e\x59\x9b\x56\x3d\x34\x50\x74\x65\x10\x6b\x38\x31\x67\xf8\xa5\xda\x33\x9c\xe5\x5b\x62\x63\x96\x35\x5e\x53\x68\xc2\x78\x13\x18\xf8\x47\x2c\xb6\x2c\xef\x88\x25\x96\x95\x8d\xe2\x71\x9f\x31\x3e\x4a\xc6\x03\x92\x38\x8e\x56\x59\x6b\x73\x0c\x62\xc7\xa1\x89\xe3\xa8\x85\xee\xe4\x85\x5e\xfb\x7d\x30\x23\xa2\x7e\x12\xa2\x9d\x5c\xab\xdc\xde\xb1\xe3\x24\x55\xd5\xcd\xdd\x01\x55\x15\xdd\x5a\x58\xec\x71\x09\xc2\x16\x88\xc2\x27\xaa\x9d\x34\xb7\x1d\xa8\x7d\x5c\x2c\x97\x93\x38\xe5\x49\xf2\xf0\xa8\x80\x9c\x3e\x05\x9f\xb5\x5b\x24\x2c\x98\x18\x0a\xb7\x63\x45\xae\xaa\x84\xab\x75\xb5\x11\x19\xaa\x2d\x1a\xa0\x8e\x9c\xc2\xdf\xd5\x4a\xd4\x86\x8f\x5c\xc9\xa7\xe6\xbe\xdf\xdc\xe5\x9f\x61\x63\x59\x49\x5f\xe6\xfd\x97\x6d\x02\xfa\x04\xb8\xd2\x24\xec\x77\x12\xbe\x36\x78\xd8\x24\xbe\xde\x92\xf8\x09\xb0\xb1\xce\xe0\x69\x43\x4a\x7b\xfa\xc7\x6f\x5a\xff\xa7\x69\x5d\xd1\x00\xa6\x2a\x7f\x3d\xcd\xd5\xc4\x76\x9b\x65\x6f\x6f\x23\xcb\xd5\x7a\x1e\x7f\xb3\x05\x6f\x9d\x71\x82\x50\xe7\xf5\xf9\xcf\x35\xb1\xfb\x35\x77\x3d\xdb\xac\xd0\xb4\x5e\x9e\xb6\x2c\x87\x66\x70\x6c\x37\x07\xde\x14\xac\x79\x4d\x35\x17\xe6\x6b\xdd\xb3\xda\x92\x90\x56\x08\xea\xdd\xd4\xf1\xda\xd6\x8f\x89\xfd\xad\x89\xad\x0f\x5c\x1d\xff\xae\x8e\x6f\xed\xf8\x98\x94\x8b\x26\xa5\x5e\x40\x1d\x7f\xba\x1e\x0f\x6b\xb7\xdc\x6e\x97\xbc\x81\xa6\x35\x0b\x5a\x5f\x82\x1a\x44\x57\xe7\x03\xbd\xab\xcf\x78\x1b\xb9\xb5\xd5\x27\xd3\xf0\x79\x5b\xe6\xca\x90\x02\x3f\x28\x5c\x5b\x80\x32\x85\xcf\x82\x96\x8c\x56\xab\x5f\xbf\xa9\x4b\xb6\x56\x89\x34\x2b\x82\x10\x5d\xeb\x1b\x46\xa8\xcf\x98\x1c\xa2\xd6\xcc\x13\x86\x87\x60\x82\x82\x4e\x5c\x0d\xc6\x57\x41\xe3\x50\x66\x65\xd7\x7c\xec\xc6\x1b\x58\x34\x49\x9f\x03\xd5\xc1\xab\x05\x7f\x48\x32\x1e\x51\xa1\x02\x71\x1a\x4b\x38\x6a\xda\x52\xe0\xc4\xb5\x63\x5f\xb0\x03\x7e\x2d\x8c\xfe\xa3\xb3\x99\x9b\xe5\x78\xdc\xaa\x32\xa6\x35\xce\x56\xd4\xc2\x56\x14\xd5\x20\xd0\xbe\xf2\x3e\x65\xe0\x6c\x65\x8b\xfc\xef\xee\xb1\x0e\xe6\x1f\x5b\x9c\xe4\xa6\x59\x04\xfc\x2d\x62\x59\x28\x4e\x17\x25\x28\x34\xac\x51\xe2\x96\x85\x35\x7b\xff\x3a\xbb\x47\xfa\x09\x11\xe5\x3c\x8a\x35\xdb\xb7\xc3\x5d\xfe\x9b\xb6\xf4\x7e\x05\x4f\x43\x0a\x01\xde\x88\x1c\x6c\xf4\xaf\xc4\x6c\x71\x54\xfb\xbf\x41\x69\xbb\x7e\x42\x08\xcc\xdb\x52\xab\xa6\xf3\x94\xcd\x4b\xbc\x62\x69\xa4\x73\x8c\x4b\x02\x66\x0d\x6c\x31\x92\xda\x80\xa4\xd8\xe4\x73\x77\x6c\x8e\xa7\x5b\xd5\x0d\x53\xd5\xee\x13\x29\x85\x90\x35\x0b\x1d\xb2\x81\x77\x88\x42\xc8\x55\x55\x9d\x75\x4a\x43\x50\x49\x1f\xc3\x2c\x9d\xc4\xd3\x12\xf4\x87\x8c\x89\xd6\x60\xd3\xd9\x41\x66\x0e\x73\xed\x59\x61\x85\x1a\x81\x63\x5b\x0d\x8e\xf2\x36\x13\xd8\xa8\x25\xf4\x07\xed\x8a\x46\x6b\x29\x48\xdd\x36\xb0\x24\xf4\x71\x2a\xf4\x53\xea\x96\x7e\xe4\xd0\xf8\x5a\x6a\xd3\x83\x25\x2d\x64\xb6\x80\x85\x8d\xd3\x69\xb7\xf8\xfa\xa2\xd7\x0a\x13\x42\x8a\x9e\x5a\x95\xe5\x72\xb9\xc4\xa2\x2b\xab\xfc\x2f\x83\xca\xfb\x62\x55\x85\x07\x36\x62\xb7\x2e\x58\x50\xd9\xb2\xcc\x35\xe9\x08\x50\x02\xfd\xc4\x7a\xf1\x07\xad\x48\x20\xce\x35\x88\x09\xd7\xc0\xd8\x10\xc9\xbc\x14\x28\x40\x13\x9e\x14\x02\x05\x42\xfb\xb9\x00\x8f\x97\x39\xd1\x10\x81\xa5\x5b\x8f\x1c\x0b\x02\xd7\xd0\xa6\xaf\xff\xb5\x4e\x53\xab\xcd\xa4\xf0\x52\xbb\x37\x1b\x2a\xbe\x96\xa7\x18\xd6\x1f\x81\x71\xe2\xbc\xea\x5c\xae\x83\x58\x84\xab\x2e\xd2\xb7\xb5\xe8\x85\x3a\x9b\xae\xb3\xe8\xc1\x20\x9a\xae\x30\x24\x44\xb7\xdd\xfa\x5f\x5d\xa5\x17\x59\x0f\xb6\x11\xcf\xc3\x8f\x4b\x05\x08\xab\xef\xe5\xa6\x37\xb4\xfb\xa4\x5e\xc7\xdd\x76\x03\xa6\xb6\x40\x3f\x48\xa4\xc3\x34\x10\xee\xd5\x5d\xce\x17\x0b\x91\x83\x71\x61\x57\x21\xc8\x98\x27\xa6\xe2\x65\x67\xbe\x84\xe8\xf6\xcc\x3c\xf3\xb8\xdd\x26\xc1\x1a\xfa\x4a\x0c\xcd\x8d\x0e\x41\x33\x90\x61\xf3\xd5\x66\x35\x8d\x0d\x52\xf6\x8f\xda\x95\xbc\x5e\xcb\xa1\xf9\x0d\xc0\xbf\xf7\x4a\x47\xd9\xe3\x6a\x4f\x83\x9c\x9a\x08\x3d\xfa\x94\x9a\x47\xde\x44\x44\xc1\x2a\xea\x03\x04\xba\x82\xff\x20\x66\xb8\xd6\xd3\x60\xa5\x2b\x5d\x69\x39\x33\x11\x46\x9b\x43\xb6\x45\x88\xf6\x51\xd3\x3e\xa4\x4a\x60\xdd\x34\x25\x53\x53\xd2\xd4\x60\xa0\xfe\x1f\x58\xd6\xa0\x9b\x9b\xbe\xb4\x8f\x46\x29\x69\xd5\x3e\x59\x3e\x04\xb1\x67\x85\xea\x34\x8e\x87\x62\x0a\xb6\xe0\x43\xe5\x06\xbb\x7a\x10\x62\xf0\xb0\x12\x34\x69\x10\x5e\x4f\x6e\xbd\xa0\x14\xe5\xf5\x3c\x86\xa3\x23\x57\x73\x23\x0a\xa1\x03\x35\x80\x03\x04\x6d\xbe\x99\x18\x3c\x4f\x06\xeb\x46\x47\x9a\x94\x61\x06\xa3\xd5\xa4\x60\x4a\x82\xcd\x8c\x5d\x88\x41\xc4\xb2\xba\x05\xd4\xe4\x74\xd3\x49\xe3\xff\xb1\x9e\xf4\x5a\x3b\x65\x1d\x9c\x60\xa8\xab\x51\xac\xdf\x5f\xcf\xd5\x59\x9d\x5c\xd4\x92\xc5\xea\x0a\xfa\xd4\x70\x14\x4d\xf3\xe3\x01\xd4\xd7\xc0\x76\x29\xfb\xcd\xf4\xf6\xc1\xbe\x90\x99\xde\x3e\xcc\x75\x73\x82\x19\x28\x68\x6c\x24\xd6\x50\x61\x56\x60\x20\x01\x5d\x6f\xdf\xaf\x7a\xb7\xa5\x55\x25\xbb\x70\xd1\xac\xb5\x54\xfb\xa7\xdb\x4b\x26\x97\x40\x7f\xe1\x94\x69\xa2\x59\x03\x8e\x96\x17\x45\x9d\xdc\xed\xcc\xfd\x18\x53\x50\xa8\x2e\x6d\x6b\x49\x3b\x33\x9b\x35\x33\xdb\x01\x66\x69\x59\xff\x85\x85\x9b\xdd\xa5\x22\x7f\x6f\xd0\x2a\xd1\x5c\x94\xda\xbf\xde\x70\xad\xd3\x7f\x31\xfe\x60\x35\x7b\x17\xe4\xd7\xab\x49\xbb\xa7\x16\x17\xab\xf2\xe9\x2c\xc3\x8f\xb5\xf8\x92\xc1\x9c\x4b\x45\x8e\x60\xb9\x85\xee\x69\x0f\xa9\xdc\x7d\x67\x0a\x35\xec\x52\xb1\xaa\x55\xd0\xfa\x5e\x93\x36\x13\xc0\xd3\x95\x4b\xac\x20\x59\x97\x23\x7a\x15\xea\x20\x2c\x5b\x47\x03\x49\xac\x3c\xa5\x2b\xd2\x4f\x0b\x8a\x17\x80\x53\x40\xa6\xac\xb9\xd5\x7b\x83\xac\xd5\x81\xcc\xb4\x2e\xef\x33\x64\xa7\xa3\x6c\x3c\x66\x7d\x6f\x60\x8c\x33\x0d\xd2\x56\xfe\x3d\xb5\x6d\x92\xb1\x4d\xe8\x7e\xa6\x68\xb0\x74\x5c\xe3\x28\xf8\xae\xa5\x41\xfa\xf0\x36\x8a\x57\xe2\xc0\xb5\x2c\xb0\x1f\x74\xbc\x99\xfb\xaf\x75\xb2\x3a\x85\x81\xa7\xa1\xfb\x80\x90\xfd\x0f\x9c\x12\xe3\x27\x71\x9b\x26\x13\x8c\x76\x94\x99\x1e\x28\x04\xd8\x5c\xe3\x54\x6c\xd1\x56\x0c\x56\xfd\xb0\x6e\x39\xdb\xda\x32\x19\xd4\xbb\xab\xaa\x74\x1e\x23\xf4\x53\x55\x58\x32\x15\x43\x96\x75\x0e\x43\x3f\x74\xba\xdd\xd1\xca\x12\x0d\x2b\xac\x41\x3f\xdb\x05\xdd\xd6\x64\x4c\x5f\xfb\xad\x4e\x55\x7d\x9a\xaf\x9c\xd1\xdb\x0e\xf1\x06\x1a\xff\x62\x07\x74\xcf\xeb\x42\xac\x52\x12\xd0\x48\xd7\x79\x25\xf4\x9d\xb5\xd0\x47\xe5\xda\x79\x4e\xeb\x23\xa8\x33\xca\xf5\xd1\xec\x69\x07\x7e\xab\xee\xb2\x52\xa3\x1d\x85\xfd\xe3\xc6\x24\x04\x59\x2f\xb9\xaf\xd6\x02\xd4\x1e\x97\x92\xa5\x4b\x83\xd5\xb5\xf7\x32\x44\x68\xca\xe4\xf2\xa9\x33\x5f\xcf\x8d\x82\x9a\xce\x8a\x94\x2b\xe3\x5d\x39\x54\x37\x0e\x11\x03\x04\x0a\x37\x68\x08\x4c\x49\xbf\xc1\x9b\x9d\x33\x32\x6d\x4f\x9b\x6e\x79\xcb\xda\xc0\x34\x5b\xd0\x4c\x6a\xce\xaa\x3e\x98\x94\xdb\xc4\x41\x79\x57\x5e\x58\xac\xdc\xf0\xb4\x91\x66\x29\x52\x39\xd0\x08\xfd\xe9\x25\x57\xb4\x80\x06\xd6\x0e\xd8\xb6\x78\x5f\x0b\x16\x0b\xf6\xe4\x5b\xd0\x4c\xce\x93\x8e\x5b\xb5\x89\xe8\xb2\xad\x6a\x1b\x2b\xb7\x8d\x81\x95\x2d\xf5\xec\x79\x9e\xb7\xab\xb2\x68\x49\x9c\x39\x97\xb3\x1f\xe4\x86\xf7\xb3\xcf\x5c\xce\xe0\xcf\xe7\x4f\x68\xfd\xde\xfb\xc3\x8e\x76\xd6\x7b\x21\x36\xbc\x04\x6a\x16\xfc\x0f\x2b\x00\x7f\x7c\x13\x90\xf5\xf8\xd1\x50\x18\x98\x28\x46\x93\x2c\x17\xf1\x34\x3d\x6b\xfc\x96\xc8\xe1\x8f\xab\x0f\x34\xd7\x7c\x26\xe8\x5c\xd0\x5b\xc1\xf0\x7c\x5d\x4d\x5a\xd1\x5a\x3f\x68\x18\xc0\xb0\x79\x5e\xfc\xf6\xe5\x63\x55\xa1\x46\x1a\x16\x69\xe7\x71\x6e\x13\xc1\xe4\xa0\xc1\xa4\x78\x26\xd8\x4c\x54\xd5\x76\xd9\x6f\x8c\xa2\xf8\x16\x11\xd2\x29\x8b\x8e\x8a\xdb\xe9\x31\xb2\x65\xed\x20\x10\x77\xb4\xdb\x88\x8d\x8e\x76\x21\x9d\x4a\x36\x13\xee\x24\xce\x0b\x09\xe7\xdb\x60\x25\x40\x6a\x92\x10\x82\xb8\x9b\xa6\xb5\xb1\x06\x72\x2d\xbb\x82\xe3\x34\xd2\xd9\xbb\x69\x64\xb9\xa4\xdb\xee\x5e\x9f\xbf\xbe\x59\x2c\x2c\x0b\x7e\x40\x6d\xfa\x5b\x5a\xf0\x89\x00\x37\x3c\xb5\x36\xf9\x70\x53\xd8\xec\x87\xf9\x3b\xef\x98\x0d\x00\xcd\x35\x3c\x2d\x09\x59\x06\x73\xd1\x51\xae\x98\xb6\xa8\xbe\x63\x8d\xa0\x33\x28\x6d\x14\x27\x85\x8d\x9a\x70\x13\x6b\x59\xfb\x20\xe1\x96\x66\x91\xb8\x68\xa5\xdc\x80\x8e\xc6\x3a\xfa\x9f\xf5\x1e\x5d\xd9\xf1\x4c\x02\x08\x3d\x08\xf6\xc8\xd3\x78\x0e\xa2\x0f\x1f\xe1\x6d\x28\xce\xd2\x77\x59\x99\xca\xa0\xef\xd1\x6b\x10\x0f\xf9\x38\xe7\x53\x71\x56\xca\x42\xac\x47\x7e\x4d\xe2\x50\xac\xc5\xfd\x1a\x47\xda\x01\xcc\x75\x76\xff\x21\x11\xf7\x9d\x4f\xf0\x4d\x6b\xc2\x67\x79\x14\xa7\x3c\x69\xa2\xc2\x2c\x29\xe7\x6d\xcb\x3a\x08\x1e\x55\x26\xa6\x92\x89\xae\xe1\xae\xfe\x3e\xcf\xb4\xee\x5e\x1d\xfe\x3a\xcb\xe3\xf4\xa6\x0e\x9d\x8a\x29\xef\xa6\x9e\xe5\xc6\x61\xcb\x34\x8f\xa3\x37\xb9\xe0\xf5\xf7\x17\x5d\xa3\xf9\x3c\x49\xa3\x4e\xe8\xeb\x82\xa7\xdd\xa0\xe4\xb9\xac\xc3\xef\xa0\x87\xab\xa1\x4e\x69\x1d\xd1\xad\xc0\xc4\xd4\x75\x4c\xb2\x54\xfe\x0a\xc2\x17\xe0\x37\x27\x4e\xc5\xbb\x84\xcf\x17\x75\xe0\xef\x4d\x92\x91\x60\x81\xcf\x7a\x10\x59\xbe\x98\x71\x3d\x3d\x92\x5f\x7f\x8d\xbf\xc3\x38\xef\xe2\x28\xbb\x83\xc8\xef\x20\x21\x00\x5f\x59\x36\x87\xe6\xe2\x24\x39\x6b\x6b\x02\xb9\xa9\x4e\xb8\x90\xd9\x62\x25\x98\x67\x37\xe2\x7d\x2d\x8f\xb3\x1a\xa5\x25\x72\xda\xb8\xcf\x8d\xd0\x4d\x1b\xb7\x51\x57\x0d\x16\x4b\x7a\x2d\xd8\x08\xfd\x2a\xae\x6f\x62\x89\x28\x9a\x17\x88\xa2\xcf\xd9\x77\x44\xd1\x19\x1a\xb7\xfb\xe1\x4e\xac\x99\x90\x68\x44\x3e\x1b\x5e\x68\x6b\xc1\xac\xaa\x90\xc1\x9b\x28\x48\xb7\x58\x11\x92\x55\xe5\x69\x7e\xe4\xc3\x06\x7f\x4f\x5d\x4a\x1e\xc4\x48\x8c\x87\x18\x21\x5b\x12\xf3\x94\x19\x48\x1b\x2d\xee\x3b\x2f\x2d\xf7\x62\x4d\x45\x1e\x9c\x6c\xc2\xc3\xd6\x43\xa2\x52\xb6\xdd\xe7\xd2\xe6\x9e\xa6\x25\x51\x1b\x9f\xf0\x8e\x83\x08\xcd\xd8\x9d\xc0\x29\x95\xa3\x74\x4c\x73\x32\x40\x93\x24\xe3\x70\x00\xa4\x20\x4a\x89\xc2\xa2\xf8\x00\x51\xa4\x96\x04\x6c\x2b\xa6\x19\x09\x14\xe1\xcb\xb2\xe5\xb2\x6b\x57\xe6\x41\x3c\x21\x1d\x73\x2d\xb6\x9b\xb2\x92\x4c\x1a\xf5\xe3\x5a\xf5\xb8\x23\x10\x6c\x8b\x8e\xfd\x55\x9f\xd0\x07\x31\x92\x63\x06\xd3\xa5\x50\x98\x91\xb6\x38\x81\xcb\xcc\x5c\xa4\x65\x2c\xc5\x1c\x16\xf9\x91\x9b\x2d\x76\xcd\x0b\x8d\x21\x72\xb3\xad\xd5\x8f\x98\x5f\x0b\xd8\x29\x33\x88\x8d\xe7\x53\xf8\x49\x17\x25\x80\xd0\x8d\x78\x98\x8a\xd4\xec\x04\xd8\xd1\x73\x21\xa1\xb6\x05\xcf\x39\x80\xb3\x16\xf6\x07\xf8\xcf\x79\x08\x79\xee\xa0\x89\x65\x07\xa7\xde\xac\xe0\xd4\x78\x82\x4f\x54\xc7\x1b\x99\xdd\x96\x28\xd5\x8f\x39\x3f\x22\xaf\xd7\xe8\x4a\x7f\xff\x90\x0a\x4d\x94\xfe\x55\xc9\x2e\xf1\xde\x5c\xc1\x56\x6b\x7b\xe9\xe9\xaa\x36\xde\xf5\x9f\xac\xb5\xaa\xfa\x18\x5d\x5d\x01\x35\x10\xa7\xbd\x9f\xee\xf7\x4b\x5f\xbb\xb6\xab\x3b\x04\xb0\xdb\x9a\x5a\xeb\x34\x0c\x29\xeb\xa5\xf7\x48\x97\x16\xfe\xda\x4e\x2f\xf8\x4b\x14\x1d\xf0\x6e\xcc\x2b\x6d\x9a\x1b\x74\xe3\x62\xed\x5d\x0c\x81\x7d\x2b\x2d\x30\x79\x3f\xaf\x8d\xe1\xad\xc8\x8f\x9a\x38\x23\xe0\x19\x6e\x84\x9d\x22\x0f\x37\xe2\xca\x3c\xde\x88\x9b\x80\xef\xfd\x8d\x68\x45\x0c\x99\xc8\x79\x5c\x14\x71\x3a\x75\x40\x98\xb3\x11\xf5\xf6\xd7\xa5\xb2\xbd\xce\x4c\xbc\x13\xad\x9c\x86\x96\xf4\xe6\xf9\x54\x00\x3f\xb6\xc8\xc3\x86\x3b\xab\xf5\xe6\x88\x0b\x36\xc6\xc1\xfd\x4e\x9c\x4e\xbf\x15\x35\xf5\x04\xb6\x8b\xc5\x53\xa9\x84\xee\xc3\x1c\xd7\x47\xfd\x50\xb8\x0b\x9e\x8b\x54\x9e\x82\x16\x2b\x1c\xe7\xbf\x09\x7d\xbd\x3d\x37\xbf\x5f\xf4\x6f\xbb\x23\xce\x44\xfd\x72\xcf\xd2\x0c\x0b\x7d\x83\xda\x62\x9f\xed\xb7\xf5\xa5\xdf\x7b\xe5\x99\xcd\x6e\x64\x3e\xa4\x50\xed\x0e\xf4\x55\x2a\xcb\xb0\x24\xf4\x37\x81\x3b\x49\xd4\xbc\xcb\xca\x15\x98\xb9\x80\x0e\x9c\x8b\xe1\x17\xf5\xbf\x31\x41\x44\x82\x2f\x82\x8d\xc4\x38\x38\x17\xac\xc3\x8a\x38\x15\x18\xfa\x77\x2e\x6a\x63\xb6\xe7\x82\x4a\xf6\x05\xee\x97\x5f\x54\x48\x8f\x12\x06\x45\x25\xd8\x66\xda\xa2\x00\x79\x26\x8c\xf6\x63\x5b\xf3\xd5\x1a\x2f\x06\x77\x1f\xa7\x3e\x8b\x56\x55\xae\x9b\xc5\xc4\xb4\x19\x3f\xaa\xfe\xc1\xbc\xbf\x11\xec\x4a\xd0\x4f\x82\xf5\x7d\xfa\x5d\xac\x08\xb3\xbc\x57\x99\x8c\xe8\xce\xb9\x61\xbb\x31\xc6\xbe\x88\xaa\xc2\xaa\x02\xaa\x46\xd9\xa9\xf4\x83\x58\xb3\x47\xd5\x4c\x75\x73\xa9\x6e\x39\x13\xb0\xb8\xfa\x7c\xc9\x32\x9c\x92\x4e\x9e\x7c\x25\x4f\xca\xf2\x91\x1c\x0f\x44\xb0\xea\x80\x09\x65\xe9\xbb\x24\x0e\x6f\xea\x97\x44\x1d\xaa\x75\x4d\xeb\xc8\xf7\x59\x79\x9d\x88\xd5\x8c\x9d\xb8\xf5\xec\x9f\xb3\xb2\x10\xef\xb3\xbb\x74\x33\x66\x6b\xd6\xcf\xd9\xed\x96\x98\xad\x59\xbf\x2d\xd6\xc3\x5b\xb3\x9d\xa4\x52\xe4\x28\xc0\x39\xeb\xe7\x0d\xeb\x85\x54\x95\x8a\xc0\xe8\xba\x94\x12\xde\xe8\x58\xeb\x76\x0a\xee\x3f\xf5\xa3\x66\x55\x19\x3d\xa4\x3a\xa4\xe8\x66\x75\x9e\x41\x98\x10\x2a\x58\x3f\xd7\xe2\x1d\x9d\x07\x55\xb5\xec\x0a\xb5\x6e\x88\x16\xa4\x5b\x2d\x20\xae\x9f\x01\x7b\xfb\x3e\x95\xb4\x49\x6c\xb8\x37\xa9\x96\x1f\x03\xa0\x8a\x27\x38\x02\x91\x2c\x15\xf5\x87\x60\x8f\xcb\xc1\xf6\x67\xbc\x3f\x04\x45\x0b\x5e\x14\xf1\xad\x40\xf0\x68\xd7\x7d\x70\x53\x75\x79\xcb\x25\xa1\x46\x8d\x97\x47\xd1\xc9\xad\x48\xe5\xa7\xb8\x90\x22\x15\x39\x46\x52\x14\x12\xd1\x3f\x04\xfd\x43\x34\xb9\x8c\x1e\xe6\xd3\x19\xcd\xa3\xd3\x5c\xe8\x16\xfc\x16\xa4\x7f\x15\xab\xba\xa7\x34\xa1\x45\x6d\x03\x43\xb3\x74\x5a\x45\x56\x50\x8a\x31\xa6\x58\x6b\x45\x6f\xba\xaf\xfd\xf4\x49\x63\xac\x34\xa5\x65\xe7\x2d\x1d\xb4\x44\xb3\x54\xcf\xa3\x20\xda\x2c\xc5\x33\xd8\x8a\xdf\x0c\x82\xf8\x27\x84\xfe\x6e\x42\x7f\x0a\xf6\x68\xf2\xaf\x3c\x54\xaa\x32\x9e\x2a\x23\x96\x1d\xbd\xd9\x7f\x6c\xed\xfc\x6a\xfd\xbf\x0a\xd3\xb3\x3f\x45\xeb\xd5\xb2\xb3\xa7\xff\x77\x97\xef\x42\x53\x06\x7b\x59\xb8\x3c\x01\xd5\x45\x29\x88\xb9\xc2\x1a\x16\x3c\x91\xac\xf9\x86\x8b\xb7\x60\x72\x10\x65\x8f\x5e\x9f\x61\xdf\xdb\x7b\xa9\x30\xae\xa2\xf2\x12\x3e\x2d\xb4\xd2\x4d\x9d\x5d\x81\x66\xfd\x6d\x24\x92\x44\xe3\xcf\x74\x5f\x3f\x42\xf1\xe9\x30\x5d\x13\xfc\xfb\x5b\x7d\x2a\xf8\xfa\x88\x01\x31\xa2\x1a\xd7\xcf\xc5\x3c\x8b\xbf\x1b\xb7\xa0\x1d\x04\xd3\xf2\x82\x60\x1b\xb5\x83\x81\x13\x61\xad\x5c\xcd\xa3\x62\xf5\x6b\xac\x22\x59\xc4\x0c\xf4\x69\x45\xb4\x5d\x1a\xe2\x5f\x75\xaf\x60\xfa\xfa\xad\xad\xcc\x86\x08\x7b\xf5\xaa\x8b\x39\xff\xab\x3d\xdb\xb6\x89\x62\x37\x1d\x34\xaf\xc2\xad\x30\x10\xc3\x92\x41\x1b\x64\x5b\x03\x8d\xd4\x89\xea\x81\x96\xb3\x14\xcb\xd6\x4e\x96\xa0\x39\x93\x83\x41\xfb\xc6\x6f\x16\xae\xad\x3d\x33\xbe\x02\xb4\x25\xab\x6c\xb5\x23\x26\x0f\xef\xea\xad\xe1\x9c\x65\xf5\x82\x92\xc7\x94\xe5\xad\x45\x29\x2d\x53\x16\x4f\x70\xa6\x69\x49\x30\x66\x0f\x5f\xfa\x62\xa2\xea\x87\xe0\x80\x6b\xeb\xed\xbc\x7b\x5c\xfc\x4b\xe0\x8c\x50\x68\x97\x77\x8f\x08\x1d\x2f\x07\x9c\x71\xb7\x88\xaf\x93\x38\x9d\x2e\xb7\x4d\xb5\xea\xa2\xe9\x58\x9f\xb1\xbc\xee\x63\xca\x32\x9a\x33\xde\x32\x89\xb4\x6d\x83\xbe\x4f\x8b\xa6\x3b\x85\xee\x4e\x01\xdd\x79\x4c\xd4\x4e\xab\x8b\x35\x63\x2a\xa0\x4f\x3a\x31\x67\x19\x4d\xff\x1f\xee\xde\x85\xb9\x6d\x1c\xf9\x17\xfd\x2a\x16\x2b\xc5\x02\x6e\x10\xfd\x25\xbf\x92\x50\xc1\xaa\xf2\xdc\x49\x26\x99\x64\xf2\x98\x99\x8c\x8f\x2b\x05\x8b\xb0\xcd\x09\x05\x2a\x20\x68\xc7\xb1\xb4\x9f\xfd\x16\x1a\x0f\x02\x24\xe5\x64\x76\xf7\x9c\x73\xeb\x4e\x4d\x2c\x12\x04\x41\xa0\x01\x34\x1a\x8d\xee\x5f\xfb\x87\x35\xad\x7d\xc5\x74\xef\xd9\xb8\x0f\xb5\x6b\xfc\x70\xf1\x4c\x97\xb2\xad\x78\xa6\xbf\xbf\xb5\xf8\x6e\xeb\xef\x6b\x21\x06\x9a\xef\x7b\x0f\x60\x5c\x3a\xf9\xee\x4f\x0c\x95\xf6\x00\x02\x48\x4f\xa3\x1b\x06\x94\x68\xd7\xf6\xb1\x8d\xa2\x67\x5c\xc6\x32\xb5\x01\x3b\x82\x78\x25\x69\x81\x37\xf8\xcc\xb4\xf6\xc0\x4d\xe8\xf5\xfa\xd0\x5d\xfa\xe9\x05\x20\x9d\x76\x68\xd8\x5f\xdb\x5f\x54\x11\xe5\xf6\x22\x33\x87\x60\x05\x0a\x60\x3b\x50\x81\x1b\x8d\x94\x23\x89\xf9\xd8\xc8\xf1\x95\xf5\xda\x5d\xd1\xae\x1d\x5d\xcb\xb7\x36\xfe\x6d\xff\x51\x7b\x01\xdf\x76\xc4\x1e\x9e\xf8\x2f\xba\x3b\xed\x68\xf6\x3a\x46\x62\xaa\xa5\xcc\x12\xad\x82\x61\x3e\x9a\x84\x15\xf1\x6e\x8a\x20\x41\x2a\xa2\x14\x11\x8a\x48\x45\x2a\xa5\x47\x28\x53\xf4\xe8\x98\x14\xf6\x58\xa8\xb4\xbf\xb5\xfd\x6d\x14\x78\x1e\xbc\x62\x2b\xb2\x68\x2f\x73\x78\xe7\x54\xd1\x64\xa9\xa5\x8d\xbc\xba\x14\x3b\x70\xd5\xac\x76\x54\xd5\x2c\xce\x17\x4c\x2c\x78\x69\xae\xb9\xc8\xcd\x85\x71\xcd\x62\xcd\xd7\x85\x16\x9a\x76\xf2\x93\xd2\x5c\x58\x97\x2b\xfb\x8e\xbd\x83\x32\xed\x75\xb3\xda\xc9\x25\x3b\xd3\x05\xe9\x5f\x53\x4e\x2e\xab\xd5\xce\xa2\x5a\x3a\xa7\x24\xfd\x34\xb8\x35\x99\x3e\xf3\x2b\x28\xe8\x33\xbf\x02\xfc\x02\x7d\xd1\xac\x76\x40\xd2\x01\x3f\xa7\xe7\x70\xb5\xa8\x56\x57\x3b\x0b\x13\xaa\x48\xf1\x1d\x53\xad\xc5\x39\x38\x2f\x59\xa3\x3d\xbd\xb7\xdf\x81\xf3\xe4\x1d\x7b\xc6\x1c\x78\xe3\xb4\x8b\xe5\x4a\xf5\x45\xe7\x6b\xb0\xbf\xe7\xf9\x6b\x91\x71\x92\x57\x4b\x10\x21\x20\x3c\xb2\x22\xe0\x66\xf6\xee\xaa\x56\x7c\xf9\x4c\xaf\x66\xd9\xf4\x70\x2d\x88\x00\xc5\x1d\xe4\xcb\x2a\x62\xb6\x52\x8f\x4d\x00\x0e\x2e\xeb\xec\x48\x1e\x07\xa2\xfc\xb9\x32\x83\xa5\xb3\xa3\x04\xd7\xff\x42\xf8\x7d\xde\xa2\xa9\xab\x46\x25\x99\xed\x69\x33\xf1\xcd\x51\x82\x21\xae\xf2\xf6\x74\xfa\xbe\xe4\x4c\x0b\xa5\x65\x3f\x37\x74\x74\x75\xe1\x73\x9b\x7b\x5d\x74\xdd\xcf\x6c\x7b\x30\xc8\xee\x52\xf4\x0b\x0d\x40\x77\x72\xc5\x91\x1a\xdb\xf4\xe7\x39\x0e\xdf\x3f\xab\x94\x1f\x1e\xa1\x9c\x5b\x56\x75\xff\xc1\x60\x69\x01\xa5\x96\x2a\x94\x64\x06\xdc\x0a\xf8\x38\xa0\xfc\x88\x52\x36\x47\x9c\xae\x14\x6a\xdf\x21\xed\xe9\x8f\x5b\xab\x94\xde\x48\x2a\x8c\xd3\x54\x29\xbd\x09\xe4\x38\x43\x7c\xdc\xed\xd8\x35\x95\x44\xf9\x7d\x71\xdb\x99\xae\xc0\x2a\x4d\x41\x85\xa0\xbc\x0a\xa1\xd2\x25\x9a\xfd\xa1\x5e\xb3\x82\x75\xfe\x42\xb5\xcb\xba\xaa\x90\x2b\x34\x50\xc6\x50\xbf\x7f\xfa\x55\x6f\xed\x22\xe7\x68\x27\xe5\xe8\x8a\x03\xc3\x8c\x56\x5e\x45\xff\xc9\x21\x02\x75\x6b\x38\xe5\x46\x2f\xb5\xd1\xdc\xa4\x42\x7c\x5c\x32\x2d\x6d\x17\x95\x2c\xd4\x15\x09\xd5\xfc\x6c\xdc\xe8\xc9\x77\x52\xf2\x4f\xb2\x11\xbf\x17\xea\xdc\x65\x43\x7c\xbc\x1a\x7a\x43\x28\x04\x20\xf1\xfa\x7f\x67\x27\xb3\x67\xe5\xab\x60\x85\xb0\xb2\x52\xa4\xe0\x0f\x6b\x67\xce\x01\x40\xba\x0b\xd7\x15\x47\xe9\xe7\xe2\xb4\x02\xa9\x0f\x6f\xc2\xb7\x62\xc6\x7b\xa6\x02\x23\x69\x38\x23\xf2\x39\x87\x80\xbc\xfb\xdd\x39\x9b\xb4\x5b\x6f\xd7\x05\x7f\x68\x7a\x85\xf3\x9e\xf4\x87\x07\x51\x47\x93\x63\x12\x8d\xbf\xb8\xd7\x82\xb1\xea\x07\x9d\x08\x06\x5d\xd8\x24\x32\x9a\xce\xd4\x18\x5c\x9a\x91\x13\x7e\x47\x93\xb6\x95\x57\xca\x69\x96\xa1\xbd\x9a\xcc\x6e\xe2\x04\xa3\xec\x44\xd9\x98\x4d\xb0\x4e\xcc\x26\x0f\x58\xa7\x65\x9c\x32\x5d\xeb\xd9\x30\xb9\xae\x5b\xd9\x58\x54\x61\x47\xe9\x4a\x73\xfd\x5d\x2b\x7b\xfc\x5f\x21\xe7\x75\x44\x30\x5b\x93\x96\x66\x8e\x25\xb4\x99\xd2\x94\xc5\x8f\x47\x94\x16\x2a\x4d\xcf\x14\x2a\xc0\x1d\xdf\xf2\x55\xcf\x21\x4a\xf3\xb0\x84\x87\x65\xe7\x61\x6d\x1e\xd6\xf0\xb0\x76\x0f\x1b\xe5\x15\xd4\x57\x0a\x93\x45\x74\x1b\x20\x53\x58\x86\x1f\x36\xc1\x9d\x47\xc7\x03\x9b\x54\x6a\xbd\x86\xfe\x9b\x90\x60\x5e\xd6\x8b\x73\x9e\x37\x25\x7f\xcc\xca\xf2\x84\x2d\x3e\xa3\xe0\xd9\x2f\x95\x5c\xb2\xd2\xcf\xec\x13\x85\xc3\x1d\xc6\x57\x98\x1f\x01\xa0\x5d\xab\x42\xba\xd4\x6c\x92\x83\xf0\x17\x0c\x15\x7c\x7d\xa9\x10\x33\xbd\xd1\xc2\x46\x5a\xf4\x33\x15\x9a\xc4\xd8\x53\x02\xa6\x8e\xc4\xf1\x4c\x46\x4d\x03\xb3\xd4\x4e\xd3\x34\x5f\xaf\x24\x0a\x7a\xe2\x52\xf7\x04\xe1\x51\x07\x5c\xea\x0e\x08\xd2\x6a\x93\x56\x43\x5a\x40\xee\x98\xda\x0a\x5b\x7c\xfe\x3c\xaa\x21\x92\x34\xd7\xb5\xc3\xdf\xaf\x9c\x91\x20\x27\x6d\x01\x5e\xed\x85\x84\x2e\x64\x12\x16\x32\xc3\x17\x9a\x03\x7a\xc8\x84\x70\xd0\xe5\xed\xa0\x6b\x83\x6e\xab\x50\x41\x76\xdd\x22\xed\x1d\x75\xac\xd1\x8f\xb5\x44\x1c\x3b\x8a\xfa\x73\xa7\xdb\xfc\x98\x26\x97\xf6\x5a\xe9\x07\xaf\xaa\x6f\x26\x75\xa9\x2f\x14\x31\x7a\x97\xcf\x2a\x38\x1f\xe5\x22\xcf\x9e\x2a\x94\x3c\x74\x09\x09\x69\xaf\x9f\x8a\x3c\xc1\xc4\xe7\x2d\xdc\x59\xea\xf6\x37\xfc\x71\x6b\xf8\x1e\x08\x6e\xdb\xdf\x81\xd3\xc3\x04\x13\x25\x99\xf0\x82\x1f\x64\x7f\xef\x53\x12\x12\xdc\x40\xb5\x36\xe4\x1d\x84\x5d\x78\xac\x22\x48\xb0\x3f\x1d\xbb\x7f\x07\xfa\x51\x1f\x74\xe6\xc8\xe0\x1e\x8f\x3e\x87\xc9\x06\xa3\x51\x11\x41\x21\x19\xba\x58\xed\x14\x62\x07\x96\x54\x31\x64\x35\x0f\x8f\x1f\xab\xa8\x60\x2a\x8e\x94\x8f\x41\xc5\x37\x79\x9a\xa2\xc7\x8a\xde\x68\x4d\x60\x0f\xd8\x02\x52\x6b\x86\x96\x14\xc2\x43\xd6\x21\x6b\x2e\xfe\x59\x8d\xc3\xce\x6a\x6f\xc8\x40\x06\xdf\x43\x37\x67\x83\x0e\x69\x6f\x71\x44\xdc\x6e\x45\xda\xf7\xa3\x0e\x0a\xee\x8c\x0e\xfd\x8d\xa2\x7f\x2a\x94\x84\x95\x4d\x30\x79\xdb\x49\x2d\x82\x01\xf2\xba\xf3\xac\xb6\x03\xe1\xbd\x49\x8f\x3e\x97\x60\xf2\x4b\xbb\x5b\xf9\xd4\x5e\xbe\x52\xf4\x28\x61\x27\x95\x04\x78\x31\xf3\xfb\x46\x91\xb6\x54\x3d\x5a\xc8\xdb\x30\xa5\x1d\xa4\xe4\x75\x98\x6e\x06\x22\x49\x16\x4c\xac\x4a\x76\x65\xae\xde\xf8\x2b\x9d\x66\x61\x1e\xda\x47\xef\x7d\x42\xde\x98\x42\xcd\x26\x23\x48\x78\xec\x12\xf8\x72\xa5\x0a\x80\x84\x0a\xae\xc4\x42\x5e\xad\xd4\xc0\x75\x1e\xff\x9a\x68\xa6\xfe\xb7\x2f\x45\x43\xda\x1b\x93\xe6\x91\x15\x13\x40\x8a\x8a\x7e\x78\x9e\x33\xc5\xfc\xcd\x93\xf0\x66\xc9\x15\x8b\x9e\xbe\x8a\x13\x6a\x4b\x21\x7d\xfd\xce\x5f\xd7\xfd\xaa\xe8\xc4\x5e\x5d\x34\x01\x0b\xc0\x1a\x08\xae\x64\x75\xa6\xb7\x71\xf1\x65\xcd\xf9\x67\xf3\x3c\xb8\x52\x10\x27\x26\xbe\x02\xd7\xaf\xf8\x4a\x15\x4b\xde\xac\x72\xa6\xb8\xbd\xf9\x60\x6f\xde\x2b\x12\x8c\x29\x18\x16\xc9\x25\x03\x10\x89\xe0\x2a\x38\xae\x7f\xae\xba\x7b\xf6\x8e\xd5\x27\xdd\xf5\x8e\xab\x47\xe2\x98\x54\xfa\xe7\xf6\xf4\x78\x56\xd1\xa4\x12\xc9\x6d\x54\x1d\x4d\x3a\x60\x54\xb7\x2b\x0b\x91\x34\xc5\x98\x7c\x02\x1f\x0b\x24\x89\xd2\x83\xdb\x5e\x57\x98\x34\xa8\x22\x47\xf2\x18\x6f\x36\x28\x5a\xe4\x45\x75\x89\x91\x99\x6c\x0f\x15\xbd\xd7\x56\xf4\xa5\x63\x7a\xa0\x4d\x4d\xdb\xb8\xac\x0f\x15\x9d\x1e\x10\x50\xb2\xeb\x47\xbb\x9d\x47\xfb\x64\xd7\x3d\xda\xef\x3c\xda\x23\xfb\xf6\x64\x6c\x77\x3f\x75\x4e\x53\xc6\xd8\x7a\x8e\x74\x86\x5d\xa2\x70\xa6\xdf\xdc\xd3\xa5\x9a\xb4\x29\xd9\xdb\x35\x89\x8a\x4e\xef\xb7\xe9\x13\x97\x77\xf7\xe0\xd0\x25\xde\x27\xbb\x07\x87\x2e\xf3\xde\xc1\xbd\x7d\xf7\xe0\x9e\xcb\xbc\x3f\xb9\xef\x73\xdf\x25\xfa\xce\x65\xdf\x9f\xde\x3b\x9c\x4e\x7d\xf9\x87\xee\x0d\x45\x0f\x77\xef\x4f\xf7\x0f\x0e\x27\xee\xd1\x81\x7e\x74\x78\x77\x3a\xb9\x77\xef\x70\x3f\xe5\x90\xb6\x4f\x5c\x82\x79\x6b\xba\xb7\xbf\x3b\xbd\x7b\x77\xf7\x9e\x7b\x69\x8f\xf8\x24\x57\xee\xbd\xc9\xc1\xde\xe4\x70\xef\xd0\xe7\xf1\xcd\x9f\x4e\xee\xee\xdd\xdd\x9f\xde\xdb\xf5\x0d\x98\x92\x36\x0d\x67\xa6\x49\xe1\x5e\xef\x9b\x8a\x4f\xc3\xf4\xb8\x2d\xc4\xd9\x4b\x26\x78\xed\xc0\xea\x45\xd0\x17\x13\x7b\x1a\x36\x21\x15\x9d\x10\x66\x42\x08\x16\x92\xe7\xf0\x06\x29\x20\x0a\x03\x8c\x7e\x97\x54\xea\x52\x0b\x71\x66\xef\x6d\x1f\x53\x86\x25\x65\xa4\xa2\x30\x2a\xbc\xff\x82\x6e\x04\xa3\xae\xc5\x77\x53\x67\xde\x51\x53\x96\xfe\xab\x98\xe9\x17\xeb\x39\x92\xf4\xa5\x42\x35\x86\xb7\x4d\xc3\xcb\x94\x32\x0c\xde\x45\x2f\x15\x2a\xed\x13\xb3\xdb\x33\x45\x8a\xf4\x5f\x05\xb6\x6f\xb2\xe0\x4d\x08\x7d\x1c\xbd\xe5\x5a\xed\x95\xb7\x06\x09\x8c\x8a\x14\xa1\xc9\x3f\x90\xa4\x7b\xd3\x3b\xb7\x14\x92\x18\xcf\x27\xd9\xf4\xc1\x03\x89\x1f\x3c\x98\xe2\x3b\x53\x32\x31\xfb\x76\x65\x9c\x03\x26\x7a\x17\x95\x16\x66\xf7\xfb\x12\x36\x51\xd5\x03\x5d\xbe\xd7\x1f\x3e\x54\xb4\xda\x58\x6a\x80\x42\x9f\x0b\xc5\xc4\x59\x69\x09\x85\xed\x71\x6b\x9b\x6e\xce\x6a\x54\x4a\xa5\xde\xb7\xcc\x70\x45\xa7\x0f\x1e\x20\x61\x2b\xa4\x30\x26\x72\x6d\x26\xbf\x4a\xe9\xbf\x2a\x6f\xd0\xde\xf6\xf6\x13\x15\xc0\x1d\x68\xc2\x70\x7a\xc7\x8f\x8f\x83\x34\xee\x7e\x3c\xe7\x59\x38\xa0\xe6\xed\x4d\x16\xec\xf6\x9e\x0d\xea\x87\x02\x17\xe5\xa9\x75\x28\x76\x88\x68\x3b\xbb\x36\xc1\x7b\x21\x5b\xb7\xad\x47\x0a\xed\xee\xa7\xff\x52\x18\xcf\x9f\x29\x64\x26\x2a\xb7\x79\x27\xfd\xbc\x7a\x52\xbb\xcc\xf7\x82\xbc\xf7\xfa\x59\x61\x4a\xff\x0b\x94\x28\x6d\xa2\x9b\xb8\x26\x1d\x71\x7a\x30\xdd\xc5\xc4\x16\x12\xd7\x4d\xe9\xfc\xed\xb4\xb3\x6f\x28\xba\x7b\x78\x6f\x7f\xef\x60\xff\xe0\x10\x13\xd5\x51\xe8\xef\x1d\xe8\x89\x16\xcc\xb4\x47\x2a\x02\xc7\xbf\x13\x9c\xc3\xff\xa5\x62\xe0\xe7\xa3\x63\xd8\x20\xec\x4d\xff\x21\x0c\x64\xb3\x3b\xc6\xf7\x47\x25\xc1\xd9\x9f\xdf\x6c\xc7\xbd\xb7\xa6\xca\x4e\x55\x75\x67\x3a\xeb\xce\xca\x94\x4a\x12\x4d\x4b\x9d\x60\x06\x9b\x16\xb9\xde\x17\x4b\x5e\xe3\x23\xe5\x87\xd6\x31\x35\xe2\xfa\x2d\x45\x5f\x31\x75\x3e\x5e\x94\xdf\xf6\x76\xe7\xed\x65\x36\x10\x0e\x0c\x62\xf8\xcf\xf7\x76\xb3\xbd\xe9\x1d\xf4\x41\x37\xf1\x7f\x7e\x53\xeb\x09\x5e\x4f\x36\xe4\x83\x2d\xa7\xac\xce\xc8\x6f\xf6\xfa\xe5\x2f\xbb\xe4\x27\x45\x83\x35\xe6\x43\xcd\xe5\x23\xbd\x59\x29\xc4\x99\xdf\x32\x7e\x89\xb2\x74\x74\x40\xe4\x67\x05\x6e\x11\xfe\x60\x50\xb5\xa6\xa4\x2f\xf9\x7a\xfd\x9c\xdb\x35\xab\xa2\x1f\x15\x61\xf4\x25\x9f\xbd\xe4\xfa\x0d\x25\xaf\xae\x5f\x71\x54\x11\x97\xdd\xa3\x0a\xa0\x97\x9c\x32\xbc\x5e\x3f\x01\x70\x86\xf6\x48\x2f\x28\xf9\x8b\x42\x3f\x29\xf2\x51\x8d\x4f\x0a\x91\xc3\x9e\xd1\x17\x13\x7a\x55\xaa\x0e\xe4\xa3\xe6\x2b\x3f\x83\x59\x1b\xaa\xa8\xe6\x17\xfb\xa9\x19\xa2\xed\xd6\x35\x4d\xef\x4c\x1f\x9c\xb6\x4a\x3b\x8e\x31\x68\x0c\xa3\x6f\x10\xd6\x0e\x10\x1f\xcf\x80\x81\x22\xc3\xe6\x88\x0e\xc2\xaa\x34\x05\x9d\xae\xc4\xfe\x70\xa2\xb2\x36\x46\x9d\x4f\x79\x4f\x9a\x95\x42\xac\xfd\x1c\x68\xe9\x82\x6f\x16\xa7\x3d\x0c\x49\x52\xb5\x7e\xd6\x5d\x85\xb1\x03\x3b\x54\x74\x69\xb6\xd4\xfe\x15\x1f\x3c\x38\xd0\x18\xbb\x78\x54\x90\xbb\x1c\xcc\x1d\x68\x8c\x5d\xb4\x33\xc8\x5d\x0f\xe6\x8e\x54\xc6\xee\xc8\xd0\xeb\x73\x7d\xc0\x70\x23\x02\x31\xb2\x54\xa8\x01\x87\x56\xa4\x07\x41\x48\x77\x52\xe1\xb6\xd4\x01\x45\xb2\x0b\xde\x11\x16\x4f\x16\x41\xb9\x8b\x1b\xcb\x0d\xf0\x1f\x5b\xda\x3b\x27\x32\xdb\x81\x9b\xe7\x12\x28\x2e\x0d\x44\x93\xc0\x9b\x60\x84\xfe\xd1\x1d\x6f\xf4\x31\x47\x32\xd4\x53\xa1\x8a\xaa\x0a\x55\xd8\x2e\xb2\x8c\xfe\xca\x51\xd5\x19\x2c\x46\xe5\xee\x87\x55\x41\xd9\x58\xb1\xb3\x99\xd3\xf2\x16\x91\x76\xb7\xa2\xff\xe4\x88\xb5\xda\xdd\x6a\x66\xde\x8f\xf4\xae\xe6\x15\xb6\x5d\xf5\xba\x67\x22\x88\xb3\xb3\x39\xbb\x51\xd3\x1a\x15\xce\xac\x0f\x53\xe5\xd4\x37\xb6\x30\x4f\xa1\x8a\x58\x1d\x08\x30\xb2\x17\xf6\x00\x8a\x5b\x4d\x96\x12\x1d\x43\x2e\x21\x8c\x6d\x94\xf2\xd2\x8f\x12\x6d\x34\x64\xca\x05\x91\x6d\x9c\xd4\x8a\x5a\xbf\xc2\x42\xec\xbc\x50\xf3\x17\xce\xe1\xf5\x85\x0a\x4d\xc2\x09\xf3\xc8\x2b\xb3\xd6\x94\x4a\xa6\x29\x84\x29\xa7\xb4\xd2\xdb\x7e\x7e\xfb\xb6\xe1\x50\x05\x95\x77\x4c\xa0\x70\x45\xa7\x33\x05\xb8\x27\xe2\x48\xde\x51\x26\x2b\xbb\xa3\x8e\x67\x4a\x67\xf6\xd5\xa3\x4e\x9e\xe7\x64\xfa\x40\xcd\xa7\x77\xbc\x7f\x73\xe0\x1d\x19\x1d\xd9\x7f\xe6\x57\x8f\xab\xdc\x49\xd4\x89\x0b\x91\x03\x0e\x0a\x73\xe7\x4c\xed\x23\xe7\xe0\x34\x9d\xee\x39\x55\x20\x9d\xee\xe1\x8c\x53\x45\xa6\x13\xab\xa5\x82\x24\xb2\xb7\xfb\x80\xf2\xf5\xda\x18\x3a\xcc\x79\x28\x29\x04\x66\xfa\xa1\xba\x98\x05\xc9\x81\x51\x4b\x29\xba\xba\xc0\xf6\x64\xc5\xc7\x62\xdc\x29\xc4\x0e\xd8\xa7\x7c\x02\x68\x28\x80\x3d\xb7\x50\xe7\x9f\x8c\xb2\xf7\xb9\xa8\x95\x83\x53\x07\x24\x74\x8b\x94\x1e\xa8\x6e\x1d\xa6\xba\x79\xc1\xe1\xa2\xdb\x13\xe3\xf7\x26\xd1\x0c\x16\xdc\x33\x6e\x2e\xac\x35\xc6\x51\x71\x0c\xaf\x1d\x15\xc7\x54\xcd\x15\xaa\x70\x56\x1d\x15\xc7\x6d\xef\xe8\x22\x8b\xfa\x89\xb1\x65\x7a\x23\x61\x99\xe5\x39\xb5\x53\xa7\x72\x6e\x45\xfe\xc9\xbc\x9f\x94\x01\x96\xac\xb3\x5c\x30\x2e\x50\xf3\x4a\x64\xcc\x36\xa9\xa8\x75\xb5\xd8\x99\xd5\x1f\x54\xab\x15\xcf\xa9\x7d\xb8\xf1\xbe\x6a\x21\xc6\xd2\xf5\xca\x94\x6d\xab\x15\xc3\x2c\x15\x75\xaf\x06\x0e\x1e\x8a\xd3\x2e\x0d\x67\xc6\xdf\x2a\x2e\x6f\xde\x4d\x40\x38\x4b\x1a\xf1\x59\x54\x97\x81\xa1\x16\x0f\x1b\x04\xa5\x04\xf7\x74\x34\xc5\x64\x1b\xf1\x2a\x81\x0d\xec\x41\xd0\xee\xac\x17\xa0\x7f\x4b\x55\x3b\xef\xcd\x7b\x29\x5b\x2a\x6b\xce\x91\x1f\x35\x27\x27\xa5\x29\x28\x4c\xa0\xa3\x09\xbe\xa1\x33\xa0\xc2\x2b\x2e\xeb\xa2\x8e\x88\xbd\x21\x45\xfd\xc6\x24\xc3\x99\xac\xd8\x68\x81\x12\x36\x3e\x82\x34\x82\x2c\x04\xc9\x05\xbd\x86\x76\xbf\x39\x67\x35\xcf\x26\xe4\x04\x3e\x58\x67\x13\x62\x2a\x00\x70\x12\x13\xa2\x8a\x25\x7f\xa7\xd8\x72\x35\x24\x92\xf1\xb1\x7f\xbc\x5e\x3f\x61\x8a\x8f\x45\x75\x89\xf0\x86\xf4\x86\xda\x84\x14\xf5\x7b\xd9\xd4\x70\xbd\x21\xa7\x82\x96\x02\xe5\x02\x93\x95\xa0\xe0\xef\x98\x0b\x72\x7d\x51\xf0\xcb\x6c\x42\x72\xae\x58\x51\x66\x93\x0d\x26\xe7\x90\x6f\x25\x30\x59\xda\x7c\x2b\x41\xae\x0d\x88\xdb\x1f\xd9\x84\x98\xab\x8f\xba\xd2\x65\xc1\x85\xfa\xc3\x5f\xe9\xb4\x15\x3b\xe3\x7f\xd8\x5f\xc8\xa3\x64\xf9\x33\xbf\xd2\xef\x9d\x17\xa7\xca\x5c\xb2\xd2\x5e\x2c\xb9\x62\xe6\xea\x8c\xab\x57\x55\x5e\x9c\x16\xd6\xb3\x2e\x7b\x23\x88\x31\x42\x04\x3a\xe9\x0b\x4d\x27\xc9\x4b\xa6\x78\x6e\x66\xf4\x10\x79\x3c\x86\x84\x1e\x82\x41\xde\x39\x87\xb0\xb9\x56\x6b\x0a\xcf\x5b\xab\xe3\x39\x1f\xab\xea\xa9\x8b\x86\x13\x66\xcc\x3a\xc5\x6c\xc8\xb2\xba\x80\x27\x7f\x0c\x7c\x3d\xf1\x0f\x0d\xfb\xe5\xe3\x36\x37\xe2\x23\x4a\x17\x22\x4d\x91\xfe\x63\x04\x1e\xfd\xd4\x42\xc4\x5c\xad\xf8\x1c\xd5\x60\xcc\x6a\x28\x7d\x67\x21\xdc\x25\x69\xda\xf4\x8f\x6d\xfa\x47\x9c\x35\x82\xd6\x82\x4e\xc8\x42\x50\x8e\x49\xad\x87\xa6\xfb\xe2\xc7\x9b\xea\xf7\xb1\x5b\xbf\x8f\x59\x23\x36\x1b\x4c\x2e\xa0\xf3\x97\x02\x93\x33\xb8\x82\xfe\x5f\x0a\x72\x9d\x33\xc5\x40\xa9\x7b\xca\xa5\x1e\x26\x98\x5c\xb5\x19\xf4\x00\x89\x7b\x06\x72\x9c\xb4\x39\xf4\x50\xf3\x7a\x51\x30\x6c\x98\x10\x5e\xb2\x55\xcd\x73\xbd\x51\xd1\x03\xa6\xe6\x4d\xee\x3b\x01\xde\xbf\x0c\xc6\xe9\xa2\x2c\x56\x27\x15\x93\xa0\x5f\x1c\x6a\x5a\x94\xc1\x35\x2f\x7e\xcb\x5a\x69\x46\x89\xba\xd1\x5f\xa1\x9e\x97\x02\x93\xa7\x71\x8d\x75\xa3\x4d\x55\x3e\x0b\x7a\xfd\xb4\x5e\x64\xc9\xd3\x7a\xc1\x56\x3c\x21\xef\x56\x6c\xc1\x4f\x98\xcc\x92\x9d\x84\xbc\xe4\xa7\x2a\x4b\x1e\x4a\x59\x5d\xea\xcb\x84\x7c\x58\xd9\xdb\x0f\xab\x84\xbc\x05\x27\x25\x73\x0f\xd7\x09\x79\x52\x5d\x0a\x9b\x02\x46\xc0\xe4\x09\x2f\xb3\xe4\x09\x68\xc6\x13\xf2\x7b\x21\xb2\xe4\xf5\xbb\x84\xbc\xe2\xa2\xc9\x1c\xfa\x93\xbe\x49\xc8\xc3\xd5\xaa\xee\x24\xbd\x5b\xc8\xaa\x2c\xb3\xc4\xfc\xbe\xac\x16\x9f\x13\xf2\xaa\xfa\xf6\x46\x16\x02\x36\x58\x7a\x82\x25\x1f\x44\x91\x73\xa1\x20\x66\x4f\xb2\x21\xef\x04\xbd\xbe\x97\x25\x8f\xd8\xe2\xb3\x45\x4f\xbd\x9f\x25\xef\xd9\x49\x42\xa6\xbb\x59\xf2\xb8\xe4\x4c\x26\x64\xba\x97\x25\xc6\x4c\x98\x4c\x0f\xb3\xe4\x9d\x9e\xc0\x09\x99\xde\x35\xdf\x97\x55\x99\x90\xe9\xbd\x2c\x79\x58\xea\xd4\xfb\x59\xf2\x86\x35\x35\x4f\xc8\xee\x24\x4b\x1e\xb3\x55\x6d\x6a\xb2\x7b\xb7\x25\xda\xde\x2e\x90\x6b\x6f\x4f\xe7\x3d\xe3\x9a\x38\x7b\xfb\xe6\xda\x90\x61\xef\x40\x7f\x31\x4f\xc8\xde\x61\x96\xfc\x54\x2d\xf5\x3b\x77\x23\xca\xee\xdd\x0b\x28\xbb\x77\x3f\x26\xeb\xfe\x24\x22\xea\xfe\x41\x96\x3c\x17\x35\x97\xfa\xd1\x61\x4b\xdf\xa9\x6e\xe3\xb3\xa9\xbe\xd8\xcb\x92\x67\xbb\xfa\x62\x3f\x4b\x9e\xed\xe9\x8b\x83\x2c\x79\xb6\xaf\x2f\x0e\xb3\xe4\xd9\x81\xbe\xb8\x9b\x25\xcf\x0e\xf5\xc5\xbd\x2c\x79\x76\x57\x5f\xdc\xcf\x92\x67\xf7\x34\xa9\x26\x59\xf2\xec\xbe\xbe\x98\xea\x02\x27\xfa\x0a\x8a\xd6\x65\xef\xea\xb2\xa7\xba\xf0\xfd\xfd\x2c\xf9\xa5\x59\x1a\x7a\x4c\x75\xad\xc2\xae\xda\xdd\xdd\xcf\x92\x57\x5c\xb1\x64\x43\x1e\x0b\x7a\xfd\xb0\x54\x59\x62\x38\x64\x42\x2c\xa1\xb3\xc4\xf2\x51\x3d\x26\x14\xcb\x12\xcb\x38\x13\x02\x9d\x92\x25\x8e\xb9\x26\xe1\xd1\x55\x20\x27\xf6\x16\x50\x6f\x61\xda\x65\xbc\xf3\x7e\x12\xe2\x38\x1b\x8d\x10\xa7\x8f\xb5\x94\x8b\xd3\x74\x34\x82\x38\xe1\xfe\x4b\x6f\x02\xe7\xcd\x3f\x8d\x96\xe1\x6d\xb0\x76\x7c\xe6\x57\xd1\x8c\x05\xc3\xde\xcf\xfc\xca\x55\xee\xb3\x38\x82\xfb\xe3\xf5\x1a\x7e\xc1\xcd\x27\x1a\xb0\x91\x51\xac\x03\xc7\x74\x16\x5b\x01\x07\x35\x56\x2b\x9c\x82\x88\x8c\xe7\x76\xf4\x66\x43\x71\xd3\x39\xce\x12\x6b\xfb\xd5\x16\xb0\x5e\x27\x60\xfe\x15\x14\xf9\xce\x56\x4e\xbf\x74\xbc\x5e\xc7\xf5\xca\x92\x64\x43\x16\x55\xae\x19\x58\x59\x2d\x8c\xf4\xf2\xe3\x8b\x9e\x0d\xa7\x6b\xde\x85\xa5\x7f\x68\x19\x74\xb2\xfb\x10\xd7\x1b\xa0\x01\xb4\x5d\x2f\xf8\xb6\xd2\x5b\x5e\xfb\x6e\xc3\x7d\xab\x75\x59\x97\xe7\xc5\xe2\xfc\x6f\x55\xe0\x6f\x7f\x63\x83\xc9\x6b\x60\xbf\x6f\x05\x26\xef\xe3\xd5\xc7\x6f\xbe\x33\x70\xe0\x54\xe7\xd9\x84\x18\x50\x6e\xbd\x72\xe8\xef\x37\x12\x24\x27\x26\xce\x74\xe7\xb0\xf2\x4d\x90\x58\x94\x20\xa4\xe8\x5f\x2d\x92\xa8\x4b\x2d\xba\x4d\x88\x2d\x14\x22\xd8\x69\x59\xe9\x8d\x2c\x96\x4c\x5e\x19\x86\xff\x4b\xbc\xba\x19\x33\xc5\x1a\x3e\xa1\x17\xb8\xf7\xfe\xde\x1c\xcf\xe5\x6d\xc2\x40\x3f\x0f\x8e\x87\x81\xae\xd6\x1f\xfe\x14\x2f\x41\x61\xd8\x85\x1f\x59\x33\x5f\xd9\x79\x07\x6b\x36\x2f\x15\x1b\x94\x53\xcc\x13\xb7\x4a\xda\x7c\xc9\xe5\x39\xe7\xe5\x93\xe0\xd1\x1d\x3e\x0e\xd2\xf4\x38\x80\xac\x1f\xb7\x16\xf9\x31\x2a\xf2\x63\x58\xe4\xc7\x81\x22\xa3\x0c\x03\xcf\xfd\x17\xff\x04\x11\xb5\x54\xec\x95\x19\x2b\x98\x3c\x07\x32\xbd\x12\x98\x3c\x14\xf4\xe8\x3e\x99\xee\x91\xdd\xbb\x64\x6f\xf7\x98\xbc\x14\x34\x4f\xd3\xe4\x71\x6b\xe8\xd9\x39\x82\x26\xdf\xac\xa2\x40\x67\x73\xa7\xea\xaf\xec\x9e\xd9\xdd\xa7\x29\xfa\x26\xda\x33\xf7\x30\x9b\xd9\xdb\x3f\x31\x9f\x79\xcf\xbf\xaa\x4e\xf9\x69\x3a\xfa\x26\xc8\x33\x78\x8e\x46\x2f\xc5\x7a\xfd\x4d\xa4\xe9\xbd\x07\xfa\xef\x74\xfa\x0f\xfa\x4d\x60\xf2\x48\xd0\x21\xa6\xb4\xb7\x8b\xc9\x5f\x22\xf2\x8d\xfa\x5d\x0c\xda\x6e\x9a\x99\x64\x15\x54\x77\xa6\x23\x4a\x1f\xb6\x9e\xb3\xca\x4d\x2b\x83\xbf\xe8\xa7\xa2\xd7\xde\xef\xde\x07\x54\x23\xa7\x3b\x70\x99\xcc\x4c\x0e\x6c\x36\xf3\xd6\x43\xa9\x35\x0f\xf5\x16\xc4\xfd\x10\x2c\x2d\x4c\x72\x38\x34\x3a\xf0\x99\xa0\x90\x30\x1b\x0e\xac\x7b\x20\x90\xd7\x40\xe0\xf2\x0a\x9e\x0f\x9a\x12\xe4\x37\x41\xaf\xc1\xcd\x31\x1b\x4d\x48\xae\x27\x8a\xfd\xd5\xfb\x20\x7d\x9d\xb8\x9b\x3b\xc0\x46\x13\xe3\x3c\xab\xb7\x33\xa3\x09\x59\x56\xc2\x78\xda\xdb\x00\x99\xe0\x1f\x5b\xd7\x97\x95\x04\xdf\x5a\x88\x3e\x00\xbe\xb2\x9c\xc9\x05\x64\x54\xbc\x34\x3f\x5f\xc1\xcf\xd6\x7d\xa5\x91\x90\x7c\xc9\xf9\xe7\x6c\x34\x09\x96\xd9\x9f\x42\x75\x4c\x9a\xb6\x28\x90\xe1\x75\x6c\x64\xe3\x94\x35\xde\x9d\x4a\xcd\x47\xa3\xdf\xc0\x38\xe7\x6a\xc5\x8f\xb3\xc8\x99\x2a\x38\x28\xf8\x12\xa0\x2a\xbc\xe7\x48\x62\x32\x79\x80\x14\x7d\x29\x91\x22\x89\x37\x0c\xc0\xb8\x8d\x26\x64\x62\x94\x9f\x0a\x94\x04\x76\x03\xce\xa2\xc0\x28\x1c\x89\xc4\xc4\x3a\x19\x9a\xdd\x69\x26\x48\x69\xbd\x97\xea\x4c\x6d\xb0\x41\x2e\xf9\xd9\x6a\xd9\x7e\xed\x6a\xd9\xfe\x09\xed\x7f\x2b\x11\x27\xa1\x96\xea\xa3\x5b\xea\x3f\x22\x09\x5e\x94\x5e\x15\x1d\xa8\x37\x03\x24\x0e\x5b\xa9\xd0\x5e\xde\x6c\x9f\x5f\x08\xef\xd6\x65\xb4\x01\x32\xb8\x51\x92\x26\x95\x30\x74\x0c\x66\xaf\x71\x5f\xb1\x4a\x53\x21\x6f\xb6\x9d\x99\x09\x19\x07\x8a\xf1\x25\x92\xc4\xea\x6a\xc1\x9a\x68\x08\x9c\x5c\xc8\xb1\xcd\xbc\xe1\x92\x2a\x69\x14\x99\x5c\xea\x2a\xbf\x10\x94\x4b\xcd\x02\x06\xb9\xc8\x7a\x7d\xff\xc1\x30\x7b\x09\x34\x7d\x12\xe1\xeb\x9f\xf5\x9e\xf1\x67\x01\x33\x66\x71\x0e\xbc\x46\xd7\xd0\x2d\x0c\xae\x33\x2b\x89\x75\xdf\xfc\xec\x6c\xdf\x5a\x95\x9d\xb4\x1d\x61\xf5\x9b\xb0\xfa\x86\xcb\x4a\x9a\x7e\x14\xe8\x57\x77\x4c\xab\xe8\x11\x58\x36\x7d\x11\x48\x91\x5f\x05\xe1\x04\x1c\x77\x31\xe1\xf4\x9f\x82\xbc\xe4\x18\xac\x85\x41\x99\xdc\x1e\xbb\x58\x5f\x51\x7f\xe0\x62\xbc\x3c\xcd\x71\x4b\xc0\x15\x98\xf4\xe8\x63\xee\x28\x01\x54\x8c\x48\x37\x14\x46\x16\x41\x3f\x0b\xaa\xf0\x98\xa9\xef\x35\x16\x67\x2d\x4b\x32\xda\x4b\x5d\x48\x80\xd1\xe5\x9b\x6d\xfc\x14\x5b\x4b\x1a\xeb\xb0\xd8\xca\x22\xe6\xc6\x0b\x2b\xde\xe3\x07\xa8\x12\x68\x33\x65\x30\x5a\xc1\xd1\xb3\x93\x3b\xb4\xc0\xac\x83\xcc\x91\xd7\xe4\xc0\x38\x37\xaf\x82\xaf\xdf\xe0\x20\xb3\xfe\x8b\x45\x3d\xf7\x57\x59\x0c\x65\xe3\x4f\x79\x8c\x66\x77\x32\x82\x6f\x4d\xff\x87\x53\x3a\xfd\x1f\x85\xd7\x6b\x0e\x60\x67\x6a\x44\xd5\x86\x2c\xe4\xf7\x62\x63\xb6\x93\x3b\x6f\x9b\xd1\x98\xcb\x28\xb8\x56\x1f\x64\xdf\xc7\xb4\x1a\x82\xe0\x57\xfe\xa9\x8a\x51\x49\x3d\x36\x2d\xc0\x33\x00\x52\x54\x98\x60\x2d\x73\x2d\x5b\x03\xb7\x2a\x6b\x3b\x1a\x59\x5c\x4b\x3a\x99\xc9\x16\x6b\x4d\xde\xbe\x8d\x35\x1f\x58\x48\x0b\xec\x4a\xc4\x91\x3c\xc6\xeb\xf5\x48\x37\xe5\x48\xdf\x1c\x13\x65\x7e\x71\x5b\x52\x5f\xbb\x7d\x2a\xdd\xd9\xee\x0c\x98\x7a\x84\xa2\x13\x03\xd0\xf4\x79\xdc\x4a\x06\xd6\x19\x44\x52\x28\xcc\x9f\x1d\x48\xe3\xa1\xa3\xb7\x2d\xb2\x05\xa8\x31\x78\x60\xfc\xb6\x0c\x8f\x1e\xdc\x41\x05\x7f\x00\x66\xef\xff\xf0\x34\xbc\x86\x10\xcd\x92\x58\xc8\x11\x75\x87\x6f\x66\x9c\x8a\x0d\xcf\x4c\x9d\xed\x37\xe4\x58\xf0\xaf\xea\x9d\xf1\x2a\xc2\xd7\x92\x46\x09\xce\x55\x77\xa3\xd3\x5b\x9f\xf9\x8d\xb4\x51\x01\x36\x50\x73\x19\x1e\x9f\x9e\xcb\x70\xf0\x8d\x20\x10\xc1\x48\x99\x73\x78\xc0\x11\x81\x94\xbd\x51\xe8\x90\x0f\xaa\x76\x03\xc8\xa3\x5a\x2f\x7d\x53\x52\xf0\x59\x9c\x25\xf6\xac\xa8\xf6\xaa\x1c\x7b\x8f\x94\xde\x8c\xea\xfb\xa5\xce\xef\xf0\x0a\xdf\x58\x59\x4f\x6f\x4e\xd1\xf4\x30\xdd\x9a\x01\x29\x1c\xd9\x2b\x2f\x25\x6a\x0f\x23\xb8\x0d\xdb\x4b\x14\xfd\x03\xe1\x99\xda\x71\xa1\xb0\x41\x6d\xfc\xd3\xfb\x57\x2f\x9f\x3f\x93\x6c\xe9\x16\x90\x99\x09\x46\x60\x46\xf0\x00\x88\x83\x0d\x00\xfa\xbb\xd1\x3b\xb9\x0d\xe2\xf8\x5c\xf2\xd3\xd6\x37\x57\x58\x9f\xe8\x91\xb0\xae\x65\xfa\xdb\x88\xd3\xce\xeb\xd8\x2f\x12\xde\x59\x35\x90\x0c\x2e\xe4\xbf\x2b\x84\xec\x68\x86\x11\x48\x22\xfa\x0e\xc0\xc6\xc3\x7d\x9b\x91\x8e\xa2\x24\xc5\xcb\xe8\xbe\x91\xf1\xbd\x93\xb2\xda\x44\xdc\xf1\x12\x57\xfa\x5e\xba\x15\xa9\x13\x2c\xd5\xf0\xc3\x33\x49\x6f\x16\xd2\xb5\x3c\x3d\xb8\x8a\x92\x2b\x8b\x92\x7c\x62\x7f\x2f\xed\xef\x57\x19\x89\xd7\x4f\xfd\x92\x64\x83\x7c\x8f\xcd\x08\x00\x2f\x43\xe1\x8b\xcc\xee\x47\x10\x52\x73\x91\x89\x18\x2f\x73\xf6\xd5\x87\xf3\xbb\x92\xeb\xf5\x95\x1c\x51\xfa\x07\x92\xc6\xa1\xbe\x5d\x82\x8c\x91\x63\x21\x90\xa4\x57\x12\xa7\xe9\x85\x9e\x53\xf3\x6b\x63\xd1\x2c\xc7\x71\x3e\xc2\x45\x1e\x26\x3e\x15\xf9\x26\xbb\x36\x21\xb9\x00\xd0\x02\x49\x8a\x64\x5c\x8f\x34\xed\x24\x78\xb0\xbb\x82\x5f\xb6\xe8\x1a\x67\xdc\x62\x31\xc2\xe1\x05\x1e\xb7\x85\x12\x73\xf9\xda\x30\x13\x39\x0e\x6f\x09\xac\xb8\xf0\x69\x39\xf6\xd7\x26\xd5\xbf\x10\xdc\x6d\xc8\xa5\x4c\xd3\x5c\xa2\x4b\x49\x80\x14\x97\x92\x4a\x2d\xb3\x4a\x2d\xb3\x9e\x48\x2d\xb4\x9a\x6a\x44\x42\xab\x0a\x84\x56\xfb\xd8\x45\x3d\xb5\x42\xab\xee\xb0\x8e\xd0\xaa\x02\xa1\x55\x6e\x30\x51\xee\x2c\xf0\x4a\xea\xf9\xfe\x5c\xa1\xc4\xba\x0f\xba\x1f\xe3\xc2\x67\xff\x56\x35\x77\x7f\x03\x6f\xbe\x45\xab\x67\xb5\x1e\x80\xce\x0d\x50\xff\xf3\x7e\x8a\xac\xf9\xfa\x38\x76\x58\xcc\x5b\xe8\x87\xc8\x31\xf1\x69\xc7\x41\x91\x9d\xbd\x6b\x5d\x15\xe1\x8f\x15\x8c\xcc\xef\x8e\x13\x71\x76\x4e\xca\x46\x5a\xa7\x44\xf7\xf7\x82\x95\x45\xee\x7f\x03\x3f\xc6\x27\x5d\x7f\xc6\x37\x81\x63\xe3\x67\x7e\xf5\x61\xb5\xd3\x71\xca\x7c\x12\xba\x67\x2e\x0d\x6a\x84\xf5\x74\x74\x7f\x9b\xda\xff\x2d\xd9\x95\xfd\x33\xe4\x96\xf9\x78\xab\x93\xe6\x93\xd8\x61\xd3\x5e\x7d\x58\xed\x48\xa6\xb8\xf5\xa5\xd4\x97\x8f\xed\x25\xb8\x52\x5a\x87\x4a\xce\x3f\x43\xf8\x5d\xf3\x03\xee\x95\xee\xa7\xe7\x4e\xfa\x78\xc8\xb5\xf4\x69\xec\x63\x0a\x97\x86\xf6\x17\x55\xd9\x2c\xdd\xf7\xcd\x8d\xdd\x2a\x05\xfe\x9b\x64\x82\x89\x1e\x43\xba\xcb\x76\xfc\x1f\x30\x70\xb1\x1d\xeb\xae\xf8\xd7\xc2\xf4\xec\x53\x77\x01\x8e\x92\x70\xf5\xd2\x5f\x55\x17\x36\xfb\x6b\x7d\xe1\x4f\x83\xcc\xd5\x2b\x7f\xa5\xbb\x1e\x2e\x5e\xbb\x8b\xca\xe7\x87\x37\x2d\x11\xe1\x5d\x7b\xfd\x2a\xb8\xd6\xef\xdb\xcb\xd7\xed\x65\x15\xbc\x09\xa5\xd4\xa0\x8f\x76\x3f\xaa\x3a\x3b\x2b\x79\xfb\xd3\x2c\xce\xa1\x7c\xb8\x82\xd2\x41\x45\x63\xfe\x46\x44\x9a\x02\x91\x5e\x29\xb2\xdb\x7a\xf2\x7c\x96\xd4\x0a\xbd\x3b\x1d\x49\x3c\x72\xaf\xed\xb8\xe5\x6e\x77\xdb\xb5\xb6\xd8\xe1\x67\xdf\x69\xc9\xef\x9d\x7c\xf0\xd9\xc9\x85\xb3\x77\x5a\xf8\xb3\xf6\xd0\x9f\xe5\xd1\x3b\x79\x4c\x26\x78\xb6\x40\x31\xfa\x09\x39\x6a\x5d\x53\x49\x60\x83\x74\x8c\x49\x9b\x15\xfa\xec\xbb\x59\xad\x71\xba\x2f\x37\xf0\x61\x25\x91\xbd\x52\xe7\x05\x5f\xfa\x4d\x2f\x34\x03\xdb\x77\xcb\xb9\x22\x76\x51\x79\xee\x10\x70\x83\x66\xd5\xa5\x7b\x48\x3b\x5b\xb8\x67\xb3\xbe\x9c\x90\x0d\x3a\x0e\xe6\x3e\x16\x97\xde\x77\xf0\xfe\xfe\xf7\x1e\xf1\xd3\x4a\xf2\xe7\x66\x97\x7d\x94\xc4\xbd\x9d\x90\x56\x19\x45\x12\x3f\x48\x12\xc0\x6b\x51\xbc\xa5\x48\xa0\xe2\x83\xb7\x3a\x83\xc6\xb7\x65\x8b\x8f\x77\xab\xe2\xea\x57\x30\x28\xdb\xbb\x71\x74\xc7\xe8\x7f\xa9\x7c\xe7\x4f\x90\xf4\x06\xf9\xbf\xf9\x05\xd8\x52\x3d\x96\xd4\xb8\xaf\xec\x58\x57\x93\x9d\xd8\xe5\x64\x27\xf6\x2f\xd9\xb1\x2e\x24\x3b\xde\x69\x64\x07\x4c\x4d\x77\xc0\x41\x64\xa7\x75\xf4\xd8\x89\x3d\x3b\x76\xbc\x1b\x47\x77\x75\x28\xc4\xd9\x8e\x73\xc1\x08\x39\x7c\xc0\xca\x4d\x74\x54\x70\xbe\xd8\xb1\xc6\xad\x3b\xad\xbb\x45\xcc\x98\x9d\x3f\x45\x38\xef\xff\x94\x20\x29\xbc\xe3\xc1\xe2\x0e\x6b\xb8\x5b\x14\x75\xe5\x62\xae\x16\x45\xc8\x5c\x54\x62\xc1\x14\x7a\x2c\x71\xe0\x9f\xff\xa6\x23\x11\xb6\x12\xae\x31\x24\x31\x71\x5f\x93\x19\xef\x9a\x17\x91\xbe\x05\x25\x61\xa4\x24\x35\x69\x60\x03\xf6\xb3\x43\xc0\x81\x08\x23\x2d\x06\x0e\xb9\x65\x43\x75\xdc\xea\x81\xb7\xdc\xbf\x67\x7b\x73\x41\x3f\xf0\x59\x17\xb0\x67\xbd\x46\xbf\x01\x1e\xcf\x4f\x9c\x2e\xf0\x66\x03\x71\x8f\x2d\x4e\x35\xd7\xf2\x51\xdf\xfe\xa9\xdd\x31\xbc\xb5\xbb\x37\x45\x8d\xbb\x86\x0a\x7d\x2f\x7b\x68\xe4\xb1\x5b\x8a\x34\x26\xc6\x33\xbd\x57\xf4\x52\xd7\x8c\x67\xd6\x04\xd1\xc6\x91\x03\x44\x41\x6f\xe6\xe5\xf7\xec\x77\xa6\xb3\xc9\x03\x5a\xcc\x8a\x3b\x77\x4c\xb1\x25\x95\x47\xc5\x31\xa9\x69\x39\x76\xdb\x2d\xd2\xd0\x32\xae\xbd\x2e\xad\xa4\xa5\xff\x1c\xa9\x47\x94\xb2\x34\xad\x06\xad\x74\x10\xc6\x0e\x7a\xea\x8d\x44\x15\x29\x49\x83\x09\xa3\xb5\x51\xcf\xe9\x3a\x15\x74\x32\x2b\x1e\xf8\xf5\xa2\xb0\xe0\xe6\x35\x45\xa6\x3a\xf8\x86\xba\x90\xff\x42\x45\x00\x29\xe5\x37\xd7\xe1\x9c\xfe\xc4\x3b\x08\x4c\x81\x0a\xe1\x75\xa8\x42\xa0\x0c\x70\xe4\x24\xe5\xb7\x93\x4f\x9f\x8c\x05\x51\x32\x03\xdf\x42\xb3\xdd\x78\x25\x91\x22\x9c\xec\x42\x48\x51\x31\x66\x79\x8e\xa4\xd5\xe1\xbe\x97\x34\x31\x56\x76\x06\x9e\x4a\xcf\xa7\xdb\x60\xb8\x2d\x99\xc8\xab\x65\x08\x3b\xbc\x77\xe8\xa2\xaf\xef\x06\x93\xe3\x17\xd8\x67\xf2\xa3\xf7\xf2\x78\xbd\x46\xf0\xab\x07\x60\x39\x0c\x9b\xf9\xa7\x84\x6a\x29\xbc\x5e\x7f\xd2\xb5\xf2\xb1\x6f\x31\x31\xf7\x13\x77\xbf\x89\xf6\xe4\x9f\x64\xd7\xec\x75\xff\x81\x9f\x2f\x7e\x9f\xe0\xc3\x35\xf8\x47\x47\xfb\xc7\xf3\xf0\x26\x9b\x10\x46\xc5\x6c\x9b\x12\x30\x4d\xef\x8f\xc2\x5d\x5d\x9a\x22\x46\x3b\xfb\x3a\xef\x17\x2c\xd3\x74\xa4\xd2\xd4\x36\xc9\xa1\x02\x1a\xde\x62\x42\xd2\x5b\x5d\x71\xb5\xa6\xbb\x84\x51\xb9\xb1\xb6\xb6\x15\x62\x98\x94\xa6\xbb\x92\xdb\x48\xcd\x13\x6f\x5e\x9c\xd8\xee\xc3\xb3\x02\x4a\x2d\x75\xff\xe9\x1d\x78\xb5\xa6\xfb\x98\xbc\x92\x60\x36\x5c\x11\x85\x49\x01\x1d\x59\x86\x54\x7a\xd5\xa3\xd2\x27\x63\x8d\xac\xb0\xc3\x8e\xf4\xd6\x50\xd5\x7c\x37\xab\xac\x5b\xc7\x24\xab\xe8\xaf\x2a\x80\xd0\xd8\x99\x66\x15\xfd\xa7\x4b\x71\xa7\x3a\x15\xfd\xa8\x36\x82\x56\x81\x45\xbc\xfe\x18\xc7\xa4\xb2\x33\x9c\x8c\x1e\x81\x26\xc0\x4b\xd5\x16\xfe\x3c\xf1\x22\xa3\x4b\x30\x92\xa2\xc1\xfa\x47\x15\x58\xd8\xc9\xb9\xef\xbf\x6a\xce\xfb\x00\x6b\xfa\x5b\xd7\x96\x52\xee\xd4\xa6\xb8\xe0\x59\xb5\xc1\xd9\x96\xec\xa3\x09\xce\x7e\xa0\xd0\x1f\x29\x29\x8c\x15\xf3\x5c\x86\x26\xf1\x86\xc5\x49\xeb\x62\x84\xa6\xa9\x32\x1e\x29\x68\x17\xae\xdc\x68\xc1\x3c\x03\xe5\xdb\x2c\xc4\xd0\x72\xfe\x48\xce\x38\xd8\x99\x61\x83\x49\xb5\x89\x6f\x5f\x78\x9e\xb8\xcd\x6e\xda\x70\x42\x4a\xab\xf5\xfa\x1e\xa5\xb4\x0c\x86\x6f\x19\xa8\xd0\x02\x50\xad\xe2\x14\x99\xa2\x0d\xe3\x73\x98\x54\x0e\x25\xa8\x98\x39\x07\xad\xc2\x55\x08\x6a\x54\x9b\x1a\x01\x7c\x1a\xd2\x0f\xb7\x54\x08\xb7\x95\xa9\x83\xca\xd4\xdd\xca\xb8\xc6\x17\xb4\x70\xc0\x43\x40\x22\xe7\x8c\x1f\x91\x0a\x15\x54\x55\x7a\xbc\xe3\x16\x2b\xec\x40\xa7\xdb\x5a\x62\x83\xe7\x54\xe3\x6b\x49\x19\x2d\x3c\xfa\xd7\x0e\xdf\x68\xee\x1c\x68\x30\x41\xa3\x69\xbf\x37\x8a\x97\x68\xf8\xe0\xb7\x36\x14\x21\xc2\xb3\x6f\xfe\x4c\xe3\xa1\x03\x57\xf6\xa7\x1a\xdf\x82\x53\x8d\x08\xb7\xdc\xe2\x12\x10\x30\xcf\x17\x98\x14\xf4\xe8\xd8\x2d\x87\x25\xfd\xc5\xcc\x4a\xe3\x65\xe1\xc7\x67\xe9\x88\x7e\x2a\x48\x43\xbb\x51\x10\x83\xd3\x58\xe7\xcb\x26\x90\x68\x17\x93\xf8\x58\x37\x3c\x11\xae\xe9\x6b\x11\xc2\xe3\x78\x9f\x8d\x86\x9a\xeb\x84\xd4\xf4\xaa\x9f\xc5\xa0\xed\xd0\xe4\xa4\x6c\x64\x3f\xcb\x09\xc8\xeb\xf0\xcc\x7c\x8d\x9d\x2a\x2e\xcd\x7d\x37\xaf\x39\x1b\xd1\xf5\xde\x35\x58\x05\x60\xbd\x19\x57\xdd\xa9\x4e\x1c\x9c\x90\xd5\x9b\x6c\x39\x7b\x6e\x8d\x25\x83\xfb\x66\xd5\x43\x17\x1a\x04\x1f\x0a\x36\x32\xba\xae\x17\xa2\x8b\x6b\x14\x40\x1a\xe9\xcd\x47\xb6\x15\xf0\x48\xef\xec\xfb\xf8\x47\xfe\x3e\xf8\xa6\x57\xf1\xf8\xfb\x0a\xba\xe6\x2c\xfa\x78\xa0\xb8\xb0\xf9\x9c\xca\x22\xbc\x0d\xda\x1d\x70\xda\xac\xa6\xbf\x84\x85\xed\xbc\x51\x26\xae\xe8\x5b\xfb\xfb\x5a\x65\x35\x3d\x89\xb2\xbc\xd7\x49\x9f\xa2\x2a\xd8\xf5\x2b\xab\xe9\x79\x94\x6e\x18\x76\x56\xd3\xe7\x71\xd7\x56\xab\x2b\x47\x56\x4f\x70\xb3\x29\xcb\x6a\xfa\x55\xfc\xdb\xb8\x4c\x81\x57\x4f\x44\x90\x40\x8b\x14\xa7\x04\x54\x09\xe1\xa2\x6e\x46\x94\x32\xf3\xe3\xbd\xb1\x50\x5b\x78\xc1\x97\xe4\x74\xb4\x48\x53\x47\x0c\x2d\x1a\x90\x53\xba\x98\x3b\xc6\x34\x2f\x6f\x27\x1e\x43\x15\xc0\x0d\xcb\xd9\x42\x4f\x71\x27\xdc\xae\xc8\x39\x95\x8e\x8f\x39\x18\x9a\x25\x45\x2b\x7a\x8e\x63\x70\x5a\xcd\xc2\x56\x9a\x7f\xf9\x95\x62\x99\xa6\x68\x45\x97\x4e\xcc\x38\x75\x0f\xd0\x92\x3e\xe3\xe8\x9c\x9c\x62\x9c\xa6\x0b\xa3\xea\x7c\x28\xd1\x39\x59\x92\x15\xc6\x98\xe4\x96\xb9\x9f\xd3\x73\xc7\xdd\x26\x0f\x16\xad\x12\xb5\x84\xad\x51\x8d\x4a\xd2\xb8\x83\xfe\x4a\x8b\x11\xa1\xce\xb4\x0c\x74\xa6\x8b\x8d\x85\xef\xd3\x6b\xd9\xdd\x54\x61\x2b\x0f\xb7\xd3\xcb\x1e\xea\x05\xe4\x06\x4a\xa1\x11\x2a\x69\x30\xeb\x3a\xd9\x5c\x12\x5e\xaf\xc1\xbd\xf9\x30\xd5\xe2\xe0\x08\x35\x00\x03\x19\xd8\x0c\xaf\xd7\x22\xb4\xbc\xd6\x99\x54\x85\x1a\x9c\xa6\xa3\xe6\xe8\x85\x3c\x06\x1c\x9c\xf5\xba\x04\xb0\x1c\x5a\xb5\x7a\xfa\x6a\x5e\x65\x90\x12\x0b\x6e\xf3\x32\x56\x7d\xbb\x45\xc1\x1c\xa7\x58\x63\x60\x52\xcf\x51\x4d\xa5\xa3\x3e\x6a\xe8\x70\xc5\xbc\x79\x38\x9e\x43\xa5\x0c\x4c\x54\x9a\xa2\x46\xbf\x95\xd3\x5f\x39\x6a\x30\x5e\xaf\x0f\x46\x94\x36\xa6\x7f\x0f\xdd\x25\x64\x33\xa7\xf2\x38\x43\xb5\x45\xcd\xa3\x12\xc3\xd6\xa1\x31\x84\x5e\xd0\x0b\x41\x96\xb4\xa3\x74\x3a\xa5\x1d\x85\xd5\xb9\xa5\x74\xa0\x23\x6a\x40\xec\xe2\x69\x1a\x91\xdc\x9c\x00\xa3\x05\x7d\x6f\x8b\x8d\xf5\x4d\xa7\xb4\xa7\xb3\x3a\xa7\xae\x80\x44\xcf\x08\xb3\x0e\xd7\xf3\x32\x93\x15\xaa\x31\x59\xd9\x94\xc6\xa4\x34\x98\xd8\x21\xb6\x40\x4b\x72\x7e\x3b\x31\xdc\x90\xd4\x30\xce\xb0\x53\xbe\xe7\xa4\x8c\x89\x49\x57\x64\x69\xdd\xb5\x2a\x04\xa2\x83\xd4\xe2\xc5\xc2\x16\x75\xaa\x8b\x32\x7c\x57\x8f\xdb\xb0\xa8\x15\x59\x74\x8a\xca\xc9\x92\x2e\x74\x5d\x97\xa4\x4e\xd3\x06\xdb\x03\xcf\x53\xda\x90\x73\x3a\x21\x2b\xba\xa0\xf5\x6c\x35\x5b\xd1\x6f\x12\xad\x30\x3e\xbf\x7d\x1b\x66\xec\x8a\x4e\xc8\x92\x9e\xce\x96\xb3\xa5\x7e\xb2\xc4\x78\x65\x9f\xcc\x26\x0f\xce\xef\xac\x66\x78\xa1\xd3\x17\x98\x9c\xbb\x98\xd9\x93\x07\xab\x3b\xe7\x33\x7c\xaa\xd3\x4f\x31\x59\xb9\x74\x9d\xc1\x76\x1f\xa5\xa7\x0e\x21\x5f\x4f\x62\x48\x08\x00\x5f\xfd\xea\x67\x8b\xb6\x45\x6d\x16\x81\xff\x9b\xb9\x76\x7c\xa4\x4e\xd3\x27\x12\x01\x96\x2e\x59\x98\xcd\x9c\x79\xd0\x78\xde\x91\xdb\x2c\x39\x69\x74\x96\x09\x40\x2b\x05\xb8\xcc\x76\x3b\x3b\x97\x15\x92\x38\x73\x67\x3f\xed\xd1\x60\xb9\xe5\x68\x30\x82\x7a\xae\xd3\x34\x01\x74\x79\x10\x36\xe1\x20\x4f\xb3\xb7\x0b\xfa\x87\xf0\x3e\xff\x3f\x09\x2d\xaa\x15\xa7\xe8\x85\xc0\x17\xb4\x96\xd6\xd9\x90\x16\x12\x44\xdd\x33\xca\x8c\x65\x0c\xaa\x69\x39\x1c\x25\xb7\xbe\x39\x4a\x6e\xd9\x0b\x15\x69\xab\x92\xa6\xe8\x82\x96\xb2\xdd\xf1\x40\xc2\x05\xb8\x56\xe2\xf9\x17\x81\x0a\x72\x01\xe3\x28\x43\x67\x69\x7a\x86\x38\x29\x89\xc4\xa4\x6b\x3b\x82\xce\x68\x19\x87\x76\xc2\x69\x7a\x36\x6e\x23\x57\xa6\x69\x10\x30\xcf\x7c\x1b\xc2\x23\x96\xc4\xa5\x93\xd2\x45\x09\x24\x67\x1d\x9a\x93\x1e\xe2\xa2\xa6\xd8\x19\x0e\x0e\x40\xcf\x7a\x07\xa0\x69\x8a\xae\x24\x3d\x23\x27\x92\x4a\x77\x7a\x89\x87\xc5\xb6\x4b\x49\x4f\x24\xb5\x27\x9e\x3d\x20\x46\xb3\x78\x7e\x95\x5a\xb0\x8d\xd6\xf2\x40\x2e\x1a\x10\xab\xbc\x3c\x04\x27\xa6\xe4\xa9\x1e\x68\x9a\x90\x91\xf8\xd0\xd9\x55\x6b\xa1\xef\x4c\xe2\x20\xc7\xa0\x8c\xea\xcb\x32\xf1\x75\xf4\xc2\xf8\x52\xe8\xe9\xdb\x11\x82\xbb\x1a\x57\xe3\xec\x7b\x42\x87\xf4\xb3\xb3\x48\xbe\xec\x28\x94\xb3\xee\x3b\x4f\x45\xbe\xfd\x0d\x7b\xc2\xd0\x7b\xc9\x2a\x6a\xbd\xa9\xc4\x89\xb3\x8d\x80\x69\xf0\x41\xcc\xc1\x56\x13\x22\x7f\x0e\x7d\xaf\x63\x13\x9d\xa6\xbb\xbb\xe6\x54\xd9\x9a\x61\x0e\xbc\x66\xa1\xac\x66\x27\x69\x8a\x9e\x89\x34\x4d\x3e\x57\x10\xdc\x71\x6c\x0c\xc6\xd3\x14\x7d\x10\xeb\xf5\xd0\x3b\x23\x4a\x4f\xe6\xfd\x3a\x50\x4a\x4f\xd2\xf4\x83\xd0\x83\x8b\x0a\x81\xf4\x8a\xc4\x45\xeb\xfa\x8a\x5e\x28\x5a\xe1\xad\xde\xaf\x1f\x04\x44\xee\x23\x93\x07\xe8\x8c\xbe\x94\x48\x92\x93\xf0\xe0\xf6\x04\xb8\xf8\x53\x81\x4e\xac\x5e\x67\x48\xe8\x38\x09\x84\x8e\xb3\x0d\x26\xe8\xca\xf3\x4d\x74\x45\x6f\xc1\x36\x07\x48\x08\xd6\xa0\xf4\x4a\x0b\x3b\xe8\x8a\x3e\x89\x43\x4b\xe1\x1b\xc6\x0a\xf4\xb8\x8b\xc5\x2f\x90\xc2\x5d\x03\x57\xe7\xa4\xbc\x0b\x56\xb0\x60\xdb\x6e\x40\xab\xd1\x5f\xba\x81\xe4\x91\xb0\xaf\xb4\x67\x0f\x3e\x46\x3b\x44\x31\x51\x4c\xaf\x5c\x8f\x44\x9a\xfe\x25\x2c\xdc\x75\xc7\x1a\xd6\xc0\xf5\x6e\x60\x3c\x64\xbd\xb8\x63\x1f\x9c\x47\x72\xb7\xda\x46\x78\x1a\xbd\x14\x69\x6a\x0d\x7f\xe7\x88\x43\x47\x11\x25\x28\x17\xd4\x39\x3d\x1b\xdb\x58\x6e\x04\x91\x60\xf3\x38\x50\x8b\x59\x7f\x43\x39\x42\x6a\x6c\x8d\xd2\xd7\x6b\x35\x36\x26\xeb\xfa\xca\xda\xac\x43\x6c\x55\x9b\x21\x4d\x5d\x06\x1b\x8e\x75\x71\xce\x64\x9a\x4e\x1f\x98\xab\xd8\x12\x6b\xc7\x24\x1a\x60\x65\x20\x6c\x8b\x6c\xd6\x37\x77\x76\x59\x36\xbd\xda\x6e\xe9\xcd\x60\x0e\x28\x3b\x07\x0c\xf9\x4d\xa7\x58\x7a\x03\xfe\x82\xb1\x31\x00\x13\x83\xf0\xb0\x29\x1c\xae\x95\x1b\xae\xdd\x03\x29\xbb\xdd\xb5\x46\xa0\xdb\x06\x72\xd5\xb1\x38\xa8\xdc\x80\xdd\xbc\xd5\xfc\xcd\x04\x30\xf3\x5a\xa4\x87\x32\x8e\xd5\x74\xed\xf4\xcb\x19\xf7\xe5\x64\x8a\x44\x8a\xe6\x4c\x04\xe6\x56\x2f\x65\x17\x3d\x4a\xb5\xdb\x12\x22\xf5\x7e\xc4\x61\x6c\x7a\xa4\x75\x0e\xfe\xea\xed\x0e\xe4\x00\x9c\x8f\xc3\xed\x07\x03\x3a\x30\x2b\x5b\x20\x46\x21\xb6\x06\xd0\x50\x8e\x1b\x61\x90\x05\xa1\xee\x0c\x40\x0d\xe2\x7c\xca\xe4\x73\x9b\x13\x9b\x09\x43\x84\xff\x08\x5b\x3a\x44\xb0\xf9\x26\x03\x04\xd5\x1e\x3e\x76\x5e\x5d\x07\x6f\x5b\x7c\xfe\x34\x3d\x18\x39\xd0\x7d\x6f\x63\x67\xd8\x46\x80\x8c\x13\xe9\xe9\x1c\x99\x18\x55\x81\x67\xb9\x51\xcd\x38\x8c\xcf\x34\x05\x8c\xf6\x99\xd3\xb9\x09\x38\x84\xf0\x42\x1b\x68\xfe\x7b\xb1\x45\x8c\x68\x66\x80\xd2\xcd\x42\x77\x60\x44\x82\x80\xaa\x0d\xec\x51\x1a\x52\xd9\x3d\x24\xaa\x35\xbd\x04\x61\x9a\x5e\x45\x48\x57\x41\x6a\xa2\xf7\x05\x95\x63\x82\x9d\xac\x8e\xb4\x36\x1f\x26\xc2\xc3\xe7\x6f\x26\x23\x4a\x0b\x3f\x9c\xb7\x9b\xc3\x14\x61\x30\xd2\x67\xd2\x05\x64\x79\x64\x2d\xa2\xfe\x92\x1d\x8b\xee\xdf\xe5\x20\x87\xb5\x31\x41\xcc\x4a\x6e\xe6\x46\x16\x48\x01\x4e\x47\xe1\x2c\xbc\x9c\x5b\xc0\x48\x8d\x59\xa3\xaa\x67\x5a\x5a\xd9\xf4\x31\x02\x6e\x45\x56\x84\x71\x18\x11\xbd\xb4\xad\xac\x2d\x2c\xdc\x89\xaa\x5e\xc8\x62\xd5\x86\x20\xe9\x9b\xdc\xf9\x68\x55\xad\xbc\x36\xf4\xb0\xe3\x93\xb0\x3d\x3a\x54\x10\x04\xfa\x3b\x39\xb6\x66\x18\x9b\x20\x54\xc6\xa7\x61\xd0\xc2\xb7\xe6\x80\xd7\x53\x35\x6a\xde\x5e\xba\x90\xb3\xbf\x0d\xbe\xb2\x28\x39\x93\xee\xa5\xf0\xc6\xbe\x16\x38\x28\xc0\x7c\x43\xd3\x28\x32\xd2\x7a\x7d\x3f\xba\xf7\x6a\x07\x3d\xf9\x4e\xaa\xfc\xca\x46\x40\x0e\xc3\x21\x26\x49\x30\x8e\xbe\xb4\x46\xb1\x36\x98\xf2\x4c\xbf\x1a\xd9\x98\x3a\x8c\x0a\xf7\x11\x80\x1c\x31\x96\x7f\x60\x01\x6a\xe6\xcf\xa6\x6f\x34\xfb\xb3\x39\x66\xa2\x06\x7c\xa0\xa8\x9a\xda\x99\xa9\xb6\x08\x4b\x93\x19\x37\x7b\xaf\x7b\x51\x43\x5a\x1c\x34\xcd\x8d\xe1\xec\xe7\x16\x84\x8b\x5b\xaf\x93\x5b\x23\x7f\x35\x4f\xa8\x8b\xbc\x3b\x09\xec\x91\x77\xf8\x4c\xdd\xb9\x03\x02\x5d\xf2\x3f\xb7\x6c\x98\x39\x75\xfb\xf6\x66\xa0\x2e\x11\x30\xbf\xfe\xe8\xaf\x92\x4e\xc8\x3f\x25\xfd\x81\x13\x35\xf2\x51\xd2\xe4\x93\xe1\x4b\xcf\x8a\x13\x2e\x6f\x25\xb7\xff\x29\xc9\x1f\x6d\xea\x1b\x59\xad\x6a\x93\xfa\xa2\x4d\xf5\xb8\xc7\xe6\x09\xaf\xfc\x13\x38\xc4\x30\x2f\xb4\x5d\xaf\xaa\xc0\x2c\xf4\xe8\xa3\x3c\x36\x87\xb2\x1e\xbf\x2c\x8c\x1e\xd0\xaa\xcc\x67\xc2\xc5\x0d\x10\x47\x2f\xe4\xf1\x7a\x2d\xf4\xab\x3e\x4a\x71\xcb\x1f\xfd\xcc\x80\x89\xe5\xc5\x38\xe1\xe7\x8c\xb0\xc1\x15\x8c\xb9\x33\xf4\x6a\xb8\x48\x19\x33\x67\x28\xdc\xd1\x72\x66\xb3\xb5\x36\xae\x02\xf0\xa1\x71\x64\x94\x3c\x14\x11\x01\x62\x75\x79\x63\x64\x6e\xca\x5d\xaf\x39\xe8\x8e\x8c\x66\x86\xb7\x9a\x19\x7b\x39\xdd\x6b\xaf\xfd\xa5\x0f\x60\xe2\xfd\x30\x2a\xbb\x62\x1d\xb8\xd0\x2f\xe6\xf4\x81\x87\xd1\x24\xa2\x88\x5f\x31\x8e\xd8\x5e\x28\x08\x54\x55\x88\xe6\x70\xf4\x07\x10\x38\x6a\x09\x8b\x7a\x8d\x57\x1e\x0b\xd6\x1f\xe7\x29\x8b\x58\xc2\xab\x63\x67\x01\xe1\xd0\x26\x8a\x8a\x1e\x1d\x93\xb2\xa2\x77\x02\x2b\xd7\x3a\xf8\xe6\xb5\x15\x31\x32\x1e\x86\x6c\x86\x0c\x93\x7f\x94\x15\xc4\xaa\x77\xa1\x36\x8a\xea\xa8\xac\x8e\x89\xf9\xb1\xe1\x1f\xaa\x3b\x77\xc2\x70\xc9\x95\x61\xdf\x65\x75\xfb\xb6\xcb\xe7\xdf\x6f\x4d\x10\x6c\x28\xd5\xd3\x8a\x5e\x6f\xc8\xaa\xa2\x75\x85\x4e\x2b\x4c\xce\xe1\x6a\x34\xc5\x64\x59\xd1\xd3\xaa\xad\xf0\x45\x15\x63\x1a\x82\x93\x82\xdd\xb1\xea\x59\x0e\x18\x84\x23\x8f\xeb\x73\x5a\xcd\x9c\xb1\x46\xb4\x5e\x4b\x2d\x9d\xd8\x09\xf2\x5c\xc0\xb0\x2d\x5f\xd9\x98\x3b\x1f\xc4\x92\xd5\x9f\xb9\x89\x7f\x6b\x1d\xea\x43\x4e\xb0\xf5\xc5\x57\xbd\xd7\x0c\x1c\x19\x61\x2e\xf0\x7b\x65\x30\x7f\xd9\x51\x75\x4c\xd5\x51\xdb\x7f\xa0\xea\xe2\x61\x25\xf1\xdf\xaa\x9d\x26\xe8\x0f\x57\x8a\x32\x4c\x58\x80\x5b\x1f\x0e\x3b\xcb\xb1\xcd\xec\x7c\x1c\x90\x35\x40\x80\xaf\x10\xbe\x6e\x2a\x74\x5e\x61\xd2\x54\x68\x15\x06\x75\x3b\xa9\x82\xf3\xb3\x55\xe5\x3a\x79\x44\xe9\x69\xd5\x35\x61\x39\xbc\x87\xf1\x6c\xa1\x0b\x20\x0a\x93\x85\x2e\x90\x84\x5e\x35\x97\x55\xd7\xdc\x26\xea\x41\xee\xb8\x4b\x58\x4b\x32\x10\x2b\x4c\x8e\xcf\xb8\x0a\xdb\xdf\xb2\x14\x2f\x0a\xea\x6e\x91\xb4\x97\x13\x81\xea\x6a\x84\xe0\x39\xef\x05\x38\x9a\xdc\x23\x5f\xc0\x86\x21\xf9\x60\xa1\x64\xb4\x70\x16\x45\x8e\x37\x68\x73\x1e\x02\x3d\x9a\xe1\xb4\xd3\xe3\x5a\x52\xdb\xd6\x89\x5c\x9e\xc5\x9d\xb8\x5e\x9f\x56\x7a\x6e\xb4\x44\x26\x86\x96\xdc\xd1\xf2\xdc\x3f\x01\xc4\xb1\xd6\xb0\xfd\x66\xba\x8e\x7a\x71\x79\x0e\xef\x63\x3c\x13\x7a\xbb\x69\xbb\x64\x59\x61\x22\x7f\xbc\xaa\x94\x93\x68\xb8\xf8\x8a\xe2\xcc\xa6\xfb\xce\x07\xb3\x50\x83\xf2\x45\xde\xd9\xdf\xc7\xd5\x4d\x98\x80\x7f\x46\x4f\xbb\xe8\xf4\xe4\x4d\xf4\xd8\x9c\x20\xf9\x87\x6f\xe3\x77\xcf\xab\xa6\xcc\x3f\x16\xbc\xcc\xc9\xeb\xf8\x9b\xfc\x4b\xc3\x6b\xf5\x86\x15\x42\x91\xf7\xd1\x23\x51\x5d\x92\x5f\xa2\x14\x3d\x84\x0c\xd9\x5d\x1d\x5f\xf2\x0b\x5e\x92\x4f\x51\xae\xe7\xcb\x25\xcf\x0b\xa6\xda\x38\x18\xaf\xaa\xef\xa2\x23\x3e\x8f\xb2\x74\xd0\xf6\x1f\x46\x0f\x5f\x56\x97\xfe\xc9\xcb\xf8\xcb\x79\xd9\x7e\xf4\x1b\xb0\xdd\x27\xce\x6e\x63\x44\xe9\xeb\x6a\xfe\xba\x8a\xe1\x8b\x9e\xd9\x8e\x78\x64\x7f\xff\xaa\xe8\x68\x4a\x7e\xaf\xe8\xfb\x0a\x61\x72\xab\xa2\x53\xbe\xff\x8f\xdf\xab\xf9\xfb\xe8\x3d\x3b\xca\x75\x9e\x3b\xbf\x57\x81\x5b\xec\x07\xcd\x3f\xec\x0e\xe2\x97\x0a\x61\x6b\x7c\xf2\xa9\x72\x7b\xf9\xfb\xf7\xcd\xa9\xe4\xab\x36\xe5\x9e\x49\x79\xde\xa6\xdc\x35\x29\x0f\xdb\x94\x43\x93\xf2\xb2\x4d\x39\xf0\xaa\x97\xee\xb2\x1b\x87\x62\xfd\xad\xea\x07\xd4\xdf\xb9\x7f\xdf\x95\xf3\xa9\x32\x25\xdf\xf7\xe0\xa3\xaf\x5c\xca\x5d\x97\xf2\xdc\xa5\x1c\xba\x94\x87\x2e\xc5\x63\xa5\xbe\xac\x7e\xb0\x3e\x3f\x55\x1d\xe7\x3d\xa8\x20\x79\x5c\x59\x5f\x4a\x2f\x69\x57\x9d\x28\xcf\x2e\xe7\x9f\x95\xb7\x50\xf0\x82\x73\x85\x42\x34\xbf\x47\x95\x43\xd0\x7a\x54\xcd\x5c\xc7\xbe\xd1\x2f\x6f\x7e\xad\x42\x6f\xc9\x5f\xed\x7b\xa3\xbf\x2a\x2f\xbc\x3d\xab\xf0\xb5\x1e\x04\x0e\x2f\xcc\x98\x45\x18\xb1\xe4\x59\x35\xfb\xa9\x42\xf7\xef\x47\x51\x5a\x8c\x87\x5c\x1c\x58\xd4\xae\xe0\x00\x87\x9f\x57\xd7\x82\x0a\x34\x9a\x60\xbb\xaf\xf7\xb1\x36\x36\x1b\x8c\xdd\x00\xb4\x9e\x51\x0a\x5f\x1b\xf2\xf9\xda\xa4\x29\x7a\x56\xd1\x67\x1e\x21\xef\xf6\x14\x03\x0d\x3e\x55\xe4\xe7\x4a\x8b\x3f\xce\x4e\x03\x46\xee\xc6\x04\x39\xfc\x67\x45\xbf\x8e\xdf\x82\xe8\x6c\xa6\xeb\x23\x5d\xfa\xe3\x4a\x9c\x16\x67\xed\x60\xfd\x58\x79\xd5\x1c\x78\x4c\x79\x2c\xad\x6a\x55\x77\xa2\x59\x2b\x83\xaf\xa0\x8c\x92\x23\xca\xd8\x8a\x67\x47\xe2\x58\x4b\x68\x47\xe2\x18\x4c\x26\x03\xd0\xd7\xc8\xb5\xf9\x0f\x10\x7f\x8c\x41\xdc\x0b\xdb\x3b\x9c\xd9\xe3\x31\xd6\x45\x33\x64\x08\x5f\x2b\x46\x39\xa3\x36\x6f\x20\xa0\xb2\x56\x62\xfc\xc3\x2f\x08\xb3\xa6\x42\x7f\x54\xd8\x06\x99\x1d\x7f\xb2\xf2\xd3\xf8\x93\x7d\x6e\xa3\xde\x07\xa2\x29\x6b\x55\x4c\x5d\x65\x92\xe8\x86\x07\x44\x56\x7c\x30\xd8\xb3\x0a\x83\xec\x14\xa8\x75\xc4\x7a\x8d\xc4\x40\x16\xa3\x33\x09\x9f\xac\xa9\xb2\x7e\xd3\x71\x22\x69\xf7\x13\xa8\x93\x1f\xcf\x02\x25\x51\x20\x39\xdb\x06\xbc\xa8\x28\x27\x86\x56\x46\x7b\x17\x04\x61\xcc\x39\x80\xe8\x8a\x45\xc1\xeb\xd6\x60\xcb\x79\x71\x1a\x12\x19\x1f\x5a\x1b\xc3\xa8\x06\xc3\x2e\xf4\xb2\x00\xbb\xb5\x38\x63\xd7\xd9\xba\x60\x6d\x34\x6d\x66\x8e\x65\x47\x53\x63\x04\x07\xd8\xd2\x5a\xd0\xe8\x2b\x26\xd2\xd4\xe3\x32\xef\x59\x23\x39\x5d\x79\xa2\x68\x9b\x8e\x89\xa2\xd7\xb6\x07\x33\x4e\xaa\x93\x9a\xcb\x0b\x9e\x3f\x2a\x54\x9d\x29\xa2\xb7\xdd\x06\x38\xc1\xc5\x08\xe1\x2c\xec\x8c\x17\x5d\xb9\x6c\x6f\xa2\xe5\x32\xce\xa8\x22\x2f\xaa\x88\x26\xf4\x1a\x1a\x9d\x4d\x48\xd8\xd0\x4c\x11\x1b\x70\x99\xcb\xda\x7c\xc9\xf6\x99\xa6\x32\x6c\xfb\xa9\x47\x15\xe2\xf1\x10\x83\xb1\x5e\xb2\xc8\xef\xae\x86\x11\xcb\xc7\xe6\xac\xe5\xd7\x86\x37\x9c\x5e\x9f\xb0\x9a\x1b\x2c\x94\x4e\x68\x4c\x53\x95\x47\xac\xb6\xe0\xfb\x99\xd9\x8a\xb0\x7e\x5a\x7d\xce\x24\xcf\xb3\x6b\x8b\xa3\x6c\x69\xc2\x4f\x4f\xf9\x42\xb9\x7a\xb7\xbb\x1e\xdb\x5b\x7a\x58\x04\x15\x21\x2a\xaa\x96\x39\x20\x54\xdb\xab\xea\xaf\x7b\xd5\xb4\x83\xa5\x4d\xe9\xd6\x59\x8f\xb0\xe8\xb9\xad\x3f\x1f\x9b\x0b\x5f\x73\x3e\xb6\x57\xa1\x2e\x6f\xc1\xc2\x15\xe4\xda\xe3\x3e\x67\xfa\x3b\x82\x67\x8a\x28\x76\x06\x60\x7c\x57\x65\xc5\x72\x43\xa1\x85\x95\x8b\xcc\x5d\x3b\x70\xda\x62\xf3\x76\x10\x87\x13\x27\x68\x3f\x76\x3c\xc1\xc8\xb6\x50\x55\xec\xb0\xab\x67\x8e\x01\xcc\x95\x1d\x17\x19\xb2\x57\x02\x7e\x88\xb0\xe9\xe0\xc3\x67\x5e\xa2\x2a\xa8\xc0\x29\x8b\x77\x7f\x61\xdf\xc8\x2e\x1f\x6a\xed\x73\x05\x85\xb8\xa0\x72\xa0\xa6\x96\xb9\x5a\x9e\x1a\x34\x4c\x50\xd1\xed\x23\x8c\xaf\xf3\xca\x22\xe5\x06\x34\x15\x2d\xae\xb6\xa1\xae\x00\xee\x00\x24\x86\xa0\x62\x2d\x99\xc7\xf6\x2a\xa0\xf5\xd8\x5d\x06\x14\x77\x84\x62\xf3\x8a\x32\x5a\x64\x8c\xda\x89\x54\x80\x96\x57\x5f\x76\x17\xca\xf8\x15\xd5\xbe\x62\x39\x28\xa4\xfa\x68\x3f\xe1\x30\x95\x37\x0c\xd3\xaa\x3b\x2c\x99\x1b\x87\xb2\x3b\x0e\xa5\x1f\x87\xc4\x86\x57\x0b\xa7\x85\xf0\x71\xb1\x10\xa7\xa2\x33\xb6\xf1\xbc\x47\x6a\xaa\x32\x6e\xeb\x4f\xba\xd9\xc3\x85\x69\xc5\x62\x53\x67\x16\x0f\x8a\x99\x61\x2e\x0e\xdc\xb8\x37\xe7\x28\xeb\x4d\x33\xca\x6c\xcb\xfc\xa8\x0d\xd4\xfb\xf8\xba\xfb\x94\xfa\x28\xe2\x0d\xad\xc9\x82\x36\x50\xeb\x59\x63\x87\xb5\x5b\x63\x28\xa5\xe5\xbc\xa0\x8b\xac\x34\x0f\x16\xa4\xa4\x0d\xbc\x96\x6f\x19\xb6\x16\xc7\xe4\x94\xa2\x9c\xe6\xd1\xc0\xed\x54\x79\x76\x6a\x23\x1d\xd8\xef\x9c\xce\xf3\x1e\x35\x17\xd9\xa9\xfb\x6e\xde\xa5\x66\x63\x83\xb3\x5a\x9b\x5f\x6c\x4d\x65\x58\x30\x2c\x4a\x3a\x21\x39\x5d\x50\x63\xac\x34\x9b\xe1\xeb\x9a\x16\x30\xc8\xa1\x09\x2b\x5a\xb4\x53\x00\x24\x00\x99\xd6\xd8\x18\xe1\xb6\x06\x29\xd0\x0e\xa8\x44\x30\x77\x56\x66\xc6\x4c\x60\xb2\x14\xd1\x64\x29\xfa\x93\xa5\x18\x9a\x2c\xd8\x19\xd4\x9e\x53\x4e\x96\xb4\x70\x67\x9e\x35\x55\x64\x45\x05\x59\x9a\x88\xcc\xd6\x9e\x3d\x8a\xd8\xef\x81\x87\xce\xe9\xd2\x7d\x0d\xe3\xeb\x53\x7a\x6e\x80\x21\x56\xe4\x94\xd4\xd8\x1f\xeb\x9f\xd2\xf3\xc8\x34\x60\x67\x2f\x3b\x37\x81\xa4\xe9\x9d\xfd\xc9\xfd\xbb\xa9\xbd\x5b\x1f\xee\xcf\xac\x41\xbd\x5f\x68\x51\x4d\xbf\xf3\xdd\x79\xf4\xd1\xec\xbc\xb5\xe9\x3d\x35\x92\x65\x58\x17\x17\xc8\x40\x8f\xef\xc9\xc6\x07\x95\xf3\xf4\x01\x15\xbd\xa9\x0c\xdd\xdb\x75\x43\x10\x62\xfe\xda\x69\x8a\xe7\xfe\x92\x1e\x15\xc7\x59\x6d\x4e\x89\x0a\x17\x48\x71\x35\xd0\x4d\xf5\x7f\xd0\x4d\xae\x0e\xf9\x1c\x2d\x68\x4e\x57\xa4\xa1\xa7\x38\xf3\x63\x62\x45\xca\x35\xad\x67\x91\x9d\x77\x01\x8f\x70\x64\xfd\xdd\x9f\x9f\xd8\x19\xb3\xd3\xda\x2c\x22\x75\x30\xf7\xba\xf3\x9b\xd6\x64\x70\x06\x6f\x1c\x7b\xca\xc1\x26\xef\x14\x93\x60\xfc\xd3\x86\xb0\xfe\x94\xea\x97\x9d\x93\x27\xe5\x9a\x96\xc4\x4a\x87\x70\x15\x49\x2b\xf4\x34\x44\xc9\x60\x81\xae\x8c\x53\xe5\x7a\x83\xf8\xab\x48\x44\x35\x71\xce\x95\xde\x6c\xb5\x1e\x58\x2a\xf4\xc0\x52\xc6\x03\xcb\xd1\x3e\xe0\x25\x95\xc5\xf9\x70\x8f\x4c\xc1\x92\x8a\x21\x7d\x59\x4f\x51\x77\x7f\x4a\x2a\x8c\x67\x95\x19\x9e\x12\xdb\x0d\xd4\x92\x51\x24\xf8\xe5\x8e\x1c\x83\x29\x89\xe0\x42\xe1\xb1\xe4\xa7\x75\xa0\xac\x0d\xb8\xb3\xb0\x66\x82\x7a\x61\x45\x26\x9e\x69\x1c\xe4\x1c\xcf\x55\x66\x76\x50\xc6\x87\x3f\xa6\x9c\x20\x06\xbb\xd7\xc8\xdd\x69\xbc\xbc\x04\x5d\x65\x95\x48\x67\x8c\x5e\x17\xf5\xab\xaa\x01\xc0\xe3\x3e\x2a\x1d\xa0\x56\xf2\x71\xac\xc2\xd2\x52\x3f\x84\x32\xd7\x5f\xda\x10\x2e\xbe\xe8\xc2\xdf\x71\x65\x16\xca\xae\x8b\xc0\x40\x01\x56\xd9\xdc\xd4\x08\x93\x8a\x2e\x00\xb1\x86\xd1\x05\x83\x70\x4b\x33\xe6\xa6\x8a\xdf\xc1\xe8\x0d\x0c\x0b\xba\x05\x13\x10\xb1\x18\x26\x79\x8d\x38\xa9\x88\xc4\xbe\x1e\x6f\xf9\xaa\x64\x0b\xfe\x5f\xab\x8b\x62\x67\x74\x4a\xfe\xb3\x3a\x3d\xab\xe4\xc2\x89\x06\xb1\x2d\xcb\xb6\x0a\x09\x53\x21\x69\x2b\x54\xe9\x0a\x41\x14\x0b\xb0\x3e\xa0\xbb\xb6\x12\xe0\xeb\xd4\x56\x42\xd9\x4a\x54\xb6\x12\x12\xc2\x21\xb4\x03\xed\x8a\x45\xae\x95\x85\x3f\x35\xee\xb3\xdc\x8e\x96\xdd\x68\xfd\xfc\x08\x36\x6d\x99\xf3\xe1\x74\x24\xa1\xf0\x6c\x14\x02\xad\x43\xa4\x5d\x8f\x97\x54\xd4\x6f\x1a\xc9\x8d\x5e\xc1\xbd\x0c\x48\x17\xba\x91\x70\x51\x11\x16\x9e\xfa\x9c\xb0\x58\x1d\x3b\x9a\x92\x8a\x9e\x56\x84\x39\x9c\x17\xa3\xda\x9e\x0d\x43\xe6\xed\xb0\xd6\x60\x63\xce\x68\xc1\x10\xc3\x19\xaa\xe8\x59\x85\x14\x9e\x2f\xab\x2c\xd0\x0f\x33\x2d\x03\xdb\xc3\x5c\x19\x97\x5e\x63\x3c\x87\x93\x95\x0a\x67\xa7\x95\xde\x51\xea\x99\xad\xc0\xda\xa0\x3f\x15\xdd\xe1\x1e\x90\x31\x70\xb7\xb3\x29\x73\xfb\x6b\xf6\x11\x6e\x7b\x24\xe9\x19\x23\x01\xe9\xa9\x22\xaa\x3b\x42\x28\x27\xff\xe9\x49\x48\xf5\x77\x4f\x42\x02\x61\xf2\x32\x60\x57\xdc\xb5\x86\x0c\x1c\xb1\x2b\xc0\x10\x82\xbe\xfd\xbd\x28\xcb\xb7\x7c\xc1\x8b\x0b\x0e\xba\x1e\x3d\x1a\xb6\x3e\x84\x41\x30\x5c\xe0\x87\x5f\xde\x3d\x7c\xf6\xf4\xd3\x8d\xe5\x7e\x2f\x8f\x29\xde\xd6\xdb\xe8\x18\xce\xd8\x78\x80\x7d\x20\xe5\x72\x91\x8e\x9a\xe2\x2b\xeb\xba\x0e\x86\xc7\x03\x15\xc0\xc3\xd5\x54\x10\x6b\x3b\xd4\x65\xe2\xa4\x82\x15\x80\x2e\x19\x81\x7d\xfc\xcc\x19\xda\x84\x23\xf9\xc6\x31\x5c\xb9\xac\x6e\x2c\xb3\xc1\xb1\xdc\x66\x83\x61\xcb\x30\x26\xb0\x15\x10\xc0\x9f\xb6\x56\x6f\x80\x1f\xe8\xda\x9d\x71\xf5\x84\xcb\xe2\xc2\x66\x7b\x26\xab\xa5\x51\xdc\xa5\x29\xb2\x6b\x18\xd3\x8b\xd2\x96\x62\xb7\x74\xe9\xb6\x52\xd7\xeb\x81\xec\x15\x20\xef\x08\xb6\xaa\xcf\x2b\x65\x6c\xce\x0c\xcf\x09\x73\xb7\x6b\xf4\xe0\x58\x80\xe5\x2e\x4d\x07\xf3\xf7\x33\xae\xd7\x48\x39\x1b\x30\x32\x58\xa3\xa1\xc2\x87\x52\x11\x1e\x7e\xff\x86\x3a\xde\xf0\x10\x61\xa2\xb4\xcc\xe2\xd8\xcb\x96\x21\x5c\xb9\xde\xb0\x7e\xc3\x3f\xd0\xfd\xf8\x3b\xcd\x7c\x52\xe4\xb6\x7a\xad\xf0\xbc\x6f\xe4\x89\xa7\x8c\x3e\x94\x92\x5d\x8d\x8b\x1a\x7e\xdb\xa5\xe7\x73\x28\xc6\x05\x71\xab\xf5\x44\xc0\x83\x9d\xc1\xd3\xb4\x0f\x8f\x67\x5e\x1f\x7f\x02\x57\x15\x6b\x00\x11\xdd\x4e\x47\x36\x44\x79\x4f\x5f\x77\xdf\x42\x01\x48\x1a\x04\x2f\xdf\x0c\x1e\xe5\xed\xdf\x25\x1c\xbb\x20\x59\x49\x72\xdb\xc7\x5b\xec\x85\xa6\x57\xba\xfe\x61\xf5\x83\x81\x0d\x4f\xe0\x67\xfc\xc9\x18\x5a\xbd\xe5\xa7\xe0\x6f\x03\x89\x19\x52\x34\x94\xb8\x8c\xf6\x59\x1a\xd9\x50\x51\x4a\x97\x0c\xac\x14\x4c\x0a\xbd\xde\xf8\xf0\xc5\x7c\x6e\x63\xc0\xaa\xa3\xea\x38\xd3\x7f\xb4\x1c\xa6\xc2\xaf\x54\x44\x59\x67\x06\x63\xe1\x15\x50\x30\x6e\xeb\xee\xbd\x7d\x8c\x8d\x31\x80\x23\x63\x27\xc3\xfd\x09\x04\x71\xeb\x1b\x19\xbd\x6b\xd5\x5c\xad\xd9\xd9\xc8\xa3\x95\x75\xe8\x3f\x25\xc9\x91\xe9\x4e\x8b\xc7\x78\x9c\x50\xda\x07\x52\x74\xd6\x3e\x16\x72\x10\xcf\xed\x18\xd8\xb9\x2c\xd4\xf9\xce\x67\x7e\x55\xef\x5c\x27\xb7\x63\x70\xc3\xf1\x5f\x55\x21\x50\x42\x76\x12\x7c\x3b\xd9\x24\x99\x0a\x05\x87\xc7\xac\x1f\x43\xc7\xec\x25\x9c\x28\xa1\x60\x83\xf2\x14\x36\x13\x4e\x6b\x2f\xe7\x16\xef\xcf\x24\x53\x41\xc2\x5c\x54\xe0\x4c\x99\xad\x8e\x4d\x88\x9f\x5a\x05\x9d\xbb\x85\xed\x89\xdd\x01\xdf\x0b\xb6\x36\x02\x56\x22\x38\x36\x8a\x6d\x38\xc3\xf3\x03\x39\xc3\xca\xac\x58\x92\xca\x71\x6d\xcd\xb8\x06\x2d\x78\x02\x03\x57\xee\xe2\xf1\xba\x62\xd4\x0c\xfb\x21\xfb\x99\x5f\x69\xd1\x8d\x2b\x03\x74\x0c\x71\x03\xed\x2d\x20\x20\x13\xa5\x45\x1b\xd5\xfd\x58\xd0\xf5\xd1\xc9\x1b\xe2\xf4\x56\x6d\x8c\x59\xcd\xfb\x74\xa2\x25\x18\xf3\x72\x0f\x8c\x81\x21\xbb\x6e\x7a\x83\x67\xf3\x8e\x24\xdc\x39\x0c\x82\xd8\xd5\xba\xfe\xcc\x41\x27\x09\xb9\xf0\x03\x31\x47\xca\x92\x72\x97\x08\x9c\xc9\x2c\xbe\x17\x01\xde\x68\x10\x3a\x9d\xfb\xe8\xe0\x41\xc9\xa0\x95\xb6\xef\x46\x12\x4e\xdd\xae\xee\x01\xa1\x8d\xe1\xdd\x21\x90\x50\xb1\xb3\x39\x42\x8a\x7e\xd1\xd2\x04\x1f\x2f\xab\x1c\x1c\x66\xec\x89\x0a\xd5\xc4\xc8\xf4\xf3\x0a\x86\x5b\x94\x1e\xa8\xcf\x07\x3f\x63\x43\x68\x8e\xb9\x71\x98\xd3\xb2\x00\x78\x39\x98\x10\x27\x48\x9a\x32\x8d\x88\x01\x25\x9f\x52\xcf\x5c\x89\x6c\xbf\x24\x75\x0d\x24\xfd\x50\x23\xf3\x2e\x01\x47\x09\xf7\xa6\xb1\xca\x8e\x6a\xbe\xb5\x9c\x40\x61\x7e\x03\x61\xf6\x1d\x61\xd6\x6b\xb5\xcd\xd5\xdd\x98\xb4\x85\x29\x71\xe6\x62\xb9\x32\xad\x06\x0c\x10\xc8\x1d\x27\x01\xd1\x7f\xfe\x11\xa2\x07\xc6\xaa\x47\xc7\xdb\x7a\x20\xf7\xfb\x21\x36\xd0\xa2\xbb\x51\x57\xff\x16\x7e\x55\x8b\x52\x7f\xaf\xb3\x4f\x83\xf5\xaf\x6f\x77\x3b\x64\x6e\x6b\x59\x82\x19\x65\x49\x72\x5b\xb9\xaf\xc7\xdf\x08\x71\x64\xc3\x23\x31\x37\x96\xda\x28\x84\xe3\x5b\xb7\xcc\x63\xab\xe6\x7b\xea\x9c\x32\x84\x1e\x25\xca\x8c\x12\xcb\x12\x06\x46\x89\x08\x47\x89\xd9\xb4\x60\x22\xda\x9a\x08\xa3\x6d\xfb\x9c\xf9\x7a\xff\x5c\xa3\x2d\x95\xd6\x6b\xd3\x53\x06\x56\x41\xbf\x23\x0f\x8a\x6b\xa8\xdc\xbe\x62\x64\x96\xa8\xb1\x76\xd1\x19\x36\x61\x5c\x75\xa5\x72\x47\x83\x39\xb4\x2a\x73\x87\x17\x3d\xfa\x0f\x99\x3b\x0b\x1c\x4f\x4a\x63\x8b\x9e\x19\xde\x90\x24\xb7\x5d\x50\xc9\x1e\xed\x03\xf3\x4d\x4f\x7b\xb1\x8d\xf6\x3b\x30\x2b\x41\x2a\x30\xd3\x94\x52\xfa\x6e\x6e\xc7\xa5\xe9\x04\x3f\x92\xc1\x30\x3f\x6b\xb9\x46\xe6\xfd\x3d\x3c\xd1\x83\xe2\x16\x71\x3e\x4b\x71\x01\x14\x17\x78\xb8\x71\xed\x7c\x30\xde\x72\x40\x6d\xb1\x85\xda\xe7\xa1\xbb\xc0\x10\x55\xe5\x00\x55\x7d\x48\x61\xe8\x67\xca\x01\xda\x41\xb8\xf0\x8f\x49\x72\x1b\xd4\x2e\x43\x64\x95\x01\x38\x88\x23\xab\xdc\x4a\x56\x5f\xb4\x45\x0e\x81\x45\x4f\x64\xf0\xeb\xbe\x26\x43\x82\x2b\xc2\x89\xec\x12\xbc\x22\xe6\x85\xac\x31\xcf\x75\xdd\x62\x7a\x2f\xc2\x66\xdc\xf4\x2d\x52\x61\xdb\x05\x12\xba\xc0\x07\xb2\xdc\xc9\x87\x28\x01\xc1\x1a\x5d\x1f\x28\xcd\x84\x07\xfb\x60\x89\x2a\x02\x2e\xae\xad\x95\x85\x39\x7d\x20\xc6\x19\x96\xe4\xb4\x20\x4b\x5a\xd0\x09\xb9\x88\xbc\x63\xf3\x34\x5d\x3e\x28\x9d\x82\x74\x79\xfb\x36\xbe\xce\xcd\x1a\xfb\x8f\xe5\x1c\x5d\xd0\xdc\xba\x30\xe3\xec\x82\xe6\x5e\x12\x30\xce\xa8\x2b\x54\x91\x9c\x94\x47\xcb\x63\x52\x87\xa1\x32\xcf\xcc\x39\x06\x75\xe7\x18\x17\x56\x0f\xbf\xe1\x69\x9a\xfb\x05\xf8\x2c\x5c\x80\x95\x2e\x0a\x93\x82\x32\x74\x46\x0a\xb2\xf4\x32\xee\x62\xde\xd0\xb3\x6c\xe1\xc5\x88\x33\xb2\xa0\x67\x24\xa7\x17\x9a\x88\x4b\x70\x18\x89\x1d\xa7\x84\x29\xa9\x09\xea\x93\x5b\x4b\x8c\x4e\x43\x9d\x94\x91\xd3\x53\x54\xb9\x66\xe8\x3d\xac\xae\x45\xde\xab\x45\x1e\xd4\x22\x27\x0b\x9a\x7b\x6b\x94\x06\xf0\x57\x72\x2a\xe1\xd3\xdb\x3e\x73\x41\xcf\x51\x4e\x2a\xb2\x0c\x3f\xe5\xfd\x05\xe8\x45\x48\x8e\x7c\x6c\x24\x7b\xd7\x82\x0b\x18\x4a\xcb\x0c\x7e\x0d\x99\x2e\x7a\x15\xbc\x08\x2a\x78\x41\x16\x9a\xec\xad\xd4\x93\x0f\x20\x4b\xb5\xc6\x95\x9a\xfc\x1c\x6f\x30\x26\x4d\x80\x85\x0c\x38\x5b\x80\xba\x66\x70\x1e\x7e\x47\xa6\x9b\x07\x36\x69\x8b\xee\xd6\xe9\x60\x82\x83\x21\x81\x6a\xba\x30\x92\x7c\x8d\x7b\x76\xa1\x07\x53\xdc\x62\xa6\xe5\xd4\x0e\xd8\x25\x2d\xc9\x05\x2d\xe9\x84\x58\xd9\xf1\xca\x1e\x58\x20\x6f\xfa\xbe\x4c\xd3\xd1\xd5\x38\xaf\x04\x9f\x5d\xdc\xbe\x1d\x64\xc0\xd7\x4b\x3b\x86\x2f\xe6\xe8\x8c\x2e\xad\xab\x3c\xce\xce\xe8\x32\x1a\xc3\x27\x30\x86\x97\xe4\xca\xb8\x69\x92\x26\x1c\xc6\x27\x7e\x18\x2f\xd3\x14\x2d\xe9\x59\x30\x8c\x97\x7e\x18\x9f\x74\x87\xf1\x12\x93\x92\x32\x74\x42\x4a\x72\x81\xdb\x63\x9c\x05\x3d\xc9\xfc\x04\xa2\x27\x24\xa7\x27\x64\x49\xcf\xf4\x30\x36\x6d\x08\x07\xf0\x12\x93\x45\x50\x93\xa5\x1d\xc0\x5b\x5a\xdb\x7a\x7d\xea\x81\xdc\xb6\xc5\x20\x3c\x30\x74\xd5\xab\xca\x55\x50\x95\x2b\x92\xd3\x2b\x3f\x54\x16\x30\x96\x97\x30\x96\x97\xf8\xfb\x5f\x3c\x47\x4b\x52\x91\x8b\xce\x57\xdb\x61\x7d\x15\x92\x67\xd9\x19\xd6\x57\x30\xac\x2f\xb2\x2b\x33\xac\xff\x6e\x5d\xa1\xc4\x1f\x1b\xd6\x0b\xc7\x36\x03\xb5\xbb\x24\x4c\xf3\x4b\xc3\x2b\x6f\xd2\xb2\xa5\x29\xf3\x2b\x84\xef\x77\x06\x11\xb6\x1a\xc0\x3a\x63\x9d\xf5\xc2\x61\x0d\xde\x54\xa8\xee\xde\x05\xb6\xeb\x17\xeb\xaf\x5f\x16\x84\x61\x61\x3e\x44\x9a\x16\x18\xa5\x31\x1e\x1f\x8d\x5d\xe1\x17\x70\x77\x97\x3a\x94\x0c\x13\x51\xd8\xd5\x17\x5f\xeb\xa6\x36\x8e\x82\x98\xc0\xc6\xa1\x21\xbd\x2a\x07\xd2\x15\xa7\xd2\x1f\xe2\xfa\x70\xc5\x4d\x67\x23\x62\x3e\xf1\x9d\xe2\x43\x49\xb1\x21\x2c\xda\x4f\x84\x5f\x81\x42\xdc\xf4\x52\x70\x43\x1a\xea\x8b\xdd\xb4\xed\x81\x9d\xcf\x6f\x35\xea\xd6\xdf\xc9\x8a\x35\x01\x7a\x75\x9a\xa3\xe5\xf2\x5a\x0b\xb7\xa6\x20\x93\xc7\x55\x32\x12\x6e\xa3\x2a\x6b\xf1\x9e\xd4\x61\x49\xb5\x5f\x7f\x4b\xc4\xbd\x0c\x60\xfb\xaa\xb1\x83\xa2\xdd\xb1\x9b\x73\x44\xd3\x4f\x06\xbc\x72\x1f\x04\x03\xf0\x93\xd9\x8a\x4c\x06\xd4\x8d\x52\xe2\xcc\xf1\x56\x08\x72\xc7\x49\xa6\x57\x64\xa7\x57\x24\x61\x5b\x37\x43\xdd\xce\x90\x61\x67\xc4\x3a\x87\x0d\x92\x5a\xa0\x67\x31\xc5\xda\x72\x42\x02\x6d\x86\xc4\x41\x36\x20\x0e\x32\xec\x43\x84\x27\xc9\x6d\x16\x80\x05\x1e\x3a\x82\xcd\xd1\x96\x46\xf5\xfb\xda\xb4\x40\x67\xf8\x72\x43\x45\x31\x29\x2d\x98\xd8\x53\x86\x98\x17\xc3\x96\x9e\x35\xe8\x47\xbf\x07\x4f\x2e\xa2\x27\x8b\x34\x7d\x67\x4f\xfa\xbc\xc1\x2a\x4b\xd3\x51\xe3\x26\x35\x8f\x2c\x29\x8c\x05\xc2\x6e\x66\x2d\x1d\x4c\xaa\x4d\x9e\x1e\x64\xdd\x35\x71\x97\x7c\x41\x2d\xdc\xbf\x3f\x1b\x4b\x5a\x0d\x9c\x69\xa4\x39\x5c\xfe\x93\xd1\xc7\x0c\x8d\x26\x98\xbc\x31\x57\x53\x4c\xde\x32\x7a\xbd\x21\xaf\x19\xad\x2b\xf4\x96\x61\xf2\xde\x5f\xfd\xe2\xae\x5a\xb5\xec\x27\xe6\x02\x0a\x52\x4a\xdf\xb2\xee\x12\x7d\x77\xbf\x75\xd4\x08\x74\x38\xaf\x58\xe4\xe0\xba\xa8\xd0\x2f\xcc\x7a\xa7\xbc\x67\xd6\xb5\xe2\x35\x23\xfa\x9b\x3c\x88\x53\xe1\x4c\xc6\x3d\x11\x14\x45\x8a\xb6\x71\x07\x5a\x88\xa0\xb1\x60\x4b\x0e\x81\x35\x3f\xbc\x7d\x9e\xad\xcc\xc2\x41\x92\x04\x77\x30\x16\x15\x5d\x71\xa4\x28\xe2\x14\x9c\x18\xe7\x61\x0c\x8c\x4c\xe1\xa8\x18\x17\x61\xde\x78\x9d\x01\x80\xca\xa6\xd1\xf5\x74\xd5\x0d\x77\xeb\xcf\x99\xf1\xde\xd1\x4f\x1b\xdd\x2a\xf8\xf9\x85\x85\x0e\xe9\x40\xba\x4f\x0c\xfd\xc2\xbc\x07\xc9\xcc\x28\x71\x3f\x31\xf4\xba\x4d\x24\x02\x6a\x69\xcd\x88\xf1\x4c\x59\x93\xdc\x0e\xb5\x44\xa8\xb5\x7c\x09\x85\xbf\xf7\x85\x58\x23\xca\xa8\x46\x46\xe5\xfe\x0d\x3a\x75\x12\xf4\xe9\x13\xe6\x3c\x4b\xad\x0b\x5c\xa0\x03\xbc\x76\x41\xeb\x95\x19\xa4\xd6\xba\x3c\x3e\x00\x08\x4c\x22\x44\x6b\x30\x05\x9a\xf6\x9c\xdb\x40\xf5\x39\x6e\xbd\x40\xc1\x53\xb4\x75\x0f\x35\xf8\x0e\x6d\x10\x2a\xb7\x92\x4c\xef\xbb\xef\x46\x87\xa1\xee\xd3\x70\xe8\x33\x96\xfc\x82\xb3\xf2\xb5\xcc\xad\x3e\x7f\x32\xa2\xe8\x70\x3f\xb5\x7a\xba\x81\x52\x63\x1f\x4a\x7c\x6d\x2f\xdc\x8c\x57\xa0\xc9\x84\x24\x8f\x71\xb8\x01\xdf\x4c\x4a\x2d\xaa\x50\xab\x6e\x85\xfa\x39\x39\x31\xb4\xa7\x51\xb6\xb8\xf5\xda\x5d\xf5\xfc\xee\x95\xcf\xb4\xf1\x65\xf8\x4a\xd8\x8b\x50\xab\xda\xf3\x7e\x7d\x66\x6d\xad\x1f\xd9\xdf\xbf\x62\x83\xdf\xdf\x23\x9b\xce\xbf\x6a\x74\x40\xbc\xdd\x0b\x99\xe0\x99\x88\xd6\xe9\xe4\xc9\xd3\x97\x4f\xdf\x3f\x7d\x92\x10\xab\x55\x08\x13\xc2\xc3\xe5\x50\x7f\xe3\x54\xd4\xde\x96\x26\x50\x6a\xcf\x51\x78\x17\xab\xc6\x79\x47\x35\xce\x23\xd5\x78\xfc\x34\x70\x5c\x8f\x99\x48\xc8\x35\x0f\xb2\xd0\x6f\xb1\x73\xf8\x82\x14\x05\x8b\xf0\xc0\x15\x5b\xc4\xe0\x47\xfe\x69\x1f\x99\xc9\xa2\x5d\x60\x1b\xfe\xbc\xa5\xc3\x68\x62\x57\xf5\xc3\xac\xf7\xb9\xc4\xc6\xfc\x32\x86\x50\xf6\x70\x72\x2f\xaa\xc3\x8d\xe5\xde\x10\xe7\xef\x83\xe3\xbf\x7f\x31\x77\x02\xf4\x88\x19\x27\x63\x37\x37\xe1\x70\xc6\x12\xcb\x1c\x16\x20\x45\xbf\x48\x24\x22\x5f\x71\xbc\x5e\xfb\x4c\xde\x8a\xdc\x1a\xdd\x4d\x27\xbb\x07\xa9\x3b\xaa\xdb\x35\x03\xcb\x58\x9f\x3e\x63\x94\xe3\xd9\xef\x0c\x3d\xd3\xfc\x67\xa3\x6f\xf5\xf8\xfb\x22\x91\x0a\xa2\x32\x61\xe7\x5d\x70\x53\x79\xfa\xdd\xd0\x59\xc8\x33\xa1\xd6\xd1\xc0\xbb\x44\x04\x70\x14\x81\xdb\x70\xe8\x4d\x6c\x02\x43\xd9\xd7\xa0\xe8\xd6\xed\xc7\x2f\x59\x23\x4a\x9f\xb1\x36\xf0\x14\xb8\xdf\x78\x81\x02\x2a\x00\x75\x9b\x10\x6b\xdb\xaa\xdc\x80\x2a\x4e\x91\xaf\xc0\x7a\x9d\x9c\x73\x96\x3b\xa4\xdd\x93\x2a\xbf\xb2\xd7\xa3\x5b\xd2\xe8\x22\x43\x06\x85\xad\x7d\xd9\x23\x36\x53\x33\x6c\x27\x25\x51\x86\x64\x61\x87\xe8\x8f\x98\x3a\x00\xbf\xe5\x5e\x46\x1f\x21\x6f\x1b\x82\xfa\x67\xaf\x10\xfb\xd3\xf1\x58\x83\x92\xd7\x3b\x49\xbb\x8b\xc1\x98\xd3\x11\x37\xf8\x2a\xf9\x3b\x6e\xfd\xd6\x3f\x3f\xf0\xe1\xbf\x36\x7d\x1f\xa3\x10\x78\xf9\xd0\x3b\xf6\xdf\x4a\xcc\xca\xa0\x19\xbe\xbb\x9a\xc3\xd5\x7a\xed\x7c\xfd\x83\x12\x36\x96\xa3\xd9\x3d\xc5\x23\x46\x9f\xb1\x39\x7c\xa6\x15\x6d\xc3\x0f\x1a\xb5\x66\x3f\x8c\xd8\x17\xbd\x26\xc3\xdb\x01\x83\x34\xb1\x15\x19\xa0\x49\x7a\x67\x2c\x16\x85\xa4\x9a\xcc\xf8\x83\x9f\x59\xe8\x54\xf5\x33\x3b\xe2\xc7\xe3\x4f\x97\x95\xfc\xfc\x5c\xbc\xb1\x18\xfb\xbf\x71\x59\x17\x95\xb0\x51\x6c\x8d\xb2\xcc\xbf\x46\x27\xc6\x1b\x8a\x75\xbc\xa1\x9e\x14\xf5\x8a\xa9\xc5\x39\x97\xe4\x23\xdb\xee\x29\x45\xfe\x60\x74\x42\x5e\xd8\x8a\xf3\xc2\xba\x28\xd9\x5f\x51\xe8\x09\x24\x8b\x88\xdf\x57\x05\x72\x1e\x5c\xbe\xe7\x77\xa7\xa1\x8c\xc0\x8a\xc8\xcd\x20\x8e\x0a\x17\x63\xd1\x2b\x8f\x72\xd2\xc1\xa5\xd7\xe3\xd1\x44\x73\x83\x50\x6e\x37\xc7\x71\x2b\x8a\xd0\x7c\x0c\x3e\xfc\x07\xa3\x4c\xb7\x4b\x11\x35\x60\xfe\xd4\x71\x04\xb1\x49\xc6\xea\x73\x42\xfe\xd9\x4a\x37\x6d\xcc\x3b\x77\x15\x97\x36\xff\x54\x64\xaf\x0a\xc2\xc1\x26\xb2\xc2\x44\x16\xf8\x9a\xd1\xc9\x2c\xaf\x60\xa7\x05\xf4\x1b\xa1\xdd\x83\x7f\xb0\xde\x6c\x99\x4c\x31\x9e\xb1\xdb\x74\xaa\xc9\xed\x29\xdf\xaf\x57\x50\x9b\xe7\xed\x97\xac\xff\x80\x2c\x60\x4b\x13\xe4\xf9\xa5\x20\xca\x4d\x63\x5e\xb4\x6e\x50\xc6\x18\xd7\xf4\xb7\xf9\xa0\xeb\x75\xd3\xcb\xaa\x57\xbf\xc9\xa0\x88\x5d\x16\xc8\xb9\x1e\x5e\x47\xa4\x30\xe6\x62\xad\x5f\x82\xbf\x85\xb6\x98\xdb\x2f\xed\x65\xe0\x2d\xd1\x39\xdf\x2a\xe6\x2f\x58\xa7\xcf\x74\x85\x33\x55\x50\x65\x5a\x41\x39\x51\x45\x70\x2a\x5a\xa0\x08\x76\xa8\x70\x15\x7c\xc1\x02\xd3\x7c\xcf\xdc\xf8\xbc\xd3\x89\x59\x8b\xd4\xc8\x1d\xa1\x2c\x5f\xde\x5e\xa7\xcc\xd6\x25\x90\x49\x15\xd6\x55\xd4\xb3\x88\x1b\x9c\xc4\x10\x0a\xa9\xcb\x2b\x35\x75\x7b\x24\x44\xfa\x5d\xdc\x31\x7a\x0a\x3c\x92\x8a\xc0\xa8\xbf\x25\xad\x4d\x36\x6e\x34\x5f\x5c\x12\x5c\x0c\x18\x70\xff\x10\x7d\xbd\x3b\x63\x40\xe6\xa6\x88\x00\x7d\x06\x2c\x4b\xe6\x0a\x71\x9c\x05\xe7\xd5\x8b\xa2\x35\x20\xd1\xbd\x44\xb4\xc8\x09\x15\x0b\x94\x89\xa2\x47\x1b\x3d\x33\x8c\xd7\xc8\x5b\x2e\x72\x2e\x79\xfe\x96\xe7\xcd\x82\x4b\xca\x1d\x1c\x44\x01\xb6\xd2\x6d\xb3\x19\x15\x03\x0e\x1f\x2c\xb4\xea\xa9\x1c\x1a\x54\x65\x3a\xce\xfc\x58\x3f\x1b\x62\xdd\x6d\xca\x4d\x50\x2a\x05\x00\xad\xd8\xd0\x3c\x2a\xaf\xb2\x65\x81\x3a\xc2\x77\xcd\xcc\xe0\x7f\x97\x94\x39\x48\xd8\x6a\x66\x1d\x8f\x16\xb4\x31\x7e\x17\xc5\x29\x42\x7f\xb0\x74\x81\x41\x61\xd6\xc2\x4f\xa1\xda\x2a\x35\x8d\xb7\x5e\x36\x21\x0c\x48\x99\x35\x63\x73\x41\x38\x3b\xe3\xd2\xd2\x23\x6b\xc6\xe1\xad\x79\x66\xc6\x8a\x7d\x62\xc6\x4a\xe0\x6d\x41\x24\x8d\x5f\x82\xfd\x69\x98\x3b\xe3\x48\x12\xf7\x39\x1b\x11\xd6\x68\xc2\x4d\x95\x16\xff\xe5\x2a\xb9\x1d\x4e\x3d\x47\x25\xad\x69\x4e\x18\x95\x38\xf3\x74\xc8\xc9\x0b\x66\x58\xf3\x9a\x2e\xc0\x42\x7f\xb1\x69\xac\x9f\x4e\xec\x45\xd5\xa4\x69\x03\xfd\xd2\x96\xc8\xa8\xcc\x6c\x39\x25\x69\x24\x92\xdd\xe5\x00\xaf\xd7\xce\x01\xb4\xbb\x50\xe8\xbc\xad\x61\x3a\xb3\x77\x66\x60\xd4\x24\x1e\x9f\xf6\x0d\x3b\x6d\x8e\x3a\x45\x11\x31\xce\xed\x7a\x7c\x1c\x9c\xf1\xff\xef\x9a\x1c\xed\xd7\x48\xd5\x4e\x0b\xb0\x48\xde\xb6\x9d\xae\xf0\xb5\xe8\xbb\x44\x95\xd4\x0d\x70\x3d\x7e\x19\xe5\x88\x91\xd2\x0d\x0c\x08\x96\x12\x74\x82\x29\x66\xd6\x48\xc4\xfe\x06\x91\x99\x67\x4b\x2d\x75\xc1\xfc\x25\xa0\x3c\x1e\x24\x36\x73\xc4\x66\x44\x06\x54\x3d\x2d\x62\x7b\x6c\x35\xfe\x74\xc6\x95\x95\xa1\x66\x92\x6a\x71\xf8\x53\x5d\x35\x72\xc1\x9d\x21\x9d\xba\x59\xe2\x0a\xc9\x34\xd7\x3c\x81\x52\x99\x19\x09\xb9\x01\x4c\x86\xb7\x9c\x19\xff\x65\x82\x38\xd5\xb3\xda\x78\x20\x40\x48\xd4\xef\x08\x73\x92\xfc\xcc\x8c\xe3\x8e\x02\x78\xbd\xf6\xcc\x25\xa8\xa5\x19\x01\x6d\x46\xe2\x07\xc3\xc1\x24\x94\xbb\x56\x45\xd7\xcc\xe0\x7d\x19\x0c\xa5\x9e\xa7\xf0\xbe\xb3\x3c\x64\x31\x95\xe0\xdc\xa3\xfd\x3e\xa9\x69\x2b\x5f\x90\x86\xd6\xe3\xc6\x76\x4d\x14\x2b\xc1\x9d\x67\x14\xa8\x32\xd8\x05\x18\x93\x05\x6d\x8e\xa6\xc7\x24\xa7\xcd\xd1\xe4\x78\xd6\x50\x55\xcc\x8c\x53\x5c\xd7\xb0\x77\x45\x4f\xc1\x9a\x90\x9c\xd3\x55\x68\x49\x4b\x96\xf4\x74\x6c\xea\x31\x3b\xd5\x97\xcd\x49\xbd\x90\xc5\x89\x19\xea\x17\xf4\x05\x6b\x5d\x93\xe3\x81\x75\xad\x8b\xcb\x56\xc4\xbc\x9c\x29\xe2\x5f\xcd\xe4\x86\x40\x1b\xcc\xd6\x3f\x6a\x44\xf4\x71\x2a\xc8\x6a\x5c\x07\xf7\x0b\x0b\x98\x10\x52\x67\x66\x25\xd5\x92\x70\x8c\xaf\xb5\x78\x16\x50\xae\x91\x28\x27\x30\xfc\x17\x7a\xc3\xc5\xe9\xa2\x46\x17\x98\x54\xbd\x91\xb3\xa6\x3c\xad\xdc\x04\x84\x14\x9d\xbb\x9f\x8f\x54\x63\x2e\x14\x13\x67\x25\xf7\x2f\x7a\x91\x5a\xd2\xf6\x29\x44\xca\x21\x5a\x12\x99\x3c\x68\xe3\x80\xec\x4d\xef\xdc\x52\xa8\xc0\xa4\xa1\xd3\x07\x0f\xea\x99\x3c\xaa\x8f\xd7\x94\x93\x22\xa5\xff\x6a\x36\x9b\x0d\x26\x47\x82\x28\x22\x8f\xf1\x56\x0a\x39\xc4\xa3\xb6\x99\xa4\x1b\x31\x83\x77\xfa\x50\xd0\x88\x8c\x80\x36\x21\x10\x0f\x08\xe5\x0c\x60\x81\x3c\xb3\x21\xf2\xc8\x0e\x79\x82\x30\xbb\x51\xf5\x6c\xd8\x25\xc0\xbc\xc7\x58\x37\xc8\x34\xa7\x91\xe8\x1c\x10\x7c\x1b\x89\x96\x44\x99\x8b\x53\x13\xbc\x14\x71\x1a\xb9\x95\x13\xc7\x3e\x5b\x6f\xf4\x0e\xab\xcd\x9a\x82\xf4\x38\x52\x96\x6f\xb0\xe7\xbc\x74\x41\xdf\x17\x41\x84\x9d\x17\xa0\x50\x6d\x0c\x7f\xa7\x9c\x34\xc1\x62\x62\xed\x21\xfc\xcc\x21\x4d\x67\x2c\x37\x01\x37\xcc\x31\xc9\x03\x53\x97\xa2\x03\x21\xb2\x2a\x10\xac\x25\x5d\xfc\x90\x65\xb0\xd8\x68\x11\x7e\xb6\x55\x8a\xe3\x10\xe7\x99\x23\xdc\x67\xd6\x21\x57\xe6\x04\x00\x90\xec\x8a\xf5\xdf\x21\x20\x0f\x09\x38\x40\xbe\xde\xba\xca\x03\xc6\x7f\x51\xf4\x6c\x00\x39\xbd\x56\xec\x2c\xe3\x64\x21\x39\x88\xec\x24\xe7\xb5\x92\xd5\x55\x26\x48\xce\x57\x75\x26\x07\xe4\x63\xa4\xf4\xbe\x21\x74\xd8\x9d\x23\x90\xc6\x9c\xae\xd0\x66\x8f\x33\xc1\x46\x33\xd0\x27\x5a\xef\x67\x8b\xe3\x6b\xb4\xd4\x61\x06\x3c\x1f\xcc\x9e\x21\xd9\xf1\xa5\xe7\xc4\x3e\x93\x9d\x0f\xe0\xd0\x78\xf5\xac\x88\x90\xa9\x02\x28\x38\xa2\x7b\xbb\xd3\x8f\xc1\x8b\x57\x45\x3b\xa7\xeb\x5e\xce\xc0\xcd\xa9\xb7\xb6\xc0\x28\x7a\xc1\x9c\xa1\x3d\xd7\x5c\x2d\xfa\xca\x45\x81\xa6\x6b\xfd\x8a\x85\xbb\xf4\x87\x52\xd2\x28\x25\x43\xfb\xcd\xcb\x5e\xf1\x35\x0c\x52\xda\x7b\x69\xd6\x0d\x45\xe7\x37\xb8\xd8\xba\xf6\xf3\xa2\x2f\xe6\x30\x5a\x8c\x6d\xdf\x07\x47\x79\xac\x40\x92\xe8\x07\xab\x56\x81\x0f\x05\x5f\x14\x60\x0c\xcc\x88\xc4\x9b\x1f\x6a\x22\x8b\x71\xc2\xa2\x9d\x92\xa6\xdd\xc1\xf4\x90\xec\x93\xd8\xf0\xf2\x69\x9c\xeb\x72\x38\xd7\xe7\x5e\xae\x7d\xb2\xdb\xc9\xf3\xee\xfb\x3b\x33\x33\xa5\x89\xde\xa0\x91\x90\x5d\x22\x1b\xa5\x2d\xb3\x7e\x7b\x3e\xa3\x57\x28\xf0\x28\x7f\xa4\x19\xd9\xb8\xb0\x5c\x81\x55\x7b\x97\x21\x09\xbb\xed\x16\x73\xe1\xc2\x32\x1e\xf1\x63\xf3\x3d\x62\x5b\xf3\xae\x88\x62\x91\x71\x1c\xb1\xae\x3f\xf5\x10\x6d\x6f\xdf\x14\xe1\x79\x03\x0c\x13\xd5\x0e\x13\x65\x15\xde\x5e\x14\x8e\x87\x42\xac\x42\x6f\x2d\xf7\x14\x0c\x06\x45\xe4\xd1\xf4\x18\xcf\xe5\xd1\xe4\x38\x43\x9d\x77\xe9\x11\x27\xea\x98\xf0\xa0\x66\x6f\xff\x4f\x55\xc5\xf4\xc9\xf7\x2b\xf4\x3a\xaa\xd0\x87\x0a\x61\x40\x73\xba\xf7\x0f\x31\xbf\x7f\x2f\x13\xd1\x4a\xcd\x01\xaf\x09\x63\xa2\x73\xdc\x7d\x20\xe6\xf7\xef\x76\x72\x98\x52\x3e\xb2\xb1\x92\x4c\x18\xcc\xee\x59\x74\x47\xa7\xb0\x96\x73\x38\xde\x55\xa8\x0d\xa8\x15\xe7\x12\x9b\x08\x30\xfb\x7d\x47\x42\xef\x78\xb8\x9a\x4d\x66\xe5\x36\x99\x9d\xdd\xa5\x85\x52\xf2\x7b\xca\x8e\x2e\x89\x14\x54\x75\xf5\x00\x94\xd2\x62\x6e\xb7\xf7\x2c\x43\x0e\x8a\xc3\x70\x59\xab\xf0\x60\x7a\xc4\xbb\xfd\x0f\xd3\x72\x53\x80\x86\xca\x29\xa5\x2f\x98\x47\x41\x2d\xd2\xb4\x80\x14\x2c\x0b\x2a\xf4\xb6\xc6\x6b\x7b\x62\x1f\x67\xf7\xf1\xf5\x5a\xa7\x1b\xc0\x85\x00\x99\x08\x15\x76\x45\xe8\xac\x8d\x18\x3b\x38\xae\xb2\x93\xc1\x2c\x7a\x35\x2d\x50\x49\x04\x48\x9e\x2c\xde\xca\x17\x84\x05\x7b\x6c\x5a\x6b\xb1\x07\xe0\xa5\xed\x01\xa0\x17\x9a\x36\xad\x2f\x30\xe8\x8f\x7f\x29\xb4\xc0\xcc\x9c\x63\x65\x56\x30\xd2\xd4\x1e\x86\x2f\xab\x0a\xb8\xb5\x0f\xcd\x9d\x5d\x0c\xcd\xcd\xf3\xe5\x8a\x4b\xa6\x8a\x0b\xfe\x13\x13\x79\xc9\x6d\xf2\x4b\x76\x55\x35\x2a\xca\xf9\x8a\x2f\x2b\x7b\xe9\xfa\xd4\xdd\x9d\xda\x2b\xd3\xb3\xe6\xfa\x09\x3f\x69\xce\x00\x6c\xc8\x27\x9c\x72\x29\x79\x1e\xa6\xbd\xf7\x63\xcd\x7d\xc4\xc8\x8f\xef\x8c\xec\x6f\xd2\x5e\xaf\xd8\x97\x86\x3f\xcf\xb9\x50\xc5\x69\x61\x3f\xeb\x50\xf5\x8a\xfa\x17\x7e\xf9\x96\x6b\x06\x55\x94\x5c\x66\xa3\xe9\x86\x7c\xba\x99\x26\xb1\xbf\xb4\xb3\x31\xe9\x2f\xb6\x47\x9c\xf4\x58\xc2\x31\xe1\x9b\x90\xa2\xa6\x68\x4b\xa7\xaf\xc3\x14\xed\xba\x8c\xff\x08\x7f\x3d\xb9\x81\xbf\xf6\xfa\x67\xb0\x41\x27\xc1\x7a\xe3\xbb\x2f\xce\x69\xd8\x44\x20\x54\xee\x0c\x30\x41\x72\x23\x0b\xdb\x84\xc3\xa1\xdb\x50\xc3\x25\x86\xca\x1f\x51\xdd\x6c\xa4\x70\xa6\x88\xec\x6a\x6f\x02\x59\x55\x19\x59\x55\xfe\x9b\xb2\x2a\x1f\x10\x55\xd5\xf7\x44\x55\xd9\x17\x55\xdd\x28\x3f\x0b\x46\xf9\xb2\x3b\xca\xff\x1c\x18\xe5\x7d\x6f\x3c\x10\xe7\x89\xa0\xea\x68\x72\x4c\x24\x55\x47\x53\x8f\x45\xfb\xb5\xe8\x85\x30\x54\x3f\xc0\xc4\x01\x9b\x79\x98\x7f\x2b\xd8\x18\xf2\x63\x4c\xc4\xa6\x33\xdd\x7a\x3b\xbf\x65\x61\x16\x03\xca\xf5\x8e\xdf\x56\x49\x4b\xa7\xf4\x75\x48\x24\xae\x17\x37\x5d\x28\x51\x86\x2e\xf1\x8c\xfd\xfe\x10\x90\x83\xdb\xfd\xeb\x60\xdb\xa9\xb7\xfc\xc1\x9d\x59\x1e\xac\x36\x80\x07\xda\x00\xb1\x21\x2b\x2d\x07\xda\x1d\xd3\x20\xab\x08\x9a\x19\x1c\x89\x43\xd4\xc8\xd8\x57\xd2\x02\x76\x39\xe3\xc9\xec\x21\x71\x7e\x83\x19\x27\x60\x90\xfa\xfa\x34\xe3\x9d\x28\x93\x76\xcf\xba\x5e\x23\x08\xfa\x2c\x50\x22\xb3\xe4\x36\xfa\x55\xde\xbe\x1d\xa3\x8c\xe3\x50\xf5\x73\x80\x61\xf5\x16\x9a\xe4\x0a\x07\x03\xc0\xc4\x2c\x7d\xc1\xc0\xc8\x0c\xa7\x29\x6a\x25\x58\x2d\x60\x5e\x14\xe8\x20\x5a\xe6\x6f\xf8\xde\xc6\x99\x92\x59\x87\x17\xe2\x71\x0e\xf5\x47\xe9\xd6\xf7\x88\xda\xdc\xcc\x5b\x5f\xdd\xcc\x5b\xdf\x14\x5b\xb9\xe3\xd3\x61\xee\xf8\xb8\xbf\xde\x7c\x6e\xd7\x9b\xb7\xd1\x7a\xb3\xf0\xeb\xcd\x55\x30\x13\xfb\x3a\x8e\x45\x81\x9a\xc2\x8c\x88\xbf\x3d\x41\xcd\xbb\xc3\x33\xf4\xe9\xff\xd5\x19\x6a\x6a\xd6\xce\xce\x23\xbd\x05\x6c\x81\xbd\x87\xa6\xe3\x79\xf1\xbd\x59\x11\x51\xec\x68\x72\xfc\x9d\xee\x7f\xfe\x7f\xb3\xfb\xf3\x1f\xec\xfe\xfc\x3f\xe8\xfe\xfc\xff\xb3\xdd\x9f\xff\x6f\xec\xfe\xfc\x07\xbb\xff\x61\xd1\xb1\x48\x78\x7d\x29\xb8\x24\x2f\x63\x43\x83\x6f\x81\x4e\xc0\x5a\xca\xf9\xf3\xf8\xf9\x1b\x70\xd7\x35\x01\x7c\x24\xce\xfe\x64\x60\x11\x03\x99\x3a\xa0\xdd\x4f\x8a\xd0\x1d\xcc\x44\x59\xd1\x2b\xb9\xd7\x7c\x4b\x7e\xea\xba\x86\xe9\x62\x2a\x4c\x24\x0d\x4c\x0a\x98\x4e\x69\x0d\x01\x5e\x16\xde\xd3\x77\x4d\xa7\xc4\xd6\x12\x4e\xff\x9d\xad\x5f\xd6\x01\x95\xec\x82\x50\xc2\xcb\x29\xbd\x73\x30\xbd\xeb\xc0\xa6\x52\xfa\xaf\x8a\x88\x12\xca\xaa\xc2\xdd\xd2\xb3\xbe\x6d\x83\x3f\x53\xb6\x0a\x0f\x11\x5a\xa3\x0d\xf8\xc2\x14\xeb\xf5\xef\x35\x2a\xf0\x7a\xed\xc5\xa6\x22\x02\xb8\x6d\x03\x3c\x00\x98\x02\x93\x3c\xc8\x2a\xa2\xac\x73\x84\x78\xe8\xba\x6b\x5c\xc2\xc0\xca\xa2\xca\xb9\xb5\x7d\x3e\x35\x54\x25\x3c\x30\x76\xb4\x1d\xc8\x81\x38\x80\x5d\x74\x40\x8c\x67\x27\x2d\xc8\x23\xd3\xc8\xc2\x36\xd2\x9b\x14\x17\x0e\xca\x9e\xe8\x45\xad\x4a\x19\x86\xa8\x46\x45\x6c\xfa\x44\x90\xa0\x21\xec\xa3\x6d\x03\x9e\x8b\x2c\x97\x18\x55\x80\xdc\xc3\xa1\x5e\x16\x18\x01\xcf\x2d\xa9\x19\xce\xc2\xce\x34\x1e\xe3\x85\xf7\x3b\xbe\xa1\x19\x6d\x0f\x3d\x1a\xee\x21\x63\x4f\x96\x4b\xd4\x31\xd4\x1a\xa8\x8d\x7e\x05\x06\x3f\x34\x93\xa5\x55\x6b\x4e\x6a\x8d\x52\xec\x28\x21\xbe\xda\x33\x13\x73\x75\xef\xde\xbe\x33\x78\x6b\xa1\x6c\x1d\xf5\x6e\x05\x63\x38\xa8\xef\x5f\xbd\x13\xb2\xd0\x80\xd0\x60\x90\x39\x27\x06\x76\xb3\xd1\x04\x98\x6b\x9d\x17\x79\xce\x21\x92\x8f\x84\x41\xb0\x5e\x27\x6e\xf6\xdf\xc9\x35\x9f\xbc\x73\x59\xa8\xf3\xaa\x51\x77\xce\x8b\xdc\x18\xde\xdb\x9c\xd8\x46\xa5\xdd\x4f\xcd\xf0\xc1\xb8\xab\x71\x06\x9c\xcb\x97\x06\xb6\x76\x43\x4e\x6a\x34\x21\xee\x48\xda\xc5\x69\x77\x40\xba\xfb\x69\xeb\x3c\xea\x6d\x3d\xd8\xdc\xe0\xc0\x99\x53\x04\x91\x09\x6f\xe6\xa3\x02\xdc\xe1\x16\x8d\x77\x9f\xdc\x50\x03\x6e\x6b\xc0\x0d\x3b\x98\xfd\x48\x65\x07\xaa\x91\x09\x6b\xb7\xe8\x1f\x22\x49\xa3\x6a\x0e\xda\x2c\xe1\x4c\x52\x61\x4a\x95\x5e\x0c\xb6\xdc\xa7\x22\xc2\x73\x9f\xb6\xa3\x7f\x8f\xb4\x41\x86\xd1\x79\xe6\xd1\xfa\x02\xfb\xd9\xcf\xed\xb8\x04\x07\xe1\x16\x83\x60\x4d\xa7\xbb\xf7\x82\xf1\x73\xab\xe8\x87\xcd\x3f\xab\x90\xe8\x60\xfc\x78\x9e\x4a\x2f\x2a\xa4\x87\x2c\x71\xdc\x55\xfc\x6d\xee\x2a\xfe\x77\x71\xd7\x0f\x45\xc7\x57\x18\x1a\xe2\x5a\x35\x9a\xcc\xbe\x56\x48\xd9\xee\x02\xb3\xe7\xe2\x14\xf9\x66\x78\xc3\x6c\x0f\x75\xd5\x12\x12\x05\x0a\x24\x67\xda\xd5\x4b\xb0\xcd\xdc\xc5\xe4\xc4\xa1\x4f\x90\xaf\xf6\xca\x2c\x43\x56\xb7\xb4\x33\xc0\xf5\x83\xef\x92\xb2\x6b\xae\x3e\x2b\x2c\xd4\x53\x69\x8d\x51\x0a\x07\xb8\x44\x1a\x8b\x74\xe0\xe0\x9c\x06\x5c\xcd\xda\x40\xb4\xcd\xbc\x60\xa8\xc1\x19\x74\x61\x33\xd4\xcd\xce\xb5\x4c\x6c\xc5\x4b\x22\xf9\x60\x98\xab\x41\x18\xa5\x62\x1b\x8c\xd2\x2c\x1f\x04\x52\x2a\x7e\x00\x78\x6b\xf0\xb5\xad\xf9\xd7\x6b\xb0\x64\x90\xeb\xb5\x09\xe2\x9c\xa6\x97\xba\x47\xf4\xd2\xd4\x60\xd2\xe2\xd1\x9e\xf6\xad\x29\x2c\x6a\xd1\x29\x59\x81\x67\x34\x29\x74\x1f\xd6\xdd\x7c\xc4\x16\xaf\xa7\x59\xbd\x5e\xb7\x61\x3e\xd6\xeb\x92\xcd\xd1\x10\xa9\x0c\x8c\x95\x1e\x16\x0b\x3d\x44\x7a\x45\x42\xc8\xe6\x92\xad\xd7\x57\x26\x97\x5e\x92\x4f\xc1\x51\x16\xcf\xd1\xdf\x21\xdc\x76\x04\xaa\x62\x18\x81\x6a\xb0\x0b\x87\x8a\x2c\x7e\x18\x77\xea\xc6\x9a\x15\x37\xe1\x4e\x6d\x29\x6e\x08\x1f\x4a\xb5\xf8\x50\x38\x43\xff\xce\x6b\xa4\x33\xe3\x68\xcf\xb4\x88\xd6\x10\x58\xd2\x3e\x74\xa3\xa3\x26\x7e\x2a\xd2\x86\x48\x5a\xfe\xbb\xdf\x97\x74\x34\x35\x9c\xe9\x3a\x66\x06\x16\xfc\xbc\xcf\x14\x48\x43\x95\xf3\x5b\x8c\x60\x5c\xe6\x65\xf6\xb1\x72\x38\x1b\x65\x5b\xeb\x86\xe4\x5d\xe9\xe0\x34\xe0\x24\x75\x8f\x73\xa0\x3a\x66\x2e\xad\xb2\xbb\xd6\x8c\xa4\xb6\x8c\xa4\xde\xce\x48\x56\x37\x30\x92\x19\x5a\x0c\x71\x92\xd5\xdf\xe3\x24\xf8\xff\x2c\x23\xc9\xed\x4c\x0f\x19\x49\x6d\x19\x09\xe9\x31\x11\x32\xc8\x44\x66\x06\x1e\xb9\xcb\x70\x82\xe2\xcf\x7f\x88\x91\xac\x5a\x46\xb2\xd2\x8c\xe4\x7c\x80\x91\x34\x21\x23\x69\x80\x91\x9c\x93\x5a\x33\x92\xc5\xdf\x20\x9c\x21\xf5\x8f\x90\xcc\xa1\xe4\xfd\x00\x2b\x71\x85\x0e\x26\x23\x09\xf5\xfc\x71\x8e\xd2\x96\xb6\xfd\xa9\x2d\xf4\x07\x18\x8b\x2b\x2d\x9a\xa2\x7f\x67\x58\x86\xaf\xee\x1e\x1c\xc6\x6c\x69\x74\xd3\x47\xd7\xeb\xd8\x30\xdd\x8e\xd6\xd3\xbe\xb5\xfa\x7a\xbd\xa5\x7a\xa3\xef\x56\xef\xdf\xfb\x88\x6e\xc8\x0f\x30\xca\xf3\x21\x46\x79\x1e\x30\xca\x9a\x48\xda\xfc\xff\x87\x22\x86\x75\x3b\x7f\xa0\x58\x16\x0e\x3c\x95\x3a\xfb\x4a\x2b\xce\x5b\x34\xfc\x8e\xff\xa1\x09\xfd\x95\xa6\xa3\xc2\xed\x81\xaa\x34\x7d\x0a\xc0\x4f\x64\x34\xc5\xc1\xc6\x51\x46\x8b\xc5\xc3\xa2\x8d\xe4\x67\x6d\x3e\x8b\xc1\x69\x3b\xc8\x96\x41\x1b\x6d\x0d\x33\xac\x5a\x25\x38\xa5\x69\xc5\xf8\x56\x2e\x06\xf1\xde\xec\xa1\x63\x9d\x0d\xa0\x7d\x7b\x21\xdf\x3c\x34\x27\x32\x84\x61\x9c\xd9\x8d\x80\xcd\xd3\x3d\xea\x31\x40\x92\x41\x8b\x27\x03\xdb\xa1\x9f\x02\x13\xa8\x28\xa6\xa3\x5b\xe1\xac\xc2\x71\x7e\x52\xa1\x09\xe9\xa6\xf6\x12\x8c\x6f\xa7\x0d\x49\x97\xf9\xcb\x34\xb5\xaf\xbb\x55\x52\x53\xdf\xf8\x25\xc7\x2e\xf4\xc6\x4b\xf6\x4b\x41\x7e\x2e\xc8\xaf\x05\xf9\x67\x41\xaf\x3b\x0e\x56\x44\x72\x25\xaf\x5e\x82\x19\x78\x00\x96\xfc\x31\xde\xbf\x93\xaa\xbb\x46\x33\xfa\xad\xb5\xd7\x04\x9d\x9a\x45\xb1\x92\xdd\x51\x83\xd7\x6b\x24\x29\x8a\xbd\x5c\x46\xbd\x01\x8c\x21\xc8\x0d\xda\x4d\x19\xc6\x44\xce\x51\x41\x47\x93\x60\xa3\x75\x78\xe0\xcc\x47\x68\x0b\x67\xd7\x9b\x03\xfe\x48\xb0\x1a\x9f\x5a\x45\xef\x7a\x3d\x32\x09\x5e\x5b\xc8\x74\xae\xf7\xe7\x45\xfd\xcc\x67\x41\x6c\x4d\xa7\xe0\x8b\xfc\x8d\x91\x69\xca\x02\xb4\x49\xe4\x95\x54\x6d\x99\x69\xfa\x81\x21\x65\xac\x27\x03\x35\x46\x9b\x81\x14\x73\xc4\xe9\x1f\x05\x00\x27\xb1\x60\xe3\xbc\x7d\x37\x2f\x36\xbd\x31\xf7\xcf\x82\x70\x9c\xf5\x60\x03\x82\xa6\xf0\xaf\x2b\xbe\x50\x3c\x7f\x59\xb1\xfc\x7d\xb1\xe4\xff\xa5\xaf\x3a\xfd\xc5\xde\xde\xc1\xc1\xfe\xfe\xde\xae\xae\x06\x42\x82\xfe\x54\xa3\xeb\x65\x95\xf3\x2c\xb9\x28\xea\xe2\xa4\xe4\x09\x71\xcd\xcf\x00\x84\x73\x10\xb9\xac\xd5\x68\x09\xbd\xe2\x74\xcd\x72\x8b\x39\xaa\x68\x7c\x18\x17\xee\xfa\x6d\xa1\x5e\x4b\x37\xe3\xb4\x88\xe0\x6c\x4a\x6a\xeb\x64\x75\x44\x6d\x95\xc4\x26\x3e\xae\x62\x18\x90\x97\xf5\xe3\x11\xa5\xc5\x1c\x81\xbd\x9c\xd9\xf0\x87\x9a\x9a\x49\xeb\x8f\x61\x56\x93\x36\x06\x54\x61\x03\x93\x38\x03\x3b\x14\x23\x61\x8a\xf0\x2e\xb6\xa5\x2b\xac\x19\x48\x80\x8b\x79\x33\x8e\x26\x64\x10\x46\x57\x58\x62\xcf\xde\xe6\xd2\x00\x4e\x4a\x9c\x19\x50\x10\x60\xe9\x8e\xe4\x6e\x05\x68\x31\x47\x02\x2f\x67\x7d\xe9\x40\x65\x64\xdb\x29\x44\x6e\x8c\xd2\x22\x80\xfe\x6a\x47\xb2\xc0\x60\xef\x62\x38\x28\x73\xbd\xd0\x93\x28\xfb\xba\x24\x08\x34\x13\x0d\xb5\x2c\xb8\x8b\x74\x51\x1b\xbd\x0c\xb7\xf4\x8f\x62\x83\xfd\x4b\x0c\x8d\xd0\x0a\x67\x48\xf4\x46\x4d\x8b\x47\x6d\x86\x8a\xd7\xd4\x55\xae\xdd\x04\x08\x5a\x91\xad\xc3\x58\x6c\x30\x31\xa3\x45\xf9\xb3\x4d\x61\xa7\x83\xc4\xc3\xb4\x8c\x42\x30\x80\x5a\xa6\x0b\x80\xca\xbd\x77\xf9\x0d\x3d\xce\xdb\x95\x49\xf4\x7a\x44\xe0\x61\x27\xc3\x08\x38\xe1\x8f\xa2\x4f\x09\xa3\x32\xef\x92\x44\x6d\x9d\x34\x6a\x63\xdb\x5f\xe1\x00\x72\x1b\xb1\x78\x82\xb0\x78\x82\x28\x9c\x31\xcd\x1d\x14\xa9\x88\x3d\xc7\x25\xc2\x80\x46\x56\x0e\x4f\x8f\xb0\xd0\xdb\xde\x5f\xb2\x96\x8c\x6e\xa1\xa6\x8c\x04\xae\xf2\x2f\xac\x86\x91\x3b\x07\x1d\x35\xeb\x87\x94\x8b\x82\xbd\xb9\x7c\x98\x54\x0c\x71\x0f\x3f\x10\x10\x8a\x97\xb1\xd8\x63\x8d\x3a\x3b\x7b\x1f\x6f\xd8\xd5\xb3\xfb\x2f\xea\x47\x6c\xf1\xf9\x92\xc9\xbc\x86\xd8\x66\x5a\x28\xf1\xc6\x1e\xfe\xf6\x9d\x62\xd2\xc4\x46\x99\x80\x75\x47\x26\x89\x62\x45\x99\x09\xf8\x79\xa5\xe9\x6f\x82\x27\xd9\xd3\x44\xb6\xc9\x50\x31\x0e\xca\xa6\x8a\x14\x63\x5f\x9c\xe9\xf0\x20\xc1\x97\x4f\x27\xa4\x80\x91\x04\xa2\xad\x2e\x9c\x0a\x7b\xa1\xbf\x42\x2b\xfb\xd8\x0e\xb4\x50\x51\xaf\xca\xef\x2a\xea\x03\x54\x0a\xc2\x00\x96\xa6\x00\xa5\xbc\x3b\x95\x8a\x06\xa9\x59\xc3\x91\x0c\xc4\x03\x8c\xb1\xa4\xd3\x54\xae\x77\x5b\x75\xe4\xe1\x7e\xe4\xbd\x68\x26\x8e\x15\x1c\xdc\x59\x03\xe6\x99\xf1\xf2\x76\x10\x16\x71\xf0\xef\xc0\xb3\x7c\x58\xa2\x48\x53\x18\x3a\x56\x97\xef\x41\x38\xcc\x2b\xdd\x47\xbe\x08\x8b\xa4\xc1\x63\x24\x0d\x0e\xd0\x29\x7d\x24\x0d\xde\x46\x25\xdc\xe1\x11\x96\x06\x1f\xc4\xd2\xe0\x1e\x4b\x83\xb7\x58\x1a\x6d\x01\x41\x5c\x42\xde\xc5\xd1\xf0\x03\x99\xb7\x65\x6f\x64\x4a\xa7\xba\x1e\x46\x72\x91\x1d\xde\x85\x87\x58\x86\x69\xb2\x05\x9e\xa8\x0c\xe8\x44\x72\x5a\x49\x18\x71\x09\x90\xdc\x2f\x8b\xa4\x8a\x70\x13\x85\xc7\x51\x06\xf4\xf2\x16\xa5\xd8\x4b\x64\x00\xbf\x02\xe7\x67\x02\x43\x1c\x32\x47\x84\xd6\x42\xbd\xc2\x7a\xc1\x77\x1f\x08\x0f\x5d\x21\x2a\x85\x68\x59\x75\xc4\x60\x31\xe1\x25\xd2\x92\xae\x5e\xec\x08\x8b\x16\x57\x87\x8c\x03\x4d\x39\x71\xb3\xc7\xb5\x05\xa6\xcd\xf0\x17\x5d\xc3\xaa\x59\x07\x9a\xbd\xda\xda\xb8\xf6\x9c\xb8\x72\xc8\x78\xc1\xf2\x52\x05\xdc\x4c\xd0\x8a\x54\x94\x6f\x4c\xbd\x27\x56\x2e\xba\xa9\xea\xaa\x3a\xe3\xea\x9c\xcb\x24\x73\x6d\x6d\x51\x4e\xac\x8d\xcc\xd0\xbb\x1e\x10\x68\xa0\xb7\xbd\x93\x6d\x77\xa7\x22\xca\x3e\x26\xbd\x51\x10\x44\xf1\x1c\x3b\x21\x2f\xc1\x37\xd2\x8a\x87\x30\xd7\x45\x1a\x1e\x72\xe1\x4e\x69\xad\xb4\xe5\x26\x56\x17\xf2\x69\xaf\x45\x4c\x0c\x81\x6c\x4c\xcf\x69\x41\xc7\xf7\x5b\x8c\x41\x12\xac\x95\xc1\xa2\xec\x59\x44\x3b\xf9\x82\xd9\x02\x67\xb8\xbe\x83\x40\x8a\xea\x14\x8a\x83\x92\xa2\xd1\xd7\x25\xe3\x30\x04\x79\xe9\x31\x09\x46\x7f\xb1\x10\x11\xcb\xf0\x61\x3b\xd7\xec\x92\x9b\x01\x22\x87\xe6\xa5\x2d\x5c\x41\x38\x26\x43\xd0\xf2\x10\xb5\x5b\xd0\x0e\x42\xb9\x8f\x98\xc8\x2d\xeb\xd7\x5b\xe5\xb8\xfa\xe1\x20\x5b\x54\x65\xc9\x56\x35\xcf\x93\x4c\x74\x6b\x20\xb7\x4c\x77\x11\xd5\x40\x6e\x99\xdc\x72\xae\x02\x0c\x03\x5d\x70\x54\x25\x73\x1d\xd5\x2b\x93\x31\x95\x03\x90\xf5\x1b\xd7\xa5\x99\x47\x75\x6e\x71\x73\x2c\xca\xd8\xf4\xd0\xc3\x8b\x0d\xa1\x8e\xdd\x35\x3f\xf7\x6c\xaa\x7d\xc9\xa1\x72\xed\x87\xf8\x37\xb3\x10\xc4\x6c\xea\xc3\x38\x9f\x39\x2d\x36\x4e\xd3\xab\x0a\xd9\x73\x5a\x1b\xeb\xcd\x85\x7a\x66\x08\x77\x02\x9a\xff\xaa\x93\x50\xa4\x18\xc1\x9d\xdd\xbe\x26\xad\x57\x47\xc9\xae\x6e\xa0\x9b\x60\xb9\x62\xbc\x29\x6e\x67\xda\x7a\x8d\x7e\xd2\x9b\xd4\x79\xab\x7b\xca\xe4\xd8\xee\xfd\xbb\xda\xa2\xb0\x11\x07\xd9\x4b\xfd\x9e\x35\x5d\xe9\x40\x7c\x41\xcc\x09\xd5\xda\x65\x84\x5f\x0e\x5b\xf6\x73\x2b\x89\x12\x77\xde\x6b\x83\x42\xc4\x47\xbe\x5e\x0c\x18\xc9\x18\x73\xaa\x2d\xab\x1b\x6a\xfe\xb0\xc5\x8c\x70\xde\xf2\xbc\x8b\x3a\x06\x4d\xc7\xd7\xb1\x1e\xca\xd5\x7c\xe6\xec\xde\xe3\xe3\x4c\x07\xab\x7c\xf4\x51\x1e\x53\x45\xe4\xd1\x1f\xf2\x58\x6f\xfd\xec\xb4\xcd\x0b\x56\x56\x67\x49\xf6\x5a\xa2\xc4\x04\x89\x4f\x74\xeb\xe0\xb6\xac\x6a\x9e\x78\xfc\x40\x33\xcf\x8a\x53\xc9\x96\x3c\x81\xe1\xe3\xce\x30\xcc\x0d\x5f\x9e\xe8\xd9\xa7\xdf\x2c\x2b\x96\x77\x5f\xbc\x28\x72\x5e\xd9\xac\xac\xc9\x8b\x2a\xb1\x72\xd0\x64\xc6\x1f\x3c\x96\x21\x96\xcb\x6b\x89\x1e\xcb\x23\x7e\xdc\x29\xc1\x58\xa0\x9a\x2f\x70\x4d\xb7\x5e\xdd\x96\x67\xf6\x03\xc5\x92\x9d\xb9\x4a\x96\x85\xf8\xdc\x79\x89\x6c\xab\x64\xce\xf5\x64\xae\x4d\x76\x55\x9d\x9d\x95\x7d\x02\x88\x55\xa3\x92\x8c\x73\x24\xf5\x06\x56\x67\x2c\xc4\x05\x2b\x8b\x5e\x61\x35\x2f\x81\x3a\x72\xfc\xe9\x52\xb2\xd5\xca\xf9\x16\x5c\x5f\xb2\xfa\x55\x53\xaa\x62\x55\xf2\x6c\x34\x2a\xc7\x4b\x7b\xb3\xb9\xa9\x34\x1f\x8e\x23\xab\x87\x3f\xbd\xf1\x68\xd1\x3b\x85\xd8\xf9\xcc\x91\xd0\x99\xec\x86\xaa\xc4\xe5\xf8\x9c\xd5\xaf\x2f\x85\x1e\x15\x5c\xaa\x2b\xd4\x60\x00\x3c\x2d\x8f\x9a\x63\x92\x38\x61\x37\xa1\x94\x36\xf3\x3e\xce\xe3\x5c\x8e\x75\x05\x60\x92\x0a\x65\x90\x54\x11\xa7\x47\xed\x8b\x84\x1d\x0f\x68\x75\x58\x9a\x76\xdf\x4c\x92\xdb\xfd\x97\x75\xe2\x31\xce\xea\xa1\x4a\x9a\x79\xc8\xd2\x34\xa9\xc4\xbb\x85\xac\xca\x12\x6a\x99\xa6\x9a\x00\xb5\x49\x20\x12\x63\x37\xd4\xdd\xd0\xb6\x3d\xf5\x4f\x24\x31\x91\x40\x33\x80\xee\x1a\xa4\x29\x64\x5a\x70\x34\xdc\x83\x66\xb0\xaf\x40\xad\x9b\xc5\xd2\xc9\xc0\x41\x45\x39\xae\xc4\xe3\xb2\x80\x50\x94\x72\x5c\x89\x85\xbe\xa6\xcf\x24\xde\x48\xda\x0d\xa4\x2c\x03\x9f\xba\x50\x9f\x6e\x4e\x27\x6d\x83\x1a\x7a\x1f\x90\x41\x3d\x32\x19\xcb\xd8\x18\x02\xbb\x3c\xb1\x30\x8b\xe0\x68\x93\x1b\xff\xd3\x53\x8e\x04\xc6\x36\x65\xae\x09\x54\xac\x14\xc0\x42\x81\x05\x5a\x33\x36\x2e\x9d\x16\x99\x11\x25\x79\x71\x91\x40\x98\x0f\xc1\xe5\x4f\xef\x5f\xbd\xa4\xc9\x03\xf3\xce\x3f\x1e\xfc\xaf\xff\xb1\x57\x09\x31\x32\xfc\xb2\xba\xe0\x80\x1f\x86\x78\x08\x26\x86\xb3\x3e\x50\xfc\xb8\xa8\xe7\xfd\xaf\x09\x72\x5d\xd4\x99\x7e\xb8\xc1\xd9\x40\x6d\x04\x26\x8e\xea\xd4\x6c\x7c\x1b\xca\x89\xf4\x53\x64\xde\xf8\x4b\x3a\x9a\xc0\x42\xfb\x0d\x50\x14\xe1\x82\x9a\x7b\x8c\x71\xd6\x2b\xfa\x97\x77\xb0\x35\x22\xdc\x32\x42\x0e\x8c\x50\x92\x2f\x85\xc5\xfb\x0a\x30\xde\x38\x69\xe8\x3b\x6e\x42\xb4\xdc\xc4\x28\x79\xc4\x28\xc1\x07\x4b\xfe\x9b\xcc\xb2\xff\xf2\x16\x86\xc9\xe8\x64\xc6\x02\x86\xc9\x3c\xc3\x64\xc7\x84\xe3\x59\xa7\x94\x01\xa6\x39\x50\xcf\x1f\x63\x9c\x3c\x64\x9c\xfd\x52\x06\x99\xe7\xc0\xc7\x3c\x03\x05\x64\x57\x46\x5f\x98\x8b\x88\x9d\xf1\x68\x1e\xba\xa9\xc7\x28\xe3\x01\xa2\x6d\x3c\x49\xf9\xcd\x6c\x56\x06\x6c\x96\x99\xb0\xb2\x92\x5c\x83\x63\x81\x73\xc5\xbc\xb1\x0e\x11\xff\xb5\x35\x2f\xf9\x4d\x55\x77\x2c\x82\x51\xb9\x01\x76\xcc\x9c\xc5\x0f\x03\xd1\xb4\xd4\x7c\x7a\x81\xf5\x3e\xb7\xcb\xf6\x4a\x6b\x48\x95\xd3\xc5\x51\x79\x3c\x4b\x6a\x75\x55\xf2\x04\x42\x29\x7f\xd5\xdf\xcc\x71\x96\xe4\x4c\x9c\x71\x59\x35\x75\x79\xf5\x8e\xab\xe7\x6e\xfa\x9a\x5c\x36\xd8\x61\x4e\xf3\x79\x3e\xfe\xf4\xe9\x5c\x2d\x4b\xdb\x4a\x9c\xa6\x17\xae\x88\x90\xeb\x97\x7d\xae\x9f\xcf\xe3\x28\x50\x62\xbd\x4e\x12\x08\xd0\x9c\xa6\x67\xae\x8c\x2e\xc7\xcf\xed\xb3\x24\xb9\xad\x1f\xd7\xcd\x6a\x25\x79\x5d\x5b\xfe\xff\x34\x2f\x40\xc7\xff\x3b\x93\xc2\x04\xb1\xa2\x65\x9a\xfa\x5c\x3f\x81\x20\x57\x54\xa2\xf3\x9c\x35\xaa\x7a\x56\x2d\x9a\xda\x26\xa0\xba\x4f\x31\xdb\xe6\xbc\xb3\x4e\x94\xf1\x3a\xc1\xdd\x81\x4b\x9e\xa6\x97\x88\x93\x92\xe4\xa4\xc1\x78\xb3\x6d\xed\xe0\xb0\x76\x70\x22\xc9\x68\xba\x75\xed\xe0\xb0\x76\x0c\x8f\x59\xf3\x35\x69\x30\xd5\xd3\x14\xa2\x32\x3d\x54\x4a\x16\x27\x8d\xe2\x28\x81\x64\x58\xff\x7e\x46\x36\x13\xde\x32\xbc\x5b\xc6\x17\x0c\x66\xbb\x7e\xa0\xd2\x7d\x02\xcf\x0b\x5d\xdf\x28\x4f\xa9\x2b\xef\x6b\x62\xc7\xe5\x6f\xa6\x42\xfd\xdc\x71\x8e\x60\xcd\xbc\x61\xcd\x63\xc1\x9a\xc7\xa3\x35\xef\x77\x17\x00\x34\x5a\xde\xe2\x58\x6b\x1d\x7b\xc9\xde\x6e\xe5\x30\xd3\xd2\xf0\x90\x44\xfe\x6b\x81\x26\xa4\x87\xe8\xa8\x39\x84\x93\xc0\x7b\xe1\xd2\x64\x10\x37\xea\x66\x71\x5c\x74\xf6\x09\x64\x48\x1c\x9f\xa3\xbe\x38\xde\xa9\x8c\x13\xbd\x61\x01\x07\xa2\x5a\xa5\x6e\x6c\x4b\x85\x24\x45\xf7\x01\x6d\xb7\x85\x20\xcd\x44\xbc\xd0\x63\xbb\xa8\xbd\xe7\x5f\x01\x11\x19\x49\x8c\x6d\xf1\xe1\x02\x26\x07\x88\x38\xf5\xfb\xb8\xa6\x42\xdf\x18\x26\xb2\x67\x42\xd3\x39\xe3\x9c\x23\x77\x64\x26\x20\x1e\x92\x8b\xa1\xaa\xa5\x16\x6a\xd5\x38\x70\x9a\xb8\x15\xfa\xb7\x3d\x5a\x04\x5a\x65\xde\xda\xbc\x7b\x5c\x26\xd3\x74\x24\xdc\x59\x69\x70\x46\xe1\x4d\x6e\x47\x43\xc5\xdf\x74\xf8\x09\x56\xde\x69\xa0\xaf\x9d\x4f\x28\xa5\x0f\x35\xf3\x78\x58\xd2\x3d\x9c\x21\x5d\xa2\xbe\xdf\x83\xdf\xf5\x5a\xa7\xef\xfb\x33\xd2\xf7\x25\x38\x1f\xa3\xe9\xde\xfe\xee\xf4\xee\xdd\xdd\xbb\xe9\x93\x12\xa7\x69\x9c\xf4\xac\xc4\xeb\xf5\xb2\x46\xef\x4b\xf2\xa9\xc4\x58\x6f\x85\xd7\x6b\xd1\x19\xec\x36\xe8\x0b\x74\xc2\x7e\xb4\x97\x6e\x9b\xf7\x8b\x44\x5b\x23\x6c\x85\xdb\xd8\xe9\xc4\x15\x20\xe1\xac\x36\x78\x72\x5f\x4f\x12\xdb\xb5\x4e\x2f\xd9\xeb\xe2\x28\x48\x90\xde\xf7\x96\xdd\x83\x6d\xff\x6e\x43\x65\xab\x94\xc7\x7a\x99\x2a\xb1\x2c\x91\x61\x84\xde\x8e\xdc\xd2\x6e\xbb\xba\xfb\x26\x65\xb7\xd3\x4c\x36\x56\x09\x69\x34\x64\x81\x3a\x9d\xb8\x0f\xfa\xa3\xca\x92\x36\x11\xc2\x08\x90\x3a\x94\xa8\x03\xeb\xe0\xb6\x33\x65\xa0\x5f\x34\x9d\x13\x1e\x6f\x82\xc6\x21\x3a\xb4\x0a\xf3\x43\xb4\x70\xd1\x6d\x81\x98\x61\x2d\xbd\xa3\x92\x0a\xec\x8e\xf3\x77\x49\xd9\x3b\x23\x2b\x7b\x9f\x22\x65\xf7\x40\x34\x20\x79\x19\x05\xc9\x2b\xe3\xe3\xa9\xd2\xb9\x34\x90\x32\xd0\xf6\x92\xb2\x63\x25\xd4\x49\x0c\x8e\xd5\xca\x3e\x46\x66\x19\x2b\x46\x6d\x5a\xcb\x49\xac\x06\x3b\xaa\x49\x13\xdc\xf8\x4a\x35\x56\x7d\xea\xaa\x66\x33\xf5\x6a\xd7\x74\xb8\x63\xd9\x43\xec\xe9\xd8\xfc\x46\x75\x8e\x3a\x9f\x94\xc6\x26\xb3\x31\x9a\x1b\x7d\x11\x36\x66\xa8\x6d\xc0\xae\x40\x47\x07\x60\x09\x75\xe6\xdc\x43\xcc\x6e\xc6\xfa\xcd\xb9\xcd\x8d\xb9\xdd\xc4\x6a\x41\xe7\xb0\x67\xad\x2a\x5a\x0e\xb3\xde\x6d\x4d\x67\xc2\xd3\x0c\xc7\x34\x41\x51\x98\xa6\xb7\x2a\x84\xff\x71\xab\x0c\x79\xc4\xe1\x3e\x29\xe9\x68\xd2\x8e\xf6\xae\xa9\x82\xb3\x56\x3d\x45\xa3\x12\x47\x2a\xfd\x27\x0c\x35\xd8\x28\xa8\x7b\xc5\xb5\x9e\x3d\xfc\xe6\x39\x23\xa2\x39\x63\x6a\x31\x09\x26\x8f\xa9\x78\xe4\xae\xe2\xb4\xbf\x69\x3a\x6a\x42\x35\x6a\x00\xd7\xdc\xa2\x6d\x6f\x9d\x5b\xa6\x2a\x5d\x03\x02\xd2\xa2\x8a\xee\xfe\x3f\x9a\x5c\x77\xe4\xc0\xf1\x20\xd0\xb0\x75\x3f\xe9\x2e\xa9\xdf\xa7\xe9\x4c\x86\xa7\x92\x73\xe4\x63\x94\xf4\x0e\x55\x1a\x9c\xa1\x96\x98\xa6\x01\x78\xde\x2a\xa3\x9b\xcc\xe7\x24\xe6\x29\x6d\xa2\x15\xd8\x77\xff\x1c\xde\xd7\x57\x44\x86\x67\xa0\x44\x5a\x95\xb2\xd7\xea\x87\x64\x8a\x08\x48\x86\x88\x41\x6f\x81\xce\x36\x3e\xbc\x57\xa1\x35\x93\x19\xaf\xe5\x7c\x9a\xaa\xf5\x6e\x36\x4d\xf5\xe2\x11\x86\x9b\xdb\xdd\xb3\x71\x2d\xfc\x12\x75\x59\xa3\x41\x45\x6c\x34\x3f\x47\xb4\x3d\xe5\xe8\x5a\x3e\x7d\xc7\x99\x69\xe4\x9c\x99\x06\x96\xcb\x4d\xf7\x44\xe5\x90\x18\xad\x78\x08\x96\x5c\x22\x3e\x88\x35\x3f\xcd\xce\x2a\x17\x71\xc3\x68\xb3\x3d\x56\x38\x7c\xc5\x4d\xe1\xfd\xc9\xfd\xc3\x14\x60\xf0\x2d\x0a\xfa\xfe\xe4\xfe\xdd\x54\xad\x0f\xf7\xdd\x36\xc1\x29\xc0\x8b\x53\xb4\x4d\xf9\x6d\xd7\x3b\xe4\x4b\xef\x45\xc5\xda\xbd\x77\x10\xe0\x01\x0f\x7c\xcb\x69\xa8\x6d\x16\x08\x14\x41\x6e\x10\xdc\xa0\xde\xc1\x07\xbf\xdf\x82\xe9\xfd\x4e\x11\xed\xa3\xbe\x44\x32\x20\x69\x44\xf5\xb9\x61\xa4\x74\x70\xf1\x77\x3a\xc7\x1f\x85\x3d\x4a\x72\x28\x2d\x82\x26\x89\x16\x43\x67\x79\x75\x2d\x6e\xd3\x9f\x90\x0d\x4f\x63\x0f\x8b\x2d\x50\xb3\x03\x9b\x0c\x40\x58\x2a\x9a\xfc\x2f\x01\xf4\xdd\x39\xe3\x02\x1c\x9a\xc5\xd9\x4e\xad\xd8\xe2\x73\xb6\x93\xdc\xd6\x63\xb4\xae\xd9\x19\xbf\x9d\xfc\x2f\xa1\x6f\xe1\x89\x9d\x90\x76\xcf\xcf\x03\x7c\x43\x78\xaf\x0a\x2a\x5a\x06\x15\x5d\x54\xa2\xae\x4a\x3e\x06\x25\x08\x52\x76\x97\xd5\xd6\xa5\xe6\x30\x03\xab\x46\x6d\x85\xd3\xfb\x52\xd0\x18\xf8\xa3\x3d\x1b\xeb\x8b\x15\x9a\x95\x1f\x50\x1b\xf2\x7a\xbd\x3e\x74\x97\x98\x8f\xd9\x4a\x2f\x67\x46\x01\x17\xc4\x7c\x68\xcf\xfb\xf7\x5d\xa8\xec\xd6\x47\xcd\x9d\x3d\x8a\xf8\xe8\x5f\xc0\x9a\xd6\x3f\xfa\x0f\x4e\xee\xa3\x83\x7f\x31\x78\xf0\x2f\xfc\xc1\xbf\x08\x0f\xfe\x5d\x6c\x00\xff\x7c\x23\xba\xe7\xfe\xee\x49\xb8\xb4\x6e\x36\xe4\xe7\x62\x8b\xf9\x13\xeb\xda\x0b\x83\x3f\x99\x89\x1c\xc9\xa3\x0d\x58\xbc\x49\x33\x36\xbf\xc4\x1c\xd6\x6d\xd1\x10\x1b\x15\x14\xec\x88\xac\x2e\xaa\xa4\x47\xc7\x37\x28\xa0\x20\xab\x55\x45\xf5\xf2\xba\x0d\xbb\x55\x32\xb1\x9e\x92\x49\x6e\xd3\x3e\x75\x4b\x6a\x55\x0c\x56\xd5\x04\xdf\x2d\xfb\xdf\xed\x6f\xcc\x47\x03\x1b\xf3\x81\x6d\xbb\xdc\xba\x6d\x87\x30\x88\xfe\x20\x41\x82\x08\x64\x0c\x8d\xe1\x54\xab\xab\x7e\xc9\x71\x9a\xb2\xa1\x44\xab\xbc\x3f\xca\x8f\xb1\xd9\x8c\x5b\x45\x56\xee\xa2\xb5\xe9\x47\x30\xd2\x0a\xfd\xb5\x06\x37\xdd\x52\x0a\xd8\x08\xae\xd7\x48\x98\x80\xe9\x47\xc5\x31\x4d\x12\x23\x11\x6d\x55\x82\x99\x70\x98\xad\x82\xcb\xde\x7f\x5f\x1b\x95\x7f\x47\x1b\x95\x77\xb5\x51\xf9\x90\x36\x2a\xc7\x73\xbd\xa1\xd4\x5d\xa4\x85\x67\x5a\x42\x90\x2e\x83\x42\x9b\x5b\xab\xc6\x99\x27\xb1\x74\x51\x19\xa5\xa6\x85\xde\xc5\xd9\x6d\x32\x9b\x6b\xea\xd8\x01\x42\x06\x89\xbe\x30\xe8\xcd\x76\x11\x5e\xb8\x9d\x58\x83\xbb\xe4\xd6\xc5\x1a\xc6\x63\x09\x3d\x1a\xa0\xf4\x7a\xbd\x48\xd3\xc5\x50\xfa\x40\x0f\xb4\xbd\xb6\xc0\x8b\xa1\x5e\x6b\x8e\x8a\xe3\x11\xa5\x8b\xa3\xe2\xb8\xdf\x85\x3a\xd5\x79\xf3\x6a\x52\x39\x72\x91\xd2\x93\x09\x30\x5a\x16\xb3\x1b\x3b\x1a\x22\x0b\xa2\x05\x5d\xcc\x17\xb1\x9e\x93\x34\xb4\x99\x37\x9d\x34\x4b\x25\x83\x76\xbd\x80\x98\x8a\x71\xd7\x2c\x70\x47\x2d\x9a\xcf\x7b\x0a\xa4\x45\x9a\x3a\xad\xe7\x28\xf0\xc9\xec\x95\x95\x24\xb7\x17\x3f\xa4\x01\xfd\x81\x31\x37\x38\xc4\x90\x6f\x4e\xa4\xf1\xcc\xbb\x1a\x4f\x52\xae\xd7\x0d\xa5\x74\xe1\x68\x8c\xb3\x9e\xe3\xea\xc2\xaf\x18\x30\x02\x1c\x0c\x0f\xa5\xf4\xe1\x7c\xd1\x42\xd4\x0c\x8c\xe6\x05\xc6\x1b\xd1\x23\xa5\x1d\x7a\xc4\x06\x50\xcc\x69\x39\xeb\x6c\x3a\xf2\xae\x4e\x70\x43\x7e\x1d\xe2\xfe\x62\xe0\x74\xcc\xb8\xe6\x96\x43\x3e\x6d\xbf\x73\xf6\xf9\x15\x5b\xcd\xed\x6f\xf6\x8a\xad\x5a\x07\x80\xc6\xdb\x5f\x20\x41\x17\x0c\xdd\x99\x42\x10\x6b\xc5\xce\xe8\x1e\x11\xe3\x15\xbb\x2a\x2b\x96\xd3\x6b\xeb\xe1\x67\x51\xd6\x9d\xad\x06\xb0\x6b\x7f\x48\x0f\x41\x50\x4f\xd8\xe2\x33\x0d\x56\xfd\x2f\x7a\x1c\x7f\x81\x8d\xc7\xcf\x25\xc4\xa5\x2b\xd1\x04\x10\xc0\x02\xdb\xcf\xc5\x0d\xb5\x70\x28\xfd\x20\xbd\x6e\x75\x1c\x89\x43\xb7\x06\x91\x98\xaf\x1d\x2e\xb7\xa9\x6b\xdb\xa4\x3e\xe4\x88\xad\x19\x91\xa8\xb2\x50\x76\x2c\x72\xee\x88\xb7\x2f\x6c\x70\xfd\x60\x91\x0b\xd1\x63\x2d\x12\x81\xad\xea\x10\x69\x06\x16\x27\xd9\xaa\xf8\x7e\x2d\xe7\xbf\x96\x54\xf0\xcb\x9d\x77\x5c\xa1\x23\x75\x5e\xd4\xc7\x38\xfb\xb5\x1c\xb3\x3c\x47\xfa\xce\x93\x12\x5b\x28\x69\x65\xa4\xba\x99\x7e\xd8\xaf\x86\x13\xd4\xc8\xb5\x7f\xf4\x0e\xc4\xbc\x16\x95\x21\x4b\x92\x0d\xd6\xec\x08\x1a\x9f\x6f\x1d\x4d\xef\xb8\x9a\xdb\xdf\xec\x1d\x57\xed\x68\x3a\x2d\x43\xb7\x18\xc9\x4f\xa3\x88\x16\xc3\x5d\xa4\x00\xa2\xd0\x81\x87\x1a\x21\x52\xe1\xeb\x6f\xb5\x89\x81\x0e\xfc\xb0\x03\x15\xda\xa2\x94\x97\x51\x78\xad\xd0\x4c\xa8\x1f\x85\x30\x0a\x52\x68\x6f\xad\x11\xd1\x7e\xc7\xf8\xc7\x99\x04\x15\xa7\x68\xf7\xe0\xd0\x69\x02\xdb\x1d\x5f\x1b\x68\xa8\xa3\xd8\xee\xd9\x16\x2b\x03\x6c\x1c\xd8\x02\x6d\x71\x01\x43\xaa\x13\x83\xd4\xd8\xb0\xcc\x45\xe0\x4e\x2b\xb0\xb1\xb3\xf9\xf4\x49\x72\xb6\x50\xcf\x05\x28\x19\xca\xa1\xe2\xa8\x43\xd7\xea\x58\x2c\x41\x44\xac\xa8\x4d\x3f\xdd\xa4\x68\xc5\xdd\x6d\xe7\xe1\x5e\xb8\xe1\x3c\xf7\xf3\xd6\x87\x80\xff\x91\x1e\x08\xf4\x35\x3e\xbe\x8c\xbe\x8a\x91\x92\xc3\x2d\xbe\x0d\x12\xa5\x05\x5b\xaa\x7c\x14\x81\xe2\x14\xed\x51\x8a\xf6\x52\xb3\xd7\x75\x36\x64\xdc\x1e\x09\xcc\xb8\xc3\xe9\xa5\x12\x61\x1f\xb1\xc9\xee\xa2\x38\x8c\xc9\xcd\x7f\xab\x2e\xd6\x0e\x7f\x26\x5d\x18\x0f\xbd\x0d\xde\x4f\x51\x45\x2b\x53\x39\xa3\x08\x9e\x82\xbd\x3d\x7a\x5e\x23\xa1\xd7\xa1\x57\xe6\x17\x43\x6c\xd1\xa8\x5e\xf1\x40\x6c\xb1\x48\x02\xb9\x7e\x3f\x15\xae\x13\xbd\x3d\xd5\x9c\xf7\x9d\xbd\x91\x39\xa9\xe8\x8c\x2f\x83\xba\x33\xef\x9c\x20\xe8\xd1\x66\xf1\x78\x3a\x4f\xf4\xc0\xeb\xbb\x47\xf6\xa3\x60\xfc\xd8\xf8\xc4\xd8\xc0\xc1\xa1\x6d\x24\x4f\xd3\x73\x86\x04\x20\x4c\xe2\x40\xe9\xb0\x2d\xbb\x8d\xef\x19\xba\x68\xb8\x8d\x9e\x1f\x9a\x66\xbb\x17\x46\xe0\xb3\xd4\xe5\x2e\x6f\x4b\xdc\x8d\xff\x7a\xd4\x13\x07\xc3\x3d\xe1\x5b\x42\x01\x73\x37\xe8\x98\xdf\xa5\x87\x37\xea\x90\x33\x4d\xf9\xf8\x54\xcb\xcc\x08\xfb\xa8\x7c\x11\x33\x72\x86\x8e\xf7\x3d\x73\x32\xf3\xc7\xce\xab\x5d\x17\x76\xb5\xab\x7c\xe8\xea\x48\xc2\xca\x89\xae\xe9\x3c\x98\xca\xb6\xf0\xb4\xa1\x7f\x45\x37\x73\xf7\x61\xeb\x61\x18\x3c\xf9\xaa\x90\xc0\xfa\xbf\x9b\x19\xc7\xb2\xec\x6e\xfb\xf9\xac\xb3\xd1\x77\xb3\x39\xa0\xb3\x89\x19\xd8\x5f\x43\x10\x44\xf0\xd5\xe2\x15\x1e\xd7\x5c\x39\x89\x70\x2e\xc3\x3b\x94\xe4\x45\xbd\x2a\xd9\x55\x42\x12\x51\x09\x9e\x90\xa4\x58\xae\x2a\xa9\x98\x50\x09\xce\xe4\xd8\x3e\xa6\xe6\xa9\x39\xd0\x89\x3f\x6f\xb5\x2e\x9d\x33\x37\xf8\xf0\xac\xb2\xcc\xa3\x4a\xd3\xaa\x2b\x99\xfa\x2f\xe3\x79\xe5\x3e\x63\x7d\x48\xcc\xdb\xfe\xdb\x97\x3c\xa8\xa6\x96\x42\x9c\x1e\xa3\x55\x7a\x88\x30\xa2\x9c\x3b\x3e\xa5\x6a\x9e\x24\x59\xa7\x66\x5e\x09\x82\x76\xf7\x5a\x35\xc8\xae\x57\x89\x78\x23\x5e\xd1\xf5\xaf\x14\x36\xe6\xc8\x7f\xa0\x32\xe1\xff\x99\xca\x84\xff\xfb\x2a\x93\x16\xc5\xbf\xb5\xd3\x7e\x57\x0d\x4a\x6b\xef\x2a\xbd\xdd\xaf\x96\xcb\x42\x3d\x2b\x4e\xb8\xfc\x20\x96\x9a\x61\x82\x44\xb2\xe5\x19\xfa\x5c\x69\xb1\xa4\x45\x3f\xfe\x01\xd9\x63\xff\xa6\x15\x50\x8b\x07\x31\xe3\x0b\x03\x27\x06\x27\x03\x5e\xe8\xb0\xeb\x98\x5b\x75\x24\x15\xe0\xbf\x63\xd7\x3a\x3d\x49\xa4\x89\x2a\x4d\x5a\x9f\x56\x6c\xc3\xcc\xee\xa7\x12\xe3\xe7\x35\x52\x1e\xfb\x4a\x52\x13\x45\xa3\x42\x41\xab\xbe\xd5\x48\x6a\xde\xb7\x11\x36\x84\x80\x8b\x8e\x04\xd2\xcf\xa6\x55\xc9\x18\x21\xe9\xb4\x44\x6a\x08\xa2\xa0\x2b\xfb\xc4\xb0\x08\x01\xb1\xb9\x75\xd9\xef\x5a\x0a\x58\xf1\x9b\xf6\xd7\x98\xa1\xa2\x3a\x2d\x00\xee\x1d\x54\xf5\x20\x83\x7a\x06\x0a\xa5\x9d\xfd\xec\xa9\x19\x24\xc1\xb0\x39\x03\x21\xb6\x87\xb9\xc4\xc3\x13\x46\x3e\x70\x48\xc8\xfb\x07\x9b\xbc\x77\xb0\xc9\x87\x8e\x26\xf9\xd0\xd1\x64\xec\xb2\xe0\xd2\xdc\xc8\x37\x77\xdd\xc3\xcb\x20\x16\x43\x19\x04\x71\x38\xa0\x3e\x0e\xe8\x5e\x7b\xb9\xef\x2e\x83\xc8\x0c\xa6\xe9\x59\x18\x58\xb9\x13\xd7\xd4\xc6\x57\xbe\xd2\x94\xf4\xfe\x4c\x61\x5c\xe0\x0e\xdb\x9f\xd8\x10\xce\x82\x2a\x6f\xcd\x1f\xad\x9d\xa2\x17\x13\x57\xd2\xd1\x34\xec\xa4\x3d\xb7\x2e\x2a\xda\xf1\x7b\x37\xa8\x56\x1d\xef\x98\x4e\x05\xa6\x18\x6f\xa6\x87\x81\xa8\x74\xc6\x91\x22\x49\x82\x5d\x2c\xe0\x94\xde\x99\xde\xc5\x33\x9e\x29\xeb\x48\x04\x4b\xd1\xdf\xe1\x5b\x57\x25\x72\x37\x18\x60\x21\xbd\x2b\xc6\x0e\xdf\x04\x0c\x0c\x8a\xff\x11\x26\x36\x3b\x68\xf9\xf5\x61\x7b\x39\xbd\xe7\xae\x4d\x45\x76\x5d\xab\xb0\xe3\xbe\x3b\x2a\x8c\xf7\xe5\x3c\x04\xf6\xfd\xe2\x11\xe4\xdb\xce\xcb\x37\x10\xc0\xb5\x2d\xdc\x20\x5d\xb6\xcb\xa0\x6b\xd9\x46\xce\x2f\xf5\xec\x01\x5b\x98\xaf\xee\x2a\x08\xc4\xd1\xf1\xed\x80\xc1\x46\x2a\xaa\x87\xa3\x34\x7a\x7c\xd8\xb7\x57\x98\xd3\x6a\x1e\xec\xb4\xb3\x30\x6a\x6a\x21\x6a\xc5\xc4\x82\x13\x35\xbf\xd7\xb1\x05\x0a\x02\xa1\xeb\x6c\x5c\x5a\x11\x13\x66\x74\x26\x06\xd2\x50\xa7\x08\x18\x8b\x6d\x29\xb8\xfb\x8a\xc0\x99\xce\x82\xa3\x83\x06\xee\x0e\x01\x41\x0c\x32\xb2\xee\xdb\xaa\x82\xd3\x71\x18\x9a\xd8\x9b\x7f\x28\xa7\x42\x06\x4f\x8c\x40\x9d\x1c\x9f\x50\xc8\x98\xe9\x9b\xd5\x16\x0c\x45\x3c\x0d\x43\x77\xc0\xc0\x68\x64\xf0\x79\x10\x3d\xe4\xbf\xdd\x05\x62\x90\xd0\x31\x75\x7e\xb0\x69\x5f\xbf\xd3\xb4\xaf\x37\x37\xed\x69\x57\x84\x24\x00\x5f\x41\x00\x55\xcd\xcc\x8f\x11\xc3\xd7\x8c\x56\x8e\x83\x19\x3f\xd3\x59\x34\x89\x19\x1e\x60\x58\xfe\x54\x84\xb2\x80\x51\xb1\x88\x51\xb5\x4c\x6a\x87\x77\xd8\x94\xb0\xc0\x55\x43\x6c\x6a\x87\x6f\x18\x75\x1e\xd2\x1b\x46\x47\x93\x8d\x15\x7a\xab\xf6\x74\xcb\xec\x18\xaf\x4d\x7d\x8d\x13\x0b\x27\x35\xad\x48\x43\xeb\xd9\x4c\x2f\xe5\x17\x25\x2a\x49\xe3\x0f\xa3\xad\x69\x49\x9a\xee\xc3\x8d\x7e\xbb\x89\xa7\x77\x43\x1a\x97\xcb\x9b\x2a\x35\x94\xd2\x7a\xd0\xa9\xb5\x19\x64\x78\x8d\x67\x78\x4d\x2b\xa8\xb5\x05\x34\x3e\xc3\xa6\xe9\x32\x39\xf7\x04\x6a\xe1\x9d\x5a\xe7\xa8\xa4\x42\x37\x2c\xa0\xb2\x9e\xa0\x65\x3b\x41\xcb\x70\x8e\x87\xe6\xf6\x35\xce\xca\x4e\x82\x1e\x89\x61\x4a\x50\x2c\xf6\x82\xf4\x7e\x4b\xdf\x20\x16\x9f\x17\x70\xc3\xba\x0c\x74\xa2\x73\xd5\x77\xed\xaa\x48\xe5\x5e\x6e\x25\x60\xff\x2d\x10\x40\x2b\xdf\x4b\xfe\x2b\x3f\x52\x88\x9e\x94\x5b\x4e\x1e\xab\xc1\xde\xa9\x7c\xef\x54\x03\x27\x8f\xba\xd9\xa0\x8b\xb0\xcb\x94\x59\x50\x10\x03\xf4\xa0\xaa\xdb\x5d\x2e\x1b\x54\xac\x2f\x58\x7f\xfe\x71\xb5\x5b\x5f\xf4\x75\xa7\xbc\x81\xec\x12\x68\x09\x5b\xf8\x5d\x31\x17\x03\x4a\x17\x2b\xf0\x5a\xa9\x54\x8b\xc0\x46\x03\x04\xf2\x2e\x44\xa6\x6f\x25\x61\xe2\xaf\x68\x14\x36\xca\xc2\x93\x22\x6c\xce\xd6\x03\xf1\x56\x02\x5c\x69\x47\xf7\x12\xef\xc6\x63\x15\xe1\x41\x2b\xc9\x83\xc3\x5c\x3b\xe0\x8c\x53\x5a\xbc\x1f\xb3\xfb\xc7\x3e\x0a\xae\x51\xbd\xc8\x19\x0f\x3d\xd7\x58\x9f\x48\x03\x21\x9d\xdb\xe8\xb4\x20\x5d\x58\x1f\x0e\x7b\x90\x6b\x4c\x29\x13\xc9\xf2\xa2\xb2\x56\x4a\x57\x2b\x6f\xb9\x22\xc7\x82\x2d\x79\x9a\x2a\x7b\xa0\xf9\x8e\x9b\xe1\xaa\xe8\x3b\x7b\xa2\x5a\xd1\xc9\xac\x7a\xe0\xc3\x8a\x57\xb7\xe9\xae\x0b\x7c\xcb\x8e\xaa\x63\x52\xeb\x9f\xdb\xd3\x9e\x3d\xbe\x20\xf5\xf7\xec\xf1\x2f\x5c\xae\xd8\xe4\xfe\xcc\x26\x5f\x22\x41\x4a\x52\x6b\x79\xc2\xd9\xb3\xc4\x47\xd4\xc2\x54\x7a\xf8\x74\xb8\xe9\x3f\xf4\x56\xe3\x7a\xc9\x0e\xdd\x22\xc6\x81\x57\x04\xb9\xe1\xd9\xa0\x91\x39\x8b\x8c\xcc\x45\x6c\x36\xce\xc0\xc8\x9c\x8f\x68\xf4\xaa\x3f\x9a\x8c\xad\xca\x07\xde\xef\x9b\x9d\x67\x43\x99\xbc\x27\xd0\xd1\x71\x96\x24\xfa\x9b\x78\xb3\x89\xc6\xf0\x61\xf6\x63\x1e\x97\xbb\xad\x55\x0e\x28\x8d\xd4\xb0\xaa\xa1\xa3\xc8\x1a\xd2\x30\x77\x26\x83\xf3\x47\x85\xa3\x10\x7b\x4d\x47\x53\xf2\x55\x21\xd1\xd5\x38\xe3\xae\xfe\x6a\xd8\x9a\x2a\x4d\xd1\xef\xa5\x31\xf2\x5a\x96\x0e\x07\x4c\xd3\xc8\x86\x99\x78\x07\x5b\xbd\x8e\xad\x4f\xf7\x49\xdf\x70\x07\x72\xe8\x02\xc9\x16\x23\xae\x9b\xf5\x5a\xef\xa2\x03\x90\x61\x16\x07\x18\x27\xdd\x79\xec\xb1\x4e\x5a\x31\xdb\x49\xf1\xa0\x6e\xe3\xa1\x05\x2a\xbf\xdc\xc9\xc1\x40\xf7\xb4\x92\x4f\xd9\xe2\x3c\x30\xb3\x51\x8e\x45\x3e\xab\xc3\x10\x29\x44\xe1\x99\x18\x9f\xb3\x1a\x29\x38\xba\x36\x87\x48\xba\x08\x75\xce\x05\x92\x44\x42\x04\x90\x80\xc7\x3f\x2e\xa3\xd8\x3d\x01\x72\x80\xb3\xcd\xe5\x3d\x68\xaf\x00\xf3\xab\x55\x0e\x06\x0a\x0d\x35\x60\x12\xe7\x87\x65\xfb\x06\xec\x17\xff\x2c\xe9\x2b\xa6\xce\xc7\x0b\x5e\x94\xe4\x4d\xd9\x01\xf9\x7f\x62\xc3\xe5\x70\x49\xde\x96\x83\x01\x00\x5e\x97\x74\x42\xde\x1b\x2b\x17\xf2\x8b\xfd\xfd\xa4\x13\x5f\xe9\x3f\xcf\x4b\x5a\x57\x68\x82\xc9\x43\x7d\xf7\xd2\x3e\xff\xa6\x6f\x9e\xe8\x3f\xcf\xf4\x9f\x47\xfa\xcf\x5f\xf6\xd9\xef\xfa\xe6\xd6\xff\x4b\xdd\x9f\x30\xb7\x8d\x23\xff\xe3\xf0\x5b\x91\xb8\xf3\x70\x81\x15\xac\x50\xb2\xe3\xd8\x54\x10\x7d\x73\x38\x9b\xcc\x24\x71\x36\xce\x9c\x5a\xfd\x5c\xb4\x04\xd9\x1c\xd3\x80\x86\x84\x7c\x44\xe2\xbe\xf6\xa7\xd0\x38\x08\x52\xb4\x93\xd9\xfd\x1e\xf5\x9f\x9a\x8a\x29\x00\x04\x71\x34\x1a\x0d\x74\xf7\xa7\x33\x3a\x78\x14\x55\x0a\xaf\x1f\x33\x84\xd7\xdf\x69\x3a\xec\x3d\x8e\x22\x68\xfa\x4f\x19\x79\x63\x5e\xfa\x23\x53\x64\xfe\x83\xf9\xf5\x0f\xf3\xf7\xef\x90\xfa\xab\xf9\xf5\x4b\x46\x0f\x23\xf2\x7d\x46\x27\x53\xc2\x0a\xf5\xaf\x34\xc7\x7d\x5e\xd0\x88\xe4\xe6\x87\x28\xe8\xce\x80\x24\x2a\x29\x05\xdb\x67\x93\x5e\x14\xb5\x48\x07\xab\xa2\x52\x68\xc2\x85\xcf\x41\x78\x9c\xe1\xb1\x6a\x60\xbc\x33\x50\x52\x48\x31\x16\x45\x2c\x0a\x68\xb3\xa7\x82\x2d\x14\xe5\x1a\x20\xf4\x61\xa8\x67\x17\x36\x32\x6b\xbd\x0a\x80\xd5\x1a\x62\xbd\xb2\x9a\x3f\x3c\xa4\x14\x82\xc3\x8d\x07\xf1\xd0\x14\xa0\x89\x3a\x66\x27\x05\xfd\x92\x81\x35\x20\xfd\xbb\xf0\x22\x4c\xe0\x35\x04\x0d\x50\x45\xd2\xc2\x6e\x86\xbf\x67\xe3\xdf\xb3\x5a\x50\xd6\x38\x52\x72\x7f\x52\x18\x43\xc5\xbd\xc1\xc1\xfe\x60\x30\x0c\xff\x95\x16\x3e\xd8\x97\x0c\xe9\x8e\x34\x4e\x08\xa0\x6a\x73\xe5\x18\x0e\x77\xb4\x61\x2f\x3d\x18\x1c\x0e\xbd\x70\x33\x0c\xda\x4b\x18\x7d\x2d\xcd\x95\xd8\x71\x86\xc3\xf0\xf0\x00\x4c\xa1\x07\xc3\x98\xd5\xc2\xf0\xd4\xb7\x9f\xce\xa1\x63\x26\x83\xc7\x9a\x89\x1c\x1e\xb8\x94\xc8\xa4\x98\xab\xfa\xc3\x7d\x9b\x73\x60\x32\x9c\xfe\x60\xd8\x34\x0c\x8c\xca\x12\x62\xd6\x15\xde\x9c\x40\x60\x35\x8b\xdd\xf1\x38\x7a\xca\x0b\xc3\xb2\x6b\x84\xe1\x58\x11\x58\x55\x56\x9c\x1e\x31\xba\xd0\x4a\xd4\xba\x8f\xc3\xcf\xb2\x3a\x57\x51\xfa\x39\x0b\x43\xf4\x3a\xdb\x50\x49\xf6\x8c\x3b\xc8\x95\x7a\xeb\x34\x73\x91\x74\x21\xf6\xdf\x00\xb4\x4b\x6a\xbc\x0e\xf4\x78\x01\x25\x68\xe2\xba\x56\xb4\x13\xa3\x65\xa1\x1d\x4a\x15\x09\x1c\xab\x6a\xd5\xea\x20\x3f\x08\x84\x31\x8e\x0d\xe5\x1c\x67\x78\xb3\x39\x3c\xd0\x07\xc3\xc3\x43\x0d\x5f\xed\xf6\xa6\x62\xac\x48\xdf\xaa\xbc\xd9\x14\xc7\xb2\x00\x56\xc5\x30\x26\xa6\x7a\xac\x56\xa4\x17\x4d\xd4\xf4\xf1\x61\xdc\x28\x90\x8d\xda\xb1\xa3\x2c\xe8\x4f\xfd\x9a\x8b\x8d\xb0\x0f\x4f\xa6\x86\xc7\x37\x1e\xf7\x51\x63\xac\x66\xe9\xdd\x7d\x55\x9a\xc1\xdf\xb5\xb7\x30\x63\xef\x32\x25\x6e\x28\xb4\x8b\x2d\xbd\x88\x33\x1d\x80\xe3\x91\x3a\xc2\x17\xab\x02\xee\x1e\x6d\x18\x67\xca\xfa\xcb\x94\x9f\xdb\xdf\x09\x65\x7d\x76\xbb\x4c\xb5\xd5\xcc\xe7\xf4\x8a\x15\x24\xa3\xac\xb6\xba\x46\xd1\xd3\xac\x11\xc9\x39\xb3\x91\x9c\xc9\x8c\x26\x93\x02\xcc\xae\x76\xd4\xac\xcf\x1c\x5b\x58\x85\x39\xd6\x7e\x44\xab\x50\x60\xbc\x9e\x51\x49\xde\x49\xb4\xb2\x16\x2d\xcf\xe5\x48\xbd\x49\x07\xd1\x53\x3a\x1f\xcf\x7a\xc3\xc7\x51\xbc\xaf\x1f\x1f\xb3\xdd\x78\x67\x60\x8e\x46\xb3\xa7\x54\x82\x7d\x1d\x34\xd3\x45\x9f\x5e\xe1\x51\x06\xc1\xa3\xe1\x06\xfb\x8b\x22\x53\x4d\xa1\xe3\xd3\x4c\xb1\x03\x49\x9f\x4b\x20\xae\x1c\xfb\x73\xd9\xa5\xf4\x8b\x08\xc3\x8f\x02\x71\xd0\x51\x7a\xc3\xe5\x6e\x6e\x4d\xda\xc7\x3c\x15\x79\x2a\xef\x68\x84\x9b\xb8\x54\x7a\x91\xb5\x14\xf5\xcd\x37\xfd\x4f\x95\x83\xc7\xb0\x24\x10\xa7\xd7\xb5\xbd\xd6\xb9\x09\xbc\x16\x63\xf4\x5a\xd0\x09\x9f\x92\x17\x82\xfe\x26\xd0\xa9\x20\xff\x10\x18\xc7\xaf\x85\x36\x09\x02\x78\x95\x2f\x02\xc7\x83\x3d\x1d\xde\x8e\xfe\x21\xd0\xe1\x21\x69\xd4\xd7\xc0\xc0\xdb\x62\x49\xf6\x70\x55\xc1\x9a\x1c\x1e\x3a\x21\xaa\x7e\x7a\xb1\xa7\x19\x67\xca\x7c\x68\x39\x53\x0d\x2f\xe5\x49\x9b\x75\x84\xe3\x5d\x87\x4f\x6a\x17\x1e\xb6\x6e\x97\x6d\xf8\x62\xf5\x8d\xe8\x9e\xcb\xd9\xdd\xc7\x07\xaa\x7b\x65\x09\x8e\x5b\xaa\xf3\x9c\x5c\x34\xfa\x8e\xdb\xa6\x4f\x6e\xcd\xb3\x27\xb9\x5c\xd8\x9d\x4c\xef\x98\x69\x41\x61\xd3\xac\x36\xc3\x66\xec\xfa\xe1\x13\x5c\xd9\xc3\xfb\xd5\xaa\x25\x70\x5a\x20\x50\xd5\xfa\xe9\xdd\x8a\x26\x3a\x9e\xf0\xb6\x45\xb1\x76\x3f\xe4\x5b\x85\xb5\xce\xe6\x38\x1b\x1d\x67\x1b\x3a\xd8\x37\xe7\xbd\xcb\x02\x69\x1b\xc2\xcf\xc6\x09\xee\x34\xd3\xf7\x74\x9a\x93\xde\x6a\x3c\x48\x3c\x1a\x81\xce\xe4\x37\x55\x5a\x43\x53\x39\xab\x99\x23\x63\x35\xa3\xe8\x3a\x41\x98\x7c\xcc\x9c\xe5\x4c\xa2\x44\x22\x61\xb9\xd8\x87\x6c\x9c\xd3\x28\x46\x9f\x7d\xc9\x28\xa7\xcf\xf5\x8e\x8d\xbe\x64\xe1\xeb\x0c\x63\xf8\x62\x54\x5d\xe8\x45\xda\xbc\x38\x5d\xa0\x21\xd5\x36\x68\xaa\xfd\xfb\x7b\x84\x79\x12\x3e\xf3\x25\xfc\x37\x39\xda\xb2\x29\x01\x99\x00\x71\xfa\x4a\x2a\xbe\x0e\x40\x43\x27\x86\xb7\x63\x32\x80\xf5\xad\x67\x48\xd2\x77\x19\x31\x6d\x20\x57\x66\x77\x01\x16\xa9\x64\x17\x4c\x9c\x46\x81\xf5\x17\x29\x4f\x8b\x0b\x36\xff\x59\xe4\x97\x6a\x16\x75\xa7\xfd\xc0\xab\xae\xc8\x3b\xe3\xc0\x99\x37\xae\x2c\x9a\xc4\xb9\xf7\xd8\x9e\x45\x9c\xcd\xd0\x71\x51\xf7\x69\xd6\x36\x09\xb6\x65\x68\x7f\x78\x38\xd8\x7b\xbc\x1f\x85\x1c\x6b\xc1\x7d\x10\x3d\x45\x39\xfd\x39\x53\xa2\xe1\x0e\xb4\x19\x5b\x1f\x41\x20\x96\xc8\xa8\x50\x14\xa1\x20\x24\xb6\x78\x3b\x0e\x39\xd6\xbc\x09\x02\xdb\xd6\xf8\xfc\x66\xab\x74\xe8\x90\xca\xfa\x52\xdb\xdf\xeb\x88\x66\xf4\xc7\x1c\x1d\x37\x58\x94\x3d\x1c\x97\x5b\x5d\xda\xab\x75\xc9\xca\x53\xba\x47\xde\x65\x94\xda\x88\xd8\x35\xe3\x52\x6f\x30\x82\xee\x0c\x46\xd1\x53\x3e\xb2\xf7\x03\x7a\x53\xe1\x78\x94\xa8\x4d\x25\x23\x28\xa3\xf9\x24\x9b\xe2\x67\x02\x60\xe3\x32\x4c\x78\x48\xff\x95\x68\x75\xb1\x20\x6a\xa4\x38\x45\x83\x61\xf4\x0c\x71\x10\x4d\x77\x38\x1e\x0f\x86\x51\xbc\x77\x10\x3d\xe3\xe3\xbd\x83\x28\x1e\x44\xf0\xa8\xfe\xc4\x83\xc3\x21\x3c\x1f\x0e\xa3\x78\x97\xed\x3e\xe3\xe3\x5d\xb6\x1b\xef\xed\x42\xaa\xfa\x13\x0f\x0e\xf7\xa3\xbf\xfd\x96\x21\xfe\x48\x3d\x61\x55\x9f\x12\x12\xbe\x3a\x32\xbc\x6d\x64\xee\xe1\x5f\xc3\x43\xc5\xbd\x6c\xb8\xfc\x8a\x30\x1b\xdc\x49\xf1\xf6\x06\x5f\x6b\xec\xfb\x57\xde\xbe\x2f\x43\xfa\xaf\x17\x19\x51\x7f\x5e\xab\xcd\xab\x3e\xc9\x1b\x60\x7e\x1e\x1d\x84\xf4\x5f\x10\x11\xb5\xb9\xe7\x8f\xa2\xa7\x72\x64\x75\xc6\x7a\x36\x24\x26\xb9\x9a\x0d\x3e\x62\x13\x3e\x55\xcc\x51\x7d\x24\xf7\x55\xe6\xee\x14\xf0\x30\xb7\x34\x8c\xd1\x49\x90\xaa\x78\x7d\x3b\x0f\x4f\xed\x75\x9d\xa4\xa7\x19\xe1\x7a\x89\x4b\x1d\x6c\x4a\xb3\x17\x38\xd8\xea\x64\xbd\x1c\x94\xa4\x6a\x0c\xa0\x6b\xe9\x91\xfe\x22\x5c\xdc\x19\x23\x06\x73\x30\xfe\xf7\xd9\x8f\xac\xd8\x8f\x6b\x9b\x61\x3f\xdc\x4a\xd9\x5b\xec\x47\xd6\xd8\x0f\xf7\x5c\x98\xfe\x2c\xfb\x91\x04\xc8\xab\x56\x5d\x8d\x22\xce\x0b\x3f\xe0\x92\xdd\x29\x74\xf4\x3e\xf3\x55\x24\xab\x20\x7e\x6a\x9b\x41\xc7\x99\x0e\xb6\x54\xc9\xdd\xde\xd4\xde\x6d\x57\x18\xd2\x9d\x21\x51\xf5\x1e\xfc\x07\xf5\x9e\x99\x7a\x67\x02\xbd\xcd\xc8\xfb\x0c\x93\xf7\x70\x9a\xf8\xa2\xfe\xf5\x94\x81\xea\x5c\xfa\x3e\xa3\x6f\xdd\x8e\x44\x56\xea\x0d\x3f\xd4\xbd\x93\xe4\x6b\xc3\xe9\x94\xeb\xfe\xf8\x45\x4e\xc8\xaf\x2d\x68\x2d\xb4\x1a\xc9\xb0\xb9\xd8\x77\x06\xe4\xa7\x1c\xa0\x80\xdc\x26\x88\xb5\xc6\xf7\x43\xd6\x10\xff\x2d\x1f\xcb\x29\x77\x78\x61\x35\x7f\x3a\x73\xff\x97\x9b\x2b\x55\x7d\x02\x78\x59\x45\x2b\x29\xac\x9f\x5d\x6d\xb3\xb8\xc7\x65\x6e\x54\x33\x52\x78\x97\xd4\x41\x97\x3a\x7b\xf0\x9e\x9f\xe2\xe4\xba\xc3\x58\xbb\xaf\xd5\x32\xa3\x38\x6f\x56\xe1\x5d\x74\xa9\x89\xf0\x95\xd2\x9f\x33\xca\xc8\x87\x0c\x70\x12\xdd\xd4\x68\xaf\xd3\xd3\x8c\xbe\xcf\xe8\x97\x8c\xca\xfa\x35\xc9\x8b\x8c\xbe\xce\xe8\xab\x8c\x7a\xc1\xfa\x8f\x3c\x0e\x36\x72\x7c\xe7\x43\x06\x94\x65\xc5\x91\xbf\x3b\x37\x24\xfa\x21\x25\x3c\xad\x0e\x3a\x39\xfd\x3e\x69\x81\xe5\x55\xf2\xc6\xc8\xda\x70\x9b\x98\xcb\x0e\xcc\x53\x6d\x24\x2e\xd0\xba\x6e\xb1\xbb\xcf\xe7\x29\xed\x02\x62\xea\x2f\x09\x8d\x88\x4c\x29\x4b\xe9\xf7\x3a\x02\x1d\xc9\x21\x3c\xde\xa7\xac\x66\x54\x6c\x85\x76\xee\x59\x45\x19\x5d\xc9\xfa\x79\x46\x07\xaa\xf3\xd2\x5e\x24\xd9\x7d\x36\xb6\x9e\x58\x24\xad\xf4\xf8\x5a\xa7\x05\x8a\x78\x60\x7d\x99\x43\xe0\x8b\xf6\x0e\x1a\xee\xef\xed\x9e\xef\x5d\x4a\x8b\x30\xdc\xf2\x48\x28\x5a\x6d\x98\x0a\xb8\xc2\xb3\xce\x43\xc5\xc8\x5d\xe1\x64\xe6\xfe\xc6\xb8\xd2\x78\x8e\xf4\xa3\xd9\x18\xd5\xbd\xc8\x67\x0d\x2f\xf2\xba\x3d\xca\x6c\xcb\x03\x5d\x3b\x0e\xcf\x4c\x18\xfa\x18\xb5\xfa\xd1\xb7\xc4\x9d\xd3\x86\xe5\x74\x0b\x8a\x82\x2c\x68\x6a\xed\x99\x96\xaa\x0b\x4b\x0a\xb8\xbf\x8b\xca\x12\xf0\x82\x2e\x9a\x41\xb2\xdc\xe1\xed\x02\x2f\xed\x4d\xd2\x85\x77\x91\xa8\xcf\x78\xea\xe5\x2b\xef\x65\xad\x8b\x59\x56\x71\xbf\xaf\x3c\x54\x0e\xd4\xd5\x29\x0f\x01\x69\x74\xe7\xb8\x54\xa4\xb5\xd4\x0d\xbb\xa6\x8b\xb6\x9b\x5e\x4a\xe9\xb5\x2e\x70\x6e\xaf\x34\x46\xe7\x70\x99\xb1\xc2\xa4\xf6\x06\x3d\xd7\x9b\xde\xb5\xc9\xad\xa6\x70\x61\xa7\x30\x5d\xa0\x85\xef\xc7\xed\xd0\x61\xf6\x77\x0f\xdc\x4f\xc5\xce\x0f\x0f\x06\xb0\x87\x65\x30\x70\x55\x53\x7c\x18\x85\x4c\xc7\xcc\x7c\x52\x0d\xcf\x9d\x71\xba\x18\xe0\xd1\x1d\x64\x0e\xc9\x3c\x41\x19\xb9\xc3\x65\x66\xaf\x4a\x9c\xb6\xbb\x2c\xac\x3a\x2d\x33\x77\x2d\x67\x34\x01\x89\xe4\x65\x32\xbb\xf0\xfb\x7f\x36\x46\xb5\x2c\x18\x87\x22\x23\xee\x8e\x87\x9c\xf5\x0b\x26\xd1\x8a\x14\x18\xc7\x2e\xa8\x03\x2a\xe8\x59\xff\x5c\xa5\xc3\xf6\xdc\x5a\x9a\x74\xc1\xff\x07\x70\xa1\xf4\x15\x51\xa6\xcf\x70\x37\xf4\x95\x2f\x69\x25\x64\x45\x32\x3c\x5a\xe9\x7b\xee\x1b\x72\x83\x4b\x37\x90\x7b\xd1\xe1\x3e\x59\xd8\x18\x8e\xae\x7b\x0b\xba\xa8\xfb\xdb\x1a\xca\x5a\xe0\x51\x41\xb5\x18\x84\xfe\x40\x1a\x69\x01\x6f\x36\xc1\xf3\x0e\xdc\x3e\x77\x9c\x45\x5a\x80\x7b\x41\xc7\x49\x6d\x1d\xa8\xa4\xe3\x3c\xd4\x49\xe7\x6c\x25\x3b\x5c\x74\x2c\xd1\x75\x7e\x7c\xdb\xb9\x49\x8a\x4e\xb1\x64\xb3\x74\x91\xb2\x79\xff\x9f\xfc\x9f\xfc\xf9\x7c\xde\x49\x3a\x4f\x4f\xa0\x9a\x82\xb9\xd2\xb4\xdf\xef\x3f\xab\xbe\xd5\xb9\x48\xcf\x2f\x58\xde\x49\x79\x47\x5e\xb0\x8e\xcc\x19\xeb\x48\xd1\x59\xe6\xe2\x3a\x9d\xb3\x4e\xd2\xc9\x44\xa2\xf8\x63\x27\xe5\xf3\x74\x96\x48\x91\x77\x44\xde\x59\x66\xc9\x8c\x5d\x88\x6c\xce\x72\x55\xda\x58\x9c\xf6\x03\x5c\x3e\xee\x56\x90\x30\x43\x4c\x0a\x9a\x66\xa8\x20\x99\x5b\xa0\x66\x33\x5c\x78\x9b\xe1\x6e\x9c\xd0\x82\xd4\x47\x15\xee\x65\xed\xd8\x2a\x69\x60\x91\xa0\x05\x59\x65\x28\x22\x09\x78\xac\xd4\x2c\x27\x06\xaa\x06\x98\xbd\x5b\xb5\xe2\xef\x96\x8c\x1c\xd1\x45\xdd\xee\x57\x2d\x88\xfd\xbd\x70\x51\x05\x28\x6d\xe1\x85\xb7\xf7\xfa\x07\x39\xd5\xc4\x51\x2b\x13\x3d\x6a\x77\xdb\xb1\x9e\x38\x9b\x4d\xf7\x1f\x00\x17\x89\x8e\x30\x80\xb2\x7c\x43\x67\x67\x19\x5a\xd4\x3b\x5b\x3e\x40\x5a\xe5\xa7\x02\x71\xcf\x7c\x51\xea\x4d\x19\x04\x19\xef\xb2\x4b\xed\x3f\xd5\xc6\x54\x59\x0b\xe8\xfd\xc8\xd3\xd0\x17\x2e\x48\x73\x75\x05\x60\xc5\x55\xef\x52\x40\xed\xc2\x16\x04\xe4\x43\x1a\x7b\xd7\xaa\x27\xad\xf2\xe7\xbe\xb9\xbd\x68\xbf\xa9\x90\x9b\x8d\x91\xe1\xcc\x15\xc5\xcb\x6f\xb8\xa2\x50\xc2\xa5\x7f\x4f\x91\x7b\xd2\x59\x03\x36\x60\x7f\x50\x29\x28\x6b\x17\x17\xcf\x3d\xc1\x59\x7d\xb3\xb2\xde\x83\x7a\x46\xf8\x63\x81\x3e\xf8\xa2\xe6\x6f\xdb\x85\xc2\xb0\xfb\x49\x09\x6c\x5b\x65\x3f\x16\x95\x4e\xef\xa7\xcc\x0f\xc6\x49\x98\x92\x77\x47\x4d\x9b\xce\xba\xe5\xa6\x8b\xed\x39\xfe\x04\xd7\xe4\x1f\x94\x1c\xd1\x10\x3e\xaa\x8f\x7d\xf2\x3e\xc6\xec\x8e\xc8\x7d\x68\xe8\x51\xaa\xcd\x6a\x8d\xb4\x01\x1b\x45\xb4\x77\x50\xc5\xe1\x59\xd7\xac\x29\x44\x06\x7e\x0c\xef\xb3\x4a\x0b\x00\x1a\x5a\x45\x49\xb0\xd3\x80\x3d\x38\xa0\x4d\x9b\xa3\xd5\xee\xd7\xed\xc3\x61\xff\xae\x82\xe5\xbe\xcf\xb0\x86\x86\xda\x0b\xb9\xdd\xb1\x2a\xc1\x2e\x22\xc2\x59\x89\x57\x38\xec\xf9\x86\x0a\xb3\x62\x84\x8f\x9e\xe3\x59\x9c\x8c\xfc\x8b\x75\x9a\x97\x1e\xa4\x92\xed\xb4\x17\xaf\xd8\x01\x52\x7b\xf2\x15\x1c\x02\xea\x81\x38\xbc\x5f\xb8\xd2\xf1\xd6\xc0\x90\x9c\x12\xb3\x96\xea\xff\xf4\x01\x5a\x1a\x55\xb2\xfb\x50\x4a\x30\x19\x3c\x95\x35\x7f\x9d\xc6\x37\xc6\xf7\x7e\x21\x6e\x74\xa2\xf1\x11\x5c\x81\xe1\x54\xf3\x9e\x80\x81\xae\xbb\x78\x74\x88\x4c\xd1\xde\x13\xe2\x11\x40\x2d\x9c\x89\xff\x91\x36\xd3\x65\x4f\x8e\x6d\x38\x4e\x39\x94\xf2\x2d\x22\x93\x78\xa4\xfe\xa5\xac\xce\xf1\x24\x1e\xf9\xe8\x63\x8f\xbd\xf5\x76\xec\x2d\x01\x50\x3d\x99\x1a\xdf\xc0\xdd\xf8\xe7\xa6\x5e\xbb\x79\x70\xfe\x6c\x18\xd7\x5c\xac\x4f\xd5\x51\xa7\xf6\xd9\x5f\x33\x7b\x93\xf0\xb5\xbb\x60\x4e\xeb\xc7\x50\xdf\xae\xb6\x09\x19\xf6\x4d\x07\x56\x02\x6e\x0d\x4e\xe2\x6d\x98\x11\x3c\x51\xdf\x6d\x51\x5e\xd8\xdb\x62\xb3\x54\x78\x7d\xa9\xe4\xa0\xec\xf1\x15\x3b\xe1\xbf\xc4\xa8\x9e\x42\xc5\xd6\x1d\x12\x8d\xea\x57\x48\xf0\xbb\x76\x79\x03\x2f\x5d\xe9\xc8\xfd\x9f\x58\xe2\xa7\x32\x2e\x13\x7e\x9e\x79\x25\x05\xad\x52\xaf\x18\x97\xc5\xc8\xb3\x5b\xf4\x2f\x09\x8b\xd6\x5b\xaa\x64\x64\x0f\x2f\xfa\x96\x2a\xc1\x64\x46\x07\x4f\x9f\xae\x46\x62\xb2\x9a\xd2\x88\x64\xea\xcf\xce\x80\x14\xe6\x6f\x12\xd2\x7f\xcd\x3c\xfa\x93\x85\xe1\x08\x7b\x61\x8e\xc3\x50\x6a\xc9\x90\xe9\xc7\x39\xcb\x98\x64\x88\x79\xda\xce\x0f\x19\xf5\x77\x0f\xb5\x30\xcd\xfa\x18\x3b\x87\x17\x6f\x59\x22\x7e\xcf\xba\xe4\x24\xaf\x47\x82\x82\xb0\xda\x71\x23\xd1\xe1\x19\x6b\x9d\x04\x3d\xce\xe0\xca\x65\x77\xb8\x75\x02\x7d\x91\xd3\x1f\x24\xb9\xce\x51\x46\xaf\x72\x7b\x57\x6c\x0c\x97\x52\xc1\x01\xda\x28\x48\x79\x27\xc3\x05\x5d\x17\xea\x57\x9c\xf5\xeb\xd9\x84\xf1\xb9\x9f\x78\xc4\xe7\xa5\xbe\xbd\x67\x71\xba\x40\x85\x92\xad\xb3\x06\x80\x62\x18\x16\xce\xd0\x28\x65\x37\x9b\xcd\x4d\xca\xe7\xe2\x86\xa0\x19\x2d\xc0\x5b\xd5\x56\xa6\x0a\xfa\xbf\x91\x71\x6a\xa4\xb3\x7e\x9e\xf0\x73\xf6\x12\xdc\x39\xd6\xea\x5c\x98\xf0\xd9\x85\xc8\xb5\xd9\xac\xfb\x79\xbc\x58\x14\x4c\x92\x15\x9d\x69\xc7\x37\xc8\x9e\xd9\x5f\x3a\x17\xae\x0b\x0a\x67\xff\x49\x56\xee\xd1\xc3\x97\xa9\x1b\xd8\x9b\x23\x25\x59\x28\xda\x58\xaa\x7f\x2e\x68\x44\xae\x68\x44\xae\x69\x46\x4c\x60\x04\xe9\x6c\x7f\x2d\x6d\xde\x8d\xae\x75\xd4\xe4\x48\x3b\x73\xab\x6d\xef\xda\x7d\x6d\xb3\x41\x0b\x3a\xef\x25\x98\xa8\x52\x2b\x5d\x6a\xd6\x52\x6a\x49\xe7\xbd\x19\x26\xea\xb0\x5a\xa5\x87\x21\x9a\xf7\xcc\x6f\x30\x9a\x32\x16\x74\x15\x6a\xdf\x1d\xbd\xf6\xf1\xa2\x47\xf8\x9c\x5e\x93\x6b\x7a\x37\xf2\x4c\x94\xaf\xd5\xb9\xcd\x98\xd7\xc2\x75\xc2\x39\x85\x8b\x81\x5e\xef\x82\x6a\xbc\xf1\x05\x9d\x63\x72\xae\xb1\xbf\x7b\xbd\x2b\xaa\x21\x1c\x96\x2a\xd5\xff\x90\xa2\xd9\x13\xcb\x9f\xf5\xad\xd0\x39\x45\xd7\xf4\x1c\x7b\xd6\xb5\xe5\x35\xbd\x2b\x0b\x0a\x2a\xdf\xc5\x66\x03\x7f\x97\x06\x19\x4e\x13\xdb\x02\xa8\x6b\x69\x94\xb8\x66\x16\x0a\x35\x84\xa6\x40\x04\x05\xa2\x7a\x81\xdf\x73\xba\x86\x09\x66\xf3\xa3\x8c\x5d\xc5\x19\x71\xd4\xf9\x49\x51\x4d\x5c\x94\xe4\x07\x49\xbb\x83\xba\x45\x0b\x79\x93\xd1\x5c\x09\x40\x8a\x20\x3e\x14\xbe\x6b\x4f\xc5\x89\xdf\x34\x45\xc4\xdd\xdd\x08\xe3\xd1\x97\x02\xbd\x81\xbb\xfc\x37\x19\x7d\xe3\x23\x10\x96\xf5\xdd\xe0\x4d\x86\x47\xf6\xa3\xfe\xe7\x00\x8b\x98\xba\x8b\xa6\x37\x56\x55\x7e\xa6\x6a\xd3\x80\x59\xe9\x02\x0d\xf6\xc3\x33\x80\xf6\x7d\xe3\xc1\x03\x82\x63\xc9\x60\x78\x10\x9e\xe9\x57\x6e\xd4\x2b\x35\xd9\xcd\x54\x7a\xa3\xf3\x6f\xe9\x0d\xf8\xc9\x9b\xd4\xdb\x7b\xce\x35\xe3\x5b\xed\x1f\x1f\xdf\xd6\x58\x06\x2e\xad\x75\xe4\x20\xda\x85\x6f\x1a\x7d\xd5\x59\x86\xde\x64\xaa\xff\xee\x66\x60\xd7\xbf\x0e\xdc\x6f\x2b\x40\x2e\x55\x9a\x27\xdd\xaa\xe1\xa9\xdd\x2b\x0e\xf7\x62\xef\x85\x41\x34\x7c\xdc\xc8\x3f\x68\xe6\x7f\xad\xce\xbd\xf8\x2b\x05\x0e\xe2\xa3\x0c\x65\xa4\x80\xb9\x52\x03\x76\x44\x0b\x6f\x3c\xcf\x33\x54\x38\x5a\x3f\x0a\xc3\xf3\x0c\x1d\xe1\x72\x7b\xda\xff\x67\x68\x27\x5d\xa0\x5b\xfa\x7b\x4e\x6e\x80\x5f\x93\x33\x7a\xdb\xf7\x28\x9d\x64\xf4\xb6\x5f\xa7\x75\x72\xd3\xa5\xf4\x2c\x54\x74\x73\x56\xe7\xc2\x61\x78\x91\xa3\x46\x5a\x7f\x6e\x1e\x0c\x60\x3b\x39\xc3\x78\x6d\x3e\x9f\x85\xe1\x75\x8e\xce\x94\xe0\x7b\x43\x81\xfe\x72\x49\xaa\x1b\x94\x5b\x9a\xf5\x19\x07\x40\x91\x5b\x7a\xe3\x20\xe4\xfd\x5d\xe4\x6c\x8c\xce\x1a\xbb\x07\xbd\x21\x67\xb5\xbd\x43\x9b\xe0\x5d\xa5\x1c\xdd\x92\x33\x6d\xe8\x6a\x39\x19\x8e\xd1\x2d\x45\x37\xb4\xd1\xe6\xcd\x66\x5e\xed\x2b\x37\x6d\xfb\x0a\x6e\xec\x29\xe8\x96\xde\x36\xb6\x15\x52\xd0\x33\x3f\x46\x82\xf9\x26\x39\xaa\xda\x63\xbb\x5c\x60\x92\x51\xd7\x6f\xe8\xf4\xf8\x28\xf6\x8a\x31\x3e\x57\x85\xba\xb7\x7d\x76\x2b\x19\x9f\x87\xe1\xd1\x33\xc0\xcb\xa6\x19\xc9\xe8\x11\x39\xa2\x85\xfa\xde\x32\x47\x67\xe4\x08\x93\x44\x3f\x65\x98\x14\x61\xa8\x58\xec\x40\xad\x4a\x6f\x7f\xdb\x6c\x6e\xbd\xdd\x4d\xed\x20\xc0\xe5\xab\x64\xbd\x8f\x41\x86\x80\x47\x95\xe5\xf6\xbb\xae\x0d\x5b\xe0\x52\x5d\xf9\xc4\x94\x57\x93\x86\x6e\xe8\x8d\x41\x31\x00\xc2\x41\x18\x3c\x9b\x61\x96\x90\xfe\x22\xb1\xf5\x63\x72\x6b\xdc\x1e\x9e\x67\x19\x94\x2e\x10\x26\x47\xcf\xb2\x31\xba\xed\x27\xf3\xb9\xae\xe0\x46\x15\xd3\x43\x80\x74\x0b\x88\xfb\x20\x8e\xd1\x8d\xaa\xfe\xa8\x25\x8f\xd4\xea\x50\xff\x91\x1b\x3a\xd1\x00\x55\xb7\xf4\x6c\xa4\x66\xaf\xda\x44\x46\x58\x6d\x1b\xb7\xde\x46\x78\xa3\x4d\x5d\x1c\x80\xcc\x2d\xc9\xd8\x42\xc6\xb7\x7d\x8d\xc6\xf3\x8e\x2d\x24\x91\x62\xe9\x12\x3e\x8b\x65\xa9\xaf\x16\x5a\xf8\xe0\x99\x1e\x32\xb5\x7a\x8c\xeb\x3c\x39\xa3\xd1\xe8\xec\xe9\x8d\x35\x51\x3f\xeb\xf5\xb0\x22\xf9\xc9\xd9\x14\x5b\xc0\x03\xef\x53\xf4\xb6\xaf\x3e\xaf\x86\xa2\x96\xf7\x59\x2c\xe9\x6d\x5f\x8a\x65\xa9\xb6\xa2\xee\x8b\x9c\xfc\x9e\xd3\x17\xb9\xb3\x1f\xb2\x3c\x77\x6b\x9b\x38\x6b\xd9\x26\x2e\x6b\xdb\xc4\xee\x7e\x78\x19\x86\x17\x19\x3a\x23\x4d\x46\x07\x1b\xc5\x25\x5e\xdf\x18\x0a\x06\x06\x77\xa2\xde\xae\x43\xa7\x9c\xe8\x7a\x5f\x52\x7f\xa7\x19\xbd\x81\x7b\x5c\x72\x43\x5f\xb6\x05\x07\x3f\x19\x9f\xa0\x1b\x1c\x9f\xb8\xb6\xdf\x94\xff\x6b\x7c\xd1\x5a\xbf\xbe\x12\xfa\x7e\x47\x68\x81\xc0\x1b\x47\xd5\xb9\xbf\x67\xd8\x19\xc2\x32\xf2\x4b\x46\xa5\x96\x54\xd5\xb0\xc2\x30\x7b\xe3\x2a\xeb\xdf\x24\x6f\xb6\x71\x85\x0f\x42\xb7\xf7\x84\x08\xa9\x39\xc0\x75\xf0\xcf\xcb\x26\x88\xaf\xea\x8a\xb4\x36\x3a\x60\xd0\xe0\x9f\x9b\xd4\x32\x34\x06\xbb\xc6\x2a\x65\xac\x4e\x10\x79\x31\xe6\x45\xaf\x17\x23\x6b\x83\xc9\x70\xcc\xf5\xf1\xce\xf7\x6a\xfd\x46\x87\xf3\x4f\x42\xb4\x7b\x9b\xab\x0c\x74\x29\x08\xb7\x01\xe1\xf6\xf7\xf4\x05\x28\x77\xca\x65\x73\xdd\xe3\xb9\xa2\xa7\x0b\xe4\xe9\x93\xff\xb0\x13\xa9\x8d\x90\x19\xfd\x21\x73\x96\xc8\x0e\xcc\xc8\x19\x74\x6e\x36\x3f\xd8\x20\x57\xd5\x59\xfa\x43\xf3\x9a\xcc\xd1\x38\xab\xcb\x35\x45\xe1\x2e\x8b\xb2\x62\xb3\x41\xba\x5a\x3b\x21\x78\xfc\xbd\x92\x92\x48\x06\x83\xaa\xc4\xbb\x08\xc7\xa0\xdf\xd1\x34\x1c\x86\x60\x6d\xfe\x26\xc3\x61\xb8\x5d\xd2\xda\x66\xb9\x45\x05\x98\xe8\x8f\xf7\x43\xc5\x29\x97\xe6\x45\xb8\x07\x7b\x3c\x18\x86\x12\x6f\x36\x7f\xcf\x36\x1b\xf4\x77\xc0\x9c\xfa\x43\xa0\xc3\x27\x04\x6d\x83\x3d\x9d\x5a\x84\xce\x52\xb1\xb4\x6d\xa2\x76\x63\xa0\x0a\xaa\xe5\x71\xa8\x4e\x00\xbf\x64\xb6\xfb\x87\x4f\x9e\xfe\x92\x8d\x0f\x9f\xc4\xbf\x64\x76\x2c\xb5\x21\xf7\x1b\x81\x18\x79\x5e\x58\x2f\xa2\xee\xa0\xaa\xea\xbd\xb9\x9a\xf8\xde\x20\xba\x49\xb5\x9e\xfe\x74\x63\xab\xfa\xde\x5a\x85\x79\xf1\xdf\x53\xdf\x73\xd3\x55\x33\x93\xbf\x66\xd8\xf6\xc1\x20\x4c\xfd\x0a\xd7\x1d\xd6\x70\xfd\xfe\x5b\x94\xdd\x81\x9b\x35\x73\x73\xbc\x3b\xb4\xb7\x2a\xc5\x08\x8c\xdc\xbd\x58\x74\xd1\x28\x7f\xca\x2d\x03\xcf\x9d\x8f\x91\xa0\x7c\x92\x4f\x49\xa2\xfe\xf4\x06\x53\x92\x51\xe1\x63\x1c\x88\xa6\x73\x57\x5b\xe0\x21\x58\x5b\x59\xfb\xe1\x21\xb9\x8f\xcf\x25\x80\x7c\xa0\x2d\x03\xbe\xcf\x8c\x65\x7e\x6b\x33\x1b\x4d\x1c\x59\x18\xd7\x82\x0a\x8b\x41\x54\x35\xb3\xf8\xb7\x9b\x51\x78\x26\x25\xde\xcd\x82\x5d\x94\xc5\x08\x33\x25\x86\x54\xec\xb1\x68\xe1\x8e\x85\x63\x8e\x45\x9d\x2f\x16\x5b\x7c\xb1\xa0\x8e\x3f\x1c\x67\x54\x82\xc9\x07\xe9\x7a\xca\xfe\x77\xce\x30\x7d\x0e\xd1\xe8\x29\x68\x76\x24\x4d\xe1\xb2\x19\x93\x01\xc6\x2a\xd1\x83\x4b\xb6\xc6\xe8\x03\x50\xe9\x81\x09\xfa\xc0\x99\xd3\x48\x9f\x08\x0d\xf0\x97\x01\x77\x32\x61\x5c\xe1\x83\xa0\x58\x70\x5b\x84\xbd\xa4\xdb\x36\xdc\x30\x6f\x1a\x60\x81\x77\x00\xb1\x44\x2c\xee\x83\x62\x92\x83\xaf\x60\xcc\xb4\x50\x12\x7f\x18\x7e\x6e\xb3\x69\xc5\x12\xfd\x46\xa5\x52\x8e\xb1\x25\xf9\x99\x1a\x41\xa6\x06\x12\x16\xf3\x00\x0e\x19\xf3\x04\x71\x22\x30\x11\xf5\x21\xe5\x6a\x48\xb9\x1a\x52\xfc\xb3\x54\x0f\xaa\xcc\x12\x82\x31\x57\x26\x9b\xff\x69\xbb\xc0\x30\xa8\x0d\x4d\x8e\xf8\x90\xbf\x56\x01\xe5\xd9\x95\x54\x33\xfa\xaa\x68\x3a\xa1\x57\xca\xe2\x2a\xd8\x57\x6e\xaf\xea\xa4\xa3\x9d\xaf\xd9\x3b\x72\x62\xd5\x4f\xe8\x34\x73\x46\x97\x48\xfb\x31\x68\xac\x0b\xb8\x60\x76\x76\x99\xa7\x99\x2a\x73\x9a\x85\xe1\xe3\x28\x7a\x06\x56\x86\x3f\x67\x63\x63\xe2\x15\xbf\xc8\x36\x94\x3b\x92\xac\xda\xff\xba\xa6\x0a\x6b\xba\x68\x69\xcd\x1c\xf7\x5a\xaf\x9d\x51\x22\x45\xe8\xc6\x99\x46\x3a\x67\x9a\xb1\xa4\x83\x58\xab\x4a\xa4\xfa\x51\xf3\x9f\x89\xb7\xbd\x67\x28\xd4\xf5\x42\x56\x7d\xf8\x57\x52\x60\xed\xd7\xb2\x37\x38\xdc\xdb\x8d\xf6\x30\xa0\x82\xb6\x2d\x36\x59\x2d\x36\xe9\x4c\x67\x6b\x91\xc4\x5f\x14\x15\xac\x24\xc0\x06\xca\xe4\x9c\x32\x02\x8f\x97\xec\x8e\x72\xfd\xe8\x60\xe0\x01\x59\x10\x60\x50\xe0\xd1\x46\x51\x85\x32\x8e\x89\xe8\x8a\xee\x96\xe6\xc9\x87\x1d\xd3\x28\xec\x2a\x35\xe5\x73\x76\x4b\x23\x62\xea\x59\x78\x59\xf5\x90\xe3\x3a\xad\x06\xb7\x02\x29\x75\xeb\x12\x48\xf2\x6d\x2a\x6a\x65\x3c\x08\x15\x9d\x0e\x21\x61\xf4\xb3\xc6\x09\x37\x0d\xf1\xd5\x2a\x90\xe9\xab\x5d\x54\x42\x93\xaf\x56\x23\x62\xec\xfa\x74\x2d\xfa\x52\x1d\x7e\xd4\x61\x64\xaa\xa1\xff\xdd\x1b\x7a\xab\x4f\x60\x37\xfe\x8c\x54\x65\x7f\x2e\x2a\x34\x97\x2e\xea\x82\x73\xd6\x32\x17\x52\x18\x1b\x84\x2e\xeb\xa7\x85\xf6\x81\xb3\x0b\xd5\x7b\xfb\xbb\x06\xfd\x56\x62\x9b\xa7\xc7\x30\xe1\xf0\x38\x55\xed\x82\x83\x85\x24\x4c\xd1\x00\xb1\xa4\x5b\x9b\x48\xe6\xff\x22\x9a\x3b\x1a\x8c\x4e\xc2\xfd\xc0\x71\x35\xa4\x97\x6a\x2c\x18\xa9\x01\xec\xe0\x18\xf1\xe6\xbc\x37\x2b\xb5\x13\xc5\xb7\x26\x81\x6f\x23\xef\xf0\xa6\xfa\x0a\x93\x9a\x36\xd1\x77\xee\x21\x36\xf0\xbf\x0d\x7d\x61\x4a\xda\x42\x4d\xe8\xb6\x2d\xd8\xc7\x86\x7e\x74\x2b\x96\x4f\x0d\xaa\xae\xee\x17\x4a\x64\x23\xf4\x32\xe1\xad\x31\x3a\x64\x2d\x46\x87\x6c\x8b\xd1\x21\xeb\x31\x3a\xbc\xd8\x07\xcc\x8b\xb5\xad\xd7\x1d\xd3\x7f\x21\xa4\xf2\x42\x43\x75\xfa\x78\xac\x3f\x16\xdb\x71\xf3\x33\x3a\xd4\xd0\x52\xac\x4d\xd2\x62\xf8\x67\xad\x72\x41\x19\x1d\x78\xbb\x4f\x33\x82\x1a\xc3\x19\x7d\x6c\x35\x12\x0d\x3f\x96\x13\xeb\x30\xf2\x53\x61\x7d\xaa\x72\xc6\x55\x0b\x88\x75\xd8\x7d\x17\x67\xf4\x80\x08\xb0\x44\xf0\x6e\x09\x5f\xba\x64\x3f\xf5\x37\x53\x1f\x62\x8a\xa8\x07\x43\xc2\x89\x24\x07\x1b\xd1\x20\xe5\xdf\x88\x26\x31\x78\xd0\x84\x90\xd8\x10\x04\x9f\xeb\x55\xec\x42\x15\xaa\x02\x78\xe1\x33\xa9\x2d\x03\xf8\xdd\xa8\xe0\x43\xbd\x82\x43\x57\x81\xff\xde\x87\xed\xf7\xbe\xd8\xb1\x78\x03\xfb\xb9\x37\x04\xaf\x6a\x35\x0e\xf7\x5a\x6b\x7c\x55\xab\xd1\x5a\xaf\xab\x09\x69\x1a\x15\x7a\x71\x2c\xaa\x48\xd6\x16\xec\xd8\x4c\xcc\xc7\x38\xa3\x83\xa8\x6e\xb3\xf3\x29\xce\xe8\x61\x3d\xe9\x58\x15\x6b\x80\xa2\x9c\xaa\xb4\xbd\x7a\xda\x7b\x95\xb6\x4f\xf2\x9a\x1a\x47\x67\xbd\x8d\x33\x3a\x1c\x3a\xd5\x4e\x43\x49\xba\x1b\x19\x63\x0a\x36\x66\xb1\x6d\x3f\x09\x02\x6c\x0f\x5b\x48\xaa\x31\xc9\x5a\x87\x84\x11\x8d\xad\xa0\xf8\xbe\x1b\x1b\xcf\x40\xf9\xa7\x2d\x7e\xac\x47\xf8\x09\x61\x24\x57\x5b\xa9\x8b\xfc\xe5\x59\xc9\xbc\xb9\xe7\xa5\xe1\xae\x7b\xcb\x6f\xc3\x17\x37\x2d\xb5\x5a\xfe\x70\x02\x92\x5f\xc7\x3e\xd1\x30\x03\xf7\x7d\xfb\x87\xe6\x5b\xd0\xf9\x3d\x52\x8f\x0f\x9d\x33\x3e\xae\x1e\xe3\xc9\xd4\x70\x75\xbf\x52\x3f\x50\xda\xba\x66\x2d\x1f\x37\x41\x50\x6c\x6c\x6a\x5b\x1f\x34\x30\xbd\x5a\xea\x4e\x82\x5e\x37\x66\xfd\x7a\x42\xe9\x0f\xf3\x3f\x5c\xab\x9d\xbc\x61\xb6\xf8\xda\x87\xac\x10\x52\x53\xac\x6b\xe9\xc0\x59\x13\xea\xb7\xcc\x95\x92\x2f\x39\xd8\xd6\x79\x5b\xf4\x96\x25\x78\xad\xbc\x89\xb4\xed\x9a\x61\xc3\x6e\xeb\x52\xd6\x9f\xc0\x08\x43\xdb\x0e\x86\xb5\xe4\xca\xc7\x50\xa7\x57\xfa\x6f\xfa\xbb\x44\x11\x36\xa9\x75\x35\xb8\xca\xda\x19\xd8\xbc\x9a\x86\x9d\xd6\xc6\xc1\x4b\x6a\xaa\xe7\x69\x55\x71\xad\x9c\xaf\xe8\xd7\x92\x5a\xdd\x18\xc0\x1f\x89\x77\xbe\xe4\x52\xd3\xe9\xfb\x8d\x37\x5f\x3e\x81\x70\x21\x47\xc9\x39\xcb\x1d\x48\xfb\xab\x44\x26\x0d\x41\xe7\xef\x0d\xf1\x7f\xf7\x69\x92\x9f\x83\x8a\xa0\x30\xa7\xe9\x30\x74\xb6\xb8\x2e\x6b\xb2\x3b\x1d\xfb\x3f\x74\xec\x16\x13\xb0\xc4\xf2\xa7\xf8\x92\x5c\x32\x0d\xa5\x49\x69\xae\xb7\xc8\x20\xe8\xe5\xc4\xd1\x3b\x23\x75\x7a\x96\x4d\x62\xf5\x0f\x2a\xbf\x16\xf5\x10\x1b\x82\x3a\xe0\x69\x92\x68\x09\x3b\xa3\xb3\x02\xa9\xe3\x15\x40\x6a\xe0\xb5\x8c\xd5\x71\xf3\x1f\xcc\x83\x02\xb3\xb0\xb7\x05\xd6\x11\x42\x07\xd6\x9e\x6a\xcb\xe6\xc3\xde\x6d\x15\x94\x7b\xb6\x95\x45\xcd\xb6\xb2\xa0\x45\x03\x91\x88\xdd\x5a\x5b\x55\xe9\x41\x30\x9e\x0b\xa4\x85\x6e\x8c\xd7\xf5\x77\x1a\x68\xbc\xef\x8d\x68\xf2\x9e\xe5\xe7\x4c\x63\x76\xbd\xac\xd7\x5a\x96\xaa\x82\x36\x3b\xc5\x02\x8f\x9a\x7d\x18\x60\xdc\x72\xa4\x5e\x19\x78\xe1\x91\x6e\xd9\x0a\x30\xe4\x6e\x04\xe2\x64\x45\x0a\xcf\x20\x92\xd3\xc2\x3a\xfc\x2c\x44\x43\x1c\x95\xb6\xb7\x63\x59\x2d\xca\x58\x6e\x85\xc7\x27\x48\xd2\x59\x82\x12\x92\x61\xbc\x0d\x58\xcf\x4a\x77\x2a\xca\x2b\x45\x91\xa1\x15\x13\x85\xd3\x81\xb3\xe7\x98\xcc\x13\x24\x88\xc4\x64\x5e\x20\x41\x32\x92\x60\xe2\x91\xf2\x2f\x9e\x1c\xae\xe1\xcc\x8c\x35\x8f\x66\xb0\x63\xc4\x2a\x90\x61\x0b\x18\xe9\xc1\xa0\x34\x9c\xbe\xbe\xaf\x6e\x3a\x7c\x88\xb4\x36\x84\x8c\x26\xa6\xc6\xda\xbb\xfd\xc8\xef\xd4\xaa\x1d\x79\xcf\x34\x32\x87\xd2\xa7\x72\xcc\x63\xff\x32\x93\xad\xcc\x0d\xa4\xf1\x66\x82\x0f\xfa\xce\xec\xdf\x37\x0f\xbf\x72\x55\x5f\xbd\xba\x35\xce\x2a\xd5\xc2\xb9\xa4\x82\x1f\x43\x48\x98\x42\x9d\x85\x9b\x69\x75\x8e\x61\xee\x8a\x41\xc1\x01\xb6\xdd\x76\x4f\xb0\x55\x77\xc1\x69\xd6\xf2\x5d\x4c\x60\x63\xdb\x25\xce\x3f\x82\x0c\x41\x22\x7e\x12\x6b\x50\x82\xdd\x38\x02\xe9\xde\xee\x04\xb5\xfd\x8c\x93\x02\xe2\x42\xb2\xc9\xf7\xf9\x94\xba\x52\xe4\x43\x0e\x58\x80\xac\x82\x1a\x63\x9e\x1e\x2b\x06\x17\xc9\x2a\x1c\x7f\x2d\x1a\xbf\xe1\x0d\x48\xd2\x7c\xc2\xa6\xb8\x7f\x7a\xce\xe4\x4f\x2c\x2f\x52\xc1\x47\x82\x0a\x24\xfb\xa7\x3a\x92\x92\xf5\x04\xe7\x5f\xe3\x98\xe3\xaf\x96\xa0\x13\x49\xc4\x34\xfe\x6a\x39\x7b\x11\x2c\x70\x09\xac\xfa\x34\x35\xcb\xfe\x93\x10\x92\x7a\x22\x3e\x5f\xd5\x8e\x94\x4c\xf3\x29\xe6\x69\xee\x0e\x1b\xbf\x07\xcd\x02\xe8\xa0\x96\xb0\xd9\x04\x1d\xe0\x34\x3b\x00\xc6\xba\xb3\x14\x29\x97\x3b\xd6\x91\xa2\x13\xb8\xc2\x3f\xe9\x98\xbe\x55\x5b\xf2\x55\x75\xdc\xb0\xc1\x8d\x5a\x81\x15\x21\xc4\x91\x2e\x91\xd2\xa4\xde\xb9\x7b\x2e\xee\x84\x3d\xbd\x88\x91\xf0\x83\x2f\xe8\x0b\xed\x5f\x0a\x94\xe2\x51\x06\x1c\x00\x31\x5c\x96\xbf\x16\x48\x92\x94\x30\x35\x80\xd6\xa8\xf2\x9e\xc6\x34\x22\x58\xa5\x0b\x24\x37\x1b\x24\xa9\x3a\xa0\x4b\xca\xc6\x87\x4d\xf2\x6a\xa8\xf3\x63\x3f\x62\xbc\xc6\x37\xd3\x93\x20\xbd\x21\xed\xca\xfe\x45\x52\x78\xe1\x91\xe7\x89\x4c\x76\xa0\x31\xb9\x10\x32\xc0\x18\x93\xae\xc4\xee\x42\x74\xc4\x8d\xe5\x26\xd4\x3a\xc2\x75\xd0\x3c\xee\x8c\x29\xd5\xb2\x83\xa5\x1d\x11\x39\x5e\x9b\x95\x16\x77\xa3\xd2\x06\xc5\x2e\x35\x26\xd8\xd6\x30\x93\xfb\xc7\xb8\x78\x68\x8c\x8b\x6a\x8c\xef\x8a\x5a\x5c\x30\x7f\xc8\x9d\x24\xdf\x81\xb7\x2a\x12\x11\x2b\xff\x0e\x63\xf8\x6d\x22\xc4\xd0\x17\x21\x86\x46\x84\x48\x17\xa8\xcb\x57\x48\x6e\x05\xa5\x8b\xa2\xca\xba\xfc\xef\x15\x47\x22\x1c\x97\x3f\x65\x8d\x30\x2c\x96\x1b\x9a\x93\x84\xa7\xab\x65\x18\x0c\x42\x6b\x17\x04\x30\xa7\xfe\xed\xc6\x66\x73\x21\xdc\xde\xf1\x2e\xa5\xdd\xa8\x8a\x1f\x4b\x29\xe2\x61\x8e\x1d\xca\xc3\x3b\xf0\x56\x93\x35\xa1\xe0\x4d\xaa\x58\xda\x1f\x5b\xae\x83\xcf\x93\x06\xbe\x31\x04\xfe\x93\x36\xf0\xdf\xad\xd8\x82\x3f\x7e\x9f\xa0\x1a\xbf\x6c\x38\xcb\x36\xfd\x0a\xb7\x02\x0e\xeb\xa8\x2a\x56\x58\x82\x3b\xf2\x53\x2b\xa4\xcc\x04\xfa\x45\x10\xd1\x3f\x35\x3d\xd5\xeb\xbe\x99\x50\x8b\x85\xdf\x19\xf8\x28\xff\x4d\xb4\x28\x4f\x67\xc9\x43\x03\xf9\xe5\xdd\xe3\xe0\xf1\xaf\xa9\x99\x9e\x18\x6d\x47\x23\xad\xae\x47\x25\xe5\x16\x5b\x14\x8f\x9d\xe9\x72\x6c\xa2\x12\x6f\xbf\x58\x6b\x20\x44\x15\xce\x69\xad\x11\xfa\xf3\xa4\x19\xe9\x57\xcd\x67\x6e\x5b\x2d\xed\x27\x47\x5e\x44\x4e\xdf\x8a\x5a\xb4\xa0\x63\x21\xe1\xc7\xc4\x04\x18\x28\x13\x16\x53\x3f\x6f\x5d\x72\xe9\xd6\xfb\x9d\xce\x8d\xc5\xdf\x56\xf8\xeb\x6d\xf0\x33\xe9\x6e\x2e\x7f\xb7\x03\xe9\x62\x76\xda\xd6\x97\xef\x52\xed\xbe\xb7\xbf\x7b\x50\x75\x55\x0b\x71\x40\xaa\x0e\xe5\xb9\xba\x06\xf5\x68\x77\xa8\x47\xcf\x06\x34\xf1\xad\xcf\x1b\x78\xdb\x72\x3b\xc1\xda\x9f\x63\xc2\x1a\x0b\x8a\x08\x7a\x2d\x90\x24\xcb\x6a\x59\x91\x24\x01\x94\x73\x22\x68\x9a\x6a\x73\x71\x49\x72\xc5\x66\x54\x62\x15\x5f\x9d\x6c\x5d\x89\x08\x27\x73\xb5\x2b\xf1\xed\x9c\x58\x9e\x03\xe0\x9b\xd5\x95\x09\xe0\x34\x82\x87\x5d\x33\x34\x86\xed\xc7\x96\xaf\xe4\xb9\x40\x39\xb6\x3b\x5f\x37\x1a\xc1\x42\xd5\x63\x0a\x70\xb6\x6d\xf5\x00\xa0\x68\xa1\xa1\xf0\x2a\x9c\x77\x9d\x32\x36\x7f\xf5\xf1\x1c\x04\xa0\x91\xde\x05\xf3\x36\x15\x96\xf6\x88\x6c\xd3\x9f\x86\xe1\xb5\x1a\xc5\x9c\x80\xe9\x87\x30\x2d\xcf\xe9\x79\x52\x13\xb2\x60\x95\xd7\x0f\x3f\x54\x92\x5b\xfd\x2a\x00\x49\x48\xfa\x93\x37\x09\xdd\x88\x24\x8a\x96\x4c\x70\x1f\x35\x58\x11\xf9\xe2\x0a\xe8\x19\x72\x91\x20\x2d\x75\x9a\x05\xb8\x1f\xab\x95\xe2\x5d\xab\x8c\x58\xec\xe2\xcf\xfc\x37\x12\x14\x4a\xa8\x50\x7b\x5f\x2a\x31\x12\xfd\x53\x73\xb2\xc0\xf6\x1a\x49\x90\x84\xea\xa6\xfb\xd0\x3c\xed\x42\x88\x63\x5d\x70\x49\x3a\x1e\xc4\x51\xb5\x63\xe8\x97\x40\x10\x77\x34\x44\x29\x3d\x76\xb0\x6b\x03\xed\xf1\x43\xe9\xa9\x4b\xda\xb3\xcb\x72\x58\x22\xa1\x1a\xff\xab\x40\x42\xcd\x50\xe2\x30\x4d\x24\xfd\xce\x1b\x4f\xe6\x60\x2d\x2a\x9f\x3b\x49\x7f\x7c\xb8\x84\x2a\xf2\xea\xe1\x22\x7b\xb1\xa4\xaf\xbd\x22\xaa\x1d\x26\xf6\x34\x26\xb9\x57\xbe\x71\x95\xb7\x1b\xed\x13\xe1\xdf\xdc\xd9\xd9\xad\x62\xac\x5a\x1e\x21\x9a\x33\xf3\x9d\xe6\x4d\x80\xf6\xdc\x88\x69\x93\x8f\x45\xfc\xab\x40\x39\x80\xee\xe2\x46\xf0\x9c\xfb\x6b\xfc\xf1\xcf\xd5\x08\x5b\x94\xde\x82\xf3\x3a\x46\xab\x73\xa6\x73\xd6\x30\xf9\x56\xe8\xdb\xa1\x06\xb3\xc8\xb7\x09\xee\xfe\x8d\x60\x2c\xfa\x7e\x00\x36\xb2\x4a\x0c\x18\x85\x5e\x61\x46\x4c\x21\xdb\xd1\xed\xed\x6b\x8a\xa2\x04\x56\x02\x03\xf1\x36\x3f\x27\x74\xa0\x44\x7f\x75\x1b\xb1\x53\xed\x41\x2f\x12\xfa\xc7\x03\x41\xa2\x7c\x3b\x76\xf2\x3a\x01\x08\xee\xdf\x15\x1b\x03\x72\xac\xf0\x71\x19\x15\x5f\x3b\xbd\x68\x60\x70\x8d\x3a\xcb\x6a\xa8\xb3\x28\xa1\x6c\x22\xd4\x61\xeb\x46\xe4\x97\x6f\xf9\xc7\x5c\x9c\xe7\xac\x28\xcc\xb9\xeb\x63\x9e\x5e\x25\xf9\x9d\x2a\xd3\x1b\x4c\xc9\x0f\xe6\x1c\x94\x68\x4b\x42\x4e\x3f\x26\x06\xd1\x13\x88\xd2\x85\xb1\xe6\x23\x3e\xc2\x56\xb3\xb4\xb3\x6b\x11\xef\x37\x83\x68\xb8\x57\x0b\x2a\x02\x8c\xea\x8b\x25\x13\x6e\x64\x2f\xc7\xa2\x1a\x44\xec\x90\xb2\x40\x1e\x73\x44\x11\x86\x3f\x26\x96\x68\xda\x09\x31\xb9\x1f\x1c\x58\xfb\xd4\x5b\x9c\xe8\x9c\x71\xf2\x5d\x0e\x64\x39\xd6\xc2\x40\x5c\x85\xa5\x83\x8c\xa4\x16\x4c\x70\xb0\x8f\xc9\xcf\xa9\x26\x1a\xd3\x8d\xcc\x1b\x08\x6b\x15\x5e\xbf\x80\x71\x0d\x6e\x8b\xbc\xec\x44\xad\x46\xd0\xe4\xaf\x08\x94\x64\x8b\xee\x9d\xff\xa9\x9d\x94\xdf\x6a\x73\x15\xfb\xa3\x5e\x6b\xee\xe0\x1b\x56\xf6\xab\x3f\xb7\xb2\x2d\xb8\xb3\x9d\xea\x66\x53\x1b\x2d\x38\x70\xe8\x6a\x0f\xbd\x56\xcd\xd8\x56\x0f\xa2\x98\xc5\xeb\xbc\x29\x38\x6f\x77\x23\xdb\x0a\x8c\xa2\xf6\xa6\x4a\xf6\x2e\xb6\x64\xef\x74\x81\xb4\xf8\x5d\x34\xc5\xef\x46\x02\x4d\xac\x14\x06\x71\xf4\x0b\x9a\x99\x30\x81\xea\x20\x92\xd0\x55\x8e\x0a\x92\xe0\x71\x14\x47\x9b\x76\x5b\x92\xd3\x59\x92\xcd\x56\x59\x22\xd9\xcb\x8b\x84\x9f\xb3\xf9\x8b\x54\x16\xe3\x7b\xd2\xa1\xb2\xd8\xb9\x8e\xee\x1a\x27\xa7\xcc\x8d\x11\xa5\x1e\x89\x87\x61\xd7\x3b\x27\xad\x7d\xce\xe5\x6e\x10\x9d\x3d\x90\xe5\x9e\x85\x5d\x94\x60\x41\xe8\x4c\x14\xb0\x67\x2d\x65\xb1\x32\x6a\x9a\x56\xef\x0c\xb7\xc2\xeb\x8c\x9a\x79\x73\x76\x6a\x33\xba\xaa\x29\x58\x6d\x7d\x33\x6d\x71\x34\x73\x77\x94\x60\xcd\xa2\x44\xe4\x59\x5f\x9c\x15\x2c\xbf\xd6\x5d\x0f\x13\x8c\xd7\x03\x4a\x69\x61\xb0\xd7\xd1\xcc\x86\xba\x0c\x77\x6c\xb4\x4b\xc0\x5d\x28\xc8\x0c\xab\x79\x32\xfe\xe4\xdc\x9d\x5b\x66\xbe\xef\x83\xea\xde\xcc\x95\xc1\x44\x24\xae\xb7\x8a\xd0\x56\x2e\xcb\x3a\x60\xd3\x99\x86\x46\xd1\x43\x96\xd1\x41\x54\x35\xc6\xd8\x6b\x54\x51\x07\x15\x47\xb1\x23\x50\x0d\x4c\x86\x2d\x50\x0e\x2d\x2a\x4b\xac\x8c\x16\x76\x30\x32\x3d\x18\x70\x7d\xab\x06\xd1\x03\x4b\xf1\x4e\x3a\x8a\xc8\x9c\xbf\xe8\xda\xcd\x51\x56\x21\xa8\x14\xe6\xa5\xcc\x25\x96\x05\xcd\x4a\xb3\xbe\x44\x7d\x49\xdd\xc3\x85\x1d\x50\xab\x3d\x99\x92\x5c\x51\x74\x7d\x69\xe1\xaa\x2a\x7b\x5e\xc8\xa9\xda\x82\xd2\x04\x09\x92\x54\x38\x20\xfe\x54\xe2\xda\xf9\xe1\x7e\x06\xe5\x98\x62\x02\x02\x9a\x6d\x46\xa3\x05\xe4\xb5\xe9\x15\xd1\xc5\x74\xa1\xc4\xc8\x4f\x16\xe1\xd1\xd4\xf4\xc2\x72\x98\x96\x9a\xfc\x17\x9e\x7c\x9d\x37\x7e\x85\x25\xfe\xbb\x92\xb4\x3d\xfb\xc0\x99\x66\x8c\x18\xed\x46\x04\xce\x33\x38\x06\x48\x2e\x3b\xcc\x67\x5a\x76\x11\xd8\x9e\x13\x40\xea\x6f\x9c\x12\x58\xd5\x23\x37\x9d\xd5\x41\xfa\x9e\x63\x6c\x75\x78\x6d\x28\x2b\x1e\xef\x9b\xb3\x28\x2e\x89\x5c\x55\x16\x34\xe6\x3c\x57\x13\xe4\xb5\x2e\x68\xeb\x0a\xb5\xba\x84\x6e\xd6\xb1\xd2\x31\xa8\xb6\xef\xbf\x5a\x2a\x01\xa0\x49\x7f\x5f\x1c\xfd\x5a\x58\x8f\x66\xf8\x53\x8b\x9b\xaf\x6f\xae\xb5\xb5\x6e\x49\x98\xac\xb5\x73\xe0\x8c\x24\xc3\x10\x01\x60\xf0\x1e\x81\x98\x82\x04\xee\xfa\xf7\xa0\xaf\x5f\x7b\x65\xff\xc9\x20\x3a\x38\xd8\xaf\xbd\x69\xd3\x54\x05\x5c\x36\x0f\x39\x55\x1d\xd6\x55\x5b\x1b\xa0\x51\xc0\x91\x1e\x41\xad\x60\x0a\x0a\x75\x71\x5c\x96\x24\x97\x8d\x1b\x53\x3b\x9f\x08\x97\xe4\x37\xb6\x75\xc3\x66\xef\x11\xea\xb8\xff\x8a\x8d\xe8\xc8\x3c\x4a\x92\x85\x08\x06\xa4\x0a\x70\xc0\x6b\x01\x0e\x0c\x1c\x15\xa7\x3a\xee\x6f\xe5\xa4\xc2\x6b\x51\x7f\x8c\x8c\xc8\xfb\x7f\xac\x58\x7e\xa7\xfd\x90\x44\xfe\x3c\xcb\x90\xfe\xe8\x44\x7d\x84\x06\xbd\xef\x4f\x8e\x3f\xf4\xb5\x41\x4b\xba\xb8\x43\x41\xd0\x93\xb8\xf7\xd7\xe9\x04\x58\xa7\x69\xc3\xf4\xaf\xaa\x5d\xd1\x48\x56\xa6\xc2\xd2\xaa\x0c\x72\xca\x27\x12\x70\x75\x73\xbd\xb2\xf2\xfe\x42\xe4\x57\x1a\xb4\x40\xe4\x57\x56\xb1\x20\xd4\xca\x81\x7b\x4a\xd1\x38\x3d\x1c\x46\x18\x8f\x7e\x45\x39\x26\x9c\xc1\x32\x2d\xcb\xf2\xbe\x00\x08\xd5\x69\xad\x1e\x00\xc1\x48\xe3\x6a\xf0\x74\xe4\x82\x30\x4c\x55\xe9\x6e\x97\x57\x51\x05\x24\xe9\x0e\xd4\x9c\x9d\x32\x7a\x5e\x90\xf7\x6c\x2b\x0a\x75\x75\x51\x6f\x0c\xbc\xf7\x7c\x08\xb9\x37\x02\x1d\x1e\x10\xe6\x79\xea\xdb\x97\xb6\x91\xe5\x92\x26\xb2\x1c\x79\xcb\xfc\x45\x04\xc6\x92\x87\x1a\x73\xda\x5f\x16\xbe\xff\xb7\x5b\x6a\xc5\x48\x56\xd1\xd8\xb6\xc0\xf1\x21\xac\x5b\x1d\x73\x78\xb8\x17\xd6\xdd\x3e\x3c\x44\x3e\xb5\xdc\x54\x9b\x4a\x84\xc9\xa9\x5a\x18\x25\x79\xce\x1a\x34\x5c\x83\x47\x19\xfe\x79\x18\x3d\x8d\xfc\xba\xa2\xeb\xa3\x6b\xc6\x65\x11\x4f\xb8\x20\xb9\x20\x42\x90\xcf\x8c\x7c\x60\xe4\xb4\x20\x6b\x23\x00\xc5\xdd\x41\x39\x2d\x49\xba\xa2\xeb\x45\xca\xe7\xe0\x26\xf2\xe2\xee\x8d\x28\xe4\x5b\x13\x9f\x29\x96\x82\x9c\xad\xf8\x3c\x03\xe5\x41\x1c\x91\x6b\x7d\x3a\x8a\x83\xc1\x93\x7e\xd4\x1f\x06\x44\x33\x3a\x96\x7f\x4c\x66\x97\xc9\x39\xfb\x90\x5c\xb1\x38\xd0\x4a\x9b\xb9\xb8\x0a\x4a\x92\xad\xe8\xda\xab\x22\x5d\xf5\xab\x5f\xae\xba\x74\xd5\x37\x8f\xad\x15\xa6\xab\x7e\x4b\xb2\x2b\xfa\x52\xf0\x45\x7a\xee\x97\xd2\x29\x44\x5c\xb3\x3c\x4f\xe7\xec\x8d\x10\x97\x27\xd5\xf5\xd5\x56\xf2\x2b\xb0\xb4\xfd\x98\xc8\x8b\x7b\x0a\x7c\x62\x6a\xc5\x6e\x17\xf0\x4e\x52\xb5\xa4\xfb\x2a\x84\xcc\x66\x65\x05\x93\x16\x94\x49\x5b\x93\xe4\x26\x7d\x76\xc1\xe6\xab\xcc\xc4\xb7\xd5\x69\xb3\x66\xb4\x82\x4f\x6c\x11\xdf\x1b\xc9\x40\xcd\xaa\x3f\x9d\x2f\xee\x60\x8e\x63\x9f\x7e\xeb\x27\x34\xc4\xe8\x2f\x0c\x31\x8c\xb5\xc0\xe6\x19\x5b\x96\xe4\x3e\x1a\x49\x95\x18\xdb\x9a\xb5\xd9\x6c\x7b\x8a\xc0\xb6\xb3\xd5\xb2\xe2\xb5\x50\x5d\xc9\x59\x71\x51\xef\x7c\x7b\xa2\x10\xd2\x8d\x9d\x29\x51\x1b\xba\x73\x66\x47\x43\x77\x58\x07\x99\x4f\x17\x28\x58\xf1\x39\x5b\xa4\x9c\xcd\xab\x10\xe9\xa7\xa7\x9f\x8e\x9e\xbf\xfc\x7c\xfa\xea\xe8\xa7\xcf\xc7\xc7\xef\x4e\x4e\xff\xfe\xee\xf8\xc5\xf3\x77\xa7\x6f\x8e\x8f\x7f\x38\x3d\x35\x9a\xa8\x15\x7d\xb8\x18\x70\xd7\x62\xd5\x4f\x8b\x57\x69\xa1\xe4\xbb\x79\x18\x16\xab\x7e\xb1\x5a\x2e\x45\x2e\x0b\x68\x06\x98\xbe\x5f\x0a\xaa\x8a\xf1\xdf\xd9\x4c\xa2\x6c\x85\xc9\x89\x4a\x30\x86\xef\x57\x0c\xaf\xcb\x52\xf6\x4f\x4f\x4f\x8e\x5e\x7e\x3a\xfa\x7c\xfa\xf6\xc3\xe7\xa3\x4f\x1f\x9e\xbf\x3b\x39\x7d\x75\x7c\xfa\xe1\xf8\xf3\xe9\x8f\x27\x47\xa7\xc7\x9f\x4e\x7f\x3d\xfe\xf1\xf4\xe7\xb7\xef\xde\x9d\xbe\x38\x3a\x7d\xfd\xf6\xd3\xd1\x2b\x9a\xac\x94\xac\x08\x2e\x22\x1f\x45\x2e\x93\x8c\x0a\x95\xa2\x06\xfa\xd5\xf1\x7b\xb8\x54\x6d\xec\xb8\xc6\xf2\xad\x89\x3d\x32\xa8\x69\x19\x6d\x2e\x73\x78\xd6\x8d\x6b\x59\xf5\x8a\xbb\xb5\x96\xf7\xde\x57\x9a\xa5\xd9\xb4\x58\x39\x38\xc0\x4d\x0b\x90\xe1\xfe\x01\x39\x86\x0b\xf4\xfe\x25\xbb\x53\x9b\x7f\x75\xa7\x57\xa3\x52\xd9\x4a\xa5\x4a\x72\x5c\x15\x17\x27\x77\x7c\x76\x1f\x67\xad\xf0\x5a\xb8\x43\x97\x51\xd5\x79\x88\xa8\xe9\x02\xb9\xae\x6b\x98\x98\xda\xde\xe3\xed\x3a\x80\x36\x05\x4c\x5d\x7d\xdb\x5a\x76\x35\x45\x8f\x6f\xd2\x11\xe6\x2b\x07\x42\xa3\x44\x55\xae\x04\xad\x6d\x49\xf2\xdf\xad\x70\x60\x2a\x34\x62\xa5\xb3\xeb\x7e\x2e\xdb\x88\xa3\x0b\xea\xfc\x46\xe5\x7b\x55\xdd\xdd\x2e\x6b\x53\x61\x87\x21\x6a\x28\x63\x6d\x1b\x4c\x43\xba\x83\x9a\x28\xda\x5a\x89\xd9\x6f\x6b\x52\x2a\xc6\xa4\x1b\x99\xf6\x9b\x03\xd4\x19\x70\x39\x13\x36\xbc\x50\x62\x85\x97\x59\x5b\x09\xad\x52\xa2\x56\x00\x93\xff\x40\xf3\x5b\x6f\x8e\x9e\xa8\x93\xd5\x99\xcc\x19\x7b\xcb\xa5\x68\xd7\xeb\x6b\x63\x30\x33\xc2\xbc\x7d\xfa\xaa\xc5\xb9\xd9\xb8\xb5\xb5\xb5\xf2\x9a\x6e\x5e\x07\xb5\x89\xd7\x9f\xea\x0e\x48\x0e\xcd\x34\xdb\x2b\xb5\x1b\x77\x49\x76\x0f\x77\x1f\xc7\x86\x9c\xe8\xb3\x75\xb0\x2a\x58\x47\xc9\xa2\x33\x19\x8c\xba\x95\x7d\x8f\x16\x8c\xfe\x3c\xdf\x6c\x55\x74\x3d\xfc\x4a\x7f\x76\xc1\x66\x97\xaf\x5e\x1e\x01\xa3\xfc\xc6\xb2\xc8\xf7\x1a\x9a\x09\x5e\x88\x8c\xf5\x19\x8c\x09\xc3\x65\x09\x4e\x3f\xec\x16\x98\x30\xe5\x68\x6f\x6f\xef\x00\x97\xe4\xf0\x70\x38\x80\xbe\x6f\xf5\xbc\x9d\x7d\x9d\xdc\x5d\x9d\x89\x2c\x0c\xf5\x5f\x25\x08\x5a\x76\x52\xa5\x8c\x38\xd2\x82\x8f\x3d\x03\x07\x98\xb8\x24\x08\x0b\x9e\xf9\x29\x8b\x3c\x39\x6f\x96\xd2\x8d\x38\xbd\x12\x73\x56\x7b\x39\x17\x8b\x34\x63\x79\x23\xed\x3a\x9d\xd7\xd3\xcc\x7d\x51\xed\x2b\x22\xbf\x49\xf2\xf9\x69\xce\x16\xb5\x0f\x19\x79\xa3\x2d\xed\x34\x4b\x8b\x5a\x1d\x57\xec\x4a\xf8\xbf\xb3\xe4\xcb\x9d\xff\xfb\x2c\x13\xb3\xcb\x5a\x4d\x2c\xbf\x66\xf9\x76\xfa\x62\xc5\xe7\x09\x18\x4a\xd6\x46\x62\xce\xce\x56\xe7\xa7\x32\x4f\x66\x6c\xab\xeb\x19\x3b\x4f\x66\x77\xa7\x17\xe9\x7c\xce\x78\xa0\x78\xec\xe1\xc1\xfe\xde\x7d\x64\xcb\x91\x9a\x58\x5c\x92\x83\xfd\xf6\xd9\xd5\x73\xf6\x4d\x13\x3c\xe2\xfe\xaf\x96\xa9\x6d\xcb\xae\xa6\xb9\x2d\xd7\x9f\xf2\xb6\xfc\xc6\xf4\xb7\x7e\xc0\x23\x85\x7b\xf2\x1d\x59\xb4\xe5\x7b\x24\xd2\x96\x9d\x14\x77\x7c\xf6\x60\x03\x66\x82\x1b\x19\xf4\xc1\x62\x0d\xba\x6b\xed\xad\x47\x83\x0f\xe5\x3b\x7a\x6c\x2b\x64\x69\xb3\x2d\xcf\xd2\x69\x5b\x9e\xa3\xcd\xd6\xc6\xd7\xe9\xb4\xad\x48\xce\x8a\xa5\xe0\x0f\x0c\x74\x31\x13\x4b\x16\xe0\x92\xec\xef\xef\xde\x4f\xae\x07\xfb\xb8\x24\xc3\xbd\xe8\xe0\xbe\x22\xe6\x94\x8f\x9e\xec\x0d\x0e\x30\x11\x74\x3f\x1a\x44\xbb\x24\x81\xbf\xfb\x23\xd9\x7f\x6d\x48\x0a\x12\x9e\x10\xd9\x3f\x81\x17\xdf\xab\x1d\x5d\x25\x1d\x10\xd9\xff\x68\x68\x46\x25\x0c\xf6\x46\xda\xd6\x4d\x65\x1e\x92\x0c\xd2\x22\x52\xc0\xdf\xe1\x48\xf6\xed\x49\x04\x12\x76\x47\xfa\x5e\x5b\x3d\x3f\x26\x33\xf8\xbb\xff\x27\x59\xe4\xdc\x67\x91\x82\xce\xb7\x57\x52\x52\x25\xba\xf5\xe3\xf5\x6c\xde\xb2\x7c\x6a\xfd\x9c\xb7\xaf\x1f\xaf\xe3\xf3\x96\xe5\x93\xd6\x52\xed\xa2\xc9\xaa\xd4\x6a\xa9\x14\x5e\x1b\x6a\x74\xed\x0d\xd7\xbc\x85\xac\x57\x55\xaa\xa1\xd3\x59\x95\xa2\xa9\x13\xb0\xc6\x16\xdf\xc0\x91\x52\xc9\xf2\x44\x8a\xbc\x8a\xcb\xb6\x54\x1b\x5e\x15\x56\x3d\xb8\x90\x72\x59\xc4\x8f\x1e\x41\xf5\xbf\x17\x7d\x91\x9f\x3f\x9a\x8b\x59\xf1\x08\x36\xc3\x9d\x39\x9b\x89\x39\xcb\xfb\x17\xf2\x2a\x1b\xa7\xfc\x3a\xc9\xd3\x84\x4b\x1a\xf4\x18\xe1\x74\x30\xe2\x5b\x62\xd0\x88\xf7\x7a\x58\xf6\x68\x10\x26\xf9\x79\x31\x99\xaa\xa2\x5c\xd5\xf1\xe3\xa7\xb7\x4e\x78\x44\x95\x50\xc4\xa7\x56\xfc\x08\xde\xa7\x1c\x70\x87\x0d\x8e\x31\x34\xa0\xf3\x97\xa0\xc7\x7a\xc1\xa8\x73\x9d\x16\xa9\xec\x04\x3d\xd9\x0b\x3a\x0b\x91\x03\xca\xf0\x62\x95\x65\x9d\x2b\x56\x14\xc9\x39\xeb\x88\xbc\xa3\x96\x80\x4a\xe7\x82\xef\x5c\xd9\xca\xe6\xec\xba\xc3\xf8\x75\x9a\x0b\xae\xbe\x08\x2f\xc3\x8b\x50\x7f\xd1\x49\xf8\xbc\x93\xcc\xe7\x10\x13\x2e\xc9\x3a\x17\x2c\x5b\x2e\x56\x59\xe7\x26\xc9\x79\xca\xcf\x8b\x7e\x50\x6a\xd4\xef\x75\x5a\xbc\x57\x12\x30\x9b\xc7\x5b\xc7\xd3\xee\xa0\x24\x8c\x03\x2a\xfc\x6b\x91\xcf\xec\xd9\xdb\x2b\xe7\xf2\x3f\x31\x00\x3d\xd6\xf7\x0a\x6d\x05\x4e\x00\x5e\xa7\x91\x59\x92\x2b\xba\x2e\xab\x59\xbc\xae\x39\xaf\x2c\xb5\x37\x20\xa9\xf9\x8d\x48\xe7\xd2\x5a\xd0\x2b\xe2\xf9\xa5\xe6\x94\x6f\x36\x17\x5e\x84\x07\xf5\x81\x2a\x3c\xc3\x7f\x5e\xf3\xb5\x77\x1b\xdd\x74\x07\xa5\xeb\x92\xf8\xf9\x85\xe9\xed\xb6\x11\xab\x35\x87\xea\x7a\x1e\x62\x15\xc1\x77\xb7\xfc\xc6\xea\x61\x44\x97\x08\xa2\xd0\xf9\x8d\xeb\x37\x06\x18\xa9\x4c\x38\xe4\x04\xb6\x15\x8a\xf3\xfa\xad\x5b\x54\x93\x59\x3b\xe9\xb4\x55\xeb\x4d\xbc\xad\x39\xf0\xde\x57\x55\x9f\x57\x55\x53\xef\x33\x06\xbb\xfc\xce\xcb\xe5\xec\xa6\x73\x3e\x3a\x53\x43\x5e\xc8\x7c\x35\x93\x22\xa7\x77\x24\x47\x67\x7e\xf3\x30\x39\xeb\xa7\xc5\xc7\x55\xce\x1a\x63\xdc\x8d\x0c\x04\xb9\xbb\xb2\xd3\xd7\x27\xb7\xd4\x9c\x90\xab\x1e\x5e\x24\xc5\xf1\x0d\xff\x98\x8b\x25\xcb\xe5\x1d\x39\xa2\xeb\x4b\x76\x17\x77\x23\x92\xb3\x85\xfa\x73\x7a\x5a\xb0\xcc\x3e\x81\xb5\x44\xdc\x8d\x3c\x42\xbc\xac\xd9\xa1\x92\x44\xcd\x6f\x6a\x80\xf7\xa9\xb3\xae\x37\xb7\xe0\x10\xaf\xa7\x93\x9a\xe8\xa6\x11\x58\x56\xe6\x6c\x01\xce\x9a\xf0\x84\x89\x97\x73\xc9\xee\xc2\x10\xa5\x34\x08\x7a\xf0\x03\x13\x89\x6f\xb5\xf5\xae\x24\x39\x0e\xc3\xee\x51\xa3\xf9\x08\xfc\x28\x92\x49\x3e\xa5\x72\x92\x4f\xad\x53\x4b\x93\x45\xed\x0c\xed\x85\x45\x81\x93\x4a\xe3\xcb\x9d\xb7\xe8\xe0\x69\x51\xf1\xc8\x15\x7d\x9e\xe7\xc9\x1d\x2a\x14\x1f\x8e\x46\xb3\xa7\xc5\x68\xd6\xeb\xe1\xd5\x64\x36\xf5\x0e\x7a\xb3\xde\x70\x3a\xf2\x2a\x83\xe0\x71\x2c\x0c\x99\x85\x1e\xd3\x3a\x36\x37\x02\x05\x6d\xe4\xb8\x03\x9b\x6a\xbe\xed\x45\x01\xbd\x68\x3a\x1b\x09\xa2\x1e\x62\x06\x3e\x47\x29\xcc\x54\x46\x60\xa5\xc6\x09\x39\x05\x18\xb4\xf8\xc6\xaa\xab\x3d\xa7\x8b\x93\xea\xe2\xee\x21\xf7\x4b\xd5\x68\xfb\x2d\x4a\xa9\x28\x35\xe6\xd3\xa3\x7f\x3e\xea\x3d\x3a\xaf\x66\xfe\x37\xff\x58\xfc\x70\x7d\x66\x81\xaa\x49\x1c\xfb\xcb\x48\x6f\x41\xeb\x80\x06\x71\x40\xa3\x80\x04\xb1\x7a\x18\x06\xa5\xdd\x11\xbe\x0b\x7a\xac\x9f\x6b\x8e\x89\x1e\x4d\x68\x3c\x7d\x74\x4e\x50\xcb\x3d\xa4\x9c\xb0\xa9\x3a\xef\xa3\x40\xbd\xa1\x88\x25\x96\x7d\x29\x4e\x40\x49\x82\x76\xf7\x7d\x18\x6d\xa7\x3a\x48\xad\x49\xbe\x6d\xf3\xa8\x76\x5e\xa5\x59\x18\x06\x67\x42\x64\x2c\xe1\xf0\x73\xb3\x41\x06\x99\xc4\x10\x56\x77\xe0\xa1\xf1\x32\x5c\x58\xfb\xe9\x8e\x51\x19\x65\x46\x65\x64\x9c\x8f\x41\x3f\x18\xf0\xd5\xd5\x19\xcb\x83\xb8\x70\xb1\xf8\xb5\x5e\xc4\x8c\x60\x7c\x9f\xf3\xab\xd0\xea\xc5\x04\x5e\x84\xb8\x0f\x85\xbd\x6a\x4a\x69\x8a\x0a\x0a\xd0\xb2\x01\x84\xd7\x1e\x07\xfd\xa0\xf7\x1b\x2a\x48\x84\xe3\x9c\x00\xfd\xf6\xd3\x42\xd3\x71\x8a\xc7\x88\xd3\x20\x30\x9a\x55\x66\xc2\xfa\xda\x51\x7e\x49\x82\xef\xc2\x47\x01\xee\x05\x8f\x02\x4c\x3e\xa2\x14\x06\x2b\x08\x5a\x87\x9d\x95\x18\x63\xa3\xc9\x49\xc3\x10\x9d\xa0\x14\xc3\x9a\x6d\xbb\x3a\xd9\x26\x60\xad\x10\x56\x54\x2c\x81\x8a\xb5\xff\xb7\xa6\x64\xa6\xf7\x1e\x4b\xcf\xac\xaf\x1f\xca\x12\xa5\x84\xf7\x50\x37\x55\xb3\xbc\xd9\x14\x61\xa8\x11\x22\x28\x85\x94\x71\x10\xc4\x8a\x08\xe0\x07\x6e\xef\x55\x8f\x81\xe2\x1c\x2c\xb3\x52\x8c\x09\xcc\x22\xa0\x68\x79\xc3\x17\xe7\xbd\x20\x0e\x1a\x63\xc7\x30\xae\xd8\x42\x34\x5a\x55\xc6\x61\x2b\xab\x5c\x9b\xd1\xbc\xf7\x1b\xca\x28\x9b\xac\xa6\x64\x85\x47\x45\x8f\x7e\x44\x5a\xef\x34\x23\x69\x15\xff\x7f\x46\xef\xbf\x4e\x67\x9b\xcd\xf6\xee\x67\xbc\x0a\xb7\x44\x3e\xc4\xe8\x22\x0c\xd9\x64\x31\xdd\x6c\xd8\x24\xf8\xaf\xff\xb2\x32\x5f\x30\xc5\x63\x13\xd7\x13\x31\xdc\xe6\x2f\x31\x33\x9e\x45\x33\xeb\x13\x41\x54\xaf\xba\xaa\xf5\x60\xa2\x81\x30\xee\xcf\x05\x67\x23\xac\x7b\xe1\x6c\x72\xa0\x37\xba\xa3\x44\xf5\x9c\xa4\x9e\xab\xbd\x63\x05\x34\x73\xf1\xf3\xd4\xb2\x24\x76\x67\xde\x1d\x90\x60\xa2\x4b\x75\xf4\x86\x34\x0d\xc0\x81\xca\xbc\xda\xb9\x49\xe5\x45\xe7\x92\xdd\x15\x9d\x75\xd0\xab\x5f\xea\xf6\x7f\x17\x29\x47\x01\xe9\xa8\xb9\x2c\x83\x58\x56\xb7\x57\x85\x87\x5e\xef\xdd\x77\x36\xee\xab\x99\x39\x1c\x4d\xa6\x10\x55\xde\x86\x22\x40\x8c\xe4\x8a\xca\xef\x21\x74\xed\x9b\x07\x00\x3e\xa2\xd7\x83\x7b\xc5\xdc\x43\x0a\x37\xb7\x9f\x3b\xfa\x12\xfc\xb4\x90\x89\x5c\x15\x55\xfc\xed\xd3\x9c\x15\xab\x4c\x8e\x24\x95\x70\xb1\x64\x0a\x00\xdc\xb5\xc9\x03\x6f\x31\x88\x0d\x52\x8b\xa1\x1d\xf9\x15\x02\xd8\x8a\xb4\xdb\x86\x57\xcf\xc0\xaf\x07\x97\x98\x3c\x58\x47\xf5\xde\xb0\xf1\x9e\xf3\xa0\xac\xfa\xe0\x22\x8b\xb9\x3e\xc0\x8c\xba\xdf\xb0\x39\x7c\x6e\x08\x1a\xd5\x26\xf1\xc1\x59\x1f\x7c\x76\xd1\x1f\x7c\x96\x59\x17\xd9\x76\x87\x5e\x60\x05\x0d\xa8\x7c\x4a\xd7\xed\x5a\xaa\xf8\x33\xf1\x33\x5e\xa8\x54\xa3\xd1\x5b\x57\x41\x9e\xe3\xa8\x24\x5b\x31\xb9\xe3\x1b\xf2\xb6\x38\x11\x57\xec\x93\xd1\xfb\x3d\x9f\xc9\x94\x9f\xc7\xbe\x82\x93\x24\x45\x91\x9e\xf3\x38\x2f\x47\xb2\xef\xfc\xb8\xd7\x57\xc9\x32\xfe\x44\x8c\x46\x37\x6e\xde\xae\x2b\xb2\xab\x59\x4c\xf4\x93\xe5\x32\xbb\xd3\xe2\xa0\x93\x15\xd4\x04\x71\x5c\x92\x99\x3a\x4d\xc4\xdb\xfb\xa1\x23\xca\xad\xea\x7a\x3d\x45\x78\xb2\x24\x52\x00\x3f\x6a\xd3\xc8\xd5\x5f\xaa\xb3\xea\xcd\x66\x32\x2d\x89\xe0\x59\xfd\xcd\x74\x81\xba\x27\xcd\x6b\xfb\x25\x1a\xec\xed\xfa\xb3\x51\x12\xd9\xaf\x44\xcc\x6b\x75\x50\x5e\xe5\xac\x4a\xb9\x23\xff\x96\x02\xea\x94\xc8\xfe\x2c\x13\x9c\x19\x6f\xb4\x36\x95\x85\x5d\xc2\xf5\xf6\x0d\xf7\x9f\x10\x66\x3c\x97\x13\x9a\x23\x75\x84\xd2\x9b\x86\x3a\xa6\x6b\x74\x81\xcc\x60\x8a\x28\x71\x4b\x6f\x20\xbe\x3c\xba\x76\x4a\xa8\x6d\x51\x94\x14\xf4\xa6\xf2\xe1\x78\x50\x2c\x65\xc6\xd8\x43\xff\x6d\x88\x75\xb0\x55\xb4\xe4\x80\xb1\xc7\x0c\xe2\xe5\x54\x52\xed\xac\x55\xaa\x9d\x69\xa9\x76\x36\xad\xfc\x86\xe5\x64\x36\xf5\x14\x0e\xab\xb1\x12\x47\x63\x95\xaa\xef\x06\x66\x0f\x08\xbd\xb3\xfb\x84\xde\x19\x5e\x5b\x61\x77\x86\x9d\xbd\xe1\x9c\x46\xa3\xf9\xd3\xd9\x68\x0e\x42\xef\xdc\x17\x7a\xe7\x5b\x42\xef\xd7\x77\xfa\x7b\xe4\xd5\x02\xe8\x4b\xab\x5f\xac\x47\x75\xab\xfe\xa5\x1a\x02\x60\x87\xda\xdb\x08\x31\x5a\x7d\x33\x23\xad\x26\x9f\xb1\x24\x35\x83\xd3\x98\xd5\x7f\x0f\x55\x82\xbc\xc8\x59\x32\x07\x80\xdd\x38\x22\x1f\xcd\x0d\x8f\xd6\x0e\xbf\x14\xbc\x58\x5d\x59\xb5\x30\xee\xdb\x5c\xef\xd3\x29\xb1\x86\xaf\x31\x53\xd4\x68\x5f\xa1\xac\xea\x9d\xa5\xf3\x4b\x97\xf2\x3a\x51\xe7\xbb\x3b\xba\xcd\x0a\x2e\x6b\xb1\x3a\x9d\x03\x8a\x01\x24\x02\x4e\x60\xd1\x79\xd9\x82\x6e\x5d\x4b\xd4\xb9\x32\x28\x39\xf5\x45\x54\xad\x34\xdb\x16\xd0\x0a\x63\x24\x11\xeb\x65\x9f\x16\x3f\x25\x59\x3a\xb7\x2d\x3f\x21\xfa\x1e\xea\xc1\x2a\x66\xc4\x7a\xaa\xc4\x6b\xb3\x99\xc4\x3b\x03\x62\xb6\x0d\x35\x3c\xe0\xd2\x12\x1f\xc3\x17\xae\xd8\x95\xf8\x8a\xd0\xb8\xb2\xa7\x9e\x99\xb8\x5a\x26\x39\xab\xe2\x74\x19\x4c\x22\x09\x35\xad\x0a\xf6\xd2\xba\xd1\xb7\x12\xd0\x07\x84\xfd\x42\xda\xcd\xdc\xbc\xf8\x10\xe1\xd9\xf7\x74\x19\xff\xb5\x57\xec\x6c\x75\xae\x8d\x98\x6b\x17\x3a\x90\x69\xbc\xe2\x1e\xaa\x52\x17\xf1\x6b\x7c\x7b\xb5\x54\x32\x5c\x7a\x6d\x4c\x3b\xb6\x98\x62\xbd\x82\x66\x71\x6b\x76\xa8\x2b\x7b\x97\xdc\x89\x95\xfc\x86\x76\xf8\x05\xfd\xd6\xbc\xbf\x6f\x72\xec\x8b\xaa\x80\xff\xc2\x27\x36\x5f\xcd\x5a\xb4\xcf\xf5\xb7\x4c\xa9\x7a\x63\xdb\x29\xb3\x7a\x65\x81\x98\x2d\xda\xbc\x37\x6a\x16\xd6\x97\x3c\xec\x1e\x3d\xe6\x93\xe1\xe1\xbd\x0a\x21\x5f\xf5\x37\xdc\x8b\x0e\x70\x49\x1e\xef\x3e\xa0\x1a\xd2\xf0\x54\xa3\x36\x58\xa3\x25\xcb\x17\x22\xbf\x4a\xf8\x8c\xb5\xaa\x36\xbd\xfc\x3e\x17\x37\xd6\xa7\xdc\x4b\x1e\x79\xca\x62\x2e\x6e\xb6\x57\x79\x27\x55\x6f\x22\xac\x0d\xaa\xcd\x91\xf6\x55\x22\x19\x29\x68\xa6\xb3\xbe\x5e\x87\x29\xb8\x53\xc0\xc9\xd2\x3b\x07\xbb\x96\x6a\xd4\x74\x1f\x60\xd2\x9d\x4d\xde\xeb\x2b\x58\xc5\x6c\x39\xcb\x1c\xf2\x06\x58\x1e\xe9\x3f\x73\xda\x6a\x31\xb7\xc2\x16\xa9\x94\xd1\x7a\x13\x11\x1e\xad\x50\x37\x22\x70\x26\x01\xf6\x55\x85\x24\x03\x29\xa0\x60\x00\x66\x23\x56\x12\xcd\x49\x84\x09\x2b\xcb\x51\x3d\x3a\xbd\xfd\xc6\xd8\x2b\xca\x89\xaa\x32\x46\x2b\xca\x48\xa3\x06\x5c\x92\xa6\x2b\xfd\x8c\x7a\x65\x34\x7d\xd7\xfc\xca\x67\x19\x4b\x72\x9b\x3f\xab\xeb\xf5\x8b\x0b\xb1\xca\xe6\xbf\xa6\x2c\x9b\xd3\xd6\xfb\xe2\xc4\xef\x31\x5c\x14\xbe\xce\x93\x2b\xf6\xa9\x46\xd4\x78\xed\xcd\xea\x82\xea\x39\xe8\x57\xad\x22\x4b\x9b\xe6\xb7\xe5\x3e\x93\x25\xa3\xe7\xb6\x71\x2c\xed\x9b\x8a\xca\xb2\xe7\x3c\xbd\x02\xff\x27\x68\xc5\xa8\x65\x96\x4d\xf1\x9c\xfd\xb1\x62\x85\xac\x97\x0f\xc3\xba\x0e\x3d\xf8\x7c\x91\x16\x9d\xb3\x5c\xdc\x14\x2c\xef\xcc\x05\x2b\xf8\x5f\x65\xc7\x98\x35\x75\x5a\xab\xe8\x77\xde\x27\x97\xac\x53\xac\x72\xd6\x91\x17\x89\xec\xdc\x89\x15\x44\x0d\xec\x24\x9d\xa5\xc8\xee\x16\x69\x96\x29\x71\x49\x47\x0b\x34\x55\x17\xfd\x4e\x9b\x02\x23\x4b\xf9\xa5\x4e\xd8\xb1\xaf\x16\x81\x7f\x04\x76\x9d\xba\xf8\x73\x2d\x6f\x1b\xab\xff\xf9\x86\x97\x3a\x74\x68\x77\x40\xae\x8d\x9f\x2e\xdd\x19\x90\x3b\xfa\x18\x50\xe7\xbf\x95\xe8\x3a\xcd\x15\xf6\x8c\x9e\x29\x32\x6c\xee\x59\x5f\xa3\x49\x86\xd7\xd1\x33\xb6\xd9\x0c\x86\x8f\x9f\xb2\x71\x63\xf4\xea\x2f\x75\x64\x72\xc9\x0a\x18\x07\x75\x1e\xbb\x66\x9d\x94\xcb\xce\x19\x93\x37\x8c\xf1\x4e\x04\xba\x97\xc1\xf0\x31\xe9\xa8\xd7\x52\x7e\xde\x59\xa8\x37\x3b\x79\x22\x59\x61\x23\x4a\xca\x8b\x84\xab\x42\x9d\xc5\xb2\xe8\xa4\x45\x87\x0b\x37\x1d\x6c\x1e\xe0\xf8\x8e\x46\x4f\xd9\x18\x22\x2d\x2c\x32\x21\x72\x34\x60\xbb\x8f\x18\x8e\x1f\x97\xe6\x12\x9c\xb3\x9b\x06\x87\x22\xb7\xf4\x06\x94\x86\xc3\x91\xfe\x3b\xe8\x0b\x6e\xf4\x48\xed\x8c\xea\x1a\xdf\xc7\xa5\xce\x28\xeb\xdd\x69\xc0\x65\xcd\xaf\xc6\xb7\xfd\xa5\x28\xa4\xf9\xa2\x09\x97\x82\xbc\xd9\xc3\x4d\x56\xd6\xf2\x02\xb1\x1e\x45\xea\xbd\x92\xd4\x19\xdb\x35\x65\xe4\x6a\xb3\x51\x75\x46\xa4\xe5\xe5\x26\x27\xe3\x78\x7d\x4e\x17\x35\xf3\x2a\x86\x9a\x1d\xb1\xa7\xd2\x1a\x83\x5b\xa2\x73\x0c\xc4\xe6\xdd\x22\x1f\xd5\x41\x3c\x2d\x1e\x8d\x01\x7c\xc1\x23\x16\xfb\xa1\x97\x73\xca\x77\x06\xcf\x9e\x3d\x1b\x10\x41\xd9\x24\x07\xab\xf3\x6e\x75\xe8\x12\x61\x18\x3d\x7d\x09\x48\x47\x26\x22\x50\x87\x8d\x18\x5c\xe0\x13\x88\x0d\x2f\x08\xa7\x7e\x60\xf8\x4b\x6f\x9f\xaf\xc2\x8c\x30\xca\x26\xd1\xd4\xda\xf5\x35\x6e\xbc\xcd\x2d\xcc\x24\x9a\x8e\x6a\xe7\xbd\xaa\x0f\x4b\xb1\x44\xda\x7c\x4a\xa7\xab\xb2\xea\x64\x14\xd7\x83\x07\xba\xce\xe6\x4f\xc5\xc8\x9a\x9d\x0f\xff\x86\xf2\xde\x00\xef\x0c\xd4\x99\x73\x92\x4c\x49\x46\x93\xde\x40\x1d\x38\x27\x59\xfd\x83\x69\x18\x46\xcf\x5e\xa2\x94\x70\x8c\x5d\x62\xa1\x13\x0b\x92\xe2\x31\x82\x8e\x17\x44\xbd\x09\x41\xbd\x14\xe1\x40\x5a\x4a\x54\xd5\x90\x96\x54\xde\xb2\xde\x38\xba\x6a\x78\x73\x1c\xfd\xea\xca\xd2\xb9\x26\xf9\xa6\x91\x5e\xcc\xca\x06\xc0\xb0\xc8\xe5\x5b\x3e\x67\xb7\x3b\xb2\x7a\xf6\x10\xfb\x29\x1f\x03\xca\xde\x7c\x47\xf6\xd3\x39\x70\xa9\xdf\xe8\x64\x4a\x3e\xaa\x7f\x3e\xd1\x01\x39\xd6\xec\xea\x33\xdd\x25\x1f\xd4\x02\x38\x55\xff\xbc\xa7\xdd\x41\x75\x43\xf4\xb6\xae\x8f\xbe\x44\x1f\x9d\x87\x9c\x1c\xf9\xf8\xe4\x15\x3c\x16\x3e\x51\x85\xaa\x51\x90\x3a\x06\x8b\xda\xfc\x9e\x52\x66\x23\x4b\xa9\x42\xc4\x6b\x37\x95\x0d\xb0\x3b\x72\x84\x7e\x53\x7b\xba\xfe\xa8\x47\x63\xcf\xcd\xa5\x88\x6a\x28\x51\xed\x23\xdd\x53\x5c\xf1\x82\x4b\xf4\x1b\xc6\xa7\x6a\xed\x71\xf4\x0e\x57\xc1\x8b\x1b\x8d\x0f\xc3\x1c\x3d\x27\x5e\xdb\x76\x98\xff\x91\x77\x7a\x61\xea\x11\x09\x43\xfd\x31\x88\x97\xf0\xc1\xea\xef\x12\xfa\x79\x64\xe3\x7b\xbc\x45\x1c\x93\x63\xf8\xb6\xfd\xc2\x71\x18\xa2\x2e\x3a\x6e\xf4\xea\x19\xc7\x9b\x0d\x0b\xc3\x6e\xfb\xb6\x80\x30\x1e\x59\x21\xf3\xd8\x8d\xe8\x3d\xc6\x19\x29\x5e\x57\x65\xec\x54\x1e\xf7\x97\x06\x59\xf0\x1d\xbb\x66\x99\xc1\x73\x48\xb7\x1a\xf2\x14\xc2\x3a\x6e\x31\xcc\x56\x78\xfc\xb1\xf7\x99\x2c\x3e\xa6\x7a\x90\xc3\xf0\x04\xfd\x86\x89\xea\xba\x66\x86\xea\xe7\x48\x0f\x82\xe7\xc6\x77\x8c\x8d\x36\x26\xaa\xe6\x62\x55\x9b\x8b\x95\x9e\x8b\x95\x37\x17\x1c\x93\x42\xb1\xd6\xea\xee\xd8\x1a\xe6\xda\x7e\x26\x40\xb2\x25\x50\xf5\x17\x9a\xf8\xdb\xec\xdb\x79\xc6\x1c\xbc\xe2\x63\x7f\xcf\x7c\x7b\x75\xc5\xe6\x69\x22\xab\xec\x81\x9f\xfd\x4e\xdc\xb8\x8c\x3d\x3f\xe3\x83\x12\xf6\x33\x97\xb7\xeb\xe7\x69\x7b\x14\x07\xbc\xe2\xe5\xfc\x58\xb0\xfc\x45\x26\x66\x97\xe0\x4b\x67\xde\x1d\xd6\xec\x59\x41\x5e\x69\x39\x10\xe3\x35\xab\xcf\x6c\x6d\xeb\xb7\xf1\x7c\x8f\x6e\xd9\x6c\xa5\x5e\xf0\x37\x85\xd3\xcd\xe6\xc3\x66\x83\xdc\x0a\xa8\xcb\xbd\x95\x0d\xfd\x47\x9f\x4c\x5a\xc4\x91\xcf\xcd\xf7\x5e\x83\x57\xab\x8f\x6a\xb9\xfd\x12\xcc\xbd\xff\x1e\xaf\x1f\xd8\x9d\xbb\xd6\x67\xa3\x36\x1b\x18\xaf\xbc\xd8\x40\x26\xe8\x95\x6a\xa3\x90\x59\x44\x5a\x49\x3f\x97\x9a\xeb\x7d\x1e\x7d\xa6\xb2\xee\x3f\x53\x59\x6d\x7f\xa6\xbc\xac\x7d\x7d\x99\xa8\xf3\x7b\xdb\x28\x35\x8c\x7c\x41\xe0\xfd\x98\xa4\x5c\xd2\x2f\xb5\x9c\x15\xff\x39\x95\x17\x6e\xf6\xea\x07\x90\x06\x30\x71\xb3\x2f\xc6\xe3\xdd\xf8\xfa\xd7\x7b\xc4\xe8\xae\xd7\x23\xe6\xf7\x48\x3e\xd4\x23\xeb\x2c\xd1\x76\x89\x92\x78\x2a\xd3\xa6\x1c\x64\x9a\x9a\xd2\xad\x23\x70\xea\x54\xc1\x69\x18\x5a\xf5\xa7\xd3\x5e\xa5\x34\xed\xcf\x59\x96\xdc\x61\x25\x0a\xa4\xe3\xac\x97\xc6\x19\xa9\x7a\xac\xd7\xf6\x4e\x0d\x50\x79\x18\x17\x74\xf8\x38\xaa\x63\x4e\x15\xb4\x72\xe7\xae\x63\x4b\x15\x74\xc0\xf6\x1a\x13\x5e\xd0\xc7\x6c\xd7\xae\x7e\x46\xd7\xe9\x3c\xfe\xd4\xeb\x11\xbb\x24\xe2\x84\xd4\xb8\x5c\xcc\x88\xe3\x1d\x71\x4a\xea\x9c\x2e\x2e\x68\xda\x2b\x88\xdb\x69\xe2\x9d\x41\x49\xd2\x67\xd9\x18\x79\x5b\x28\x4d\xc9\x11\xfa\x48\x1c\x16\x9f\xe1\x70\x0c\x9e\x3e\x62\xb5\x03\x8c\x05\xc2\xf1\x7b\xb5\xac\x14\xb7\x4a\x77\x32\x8c\x95\x00\xe0\xd5\x51\xc0\x9e\xc5\x30\xd9\x5a\x83\x4a\x62\xf4\xa7\xf1\x26\x4f\x96\xad\xcb\x5e\xd3\xff\x67\xbb\x8b\x37\xbc\x44\xdb\xe8\xff\x1e\x25\x46\x8d\x82\xca\x92\xec\x1e\xec\x45\xdf\x72\xa1\xf2\x78\x17\x97\xe4\x30\x7a\x72\x5f\xd9\x0a\x8d\x4f\xaf\x01\xb3\xff\xcb\xcd\x46\x3e\x73\x51\xdf\x42\x1d\xcb\xc0\xfc\x1a\x55\x71\x38\x22\x92\x83\xc0\xaf\xaf\xb1\x25\x1e\xf1\xa7\x12\x4c\xd2\x72\x25\x4d\x2a\x91\xd2\x19\xbb\x97\xbc\x3f\x47\x92\xac\x7f\x8b\x11\xa6\xcf\xf2\x12\xab\x3e\x3c\x39\xf8\x96\x76\x81\x78\xb0\xa5\x1a\x76\xaa\x92\xed\x8a\x9f\xec\x0e\xf7\xbf\xb9\xe2\xca\x76\xdf\x68\x3c\x54\x87\x3e\xb1\x05\xcb\x19\x9f\x31\xad\xfe\x08\xd4\x74\x74\x2e\x12\x38\x9d\x9e\xa9\xd3\x54\xca\x53\x99\x26\x59\x5a\xb0\x79\x67\x47\x9d\x90\x58\x8e\x70\xad\x84\x22\x6e\x75\x64\x1a\x3d\xd0\xd0\xdd\xc1\xde\xde\xb7\xce\x8c\x37\xea\x6a\x98\x7d\x03\x40\x0b\x4b\x07\xe3\xdd\x67\x7c\x75\xc5\x72\x45\x97\xd4\xff\xb1\xd9\x74\x07\x24\xef\xcf\x40\x6b\xb7\xd2\xf9\xdd\x88\x04\xa0\x63\x0e\x52\xde\xc9\xc3\x10\xe5\xfd\x9b\x3c\x95\x26\x0f\x5b\x17\x1f\x7d\xb5\xe1\x34\x24\x8c\xe4\xa0\xee\xc9\x7d\x09\x4b\x34\xae\x1d\x41\x22\xf3\xe2\x15\x10\x09\x46\xb8\xb9\x76\xe2\x6d\x0c\x86\x50\x83\xb1\x77\xb8\x37\xfc\xb6\xc1\xf0\x3f\xa3\xce\xfa\x6c\x7c\x5f\x43\x25\x59\x43\xff\x62\x4e\xaa\x91\x88\xbb\x11\xf1\x87\x41\xfd\xb6\xdd\x8e\xbb\x51\x89\x63\x36\x91\x53\x80\xdd\x6e\xa1\xad\xbd\xfd\x6f\x69\xa5\x6b\x60\x6e\xad\xc0\xb4\x8a\xd3\xf3\xb6\xab\x49\xe2\x83\x91\xdc\x36\xee\x74\x3e\xc4\xdc\x53\x03\x49\x2f\x88\x92\xea\x3c\xc7\x5f\x31\x33\xb3\xca\x74\x30\xd7\x82\x53\x0a\x9f\xe4\x53\xe7\xae\xc5\x4a\x92\xdf\xc3\x74\xb6\x7b\x3f\x78\x62\x7c\x32\xbe\x81\x60\x9b\x03\x50\x30\xf9\xd1\x36\xf1\x78\xe1\x0f\x84\x57\x9a\xf5\x4f\x4f\xa1\x23\xa7\xa7\xea\x50\x5a\x92\xbc\x81\x4c\x2b\x4c\xf0\x2b\xcf\x7c\xcf\xd4\xaf\x55\x33\x48\xfa\x26\x7b\x5e\xb1\x9a\x75\x1f\xb3\xf5\x6e\x93\xe1\xe1\xe0\xf0\xf0\x9b\x99\x47\xdb\xbd\x9f\x35\x0a\x36\x16\x3f\x93\x86\x71\xf0\x54\xa3\x44\xa9\x9c\xba\xf9\x88\x45\x0f\x02\x46\xb7\xc8\xc5\x15\x62\x6d\x53\xf0\x78\xb8\xff\xe4\x9b\x08\xb0\xe2\x66\x9f\xef\x96\x96\x91\xbd\xe5\xd7\x49\x96\xce\x3b\x89\x94\xec\x6a\x29\x3b\x52\x74\x20\x52\xd5\x6a\x26\x57\xb9\xb6\xe5\x85\x26\x9d\x65\xac\x93\x1a\xbf\xcf\xfe\x3f\xf9\x5b\xde\x11\xf9\x9c\xe5\xaa\xfc\x19\xeb\xd8\x22\x04\x5e\x48\x54\x8b\x3b\x5a\x10\x29\x3a\x57\xab\x42\x76\x2e\x92\x6b\xd6\x49\x3a\x5b\x7d\x47\xb8\x73\xc5\xe4\x85\x98\xf7\x83\xd6\xbe\x1d\x1e\xdc\xdb\xb7\xe6\x4c\x39\xb3\xfb\xdd\xdd\xfd\x7d\x3c\x6a\x12\xc8\x96\x2d\xca\xba\x34\xea\x03\x41\x12\x8a\x22\x92\xf7\x7f\xc3\x50\x54\x1d\xc7\x0c\x09\x9d\x33\xe9\x2d\x1c\xdd\xf8\xc2\x1d\xe0\x1e\x28\x83\x98\xde\x16\x35\x88\x55\x5a\x81\x58\xf5\x30\xa7\xe9\x44\x4c\x89\xd4\xb1\x37\x8e\x17\x88\xe3\x67\x34\xda\x6c\xb6\x56\xed\xd2\x54\xf9\xb6\x38\x72\xac\xca\x98\x0a\x11\xae\x95\xd2\x66\x53\x75\x6b\x37\x51\x92\xc0\xee\xfe\xfe\xb7\x2e\xc9\xfb\x07\x25\x27\x82\xae\x4b\x92\xd0\xba\x01\x10\x74\x4a\x07\x41\x4b\xaa\x20\x68\xaa\x53\xc9\x24\x6f\xe9\x14\x12\xae\x8d\x76\xdf\x13\x2d\xf3\x7c\xb8\xb7\x7b\xf8\x4d\xf3\x9c\xfa\xf3\x7c\xf0\x04\xdc\x2b\x38\x1a\x1c\x0c\x30\x49\x94\x74\x33\xdc\x7f\xe2\x4d\x7d\xea\xb3\x12\x37\xc5\xb8\xc9\x6a\x34\x47\xb5\x31\x25\xb4\xa1\xd7\x03\xeb\xb8\x6d\x05\x37\xd6\x6e\x65\xe6\xe0\x6c\x73\x15\x95\x4d\xa6\x24\x55\x7b\x6c\x06\x68\x8e\xe6\x6e\x81\x53\x6e\x0d\xc0\x46\x5d\x94\x52\x94\x53\x5e\xb3\xff\x82\xa9\xd6\x17\x7c\xb9\x01\x6b\x20\x5d\xb9\xd9\xd8\x09\x80\x5b\xb3\x91\xaa\x18\x8f\xaa\xcb\x4d\x08\xfd\x27\x28\x73\x92\x22\x78\xc8\x5a\x44\x3a\x1b\x9f\x6b\xb3\xb1\x4f\xde\xa9\x24\x5d\x20\x6b\x3b\x26\x4a\x8f\xb4\x60\xb4\x36\x1b\x14\x11\x61\xd7\x0a\xfc\x4a\xd4\x2f\xac\x48\x6f\x6f\x77\xf7\x4f\x4f\xe3\x61\xf4\x44\xcf\xa2\x62\xb4\x7a\x1a\xd5\x7c\xd6\x66\xd1\x6d\x07\x0d\xc3\x99\x7b\x84\xc0\x6a\xaa\x4b\x98\x6e\xd7\x62\xaf\xbd\x35\x32\xf8\x76\xe6\x58\x2c\x73\x96\xcc\xff\x77\xf9\x22\x8c\xed\x20\x8a\x86\xdf\xb6\x0d\xb9\x7d\xf6\x01\x07\x95\xa0\x80\x87\x66\x86\x6b\xc0\xb8\xcd\x0a\xcf\x98\x42\x96\x6d\x86\x4f\xed\xfa\x55\xb7\x64\x6a\x9b\x2d\xa5\x2e\xbd\x6b\x9f\x2b\xbe\x37\xb6\x6d\x73\xb1\x5d\x60\xd3\x6f\x95\x3e\x0e\x06\x7f\x7a\x77\x50\xe4\xd6\xb6\x39\x98\xfd\x7b\x3b\x52\x51\x83\xa4\x88\x01\x51\xe5\xdb\xd6\xfc\xd6\xe2\xd9\x2e\xe7\x7e\x91\xa5\x33\x86\x0e\xc8\xce\xc0\x79\xd9\x1c\x3b\xf3\x4c\xde\x18\x16\x63\x09\xec\xa5\x00\xac\x0d\x26\xc1\xfb\x64\x09\x2f\x6c\x36\xc1\x09\xd3\xef\x8e\x6b\x52\x41\x1c\x3c\xb7\x42\x9a\x29\xf8\xe8\xff\xa1\x71\xfc\x63\xba\x79\x8b\xb9\x44\xe3\xf8\x60\x33\xd8\xdf\xec\x0e\x31\x1a\xc7\x2f\xb3\xe4\x6a\xc9\xe6\x58\xd7\xf0\xdd\xa3\xbe\x64\x85\x44\x1c\x8f\xfd\x1e\x1a\xeb\x0e\x38\x59\xca\x9a\xeb\x0b\x47\x55\x54\x0c\xa3\x50\xa8\xd4\x09\x56\x64\x11\xf6\xc0\x69\x2e\x52\x55\x49\xba\x36\x69\xf1\xba\x2c\xdd\x19\x68\x92\x4f\xf5\x68\x25\xf6\x15\x92\x90\xea\x99\xe3\xea\x47\xc9\xfb\x9c\x32\xfa\xcc\x6a\x14\xd4\xf0\x9d\x9e\xb2\xe2\xbd\x98\xaf\x32\x36\x56\xf3\xec\x6c\xbc\x60\xd6\xab\xc0\x66\x9a\x16\x92\x58\x96\x60\xbf\xc7\xfb\x73\x6a\xcd\x09\x6a\xa2\xb3\xc4\xbc\x2f\xac\x7b\x83\x7a\x64\xf0\x78\xef\xa9\x87\xac\xeb\x87\x88\x73\x26\x63\xd5\x57\x45\x9b\xbc\x7f\xde\x50\x66\x6d\x5d\xcd\x9c\x67\xe2\x2c\xc9\x3e\x5f\xa4\xce\xd0\xb3\x4a\xa9\xdd\x18\x5d\xa4\xc5\x66\xa3\x78\xd3\x6b\x5b\x61\xe0\x65\x05\xb8\x11\x52\x74\xeb\x43\x26\xe4\xba\x79\x47\xff\x02\x2f\x6b\xde\x17\x76\x24\xbe\xe9\xd0\xa0\x4f\x6d\xfd\x1c\xe6\xe1\xa1\x3d\xd2\x2c\x6a\xbb\x22\x3e\x27\xe7\xf7\x0f\xe3\x76\x59\x7b\x48\x0b\xf4\xdc\x06\xe5\xfd\x27\xcf\xa0\x22\x81\xc0\xbe\xa6\x8e\x6c\x25\x41\xa8\xd5\x5c\x84\x81\x63\xe6\xfe\x10\x80\xa3\xd0\x93\xe1\xe1\x1e\x26\x8a\x2f\x3c\xde\x3f\xd4\xfb\x50\x5f\x91\xb8\x96\x26\x1e\xef\x3f\xc6\x24\xa5\xeb\x9f\xd9\xd9\x65\x2a\x5f\x0b\x2e\x4f\xae\x84\x90\x17\x29\x3f\x8f\x83\x84\xc3\x81\x3f\x29\xd8\x3c\x20\xef\xc5\x97\xe3\xe2\xb6\x51\xe2\x3c\x4f\xee\x8a\x59\xa2\x5a\x76\x26\x6e\x4f\xd2\x2f\x90\x7a\x06\x1b\xc4\xce\x99\xb8\x0d\x4a\xe2\xdd\xcc\xfa\x82\x0a\x53\x0b\x71\x3d\x13\x99\xc8\x63\xd9\x5f\x26\x19\x93\x92\x41\x2c\xfc\xfe\x52\x63\x9c\x96\x1a\xfc\x4d\x9c\xe7\xc9\xf2\xe2\xae\x7f\x26\xe6\x77\x43\xb2\x3e\x4b\x66\x97\xe7\xb9\x58\xf1\xf9\xcb\xc6\xbb\x55\x8e\xb3\x60\x0e\xfe\x0b\x6e\xcb\x3b\xcb\x3c\xe5\x32\x88\x1f\x78\x79\x26\xae\xae\x04\xef\xdf\x5c\xa4\x92\x95\x25\x2e\x47\xc0\xa4\x3a\x05\xb5\x9b\x29\xda\xee\xc5\x3a\xf8\x2f\x4d\xcd\x41\xbc\xbe\x90\x57\x59\x9c\x92\xe0\x6f\xa4\xf3\xb7\x38\x3e\x63\x0b\x91\x33\x78\x4c\x16\x92\xe5\xea\xd3\xd5\xf0\xa4\xfc\x82\xe5\xa9\x0c\x4a\xa2\x78\xb1\xe0\xe7\xa4\x73\x16\xc4\xeb\x85\xe0\xf2\x67\x96\x9e\x5f\xc8\xb8\xd6\xf1\x2a\xfd\x85\xc8\xe6\x25\x51\x03\x11\xbb\x11\xbc\x4a\xf2\xf3\x14\xcc\x90\x33\x24\x31\x59\x07\x61\x1c\xab\x6e\xce\x73\xb1\x7c\xb0\xc7\xdb\xc3\xa5\xfa\x5d\x96\x98\xac\x39\xa0\x25\xbd\x5f\xa5\x2f\x8b\xe2\x45\x52\xb0\x2c\xe5\x8a\x42\xeb\x00\x53\x56\x87\xe7\x60\x05\xbd\xa8\x33\x5c\x8b\x98\xdc\x31\xc1\xfe\x2c\x4b\x8a\x82\x15\x4d\x23\x45\x54\x39\xd4\x1a\x24\x54\x5c\x1a\x8b\xdb\x95\x92\x7f\x0f\x77\x1f\x63\x32\x53\xf2\xd2\x93\xa1\x2f\x30\xcd\x3d\x4f\xa3\x47\x01\xd5\x41\xc0\x92\xfc\xb9\x44\x91\x77\x70\x5e\x34\xaf\x91\xa4\x5a\x07\xbd\x41\x53\xd5\xca\x7b\x74\x40\xf2\x1e\x1d\x60\xa6\x65\xf9\x7c\x3a\x32\x4a\xdb\xb2\xee\xd7\xea\xfa\x03\xcb\xf0\x78\x31\x76\x4f\x08\xc7\x5b\xfc\xc5\x64\xb9\x80\x10\x9a\xa6\x2e\xa8\x87\x62\x61\x2d\x90\xa5\x1a\x35\x1b\x85\x3a\xaa\x4c\xd8\xa5\x13\x67\xab\x10\xd5\x5b\x52\xa1\xc4\xf5\x93\xb4\x4d\x57\x47\x28\x7b\x6b\x06\x98\x71\x16\x48\x44\xf6\xd9\x35\xcb\xef\x7c\xa2\xf6\xa2\x73\x42\xab\xe0\xbe\x44\x63\x7e\x6c\x31\x5b\x59\xb9\x8f\x54\x71\x83\xed\x95\xdc\x52\x91\xa1\xa0\x4b\x2f\x06\x47\xde\x85\x8e\x08\x50\xe8\x6a\x3c\xb7\xd8\x3f\x74\xd5\xae\x8b\xd0\xba\xd4\x01\x0b\xb6\xda\x58\x6b\xa1\x3a\x8b\xd9\x46\x56\x11\xc8\xcd\xb2\xbd\xda\xf6\xf6\xec\xfa\x77\x9d\x9e\xf0\x0b\xee\xc6\x9d\x45\x92\xc2\xcd\x65\xdd\x03\xf6\x5e\x12\x1b\xb3\x38\x78\x14\xf4\x98\xef\xe3\xea\x5f\xe9\xb4\xde\xf3\x68\x37\x09\x29\xde\x89\x1b\x96\xbf\x4c\x0a\x86\xb0\x3b\x4b\xca\x7a\x3a\x0e\xc3\x9d\x41\x97\xd2\xe0\xd1\xf8\x2f\x81\x2b\xe4\x1a\x60\xe7\x14\x63\x7d\x60\x19\xb3\x7e\xb1\x3a\x2b\x64\x5e\xe5\xf8\x46\x0a\x77\xf7\xf6\xc4\xae\x82\x9d\x01\xd4\x01\xb2\x5c\xa4\x64\x39\xff\xf5\x33\xcf\xc6\xa1\xbf\x4c\xe4\x05\x40\x11\x82\xfa\x9e\x25\xf9\xec\x82\xe4\x14\xb6\xd2\x0b\x22\xd4\x2c\x07\x8f\x02\x27\x95\x84\x61\x30\x0e\x74\x88\x26\x24\x7a\x34\x18\x6b\xe8\xc2\x6a\x1c\x79\x1c\x8c\x83\x1e\xc7\x24\x0f\xc3\xe0\x2f\x81\x0e\x90\x0c\x45\xff\x02\x8e\x52\x5e\xd1\x3c\x0e\xfe\x12\xf4\x72\x4c\x44\xd5\xb4\x1b\x54\xc7\xe8\x1b\x6d\x09\xb7\x72\x8c\x92\x16\xf5\x04\x83\x76\x12\x70\x53\xcb\xd5\x3f\x82\x56\x07\xfb\xe0\x2f\x01\x1e\xc1\xf8\x8b\x30\x04\xa8\x71\x33\xba\x42\x63\xb0\x9a\x5f\x11\x11\xce\x39\xc0\x7b\x79\xec\xee\xbf\xa1\x8a\x04\x84\x5e\xf7\x52\xd2\xa8\x22\xc1\x98\xac\xed\xa0\xc6\x92\xe8\x21\x8d\xcd\x48\x8d\x83\x20\xe6\x44\x8d\x6d\x6c\x06\x44\xa5\xe4\x65\xa9\xd6\x58\xa2\xe1\xa5\x20\xa6\x6c\x65\xa9\x02\x17\x3d\x7a\x6b\x28\x21\xf6\xa1\xad\x5c\x1f\xb1\xcd\x0f\x1a\x04\x50\x01\x7c\x6d\xac\x27\xc9\xfe\xac\xc6\x1c\x5e\xd1\x89\x6a\xee\x7a\xf6\x07\x8e\xab\xe4\x80\x24\x30\xf9\x63\x3d\x7d\xfa\x47\xa3\x0a\x95\xa4\x66\xb4\xa7\x1f\xd5\xeb\x3a\x29\xa8\xfc\x1e\xb8\x17\x64\x22\xb1\xe1\x1e\x50\xd5\x47\x0c\xe2\xa2\xd7\x03\x0d\x1c\xf0\xe3\xa7\xb7\x5e\xb7\xb6\x2c\x9f\xaa\x93\xab\x58\x74\x7e\xfc\xf4\x16\x16\xfe\x58\xb1\x00\xfb\x03\xfd\xf5\xa3\x79\xb9\x13\xfc\xb5\x57\x55\xd5\xfb\x6b\xd0\x99\x89\x55\x36\x07\x7b\xb0\x33\xd6\xd1\xdf\x9b\xf7\x3b\x60\xbf\x97\x16\x9d\x2c\xbd\x64\xd9\x5d\x67\x96\xac\x0a\x36\xef\x9c\xdd\x75\x12\xde\x49\xcd\x71\x7a\xc9\xf2\x19\xe3\x72\x07\x90\x09\xd4\x79\xe9\xaf\x6a\x49\x59\x76\x08\x1d\xbb\x64\x77\x54\x51\xf3\xb8\xfa\xe6\x38\x78\xa4\xc7\xd0\x26\x34\xc6\xd1\xf5\xbd\x71\xb9\x53\xf7\x58\x08\x02\x6c\x6f\xb8\xf4\x11\xa2\x58\x66\xa9\x44\xc1\xa3\x00\xfc\x73\x14\xa9\xab\x1d\xa0\x91\x9a\xa8\xb2\x6a\x5b\x25\xa9\xca\x9f\x2b\x0a\xcb\x68\xb2\xd9\xa4\x23\xed\x68\xac\xf2\xc6\x82\xe6\x71\xee\xb6\x11\x24\xf4\x26\x49\x04\x15\x80\xc0\x92\x48\x94\x63\x4c\xba\xc2\xb2\x21\xc7\x75\x54\x25\x2e\xd5\x06\x51\x9a\x08\xc7\x7f\xa6\x23\x4e\x83\xbe\x22\xf1\x62\xb3\x09\xfa\xee\x09\xfe\xda\xc8\x79\xdd\xc1\xc8\xf3\x8e\x24\x33\x6a\xdf\x1f\xcd\x9e\xd1\x68\x34\xdb\xd9\xd1\x55\x2f\xa9\x98\xcc\xa6\x23\x5d\xdf\x72\xbc\x40\x82\xcc\x70\x6c\x6a\x5d\x8e\x91\x4e\x00\xc7\xc2\x78\x15\x86\xee\xf7\xce\x0e\x98\x7d\x74\x33\x70\x5b\x1c\xad\x76\x76\x46\x2b\x2c\xfa\x2b\x5e\x5c\xa4\x0b\x89\x54\x05\x78\xd4\xcd\x4c\xb3\xc4\x24\x9a\x6e\x36\xea\x5f\x35\x38\xea\x2f\xde\x6c\xbc\xd2\x66\x1a\x2e\xa8\x30\x3e\x85\x8f\x2a\xcd\x98\xe2\x8c\x30\xd7\x17\x96\x15\xec\x0c\xd4\x1c\x5f\xf4\x28\xb8\xc5\x5e\x94\xde\x74\x13\x51\x11\xb8\x5a\x3b\x8e\x0c\xaa\x74\x2f\x75\xb3\xa9\xad\x73\x55\x5b\x52\x71\xcc\x5b\xe7\x2f\xa7\x6d\x3d\xe8\xc4\xea\x2b\xd7\x5a\x59\x71\xb5\xf4\x5c\xc6\x3c\x25\x05\x95\xc4\x37\xef\x33\xd4\x66\xdc\x95\xcb\x52\x6b\x97\xf2\xab\xcf\xce\x33\xee\xb3\xf0\xea\xb1\x5c\xda\x0f\x06\xa2\x39\x67\x1b\x28\xdf\x58\xcb\x45\x31\xdb\xe6\xe7\xc9\xb8\x0d\x9b\x7d\x9c\xa3\x44\x09\x15\x02\x75\x23\xf8\x17\x38\xaf\x31\xea\x81\xc4\x92\x24\xcb\x25\xe3\xf3\x77\x69\x21\x19\x6f\x60\x4d\x6a\xe1\xb0\x1b\xd5\x95\x09\x70\x7b\xa1\xb5\x44\x7a\x85\xf9\x7a\x22\x67\xf1\xaa\x2f\x2d\xb1\x3f\x38\x1c\xe2\x58\x51\xd9\x5f\xa4\x99\x64\x39\x6a\xf5\x96\x53\x5b\x5d\x09\x28\xb0\x5c\xc8\x74\x71\x67\x1b\x56\xf8\xb0\x1c\x96\xda\xd9\x96\xb7\x15\xe1\x9e\x16\x9a\xa9\xf3\x5d\x34\xca\x9f\x32\x7d\x53\x3d\xc9\x7d\x27\xaa\x7c\x3a\x92\xed\x18\xb1\x0d\x05\xbc\xe9\x25\x07\x91\x4a\xdb\x25\x1d\xd1\xee\x83\xb6\xfa\x5d\x63\xb3\x6d\x23\xbe\x6d\xa7\xd4\xe5\x7d\xdc\x00\x76\xc0\x6b\x89\xac\x95\xb8\x26\x20\xc4\xb0\x36\x47\x3e\xa1\xc1\x52\x2c\x81\xfd\x07\xe4\x25\x0d\xd4\x8e\x31\x03\x6f\xab\xc0\xc7\x08\xc0\x6b\xef\x1a\xc1\x54\x75\x91\x16\x52\xe4\x77\x7a\xef\xd8\x6c\xd6\x65\xb5\x2d\x58\x1d\x40\xe9\xfb\xeb\x6f\xf3\xd0\x75\x89\xc9\xd1\x66\x73\x85\xba\x83\x8a\x99\xd6\x6b\x27\x82\x6a\x7f\x5c\xc4\x6d\x0e\x4f\xae\xd3\xf3\x44\x8a\xbc\xbf\x2a\x58\xfe\xfc\x1c\x02\x66\x3a\xc1\xe0\x39\x9f\xe7\xea\x2b\xc3\x7e\x00\xf2\x1d\x88\x42\x5b\xb9\x7b\xfd\x48\x71\xe4\x66\xf6\x7b\x71\x96\x66\xac\x73\x92\x2c\x92\x3c\xd5\x05\xba\xb5\x02\x2f\x2f\x72\x71\xc5\xda\x72\x7e\x86\xc6\x15\x9d\x8f\x17\x82\xb3\x40\xc9\x96\xf5\x8e\x84\x61\xa0\x88\x58\xe3\x93\xa4\xcd\x41\x24\x09\xed\xea\x7e\xde\xdf\xc9\xea\x5b\x9f\xf3\x74\x0e\x50\x48\xb0\x8d\x90\x8c\xa6\x1a\xe2\xc4\x80\xa1\x92\x82\xba\x0d\x3f\x0b\xc3\x8c\xac\x68\xda\x3f\x67\xf2\xc7\xc2\x60\xe3\xe6\xda\xec\x9d\xcc\xaa\xb3\xe4\x6a\x7c\x19\xaf\xc8\x5c\x7b\xdf\xbf\xd3\xc4\xbf\xa8\xb2\xe7\xe3\xfd\x78\x4e\x96\x54\xf6\xcf\x92\x02\x10\x6c\xc7\x77\xe8\x1a\x55\x3f\x31\x8e\x03\x8f\x62\x2e\x6a\x42\xe0\xba\x24\x5c\xbb\x5c\x42\xbc\x0e\x20\x18\x22\x6c\x57\x33\x31\xd3\xcd\x49\x3c\x56\xdb\x13\x46\xf6\xe9\x09\x90\x62\x2c\x4b\x5f\xaa\x2d\x9a\x9e\xa3\x84\x2c\x31\x26\x37\x28\x01\x94\x7a\x9f\xcc\xdc\x82\x03\x5b\xf2\x3c\xe1\x73\x71\x85\x70\x0d\x45\xc2\xee\x06\x43\xb2\xd0\xab\xe0\x13\xbd\x45\xde\xa2\x39\x56\xb4\x6a\x05\xbc\xdf\x89\xc4\xe4\x77\x7b\xbe\xb3\xdb\x32\xf9\xd4\x6f\x70\x14\xf4\x7b\xd5\x93\xdf\xfb\x09\xd4\xe4\x35\xec\xb3\x1a\x91\x36\xbe\xe0\x41\x3c\x1a\x79\x4c\x53\xe5\x43\x04\xf0\x32\x4f\x8f\x4f\x02\x5c\x6a\xed\xc3\x7b\x74\x81\xcc\xcb\x7e\x18\xcc\x0f\x08\xaf\x55\xd6\x6f\x08\x9b\xc5\x7e\x5a\x33\xd9\x7d\xaf\x1a\x71\x3a\x46\x60\xbb\x7a\x8c\x30\x8e\x3f\xf5\x5b\xf6\x17\xc4\x48\xf0\xf1\xf8\x63\x40\x66\x75\x7f\x74\x39\x3e\x46\x6b\xdd\xcd\x58\x17\xb0\xdd\x8f\x59\x89\x5b\x1c\xa2\xbd\xf1\xe1\xf4\xb9\x77\x28\xbb\x64\x77\xea\x24\xa0\xaf\xb2\x11\xa7\x91\xbd\x64\x7f\xee\x1d\xca\xaa\x42\x60\x4e\x62\x0b\x09\xca\x77\xf2\x91\x3a\x41\x80\x11\xd5\x17\x24\xe0\xb8\x06\xcc\x55\xe5\xbf\xa5\x7a\x00\xc8\x73\x3a\x79\xab\x2a\x99\x8e\x7c\xdb\x5d\x37\x0b\xcb\x9e\x3a\x80\x55\x83\xf7\x05\xf2\xfa\xe7\x42\xa5\xaa\x8a\x5e\x51\x6f\xe3\x7a\x0d\xb8\xf7\x8a\x2b\xbd\xea\x51\x86\xc3\x10\xbc\xed\xc7\x96\xc9\x26\xf3\x39\xe0\x6f\x5b\xda\x40\x27\xe4\x33\x26\x89\x63\x09\x5b\xf9\x2f\xc9\x07\x8c\x63\x45\x04\xaf\xc2\x10\x39\x0f\x9d\x2b\x71\xcd\x1e\xac\xa8\xad\x08\xd4\x05\x4d\x7e\xa1\x26\xf6\x77\xba\xd6\x14\xeb\x24\x4a\xd2\x3e\x69\x6f\x89\xde\x43\xde\xe4\x6c\x11\xbf\x23\x8a\x59\xc5\x6d\xea\xcd\xe0\xe3\x8f\x27\x6f\x02\x92\xd0\x1b\xd0\x98\x7c\x44\xb0\x3a\x4c\x2d\x78\xd4\x4e\x43\x09\xe0\x66\xa0\x86\xd6\xcd\x91\xc6\x3b\x75\x62\x4b\x69\x62\x9c\xbd\xcd\x79\x04\xa4\x59\x9c\x2e\x50\xde\x77\xac\x13\xad\xb5\xf7\xb1\x8e\x47\x97\x95\x36\xa4\x3d\x29\x70\x83\x9d\xf4\x2f\x72\xb6\xa0\xd2\x37\x26\xae\xe8\xa9\x6a\xb1\xf6\xfd\x9e\xd1\xe7\xee\x60\xbe\xea\x0d\xf0\x68\x66\x22\x3e\xe9\xec\xe7\x74\x46\x2a\x6a\xe7\xd5\xa0\x25\xa5\x11\x7f\xda\x3f\x5e\x42\x88\x05\x83\x5e\xd2\x3e\x9a\x9f\x8e\x3e\xbe\x7b\xfe\xf2\xe8\x7f\x7b\x40\x73\x0f\xbf\xec\x4f\x8c\xa9\x05\x62\x91\xf8\x9b\xc6\x55\x9f\xef\x95\xf0\xff\x7c\xb2\x9a\x52\x33\x9a\x7f\x6e\x24\xab\x4f\xea\xd1\x3c\x17\xf1\x17\x72\x2e\x5e\x24\xb3\x4b\x5f\x88\xfb\xa2\x64\x7b\x95\xfb\x5a\xfb\x46\xd7\xf3\x54\x16\xa0\x3e\xd6\xf9\x92\x63\xbd\x20\x64\x5b\x29\x44\xd2\x4f\x7d\x27\xa6\xa3\xca\x61\xfb\xc5\x66\x83\x5e\xa3\x01\x26\x2f\xc0\x86\x6d\xdb\xaa\xf9\x45\x18\x22\x58\x74\xaf\x55\x63\x30\x91\xa0\x70\xcd\x60\x65\xb6\x30\xc4\x4f\xfd\xba\xb4\xec\x7d\x0a\x3e\xe3\x7d\xe0\xb5\x0e\xe7\xaf\xea\x73\x3a\xaf\xdf\xcd\xd6\x55\xd9\xcb\x92\x63\xda\xa6\x4b\xa9\x94\x41\xe3\xea\xb1\xd5\x32\x41\x8f\xfd\x58\xff\x89\xab\x5b\x83\xfe\xf9\x98\xf7\xcf\x63\x5f\x7f\xf7\xb9\xea\x47\x75\xb8\x11\xf5\x6e\x1a\xb9\x9d\xe1\x92\x88\xc5\xa2\x9e\xd5\x26\xb8\x7b\x41\x3c\xba\x94\x32\x3d\xdd\x4c\x6e\x03\xf5\x75\x58\x49\x0a\x3f\x03\x60\x95\x19\xe5\xa4\x4d\x06\xf7\x63\x83\x30\x7d\xf7\x6d\x04\xef\x0f\xb4\x01\x56\x50\xb3\xe8\xa8\xe0\xd0\x48\x4a\x32\x1a\x9c\x1a\x5c\x69\x1d\x2f\x79\xc7\x40\x04\xec\x04\x3d\x84\x8e\x27\xa9\xca\xd7\xc3\x7b\xba\xe2\xe9\x1f\x2b\x76\x9a\xce\x4f\x4f\x83\x29\x55\x99\xd3\xcd\x26\xc2\xbd\x01\xee\x05\xa7\xa7\x80\x29\x59\x33\xd6\x73\xc1\xd1\xcd\xb1\x51\x9a\xf1\x04\xe3\xd8\x56\x0b\xba\xcd\x46\x25\xe0\x3e\xbb\x4a\xa5\x64\x39\xfd\xac\xad\xd3\x6c\x04\x5d\x4c\x64\x89\x22\x32\x53\xf2\x8b\x24\xcc\xee\xa7\xde\xad\xb9\xbb\x34\x56\x82\xa1\x1f\xb5\x7f\x2b\xe0\xcc\xc8\xc5\xa7\x5f\x97\x78\x92\x4d\x75\x00\x1a\xf3\x61\x30\xa4\xeb\xcf\x2c\x7a\xc8\xcf\x69\x96\x7d\x62\x33\x96\x5e\xeb\x60\x07\x4d\x5c\xf1\x0a\x8c\x50\xb7\x13\x62\x78\xeb\x16\xeb\x8e\x2b\xf9\xb0\x51\x06\xd4\x08\x3a\x36\x19\x42\x09\xcd\xb1\xda\x76\x53\x2a\xf0\x18\x30\xba\x37\x9b\xc1\xa3\x84\xd2\xc1\xa3\x34\x4e\xba\x34\x09\xc3\xb4\x4b\x53\x3c\x96\x34\x8a\x91\x6c\x3b\xf7\xf2\x31\xd7\x77\xe3\x9f\x20\xc0\xae\xdc\xd0\x08\x87\xa1\xdf\x29\xb5\xf8\x11\xb3\x18\x49\x66\x33\x4d\x48\xaa\xba\xda\x04\x64\xc7\xbe\x6e\xd5\x34\xdb\xea\x6a\x4a\x35\x0b\x1e\xda\x0a\x44\xad\xf6\x86\xfa\xf3\xdd\x92\x15\x14\xa1\xdc\x8e\xac\x40\xb8\xaf\x6f\xfc\x01\x70\xf1\x8f\x55\x9a\xb3\x39\xc9\xad\xa6\xc6\x27\x68\x4f\x8f\xbe\x35\x4f\xf2\x61\x9a\xd1\x77\x7d\x46\xc5\xc9\xd4\xfc\x03\xe8\x01\xc2\x25\x61\x7d\xc1\x9b\x38\x89\xa0\x3b\x51\x23\x85\xa2\x0d\xab\x85\x20\xc3\x21\xc7\x70\xf3\x65\x91\x18\xdb\xea\x54\xb5\x3a\x5a\xe4\xd6\xe8\x21\xa7\xbc\x8d\x16\xbf\x8d\x90\xec\x2d\xb9\xdf\x16\x0d\x11\xe9\xa7\x18\x3b\x2c\x39\xfe\x14\xcb\x1a\x91\xbe\x4a\xe7\xef\x9b\xa1\x95\x7c\x60\xcc\x49\x36\x35\xf4\x50\x25\xf4\xd5\x40\xc0\x17\xcc\xf8\xe0\x91\x17\x8d\x49\x4f\xfb\x37\x35\x87\x8d\x3f\xc5\xdb\x6b\xe6\xc7\xed\x60\x4f\x5f\x6f\xd1\x62\xd1\x68\x92\xaa\xd6\x8e\xfc\x7d\x14\x5a\x55\x30\x6e\x56\x78\xce\x24\xc2\xba\x71\xf7\x51\x39\xaa\x75\xd8\xe9\x24\x9b\xd6\x53\x63\x36\x89\xa6\x31\xc3\xba\x7d\x40\x6f\x66\x95\xeb\x51\x2b\x09\x6f\x2c\x0c\xd3\xc4\x95\x6d\x8f\x5d\x1a\xc9\xf6\xd2\x20\x09\x26\x6b\x07\xe9\x52\x54\x78\x2e\xab\xd2\x2a\xa6\x4e\xe9\x07\xf8\xd0\x7b\xca\xd1\xde\x93\x27\x87\x98\xbc\x05\x75\xfc\x7b\x25\xc9\x21\x8e\xf6\xf7\x77\x31\x31\xf6\x9d\x98\xbc\x53\x49\x07\xfb\xaa\xd8\x36\x95\x9d\x22\x0f\xaf\x65\x9e\x16\xcb\x2c\xb9\xfb\x90\x5c\x69\xd8\x16\x4c\xbe\xd0\x77\x28\xf8\x24\x56\x92\xe5\x3b\x6f\xf4\x51\x3e\xc0\xe4\x55\x95\x1a\x60\xf2\xba\x9d\xd9\xc3\x32\xd6\x41\xf6\xcd\xe0\x82\x9e\x17\x10\x84\xd4\xc2\x95\xcd\x05\xeb\x44\x25\xe9\xae\x5e\x6c\x52\x49\x78\xff\xd4\x01\xdb\x2a\x09\x84\xf7\x4f\x6d\x18\x22\x53\xc6\xba\x9d\xa9\xda\xd2\x99\xdb\xef\x10\xef\xaf\xb8\x16\x51\xa8\x57\x31\x24\xd4\xef\xb1\xfc\x4f\x8c\xb9\xb7\xea\x6b\xe7\xbe\x96\x0f\x03\xbc\xa0\x9a\x72\xc7\x05\x18\x26\x1c\x56\xc0\x4a\x42\x38\x97\xf7\x89\x9c\x5d\xb4\xe1\xd0\x2c\x13\x79\x11\x07\x8f\x02\xb2\xca\x33\xf8\xbb\x4c\xf2\xe4\xaa\x88\xd7\x25\x49\x8b\xa3\xdb\x64\x26\x63\xa3\x6c\x33\xb1\x8f\xbe\xc6\x58\xee\x5d\xfc\xfe\xf0\x45\x26\x52\x5b\xa3\x23\x66\x0d\xb6\x74\xbc\xb5\x78\x89\xbf\x79\x9d\xdb\x19\x08\x43\x54\xfb\x8d\x30\xd9\x6a\xdc\xa0\xbd\x71\xe6\x8a\xf8\xc1\x2d\xaa\x61\x15\xf0\xca\x61\x1f\x59\x83\x97\xb5\x99\xff\xd8\x5b\xe5\xf6\x86\xaa\xde\x59\xbd\xa8\xdd\x81\xfe\x4a\x4d\x60\xbc\x3d\xa7\xa8\xa5\x70\x75\xcd\x4e\x6a\xb4\xe8\x7f\xb4\x96\x51\x6e\xa1\x2e\xa1\x2f\x5e\xd3\x2d\x1b\x8a\x5b\x58\x93\xd6\xeb\x13\xdd\xbb\xed\x4e\x81\x84\xd9\xe4\x45\xde\x8f\x91\x3e\x46\xdf\x2b\xac\x3d\xec\x5b\xa5\xd7\xef\xb6\x20\xc6\xdb\x04\x31\xfe\x0d\x34\x6a\xf6\x19\x0e\xb9\x86\x1a\x6b\x69\x3e\xfb\x50\xac\xa3\x24\xf5\x6a\xef\xc3\x40\xb6\x95\xe8\xfc\x46\xcd\x3a\xb1\x51\x35\x61\xf5\xca\x1f\xa2\x6e\x57\x91\xce\x6f\x56\xaf\x53\xdb\x9a\x7e\x2f\x25\x1b\x4f\xd7\xfa\xc4\x91\xdf\xe9\xba\x24\x3f\xfb\xf7\x34\xdf\xb5\x63\x8e\xe9\xe3\x1e\x28\x6d\x5a\x6e\xa4\x0d\x43\x19\xb3\x26\xba\xde\xef\x13\xe6\x9c\x29\xd4\xb3\x39\x2c\xbe\x45\x18\xc6\x21\xcd\x98\x77\x82\xfb\xf9\xe9\x80\xed\x85\x21\xbc\x44\x25\xf9\xb9\xd7\x03\xa1\x5c\x6d\x8a\x64\xbd\xcc\x99\x94\x77\xda\xbe\xcc\x35\xf6\x47\xe4\xac\x3b\xdc\x42\x9a\xc3\x2a\x02\x6b\x32\x29\x48\xa2\x98\xdb\xaa\xb8\x20\x69\x75\xc1\x9b\x84\x61\x32\xba\x77\x81\xdb\xcd\xb1\x19\x06\x92\xe3\x35\xf7\x2f\xde\x55\xcd\x6e\xa1\x53\x5e\x5f\x7f\xa4\xa0\xe9\x58\x1b\x8e\xc7\x89\x3d\x8f\x93\x15\xbd\x41\xf9\x78\x4b\x75\x24\xc6\xdf\x21\x41\xf2\xbe\x66\xd4\x38\xf6\xf4\xe4\xc2\xd3\xc1\x7f\x87\xaa\xbb\xde\xaa\x74\x89\x63\xe1\x46\x30\x1b\xa3\x02\xad\xb4\xa3\x25\x8e\x9b\x7d\x7b\x41\xd6\x86\xe8\xfd\xe3\xa1\x7a\xa1\x24\x96\x66\xe3\xba\x10\x5b\xd9\xcf\xdf\x20\x35\x9e\x78\x94\xd3\x84\x08\x5f\x95\xbf\x22\x70\x17\x02\x17\x15\x25\x86\x86\x19\x15\x1f\xf5\x2e\xa7\xc3\x30\xb7\x9a\x79\x95\xac\x1f\x55\x22\xe8\xdb\x55\x92\x7a\x50\x09\x1a\xd2\x56\x68\xb4\xc1\x0b\x94\xdb\xbb\x6f\x73\x5b\xbb\xd9\xe8\x06\x4b\x11\x8b\xd2\xdd\x59\xfe\xa4\xe8\xf8\x8d\x4f\xc7\x7f\xb4\xaa\xa0\x15\xb1\x6e\x1b\x1a\xcb\xcd\x66\xcb\x6e\x49\x17\x87\xcd\x54\x96\x8e\x09\x11\xd8\x2c\x13\xa9\xe9\x8b\xa9\xdd\x94\x24\xd4\x07\xf5\x10\x24\x05\x62\xc8\xd3\x99\x24\x19\xf5\x31\x30\x52\x52\xa8\x2c\xc6\x35\x22\x0c\x59\x51\x1f\xc5\xa2\x30\x93\x38\x99\x56\x1a\xeb\x7e\x0e\x48\x61\x35\x73\x28\x1b\xcb\x2a\x0c\x03\xb0\x60\x69\x86\x23\x93\xd8\x05\xe1\xd5\x2b\xa3\xf5\x0e\x2d\xe8\xc9\x3e\xe3\xf3\x9e\x0d\x02\xa1\x1e\x5c\xc3\x72\xfa\xd3\x84\x4f\x37\x1b\xa4\xfe\xa8\x31\x83\x88\x99\xde\x52\xce\xed\x52\x16\x14\x34\xf4\xeb\x9c\x9d\xb3\xdb\x65\xfc\x16\x61\xc4\x88\x20\x12\x93\x4b\x76\x57\xc4\xc2\xdd\xbc\xbc\x31\x6b\x5b\xbd\x49\x13\xf2\x46\xad\xed\xa4\x44\x9c\xac\x19\x9f\xc7\x09\xd1\xad\x88\x33\xe2\x5a\x11\xaf\x4a\x4c\x04\x55\x9b\xb3\xaa\x9b\xa4\x14\x68\xa3\x20\x05\x15\x7d\x76\xcb\x66\x8a\x73\x40\x10\xb9\xda\x08\x68\x0c\xc8\x62\x12\x4d\xc9\x9c\x16\xe6\x86\x72\x80\xc9\x82\x2a\x82\x9c\xd9\xf6\x24\x61\xd8\x5d\x68\x63\x40\x3d\xc9\xdc\xca\x4b\xfa\x4e\x1d\x14\xe9\xb3\x71\xf0\x28\x88\x67\x4e\x6e\x5a\x58\x59\x2a\xdd\x9e\x98\xba\x2b\x24\x9b\x48\xb0\x20\x9f\xd2\xf9\x84\x4f\x09\x2b\x31\x59\x97\xb8\x2c\xcd\xd2\x04\x9a\xfd\x81\xfa\xbc\xa5\xcd\x5f\x91\x3f\xb8\x49\x3a\x8b\x55\xd8\x2a\x21\xf8\x71\xfe\x40\x44\x5d\x3b\xf5\xea\xdd\x3f\xcf\xfd\x72\xbc\xce\x7d\xee\x27\xb4\xd0\xb8\x2c\x9c\x8c\xb2\xd9\xe4\xbe\x5e\xca\x66\xd7\xb8\xf2\xb8\x35\x35\xb6\xa9\x6a\x22\xc6\x7f\xf8\x6c\xce\xe4\xe0\x38\xef\x83\xbc\x44\x52\x9f\xf5\xe4\xa4\x92\x27\x85\x11\xa8\x92\x12\x03\x3b\xd6\x18\xda\x05\xad\x02\x9b\x93\x95\xfa\x61\xf7\x3e\x32\x83\xc0\xd6\x6a\x8c\x46\xad\x36\x8a\x05\x0e\xc3\x16\xdd\x13\xf0\x12\x87\x8b\xdb\x07\x28\x5b\x70\x76\x29\x20\xda\xb9\x81\xe5\xfc\xba\xdc\x98\x96\x24\xd5\x7d\x1a\x17\x6d\xa6\x03\xc5\xb8\x40\x29\x8e\x8b\x78\x35\x6e\x56\xb6\x22\x29\x8e\x67\xe3\x99\xca\xbf\x07\x1a\xdb\xbe\xae\xa9\x0d\x6e\xd4\xbf\x22\xb2\xfd\xe3\xff\xd3\xd4\x48\x12\x60\xbb\xf7\x53\x64\xf5\x0d\x37\x75\xf6\xd6\x93\x37\xcf\xe6\xb5\x3d\xdf\x19\xbc\x26\x61\xd8\xc4\x03\x45\x1c\xe3\xb5\xa0\xdc\x20\xc1\xf8\x64\xbc\xd9\xd8\x5f\x8b\x5c\x5c\x8d\x12\x9a\x8d\xff\x40\x69\x45\xd8\x1e\x15\x5b\x5a\xd5\x7c\x28\x2b\xb1\xa3\xf6\xb2\xc4\x98\x24\xe3\x3a\x4c\x30\x12\x1e\xd5\xa7\xa4\xbe\x92\x92\x12\xc7\x2e\x4e\xf5\xf6\x94\x57\x28\x9e\xd0\xe4\xbf\xdf\x77\xcc\xf6\xbc\xa1\x09\xdf\x36\xf1\xf0\x81\x06\x38\x26\xda\xd1\x92\x83\x87\x65\x3e\x11\xbe\x89\x87\x98\xfa\xf7\xb2\x4a\x5e\x35\x44\xc4\xc8\x44\x4d\xbd\xb7\xd7\xb9\xb3\xbb\x11\xaa\xe8\x47\x7b\x41\xab\xa4\xc0\x3a\x79\x99\xe3\xf0\x43\xe4\x75\x0f\x4d\xbd\x26\xf5\x03\x9b\x95\xe0\x1e\x3a\x11\x95\xdf\x70\xe2\xf9\xb5\x15\x26\xf4\x3e\x1b\x22\xb8\x33\xfa\xa5\xfd\x95\x2d\x2f\xa8\xf1\x0d\x62\x55\xd0\x73\xa2\x5f\xfe\x9e\xb6\x22\x5d\x13\xc6\xa8\x8f\x75\x3b\xaa\x04\x78\x90\xe0\x19\xfd\xde\x28\x6c\x18\x65\xfe\xf6\x05\xda\x00\xcb\xd8\x53\xce\x21\x50\x2e\xb0\x71\xa3\x55\x67\xb0\xc0\x04\x7f\x99\xa5\xb3\x4b\x92\x29\x36\xfc\x5c\x4f\xc5\x24\xb0\xe5\x03\x12\xd8\xd2\x01\x09\x4c\xd9\x60\x8a\x81\x0d\xcb\x24\x3f\x67\x92\xac\x7c\x06\x9e\x29\x89\x14\x4a\xd5\x35\x1d\xf9\xdd\x5a\xc9\x4b\x55\xa8\x42\xe9\xec\x26\xfb\xcb\x9c\x5d\xab\xa3\x99\x76\x0d\x50\xc7\xfd\xd2\xc3\x97\x86\x3c\x36\xdf\x6c\x22\xb8\x28\x3f\x5b\x49\xa9\x18\x41\x11\x86\x01\xc4\x73\x51\x22\x53\x51\x77\xfc\xb7\xf1\x39\x11\xeb\x5f\x31\x99\xfc\xc0\xee\x36\x1b\x08\xb8\x6f\x9e\x66\x32\xcf\xcc\x23\x18\xd0\xfd\xc0\xee\xac\x6f\x63\x4b\x6b\x12\x08\x2a\xed\x5d\xcf\xe5\x6c\x41\xbf\xef\xea\x09\xc8\x37\x1b\xb1\xb5\x37\x04\x49\x40\x56\x00\xac\xcf\x1f\x9a\x94\x6a\xe7\x4a\x2a\x23\x13\x31\x96\x2c\xd6\x22\xa7\x3d\x64\x64\xfa\xe0\x53\xf8\xf3\xb8\xaa\x4d\x97\xab\x29\x20\x81\x79\x2b\x20\x81\x14\x01\xa9\x66\x72\x8a\xff\xf3\x13\x92\xf0\x4e\x48\x33\xfa\x0b\xfa\x15\x65\x84\x57\x6a\xda\xda\xf3\x9c\xce\xc6\xa2\x5f\xa9\xd3\xd1\x0c\xc7\x41\x40\x16\x8d\x93\xc6\x45\xce\x16\xf1\x9c\x58\x2a\x8b\xb7\x42\xfd\x37\xbf\x21\xe9\x19\xf2\x7e\x53\x4a\xcf\xd0\x2f\x88\x61\x3c\x42\xe9\x66\x23\xc7\xc2\x8e\x5b\x2c\xe0\xb4\x06\x8e\xab\xd5\xf4\xe9\x89\x1b\x2f\x60\x16\xf3\xcd\xa6\x88\x17\x6e\x54\xe9\xb6\xd3\x48\x42\x16\xd8\x04\x5f\xcd\xd9\x3d\x2b\x54\xdc\xb7\x42\x85\x5a\xa1\x82\xd1\x9c\x61\x22\xee\x23\x83\x49\x90\xe4\x69\xb2\x63\xe0\xad\x83\x69\x9d\x18\x82\x65\x72\xce\x02\x43\x10\xc9\x4c\x89\xd1\x2f\xb3\xa4\x28\x20\xfa\x77\x56\x95\x4c\xc7\x81\xce\x0d\x62\x7d\x28\xd1\xbf\x4e\xe4\x5d\xa6\x8e\x25\x5c\x7b\xc5\xc0\x5b\x33\x77\xce\x99\x2b\x8a\x2a\x9e\x43\x49\xb2\xa0\xd5\xa8\x92\x65\xed\x58\x73\x51\x9d\x7f\xae\xe1\x51\x55\x7a\xae\xa9\xf2\xce\xa7\xca\xb3\x1a\x55\xd6\xfa\x45\x82\x46\xeb\x5d\x0a\xb4\x31\x20\xc1\xcc\xcb\x81\xf6\x29\xea\x35\xad\x0b\x48\x60\xdb\x16\x90\xc0\xb5\x2c\x00\xb7\xa6\x14\x8a\x16\xa6\x9a\xff\x09\xaa\x5f\xa8\xcd\xdf\x0d\x4e\x0a\x94\x7f\x4e\x04\x56\xff\xdf\x50\x4f\x08\xb8\xa5\x37\x61\x78\x53\x85\xf9\x41\x93\x7e\xef\x6f\x63\xfa\xff\xba\xf1\x77\xeb\x12\xe1\xc9\x3f\xa7\x9b\x47\xff\xfc\xe7\x14\x3f\x3a\x27\xc1\x3f\xff\xf9\xdd\x20\xc0\xe4\x88\xde\xd6\x25\x64\x2d\x35\xdc\x12\x18\x83\x78\xe6\x9d\x9f\x96\xf6\x50\x75\x61\x84\x02\x72\x49\xbb\x5d\x34\x1f\xcf\xd1\x11\x11\x38\x3e\xc2\xe4\xa4\x4d\xdb\xb7\x1a\xaf\xd0\x25\x8e\x57\xe4\x65\x5b\xee\xf5\xf8\x5a\xe5\x5e\x8f\x2e\xc3\x10\x9d\xd0\x6f\xb3\x09\x95\x75\x9b\x50\x0d\x9b\xc3\x74\xc0\x3c\x75\xc4\xf4\x83\xe2\x55\x33\xf0\x90\x95\x6a\x89\x6d\x40\x94\x4e\x80\x4b\x74\x42\x32\x4c\x5e\xfa\xcc\xe2\x25\x29\x8c\x13\xc4\x6f\x55\x72\x9d\xc8\xe2\xcb\x30\x4c\xcc\x75\xa7\x23\xa7\xf8\x84\x00\x6d\xc4\x2f\x89\x14\x4a\x4a\x3f\xab\xbc\x85\x98\x3a\xe2\xb3\xf1\x6f\x96\x1b\xdc\xc5\xbf\x55\xdc\xe0\x6e\x8b\x1b\x70\x46\x7e\x33\xec\x40\xdf\x18\x31\x92\x32\x92\x31\x08\xab\x1b\x45\x98\x14\xac\x25\xd2\xb1\x95\xb6\xd9\x0d\xe2\x9b\x0d\xe2\xf4\x63\x2e\xae\xd2\x82\x61\xdf\xcd\x4d\x90\xc4\x13\xd8\x52\xbb\x69\x16\x28\xd7\xf0\x05\x0c\x7b\x1e\x07\x09\xaa\xe1\x2f\x66\x7e\x69\xd8\x55\x1f\x2c\x5e\x38\xcd\xce\x88\x01\x26\xc2\x58\x58\x4d\x2f\x8e\x41\xac\x33\x5a\x5f\xdf\xa3\x81\x8f\x65\xac\xa6\xbc\xa1\x0f\x01\x93\x14\x8c\xb1\x8e\xf7\x92\x92\x0c\x97\x05\x42\x39\xcd\x9d\x54\x28\x37\x9b\xc9\x14\x63\x0b\xc2\x00\x72\xec\x8a\xb5\xdd\x61\x68\xe8\x71\x92\xd2\x75\x96\x9c\xb1\x2c\x8e\x14\xe9\xd7\x6e\xb6\xd2\x05\x1a\x84\x60\xfe\x6e\x00\x15\x26\x03\x47\x5d\xea\xb9\x24\x32\xbf\x2b\xe2\xc9\x94\x88\xa5\xfa\xe3\x2e\x2b\x12\xba\x56\xdf\x8f\x33\x14\x61\x02\xef\xc6\x19\x1a\x28\x9e\xae\xb2\xe3\x0c\x0d\x71\x49\x1e\x70\xb9\x47\xc9\x16\xa8\xc0\x3d\xca\xc5\x12\x93\x64\xe4\xcd\x4c\xb2\xed\xa9\x95\x6d\x27\x25\xfa\x58\x82\x5b\x81\x13\xfe\xce\xb8\xfe\x66\x27\x2d\x3a\x49\x96\xb3\x64\x7e\xd7\x61\x1a\xa8\x8f\x9f\xf7\x03\x8d\x23\x32\x4a\x47\xd8\xc4\x6d\xe7\x74\x40\xc0\xb9\x89\x0e\xc3\x64\x12\x4d\xc7\xb9\x81\xa5\x88\xcd\x2f\xf8\xcc\x66\x83\x90\xbe\x8d\x51\x59\x38\x0c\x85\xbe\x7e\xce\x31\x84\xda\x82\x09\xc3\x61\xd8\x45\xe0\x72\x01\x39\x24\x99\x0c\xa6\x16\x48\xc3\x8e\xbb\x85\xcb\x03\x60\x59\xb0\x4c\x9d\xe8\xcf\x12\xa1\x09\x69\x8a\x89\xfa\x69\x60\xf0\xa2\xd8\xa0\xe1\x09\x9a\xd4\xb1\xed\x1c\x04\x3c\x4c\x7f\xaf\x67\x0f\xd6\xea\xa3\x44\x7d\x32\x06\xb7\x3b\x0d\x91\x57\x95\xca\x29\x14\x48\xe8\x24\x9a\x8e\x2c\xda\xa3\x2e\xf6\x24\x4e\x68\xda\x87\x13\x1c\x38\x8f\xa4\x7d\x45\x1f\x06\x23\xd7\x15\xb5\x6e\xee\x00\xc0\x8a\x04\x45\x82\xea\x82\xd8\x70\xbb\x67\x51\x18\xd6\x3c\x48\xf0\x66\xb3\xdf\xa5\x34\x01\x87\x8c\xa1\x79\xc2\x78\x9d\xd2\xc8\x55\x5b\xa6\x0b\xb4\x4b\x6d\x21\xd4\x15\x9b\x8d\x6a\xe7\x33\xed\xc5\xa1\x1e\x9f\x8a\xc9\x2e\xbc\xa5\xbb\x02\xdd\xd0\x23\xa2\xde\xdd\x77\xef\x9a\xfc\xa7\x8a\xc2\xab\xd2\xea\x17\x71\x63\xa8\xde\x10\x7e\xd1\x61\xad\xe8\x70\x4a\xcc\x38\x80\x41\x1f\x36\x2f\xa9\x0c\xf5\xd2\x57\x46\xa8\x4c\x0c\x62\x2d\x62\x24\xf5\xf9\x0a\x9d\xec\x13\x36\x25\x39\x8d\x1c\xdc\x09\xa7\x82\x46\xaa\x35\x8f\x81\x06\x0c\x45\x27\xd5\x42\x75\x93\x1a\x4d\xc7\x2a\xd9\x58\x58\x99\x09\x8e\xca\x12\x4d\x12\x92\x4d\xc1\xc8\xcb\xad\xa3\x19\xf3\x23\x8b\xb1\x9b\xce\xab\x44\x32\x34\x60\x3b\xfb\x7f\x63\xb8\xec\xd6\x38\xd2\x84\xf5\x3f\x08\x79\x22\x93\x5c\xb2\x39\x8d\xa6\x34\xa8\x7e\x06\x44\x65\x7f\x5a\x71\x9e\xf2\x73\x3a\x98\xd2\xc0\x3c\xeb\x0c\x75\x02\xcc\x98\x7a\x6d\x38\xa5\x81\xfb\x15\x94\x28\x01\x67\x17\x30\xff\xa9\x6b\xc8\xd5\x6b\xef\xd3\xa2\x50\xf5\xa9\x6f\x99\x67\x5d\xdf\xfb\xe4\xd6\xa0\x9e\xd0\xe1\x63\x95\xe9\x7e\xeb\xfc\x77\x22\x99\xb3\x39\xdd\x55\x2f\xea\x67\x9d\xfe\x3c\xcb\x7e\xce\x53\x29\x19\xa7\xfb\x2a\xaf\xfa\x6d\xda\x99\x89\x82\xcd\xe9\xa1\xca\xd3\xcf\x3a\xfd\xed\x95\x86\x12\xa7\x83\xa1\xca\xb2\x3f\x4d\x26\x9f\xb3\xdb\xaa\xc4\x1e\x94\xf0\xd3\xec\xb7\x25\xcb\xd9\xfc\xf9\x4a\x8a\xb7\x7c\x46\x07\x8f\x75\x03\xfc\x44\xd3\x88\x0b\x36\xbb\x2c\x56\x57\x27\x97\xe9\x72\xa9\x6a\x7c\x02\xcd\xa9\xa7\xd6\x8b\x5e\xa9\x62\x07\x7e\xb1\x2b\xf7\x59\x9e\x64\x77\x5f\x98\xad\x6c\x18\xc1\x67\x6b\x89\xb5\x82\x73\x3a\x1c\x78\x45\xbc\x01\x05\xae\xa9\x46\xd5\x0c\xaa\xf9\xad\x0b\xa8\x61\x64\xb6\xc4\xfe\x94\x06\x7e\x82\x37\xb8\xb6\xc8\xa1\x1d\xe1\x5a\x11\x3d\x62\xb6\xcc\x60\xe8\xc6\xba\x5e\xaa\x1a\x5c\x57\x74\xaf\x3e\xe8\xb5\xf2\x30\xc8\x66\x88\xdd\x0b\x8f\xed\xe8\xd7\x33\xea\xe3\xea\x4a\x1f\x78\x43\x5b\xaf\x5b\x0f\x93\x2d\x38\x1c\x54\x43\x67\xcb\x95\x28\x55\x44\x9e\x6a\x22\x07\xf9\x66\xce\xe8\xfa\x44\xc7\xbb\x49\x1d\x99\x93\xe7\x59\x26\x66\x2f\x92\x82\xc5\x11\x39\xe2\xe7\x29\x67\x1a\x86\xa4\x72\x86\x67\x2e\x2e\xa5\xa8\x80\x5f\xfb\x85\xd9\x01\x12\x7f\x81\xc6\x4e\xb7\x61\xf3\xcc\x8a\xb4\x19\xdc\x65\xb8\xf5\x18\x3b\x95\xf3\xd5\x58\xc4\x3e\xa4\xfa\x92\x55\xbb\x71\x61\x62\xd7\x1a\xfe\x62\xfe\xa0\x7b\x4c\xfb\x3a\x2b\x53\xbc\x66\x32\x69\xda\x2e\x35\x23\x75\x3b\x98\xd1\xeb\xec\x91\x05\x53\xd9\x41\xbf\xff\x48\x26\xc5\x65\x11\xe0\xe9\xc8\xec\x6e\xae\x08\xa8\x61\x24\xc2\x00\x38\x81\x6c\x81\x61\x5c\x79\xbb\x99\x02\x64\x32\x24\x19\xeb\x2f\x93\xbc\x50\xdc\x6e\x5a\x6a\x41\xb3\xea\xdc\xc5\x9f\xea\xdc\xbd\xdd\x62\xde\x94\x7c\xb5\x5b\xcb\x5c\x9c\xe7\xac\x28\xa0\x7f\x6d\xdd\x63\xb6\x7b\xbf\x17\xea\xb3\x8d\xee\x4d\x86\xae\xc0\x76\x7f\xae\x7c\xa6\xfe\x6d\xb3\x25\xef\x9f\x2d\xee\xba\xc5\xbf\x75\xb6\xc8\x5a\xc3\x42\xc5\xc1\xc7\xe3\x93\xcf\x81\x86\xbb\x60\x65\xb3\x97\x48\xea\xd3\x30\x60\x88\x89\xcb\xf1\x64\x38\x8d\x61\x62\x1b\x5d\x36\xc2\x9b\x1d\x10\x88\x22\xb1\xd5\xe9\xeb\xff\x8b\x49\x4c\x56\x05\xfb\x8f\x26\xaf\x0f\x55\xcc\xb7\xe7\xf0\xfc\xff\x78\x0e\x1f\x05\x3d\xd6\xd2\x31\xfe\xf0\xa2\xab\x26\xb4\xb6\xe8\x64\x0b\x91\xde\xfd\xb9\x0e\xfe\x37\x32\x13\xd5\xb5\x8a\x42\x5f\x1d\xbd\x3b\xfa\x7c\x14\x6c\x11\x67\xc7\x63\x1f\xdb\xad\x3f\xfb\x3f\x6d\x7d\x2f\x78\xb4\xc8\x05\x97\xfe\x42\x7b\xfe\xf9\xe5\x9b\x3f\xdb\x8b\x9b\xff\xeb\x5e\x9c\x25\xb3\xcb\xff\xb4\x13\xb7\xff\xc6\x4a\x21\xfc\xfe\xb5\x92\xbb\xce\xe4\x7f\x8a\x8d\x9f\x65\x6c\x2c\x69\xd0\x03\xbc\x00\xf6\xe3\xa7\xb7\x4e\xed\x81\x18\x6e\x59\x4a\x48\xd2\xdc\x71\xbf\x06\x9f\x80\xb3\xa6\xcd\x25\xb2\x2f\x2e\xb1\x63\x1d\x7c\x3a\xb2\x0c\xb1\xc6\x09\xc1\xd7\x97\x51\x8e\x1e\x1f\x1e\x3c\xc1\xe4\x52\x3d\xee\x47\x83\x08\x93\x13\x06\x38\x94\xbb\x7b\x98\xbc\x84\x02\x83\xc3\x21\x26\xbf\xc1\xed\xca\xc1\xe1\x3e\x26\x1f\xa1\xc0\xde\xee\x2e\x26\x9f\x00\x79\x6a\x77\xb8\x8f\x8d\xb9\xeb\x31\x6b\xba\x31\xe8\x00\x32\x9e\xb3\x06\xf3\xdc\x19\x1a\xb0\xb6\xba\x68\x85\xbe\xe7\x29\x15\xaf\x92\xe5\x03\x61\x48\xef\xf1\x76\x9e\x80\xaf\xde\xb4\x35\x2e\x72\x18\xa2\x68\x2b\x10\x21\x46\x0c\x8f\x55\xb1\x98\x19\xcf\x3d\x3f\x28\xef\x07\xd6\xb0\x46\x30\x70\x98\x13\x39\x1d\xab\x7f\x6c\x84\xe9\x89\x9c\x56\x2f\x9d\x42\x7f\xab\x9b\x66\xd5\x7f\xa7\x01\xc3\x7e\xb0\x24\x0d\x5d\x54\x29\x0b\xbd\xef\x00\x90\xdb\x58\x4e\xf8\x34\x66\x13\x3e\x2d\x99\x71\x65\x95\x54\xaa\xbf\x23\x63\x4e\xd4\x36\x9c\x00\xd1\xe9\x50\x14\x52\x80\x92\xc6\xa9\xae\x30\xf1\x80\x1d\x26\xe9\x94\x26\x50\x18\x10\x07\x74\x24\x6b\xa3\x80\x5d\x97\xae\x82\x42\x63\xca\xad\xd5\x41\x77\x52\x4c\x71\x85\x9d\xaa\x7e\xfa\xf0\xa9\xc6\x21\x4b\x25\x4f\xf2\xe9\x28\x9b\x98\xa7\x29\xe5\x68\x85\xcb\x6c\x52\xa8\xa7\x02\x97\xf7\xc0\xaf\x66\x93\xc4\x94\x4e\xbc\x98\xf5\x9d\xac\x44\x9c\x54\x96\x59\x3e\xaa\x50\xd2\x46\x07\x2e\xbe\x40\x32\x49\x01\xda\xaf\x75\xda\x33\x6c\x31\x2a\x60\x68\x38\x59\xe9\x07\x41\x66\x94\x4f\xd2\x29\x99\xd3\xd6\xf7\x20\xbc\xea\xcc\xe8\x35\x53\x3e\xea\xae\x40\x27\xd6\x9d\x8f\x57\x9b\x4d\xb7\xd8\x6c\xe6\xe3\x55\x18\x16\xf7\x10\x9b\x09\xc3\x9a\x4e\x75\xe5\xbe\x36\x1a\x23\xd0\xe1\x1d\xdd\xa6\x20\x69\x7b\x51\x3b\x33\x4c\x52\x1e\x57\xdf\x24\xec\x36\x95\xf1\x07\x86\x32\x12\xa8\xc7\x80\x30\x4c\x18\x97\x2c\xb7\x89\xea\x59\xa5\x96\x18\xc7\x0f\x7c\x2d\xe5\x71\x77\x50\x3e\x58\xe4\x81\x06\x75\xa3\x3f\xd3\x10\xad\x81\x07\x2e\xf4\xde\x81\x5b\xc3\x95\x44\xab\x12\xb1\xd3\x08\xd9\xad\xb8\x41\x9b\x53\x15\x53\x4b\x0f\xe3\x92\xbc\x65\xf7\x99\x5d\xb8\x8b\x4e\xb5\x5e\x00\x97\xb6\xb2\xf6\x64\x9e\xa5\xfb\x05\xc4\xbd\xd4\xdd\xd5\x9d\x45\x11\xf9\x04\xd7\xdd\x79\x15\xc4\x38\xb7\x16\xf1\xc6\x59\x40\xc7\x81\x5d\x1b\x1b\x69\x75\x7e\xea\x46\x25\xf1\xeb\x8a\x05\x59\xa4\x79\x21\x75\xa4\x68\xc8\xce\x4b\xdf\xbc\xc3\x28\x3b\xf2\x6d\xbb\x5c\xf1\x0d\x76\xb9\x57\x0d\xc3\xf1\xca\x42\xfc\xfe\x16\x0e\xca\x12\x97\x44\x7c\x9b\x05\xad\xfb\xc0\xc0\xf8\x78\xbc\x62\x79\x7a\xcd\xe6\xf0\x95\xd7\xb9\xb8\x6a\x3a\xc9\xd4\xcd\x1d\x79\x65\x0e\x92\x52\x5e\x1b\x65\x7b\x33\xe5\x4c\x06\x78\xdf\x1b\xa9\x31\xca\x29\x23\x82\xa6\xe4\x33\x43\x79\x9b\x51\x09\xf3\xc0\x06\x9b\xb4\xcb\x3c\xda\x15\xb5\x10\xb8\x86\x76\x93\xe5\x92\x25\x40\xa8\x8c\x04\xfa\x47\x40\x72\x8f\x7e\x99\xa3\x5f\x95\x6a\x28\x9d\x59\x4a\xcf\x31\xd8\x4c\xe2\x18\xd8\x7d\x42\x52\x5c\x9f\xe5\x41\xa9\x06\xd8\xef\x2d\x6d\x31\x08\x55\x9b\x43\x8b\x9d\x04\x1e\x01\xe5\x2b\x7e\x94\x6f\x36\xce\xbd\xce\x76\x48\xed\x93\xf5\x14\xc4\x8d\xb1\xbe\x99\xac\xa6\xb7\x40\x4d\xd4\xd7\x5f\xae\xd9\xcd\x54\x1f\x36\x94\x37\x67\xea\xc4\xdf\xc9\x27\xd0\x90\xa9\x67\xe8\x0e\x02\x05\x50\x4f\xbb\x25\x92\xef\xa5\x43\x34\x16\xac\x55\xb7\xe7\x16\x4b\xd0\x44\x2b\xd6\xe6\xaf\xcf\x35\x5e\x6b\x5d\x9b\xee\x17\x0b\xa6\x6a\x4f\xf3\x8c\xf9\x7d\xc2\x26\x29\x7d\xcf\x7c\x4b\x7f\xd7\x15\xe0\x19\x79\xb3\x47\xa2\xaf\xe7\x9a\xb8\xdf\x30\xc9\xde\xcf\xdb\x54\xda\xf8\x2a\x7c\xcb\x62\xec\x98\x6d\xd9\x9f\x25\x25\x49\xb7\x4d\x84\xdb\x0b\x6e\x29\xb6\x88\x20\x69\x9b\x85\xd1\x5b\x2d\x59\x68\x57\xa4\xb5\x62\x6f\xb5\xc8\xdf\x8a\xfd\x98\xb2\x71\x30\x4f\xaf\x03\xe2\x0f\x58\x2b\xb4\xb1\x73\x50\x7a\xce\xe8\x5b\x06\x3c\xe7\x1d\xa3\xf7\x23\xbf\x8c\xbd\xd0\xc3\xf1\x56\x10\x60\x53\xd7\x17\x46\x5b\x01\x23\x0d\x14\xa4\x9a\xf0\xe5\x2a\x2b\x34\xe4\x86\xb3\xd1\xcd\xc3\x30\x27\x09\x65\xfd\x3c\x5d\x2e\x33\xf6\x0b\x84\x5a\xd7\xcf\xbf\xea\x70\xeb\xf0\x7c\x92\x7e\x61\x10\x75\x3d\x55\xbb\x33\x73\xc4\x5e\x87\x0e\xf1\xe3\x25\x01\x8a\x08\xeb\x4b\x13\xd8\x74\x41\xab\x20\xbf\xa8\x3b\xc0\x64\x49\x17\x93\x68\x4a\x2e\xe8\x62\x32\x98\x92\x2b\x45\x7d\x97\xb0\x08\xb8\xf9\x24\xb1\x0f\x3f\xa5\x45\x7a\x96\x31\x22\xc2\xd0\x26\x7d\xd4\x1d\xc1\xe4\x9a\xae\x6f\xd2\xb9\xbc\x88\x33\x72\xa1\xc1\x3c\x33\x22\xc5\x32\xde\xc9\x1e\x0d\x7b\x29\xc9\xd8\x42\xea\xe7\xa4\x24\xe7\xfe\x37\x60\x8e\xc8\x52\x55\x09\x8f\xef\x58\x72\x9d\xf2\x73\xfd\x11\x48\x71\xdf\xb8\x53\xef\xbd\x84\xf7\x66\x8e\x84\xdf\xb1\x5a\x00\x46\x6d\xb2\xbb\xbe\x40\xdd\xc8\x7a\x04\x7a\xb1\x66\xef\xc8\x1c\xb7\x44\xe8\xa9\xc5\x9b\x65\x1a\x0d\x74\x72\x47\x0a\x32\x9f\x6e\x1b\x5b\x06\xc5\x32\xe1\x01\x59\x57\x3a\xdd\x2b\xa3\xd3\xbd\x2e\xbf\xa1\xf0\xb9\xda\x99\xa1\x65\xaf\xea\xa6\x1a\xf7\x5a\xe6\xe8\xb5\xd8\x66\x07\x6e\x49\x2a\xab\xd9\x54\x00\x78\xeb\x11\x73\xf6\x38\x86\x61\x07\xa6\x74\xcd\xba\x61\x8a\xc9\xca\x27\x88\xc9\x14\x93\x19\x5d\x69\xfb\xe6\x95\x22\x08\x43\x2f\xaa\x81\x11\x06\xc0\x19\xf3\x4b\x1f\x53\xbc\x05\x51\x9b\x87\xa5\x8d\xf1\x1f\x86\xc8\x3d\x23\x4c\xdc\xb3\x71\x8f\xc2\x64\x32\x9b\x5a\xc4\x30\x57\xb7\xa2\xcb\xab\xc6\xa7\xc8\x75\x33\xe1\xfc\x5b\x1b\xf3\x95\x19\xbf\xb2\x6d\x02\x13\xea\x89\x69\xce\x1d\xad\x05\x3d\x6f\x47\x81\xb5\x0b\x39\xf7\x16\xae\xf0\x16\x6e\x52\x5f\xb8\x6a\x1d\xcf\xce\x46\xf3\x36\xab\x83\xca\x32\x1f\x45\xe4\x23\xd3\x48\xf6\x64\xb2\xe5\x68\xc5\xb4\x47\xc4\xc2\x36\x9a\x98\x79\x8d\x53\x62\xd6\x78\xfc\xf8\x71\x44\x4c\xcb\x62\x4e\x4c\xbb\xe2\xdc\x3c\xfd\x1a\x0b\x52\xb5\x29\x4e\x4a\x0c\x68\xa2\xc4\xd5\xd8\xa3\x03\x6f\x9e\x32\x35\x26\xe9\x14\x93\xb3\x7b\x07\xc4\x6e\x72\x4d\xcb\x8c\x67\x91\x45\x37\xec\x52\xcf\x0a\x23\x9a\x8e\xfd\x1f\x31\x1c\xe1\xb6\xde\x1d\xb4\xbe\x3b\xf0\xdf\x1d\xc0\xbb\xdb\x26\xa4\xcf\x86\x5e\xa1\xa1\xd3\xea\x81\xbf\xfd\x3d\x9c\x37\x55\x27\x76\xbd\xd2\x6a\x96\x4c\xc9\x66\xe3\x5e\x02\x6b\x26\xd9\x5f\x24\x97\x76\x36\xb6\x9c\x2c\xd2\x05\x0a\xae\xc4\xaa\x60\x73\x71\xc3\x35\xe6\xa8\xda\x40\xc2\xf0\xc2\xd1\x98\x7b\xa2\xdd\x81\xc6\xec\x08\xa4\x58\xcd\x2e\x20\x0e\x9a\xff\x0a\xf2\x4a\x1a\x66\x36\x23\x73\xb2\x20\x4b\xba\xd2\xbe\x05\xe7\x8e\x06\xce\xe8\x72\xbc\x54\x72\xe8\x0b\xb1\x02\x2f\xc4\x97\x59\xca\xb8\xfc\xa4\x56\x02\x8e\x0d\x6b\x8e\x2c\x6b\x8e\x34\x3f\x8e\x80\x43\x47\xa5\x6a\x75\xb6\xd9\x68\xc8\xa3\x19\xbc\xf8\x4b\x18\xfa\x3f\x7f\xdd\x6c\xba\x5e\x56\x97\xf5\xa1\xc9\xac\xc0\x33\xaa\x51\x9d\xd4\x67\xd1\x59\x1f\x3e\xf4\x68\x88\xc9\xbc\x9e\xae\x3f\xfc\x68\xe8\xa1\x94\xdc\x50\x57\xcb\xd8\x3d\x81\x9b\x32\x84\x11\x36\x1f\x23\x47\xee\xf9\xd7\x51\xed\x63\xb7\x3b\x67\x7d\xd5\x8d\xc6\xb7\x8e\x76\xce\xfa\x52\x2c\x01\xd1\x30\xc3\x68\xa1\xf3\x8a\x3f\x72\x89\xd0\xf0\x6f\xf0\x63\x29\x6e\x6c\x53\xc9\x10\xf7\xbc\x34\xdd\x4c\x32\xc4\xf8\xd1\x2e\xc6\xff\xbf\x21\xa5\x51\x18\xa2\x45\x8f\x0e\xbc\x86\x5f\x52\x53\xcf\x55\x72\x8b\xe0\x21\x39\x2b\x10\x52\x13\xa0\x1b\xfa\xb3\x1e\x6d\xbc\x33\xc3\x64\x86\x7b\x43\x72\xf2\xb5\x37\xde\x98\x79\xc1\x3b\x73\x4c\xe6\xb8\x37\x1c\xf9\xed\x76\x0d\xbc\xac\x35\xf7\x44\xb5\xb3\xac\x06\xd1\xc8\x67\xd7\x1e\xe7\x75\xcf\xbe\x40\x7a\x87\xd6\x96\xa0\x85\x63\x0e\x33\xc7\x1c\xe6\x3e\x73\x58\x90\xd9\x59\x0c\x26\xca\x8e\x49\xfa\xfb\x69\x8d\x05\xb4\x7d\x17\x61\x72\xbd\xc5\xf1\x0f\x22\x8c\xe3\x7f\xab\x15\x8a\x15\x25\xe4\x6e\x8a\xc9\xcd\x03\xcc\xe8\x4c\xc9\xef\xae\x76\xf0\xe9\xc3\x64\x72\x36\xc5\xe4\xf6\x7e\x9e\x6e\xf0\x92\xef\xd9\x18\x88\x5e\xa3\x8c\xcf\xfd\x15\xea\xba\xe6\x42\xd4\xf5\x97\x2c\x2f\xd2\xa2\xd6\xef\xad\x31\x80\x2b\xd6\xff\x3f\x7b\xef\xa2\xdc\x36\xae\xac\x0b\xbf\x8a\xc4\x3f\xc3\x43\xec\xb4\x35\x92\x6f\x49\xe8\xc5\xa5\xed\x38\x4e\xc6\x33\x71\xec\xb1\x9d\xb9\x44\x47\x27\x8b\x96\x20\x89\x31\x05\x2a\x24\xe5\x4b\x24\xbe\xfb\x5f\xb8\x03\x24\x25\xcb\x99\x59\xa7\xf6\xd9\xb5\xab\x52\xb1\x48\x82\x20\xee\xe8\x6e\x74\x7f\x9f\xf7\x68\x83\xde\x73\xde\x2a\x84\xd0\x41\xe9\xfd\xe1\x0a\x3c\x43\xb9\xea\x2a\x50\x63\x86\x68\x8c\xcc\x5d\x37\x17\x3b\x9c\xa6\x2e\xcf\xf0\xc9\x74\x86\xd3\x30\x8f\x6e\xf1\x4f\x4c\x35\xf3\xd2\x1a\x13\xb6\x6a\xcf\x3b\xce\xd8\xe8\x5f\x43\x46\x97\x8f\x7b\xd6\x29\x77\x70\x0d\xf7\xab\x85\x25\x0d\x7c\xaf\xe4\x20\x25\x02\x46\xad\x34\x49\x72\x88\x11\xa4\x78\xe4\x8f\x0b\xc8\xaa\xd9\x1c\x62\x30\x84\x7b\xae\xb3\x52\xe5\xb3\xd9\x2e\x60\xc0\x5d\xe0\xb8\xec\xfd\x16\xd7\x20\xd7\xeb\xe8\x75\xfa\x25\x7f\x91\xdc\xe2\x74\x14\x27\x77\xbe\x33\x89\x86\x43\x4c\x1c\x98\x25\x11\x5d\xfa\x19\x6e\x57\xe6\x3b\x24\x21\x98\xde\xe4\xe0\x4e\xbe\x13\x5e\x67\x49\x3c\xcf\xb1\x03\xdf\x38\x11\xa5\x58\x39\x21\x15\xcb\xe9\x75\x92\xe7\xc9\x54\xaf\xab\x9c\x09\xe0\x22\x1c\x46\xf3\xcc\x04\xbe\xe7\x63\xda\x5f\x24\xb3\x70\x10\xe5\x0f\x7e\xbb\xee\x23\x32\x99\x10\xb7\x75\xea\xd6\x0e\xe4\x69\x48\xb2\x51\x92\x4e\x7d\x87\xf1\x0f\x78\x1d\xe4\x40\x28\x69\xf3\x7d\xe7\x19\xdb\xc2\x1a\x8e\x14\x25\xa8\x24\xe0\x4c\xb3\x86\x83\xe4\x1d\xdc\xca\x15\x6c\x55\xd6\xc2\x61\x16\x91\x31\xfd\x83\x4f\xc8\xd9\x3c\x47\xf2\xe3\x42\xe8\xf6\x17\x2a\xf3\x37\xf3\x54\x7c\xc4\xa9\xcf\x6b\x28\x12\xb4\xb2\x49\x92\xd2\x8d\xd4\x99\x66\x0e\x2a\xb8\x16\xa6\x6b\xd1\x01\x81\xda\xe0\x3b\x0c\x00\xca\x01\xbe\x3b\x39\x9d\x76\xfb\x07\x47\x6e\x51\xe2\xca\x6e\xc8\x3d\x76\xab\x04\xed\xef\x88\xa1\xcd\xae\x1c\xf1\x39\xa1\x45\x98\x2d\x6d\xb5\xd2\x7d\x94\xff\xa5\x46\x32\x15\x13\x7f\x51\x37\x52\xcc\x1d\xd6\xfa\xb6\x98\x47\x8d\xed\xbd\x76\x9b\x7e\x74\xb3\x6f\x82\xd3\xd8\x66\xe9\x23\x32\x8a\x48\x94\x63\xda\xb2\xce\x7f\xde\xe0\x07\x46\xed\x9f\x35\xb8\x94\xef\x2f\x9c\xf6\x0f\x8e\xbf\xa8\x8c\x93\x36\x72\x40\x8d\xa3\x4e\x01\xbc\x7d\x6b\x12\x76\xcc\x84\x3b\x45\xe9\x23\xf7\x51\xae\xbe\xa1\x3a\x54\xe7\xa6\x5a\xbb\xf4\x9e\xa8\xf3\xea\xe2\x75\x90\x53\x00\xeb\xdf\xba\xb2\xb7\x5e\x6d\xb3\xe7\x6b\xca\x5c\x70\x0a\x87\x51\x1c\xcd\xfc\x66\x07\x14\x95\xc3\x15\x5d\xb6\x2f\xd8\x90\x76\x0a\xe4\xe5\xad\x29\x9e\x26\xde\x1b\x2c\x9c\x4a\x5e\x6f\xa6\x83\x71\x74\x34\x66\xb8\xe3\x31\x1f\x17\x78\xc4\x35\x30\xd6\xec\x3c\xff\xda\x78\x5c\x65\xa1\x1b\x18\xfa\xda\xd0\xd2\xd7\x46\x56\xf8\xc5\x4c\x4b\x9f\xa3\xae\xc3\xbf\xe6\xf8\x23\xe6\xf7\x3e\x8c\xb2\xf0\x3a\xc6\x43\x98\xea\x2f\x4d\x5c\x77\xc2\x3c\xe1\xc5\x43\x51\x96\xb1\x4e\x71\xeb\xba\xb7\xcc\x35\x5e\xa4\x30\x9a\x04\xae\x75\xb2\x07\xd7\x7d\x80\xbb\x80\xb4\x46\xc9\x60\x9e\x89\xe7\xf7\xfa\xf9\x9d\xeb\xde\xc1\xb1\x7c\x2e\x16\x27\xed\xff\x7f\xc3\xe2\x77\x5e\xc7\xf3\x14\x2e\x8d\x50\x9e\x23\xf6\xfb\x2d\x7d\x05\x3e\xe9\xdf\xd2\x94\x70\xce\x6e\xfd\x82\x1f\xde\x24\x77\x04\x2e\xe4\xd5\xc7\x19\x9c\xb1\xdf\xa7\x54\x96\x66\xcf\xae\xf4\x35\x9d\xdc\x18\x3e\xe8\x1b\x1f\x67\xf0\x99\x5d\xb1\xaa\x1d\x93\x21\x9c\xea\xcb\xd3\xe4\x16\x33\xb8\x19\x71\xcd\x7c\x7d\xe0\x90\xdd\x78\x93\x86\x63\x9e\xdb\xfb\x80\xb4\xf2\xf0\x9a\x2d\xef\xf0\x4d\xf7\xc1\xfb\x6e\xdb\x7f\x0f\x6f\x02\xd2\x32\x9a\x8d\x99\x9b\xe0\x2d\x7d\xe5\x61\x86\xe1\xb5\x4e\xfe\x56\x77\xd9\x5b\xf8\x62\x2b\xe2\x7c\x10\x39\xe0\xa8\x21\x44\x55\x71\x63\x00\x49\x13\x5f\x4a\xb7\xa4\x5a\x75\x1d\x2c\x7b\xa0\x1c\x0e\xfa\xa7\xca\xa7\xda\xd5\x0e\x38\x46\xc7\xca\xab\x72\x37\xb2\xc0\x2a\xda\x89\x46\x84\x15\xfd\xc5\x3a\x4d\xff\x12\xaf\xb1\x1b\xa2\xf3\xe4\xef\x8f\x33\xf6\x4b\x75\x9c\xbe\x62\x0d\xad\x2f\x45\x42\xd9\x65\xfa\x82\x76\x98\xbe\x62\xdd\xc5\x2e\x55\x67\x39\xe0\xc8\xae\x72\xc0\x29\xf7\x0b\x7d\xfa\x30\x63\xa6\x8d\xdf\xcb\x16\x83\x67\xe5\x1b\x1f\xcb\xd6\xb0\xdf\x82\x8f\xbd\x76\x1f\x7e\x0a\x3e\xf6\x3a\xfd\x83\xa9\xeb\xfe\xe6\xba\x3f\xa9\xe8\x8b\xaf\xb4\x47\x3f\xb1\x1e\x45\xf0\x4b\xf0\xb5\x15\x65\xd6\x70\xfe\x35\xf8\x2a\x26\x81\xbc\xf3\x2e\xf8\xda\x4a\xf1\x48\x9f\xfc\xfe\x69\x06\xca\x57\x15\xd7\x5a\xa5\x77\xbb\x6f\xeb\xb3\xd7\x07\xca\xc4\xcf\xcd\x61\x75\x64\x21\xb9\xeb\xe6\x5e\x8a\xa0\x49\x5c\xf7\x99\x96\xcd\xd5\xcf\x1e\xee\xb3\xc7\xed\x02\xa1\xa2\x5e\x0e\x4c\xea\xe4\x40\x73\xdc\x98\xfe\xf0\x3f\x79\xcd\x36\x82\xdf\x65\xf6\x7c\x99\xf0\x84\x31\x8d\x89\x86\xf5\xc6\x99\xdf\x5c\xf7\xde\x75\x9b\x63\xa3\x68\x52\xe1\xf6\x98\xe0\x3e\x86\x7b\xf8\x4d\x18\x65\xfe\x08\xfe\xf4\x1c\xae\x29\xc3\x19\x82\x9f\xf9\x65\x32\x73\xe0\x10\x01\xc6\xfa\xf2\x03\x82\xdc\xb8\xb4\x84\xc1\xdf\x5c\xb7\x26\xb4\xee\xca\x75\xaf\xc4\x69\x37\xc1\xc6\x67\x4e\x58\xb4\x95\xca\xe9\x33\x82\xc4\xb8\x3c\x45\x10\xae\xf9\x8e\xf7\xab\x87\x11\xb0\x01\x84\xe0\xc6\x75\x6f\xd8\x17\x80\x8e\xb4\x08\x07\x35\xfd\x87\xd1\x42\x35\xe1\x72\xe9\xa9\xdf\x54\x15\xe7\xbf\xae\x58\xa4\x23\x82\x5f\x3c\xc6\x1f\xc9\x9b\xfd\x93\xeb\x7e\xf2\x30\x42\x70\xe4\xba\x47\xa2\x16\x31\xae\x1e\x43\xcc\x5b\xa3\x88\x0c\xdf\x9c\x9d\x7e\x48\x86\x58\xe7\x8e\x0c\x34\x67\xb9\x80\x35\x83\x60\xe6\xba\x4d\xcf\x39\x14\x2a\x4f\x38\xfe\xc0\xa0\x36\x30\xc3\x52\x45\x05\x64\xd8\xb6\xd8\xcd\x57\xd5\x88\xf6\x6f\x86\xf5\x18\xfc\xcd\x1a\x91\x4e\x83\x7f\x80\x41\x72\x78\x3a\x5d\xd0\xa4\x5a\x83\x56\xa8\xf4\xf0\xa0\x6d\x6d\xf9\x41\xa0\x85\xf9\x30\x4c\x73\xde\x04\x08\xb0\x08\x0c\xe5\xb6\x0c\xb3\x01\x5d\x37\xc6\x1e\x2a\x7d\xbd\x66\x58\x9c\xbb\xee\xb9\x87\x37\xca\xe9\x98\x89\x60\x3a\xb7\xe6\xd4\x75\xeb\x82\x38\x2f\x5d\xf7\x92\x05\xc5\x20\x04\x83\x35\x6d\x66\x15\xed\x99\xd5\x7c\xcd\x6a\x50\x6a\xa9\xed\x3a\xdf\xd3\x76\x72\xde\x89\xd6\xbb\x70\xdd\x0b\x5a\xf7\x4b\xda\x32\x4f\x6a\xc8\xda\xf2\x5d\x8a\x81\x39\xc4\xc1\xec\x40\x0e\xb3\x20\x08\x86\xd8\x75\xbf\xb0\x41\xe5\xba\xde\x10\x07\x4e\x28\x38\x24\x46\x38\x58\x14\x76\xca\xae\x37\xe2\xda\x77\xf0\x1a\x46\x58\x49\x44\xc1\x14\xf9\x9e\x13\xda\xb9\x2d\x97\x34\x71\x9a\xc4\x38\x90\x79\x20\x18\x61\x11\x0c\xa8\x76\xcf\x7e\x30\xe5\x9f\x9b\xb1\xbe\xb8\x64\x7d\x11\x42\x8a\x60\x62\xdc\x78\x07\xbf\x23\x98\x1a\x37\x66\x18\x26\x18\xc1\x2d\x2e\x6f\x21\x63\x1c\xdc\x62\xba\x89\x3c\xb0\x1f\x9d\xfe\x4a\xbb\xf4\x03\x66\x1c\x0d\xda\xe6\x7c\x8d\x83\x31\xe6\x8b\x61\x73\xba\x2a\x58\x70\x88\xd7\xea\xd3\x03\xae\x4f\x0f\xe1\x37\xd7\xed\x0d\x2c\x69\x0d\x8e\xfb\x30\x75\xdd\x81\x6a\x36\x04\x7c\xb7\xf2\x43\x0c\x32\x54\xfa\x12\xc4\x26\xef\x47\xf4\xa6\xd8\xde\xfd\xb9\xb8\xf8\x38\xf3\x07\xf4\xa7\xda\xe0\xfd\x3f\xc0\xdc\xe0\xfd\x5c\x3d\xfd\x38\xf3\x31\xbd\x50\x1b\xb7\xff\x33\xe8\x0d\xdf\x4f\x31\x18\x3b\xbe\x9f\xa8\x4b\xb6\xe5\xfb\x04\x33\x83\xc0\x14\x83\xdc\xec\xfd\x69\x77\xab\xe3\x7f\x2b\x60\x84\xe1\x0b\x82\x0c\xae\x71\xe5\x2c\xf2\xad\xd1\x38\xf4\xf5\x67\xc0\x25\x2c\x3f\x2e\xe0\x0d\xd2\x90\x15\xc2\x5e\xf0\x45\xdb\x0b\x84\x71\x40\x29\xa7\x11\x89\x23\x82\xb7\x46\x31\x95\x32\xc2\x38\x1a\x93\x93\x1c\x4f\x33\x5f\x1d\xa8\x7c\x99\x67\x79\x34\x7a\x60\x1e\x5e\x24\xd7\xf7\xb5\x36\x98\xe2\x38\xe4\xa1\xa1\x9c\x67\xf0\x2a\x9c\xfd\x14\x8d\x27\x31\xd5\x70\x85\xf2\xca\x74\x99\x59\xc8\xc3\x52\x2b\xaa\xad\xf5\x34\x99\xe7\xb4\x44\xca\xbc\xe0\xb7\x41\xb2\xe0\xd9\x7a\x72\x1b\x66\xe1\x70\x48\xd5\xdf\x36\x0c\xe6\x69\x46\x73\x12\x16\x0e\x07\xe6\x19\x4e\x2f\x71\x8c\x07\xb9\xb4\x73\xdc\xe2\x34\x8f\x06\x61\x7c\x48\xeb\xe8\x3b\xd3\x68\x38\x64\xa2\xdd\xd6\x34\xf9\xb6\xc5\x0f\x86\x43\x32\xc0\x8e\x4c\xef\x6c\xdd\xb1\xda\xd4\x3d\xcb\xf1\x7d\xfe\x06\x0f\x12\x69\x2a\xe0\x77\x39\xdd\xa1\xb2\x83\x80\xe3\xfa\x3e\xcb\x9d\x0d\xce\x2d\x16\xe4\xc8\xb8\x02\x69\x25\x58\x08\xae\x78\xb3\x00\xc7\x7d\xa6\x26\x2a\x55\xb4\x6b\xec\x34\xb2\x8a\x62\xc1\xa1\x2f\x95\xf8\x0f\xd9\xf7\x0f\x87\xb4\xc3\x7c\x11\xce\x5b\x14\x20\xf3\xf5\x17\x05\x58\x42\xcd\xa2\x28\x0c\x32\xc0\xd7\x6c\xe5\x78\x1d\x66\x4c\x81\x7c\x2d\x20\xe3\x7e\x67\xee\x7f\x2f\x3a\x1d\x39\x92\x9e\x55\x7d\xfe\x16\x02\xd9\xe9\xe3\xf7\x1f\x29\xc3\x6f\x1b\x2a\xa8\x6a\x7c\x96\x42\xb6\xc5\xa0\x94\x41\xdb\xf3\x3c\xe1\xba\x58\x9d\xae\xca\xd7\x48\x75\x92\x2c\xce\x34\xb8\xb6\x2a\xd5\xd8\x91\xa1\xc6\xce\x2c\x35\x76\x62\xa9\xb1\xd3\x80\xb4\x68\x3b\x84\x11\xc1\xa9\x3a\xc3\x87\x5b\x5d\xb8\x69\xd7\x89\x23\xc7\x9f\xb2\xe0\x6d\x95\x94\xab\x56\x0f\x81\x37\xd6\x29\xc7\xdd\x45\xe1\x8f\x91\xf1\xad\x6b\xad\x59\x8d\xa1\x67\x9f\x67\x52\x15\x76\x88\x49\x56\xaf\xbc\x2a\x15\xfa\x46\x3f\x3c\x76\xdd\x63\xa6\xb4\x8a\x87\xef\xe6\x79\x8e\xd3\x0c\x8e\x74\x12\xba\x65\x33\xfd\x75\x18\x71\xf7\x85\x73\xfd\x8c\xca\x5e\x4c\x75\xad\x57\x8c\xcf\x98\x7f\x37\x9d\x70\x78\x08\x57\xfa\xb5\x33\xd7\x3d\x83\x0f\x25\x15\x51\x75\xa3\x03\x8e\xea\x2c\xa5\x32\x3e\x55\x41\xac\x76\x80\x79\x53\x6a\x4b\xac\xb1\x6a\xd5\x49\xd1\x10\xec\x06\xab\xf6\x1a\xb5\x51\x56\x91\x76\xc1\xe7\xc0\x04\x83\xf1\x9e\x61\x04\xa7\xc1\x82\x7d\xc7\xbf\x5f\x2e\x3f\xf3\xfe\x59\x2e\x9b\x1d\x73\x61\x0d\x0b\x38\x29\x9f\xe8\x7e\xb4\x4f\xf7\x63\xd7\x3d\xd1\x72\xd0\x49\x45\xd7\x40\xd0\x8b\xc5\x56\x7a\x68\xe2\x28\xe5\x09\x8f\x0e\x1f\x22\x78\x1f\x1c\x6a\x7f\xcf\x36\xfc\xce\xda\xfe\xb0\x77\xa8\x03\x2a\xa1\xe7\xbc\x8f\xb2\x9c\x16\xea\x12\x0f\x12\x32\x0c\xd3\x87\x43\xae\xbb\xf7\x11\x7c\x5b\x77\x2c\xac\x4a\x54\x12\xb4\xb1\xd8\xe4\xe1\x8d\x96\x1f\xbe\x51\x09\xe3\x6d\xb0\x6e\x2b\x1f\xf1\xad\x7c\x06\xa7\xbc\xc5\x5c\x77\x24\x86\x76\xf3\x88\xfe\x1e\x8b\x81\x7a\xce\x1e\x88\x91\x79\xc3\x2f\xc4\x30\x1f\xd0\x2b\x31\xb1\xe5\x62\xc0\x41\x0a\x47\xc6\xa2\xf1\x36\xc6\xf7\xdc\x2e\xf2\x9e\x3e\xc8\xec\x6a\x53\xd5\x68\xa4\xc6\x30\xd2\x0b\xe7\x4d\x41\xf5\xac\xd7\xc1\x64\xb9\xa4\x73\x59\x0a\x2c\x03\xd7\xf5\xde\xea\xb5\x80\x3d\x66\xfe\x38\x6f\xeb\xa7\x48\x60\x54\xd8\x12\x57\x2e\x68\xe6\x5f\x30\x82\xf7\x5d\xef\x75\x60\x64\xb9\x5c\x4e\xba\xaf\x85\x93\x0f\xfd\x72\xc0\xac\x5c\x9e\xf8\xf9\xba\xfb\x3a\x60\xcf\x7c\x71\xc3\x78\xb3\x54\x34\x96\x0c\x55\x0f\x1c\x9e\x55\x3d\x95\x4e\xab\xde\x1d\xb7\xb0\xbe\xf7\x06\x72\xaa\xc1\x03\x3f\xdd\x78\x53\xc0\x75\xf5\x63\xaf\xe1\x2d\x55\x5f\x0f\x79\xa4\x2b\x42\x55\xc7\xa9\xcd\x8a\xf3\xda\x16\x7d\xde\x14\xf0\x16\xc1\xa1\x79\x3c\xf2\xd3\x26\xc7\x23\x4a\x02\xe2\xa2\x4f\x59\xcc\xa1\x77\xb7\x84\x6e\x5c\x27\x16\xd5\x89\x3f\xf5\x62\x81\x65\xf7\xaf\xe7\x51\x66\x6f\x0a\xc1\x24\xc6\xa3\xdc\x91\xa2\xcd\x55\x32\xf3\x5f\xca\x8b\xd7\xfc\xf8\xe5\x25\x95\x16\xcc\x01\x54\x43\x04\x8c\x15\x11\x30\x37\xc7\xa9\x61\xcd\x44\x0d\xb5\x4e\x37\xf4\x6f\x7f\x92\xdc\x72\xf1\xe4\x49\x59\x19\x52\x8b\x32\xa7\xef\x71\xc2\x38\x3e\x26\xcc\x63\x03\xd5\x52\x15\x49\x04\xf8\xaa\xb9\x30\xaa\xbd\x5b\xaa\xf6\x6e\x01\x35\x33\xd9\x5f\x98\x9d\x63\x74\x9a\x2d\xf8\x88\x55\x43\x0a\x5f\x22\x4b\xa7\x33\xbb\x6f\x64\x49\x1c\x0d\xcd\xf3\x09\x59\x5d\xf1\x0e\x32\xe5\xd5\x38\x9a\xf9\x8e\x28\x97\x60\xc0\x16\xab\x93\x2a\xfb\x7b\x3c\xca\xfd\xce\xbe\x2c\xfd\x05\x3b\xe7\xe9\xec\x17\xc0\x97\x27\x61\xd7\xe7\x2d\x62\x1f\x86\x08\x4f\x7e\x47\x7f\x6f\x8b\x89\x74\x0e\x2c\xe4\xa1\x93\xbf\xf6\x2c\x2a\xcb\x0b\x44\xa5\x4e\xd9\x95\xf5\xe3\xf1\xd1\x0e\x66\xaf\x2b\xe9\xd2\x63\x97\x7e\x83\xbe\x8c\x6a\xc6\x87\x25\xbd\x17\x45\x01\xa5\x65\x55\x35\x0c\x6f\x89\xdd\x97\x34\x85\x18\x73\x8b\x12\x23\xb5\xdc\x90\xa8\x08\xfa\x9b\x10\x41\xbf\xf2\x10\x95\x17\x1d\x04\xbf\xe0\x60\x31\xe9\xf8\xce\xa4\xe3\xc0\x64\xdb\x77\x26\xdb\x0e\x4c\x76\x7c\x67\xb2\xe3\xc0\x64\xd7\x77\x26\xbb\x0e\x4c\xf6\x7c\x67\xb2\xe7\xc0\x64\xdf\x77\x26\xfb\x0e\x64\xf3\xeb\x3c\xca\x63\xdc\xb1\x2f\xb7\xf9\xe5\x75\x32\x7c\xe8\xf8\xce\x8c\xff\xda\xa6\xbf\x0a\xf8\xf5\x09\xc2\x68\x49\x0e\x95\xb2\xbf\xbf\xde\x73\x8d\x8a\x90\x71\x92\x2a\xbf\x9a\x20\x08\x32\xfa\x72\x94\x47\x61\xec\xf8\x19\x3f\x46\x51\xe2\xe4\x90\x0b\x6d\x74\xb9\xb2\xc9\xd1\xf4\x2b\x43\x26\xa6\xf2\xb1\xc8\x47\x37\x4c\xb4\x10\x36\x73\xdd\x19\x93\x55\x49\xf2\x7b\x1a\xce\x94\x7c\xda\x0c\x82\xa9\xeb\x72\xd9\x74\x16\xa6\x21\xe3\x24\x87\x07\xfd\x74\xec\xba\x63\xb8\x0e\x48\x4b\x50\x29\xc3\x9d\xfe\xfc\x75\xd7\x61\xcd\xe7\xf8\xd7\x70\xaf\x93\x9c\x86\xb3\x59\x44\xc6\x70\xac\x53\xde\x77\x7f\xc1\xfe\x3d\xdc\xd4\x48\x81\x6b\x04\x3c\x36\xf2\xcb\x27\x01\xb4\x0d\x1c\x70\xcc\x8a\x3a\xe0\xf0\x6a\x39\xe0\xa8\x4a\x38\xe0\x88\xf2\xe8\x5f\xa2\x64\x54\xbc\xb9\x0c\x06\xcb\xa5\xf7\xd0\x75\x66\x8e\x7f\xdc\xbb\xeb\x2f\x97\xbf\xe0\xde\x5d\x1f\x2d\x97\xfc\x28\x7f\x95\x51\xe2\x72\xa3\x33\x7e\x50\xe3\x80\xcb\xe4\x51\xef\xae\x0f\xaa\xaf\x38\x33\x51\xd4\x13\x55\x34\xdc\xe1\xbe\xb2\x5c\xe6\x08\xf5\xe1\xd6\x75\x23\xd9\x5b\x13\xfa\xdb\xea\xda\x07\x7a\x47\x77\x98\xf9\xb9\x90\x65\xcd\xdb\xb6\x92\x75\x48\xb3\x36\x0b\x32\x62\xa9\x65\xbb\x56\xd2\x8f\x10\xea\xf3\x2d\x3d\x2d\xe0\xc6\xdc\x62\xdf\x6d\xb2\xc5\x6a\xf6\x7a\x3e\xbb\x70\x95\xf1\x9f\x4f\xc0\xca\x83\x0e\x0c\xc2\x99\x5c\xf0\xf4\x23\x71\x53\x2e\xa5\xf6\x6b\x5c\xfa\x9b\x94\x72\x9b\x74\xe8\x52\x61\xdf\xda\xa6\xab\x86\x7d\x6b\x87\x2e\x20\xf6\xad\x5d\xba\x96\xd8\xb7\xf6\xe8\xb2\x62\xdf\xda\x37\x56\x18\xeb\x89\xba\x6d\xac\x39\xb5\x09\xb6\x81\x2e\xb0\xcc\xe6\x61\x3d\x97\x77\x21\x4b\xcf\x48\xfc\x50\x7f\xfe\x2e\xfc\x08\x3a\x42\xca\xe8\x40\xc5\xeb\x43\x6c\x9b\x6c\x5b\x5a\x94\xe5\x0c\xf1\xf0\x88\x1b\x8f\xcc\xc7\x42\xce\x11\x09\xf8\xda\x6d\x3e\x67\x3e\x21\xf2\xf1\xcf\x5c\x78\xb2\x12\x08\x81\xca\x29\x80\x0f\xe3\x3a\x87\x14\x9a\xfc\x4c\xdd\xc5\x71\x1c\xcd\xb2\x28\x73\xe0\x6e\x12\xe5\xf8\x72\x16\x0e\x98\x85\xe4\x8e\xce\x6d\xb9\xd1\x8a\xad\x5b\x8c\x2d\xb9\x91\xb7\x5b\x3b\x7b\x74\xdb\x00\x35\x29\x4a\x29\xe8\x06\xcc\xe6\xdb\x09\x9f\x2a\xc2\x5a\x62\x7a\xad\xb0\x1b\xe7\x69\x34\x0d\xd3\x07\xf9\x58\xef\x8d\x33\xfe\xa0\x35\x0d\x23\x22\xd2\x2a\xb5\xa9\x9a\x5a\xed\x81\x66\xfa\x2b\x7c\x9f\xaf\xcc\x9f\x36\x85\xfc\x88\x91\x7e\xcd\x37\xd8\x1b\xea\x43\xe2\x1d\x86\x2c\x51\x4d\xcb\xc2\x41\x45\x59\xc4\x6c\x3f\x61\x86\xbf\x8a\x25\xd0\x51\x09\x5e\x33\xde\xb2\x45\xc9\x8d\xa5\xb4\x63\x5f\xa9\xf1\x4a\xf7\xec\x5f\xc5\x9e\xfd\xe7\x86\x3e\xdf\xd2\xdc\x12\x1a\x7b\x65\x64\xed\x95\xb1\x71\xa0\xaf\x3e\x55\x43\x34\x4a\x5a\x11\xc9\x70\x6e\x5a\x75\xe6\xae\x3b\x67\x5b\xa7\x68\x55\x66\xd4\x11\xbf\x75\x5e\xdc\x12\xc3\xc1\xf7\x44\x53\x72\xf0\x3d\x79\x55\x4e\x3a\x2d\xf9\x9d\x3f\x66\xa9\xa8\x94\x9e\x61\xe5\x65\x98\x6e\x4c\xa2\x34\xfa\x57\xe9\x63\xcc\xe0\x20\xca\x61\xfe\x2e\x27\xeb\x2b\xb7\x71\xc3\x18\x21\x74\xe8\x71\xc0\x23\x57\x87\xdd\xa1\x9f\x1c\x70\xef\xc9\xf1\x72\x39\xe6\xc7\x0b\x41\xf0\x0e\x2f\x97\xd9\x72\xe9\x8d\x83\xf2\x66\xf7\xce\x30\x32\x8b\x2d\xd4\xbf\xe5\x9b\xfe\xb6\xe3\x8b\xcd\xdf\x00\x7d\x0b\x55\x4b\x1b\x11\x2a\xdc\x33\xae\x3c\x88\x60\x84\x60\x8c\xa4\x07\xfa\xec\xc0\x88\xb1\x0d\x82\x87\xe5\xf2\xa1\x5c\xba\x87\x8d\x4a\x27\xca\x66\x95\x49\x77\xab\x98\xf1\xb9\x39\xad\x6a\x8a\x36\x41\xf0\x50\xa3\x2b\x73\x35\x7c\xdd\xf6\x1f\xf2\xed\x3f\xa2\x9b\x77\x28\x5a\x7f\x40\x7f\xf2\xa1\x39\x76\xdd\x07\x7a\x35\x9d\xc7\x79\x44\xa7\x9a\xda\x59\xa7\x08\xc6\xf0\x60\xec\xae\x7f\x54\xec\xf5\x54\xb3\xf1\x9d\x4e\xa3\xd3\x08\xe7\x79\xe2\xc0\x34\x22\xc2\xff\x56\x58\xc7\xb9\xca\x64\xad\x79\xbb\x05\xa8\x6f\xc9\xe5\x90\x26\xdb\xb7\x93\xed\x2b\xed\xab\x00\x56\x52\x5b\x95\xd9\xdb\x2f\x60\x26\x57\x2d\x43\xba\x2f\xd9\x8f\xa5\xe8\x4e\x17\x2d\xba\x14\xfc\x29\x96\x82\x9f\x37\x5c\x0a\xc4\xec\x0f\xad\xd9\x1f\x95\xe6\x5a\x6d\x68\xc7\x2a\x59\xed\xf1\x0e\x4b\x78\x87\x85\xaa\x23\x22\x2e\xe2\xfc\x8c\x5b\xd3\x79\xc4\x6c\x36\x2b\x6d\x64\xa2\xa7\x70\x5e\xee\xa9\xba\x5d\x3a\x15\x4a\x20\xf3\x93\xe3\xfe\x7d\x86\x77\x17\xfb\x19\x87\x39\xfe\xd3\xdb\xda\x6b\xff\x80\x9c\xda\x86\x2d\x17\xa0\x40\xde\xcf\xa2\x8d\xf3\xfc\xef\x5c\x6e\xb5\xde\x91\x69\x11\x3e\xee\x3a\xf3\xd8\xf1\xf9\x52\x2b\x86\x76\xcd\x52\x2b\x16\xbb\x73\x3e\x7e\x94\xb2\xd2\x0c\x82\xa1\xeb\x72\x1d\x25\x9b\x5f\x4f\x70\x38\xc4\x29\x4c\x9e\xb8\x92\x5a\xaa\x80\x6d\xcd\x15\x1f\xa4\x6b\xa4\xcc\x9e\x2e\x8a\x22\xb8\xe6\x14\x4f\x93\x9a\x48\x19\x61\xaa\x1d\x14\x32\x3c\x67\xc5\x40\xaa\x31\x4b\x4d\xab\x66\xa9\x6c\xb3\xb5\x61\xa0\xd7\x86\xe6\x88\xfe\x16\x73\x0d\x66\xf4\x42\x95\x5e\x0d\xc9\x09\x82\x19\x24\xa6\xe8\x4d\x2a\x43\x2e\x8e\xb2\xdc\x3c\x4f\xd2\x07\x66\xfa\x84\xac\xd6\x0a\x23\x1f\x2f\xd6\x99\x9b\x8c\xe5\x41\x15\xcf\x7a\xa3\x5d\x19\xaf\xcc\x07\x51\x52\xee\xe5\x7f\x69\x01\x90\xaa\xb2\x0d\xbc\x2b\x0f\xc1\x04\xf2\xae\x1e\xb2\xb6\x46\x1d\x47\x52\x99\x2e\x9d\x79\x0c\xf5\xc0\x1c\xb8\xee\x80\x89\x06\x22\xc9\x65\x1e\x0d\x6e\x1e\x94\x83\x22\x57\x92\xb8\x63\x22\x5f\xc7\xab\x5e\x89\x8f\x2e\x52\x2b\xd5\xd9\xf2\xf1\x83\x51\x02\x25\x26\xac\x1e\x98\xf3\x8d\x56\x37\x50\xad\xc5\xc5\xa5\x64\xa5\xe6\x19\x53\xf5\x70\xea\xba\x89\xa8\x69\x73\x46\x7f\x67\xbc\x41\x9a\x43\x7a\x21\xac\x5d\x6a\x78\xde\x9a\x23\x33\xc9\x37\x50\x0a\x57\x58\x40\xe9\x26\x25\xe2\x43\x9c\xdd\x97\x33\x76\xa7\x34\xaa\xd7\x0b\xc0\x30\x4a\x48\xfe\x36\x9c\x46\xf1\x83\xad\x47\xe9\xfb\x2c\xc9\xef\xfc\x23\x95\x24\xfc\xfe\x29\x1e\x46\xf3\x29\x4b\xc8\x62\x32\xac\x64\xb3\xfb\xab\xe4\x02\x4f\xbd\xce\x2e\xfa\x0e\x75\x61\xb5\xe6\xb1\xb1\x09\xb1\x66\x7b\x7e\xb1\x5d\x00\xef\x21\x73\xeb\xc9\xc4\x10\xe2\x7e\xd9\xc2\x9d\xbf\x53\x3d\x79\x57\x65\xa8\xda\xe1\x2e\xd5\x42\x5a\x20\x2f\x15\x93\x39\xcc\x19\x8a\xcc\xde\x2b\x04\x51\xce\xec\x72\xfb\xaf\x10\xc4\xf4\xe7\xfe\xf6\x3e\x82\x8c\xfe\xda\xdd\xde\xd9\x47\x30\xcf\x83\x35\x54\xbf\x95\x23\x60\xdf\x38\x20\x16\xc3\x69\xb0\x72\xe5\x30\x40\x65\x74\xd4\x37\x8b\x48\xd4\x67\x11\x61\xa0\xfc\x66\xce\x93\x34\x0f\xe3\x32\x7b\x15\x0b\x53\x4c\x08\x8f\xda\xc7\x43\x16\xf4\xa6\x3c\x5c\xb8\xdf\xa4\xe6\xc0\xe1\x31\xa2\xea\x54\xab\x42\x62\x91\x22\x86\xf8\x3a\xe2\x51\x1b\x3a\x98\xbe\x14\xec\x12\x2d\x97\xc3\xda\xa0\x96\x60\x05\xcb\x01\xf2\x31\x54\x0e\xd9\xbc\x04\x2d\x97\xc3\x64\xc0\x5c\x25\x99\xbd\x84\x1d\xbc\x25\x10\xf5\x69\xbb\x97\x23\x85\x07\xae\xdb\x8c\x90\xf2\xa5\xcc\x72\xbe\x54\x0d\x2c\xa6\x67\xe3\x01\x77\x1e\xa1\x39\x12\x18\xd4\xe5\x19\xbb\xae\x37\x58\x2e\x23\xe4\xba\xb1\x38\x8e\x14\x09\xa3\x6e\x5d\xcb\x94\xb8\x37\x52\x60\x07\x37\xa3\x02\xf9\xa9\x3f\xe8\xce\xc5\xaa\xc6\x7b\xc9\x4b\x61\x80\xfc\x81\x82\x43\xa4\x03\x6a\x7b\x6f\xff\x25\x82\x11\xfb\xf9\xe2\x65\x07\xc1\x8c\x8d\xbd\xce\xee\xae\x81\x35\x34\xc9\x95\xfb\x9f\x6a\x9a\x1a\x81\x10\x1d\x60\x8e\xa6\xce\x23\xe3\x02\xe7\xd5\x2b\xba\xd8\xc8\x9b\xdc\x9e\x52\xbe\x2b\x27\x56\x60\xc8\x74\xf2\x59\x9e\xcc\x02\x67\xeb\xd5\x2b\xfb\x0d\x69\xeb\x08\x9c\x6c\x90\x26\x71\xec\x80\xd5\x5f\x82\x81\x9b\x9d\xdc\x7a\x52\x8a\xa3\xc3\x71\x34\xca\x30\x8f\xac\xdb\xc2\x66\x9c\x9d\x82\x32\xb0\x72\xe1\x3c\xfc\x32\x17\xc8\x19\xc6\xca\x94\x36\xce\x8b\xce\x8e\xd1\x36\xb7\x39\x77\xc7\xcd\xbb\x8c\x35\xf7\x30\xcf\xd3\xe8\x7a\x9e\x63\x8f\xfb\x88\x49\x73\x8c\x93\xa7\x73\xec\x20\x1f\x8b\x8c\x57\xa4\x33\xb1\xe8\x72\x63\x10\x33\x44\xb7\x13\x92\x7b\x82\x4a\x7d\x8c\xf3\x23\x41\xac\xc2\xd6\x71\x0f\xa3\x9e\x3a\x3c\xe1\xf6\xa3\x3e\x74\xda\x68\xb9\x6c\x1b\xe0\x6f\xb9\xc4\x5d\xe2\xf3\xbb\xe2\x3b\xbc\x53\xeb\x3b\xbc\x63\xfa\x0e\xef\xf4\x19\x1e\x75\xf5\xdd\x5d\x23\xd1\xae\x0a\x98\x0d\x83\x5e\x0e\xa4\x1a\x97\x9c\x22\x04\x51\xd0\x73\xae\x8e\x4f\xcf\xdf\x1f\x5e\x1d\x3b\xe0\x5c\x1e\x5d\x9c\x9c\x5f\xd1\x1f\x57\x7f\xbe\x3f\x76\xfa\x07\xbd\xbe\x84\x21\x12\x68\xbd\x2b\xc0\x4a\x3a\xcc\x69\x90\x24\x43\x7c\xc5\x62\xea\xb6\xe8\x8d\x50\xf1\xd7\x63\x24\x6e\x45\xfa\x96\x74\x45\x45\xae\xcb\xfa\x2f\x29\xe1\xcc\xe5\xa6\x8b\xf5\x56\x47\x41\x69\xb5\xb2\x64\x6a\x93\x6a\xa5\x9a\x9f\x23\xe7\xee\xb4\x24\x48\x81\xf9\xe4\x21\x20\x6c\xd0\xdc\x59\xb1\x93\xea\x23\xd8\x43\x8b\x66\x25\x7a\xb0\xe9\x61\x13\xa7\x3c\x47\xf5\x20\xda\x47\x21\x21\x49\xde\xa0\xed\xd2\x08\x1b\x4c\x42\x69\x84\x59\x23\x54\x11\xea\x0e\x2a\x04\x16\x8f\x82\x30\x19\x86\x71\x16\xf4\xfa\xa0\x48\x82\xd9\x62\x4e\x6f\x69\xf6\x9a\x59\x2e\x60\x43\x58\x84\xb8\x13\x0e\x87\x8e\x60\xda\xac\x63\x69\x33\x32\x36\x9a\xfb\x20\x1a\x79\x5b\x1d\x8b\xfa\xed\xc0\x4e\x2b\x51\xf7\x8d\x5b\x82\x55\x1e\x30\xbf\x71\x81\x47\xbc\x6b\xd4\x25\x48\x0f\xfa\xb4\x86\x38\x5a\xd1\xd5\x6f\x3a\x66\x18\x9f\xb5\x9a\x83\xae\xcb\xa7\x27\x1b\x48\xe3\x95\x93\x18\x31\x84\x18\x41\x7f\x8f\x18\xf7\x63\x8e\x0e\x1e\x72\x2f\x67\xc5\x9e\x93\x9c\xee\x22\x46\x15\x80\x8d\x04\x01\x44\x74\x9d\x7b\xa5\x96\xaf\x87\x61\xd3\x09\x82\x20\xc8\x0b\x85\x91\xc4\x9a\x34\xe9\x96\x33\xe9\x25\xfd\x72\x1b\x12\xe4\x97\x53\xf1\x67\x0b\x9e\xd0\xef\xe1\xbe\x71\x8a\x9c\x43\x8a\xb3\x3c\x49\x31\xdf\x60\x79\x65\x2f\xa3\xeb\x38\x22\x63\x5a\xa1\xcc\x4f\x0b\x9a\x29\x55\x45\xd8\xa8\x60\x55\x5d\x37\x2e\xd6\x56\x55\xa1\x4c\xb1\x0a\xe5\xd5\xf1\xc3\xd0\xe2\x82\x72\x35\x49\xff\x80\x4a\x01\xac\xa0\xcb\xa5\xa7\x7e\xd7\x43\xef\x07\x6c\x91\x62\xdc\x7f\x46\x83\x32\x3a\xbe\x5c\x69\x23\x6c\xf7\x78\x9f\x0c\x6e\xd8\xcc\xab\x8e\x2a\xaf\x0d\x31\x9f\x0f\x86\x9a\x40\x37\x07\xc6\x25\xea\xb5\x61\xca\x9e\xe6\x88\x93\x2c\xb0\xcd\xe4\x9f\x79\x4b\xee\x23\x62\x6f\xb4\x42\xba\x71\x8b\xef\x59\x5c\x1c\xff\x27\xb6\xa2\xb7\x0b\x2f\x14\xf0\x69\x51\x40\xb7\xdc\x83\x54\x74\x9b\x00\xba\x91\x3b\xa6\x21\xba\x02\xeb\x10\x7b\xe1\x07\x1c\x33\x96\x39\x91\xbe\xb2\x2f\x04\x3a\xfc\x72\x9c\x7b\x21\x7a\x1e\x81\x33\xbb\x77\x10\x10\x5d\xe3\x10\xb5\xbe\xce\x71\xfa\xc0\xfd\x3c\x93\xf4\x30\x8e\x3d\xa7\x35\x9d\x47\x5b\xa3\xe8\x1e\x0f\x1d\x04\xe5\x99\x56\x9a\x60\x89\x18\x8d\x35\x65\x46\x50\x77\xd7\x2e\x15\x56\xa5\x92\x20\x8b\x71\x40\xf5\xf9\x54\xb7\x2b\x64\x81\xf3\xd3\xd5\xe9\x7b\x3a\x6b\x63\xb6\xfc\xf3\xe0\x02\x29\x15\x04\x41\xb0\x6a\xb3\x8c\x51\xcf\x91\x52\xc4\xd6\x83\xd3\xef\xc6\x7e\x58\x6a\xec\xac\x24\x6c\xf0\x86\x96\x57\xac\x8d\xb3\x02\x41\x56\x91\x49\xe4\xd1\x50\x15\x31\x84\xb8\xee\xda\x46\xa3\xc3\x37\xe9\xe5\xfd\x6e\x6d\xf3\x24\x1c\x18\x91\x3f\xe1\x32\xc4\x79\x9a\xcc\x70\x9a\x3f\x78\xa5\x1e\xe6\x33\xa8\x1e\xcb\x51\x4a\x43\x9c\x13\x83\x04\xb8\x85\x63\x86\x3d\x72\x83\x1f\x0e\xf2\xae\xa0\xc3\xa1\x92\x8c\xca\x3d\x85\x1c\xf9\xa4\xfe\xcb\x29\xeb\x9f\x82\xa5\xd1\x0b\x04\x4f\x54\x5d\x21\xe4\xe7\xd7\xed\x1b\x74\xd1\xb3\x19\x42\xff\x6d\xeb\x49\x34\xf2\x52\x99\x3c\x9b\xb1\x70\xf7\xb4\xfa\x3a\x74\xac\x1d\x54\xa6\xcc\xe9\xfd\x76\x10\x04\xa9\xbd\xab\x21\xb5\x32\xb9\xae\xfa\xe9\xad\xdd\xd8\xda\x08\x1e\x72\x2f\x35\x14\xac\x55\xdb\x49\xab\xba\x38\xb3\x48\xa0\xf2\x6a\x2f\xca\x48\xc0\x44\x9d\x48\x54\x51\x7b\xa5\x32\x6f\x75\xfa\x07\x89\x5d\xbe\xc4\xda\x78\xe5\x68\xce\x55\x17\x47\xd9\x55\x32\x3b\xa5\x49\xea\xba\xd9\x60\x10\xb1\xbf\xf4\xcf\xb6\xc0\x50\x13\x05\xa9\xa6\xd8\xea\xf4\x39\xf7\x7b\x1f\x01\x2e\x3c\x69\xff\xb8\xcf\xeb\x21\xb1\xe4\xee\x9e\x6a\x95\xf4\x50\xb9\x28\xd7\x81\x63\x89\x44\xc7\x64\x94\xa4\x03\xcc\xd3\xd5\x69\xaf\x32\x1e\x92\x77\x20\x4f\x57\x3e\x1b\x1b\x70\x71\xe1\x4d\x32\x60\x00\x59\x51\x76\x4c\xb8\xcf\xe4\x88\xea\x1b\x33\x4c\x4c\xb4\x23\x04\x93\x72\xec\xe0\x3a\x80\xa2\x2a\x38\x11\xac\xc5\x13\x1a\x3f\xe6\x38\x7a\xad\x55\x6c\x42\xd5\x69\x78\x50\x18\x18\xec\x7b\x16\xa0\x43\x4d\xa8\xc9\x9d\x46\x02\xa1\x39\x8e\xfa\x08\x9a\x77\xda\x95\x76\xe4\xba\xab\x6d\x12\x16\x90\xc8\xc0\x43\x82\xcf\x4b\xc2\x0a\xae\x8c\xec\xa3\xdb\xb2\xd4\x3c\xd5\xde\x34\xd6\x31\x67\xc9\x72\xd9\x1c\xeb\x60\x37\xf5\x53\xce\x85\xcc\xc3\xa5\x4f\x2d\x97\xfa\xfd\xd6\x24\xcc\x0c\x51\x4f\x45\x84\x22\x33\x27\x5b\xa7\xd3\x51\xa3\x5b\x1d\x04\xe3\xb2\xfb\xb0\xd4\x36\xcd\x55\x9f\x9d\x10\x06\x63\x03\xdb\x04\xd3\x0f\xbf\xe5\x6f\xb8\x6e\x33\x72\xdd\x21\xfb\xa1\x30\x36\xba\x46\xea\xe6\x06\x95\x72\xdd\x4a\x49\xfc\x99\x11\xc8\x85\x0a\x20\x81\xb9\x60\xaa\x6f\xbe\x62\x6c\xb1\x37\xf8\xe1\x28\x19\xb2\xc0\x3c\x2b\xe3\xc0\x2e\xf7\xcc\x8c\xab\xcb\x15\xd9\x60\x77\x5a\xf9\xf8\xa4\xd2\x30\xc5\x01\x6e\x85\xc3\x21\x8b\xbb\x78\x1f\x65\x39\x26\x38\xf5\xb8\x2b\xb8\x03\x39\x5b\x03\xeb\x12\xdc\xe0\x07\x86\x83\x04\x44\x49\xd2\x69\x90\xe1\xfc\x84\xe4\x38\xbd\x0d\x63\x6b\xb4\xe4\xcc\x60\xb2\xd7\x5e\x09\xd0\xa6\xde\x4a\xe9\xd7\xf8\x2e\xb5\xbe\x44\xb5\x69\xec\x42\x41\xb6\x5c\x7a\x06\x74\xcd\xad\x5d\xf7\xca\x8d\x1a\x40\x9b\x42\x98\x98\x20\x83\x21\x8c\x6a\x40\x50\xf2\xd6\xdb\x34\x1c\x33\xa9\x87\x73\x6c\xd6\x9e\xc7\x2d\x54\x98\x53\x9b\xd9\x90\x27\xe0\x0c\xc3\x3c\xdc\xca\x71\x96\x3b\xbe\x93\x61\x92\x47\x04\xc7\x3c\x1e\xba\x40\x25\x70\x4f\x8f\x70\xdb\xd1\x75\x81\x36\xcc\x7f\x5a\x9f\xff\x31\x19\x3a\x0a\xa2\xee\x38\x0f\x84\x71\x5a\x58\x4a\xb7\x3a\xc6\x79\x09\x17\x26\xab\x20\x28\xdc\xb6\x2a\xa1\x50\xca\x96\xd5\x74\x7c\x1d\x7a\x6d\x68\x88\x7f\xad\x3d\xb4\x61\x78\x54\x01\x11\xb9\x95\x8e\xb1\x8f\x38\x5b\x8a\x7d\xe7\x66\xb3\x23\x16\x95\x6f\x2d\xca\x1e\xdb\x0a\x62\xfb\x2c\x43\xbd\xe1\x80\x43\x9f\x1b\x67\x11\x51\xf7\x91\xf3\x56\x4b\x2b\xf5\x9b\x6d\x79\x62\x10\xc3\x82\xe3\x08\x1a\x28\xa4\xc7\xb9\x38\xab\xe8\x1e\xe7\x2d\xa3\xfa\x05\xc4\x5c\xa4\x63\x70\xc6\x82\x93\x97\x75\xd9\x25\x67\xc3\xbb\x93\xb6\xe2\xa3\x4d\x9a\xc0\x6b\x43\x98\xf3\xa8\xf6\x90\x5e\x44\xec\x42\x9b\xbd\x85\xa8\xc0\xf0\x4b\xcd\xe2\x31\x84\x55\x3c\xc5\x7e\x52\x20\x88\x82\xb0\xf5\x3a\x1c\xdc\x0c\xd3\x64\xa6\x23\x7e\xac\xe3\xa9\x9b\x9c\x9d\x4b\xe9\x74\xdc\x73\x64\x10\x84\x5a\x16\x18\xd2\x8b\x38\xc9\xf0\xe1\x28\xc7\xe9\x95\x72\xea\xad\x39\x33\x0d\x0d\xa1\x6b\x12\x84\x55\x11\xa2\x7a\x22\xa5\x12\xa9\x92\x32\x98\x8a\x2a\x5c\x46\x58\x2b\x6b\x54\xf1\x32\x74\xba\x6c\x10\xce\xb0\x84\xb2\xa8\xc6\x1e\x85\x25\xa3\x7b\x35\x00\x29\xac\x15\x5b\xaa\x51\x48\x61\x55\x07\xae\x89\x47\x0a\xa9\xb8\xa9\xaa\x09\x67\x3a\xc1\x85\xeb\x5e\xc0\x55\x10\xb6\x6e\x30\x9e\x9d\x72\x70\x5c\xf8\xa0\x9f\x5f\xb9\xee\x15\x7c\x0e\xc2\xd6\x34\x24\xe1\x18\xa7\x70\xaa\xfb\xf0\x73\xf7\x32\xf7\x3f\xc3\x49\x10\xb6\x12\x62\xb7\xe1\x21\xbb\xc7\x08\x8a\xe0\x3d\xfb\x6d\x37\xc9\x37\x76\x4f\x9d\x2a\xbc\xa1\x97\x74\x6a\xbd\xd5\x53\x2b\x84\x9e\x53\x19\x42\x0e\x38\xd6\x70\x29\x47\x41\x55\x87\x0a\x3b\x4e\x14\x03\x43\x9f\x1e\x1e\x1a\xf1\x54\x75\x83\x40\xdf\x36\xbb\xdc\xb8\x6b\xd6\xc6\x38\x61\x67\xdd\x69\x60\x70\x18\x9d\x67\x1c\x5d\xaa\xae\x72\xc0\x31\x3b\xc6\x01\xc7\xe8\x06\x07\x1c\xd1\xe8\x1c\x89\xa3\x54\x3e\xd1\xbc\xec\x57\xb9\x38\xba\x69\xf5\x9a\x04\xaf\xad\xe0\xe4\x36\x82\x2f\xc1\xeb\x5e\xbb\x0f\xbf\x07\xaf\x7b\x9d\xbe\x89\x87\xb1\x28\x14\x1a\x86\x96\x59\x7f\x2b\xdf\xf8\x49\x8b\xa1\xbf\x41\x8a\xe0\x6b\x50\xc7\x75\xac\x25\x7b\x2a\x94\xc8\xdf\x02\x9e\x79\x12\x66\x67\x77\x44\x6b\xbf\x11\xb3\x76\x86\x08\x7e\xa9\xb2\x18\x2a\xa9\xf1\xa3\x86\xe8\x84\x5f\x6b\xd8\x0e\x75\x08\xbb\x54\x7c\x82\xdf\x14\x38\xa2\xf9\x50\xe8\x65\xc1\xc7\xea\xd3\x02\xde\x99\x39\x9f\xf2\xd4\xde\xaf\x1e\x82\x45\xa5\x17\xfd\xf3\x02\xc1\x6f\x5a\xce\x64\x0f\xae\x92\x59\xd0\x2e\xe0\xcf\xba\x90\x7e\x29\x08\xff\xf5\x33\xae\x19\x5a\x2e\x7f\xf1\x10\xb3\x65\x1d\x9c\x52\xb1\x8b\x95\x11\x1b\xe5\x71\xdd\x77\x1e\xd3\x9c\xff\x58\x03\x93\x27\xbe\x7e\xda\xd2\xda\x20\xcd\x88\x69\x1c\xa7\x7d\x04\x3f\xaf\x40\x26\xf8\xa8\x31\x29\x00\xbb\xae\xf7\xcd\x75\xbf\x79\x08\xde\xb8\xee\x1f\x1e\xea\xbe\xf3\x90\x7f\x9b\x7b\xba\xf5\x9b\x6d\x8e\x74\x80\xf1\x9a\xb2\x9c\x0a\x59\xcd\x2c\x00\xd5\xf0\x37\x47\x74\xc5\xd8\xe3\x47\x73\x18\xaf\x01\x1b\x79\xd3\xfd\xd3\x43\xfe\x57\xd7\x1d\x2d\x97\x58\xe0\x8b\xbc\x01\x8c\xe1\x2b\x8c\xe0\x4f\xaa\x14\x7d\x70\xdd\xe6\x1b\xd7\xf5\x9a\x5f\x97\xcb\x2f\x08\x19\xfe\x77\x92\xd9\x7c\xe5\x01\x7e\x45\x32\x12\x42\x13\x6e\xf1\x1f\x7c\x6c\xae\x97\x97\x0a\x61\xc1\xf5\x17\x6c\xaf\x8f\xe2\x28\x7f\xd0\x1e\xcb\x45\xe1\x25\xcb\xa5\x14\xc6\x46\x79\xeb\x53\xc1\xd0\x4a\x16\x8a\x5c\x54\x2d\xd4\x92\x1a\x41\x4a\x7d\xae\xeb\x11\xac\xae\x2a\x8f\x97\x4b\x67\xab\xe3\x20\xf8\xca\xd3\x25\x84\x81\x59\xd0\x11\x30\xcc\xcb\x03\xf9\x77\x8f\x2a\x25\x08\x06\x1a\x70\x9d\x26\xa6\x25\x51\x78\xd4\x2b\xdf\x6c\x23\x18\xb9\xae\x68\xfb\x41\x09\xb2\xbd\xc6\xbb\x70\x90\x73\xc1\xf6\x67\xc3\xe6\x3d\x03\x6b\xed\xf5\x6f\x8a\xc7\x9c\x12\x69\x0e\x3f\x19\x68\x06\x66\x1f\x3a\x7c\x25\x35\xd0\x2b\xfe\xa0\xca\x95\xf7\xde\x75\xdf\x7b\x18\xc1\x3d\xa3\x62\xcf\x72\xbe\xfd\x84\xe3\x90\x57\x06\x0e\x5d\xf7\x90\x61\xdf\x5b\x0b\x31\xc3\x81\x4f\x93\x18\xfb\xce\x2c\xc5\x54\xaa\xe6\x4c\xd1\x05\xbc\xad\x91\xef\x72\xcc\xe5\x3b\x3a\xe4\xbe\x74\x73\xdc\x92\xbd\x5f\xc0\x5b\x25\xe0\xc1\x19\x87\x7b\x2d\xd7\x31\xd6\xf5\xa3\xeb\xbd\xff\x06\xea\xe8\xee\xd7\x21\x77\x78\x27\xae\x7b\x42\xeb\xd8\x1c\xbb\xae\xac\xcf\xb5\xb5\xe9\x30\xc3\x60\x56\xd3\x31\xf7\xb9\x5a\x16\xcd\xfd\xd2\xbf\x86\xf2\x7e\xeb\x4f\xa1\x66\x6f\xf4\x8f\x80\x5b\x5f\xfc\x5f\x40\xd9\x5e\xfc\x3f\x80\x57\xa5\x28\xeb\x37\x03\x20\x18\x21\x4d\x77\xfc\x29\x0f\x88\xf7\x6a\x77\xe7\x15\xbf\x3c\x67\x4e\x15\x53\xb9\x8b\x5e\xe4\x01\xe3\x24\xa0\xbf\xcf\xe8\x6f\x3a\x40\x99\x1f\xdc\x95\xbc\xa2\x8f\x3e\x88\x64\xec\xc9\x67\xdb\x48\x65\x70\xd0\xe8\x53\xd7\x03\xe6\x57\xa1\xa8\x32\xe8\x03\x4e\x95\xc1\x8f\x89\x20\x0c\x88\xeb\x36\x49\x4b\x13\x4b\x74\x73\x0e\xa6\xef\xe7\x02\x64\x5f\x93\x66\xf0\x6b\xce\x69\x18\x08\xcd\x30\x22\xdd\xb0\xeb\x25\xc1\x45\x0e\xa5\x04\x67\x39\xf2\x93\xe0\x2a\xf7\x13\xba\x8e\xf2\xaa\x9e\xb1\x79\xb3\x5c\x8a\x9d\xed\x8c\x4f\xc4\xee\x79\xee\xb3\xf7\x05\x2b\x47\xc6\x59\x13\x93\x02\x38\x91\xae\x5c\x81\xf9\x37\x35\xef\x06\xa1\x7b\x08\xd9\x88\xcd\xc2\x20\x1b\x69\x45\xc4\x75\x19\xec\x0e\x2d\x65\x10\x9c\xe7\x5d\xf9\xc5\x8b\xbc\xe0\xba\x89\x50\xfd\x49\x95\xcd\x23\xdd\x80\xcd\x63\x3e\x1b\x86\x39\xe6\xcd\xe0\x49\x4a\x0f\xb3\x6d\xe8\x8c\xb3\xf2\xf9\xc8\xde\xa8\x39\x6a\x64\xeb\x78\x34\xf2\x70\x33\x30\x28\x19\xac\x13\x51\xce\x98\xc0\x6b\x70\x60\xf0\x50\x44\xa4\x4b\x9a\x41\x70\x96\xbb\x2e\xfd\x7b\x45\xa7\x4f\xce\x7a\xc5\xbe\xbd\x5c\x7a\x79\xf0\x21\x47\x45\x4d\xd9\x3b\x90\xdb\x65\x5d\xc7\x31\x32\x08\xc9\x00\xc7\x1f\x8c\x0e\xf3\x90\x60\x1b\x11\x70\xb1\x59\x05\xe0\x89\x33\x5d\x1a\x55\x93\xb8\xff\x07\x9a\xe2\x31\x20\x01\xa7\x99\x6f\x06\xa9\xeb\x3a\x64\x3e\xbd\x66\x41\xe1\x42\xf0\x48\x5d\xd7\xc3\x41\xca\x39\x1f\x72\xfa\x83\xa1\x62\x13\xc3\x1a\x2b\x1a\xbf\x2b\x7f\xf8\x39\x82\x05\x03\x64\xc5\x82\x2a\x24\x97\x54\x22\xa4\xa0\x45\x36\x5b\xa1\x7c\xe4\x27\x37\x2c\xcc\xbe\xdb\xec\x20\x51\xb6\x20\x97\xa7\xa5\x35\xed\x00\x74\x39\x3b\xcb\xbb\xbc\xa2\x38\x1d\x25\xe9\x94\x8d\x7d\x0f\x23\xdf\xba\x79\x1f\xe5\x1e\x92\xf7\x58\x8b\x58\x73\x47\x92\x82\x18\x9d\x1e\x04\xc1\x45\x5e\x26\x0b\x91\x43\xfa\x3c\x2f\x58\x27\x98\xdf\x0c\xea\xcf\x48\x80\x98\xfd\xc0\x5b\xd1\x38\xc9\xc0\xf7\xa2\xf8\xe2\xc2\x58\x33\x7c\x0c\x89\xf9\x2e\x49\x86\x54\x06\xef\xf6\xd2\xbe\xdf\xb3\x05\x42\x46\xd3\x03\x69\x1f\xc2\x20\xa1\x82\x7d\xc4\xb9\x98\x63\xfe\xba\x31\x54\x3c\x04\x59\x90\x76\x63\xd9\x65\x31\x2f\xd1\x01\x5e\x2e\x49\xd7\xe4\x5b\x11\xbb\xb9\xc7\xe8\x5b\x78\x23\x84\x23\x7c\x59\x6e\x88\xb3\xbc\xb0\x40\xa4\x72\xfb\xf5\x88\x8c\x45\x0e\xad\x84\x68\xcd\xec\x98\x0c\xbd\xac\xf4\x5e\x6d\xf6\x57\xeb\xb3\xc7\x43\x96\xbb\xa0\x71\x43\xb2\x83\xbf\x37\x2b\xce\x04\x9f\x9a\x83\xa6\x9e\xc2\x05\x72\xab\x4f\x19\x2d\x4a\x5d\x53\xa7\x75\xdd\xc7\x87\xba\x5f\xd3\x81\x07\x79\xb9\x0b\xe8\xb0\x4d\xd7\xb5\xff\x87\x52\xad\xb0\xf5\x2e\x6d\x7e\x66\x26\x2d\x37\x3e\xe1\x85\xb6\xdf\xac\xfd\xc0\xc5\xda\x0f\xe0\xa1\x38\x3d\x7c\xb4\xf9\x37\xcc\x87\xae\x8a\x95\x89\x5e\x63\x8a\x67\x1f\x32\x77\x31\xba\x0c\x97\xef\x89\xac\x3c\xd1\x80\x95\x4d\x8f\x7d\xce\x2c\x6d\x69\x51\x12\xbd\x9c\xe1\xdc\x5a\x76\x72\x54\xa2\x93\xc2\x62\x3d\x2f\x25\x5c\xbd\x20\x34\xdb\x07\xe6\xe9\x1a\xa9\x7d\x29\x65\xa7\xcd\x1e\x09\xe8\x7e\x51\xb3\x63\x63\x2f\xa5\x0d\xb6\xaa\xd6\x56\xa3\x31\x86\xaa\x4a\x4a\x5a\xe6\xd2\xc8\x28\xb7\x40\x7d\xfd\x0f\x8c\x8d\xd2\x1e\xdc\xd5\x5b\x52\xd8\xf4\x6b\x57\xac\x80\x87\x34\x61\xd7\x6d\x1a\xaf\x86\xc3\xe1\x31\x19\x4a\x63\x3d\xdd\xa9\xa9\x3c\x95\xb2\xb3\xa4\x95\xc9\xa4\x15\xb3\x6e\xc5\xac\x54\xbd\xef\xf7\x48\xb5\x41\x4a\xeb\xe7\xc1\xca\x6f\xf1\x65\x87\x8f\x45\xec\xba\x06\x74\x7b\x25\x4f\xc0\xa8\xc0\x71\x86\x1b\x6b\x13\xb5\xd9\x00\x5a\x4b\x1b\x65\x49\x24\x54\x78\x61\x52\x56\x45\x35\x35\xbb\x05\x52\x33\xac\x25\x09\x3c\xd2\x8a\x08\x10\x4b\x4c\x04\x62\x6f\x85\x40\x24\x0d\x14\x91\x7b\xbe\x58\xe1\x14\x79\x10\x29\xb5\x06\x10\xb9\x8a\xea\x5f\x11\x19\xeb\x0b\x3c\xe4\xbf\x79\x36\x6a\x6d\x52\xbf\xd9\x73\xd1\x59\x20\x79\xaf\x4a\x31\x2f\x11\xfd\xcf\x2c\xb8\x03\x8e\x55\x70\x47\x73\x95\x49\x76\x32\x41\x48\xe6\x88\x82\xd3\x14\x56\xc1\xb9\x05\x4d\xa4\xd5\x05\xd7\x17\xdc\x8a\x26\xb3\x57\x05\x57\xbf\xd9\x73\x51\x70\xa7\x8f\x56\x46\x22\xd4\x50\x5e\x31\x89\x18\x6a\x4c\x3e\x69\x37\x65\xde\x8c\x7e\x49\xf5\x31\x80\x8c\x12\x12\x3f\xd0\x85\x3d\xa1\x0b\x00\x29\xf1\x63\x29\x8d\xe5\x34\xf7\xd0\xa2\xf8\x9c\x4b\xd1\xe2\xea\x61\x86\x83\x33\x0c\x9f\x73\x9b\x40\xeb\x73\x5e\x22\xd0\x62\xe4\x87\x60\xb6\x35\xbd\xb6\x1a\x9b\xde\x10\x22\x44\xb3\x23\xa4\x3d\xc9\x7a\xd8\x6c\x83\x68\x3e\xff\x34\x07\xdd\xac\xc6\x15\x1e\x8a\x0b\x9a\x5e\xfd\xd2\x69\x38\x39\xdd\x69\xce\x0a\xf7\xf1\xc3\xe9\xd9\xc7\x0f\x57\xc7\x6f\x82\xf3\x9c\x5e\x1f\xff\x71\x42\x2f\x2e\xf8\xc5\x87\xab\xe3\x8b\x93\x0f\xef\x82\x33\x7d\x79\xfc\x26\xb8\x52\x29\xe9\xb3\x0f\xf2\x18\xe4\x24\x0f\x3e\x73\x87\x94\x43\xe6\x22\xbd\xfd\xaa\x83\xe0\x3d\xfb\xf9\x62\xcf\x68\xba\x6f\xb9\x69\x7c\x14\x87\x22\xcb\xe5\xfb\xbc\xf5\x89\x39\x32\xbd\xc9\x6b\x2d\x78\xda\x00\x68\x50\xcf\xbf\xb5\x1c\x51\x35\x05\x17\xd5\x21\x99\x6e\xaf\x5c\x1c\x82\x20\x48\xbb\x8b\xc2\x97\xca\xa1\x86\x35\x49\x0c\x58\x13\x89\xc0\xbf\x5c\x4a\xa1\x5d\x0d\x1d\xd2\x25\x3e\xe9\x31\xeb\x27\xee\x2f\x97\x6d\x18\xe2\x38\x7c\xb0\xdf\xa6\x77\x0a\x56\x89\xd7\x79\xb0\x90\x1a\xb1\x85\xe3\x2e\x14\x63\xf3\x5e\x01\x5f\x64\x6a\xff\x30\x6f\xdd\xbf\x6a\xc9\x37\x2f\x07\x29\xc6\x82\x78\x93\x3f\x89\x39\xea\x3e\x7f\x50\xc0\xef\xdf\x11\x7d\xa7\x22\x7d\xd2\x68\x90\x9f\x26\x43\x4c\xc7\x77\x98\xd7\x38\x79\xb0\x15\x2d\x0b\xf4\x0a\x34\x0f\xcc\x65\x67\x10\x58\x2b\xd2\x30\x50\xeb\xd0\x28\x30\x56\x9f\x59\x60\x2e\x4b\x2c\xbe\x99\xf5\xcc\x34\x20\x2d\xbd\x3f\xae\x00\xb0\x3b\xc9\x05\x7c\x9d\xec\xd9\x07\x13\xb4\xee\x4b\xee\x8f\x4d\xa4\xba\xd2\xb2\xb6\xa2\xa6\x72\xc1\xab\x2c\x4f\x72\x45\xb2\x96\x2a\x73\x79\x32\x96\x2c\x11\xf1\x47\x6b\xe2\x80\x53\x53\x0f\x63\x69\x64\x90\x79\x74\xd8\x33\xda\x9d\x39\xc9\x18\x2d\xf3\xe7\x4c\x95\xcb\x75\x9b\x11\x1c\x97\x4f\x02\x6e\xf4\x49\x40\xc2\x1c\x52\x52\x04\x97\xfa\xde\x7d\xf7\x58\x7a\x91\xdf\x20\x38\xaa\x9b\x34\x36\xf5\x23\xdd\xd7\xa4\x6b\xfb\x7d\xb7\x77\xac\xec\xc7\x79\xdf\x67\x5e\xe8\x9c\x18\xf1\x53\xce\x19\x42\xb7\x51\x69\xc7\x36\x4e\x19\xb1\x17\x22\x1f\xf3\x9d\xba\x28\xe0\x53\x70\xe4\x0d\x10\x9c\x07\x47\x65\xbe\x97\x37\xb9\x0c\x31\x20\xc1\xdb\xdc\x13\xe6\xb9\x89\xe2\xd1\x7a\x28\x60\x41\x67\x94\x2f\xb6\x95\xc2\x88\x91\xe0\x27\xd6\xaa\x65\x83\xbb\x5a\xc4\x22\x31\x8f\x1c\x20\xda\x6f\x32\x7f\xca\x4b\x99\xeb\x66\x92\x07\x06\x2e\x82\x23\x6f\x8e\xe0\x2c\x38\xf2\x66\x08\xae\xec\x0a\x49\x49\xf3\x91\x8a\xd0\x11\xf3\x17\xea\x91\x7f\x4f\x3d\x72\x04\x43\xd7\x1d\x0a\x6f\xbe\x0f\xc1\x91\x37\x5a\xb9\x61\x1a\x98\x6a\x72\x9b\x69\x43\x44\xfc\x18\xc4\x6e\xeb\x1b\x43\x4b\xee\x36\xe7\xc6\xf6\x72\x61\x6e\x3c\x9f\xe4\x56\x73\xa5\x37\x97\x0f\xc6\xa6\x73\x66\x36\xd1\x35\x82\xd2\x12\xa5\xcb\x68\xee\xc7\x89\x2e\x62\xc9\xa0\xab\xd9\x46\x4c\xeb\xbd\x30\x44\x36\x83\x80\x2c\x97\xb1\x54\x03\x35\x0c\xc9\xeb\xbc\x47\xfa\x30\x81\x44\x48\x9c\xdc\xee\xcb\xdc\x02\x2e\x0b\x48\xa5\x92\x25\x81\x46\xf3\xe0\x77\xbe\x93\x7d\xfc\x5b\xa3\x9b\xb5\x13\x44\x1d\x88\x04\x3b\xa9\xa5\x6b\x6a\x75\x3b\x62\x6b\x6b\xdd\x5a\x69\x21\x32\x3d\xcb\x19\x14\xd3\xd3\x02\x9b\x2b\x6e\x16\xe0\x54\xbf\xbf\x62\x85\x5b\x1d\x1d\x3a\xd2\xfd\x17\x11\x7f\xae\x86\xc0\xa0\x80\xd9\x4a\xef\x99\x75\xa1\xcb\x19\xc7\x32\x10\x65\x45\xb0\xca\xc3\xc3\x8a\x56\xfe\xad\x12\xad\xbc\xc6\xc7\xa6\x84\xc9\xf7\x14\x38\xe2\xff\x8a\xee\x39\x26\xbc\xae\x3c\x07\x2f\x90\xf7\x51\x28\x98\x3f\x09\xdb\xfe\x0b\x43\x30\xfb\x6a\x09\x53\xf5\x61\x03\xf9\x2a\x06\x3c\x7e\x94\x38\x0a\x6f\xf0\x95\x44\x17\x40\x24\x28\xdd\x31\x7d\x6d\x57\xf9\x9e\xe7\xe8\x80\x04\x09\xbd\x2f\x0f\xb0\x19\xe1\xae\xa7\x30\x91\x15\x7a\x81\x83\x96\xcb\xba\x84\x46\x02\x26\x8b\x85\x41\x1b\xa2\xa0\x2d\x54\x5d\x1e\xd0\x4b\x57\x0a\xd7\x75\xe8\x16\x4c\xc6\x86\x90\x27\x49\xdc\x09\x73\x11\xce\x3d\xc7\x73\x50\xaf\xd3\x97\x57\xc8\x41\xbd\xb6\xba\x02\x07\x1d\x84\x81\x0a\x3d\x8b\x7b\xbb\x2c\xa6\x0c\x22\xf3\xde\x1e\xbb\x27\x1c\x84\x39\xf2\x11\x0b\x8f\xd0\xd0\x0b\x7f\x78\xca\xb3\x5f\x34\x8a\x0e\x97\x00\x67\x76\x8f\x1a\x66\x52\xc5\xa0\x14\x6e\xa5\x8c\x9d\x8f\x25\x71\x90\x84\x45\xaa\x64\xbe\xa5\x72\xe7\xe9\x9f\xa7\x3c\xfc\x70\x2b\x54\x6f\xce\x67\xe5\xd7\xfe\xac\x2f\x13\x8f\xc3\x28\x15\xea\x4f\xa3\x50\xd1\x56\xda\xca\x93\x99\xca\xd9\xc4\x97\x30\xca\x91\x27\xb3\xe7\xa9\x08\x78\xdc\x8a\x44\xea\x82\x0d\xb5\x03\xe2\xba\x5e\x5e\xdd\x3b\x69\x87\x06\x04\x72\x73\x6b\xe4\xf7\x78\x2f\xff\xf2\x9d\x32\xb4\x58\x2b\x7e\xfd\x2e\x49\x3a\xc5\x1c\xbe\x35\xd2\xeb\x70\xd8\x75\x98\xf3\xa3\x5f\x2b\x41\x0f\x2c\x09\x7a\x68\x4b\xd0\x5a\x6c\x36\x84\x66\x3c\x64\x32\xb3\x96\xa0\xa7\x4a\x82\xbe\x35\xe4\x62\x03\xcc\xf9\xb6\xfb\x4b\xee\x73\x3e\xa2\xba\x3d\xe3\x5a\xa7\x7c\xa0\xf2\xf5\x03\xdc\xad\x91\xa0\x45\x0d\xff\x0d\x32\xb3\x36\x1c\xd4\xef\x2d\x70\xcf\x65\xe6\x1a\xb9\x78\x8d\x9b\xf7\xf1\x63\x6e\xde\x97\x65\xa9\x9a\x09\xcf\xea\xde\x25\x95\xb2\x3f\xad\x17\xa6\xd1\x02\xbb\xae\xa7\x5a\x31\xef\x62\x4f\x7d\x96\x8a\xc5\x86\x64\xcd\xce\x76\xcf\x83\x4f\x65\xb9\xf8\x6b\xee\x45\x80\x11\x30\xf9\xb8\x2c\x82\x9a\xa9\x8d\x70\x54\x2a\x76\xca\x8d\x74\x2c\x08\x91\xa7\x55\xf9\x39\x5f\x25\x77\xde\xd7\x8a\x90\xd5\x65\x15\x8c\xd3\xf3\x14\x16\x9c\x27\xcd\xbf\x5f\x45\x9e\x76\x36\xcf\x59\xb0\x5f\x55\x66\xad\xff\xe0\xdf\xf5\xa1\xf2\xda\x20\xf1\xf1\x2b\x0b\x84\x78\xc0\xe4\x63\xda\x9c\x34\x93\xb3\xe0\x13\xd5\x58\xae\x82\x4f\xde\x84\xca\xcb\x56\x93\xcb\x2d\xf0\x91\x06\x17\x72\xfe\xdf\xda\xde\x64\x7d\x33\x64\x93\x30\x9d\xfd\x0d\xad\xbd\xe9\x67\xd8\x30\xcd\x99\x3f\xc9\xc8\xe3\xc3\xf3\xb3\x3d\x98\xd9\xe1\x46\x7d\xfd\x1d\xa7\x4e\x91\x71\x1c\x98\xb9\xee\x4c\x68\x2a\xa7\x6b\x3c\x96\x8e\xb5\xaf\x15\x2b\x87\x9e\x63\x82\x2f\xf9\xb1\x88\x8c\x68\xe4\x35\x63\xd7\xe5\xeb\x31\x87\xe1\x17\x9b\x24\xbd\x30\xe2\x26\x7e\xaa\xb8\xd1\xac\xfb\xb6\xfa\xae\xd8\x19\xab\x5e\xf9\x29\xce\xa2\x6f\xd8\xa1\x13\xdc\x3a\x96\x61\x4e\xf6\x1e\x02\xf1\x62\xad\xf3\xbc\x7e\x97\xbb\xbd\x47\x10\xaf\xf1\xb6\x8a\x97\xcb\x53\x09\x83\x70\x5a\xe3\x18\x7f\xad\x7b\x5d\x2a\x77\xc7\xb5\x3a\xdd\x99\xa9\xd3\x5d\x48\x9d\xee\x83\xd6\xe9\x3e\x1b\x3a\xdd\x15\x94\x14\x47\x35\x4b\x0a\xb8\x7b\xba\x8a\x47\x65\xf7\x23\x28\x29\x7a\x4f\x51\xef\xa6\x25\xc5\xce\x54\xe9\x68\x27\xbf\xfb\xeb\x38\x40\xb5\xce\xd6\x1c\x02\x9d\xe3\x00\x65\x5f\xe7\x61\x8a\xcb\x74\xd5\x6c\xc3\xc7\x31\xbe\x95\x7a\x9c\xf6\x1e\xeb\x76\x7c\x0e\xfe\x23\xf1\x6d\x6d\x5e\x42\xf5\x12\xa7\x26\xdc\x08\xe7\x47\x9b\x9e\x78\x69\x1c\x30\xb2\xd1\xa8\xb4\xab\xf5\xb6\x78\x43\x54\x1f\x41\x94\xc2\xa8\x7a\x67\xdd\xa4\x25\xaf\xfd\xa4\x67\x7c\x51\xca\x7b\x43\xd4\x87\xe6\xdc\x75\x13\x4e\x20\x8d\x87\x06\xc2\x94\xa1\xae\xfd\x59\x07\xe1\xa3\x16\x63\xed\x80\x97\xd3\xf5\x69\x98\xdc\x65\x75\x11\x9c\x74\x73\x25\x75\x85\xc8\x51\x3f\x60\x00\x40\xec\x5d\x1f\x17\x74\xf9\xd1\x43\x90\xe3\x03\x95\x74\xaa\x5c\x61\xea\xe8\x27\xad\x59\x38\xa3\x82\x5c\x29\x81\x89\xa1\x09\x06\xcc\x76\x5e\x0f\xb3\x9d\xdc\x6f\xf1\x4a\x38\xcc\x97\x8d\xb5\x8a\x44\x08\x17\x1c\x33\xac\x9a\x33\xdc\x32\x6f\x16\xa0\x5a\x5a\x24\xae\x05\x12\xcf\x2b\x40\xe2\x45\xc1\x36\x3e\x43\x2b\x3c\xa7\xd5\xa0\x2a\xe1\x3b\xa1\x12\xfe\x91\x07\x0b\xa6\xb2\x8a\x35\x52\xa8\xb5\x02\x14\x9e\xa1\xc7\xf1\xa8\x1e\xa1\xe6\x52\xad\xa1\x80\x9f\xbf\xd7\x74\x8d\xc9\x66\x48\xd7\x64\x30\x49\xd2\x12\xd4\x35\x2b\x92\xc0\xb9\xb6\xe3\x1c\x62\x53\x46\xcf\x8c\x39\x3d\xb7\xe6\xf4\xba\x59\xb9\x2f\xa6\x25\x73\xd7\x95\x10\x9d\xde\xc8\x9c\x9c\x8b\xc2\x1f\xa1\xd2\x97\x8d\x29\x3a\x32\x7c\xec\x15\x48\xe6\x54\x50\x76\x26\x19\x17\xdc\x99\xb9\xa7\x8e\x43\x94\x75\x0c\xcf\xd3\x12\xd5\x17\x85\xcf\xd9\x43\x2f\xe3\x68\x28\x08\x32\xef\x57\xc8\xf8\x16\x00\xf6\xaf\x39\x03\xc0\xae\x35\x2c\x5d\xea\x84\x37\xdd\x9f\x73\x9f\xd3\x89\xca\x15\xe9\x93\x7e\x7a\xd4\x75\x72\x3c\x9d\x25\x69\x98\x3e\x38\xfe\x11\x9c\x97\x00\xb5\x59\x37\x3d\x16\x47\x50\xb7\x6a\x99\x0b\x94\x6e\x72\xdb\x13\x9f\xdb\xa5\x74\xc3\x38\xe0\xe8\x46\x58\x6d\x7e\xaf\xb3\x63\xe9\x35\x10\x2e\xb8\x7e\x71\x66\x51\xec\xad\x64\x12\x3b\x33\x82\xfb\x0c\x3e\xb1\xab\x5a\x9f\x3d\x27\xcd\x63\xee\xed\xaa\x34\x28\xd7\xad\xea\x14\x2c\x22\xbb\x27\x66\x98\x98\x76\x7d\x33\x32\xdb\xcb\x51\xf7\x8f\xbc\x97\xf7\xfd\xbc\xf0\x2e\x20\xa4\xa2\x6a\x79\xcd\xfe\x33\xd7\xcb\x98\x6a\x4c\xdf\xe8\xad\x20\x08\x3e\x75\x87\x7e\x1b\xf8\xa6\xc0\x28\xbd\xaf\x6b\xcd\x6d\x99\x58\xdc\xb2\x9e\xc3\x7e\x1c\xf2\x5e\xad\x80\xb5\x5d\x21\xd4\x87\x6b\x63\x3e\x19\x5f\xe3\xe1\x31\x76\x0e\x6f\x92\xc1\x0d\x1e\xd6\xe7\x43\x57\xa5\x98\x99\x8f\x9c\x19\x4e\xa7\x21\xeb\x3c\x5a\x64\xf4\xdd\xd8\x9a\x19\xdf\xa7\xb2\xd6\x90\x7d\x17\xe6\x6a\xbf\x39\x47\xf0\x81\xf7\xdb\xe7\x4a\x3b\x1e\x5b\x36\xcb\x31\xa8\x9e\xf3\xff\xc8\x7b\x57\x7d\x25\xe3\x5c\x4a\xe1\xe7\x4c\x87\x35\xdc\xb1\x7c\x45\xdf\x0b\x4e\x40\x59\x8f\xee\xdf\x5c\x81\xcf\x55\xf2\x92\x23\x63\x08\x58\x13\xd0\x74\x84\x8e\x60\x06\x8b\xea\x9c\xf0\x2f\x0b\x04\x95\x88\x20\xff\xb7\x1c\xd6\x15\x8c\xfb\xd9\xcf\x11\xf7\x25\x1e\x83\x98\xac\xfe\x54\x15\x14\x26\xb4\xa8\x7a\x77\xcf\xc9\x06\x00\x7d\x05\xf0\x1a\x4b\xd0\xd9\x76\xa3\xcd\x41\x67\x0b\x60\xc3\x49\x03\x79\xff\xe9\x3b\x1c\x8d\xb6\x64\xb7\xa5\xff\xbf\x51\x3d\xe7\x0c\x92\x78\x3e\x25\x65\xce\x73\x89\x68\x2b\x32\xaf\x44\x11\x0c\xd3\xf0\x0e\xa7\xc2\x28\x2b\x41\xc2\x79\x64\x0a\x03\x0f\xcc\x93\xf9\x60\xe2\x54\x6d\xc8\xdc\xee\xab\x58\xe4\x44\xa1\xf9\x1c\xe0\x20\xe8\xc2\x26\x2c\xb6\x56\xb3\x6a\x3c\x95\x00\x3b\xe7\xfb\x30\x2f\x9c\xb0\x2e\x5b\xc9\xae\x92\x99\xbf\xb0\xad\xcc\x62\x53\xb6\xde\x51\xd5\x16\xc0\xbd\xe1\xfd\x4f\x66\x3b\x58\x59\x4a\x70\x73\xb6\xd1\xf3\xf4\x76\xd6\xed\xef\xc9\x95\xcf\x7c\x5e\x77\x21\xc8\x88\xa4\x9b\xd0\x9f\xd4\x64\xc5\x6a\xfe\x1d\x4c\x2a\x35\x59\x89\xb6\xe6\x99\xb1\x22\x7e\x77\x56\xb2\xf1\x78\x5e\xb4\x8c\x9b\x66\xc5\x26\x52\x85\x8c\xe4\x0d\x1b\x80\x74\xa0\x32\xb2\xf5\x02\x79\x98\x88\x63\x54\x12\x10\xef\xd5\xfe\xab\x1d\x04\xe9\x66\x12\x14\x1e\x8e\xeb\xa3\x6e\x95\x9c\x14\x1b\x72\x52\x66\xc9\x49\x73\x85\x81\x3a\xd0\xa2\xc0\xdc\xc0\x40\xb5\xa0\x77\x87\xb5\xa0\xbb\xe2\xe1\x5b\x83\xf3\xbc\x8e\x1e\x84\x6a\xbd\x25\xf2\xba\x29\x03\xc4\xe4\x04\x76\x96\xb4\x41\xab\xb4\x19\x53\x1b\x47\x3e\xad\xf2\xae\xbd\xb5\x88\xba\x99\xc6\xbd\x5a\x2b\xfa\xb2\x9e\x0e\x34\x16\x8b\xa2\x05\x76\x3a\x70\xdd\x78\x25\xd8\xe9\x80\xee\x9f\x23\xd7\x8d\x75\xcb\x39\xd9\x34\xe4\xa0\x3c\xb7\xec\x4d\x56\xa4\xca\x8b\xb7\xf4\xc5\x05\x63\x19\xf2\x63\xd6\xb3\x9c\x53\x0c\x93\xa1\xb8\x3e\x26\xc3\xa2\x17\xf6\x11\x98\xb4\xe7\x54\x4f\x37\xa8\xc9\xfd\xe6\x44\x33\x14\x8d\xe4\x8a\x3d\xae\x39\x98\xe3\x08\xea\x46\xa5\xe3\x56\x1c\x5e\xe3\x58\xc1\x55\x0b\xf0\xd5\x4d\xd6\xf6\x2a\xc1\x03\x94\x16\xf9\x47\xa0\x4f\xb7\x77\x91\x42\x0d\xee\x6c\xdb\x84\x9c\x1c\xd8\x5a\xb3\x3c\xa8\x43\xcd\x41\x3d\xcf\x10\x87\x71\x80\xff\x7b\x7c\x48\x65\xd5\xd2\x6b\x03\x21\xad\xb7\x5f\x91\xb7\xaa\x6c\xf5\xdc\x48\x67\xfc\xfc\x1b\x7d\x2f\x47\x52\x89\x38\x6b\x3d\x1f\xea\x8a\xc6\x93\xef\x17\x05\xa8\x21\x28\x41\xde\xd9\x3a\xba\xd5\xd9\x06\xe7\x19\x1d\xc2\x97\x74\x54\xbb\x8e\xfd\x74\x47\xbc\x78\x4c\x86\xf2\x01\x5f\x8b\x57\xbe\x27\x1e\xef\x14\x7f\x23\x93\xc6\x53\x7b\xc7\x7a\xf7\xdf\xd3\x39\x4f\x25\xf7\x78\x6a\x15\x4a\x6f\xff\xbb\x2a\x61\xb2\x9f\xa9\xce\x54\xd0\xc1\xfe\xce\x63\x10\xc7\x2f\x51\x01\x6c\x99\xf1\x17\x16\x81\xdd\x9a\x23\x7a\x45\x7c\x5b\x3e\xa3\x5f\x81\x32\x7c\x32\x48\x08\xa7\x9d\x65\x10\xc3\x62\x73\x0d\xc9\xbf\x9b\x30\x00\xe2\x0a\x57\xc6\x5f\xe7\x10\x00\x93\x7c\x8e\xa1\xbd\xe9\xa6\x71\xdd\xa4\x8e\x85\xb2\x4c\x3b\xc0\xd7\xf1\x78\x93\x75\x5c\xd1\x3f\xec\xed\x3f\xb2\xba\xd2\x52\x5d\x4e\xd2\x88\xdc\xf8\x6d\xa8\x65\x7d\x5e\xc1\xab\xa7\xf9\x22\x5e\xae\x60\x69\xa3\xfd\x47\x7b\x2e\x24\x86\x03\x43\x66\x14\xd6\xc9\x06\x61\x8c\xf5\x29\x36\x06\x07\x1a\xfa\x9c\xfa\x34\xcc\x27\xad\x59\x72\xe7\x61\xd8\x46\xe0\x20\x07\x15\xc4\x7b\xf5\x72\x7f\x97\x0f\x84\x39\xa9\x75\xdf\x34\x98\x13\x32\xe2\x75\x50\x9d\x3b\xa7\xc9\xae\xc0\x19\x96\x0b\x18\x90\xff\xb7\xdd\x34\xe5\x21\xb3\x2d\x9e\xb1\x3d\x5b\xb8\x67\xd6\x19\xa1\x2c\x57\xcd\x93\xff\x2a\xae\x9a\x8f\x1e\x3b\x9b\x98\x5f\x70\x6f\x5e\x1c\x73\x83\xd1\x4d\x70\xbc\xd2\x89\xf3\xb2\x7c\x58\x7d\x54\xe3\xc4\xf9\x49\xdf\xbb\xe9\x5e\x4a\x4f\xbb\x23\x04\xe7\x4f\x73\xe2\xbc\xe9\xf6\x2e\xff\x3e\x27\xce\x8b\xe0\xdc\x1b\x20\x38\x0b\xce\xd7\x38\x71\x42\x5a\xeb\xfd\x78\x5b\x39\x86\x86\x24\x48\x95\x4c\x04\x21\xbd\xc0\x71\xf8\x70\xc0\x47\x0d\xf3\x52\xf0\x48\x70\x6c\x89\x50\x63\x9c\x1f\xce\xf3\x84\x6b\x93\xd2\x3e\xe1\xd9\x18\xa0\x08\xee\x35\x38\x14\xf2\x49\x90\xd4\x1d\x32\xf6\x8e\xd7\xbb\x4b\x6a\x21\x8e\x08\x3f\xee\xb0\x40\x70\xfc\xd8\x09\xaa\x7e\xad\xb5\xbf\xbf\xff\x1f\xc6\xbb\xfd\xd6\x97\x24\x22\xcc\x25\xc8\x3e\xcd\xbf\x0a\xce\xbd\x39\x82\x0f\xc1\xb9\x37\x43\xf0\xd9\x6e\x5c\xe1\x50\x0a\xe4\xb1\x46\xe5\x47\xcd\x2c\xe4\x44\xb5\x69\xc2\xd8\x50\xca\x6d\x9a\xff\xc5\x36\xcd\x91\x9f\x07\xe9\x5f\x6b\xd3\x5c\xfa\xc6\x7f\x47\x9b\xaa\x77\x97\xcb\xd6\xce\xce\xce\x7f\xe4\x76\xdb\x2a\x8c\x73\xfe\xd5\xc0\x69\x97\x0e\x99\xd9\x89\x7f\x46\xbc\xd6\x8b\x3d\xcb\x25\xf6\x34\x38\xb7\x5c\x62\x37\x05\xbd\x60\x47\xb6\x32\xb6\xe8\x4e\x9f\x02\x0b\x6f\x92\xf2\xa6\xfd\xf0\xa8\x6f\xad\x31\xe3\xe5\x39\xec\x99\x71\x0e\x7b\x55\x7b\x0e\xfb\xd9\x08\xdc\x30\xce\x61\x3f\x80\x1d\x73\x53\x0b\x36\x7c\xd3\xc5\x7e\x6e\x8c\x11\xd7\xd5\xf5\x08\x8c\xc0\x29\xa2\x47\xc1\x72\xd9\x66\xe1\x6f\x62\x20\x1a\xe3\x8b\xa1\x24\xdc\xfe\xbd\x8e\xbc\xd6\xa6\xca\xfa\xed\x29\x67\xbf\x73\xb2\xd2\xb5\xf7\x93\xe5\xda\x4b\x5a\xd3\x79\x74\x39\x9f\xcd\x92\x94\x4d\x89\xa0\xd9\x16\x62\xcf\x90\x04\x03\xa2\xc5\x88\x91\xd5\x7c\x32\x9c\xb0\x12\x10\x92\x77\x49\xa0\x9d\x40\x99\x1f\x10\x09\x24\x8a\xff\x8f\xdb\xbe\xc3\xed\x66\xec\x09\x8b\x35\x94\xcf\x10\x10\x0d\xa5\x3e\xfb\x4b\x1f\x63\xe2\x31\xfd\x96\xf2\xfd\x93\x9f\x62\x4f\xac\x2f\x4d\x8c\x4d\xa5\x87\x5b\x93\x24\x8d\xbe\x25\x24\x0f\x63\xc0\xad\x5b\x9c\xe6\xd1\x20\x8c\xfb\xad\x69\x38\xab\x93\xfd\x2a\x05\xc2\x5d\xc7\x94\xad\x66\xf7\x0e\xf2\x71\x81\x90\x98\xab\x0d\x13\xa9\x7f\x6a\x66\xb4\x12\x87\x87\x79\xf1\xdd\x6e\x78\x2a\x38\x10\xdb\x8a\x3c\x20\x3c\x8e\x99\x49\x8b\x5f\x9c\xa5\xd1\x38\x22\xf6\x51\xfd\x42\x56\xd1\x77\xf2\x64\xe6\x80\xae\xbe\xa4\xa3\x14\xe7\xf8\x3c\x8b\x73\x61\xda\x65\xd2\x13\xbf\x75\x81\x47\x38\xc5\x64\x80\xed\xf3\x42\x47\x16\xc0\x11\xe7\x86\x4a\x8a\x9b\x19\xaa\xc2\xc4\x52\x15\xa6\xcc\xac\x26\x71\xd5\x6e\xad\xc3\x48\xcb\x91\xef\xa5\xf0\xe3\x63\x5e\xb2\x4c\xa3\x39\x94\xd5\xbd\x0e\x48\x4b\xc8\xc9\x93\x14\x67\x93\x24\x1e\xda\x0c\xb9\x9d\x7d\x41\x8e\x2b\xc5\xc2\x63\x4b\x2c\xbc\xb1\xc5\xc2\x4b\x2d\x16\x1e\x99\x62\xe1\x27\x4b\x2c\x3c\x97\x07\x97\x17\xf6\x41\xe5\x99\xfe\xf0\x45\x77\x51\xf8\x17\x70\x25\xcf\x1b\xe9\xc4\x16\x1d\xf2\x41\xa7\xba\xda\xa4\x43\xae\xe0\xf3\x0a\xd1\xd2\x82\x4b\x1b\x12\x06\x97\x56\x7b\xbe\x79\xa8\x13\x9e\x48\x89\xf5\x04\xde\x5b\xd9\xf2\x2a\x7c\xd3\x29\xdf\xd3\x2a\xbc\x87\x37\xa5\x23\x4e\xe9\x08\xa9\x3a\x5c\xfe\xe4\xd5\x53\x97\x72\xec\xa8\x1b\x6a\xe4\x6c\x66\xb3\xd4\xb0\x6a\xe6\xd9\x68\x75\x08\x30\x24\x33\x6b\x00\xfc\x3d\x92\x72\xdd\x71\x6b\xa9\x2b\x9f\x76\xe6\x5a\x6a\x6a\x2a\x64\xbf\x35\xe5\xea\xd7\xeb\x1c\x3a\xa3\x91\x57\x6e\xd7\x20\x08\x86\xf2\x74\x30\x13\x88\xb2\x53\xe2\x85\x0c\xa1\x3d\x77\x5d\x86\x91\xad\x08\x2f\xba\xb9\xaf\x40\xce\xde\xaa\x0d\x9c\x53\xd7\xac\xf2\x66\x87\x34\x60\x80\x19\xdd\xb8\xa5\x87\xa9\x58\x7c\x65\x00\x61\x9e\xcc\x7c\xc2\x3c\x99\x47\x7c\x75\xe2\xe7\x25\x84\x3b\x59\xcf\xe8\xbd\xd8\x58\x65\xb9\xc8\x10\x5a\xf7\x40\x67\x0f\x19\x0c\xfb\x08\xbe\xac\x6b\x0a\x5e\x53\xe6\xc8\xfe\xe0\xba\x7a\x1c\xb2\xf6\x10\x3b\xc8\x83\x00\x0a\xe7\xb8\x70\x12\x10\x97\x20\xa9\x33\xd8\x12\xc2\x28\x49\x3d\x11\xd8\x4c\xab\x7c\x40\x38\xc4\x0a\x3e\x40\xe9\xf3\xc0\x23\x9c\x9a\x5b\x43\xca\x23\x1d\x84\xa9\xd0\x65\x0a\xc6\x88\x74\x90\xd3\x95\x81\x31\xc8\x5c\x25\xb3\xe7\xc4\x92\x2f\x7f\xdc\xde\x4a\x97\xcb\x76\xa1\x51\xb2\x11\xf4\x8c\xaa\x0f\xe1\xa1\x8f\xe0\xf7\xc7\xab\x5e\x21\x55\xe9\xd4\x12\xb2\x74\x4c\x42\x96\x4e\xdf\x97\xbb\xaa\x5e\x72\xd8\x16\xff\x41\x95\x00\x3d\xcf\xcd\xf5\x67\xc6\x9f\x96\xfb\xce\xbc\x63\xbc\xdc\x47\x12\xe4\x6f\x5d\xd1\xbf\x30\xe2\x89\x40\x18\xb4\x2c\xb6\x1d\x79\x9e\x26\x6f\x0a\xb2\x03\x48\x83\xdf\x3d\x02\x39\x3f\x1b\x67\xa6\x04\x63\xe0\xf3\xe1\x37\x8f\x63\x31\xea\x18\xb6\x91\x3d\x49\xfd\x09\xf1\x52\x01\x33\x9b\x04\xaf\xbd\x1c\x51\x25\x90\x8e\xd8\xad\x54\x37\x7e\x1c\x24\x6c\xc4\x6e\xa5\x66\xf5\xb2\x20\x7a\x4e\x84\xbc\x02\xf3\x20\x7e\x4e\xb8\x44\x01\x83\x40\xf1\x3a\xb0\x29\x87\x60\x14\x0c\xcc\xe0\x80\xad\x3b\x98\xc9\x3b\x9c\x4c\xe8\x8e\x56\x20\xfa\xc7\x1d\x6f\x8a\x49\x10\xd1\x3b\x5b\xc1\x04\x74\x29\x9e\x07\x13\x1e\xc8\x1f\x8d\xbc\xec\x9f\x02\xd2\x7a\x1a\x64\x5b\x23\x9a\x72\x6a\xa5\x9c\x16\xd1\xc8\x8b\x65\x76\xb7\x41\xbc\x75\x77\x10\x6f\x05\xb7\x60\x56\xe0\x79\x70\xab\x32\x9c\xff\x73\xc6\xd3\x8e\x83\xf9\xd6\x8c\xa6\x1d\x97\xd2\x8e\x0b\xa3\x51\xb5\x5c\xc3\x8c\x44\xcc\xd0\xe9\x45\x48\x70\x40\xf0\x93\xd9\xba\x24\xb1\x4c\x52\xdf\x0d\x7c\xf6\x0f\xe1\x35\x7c\x81\xdf\xe1\xae\xaf\xb0\x20\x6b\x7d\x5f\xb9\x6b\xaa\x5a\xae\x0e\xb4\xda\x9f\x07\xcf\xe8\x14\x97\x58\x1d\xb4\x3b\x19\x64\xb6\x66\x84\x62\xf7\x34\xc6\x0f\xeb\x5d\x23\x09\xbd\x14\x77\x51\x55\x77\xe2\x65\x0e\xf2\xf2\x1d\x56\xfe\x67\x7d\x05\x58\x59\x3f\xd6\xdf\x3e\xe2\x7d\xbf\xd2\xbb\xe6\xdc\x75\x3f\x72\x3c\x45\x96\xe2\x64\x3a\xc3\x29\x63\x8a\xfc\x29\x24\xc3\x18\x53\x3d\xa2\xaa\xa6\x9d\x77\x17\x1c\xf6\x48\xee\x0c\xbe\x91\x86\x66\x27\xb0\xb1\x10\xf4\xce\xe1\x63\x7f\x2d\x8c\xfa\xf9\x5a\x77\x60\x5e\xb6\xff\xab\x7e\xbf\xac\xc4\x3c\x56\x2b\x38\x14\xea\x5b\x33\x08\x0e\x97\xcb\xd3\x92\x22\xb3\x5c\x7a\x3f\x09\xe1\x85\xbf\xf0\x35\x98\x2e\x97\x5e\xd8\x55\xdb\x1e\x9f\xa9\x6c\xcb\xf3\x65\xc2\x15\x56\x67\xd3\x95\x44\xc3\x01\x7e\xe5\x7e\x1e\xe7\xdc\x6a\x0c\xb6\x8f\xc9\x42\x47\xa5\x35\xdb\x45\x9d\xdb\xc8\x8c\x1b\xaa\x27\xa8\x80\x37\x55\x9d\xf9\x74\x85\xce\xac\xdc\x93\xfd\x7b\x43\x41\x3e\x96\x3a\xf1\xa5\xd6\x89\x8f\x0c\x9d\xf8\x93\x52\x5b\x7f\x2a\xe0\x1b\x2c\x0c\x75\xba\x06\x30\x91\xed\x82\x37\xae\x7b\xc3\x7e\x01\xeb\x67\xf8\x66\x08\xc6\xa8\x06\xed\xbb\xde\xe3\x6a\xcc\x1a\xe7\xb7\x02\xce\x6a\x7d\xab\x66\xc2\xb7\xea\x4c\xeb\x01\x34\xef\x11\x32\x0d\xf0\x63\x52\x8e\x58\x54\x8e\x2f\x75\xdc\xbe\x15\x67\x18\x79\xe3\x0f\xcd\x73\xaf\xcc\xf5\x9d\x7d\xfa\x5b\xb8\x6a\xd0\x8b\xf0\x9e\x3f\x70\x06\x61\x3c\xf0\x3a\xed\xf6\x0f\x8d\xad\xc6\xce\xf6\xec\x1e\x59\x4e\x1d\x35\x4f\xb5\x87\x8b\x19\x67\x78\x9e\xcc\xd8\x59\x54\x81\xbc\x5b\xd3\x2c\xff\x40\x24\xad\x9a\x42\x48\x63\x41\x33\xad\x51\x94\x66\x39\x03\xde\xf0\x73\xd7\xe5\x38\x3c\xa2\x8d\x05\x83\x47\xb7\xee\xa6\x4f\xb8\x19\xc2\xcc\xc0\xe0\x26\xab\xff\x1a\xb1\xbf\x87\x5b\x71\x68\x7d\x7b\x96\xe2\xdb\x28\x99\x67\x95\xef\xd7\x3f\xd0\x65\x50\xf9\xe8\x22\xdc\x69\xba\x32\x1d\x24\x24\xf6\xed\x66\xfb\x40\x82\x55\xb0\x2d\xf2\x0a\xdf\xe7\x15\x64\x51\x22\x94\xf8\x1c\xdf\x4b\xa1\x1f\x01\x95\x71\x98\x48\x96\xa7\xd1\xd4\x43\xad\x3c\x79\x9f\xdc\xe1\xf4\x28\xcc\xb0\x87\x90\x90\x88\x58\xec\x5c\x8a\x67\x38\x64\xc8\x88\xa4\xd7\xee\x4b\x06\x83\xac\xd7\xee\xfb\x2c\x77\xe5\x61\xc8\xef\x0b\x95\x9d\xe1\x6a\xaa\x3a\xdc\x8b\x66\x84\x14\x12\x08\xb5\xa4\x18\x05\xcd\x0e\x95\x19\xd8\xd3\x66\x33\x77\x5d\x82\x0e\xe2\x03\x56\xd9\x98\x79\x3c\xea\x56\x66\x37\x25\xfb\xe3\x41\x14\x34\xdb\x4c\xc7\xcf\x82\x66\xea\xba\x9e\x76\x7e\x58\x2e\x15\xbd\x58\x5c\x47\x2f\xa6\xce\xab\x11\x93\x85\xe2\x2a\x2f\x45\xc4\x79\x29\x5c\xf7\x8e\x78\x31\x84\xc8\x75\x9b\x19\x32\x5b\x35\x96\xdc\x02\x07\xbc\xec\x31\xe3\xeb\x62\x00\xfc\xc4\xe4\x0a\x0d\xea\xb8\x42\x4d\x96\x50\x93\x37\x14\x6e\x9e\x62\xad\xe0\xe7\x85\xa1\x42\x4e\xaf\x3b\xc8\x51\x4f\x4f\x72\x3c\xad\xa1\x53\x21\x26\x88\xbb\x69\x51\x30\x48\x84\x87\xfc\x34\x8d\xe6\x42\x2f\x6b\xd9\x84\x45\x52\xba\xfb\xfc\x9e\x86\xb3\x1a\x14\x77\xaa\xf5\x4b\x58\xf1\xb1\xe1\x12\x6c\x1d\xea\x38\x19\xa3\xbf\xc2\xc3\x53\x4c\xe6\x4e\xf5\x80\x47\x54\x9c\x2a\xc2\x06\x32\xb8\x55\xc9\x1a\x95\x58\x28\xc2\xf5\xd5\xd1\x0f\x64\xe1\x99\xf6\xaa\x41\xba\x0d\x07\xdf\xbb\xf2\x61\x8c\x71\x9a\xb3\xa0\x23\xdf\xef\xf5\x41\x4d\x16\xba\xeb\xc8\xc9\xfe\x0b\x7e\x38\x0d\xf3\xc1\x04\x0f\xe9\x5d\x3a\xc5\xaf\xa2\xa9\xc0\x15\x42\x07\xc7\xc4\x96\x1e\x5c\xf7\xae\x4c\x61\x21\x22\x94\x9e\x20\xcd\x2c\xc2\xe1\x97\xb9\x60\x1d\x7e\x9b\xa4\xdc\xdb\xf0\x3a\xac\xb7\xe9\x6a\x62\x19\x93\x50\x94\x49\x89\x96\xe6\xf5\x0f\x9d\xce\xbc\x4d\x27\xad\xd0\x07\xb5\x28\x3b\xa1\x7a\x2f\x93\x60\x0f\x4a\xb9\xf7\xa4\x3b\x73\xae\xdd\x99\xbb\x8e\xc1\x04\xec\x28\x8a\xb5\x0b\x41\xa1\x96\x42\x6d\x09\x03\x63\x37\x79\xae\x1d\xe3\x52\x7e\x02\x2b\xc5\x2b\xe5\x57\x5b\x18\x8e\xd6\xc7\xeb\xe4\xce\xbb\xc7\xa2\x3e\x0d\x2c\x95\x63\x8e\xa3\xb2\xd5\x39\x30\x50\x9f\x64\x24\xc9\x00\x4a\x4c\xbf\x15\x4e\x59\xc6\x61\x29\x11\xf6\xf4\x0a\xe6\xd9\x73\x21\x60\xec\x05\x32\x99\x7c\xb4\x5c\x32\xfe\xae\x4b\x9a\xc5\x65\x40\x74\x80\xd2\x51\x60\x94\x65\x1a\xce\xaa\xe5\xa0\x2a\x3d\x7b\x55\xf4\x9b\x0e\x87\xc9\x5c\xd7\x4b\xf5\xca\x11\x34\xdb\x08\x34\xe4\x67\x05\xa3\xba\xae\x9c\x5e\xaa\x61\xab\xdb\x15\xde\x13\x0c\xa9\xea\x1b\x5c\xac\x06\xe2\x22\xb9\x19\x4f\x13\x63\xdf\x99\xd2\x4f\x30\xb1\xe8\xc6\x10\x0b\x87\x2b\x50\xa2\xb9\x76\xa3\xba\x92\x91\xaf\xdd\xe0\x07\x48\x35\xb5\x51\x5e\x62\x46\x62\xaa\xf1\x61\x9a\x26\x77\x6c\xf6\xd3\xcd\x0d\x61\xb6\x65\x63\x92\xbf\xe1\xde\x78\x1e\x82\x7b\xe2\xe5\x90\xc2\x14\x66\xf0\x40\x38\xe3\x57\x43\xbd\xf9\x71\xb6\xc9\x7b\xd7\xe6\x7b\x3f\x25\x53\xbc\xfe\x25\xa6\x8f\x57\xbe\x77\x4c\x86\x1b\xbe\x66\x7e\xae\xc3\xf6\x6c\xc1\x9e\x26\x36\x15\x75\x54\xc3\x36\x15\x4b\x14\x80\x28\x10\x20\x9b\x21\x19\xe0\x16\x49\xee\x3c\x74\x90\xf0\x9d\x5e\x93\x8c\x79\xd1\x56\xd2\x92\x0b\xdb\x3f\xf7\xda\xed\xae\xc7\xd3\x30\x66\x48\x2d\x42\x04\xcd\x36\x3b\x5a\x29\xaf\x8b\x74\x98\xf9\x46\x3a\xd7\x0d\x9b\x41\x90\x48\x41\xc3\x75\x3d\x2b\x93\x0e\x42\xa0\xbf\x17\x44\x20\x0a\xc4\x28\x05\x43\x3e\x09\xe2\x20\x75\xdd\xa6\x95\xe7\x1d\xf1\x52\x48\x68\xf1\xab\x25\xa0\x22\xc4\x72\x29\xba\xa8\xd9\x61\x6d\x0d\x09\x42\xdd\x6a\xe3\xfa\xf5\x35\xe8\x14\xb7\xae\x7b\x4b\x17\x09\x50\xcc\x3d\x51\xb7\xed\x6f\x75\xd8\x01\xd7\x91\x21\x98\x5f\x92\xe0\x86\xf0\xa9\x4a\x82\x75\xa6\x6b\x7e\x10\x53\xc0\xa7\xf5\xc9\xb8\x85\x1b\xce\x37\x14\x20\x94\xd0\x60\xc6\x41\x2d\x97\x8f\xf8\xf1\x96\x51\xc2\x99\x50\x31\x28\x05\x28\x52\x39\x82\x2e\x05\x74\x3b\xe5\x96\x70\x0b\x54\x66\x51\xf8\xd2\x37\x84\xc7\x2e\x4d\xec\x73\x83\xa9\x3c\x11\xb8\xb5\x4f\x04\xac\x63\x8c\x45\x21\xce\x31\x84\x8a\x70\x24\x0a\x79\x5d\x6f\xb4\xb7\x8e\x31\x84\xd1\xfe\xba\x14\xeb\xc4\xbf\x72\x1c\x78\xf7\x66\xa8\xd3\xa2\xf0\xef\x91\x59\xbc\x1b\x2d\x90\xdc\x43\xcf\xb4\x83\x33\x28\x00\x2d\xd7\x1c\xe9\x6c\x2e\xcb\x72\xcd\x25\xf7\xd8\x30\xe4\x1a\x43\x9a\xa9\x35\xe8\xd7\xb5\xbc\x03\x8e\xd5\xce\x65\xb2\x11\xc3\x40\x5f\x63\x80\xb7\x5b\x6e\x53\x4b\xbb\x25\x0e\x9d\x73\xf7\x95\x0b\x2a\x6e\x36\x07\xae\x3b\x35\x43\x9f\xb8\x80\x74\x55\xbe\xf1\xa1\xb4\x4f\xd2\xbd\x29\xfa\xfe\x3d\x92\x6d\x08\xcd\x20\x38\x5a\xb9\x37\x7e\xa0\xaf\x7e\x30\xf7\xc6\xcf\xc1\x63\xdf\x97\x30\x9d\xf4\xf5\x6e\x65\xf3\xe2\x84\xef\x46\x3c\xe9\xd5\x0a\x61\x21\x67\xf1\xa0\x9c\x89\x1e\x33\x5f\x1d\x76\xce\xef\xaf\xdb\xf3\xc6\x44\xef\x79\xd5\x13\x1a\xbf\x6a\xb3\xba\xd2\x41\x43\x62\xb8\xf8\x0f\x2a\x7a\x66\x06\xa5\x0e\x34\x8e\xcb\xb5\x19\xc3\x16\x08\xcf\x74\xa4\xba\xfa\xd9\x5a\x21\x4b\x7a\x18\xce\x11\x50\x09\x9f\x9b\x3b\x8e\x5d\xf7\x98\x7b\xaa\x14\x70\x83\xc0\x3c\xcd\xf2\xa5\xcc\x77\x6e\xc8\x7c\x47\xc4\xff\x44\x2a\xf6\xcd\xd5\x29\xf5\x08\x36\x03\x91\xc6\xc2\x3e\x82\xed\xbb\x6a\xe9\xe2\x96\x8f\x98\xdb\x4b\x0a\x2a\xc1\x31\xe3\x93\x08\x2d\x82\x9a\x10\xa6\xbb\x02\x3e\x55\xcd\x34\x97\x46\xdf\xac\xe0\xa5\xb8\x0a\xaf\x0d\x52\x0a\xaf\x66\x5b\xe6\x58\x05\x40\x95\x4c\xcd\x3f\x51\x80\xd0\x6c\xfc\x33\x50\x6b\x81\x1f\xba\x2e\xe7\x67\xfd\xb0\x5c\x0e\x10\x58\x6a\x8e\x7f\x01\x62\x26\xfa\x47\x05\x8c\xa0\x3e\x8e\x20\x8e\xb2\x1c\x46\xb6\x81\xe8\xb3\x69\x1f\xba\x30\xec\x43\xc2\x2e\xb4\xc2\x52\xf3\x6a\x9f\x59\x6a\x1e\x09\x61\x2a\x80\x7e\xd2\x5f\xd4\x1b\x74\xd8\xea\x57\x20\xef\x5c\xb8\xc7\x9e\x91\x80\x78\xbb\xaf\x76\xb7\x11\x5c\x6d\xb0\x71\x3d\x82\x86\xa6\x63\xea\x33\xbd\xf6\xc6\x5d\x27\x8e\x1c\x9f\x23\xa2\x89\x95\xe3\xdd\x3c\xcf\x71\x9a\x99\x3b\xd7\xdc\x75\x79\xe4\x89\xf4\x07\x95\x3b\x0a\xd5\x83\xa9\xec\x59\x0a\xa6\xa7\xeb\x4e\x44\xd7\x60\x9f\xeb\xbf\x72\xd1\xe1\xde\x8d\x62\xef\x87\xdb\xa7\x46\xd9\xdb\x05\x74\xc0\x29\x15\xc7\x01\x87\x16\xc6\x01\xb5\xa1\x38\xa0\x29\x32\x75\xc0\x09\x31\x17\x49\x83\x94\x75\xda\x9d\xfa\x5b\x9d\xea\xc8\xfe\xc9\x08\x48\xb9\x66\x5e\xcc\x0c\x02\x8d\xca\xdc\x33\x2d\xca\x24\xa0\xca\xea\x67\x20\x4b\xe0\xab\xd8\x0f\x51\x6c\x7f\x00\x95\xe9\x38\xc4\x24\xc3\x7e\xd8\x62\x7f\x0b\x18\x22\x58\x07\xce\x36\x71\xdd\x50\x37\x29\xdd\x5a\xc2\xd6\x98\x67\xae\xfc\x8c\x6f\xcd\x61\xfc\x81\xd4\x47\xfa\x9b\x7e\xc6\x26\x85\x8b\xe9\x25\x7e\x9d\x0c\x1f\x3a\xb4\xfa\x67\x84\x3d\xd6\x36\xcd\xdd\x97\x32\x3c\xe4\x2a\x99\xf9\xfb\xf2\x42\xc4\x66\xed\xc3\x75\x72\x7f\x19\x7d\x63\xa3\x9f\xc7\x8e\x6c\x5d\x27\xf7\x0e\x08\x17\x73\xdb\x80\xaa\xed\xa7\x77\x93\x28\xc7\x97\xb3\x70\x80\x7d\x87\x24\x77\x69\x38\x73\x68\x89\xae\x53\x1c\xde\xcc\x92\x88\xe4\x59\x6b\x3e\xf3\x9c\x6c\xea\x20\x30\x0a\x23\x62\xfb\x10\x02\xd1\x12\xcc\x19\x5e\xf6\xc1\xa2\x00\xde\xc4\xeb\x6a\xb9\x5d\x97\x9f\xed\x0e\x4d\x67\x28\x93\x2d\x0a\xe4\x5d\x89\x59\xfa\x99\xc0\x29\x9d\xa8\x9d\xfd\x17\x3b\x08\x4e\x58\xbc\xd8\xde\xab\x5d\x04\x87\xf4\xe7\x8b\xed\x57\x2f\x11\xbc\xa7\x3f\x5f\xee\x75\x76\x10\x7c\x23\x81\xf7\x99\xd4\x33\x8f\x7c\x26\xc1\xd9\xf5\x17\x3c\xc8\x05\xdf\x35\x27\x16\x39\x1b\x2d\x97\x8b\xcf\x9f\x19\xd1\xc8\xe7\xcf\x7e\xaf\x5f\x44\x24\xcb\xa9\xb2\x91\x8c\x1a\x87\x69\x1a\x3e\x98\xb1\xce\x34\x3b\xdc\x52\xc9\x83\xbc\x58\x2e\x57\x1c\x42\x37\x22\xd2\xc8\x91\xf8\xa2\xe2\x31\x29\xd1\x99\x09\x6e\x18\x20\x4c\xc6\xe8\x91\x7e\x90\xf7\x48\x1f\x15\xf0\x99\x08\xb0\x78\x3b\x77\xaa\x77\x29\x9f\x23\x45\xc1\x91\xbb\xae\x3c\x1f\x43\xf9\x24\x4d\xee\x1a\x04\xdf\x35\xae\x1e\x66\xf8\x38\x4d\x93\xd4\x73\xd8\x0c\x6e\xe0\xfb\x1c\x93\x61\xd6\x60\xb0\xd2\x0d\xe7\xf9\x25\xc3\x8b\xf3\x72\xf4\xdc\x69\x44\x59\x83\x24\x79\x23\x6c\xb0\x31\x9d\xce\x07\x79\x92\x36\x92\x94\xa1\x85\x3b\x86\xf9\x5b\xb3\x8d\xe8\x74\x01\x2e\x44\x71\x01\xeb\x9a\x0a\xc0\xf6\x20\xef\x8a\x36\x10\xee\x92\x39\xf2\x3d\x83\xd8\x25\x30\x1a\x07\x68\xb1\x09\x2a\xe4\xcc\x7a\x43\x56\x31\xec\x28\x8b\x8f\xc9\xae\xa3\xb8\x75\x14\x57\xcc\x84\x59\xa8\xae\x92\xf1\x38\xc6\x74\x74\x59\x4c\x70\x1a\x96\xbf\x2e\x3c\x80\x2e\xb2\x67\x33\x4c\xf0\xd0\x6f\xe2\x96\xbe\x2a\x04\xf9\x00\xcf\x9a\x49\x3a\x6b\x72\xb6\xb2\xe9\x14\xc6\x9b\x97\x79\x32\xbb\x0a\xb3\x9b\x2a\x86\x7b\xaa\xac\x1c\xd9\xcd\xc9\x1b\xc8\x83\x01\xf6\x30\xb7\x90\x0f\x42\xee\x55\x4e\xc6\x9c\x2a\x7b\x14\xa5\x53\xcf\x79\x93\x34\x1e\x92\x79\x23\xc5\x61\x1c\x3f\x34\xee\x42\x92\x37\xf2\xa4\x91\xe5\xc9\xac\x11\x92\x61\x63\x88\x63\x9c\xe3\x06\xcd\xae\xf1\x75\x8e\xe7\x78\xd8\x08\xf3\x86\xf3\x3c\x7f\xee\x74\x1d\xc4\xec\x25\x92\x61\xe1\x0d\x4b\xea\x61\x54\xad\xa0\x67\x56\xfb\x34\xb9\xc5\xb4\xf0\x57\xc9\xdb\x34\xb1\xa9\x68\x74\x66\x2c\x11\x4f\xe0\xd9\x75\xaa\xcd\xbe\x2e\xf7\xd7\x25\x4e\x87\x72\xe6\xf4\xf9\xa6\x79\xa7\x78\xa4\xa2\xe4\xb9\xa7\x8e\x22\x3c\xb2\x3b\x09\x52\x69\x1f\xfa\x46\x24\xc7\x91\x9e\xbf\x55\xe4\xfd\xb5\x11\x2f\xb5\x04\xbe\x09\x81\x05\x1e\x8e\x99\x83\xf9\x90\x9b\x94\xd8\x9c\xa2\x52\xba\xa4\xe4\x62\x37\xca\xe3\xb7\xca\x5b\xf6\x9e\xb4\x3e\xb1\x8f\xd4\x30\x6e\x5d\x10\x58\x48\xb7\x1a\xf5\x01\x65\x6a\x61\x62\xa8\xc1\x17\xa0\x1b\x41\x49\xf0\x46\x19\x54\x63\x16\x75\x92\x69\x6d\x2d\x3f\x10\x58\xd4\xd4\x46\x0e\x7c\x10\x61\xc3\x26\xd5\xce\x34\xb9\xa5\x7b\x79\xf5\x1b\xf1\x8a\x6f\x1c\xd2\xea\xcb\xb8\x39\x15\x10\xe6\x14\x35\xad\xf1\x07\x86\x85\x88\x7a\xbb\x52\x5b\x93\x38\xf3\xad\x66\x20\x48\x30\xac\x62\x75\x1d\x3e\x3f\x1c\xdf\xa1\x95\x70\x10\xaa\x49\xe4\xba\x4f\xa5\x73\x5e\xd1\x4e\xa5\x39\xb6\x79\x9b\x9c\xac\x19\x12\x7f\x60\xfe\x8e\x43\x73\xa7\xab\xc4\x88\xe6\xed\xd4\xa4\x7c\xb4\x54\xaf\x19\x2f\xc8\xa6\x85\x3a\x7d\x4a\xa1\xae\x43\x46\x24\xc7\xe8\xdb\x2a\xac\x05\x74\x91\x7c\x4b\x82\xd5\x44\x99\xf6\x71\xe9\xff\x3b\x5b\x3e\xe6\x78\x7e\x07\xab\x22\x65\x6a\x36\x7e\xa2\x36\x7e\xf2\x1d\x1b\x3f\x79\xca\xc6\x9f\xd6\x6d\xfc\x79\xc1\x0b\x0d\x79\x75\xdf\x27\xa5\x7d\x9f\x20\x9f\x2f\xd5\x32\x59\x69\xdf\x4f\x51\x51\x78\x08\x5e\x93\x9a\xb5\xf5\xb5\x12\xdd\xc2\x2c\x8b\xc6\xc4\xec\x01\xdd\xfe\x39\x90\xa0\x03\x69\xc5\xb1\xee\x80\xfc\x23\x3d\x20\xcf\x9f\x23\x99\x30\x61\x1d\x65\xf8\xd8\x91\xfe\xa6\xbd\x96\xf0\x5e\x4b\x68\xaf\x25\x5a\xe7\xc1\x05\xbc\x66\x74\x28\xf1\x03\x97\x45\x54\xde\xa8\x80\x2f\xb6\x40\x0a\x66\x84\x01\xc1\x77\x1e\x59\x2e\x3d\x12\x9c\xa7\xc9\x34\xca\x30\x32\xb5\x08\x7e\x58\x2d\xbb\x20\xa2\x95\xcd\xd3\x87\x45\xe6\x71\x62\x3e\x0f\x23\x54\x0c\xc2\x7c\x30\xa1\x4f\x42\x0f\xa3\x42\x9f\x79\xc7\x66\x6a\x36\x38\xd6\x26\xcf\xd4\xa1\xc5\x01\x6e\x0d\x13\x82\xbb\x89\x87\x5b\x6c\xc4\x20\xdf\xcb\x03\xf1\x1b\xf2\x86\x31\x59\x48\x37\xf7\x99\xcc\x56\x02\x51\xe4\xe8\x8a\xa8\x95\x4f\x30\xf1\x22\x88\x51\x91\x79\x5e\xca\x89\xe0\xe2\x07\xda\x08\xcb\x65\xaf\x8f\x10\xaf\x05\x8f\x6a\x80\xdf\x57\xc0\x34\x43\x02\x21\x44\xc1\x82\x07\xd1\xb6\x21\xa3\x2a\xa0\xed\xef\xd4\x71\x93\x5e\xbb\x2f\xa6\x00\x8b\x0c\x13\xcd\x4b\x7f\x17\x90\xa7\xfc\x74\x94\xae\xf5\xbd\xbe\x9a\x61\x61\xb0\xa0\xdf\xf7\x63\xaf\x4d\x57\xf2\x34\xb9\xf3\x63\xaf\x43\x95\x3c\xfa\xd8\x8f\xbd\x6d\x54\xcb\xbb\x72\xf9\x30\xbd\x4e\x62\xd7\xf5\xc2\x1e\xff\xd9\x8a\x72\x9c\x86\x79\x92\xf6\xeb\xe4\x82\x49\x94\x15\x08\xc2\x03\xa3\x67\xc2\x6a\x70\x4e\x5c\xbd\x15\xf2\x83\xb2\xfa\x99\xfd\x0e\x13\xfe\x4d\x3a\x83\xc3\x38\xc5\xe1\xf0\xa1\x81\xef\xf1\x60\x9e\x47\x64\xdc\xa2\x53\x37\x49\xbd\x83\xe8\x00\xd1\x31\xc0\x0e\xdc\x3a\x90\xba\xae\x97\x04\xdb\x6e\xd8\x6b\xf7\xbb\x54\x24\x62\x15\x15\x57\xec\x33\xcb\xa5\xe7\x25\x81\x7c\x84\x5c\x37\xe1\x23\x3f\x45\xd0\x46\x3e\x1f\x76\xc8\x75\x9b\x5e\x12\xc8\x27\x10\xf6\x3a\xb4\x2f\xe9\xa0\x91\x6e\x0a\xc9\x41\x76\x17\xd1\x81\x96\x06\x6d\x48\x68\x53\x05\x3d\xfe\x59\x48\xf8\x40\xea\x23\xa0\x97\x68\x31\x08\x33\xdc\x68\xfb\xec\x4f\xc7\x4f\x82\xf0\x80\x69\xa3\x07\xec\xc6\xae\x2f\x59\xf2\x39\x54\xc3\xf3\xe7\x92\x15\x87\x7e\x14\xe8\x27\xa9\xc8\xc6\x13\xef\xf9\x3a\x55\x1a\xb0\x04\x61\xd0\x6b\xf7\xa9\xa4\x9c\x47\x64\x8e\x79\xb2\x17\x7e\x18\x44\x2d\xba\x65\xcf\x92\x99\x87\x20\x6a\xd1\xf1\xc1\x2f\x74\x52\x81\x7e\xe1\x47\x23\xaf\x49\x9b\xc4\x4b\x02\x9e\x10\x19\xe7\x4e\x49\x2f\x11\x57\x5b\x9d\x3e\x5a\x2e\xf7\x9b\x41\x10\xb2\x03\xa3\x6d\xf1\x0b\xa1\x45\x14\xb4\x55\xb6\x45\x34\xf2\x76\x02\x99\xc8\x6b\x26\xcb\x25\x2d\xe7\x3f\x13\x76\x4d\x7f\xfe\x23\xe9\xed\xb0\xb7\x78\x55\x58\x35\x78\x8b\xd0\x77\xf7\xd5\xbb\xe2\xf9\x3f\xe8\x08\xd7\xa9\x19\x99\x9f\x6a\x43\xfa\x46\x62\x26\xdd\xb6\x92\x6e\xf7\x41\xb4\x83\x38\xb7\xe2\x2f\xd1\x07\xf4\xa5\x47\x5a\xa8\x08\xa9\x38\x4d\x47\x00\x86\xc8\x5c\x57\x82\xde\x3e\xe0\x3e\xa4\x41\xbb\x18\x45\x84\xea\x24\x0b\x12\x24\x41\x9b\x96\x66\x8f\x8d\x01\x31\xa2\x43\x3d\x51\x55\xa7\xb6\xfb\x5d\x7a\x5b\x06\x95\xf1\x0e\x6e\x17\x85\xd7\x0b\x21\xee\xb3\xd0\xce\x67\x2b\xb5\x42\x83\x3b\xc7\xe0\x5c\x2d\x69\x85\x44\x4a\xfd\x51\xf6\x3e\x09\x59\x0c\x7f\xb3\x03\x54\x79\x38\x1a\x8d\x05\xd9\x12\x91\x1a\xc0\xdb\x1a\x0d\x40\x88\xb1\xcc\xfa\x71\xc5\x74\x8e\xba\x40\xd7\x2f\x84\x7f\x5e\x54\x44\xfc\x29\x7b\xc5\x2a\x6f\xa9\xdf\x45\x72\xc3\xf4\x88\x16\x62\x0e\x11\xde\x63\x6a\xaa\x98\x8c\x70\x5a\xd3\x34\xaa\xc3\x20\xdd\x76\x4d\xe1\x74\x8c\x59\x51\x8f\x46\x63\x0f\xa3\xfe\x81\x98\x6c\x32\x23\x66\x43\x24\xb9\x57\xa6\xab\xab\x6f\x22\xe6\xf0\xbe\xdd\x2f\x04\x9b\x9f\xd5\x36\x6b\xc9\x59\x37\x6e\x99\x95\x6d\x82\x55\x9b\xe0\xfa\x36\x91\x36\x07\x83\xcf\x34\xcc\x6e\x7e\xa5\x5a\xaf\x54\x7c\xba\xbd\x1d\xd8\xee\xfb\xb2\x7d\xaa\xbd\xe9\xad\x7b\x5b\x37\x1e\x96\x6d\x26\x8a\x12\x6c\xf3\x27\xdb\xa2\x2c\xab\x9a\x88\x2b\x90\xd2\xb6\x1a\xd8\x87\x3f\xdc\xa8\xc1\x6a\x9d\x70\xbd\x7f\xd5\x59\xcd\x4f\x18\x0c\x6b\xe9\x0d\x7e\xf0\x1d\xe7\x39\xae\x32\x3a\xab\xd6\x4c\xeb\xaa\x8a\x91\x01\x70\x61\x28\x83\xaa\xe3\x8b\x75\x7a\x94\x9f\x28\xab\xc4\x1b\xc6\xd7\xca\x2d\x13\xa0\xf4\x28\x23\xc1\x55\x34\x55\x09\x6a\xbc\x50\xf1\x0a\xe5\xe8\x0d\x81\xd7\xc4\x5b\x70\xdd\xde\xc7\x20\xb4\x2c\x9f\x98\x0a\x9a\x50\x14\xd6\x6a\xe9\x06\x27\xa7\xc5\x47\x28\xac\xc5\x07\x4f\xd7\xe2\x73\x62\x1e\x7c\x10\x89\xb3\x26\xcd\xcf\xe2\x48\x43\xde\x67\xa7\x47\x05\xd7\xba\x9b\x6d\x75\x7e\x62\xc0\x04\x16\x8f\x53\x89\x90\x56\x9e\x24\xf1\x75\x98\xd6\xb4\xe0\x2a\xf5\x32\x11\xf7\x9d\x23\x3e\x82\x1d\xed\x4c\xbf\x66\x9c\x0b\x3e\x5b\x7b\xb0\xae\x9d\x19\xd0\xac\xb1\xed\xab\x8f\xb3\xa4\x8e\xa5\x30\xeb\x1c\x98\x55\xaa\x14\xac\x69\x32\x46\x97\x4b\x01\xcd\x36\x93\x2f\xab\xdf\x7b\x87\xed\xe6\x1a\xf0\x23\x4c\x98\x85\x69\xc8\x34\x7e\xe6\xd4\x1d\xe3\x16\xe7\xca\x88\x46\x5c\x5c\x17\xa3\x5e\xac\x70\x72\x49\xda\xae\xd5\x3f\xb9\x69\xf2\xe3\x7a\x70\x11\xd1\x4d\x3e\x6e\x4d\xa3\xfb\x88\x64\xb2\xdf\x80\x0f\x06\x09\x05\xd3\x79\xd9\xb6\x70\x45\x0a\x30\x06\x8b\x91\xa8\x00\x51\x11\x0e\x25\xf8\x8e\x8a\xaa\x1d\x05\x1f\x85\x5b\xd9\x2c\x1c\xd0\x99\xb5\x83\xc0\x80\x26\xa2\xb9\x9b\x06\xff\x59\x8a\x19\x72\x0c\xf2\x9e\x09\xeb\xfa\x6f\x24\x20\xde\xde\x76\xfb\x95\xac\xd6\x4f\xac\x5a\xbf\xb1\xc3\x88\xca\x68\x9c\x85\xf9\xc4\x81\xc5\xd0\x77\x4e\x3b\xdb\x8d\xed\xa3\xfd\xd6\xee\x8b\xc6\x76\x63\xbb\x21\x7e\x74\xb6\xb3\x5d\xfa\xab\xd3\x56\xff\xb6\xc4\x8d\xad\x4e\xfb\xb2\xf3\xa2\xb5\xb7\xc3\x92\x35\xb6\xbf\x4d\xf7\x1a\x9d\x9d\xd6\xde\xab\xf7\x9d\xbd\xd6\xde\xab\x46\xe7\x05\xbd\xdd\xd9\x69\xed\x76\x1a\x2f\xe9\x7f\x9d\x17\x8d\x17\x0d\xf1\xac\xcd\xfe\xdf\x6e\xbc\xe0\x8f\xd8\x7f\x3c\x3d\x7f\xc2\x52\xbd\xa0\xaf\xf0\x57\x59\x2e\xf4\xb1\xc8\xe1\x9b\x53\x20\x70\x8e\x18\xd9\xa9\xa9\xd2\x7e\x35\x23\x79\x5f\x87\x83\x1b\xda\x8c\x9a\xd7\x7f\xb9\x94\xf6\x1e\x79\x87\x53\x73\x6c\xe8\xe5\x72\x1b\xe6\x61\xfa\xd8\xa9\x21\x5d\xab\x43\xce\xa1\x24\xb1\xe9\xe6\xfa\xac\x2f\x33\xb0\xe9\x38\xf8\xb6\x3e\x66\x1c\x72\xc0\x04\x9c\xe3\x93\x41\x42\x2c\x97\xd9\x5a\x27\xd9\x88\xa6\x9a\x06\x42\x96\x10\x3e\xb1\x6c\xaf\x60\x1e\xb1\xd2\xf6\xcb\x1c\x5b\xb4\xb3\xec\xb5\xbc\xfa\x38\x63\x68\xbd\x0c\xd7\xce\x70\x52\xb9\xd3\xb8\x76\x77\x2c\x24\x57\x7a\xa0\xdc\xe8\x34\xc7\x46\x2d\x8e\x39\x63\x85\xe1\x7c\xc2\x9a\x69\x75\xfc\xa8\x6c\x20\x03\xff\xce\x3a\xb3\x54\x2d\x60\x03\xe3\x45\xfc\x0e\xab\xab\x70\x4d\x89\x06\x37\xec\x97\xe8\x53\xdb\xcf\x56\xd4\x51\xa2\xe7\x59\x9e\x26\x47\x65\x37\x12\x03\xf1\xe4\x08\xd2\x32\xd0\x09\x5d\x5b\x78\x30\x49\x38\xe6\xf8\x14\x08\xc6\xae\x3b\x66\x7b\xed\x45\xd0\xf4\x9a\x9d\x20\x08\xe2\xe5\xb2\x79\x8b\x96\xcb\x18\xce\x02\x8d\x96\x77\x0f\x57\xc1\x60\xb9\xf4\x2e\xba\x5f\xb0\xcf\x56\x7f\x04\x1f\x82\xab\x20\x08\xbe\xe0\xee\x42\x1f\x80\xb2\x47\x85\xbf\x28\xe0\xb3\xa2\xa8\x1f\xf3\xb1\x77\x1a\xa8\x23\x4d\x13\xc1\x6f\xee\xba\xfa\x9a\xe1\x23\x87\x3d\xa3\xf5\x8e\xea\xa1\xfd\xe6\x08\xf5\x7d\x2b\xe1\x99\x40\xec\x5e\xf3\x02\x82\x33\xd7\x0d\x8d\xc1\xc9\x10\xb3\xd0\xc1\xe7\x60\xe8\xba\x15\xef\x9a\x21\x2a\x3b\xb9\x0c\x6b\xfd\x09\x86\xe6\x7e\xcd\x26\x90\xf9\x09\x38\x45\x4a\xf4\x39\x2f\xaa\x98\xb2\x3f\x91\x15\x8c\x5c\x2b\xb3\x60\x73\xfd\x84\xb7\x6e\x52\x53\x6e\x66\x08\x3a\x09\x2a\x08\x11\xf5\x9f\x11\xab\x41\x52\xa9\x04\x6b\x2a\xfe\x94\x35\x13\x94\x3a\x2d\x94\x53\x64\x5d\x83\x4b\xe7\xa2\x43\x5e\x5c\xb1\x6f\x4e\x6a\x4a\x3d\xa1\xa5\x3e\x2c\x97\x7a\xb2\xa2\xd4\x6c\xcd\x98\xd4\x97\x39\x92\x1d\x5b\x53\xe2\x68\xfd\x88\x42\x75\xe6\xf9\xab\x92\xbb\xed\xc5\x72\x39\xee\x3a\x5c\xc2\x75\xa4\x3a\xb8\xee\xdc\xbe\x54\x8c\x5e\xb8\x12\xb0\x92\x96\x01\x2e\x58\x49\xd5\xfa\xb2\xa6\xb8\x74\xf6\xca\x39\xf0\x48\xd2\xbe\x55\x8a\x1b\x5a\x0a\xc5\x26\xa0\xa5\x66\x7d\x4f\x40\xfb\x19\x02\xb3\x7e\xa6\x70\xf3\x8a\xde\xbc\xdf\x87\x19\x9b\x53\x72\x85\x67\x5d\xa0\xd0\xe8\x58\x65\x8c\xcd\x64\xac\xe6\x5f\x68\xf0\xcb\x69\xa0\xc4\x66\x73\xb6\x5c\x8a\x26\x55\x0e\x16\xac\xc1\xdb\x1a\xcd\x85\xcf\x84\xdb\x15\xee\xcd\x4a\xec\xbb\x0a\xd3\x31\xce\xd9\x0e\x99\xb3\x9f\xae\xcb\xf6\x55\xee\x13\x57\xf2\x3f\x7a\x70\xdd\x07\xb6\x0e\x8a\xf5\x76\xe3\x2c\xbd\xb1\xc8\xb6\x4b\xd7\x51\xdf\x39\xce\x06\xe1\x0c\x1b\xde\x4e\x47\x5a\x70\x55\x3f\x5b\xd7\xf1\x3c\xf5\x10\x82\x6b\xd7\xbd\x66\x9f\x15\x38\x2a\x1f\xe0\x12\xc1\xc9\x72\x79\xb8\x01\x46\xa8\x31\xd0\xf8\xce\xc9\x9a\x9e\xfd\xe4\xeb\x5a\x01\x53\x1b\x1b\xfa\xd7\x15\xa2\x21\xf7\x08\x77\x62\x45\x6c\xa6\xe9\x16\x1e\x66\xb8\xab\x2f\xc7\x29\x7e\xe8\xed\xb4\xdb\x7d\xbf\x74\xef\x45\xbb\xdd\x07\x96\x7b\x05\x0c\xd1\x62\x6c\x68\x6d\xef\x4b\xbd\x51\x04\xde\x8d\x12\x92\xbf\x0d\xa7\x51\xfc\x60\xa3\x14\xea\xfb\x8f\xc1\x18\xee\xa0\x7a\xd0\xbb\x27\x71\x0b\x8a\xd8\xf0\x9d\xed\x0a\xd6\x9e\x70\x37\x4c\xc3\x2c\xbf\xc2\xf7\xb9\x97\xa3\x0a\xd5\x60\x6e\x83\xa4\x76\xf6\xeb\xbc\x59\x1e\x05\x41\xed\xd5\xa0\xa0\x9a\x0c\x16\x7d\x04\x83\x79\x9a\x25\xa9\xaf\xa6\xb2\x8e\x10\x04\xda\xcc\x6f\xf0\x20\x11\xae\x7a\x82\x8c\x49\x92\x57\xf0\x2b\x29\x96\xb7\x41\xba\x4c\x0b\xa0\xd8\x69\x34\x1c\xc6\x2c\x79\xad\xeb\x8e\x8d\x65\x2a\x11\x85\x5a\x7b\xc0\x1c\x73\x70\xca\x42\x6c\x33\x89\xc3\x07\x8e\xdb\x78\x26\xa4\x27\x0b\x90\x74\x0f\x2c\x94\xd1\x7d\xe1\x12\xb4\xbd\x2b\x5b\x7f\x7b\x57\xb4\xfe\xa6\x43\xf1\x45\xcd\x50\xa4\xc3\xf3\xb1\x21\xc3\xcc\xe7\xaa\x94\x47\x06\x96\xa9\xb3\x1a\xcc\x74\x60\x8c\x82\xca\x10\xa8\x26\x1f\x86\xe9\x4d\xe5\x2b\x6a\xe9\x74\xd6\x61\x8e\x6e\xf8\x25\xfd\x42\xf9\x5b\x6c\xfe\xdb\x8d\xbf\x6b\x37\xfe\x2e\x48\x15\x4e\x36\x7e\xe7\xe5\x63\xad\xd6\x46\x85\x05\x34\xaa\x7a\xad\x0c\x07\xfb\x78\xe3\x30\x5c\xd4\x4d\x1a\xba\x0a\xd5\xba\x49\x7b\xd4\x66\x5f\xdf\xbe\x36\x8c\xaa\xda\xa9\xfc\xc5\x3c\xc3\x29\xb7\x48\xc9\xe9\xb3\x11\x79\xa8\x9a\xa3\x62\x6e\x38\x0a\x3c\x16\x1a\xae\xcf\xc2\xd6\x56\xa2\xc8\x7e\xde\x45\x5e\x0e\xad\xf6\x4b\x36\x3c\x7d\x1e\x82\x43\x53\x6b\x3a\x1d\xc9\xc9\xd3\xeb\xf4\x0b\xa3\xb8\x47\x56\xfb\x3f\xed\x8b\x2b\x7a\x87\x15\xa3\xfc\x09\xa3\x1f\xbe\xf7\x23\xa5\x5e\x12\x9f\x51\x32\x01\xcb\x78\xe3\x66\x32\x5e\xac\x34\xc1\xf7\xd7\x7c\xbb\x9a\xb1\x5d\xf1\xbf\x52\x5f\x96\xb9\x41\x2f\xb4\x16\x19\x7a\x0d\xf9\xd0\xca\x35\xb2\x42\x7c\xbb\xbd\x83\x1c\x41\x87\xbb\xbd\xb7\x07\x0d\xfd\x1f\x7f\x86\xc0\x79\xa6\xba\x59\xf5\xaa\x79\x8b\xd5\x17\x1a\xcf\x54\x9b\x3c\xd6\x04\x6b\x44\x80\xf5\x68\xc8\xab\x77\x8f\xdd\x47\x16\xb8\x6d\xfe\x9c\xe9\xd7\x75\x2f\x2a\xb5\xa0\xf6\x35\x43\x5d\xb7\xc1\xb0\xf7\xca\xcf\xed\x3c\x78\xa2\x1d\xa3\x4b\x37\x03\xc5\x5e\xd3\xb1\xf5\x6f\xfc\xdb\x3b\xe9\x09\xb8\xdb\x46\x6d\x37\xc7\xd0\xde\xa8\xc6\xf6\x3b\xff\xf6\x3a\x3f\x09\xa8\xbb\x28\x80\x0f\x3e\xba\x51\x18\xc3\x50\x5f\xda\x4b\x90\x75\xd7\x68\xa7\x02\xe8\x50\x54\xae\x5d\x7f\x55\xd4\x59\x23\x60\xf1\x2f\x89\x42\xd6\xec\xf7\x6b\xc4\x03\xfe\xea\x51\x0d\xca\xbb\x01\x02\xaf\x92\x54\x46\x81\x91\x48\x20\x8c\x57\x3d\xbe\xe9\xaa\x70\xa6\xee\xe2\x38\x8e\x66\x59\x94\x29\x29\x95\x1b\x8a\xb7\xc1\x8c\x78\xa6\xd7\xb5\x8e\xe2\x5a\xeb\x51\xf8\xe7\xec\xfd\x97\xf6\xeb\x2f\xc5\xb2\xce\x26\xb2\xbf\xd8\x70\x43\x67\xf7\x88\x12\x52\xb7\xa5\xdc\xba\x5d\xdd\xeb\x79\x23\xfa\x4e\xbb\xb1\x37\xbb\x6f\xb4\x1b\x5b\xfb\xb3\x7b\xc7\x84\x8f\x1f\x94\xc6\x22\x81\xd6\xae\xda\x6d\xf4\xfa\xa2\x84\xab\x8e\x94\x92\x19\x92\x88\xee\xa1\x5d\xb3\xf3\x68\x77\x95\x2c\x66\xa5\x4e\x5b\x37\xe1\x2d\x69\xb3\xf5\x02\x59\x02\x8b\x92\x41\x36\x12\xd6\x2a\xc5\xa8\x0c\x8c\xf5\xb3\xf0\xfb\x8a\xb2\x42\xb0\x33\x0b\x63\x19\x07\x9f\xd0\x36\x7c\xcb\x7e\x6a\x9b\xd0\xb7\x56\x7f\xfe\x89\x6d\xf2\xb4\x22\xd8\xef\x15\x25\x58\xf7\xa3\x49\xc4\xe8\xe9\x7f\x11\xa7\x2c\xef\x48\x40\xbc\x9d\x97\x2f\x5e\x22\xf8\x93\x05\x30\x74\x5e\xbd\x42\xf0\x07\x0b\x6b\x78\xd9\x41\xf0\x33\x3f\x85\xd9\x7f\x81\x00\xa7\x4f\xc7\x56\x5f\x17\x94\x14\xc7\xe1\x2c\xc3\x43\xc1\x74\x9e\x99\xf7\xa8\x0a\x52\x3a\x6c\x68\xcf\xee\xeb\x0e\x1a\x4c\x7c\x50\xc6\x11\x3a\x30\x8f\x1b\x2a\x98\xee\xb5\xa7\x0f\x44\x50\x06\x72\xf0\xce\x5b\x0b\xbc\x73\x6c\x07\xe1\x3e\x68\xf0\xce\x6b\x13\xbc\xf3\xce\x02\xef\xbc\x57\x98\xee\xc7\x06\xa6\xbb\x75\xec\xc0\x99\x1a\xb3\x3c\xa4\x5d\x35\x64\x67\x0f\xf5\x00\x9c\x56\xb8\xec\x49\x5e\x0d\x91\xdd\x84\x9b\xc7\x6c\x69\xf3\xce\x25\x3f\x50\xa8\x89\xb4\xfa\xaf\x80\x0f\xaf\xc2\x68\x0d\x04\xcb\x75\x81\xb4\x08\x3e\x04\x65\xf8\x5c\x2f\x5e\x2e\xe7\xc8\x80\xd0\xa5\xd7\x02\x45\x97\xfe\x3c\xf8\x4e\x80\xea\x8b\x32\x40\xb5\x88\xa0\x3d\x5f\x01\x58\x3f\x93\x04\xcc\xba\xe4\x27\xfa\xa8\x26\x85\xcf\xdd\x53\x09\x18\x06\x87\x4f\x03\xa7\xff\xdc\xed\x9d\xfe\x7d\xe0\xf4\xef\x83\xc3\x32\x6a\x97\x84\xae\xe3\x1b\x52\xf0\x01\xa6\xae\x3b\x55\xb8\xeb\xdf\xaa\x2f\x70\x47\x27\x15\x24\xdb\x3d\xab\xc5\x46\xf1\xdb\x16\xc6\xfd\xbd\x82\x13\xbb\xa9\x60\xdc\x2b\x2c\x76\x06\x43\x21\x41\xb2\x6f\xe4\xa2\x73\xbe\x01\x10\x3b\x41\x07\x55\xa8\x75\xf9\xd4\x00\x67\x49\xc0\x99\x66\x0e\x02\x1d\xbb\x9c\x70\x7c\xc3\x75\x6f\xf3\x13\x7b\xed\x85\x99\x76\x53\x03\xba\x30\xe5\x59\x1e\x94\xda\x51\x27\x20\x02\xcf\x90\x1f\xc5\x89\x76\x7d\xf3\x68\x47\x88\x48\x3a\x0e\xad\x20\xde\x7a\x6b\xbf\x25\x2d\xbb\x8f\xf7\xc5\xea\xd2\xe5\xa2\x74\xd2\x40\x8e\x10\xbc\x0e\x0e\xbd\x6b\x04\x5f\xbe\xf7\x63\x16\x0e\x7f\x6d\xc7\x73\x1c\xfe\xb5\xfd\x9e\x6e\xd4\xef\xf9\x86\xfd\x9e\x56\xfa\x3d\x7d\x7a\xbf\x93\x2e\xf1\xad\x6e\xad\xeb\xf7\x0f\x70\xe7\xba\x77\xbc\x25\x57\x82\x03\x5a\x14\x99\x13\x85\xcf\xf7\xde\xc0\xe7\x7b\x63\x02\xd8\x7f\x93\x60\x7d\x6f\x35\x58\xdf\x6b\x03\xac\xef\xcb\x26\x00\xf6\x9f\x6d\x00\xfb\x1b\xd7\xd5\xeb\x9c\x0d\x60\x7f\x55\x02\xb0\x97\x98\xfb\x7a\x19\xab\x62\xda\xdf\x70\x20\xb7\x1b\x16\x42\xbe\x12\xd3\xde\x6a\x86\xe1\x5a\x56\x1e\x71\xbc\x16\x1a\x08\xdf\x11\x2c\x24\x51\x4c\xd8\x12\xbf\x80\x03\xdb\xfb\xcd\x89\xeb\x32\x31\x22\x08\x82\x0f\xae\x1b\xb6\xb8\x1a\x52\xf4\x48\x1f\x95\x39\xd1\x75\x38\xe8\x87\x02\xee\x79\x6c\xed\x49\x01\x29\x7a\xdc\x0f\x2a\x6c\x51\x8d\x64\x86\x53\xf6\xd2\x59\xf1\x84\x37\x4e\x08\x61\x7e\x58\x48\x61\xe9\xe3\x74\x25\x96\x7e\x9e\x6e\x40\x21\x34\x91\x13\xae\x46\xf9\x7a\x8c\x91\x8d\xbf\xeb\x98\xdc\x3b\x36\x1f\x65\x95\x04\xae\x00\x9e\xbb\x6f\x91\xca\x2b\x06\x01\x51\x4d\x7f\x61\xf3\x4b\xa9\x07\xac\xfe\x36\x15\x55\x59\x7c\x15\x92\x0b\x15\x61\x71\x8a\x80\xa4\x2a\x6e\x4e\x12\x3d\x2d\x0a\xbe\x17\xa7\x69\x40\xbc\xed\x17\x2f\xf6\x10\x24\xe9\xa6\x31\xf4\x52\x76\x8d\x0c\xd9\x35\xb6\x64\x57\x06\xf7\xc2\x0f\x5f\x8e\xef\x67\x21\x19\xe2\x61\x2d\x15\xbd\x3a\x0e\x1d\xea\x87\x03\xd7\xe5\xe2\x29\x96\x6f\x0a\xbc\x97\x49\x48\xc6\x1c\xf0\x45\x90\xdb\xd7\xc1\xc4\xd5\x49\x87\x16\xf8\x4b\x9e\x0a\xf0\x97\x32\x78\xcb\xf5\x13\x25\xc6\x52\xfd\x6c\xf7\x15\xac\xef\xca\x92\x9b\x34\xf8\xf5\x68\xe5\x35\xc0\xe4\x77\xb4\x50\x69\xaa\xf0\x4f\xd3\x24\xe6\x2c\x89\xd2\xbb\x7d\x0e\xbc\xdb\x59\x31\x32\xfa\x6a\x48\x70\xec\x00\xf3\x87\xf3\x75\x39\x0a\x04\xf7\x5a\xd8\xb9\xa3\xc2\xce\x71\x70\x4f\x85\x9d\x9b\xe0\xbe\xd7\xe9\x4b\xaa\xa0\x7a\x40\xb3\x1b\xaf\x79\xac\xc0\x27\x9a\xc7\x0c\xc6\xec\x18\x66\x70\xc3\xbc\x6b\xbc\xc4\xc4\x44\xc9\x13\x16\x81\xe5\x85\x0c\xbf\xe4\x1d\xf3\x44\x4b\xd0\x72\xe9\xb5\xe1\x4f\xf3\xe2\x0f\xf3\xe2\x67\x76\x81\x10\x7c\x0a\x8e\x68\xa1\xce\x83\xa3\x56\x16\x47\x03\xec\x75\x94\x6c\x7b\x8a\xa7\x49\x8d\xf4\xb9\x90\x75\xf4\x8f\xf5\x19\xc5\x10\x72\x16\x73\xe9\x5f\x16\xbc\xac\x43\xb8\x5c\xcd\xa8\x69\x22\xa8\xd6\x2c\xa1\x11\x5f\x42\x63\x38\x76\xdd\x48\x0f\xcb\x21\xbd\x52\x23\xb8\x39\xa5\x97\x82\x3b\x5f\xe0\x0c\x48\x8a\xeb\x29\x03\x70\xaa\xf8\x7b\xa6\xad\xf3\x34\x61\x21\x94\x32\x26\xe2\xa2\x16\x39\x64\x6c\xed\x73\xc7\xa5\x4d\xa3\x80\x87\x95\x0b\x2e\xf7\x1b\x60\x56\x9f\x18\x0f\xaf\x1f\x1c\xff\x93\x70\x06\x89\x86\x10\x0d\xe5\x55\x8f\xa7\x13\x03\x2c\x73\xfa\x1c\xbc\xc1\x49\xf1\x38\x4a\xe8\x9a\x74\x6e\xc1\xc2\x86\xe9\xba\xf3\xf1\xcd\x19\x29\xed\x13\x6e\x8d\x28\x9b\xe2\x98\xc1\x13\x6e\x72\x16\xcc\xcd\x3b\x4e\x1f\x72\xa6\xf9\x5f\xe3\x51\x92\x52\x85\xbf\x0e\x9f\x56\x10\x08\xe7\xc9\xcc\xdf\xea\x94\xe9\x83\x3b\xca\x43\xf3\x7f\x39\xce\xff\x02\x4d\xa0\xb6\xfa\x20\x4d\xc4\xbf\x6e\x50\x4a\xc5\x4a\x54\x3d\xbb\xee\x33\x90\x00\xc7\xf5\x19\x50\xe9\x16\x5b\x76\x1c\x76\x7a\xa2\xea\xa2\x36\x02\x49\xe0\xe6\xb8\xcf\xd4\xc4\x96\x16\x76\xdf\xe9\xec\xcf\xee\x1b\x6d\xa7\x9a\x97\xe6\xaf\x6b\xb3\x2f\xc5\x61\xe5\xa1\x40\xa5\xe0\xcf\xd5\x87\x15\x29\x8e\xfd\xcd\xc6\xf3\x86\xbb\x41\x11\xd7\xf0\x7a\xae\xe4\xf0\x7c\xad\x12\x16\x05\x88\xc9\xa4\xa8\x9a\xb9\xdb\x40\xbb\x5a\x41\xc5\x73\xfc\x1e\x8f\x72\x91\x8c\x1d\x01\xce\x70\xcb\x7c\x17\x54\x42\x66\x1d\x5c\x93\xb2\xda\x4e\x26\xc9\xf3\x66\x9f\xe1\x69\x1f\xfb\x12\x38\xff\x99\x71\xc9\x25\x6b\x78\x5b\xd3\x6c\x2b\x9a\xe2\x2d\xe6\x92\xe1\x33\x1a\x5a\xb4\xfa\xdb\xed\x95\x1f\x6a\x53\x25\x55\xad\x8b\x0b\xeb\xf0\xd6\x96\x15\x4a\xfb\x46\x81\xbc\x24\xe5\xa2\x41\x94\xfe\xbb\xd9\x27\xff\x3a\xd5\xe4\x0a\xde\xc8\x4d\x84\xbe\x12\x7b\x67\xd5\x15\xbb\x03\xdb\xb0\x8d\xd6\x36\xd7\x1b\x9c\x87\x51\x9c\xd1\x56\x8b\x44\xab\x65\x7f\xab\xfd\x8f\x77\x21\x73\x6e\xa4\x22\x95\xa6\x09\xe5\x22\x0b\x67\x56\x7c\x1d\xcf\x53\x41\xab\xc8\xdd\x81\x39\xa7\x22\x03\x7b\xfa\x8d\xcb\x9c\x30\x7a\xa2\x70\xa3\x3f\xec\x80\x53\xfa\x2c\x93\x69\xe8\x47\x4b\x7e\xb9\xe6\x07\xa9\xec\x32\xe3\xdb\x36\x8f\x44\x6a\x76\x10\x4c\x82\x19\xdd\xdb\xa7\xc1\x8c\x0a\x1c\xb7\x36\xf5\x28\x49\x11\x15\xd4\xf4\x86\xfa\xa0\xa5\x3b\xaa\xf2\xc3\x75\x70\xab\xf7\xde\xbb\xe0\xb6\xc5\x77\xf8\x4d\x58\xb2\x2d\xb2\xe9\x8e\x9c\x0c\x9a\x8c\x5a\xcd\x8e\x07\x28\xb9\xe8\x0a\xcf\x3b\xbd\xda\x5e\xaf\x75\x61\x7c\xb0\x7c\xfc\xae\xe9\x95\x2a\x32\x83\x25\x62\x25\xa1\xf2\x81\xdd\x5c\x96\x1b\xdd\xd4\x6b\xb6\x35\x59\x1c\xf0\xb6\x2e\xa7\xe8\x20\x98\xbb\xee\x5c\xa4\x28\x85\x0c\x61\xb4\x10\xda\x33\x50\x69\x5a\x79\xce\xa5\x05\x8c\x36\x50\xce\x8c\x7a\xc9\xf0\x0b\xab\x2a\xf4\x93\x08\xe2\x2a\x50\x42\x42\x1e\x51\x45\x8d\xf1\x6c\xe7\x08\x06\x9a\x46\xb9\x0b\x94\x83\x23\x0b\x44\x61\x92\x09\x0f\x49\x61\x5d\x23\xf4\x26\x16\x16\x92\x21\x88\xcd\x85\x60\xfe\x6f\x11\x54\x4a\x2b\x87\x85\xf8\xb4\x81\xc0\x12\x91\xad\x89\xb4\x31\xd7\x4a\x03\x35\x6b\x51\x9b\xd1\xc2\x8a\x83\x0d\x9f\x24\xb9\xa7\x76\x57\xba\x3f\x94\xcf\xd7\x2a\x12\x82\x2a\xe2\x3e\x3b\xe5\x7f\x26\x86\xe1\x26\x3b\x33\x4b\x5a\xac\xf0\x6d\x5b\xb9\x8f\x8b\xc3\xe0\xd2\x2e\x24\x3e\x5b\xda\x90\x74\x68\x4c\xa9\x65\x8d\x48\x99\xa7\x09\x82\x4a\x22\xda\x96\x12\x51\x9d\xbc\xb4\xdd\x66\x4f\x55\x19\xf9\x61\xa7\xc1\x97\x9b\x26\x6c\xe9\x6a\x0f\xf1\x18\x6d\x60\x0a\x30\x58\x24\xf3\xb5\x64\xeb\x36\x43\x75\xa9\x74\xd5\xef\x77\x5e\xf2\x12\x14\x6b\xf7\xa2\xcb\xf9\x74\xca\x91\x53\xbc\x4c\xec\x45\x83\x0d\xf7\x22\x1c\xc7\xe2\x7c\xc9\xc4\x73\xed\x76\x5e\xb6\xfd\x47\x20\x5d\xf5\x6e\x35\xe7\x27\x53\x1a\x16\x2f\x08\x82\x79\x77\xdb\xe7\xb8\x78\xfa\x30\xca\x42\x73\x75\xe6\xb1\x23\xf0\x5c\xc5\x48\x87\x89\x7e\x3e\xeb\xee\xfa\x33\x76\xea\xc4\x8f\x89\xca\x78\x78\xaa\xd8\x9b\xf1\x98\xc5\x59\xe9\x10\x47\x7c\x52\x1d\xb6\xac\x16\x48\x46\x6b\x97\xb5\x98\xaf\xfe\x99\x52\xfa\x4a\x56\x32\x3e\xdc\xb6\x26\x3f\x6e\x17\x30\x45\x05\xdc\xd2\x25\x78\x25\x84\x28\x3f\xb7\x68\x56\x1c\xff\x09\x42\x46\x88\x2c\x37\xde\x70\x08\x8e\x59\xc6\x5a\x7e\xb9\xec\x30\x12\x56\x7e\x27\x4d\xee\xe8\x9d\x83\x7a\x1e\x4c\x02\x65\xfe\x4b\x61\x4e\x52\x66\xd9\x4e\xbb\xfd\xe3\xe0\x3f\x52\x70\x7e\x70\x10\x58\x16\xad\x20\x08\x42\x09\x83\x1b\xfe\x47\xf2\x7c\xa2\xd6\x2b\x56\x43\x62\x11\x5f\x16\x2c\xcc\x4f\xaf\xc8\xc3\xb4\xcc\x28\x52\x33\xe7\x7f\x4f\xc3\x99\xef\x70\x6f\xe0\x0a\xa7\x48\x1c\x09\x24\xd1\xaa\xb7\xee\x63\xe8\x92\x26\x98\xe4\xbb\x34\x62\x66\x5e\x3a\x5f\x06\x62\xbe\x8c\xd2\xd5\xf8\x15\x07\x98\x33\x98\x4d\x67\x31\xce\x31\x03\xe7\xe4\x6c\x97\xd2\x62\xfd\x4f\x6c\x93\x93\x99\x94\x5a\x3f\xd6\x3f\xe3\xa3\xb7\xeb\x31\x72\x0d\x36\xb0\x68\x89\x90\x20\xe4\x11\x50\x1b\x6c\x4b\x3d\xc7\x3c\x9e\x2f\x9a\x8e\xdf\xce\xe3\x98\x65\xda\xca\x66\x71\x94\x33\x6e\x4b\x84\xc0\x4b\xed\x3c\xc2\xe1\x50\x64\x90\xd6\x64\xc0\xbf\x6c\xe5\x80\x7c\xcf\x4b\xd6\x94\x23\xd9\x2c\x1b\xf0\xc2\x55\x05\x09\x37\xaa\x09\x42\x05\xcc\xfe\x46\x21\xda\x13\xeb\x92\xb1\x08\xa1\x15\x10\x9f\x1e\x61\xd3\x06\x9e\x7c\x72\x5c\x5e\x59\x68\x2e\x4e\x1f\x21\x18\x94\x8e\x33\x1f\x23\xfc\x6d\x96\x8e\xb2\xd8\x38\x93\x83\xae\x3b\x4a\xd9\x6d\x1f\xd7\x70\x3d\xc5\x49\x38\x74\xac\x18\x7c\x91\x9a\xcd\x3f\x6f\xa0\x01\xda\x35\xad\x55\x4d\x01\xd6\x90\x4e\x8d\xd2\x72\x2e\xff\xd7\x08\xa8\x10\xf4\xc2\x1a\x76\xe3\x6c\x93\x83\x8f\x48\xe9\x88\xf3\x8d\xce\x25\xf2\x88\xc3\x97\x59\x0b\x74\x02\x35\x8a\x64\xa3\x06\x68\xba\xeb\x44\xd3\x31\xf7\x52\xcb\x1f\x66\x98\xd9\x36\x7f\x67\xc5\xc1\xd0\x73\x4e\xa6\xe1\x98\xee\x33\x2b\x50\xa1\x07\x05\xf2\x25\xab\x87\xb5\x6a\x4e\x2a\xab\xe6\x8a\x08\x04\x3b\x14\x99\x56\xa5\xde\xae\xa6\x16\xdd\xeb\x38\xa1\xda\x9b\x5c\xe0\xd9\x69\x42\xf5\x18\xa4\x00\x6b\xc2\xeb\x23\x0e\x9e\xde\x10\x59\xd8\xcf\x38\xcc\xf1\x1f\xde\xd6\x5e\xfb\x07\xe4\x40\xdd\xe7\x39\x6b\xdd\x5e\xfb\x07\x9d\x33\xe7\x7e\xb2\x4e\x35\x60\xa5\x45\xb0\xf4\xad\x3f\xe5\xb7\x18\x5f\x1e\xcb\xb6\x6e\xa9\xbf\x8a\x62\x76\x24\x32\x13\xcb\xfd\xf4\xaf\x19\x38\x48\x2b\x0d\xa3\x0c\x0f\x15\xb1\x6f\x33\x08\x22\xd7\x8d\x20\xdb\x04\xb7\x97\xbf\xeb\x7c\xb7\x4d\x5a\x5b\x40\x34\xe5\x57\xdc\x7d\xe9\x77\xe4\x68\xcf\xcc\x01\x74\x5b\x19\x40\xd5\x3e\x36\x9b\xec\x28\x4c\x87\xb4\xa9\xa6\xa2\xa9\xc6\x7f\xb5\xa9\xb4\x00\x68\xd1\x20\x73\x6f\xa4\x0d\x9b\x6c\x60\xb8\xbd\xac\x6a\xb5\xf8\x69\x66\x23\xab\x91\x1e\x2a\x8d\x24\x45\x8b\xce\x7e\xc5\x1c\x68\xa3\xf9\x6e\xef\x16\x95\xf6\x13\xb1\x53\xb4\x19\xc7\xa2\x19\xaf\xd3\x27\xd3\x49\xf3\xb0\xd3\xf5\x27\x6d\xba\x71\x4b\xa1\xe7\xb4\x71\xad\x83\x36\x8d\x9b\x58\x7b\xe2\x96\xcd\xaf\x27\x38\x1c\xe2\x94\x8b\xe4\xf2\xaa\x84\xb6\xc8\x8e\xe0\xf2\x28\x8f\x39\x73\x34\xfb\x55\x4e\x72\xbb\x8a\xac\xf8\x91\x68\xf1\xaa\x8f\x95\xce\x99\x0a\xea\xb2\x48\xe6\xef\xd2\xb7\x99\xd3\x54\x2e\x9c\xa7\xaa\x45\x73\xfa\x08\xc6\xc1\xe4\x80\x03\xcd\x8c\x97\xcb\x31\x5b\xa9\x83\x20\x78\x87\x97\xcb\xe1\x72\xe9\x8d\x83\x1a\x50\x0a\x35\xac\x24\xee\x47\xd8\x75\x18\x2a\xb2\xe3\x3b\x93\x3d\xc7\xb0\x0a\x45\xa2\x6d\x0c\x33\x06\x8f\x49\x2c\x2d\xba\x2c\xec\x70\x2c\x02\x7f\x1f\x82\xd1\x81\x85\x80\xf3\xb0\x5c\x3e\x94\x0b\xf6\xf0\xd4\x82\x31\x70\x6a\xbb\x6c\xba\x8b\x85\x07\x72\x8e\xef\x73\x1d\x6e\xb5\x41\xa9\x67\x08\x1e\x6a\xc2\x7f\xe7\x1b\x1d\xa1\x19\x00\xdc\x10\x56\x0d\x48\x95\xfd\x38\x12\x33\xa0\xa0\x93\x76\x83\xd4\xc2\x94\x50\xc0\x18\x1e\x10\x24\x9b\x7d\x81\x0d\x4e\xe6\x51\xa0\x17\x83\xbb\xc7\x14\x95\xba\xa8\x49\xbd\x5e\x68\x1f\x78\x9a\xda\x77\xda\x8d\x76\x83\xeb\x2f\xa6\x77\x32\x4b\xc7\xbe\x5e\x4d\xc7\xf2\xbf\xc4\xf1\x88\x7f\x70\x2b\xcb\xc3\x34\x97\xaf\x5f\x25\x33\x7f\xeb\xa5\xed\x8b\xfe\xb2\x84\x31\xe2\x3b\x9d\x46\xa7\x21\x8e\x08\xd9\x90\x64\x98\xdf\xb2\xff\xfd\x45\x65\xc5\xfa\x89\x4f\xad\x02\x79\xd7\x29\x82\xfb\x34\x70\xfe\x3f\x3c\xc0\xa3\x51\xc7\x81\x63\x7a\xb1\xbb\xb7\x17\xee\xef\x3a\x70\x43\x2f\x46\xaf\x46\xd7\xf8\x85\x03\x97\xf4\x22\x1c\x5d\xef\x6e\x5f\x3b\x9c\x91\x26\x0d\x88\xf7\x72\x67\x67\x17\xc1\x27\xfa\x73\x67\xef\x65\x07\xc1\xf9\x5f\xdf\x41\xe2\x24\x2d\xed\x1e\x33\x19\x8c\xc8\xb9\xf2\x39\xbe\xe1\x5c\xfe\x7a\x3d\x1f\x8d\x30\xb7\x8c\x4b\x50\x0b\xdb\x15\x36\x22\x43\x9c\xe3\x74\x1a\x91\x30\xc7\xdc\x29\x76\xa3\x6d\x88\x87\x9c\xb2\x6f\xc8\xbf\xfc\x5b\x36\xec\xc4\x8c\x7b\x66\x4e\x82\x45\x01\xd3\x60\x71\x1d\xa6\x1d\xda\x03\xd7\x61\xba\x4d\x1b\xff\x20\x1a\x79\x9e\x63\x96\x20\x08\x82\xe1\x72\xe9\x5c\xf3\xbc\x18\xbb\xb2\x41\x28\x9d\xa1\xc5\x44\x1c\xd4\xb2\x4f\x92\xe4\xce\xe9\x07\x06\xe3\x6f\x86\xc0\x4a\x30\x8d\x88\xd3\x0f\xda\xa5\x9b\xe1\xbd\xd3\x0f\x3a\x6d\xce\xfb\x78\x1b\x64\x5b\xf4\xb7\xe4\xcc\x98\x69\xce\x0c\xd7\xf5\x6e\x83\xad\x5b\x04\xd3\x16\x2d\xb9\x26\xe0\x0d\x4c\x21\x4f\xd9\x0b\x6e\xc1\xf9\x01\x39\xa8\x88\x46\x9e\x59\x01\xa3\xfc\x73\xc9\x7a\xec\xcd\x97\xcb\x36\x5a\xf3\xdd\x71\xb0\x35\x16\xdf\xdd\x7e\xec\xbb\x63\xf1\xdd\xbf\x7a\x94\x94\xac\x04\x1b\x88\x11\xea\x43\x08\x0b\xa3\xa7\xfc\xa4\x65\x5c\x81\x35\x8e\xfc\xa4\x65\x5d\x03\x6f\x0d\x3f\x69\xf1\x1f\xf0\x75\x8e\x19\xae\x16\xfb\x5b\xf4\x86\x7d\x24\x4e\xdb\x67\x69\x32\x4e\x71\x96\x5d\x87\xa9\x53\xc0\x84\xeb\x04\xdc\x64\x6f\x36\x69\x77\x73\xfb\x7d\xd2\x1a\x86\xd9\x04\x0f\x69\xed\xf8\xaf\xa3\xd5\x75\x44\x05\xf2\x6b\xf1\xa7\xd6\xe5\x7f\x1d\xa6\x34\xf3\xeb\x95\xf0\x16\xac\xf5\xbc\xd2\x54\x13\x03\x9d\xb5\x80\x1c\xe7\x2c\xaf\xce\x89\xd5\x74\xa5\x36\xa7\x09\xde\xd4\xb6\x6c\x98\x76\xf8\x0c\xe4\xed\xc9\x6d\x5b\x7c\xe0\x16\x08\x2a\x93\x8c\xfb\xd8\x3d\xb5\x9e\x1b\xd7\x62\xdb\xae\x85\xd5\x79\xbd\x47\x06\x1a\xcf\x80\x57\xa6\xef\x3f\xda\xb4\x56\x5d\xb7\x0b\x8b\x9c\x65\xed\xe1\x47\x15\xa6\x6b\x65\x84\x15\x8f\xbb\x78\x46\x58\x34\xe9\xfe\x36\x92\xe1\x9b\x5f\xd8\x8d\x3d\x54\x00\x09\x56\x87\xe3\xa5\xc1\x9a\xc0\xb5\xc7\x3d\x40\xaa\x2e\x79\x42\xf7\xdc\x05\xe7\x3f\xa7\x78\x18\x85\x8d\x59\x1a\x91\x5c\xc6\x78\x1c\x32\xaa\x21\xdf\xc1\xf7\xe1\x20\xa7\x4a\xcd\xfa\x90\x6b\xf2\x78\xe0\x74\x5a\x80\x39\x0c\x17\x45\x69\xbe\xd3\x25\x9d\x0f\xc4\xc7\x0c\xfd\x7c\xe6\xaf\xb3\xf0\x03\x9f\xa5\xf5\xee\x2b\x86\x1b\x47\x49\x61\xb7\xb4\xe6\x90\x44\x53\x01\x6e\xf0\x8c\x17\xac\xb1\x93\x35\x22\x32\x8a\x48\x94\xe3\x46\x1c\x11\xcc\x16\x18\x63\x41\xa8\x69\x1e\x66\xaa\xf0\x9d\x34\x1c\x46\x61\xbc\x35\xa6\x7f\xd9\x1c\x31\xdc\x76\x1b\xed\x1f\xa0\xe1\x20\xf3\x4e\x67\xff\x07\x68\x18\x95\x6e\xec\x6e\xd3\xd5\xd9\xf0\xa1\x61\x71\xf3\x4e\xa7\x3d\xbb\x6f\xd0\xff\x1c\xe3\x91\xa2\x4d\x77\xda\x8d\xad\xed\x9d\xd9\xbd\x5d\xc8\xda\x2e\x7a\xac\x98\x69\xa5\x98\xe9\xbf\xa3\x98\xd7\x61\xba\xd2\x76\x51\xf1\x3f\xba\x16\xbe\x36\xcc\x5c\xd1\x36\xcf\x95\xf4\x11\x52\xa3\xdd\xda\xce\x64\x5f\x55\x29\xae\x04\x5f\xdf\x75\x39\x96\x72\x33\x44\x01\xfd\xe2\x77\xe0\x05\xb0\x97\xed\x75\x5a\x55\x5d\x48\xae\xc6\x00\xb4\xa6\x4a\xa7\xb1\xdd\xea\x64\x8d\xc1\xfc\x3a\x1a\x6c\x5d\xe3\x6f\x11\x4e\xbd\x76\x6b\x9f\x05\x58\xbf\xec\xb0\x3f\x2f\x76\xd8\x9f\x9d\x57\x7b\x48\x0d\x59\x5e\x51\x73\xe5\x17\x73\xa8\xd2\x68\x2d\xd5\xef\xbb\xe0\xa8\xe6\x43\xfc\xfd\xd7\x62\x92\x7e\xe3\x87\xc9\x1d\x78\x7a\x1e\xdb\xdf\x55\xed\xed\xda\x6a\x77\x44\xbd\x77\xe9\xff\xbb\xbb\xd0\xe8\xa0\x46\xa7\xd5\xd9\xcb\x4a\xf5\xde\x96\xe5\x7e\x62\x71\x9d\xff\xbc\xc1\x0f\xa3\x34\x9c\x62\x9a\xa3\xd9\x0b\x8e\xbf\x70\xda\x3f\x38\xfe\x82\x9b\xe1\xb6\x76\xf6\x7e\x70\x84\x37\x9c\x70\x27\x06\x67\xdf\x48\xc0\x07\xb4\x48\xb0\xf5\x8a\x27\x60\x37\xd7\xa4\x58\x53\x80\xed\x72\x01\xb6\xcd\xd7\xeb\x4b\xf0\xc2\xc8\xff\x65\x5d\x01\xca\x09\xec\xef\x8b\x1d\x58\x7e\xb7\xce\xb9\xaf\x6e\x5a\x33\x5b\xa2\xe1\x06\xf7\x58\x72\x51\xa6\xf5\xd9\xd3\xea\xce\xee\xe5\x4b\xa5\x33\xdd\xf7\xac\xff\xce\x85\x24\xc8\xd8\xce\x84\xed\xe8\x8c\xea\x52\xfb\x2f\x76\xf6\x10\x5c\xf1\x9f\x7b\x7b\x08\x3e\xa4\x01\xf7\xe5\xf7\x79\xac\x1c\x16\xa1\x0e\x97\x83\x14\x63\xc2\x9c\xfa\xc5\x93\x18\x87\xb7\xea\x41\x01\x9f\x37\xd3\xc7\x5e\x87\x83\x9b\x61\xca\xd1\xf0\xb2\x27\x79\x7f\x73\xeb\x8d\x7c\x9f\x3b\x26\xad\x71\x01\xe7\x78\x50\x12\xb5\xb0\xce\x38\x35\x9a\xc7\xb1\xa8\x56\x5d\x80\xe2\x48\x1a\x91\x6b\xdd\xc2\xa7\xe1\x3d\x7f\x68\xf9\x82\x3b\xd9\xd4\x11\xde\xe0\x09\xb1\x8b\x7a\x6d\x70\x8c\xde\x19\x81\x8f\xf7\x56\xe0\xe3\xb1\x1d\xf8\x78\xc3\x2f\xad\xaa\x5c\xea\x60\xc8\x23\x33\x18\xf2\x93\x15\x0c\x79\x2e\x79\x4b\x2f\x24\x6f\xa9\x76\x5f\x3f\xd3\x45\xbe\xe8\xfe\x99\xfb\x17\x70\x65\x93\x9b\x7e\xd0\x09\xae\xba\x8b\xc2\xbf\x82\xcf\x01\x69\x65\xec\xfc\x13\x4e\xf5\xc3\xcf\x5d\x87\x41\xda\x3a\xfe\x67\x38\x59\xe1\x2b\x7f\xa8\x93\x9f\x74\x9f\xe5\xfe\x09\xbc\xaf\x67\x45\xfd\xa6\x13\xbe\xef\x7e\x48\xfd\xf7\xf0\xa6\xc6\xa9\xfe\x6d\x40\x84\xf6\x39\xc4\xd9\x20\x8d\xae\x99\x17\x72\x1f\x5e\xab\xfb\x86\x73\x72\x1f\xbe\xd8\x0a\xb8\x35\xfa\x36\x39\xe5\xaf\x1b\x75\xfa\xb6\xd5\x31\x0e\x38\x7a\x44\x89\x0b\x36\x44\x1c\x70\xe4\x68\xe1\x9e\x6e\xa5\xcc\x2a\x2c\xa9\x8f\x84\x79\x96\x3e\xfa\x58\xe0\xa7\xc9\xb6\x6a\x06\x07\x58\xf4\xab\xbc\x6f\x57\x06\x12\x6c\x48\xc6\x5a\xe9\x17\xa8\x76\x09\x82\xdf\x8d\xd8\xd1\x95\x91\x58\xf9\x86\xd6\x3f\xd5\x98\xca\xcc\xf8\x5b\x0e\x56\x37\x6b\x97\x84\x1a\x66\xcd\x6f\xcc\xf3\x6c\x40\xdb\xff\x70\x94\xe3\x54\xd7\x89\xf9\x7f\xcd\xbb\x8b\xba\x11\xe0\xcf\x19\xd2\xe6\xa2\x6e\x18\x30\xfa\x6f\xfb\xce\x8d\xa2\x4f\xba\xe6\x68\xcf\xe7\xd2\x68\xf9\xa5\x6a\x83\x3c\xd4\x15\x0f\x67\x33\x1c\xa6\x7e\xb3\x0d\x11\x7d\x47\x7a\xe9\x7f\x53\x71\x69\x77\x66\x2c\xda\xb1\x11\xa4\x76\x2f\xe3\xd2\x2e\x8d\x60\xb4\x4f\x3a\x46\xed\x48\x58\x08\x48\x42\x70\x63\x96\xe2\x0c\x93\x9c\x77\x6b\x01\x6f\x9e\xe2\xd0\x17\x99\x51\x60\x3d\x39\x8c\x2a\x9a\xe5\x29\xd3\x2c\x13\x72\x9a\xcc\x33\x5c\x01\xf9\xcb\x35\xba\x9f\x85\xf7\xe7\xba\xc6\xb3\xdf\x35\x9c\x9f\xa7\x7e\x33\x74\x4b\x19\x22\x09\xcd\xb9\xeb\x72\x60\x3f\xee\x08\xa7\x27\x19\x62\x4e\x8d\xec\xeb\x15\xdc\x42\x9d\x99\xfc\x5a\x51\x8d\x1e\x3b\xd3\xbd\xa2\x8f\xc7\xb6\x77\x45\x33\x52\x5d\x21\x19\xd7\x4d\x00\xff\x6d\x75\x0a\xf8\xaf\x0b\xf8\xb0\xa2\x35\xd9\x72\x4a\x5b\x92\xfd\xb8\x5c\xd3\x9c\x2a\x11\x5f\x58\x2a\x69\x04\xb2\xfa\x18\xd1\xb4\x1f\x8c\xcd\x74\xe6\xba\xe2\x3b\x6f\xf5\x06\x38\xb5\x6e\xb2\x2c\x51\x81\x20\xb4\x8f\x8d\x4f\x37\xf1\x83\x2e\x6b\xd1\x55\xc5\xa5\xd1\x8c\xa6\xb3\x24\xcd\x43\xc2\x14\x6a\x3e\x68\x04\xc0\x75\xc9\x28\xbe\x0a\x36\xb0\xc6\x58\x2e\x33\x7a\x9d\x0c\x1f\xf4\x71\xe4\x9f\xe5\xb0\xb9\x3f\x6c\x20\x14\x01\xc4\x27\xf3\x75\x5c\x3f\xa4\xeb\x00\xd3\xfe\x8d\xe8\x8d\x32\xd0\xa1\x38\xe6\x5e\x01\xe7\x57\xab\x4c\xb7\xb9\xf1\x40\xcc\x96\xf2\x91\x77\xb9\xd5\x2c\x0f\xa9\x42\xe3\x0d\x16\xa0\x78\x71\x99\x17\xd8\xce\x36\xac\xb3\x72\xa8\xea\x97\xf3\x37\x12\xc8\x30\x42\xd0\x70\x67\x2a\xea\xc2\x18\x86\xf5\x1d\x44\xff\x7f\x23\x4d\xad\xbe\x33\x48\xe2\xf9\x94\x38\xb0\x82\xb5\x77\x7f\x77\x76\x8f\x1c\x2b\x5b\xde\x5d\x4f\x6b\x5f\xa3\xe3\x84\xe2\xaa\x67\xc2\xdb\x30\xce\x30\xa3\x0d\xe6\x1e\x00\xab\xbf\xcf\x9e\xff\x91\x19\x69\x99\xed\x7b\x1a\xde\x7b\xd8\xe2\x3f\x65\x76\xee\xac\x75\x9f\xc1\xee\xee\x2e\x02\xc7\x7d\x56\x2a\xbf\xe3\x6b\xbe\xd6\x02\xec\x97\x87\xc9\x1d\xf1\x36\xca\xf8\xf9\xfe\x2e\x82\xf5\x05\x47\x66\xd1\x2f\xa7\x46\xd1\x6b\x33\xce\xa6\xdf\x53\xd8\x15\x59\x3d\xb5\x78\xa7\xc3\xc7\x8a\x37\x1d\xfe\x6d\xc5\x9b\x0e\x9f\x5a\xbc\xf7\xe3\xc7\x8a\x17\x8f\xff\xb6\xe2\xc5\xe3\xa7\x16\xef\x8f\xf8\xb1\xe2\xdd\xc7\x7f\x5b\xf1\xee\xe3\x27\x14\xaf\xea\x5c\xb3\x72\x86\xe9\x0d\x46\xad\x57\x6d\xdb\xb6\xa8\xbf\xc8\xaf\xed\x45\xd1\x58\x45\x4c\x58\x55\x23\x6e\xab\x5a\x7f\xfd\xa1\x52\xde\x65\xcd\xf8\x0d\xdf\xb4\x0b\xe4\x7d\x16\x1a\xf1\xc9\x5f\x3d\x52\x14\xf1\x7b\xd9\xf7\x79\xf0\xc8\xb7\xff\x96\x40\x26\x88\x5d\x37\x51\x05\xaa\xf7\x4f\x39\xdc\x64\x3b\x2f\x9d\xfc\x3e\xe6\x13\x5b\xdd\x79\xe4\x19\xb6\xf3\x72\x76\xdf\xd8\xde\x15\xb8\x5c\x76\xbc\x9d\xc1\x6b\xbd\xdd\x2e\x0a\x49\x04\x9a\x69\x8f\x19\x1e\x8c\xc8\x5f\x57\x41\x77\x8f\x80\xda\x89\x5c\x90\x15\xd5\xb6\xe1\x3b\xb5\x83\xc5\xf0\xc0\x39\x11\x63\xe6\xfd\xfa\x31\xb3\xa2\x1f\x4d\x37\x0b\xc3\x41\x62\xe6\x68\x16\x18\xe9\x6a\x51\xeb\x54\x21\x7a\x93\x98\xbd\xf9\xad\xe2\x60\x60\x45\x62\x76\xb6\xad\xe3\x79\xab\x42\x57\xf8\x9e\x55\xea\xbd\xa8\xd4\x9b\xbf\x35\xe6\xac\xea\x2a\x94\xe9\xe9\x11\xbb\x2e\xf3\x94\x7d\x5a\xa4\x7c\xc5\x93\xe7\xaf\x4c\x99\x3a\xbf\xce\xac\x9b\xf8\xb5\x4c\x32\xba\xb3\x26\xdb\x46\x6f\x4d\xf6\x9d\x92\xbf\xc7\xdb\x15\xdd\xe1\xb7\xa1\x6e\x4c\x97\xbc\x35\x6a\xfa\xea\x8a\xf9\x20\x15\xc8\x7b\x23\x7a\xe9\x75\x1a\x10\xaf\xf3\x62\xfb\x05\x82\x2f\xe9\xff\xb0\x9f\xfe\x37\x65\x3f\xfd\x3d\xfd\x8b\xdc\x76\x9c\xe3\xeb\x6c\x86\x09\x1f\x47\x35\xfc\x6b\xc4\x20\x78\xe3\xba\xac\xe4\xbe\x6e\x17\x8c\x46\xcb\x60\x7c\xfe\x8e\x4c\x3a\x3c\x13\x41\xb2\x57\x7e\xa6\xa9\xf5\xbe\xa4\x9b\x90\x6b\xb3\xd1\x0d\x04\xd2\x1a\xce\x2e\x48\xcc\x9b\x71\x98\xe5\xac\xdf\x99\x03\xc5\xfd\xd9\xc8\x73\xfe\x37\x71\xd4\x4a\x91\xfc\x33\x68\x77\x3d\x5c\xff\x46\x36\xbf\xce\xf2\xd4\x6b\x43\x82\x6c\x76\xb0\x4a\x92\xe4\x79\x07\x21\x7f\x45\x3e\x40\x02\xc7\xa9\x1a\x54\x1e\x23\x80\x4e\xea\xa9\x96\x75\x27\x8a\x7d\xc1\x6c\x01\xe6\xce\xc4\xdd\xb2\x9c\xcb\x49\x72\xd7\xa0\x85\x68\x60\x5a\x8a\xc6\x14\x67\x59\x38\xc6\x35\x84\x62\xaf\xd3\xd5\x2c\xcc\xa7\x29\x2c\xca\x9c\xe0\x66\xef\xad\x64\x05\x17\x65\xd4\x02\x58\x3c\xae\xf9\xf4\xdb\x94\x57\x1e\xd7\x18\xc1\xd2\xfa\x76\xf9\x96\x9a\x76\x13\xc6\xd6\x3e\xb8\xb9\x4a\xc3\x01\x66\x9b\xe1\x6a\x72\xae\x67\xeb\x45\x1d\x9d\x8f\xbf\x28\xf3\x63\xad\x40\x67\x1f\x84\x33\x11\xce\xc8\x9f\x72\x1a\xad\xdf\xc5\xda\xfc\xf1\x7f\x16\xe4\xff\xae\x0b\xf2\x6f\x69\xb0\x18\x28\xe7\x46\x69\x99\xaa\xf1\x7f\x07\x9a\xea\x33\x49\xe8\xa2\x98\xe6\x75\x98\xe3\xf7\xa9\x48\x94\xce\x09\xa1\x12\x41\x25\xc5\x8d\x4c\x91\xcd\x07\x03\x5c\x97\xc7\x51\xda\xfa\xd4\xdb\x6b\xf7\x45\xba\x51\x18\xc5\x75\xc9\x3e\xa9\x64\xd2\x2b\xec\x75\x68\x1a\xa1\xf0\x3d\x95\x39\x7e\x4a\x83\x1f\xff\xcf\xbf\x3c\xaf\xeb\xf7\xfe\xcf\xbf\xfa\xcb\x7f\xfd\x0b\x3d\x47\xff\xfa\xdf\xad\xf2\x9d\x67\x3f\xc2\xd7\x95\xdb\x92\xde\x10\x78\xc7\xb3\x38\xb7\x5a\x1e\x6c\xbe\x53\xc9\xd5\xff\xe3\xdf\xb1\xfa\x8f\xb0\xcd\x48\x78\x1d\xe3\x13\x32\x4a\x20\x6d\x95\x3a\x43\xde\x11\x2d\x2f\x2f\x45\x33\xcb\x4b\xde\x9a\x08\xc2\xa0\x9c\x2b\x5d\x80\x5a\x53\xc6\x70\xfb\x53\x8a\x0e\xc2\xae\x47\x18\x31\x6f\x2b\xc5\xb3\x38\x1c\x60\xef\xc7\x7f\xfd\xeb\xc7\x31\x38\xff\x72\x10\xe0\x20\xec\x6d\xd7\x3d\x41\xbe\x47\xf7\x07\xc0\xb5\xd9\x0b\xd4\x8c\xa0\xd3\x6e\xff\x47\x5d\xa5\x5a\x77\x3f\xd6\xde\xfe\x06\x71\xc0\x0f\x67\x46\x38\x4d\xf1\xb0\x91\x27\x8d\x13\x66\x70\xc5\xa9\xdf\x70\x9e\x5f\xa5\x5e\x7d\x76\x74\xb6\xfd\xb8\x26\xc1\xb7\x95\x42\xf6\xad\xb5\x2e\x27\x62\x1b\xaa\xab\x54\x75\x1b\xb8\x93\xef\xe2\x4c\x1b\x5d\x79\xfb\x5b\x53\x4c\xfa\x1c\x63\xc3\xe5\x98\x40\x9d\x47\xbe\xbf\x28\x6b\x51\x24\x61\x21\xa0\x2c\xa4\x7f\x85\x97\x7f\xe9\xa5\x6d\xeb\x25\xe1\x53\xfd\xe8\x36\x5e\xd7\x6a\xd3\xaa\xcf\xf8\xb3\x14\x16\x4a\x44\xf0\xeb\xdf\xaa\xe1\xf3\xa4\x52\x81\x56\x40\x08\x86\x3c\xf1\x9d\x1f\xd9\x3b\xdd\x3c\x70\x9e\x63\x32\x48\x86\xf8\xe3\xc5\x89\xda\xfe\xbc\xda\x71\x55\x73\xbc\xa1\xa5\x80\x3a\x2a\xd6\x87\x15\xdb\xf1\x45\x69\x3b\x36\x96\x16\xad\x1a\x99\x1e\x8e\xc0\x51\xa9\x22\xd1\x95\x2c\x2c\x6d\xd5\x96\xfd\x8b\xde\xb2\x7f\x4b\x91\xf7\x55\xec\xac\xbf\xfe\xcf\xce\xfa\xdf\x75\x67\x7d\x97\xd6\xa8\x15\xef\x52\xd9\x8f\x61\x96\x45\x63\x62\xf6\x80\x6e\xff\x1c\x18\x99\x7d\xa0\x36\x17\x41\xc2\x7e\x40\xfe\x91\x1e\x90\xe7\xcf\x91\x4c\x98\xb0\x8e\xd2\xe9\x68\xfb\x6f\xd8\x6b\x09\xef\xb5\x84\xf6\x5a\xa2\x0d\x0e\xb8\x80\x77\x69\xfd\x06\x57\xc0\x9f\x7f\xfb\x36\xf9\xeb\xe6\xdb\x64\xdd\x16\x49\x82\x5e\x1f\xd2\xa0\xd9\x39\xb0\x5b\xc4\x26\xe1\x95\xfe\x42\x2d\xa1\x63\x86\xc1\xca\x04\xbd\xa4\x7f\x10\xb6\x32\x9b\x62\x9b\xea\x0a\xf3\xcc\x75\x3d\xc2\x99\xe4\x7b\x09\x84\x7d\x04\x21\x5d\x0c\xbd\x34\x68\xb6\x11\x2a\x48\x2b\x4b\xd2\xbc\x0c\xb6\x2b\x1b\x95\x6e\xa5\x53\xd7\x6d\xe6\xec\x47\x77\xab\xe3\xe7\xf2\x16\x7f\xd6\xed\xf8\xb8\xd7\xee\xff\x23\xef\xb5\xfb\xf4\xf1\x73\x8f\x5e\xfe\x93\x5e\x2a\xf6\xc3\x88\x47\x33\x0c\x70\x14\x7b\x22\x34\x38\x22\x44\x58\xd8\x7f\xdc\x69\xb7\x57\x6e\x68\x61\x0a\x8b\x12\x1e\xa3\xb9\x4e\x97\x1e\x55\x17\xd4\xf9\x8a\x15\xd3\x66\x23\xc6\xad\x59\x48\x70\xcc\x2c\x3b\x86\x2d\x69\xcf\x29\xac\xad\x84\x3e\xae\x2e\xca\xbf\x12\xba\x89\x5c\xe3\xd8\x27\x62\xb0\x0b\xa5\x30\xed\x3a\x99\xa6\xbb\x52\x9c\x65\x75\x14\x8b\xf1\x8a\x62\x0e\x53\xbb\x98\x63\x11\xf1\x4a\xbf\x90\xf9\x11\x68\xa8\x0c\xbf\xb3\xc3\x30\x1a\x6c\xaa\x66\xac\x4c\x13\xbd\x36\x1d\x6e\x58\xf3\xfa\x57\x9a\x7a\x92\xc2\xe2\x06\x3f\x30\xfe\xee\xd2\xa3\x5f\x52\x58\xa8\x6d\x8b\x6e\xf6\x72\x7b\xf4\x53\xee\x99\x5e\xb7\x7d\xc0\x1f\xff\xc5\xe6\xdc\x7a\xcb\xa4\xd5\xce\x69\x92\xe4\xd5\x66\xf8\x33\x85\x77\xa9\x57\x19\x8f\xcd\x36\xf0\x79\xe6\x87\xb8\x75\x21\xe4\x58\x61\x00\x38\xe4\x3c\x05\x36\x25\xfa\x77\x65\x7c\x24\xc0\x02\x86\x32\x6b\x75\x63\xc3\xdc\x75\x56\x1f\xb4\xf4\x2d\xf2\x3a\xc7\x64\x18\x91\x71\x29\xa7\x95\x22\xc1\xcf\x9b\x1c\x58\xd4\x71\x60\x17\x20\x47\x70\x09\xe7\x16\xf4\x04\x34\x89\xb4\xb9\x32\xff\x87\x10\x39\x70\x12\xf4\xda\xd0\x81\x6d\xd8\x81\x5d\xd8\x83\x7d\x78\x01\x2f\xe1\x15\x74\xda\x7d\xc8\x93\xa0\x27\x0e\x3a\x9a\xf5\x69\xa0\xd3\x81\xce\x76\x5f\x6f\xa7\x24\xd1\x51\x13\xe5\xfd\xea\x9f\x1d\x23\xc0\x49\x6f\x52\x9d\x7e\xd7\xbc\xf0\x3b\x40\x82\x59\x98\x66\xf8\x6d\x9c\x84\xb9\x87\xe5\x3a\x66\xa0\x60\xff\x98\x2b\x0f\x75\xb1\xe7\x63\xa4\x54\x10\x25\x05\x80\xe3\xa0\xe5\x92\x21\x8d\x33\x7a\xdb\x34\xd9\x2c\xa0\x38\x8e\xc6\x44\xc8\xe5\x36\xc6\x8f\x93\xe5\x29\xce\x07\x13\x47\x20\xfd\x68\x47\x8d\x52\xa8\x9d\x4a\x17\x69\xe0\x1f\xcc\x11\xe8\xf4\xf1\xc1\x86\xbc\x13\xda\x07\xa9\xce\x91\x53\x45\x82\x29\x47\xce\x20\x08\x26\x5d\x27\x4d\xee\x1c\x9f\x7b\x73\x46\x39\x9e\x2a\x4f\xce\x66\x10\xdc\xba\x2e\xf7\xe2\x14\xfe\x27\xcc\x7b\xd3\xf6\x45\x81\x3b\x9d\xd9\x75\xd7\x0c\xa9\xf4\xaf\x99\x53\x67\x3c\x86\x63\x9d\xe3\xbd\xeb\xde\x33\x77\xce\xe9\x10\x2e\xf5\xed\x1b\xd7\xbd\x61\x6e\x9c\xd9\x14\x3e\xe9\xdb\x47\xae\x7b\xc4\x5c\x38\x25\x8a\xd1\x85\xfe\xd8\x79\xb7\xed\x9f\xc3\x59\x40\x18\x7e\x35\x5c\xe9\x27\x67\x5d\x8e\x71\xe3\x9f\xc1\x87\x80\xb4\xee\x63\xf8\xac\xb3\xfc\xe0\xba\x1f\xe0\x94\xde\xce\xe0\x44\xdf\x3e\x75\xdd\x53\x38\x0c\x48\xeb\x1b\x4e\x93\xd3\x88\x70\xa7\xd6\xf7\x3a\xc1\xa1\xeb\x1e\xc2\xb7\x52\xf4\xb5\xd1\xfd\x0e\x38\xba\x8f\x37\x8a\xc3\x56\xbd\xc5\x4e\x72\x44\xdf\x38\xe0\xd0\x4e\x70\xc0\x11\xcd\xac\x7f\xe9\x0f\xc5\x63\x07\x9c\xe9\xd0\x01\x27\x9b\x5a\x78\x4b\x1c\xda\xc7\xb9\x8f\xe9\x7f\xf4\xdb\x66\x6d\x9c\x3e\x82\x37\x9a\x03\x3b\xe3\xc7\x3d\x73\x98\xb9\x6e\x2f\x33\xc6\x0e\xad\xed\x85\xeb\x66\x3d\x99\xf1\xd6\x7d\xb6\xe5\x94\x26\xd1\x05\xe3\xf4\x1d\xbb\x6e\xc6\x07\xcd\x7b\xfa\xcb\x6a\x3b\x36\xae\x9a\x41\x30\x65\x59\xa9\x0a\xd6\x65\xf6\xff\xb3\xf7\xa6\xcb\x6d\x1b\x69\xc3\xe8\xad\x50\x78\xfd\xe2\x43\x8f\x5b\x1c\x50\xb6\x6c\x07\x0a\xc2\x4f\x96\x65\x5b\x8e\xb7\x58\x72\xec\x98\x2f\xcb\xd5\x22\x9a\x22\x2c\x10\xcd\x00\xa0\x24\x9a\x44\xd5\xf9\x7b\xee\xe2\x5c\xcb\xb9\x94\x73\x25\xa7\x7a\xef\xc6\x42\x52\x8e\x33\x33\x5f\x2a\x35\x13\x0b\x04\x7a\xef\xa7\x9f\xad\x9f\x65\x0a\xc0\x50\x0c\x7e\x27\x0c\xcf\x58\x05\xfa\xab\xa9\xec\x19\x2b\x2b\x4f\x0d\xbf\x39\xcb\xc5\x56\xec\xd2\xa1\xe4\x4d\xb5\x92\x6a\x2d\x64\xd4\x12\xc2\x76\x53\x3d\xc4\xea\x19\x40\xbd\x13\x86\xde\x62\xb5\xba\x06\xac\xbe\xd8\x99\x75\x2d\xb0\xc2\x60\x08\x77\x7a\x3b\x61\x78\xc2\x6a\x51\x1c\xdc\x54\xf4\x44\x95\xfb\xa4\xcb\xe5\xd3\x5a\xb9\x4f\xaa\xdc\xa9\x2e\x37\x8d\x6a\xe5\x4e\x55\xb9\x63\x5d\x2e\xb9\xa8\x95\x3b\x56\xe5\x3e\x1b\xe3\x4b\x6a\xe5\x3e\x03\xd0\x7e\xbf\xd8\x18\x2c\xff\x89\xbc\x4a\xfc\x6a\x5e\x09\x12\xd2\x40\xbe\x14\xcf\x6b\x24\xbb\xa6\x64\xcc\xb2\x15\x6b\x89\xce\xb2\x21\xd4\x95\x4d\xe9\x28\x8c\xb4\xb6\xa4\xf2\x67\x39\x25\x34\xa1\x99\x85\xfa\xe3\x4f\x7e\x09\x6d\x68\x16\xb6\x5e\x9c\x6e\xd6\x6d\xc0\x9a\x8b\xef\x66\xf8\x0a\x67\x39\x6e\xab\xa6\xbe\x57\xab\x67\xe4\xba\xbd\xae\xf9\xb1\x84\xea\x0c\x89\x34\x65\xbc\x38\x5f\x19\x95\xb9\x4c\x15\x62\x7f\xed\x96\xf5\x22\x9a\xad\x56\x8e\x9a\x30\x19\x0c\x96\x8d\xb6\x88\xd5\xd2\x26\x7d\xb0\x6a\x18\x1f\x5a\x6a\xe1\x34\x6a\xaa\x43\x5f\xd7\x6b\x9c\xa3\x1c\x27\x71\x8a\x2b\x35\xd4\x6b\x55\xc3\x38\xba\xf6\x4c\xaa\xb6\x96\x4d\x35\xea\xb3\x51\xb5\x9a\xe6\x53\xad\x69\xcc\xc8\xae\x67\xcd\xc9\xa8\x45\x11\x32\xde\x3d\xc7\xc5\x35\xc6\x69\xad\xaa\xfd\xb5\xbd\x3e\x62\xfa\xf0\x96\xea\xe2\x63\x09\x9b\x90\x9b\x5a\xa1\x16\x7b\xd4\xe6\x5a\xc6\x5c\xab\xf5\xcc\xd9\x36\xd4\xac\xce\xb7\x5a\xbd\x36\xe3\xd6\x36\xd4\x9c\x9b\x9b\x58\x3b\x6b\x5e\x04\x5f\xe1\x34\x59\xb4\xb6\x20\x3e\x97\x25\x6c\xca\x6d\xb2\x54\x3a\x2d\x4c\x28\x5f\x79\x8c\x46\x13\x1b\xf9\xf1\xb8\x83\x9a\x59\x2f\xc0\x01\x25\xc4\x99\xeb\x7a\xa9\xa6\xc4\x3a\xfb\x2a\x23\xef\xbb\xda\xfd\xb2\x00\xc3\x50\x45\xe0\xd4\xe5\x52\xc2\x12\x30\x01\x58\xb3\x51\xbb\xdb\xb1\x0a\x01\xe8\xb0\x4c\xac\x6e\xe7\xa7\xce\x1d\xc6\x82\x68\x11\x42\x34\x52\xb2\xa0\x83\x4c\x26\xa1\x52\x8e\x69\x40\x77\x89\x17\x79\x37\xc3\xd1\x7c\x84\x5b\x4c\x7f\x4c\x5d\x9e\x66\xa1\x97\xe5\x41\xd1\xb4\x20\x3a\x29\x3c\x23\x46\xa6\xdb\xa9\x31\x67\x0c\x0e\xe2\xb1\xb7\x43\xd7\x09\x03\x95\xa3\x87\xfd\x12\xeb\xae\x05\x01\x23\x9e\x03\xfe\x67\x6f\xef\x1f\x3d\xfc\x08\xfc\xb3\x87\x1f\xb0\x40\x8c\x07\x64\x50\x0c\x43\x86\xf3\x1e\xa3\x3c\xce\x83\x54\xc7\x48\x35\x0c\xe8\xd2\x92\x27\xe5\xa9\x96\x16\x82\x4f\x53\x15\x61\x41\x7c\xd0\x58\xcf\x37\x23\xb1\xd6\xcc\xf4\x00\x60\x4c\x5c\x18\x86\x59\x5f\x12\xc5\x02\x12\x10\x14\x83\xd4\x5a\xfc\xf9\xcc\xcb\xc0\x30\x24\xa5\x97\xc2\x02\x66\x74\x87\x00\x5c\x32\xcd\x40\x25\x5a\x97\x53\x02\x2f\x23\x00\x22\x52\x4b\x5c\x22\x34\x45\x24\x74\x98\x76\xc1\x81\x09\xf9\x73\x42\x53\xc5\x44\x88\x3a\x02\xba\x2a\xb1\x95\x52\x92\x4d\x51\x22\xc3\x2b\xe5\xf1\x57\x5c\x91\x77\xa6\x38\x8a\xe7\x53\x29\xf2\xe4\x45\x3c\xba\x5c\x3c\x97\xc1\x95\xaa\x52\xcf\xad\xa2\x5f\x41\x47\x0c\x89\xf2\xd4\x3c\x37\x9d\xd9\x3c\xe5\x9f\xa7\xeb\x33\x66\xc8\x03\x33\x67\x69\xca\x83\x08\x9a\xf5\x83\x19\x0b\xb8\x37\x87\x11\x9c\xb5\xf3\x51\x88\xd4\x92\x57\x4c\xeb\xaa\x10\x23\x1c\x17\x73\xbd\x48\xe8\xd2\x12\x1e\x7e\x41\x6e\x20\x0f\x9a\xba\xce\x36\x72\xe6\xba\xc4\x5a\x41\x50\xc2\x89\xe5\xe9\x90\xaf\x65\xd5\xaa\x01\x7c\x44\xc7\x96\x65\x2b\xe7\xae\x64\xe6\x9c\x40\x65\xff\x93\x5f\x4e\x39\x66\x63\x56\xac\x1d\x61\x4c\xe0\x68\x5f\x25\x3a\x75\xc3\xda\x80\x5d\x49\x41\xb5\xce\x85\x42\x97\x7b\x40\x9a\x82\xd8\x59\x9f\x95\x06\xb0\x66\x2c\x0f\x45\x67\xa7\x71\x84\x29\x13\x58\x14\x64\xca\xac\x7b\xad\x3d\x5b\x56\xc7\x9f\xe3\x19\xca\x50\x81\xab\xb9\x81\xce\xd8\xdc\x4b\xe0\x25\x04\xc0\x79\xdb\xf9\x1a\x91\xd0\xbe\x5f\x73\x4a\x38\xa6\x67\x8e\x3d\xc3\xd9\x9f\x74\xe6\xc6\xe4\x7b\xc6\x82\x9b\xd7\x41\x74\x44\xd6\xc2\xe8\xe6\x90\x71\x50\x81\xf1\x58\x82\x71\x46\xae\x2f\x32\x32\xa7\x4c\x6a\x6e\x47\x6d\x24\xad\x21\xa4\x18\x04\x32\x1e\x59\x54\x2d\xab\x5b\xc4\xac\xa3\x4b\xe0\xcd\x88\x08\x56\x48\xb6\xc9\xce\xa4\x75\x38\x15\xf5\x8d\xcc\x33\x7c\x2b\xf5\x8d\xc6\x7d\x0c\x85\x8d\xc8\x0c\xf3\xc0\x70\x14\xdb\xb1\x3c\x4c\x24\x2b\x9e\x18\xea\x1a\x1d\x68\xe9\xaa\x41\x03\xb1\x95\xb6\xc1\x40\x6d\xb4\x3f\x03\xc5\x99\x7d\xd9\x81\x96\x2e\xec\x4c\x02\x88\x00\xb8\xb0\x5f\xcd\x09\x80\xe7\xe1\xc2\x75\x9d\x09\x46\x11\xa5\x55\x0b\x39\xd4\x83\x51\xdf\x43\xe1\x08\x92\xf0\xbc\x2f\x84\x1a\x11\x62\x2e\x60\x21\xa6\x1d\x10\x20\xfa\xa9\x98\x38\x81\x53\x44\x3c\xc6\xd5\x75\x38\x3e\xd8\xb9\x66\xee\x6b\xde\x75\x48\xab\x39\x7c\x9b\x6e\x42\x16\x41\xce\x75\x2f\xe4\xda\xf5\xd5\x53\x20\x89\x06\x80\xc7\xe1\x4c\x16\xa3\xd3\xeb\xf3\x3f\x81\x24\x1a\x00\x5e\x86\xd3\xd5\x6a\xe1\xba\x6a\x98\xf0\x94\xdd\xd6\x49\x58\x9f\xb8\xae\x77\x1a\x3a\x28\x1f\x39\x5c\x3b\x86\xf2\x91\x50\xce\x06\x4e\x84\xd5\x8f\xba\x9a\x17\x19\x28\xb9\x0d\xf3\x0a\x9d\x4b\x3e\xb8\x1c\xc2\x39\x54\xc0\x63\x6b\x31\x5a\x02\xd8\xc8\x49\x72\x25\x5a\x3e\x50\x3b\x5a\x2b\x7e\xc3\x8a\x8b\x29\x2b\xe9\x9f\x6d\x77\xad\x2c\x93\xfd\xd5\xe6\x5d\xba\x2e\x5f\x3b\x03\x05\xba\x6e\x6e\xd3\x08\xe1\xc9\x47\xe1\xc6\x09\x4e\xf9\xc1\x25\x90\x41\x55\x70\x5d\xc2\x2b\x2b\x3e\xe6\x16\xf4\x63\x03\xae\xaf\x9c\x6d\x06\x3a\x55\x87\x28\xb9\x90\x6d\x16\xee\xff\x93\x76\x3a\x1d\xcd\xef\xea\x88\x3c\x45\x5b\x44\x1e\x9d\x13\xb9\xa8\xa5\x25\xea\x01\xd8\x7d\xf4\xc8\x0c\xd7\xb3\xa9\xf4\x83\x47\x00\xd4\x09\x90\x11\xd5\x0e\x40\xba\x05\x32\x9d\x72\x85\x86\x89\x10\x23\x90\x0a\xae\xe2\xb6\xc9\x5a\xa8\xd9\xcd\x19\x79\x87\xa7\xde\xde\x7d\xc0\x8c\xf4\x3e\x34\x94\xd1\xef\x5f\x31\xb8\x28\xe1\x39\x73\x38\x5b\xd7\x21\x25\x4d\xa4\xa0\x44\x70\x03\x69\xdd\x38\xb0\x1e\xd0\xd6\x83\x8d\x25\x7a\x7b\x94\xf0\xc6\x5f\xb1\x9d\x43\x3d\x70\xa4\x65\x78\x87\x3e\xf4\x64\x36\xf3\xa6\x88\xa1\x3a\xf2\x1f\x73\x87\x61\xef\x8e\x26\x78\x74\x79\x4e\x6e\x1c\x79\xdd\xb1\x77\x5f\x5b\x9d\xfb\x1d\x9e\xc6\x60\x7d\xb3\xcd\x69\xe0\x59\x2f\x9d\x9f\x3a\xff\x30\xa4\x24\x96\x1b\xa8\xd2\xb1\xec\xf7\xfe\x23\xb3\x5f\xfa\xbf\xfb\x9b\xfa\xf4\xed\x2e\xef\xeb\xc6\x5f\x93\x14\x1b\xdd\xb6\xb5\xc2\xb2\x4b\x31\x8c\xc2\xda\x5b\xd6\xbd\x05\xb9\xfc\xcf\xc3\x5c\x2c\xeb\x5e\xa0\xa2\x00\xef\xdf\xfc\x9e\xf1\xe4\x00\x6b\x95\x4f\xac\xea\x0b\x2e\x2a\x5b\x95\xa5\x5e\xbb\xca\x68\x69\xf7\x4d\xfe\xde\x11\x61\x7c\x44\x70\x1f\x11\x5d\x66\xaf\x96\x36\x4c\x43\xa5\xfe\x22\x2f\xa6\x9b\x78\xb4\x23\x8a\x40\x4a\xe0\x4d\x05\x03\x70\x61\xb2\x64\x0c\x11\x96\x70\x41\x59\x32\xf6\x0c\xcf\xff\x24\x96\x6c\xf1\x67\xb3\x64\x17\xdf\x8f\x25\x5b\x6c\x64\xc9\xae\x37\xb1\x64\x9c\xf4\xb7\x72\x65\xcf\xd9\xba\x03\xef\x5c\x6c\xca\xcd\x9f\xb4\xea\x4e\x91\x49\x56\x8d\xe7\xb2\x6f\x8a\x9c\x92\xe3\x04\x8f\x8a\xc6\xe4\x99\xb7\x94\x27\x79\xa2\x12\xe8\xc8\x16\x8d\xec\x4d\x06\x07\xb5\x45\xcc\xe5\xad\x64\xb9\x25\xa3\x21\xa4\x4b\xff\x48\xd4\x4d\xba\xfc\xa1\x1c\xcc\x24\xc7\x33\x84\x73\x2a\xf7\xf1\xf9\x47\x4c\x04\x14\xc3\x93\x01\x13\x0b\x16\x53\x2f\xd1\x9b\x4e\xa5\x14\x73\xbb\x8f\xc9\x16\x17\xd0\xc2\x65\x4b\xd1\xe6\x3a\x93\xde\xea\xd8\xac\xdc\xbc\x29\x2e\xe7\xb9\x79\xda\x72\xbe\xd4\x32\xe5\xb0\x82\x8c\x08\xa8\x7d\xec\xe8\xe7\xd6\x76\x34\x09\x6f\x0b\xd0\x05\x6b\x5d\xc9\x46\x45\x52\x1e\x50\x96\x50\xf5\xb3\x2c\x21\x1f\x38\x7d\x60\xb4\x5d\x93\xd3\x26\xb4\xf4\x8e\xae\x32\xf0\x6e\xc4\x01\xb8\x24\x7f\x9b\xf7\xfd\x35\xcd\xfb\x74\x87\xa7\xc4\xc8\x79\x80\xbb\x19\x46\xd1\x4f\xbe\xeb\xf2\xa7\x1f\x71\xb7\x20\x05\x4a\xfa\xfc\xe7\x3f\xc5\xcf\x40\x7c\x0d\xfd\xfe\x5e\x70\xaf\xe4\xc7\xf1\x88\x7c\x6f\x4b\x9f\x4b\xb2\xbd\xa5\xcf\x60\x78\x60\xc3\x47\xc5\xd6\x56\xd9\xc8\x1d\xa7\x17\x71\x8a\x73\x65\x83\x98\x85\xbe\xed\xa8\xd4\x58\x7c\x90\x0e\xbb\x47\x93\x79\x7a\x99\x1f\x64\x3f\x12\x69\xcf\x98\xdd\xbd\x2b\x4d\xf2\xc8\x20\x1b\x1e\x60\x6e\x60\xc7\x2c\xa8\x50\xf7\x67\xbc\xe8\xbe\x45\xc5\xe4\xae\x13\x38\x77\xf9\xcf\x37\x2c\x33\x0c\xc4\xac\xd1\x93\x27\xc1\xdd\x14\xd2\x85\x0c\x10\x6f\x5c\x7c\xdf\xb5\x0a\xf3\x15\x97\x25\x8e\xd3\xa8\xa1\x50\xa9\x42\xe4\xe2\x46\x43\x3e\xae\x87\x66\x5b\x0d\x33\xfa\xb7\x50\xf8\x3e\xfd\x31\xeb\xef\xf6\x82\xf4\xa7\xac\xdf\x0b\x70\xf7\x12\x2f\x7e\x2c\xe8\xbf\xc2\x8c\x8f\x3e\xfe\xc4\x5e\x80\x26\x9b\x35\xd4\x62\xb3\x26\x4d\xee\x9c\xa7\x71\x82\x73\x67\x7b\x63\xb7\x9c\x34\xbf\xbf\x6e\x79\x7f\xdc\xf2\xfe\x4a\xbc\x77\xd8\xb2\x35\x0c\x40\x15\xe0\x3b\xbc\xae\x84\x0a\xd8\x06\x1a\x56\x60\x22\x4a\xe1\xba\xd5\x5d\x0b\x45\x3d\x26\xdc\xc6\x8e\xad\x6d\xd9\xd4\xad\xe9\xd9\x5a\x4c\x1c\x21\xd6\x0a\x1a\xc8\xaa\xad\x19\x6d\xe0\x40\xdc\x95\x10\xd6\x5e\xae\xc9\x7c\x9c\xf3\x6c\x3d\xdf\xff\x87\x7d\xde\x9b\xed\xc7\x45\xee\xa7\x66\x4f\x2f\x0a\x71\x9f\xfe\x26\x1f\x7f\x55\xeb\xf0\xb7\xdf\x1d\xd9\x7f\x22\x7f\xd0\x94\xba\x66\xf1\x0c\xb3\x30\xfd\x31\x8c\x71\xf7\x15\xba\x39\x49\xaf\x50\x12\x47\x7d\xdc\x65\x3e\x98\x81\x0a\x99\x0a\xed\x89\xe4\xd7\x71\x31\x9a\xd0\xa7\x11\xca\x71\x27\xc6\xdd\x97\x04\x45\x6c\x9b\x70\x14\x88\xa1\xfa\x07\xe6\x47\x1c\x05\xf2\xe7\x87\x2c\x2e\x70\xa5\x70\x4f\x15\x3e\x4c\x12\x5a\xa0\xc0\xa9\xaa\xc0\x1c\x34\x2b\x15\xf6\x0e\xac\xaf\xba\x75\xee\x36\x54\x29\x7d\xef\xc0\xfe\x6c\x96\xa7\xb2\x6a\x63\xa5\xfb\x07\x0d\x65\x8c\x9a\x87\x49\x81\xb3\xc3\x79\x41\x4e\xd2\x51\xa5\xea\xfe\x81\x55\x08\x47\xa2\x98\x9e\xd2\x04\x8f\x2e\xf3\xf9\xb4\x52\xef\xc1\x41\xb5\xc0\xd4\xe8\x50\xbe\x3b\xbd\x8c\x67\x33\x73\x20\x29\x4a\x16\x5f\xab\x2b\xf4\xf0\xa0\xf2\xbd\x56\x41\xb6\x23\x2a\x3c\x3a\x90\x09\xf5\xe5\x0e\x96\xa5\x97\x6e\x88\x52\xc0\xb0\x24\xc3\x33\xdd\x71\x46\xa6\xde\x92\x13\x7d\xcb\x43\x88\x22\xc7\x12\x54\x30\x7f\x0a\x51\x2b\xee\x17\x66\xc6\x8c\x41\x80\x96\xed\xb9\xa0\x31\x4f\x48\x71\xd7\xe9\x38\x77\x33\xf6\xaf\x87\x7e\x24\x7d\xdc\x1d\xc7\x49\x82\xa3\x00\x77\xf1\x74\x46\x39\x7c\x46\x8a\xd7\x83\xed\xab\x38\xcf\xe3\xf4\x42\x4c\xd8\x99\xf2\x9f\x4e\x15\x72\xc5\xe7\xeb\x8c\x07\x28\x6c\x82\x55\x51\x64\x94\x10\xbb\x05\x01\x9d\xe2\x33\x0f\x22\x66\x15\x50\x60\x65\x15\xc1\x91\xd3\x02\x7d\xb2\x18\x7d\xd9\xa9\x17\xae\xc0\x9b\x28\x1d\x91\x38\xbd\xe8\x8c\x04\xfc\x38\xb7\x82\x32\xd1\x04\x62\x30\x63\x4f\x7f\x2b\xb8\x72\xc6\x71\x1a\xe7\x13\x73\x90\x75\x6c\xc1\x72\xb7\xd1\x31\x7a\x98\xbf\x07\xba\x74\x03\xbe\x90\x5b\xd1\x54\xbc\x01\x5b\xc8\x6d\x69\x2a\xde\x74\xf4\xf5\x3e\x35\xd6\x68\xc3\x18\xd6\xa6\xb4\x54\x6e\x47\x1a\x0e\xa2\x9f\x58\x2c\x8d\x4e\x9c\x8e\x1a\xa7\xd6\x88\x35\x1c\xb9\xaf\x8d\xfd\x35\xe1\x06\xbd\x99\x66\x15\xfb\xf4\x3b\xf3\xf4\x32\x25\xd7\xa9\xc3\x90\x40\xab\x7d\xfb\xbb\xf5\xea\x05\xe3\xc0\x4a\xfd\xea\x23\x19\x31\xe9\x51\x5b\x88\x3a\x33\xa5\xcb\x23\x3b\x80\x92\x48\x98\x26\x8e\xfa\xb2\x84\xec\xac\xd3\x87\x99\x8c\xff\xed\xb8\x77\xf8\x67\x67\xfb\x58\xe0\x8e\x7b\x87\x35\xd4\xaa\x6c\xb8\x93\x82\x96\xe8\xfe\xb0\xfb\x00\x94\x25\xe4\x04\x73\xcb\xce\x59\xe1\x6f\xeb\x5a\x57\xe5\x1d\x33\xab\xff\xb7\x42\x13\xf1\xe6\x6f\x56\xf2\xaf\xaa\x89\xe0\xa7\xed\xec\xbb\x33\x94\x6f\x6e\xc9\x50\xc2\x54\x82\xce\x25\x5e\xe4\xde\x46\x05\x42\x85\xea\xab\xfb\xc4\x41\x01\xf1\x5a\x55\x42\x31\x1c\x1a\xe9\x35\x37\x78\xde\xf9\xc3\xdd\x62\xe0\x0f\x5b\x64\xef\x06\x6f\xa1\x76\xf7\x37\x21\xe9\xfe\x5b\xa5\x71\x3e\x84\xce\xc9\x93\x75\xf2\xf6\x29\x63\xdf\xd7\x95\x10\x5a\x85\x35\xe2\xf8\x1f\x71\x82\x93\x02\x7a\x7a\x7b\xe1\x9c\x4a\xdf\xe9\x2d\x84\x6e\x02\x97\x5c\xbf\x73\x5f\x7a\x79\x65\x5d\x3e\xfd\xa6\x1d\xa7\xbd\x23\xf3\xf6\xab\x84\x99\x50\x4b\x09\x95\xd4\x06\x89\xfc\xf5\xdf\x68\xf4\xaf\x2a\x91\x7f\xfe\xee\x08\xf4\x75\x03\x02\x55\xb0\xff\x24\x8e\x5e\x91\x79\x5a\x98\xf0\x64\xa0\x4c\x92\x1e\x4d\x50\x7a\x81\xb9\xeb\xe3\x99\x89\x07\xdb\xc2\x20\x34\x76\xf3\x21\x4e\x92\xf7\xe9\xf4\x1b\x7b\xe2\x17\x67\x95\xb6\xff\x85\xbe\xa2\x84\x61\x0b\xe9\x38\xb2\xe3\xcb\x08\xca\x55\x9b\x71\xd8\xe8\x1d\x60\xc9\x87\xcc\x47\xf3\x59\x16\x47\xcd\xbd\x30\x7f\x92\x26\xe4\xff\x0c\x43\xe3\x62\xf9\x5e\xc5\x99\x59\x2d\x3f\x58\xd7\xaa\x3d\x10\x5a\xe7\x09\x29\x0a\x1c\xc9\x75\x2e\xd7\xe0\xb5\x47\x12\xaf\xb5\xd2\x53\x85\xee\xea\x63\x38\x23\xc2\xe5\x58\x16\x6e\x6d\xa5\x21\x4e\xc6\xd1\x2d\x2a\xb7\x0a\x01\xaf\xc8\x37\x3b\xb9\xaa\x1d\xab\xc4\x7e\xc4\x86\xb9\x68\x09\x1b\x96\x53\x8a\x13\xf7\x1e\xf8\x9c\x09\xfe\x2c\x98\xe0\x13\xf2\xe7\x67\x59\x94\x06\x10\x15\x83\xe8\x71\x7c\x43\x39\xff\x1c\x8e\x6e\x93\x44\x51\x36\xb6\x65\x22\xe4\xfc\xf7\x39\xca\x30\x03\x38\x23\xb2\xa3\xc8\x08\xab\x23\xbd\xdf\x87\x6b\x13\xfd\xa9\x4e\x6b\x66\x66\x73\x96\x82\x6d\x53\x2a\x40\x31\xd7\x30\x0c\xe7\xae\xeb\x4c\xe7\xf1\x2e\x7f\xa1\x22\x52\x8e\xac\xb0\xad\x64\x5d\x1e\xb6\xd6\xac\x6b\xfa\xe7\x45\x86\x17\x83\x9e\xef\x0f\x83\xca\xbb\x1f\x7c\x7f\x78\xd0\x6c\xe2\xbc\x36\xda\x77\xc5\xf0\xb9\xd1\xc3\x4c\xd8\xb1\xe0\x2e\x7f\xa0\xd4\xe0\x31\xca\x2a\x09\xc6\xe5\x42\x3e\xa5\xd3\x37\x4d\x63\xf8\x7a\x98\x96\x31\xc2\xf7\x80\xa7\xe8\xf1\xe1\xe6\xa8\xf3\x2c\x9c\xb9\x78\x7b\x28\xde\x35\xe7\x45\x6b\xed\x45\x37\x70\xca\x4c\x75\x36\x18\xef\xb4\x57\x46\x45\x3c\xb2\x2b\xd3\x37\x8e\x2e\xf2\x4e\x44\x72\x6f\xcc\x61\x27\x52\xcc\x3d\x11\x2a\x86\x9a\xa8\x5b\x08\x93\x70\x63\x77\x71\x71\x44\xd2\x22\x43\x39\x8b\xf5\xea\x15\x60\x53\x1e\xbb\x16\xf9\x7c\xd4\xf2\x71\x64\xb4\xbe\x39\x03\x5e\xab\xa5\xc1\xa8\xf5\x73\x43\x07\x27\xdc\xc0\xa2\x66\x70\x21\x3e\x9f\xe9\x74\x6c\x1b\x12\xe9\xc1\x6a\x03\xb6\x99\xc2\x21\x83\x54\x16\xf4\x57\x60\xc5\x97\xe4\xcf\xce\x5e\xae\xa2\xe6\x3e\x9b\x17\x05\xce\xf2\x46\x7b\x9d\xe6\x24\xb4\x19\xbe\x98\x27\x28\xbb\x45\xfa\xd9\x5a\x8a\x6c\xd1\xa9\x65\x14\xfd\x87\x12\xa4\x93\x41\x44\xf1\xdc\x0e\x33\xc0\xb9\xe0\xad\x2b\xe4\x66\x59\xd8\x7c\xdd\x8a\xfa\x35\x64\x3c\xd8\x9c\x4d\xb9\x84\xa2\x67\x23\x46\xba\x69\x78\x68\x52\x49\xdb\x06\xd1\xa6\x9f\xb8\xea\x84\xe4\xe4\x53\x07\xc0\x96\xb6\xee\xb5\xb6\x75\x0f\x94\x74\x0d\xd8\x6e\x05\xb8\x3b\x8d\x6f\xe2\x34\xef\x16\x84\x24\xe7\x28\x83\x11\x4e\x59\x1e\x83\x38\x15\x16\xa6\xf7\x1f\x55\xcd\x67\x78\x49\x16\xb8\x59\x00\xe6\x93\x2d\xc3\x37\xa4\xa3\x09\xc9\x78\xee\x3f\x3b\x7c\xc3\x52\x1a\x26\x05\x4e\x41\x66\x0e\x9c\x90\x2c\xfe\x4a\xd9\xc9\x44\xc9\x7f\x22\xb0\xc3\x39\x8a\x2e\xb0\x8c\x85\x90\x98\xd1\xa0\x37\xf9\x03\x50\x86\xa0\x12\xca\x41\x84\xa8\x51\xe1\x1c\xe4\xe9\x98\xe9\x62\xe3\x3e\xcf\x1f\x1e\xf0\xa0\x0e\x71\x2a\xd2\x56\x30\x2f\x81\x29\xba\x81\x57\xba\xec\xb4\xff\xc3\x0f\xc1\x14\x5e\x84\x69\x97\x5c\xe1\x2c\x41\x33\xb8\xd0\x5f\x2f\xe8\x19\x19\x15\x28\xbd\x48\xb0\x13\x5c\xb0\xd8\x0e\xf9\x84\x5c\x7f\xc2\x19\x51\x51\x1d\x76\xc2\xf0\xdc\x75\x79\x24\x07\x79\xce\x8e\x75\x1b\x37\x7d\x8a\xb3\x29\x6a\x8a\x9c\xe0\x06\x5e\x56\xbc\x13\x8c\xf5\x75\xa0\x63\x2e\xd5\x36\x49\xa7\x24\x2f\x63\x9e\x4c\x35\x5f\x9e\x4d\xca\x81\x8e\x98\x99\x03\x1d\x39\x78\xdb\x89\xe1\x54\xe5\xa4\x9f\xb8\xae\xc7\x10\x8c\xeb\xee\x5c\xaf\x56\xfc\x65\xec\xba\x4e\x44\x98\x0d\xfe\x31\x60\xc6\xff\x3b\x3e\x07\xa2\xa3\xd0\x71\x0e\xd4\x5d\x47\x21\x2c\xe9\xbd\xa3\x30\xfe\xe9\xaa\xef\x98\x09\x9a\xef\x3a\x20\x88\xeb\x6c\xf0\x6c\x2d\x4a\x90\xf1\x17\xd4\xf9\xbf\x04\xb0\x21\x47\x30\x4f\x16\xdf\xdc\x00\x5b\x50\x98\x0f\xf4\x60\x50\x57\x43\x2a\xa8\xb1\x59\xa8\x2b\xc1\x1a\x40\xa7\x74\xc0\x90\xd6\xb5\x36\x69\x5d\x95\xa6\xf6\x8c\xde\xea\x9f\x17\xcc\xb7\x40\x02\xf5\x0e\xcb\x5a\x9d\xb7\xf2\x80\x11\x2d\x7d\xca\x02\x4a\x28\x98\x66\xeb\x1e\x72\x0f\x86\x6e\x44\x28\xb9\x3e\xb2\x82\x8b\xff\x61\x2c\x29\x2e\x09\x38\xb2\x6c\xb1\x46\xb4\x79\x33\xb6\xe8\x9b\x38\x42\x66\xdc\x58\x8d\x43\xb0\x36\x89\xcf\x36\xa9\x7d\x1a\x93\x9f\xb6\xf0\x99\x63\x92\x16\x4f\xd1\x34\x4e\x16\x76\xbc\x5e\xfd\xde\xf4\x15\xc0\xeb\x7c\x05\x5a\x22\xff\x1a\xb6\xfb\x50\x45\x47\xd8\xf3\x4d\x6f\x80\x9e\x69\xf5\xce\xac\xec\xc5\x35\xcd\x9e\x6f\x5f\xc1\xf4\x94\x81\xb7\x95\x3e\x14\x1b\x09\xf2\x72\xa9\x95\xd1\x49\x3a\x1d\xb8\xc4\x28\xe7\xf2\x9f\x59\x90\xbf\xa4\x7f\xf0\x49\xfa\x66\x5e\xc0\x48\xe6\x39\xb3\xcb\xc9\xd7\x95\xec\x8e\xe5\x5f\x81\x2b\xe4\x31\x35\xb7\xba\x2f\xaa\x35\xcc\x3f\xd9\x8d\x46\xf4\x28\x59\x7b\x76\x5f\xdf\xb9\xa9\xed\xd7\x6e\x0e\x7e\x09\x4d\xcc\x72\x46\x66\x8c\xee\xbf\x93\x14\x27\x58\x72\x09\x41\x0a\x2e\x46\xf2\xe6\x7c\x84\x12\xec\xf5\x40\x47\xe5\xa5\xf7\xf6\xfd\xff\x86\x9d\xdd\x7d\xff\xbf\x41\x43\xd2\x5e\xe6\xce\xce\x92\x47\xb9\x77\x34\x7d\xb0\xf2\x41\xf3\x26\xfd\x96\x26\xcb\xb5\x63\x65\x7c\xc9\x7f\xee\x68\xb9\x6e\xa3\xba\xb8\x2a\x17\xf2\x2d\x46\xbc\x6e\xc0\x22\x3b\xd7\xad\x87\xbc\xdd\x88\xf9\x12\xff\x27\x8f\xf9\x8c\xcc\x28\x43\x5b\x03\x5f\xe1\x9d\xb2\x7e\xa4\xbb\x6b\x01\xe2\x5b\xc0\x61\x77\x2d\xf4\x1a\x23\x35\x81\xf7\x3f\x6f\xac\x1c\x12\x2a\x0b\xab\xc0\xe0\x16\xe3\x6d\x1f\xee\x37\x00\xc1\xee\x06\xc8\xad\x2d\xef\x7f\xf0\x88\x25\x2e\x3b\x8a\xb3\x91\x84\x5a\xa7\x77\xdf\x48\x0b\x4d\x9f\xff\x03\x91\x2f\x1d\xb0\x06\xde\xff\xe8\x21\x1b\xf8\x4c\x2e\xf3\xb9\xf4\x40\xfd\x86\x61\xff\x1b\xd0\xb0\x5e\xec\xff\x13\x06\x2e\x30\x5c\x1d\xa4\x45\xce\xf2\xcd\xc3\xfd\x77\x20\xe4\x26\x80\xfe\xcf\x1c\xb0\xc6\x72\x8d\xe0\x7c\xcb\x41\xff\xcb\x51\x73\x0b\x30\xff\xe7\x0c\x5b\xd5\x0b\x96\xff\x06\x59\xc7\xce\x57\x5f\x4d\xf0\xf6\x98\x4a\xb7\x2c\xbb\x96\x50\xa5\x3d\x26\x61\xea\xed\xdf\xbf\xb7\x07\xe0\x97\xbf\x4d\x18\xfe\xda\x96\x60\x1f\xbe\xbb\x21\xc3\x97\xad\x2c\xc1\x36\x1b\x83\x37\xa7\x80\xb0\xfd\x4b\x45\x2c\xe5\x33\x94\x5f\x76\xe2\x74\x4c\x1c\xd8\x94\x24\x22\xbf\xcc\x9b\x72\x30\x11\xb8\x34\xd5\x93\x41\x25\xce\xfb\x2f\x73\x3c\xc7\xdd\xdf\xd9\xbf\x56\x90\x71\x75\x89\xdb\x90\x52\x8a\xe8\x64\x12\x2d\x46\x41\x77\xe8\xe1\xba\xf7\xf0\xa1\x0f\xe0\x7b\xfa\xf8\xe0\xc1\xfe\x1e\x80\xbf\xfe\x7d\xce\xfe\xda\xe7\xec\xf9\x77\x3f\x67\xbf\xfe\x91\x73\xd6\x7e\x98\x8c\x53\x30\x43\xf3\x1c\x47\x7d\xe7\x1d\xce\xe7\x53\xec\x04\xce\x5b\xfa\xc2\x81\x56\x7a\x36\x69\x17\x74\x46\x2e\x2e\x12\xcc\x4a\x44\x50\x66\xa9\x24\xf3\xd1\xe4\x5d\x3c\x9b\x25\x98\x9b\xcb\xd4\xda\xae\x8e\xeb\xbd\x3a\x40\xb5\x8c\x33\x77\xf4\xd9\x6a\x3e\x59\xbf\xb3\xe3\xb4\xd7\xf3\x01\xfc\xf9\xef\xe3\xf4\x57\xb5\xbc\xfb\xc5\x3c\x48\x50\x44\x96\x94\x27\x08\x5f\x7b\xe9\x6a\xe5\xa5\xe1\xdb\x8c\x4c\xe3\x1c\x03\xf3\x92\x80\x40\x64\x1c\xbc\x98\x1e\xc3\x22\x5b\x2c\x73\x2f\xeb\xa6\xf8\xa6\xf0\x30\x00\xe5\x08\x09\xcf\x1e\xe4\x61\x50\x96\xaa\x74\x62\x96\x66\x2b\xb9\xb6\x78\xae\x8c\x52\x0e\x70\x37\x22\x29\xee\x13\x0f\xf3\x94\xd3\x20\xf0\x8a\x50\x3c\xc3\xa2\x63\x40\x56\xda\xa7\x44\xeb\xba\x93\xda\x17\x1b\xd8\x2b\x98\x99\x69\xb7\x98\xe0\xd4\x8b\x61\x02\xca\xdc\xf3\xb2\x50\x26\x5e\xc1\xb0\x58\xad\x06\x43\x00\xf8\x2c\xd8\x5d\x49\x09\x9f\xd9\xcb\x24\xec\x71\x61\x06\x79\x64\x33\x91\x3e\xc3\x87\x39\xa5\x7c\xc6\x59\x89\xc7\x5e\xcf\x25\x03\x7f\x28\xe0\x85\x18\x96\xbb\xf4\xb9\x84\x45\xb6\xc8\x83\xc1\x10\x92\x19\xfd\xa3\xc0\x11\x85\x4b\xda\x7f\x90\x78\x3e\x80\xac\x6e\x90\x78\x3d\x00\xf9\xe7\x20\x61\xf7\xc7\x1a\x44\x43\x09\xa2\xa7\x8b\xe9\x39\x49\x5c\xd7\x43\x03\xfe\xd8\x8d\x0b\x9c\xa1\x82\x64\xc3\x26\x3c\x46\x11\x20\x80\xe8\xc0\xd8\x19\x54\x0f\x38\x9a\xd4\x5f\x21\x36\xb7\x96\x63\xf0\x0c\xa7\xbc\x4f\x0a\xee\x28\xc9\x30\x8a\x16\x1d\x7c\x83\x47\xf3\x82\x72\xda\x14\xce\x49\xe6\x1d\xc4\x07\x80\xc2\x00\x6d\x27\xec\xc1\xcc\x75\x3d\x12\xee\xb9\x68\xe0\x0f\xfb\x59\x57\x4c\x54\xfc\x62\xdd\xac\x56\x9e\x47\x42\xf9\x09\xb8\x2e\xe1\x87\x3b\x03\xd0\x07\x01\x07\x3b\xe0\xba\x3b\x1e\x09\xe5\x17\x88\x06\x3d\xba\x97\x14\x68\x80\x5c\xf7\x03\xe1\x71\xc6\xbc\xe7\xe9\x52\x85\x03\xde\x2d\x24\x1c\x90\x86\x00\xd2\x9f\xc2\x21\xcd\xe7\x8e\x54\xbd\x80\x84\xe8\x80\x5d\xd8\x73\x37\x9e\xfb\xd2\x21\x2f\xee\xb2\xed\xbf\x7b\x57\x3a\x21\xd3\x4e\x21\xed\x32\xd8\xe9\x95\xbc\xf0\x7e\xa0\x4b\x65\x2c\xbf\x1b\x44\xe1\xc0\x1f\x52\x7a\x56\xc4\xe9\x1c\xf3\x62\x0f\x03\x14\xc6\x5d\x86\xd1\xc9\xcc\x03\x30\xee\x52\xf8\xe0\x3f\x74\x51\xe9\x12\x14\x8f\xbd\x1d\xba\x24\x1e\x09\x79\x41\x20\x93\x3f\xf8\xae\x4b\x06\xd2\xd5\x7f\xb7\x37\x04\xab\xd5\x83\x9d\x30\xa4\xb3\x72\xdd\x3d\xf1\x04\xc0\x32\x0e\x7d\xd5\x6c\x19\x8f\xbd\x7b\xa1\x2c\xe4\xed\x90\xd5\x8a\x8e\xf3\x27\xc2\x7e\xd3\xc7\x1f\xc9\xe0\x1e\xab\xc5\xa7\xc2\xa6\xc1\x57\x84\xd6\x7d\xa0\xea\x8a\xef\x3f\x52\x08\xd7\xa5\xe9\x2f\xa8\xd6\x90\xd6\x20\x66\xd1\x3d\xab\xe8\xde\x10\x8a\x75\x98\xe7\x13\x0f\x01\x51\x89\x7e\xa0\x95\x36\xac\x50\x89\xc2\x82\x43\x00\x86\xb1\x89\x57\xc2\xc1\x03\x88\x87\x30\x0b\xfd\x72\x1c\xa7\x28\x49\x16\xcb\x34\x24\xa1\x4f\x47\xb3\xcf\x60\x40\x40\x34\xd2\x07\x55\x6d\xaa\x3f\xec\xd3\xd7\x01\xbf\xbb\x17\x1b\xec\x97\xa5\x37\x40\x30\x19\x52\x39\x10\xfe\x46\x42\x66\xab\xf5\x0e\x8f\x33\x9c\x4f\x4e\xd2\x02\x67\x57\x28\x71\x04\xdb\xf2\xb1\x95\x6d\x49\x75\xfc\x62\x9d\x82\x37\xad\xa4\xe0\xcd\xcc\xd4\xa8\xaf\x70\x3a\xb7\x8e\xb4\x91\x35\x77\x8a\xd3\xb9\x95\x33\x57\xd6\x14\xe3\xb2\xeb\x55\x1a\xf5\x00\xa4\x67\x8c\x15\xf4\x8c\xba\x9c\x25\x59\xd3\x6d\xd3\x05\xb2\x39\x12\xdc\xd5\xbf\x4a\x86\x56\x55\xdf\xcc\x0a\x5a\xae\x56\xd8\x10\x87\x60\xe3\x80\x47\x56\x13\x8c\x7e\xf0\x69\xa8\x38\xa2\xef\xf0\x98\x95\x14\xd9\x83\xe3\x5c\x2c\x46\x9c\x5e\x04\x3b\x3d\x68\xad\x19\x6c\xd8\xc4\xc0\x2f\x61\x26\xd9\xc5\x9f\x1b\xd9\xc5\xfa\xe2\x8a\xb4\x3f\x84\x6f\xa8\x80\x1c\xf1\xc7\x6b\xc8\x51\x26\x0a\x7a\x4d\x0e\xb2\xfc\x70\x28\xac\x64\xe0\x70\x63\xeb\xed\x69\xf9\x25\x80\x83\xfb\xd0\x62\x2d\xdf\xc9\xad\x1d\x1e\x08\xc4\xa6\xc3\x6f\x50\xce\x10\xc0\xb5\x4d\xf6\x68\x93\x7b\xc3\xb2\x14\xa4\xd1\x32\x7d\x6f\xdf\x47\x6e\x53\xca\xa0\xb9\xd2\x7c\xd3\x52\xe3\x12\xc0\x84\x8c\x50\x72\x5a\x90\x0c\x5d\xd0\x91\x15\x27\x05\x9e\x7a\xbf\x11\xe8\x38\x77\x31\x80\xa3\x04\xa3\x4c\x6d\x37\x6b\xd2\x68\xe8\x2c\x9e\xe2\x4c\x4c\xa4\xfa\x3a\xc4\x3f\xf9\x7d\x91\xc4\x8b\x36\x2b\xdb\xf0\x9a\xf8\x7c\x7d\x0e\x00\xec\xe1\x7b\xff\xc0\x40\x1c\xff\x72\x7b\xd7\x82\xad\x81\x80\x71\xd6\x07\xad\xa0\x50\x28\x50\x28\x1a\x41\x41\x6e\x74\xd6\xb6\xc1\x85\xdc\x60\x1c\xfa\x2b\x6b\x79\x2f\xd4\xf2\x8a\x45\xab\x1d\xa7\xf6\x3d\xdf\xe0\xee\xb0\xcd\x46\x95\x7f\x8a\x7a\x23\xc3\xe3\x40\x2e\x88\xd4\x6d\x88\x6e\x6b\x96\x9a\xb0\x21\x49\xb6\x46\x78\x75\xd5\xc4\xef\xa4\x3d\xdb\xf5\xbb\x14\x2e\xb9\x62\xf5\x38\x51\x03\xe8\x8e\xe6\x59\x86\xd3\x02\x56\xf3\x60\x6b\xbc\xd3\x9a\x05\xbb\x79\x08\xa7\x69\xf3\xd4\x5f\xa7\x2c\xe4\x27\x95\x18\x23\xb3\x23\xf3\x18\x37\x4d\x57\x7c\x85\x22\xec\x26\x13\x31\xe5\x7a\x75\x52\x72\xdd\xe0\xd3\x46\x44\xba\x52\xe7\x70\x5e\x90\x8e\x80\xbb\x86\x72\xaf\x9b\xb3\x90\xdb\x68\xdf\xdb\x03\x3a\xf8\xd7\x9e\x4c\x03\xc8\xc7\xde\x80\x23\x4a\xe8\xec\x75\xb8\x01\x47\xfe\xcd\x5d\xde\xf3\x7d\xa3\xd3\x7b\xbe\xbf\x4d\xb7\xfb\x9d\x69\x9c\xce\x0b\xfc\xed\xdd\x9a\x9d\x6e\xd5\xe5\x9b\xf1\xd8\x69\x57\x82\xbd\xd8\xd2\x8a\x58\xda\x55\x22\xc3\xae\x32\xb6\xec\x2a\x13\x65\x57\x99\x6b\x13\xc5\xc4\xb0\xab\x4c\xb8\x21\xa6\xb2\xab\x1c\xe9\x62\xf3\xbe\x73\x3e\x2f\x0a\x92\x3a\xc1\x9c\x85\x68\x96\x40\x08\xc7\xda\x14\x32\x72\xdd\x88\x45\x6a\x16\x1f\x8f\xa5\x67\x04\x9c\xe8\x42\x33\xd7\x9d\x31\x6b\x4c\x51\xe8\x29\x19\xcd\x73\xae\xf8\x50\xc6\x99\x3c\x2f\x12\x37\xcd\xc4\x69\x74\x32\x22\x29\xcb\xb3\x35\xa6\x65\x7f\xe5\xb7\x03\x47\x6a\x5e\xe7\xf4\xcb\x3c\x49\x78\x62\xa5\x26\xd3\x4c\x16\x39\xda\xb6\xcb\x94\x71\xf2\x79\xba\x2d\x96\x89\x84\x75\x73\x1a\xa6\xcc\x11\x02\x1e\xe9\xe2\xa7\x7a\xf2\xa7\xf0\x93\x61\xea\xf9\x56\x97\xf9\xd4\x77\x0a\x7c\x53\x38\xc1\x27\xf8\xae\x62\x4f\xfd\x2d\x86\x9c\x72\x79\xf5\xa3\x5a\x4c\xfd\xca\x58\x3a\x07\x3a\x62\xa1\x1c\xe8\x34\x2e\x13\x7d\x2f\x17\xc9\x8c\xe0\x2f\x26\xee\x40\x87\x4e\xdb\x36\x0e\x7d\x13\x5e\xd6\xd3\x12\xaf\xb1\xb9\x44\xc6\x42\xa2\x81\x13\x8f\x48\x7a\xda\x1a\x57\x19\x30\x9b\xce\xb3\xf0\xe2\x96\x5d\x48\x80\xd8\xa6\x83\x8b\x56\x83\xf4\x2f\x78\xad\xf9\x29\x12\x81\x23\x07\x6f\x87\x30\xd6\xa1\xa8\x99\xcf\x11\xea\x5a\x8e\x05\xa6\x09\x67\x4e\x65\x29\x6d\x6f\xfa\xb6\x6e\xf5\x99\xd7\xa3\x4f\x0f\xac\x2a\xd0\x61\x33\x02\xcd\xb1\xa8\xd1\xba\x48\xd5\x43\x38\x71\x5d\x54\x3f\x7d\x63\xe3\x6d\x04\xaf\xe9\x2f\x05\x0a\xc0\xb8\x06\x18\x41\x45\x5a\xc6\x70\xac\x81\x2b\xd8\xb9\x82\x8d\x30\x65\xae\x97\x59\x00\x2e\x64\x90\x54\x0a\x53\xc1\x51\x09\xdf\x81\x2d\x6c\x77\x11\xe7\x7c\x4a\xf8\x06\x12\x78\x66\x5a\xb2\x62\xf4\x07\x02\x65\xb3\xa3\x0b\x5b\x73\x5a\x49\xe3\xbc\x07\x46\xf0\x63\x1d\x4e\xd9\xb2\xe9\x2b\xba\xf9\x04\xcd\x70\xd7\x7c\x09\xd7\x06\xa5\x36\x6e\x30\x8b\xa6\x1b\xcc\x81\xa3\x4d\x10\x77\x25\x22\x38\x27\x37\xbb\xf9\x04\x45\xe4\x9a\xfd\xc8\x58\x76\x0d\xb8\x54\x57\x97\x45\xf3\xd5\x65\x3e\x21\x59\x51\x02\xe8\xb8\x2a\x8c\x27\x1d\xcb\x13\x3c\x22\xa2\x22\x4f\xb7\x02\xdb\x83\x7b\xb6\xcd\xa2\x31\x8a\xa8\x8c\xeb\xa9\xbc\xaa\x3c\x1e\xd2\xb3\x43\x7b\x01\xce\x06\x77\x1a\x16\x86\x43\xa1\xb9\x4d\x85\xab\xa5\xab\x8b\x2e\xc6\x25\x4b\x94\x54\xc4\x60\x6a\x3b\x2b\x91\xa7\x69\xd8\x2c\x58\x43\xd3\x8e\x58\xbd\xac\x9a\x22\x6b\x9f\x21\xba\x2c\x95\xf8\xdb\x8f\x66\x37\xe2\x83\x32\x88\xad\x8e\xce\x32\x83\x35\xb6\x67\x9b\x8d\xb0\xea\xfe\x29\x1b\x51\xf2\xd1\x1b\x36\xb7\xd5\xf1\x57\x2c\x6d\x6f\x39\x83\x4a\xed\x3f\x6b\x0e\x22\x2a\x6e\x64\x6c\xcf\x3e\x3d\xc6\xfb\xfa\x18\x1b\x31\xef\xb7\x08\x77\xef\x64\x17\xe7\xc8\xf3\x61\x47\xfc\xbf\xbb\x77\x0f\x38\x01\x7f\xbb\xb7\xbf\x0f\x3b\xfa\x1f\xfe\x0d\x54\x41\xba\xbd\xd3\x56\xc8\x7d\xac\xa6\x09\x8c\x39\x6d\x07\x59\x6b\xfa\xdb\x08\x59\xdd\x7d\x60\x61\x8e\xad\xc6\x6e\xb6\x00\xe0\x7f\x0c\x34\xcb\x55\xdb\x1e\xa2\x6f\xb9\x72\x95\xda\xdf\xb4\x76\x76\x1b\xdb\xad\xde\xbf\xe4\x24\x7d\x07\x20\xa6\xa0\x2b\xc3\x0b\x34\xa4\x6d\xa8\xf9\x99\xda\xfe\xc5\xf7\x7c\x7f\x08\xd6\x04\xb2\x57\x85\x98\x73\x07\xa3\x93\x9c\x32\x47\xe4\x3a\x1f\xec\x0d\xd7\xe1\x27\xbb\x95\xee\x61\xcf\xf7\x1b\x5b\xb9\x3f\x6c\x5f\xbe\xe6\x4e\xb7\x18\xef\x26\x92\xb7\x05\x52\xe0\xdb\x63\xf2\x5a\x2d\x23\x7a\xc0\x7a\x0b\x10\xcf\xf0\xdd\x5c\xe6\xd1\xf0\x96\x64\xb5\x71\xa9\xfc\x75\x73\x5f\x37\x11\x05\x21\x1b\xb1\x9b\xe9\x6b\xb1\xa6\xb3\x6d\xc9\x6c\xbd\x46\x84\xb2\xcb\xad\xcf\x4b\x73\x87\xa5\x39\xa3\xad\x30\xcf\x96\xb3\xda\x9e\xf8\x36\xd5\xf9\xc6\x99\xd9\x9d\xd2\xb9\x55\xa5\x0a\x13\xa4\x04\x5f\x69\xa1\x40\xfb\xdb\x7a\xb0\xd5\x65\x9a\x00\xd6\x68\xc1\xc2\x4b\x95\xef\xa5\x25\xa3\x04\xcb\x52\x4b\x33\xcb\x0d\xbe\xe0\x3a\x0d\x1b\x7d\x2b\x94\x79\xec\x97\xe0\xec\x4e\x1b\x72\xaf\xdc\x9f\xdd\x74\x18\x6f\xb1\x21\x77\x0b\x0b\xb9\x21\xda\x78\x89\xb2\x0b\x23\x39\x89\xf3\x88\x32\x28\xbd\x2d\x1a\xd9\x07\x06\x59\x6b\x18\xcc\xbd\xd9\x4d\xe7\x87\x2d\x07\x63\xb6\x53\x1d\xd0\xc3\xd9\x4d\x67\x6f\xdb\x01\x69\x70\x6f\x59\x9e\x9e\xbf\xe5\x90\xac\x96\x9a\x16\x69\x6f\x6f\xcb\x31\x19\x59\x72\xf8\x0f\xd1\x5a\x09\x95\xc8\x5b\x4d\xee\xaf\x74\x16\x86\xdb\xa2\x82\x0c\x3b\x30\x22\xff\xc5\x7c\xb7\x77\xef\x33\x23\x57\xa1\x81\x60\x5d\x3a\x32\xa0\x0a\x2f\xb0\x57\x96\x50\x28\x2b\x36\xb5\xbc\x7b\xdf\x6c\xfa\x51\x7b\xcb\xa2\x38\x6d\xda\x2a\x10\x2c\x79\xc2\x9d\x60\x1c\x67\x46\xae\x1b\xb5\x60\xbd\x47\x46\x0d\xee\xb7\xb8\xa9\xca\x9e\x6f\x54\x11\xab\xb8\xa1\xc6\x5e\x59\xb5\x97\xe5\x6a\xb3\x12\x78\x2f\x84\xc1\x6c\x81\xb6\x52\x67\x8a\xa3\x2b\xd2\x1f\x2a\xef\xf3\x9d\x30\x24\xae\x4b\xb4\x62\x13\xe7\x5c\xad\xa9\x94\x81\x95\x9c\x31\x76\x3b\x2d\x2a\xb8\xe1\x86\x80\xbb\xeb\x14\x45\x31\x57\x14\x25\x70\x07\xb9\x6e\x2c\xbd\xf6\x95\xd7\x72\x6e\x6a\x31\x52\xd4\x9a\x06\xa6\x35\x1c\x81\xd2\x49\x3c\x82\xad\xd9\x81\x99\x2b\x2d\xcf\x9c\xc4\x62\x89\x94\x50\x0c\x43\x6c\x58\x90\x92\xc2\x33\x37\x0d\xd8\x90\xfa\xa8\xb4\x52\xce\x3c\x89\x51\x42\x2e\x0e\xd9\xae\xe4\x74\xef\x0a\x64\x1a\x2f\x21\x2b\x2d\x43\x3e\x3f\xcf\xb9\x09\xd4\x1e\xe8\x16\xe4\x25\xb9\xc6\xd9\x11\xca\xb1\x07\x44\xf6\x05\x82\xc2\x86\x58\x77\x5a\x5f\x9d\x85\x58\xee\xf6\x3b\x8c\x46\xc5\x59\x86\x31\x24\x7a\xbf\x33\xd7\xcd\x20\x0a\x71\x77\x4a\xe6\x39\x3e\xbe\xc2\x69\x01\x63\xad\x77\x45\x7d\x47\xa8\xe4\x9d\x00\xc1\x24\xc4\x5d\xf1\xf3\xf0\x1a\x2d\x60\x1e\xe2\x6e\x41\xe6\xa3\x09\xaf\x37\xb2\x42\x07\x91\x94\x19\xdd\x1d\xa7\x2c\x7e\x50\xc4\x13\xcf\x50\x98\xdc\xe9\x01\x38\xd6\x3f\xd9\x4d\x90\x4c\x4c\x23\xbf\x4f\xac\x9f\x07\xec\xc7\xf1\x78\x8c\x47\x45\xd3\x5d\x63\x8e\x8b\xb3\x78\x8a\xc9\xdc\xfe\x3a\x93\x17\x47\x21\xbb\xcc\xf5\x8d\xd8\xc9\xd6\xc7\x1e\x4b\x8d\x3a\x14\x29\x19\x45\x86\x1c\x94\x24\x94\x7e\xdb\x37\xf3\xea\x2a\x2a\x9c\x77\xc7\x71\x1a\x3d\x79\xf3\xea\x35\x89\xb0\x87\x01\x6f\x81\x67\x48\x3c\xe5\xe7\x83\xdd\x9d\x4d\x01\xbc\xa0\xef\x8e\x70\x4b\xa8\xa0\x89\x6c\xf2\x20\x1e\x7b\x13\x63\x50\x50\x8d\xd0\x75\xc7\xfa\x71\xa7\xe1\x86\x3f\x22\x23\x66\x98\xd9\x95\x0f\xe2\x80\x75\x47\x49\xcc\x6e\x17\xa3\x62\xf2\x23\x16\xbf\x3e\xae\x56\x1b\xca\x73\xff\x69\x55\xe1\xb7\xd2\xc3\x00\xc4\x63\x2f\x92\xa3\x00\x91\x31\x4e\x96\x5d\x78\xe9\x89\xdb\xcc\x1c\x47\x6f\x51\x31\xe9\xdb\x3f\x3d\xd0\x65\x91\x84\xdf\x8c\x3d\x35\x15\xf0\xd3\x6e\x2f\xd8\xf1\x7c\x98\x14\x74\x69\xf4\xfb\xfa\xa8\x38\xf9\xca\x3d\xdc\x2d\x28\xa2\x2c\xc0\x6a\xa5\x8a\x37\x7c\x05\xab\xd5\x0e\x71\xdd\x62\xb5\xe2\xc6\x0c\x00\xc0\xc5\x5a\xc3\x88\x02\x2c\x8d\x95\xf7\x0f\xb8\x39\x49\xca\xaf\xfd\x07\x78\x78\x40\x4f\x89\x57\x50\xb9\xeb\x3c\x64\x77\xa3\x57\xd2\xda\x6c\xa7\xc7\xf3\x33\x79\xe7\x83\xd1\x30\x5c\x78\x23\x76\xa9\xd9\x0c\xad\x31\x05\x66\x5a\x5c\x1a\x82\x66\xc8\x1b\x01\x58\x84\x0d\x8b\x00\x53\xf3\x12\x37\x32\x21\x59\x63\x53\x14\x45\xec\xe4\xbd\x8c\xf3\x02\xa7\x38\xf3\x30\xbc\xa0\xdd\xd7\xde\x3b\xec\x94\x4e\xc9\x15\x66\x61\x2a\xcd\x88\x7a\xdd\x0c\xd3\xf7\x8d\xed\x34\x7d\xb2\x9b\x62\x04\x69\x70\x01\x47\x43\x00\xd9\xdc\x62\xb6\x14\x31\x5d\x8a\x78\x8b\xa5\x88\x8d\xa5\x88\x5b\x96\x62\xd3\x7c\xb7\x9a\x8d\x1c\x68\x3c\xac\xab\xca\x8b\xee\xd3\x0c\x5d\xd0\x47\x75\x2b\x9c\x90\x54\x7d\x4e\xe1\x39\x00\x25\x03\x0a\xb4\x1d\x79\xe5\x62\xd9\x86\xbb\xc2\x29\xce\x73\x74\x81\x59\xa4\x96\x8c\x24\xb8\x12\x79\x0d\x25\x38\x2b\x1a\x22\xaf\x21\x99\x2a\xb5\xf9\xb6\x4b\xb4\xea\x40\x87\xb6\xb9\x65\x00\x36\x96\x78\x6b\x0e\x75\x1c\x36\x1d\x74\xed\x01\x6c\xbf\xbe\x89\x8d\xd0\x68\x70\x63\xb0\x44\x24\x67\x5c\xc2\x04\x40\xd2\xdf\xa2\x02\x9f\x6b\x09\x09\x08\x18\x95\xd0\xb4\x3e\x6e\xb9\xb1\x10\x89\xd7\xdb\x74\x8e\xdd\x47\x41\xf7\x87\x47\x30\x0b\x45\xf6\xcc\xfb\xa6\xfa\xa7\x9e\xc1\x0f\xaa\x5c\x01\xdb\x24\x0b\xd5\x01\x8d\x36\x69\x64\xb2\xba\xfe\x25\xdb\x22\x76\x52\x2d\xa6\xc7\x37\x5d\xa8\xe8\xac\xef\x65\x25\x8f\xbe\x8e\xa2\xa4\xca\x38\x71\x1a\x17\x31\x4a\x8c\x8b\x9c\xbd\x47\x8f\x28\x46\x15\x9b\x59\x11\x24\x7c\xa7\x84\x7c\xd7\xb6\xe2\xbe\x0c\x2e\x49\xc4\x69\xb3\x12\x5f\x3e\xb0\xb9\xf8\x6a\xec\xa5\xd3\x14\x8d\x2e\xcf\x51\x26\xa3\xfa\x94\xc0\x43\x88\x53\xf1\xe4\xd6\x07\xd5\x0a\xc7\x14\x87\x1e\x32\x99\x20\x23\x22\x93\xc8\xd5\x6d\x05\x65\x92\xb1\xad\x02\x04\x54\xc4\x1a\x98\x84\x66\x84\x1a\x76\xcc\xe9\x14\x9f\xc7\x11\x7e\x22\xee\x94\xec\x23\xcf\x12\xde\xf1\xa0\x62\x8a\x7d\x8b\x0c\x14\x32\xb6\x50\xc8\x2c\x4c\xbb\x8a\x13\x93\xa8\xee\x2d\x25\x58\x2c\x34\x93\x58\x13\xfe\xc2\xb0\x07\xf8\xc0\x8c\xb7\x1e\x27\xf3\x4c\xd6\x69\x34\x0b\x90\xc8\x69\x11\xa6\x5d\x61\x5a\xc3\x0c\x01\x48\x7a\x4c\xa7\x0a\xaf\xf5\x33\x8e\x98\x11\x80\xf8\x45\xc5\x89\x63\xfe\xf3\x26\x2e\xd8\xed\x3f\x7f\xc4\x11\xbb\xfc\xe7\x3f\x68\xa9\x23\xf6\xeb\x15\x63\x3b\x59\x9b\x9f\xf4\x8b\x97\x18\x5d\x61\xf8\x96\xbe\x98\xe1\x14\xbe\xa3\x28\x92\xb9\x7e\x58\xab\xf7\x26\x4c\xbb\x67\xea\xaa\x4e\x19\x76\xc0\x33\xbd\xaa\x6f\xfa\x51\x1a\xbc\x81\xaf\xc3\xd4\xb8\xd4\x53\x0d\x7c\xd6\x05\x5f\xf7\x97\x3c\x15\xe9\x61\xd1\xbd\xf9\xa1\x12\x93\x05\xe2\x9b\xb8\x10\x5f\x6c\x0f\xc6\xe0\x35\x7c\x65\x8d\x82\x2f\xf8\x49\x0b\xce\xae\xc4\xa4\xaa\xc2\xc3\x36\x71\xa9\x9a\xf7\x9c\x7e\x30\x76\x5c\x1b\x31\xd4\xf7\xdb\x22\x12\x62\x6f\xd9\xd3\x31\x3f\x93\x8e\xda\x57\xfd\xcc\x85\x3b\xbe\x77\xea\x41\x16\xe0\xfb\xc9\x9e\xf5\x6e\xea\x9f\x6c\x2f\xe9\xcf\x19\x9b\x55\x7d\x1f\x1d\xe8\x34\xec\xa2\x03\x9d\xfa\x8e\x59\x45\xf9\x4c\x87\x00\x1e\x6a\x61\x01\xc0\x97\xfc\x07\x37\x90\xdc\xf1\x01\xfc\x1a\xbe\x1c\xf8\x43\xf8\x24\x7c\x39\xe8\x0d\xe1\xd3\x26\x66\x1c\x2c\x59\x52\x6e\xee\xc5\x20\x8c\x0b\xb5\xb3\x13\xc5\x76\x8f\x5b\x78\xf8\x85\x74\x6b\xc1\xae\xeb\x31\x73\x3d\x29\x88\x1c\x6a\x56\x4e\x3d\x86\x2d\x82\xca\x53\x8f\x9b\x82\x15\xfc\x9b\x43\xa5\x09\xcc\x45\xdb\x0d\x92\xcf\x5b\xd7\x7d\xec\xcd\x2d\x1e\xa8\x65\x14\x8c\xff\x79\x0b\xe7\xf0\xb1\x10\x74\xbe\x84\x5b\x54\x82\x1f\x5a\xc5\x21\xb0\xe4\x33\x9f\xd3\x21\xf0\xc7\x77\xfd\x77\x41\x77\xff\x1f\x73\x26\x0d\xcd\xe1\x3b\xd6\x97\xe2\x3f\xda\x39\xc1\x2b\xd7\x7d\x2b\x5d\x0c\x84\x75\x69\x9d\x85\x65\xea\x47\x07\x7e\x00\xb0\xb5\xc8\x79\x32\xcf\x1c\xf8\xc5\x5a\x0e\x51\xb8\x91\x95\xad\x35\xd9\x58\x4a\xb6\xca\x56\xf0\x0a\x7e\x80\x6f\x29\xb3\xfb\xd6\x75\xbf\x72\x94\x5d\xb3\xec\x33\x92\xb1\x1b\xd2\x72\x50\x81\x9b\x85\x87\xe9\xc9\x8e\x47\x97\xe8\x1a\x2d\x1c\x2a\x5c\xcc\xda\xd8\xa8\x75\x2a\x92\x88\x33\x63\xd1\xa6\x60\x6a\x71\x43\x90\x34\x16\xfa\x76\x0c\xa0\x79\x72\xad\x71\x1e\xb9\xee\x91\x87\x01\xfc\xe2\x81\x12\x9a\x07\xda\x2a\xf5\xc9\x75\x3f\xd1\x52\x1f\x98\xcd\x3b\x67\x09\x4f\x1a\xc2\x3a\xeb\x79\xa0\xd9\x0c\x23\x16\x1a\x3b\x4e\x83\xb7\x50\xa0\x19\x3a\xa9\xa8\xa8\x9e\xcd\x27\xde\x4e\x8f\x42\xd4\x39\x80\x0a\x35\x05\xd7\x50\xa3\xa6\xe0\x06\x72\x34\x14\x1c\x43\x89\x9a\x5a\x9b\xf2\x69\x53\x97\x00\x2a\xc4\x15\x9c\x42\x71\xee\x82\xcf\x30\xd2\x51\xd4\x0a\x32\x73\x44\x40\x50\x72\x9d\x3a\x81\xc3\x32\x0f\xbf\x02\x70\xb4\x5a\x55\x67\x16\x1b\x5b\x2e\x19\xa3\x0b\xc9\x08\x91\x12\x4e\x78\x6c\x7e\xc5\xbe\xe6\x6b\xd9\x57\x16\xa3\xe1\x51\x09\xb3\x50\x06\x11\x78\x54\x42\x12\x2e\x5b\x35\x54\x25\x44\x2d\x5f\x99\xf2\xd5\x29\x61\xcc\x1b\xdd\xbb\x5f\xc2\x44\xb5\x4a\x7f\xe5\xe1\x92\x07\xda\xa0\x3f\xe6\xe1\x92\x05\x2a\xa0\xcf\x23\xf1\xcc\xf2\xd3\xc8\x60\x1c\x9c\x47\x33\xc2\x0d\xa8\x28\x03\x1f\x3d\x11\xcd\xc1\x0e\x5d\x2c\xe2\xaa\x15\x32\xe0\x70\x2e\x58\x36\x58\x8b\x2a\x5c\xe1\x16\x13\xae\xa9\xcd\x84\x66\x78\x6d\xf4\xba\x6a\x84\xd1\x4a\xfc\x0b\x91\x63\xdc\x60\xde\x53\x83\x57\x6f\x65\x82\x8d\xf2\x31\x1c\x01\x00\x1a\x22\x3e\xd4\x9b\xce\x6e\xd9\x74\x52\x6f\x5a\x06\xa1\xb1\x47\x4c\x6e\xd5\xb0\x11\xfa\x98\x0e\x3f\x6f\x1e\x7e\xad\x9b\xec\x8f\x74\x93\xd4\xbb\x11\xd1\x47\xec\x99\xa0\x5b\x75\x61\x42\x1e\x9d\xca\xbc\x79\x2a\xd5\x6e\xb2\x3f\xd4\x4d\xc2\xba\x61\xd2\xc6\x38\x89\x67\xc1\x4e\x0f\xd6\xa4\x0e\x2a\x6e\x24\x42\xdc\x98\xa3\x30\xf5\xf6\x1e\x3d\x32\x14\xb9\x23\xa4\x75\x7c\x22\x2f\x0c\x4c\x43\xcc\x4d\x95\x73\xa6\x97\x9d\xce\xe3\xa7\x24\x9b\x32\xd1\x90\x24\x3a\x31\x4c\x86\xa3\xf9\xc8\xf2\x09\x32\xfd\x84\xa5\x1f\x2e\xcc\x5c\x57\xb1\xaf\xf4\x85\x74\xd2\xcd\x06\xe9\x10\x40\x4c\x07\x5f\x82\x92\x8e\x20\x42\xca\x93\x47\x66\xfe\x96\x98\x68\x8c\xc2\xc8\xf0\x61\x9c\x21\x2b\x0f\xcd\x0c\x65\x39\x3e\x49\x0b\x0f\x0f\x8a\x21\xec\xf9\x60\xb5\xf2\x59\x8b\x13\x14\x3a\xf3\x34\xc2\xe3\x38\xc5\x91\xf6\xf2\xe5\x64\xb4\xcf\x68\xfd\x4b\xb4\x20\xf3\x82\x53\xfc\xc0\xa0\xfe\x70\x8a\xc2\x25\x8b\x41\x12\x27\x71\xb1\x08\x9c\x49\x1c\x45\x94\x35\x6c\x8a\x2f\x49\xae\x70\x36\x4e\xa8\x20\x2a\x4b\x89\xb0\x7f\x3e\x6c\x0b\x2b\xa6\x50\xd2\x27\xcf\xa7\xf8\x88\xcf\xf3\x6a\x3b\x81\x50\x66\x95\x60\x22\x61\x46\xae\xb9\xe2\x86\x3e\xbc\x42\x37\x4c\x6d\xc3\x9e\x63\x1e\x60\x77\x8a\x6e\xde\xd1\x32\x73\xfa\x1c\xa7\xec\xd9\xb2\xea\xee\x09\x73\xee\xbc\x58\x24\x98\x09\x70\xdc\xdb\x76\x66\xcb\x07\xb2\x57\xa6\xb5\xb9\xce\xc5\x9f\x57\x2c\xc2\xac\xe8\x8f\x47\x9c\x7d\xc7\xbf\x8a\xbe\x98\x81\xf1\x22\xe1\x56\xc5\xc9\x1c\x53\x5e\x78\x12\xe6\xab\x55\x0c\xa7\x21\x5a\xad\x92\xd5\x6a\x04\xaf\x6c\x4d\xfb\x4e\x38\x06\xca\x9f\xe2\xa2\xaa\x85\x5f\x68\xf5\x75\x06\x2f\x00\x3c\xaf\x16\xb8\xd6\x2f\x7c\x00\x6f\x4c\x5e\x7b\x59\x02\x78\x1c\xde\x50\x5e\xfb\x32\xbc\xa1\xbc\xf6\xe9\x1a\xde\x91\x6b\xfd\x2e\xd4\x50\x8a\x50\xb0\x60\x4c\x57\x32\x9d\xcd\x0b\x1c\x9d\xd2\xc9\xf1\xd4\xc5\xe7\x4a\x4b\x9e\xf1\xc5\xec\xb2\x4b\xc6\xb0\xe0\x7f\x61\xc6\x17\x56\xba\x33\xaf\x56\x69\x77\x96\xa0\x11\x9e\x90\x24\xc2\xd9\x6a\xe5\xd0\xa5\xfc\x9f\x94\x12\x74\x51\xb4\x9b\x27\xf1\x08\x7b\xbb\x3d\xe0\xba\x9e\x78\x77\x37\x74\x3a\x0e\x3f\xd1\x24\x2c\x06\xdc\x52\x94\x19\xb5\x3a\x43\x88\xc2\x19\xf2\x0a\xe8\x08\x0d\xc5\xae\x50\x04\x80\xbb\xf6\x6b\xca\x36\x00\x18\x8b\xc2\xca\x14\x96\x96\xdd\x65\x63\x55\x35\xc4\xb7\x82\xcc\xe4\x07\x98\x84\x59\x37\x1f\x65\x24\x49\xb8\x0e\x7e\x17\x1d\xc8\x99\x39\x37\x0e\x1b\x58\x5e\x2b\x02\xe7\x61\x72\x30\x75\x5d\x6f\x1e\xbe\x42\xc5\x84\x42\xa5\xf7\x7a\x3e\x3d\xc7\x99\x37\x05\xff\xc8\x29\x2a\x83\x13\xe3\x73\x9c\xca\xcf\x13\xf1\x99\x35\x3c\x0a\xcd\x06\xe6\x14\x99\xdf\xf5\x4c\x5b\x5e\x16\x9b\x1a\xdd\x8d\x03\x1f\xc0\x88\x97\x44\xe7\xb9\x37\xdf\x4d\xc0\x8f\x61\xef\xe0\xb2\x31\x09\xf2\xb5\xdc\xb8\x1f\xf7\x7c\x2a\x22\xfd\xe4\xbb\xae\xaa\xea\xe1\x2e\x99\x17\x38\xe3\x33\x61\xdb\xbd\x5a\xf9\x60\x77\x04\x7e\xea\xad\x56\xb8\x2b\x4f\xff\x4e\x18\x46\xa0\xef\xa9\xb6\xee\x86\x3d\xb8\x54\xa8\x21\x82\xd5\x46\x82\x51\x09\x02\xcc\x3c\xae\xe0\x60\x02\xa7\xd0\x82\x86\xcd\x32\x09\x07\x4e\xcf\x87\xcf\x6b\x1c\xa4\x1a\x43\xe8\xc3\x53\x0f\x18\x09\xbd\x5a\xa5\x92\x0c\x73\x6f\x00\x6c\xc9\x25\xb8\xcb\x64\x2e\x6f\xbd\xec\xa1\xeb\x32\xe9\xe3\x94\x9e\x70\x64\x0d\x88\x0f\xa2\x55\xd1\x6e\x8c\x97\x36\x30\xde\x4e\xfd\x6d\x8b\x20\x94\x60\xa0\x0c\x23\x43\x0e\xe1\x7e\xbd\x63\x28\x31\x97\x25\x0e\x98\x6b\x74\xb5\x5a\x9d\x7a\x00\x12\xd7\x25\x1e\x16\xd2\xc1\x02\x52\xa4\x16\x4c\x21\x3b\xc9\x9a\x6a\x0b\xd4\x7e\x5c\x03\x0a\x4d\x06\x8e\x15\x4c\xf4\x25\x45\x60\xaa\xe1\x12\x46\x80\xca\x4f\x60\xdd\xe8\x97\x0e\xca\x62\xb4\x2b\xeb\x59\x09\x6e\x4c\xd5\x5a\x86\x51\xf4\x26\x4d\x16\xb4\x04\x1d\xef\x39\x2c\xd0\x39\x67\x64\x77\x7b\xd5\x41\x97\x70\x8a\x68\xe7\x9c\xbd\x57\x84\xf4\xc2\xbc\xc7\x55\x2a\x82\x1d\x8f\x27\x96\x8d\x73\xf6\xd7\xc3\xc0\x75\x7d\x96\x25\x44\xa4\xf1\xd2\x81\x1b\x16\x06\xff\xa0\x74\x11\xd2\x47\xbd\x27\x49\xff\x4e\xa8\x3f\x0e\x7a\x43\xd7\x35\x7f\x49\xc8\xc4\xae\xeb\xd1\xf1\x88\xb0\x0f\xae\xeb\x38\x3b\xa1\x46\x95\x85\xeb\xb2\xaf\x42\xe9\xfd\xab\x5d\xc8\x7a\xcb\x68\xff\xb9\x45\xfb\xc3\x26\xda\x6f\x52\x7d\x93\x0f\x80\xd7\x5b\x91\xe1\x01\xdf\xa8\x08\xe7\xa3\x2c\x3e\xc7\xd1\xf9\x82\xe1\x5f\xae\x40\xa5\xd4\x21\xc1\x05\xcf\xe1\x40\x5f\x30\x3f\x1d\x6d\xa7\x80\x73\x1d\xfc\x9e\x6d\xe7\x3c\xf4\xa4\x67\x56\x6a\x4f\x87\xe9\x5a\x95\xf5\x5d\xc4\xdd\xa1\x0e\x23\x92\xa5\xec\x34\x8c\x69\x45\x16\x8e\x18\xa6\xa6\x4b\xc7\x4c\x2b\x4c\xc7\xae\x2b\x42\xe1\x47\x4c\xcb\x1a\xa7\xb3\x79\xa1\x35\x91\x56\x38\x7c\x87\x7d\x74\x44\x4c\x7c\xf6\x83\x6b\x0b\xad\xb0\xf8\xcb\x52\x44\xc3\x67\x05\xde\xe1\x31\xbc\xa6\xc3\xe0\x8a\x70\x98\x76\xa7\xf3\xa4\x88\x93\x38\xc5\x94\xfc\xaa\x71\x5c\xbb\xee\x35\xd3\xbb\x52\x36\x55\x68\x5d\x1f\x27\xf3\x4c\xe8\x5c\x05\x53\x73\x24\xb4\xb9\xf1\xe8\x52\x68\x5b\xf9\xda\x31\x45\x6b\xfa\x33\x5e\x3c\x21\xd7\x5c\xdb\xca\x7e\xbd\x9f\x31\x15\xab\x81\x3a\xe1\x19\xd3\xc4\xf2\xe3\xc1\xb4\xaa\xdc\xe1\xf4\x74\x3e\x1e\xc7\x37\xf0\xb3\x64\x9a\x5e\x19\x4c\xd3\x89\xc1\x34\x1d\x1a\x4c\xd3\x4b\x83\x69\xfa\x2a\x9d\xc4\xf4\xe2\x3f\x91\x9e\x62\x4f\xf5\xea\x3c\x91\x5e\x60\x4f\xe0\x63\xc5\x4b\x7d\xa9\xe8\x5a\xab\x90\xc3\xd5\xac\x12\x6a\xc4\xcf\xa7\x5c\xf3\xb3\xc1\x65\xcc\x04\x16\xdb\x6b\xcc\x84\x13\xfa\x93\x02\x49\xc5\x05\x2c\x8e\x58\xc6\x00\x13\x1e\xe4\x0b\xa9\xa3\x95\x5b\xcc\x98\xbb\x8c\xeb\x84\xd5\xfe\x3a\xd0\x49\xf9\x70\xf8\x56\x72\x6d\xad\xe4\x13\xa5\x55\x06\x7d\x92\x93\x51\x5b\x28\x9f\xdf\xcf\x1c\xe8\x18\xdb\xc7\xd4\xaf\x7c\xf3\xd8\xa3\xde\xba\x6f\xe1\x3c\xcd\xed\x32\xfd\xdb\x04\x27\xfa\x21\xe4\x68\x6f\xc1\xf7\xa9\x2f\xfe\x06\x8f\xe1\x9d\x2a\x4b\xfa\x41\xb3\xa4\xef\x4d\x5d\xee\xaf\xeb\x6c\x31\x84\xc5\xc5\x73\xcd\xb2\x2e\x98\xc5\xc5\xaf\x00\xfe\xae\xdf\x9d\xc3\xe7\x00\xfe\xac\x7f\xbf\x87\xbf\x03\xf8\x8b\xa5\x23\xee\x01\xf8\x2c\xfc\x85\xf2\xad\xbf\x85\xbf\x50\xbe\xf5\xa3\xe8\x56\x88\x4a\x11\x02\xf0\x45\x38\x42\xde\x92\x49\x71\x41\x0a\x6d\xc1\x2d\xf8\x08\xb9\x50\x17\x0c\x34\xe4\x18\xa0\x22\x60\x83\x93\x9d\x97\xe8\x1c\x27\xe6\x7e\x67\xf8\xf7\x79\xcc\x95\xed\x22\xcf\xee\xb0\x04\x07\x2f\xb8\xc3\x17\x8e\xc2\x8f\xfd\x8f\xf2\x39\x78\xd6\x4a\xe6\x77\x3e\xba\xee\xc8\x75\x9f\xb9\xae\xf7\x1b\x9b\xd1\xa5\xeb\x5e\x7a\x9c\x01\xfa\x08\x47\xf0\x19\xbc\x14\x6a\x5f\x8c\xc3\x8f\xae\xfb\x91\x9e\x7d\xd6\x1d\x2c\xd4\x8b\xe3\xe9\xac\x58\xc0\x14\xaf\x5b\x75\x46\x96\xfa\x18\xbb\x2e\xc6\x1e\x08\x0a\xec\xba\x05\x66\x2e\xfe\x03\x8c\x61\x81\x87\xe0\xe0\xdc\x66\x50\xee\xb8\x6e\x8a\x25\xc7\xf0\xa1\x64\x45\x3f\xc0\x14\xc3\x3b\xc3\x76\xb6\x25\xc5\xde\x7b\xad\x85\xd6\xd6\x39\x19\x0e\xaf\x20\x61\xbc\x99\x24\xbf\x0b\xee\xad\xfe\x73\x29\x39\x31\x87\x5b\x4c\x69\xa9\x34\xc3\x7d\xb3\x8a\x3c\x75\xc1\xcf\xdc\x7f\xee\x69\x09\x09\xe6\x8d\x30\x56\x02\x04\x37\xfd\x9d\xcf\xab\xd5\xe1\x6a\xf5\x72\xb5\x7a\xb5\x5a\x9d\xf4\x3d\xb3\xbe\x38\x03\xc1\xe7\xd5\xea\x25\x14\xc7\x25\x78\x05\xc5\x21\x09\x0e\x69\x73\x00\xd2\x91\x22\x10\x64\x38\xd4\x1c\x48\x60\x36\xa3\xfb\x6e\x5f\x06\xb6\x31\x39\xe6\xe7\x8c\x0a\x44\x28\x2b\xbc\xc7\x84\x24\x18\xa5\xde\x57\xb9\xbd\x5f\x87\xdf\xa2\x37\x4e\x84\x69\x5d\x6b\x4e\x8c\x17\x9c\x68\xae\x56\x2a\xcc\x20\x00\x43\x98\xc3\x17\x8a\x64\xba\x6e\xa2\xc9\xe7\x0b\x4e\x2a\xe9\x3b\x4e\x33\x67\xf4\x51\x7b\x0e\x2b\x90\x66\xaf\xf9\x23\xfc\xc8\x7f\xa8\xb3\x04\x6f\xe8\x0b\x85\x03\xe1\x57\xfa\x13\x19\xb3\x87\x91\xf1\xe6\x38\x8d\x28\x92\x4e\x73\x4c\x85\x93\x17\x82\x48\xb2\x16\xd8\xd3\x13\xfa\x09\x28\x87\x7d\x13\x8e\xdf\x6b\x8b\x2a\x2c\x1f\xcf\x98\xf9\x10\x63\xc7\xb8\x25\x91\xeb\xaa\x62\x7c\xc4\x1e\x80\x42\x23\xae\xf4\xdc\x5f\x00\xfc\x5a\x5b\xfd\x31\xea\xbe\xcd\x08\x8b\x05\x20\x03\x1b\x71\x2e\xb5\x5a\x30\x33\xfc\x64\x39\xe9\x8a\xd3\x2b\x94\xc4\x91\x13\x88\xf5\x84\x75\x8a\x16\x10\x68\x92\xb4\x00\x41\x45\xd2\x82\x18\x9a\x44\x2b\x98\x6b\x2b\x6d\xbd\x6d\x30\x8e\x82\x09\x24\xe9\x61\x1a\x4f\x91\xc8\x85\x96\x15\xd6\xf2\xa4\xd8\x63\x29\xf0\x68\xc3\xbb\x14\x2f\xed\x8e\x50\x3a\xc2\x09\x4f\x69\x87\x64\x45\x0a\x51\x7d\xb5\x46\x81\x98\xaa\x73\xe3\x94\xa0\xe4\x1a\xb3\x63\x68\xd0\x9f\xe0\x8d\xe6\xad\xcf\xa0\xc4\x7c\xc1\x8b\xae\x7c\xe4\x82\xc1\x67\x28\x90\x05\x54\x14\x8d\xdd\x11\x30\x8a\x16\xbc\xe3\xc7\xb5\x11\xa2\xd9\xd1\x86\x0b\x83\xf9\x6b\x01\x56\x06\x66\xac\xf4\x2b\x05\x6b\x2f\xba\x06\x8a\x56\xdf\x9f\xeb\x77\x1c\x1a\xd9\xdb\xc3\x1a\x48\x9a\xaf\x19\x5c\xe6\x18\x65\xa3\x09\x5d\xb0\xa7\xea\xfb\xd9\x62\x86\x4f\xd9\xfb\x16\xb8\xe5\x43\xb2\x81\x97\x12\x7f\x6b\x73\x18\x6e\xc7\x00\x2e\x04\x93\xe7\xba\xf2\x89\xbe\x15\xc8\x9c\xfe\xec\x7f\xd4\xef\x03\x46\x17\xca\x66\x89\x2d\x1e\x7b\x3b\x77\xb4\xb6\x92\x43\xff\x6a\xf5\xde\xb4\x4d\xe4\xc1\xf2\x0a\x23\x6c\x19\x0f\x59\xe6\xf9\x70\xce\x6e\x32\x7a\x00\x1c\x68\x4c\x5f\x70\x72\x5f\x82\x52\x05\x1d\xac\xc9\x31\x30\x0b\x69\x3b\x5c\x16\x4a\x7f\xea\xf5\xd3\xdd\x5e\xe0\x03\x48\xc2\xde\x01\xf9\x31\x3d\x20\x77\xef\x82\x6c\x40\x76\x7b\x43\x43\xca\x21\xc3\x83\x85\x62\x69\xf9\xd4\xf9\xb3\xb8\xbf\x5d\xc0\x01\x1e\x4a\x64\x96\x01\x00\x4f\x5d\xf7\xd4\xbe\xdb\xb5\x0b\xd0\x35\xe1\x87\xc7\x5c\x12\x0d\x38\x7d\xdc\xcd\x0b\x32\xa3\x4c\x1b\xba\x40\x1c\x33\x07\x9e\xbc\xf3\x5a\x48\x2e\x9a\x0f\x85\x3d\x1a\xdb\xc0\x7e\xf7\x3f\x1a\x5f\xe8\x46\xf8\x4c\xb9\x0c\x00\x8c\xe0\xeb\xfe\x6b\xcf\xa0\x66\x2f\xe0\xd2\xe6\xac\x82\xaf\x25\xa8\x99\x3f\xdd\x7c\x93\xf9\x13\xcc\x42\xe9\x9a\x61\x39\x61\x40\xc2\x7d\xda\x82\xb4\xdf\xbd\xbf\x17\x74\xf7\x37\xfa\x55\x3b\xa2\x86\xb3\xa5\xdb\x34\xce\x28\x42\x20\xe1\x52\xf6\xe4\xf8\x9d\x9d\x78\x3a\x23\x59\x81\x98\xb3\x32\xd2\x9f\xe4\x20\xd4\x4d\x92\xf3\xbf\x2f\x12\x72\x8e\x12\x27\x58\x3a\xff\xfb\x12\x2f\xc6\x19\x9a\xe2\xbc\x63\xa1\x27\x27\x58\x96\xb0\xf5\xab\x44\x5e\xc1\xb2\x2c\xe1\x46\x4b\xae\x1e\x5c\xae\x75\x3a\x37\x52\x0c\x39\xbd\x6e\xef\xd1\xc3\x07\x78\xda\x9a\x09\xa9\x29\xff\xd3\x68\x9e\xe5\xcc\x31\x90\xca\x32\x2d\xd9\xa0\x9a\xac\xa5\xd6\x3b\x93\xb1\x31\x2a\x04\x27\xfb\x90\xd1\x13\xca\x12\x40\x83\xce\x32\x8f\x0d\xc1\x55\x56\x5c\x79\x4c\x6a\x6b\xfc\x3e\x4e\xd9\x57\xcc\x33\xfb\x94\xd0\xa0\xb0\xec\xa7\x44\xa3\x86\x41\x98\x62\x29\x1e\x40\x67\x76\xd3\xf1\x3b\x3a\xec\xc2\x43\xfa\x86\x7b\xf4\x1a\x0d\x39\xaa\xf2\x19\x99\x05\xf7\xca\x7a\xba\xa2\x35\x7e\x26\x0c\x75\x72\x77\x09\xc3\x0d\x84\xad\x4d\x26\x1c\x14\x8c\xf7\x8d\xe7\xe0\x36\x23\x17\x8e\x9b\xbe\xb9\xf1\x23\x7e\x3d\xc9\x77\x5e\x5b\xf8\x49\x07\xae\x49\x0d\x68\xf8\xdc\x03\x1f\x7e\xc0\xe7\x97\x71\x71\x86\x66\xcf\xe3\x8b\x09\x3b\xbe\x4d\x29\x32\x15\xa8\x9c\x27\x84\xca\x7e\xca\x26\xcf\xb7\xb3\xbf\x5a\xf4\x39\x68\x26\xe4\xba\x90\x34\xae\xa1\xb5\xa7\x39\xf3\x33\x0b\x76\xaf\xd9\x80\x76\xd9\xa2\xee\x9a\x22\x64\x90\xf1\x02\x53\xf2\xb5\xe1\xfd\xee\x34\x5f\x57\xa7\xfd\x23\x37\xc5\x08\x96\xc2\x7b\x2a\xf0\x99\xbb\x9a\x62\x86\x9a\xbd\xd9\xd4\x30\x39\xad\xdd\x8d\x54\x2c\x06\x8a\x2b\xe4\x47\x6e\x6b\x40\x67\xed\xe8\xca\x2c\x7c\xc1\x20\x42\x05\xda\xcd\x59\x76\xb5\x70\x8c\x92\x1c\x0f\x3b\x77\x3b\x77\x8c\x73\xd2\x71\x69\x4b\xeb\x17\x84\xb4\x2c\x08\x59\xb3\x20\x64\xdd\x82\x10\xb5\x20\x6b\xfb\x45\x66\xb1\x5a\xef\xc6\xd7\x96\x6e\xec\xfa\xcd\x45\xaa\x6e\x81\x12\x49\xf7\xd8\xfa\xab\x15\x9e\x17\x44\x60\xe1\x06\xa8\xda\xf7\x7d\x3f\x5f\x0f\x94\x3c\x31\x81\xcd\xfa\x54\x70\x01\xb4\xb9\xb5\x40\x6a\x8b\x65\x7e\x5f\xa6\x28\x97\x27\xcd\xc8\x03\x56\xe1\xbb\x28\x5c\xd0\xb5\xb2\x80\x82\xa2\xce\x71\x8c\x13\x2a\x84\x37\x42\x8d\x2e\x20\x1a\x3c\xac\x20\xc9\x0a\xf7\xa7\x5e\x19\xdc\x23\x25\x3e\x96\xf9\xea\x09\x2d\xf0\x18\xe5\x2c\xe3\xc1\xb5\xb8\x49\x3e\xbe\x95\x03\xd7\xfb\x34\xc2\x19\x63\x5e\xab\xb6\xe6\x5a\xee\x4a\xb4\x96\x30\x76\x5d\x9e\xd7\xb6\xa2\xa6\xb4\x2d\xcf\x85\x9a\x92\x5b\xa2\x6a\x51\x2c\xd2\xed\x8c\x5c\x97\x27\x09\x65\x5c\x85\x9d\x1f\x94\x2b\xe8\xc6\x70\xd2\xe8\x29\xa6\x06\x6c\xe9\xde\x2c\xb5\x59\x55\x63\x66\x2a\xc4\x98\x8e\xa9\xdd\xa6\xfd\x06\x55\x24\x5e\x9c\x9b\x94\x1e\x41\x65\xc6\x6d\xd9\xb1\xef\x10\xd7\x45\xdd\xb9\x1c\x1a\x80\xea\x51\x28\x04\x0c\xa2\x93\x40\x7b\x80\xc1\xdc\x20\x7d\x91\x19\x96\x67\xc6\xcc\x7e\x28\xcf\x76\x8c\xba\xd3\x79\x4c\xc1\x3e\x74\xd8\xa6\xcb\x98\xa6\x97\xe8\x9b\x92\x88\xd7\x22\x67\xdc\xdf\x6b\x8f\x9c\xf1\x10\x38\x07\x9b\x32\x52\x96\x36\x6b\xc0\x91\x63\xe7\x2e\x43\x7e\x9c\x44\xd1\x33\xd8\x7b\x50\xb6\x32\x0d\x55\x3a\xed\xb8\x77\xf4\x22\xa2\x71\x61\x04\x6e\x10\x96\x33\x6b\xb3\x0d\x96\xa5\xb1\x07\x14\xff\x36\x35\x11\x38\x7b\xf5\xa0\x09\xb8\x25\x7a\x86\xb0\x13\x50\xc9\xb2\x04\xa9\x0e\xfe\x97\xe3\xfc\xaf\x46\xcb\x83\xb6\x34\x70\x1f\x3d\x5f\xa6\x66\xd9\x36\x75\xca\xa6\xa4\x28\x82\x45\x86\x9b\x52\xac\xbc\x99\x17\x25\x80\xcc\x84\x05\x67\xec\xa2\x30\xaf\xf9\x7f\xe3\x48\xad\x55\x7d\xe4\x3d\xc0\x4b\x72\x26\x6e\x9b\x6d\x31\xf2\x34\xb6\x36\x17\x9c\xe3\x31\xc9\x70\x6d\x77\x9a\x42\x5a\xac\xdb\x88\xff\xf9\x1f\xdf\x47\xfe\x36\xdb\xb1\x6e\xe1\xed\x1b\x77\xa1\x8f\xdd\x76\x0b\xd6\x2c\x2f\xf7\xbd\x67\xbe\x9e\x8a\x20\x82\xb6\xa9\xaf\x05\x4c\x53\x98\x58\x13\x46\x64\xf3\x5a\xda\xc1\x44\x9a\xc7\xc2\xef\xc3\x9d\x88\x14\x05\x8e\x28\x99\xdd\x82\x81\xb7\x98\x6c\xc5\x58\x37\x51\xe8\x3a\x55\x6e\x20\xb8\x4d\x64\x8f\x92\xbc\x63\x41\xf2\x4e\xff\x26\x79\x7f\x39\x92\x77\xda\x46\xf2\x8e\xbe\x89\xe4\xc1\x34\x2c\x6e\x4d\xf6\x60\xd6\x54\xc9\xff\xa1\xbd\x12\xfd\xb6\x91\x58\x36\xb8\x6e\xf1\x03\x27\x73\x5f\x72\xdf\x2b\xdc\xe4\x7b\xa5\x0a\xf2\xfc\xa3\x6b\x4a\x6e\xc6\x73\xb5\xc0\x76\xdf\x99\xce\xac\x8b\x84\x52\x5f\xd6\xde\x9a\xe0\x5d\xf4\xdb\xd6\x41\x52\xb2\xd2\x24\x66\xdb\x75\xbe\x69\x4f\x37\x46\x06\x6a\x98\xcf\x1a\xd8\xa2\xdf\xca\xbf\x79\x9e\xbf\x79\x9e\xad\x78\x9e\xf4\xff\x78\x9e\x67\xfb\xb9\xb6\x30\x39\xdf\xc2\xa7\x6c\xa5\x9d\xb4\xbc\x45\xf7\x6c\x5d\xa5\xf8\xc6\x6d\xdc\xe9\xc7\xdb\xa8\x2e\xf7\x1e\xce\x6e\x3a\xbd\x3d\x15\x64\x67\x9d\x9e\x72\xef\x9e\xd4\x37\x88\x95\x79\x50\x2a\xa6\x69\x4d\x83\x4d\xda\x13\xae\x06\x7c\xac\x75\x5d\x6d\x22\x20\x73\x3c\x62\x21\x49\xfc\x4e\xcf\xf7\x67\x37\x9d\xff\xda\x7b\xf0\xe0\xe1\x0f\x8f\x3a\x71\x9a\xe3\xc2\x91\x0a\x45\x7c\x53\x3c\x8d\x93\x44\x28\x13\xd7\xb7\xf6\x5f\xe3\xf1\xd8\x81\x23\x94\xe1\xe2\x16\xe5\x9b\x68\x5f\x35\xf2\x53\x85\xe0\xe9\x80\x9f\x1b\xb4\x3e\x0d\x2b\xdb\xa0\x56\x31\x2a\xf4\x1e\x55\x2a\xf4\x7e\xe0\xb9\x32\xed\x4e\xec\xfd\xeb\xf9\xd5\x4a\xbd\xb2\xce\xd8\x56\x55\x4a\x87\xad\x80\xe8\x37\xa8\x83\x2c\x60\xf4\x2b\x1c\x31\x37\xc4\x50\x7c\xf1\xa9\xe0\x8b\x3f\xad\xe7\x8b\xb5\x97\xf0\x81\x8a\x52\x2e\xb8\x61\x64\xd9\xbf\x51\xde\x98\x49\xf4\xcc\x46\x8e\x3d\x71\x36\x99\xb2\xc5\x29\x29\x46\x13\x1c\x31\x13\x76\x6e\xa5\x3e\xba\x65\x7c\xed\x44\x58\xb4\xe8\x86\x1d\xe8\x88\x66\x95\x85\xfa\x10\xc0\x28\x74\xb2\x82\x5d\x20\x7f\x2d\x3c\xd0\x55\x9e\x56\x7d\x87\xe1\x39\x27\x70\x28\x9a\x74\x0e\xe2\xb1\xa7\xb9\x77\xd0\x16\x39\x88\x69\xe3\x18\xa4\x57\xee\xcf\x1b\xad\x3b\x15\xfb\x4b\x44\xe0\x69\x19\x40\x99\x1b\x73\xce\x9b\x23\x18\x24\xf8\x82\xc5\xff\x59\x36\x36\xc4\xbf\x32\x18\x4c\x70\x04\x73\xd7\x95\xef\x5e\xf3\xc9\x83\x12\xc6\xfd\x96\xb0\xcc\xcc\xd0\x36\xae\xa7\x96\x93\x51\x9b\x23\x94\x5e\xe0\x8c\xcc\xf3\x64\x71\x8a\x8b\x93\x34\xc5\xd9\xf3\xb3\x57\x2f\x83\xe5\xe7\xcf\x93\x62\x9a\x04\x8e\xfb\x5f\x8f\xf6\xfc\x7b\x07\x0e\xbb\x46\x64\x00\x30\x0e\x93\x9f\xfc\x7e\xf7\xe1\xfe\x3f\x92\xbb\x8f\x82\xae\xdf\x3b\xf8\x23\x6b\x67\x5b\xb9\x9a\x9e\x34\xd2\xd2\xbd\x6e\x30\x12\x01\x00\x1f\x01\x38\x07\x5b\xac\xfc\xd6\x2b\x2e\x17\x55\x8c\x48\x5c\xfa\xe4\xfd\x31\x9d\x62\x59\xc2\xef\xb3\x82\xfa\x6a\xf5\x6d\x8b\x80\xd2\x22\x16\x68\x6a\xad\xa8\x7b\x66\x38\xa8\xec\xee\x4b\xe2\xaf\xae\x7a\x14\x49\xf0\x59\x6c\xe3\x46\xe2\x6b\x87\x71\xa8\xa2\x53\x41\x2b\x19\xed\x95\xef\xb8\xa8\xd6\xab\x3b\xcc\x94\x90\xaf\x1f\x8f\x56\x7d\x98\xc4\x17\xa9\x38\x69\x5a\x4b\x6e\x5f\x69\xb2\xf8\x74\x1b\x79\x0e\xee\xb2\x60\x70\x19\xbd\x7d\x7f\x3b\x6e\x4e\x8e\x48\x1e\x1d\x23\x52\x84\xb8\xd7\x12\x97\x59\xc2\xdb\xb0\x7d\xd8\xe2\x0a\xa0\xd7\xd3\xa1\xeb\x1c\xbf\xfb\x70\x1f\x4f\x1d\xd8\xe4\x61\x34\x45\x37\x7c\x9d\xba\x7e\x6f\xf3\x0c\xa7\xe8\x66\xb7\x36\xcb\x6d\x27\x09\x59\x68\x30\x06\x8b\x36\x75\xd8\x87\x16\x2d\xd8\xaf\xdd\xff\xf2\x35\x28\xe5\x2a\x09\x64\x12\x2c\xd5\xe0\x7b\xf8\xde\x37\x0e\xbe\xe7\x6f\x35\x7a\x18\x61\x3a\xa0\x7d\xdf\x4e\xd0\xfc\x36\x8b\xaf\x50\x81\xc5\x80\xde\xf0\x8b\x3a\x4a\xb0\x3e\x09\x82\xf5\x6e\x3b\x45\x8e\x49\xa5\xb4\xce\x26\xd6\xba\x16\xe4\xba\x88\xd1\xaa\x8a\xce\xc6\xce\xab\x21\x74\x36\x3c\xab\x06\xa7\x6f\x23\x9b\xbe\x45\xba\xfc\xa8\xef\x07\x5c\x7f\xa3\xb5\x3b\x4d\x66\xdc\x92\x1c\x4e\xa5\xa6\xc7\xb6\xe0\xe6\x9a\x9e\x29\x0f\xe9\x65\xd0\xc8\xed\xd4\x3a\x8d\x94\xd2\xb2\xf7\x55\x54\xf3\x16\x5a\x1f\xd3\x8c\x37\x68\xf0\xc0\xa9\xd6\x7d\x8b\x6c\xf4\x9a\x5a\xfb\x29\xe2\xba\xcf\xa1\x1e\x64\x10\x41\x51\x26\x50\x0b\x36\xe9\x4f\x02\x69\x87\x88\x2b\xa6\xdb\xab\x15\xee\x72\x53\x56\xf6\xc4\xf9\x78\x40\xcf\x7d\x83\x82\x8a\x54\x15\x54\x82\x4e\x10\x53\x39\x65\x0f\xb1\xae\xa1\x8a\xab\x1a\xaa\xdc\x60\xea\x67\xa6\x86\xea\xaa\x84\x17\x1c\xdb\xbf\x6b\xd3\x50\xbd\xf9\x4e\x97\x32\x9b\xc2\x99\x6f\xa1\x68\x32\x89\x40\xa3\x96\x48\x8a\x68\x9d\x3b\xf6\x12\x29\xe1\xaa\x2a\xdb\x9a\x62\x59\xd9\xaa\x93\xd9\xb2\xd9\xc2\x52\xd5\x6c\x3d\x86\x86\xa0\xea\x22\xb2\x90\x16\xd4\xb7\x6e\x4c\x0b\xeb\x96\x90\xb9\x75\xfd\x5a\x66\x83\x26\xb5\xce\x6d\x67\x58\x53\xec\xdc\x5e\x98\xbd\xbf\x4e\x98\xbd\x7f\x3b\x61\xb6\xf7\xa8\xcb\x42\xf5\xdf\xdf\x24\xc9\xf6\xfc\xee\x7e\x55\x16\xf2\xbb\xfb\x65\x59\x3d\x81\x15\x30\xa8\x49\xbb\x95\x1e\xff\x52\xa2\xee\x6d\x85\xd8\xb6\x45\xfd\x57\x4a\x98\x62\xdf\xb4\x8c\xf9\xce\x8c\x39\x7a\x86\xcc\x3c\x71\x86\xe7\xc3\x18\x71\x8f\xaf\xd7\xe8\xfb\x25\xc9\x32\x7c\xb1\x54\x6a\x1c\x50\x21\xed\x9c\x50\x32\xd2\xee\x19\x0e\x5a\x86\x33\x16\x77\x5d\x48\x95\x1d\x79\xaa\x4d\x88\xbf\x6b\x76\x28\xe5\xd8\xc3\x5d\x33\x44\xf2\x27\xf6\xa4\x1c\x37\x86\x00\xc0\xd1\x3a\xff\x10\xba\xbe\x75\x17\x11\xd3\xf1\x43\x35\xda\xde\xf5\xb0\x6c\xe5\x06\xf2\xed\x72\x2d\xb5\xd9\xf9\x8f\x1a\xed\xfc\x63\x38\x32\x4c\xa7\x8d\x04\x47\x23\x69\xe7\x8f\xc4\x76\x8c\xc4\x76\xb0\xc4\x47\x7c\x63\x46\xda\xd6\x1f\xa9\x3d\x1a\xa9\x3d\xa2\x6f\xe5\xb3\x92\x07\xe7\x00\x12\xab\x4c\x9b\x64\xb7\x8d\x9c\x8f\xba\x28\x2f\x70\x16\xe7\x97\xb5\xf1\x82\x12\x3a\xff\xdf\xff\xf5\x7f\x3b\xd0\xf9\x87\x63\x0a\x7e\x9f\x6f\x93\x04\xa9\xd1\xf8\x52\xa1\xfd\x66\xa3\x52\x43\xc8\xea\x19\x42\x8c\x75\xd9\xb1\x2e\x01\x49\x79\x1b\x03\x50\x4d\x4a\x1b\x4a\x1a\x44\xb3\x04\x6b\x08\x9e\xb3\x29\xb3\x47\x3b\x69\x53\xf4\x89\x43\x04\x7d\x52\xf6\xfe\x94\xf2\x89\xdd\x61\xbd\x6d\x33\xcc\x8a\xc6\x8c\x64\x53\xee\x49\x55\x02\xef\xb5\x10\x3f\x5e\xdd\x5e\xfc\xb0\x95\x64\x62\xfc\xca\x2d\xa2\xe1\x1e\xd9\xf4\xc4\xe4\x76\x83\x80\x23\x29\x99\xb3\xae\x45\x2e\x30\x51\x4e\xb5\x1b\xd3\x1b\x8c\xb7\x69\xa5\x89\xa3\xc8\x85\x61\x90\x28\xcc\x0f\x14\x96\x8c\x98\xbf\x97\x17\x85\x23\xc5\x6b\xab\x43\x47\x1f\x4d\xd6\x42\xea\x87\xd6\xa0\xa8\x91\xc6\x4f\x6a\x2c\x6a\x08\xed\x98\xe7\xb3\x21\x87\x38\x86\x31\xa5\x13\x44\xeb\x74\x40\x70\xe4\xba\xc4\x72\xfb\xd9\x49\xe8\x1b\x6e\x22\x88\x23\x18\xd1\x5f\xbc\x29\xc3\x51\x62\xac\x1c\x25\x88\xe9\xe0\x03\x97\x02\xc6\x88\x44\x3f\x2a\x57\x11\xe9\xca\xc7\x72\x30\x96\x7b\x34\x04\x4a\x10\x59\x4a\xe8\x25\x0a\x4b\x29\x20\x26\x1a\xe5\x71\x60\x26\x02\xdf\x29\x38\x26\x9a\xe8\x28\x78\x26\x0a\xf1\x94\x1a\xb1\x19\x58\xe6\x64\x1b\xf5\x52\x55\x1f\xa2\xae\xa1\x78\xc4\x1b\x16\x9b\xaa\xc3\x94\x21\x9b\xcf\x5f\xf3\xa9\xab\x58\x7c\x35\xe9\xb3\x64\x64\x15\x16\x66\xa5\x29\xbe\x0a\x15\x76\xf6\xee\xcf\x6e\x40\x87\xdd\x8d\xf1\xab\x31\x8b\x1d\x6d\xad\xd5\xab\xd4\xe2\x5b\xdd\x5e\xa1\x47\xd9\x49\x59\xc3\xef\x3e\xdc\x07\xeb\x17\x45\x02\x92\x68\x71\x8d\xa2\x44\xd3\x63\x7d\x7b\x39\xfc\xce\xd7\x97\x1a\x09\x8a\x70\x58\xbd\x66\xa5\x5f\xe3\xec\x7b\x7b\xb3\x1b\xd8\xd9\xf3\xad\x15\xab\x73\xf1\x6b\xea\xf6\x1e\x56\x56\xdb\x71\xef\xc8\x63\xba\xb6\x9e\x5f\x5b\xf3\xdb\x74\xfb\xb0\x5a\xdb\xce\x22\xf6\x2d\x4b\x71\xff\x0f\x2c\x05\xab\x4b\x47\x76\xcb\xa5\x60\xf5\x76\x1f\x34\x4c\xa6\x6e\xd5\xa4\x48\xd2\x2b\x41\x92\x0e\xd1\x9f\x9d\x5d\x56\xb2\x6c\x1b\xb2\xcb\x46\xf1\xd5\x56\xa9\x65\x39\x86\x6b\xca\x27\xab\x35\x75\x4d\xf1\x62\x25\xf6\x5c\x84\xa9\xe9\x45\x07\xcf\x75\xd9\x85\xeb\x2e\x58\xdc\x58\x41\x40\x6f\xf4\x00\xaf\xfb\x7c\xdb\x03\x1e\xc3\x40\x61\xd5\x4b\x5d\xfb\xd8\x75\x8f\x59\x30\x03\x96\x6c\xf6\xc8\xc8\x12\xfb\x49\xb7\x73\xd4\x77\xf2\x02\x51\xf6\x24\x72\x82\x23\xf8\x36\xfc\x73\x64\x01\x43\xc7\xa7\x39\xf7\xcd\xee\xdd\x22\x27\xac\x91\x00\xf6\x9d\xe9\x87\x5e\x0f\x40\xb3\xa3\xae\x70\x08\xe5\x86\x8f\xc4\xf8\x29\x40\x1d\xa3\xd1\xc4\x23\x76\x82\xf3\x78\x4c\x79\xfa\x0f\x6c\xbe\x05\x1c\x08\xad\x16\x74\x4e\x59\xba\x64\xca\x49\x08\xff\x30\xab\x94\xfa\xda\x2f\x44\x9a\x7b\x2e\xcc\x17\x07\xa9\xeb\x8a\x10\xf8\x15\x05\x9f\xeb\x7a\x38\xdc\xf1\x79\x64\x7d\x4c\xff\x79\x13\xbe\x1b\xf8\x43\x78\x16\xbe\x1b\xf4\x86\xf0\xf5\x77\x9d\xd6\xfa\x39\xb9\xee\x02\x79\x62\xe4\x70\xc7\x07\x6a\x6c\x72\x68\x9f\xc3\xd7\x74\x68\xaf\xc2\xd7\x74\x68\x27\x55\xcf\xff\xc3\xf0\x84\x7e\x7e\x19\x9e\xd0\xcf\x5f\x35\xc0\x5d\xf4\x2f\x82\xc3\x83\xb1\xeb\x7e\x75\xdd\x97\x2c\x09\x05\x1d\xfd\x93\x35\x21\xad\x5e\x89\xe0\x92\x83\x21\x80\x4f\xc3\xa5\xa5\xdc\x79\x03\x2b\x5e\xdc\xc1\x99\x70\x41\xca\xcd\xac\xb0\x9c\x6a\x4f\x24\xbd\xf8\xac\xa8\xfb\x57\x43\xdb\x79\x05\x0d\x58\x0b\xce\xe5\xcd\x92\xe7\xe4\x2c\x97\x0d\xcf\xa8\xcc\x99\x26\xa1\xb0\x05\xab\xd5\x4d\xcd\x91\x14\x2c\x5f\x4a\x8f\x50\xe6\xf8\x1f\xac\x9d\x59\x4f\xce\x4c\xc6\x0d\x08\x9e\xd4\xdd\x26\x59\x93\x3e\xf3\x8d\xbe\x88\x29\xaf\x21\xe2\xc0\x08\xb7\x4b\xc5\x8a\x5c\x42\x71\x08\x82\x4f\x65\x1b\x6b\xd9\xe0\x42\xfd\xb4\x7e\xdb\x37\xda\x46\xf4\x8d\x21\x47\x2f\x3b\x61\x78\xc3\x32\x08\x8b\xd3\x59\x93\x84\x6f\xa8\xe0\x7b\x55\x49\xe0\x2b\xb8\xb8\xb7\x00\x12\x93\x91\x7b\xd9\x9e\x6d\xc6\x72\xe4\xa3\xff\x3e\xd1\x51\x45\x47\x24\x99\x4f\xd3\x66\xbf\x40\xc3\x9d\x4b\x8b\x87\xea\xde\x50\x39\x9c\xc9\x08\xe3\xe2\x52\xac\x20\x33\xc5\x77\xbd\x26\xd9\x14\x25\xb6\xd1\xbe\xf8\xf4\x58\x45\x12\xb5\x58\x34\x5d\xf2\x91\x5d\xf0\x7e\xbb\xab\x5d\x59\x91\xc4\x04\x1b\x49\x09\xdf\xa1\x20\x7c\x5f\xbf\x33\xe1\x6b\xbe\x02\x9a\xdd\x52\x47\xa4\x44\x37\x45\x61\xda\x04\xb7\xcd\xa4\xe2\xb6\xea\xa2\x26\x8a\x60\x0b\x79\x5b\x6b\x90\x64\x35\xa3\xd1\xdb\xaa\xac\xfe\xa0\x32\xc9\x93\xad\x87\x61\x38\x92\x4b\xb8\x5a\x39\x92\xbd\xb3\xde\x03\x7a\xa0\x54\x0a\xb2\x7f\x99\x62\xc9\x10\x1c\x47\x4a\x70\x44\x76\x64\x08\xad\x7a\x72\x3a\x3c\xbe\xdd\xf7\x30\x27\x08\x88\x81\x27\x9e\xfc\x69\x6a\xa5\x11\x9a\x31\x2d\x45\xfd\x62\x5f\x1f\xea\x7b\x1a\x7f\xfc\x39\xca\x23\x25\x67\x9a\xc2\x67\x0b\x86\xb9\x6f\xa5\x2d\x35\x72\x3f\xf4\xee\x5b\x89\x1e\x7a\xf7\x2d\xb1\xb6\x51\x83\x54\xd7\x07\x3d\xc7\xc9\x0c\x67\x67\xf8\x86\x29\xb8\xbf\x0a\x44\xf4\x14\x85\xa9\xb7\xff\xe8\xde\x3e\x80\x8f\xe9\x63\xcf\xf7\xf7\x0c\xd5\xf7\x17\x2b\xde\xa9\x43\xce\xbf\x50\xb6\x22\x0c\xe9\x9e\x3d\x66\x9b\x46\xc1\x97\x47\x29\x0a\x8b\x3e\x0e\xc3\xb0\x08\x4e\x79\x46\x2e\x0c\x28\xa9\xe5\xcf\x05\x57\x94\x7f\xb8\x4d\x78\x33\xae\xe5\xd6\x81\xcd\x78\x2c\x2e\x19\xd5\x4c\x7a\x32\x18\x48\x32\x37\x90\xe4\xdc\x42\x92\x2c\x8e\x99\x11\xf7\xa3\xca\xe8\xb3\x1f\x94\x38\xf1\x10\x3f\x94\xd3\x3f\x19\x99\x29\x13\x26\x66\xc0\xb1\xa9\xbc\x46\x3f\x89\xe0\x55\x98\x76\x5f\xe1\x74\xce\x23\x95\x5d\x68\xf4\x7b\xd5\x5f\x96\xc1\x15\x63\xf8\xd9\x9d\xd3\x2c\xe1\x19\x22\x58\x00\xb2\x6b\x1d\x80\xec\xc6\x0c\x40\x76\x6c\xa4\x93\xb8\x34\x02\x90\xf1\x28\x65\x6f\x66\x38\xe5\x31\xca\xe8\xc3\x27\x33\xd4\xd8\x5b\x15\x6a\x8c\xcf\xef\x5d\x98\x76\x39\x0f\xf8\x84\x4f\x8c\x8f\xef\x8d\x1e\xdf\x3b\x3a\xbe\x77\x2c\x60\x99\x8c\xde\x07\x5f\x53\x52\xc1\xfd\x09\x44\x2c\x3c\x16\xb2\x4c\x92\x80\x57\xba\xf6\x67\x53\x92\xf8\x5c\xcb\xe7\xa0\xb7\xcf\x0e\x27\xa6\x36\x6e\x9b\x4c\x0e\xed\xd1\xc5\xcc\xcd\x72\xa0\x63\x6d\x95\x1d\x36\x4c\x6c\x93\x03\x1d\xb5\x49\xd2\xa6\x60\x96\x6c\x11\x42\x4c\xe6\x7e\xd0\x21\xc4\xde\xf0\x34\x0d\x2a\x5b\x43\x25\x5c\x98\x1c\x6d\x7d\xf1\x1d\xe8\xc8\x85\xae\x46\x03\xb3\x84\x9e\x43\xba\x96\x59\x26\xf0\x1d\xa3\x6f\xf4\x78\xbf\x96\x81\x6b\x82\x91\x88\xb5\x2c\x78\xfc\x12\xc0\x97\xb4\xca\x27\x16\x8b\xf3\x10\xee\xd5\x53\x3a\x54\x82\xd4\x3e\x36\x99\x7c\xfe\xea\x4b\xf8\x98\xd6\xf8\x10\x3e\xa6\x35\x6a\x01\xc8\x8e\x6a\x01\xc8\x78\x65\x00\x7f\x0d\xdf\xd3\x8a\xcf\xc3\xf7\xb4\xe2\xef\x55\xf1\xe1\xe7\xf0\x77\xfa\xf9\x97\xf0\x77\xfa\xf9\x99\x19\x3e\x77\x22\x92\x37\x9c\x4c\x67\x38\x63\x1c\xde\x73\x94\x46\x09\xf6\x9e\xc1\x7a\x22\x07\xae\x88\x34\x39\xe9\x2f\x32\xe2\x50\x09\x53\x12\xe1\xe0\xa9\x1a\x21\x67\x86\xbf\xb2\x80\xa0\x5f\x44\xf0\xa7\xe6\xf0\x51\xc8\x75\xbf\xb8\xae\x6e\x09\xc0\x01\x82\x5f\x86\x6b\xd3\x72\x7d\x31\xc2\x9f\xf2\x4c\x5c\x5f\x40\xf7\x02\xcb\x64\x6c\x8f\x17\x27\x91\x37\x05\x07\xf1\x58\xdb\x44\x18\x0d\x5c\xe0\x82\x6f\x1b\xfb\xd9\x8d\xf3\x23\x92\x24\x68\xc6\x08\xb6\x1e\x87\x0a\x4c\xd9\x10\x2d\x75\xc4\xc3\xda\x15\x95\x60\xa9\x8d\xd1\x51\x55\x59\xae\x8d\x19\x4c\xe9\xe4\x18\xda\xff\x0d\x7e\x84\x2f\x8c\x9c\x6f\x14\xc7\xe3\xfe\xa9\xeb\x9e\x7a\x05\x08\x8e\x5d\xf7\xd8\x2b\x00\xbc\xb3\x5a\x79\xcf\xbd\x98\x5f\xf2\x7e\x31\xb3\xe5\x01\xf8\x8b\x87\x01\x28\x21\xc6\xa1\x21\xa2\x16\x84\xc7\xaa\x49\x00\x2c\xf0\xa6\x94\x72\x4c\xd8\xa6\x0b\xb5\x58\xad\x5e\x78\x3b\x3d\x3a\xa7\x05\x58\xa6\xa1\x1d\x03\xf4\x2b\xe8\x7f\x15\xc1\x88\x41\x30\x18\x8a\xe4\x73\x5f\x55\xc2\x3c\x11\x3c\x5c\x20\xac\x83\xdd\x5e\x18\x86\x59\x3f\xed\xce\xe6\xf9\xa4\xf2\x31\x48\xbb\xf9\x8c\xb5\x94\xc1\x1e\x28\x71\x92\x63\x96\x0d\xd2\x28\x73\x20\x7f\x89\xa0\x58\xae\x5b\x79\x41\xd7\xe5\xeb\x4e\x18\xa6\xae\xeb\x3d\xf1\x52\x00\x6f\x5c\x97\x0a\xd8\x38\xcb\xe3\xbc\xf0\x00\x7c\xc3\x68\x64\x97\xc7\xff\xa4\x27\x1f\x67\xc5\xc2\x2b\xe8\xe9\xcf\x2e\x70\xe1\xc0\xe5\x75\x16\x17\x14\x95\x05\x3b\xbe\x00\x56\x19\x03\x8b\x9f\xec\x73\xba\x59\x37\x5e\x01\x31\x0b\xb2\x0e\x53\x2c\x42\x05\x86\x5f\x5c\xd7\xbb\xd3\x3f\x0a\x7e\x06\x07\x11\x4e\x70\x81\x3b\x27\x03\x3b\x2c\xd6\x50\x86\x81\x1b\x0c\x21\x61\xba\x04\x6f\x81\x64\xcc\xa1\xaf\x25\x58\xad\xc6\xc0\x75\xbd\xb7\xfd\xdf\xc2\xb7\xde\x57\x10\x10\xa6\x0d\xe0\xc9\xdb\x70\x88\x71\x77\x8a\x66\xb6\xe6\x3d\x1e\x7b\x3b\x45\x37\xce\x7f\xa5\xed\x4b\xb6\x0f\x03\x60\xc4\x6e\x3d\xd0\x5b\xc9\xcb\x57\x77\xb0\x3d\x28\xd2\x1e\x00\x07\x5e\x1a\x7e\xed\xe6\x64\x8a\x9b\x38\x40\xca\x82\x14\xd0\xde\xc7\x12\x00\xe0\xba\x04\xbb\x6e\x86\xed\x7d\x96\x44\x85\x6f\xae\x97\x86\x5f\x90\xf7\xb5\x52\x5b\x54\xf5\x3e\x86\xb5\x5a\x06\xd3\x6f\x66\xb8\xc3\xf2\x52\x35\x67\x67\x97\x32\x88\x69\xdf\x29\xb2\xb9\xd2\x20\xa8\x18\x6a\x05\x0b\xc8\x2d\x63\x71\x99\xd3\xe1\x1c\x74\xd1\xbd\xc4\x0b\xd7\x2d\xba\xb3\x0c\xd3\xc3\xfa\x84\x23\x75\x0f\x40\x0d\x67\xac\xae\x09\x78\xec\x05\xe5\xa1\x20\xcb\x44\xe7\x90\x19\xbf\x17\x93\xc3\x09\x52\x01\x47\x62\x30\xfc\xaa\x89\xd3\x96\xc0\x9a\x7c\xc9\x38\x6f\x36\xfd\xdf\xc2\x45\x3f\xc3\xdd\x2f\x24\x4e\x3d\x07\x76\x1c\x10\x7c\xe4\x70\x10\x63\x98\xe0\xf0\xd7\x83\x9d\xd8\x75\xef\x30\x0c\xe9\x25\x38\xac\x1c\xff\x18\x6b\x55\xd0\x59\xff\x2c\x88\x38\x92\xe0\xb9\x21\x73\x1c\xbe\xe9\xc6\xd1\x6a\xe5\x9d\xf7\x59\x20\x0b\x25\x0e\x8a\x15\xdc\x55\xba\x85\x73\x20\x75\x30\x6d\x02\xd7\xc6\xf0\xcb\x1b\x23\xf9\xe5\x5c\x28\xcb\xbb\xbc\x73\xf5\x40\x59\x02\x98\x0f\x5e\x0d\xe1\x1c\x46\xae\x9b\x2b\x8e\x90\x0b\x3e\x1f\x74\x58\xe3\x18\x8b\x95\x3f\xe7\x19\x85\x65\xd0\x39\x25\x2f\x44\x15\x70\xe0\xdf\xf1\xcd\x0c\xa5\x11\x03\x17\xdc\x58\x60\x82\xf2\x19\x99\xcd\x67\x4e\xe0\x24\x71\x5e\xb0\xb8\x38\x26\xf7\x14\x10\xf3\x67\xc2\xa3\xdb\x0d\xa6\x30\xc7\x43\x2a\xf1\x15\x38\x93\xd1\x0e\x81\xd8\xc8\x8e\x03\x56\x2b\x05\x93\x32\x3a\x9c\x95\x8c\x66\xb5\xda\xed\xed\x84\xe1\xc0\xe9\x38\xd0\x39\xcc\x32\x72\xcd\xe2\xa0\xb2\x27\x11\x1d\x95\xa7\xa8\x1a\x1a\x38\xf6\x12\x2f\x98\xee\xb0\x0e\xb7\x2f\xbc\x1d\x9f\x65\x63\x92\xf9\x6f\x58\x8f\xd1\x6a\xf5\x89\x83\x84\xd9\x37\x8f\xe5\xcc\x17\xb1\xb9\x35\x45\x04\xad\x76\x6b\x21\xde\x76\x52\xec\xba\xd7\xbc\x89\x0d\x98\x17\x6f\x83\x79\xbf\x1a\x98\xf7\xda\xc3\x66\xd0\xb3\xcb\x12\xbe\x81\xcb\x38\x0a\x72\x5c\x1a\x44\xd7\x8e\x5e\x1d\x86\x78\xb5\x92\x81\x35\x55\xc8\x67\xec\xba\x3b\xb8\x5b\x64\xf1\xd4\x03\xa5\xf7\x1b\xf8\x3e\xd2\xf3\x6f\x0d\x8e\x01\xdc\xd8\xb7\x1a\x7f\xbc\x81\x90\x8a\xe3\xee\x00\x35\x65\x06\xeb\x4f\x61\xcd\x6a\xa4\x31\x10\x9e\x88\x80\xd7\x40\x26\x14\xcb\x62\x61\x1b\x60\x80\x10\xdf\x05\x49\xa7\xe3\xb1\xc7\xc0\x50\x45\x65\xc3\x78\x50\x0c\x0f\x9e\x78\xa9\x85\xac\x29\x79\xbd\x61\x09\x3e\xca\xd2\x0a\x33\xae\xcf\x79\xde\x4d\x19\xfb\xc8\x74\xdf\x46\xa8\x47\x54\xc2\x93\x86\x80\xe7\x33\xd8\x8c\x23\xe2\x11\x49\x61\x3e\x70\xe8\xdf\xba\xea\xf3\x15\x00\x43\x48\x81\x8e\x17\x64\xa2\x98\x8d\x33\xca\x7a\x57\xef\x52\xbd\x23\x71\x14\x38\x53\x9c\xce\x0d\xd4\xb7\x5a\x39\x8e\xcc\xd5\x72\x9c\x04\x5f\x20\x15\x2a\x82\x14\x43\x21\x79\xd8\xf1\xf6\x28\x87\x84\xe9\x2a\x5c\xc0\x25\xc5\x5c\x94\xcd\x63\x82\x45\x50\xf1\x52\x31\x71\xc5\x54\xe0\x2d\x85\x5d\xc4\x70\x69\x65\x96\x29\x73\xc7\x2f\xe1\x45\xd7\x6a\x0f\xc0\xb7\x68\x26\xf2\xe6\x99\xa6\xc8\x17\x5d\xfd\x1e\x2e\x2b\x61\xde\x95\x6e\x36\xc1\x25\xe4\xdc\x8a\x59\xbe\x6f\xfe\xe0\x8e\x54\x32\x66\x5f\x09\x20\xc2\xa6\xe6\xf8\x0e\x0a\x3f\x20\xf8\x9e\xe9\x85\x7e\x65\x5e\x35\x35\x70\x9f\x21\x6e\xb8\x1f\x38\xaf\x1e\x76\x7a\x7e\xb2\xdf\xd9\xef\xec\xef\xee\x7f\xa5\xc2\x90\x40\x64\x19\x99\x31\x64\x06\xe0\xaf\xdf\xc9\xee\x25\x62\xda\x06\x5b\x2f\x90\x9b\x7a\x81\xb9\x21\x2b\xdb\xd7\x8b\x5a\x56\x9e\xc3\x28\xdc\xde\x06\x26\x5a\x2f\xdd\x6a\xa9\xf1\x9b\x89\x27\xa7\x84\xeb\xe9\xa7\x32\x39\x17\xf4\x93\x0c\x46\x43\x88\x60\xec\xba\xc4\x20\x99\x4a\xc1\x15\x33\x8c\x92\xaf\x56\x59\x09\x23\x00\xa0\x56\x80\x34\xe7\x83\x4b\x5a\x1c\xc8\xd8\x81\x24\x6d\x07\x72\xc4\x8c\xf0\xac\x21\x88\x1c\x03\x74\x43\x9f\xa3\xb0\xd5\x7a\xa4\x14\x7c\x53\x63\xa8\x2b\x7e\xbd\xbe\x26\x36\x1a\x9c\xe7\x38\xe3\x32\x5c\xa3\x33\x92\xaf\xaf\x29\x7a\x0f\x54\x98\x41\x71\x89\xef\x98\xa1\xdc\xaa\x5e\xf6\xdb\x9b\xce\xfb\xfb\x6b\xfc\xf9\xf7\x41\x75\x44\xa5\x0a\xa6\xc6\x19\x12\xc7\xb8\x8b\xd1\xae\xe2\xa6\xf2\xb3\x1a\x1c\x11\x3a\xee\x40\x6e\xe2\xd0\xa9\xc4\x16\x63\xcd\xa7\xa4\xf0\x74\x11\xd0\xe1\x2c\x2a\xec\x34\x7e\xa1\xb3\x9e\x35\xac\x00\x6e\xca\x35\x3c\xa3\x78\x83\xf6\xe1\x3a\x15\x2b\xde\xbd\xfb\xa5\xd6\x7e\x36\x7c\xbf\xb7\x67\x59\x54\x6c\xe3\x2e\xd0\xdc\x86\x66\x17\xab\x61\xd5\xa6\x71\x5a\x0f\x75\x59\xe0\x9b\xe2\x8d\xf2\x33\xc3\x49\x12\xcf\xf2\x38\x77\xe0\xf5\x24\x2e\xf0\xe9\x0c\x8d\x58\x1c\x36\x9e\xa2\xb8\xc1\x1f\xcd\xd4\x14\x53\xd8\x6f\x36\x3f\x32\xbd\xe8\x9c\x11\x4a\x46\xde\xbe\xff\xdf\x9d\x5d\x6e\xc2\xd1\xe2\x35\x37\x6a\x36\xee\xa7\x7f\xae\x70\xa3\x02\x7c\x9d\x23\x80\xa4\x83\x96\x65\x48\x46\x98\xee\xa7\xf7\xc8\x8f\xf0\x05\x70\x78\x29\x71\x23\x2a\x92\x88\x3d\x14\x55\xd5\xc6\xa8\xd7\x06\x1d\x0f\x96\xca\x5f\x50\x18\x5a\x35\xa6\xbf\x12\xe1\xf6\xfc\xe6\xf9\xda\xb7\x72\x25\xfc\x5d\xe7\xf9\x92\xc8\xe7\x12\x41\xae\x01\xfb\xf9\x0f\xde\xc8\xd9\x74\x21\xd1\xe8\x3f\xee\xbf\x47\x81\x11\x63\xc7\x0e\xad\xf3\x3b\x12\x51\x75\x8c\x7c\x17\x51\xbb\xc1\x64\x93\xce\xb4\x91\x40\x54\x53\x29\x98\x57\x69\xe3\xdb\x5f\xa5\xd9\x17\x62\xa6\x6c\x3c\x87\x76\xe0\x78\xed\x64\xf4\x2b\x82\x7a\x08\xc6\x1d\x8e\x98\x43\x40\x94\x99\x21\x82\xd6\x1c\x82\x44\xdd\x7f\x2b\xa3\x44\xe1\x9e\xc4\x16\xae\x84\x23\x38\xef\xcf\x4d\x73\x0c\xde\xc7\xb2\x54\x57\x56\x11\xa7\x05\x3f\x1b\x5e\x4c\xa7\x9a\xd4\x31\xd5\xc3\x73\x64\xdc\x90\xbc\x66\xa0\xa7\x54\xaa\xde\xcf\xe2\x7e\xe4\x17\x14\x3e\x47\xf0\xd9\x1a\xc0\xf9\xad\xfe\xed\x48\x7e\xfb\xd8\x06\x54\x9d\xd4\xcb\x20\xe1\x60\x85\xc2\xcc\xb8\xd1\xa8\xfb\xf9\x65\xe6\x0d\x47\x66\xdc\x70\x64\xf6\xad\xc5\x48\xd7\x9c\xbb\x2e\x65\x34\xb2\x0a\x54\x8e\x35\xe4\x45\x14\x2a\x23\x38\x0b\xb3\x6e\x1c\xc1\x09\xfd\xc3\x80\x73\x2a\x9f\x38\x28\x5e\x85\x99\xf0\x1d\xbc\x90\x4f\x27\x11\x5c\xc8\x67\x3e\xe4\x73\xdd\xec\xa2\xef\x07\x0b\x78\x1d\x66\xc6\xa5\xc8\x4d\x98\xe9\x2b\x90\x63\x3d\x48\xca\xd9\xc3\xcb\x30\x13\xec\x3b\x3c\xd5\x9f\x2e\x5d\xf7\x12\x1e\x85\x99\xba\x0c\xf9\xc4\x9e\x19\xd7\xfd\x96\x3e\xf2\xac\xd7\x99\x75\xe7\xf1\x26\xcc\x9a\xee\x3c\xce\x58\x46\x33\x0e\x44\xaf\xf5\x48\xcf\x4c\xae\xec\x0c\x7e\xd6\x5c\x59\x06\x07\x9b\x2f\x2a\x36\x5d\x41\x44\x6d\x07\xd1\x72\x72\x64\x37\x13\x96\xbb\x63\xeb\x35\x05\x37\x81\xb0\x2e\x25\xaa\x57\x11\x1b\xef\x1f\x8c\x5b\x86\x57\xe1\x69\xff\x57\x14\xdc\x41\xf0\xc4\xc0\x06\xd9\xd6\xd8\x40\x5f\x6a\xbf\x86\x87\xe1\x64\xb5\x5a\xca\xd5\x0c\x9e\x21\x4d\x74\xab\x27\xe3\x0d\x82\x4b\xee\x41\x79\x65\x7a\x50\x9e\x53\xc9\x9a\x13\x89\xdf\x50\x39\x38\x19\xb6\x20\x9b\xc3\x56\x64\xf3\x6a\x3d\xae\x49\x2a\x18\x66\xac\x30\xcc\x89\x89\x59\xa0\x5c\xf2\xe0\xb8\x84\xa7\x7d\x2a\xb4\xcd\xca\x60\xa9\xa0\x21\x88\xa1\xb9\xf1\xc1\x08\x8a\x6d\x0c\x2e\xa0\xda\x39\x96\x7b\x97\x0b\x70\x47\x50\x90\xc8\x4f\x5c\xb6\x7b\x0b\x8d\x5d\x0a\xde\xc1\xfa\x2e\x05\xa6\xc0\x38\x2b\xe1\x1b\x50\xc2\x29\x54\xa1\xcb\xa6\x7d\xcf\x87\x4f\xb9\x55\xcd\x39\xca\xf1\x91\x78\x9f\xc3\x14\x5f\xcb\x1f\x53\x85\x23\xf4\x84\xd3\x12\x04\x79\x09\x27\xfd\x49\x3b\xda\x24\x25\xfc\xcc\xd1\xe6\xc7\x3a\xda\x14\xc2\xd9\x0b\x7d\x5d\xff\x8b\x89\x3f\x35\xe6\xfc\x28\x30\x27\x8e\x43\x0d\x13\x97\x48\xee\xef\x91\x01\x1d\x6f\x50\x09\x8b\x78\x2b\xba\x6b\x65\xb6\xaa\xde\x08\xd7\x3d\xa3\xb7\xbc\x13\xe6\x16\xa3\x96\x1f\xb4\xb6\x18\xe5\xfe\xd0\xd6\xb5\xf1\xcc\x94\x06\x9b\xac\x40\xb9\x61\x46\x93\x05\xa8\x7d\x05\x2f\x13\x5b\x99\x76\xa3\x4d\xb6\xa0\x13\x55\x83\x5d\x14\x9b\xa6\xa3\xc7\x3c\xab\xd6\x25\xe5\x3d\x94\x71\x2d\x6f\xf7\xd4\xe6\x27\x8e\x64\x11\xfe\xf3\x93\x29\xb3\xbe\x55\xce\xe1\xef\x2c\xe7\xef\x37\x7a\x30\xef\x5c\x97\xdf\x13\xb3\xab\xeb\xd7\xfa\xea\xfa\xb3\x79\x75\xfd\xca\xb8\xae\x3e\xa9\x64\xc5\x3a\x34\x8d\x56\x5f\xea\x96\x0f\x5d\xf7\x90\xe5\xb6\x62\x49\xb1\x9e\x18\x49\xb1\x9e\x1a\x89\xb0\x1e\x1b\x89\xb0\xbe\x84\xa9\x94\x42\x3f\xe8\x76\xbe\xb8\xee\x17\x78\x47\x5d\x79\xf3\x69\xbe\x97\x2e\xea\xbf\xaa\x54\x58\xcf\x0d\x01\xfd\x77\xbd\xe9\xcf\x4d\x52\xf0\x9c\x67\x43\x32\x2e\xb3\xd7\x64\xc7\xda\xd6\x62\x76\x4d\xa2\x2c\x61\x8d\xd4\x00\x1e\x15\x53\x5a\x0d\x0a\x35\x6b\x5a\x46\x6d\x2a\x40\x50\xa5\x3b\x27\x2d\x89\xb5\x24\x3d\xda\x3a\xaf\x96\x9c\x7c\x35\x6f\x96\xb2\xda\xaa\x25\xca\x6a\x4c\x8f\x25\x98\x31\xc7\xd8\xb2\xb5\xd7\xe2\xbf\x84\xcb\xf2\x20\x1e\x7b\x96\x0d\xd5\xef\xae\xeb\x5d\x1a\xb9\xfe\x2e\x85\x53\x8c\xeb\x7a\xbf\x48\xc7\x7d\xf5\x12\xc0\xb7\xc2\xc4\xf7\x19\xfc\x4d\xde\xa8\x79\xcf\x42\xae\xbf\xbd\xec\xf3\x56\x82\x4b\xed\x7a\x67\xb4\xfc\xac\xff\x2c\x78\x79\xf0\x0b\x3f\x2b\xe1\x26\x35\xcb\x5b\xf8\x9b\xeb\x3a\xff\xef\xff\xf3\x0f\x07\x94\x1f\x5c\xd7\xbb\xe3\xba\x77\x04\x9b\xb3\x5a\x79\xbf\x74\x63\x89\x72\x00\xfc\xa5\x29\x99\x9f\xfc\xca\x10\xe9\xc7\xf0\xda\x75\x8f\xfb\x3a\xe8\xfe\x31\x74\x76\x39\x34\xec\xb2\x80\x0b\xf2\x0a\x05\xbe\x08\xdf\xd6\x4b\xf2\x0d\x56\x65\x30\x0e\x71\x3c\xf8\x7d\x08\x0b\x5c\x9b\x06\xae\x65\xdb\xb1\xd2\xea\x7c\xb4\xd3\xea\x90\xf6\xb4\x3a\x63\xc3\x36\xf2\xdc\xf0\xb9\x7e\xc3\x75\xce\x67\x3c\x8f\xcd\x57\x95\x1d\xea\x89\xca\x0e\xf5\x14\xca\xf4\x51\x8f\x39\x61\x7e\x2f\x14\xf5\xbf\xc2\x38\x0a\x8e\xa1\x4a\x4e\xf5\x49\x5e\x0b\xbc\xd6\x9a\xea\xcf\x4a\x69\xff\xca\x4a\xab\x73\x62\x32\x07\xa7\x25\xfc\x05\x1e\x81\x56\x95\xd9\x4b\xb4\xcd\x65\xd2\xdc\x50\x78\x4d\x84\x95\xd7\x95\x35\x6b\xd3\x08\xf9\x46\xc4\x58\x50\x06\x5a\x2f\x85\x2c\x1e\x29\x3e\xe4\xf7\x12\xfe\x0c\xe0\xdb\xba\x5b\xe7\x89\x31\x9e\x49\x31\x4d\x9e\x92\x8c\xae\x43\x14\xbc\x28\x21\x83\x69\xf8\xa1\x76\xaf\xf0\x02\x6d\xd8\x48\xb6\x96\x92\x77\x79\xa1\x97\x98\x9b\xb6\xe3\x12\xde\x01\x30\x01\x41\x81\xe1\x75\x7d\x44\x4f\x90\xa5\xd6\xfe\x58\xc2\x0b\x00\xaf\x4d\x15\x6e\x1a\x57\x8d\x7f\x2d\xa3\x58\xee\x8b\xce\xc2\xc5\x03\xaf\x88\x45\xea\xb2\x38\x4c\xbd\x7b\x3f\xec\x3f\x04\x90\xb0\xc7\x07\x0f\x00\x44\xf4\x69\xef\xfe\xfe\x0f\x00\xc6\x71\x58\x33\x95\xd7\xf7\xab\x66\x06\xf0\x50\x5c\x04\xe5\x98\x6e\x79\x41\x28\x1c\xbd\x19\xaf\x56\xcb\xcf\x9f\x67\xf4\xf7\xe7\xcf\xc1\x60\x58\xc6\x29\x45\xfa\x23\x4c\xc6\x3c\xc1\x8e\xeb\x56\xcc\x21\xba\xaa\x78\x58\x94\xab\x95\xfd\x55\x25\xed\xe9\xc4\x69\xa7\x00\xa2\xc7\x99\xec\xae\x3b\x41\xf9\x9b\xeb\x54\x5e\x42\x75\x47\x28\x49\xd8\x20\x65\x12\xf2\x62\x90\x0e\x41\x09\x31\x7b\xa9\x0c\x3e\xec\xf9\x50\x6c\x27\xdf\xe8\x6c\x6d\xa9\xb2\xb7\x4b\x8d\x6b\xf5\xb3\xc5\x0c\xf3\xab\x75\x87\xb1\x81\x1d\x7c\x53\xe0\x34\xca\x3b\x6c\x6b\x3b\xce\x5d\x61\x88\x97\x82\xbb\x4e\x27\xce\x3b\x29\x29\x3a\xa8\xc3\x76\x2b\x9b\x8f\x0a\x92\x75\x48\xc6\x6e\xb2\x1c\xc3\xfa\x2f\xf3\xc0\xb2\x98\xc4\x79\xd7\x28\x17\x16\x25\x1f\x34\x34\xa6\x2b\x70\x68\x98\xf6\xc5\x42\x08\xef\xb1\x14\x04\x5e\x66\x16\xd3\xcf\x94\x61\xed\x64\xa0\x2c\x3d\x00\x93\xd8\xd2\xd6\x1a\x42\xb2\xbe\x1d\x12\x4b\x38\x89\x73\x58\x80\xd5\x8a\x3e\xe8\x8c\xf0\x13\x66\x39\x44\x39\xed\x27\x31\x4a\xc8\x45\x58\x33\x20\xea\x50\xbe\xa1\x10\x99\xb8\x23\x56\x88\x16\xc7\x51\xb0\xe3\xb3\x64\x5c\xa2\x0d\xc6\xb7\x7f\x43\x23\xbd\x5a\x23\x6c\x37\x36\xb4\xc1\xf0\x46\x63\x13\xef\x67\x09\x41\xd1\xd3\x38\xb1\xcd\x68\x64\x06\x2a\x2b\x23\x5b\x77\x1c\x27\x38\x97\x39\xa8\xf4\x9d\x1a\xcf\x1e\x45\xdb\x78\x87\x51\x84\xb3\x03\x2a\x43\xd3\x66\x9b\x2c\x73\xcc\x61\x15\x28\xbf\x3c\x22\xe9\x38\x66\x9e\x7b\xbc\x8f\x0c\xe7\xf3\x84\x39\xeb\x65\xcc\xec\xf0\x30\xa7\xa7\xd8\x2b\x06\xfe\x90\xd9\xa8\xc8\xa9\x33\x4c\xfc\x2d\x1d\x48\xfb\x04\xd5\xd4\xe9\xfc\x7c\x1a\x17\x67\x28\xbf\x6c\x58\x45\x1c\xa6\xb0\x08\xe5\x45\x77\x0d\x33\xd4\x0e\x14\x3b\xb4\x0c\x94\x60\x06\x09\x44\x30\x0e\x85\x20\xea\xc3\x9c\x49\x84\x96\x95\x57\xcf\x25\x74\x62\xfc\x7c\x11\x23\x57\x30\x7d\x2e\x61\x91\x2d\xf2\x60\x30\x84\x94\x9e\x0c\x86\xea\xf8\xa2\x70\x99\xe2\x9b\x22\x48\x3c\x1f\x40\x56\x37\x48\xbc\x1e\x15\xae\xe8\xe7\x20\xf1\xf6\x40\x09\xf5\x91\x56\xf7\xc4\xa7\x8b\xe9\x39\x49\x5c\xd7\x43\x03\xfe\xd8\x8d\x0b\x9c\xa1\x82\x64\xc3\x86\xa9\x53\xd0\x2f\x01\x44\xfa\x9c\x26\x1e\xaa\x5b\x58\x25\xf5\x57\x88\xcd\xad\x05\x6d\x3c\xc3\x29\xef\x93\xa2\x07\x94\xd0\x3d\x5e\x74\xf0\x0d\x1e\xcd\x8b\x38\xbd\xe8\x52\xbc\x40\x32\xef\x20\x3e\x00\x45\xb6\x60\xed\x84\x3d\x98\xb9\xae\x47\xc2\x3d\x17\x0d\xfc\x61\x9f\x02\x06\x9b\xa8\xf8\xc5\xba\x59\xad\x3c\x8f\x84\xf2\x13\x70\x5d\xc2\x4f\x72\x06\xa0\x0f\x82\xac\x4b\x17\x0c\xb8\xee\x8e\x47\x42\xf9\x05\xa2\x41\x6f\x08\x40\x37\x22\x29\x96\x66\x46\xe4\x20\xbf\x8e\x8b\xd1\xc4\xcb\x42\x1f\x12\xba\x54\xe1\x80\x77\x0b\x09\x07\x9d\x21\x80\xf4\x27\x58\x8e\x50\x8e\x3b\x7e\xc0\xfe\xf4\x02\x12\xa2\x83\xf3\x0c\xa3\xcb\x03\xf6\xe2\x7e\x20\x1a\x8c\x39\x2b\x77\xf7\xae\xf4\x9e\xa1\x9d\x42\xda\x25\x3d\x89\xbc\xf0\x7e\xa0\x4b\x65\x21\x2b\x80\xc2\x81\x3f\xa4\x54\xae\x88\xd3\x39\xe6\xc5\x1e\x06\x28\x8c\xbb\x54\xa8\x9e\x91\x99\x07\x60\xdc\xa5\xf0\xc1\x7f\xe8\xa2\xd2\x7c\x33\x1e\x7b\x3b\x74\x49\x3c\x12\xf2\x82\x40\x66\xad\xf6\x5d\x97\x0c\x88\xf8\xb5\xdb\x1b\x82\xd5\xea\x01\x15\x6a\x07\xfe\xd0\x75\xf7\xc4\x13\x00\xcb\x38\xf4\x55\xb3\x65\x3c\xf6\xee\x85\xb2\x90\xb7\x43\x56\x2b\x3a\xce\x9f\x08\xfb\x4d\x1f\x7f\x24\x83\x7b\xac\x96\xe0\x5d\xe9\x3b\xbe\x22\xb4\xee\x03\x55\x57\x7c\xff\x91\x42\xb8\x2e\x4d\x7f\x41\xb5\x86\xb4\x06\x31\x8b\xee\x59\x45\xf7\x86\x50\xac\xc3\x3c\x9f\x78\x08\x88\x4a\xf4\x03\xad\xb4\x61\x85\x4a\xa6\x48\xa5\x10\x80\x61\x0c\xca\x11\xa2\xdb\x8d\xc1\x12\x85\x83\x07\x10\x0f\x61\x16\xfa\xe5\x38\x4e\x51\x92\x2c\x96\x69\x48\x42\x9f\x8e\x66\x9f\xc1\x80\x80\x68\xa4\x0f\xaa\xda\x54\x7f\xd8\xa7\xaf\x25\xfb\xcb\x37\xd8\x2f\x4b\x6f\x80\x60\x42\x51\x57\xc9\x89\x8a\x65\x7a\x26\x60\xad\xe0\x33\x53\x20\xa5\x38\x46\x3e\x7a\x3a\xc9\x81\x0f\xf7\x20\xbc\x37\x04\x70\x70\x1f\x32\x5a\x29\x8d\xb6\x34\xfa\x62\x1d\x74\x99\x16\xad\xab\x31\x1f\x18\x1e\x08\x10\x55\xcd\x52\x44\xe4\x01\xde\x4c\x8d\x1c\x79\x00\x0e\xee\xc1\x7b\xa2\xd6\x5e\xa0\x10\xa1\x5d\xaf\x85\xb8\xf8\x9c\x47\x7d\x85\xf3\x1c\x5d\xe0\xc0\x71\xee\xe2\xd2\x6a\xf0\x9e\x68\x70\xb0\x37\x2c\x4b\x40\xd1\x30\xbe\xf6\xbc\x2c\x54\x1e\x72\x5e\x16\xbe\xcd\xc8\x34\xce\x31\x00\x96\x96\x06\x19\x14\x3b\xa6\x1b\x46\xf1\x43\xee\x11\x76\xb4\x99\x2d\x8d\xde\x4a\x0f\x83\xb2\x34\xf0\x96\x51\x9a\x6d\xe1\xda\xe2\xb9\xa2\x80\x07\x98\x21\x87\x7e\xaa\x92\xb6\x07\x5e\x21\x33\xb6\xc3\xa2\x63\xf0\x76\x59\xbf\x08\x18\xab\x61\x9b\xab\x60\xaf\x60\x66\x84\xdd\x62\x82\x53\x2f\x86\x09\x28\x73\x8f\xe1\x20\x9e\x09\x11\xc3\x62\xb5\x1a\x50\x2c\xc4\x66\xa1\x6f\x96\x31\x2c\x28\x05\xa1\x64\x8a\xed\x68\x58\x65\x04\xa0\x4d\xd4\xab\xeb\x0e\x0d\xda\xe7\x38\x25\x4c\x4b\x89\x90\x62\x2f\x85\x18\x40\x83\x47\x12\xea\xed\x3a\xdf\x6b\x00\x9a\x50\x3c\xb4\x06\x33\x65\xd6\x71\x8d\x77\xff\x24\x85\x4b\x65\xb6\xa8\x41\x4e\x73\x51\x32\x09\x9c\x0a\xaf\x59\xc4\x45\x82\x03\x87\x43\x36\xa3\x1f\x74\x32\x4e\x43\xda\xd6\xb8\xfb\x89\x5f\x81\xd4\x8d\x62\x5e\x65\x70\xc9\x94\xa1\xc6\xa9\x30\x97\x50\x29\x4f\x9b\x8f\x81\x21\x63\xed\xf8\x3a\x62\xa5\x93\x4f\x95\x71\xcb\x63\x34\xba\x8c\x32\x32\xe3\x53\xdb\xf1\xeb\xe3\x7b\x9a\xf1\x25\x91\x53\x61\xd3\xa8\x0f\xf5\x30\x5b\x67\x72\x68\x48\x87\xb8\x3b\x67\xfc\xda\x63\x66\xd9\x56\xb6\xda\x67\x2d\xd1\x68\x84\x67\x45\xe0\x74\x0b\x32\x4d\x1c\x21\x23\xd2\x89\xc4\x51\xe0\xf0\x36\x76\xe9\x60\x76\x47\x0c\x42\x1c\x2e\x03\x3b\x94\xc1\x73\xb4\x9c\x6b\xac\x8c\xe6\x13\xcb\xa6\x78\xb1\x5c\xb9\xa3\xe4\xc6\xa6\x2e\xea\xa3\xc5\x08\x2e\x95\xc5\x66\x20\x6c\xd4\xa4\x9c\xea\x28\x17\xa5\x86\x9a\x88\xee\xbb\xb5\x2e\x09\x1e\x17\x27\x23\x92\x96\x00\x3a\x7c\xac\x0e\x68\x00\x8a\x34\x96\xf7\x02\x0e\xc5\x98\x1d\x3e\x36\x11\x4d\xc2\x31\x34\x08\x3b\xbe\x0d\x00\x4c\x91\xe0\xec\xf9\x8e\x90\x61\x1b\x51\x6d\xe3\xca\xf1\x37\x65\xd3\x60\x50\xf3\xb6\xd3\x75\x69\x38\x30\x26\x70\x8a\x13\x23\x75\xc8\x25\x74\x8e\x78\x3a\x41\xb0\x6d\x6b\x9a\x6c\xc8\xc6\x94\x7f\x9b\xa3\x55\x0e\x7e\x18\x86\x8d\x53\x15\xdc\x43\x29\x41\xbb\x71\xb5\x47\x42\x4d\xe5\x74\x9c\xda\xb7\x1c\xd5\x8f\xa7\x81\xd1\x98\xce\xe7\x79\x1c\x61\x95\xbf\x6e\x1f\xdf\x6b\x3d\xb2\x8c\xb5\xac\x83\x49\x8c\x6c\x20\x61\xed\x9f\xa6\x68\x74\xf9\x18\x65\x70\x2a\x70\x65\x75\x00\x02\x87\x42\x6e\x89\x10\x34\xa1\xb3\x2a\xc2\x6a\xdb\xad\x96\x71\x11\x8d\xb6\x28\x6d\xa0\x44\xb0\xf4\x8a\xae\xba\x45\x91\xea\x8d\x3c\x5e\x1b\xa4\x46\xc2\xbc\xf4\xe1\xe3\x96\x24\xb8\x9b\xf3\x2c\x9b\x5e\x0f\x94\xd0\xc4\x17\xb2\x9c\xf0\x2c\xd6\x05\xef\x01\x11\xa8\x46\xae\x8d\x69\x32\x53\x0b\xf2\x18\xa1\xec\xb2\xa4\xb4\xdb\x4b\x84\x4a\x65\x1e\xff\x41\xcb\x37\x7e\x3f\x62\x19\x33\xe8\xfb\x11\x6e\xd3\x30\x6a\x49\x19\x84\x64\xba\x20\x71\x59\x10\x19\xf7\x03\xe3\x30\xed\x9e\x29\x47\x4d\x71\x6d\xc5\x2e\x57\x54\x50\x53\x75\xbb\x12\x86\xe1\xac\xef\x88\x4c\x2b\xfc\x92\x45\xaa\xf0\xed\xd8\xb3\x72\xd3\xd7\x85\x9f\xdd\x14\xcd\xc2\xd0\x78\x4b\x35\x77\x6d\x9c\x0e\x74\xe6\x46\xca\x22\x43\x45\xbd\x60\x6e\x58\xac\x5b\x00\xcf\xc3\x45\x37\xce\x59\x2b\xbf\xc6\x79\x7c\x9e\x60\x78\x1d\xca\x3c\xd4\xf2\xcd\x4d\xb8\xe8\x66\x78\x0c\x8f\xab\x7e\x53\x97\xe1\x31\x15\x6d\x4e\xc3\x63\xca\x7f\x1f\x99\x7e\x53\x37\xad\x9a\xcb\x67\x78\x2b\x33\xbe\x81\x31\xfe\x9a\x59\xdd\x04\x80\x21\x44\xf0\x92\x07\xa0\x32\x06\x2f\x4d\xdf\x43\x66\x5d\x40\x84\x11\xb7\x0e\x15\x35\x16\xe8\x2a\x81\x23\x23\x11\x52\x73\x76\x6e\xef\xda\x03\xf0\x94\x4e\x14\xc0\x91\xeb\x8e\x58\xbe\xf8\xa6\x24\xd3\xe7\x1e\x06\xae\x7b\xea\xed\xf8\x00\x46\xae\x1b\xa9\xc4\xf2\x47\x8a\x1e\xe9\x88\xb5\xfc\x6c\x8e\xea\xaa\x47\x9d\x37\xe6\x35\xe5\xfe\x99\x3f\xf0\x13\x95\x0a\x55\xd9\xc0\xa9\x52\xcf\x59\xb4\xd7\xe6\x62\x66\xda\x9f\x6a\x01\xbd\xac\x66\xae\x9a\xc3\xe4\x1a\x2d\xf2\xb5\xa5\xe1\xb9\xc0\x03\x4d\x51\x0f\xb6\x4b\x7d\x5b\x33\x26\xb4\xbe\xaa\xac\xb1\x3a\x4a\x42\x25\x6e\x82\xb2\x5e\xd4\x91\x15\x6a\xb6\x8b\x75\xcb\xc7\x4a\xa8\x85\x69\x1c\x45\xcc\x5c\xe1\x5b\xec\x2a\x55\x92\x58\x06\x76\xbb\x71\x9a\x1a\x99\x68\x44\x48\xf7\x4a\x62\x1b\x01\x9b\x46\x5a\x5c\x61\x91\x28\xfc\xa3\xc5\xf7\x8a\xf6\xf9\x65\x9c\x5e\x3a\x25\xf0\xe6\x02\x4b\x46\x7f\x2b\x96\xff\xa2\x8a\x65\x81\x12\xc6\xad\xea\x65\xcb\x87\x63\x27\x0c\xb1\xeb\xca\x34\xf9\x4c\x29\xa0\xb2\xea\x0b\x8d\xb3\x94\xd5\xa2\xad\x64\xb5\xb5\x22\x99\x81\xa1\xab\xd2\x1c\x7d\xd9\x10\xca\x25\xae\xf3\x37\x8a\x29\x9f\x3c\x70\x0c\xbc\x9b\x62\x58\x10\xca\x85\x92\x8b\x0c\xe7\x39\x3d\x31\x67\xf1\x93\xc7\x9d\x97\x14\x7b\xa4\x71\x7a\xe1\x34\xf1\x36\x14\xea\x66\x7f\x9f\x85\xbf\xea\x25\xcb\xe4\xbb\x9f\x82\xd9\x1f\xd2\x58\xc0\x34\x64\xbd\x3c\x46\xd9\x5d\xa7\xe3\xdc\x1d\x63\xcf\x28\x44\x25\x9a\xb7\x02\x7e\xa1\x2c\xf7\x39\x25\x05\x8b\x0e\x85\x23\xfd\x2e\x9b\xa7\x14\xa4\xf5\x8b\x7c\x3e\x1a\x61\xb3\xc4\x18\xc5\x09\x8e\xc0\xc1\xb6\xe7\x11\x33\x46\xa9\x7e\x02\x0f\x09\x34\x28\xf4\x38\xbe\xc1\x91\x63\xf8\x21\x35\xc8\xfd\x5f\x49\xb3\x24\x39\x8e\xed\xfe\x98\x62\xa5\x04\xb0\x65\x01\xba\xd3\xfa\x25\xec\x9d\x8c\x4a\xcc\x79\xc1\xe0\x31\x68\xad\x58\xd5\xe1\x34\x68\x09\x3e\x10\xc8\x2e\x64\x7e\x99\xe3\x39\xae\xb6\xc4\x5e\x36\x54\xca\x63\x2a\xbd\x6a\x61\x35\x68\xd1\x7d\x36\x54\x7d\x4e\x97\x11\xb1\xe8\x25\x46\x25\xfe\x06\x92\xf4\x8c\x5c\x5c\x24\xf8\x6d\xad\x80\xfd\xa5\xa1\xdd\x8f\x84\x0e\xe9\x1d\x1e\x67\x38\x9f\xd8\x35\xc5\xcb\xb5\x42\xdd\x34\xde\x22\xf2\xe8\x38\xc1\x37\xcf\x32\x72\x1d\xf4\x4a\xa1\x0d\xb3\x5e\x71\x80\x33\xa3\x6a\x4a\xe4\x14\x34\x24\xa4\xd4\xa5\x74\x32\x78\xbf\x7b\x2f\x77\xa0\x08\xfe\x88\xbb\xfc\xa1\x1b\x65\xe8\x1a\x67\x77\x55\x0f\xc6\x41\xa8\x7b\x51\x1c\x67\xaa\x98\x38\x1b\xf5\x32\xa7\xba\x8c\x38\x2e\xf5\x32\x47\x59\xf7\xd3\xe0\xa1\xef\x0f\x55\x51\x7e\x90\xea\x25\x3f\xa9\x92\x4c\xfc\x9c\x08\xc6\xea\xea\x6f\x62\xf2\x57\x25\x26\x17\xb1\x15\x3c\x02\x32\x7d\x82\xa4\x22\xf8\xda\x4b\x57\x2b\x2f\x6d\xbc\x2f\x20\x6d\xf7\x05\xd9\xad\xee\x0b\xb2\x6f\xba\x2f\x20\x9b\xef\x0b\x52\x71\x5f\x90\x6e\x73\x5f\x90\x85\xd9\x9a\xfb\x82\x12\x2e\xe2\xf0\xef\x1b\xe8\xbf\x6f\xa0\xff\xbe\x81\xfe\xfb\x06\x7a\xdd\x0d\x34\x3c\xff\x3e\x06\x50\x82\xcd\x69\x38\xb1\x17\x94\x55\x17\x03\x10\x7f\x6a\x81\x67\x39\x1a\x87\x44\xb6\xba\x88\xab\x37\xe3\x48\xdd\x8c\xa3\xc6\x9b\xf1\xc1\x7d\x28\x50\x7e\x97\x8e\x75\x30\xc3\x54\xee\xa0\xff\x5c\x61\x75\x3f\xcd\x14\xfa\x13\x94\x1f\x32\xaf\xc3\x33\x74\x9e\x60\xca\x05\xf7\x6f\xb0\x79\x4f\x8e\xec\xaf\xa0\xcb\x37\xa3\x1e\x19\xaa\x13\xe1\x12\x80\x40\xf6\x9b\xe1\x9c\x24\x57\xd8\x8b\x30\x18\xd6\x6e\xd8\x71\x88\xd4\x5d\x79\x88\xe9\xc9\x4d\x43\x4c\xc1\x2b\x0b\x31\x05\x1d\x12\xe2\xc1\xbd\x61\xf5\x1e\xdd\xe0\x8d\xa1\xc9\x5c\x07\x29\x14\x6c\x6c\x06\x8d\xe1\xaa\xcf\xa4\x04\x50\xde\xa6\x03\xc3\xae\xc9\x64\x63\xcd\xad\x32\x0c\xa4\x5a\x22\x2b\xb0\x2a\x7d\xa3\x4a\xce\xd7\x6c\xcd\xce\x8a\xca\x73\x5c\xdd\x4b\xac\xf6\x12\xb7\xed\xe5\x18\xd3\xcf\x4e\xb7\xfb\xcf\x0c\xe7\xf3\x29\x76\xe0\x72\x8a\x8b\x09\x89\x02\xe7\xed\xfb\x33\xa7\xac\xaf\xaf\x5c\x5d\x63\xda\x1e\x08\xfe\x0d\x03\x66\x4b\xf5\x8d\xe3\x55\xd2\xc9\x8e\x5c\xf2\xd2\xda\xbf\x26\xbb\x34\xbc\xed\x49\x6b\x3d\x5b\x9b\xac\x4e\x06\xf7\xe1\x14\x7b\xb8\xdd\x6a\x24\xc7\xc5\x59\x3c\xc5\x64\x5e\x78\xc6\x75\x97\x40\x09\x70\xdf\xf7\x9b\xa1\xf1\x09\x8b\x23\xf5\x6f\x98\xcd\xe2\xcf\x98\xcd\x2b\x72\xc5\xe6\x72\x46\x9e\x66\x24\x2d\xbe\x61\x4a\x8c\x5f\x84\x69\x3b\x12\xcc\xd4\xd4\xb2\xb6\xa9\x9d\x37\x4d\x2d\xd3\xa8\xc7\x42\x30\x30\x0d\x97\x25\x1c\xdc\x87\x14\x5b\x56\xad\x7b\x0a\x53\x0f\x33\xf0\x52\x2d\x93\x87\xaa\xbd\x14\x0c\x37\x2d\xc6\x63\x34\xba\xfc\x37\xad\xc5\xf5\x7f\xc6\x5a\xf0\xdb\xfe\xc3\x3a\x9a\xfe\xf6\x65\x09\x4d\x12\xdc\xb8\x36\x72\xe0\xe1\x4e\xaf\x42\x54\x8c\x9b\x58\xa3\x18\xa6\x22\x62\x95\xf4\xc1\x65\x9d\x58\x52\x06\xb1\x04\x4d\x47\x71\x8b\xa1\xff\x81\xfd\xec\x14\xae\x8b\xfb\x83\xfb\xf0\x86\xed\x6a\x30\xd8\xab\xee\x6c\xaa\xf7\xa2\x42\x46\x9b\x66\xe1\xc3\xca\x64\x03\xdc\x48\x4a\x53\x9b\x94\x02\xfe\x4b\x6d\xb1\x30\xc4\xd2\x84\x7a\x29\xec\xa3\x59\x8c\x19\xf8\x3b\x7b\x37\xa0\x52\x93\x49\xbe\x97\x79\x80\x70\xf7\xb5\x56\x29\xb2\xbb\xc2\xa9\x72\x32\x6f\x5c\xf6\xda\x80\x1d\xa7\x71\xc4\x11\x96\xcc\xc1\x4e\xcf\x30\xf2\xba\xba\xa5\xca\x54\x40\xd9\x76\xb6\x5e\xcf\x20\xf3\x09\xe5\x17\x5d\xff\xbc\xc6\xe7\x0d\x16\x3a\xb9\xf0\x4c\xaf\xbe\x9f\xc6\x35\x25\xa0\x36\x2d\x61\x2f\xed\xc5\xab\x94\x50\xaa\x5a\x53\xb1\xc7\x3f\x2b\xc5\x9e\xa5\x99\xb3\xf1\x79\x5d\x93\x58\x33\x86\x69\x52\x0c\xd6\xf9\xa9\x26\x23\xa8\x29\x8a\x53\x67\x4b\x43\xae\xb4\x5b\x10\x92\x9c\xa3\xac\xa1\xa1\x5f\x9a\xdb\xf8\x99\xf2\x0b\xc5\x24\x70\xfe\x69\xdc\xb7\xd4\x1c\x72\x32\xbe\xbc\x9b\xd6\xaf\xc9\x1c\x49\x77\x40\x4b\x36\xb5\xfe\x3e\xdd\xb8\x79\x17\x98\x2d\xe3\xd1\xf8\x22\xb8\xc0\x90\xa4\x9c\xec\x9b\xcb\xa8\x19\x01\x16\xc8\xed\x0a\x0b\x1a\x6a\x96\xa9\x90\x57\x55\x90\xd2\x97\xe6\x72\xf4\xcb\xa6\x49\x9d\x27\xd8\x29\xa1\x85\x12\x85\xfb\x42\x37\x21\x23\xa6\x18\x6d\x03\xf9\x57\x4c\x77\x2d\xcf\x62\x84\x47\x24\xc2\xef\xdf\x9d\x28\xe5\xae\x47\xb1\x11\xca\x46\x93\x6e\x3e\x3f\xcf\x8b\xcc\xbb\x47\xc7\x62\x9d\x54\x5c\x97\x38\x14\x34\x4b\xbb\xb1\x06\xba\x11\xe0\x4d\x94\x85\xc5\x5a\xac\xef\x15\x5c\x16\xc4\x02\x96\x46\xa5\x34\xbc\x5e\xaf\x8e\x16\x60\x1a\xe0\xee\x34\xbe\x89\xd3\x5c\xc1\x6d\x09\x80\x77\x1e\x83\x03\xcf\x87\x73\x81\x5a\xea\x01\xb4\xae\x63\x81\x06\x22\x32\x62\x57\x3b\xd5\x08\xb6\x0e\x9a\xcd\x58\xf6\x3f\x8f\xfd\x77\xf0\xff\x07\x00\x00\xff\xff\x5d\x5c\xd5\xa7\xeb\x7c\x06\x00"), }, "/index.js.LICENSE.txt": &vfsgen۰CompressedFileInfo{ name: "index.js.LICENSE.txt", - modTime: time.Date(2021, 9, 1, 11, 28, 9, 926935026, time.UTC), + modTime: time.Date(2022, 3, 24, 7, 23, 19, 947380642, time.UTC), uncompressedSize: 1277, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x91\xd1\x6e\xd4\x30\x10\x45\xdf\xfd\x15\xc3\x5b\x1b\x51\x27\x1b\xaa\x22\x21\x84\x16\xad\x8a\xb4\x88\x82\x44\xfa\x03\x8e\x3d\x49\x26\x9b\xf5\xac\x3c\x93\xad\xfa\xf7\xc8\x21\x0b\x7d\xe1\x07\xe8\xa3\x6f\x6e\x6e\xce\x89\xcb\xc2\x70\x3b\xa2\xd7\x1b\x27\x42\x7d\x34\x57\xfe\x1a\x1a\x8a\x21\x21\x34\x9c\x86\x59\xcc\x76\x22\x8f\x51\x10\x1e\xf6\x8f\xa6\x28\x8d\x29\x8b\x37\x06\xea\xaa\xae\xe0\xab\x13\x8e\xf0\x30\x4f\x13\xf5\x2e\xc2\xc7\x31\x9f\xed\x71\x3d\x6f\xdd\x99\x29\x3c\x71\x3a\x58\xcf\xc7\x4f\x06\xb6\x67\x4c\x42\x1c\xe1\xce\xde\xda\x6a\xdd\x2a\x0c\x14\xf0\x19\x5a\x54\xc5\x04\xae\x15\x4d\xce\x6b\x6e\xf1\x19\x13\xec\x9a\xc6\x1a\x58\x4a\x5b\xcf\xa7\xe7\x44\xfd\xa0\xf0\x63\xc2\x1e\xf6\xc2\x11\x23\x5c\x35\x13\xb7\x1c\xe4\xc0\x74\x0d\xe5\x25\xad\xab\xcd\xed\xcd\x29\xa1\x60\xd4\xe5\xe5\x27\x6c\x85\x14\x61\x50\x3d\xc9\x87\xb2\xec\x49\x87\xb9\xcd\x64\xa5\x17\xa1\x38\x4a\x39\x8a\x2c\xd5\x97\xc2\xb0\x52\xfe\x4d\x7f\xa2\xf3\x0a\xe7\xca\xd6\x95\xad\x73\x5f\xfc\x80\x61\x9e\x30\xd9\x53\xe2\x30\x2f\xf0\xf6\x48\xd1\x8e\xb2\x92\xef\xfe\x80\xe7\xdf\xfb\xc5\x79\x6c\x99\x0f\x6f\x61\x1f\xbd\x05\x17\x03\x90\x0a\xb8\xae\xa3\x89\x9c\xa2\x5c\x84\x1f\x07\x12\x10\x9e\x93\x47\xf0\x1c\x10\x48\x60\xa5\x08\x30\xc7\x80\x09\x74\x58\x30\x2f\x31\x74\x3c\xe7\xb9\x98\x1f\xe4\x89\x6f\xfb\xdd\xfd\xf7\xe6\x1e\x3a\x9a\x70\x8d\x21\x31\x2b\x04\x4a\xe8\x95\xd3\x33\x70\x07\xfa\xe2\x43\x9a\x10\xed\xbf\xb5\x37\x77\x76\xf3\xce\x6e\xf2\x76\xca\xc9\x0d\xc9\xab\xd0\x7e\x6f\xd7\xdb\xfe\x6d\x1d\xf8\xf8\x0a\xb5\xff\x33\xe5\x5f\x01\x00\x00\xff\xff\xe2\x96\x93\xec\xfd\x04\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xe4\x91\xd1\x6e\xd4\x30\x10\x45\xdf\xfd\x15\xc3\x5b\x1b\x51\x27\x1b\xaa\x22\x21\x84\x16\xad\x8a\xb4\x88\x82\x44\xfa\x03\x8e\x3d\x49\x26\x9b\xf5\xac\x3c\x93\xad\xfa\xf7\xc8\x21\x0b\x7d\xe1\x07\xe8\xa3\x6f\x6e\x6e\xce\x89\xcb\xc2\x70\x3b\xa2\xd7\x1b\x27\x42\x7d\x34\x57\xfe\x1a\x1a\x8a\x21\x21\x34\x9c\x86\x59\xcc\x76\x22\x8f\x51\x10\x1e\xf6\x8f\xa6\x28\x8d\x29\x8b\x37\x06\xea\xaa\xae\xe0\xab\x13\x8e\xf0\x30\x4f\x13\xf5\x2e\xc2\xc7\x31\x9f\xed\x71\x3d\x6f\xdd\x99\x29\x3c\x71\x3a\x58\xcf\xc7\x4f\x06\xb6\x67\x4c\x42\x1c\xe1\xce\xde\xda\x6a\xdd\x2a\x0c\x14\xf0\x19\x5a\x54\xc5\x04\xae\x15\x4d\xce\x6b\x6e\xf1\x19\x13\xec\x9a\xc6\x1a\x58\x4a\x5b\xcf\xa7\xe7\x44\xfd\xa0\xf0\x63\xc2\x1e\xf6\xc2\x11\x23\x5c\x35\x13\xb7\x1c\xe4\xc0\x74\x0d\xe5\x25\xad\xab\xcd\xed\xcd\x29\xa1\x60\xd4\xe5\xe5\x27\x6c\x85\x14\x61\x50\x3d\xc9\x87\xb2\xec\x49\x87\xb9\xcd\x64\xa5\x17\xa1\x38\x4a\x39\x8a\x2c\xd5\x97\xc2\xb0\x52\xfe\x4d\x7f\xa2\xf3\x0a\xe7\xca\xd6\x95\xad\x73\x5f\xfc\x80\x61\x9e\x30\xd9\x53\xe2\x30\x2f\xf0\xf6\x48\xd1\x8e\xb2\x92\xef\xfe\x80\xe7\xdf\xfb\xc5\x79\x6c\x99\x0f\x6f\x61\x1f\xbd\x05\x17\x03\x90\x0a\xb8\xae\xa3\x89\x9c\xa2\x5c\x84\x1f\x07\x12\x10\x9e\x93\x47\xf0\x1c\x10\x48\x60\xa5\x08\x30\xc7\x80\x09\x74\x58\x30\x2f\x31\x74\x3c\xe7\xb9\x98\x1f\xe4\x89\x6f\xfb\xdd\xfd\xf7\xe6\x1e\x3a\x9a\x70\x8d\x21\x31\x2b\x04\x4a\xe8\x95\xd3\x33\x70\x07\xfa\xe2\x43\x9a\x10\xed\xbf\xb5\x37\x77\x76\xf3\xce\x6e\xf2\x76\xca\xc9\x0d\xc9\xab\xd0\x7e\x6f\xd7\xdb\xfe\x6d\x1d\xf8\xf8\x0a\xb5\xff\x33\xe5\x5f\x01\x00\x00\xff\xff\xe2\x96\x93\xec\xfd\x04\x00\x00"), }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/br/pkg/restore/client.go b/br/pkg/restore/client.go index 9ecec2ce7b9e2..ba738ede519a6 100644 --- a/br/pkg/restore/client.go +++ b/br/pkg/restore/client.go @@ -41,6 +41,7 @@ import ( "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/mathutil" "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" "go.uber.org/zap" @@ -712,7 +713,7 @@ func (rc *Client) createTablesInWorkerPool(ctx context.Context, dom *domain.Doma numOfTables := len(tables) for lastSent := 0; lastSent < numOfTables; lastSent += int(rc.batchDdlSize) { - end := utils.MinInt(lastSent+int(rc.batchDdlSize), len(tables)) + end := mathutil.Min(lastSent+int(rc.batchDdlSize), len(tables)) log.Info("create tables", zap.Int("table start", lastSent), zap.Int("table end", end)) tableSlice := tables[lastSent:end] diff --git a/br/pkg/restore/client_test.go b/br/pkg/restore/client_test.go index 492d1324ee1df..674ff2876c183 100644 --- a/br/pkg/restore/client_test.go +++ b/br/pkg/restore/client_test.go @@ -45,7 +45,7 @@ func TestCreateTables(t *testing.T) { client.SetBatchDdlSize(1) tables := make([]*metautil.Table, 4) intField := types.NewFieldType(mysql.TypeLong) - intField.Charset = "binary" + intField.SetCharset("binary") for i := len(tables) - 1; i >= 0; i-- { tables[i] = &metautil.Table{ DB: dbSchema, @@ -115,7 +115,7 @@ func TestPreCheckTableClusterIndex(t *testing.T) { tables := make([]*metautil.Table, 4) intField := types.NewFieldType(mysql.TypeLong) - intField.Charset = "binary" + intField.SetCharset("binary") for i := len(tables) - 1; i >= 0; i-- { tables[i] = &metautil.Table{ DB: dbSchema, diff --git a/br/pkg/restore/db_test.go b/br/pkg/restore/db_test.go index a7fd2eb82ed78..67f93cb9a0883 100644 --- a/br/pkg/restore/db_test.go +++ b/br/pkg/restore/db_test.go @@ -138,7 +138,7 @@ func TestCreateTablesInDb(t *testing.T) { tables := make([]*metautil.Table, 4) intField := types.NewFieldType(mysql.TypeLong) - intField.Charset = "binary" + intField.SetCharset("binary") ddlJobMap := make(map[restore.UniqueTableName]bool) for i := len(tables) - 1; i >= 0; i-- { tables[i] = &metautil.Table{ diff --git a/br/pkg/restore/merge_fuzz_test.go b/br/pkg/restore/merge_fuzz_test.go index 624f0c3ef4378..e47f53524d1f8 100644 --- a/br/pkg/restore/merge_fuzz_test.go +++ b/br/pkg/restore/merge_fuzz_test.go @@ -1,6 +1,5 @@ // Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. //go:build go1.18 -// +build go1.18 package restore_test diff --git a/br/pkg/storage/local_unix.go b/br/pkg/storage/local_unix.go index 2dfb89deab476..ab9bcc5ab2bb3 100644 --- a/br/pkg/storage/local_unix.go +++ b/br/pkg/storage/local_unix.go @@ -1,7 +1,6 @@ // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. //go:build !windows -// +build !windows package storage diff --git a/br/pkg/storage/local_windows.go b/br/pkg/storage/local_windows.go index fc79722f34bf4..98d36b22a8dd6 100644 --- a/br/pkg/storage/local_windows.go +++ b/br/pkg/storage/local_windows.go @@ -1,7 +1,6 @@ // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. //go:build windows -// +build windows package storage diff --git a/br/pkg/task/backup.go b/br/pkg/task/backup.go index a94d943577c44..e6fb113135279 100644 --- a/br/pkg/task/backup.go +++ b/br/pkg/task/backup.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/mathutil" "github.com/spf13/pflag" "github.com/tikv/client-go/v2/oracle" "go.uber.org/zap" @@ -269,7 +270,8 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig if err != nil { return errors.Trace(err) } - log.Info("get newCollationEnable for check during restore", zap.String("newCollationEnable", newCollationEnable)) + log.Info("get new_collations_enabled_on_first_bootstrap config from system table", + zap.String(tidbNewCollationEnabled, newCollationEnable)) client, err := backup.NewBackupClient(ctx, mgr) if err != nil { @@ -479,7 +481,7 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig } } updateCh = g.StartProgress(ctx, "Checksum", checksumProgress, !cfg.LogProgress) - schemasConcurrency := uint(utils.MinInt(backup.DefaultSchemaConcurrency, schemas.Len())) + schemasConcurrency := uint(mathutil.Min(backup.DefaultSchemaConcurrency, schemas.Len())) err = schemas.BackupSchemas( ctx, metawriter, mgr.GetStorage(), statsHandle, backupTS, schemasConcurrency, cfg.ChecksumConcurrency, skipChecksum, updateCh) diff --git a/br/pkg/task/restore.go b/br/pkg/task/restore.go index f88440dca6447..656e2d6052c47 100644 --- a/br/pkg/task/restore.go +++ b/br/pkg/task/restore.go @@ -276,11 +276,12 @@ func CheckNewCollationEnable( if backupNewCollationEnable == "" { if CheckRequirements { return errors.Annotatef(berrors.ErrUnknown, - "NewCollactionEnable not found in backupmeta. "+ - "if you ensure the NewCollactionEnable config of backup cluster is as same as restore cluster, "+ - "use --check-requirements=false to skip") + "the config 'new_collations_enabled_on_first_bootstrap' not found in backupmeta. "+ + "you can use \"show config WHERE name='new_collations_enabled_on_first_bootstrap';\" to manually check the config. "+ + "if you ensure the config 'new_collations_enabled_on_first_bootstrap' in backup cluster is as same as restore cluster, "+ + "use --check-requirements=false to skip this check") } else { - log.Warn("no NewCollactionEnable in backup") + log.Warn("the config 'new_collations_enabled_on_first_bootstrap' is not in backupmeta") return nil } } @@ -297,7 +298,7 @@ func CheckNewCollationEnable( if !strings.EqualFold(backupNewCollationEnable, newCollationEnable) { return errors.Annotatef(berrors.ErrUnknown, - "newCollationEnable not match, upstream:%v, downstream: %v", + "the config 'new_collations_enabled_on_first_bootstrap' not match, upstream:%v, downstream: %v", backupNewCollationEnable, newCollationEnable) } return nil diff --git a/br/pkg/utils/dyn_pprof_other.go b/br/pkg/utils/dyn_pprof_other.go index ed094f4a7d08b..76756181c02d6 100644 --- a/br/pkg/utils/dyn_pprof_other.go +++ b/br/pkg/utils/dyn_pprof_other.go @@ -1,5 +1,4 @@ //go:build !linux && !darwin && !freebsd && !unix -// +build !linux,!darwin,!freebsd,!unix // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. diff --git a/br/pkg/utils/dyn_pprof_unix.go b/br/pkg/utils/dyn_pprof_unix.go index 36084c5853f20..fe7b1c374c0a7 100644 --- a/br/pkg/utils/dyn_pprof_unix.go +++ b/br/pkg/utils/dyn_pprof_unix.go @@ -1,5 +1,4 @@ //go:build linux || darwin || freebsd || unix -// +build linux darwin freebsd unix // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. diff --git a/br/pkg/utils/json_test.go b/br/pkg/utils/json_test.go index 691521b7bf25a..8d8eeb6457332 100644 --- a/br/pkg/utils/json_test.go +++ b/br/pkg/utils/json_test.go @@ -54,13 +54,13 @@ var testMetaJSONs = [][]byte{ "origin_default_bit": null, "state": 5, "type": { - "Charset": "utf8mb4", - "Collate": "utf8mb4_bin", - "Decimal": 0, - "Elems": null, - "Flag": 4099, - "Flen": 256, - "Tp": 15 + "charset": "utf8mb4", + "collate": "utf8mb4_bin", + "decimal": 0, + "elems": null, + "flag": 4099, + "flen": 256, + "tp": 15 }, "version": 2 } diff --git a/br/pkg/utils/math.go b/br/pkg/utils/math.go index d04369bcfe07d..62c69140a81e8 100644 --- a/br/pkg/utils/math.go +++ b/br/pkg/utils/math.go @@ -4,49 +4,17 @@ package utils import ( "github.com/pingcap/log" + "github.com/pingcap/tidb/util/mathutil" "go.uber.org/zap" ) -// MinInt choice smallest integer from its arguments. -func MinInt(x int, xs ...int) int { - min := x - for _, n := range xs { - if n < min { - min = n - } - } - return min -} - -// MaxInt choice biggest integer from its arguments. -func MaxInt(x int, xs ...int) int { - max := x - for _, n := range xs { - if n > max { - max = n - } - } - return max -} - // ClampInt restrict a value to a certain interval. func ClampInt(n, min, max int) int { if min > max { log.Error("clamping integer with min > max", zap.Int("min", min), zap.Int("max", max)) } - return MinInt(max, MaxInt(min, n)) -} - -// MinInt64 choice smallest integer from its arguments. -func MinInt64(x int64, xs ...int64) int64 { - min := x - for _, n := range xs { - if n < min { - min = n - } - } - return min + return mathutil.Min(max, mathutil.Max(min, n)) } // NextPowerOfTwo returns the smallest power of two greater than or equal to `i` diff --git a/br/pkg/utils/math_test.go b/br/pkg/utils/math_test.go index cce36cf342222..b63afc4ac5edf 100644 --- a/br/pkg/utils/math_test.go +++ b/br/pkg/utils/math_test.go @@ -8,20 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestMinInt(t *testing.T) { - require.Equal(t, 1, MinInt(1, 2)) - require.Equal(t, 1, MinInt(2, 1)) - require.Equal(t, 1, MinInt(4, 2, 1, 3)) - require.Equal(t, 1, MinInt(1, 1)) -} - -func TestMaxInt(t *testing.T) { - require.Equal(t, 2, MaxInt(1, 2)) - require.Equal(t, 2, MaxInt(2, 1)) - require.Equal(t, 4, MaxInt(4, 2, 1, 3)) - require.Equal(t, 1, MaxInt(1, 1)) -} - func TestClampInt(t *testing.T) { require.Equal(t, 3, ClampInt(100, 1, 3)) require.Equal(t, 2, ClampInt(2, 1, 3)) @@ -30,13 +16,6 @@ func TestClampInt(t *testing.T) { require.Equal(t, 1, ClampInt(100, 1, 1)) } -func TestMinInt64(t *testing.T) { - require.Equal(t, 1, MinInt(1, 2)) - require.Equal(t, 1, MinInt(2, 1)) - require.Equal(t, 1, MinInt(4, 2, 1, 3)) - require.Equal(t, 1, MinInt(1, 1)) -} - func TestNextPowerOfTwo(t *testing.T) { require.Equal(t, int64(1), NextPowerOfTwo(1)) require.Equal(t, int64(4), NextPowerOfTwo(3)) diff --git a/br/pkg/utils/retry.go b/br/pkg/utils/retry.go index 2f8af3a42ed99..60217f4e075b2 100644 --- a/br/pkg/utils/retry.go +++ b/br/pkg/utils/retry.go @@ -4,22 +4,13 @@ package utils import ( "context" - "database/sql" - stderrors "errors" - "io" - "net" - "reflect" - "regexp" "strings" "time" - "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" tmysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/terror" "go.uber.org/multierr" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) var retryableServerError = []string{ @@ -32,6 +23,7 @@ var retryableServerError = []string{ "body write aborted", "error during dispatch", "put object timeout", + "internalerror", } // RetryableFunc presents a retryable operation. @@ -83,63 +75,6 @@ func MessageIsRetryableStorageError(msg string) bool { return false } -// sqlmock uses fmt.Errorf to produce expectation failures, which will cause -// unnecessary retry if not specially handled >:( -var stdFatalErrorsRegexp = regexp.MustCompile( - `^call to (?s:.*) was not expected|arguments do not match:|could not match actual sql|mock non-retryable error`, -) -var stdErrorType = reflect.TypeOf(stderrors.New("")) - -// IsRetryableError returns whether the error is transient (e.g. network -// connection dropped) or irrecoverable (e.g. user pressing Ctrl+C). This -// function returns `false` (irrecoverable) if `err == nil`. -// -// If the error is a multierr, returns true only if all suberrors are retryable. -func IsRetryableError(err error) bool { - for _, singleError := range errors.Errors(err) { - if !isSingleRetryableError(singleError) { - return false - } - } - return true -} - -func isSingleRetryableError(err error) bool { - err = errors.Cause(err) - - switch err { - case nil, context.Canceled, context.DeadlineExceeded, io.EOF, sql.ErrNoRows: - return false - } - - switch nerr := err.(type) { - case net.Error: - return nerr.Timeout() - case *mysql.MySQLError: - switch nerr.Number { - // ErrLockDeadlock can retry to commit while meet deadlock - case tmysql.ErrUnknown, tmysql.ErrLockDeadlock, tmysql.ErrWriteConflict, tmysql.ErrWriteConflictInTiDB, - tmysql.ErrPDServerTimeout, tmysql.ErrTiKVServerTimeout, tmysql.ErrTiKVServerBusy, tmysql.ErrResolveLockTimeout, - tmysql.ErrRegionUnavailable, tmysql.ErrInfoSchemaExpired, tmysql.ErrInfoSchemaChanged, tmysql.ErrTxnRetryable: - return true - default: - return false - } - default: - switch status.Code(err) { - case codes.DeadlineExceeded, codes.NotFound, codes.AlreadyExists, codes.PermissionDenied, codes.ResourceExhausted, codes.Aborted, codes.OutOfRange, codes.Unavailable, codes.DataLoss: - return true - case codes.Unknown: - if reflect.TypeOf(err) == stdErrorType { - return !stdFatalErrorsRegexp.MatchString(err.Error()) - } - return true - default: - return false - } - } -} - func FallBack2CreateTable(err error) bool { switch nerr := errors.Cause(err).(type) { case *terror.Error: diff --git a/br/tests/README.md b/br/tests/README.md index 53685c967ad24..4e0e245dd5402 100644 --- a/br/tests/README.md +++ b/br/tests/README.md @@ -44,7 +44,6 @@ This folder contains all tests which relies on external processes such as TiDB. * `bin/mc` * `bin/tiflash` * `bin/cdc` - * `bin/tikv-importer` The versions must be ≥2.1.0. diff --git a/br/tests/_utils/generate_certs b/br/tests/_utils/generate_certs index 789f42d269fcd..4895f0b04bdc1 100755 --- a/br/tests/_utils/generate_certs +++ b/br/tests/_utils/generate_certs @@ -21,7 +21,7 @@ openssl ecparam -out "$TEST_DIR/certs/ca.key" -name prime256v1 -genkey # CA's Common Name must not be the same as signed certificate. openssl req -new -batch -sha256 -subj '/CN=br_tests' -key "$TEST_DIR/certs/ca.key" -out "$TEST_DIR/certs/ca.csr" openssl x509 -req -sha256 -days 2 -in "$TEST_DIR/certs/ca.csr" -signkey "$TEST_DIR/certs/ca.key" -out "$TEST_DIR/certs/ca.pem" -for cluster in tidb pd tikv importer lightning tiflash curl ticdc br; do +for cluster in tidb pd tikv lightning tiflash curl ticdc br; do openssl ecparam -out "$TEST_DIR/certs/$cluster.key" -name prime256v1 -genkey openssl req -new -batch -sha256 -subj '/CN=localhost' -key "$TEST_DIR/certs/$cluster.key" -out "$TEST_DIR/certs/$cluster.csr" openssl x509 -req -sha256 -days 1 -extensions EXT -extfile "tests/config/ipsan.cnf" \ diff --git a/br/tests/_utils/run_lightning b/br/tests/_utils/run_lightning index 0804275ab2fab..fb2d70add28b2 100755 --- a/br/tests/_utils/run_lightning +++ b/br/tests/_utils/run_lightning @@ -26,7 +26,6 @@ bin/tidb-lightning.test -test.coverprofile="$TEST_DIR/cov.$TEST_NAME.$$.out" DEV --pd-urls '127.0.0.1:2379' \ --config "tests/$TEST_NAME/config.toml" \ -d "tests/$TEST_NAME/data" \ - --importer '127.0.0.1:8808' \ --sorted-kv-dir "$TEST_DIR/$TEST_NAME.sorted" \ --enable-checkpoint=0 \ --check-requirements=0 \ diff --git a/br/tests/_utils/run_lightning_ctl b/br/tests/_utils/run_lightning_ctl index 0d82f6cf7e293..a20c30cdb9d63 100755 --- a/br/tests/_utils/run_lightning_ctl +++ b/br/tests/_utils/run_lightning_ctl @@ -24,7 +24,6 @@ bin/tidb-lightning-ctl.test -test.coverprofile="$TEST_DIR/cov.ctl.$TEST_NAME.$$. --tidb-port 4000 \ --pd-urls '127.0.0.1:2379' \ -d "tests/$TEST_NAME/data" \ - --importer '127.0.0.1:8808' \ --sorted-kv-dir "$TEST_DIR/sorted" \ --enable-checkpoint=0 \ --check-requirements=0 \ diff --git a/br/tests/_utils/run_services b/br/tests/_utils/run_services index ed16c6eb1ad55..a0fbe006fd189 100644 --- a/br/tests/_utils/run_services +++ b/br/tests/_utils/run_services @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -28,12 +28,11 @@ export TIKV_STATUS_ADDR="127.0.0.1:2018" export TIKV_COUNT=3 export TIFLASH_STATUS="127.0.0.1:17000" export TIFLASH_HTTP="127.0.0.1:8125" -export IMPORTER_ADDR="127.0.0.1:8808" export TIKV_PIDS="${TEST_DIR:?}/tikv_pids.txt" cleanup_data() { # Clean up data - for svc in "br" "tidb" "tiflash" "tikv" "pd" "importer"; do + for svc in "br" "tidb" "tiflash" "tikv" "pd"; do find "$TEST_DIR" -maxdepth 1 -name "${svc}*" -type d -exec echo delete {} \; -exec rm -rf {} \; 2> /dev/null done } @@ -46,7 +45,7 @@ stop() { } stop_services() { - for svc in "br" "tidb-server" "tiflash" "TiFlashMain" "tikv-server" "pd-server" "cdc" "minio" "tikv-importer"; do + for svc in "br" "tidb-server" "tiflash" "TiFlashMain" "tikv-server" "pd-server" "cdc" "minio"; do stop $svc & done sleep 2 # give some time for the OS to reap all processes @@ -181,16 +180,6 @@ start_tidb() { done } -start_importer() { - echo "Starting Importer..." - bin/tikv-importer \ - --addr "$IMPORTER_ADDR" \ - --import-dir "$TEST_DIR/importer" \ - --log-file "$TEST_DIR/importer.log" \ - --config "tests/config/importer.toml" & -} - - start_services_impl() { stop_services || true cleanup_data || true @@ -231,7 +220,6 @@ start_services_impl() { done ensure_tikv start_tidb - start_importer if $RUN_TIFLASH; then start_tiflash diff --git a/br/tests/br_check_new_collocation_enable/run.sh b/br/tests/br_check_new_collocation_enable/run.sh index d74262148fb5c..d3ed9ad87cc24 100755 --- a/br/tests/br_check_new_collocation_enable/run.sh +++ b/br/tests/br_check_new_collocation_enable/run.sh @@ -54,7 +54,7 @@ bin/brv4.0.8 backup db --db "$DB" -s "local://$TEST_DIR/$DB" \ # restore db from v4.0.8 version without `newCollationEnable` echo "restore start ... without NewCollactionEnable in backupmeta" restore_fail=0 -error_str="NewCollactionEnable not found in backupmeta" +error_str="the config 'new_collations_enabled_on_first_bootstrap' not found in backupmeta" test_log="new_collotion_enable_test.log" unset BR_LOG_TO_TERM run_br restore db --db $DB -s "local://$TEST_DIR/$DB" --pd $PD_ADDR --log-file $test_log || restore_fail=1 @@ -84,7 +84,7 @@ start_services --tidb-cfg $cur/config/new_collation_enable_true.toml echo "restore start ... with NewCollactionEnable=True in TiDB" restore_fail=0 test_log2="new_collotion_enable_test2.log" -error_str="newCollationEnable not match" +error_str="the config 'new_collations_enabled_on_first_bootstrap' not match" unset BR_LOG_TO_TERM run_br restore db --db $DB -s "local://$cur/${DB}_2" --pd $PD_ADDR --log-file $test_log2 || restore_fail=1 if [ $restore_fail -ne 1 ]; then diff --git a/br/tests/br_full/run.sh b/br/tests/br_full/run.sh index 0d15794788b26..21f2e2143a002 100755 --- a/br/tests/br_full/run.sh +++ b/br/tests/br_full/run.sh @@ -30,7 +30,7 @@ done # backup full and kill tikv to test reset connection echo "backup with limit start..." -export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/backup/reset-retryable-error=1*return(true)" +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/backup/reset-retryable-error=1*return(\"Unavailable\")->1*return(\"Internal\")" run_br --pd $PD_ADDR backup full -s "local://$TEST_DIR/$DB-limit" --concurrency 4 export GO_FAILPOINTS="" @@ -49,7 +49,7 @@ fi # backup full echo "backup with lz4 start..." -export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/backup/backup-storage-error=1*return(\"connection refused\")" +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/backup/backup-storage-error=1*return(\"connection refused\")->1*return(\"InternalError\")" run_br --pd $PD_ADDR backup full -s "local://$TEST_DIR/$DB-lz4" --concurrency 4 --compression lz4 export GO_FAILPOINTS="" size_lz4=$(du -d 0 $TEST_DIR/$DB-lz4 | awk '{print $1}') diff --git a/br/tests/br_gcs/run.sh b/br/tests/br_gcs/run.sh index 3829bed165ce9..058191864ad71 100755 --- a/br/tests/br_gcs/run.sh +++ b/br/tests/br_gcs/run.sh @@ -126,7 +126,7 @@ for i in $(seq $DB_COUNT); do done echo "v4.0.8 version restore start..." -bin/brv4.0.8 restore full -s "gcs://$BUCKET/${DB}_old" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" +run_br restore full -s "gcs://$BUCKET/${DB}_old" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" --check-requirements=false for i in $(seq $DB_COUNT); do row_count_new[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') diff --git a/br/tests/br_s3/run.sh b/br/tests/br_s3/run.sh index 2357069cb751a..df06051358ae5 100755 --- a/br/tests/br_s3/run.sh +++ b/br/tests/br_s3/run.sh @@ -103,7 +103,7 @@ for p in $(seq 2); do exit 1 fi - target_log="get newCollationEnable for check during restore" + target_log="get new_collations_enabled_on_first_bootstrap config from system table" if ! grep -i "$target_log" $BACKUP_LOG; then echo "${target_log} not found in log" exit 1 diff --git a/br/tests/config/importer.toml b/br/tests/config/importer.toml deleted file mode 100644 index e8b2294795d45..0000000000000 --- a/br/tests/config/importer.toml +++ /dev/null @@ -1,4 +0,0 @@ -[security] -ca-path = "/tmp/backup_restore_test/certs/ca.pem" -cert-path = "/tmp/backup_restore_test/certs/importer.pem" -key-path = "/tmp/backup_restore_test/certs/importer.key" diff --git a/br/tests/lightning_alter_random/run.sh b/br/tests/lightning_alter_random/run.sh index c0c81e37ff110..3baf1dcd11c20 100644 --- a/br/tests/lightning_alter_random/run.sh +++ b/br/tests/lightning_alter_random/run.sh @@ -22,7 +22,7 @@ check_cluster_version 4 0 0 AUTO_RANDOM || exit 0 # test lightning with autocommit disabled run_sql "SET @@global.autocommit = '0';" -for backend in tidb importer local; do +for backend in tidb local; do if [ "$backend" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_auto_random_default/run.sh b/br/tests/lightning_auto_random_default/run.sh index 432582bf72e24..41b9798de4560 100644 --- a/br/tests/lightning_auto_random_default/run.sh +++ b/br/tests/lightning_auto_random_default/run.sh @@ -19,7 +19,7 @@ set -eu # FIXME: auto-random is only stable on master currently. check_cluster_version 4 0 0 AUTO_RANDOM || exit 0 -for backend in tidb importer local; do +for backend in tidb local; do if [ "$backend" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_checkpoint/config.toml b/br/tests/lightning_checkpoint/config.toml index 9828bd6dea636..a1d2090a4bb63 100644 --- a/br/tests/lightning_checkpoint/config.toml +++ b/br/tests/lightning_checkpoint/config.toml @@ -2,6 +2,9 @@ index-concurrency = 1 table-concurrency = 1 +[tikv-importer] +backend = "local" + [checkpoint] enable = true schema = "tidb_lightning_checkpoint_test_cppk" diff --git a/br/tests/lightning_checkpoint/run.sh b/br/tests/lightning_checkpoint/run.sh index 7afe980fcd133..86551fd6246eb 100755 --- a/br/tests/lightning_checkpoint/run.sh +++ b/br/tests/lightning_checkpoint/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -58,66 +58,57 @@ for i in $(seq "$TABLE_COUNT"); do done PARTIAL_IMPORT_QUERY="SELECT *, $OUTER_QUERY AS s FROM (SELECT $INNER_QUERY) _" -for BACKEND in importer local; do - if [ "$BACKEND" = 'local' ]; then - check_cluster_version 4 0 0 'local backend' || continue - fi +check_cluster_version 4 0 0 'local backend' - # Set the failpoint to kill the lightning instance as soon as one table is imported - # If checkpoint does work, this should only kill 9 instances of lightnings. - SLOWDOWN_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownImport=sleep(250)' - export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailBeforeIndexEngineImported=return" +# Set the failpoint to kill the lightning instance as soon as one table is imported +# If checkpoint does work, this should only kill 9 instances of lightnings. +SLOWDOWN_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownImport=sleep(250)' +export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailBeforeIndexEngineImported=return" - # Start importing the tables. - run_sql 'DROP DATABASE IF EXISTS cppk_tsr' - run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint_test_cppk' - run_sql 'DROP DATABASE IF EXISTS `tidb_lightning_checkpoint_test_cppk.1357924680.bak`' +# Start importing the tables. +run_sql 'DROP DATABASE IF EXISTS cppk_tsr' +run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint_test_cppk' +run_sql 'DROP DATABASE IF EXISTS `tidb_lightning_checkpoint_test_cppk.1357924680.bak`' - # panic after saving index engine checkpoint status before saving table checkpoint status - set +e - for i in $(seq "$TABLE_COUNT"); do - echo "******** Importing Table Now (step $i/$TABLE_COUNT) ********" - run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 2> /dev/null - [ $? -ne 0 ] || exit 1 - done - set -e - - export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS" - # After everything is done, there should be no longer new calls to ImportEngine - # (and thus `kill_lightning_after_one_import` will spare this final check) - echo "******** Verify checkpoint no-op ********" - run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 - run_sql "$PARTIAL_IMPORT_QUERY" - check_contains "s: $(( (1000 * $CHUNK_COUNT + 1001) * $CHUNK_COUNT * $TABLE_COUNT ))" - run_sql 'SELECT count(*) FROM `tidb_lightning_checkpoint_test_cppk`.table_v7 WHERE status >= 200' - check_contains "count(*): $TABLE_COUNT" - - # Start importing the tables. - run_sql 'DROP DATABASE IF EXISTS cppk_tsr' - run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint_test_cppk' - run_sql 'DROP DATABASE IF EXISTS `tidb_lightning_checkpoint_test_cppk.1357924680.bak`' - - export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/SetTaskID=return(1357924680);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfIndexEngineImported=return(1)" +# panic after saving index engine checkpoint status before saving table checkpoint status +set +e +for i in $(seq "$TABLE_COUNT"); do + echo "******** Importing Table Now (step $i/$TABLE_COUNT) ********" + run_lightning -d "$DBPATH" --enable-checkpoint=1 2> /dev/null + [ $? -ne 0 ] || exit 1 +done +set -e - set +e - for i in $(seq "$TABLE_COUNT"); do - echo "******** Importing Table Now (step $i/$TABLE_COUNT) ********" - run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 2> /dev/null - [ $? -ne 0 ] || exit 1 - done - set -e +export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS" +# After everything is done, there should be no longer new calls to ImportEngine +# (and thus `kill_lightning_after_one_import` will spare this final check) +echo "******** Verify checkpoint no-op ********" +run_lightning -d "$DBPATH" --enable-checkpoint=1 +run_sql "$PARTIAL_IMPORT_QUERY" +check_contains "s: $(( (1000 * $CHUNK_COUNT + 1001) * $CHUNK_COUNT * $TABLE_COUNT ))" +run_sql 'SELECT count(*) FROM `tidb_lightning_checkpoint_test_cppk`.table_v7 WHERE status >= 200' +check_contains "count(*): $TABLE_COUNT" - # After everything is done, there should be no longer new calls to ImportEngine - # (and thus `kill_lightning_after_one_import` will spare this final check) - echo "******** Verify checkpoint no-op ********" - run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 - run_sql "$PARTIAL_IMPORT_QUERY" - check_contains "s: $(( (1000 * $CHUNK_COUNT + 1001) * $CHUNK_COUNT * $TABLE_COUNT ))" - run_sql 'SELECT count(*) FROM `tidb_lightning_checkpoint_test_cppk`.table_v7 WHERE status >= 200' - check_contains "count(*): $TABLE_COUNT" +# Start importing the tables. +run_sql 'DROP DATABASE IF EXISTS cppk_tsr' +run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint_test_cppk' +run_sql 'DROP DATABASE IF EXISTS `tidb_lightning_checkpoint_test_cppk.1357924680.bak`' - # Ensure there is no dangling open engines - ls -lA "$TEST_DIR"/importer/.temp/ - [ -z "$(ls -A "$TEST_DIR"/importer/.temp/)" ] +export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/SetTaskID=return(1357924680);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfIndexEngineImported=return(1)" +set +e +for i in $(seq "$TABLE_COUNT"); do + echo "******** Importing Table Now (step $i/$TABLE_COUNT) ********" + run_lightning -d "$DBPATH" --enable-checkpoint=1 2> /dev/null + [ $? -ne 0 ] || exit 1 done +set -e + +# After everything is done, there should be no longer new calls to ImportEngine +# (and thus `kill_lightning_after_one_import` will spare this final check) +echo "******** Verify checkpoint no-op ********" +run_lightning -d "$DBPATH" --enable-checkpoint=1 +run_sql "$PARTIAL_IMPORT_QUERY" +check_contains "s: $(( (1000 * $CHUNK_COUNT + 1001) * $CHUNK_COUNT * $TABLE_COUNT ))" +run_sql 'SELECT count(*) FROM `tidb_lightning_checkpoint_test_cppk`.table_v7 WHERE status >= 200' +check_contains "count(*): $TABLE_COUNT" diff --git a/br/tests/lightning_checkpoint_chunks/config.toml b/br/tests/lightning_checkpoint_chunks/config.toml index 0006a2caa7d5a..106e4d68dbbdc 100644 --- a/br/tests/lightning_checkpoint_chunks/config.toml +++ b/br/tests/lightning_checkpoint_chunks/config.toml @@ -2,7 +2,7 @@ region-concurrency = 1 [tikv-importer] -backend = "importer" +backend = "local" [checkpoint] enable = true diff --git a/br/tests/lightning_checkpoint_chunks/file.toml b/br/tests/lightning_checkpoint_chunks/file.toml index 9a7a9657e9555..4b2a4083bf9ea 100644 --- a/br/tests/lightning_checkpoint_chunks/file.toml +++ b/br/tests/lightning_checkpoint_chunks/file.toml @@ -2,7 +2,7 @@ region-concurrency = 1 [tikv-importer] -backend = "importer" +backend = "local" [checkpoint] enable = true diff --git a/br/tests/lightning_checkpoint_chunks/run.sh b/br/tests/lightning_checkpoint_chunks/run.sh index 1bfd48da6e4c5..35cabe0aadfc5 100755 --- a/br/tests/lightning_checkpoint_chunks/run.sh +++ b/br/tests/lightning_checkpoint_chunks/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -52,7 +52,7 @@ done # one file (after writing totally $ROW_COUNT rows) is imported. # If checkpoint does work, this should kill exactly $CHUNK_COUNT instances of lightnings. TASKID_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/SetTaskID=return(1234567890)" -export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return($ROW_COUNT)" +export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return" # Start importing the tables. run_sql 'DROP DATABASE IF EXISTS cpch_tsr' @@ -76,32 +76,13 @@ run_sql 'DROP DATABASE IF EXISTS `tidb_lightning_checkpoint_test_cpch.1234567890 # Set the failpoint to kill the lightning instance as soon as one chunk is imported, via signal mechanism # If checkpoint does work, this should only kill $CHUNK_COUNT instances of lightnings. -export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/KillIfImportedChunk=return($ROW_COUNT)" +export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/KillIfImportedChunk=return" for i in $(seq "$CHUNK_COUNT"); do echo "******** Importing Chunk Now (step $i/$CHUNK_COUNT) ********" do_run_lightning config done -set +e -i=0 -wait_max_time=20 -while [ $i -lt $wait_max_time ]; do - lightning_proc=$(ps -ef|grep "[b]in/tidb-lightning\\.test.*$TEST_NAME") - ret="$?" - if [ "$ret" -eq 0 ]; then - echo "lightning is still running: $lightning_proc" - sleep 1 - else - break - fi -done -if [ $i -ge $wait_max_time ]; then - echo "wait lightning exit failed" - exit 1 -fi -set -e - verify_checkpoint_noop # Repeat, but using the file checkpoint @@ -111,7 +92,7 @@ rm -f "$TEST_DIR"/cpch.pb* # Set the failpoint to kill the lightning instance as soon as one chunk is imported # If checkpoint does work, this should only kill $CHUNK_COUNT instances of lightnings. -export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return($ROW_COUNT)" +export GO_FAILPOINTS="$TASKID_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return" set +e for i in $(seq "$CHUNK_COUNT"); do echo "******** Importing Chunk using File checkpoint Now (step $i/$CHUNK_COUNT) ********" diff --git a/br/tests/lightning_checkpoint_engines/config.toml b/br/tests/lightning_checkpoint_engines/config.toml index 412e5a01f755c..b5e9bfd8f80e6 100644 --- a/br/tests/lightning_checkpoint_engines/config.toml +++ b/br/tests/lightning_checkpoint_engines/config.toml @@ -1,6 +1,9 @@ [lightning] table-concurrency = 1 +[tikv-importer] +backend = "local" + [checkpoint] enable = true driver = "file" diff --git a/br/tests/lightning_checkpoint_engines/mysql.toml b/br/tests/lightning_checkpoint_engines/mysql.toml index 4beafd48030ee..433c95cac1e79 100644 --- a/br/tests/lightning_checkpoint_engines/mysql.toml +++ b/br/tests/lightning_checkpoint_engines/mysql.toml @@ -1,6 +1,9 @@ [lightning] table-concurrency = 1 +[tikv-importer] +backend = "local" + [checkpoint] enable = true driver = "mysql" diff --git a/br/tests/lightning_checkpoint_engines/run.sh b/br/tests/lightning_checkpoint_engines/run.sh index 7a7bce45cb7ad..ad311ee58332c 100755 --- a/br/tests/lightning_checkpoint_engines/run.sh +++ b/br/tests/lightning_checkpoint_engines/run.sh @@ -17,88 +17,82 @@ set -eux do_run_lightning() { - run_lightning --backend $1 --enable-checkpoint=1 --log-file "$TEST_DIR/lightning-checkpoint-engines.log" --config "tests/$TEST_NAME/$2.toml" + run_lightning --enable-checkpoint=1 --log-file "$TEST_DIR/lightning-checkpoint-engines.log" --config "tests/$TEST_NAME/$1.toml" } -for BACKEND in importer local; do - if [ "$BACKEND" = 'local' ]; then - check_cluster_version 4 0 0 'local backend' || continue - fi - - # First, verify that a normal operation is fine. - rm -f "$TEST_DIR/lightning-checkpoint-engines.log" - rm -f "/tmp/tidb_lightning_checkpoint.pb" - run_sql 'DROP DATABASE IF EXISTS cpeng;' - rm -rf $TEST_DIR/importer/* - - export GO_FAILPOINTS="" - - do_run_lightning $BACKEND config - - # Check that we have indeed opened 6 engines (index + data engine) - DATA_ENGINE_COUNT=4 - INDEX_ENGINE_COUNT=2 - ENGINE_COUNT=6 - OPEN_ENGINES_COUNT=$(grep 'open engine' "$TEST_DIR/lightning-checkpoint-engines.log" | wc -l) - echo "Number of open engines: $OPEN_ENGINES_COUNT" - [ "$OPEN_ENGINES_COUNT" -eq $ENGINE_COUNT ] - - # Check that everything is correctly imported - run_sql 'SELECT count(*), sum(c) FROM cpeng.a' - check_contains 'count(*): 4' - check_contains 'sum(c): 10' - - run_sql 'SELECT count(*), sum(c) FROM cpeng.b' - check_contains 'count(*): 4' - check_contains 'sum(c): 46' - - # Now, verify it works with checkpoints as well. - - run_sql 'DROP DATABASE cpeng;' - rm -f "/tmp/tidb_lightning_checkpoint.pb" - - # Data engine part - export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownImport=sleep(500);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfStatusBecomes=return(120);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfIndexEngineImported=return(140)' - for i in $(seq "$ENGINE_COUNT"); do - echo "******** Importing Table Now (step $i/$ENGINE_COUNT) ********" - ! do_run_lightning $BACKEND config 2> /dev/null - done - - echo "******** Verify checkpoint no-op ********" - # all engines should have been imported here. - do_run_lightning $BACKEND config - - run_sql 'SELECT count(*), sum(c) FROM cpeng.a' - check_contains 'count(*): 4' - check_contains 'sum(c): 10' - - run_sql 'SELECT count(*), sum(c) FROM cpeng.b' - check_contains 'count(*): 4' - check_contains 'sum(c): 46' - - # Now, try again with MySQL checkpoints - - run_sql 'DROP DATABASE cpeng;' - run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint;' - rm -rf $TEST_DIR/lightning_checkpoint_engines.sorted - rm -rf $TEST_DIR/importer/* - - set +e - for i in $(seq "$ENGINE_COUNT"); do - echo "******** Importing Table Now (step $i/$ENGINE_COUNT) ********" - do_run_lightning $BACKEND mysql 2> /dev/null - [ $? -ne 0 ] || exit 1 - done - set -e - - echo "******** Verify checkpoint no-op ********" - do_run_lightning $BACKEND mysql - - run_sql 'SELECT count(*), sum(c) FROM cpeng.a' - check_contains 'count(*): 4' - check_contains 'sum(c): 10' - - run_sql 'SELECT count(*), sum(c) FROM cpeng.b' - check_contains 'count(*): 4' - check_contains 'sum(c): 46' +check_cluster_version 4 0 0 'local backend' + +# First, verify that a normal operation is fine. +rm -f "$TEST_DIR/lightning-checkpoint-engines.log" +rm -f "/tmp/tidb_lightning_checkpoint.pb" +run_sql 'DROP DATABASE IF EXISTS cpeng;' +rm -rf $TEST_DIR/importer/* + +export GO_FAILPOINTS="" + +do_run_lightning config + +# Check that we have indeed opened 6 engines (index + data engine) +ENGINE_COUNT=6 +OPEN_ENGINES_COUNT=$(grep 'open engine' "$TEST_DIR/lightning-checkpoint-engines.log" | wc -l) +echo "Number of open engines: $OPEN_ENGINES_COUNT" +[ "$OPEN_ENGINES_COUNT" -eq $ENGINE_COUNT ] + +# Check that everything is correctly imported +run_sql 'SELECT count(*), sum(c) FROM cpeng.a' +check_contains 'count(*): 4' +check_contains 'sum(c): 10' + +run_sql 'SELECT count(*), sum(c) FROM cpeng.b' +check_contains 'count(*): 4' +check_contains 'sum(c): 46' + +# Now, verify it works with checkpoints as well. + +run_sql 'DROP DATABASE cpeng;' +rm -f "/tmp/tidb_lightning_checkpoint.pb" + +# Data engine part +export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownImport=sleep(500);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfStatusBecomes=return(120);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfIndexEngineImported=return(140)' +for i in $(seq "$ENGINE_COUNT"); do + echo "******** Importing Table Now (step $i/$ENGINE_COUNT) ********" + do_run_lightning config 2> /dev/null && exit 1 done + +echo "******** Verify checkpoint no-op ********" +# all engines should have been imported here. +do_run_lightning config + +run_sql 'SELECT count(*), sum(c) FROM cpeng.a' +check_contains 'count(*): 4' +check_contains 'sum(c): 10' + +run_sql 'SELECT count(*), sum(c) FROM cpeng.b' +check_contains 'count(*): 4' +check_contains 'sum(c): 46' + +# Now, try again with MySQL checkpoints + +run_sql 'DROP DATABASE cpeng;' +run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint;' +rm -rf $TEST_DIR/lightning_checkpoint_engines.sorted +rm -rf $TEST_DIR/importer/* + +set +e +for i in $(seq "$ENGINE_COUNT"); do + echo "******** Importing Table Now (step $i/$ENGINE_COUNT) ********" + do_run_lightning mysql 2> /dev/null + [ $? -ne 0 ] || exit 1 +done +set -e + +echo "******** Verify checkpoint no-op ********" +do_run_lightning mysql + +run_sql 'SELECT count(*), sum(c) FROM cpeng.a' +check_contains 'count(*): 4' +check_contains 'sum(c): 10' + +run_sql 'SELECT count(*), sum(c) FROM cpeng.b' +check_contains 'count(*): 4' +check_contains 'sum(c): 46' diff --git a/br/tests/lightning_checkpoint_error_destroy/run.sh b/br/tests/lightning_checkpoint_error_destroy/run.sh index 8afc6a0fbd26b..f24c0e10dd15c 100755 --- a/br/tests/lightning_checkpoint_error_destroy/run.sh +++ b/br/tests/lightning_checkpoint_error_destroy/run.sh @@ -18,7 +18,7 @@ set -eux # Make sure we won't run out of table concurrency by destroying checkpoints -for i in $(seq 8); do +for _ in $(seq 8); do ARGS="--enable-checkpoint=1 --config tests/$TEST_NAME/mysql.toml -d tests/$TEST_NAME/bad-data" set +e run_lightning $ARGS @@ -34,18 +34,14 @@ check_contains 'x: 1999-09-09 09:09:09' run_sql 'DROP DATABASE cped' -CHECK_POINT_FILE="/tmp/cp_error_destroy.pb" - # clean up possible old files -rm -rf CHECK_POINT_FILE -for i in $(seq 8); do +rm -rf '/tmp/cp_error_destroy.pb' +for _ in $(seq 8); do ARGS="--enable-checkpoint=1 --config tests/$TEST_NAME/file.toml -d tests/$TEST_NAME/bad-data" set +e run_lightning $ARGS set -e - ls -la /tmp/backup_restore_test/importer/.temp/ run_lightning_ctl $ARGS -checkpoint-error-destroy=all - ls -la /tmp/backup_restore_test/importer/.temp/ done run_lightning --enable-checkpoint=1 --config "tests/$TEST_NAME/file.toml" -d "tests/$TEST_NAME/good-data" diff --git a/br/tests/lightning_checkpoint_parquet/run.sh b/br/tests/lightning_checkpoint_parquet/run.sh index 858d5335765a0..db089722c8b09 100755 --- a/br/tests/lightning_checkpoint_parquet/run.sh +++ b/br/tests/lightning_checkpoint_parquet/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # diff --git a/br/tests/lightning_checkpoint_timestamp/config.toml b/br/tests/lightning_checkpoint_timestamp/config.toml index e40b6348717ca..a85083e17b78b 100644 --- a/br/tests/lightning_checkpoint_timestamp/config.toml +++ b/br/tests/lightning_checkpoint_timestamp/config.toml @@ -8,7 +8,7 @@ driver = "file" dsn = "/tmp/backup_restore_test/cpts.pb" [tikv-importer] -backend = "importer" +backend = "local" [mydumper] read-block-size = 1 diff --git a/br/tests/lightning_checkpoint_timestamp/mysql.toml b/br/tests/lightning_checkpoint_timestamp/mysql.toml index b2442745fbe26..e76a33657664c 100644 --- a/br/tests/lightning_checkpoint_timestamp/mysql.toml +++ b/br/tests/lightning_checkpoint_timestamp/mysql.toml @@ -8,7 +8,7 @@ driver = "mysql" keep-after-success = true [tikv-importer] -backend = "importer" +backend = "local" [mydumper] read-block-size = 1 diff --git a/br/tests/lightning_checkpoint_timestamp/run.sh b/br/tests/lightning_checkpoint_timestamp/run.sh index 9a68ecdc1c1df..c442ed377af3b 100755 --- a/br/tests/lightning_checkpoint_timestamp/run.sh +++ b/br/tests/lightning_checkpoint_timestamp/run.sh @@ -19,7 +19,7 @@ set -eu run_sql 'DROP DATABASE IF EXISTS cpts' rm -f "$TEST_DIR"/cpts.pb* -export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/SetTaskID=return(1234567890);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return(28)" +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/SetTaskID=return(1234567890);github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return" for i in $(seq 5); do echo "******** Importing Chunk Now (file step $i) ********" diff --git a/br/tests/lightning_cmdline_override/config.toml b/br/tests/lightning_cmdline_override/config.toml index aaf4480a91ee5..e55e3beea3dff 100644 --- a/br/tests/lightning_cmdline_override/config.toml +++ b/br/tests/lightning_cmdline_override/config.toml @@ -4,7 +4,7 @@ file = "/tmp/xyzxyzxyz" level = "xyzxyzxyz" [tikv-importer] -addr = "xyzxyzxyz" +backend = "local" [mydumper] data-source-dir = "xyzxyzxyz" diff --git a/br/tests/lightning_cmdline_override/run.sh b/br/tests/lightning_cmdline_override/run.sh index 0b8875f759463..5a476ae140358 100755 --- a/br/tests/lightning_cmdline_override/run.sh +++ b/br/tests/lightning_cmdline_override/run.sh @@ -11,8 +11,7 @@ run_lightning \ --tidb-status 10080 \ --pd-urls 127.0.0.1:2379 \ -d "tests/$TEST_NAME/data" \ - --backend 'importer' \ - --importer 127.0.0.1:8808 + --backend 'tidb' run_sql 'SELECT * FROM cmdline_override.t' check_contains 'a: 15' diff --git a/br/tests/lightning_column_permutation/run.sh b/br/tests/lightning_column_permutation/run.sh index db69f64482309..8613dd9c915e5 100644 --- a/br/tests/lightning_column_permutation/run.sh +++ b/br/tests/lightning_column_permutation/run.sh @@ -1,6 +1,6 @@ set -eu -for BACKEND in local importer tidb; do +for BACKEND in local tidb; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_common_handle/run.sh b/br/tests/lightning_common_handle/run.sh index 7e6f710319394..c7a3ec7ad2984 100644 --- a/br/tests/lightning_common_handle/run.sh +++ b/br/tests/lightning_common_handle/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -39,7 +39,7 @@ INSERT INTO t (s, i, j) VALUES _EOF_ echo 'INSERT INTO t(s, i, j) VALUES ("another test case", 6, 6);' > "$DBPATH/ch.t.1.sql" -for BACKEND in local importer tidb; do +for BACKEND in local tidb; do # Start importing the tables. run_sql 'DROP DATABASE IF EXISTS ch' diff --git a/br/tests/lightning_csv/run.sh b/br/tests/lightning_csv/run.sh index 334d244a0ae5d..83c4917b4b76c 100755 --- a/br/tests/lightning_csv/run.sh +++ b/br/tests/lightning_csv/run.sh @@ -2,7 +2,7 @@ set -eu -for BACKEND in importer tidb local; do +for BACKEND in tidb local; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_fail_fast_on_nonretry_err/config.toml b/br/tests/lightning_fail_fast_on_nonretry_err/config.toml new file mode 100644 index 0000000000000..95da85a3d5726 --- /dev/null +++ b/br/tests/lightning_fail_fast_on_nonretry_err/config.toml @@ -0,0 +1,12 @@ +[mydumper.csv] +separator = ',' +delimiter = '"' +header = false +not-null = false +null = '\N' +backslash-escape = true +trim-last-separator = false + +[tikv-importer] +send-kv-pairs=10 +region-split-size = 1024 diff --git a/br/tests/lightning_fail_fast_on_nonretry_err/data/csv-schema-create.sql b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv-schema-create.sql new file mode 100644 index 0000000000000..bdeb27b131ed7 --- /dev/null +++ b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv-schema-create.sql @@ -0,0 +1 @@ +CREATE DATABASE `CSV`; diff --git a/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads-schema.sql b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads-schema.sql new file mode 100644 index 0000000000000..ab54a49520aa5 --- /dev/null +++ b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads-schema.sql @@ -0,0 +1,27 @@ +CREATE TABLE `threads` ( + `THREAD_ID` bigint(20) unsigned NOT NULL, + `NAME` varchar(128) NOT NULL, + `TYPE` varchar(10) NOT NULL, + `PROCESSLIST_ID` bigint(20) unsigned DEFAULT NULL, + `PROCESSLIST_USER` varchar(32) DEFAULT NULL, + `PROCESSLIST_HOST` varchar(60) DEFAULT NULL, + `PROCESSLIST_DB` varchar(64) DEFAULT NULL, + `PROCESSLIST_COMMAND` varchar(16) DEFAULT NULL, + `PROCESSLIST_TIME` bigint(20) DEFAULT NULL, + `PROCESSLIST_STATE` varchar(64) DEFAULT NULL, + `PROCESSLIST_INFO` longtext, + `PARENT_THREAD_ID` bigint(20) unsigned DEFAULT NULL, + `ROLE` varchar(64) DEFAULT NULL, + `INSTRUMENTED` enum('YES','NO') NOT NULL, + `HISTORY` enum('YES','NO') NOT NULL, + `CONNECTION_TYPE` varchar(16) DEFAULT NULL, + `THREAD_OS_ID` bigint(20) unsigned DEFAULT NULL, + `RESOURCE_GROUP` varchar(64) DEFAULT NULL, + PRIMARY KEY (`THREAD_ID`), + KEY `PROCESSLIST_ID` (`PROCESSLIST_ID`), + KEY `THREAD_OS_ID` (`THREAD_OS_ID`), + KEY `NAME` (`NAME`), + KEY `PROCESSLIST_ACCOUNT` (`PROCESSLIST_USER`,`PROCESSLIST_HOST`), + KEY `PROCESSLIST_HOST` (`PROCESSLIST_HOST`), + KEY `RESOURCE_GROUP` (`RESOURCE_GROUP`) +); diff --git a/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads.csv b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads.csv new file mode 100644 index 0000000000000..1062fa27ed98c --- /dev/null +++ b/br/tests/lightning_fail_fast_on_nonretry_err/data/csv.threads.csv @@ -0,0 +1 @@ +"1","thread/sql/main","BACKGROUND",\N,\N,\N,"mysql",\N,"31285",\N,\N,\N,\N,"YES","YES",\N,"7059733",\N diff --git a/br/tests/lightning_fail_fast_on_nonretry_err/run.sh b/br/tests/lightning_fail_fast_on_nonretry_err/run.sh new file mode 100755 index 0000000000000..ccf396b24f3fb --- /dev/null +++ b/br/tests/lightning_fail_fast_on_nonretry_err/run.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -eu + +run_sql 'DROP DATABASE IF EXISTS csv' + +out_file_name="$TEST_DIR/sql_res.$TEST_NAME.txt" +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/backend/local/WriteToTiKVNotEnoughDiskSpace=return(true)" +start_time=$(date +'%s') +run_lightning --backend local > $out_file_name 2>&1 || true +export GO_FAILPOINTS="" +check_contains "The available disk of TiKV" +used_time=$(($(date +'%s') - $start_time)) +echo "time used to run lightning ${used_time}s" +# writeAndIngestByRanges will retry for at least 810s on retryable error +if [ $used_time -ge 60 ]; then + echo "lightning failed to fail fast" + exit 1 +fi + +run_sql 'SELECT count(*) FROM csv.threads' +check_contains 'count(*): 0' + + diff --git a/br/tests/lightning_file_routing/config.toml b/br/tests/lightning_file_routing/config.toml index b837614aa50f9..d197216807b1d 100644 --- a/br/tests/lightning_file_routing/config.toml +++ b/br/tests/lightning_file_routing/config.toml @@ -1,6 +1,9 @@ [lightning] table-concurrency = 1 +[tikv-importer] +backend = "local" + [checkpoint] enable = false diff --git a/br/tests/lightning_file_routing/run.sh b/br/tests/lightning_file_routing/run.sh index 36ed5611b51e2..b02c597acd756 100755 --- a/br/tests/lightning_file_routing/run.sh +++ b/br/tests/lightning_file_routing/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -48,22 +48,18 @@ SET character_set_results = @PREV_CHARACTER_SET_RESULTS; SET collation_connection = @PREV_COLLATION_CONNECTION; _EOF_ -for BACKEND in local importer; do - if [ "$BACKEND" = 'local' ]; then - check_cluster_version 4 0 0 'local backend' || continue - fi + check_cluster_version 4 0 0 'local backend' - run_sql 'DROP DATABASE IF EXISTS fr' +run_sql 'DROP DATABASE IF EXISTS fr' - # Start importing the tables. - run_lightning -d "$DBPATH" --backend $BACKEND 2> /dev/null +# Start importing the tables. +run_lightning -d "$DBPATH" 2> /dev/null - run_sql 'SELECT count(*) FROM `fr`.tbl' - check_contains "count(*): 10" - run_sql 'SELECT sum(j) FROM `fr`.tbl' - check_contains "sum(j): 55" +run_sql 'SELECT count(*) FROM `fr`.tbl' +check_contains "count(*): 10" +run_sql 'SELECT sum(j) FROM `fr`.tbl' +check_contains "sum(j): 55" - run_sql 'SELECT sum(i), count(*) FROM `fr`.v' - check_contains "sum(i): 15" - check_contains "count(*): 5" -done +run_sql 'SELECT sum(i), count(*) FROM `fr`.v' +check_contains "sum(i): 15" +check_contains "count(*): 5" diff --git a/br/tests/lightning_generated_columns/run.sh b/br/tests/lightning_generated_columns/run.sh index b1632ac759241..c61ef6b3bfb38 100644 --- a/br/tests/lightning_generated_columns/run.sh +++ b/br/tests/lightning_generated_columns/run.sh @@ -27,7 +27,7 @@ trap undo_set_globals EXIT # and the changes are actually effective. So we have this check-and-retry loop # below to ensure Lightning gets our desired global vars. run_sql "SET GLOBAL time_zone='-08:00', GLOBAL default_week_format=4, GLOBAL block_encryption_mode='aes-256-cbc'" -for i in $(seq 3); do +for _ in $(seq 3); do sleep 1 run_sql "SELECT CONCAT(@@time_zone, ',', @@default_week_format, ',', @@block_encryption_mode) res" if [ "$(read_result)" = '-08:00,4,aes-256-cbc' ]; then @@ -35,7 +35,7 @@ for i in $(seq 3); do fi done -for BACKEND in 'local' 'tidb' 'importer'; do +for BACKEND in 'local' 'tidb'; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_issue_282/run.sh b/br/tests/lightning_issue_282/run.sh index 87f67ee6ce07f..0040d29bf01fc 100644 --- a/br/tests/lightning_issue_282/run.sh +++ b/br/tests/lightning_issue_282/run.sh @@ -16,7 +16,7 @@ set -eu -for backend in tidb importer local; do +for backend in tidb local; do if [ "$backend" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_issue_410/run.sh b/br/tests/lightning_issue_410/run.sh index b4f02b26814eb..d8f8e95760d26 100644 --- a/br/tests/lightning_issue_410/run.sh +++ b/br/tests/lightning_issue_410/run.sh @@ -16,7 +16,7 @@ set -eux -for backend in tidb importer local; do +for backend in tidb local; do if [ "$backend" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_local_backend/run.sh b/br/tests/lightning_local_backend/run.sh index 5843210fea738..b1c7440249c27 100755 --- a/br/tests/lightning_local_backend/run.sh +++ b/br/tests/lightning_local_backend/run.sh @@ -113,7 +113,7 @@ for ckpt in mysql file; do run_sql 'DROP DATABASE IF EXISTS tidb_lightning_checkpoint_local_backend_test' rm -f "/tmp/tidb_lightning_checkpoint_local_backend_test.pb" set +e - export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/restore/LocalBackendSaveCheckpoint=return;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return(1)" + export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/restore/LocalBackendSaveCheckpoint=return;github.com/pingcap/tidb/br/pkg/lightning/restore/FailIfImportedChunk=return" run_lightning --backend local --enable-checkpoint=1 --log-file "$TEST_DIR/lightning-local.log" --config "tests/$TEST_NAME/$ckpt.toml" set -e run_lightning_ctl --check-local-storage \ diff --git a/br/tests/lightning_max_incr/config.toml b/br/tests/lightning_max_incr/config.toml new file mode 100644 index 0000000000000..d2152b47c922a --- /dev/null +++ b/br/tests/lightning_max_incr/config.toml @@ -0,0 +1,2 @@ +[tikv-importer] +backend = 'local' diff --git a/br/tests/lightning_max_incr/data/db-schema-create.sql b/br/tests/lightning_max_incr/data/db-schema-create.sql new file mode 100644 index 0000000000000..c88b0e3150e76 --- /dev/null +++ b/br/tests/lightning_max_incr/data/db-schema-create.sql @@ -0,0 +1 @@ +create database db; \ No newline at end of file diff --git a/br/tests/lightning_max_incr/data/db.test-schema.sql b/br/tests/lightning_max_incr/data/db.test-schema.sql new file mode 100644 index 0000000000000..494571fe9736d --- /dev/null +++ b/br/tests/lightning_max_incr/data/db.test-schema.sql @@ -0,0 +1,5 @@ +create table test( + a bigint auto_increment, + b int, + primary key(a) +); \ No newline at end of file diff --git a/br/tests/lightning_max_incr/data/db.test.000000000.csv b/br/tests/lightning_max_incr/data/db.test.000000000.csv new file mode 100644 index 0000000000000..cb1603f9d4a71 --- /dev/null +++ b/br/tests/lightning_max_incr/data/db.test.000000000.csv @@ -0,0 +1,3 @@ +"a","b" +1,2 +9223372036854775805,3 \ No newline at end of file diff --git a/br/tests/lightning_max_incr/data/db.test1-schema.sql b/br/tests/lightning_max_incr/data/db.test1-schema.sql new file mode 100644 index 0000000000000..d44068487af8b --- /dev/null +++ b/br/tests/lightning_max_incr/data/db.test1-schema.sql @@ -0,0 +1,5 @@ +create table test1( + a bigint auto_increment, + b int, + primary key(a) +); \ No newline at end of file diff --git a/br/tests/lightning_max_incr/data/db.test1.000000000.csv b/br/tests/lightning_max_incr/data/db.test1.000000000.csv new file mode 100644 index 0000000000000..abe9c63c2a028 --- /dev/null +++ b/br/tests/lightning_max_incr/data/db.test1.000000000.csv @@ -0,0 +1,3 @@ +"a","b" +1,2 +9223372036854775807,3 \ No newline at end of file diff --git a/br/tests/lightning_max_incr/run.sh b/br/tests/lightning_max_incr/run.sh new file mode 100644 index 0000000000000..ce044c0230623 --- /dev/null +++ b/br/tests/lightning_max_incr/run.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eux + +check_cluster_version 4 0 0 'local backend' || exit 0 + +ENGINE_COUNT=6 + +check_result() { + run_sql 'SHOW DATABASES;' + check_contains 'Database: db'; + run_sql 'SHOW TABLES IN db;' + check_contains 'Tables_in_db: test' + check_contains 'Tables_in_db: test1' + run_sql 'SELECT count(*) FROM db.test;' + check_contains 'count(*): 2' + run_sql 'SELECT count(*) FROM db.test1;' + check_contains 'count(*): 2' +} + +cleanup() { + rm -f $TEST_DIR/lightning.log + rm -rf $TEST_DIR/sst + run_sql 'DROP DATABASE IF EXISTS db;' +} + +cleanup + +# db.test contains key that is less than int64 - 1 +# while db.test1 contains key that equals int64 - 1 +run_lightning --sorted-kv-dir "$TEST_DIR/sst" --config "tests/$TEST_NAME/config.toml" --log-file "$TEST_DIR/lightning.log" +check_result +# successfully insert: max key has not reached maximum +run_sql 'INSERT INTO db.test(b) VALUES(11);' +# fail for insertion: db.test1 has key int64 - 1 +run_sql 'INSERT INTO db.test1(b) VALUES(22);' 2>&1 | tee -a "$TEST_DIR/sql_res.$TEST_NAME.txt" +check_contains 'ERROR' +cleanup diff --git a/br/tests/lightning_max_random/config.toml b/br/tests/lightning_max_random/config.toml new file mode 100644 index 0000000000000..d2152b47c922a --- /dev/null +++ b/br/tests/lightning_max_random/config.toml @@ -0,0 +1,2 @@ +[tikv-importer] +backend = 'local' diff --git a/br/tests/lightning_max_random/data/db-schema-create.sql b/br/tests/lightning_max_random/data/db-schema-create.sql new file mode 100644 index 0000000000000..c88b0e3150e76 --- /dev/null +++ b/br/tests/lightning_max_random/data/db-schema-create.sql @@ -0,0 +1 @@ +create database db; \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test-schema.sql b/br/tests/lightning_max_random/data/db.test-schema.sql new file mode 100644 index 0000000000000..eb1838507ea94 --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test-schema.sql @@ -0,0 +1,5 @@ +create table test( + a bigint auto_random(10), + b int, + primary key(a) +); \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test.000000000.csv b/br/tests/lightning_max_random/data/db.test.000000000.csv new file mode 100644 index 0000000000000..a278110306af9 --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test.000000000.csv @@ -0,0 +1,3 @@ +"a","b" +1,2 +9007199254740990,3 \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test1-schema.sql b/br/tests/lightning_max_random/data/db.test1-schema.sql new file mode 100644 index 0000000000000..5ab8c5e9b32ef --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test1-schema.sql @@ -0,0 +1,5 @@ +create table test1( + a bigint auto_random(10), + b int, + primary key(a) +); \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test1.000000000.csv b/br/tests/lightning_max_random/data/db.test1.000000000.csv new file mode 100644 index 0000000000000..550f578de3e1a --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test1.000000000.csv @@ -0,0 +1,3 @@ +"a","b" +1,2 +9007199254740991,3 \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test2-schema.sql b/br/tests/lightning_max_random/data/db.test2-schema.sql new file mode 100644 index 0000000000000..740458dfd43df --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test2-schema.sql @@ -0,0 +1,5 @@ +create table test2( + a bigint auto_random(10), + b int, + primary key(a) +); \ No newline at end of file diff --git a/br/tests/lightning_max_random/data/db.test2.000000000.csv b/br/tests/lightning_max_random/data/db.test2.000000000.csv new file mode 100644 index 0000000000000..8de1e50edd09a --- /dev/null +++ b/br/tests/lightning_max_random/data/db.test2.000000000.csv @@ -0,0 +1,3 @@ +"a","b" +1,2 +9007199254740992,3 \ No newline at end of file diff --git a/br/tests/lightning_max_random/run.sh b/br/tests/lightning_max_random/run.sh new file mode 100644 index 0000000000000..972481e5bc0a5 --- /dev/null +++ b/br/tests/lightning_max_random/run.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eux + +check_cluster_version 4 0 0 'local backend' || exit 0 + +ENGINE_COUNT=6 + +check_result() { + run_sql 'SHOW DATABASES;' + check_contains 'Database: db'; + run_sql 'SHOW TABLES IN db;' + check_contains 'Tables_in_db: test' + check_contains 'Tables_in_db: test1' + check_contains 'Tables_in_db: test2' + run_sql 'SELECT count(*) FROM db.test;' + check_contains 'count(*): 2' + run_sql 'SELECT count(*) FROM db.test1;' + check_contains 'count(*): 2' + run_sql 'SELECT count(*) FROM db.test2;' + check_contains 'count(*): 2' +} + +cleanup() { + rm -f $TEST_DIR/lightning.log + rm -rf $TEST_DIR/sst + run_sql 'DROP DATABASE IF EXISTS db;' +} + +cleanup + +# auto_random_max = 2^{64-1-10}-1 +# db.test contains key auto_random_max - 1 +# db.test1 contains key auto_random_max +# db.test2 contains key auto_random_max + 1 (overflow) +run_lightning --sorted-kv-dir "$TEST_DIR/sst" --config "tests/$TEST_NAME/config.toml" --log-file "$TEST_DIR/lightning.log" +check_result +# successfully insert: d.test auto_random key has not reached maximum +run_sql 'INSERT INTO db.test(b) VALUES(11);' +# fail for further insertion +run_sql 'INSERT INTO db.test(b) VALUES(22);' 2>&1 | tee -a "$TEST_DIR/sql_res.$TEST_NAME.txt" +check_contains 'ERROR' +# fail: db.test1 has key auto_random_max +run_sql 'INSERT INTO db.test1(b) VALUES(11);' +run_sql 'INSERT INTO db.test1(b) VALUES(22);' 2>&1 | tee -a "$TEST_DIR/sql_res.$TEST_NAME.txt" +check_contains 'ERROR' +# successfully insert for overflow key +run_sql 'INSERT INTO db.test2(b) VALUES(33);' +run_sql 'INSERT INTO db.test2(b) VALUES(44);' +run_sql 'INSERT INTO db.test2(b) VALUES(55);' +cleanup diff --git a/br/tests/lightning_new_collation/run.sh b/br/tests/lightning_new_collation/run.sh index fea83277a3206..e572cefb88a52 100644 --- a/br/tests/lightning_new_collation/run.sh +++ b/br/tests/lightning_new_collation/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -24,7 +24,7 @@ cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # restart cluster with new collation enabled start_services --tidb-cfg $cur/tidb-new-collation.toml -for BACKEND in local importer tidb; do +for BACKEND in local tidb; do # Start importing the tables. run_sql 'DROP DATABASE IF EXISTS nc' diff --git a/br/tests/lightning_parquet/run.sh b/br/tests/lightning_parquet/run.sh index 32d0633ab9e50..ce5817415ef75 100755 --- a/br/tests/lightning_parquet/run.sh +++ b/br/tests/lightning_parquet/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -21,7 +21,7 @@ check_row_count() { check_contains "count(*): $2" } -for BACKEND in local importer tidb; do +for BACKEND in local tidb; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_partitioned-table/run.sh b/br/tests/lightning_partitioned-table/run.sh index 7b447f4e9753f..966d30cda7f88 100755 --- a/br/tests/lightning_partitioned-table/run.sh +++ b/br/tests/lightning_partitioned-table/run.sh @@ -18,7 +18,7 @@ set -eu -for BACKEND in tidb importer local; do +for BACKEND in tidb local; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_reload_cert/config.toml b/br/tests/lightning_reload_cert/config.toml new file mode 100644 index 0000000000000..850796f5cdb8a --- /dev/null +++ b/br/tests/lightning_reload_cert/config.toml @@ -0,0 +1,2 @@ +[checkpoint] +enable = false diff --git a/br/tests/lightning_reload_cert/data/test-schema-create.sql b/br/tests/lightning_reload_cert/data/test-schema-create.sql new file mode 100644 index 0000000000000..14379bd68472a --- /dev/null +++ b/br/tests/lightning_reload_cert/data/test-schema-create.sql @@ -0,0 +1 @@ +CREATE DATABASE test; diff --git a/br/tests/lightning_reload_cert/data/test.t-schema.sql b/br/tests/lightning_reload_cert/data/test.t-schema.sql new file mode 100644 index 0000000000000..57a1b65732950 --- /dev/null +++ b/br/tests/lightning_reload_cert/data/test.t-schema.sql @@ -0,0 +1 @@ +CREATE TABLE t(a INT PRIMARY KEY, b int); diff --git a/br/tests/lightning_reload_cert/data/test.t.sql b/br/tests/lightning_reload_cert/data/test.t.sql new file mode 100644 index 0000000000000..30e06b42e169b --- /dev/null +++ b/br/tests/lightning_reload_cert/data/test.t.sql @@ -0,0 +1 @@ +INSERT INTO t VALUES (1,1); diff --git a/br/tests/lightning_reload_cert/run.sh b/br/tests/lightning_reload_cert/run.sh new file mode 100644 index 0000000000000..e06ef8d7fbf51 --- /dev/null +++ b/br/tests/lightning_reload_cert/run.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eux + +cp "$TEST_DIR/certs/lightning.pem" "$TEST_DIR/certs/lightning-valid.pem" +trap 'mv "$TEST_DIR/certs/lightning-valid.pem" "$TEST_DIR/certs/lightning.pem"' EXIT + +# shellcheck disable=SC2089 +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/SetCertExpiredSoon=return(\"$TEST_DIR/certs/ca.key\")" +export GO_FAILPOINTS="${GO_FAILPOINTS};github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownWriteRows=sleep(15000)" + +# 1. After 10s, the certificate will be expired and import should report connection error. +run_lightning --backend='local' & +shpid="$!" +sleep 15 +ok=0 +for _ in {0..60}; do + if grep -Fq "connection closed before server preface received" "$TEST_DIR"/lightning.log; then + ok=1 + break + fi + sleep 1 +done +# Lightning process is wrapped by a shell process, use pstree to extract it out. +pid=$(pstree -p "$shpid" | grep -Eo "tidb-lightning\.\([0-9]*\)" | grep -Eo "[0-9]*") +if [ -n "$pid" ]; then + kill -9 "$pid" &>/dev/null || true +fi +if [ "$ok" = "0" ]; then + echo "lightning should report connection error due to certificate expired, but no error is reported" + exit 1 +fi +# Do some cleanup. +cp "$TEST_DIR/certs/lightning-valid.pem" "$TEST_DIR/certs/lightning.pem" +rm -rf "$TEST_DIR/lightning_reload_cert.sorted" "$TEST_DIR"/lightning.log + +# 2. Replace the certificate with a valid certificate before it is expired. Lightning should import successfully. +sleep 10 && cp "$TEST_DIR/certs/lightning-valid.pem" "$TEST_DIR/certs/lightning.pem" & +run_lightning --backend='local' diff --git a/br/tests/lightning_shard_rowid/config.toml b/br/tests/lightning_shard_rowid/config.toml index e69de29bb2d1d..261c42def21e0 100644 --- a/br/tests/lightning_shard_rowid/config.toml +++ b/br/tests/lightning_shard_rowid/config.toml @@ -0,0 +1,2 @@ +[tikv-importer] +backend = "local" diff --git a/br/tests/lightning_shard_rowid/run.sh b/br/tests/lightning_shard_rowid/run.sh index f170c3d338b68..d063e61bf6c79 100644 --- a/br/tests/lightning_shard_rowid/run.sh +++ b/br/tests/lightning_shard_rowid/run.sh @@ -25,25 +25,21 @@ if [ "$is_on" = "ON" ] || [ "$is_on" = "1" ]; then sleep 2 fi -for backend in importer local; do - if [ "$backend" = 'local' ]; then - check_cluster_version 4 0 0 'local backend' || continue - fi +check_cluster_version 4 0 0 'local backend' - run_sql 'DROP DATABASE IF EXISTS shard_rowid;' - run_lightning --backend $backend +run_sql 'DROP DATABASE IF EXISTS shard_rowid;' +run_lightning - run_sql "SELECT count(*) from shard_rowid.shr" - check_contains "count(*): 16" +run_sql "SELECT count(*) from shard_rowid.shr" +check_contains "count(*): 16" - run_sql "SELECT count(distinct _tidb_rowid & b'000001111111111111111111111111111111111111111111111111111111111') as count FROM shard_rowid.shr" - check_contains "count: 16" +run_sql "SELECT count(distinct _tidb_rowid & b'000001111111111111111111111111111111111111111111111111111111111') as count FROM shard_rowid.shr" +check_contains "count: 16" - # since we use random to generate the shard bits, with 16 record, there maybe less than 8 distinct value, - # but it should be bigger than 4 - run_sql 'SELECT count between 5 and 8 as correct from (SELECT count(distinct _tidb_rowid >> 60) as count from shard_rowid.shr) _' - check_contains "correct: 1" -done +# since we use random to generate the shard bits, with 16 record, there maybe less than 8 distinct value, +# but it should be bigger than 4 +run_sql 'SELECT count between 5 and 8 as correct from (SELECT count(distinct _tidb_rowid >> 60) as count from shard_rowid.shr) _' +check_contains "correct: 1" if [ -n "$is_on" ]; then run_sql "set @@global.tidb_enable_clustered_index = '$is_on'"; diff --git a/br/tests/lightning_source_linkfile/run.sh b/br/tests/lightning_source_linkfile/run.sh index c55266cc8a90f..095db16e10702 100644 --- a/br/tests/lightning_source_linkfile/run.sh +++ b/br/tests/lightning_source_linkfile/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # diff --git a/br/tests/lightning_tidb_rowid/run.sh b/br/tests/lightning_tidb_rowid/run.sh index ae762c514d93c..176e4cfdcf2bc 100755 --- a/br/tests/lightning_tidb_rowid/run.sh +++ b/br/tests/lightning_tidb_rowid/run.sh @@ -18,7 +18,7 @@ set -eu -for BACKEND in local importer tidb; do +for BACKEND in local tidb; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_tiflash/run.sh b/br/tests/lightning_tiflash/run.sh index c7ac62a6db0db..20b9e47b3996b 100644 --- a/br/tests/lightning_tiflash/run.sh +++ b/br/tests/lightning_tiflash/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -49,7 +49,7 @@ tiflash_replica_ready() { done } -for BACKEND in importer tidb local; do +for BACKEND in tidb local; do run_sql "DROP DATABASE IF EXISTS $DB" run_sql "CREATE DATABASE $DB" run_sql "CREATE TABLE $DB.t1 (i INT, j INT, s varchar(32), PRIMARY KEY(s, i));" diff --git a/br/tests/lightning_too_many_columns/run.sh b/br/tests/lightning_too_many_columns/run.sh index 2f8b8587f3ec3..b022cbb7de0e4 100644 --- a/br/tests/lightning_too_many_columns/run.sh +++ b/br/tests/lightning_too_many_columns/run.sh @@ -16,7 +16,7 @@ set -eux -for backend in tidb importer local; do +for backend in tidb local; do if [ "$backend" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_various_types/run.sh b/br/tests/lightning_various_types/run.sh index d46b9fa068e63..c9d638ac1b3a7 100755 --- a/br/tests/lightning_various_types/run.sh +++ b/br/tests/lightning_various_types/run.sh @@ -18,7 +18,7 @@ set -eu -for BACKEND in importer tidb local; do +for BACKEND in tidb local; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/lightning_view/run.sh b/br/tests/lightning_view/run.sh index 868c170c901c6..f51e5e2904e1c 100755 --- a/br/tests/lightning_view/run.sh +++ b/br/tests/lightning_view/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Copyright 2019 PingCAP, Inc. # @@ -15,7 +15,8 @@ # limitations under the License. set -euE -for BACKEND in local importer tidb; do + +for BACKEND in local tidb; do if [ "$BACKEND" = 'local' ]; then check_cluster_version 4 0 0 'local backend' || continue fi diff --git a/br/tests/up.sh b/br/tests/up.sh index b7b17558fe39d..78b04c3302fbb 100755 --- a/br/tests/up.sh +++ b/br/tests/up.sh @@ -149,7 +149,6 @@ COPY --from=ycsb-builder /go-ycsb /br/bin/go-ycsb COPY --from=tiflash-builder /tiflash/tiflash /br/bin/tiflash COPY --from=tiflash-builder /tiflash/libtiflash_proxy.so /br/bin/libtiflash_proxy.so COPY --from=tiflash-builder /tiflash/flash_cluster_manager /br/bin/flash_cluster_manager -COPY --from=lightning-builder /tikv-importer /br/bin/tikv-importer COPY --from=minio-builder /usr/bin/minio /br/bin/minio COPY --from=mc-builder /usr/bin/mc /br/bin/mc COPY --from=gcs-builder /bin/fake-gcs-server /br/bin/fake-gcs-server diff --git a/cmd/ddltest/column_test.go b/cmd/ddltest/column_test.go index eb926a7a67eb1..2fbf581764ca9 100644 --- a/cmd/ddltest/column_test.go +++ b/cmd/ddltest/column_test.go @@ -15,6 +15,7 @@ package ddltest import ( + goctx "context" "fmt" "reflect" "sync" @@ -29,7 +30,6 @@ import ( "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" "go.uber.org/zap" - goctx "golang.org/x/net/context" ) // After add column finished, check the records in the table. diff --git a/cmd/ddltest/ddl_test.go b/cmd/ddltest/ddl_test.go index ad22b4c720e60..ca5d128f0f64e 100644 --- a/cmd/ddltest/ddl_test.go +++ b/cmd/ddltest/ddl_test.go @@ -15,6 +15,7 @@ package ddltest import ( + goctx "context" "database/sql" "database/sql/driver" "flag" @@ -49,7 +50,6 @@ import ( "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" "go.uber.org/zap" - goctx "golang.org/x/net/context" ) var ( diff --git a/cmd/ddltest/index_test.go b/cmd/ddltest/index_test.go index 705e3a13dec03..7472ddca22a8a 100644 --- a/cmd/ddltest/index_test.go +++ b/cmd/ddltest/index_test.go @@ -15,6 +15,7 @@ package ddltest import ( + goctx "context" "fmt" "math" "sync" @@ -25,7 +26,6 @@ import ( "github.com/pingcap/tidb/store/gcworker" "github.com/pingcap/tidb/table" "github.com/stretchr/testify/require" - goctx "golang.org/x/net/context" ) func getIndex(t table.Table, name string) table.Index { diff --git a/cmd/explaintest/config.toml b/cmd/explaintest/config.toml index de401d4952ab4..aa770e051bec0 100644 --- a/cmd/explaintest/config.toml +++ b/cmd/explaintest/config.toml @@ -13,7 +13,6 @@ # limitations under the License. lease = "0" -mem-quota-query = 34359738368 host = "127.0.0.1" new_collations_enabled_on_first_bootstrap = true diff --git a/cmd/explaintest/disable_new_collation.toml b/cmd/explaintest/disable_new_collation.toml index c66f92d0b30c8..2846390a814ec 100644 --- a/cmd/explaintest/disable_new_collation.toml +++ b/cmd/explaintest/disable_new_collation.toml @@ -13,7 +13,6 @@ # limitations under the License. lease = "0" -mem-quota-query = 34359738368 host = "127.0.0.1" new_collations_enabled_on_first_bootstrap = false diff --git a/cmd/explaintest/main.go b/cmd/explaintest/main.go index 71c5ef17ab755..9e286a6330d97 100644 --- a/cmd/explaintest/main.go +++ b/cmd/explaintest/main.go @@ -721,6 +721,8 @@ func main() { "set @@tidb_projection_concurrency=4", "set @@tidb_distsql_scan_concurrency=15", "set @@global.tidb_enable_clustered_index=0;", + "set @@global.tidb_mem_quota_query=34359738368", + "set @@tidb_mem_quota_query=34359738368", } for _, sql := range resets { if _, err = mdb.Exec(sql); err != nil { diff --git a/cmd/explaintest/r/cte.result b/cmd/explaintest/r/cte.result index 6c1da3d121e77..3c8737d7400b8 100644 --- a/cmd/explaintest/r/cte.result +++ b/cmd/explaintest/r/cte.result @@ -730,3 +730,78 @@ c1 c2 2 1 2 2 2 3 +use test; +drop table if exists t1, t2; +drop view if exists v1; +create table t1 (a int); +insert into t1 values (0), (1), (2), (3), (4); +create table t2 (a int); +insert into t2 values (1), (2), (3), (4), (5); +drop view if exists v1,v2; +create view v1 as with t1 as (select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc; +create view v2 as with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc; +create database if not exists test1; +use test1; +select * from test.v1; +a +5 +4 +3 +2 +select * from test.v2; +a +6 +5 +4 +3 +use test; +drop table if exists t ,t1, t2; +create table t(a int); +insert into t values (0); +create table t1 (b int); +insert into t1 values (0); +create table t2 (c int); +insert into t2 values (0); +drop view if exists v1; +create view v1 as with t1 as (with t11 as (select * from t) select * from t1, t2) select * from t1; +use test1; +select * from test.v1; +b c +0 0 +use test; +drop table if exists t11111; +create table t11111 (d int); +insert into t11111 values (123), (223), (323); +drop view if exists v1; +create view v1 as WITH t123 AS (WITH t11111 AS ( SELECT * FROM t1 ) SELECT ( WITH t2 AS ( SELECT ( WITH t23 AS ( SELECT * FROM t11111 ) SELECT * FROM t23 LIMIT 1 ) FROM t11111 ) SELECT * FROM t2 LIMIT 1 ) FROM t11111, t2 ) SELECT * FROM t11111; +use test1; +select * from test.v1; +d +123 +223 +323 +use test; +drop table if exists t1; +create table t1 (a int); +insert into t1 values (1); +drop view if exists v1; +create view v1 as SELECT (WITH qn AS (SELECT 10*a as a FROM t1),qn2 AS (SELECT 3*a AS b FROM qn) SELECT * from qn2 LIMIT 1) FROM t1; +use test1; +select * from test.v1; +name_exp_1 +30 +use test; +drop table if exists t1,t2; +create table t1 (a int); +insert into t1 values (0), (1); +create table t2 (b int); +insert into t2 values (4), (5); +drop view if exists v1; +create view v1 as with t1 as (with t11 as (select * from t1) select * from t1, t2) select * from t1; +use test1; +select * from test.v1; +a b +0 5 +0 4 +1 5 +1 4 diff --git a/cmd/explaintest/r/explain_easy.result b/cmd/explaintest/r/explain_easy.result index 7cc05e4d9702b..247ae4b059e0b 100644 --- a/cmd/explaintest/r/explain_easy.result +++ b/cmd/explaintest/r/explain_easy.result @@ -172,11 +172,13 @@ Union 26000.00 root ├─HashAgg 16000.00 root group by:Column#10, funcs:firstrow(Column#12)->Column#10 │ └─Union 16000.00 root │ ├─StreamAgg 8000.00 root group by:test.t2.c1, funcs:firstrow(test.t2.c1)->Column#12, funcs:firstrow(test.t2.c1)->Column#10 -│ │ └─IndexReader 10000.00 root index:IndexFullScan -│ │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo +│ │ └─IndexReader 8000.00 root index:StreamAgg +│ │ └─StreamAgg 8000.00 cop[tikv] group by:test.t2.c1, +│ │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo │ └─StreamAgg 8000.00 root group by:test.t2.c1, funcs:firstrow(test.t2.c1)->Column#12, funcs:firstrow(test.t2.c1)->Column#10 -│ └─IndexReader 10000.00 root index:IndexFullScan -│ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo +│ └─IndexReader 8000.00 root index:StreamAgg +│ └─StreamAgg 8000.00 cop[tikv] group by:test.t2.c1, +│ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo └─IndexReader 10000.00 root index:IndexFullScan └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:false, stats:pseudo explain format = 'brief' select c1 from t2 union all select c1 from t2 union select c1 from t2; @@ -184,14 +186,17 @@ id estRows task access object operator info HashAgg 24000.00 root group by:Column#10, funcs:firstrow(Column#11)->Column#10 └─Union 24000.00 root ├─StreamAgg 8000.00 root group by:test.t2.c1, funcs:firstrow(test.t2.c1)->Column#11, funcs:firstrow(test.t2.c1)->Column#10 - │ └─IndexReader 10000.00 root index:IndexFullScan - │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo + │ └─IndexReader 8000.00 root index:StreamAgg + │ └─StreamAgg 8000.00 cop[tikv] group by:test.t2.c1, + │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo ├─StreamAgg 8000.00 root group by:test.t2.c1, funcs:firstrow(test.t2.c1)->Column#11, funcs:firstrow(test.t2.c1)->Column#10 - │ └─IndexReader 10000.00 root index:IndexFullScan - │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo + │ └─IndexReader 8000.00 root index:StreamAgg + │ └─StreamAgg 8000.00 cop[tikv] group by:test.t2.c1, + │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo └─StreamAgg 8000.00 root group by:test.t2.c1, funcs:firstrow(test.t2.c1)->Column#11, funcs:firstrow(test.t2.c1)->Column#10 - └─IndexReader 10000.00 root index:IndexFullScan - └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo + └─IndexReader 8000.00 root index:StreamAgg + └─StreamAgg 8000.00 cop[tikv] group by:test.t2.c1, + └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:true, stats:pseudo select * from information_schema.tidb_indexes where table_name='t4'; TABLE_SCHEMA TABLE_NAME NON_UNIQUE KEY_NAME SEQ_IN_INDEX COLUMN_NAME SUB_PART INDEX_COMMENT Expression INDEX_ID IS_VISIBLE CLUSTERED test t4 0 PRIMARY 1 a NULL NULL 0 YES YES diff --git a/cmd/explaintest/t/cte.test b/cmd/explaintest/t/cte.test index df9ee6c3b8d06..0c1623caa81dd 100644 --- a/cmd/explaintest/t/cte.test +++ b/cmd/explaintest/t/cte.test @@ -256,3 +256,61 @@ select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 un explain select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +# Some cases to Test Create View With CTE and checkout Database +# With name is the same as the table name +use test; +drop table if exists t1, t2; +drop view if exists v1; +create table t1 (a int); +insert into t1 values (0), (1), (2), (3), (4); +create table t2 (a int); +insert into t2 values (1), (2), (3), (4), (5); +drop view if exists v1,v2; +create view v1 as with t1 as (select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc; +create view v2 as with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc; +create database if not exists test1; +use test1; +select * from test.v1; +select * from test.v2; +# case +use test; +drop table if exists t ,t1, t2; +create table t(a int); +insert into t values (0); +create table t1 (b int); +insert into t1 values (0); +create table t2 (c int); +insert into t2 values (0); +drop view if exists v1; +create view v1 as with t1 as (with t11 as (select * from t) select * from t1, t2) select * from t1; +use test1; +select * from test.v1; +# case +use test; +drop table if exists t11111; +create table t11111 (d int); +insert into t11111 values (123), (223), (323); +drop view if exists v1; +create view v1 as WITH t123 AS (WITH t11111 AS ( SELECT * FROM t1 ) SELECT ( WITH t2 AS ( SELECT ( WITH t23 AS ( SELECT * FROM t11111 ) SELECT * FROM t23 LIMIT 1 ) FROM t11111 ) SELECT * FROM t2 LIMIT 1 ) FROM t11111, t2 ) SELECT * FROM t11111; +use test1; +select * from test.v1; +# case +use test; +drop table if exists t1; +create table t1 (a int); +insert into t1 values (1); +drop view if exists v1; +create view v1 as SELECT (WITH qn AS (SELECT 10*a as a FROM t1),qn2 AS (SELECT 3*a AS b FROM qn) SELECT * from qn2 LIMIT 1) FROM t1; +use test1; +select * from test.v1; +# case +use test; +drop table if exists t1,t2; +create table t1 (a int); +insert into t1 values (0), (1); +create table t2 (b int); +insert into t2 values (4), (5); +drop view if exists v1; +create view v1 as with t1 as (with t11 as (select * from t1) select * from t1, t2) select * from t1; +use test1; +select * from test.v1; diff --git a/cmd/importer/data.go b/cmd/importer/data.go index d682c60a254eb..d041ef41cb99a 100644 --- a/cmd/importer/data.go +++ b/cmd/importer/data.go @@ -20,7 +20,7 @@ import ( "sync" "time" - "github.com/cznic/mathutil" + "github.com/pingcap/tidb/util/mathutil" ) type datum struct { @@ -75,8 +75,8 @@ func (d *datum) nextInt64() int64 { defer d.Unlock() if d.useRange { - d.intValue = mathutil.MinInt64(d.intValue, d.maxIntValue) - d.intValue = mathutil.MaxInt64(d.intValue, d.minIntValue) + d.intValue = mathutil.Min(d.intValue, d.maxIntValue) + d.intValue = mathutil.Max(d.intValue, d.minIntValue) } d.updateRemains() return d.intValue diff --git a/cmd/importer/db.go b/cmd/importer/db.go index 235bd0b6ed74f..49f3d0ec67ad5 100644 --- a/cmd/importer/db.go +++ b/cmd/importer/db.go @@ -146,9 +146,9 @@ func genColumnData(table *table, column *column) (string, error) { if _, ok := table.uniqIndices[column.name]; ok { incremental = true } - isUnsigned := mysql.HasUnsignedFlag(tp.Flag) + isUnsigned := mysql.HasUnsignedFlag(tp.GetFlag()) - switch tp.Tp { + switch tp.GetType() { case mysql.TypeTiny: var data int64 if incremental { @@ -216,9 +216,9 @@ func genColumnData(table *table, column *column) (string, error) { case mysql.TypeVarchar, mysql.TypeString, mysql.TypeTinyBlob, mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: data := []byte{'\''} if incremental { - data = append(data, []byte(column.data.nextString(tp.Flen))...) + data = append(data, []byte(column.data.nextString(tp.GetFlen()))...) } else { - data = append(data, []byte(randStringValue(column, tp.Flen))...) + data = append(data, []byte(randStringValue(column, tp.GetFlen()))...) } data = append(data, '\'') @@ -280,7 +280,7 @@ func genColumnData(table *table, column *column) (string, error) { data = append(data, '\'') return string(data), nil case mysql.TypeNewDecimal: - var limit = int64(math.Pow10(tp.Flen)) + var limit = int64(math.Pow10(tp.GetFlen())) var intVal int64 if limit < 0 { limit = math.MaxInt64 @@ -298,7 +298,7 @@ func genColumnData(table *table, column *column) (string, error) { intVal = randInt64Value(column, (-limit+1)/2, (limit-1)/2) } } - return intToDecimalString(intVal, tp.Decimal), nil + return intToDecimalString(intVal, tp.GetDecimal()), nil default: return "", errors.Errorf("unsupported column type - %v", column) } diff --git a/config/config.go b/config/config.go index 4ffd599416aa7..9bd27332c470e 100644 --- a/config/config.go +++ b/config/config.go @@ -19,6 +19,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "math" "os" "os/user" "path/filepath" @@ -73,6 +74,12 @@ const ( DefStatsLoadQueueSizeLimit = 1 // DefMaxOfStatsLoadQueueSizeLimit is maximum limitation of the size of stats-load request queue DefMaxOfStatsLoadQueueSizeLimit = 100000 + // DefDDLSlowOprThreshold sets log DDL operations whose execution time exceeds the threshold value. + DefDDLSlowOprThreshold = 300 + // DefExpensiveQueryTimeThreshold indicates the time threshold of expensive query. + DefExpensiveQueryTimeThreshold = 60 + // DefMemoryUsageAlarmRatio is the threshold triggering an alarm which the memory usage of tidb-server instance exceeds. + DefMemoryUsageAlarmRatio = 0.8 ) // Valid config maps @@ -90,6 +97,51 @@ var ( tempStorageDirName = encodeDefTempStorageDir(os.TempDir(), DefHost, DefStatusHost, DefPort, DefStatusPort) ) +// InstanceConfigSection indicates a config session that has options moved to [instance] session. +type InstanceConfigSection struct { + // SectionName indicates the origin section name. + SectionName string + // NameMappings maps the origin name to the name in [instance]. + NameMappings map[string]string +} + +var ( + // sectionMovedToInstance records all config section and options that should be moved to [instance]. + sectionMovedToInstance = []InstanceConfigSection{ + { + "", + map[string]string{ + "check-mb4-value-in-utf8": "tidb_check_mb4_value_in_utf8", + "enable-collect-execution-info": "tidb_enable_collect_execution_info", + "plugin.load": "plugin_load", + "plugin.dir": "plugin_dir", + }, + }, + { + "log", + map[string]string{ + "enable-slow-log": "tidb_enable_slow_log", + "slow-threshold": "tidb_slow_log_threshold", + "record-plan-in-slow-log": "tidb_record_plan_in_slow_log", + }, + }, + { + "performance", + map[string]string{ + "force-priority": "tidb_force_priority", + "memory-usage-alarm-ratio": "tidb_memory_usage_alarm_ratio", + }, + }, + } + + // ConflictOptions indicates the conflict config options existing in both [instance] and other sections in config file. + ConflictOptions []InstanceConfigSection + + // DeprecatedOptions indicates the config options existing in some other sections in config file. + // They should be moved to [instance] section. + DeprecatedOptions []InstanceConfigSection +) + // Config contains configuration options. type Config struct { Host string `toml:"host" json:"host"` @@ -106,7 +158,6 @@ type Config struct { OOMUseTmpStorage bool `toml:"oom-use-tmp-storage" json:"oom-use-tmp-storage"` TempStoragePath string `toml:"tmp-storage-path" json:"tmp-storage-path"` OOMAction string `toml:"oom-action" json:"oom-action"` - MemQuotaQuery int64 `toml:"mem-quota-query" json:"mem-quota-query"` // TempStorageQuota describe the temporary storage Quota during query exector when OOMUseTmpStorage is enabled // If the quota exceed the capacity of the TempStoragePath, the tidb-server would exit with fatal error TempStorageQuota int64 `toml:"tmp-storage-quota" json:"tmp-storage-quota"` // Bytes @@ -117,6 +168,7 @@ type Config struct { TiDBEdition string `toml:"tidb-edition" json:"tidb-edition"` TiDBReleaseVersion string `toml:"tidb-release-version" json:"tidb-release-version"` Log Log `toml:"log" json:"log"` + Instance Instance `toml:"instance" json:"instance"` Security Security `toml:"security" json:"security"` Status Status `toml:"status" json:"status"` Performance Performance `toml:"performance" json:"performance"` @@ -363,10 +415,37 @@ type Log struct { SlowQueryFile string `toml:"slow-query-file" json:"slow-query-file"` SlowThreshold uint64 `toml:"slow-threshold" json:"slow-threshold"` ExpensiveThreshold uint `toml:"expensive-threshold" json:"expensive-threshold"` - QueryLogMaxLen uint64 `toml:"query-log-max-len" json:"query-log-max-len"` RecordPlanInSlowLog uint32 `toml:"record-plan-in-slow-log" json:"record-plan-in-slow-log"` } +// Instance is the section of instance scope system variables. +type Instance struct { + // These variables only exist in [instance] section. + + // TiDBGeneralLog is used to log every query in the server in info level. + TiDBGeneralLog bool `toml:"tidb_general_log" json:"tidb_general_log"` + // EnablePProfSQLCPU is used to add label sql label to pprof result. + EnablePProfSQLCPU bool `toml:"tidb_pprof_sql_cpu" json:"tidb_pprof_sql_cpu"` + // DDLSlowOprThreshold sets log DDL operations whose execution time exceeds the threshold value. + DDLSlowOprThreshold uint32 `toml:"ddl_slow_threshold" json:"ddl_slow_threshold"` + // ExpensiveQueryTimeThreshold indicates the time threshold of expensive query. + ExpensiveQueryTimeThreshold uint64 `toml:"tidb_expensive_query_time_threshold" json:"tidb_expensive_query_time_threshold"` + + // These variables exist in both 'instance' section and another place. + // The configuration in 'instance' section takes precedence. + + EnableSlowLog AtomicBool `toml:"tidb_enable_slow_log" json:"tidb_enable_slow_log"` + SlowThreshold uint64 `toml:"tidb_slow_log_threshold" json:"tidb_slow_log_threshold"` + RecordPlanInSlowLog uint32 `toml:"tidb_record_plan_in_slow_log" json:"tidb_record_plan_in_slow_log"` + CheckMb4ValueInUTF8 AtomicBool `toml:"tidb_check_mb4_value_in_utf8" json:"tidb_check_mb4_value_in_utf8"` + ForcePriority string `toml:"tidb_force_priority" json:"tidb_force_priority"` + MemoryUsageAlarmRatio float64 `toml:"tidb_memory_usage_alarm_ratio" json:"tidb_memory_usage_alarm_ratio"` + // EnableCollectExecutionInfo enables the TiDB to collect execution info. + EnableCollectExecutionInfo bool `toml:"tidb_enable_collect_execution_info" json:"tidb_enable_collect_execution_info"` + PluginDir string `toml:"plugin_dir" json:"plugin_dir"` + PluginLoad string `toml:"plugin_load" json:"plugin_load"` +} + func (l *Log) getDisableTimestamp() bool { if l.EnableTimestamp == nbUnset && l.DisableTimestamp == nbUnset { return false @@ -435,6 +514,38 @@ func (e *ErrConfigValidationFailed) Error() string { e.UndecodedItems, ", ")) } +// ErrConfigInstanceSection error is used to warning the user +// which config options should be moved to 'instance'. +type ErrConfigInstanceSection struct { + confFile string + configSections *[]InstanceConfigSection + deprecatedSections *[]InstanceConfigSection +} + +func (e *ErrConfigInstanceSection) Error() string { + var builder strings.Builder + if len(*e.configSections) > 0 { + builder.WriteString("Conflict configuration options exists on both [instance] section and some other sections. ") + } + if len(*e.deprecatedSections) > 0 { + builder.WriteString("Some configuration options should be moved to [instance] section. ") + } + builder.WriteString("Please use the latter config options in [instance] instead: ") + for _, configSection := range *e.configSections { + for oldName, newName := range configSection.NameMappings { + builder.WriteString(fmt.Sprintf(" (%s, %s)", oldName, newName)) + } + } + for _, configSection := range *e.deprecatedSections { + for oldName, newName := range configSection.NameMappings { + builder.WriteString(fmt.Sprintf(" (%s, %s)", oldName, newName)) + } + } + builder.WriteString(".") + + return builder.String() +} + // ClusterSecurity returns Security info for cluster func (s *Security) ClusterSecurity() tikvcfg.Security { return tikvcfg.NewSecurity(s.ClusterSSLCA, s.ClusterSSLCert, s.ClusterSSLKey, s.ClusterVerifyCN) @@ -483,8 +594,10 @@ type Performance struct { CrossJoin bool `toml:"cross-join" json:"cross-join"` RunAutoAnalyze bool `toml:"run-auto-analyze" json:"run-auto-analyze"` DistinctAggPushDown bool `toml:"distinct-agg-push-down" json:"distinct-agg-push-down"` - CommitterConcurrency int `toml:"committer-concurrency" json:"committer-concurrency"` - MaxTxnTTL uint64 `toml:"max-txn-ttl" json:"max-txn-ttl"` + // Whether enable projection push down for coprocessors (both tikv & tiflash), default false. + ProjectionPushDown bool `toml:"projection-push-down" json:"projection-push-down"` + CommitterConcurrency int `toml:"committer-concurrency" json:"committer-concurrency"` + MaxTxnTTL uint64 `toml:"max-txn-ttl" json:"max-txn-ttl"` // Deprecated MemProfileInterval string `toml:"-" json:"-"` IndexUsageSyncLease string `toml:"index-usage-sync-lease" json:"index-usage-sync-lease"` @@ -627,7 +740,6 @@ var defaultConf = Config{ TempStorageQuota: -1, TempStoragePath: tempStorageDirName, OOMAction: OOMActionCancel, - MemQuotaQuery: 1 << 30, EnableBatchDML: false, CheckMb4ValueInUTF8: *NewAtomicBool(true), MaxIndexLength: 3072, @@ -658,10 +770,24 @@ var defaultConf = Config{ EnableErrorStack: nbUnset, // If both options are nbUnset, getDisableErrorStack() returns true EnableTimestamp: nbUnset, DisableTimestamp: nbUnset, // If both options are nbUnset, getDisableTimestamp() returns false - QueryLogMaxLen: logutil.DefaultQueryLogMaxLen, RecordPlanInSlowLog: logutil.DefaultRecordPlanInSlowLog, EnableSlowLog: *NewAtomicBool(logutil.DefaultTiDBEnableSlowLog), }, + Instance: Instance{ + TiDBGeneralLog: false, + EnablePProfSQLCPU: false, + DDLSlowOprThreshold: DefDDLSlowOprThreshold, + ExpensiveQueryTimeThreshold: DefExpensiveQueryTimeThreshold, + EnableSlowLog: *NewAtomicBool(logutil.DefaultTiDBEnableSlowLog), + SlowThreshold: logutil.DefaultSlowThreshold, + RecordPlanInSlowLog: logutil.DefaultRecordPlanInSlowLog, + CheckMb4ValueInUTF8: *NewAtomicBool(true), + ForcePriority: "NO_PRIORITY", + MemoryUsageAlarmRatio: DefMemoryUsageAlarmRatio, + EnableCollectExecutionInfo: true, + PluginDir: "/data/deploy/plugin", + PluginLoad: "", + }, Status: Status{ ReportStatus: true, StatusHost: DefStatusHost, @@ -672,12 +798,12 @@ var defaultConf = Config{ GRPCKeepAliveTimeout: 3, GRPCConcurrentStreams: 1024, GRPCInitialWindowSize: 2 * 1024 * 1024, - GRPCMaxSendMsgSize: 10 * 1024 * 1024, + GRPCMaxSendMsgSize: math.MaxInt32, }, Performance: Performance{ MaxMemory: 0, ServerMemoryQuota: 0, - MemoryUsageAlarmRatio: 0.8, + MemoryUsageAlarmRatio: DefMemoryUsageAlarmRatio, TCPKeepAlive: true, TCPNoDelay: true, CrossJoin: true, @@ -692,6 +818,7 @@ var defaultConf = Config{ TxnEntrySizeLimit: DefTxnEntrySizeLimit, TxnTotalSizeLimit: DefTxnTotalSizeLimit, DistinctAggPushDown: false, + ProjectionPushDown: false, CommitterConcurrency: defTiKVCfg.CommitterConcurrency, MaxTxnTTL: defTiKVCfg.MaxTxnTTL, // 1hour // TODO: set indexUsageSyncLease to 60s. @@ -801,6 +928,8 @@ var deprecatedConfig = map[string]struct{}{ "stmt-summary.max-sql-length": {}, "stmt-summary.refresh-interval": {}, "stmt-summary.history-size": {}, + "mem-quota-query": {}, + "query-log-max-len": {}, } func isAllDeprecatedConfigItems(items []string) bool { @@ -812,10 +941,6 @@ func isAllDeprecatedConfigItems(items []string) bool { return true } -// IsMemoryQuotaQuerySetByUser indicates whether the config item mem-quota-query -// is set by the user. -var IsMemoryQuotaQuerySetByUser bool - // IsOOMActionSetByUser indicates whether the config item mem-action is set by // the user. var IsOOMActionSetByUser bool @@ -839,6 +964,9 @@ func InitializeConfig(confPath string, configCheck, configStrict bool, enforceCm fmt.Fprintln(os.Stderr, err.Error()) err = nil } + } else if tmp, ok := err.(*ErrConfigInstanceSection); ok { + logutil.BgLogger().Warn(tmp.Error()) + err = nil } } @@ -875,9 +1003,6 @@ func (c *Config) Load(confFile string) error { if c.TokenLimit == 0 { c.TokenLimit = 1000 } - if metaData.IsDefined("mem-quota-query") { - IsMemoryQuotaQuerySetByUser = true - } if metaData.IsDefined("oom-action") { IsOOMActionSetByUser = true } @@ -892,6 +1017,31 @@ func (c *Config) Load(confFile string) error { err = &ErrConfigValidationFailed{confFile, undecodedItems} } + for _, section := range sectionMovedToInstance { + newConflictSection := InstanceConfigSection{SectionName: section.SectionName, NameMappings: map[string]string{}} + newDeprecatedSection := InstanceConfigSection{SectionName: section.SectionName, NameMappings: map[string]string{}} + for oldName, newName := range section.NameMappings { + if section.SectionName == "" && metaData.IsDefined(oldName) || + section.SectionName != "" && metaData.IsDefined(section.SectionName, oldName) { + if metaData.IsDefined("instance", newName) { + newConflictSection.NameMappings[oldName] = newName + } else { + newDeprecatedSection.NameMappings[oldName] = newName + } + } + } + if len(newConflictSection.NameMappings) > 0 { + ConflictOptions = append(ConflictOptions, newConflictSection) + } + if len(newDeprecatedSection.NameMappings) > 0 { + DeprecatedOptions = append(DeprecatedOptions, newDeprecatedSection) + } + } + if len(ConflictOptions) > 0 || len(DeprecatedOptions) > 0 { + // Give a warning that the 'instance' section should be used. + err = &ErrConfigInstanceSection{confFile, &ConflictOptions, &DeprecatedOptions} + } + return err } @@ -953,8 +1103,8 @@ func (c *Config) Valid() error { return fmt.Errorf("txn-total-size-limit should be less than %d", 1<<40) } - if c.Performance.MemoryUsageAlarmRatio > 1 || c.Performance.MemoryUsageAlarmRatio < 0 { - return fmt.Errorf("memory-usage-alarm-ratio in [Performance] must be greater than or equal to 0 and less than or equal to 1") + if c.Instance.MemoryUsageAlarmRatio > 1 || c.Instance.MemoryUsageAlarmRatio < 0 { + return fmt.Errorf("tidb_memory_usage_alarm_ratio in [Instance] must be greater than or equal to 0 and less than or equal to 1") } if c.PreparedPlanCache.Capacity < 1 { diff --git a/config/config.toml.example b/config/config.toml.example index 99cefd528b837..486d011467787 100644 --- a/config/config.toml.example +++ b/config/config.toml.example @@ -31,13 +31,10 @@ split-table = true # The limit of concurrent executed sessions. token-limit = 1000 -# The maximum memory available for a single SQL statement. Default: 1GB -mem-quota-query = 1073741824 - -# Controls whether to enable the temporary storage for some operators when a single SQL statement exceeds the memory quota specified by mem-quota-query. +# Controls whether to enable the temporary storage for some operators when a single SQL statement exceeds the memory quota specified by the memory quota. oom-use-tmp-storage = true -# Specifies the temporary storage path for some operators when a single SQL statement exceeds the memory quota specified by mem-quota-query. +# Specifies the temporary storage path for some operators when a single SQL statement exceeds the memory quota specified by the memory quota. # It defaults to a generated directory in `/_tidb/` if it is unset. # It only takes effect when `oom-use-tmp-storage` is `true`. # tmp-storage-path = "/tmp/_tidb/MC4wLjAuMDo0MDAwLzAuMC4wLjA6MTAwODA=/tmp-storage" @@ -47,7 +44,7 @@ oom-use-tmp-storage = true # The default value of tmp-storage-quota is under 0 which means tidb-server wouldn't check the capacity. tmp-storage-quota = -1 -# Specifies what operation TiDB performs when a single SQL statement exceeds the memory quota specified by mem-quota-query and cannot be spilled over to disk. +# Specifies what operation TiDB performs when a single SQL statement exceeds the memory quota specified by the memory quota and cannot be spilled over to disk. # Valid options: ["log", "cancel"] oom-action = "cancel" @@ -62,9 +59,6 @@ compatible-kill-query = false # The health check will fail immediately but the server will not start shutting down until the time has elapsed. graceful-wait-before-shutdown = 0 -# check mb4 value in utf8 is used to control whether to check the mb4 characters when the charset is utf8. -check-mb4-value-in-utf8 = true - # treat-old-version-utf8-as-utf8mb4 use for upgrade compatibility. Set to true will treat old version table/column UTF8 charset as UTF8MB4. treat-old-version-utf8-as-utf8mb4 = true @@ -142,25 +136,12 @@ format = "text" # Enable annotating logs with the full stack error message, if not set, it will be defaulted to false. # enable-error-stack = false -# Whether to enable slow query log. -enable-slow-log = true - # Stores slow query log into separated files. slow-query-file = "tidb-slow.log" -# Queries with execution time greater than this value will be logged. (Milliseconds) -slow-threshold = 300 - -# record-plan-in-slow-log is used to enable record query plan in slow log. -# 0 is disable. 1 is enable. -record-plan-in-slow-log = 1 - # Queries with internal result greater than this value will be logged. expensive-threshold = 10000 -# Maximum query length recorded in log. -query-log-max-len = 4096 - # File logging. [log.file] # Log file name. @@ -242,14 +223,6 @@ max-procs = 0 # Memory size quota for tidb server, 0 means unlimited server-memory-quota = 0 -# The alarm threshold when memory usage of the tidb-server exceeds. The valid value range is greater than or equal to 0 -# and less than or equal to 1. The default value is 0.8. -# If this configuration is set to 0 or 1, it'll disable the alarm. -# Otherwise, related information will be recorded in the directory `tmp-storage-path/record`. -# Note: If the configuration `server-memory-quota` is set and larger than 0, the alarm threshold will be -# `memory-usage-alarm-ratio * server-memory-quota`; otherwise, it'll be `memory-usage-alarm-ratio * system memory size`. -memory-usage-alarm-ratio = 0.8 - # StmtCountLimit limits the max count of statement inside a transaction. stmt-count-limit = 5000 @@ -275,10 +248,6 @@ query-feedback-limit = 512 # row count in statistics of a table is greater than it. pseudo-estimate-ratio = 0.8 -# Force the priority of all statements in a specified priority. -# The value could be "NO_PRIORITY", "LOW_PRIORITY", "HIGH_PRIORITY" or "DELAYED". -force-priority = "NO_PRIORITY" - # Bind info lease duration, which influences the duration of loading bind info and handling invalid bind. bind-info-lease = "3s" @@ -470,3 +439,46 @@ allow-expression-index = false [isolation-read] # engines means allow the tidb server read data from which types of engines. options: "tikv", "tiflash", "tidb". engines = ["tikv", "tiflash", "tidb"] + +# instance scope variables +# These options are also available as a system variable for online configuration +# changes to the system variable do not persist to the cluster. You must make changes +# in this configuration file on each tidb-server. +[instance] + +# tidb_general_log is used to log every query in the server in info level. +tidb_general_log = false + +# tidb_pprof_sql_cpu is used to add label sql label to pprof result. +tidb_pprof_sql_cpu = false + +# ddl_slow_threshold sets log DDL operations whose execution time exceeds the threshold value. +ddl_slow_threshold = 300 + +# tidb_expensive_query_time_threshold indicates the time threshold of expensive query. +tidb_expensive_query_time_threshold = 60 + +# Force the priority of all statements in a specified priority. +# The value could be "NO_PRIORITY", "LOW_PRIORITY", "HIGH_PRIORITY" or "DELAYED". +tidb_force_priority = "NO_PRIORITY" + +# The alarm threshold when memory usage of the tidb-server exceeds. The valid value range is greater than or equal to 0 +# and less than or equal to 1. The default value is 0.8. +# If this configuration is set to 0 or 1, it'll disable the alarm. +# Otherwise, related information will be recorded in the directory `tmp-storage-path/record`. +# Note: If the configuration `server-memory-quota` is set and larger than 0, the alarm threshold will be +# `tidb_memory_usage_alarm_ratio * server-memory-quota`; otherwise, it'll be `tidb_memory_usage_alarm_ratio * system memory size`. +tidb_memory_usage_alarm_ratio = 0.8 + +# check mb4 value in utf8 is used to control whether to check the mb4 characters when the charset is utf8. +tidb_check_mb4_value_in_utf8 = true + +# Whether to enable slow query log. +tidb_enable_slow_log = true + +# Queries with execution time greater than this value will be logged. (Milliseconds) +tidb_slow_log_threshold = 300 + +# tidb_record_plan_in_slow_log is used to enable record query plan in slow log. +# 0 is disable. 1 is enable. +tidb_record_plan_in_slow_log = 1 diff --git a/config/config_test.go b/config/config_test.go index bc90a2763bfad..175466b0e6136 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -17,12 +17,14 @@ package config import ( "bytes" "encoding/json" + "fmt" "os" "os/user" "path/filepath" "reflect" "regexp" "runtime" + "strings" "testing" "github.com/BurntSushi/toml" @@ -106,9 +108,6 @@ func TestNullableBoolUnmarshal(t *testing.T) { func TestLogConfig(t *testing.T) { var conf Config configFile := "log_config.toml" - _, localFile, _, _ := runtime.Caller(0) - configFile = filepath.Join(filepath.Dir(localFile), configFile) - f, err := os.Create(configFile) require.NoError(t, err) defer func() { @@ -177,11 +176,8 @@ func TestConfig(t *testing.T) { conf.Performance.TxnTotalSizeLimit = 1000 conf.TiKVClient.CommitTimeout = "10s" conf.TiKVClient.RegionCacheTTL = 600 - conf.Log.EnableSlowLog.Store(logutil.DefaultTiDBEnableSlowLog) + conf.Instance.EnableSlowLog.Store(logutil.DefaultTiDBEnableSlowLog) configFile := "config.toml" - _, localFile, _, _ := runtime.Caller(0) - configFile = filepath.Join(filepath.Dir(localFile), configFile) - f, err := os.Create(configFile) require.NoError(t, err) defer func(configFile string) { @@ -217,7 +213,6 @@ enable-batch-dml = true server-version = "test_version" repair-mode = true max-server-connections = 200 -mem-quota-query = 10000 max-index-length = 3080 index-limit = 70 table-column-count-limit = 4000 @@ -292,7 +287,6 @@ grpc-max-send-msg-size = 40960 require.True(t, conf.RepairMode) require.Equal(t, uint64(16), conf.TiKVClient.ResolveLockLiteThreshold) require.Equal(t, uint32(200), conf.MaxServerConnections) - require.Equal(t, int64(10000), conf.MemQuotaQuery) require.Equal(t, []string{"tiflash"}, conf.IsolationRead.Engines) require.Equal(t, 3080, conf.MaxIndexLength) require.Equal(t, 70, conf.IndexLimit) @@ -378,7 +372,7 @@ spilled-file-encryption-method = "aes128-ctr" require.NoError(t, f.Sync()) require.NoError(t, conf.Load(configFile)) - configFile = filepath.Join(filepath.Dir(localFile), "config.toml.example") + configFile = "config.toml.example" require.NoError(t, conf.Load(configFile)) // Make sure the example config is the same as default config except `auto_tls`. @@ -398,7 +392,6 @@ spilled-file-encryption-method = "aes128-ctr" // Test for TLS config. certFile := "cert.pem" - certFile = filepath.Join(filepath.Dir(localFile), certFile) f, err = os.Create(certFile) require.NoError(t, err) _, err = f.WriteString(`-----BEGIN CERTIFICATE----- @@ -424,7 +417,6 @@ c933WW1E0hCtvuGxWFIFtoJMQoyH0Pl4ACmY/6CokCCZKDInrPdhhf3MGRjkkw== require.NoError(t, f.Close()) keyFile := "key.pem" - keyFile = filepath.Join(filepath.Dir(localFile), keyFile) f, err = os.Create(keyFile) require.NoError(t, err) _, err = f.WriteString(`-----BEGIN RSA PRIVATE KEY----- @@ -534,6 +526,95 @@ func TestPreparePlanCacheValid(t *testing.T) { } } +func TestConflictInstanceConfig(t *testing.T) { + var expectedNewName string + conf := new(Config) + configFile := "config.toml" + _, localFile, _, _ := runtime.Caller(0) + configFile = filepath.Join(filepath.Dir(localFile), configFile) + + f, err := os.Create(configFile) + require.NoError(t, err) + defer func(configFile string) { + require.NoError(t, os.Remove(configFile)) + }(configFile) + + // ConflictOptions indicates the options existing in both [instance] and some other sessions. + // Just receive a warning and keep their respective values. + expectedConflictOptions := map[string]InstanceConfigSection{ + "": { + "", map[string]string{"check-mb4-value-in-utf8": "tidb_check_mb4_value_in_utf8"}, + }, + "log": { + "log", map[string]string{"enable-slow-log": "tidb_enable_slow_log"}, + }, + "performance": { + "performance", map[string]string{"force-priority": "tidb_force_priority"}, + }, + } + _, err = f.WriteString("check-mb4-value-in-utf8 = true \n" + + "[log] \nenable-slow-log = true \n" + + "[performance] \nforce-priority = \"NO_PRIORITY\"\n" + + "[instance] \ntidb_check_mb4_value_in_utf8 = false \ntidb_enable_slow_log = false \ntidb_force_priority = \"LOW_PRIORITY\"") + require.NoError(t, err) + require.NoError(t, f.Sync()) + err = conf.Load(configFile) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "Conflict configuration options exists on both [instance] section and some other sections.")) + require.False(t, conf.Instance.CheckMb4ValueInUTF8.Load()) + require.True(t, conf.CheckMb4ValueInUTF8.Load()) + require.Equal(t, true, conf.Log.EnableSlowLog.Load()) + require.Equal(t, false, conf.Instance.EnableSlowLog.Load()) + require.Equal(t, "NO_PRIORITY", conf.Performance.ForcePriority) + require.Equal(t, "LOW_PRIORITY", conf.Instance.ForcePriority) + require.Equal(t, 0, len(DeprecatedOptions)) + for _, conflictOption := range ConflictOptions { + expectedConflictOption, ok := expectedConflictOptions[conflictOption.SectionName] + require.True(t, ok) + for oldName, newName := range conflictOption.NameMappings { + expectedNewName, ok = expectedConflictOption.NameMappings[oldName] + require.True(t, ok) + require.Equal(t, expectedNewName, newName) + } + } + + err = f.Truncate(0) + require.NoError(t, err) + _, err = f.Seek(0, 0) + require.NoError(t, err) + + // DeprecatedOptions indicates the options that should be moved to [instance] section. + // The value in conf.Instance.* would be overwritten by the other sections. + expectedDeprecatedOptions := map[string]InstanceConfigSection{ + "": { + "", map[string]string{"enable-collect-execution-info": "tidb_enable_collect_execution_info"}, + }, + "log": { + "log", map[string]string{"slow-threshold": "tidb_slow_log_threshold"}, + }, + "performance": { + "performance", map[string]string{"memory-usage-alarm-ratio": "tidb_memory_usage_alarm_ratio"}, + }, + } + _, err = f.WriteString("enable-collect-execution-info = false \n" + + "[log] \nslow-threshold = 100 \n" + + "[performance] \nmemory-usage-alarm-ratio = 0.5") + require.NoError(t, err) + require.NoError(t, f.Sync()) + err = conf.Load(configFile) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "Some configuration options should be moved to [instance] section.")) + for _, deprecatedOption := range DeprecatedOptions { + expectedDeprecatedOption, ok := expectedDeprecatedOptions[deprecatedOption.SectionName] + require.True(t, ok) + for oldName, newName := range deprecatedOption.NameMappings { + expectedNewName, ok = expectedDeprecatedOption.NameMappings[oldName] + require.True(t, ok, fmt.Sprintf("Get unexpected %s.", oldName)) + require.Equal(t, expectedNewName, newName) + } + } +} + func TestMaxIndexLength(t *testing.T) { conf := NewConfig() checkValid := func(indexLen int, shouldBeValid bool) { @@ -658,8 +739,7 @@ func TestTcpNoDelay(t *testing.T) { func TestConfigExample(t *testing.T) { conf := NewConfig() - _, localFile, _, _ := runtime.Caller(0) - configFile := filepath.Join(filepath.Dir(localFile), "config.toml.example") + configFile := "config.toml.example" metaData, err := toml.DecodeFile(configFile, conf) require.NoError(t, err) keys := metaData.Keys() diff --git a/config/config_util.go b/config/config_util.go index c192a54fd7dbc..8ca7da61e5a18 100644 --- a/config/config_util.go +++ b/config/config_util.go @@ -46,13 +46,11 @@ var ( "Performance.StmtCountLimit": {}, "Performance.TCPKeepAlive": {}, "OOMAction": {}, - "MemQuotaQuery": {}, "TiKVClient.StoreLimit": {}, "Log.Level": {}, - "Log.SlowThreshold": {}, - "Log.QueryLogMaxLen": {}, "Log.ExpensiveThreshold": {}, - "CheckMb4ValueInUTF8": {}, + "Instance.SlowThreshold": {}, + "Instance.CheckMb4ValueInUTF8": {}, "TxnLocalLatches.Capacity": {}, "CompatibleKillQuery": {}, "TreatOldVersionUTF8AsUTF8MB4": {}, diff --git a/config/config_util_test.go b/config/config_util_test.go index f23c47f8dd796..d4e561aaef7e6 100644 --- a/config/config_util_test.go +++ b/config/config_util_test.go @@ -33,11 +33,11 @@ func TestCloneConf(t *testing.T) { c1.Store = "abc" c1.Port = 2333 - c1.Log.EnableSlowLog.Store(!c1.Log.EnableSlowLog.Load()) + c1.Instance.EnableSlowLog.Store(!c1.Instance.EnableSlowLog.Load()) c1.RepairTableList = append(c1.RepairTableList, "abc") require.NotEqual(t, c2.Store, c1.Store) require.NotEqual(t, c2.Port, c1.Port) - require.NotEqual(t, c2.Log.EnableSlowLog, c1.Log.EnableSlowLog) + require.NotEqual(t, c2.Instance.EnableSlowLog, c1.Instance.EnableSlowLog) require.NotEqual(t, fmt.Sprintf("%v", c2.RepairTableList), fmt.Sprintf("%v", c1.RepairTableList)) } @@ -54,17 +54,16 @@ func TestMergeConfigItems(t *testing.T) { newConf.Performance.QueryFeedbackLimit = 123 newConf.Performance.PseudoEstimateRatio = 123 newConf.OOMAction = "panic" - newConf.MemQuotaQuery = 123 newConf.TiKVClient.StoreLimit = 123 // rejected newConf.Store = "tiflash" newConf.Port = 2333 newConf.AdvertiseAddress = "1.2.3.4" - newConf.Log.SlowThreshold = 2345 + newConf.Instance.SlowThreshold = 2345 as, rs := MergeConfigItems(oldConf, newConf) - require.Equal(t, 10, len(as)) + require.Equal(t, 9, len(as)) require.Equal(t, 3, len(rs)) for _, a := range as { _, ok := dynamicConfigItems[a] @@ -82,9 +81,8 @@ func TestMergeConfigItems(t *testing.T) { require.Equal(t, newConf.Performance.QueryFeedbackLimit, oldConf.Performance.QueryFeedbackLimit) require.Equal(t, newConf.Performance.PseudoEstimateRatio, oldConf.Performance.PseudoEstimateRatio) require.Equal(t, newConf.OOMAction, oldConf.OOMAction) - require.Equal(t, newConf.MemQuotaQuery, oldConf.MemQuotaQuery) require.Equal(t, newConf.TiKVClient.StoreLimit, oldConf.TiKVClient.StoreLimit) - require.Equal(t, newConf.Log.SlowThreshold, oldConf.Log.SlowThreshold) + require.Equal(t, newConf.Instance.SlowThreshold, oldConf.Instance.SlowThreshold) require.Equal(t, oriConf.Store, oldConf.Store) require.Equal(t, oriConf.Port, oldConf.Port) diff --git a/ddl/cancel_ddl_test.go b/ddl/cancel_ddl_test.go deleted file mode 100644 index 695d1dea30b34..0000000000000 --- a/ddl/cancel_ddl_test.go +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright 2022 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package ddl - -import ( - "context" - "sync" - "testing" - "time" - - "github.com/pingcap/errors" - "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/parser/charset" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/mock" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" -) - -type testDDLSerialSuiteToVerify struct { - suite.Suite -} - -func TestDDLSerialSuite(t *testing.T) { - suite.Run(t, new(testDDLSerialSuiteToVerify)) -} - -func (s *testDDLSerialSuiteToVerify) SetupSuite() { - SetWaitTimeWhenErrorOccurred(time.Microsecond) -} - -func checkCancelState(txn kv.Transaction, job *model.Job, test *testCancelJob) error { - var checkErr error - addIndexFirstReorg := (test.act == model.ActionAddIndex || test.act == model.ActionAddPrimaryKey) && - job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 - // If the action is adding index and the state is writing reorganization, it wants to test the case of cancelling the job when backfilling indexes. - // When the job satisfies this case of addIndexFirstReorg, the worker hasn't started to backfill indexes. - if test.cancelState == job.SchemaState && !addIndexFirstReorg && !job.IsRollingback() { - errs, err := admin.CancelJobs(txn, test.jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return checkErr - } - // It only tests cancel one DDL job. - if !terror.ErrorEqual(errs[0], test.cancelRetErrs[0]) { - checkErr = errors.Trace(errs[0]) - return checkErr - } - } - return checkErr -} - -type testCancelJob struct { - jobIDs []int64 - cancelRetErrs []error // cancelRetErrs is the first return value of CancelJobs. - act model.ActionType // act is the job action. - cancelState model.SchemaState -} - -func buildCancelJobTests(firstID int64) []testCancelJob { - noErrs := []error{nil} - tests := []testCancelJob{ - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 1}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 2}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 3}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 4}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 4)}, cancelState: model.StatePublic}, - - // Test cancel drop index job , see TestCancelDropIndex. - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 5}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 6}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 7}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 8}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 8)}, cancelState: model.StatePublic}, - - // Test create table, watch out, table id will alloc a globalID. - {act: model.ActionCreateTable, jobIDs: []int64{firstID + 10}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - // Test create database, watch out, database id will alloc a globalID. - {act: model.ActionCreateSchema, jobIDs: []int64{firstID + 12}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 13}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 13)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 14}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 14)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 15}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 15)}, cancelState: model.StateWriteReorganization}, - {act: model.ActionRebaseAutoID, jobIDs: []int64{firstID + 16}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionShardRowID, jobIDs: []int64{firstID + 17}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 18}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 19}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - - {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 20}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 21}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 21)}, cancelState: model.StatePublic}, - {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 22}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 23}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 23)}, cancelState: model.StatePublic}, - - {act: model.ActionRenameTable, jobIDs: []int64{firstID + 24}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionRenameTable, jobIDs: []int64{firstID + 25}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 25)}, cancelState: model.StatePublic}, - - {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 26}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 27}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 27)}, cancelState: model.StatePublic}, - {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 28}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 29}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 29)}, cancelState: model.StatePublic}, - {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 31}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 32}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 32)}, cancelState: model.StatePublic}, - - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 33}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 34}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 35}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 36}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 36)}, cancelState: model.StatePublic}, - {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 37}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 38}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 38)}, cancelState: model.StateDeleteOnly}, - - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 39}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 40}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 41}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 42}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 42)}, cancelState: model.StatePublic}, - - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 43}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 43)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 44}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 44)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 45}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 45)}, cancelState: model.StateWriteReorganization}, - - {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 47}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 48}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 48)}, cancelState: model.StatePublic}, - - {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 54}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 55}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 55)}, cancelState: model.StatePublic}, - - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 60}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 61}, cancelRetErrs: noErrs, cancelState: model.StateReplicaOnly}, - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 62}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, - - // modify column has two different types, normal-type and reorg-type. The latter has 5 states and it can be cancelled except the public state. - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 65}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 66}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 67}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 68}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 69}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, - - // for drop indexes - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 72}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 72)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 73}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 73)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 74}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 74)}, cancelState: model.StateWriteReorganization}, - - // for alter db placement - {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 75}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 76}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 76)}, cancelState: model.StatePublic}, - } - - return tests -} - -func (s *testDDLSerialSuiteToVerify) checkDropIdx(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { - checkIdxExist(t, d, schemaID, tableID, idxName, !success) -} - -func (s *testDDLSerialSuiteToVerify) checkAddIdx(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { - checkIdxExist(t, d, schemaID, tableID, idxName, success) -} - -func checkIdxExist(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, expectedExist bool) { - changedTable := testGetTable(t, d, schemaID, tableID) - var found bool - for _, idxInfo := range changedTable.Meta().Indices { - if idxInfo.Name.O == idxName { - found = true - break - } - } - require.Equal(t, found, expectedExist) -} - -func (s *testDDLSerialSuiteToVerify) checkAddColumns(d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { - changedTable := testGetTable(s.T(), d, schemaID, tableID) - found := !checkColumnsNotFound(changedTable, colNames) - require.Equal(s.T(), found, success) -} - -func (s *testDDLSerialSuiteToVerify) checkCancelDropColumns(d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { - changedTable := testGetTable(s.T(), d, schemaID, tableID) - notFound := checkColumnsNotFound(changedTable, colNames) - require.Equal(s.T(), notFound, success) -} - -func checkColumnsNotFound(t table.Table, colNames []string) bool { - notFound := true - for _, colName := range colNames { - for _, colInfo := range t.Meta().Columns { - if colInfo.Name.O == colName { - notFound = false - } - } - } - return notFound -} - -func checkIdxVisibility(changedTable table.Table, idxName string, expected bool) bool { - for _, idxInfo := range changedTable.Meta().Indices { - if idxInfo.Name.O == idxName && idxInfo.Invisible == expected { - return true - } - } - return false -} - -func (s *testDDLSerialSuiteToVerify) TestCancelJob() { - store := createMockStore(s.T()) - defer func() { - require.NoError(s.T(), store.Close()) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(s.T(), err) - defer func() { - require.NoError(s.T(), d.Stop()) - }() - dbInfo, err := testSchemaInfo(d, "test_cancel_job") - require.NoError(s.T(), err) - testCreateSchema(s.T(), testNewContext(d), d, dbInfo) - // create a partition table. - partitionTblInfo := testTableInfoWithPartition(s.T(), d, "t_partition", 5) - // Skip using sessPool. Make sure adding primary key can be successful. - partitionTblInfo.Columns[0].Flag |= mysql.NotNullFlag - // create table t (c1 int, c2 int, c3 int, c4 int, c5 int); - tblInfo, err := testTableInfo(d, "t", 5) - require.NoError(s.T(), err) - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - require.NoError(s.T(), err) - err = ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "1") - require.NoError(s.T(), err) - defer func() { - err := ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "0") - require.NoError(s.T(), err) - }() - testCreateTable(s.T(), ctx, d, dbInfo, partitionTblInfo) - tableAutoID := int64(100) - shardRowIDBits := uint64(5) - tblInfo.AutoIncID = tableAutoID - tblInfo.ShardRowIDBits = shardRowIDBits - job := testCreateTable(s.T(), ctx, d, dbInfo, tblInfo) - // insert t values (1, 2, 3, 4, 5); - originTable := testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - row := types.MakeDatums(1, 2, 3, 4, 5) - _, err = originTable.AddRecord(ctx, row) - require.NoError(s.T(), err) - txn, err := ctx.Txn(true) - require.NoError(s.T(), err) - err = txn.Commit(context.Background()) - require.NoError(s.T(), err) - - tc := &TestDDLCallback{} - // set up hook - firstJobID := job.ID - tests := buildCancelJobTests(firstJobID) - var checkErr error - var mu sync.Mutex - var test *testCancelJob - updateTest := func(t *testCancelJob) { - mu.Lock() - test = t - mu.Unlock() - } - hookCancelFunc := func(job *model.Job) { - if job.State == model.JobStateSynced || job.State == model.JobStateCancelled || job.State == model.JobStateCancelling { - return - } - // This hook only valid for the related test job. - // This is use to avoid parallel test fail. - mu.Lock() - if len(test.jobIDs) > 0 && test.jobIDs[0] != job.ID { - mu.Unlock() - return - } - mu.Unlock() - if checkErr != nil { - return - } - - hookCtx := mock.NewContext() - hookCtx.Store = store - err1 := hookCtx.NewTxn(context.Background()) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - txn, err1 = hookCtx.Txn(true) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - mu.Lock() - checkErr = checkCancelState(txn, job, test) - mu.Unlock() - if checkErr != nil { - return - } - err1 = txn.Commit(context.Background()) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - } - tc.onJobUpdated = hookCancelFunc - tc.onJobRunBefore = hookCancelFunc - d.SetHook(tc) - - // for adding index - updateTest(&tests[0]) - idxOrigName := "idx" - validArgs := []interface{}{false, model.NewCIStr(idxOrigName), - []*ast.IndexPartSpecification{{ - Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, - Length: -1, - }}, nil} - - // When the job satisfies this test case, the option will be rollback, so the job's schema state is none. - cancelState := model.StateNone - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[1]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[2]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[3]) - testCreateIndex(s.T(), ctx, d, dbInfo, tblInfo, false, "idx", "c2") - require.NoError(s.T(), checkErr) - txn, err = ctx.Txn(true) - require.NoError(s.T(), err) - require.Nil(s.T(), txn.Commit(context.Background())) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for add column - updateTest(&tests[4]) - addingColName := "colA" - newColumnDef := &ast.ColumnDef{ - Name: &ast.ColumnName{Name: model.NewCIStr(addingColName)}, - Tp: &types.FieldType{Tp: mysql.TypeLonglong}, - Options: []*ast.ColumnOption{}, - } - chs, coll := charset.GetDefaultCharsetAndCollate() - col, _, err := buildColumnAndConstraint(ctx, 2, newColumnDef, nil, chs, coll) - require.NoError(s.T(), err) - - addColumnArgs := []interface{}{col, &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 0} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[5]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[6]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[7]) - testAddColumn(s.T(), ctx, d, dbInfo, tblInfo, addColumnArgs) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, true) - - // for create table - tblInfo1, err := testTableInfo(d, "t1", 2) - require.NoError(s.T(), err) - updateTest(&tests[8]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo1.ID, model.ActionCreateTable, []interface{}{tblInfo1}, &cancelState) - require.NoError(s.T(), checkErr) - testCheckTableState(s.T(), d, dbInfo, tblInfo1, model.StateNone) - - // for create database - dbInfo1, err := testSchemaInfo(d, "test_cancel_job1") - require.NoError(s.T(), err) - updateTest(&tests[9]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo1.ID, 0, model.ActionCreateSchema, []interface{}{dbInfo1}, &cancelState) - require.NoError(s.T(), checkErr) - testCheckSchemaState(s.T(), d, dbInfo1, model.StateNone) - - // for drop column. - updateTest(&tests[10]) - dropColName := "c3" - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - updateTest(&tests[11]) - dropColName = "c4" - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - updateTest(&tests[12]) - dropColName = "c5" - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - // cancel rebase auto id - updateTest(&tests[13]) - rebaseIDArgs := []interface{}{int64(200)} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionRebaseAutoID, rebaseIDArgs, &cancelState) - require.NoError(s.T(), checkErr) - changedTable := testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().AutoIncID, tableAutoID) - - // cancel shard bits - updateTest(&tests[14]) - shardRowIDArgs := []interface{}{uint64(7)} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionShardRowID, shardRowIDArgs, &cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().ShardRowIDBits, shardRowIDBits) - - // modify none-state column - col.DefaultValue = "1" - updateTest(&tests[15]) - modifyColumnArgs := []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - changedCol := model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) - require.Nil(s.T(), changedCol.DefaultValue) - - // modify delete-only-state column, - col.FieldType.Tp = mysql.TypeTiny - col.FieldType.Flen-- - updateTest(&tests[16]) - modifyColumnArgs = []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} - cancelState = model.StateNone - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - changedCol = model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) - require.Equal(s.T(), changedCol.FieldType.Tp, mysql.TypeLonglong) - require.Equal(s.T(), changedCol.FieldType.Flen, col.FieldType.Flen+1) - col.FieldType.Flen++ - - // Test add foreign key failed cause by canceled. - updateTest(&tests[17]) - addForeignKeyArgs := []interface{}{model.FKInfo{Name: model.NewCIStr("fk1")}} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 0) - - // Test add foreign key successful. - updateTest(&tests[18]) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 1) - require.Equal(s.T(), changedTable.Meta().ForeignKeys[0].Name, addForeignKeyArgs[0].(model.FKInfo).Name) - - // Test drop foreign key failed cause by canceled. - updateTest(&tests[19]) - dropForeignKeyArgs := []interface{}{addForeignKeyArgs[0].(model.FKInfo).Name} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 1) - require.Equal(s.T(), changedTable.Meta().ForeignKeys[0].Name, dropForeignKeyArgs[0].(model.CIStr)) - - // Test drop foreign key successful. - updateTest(&tests[20]) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 0) - - // test rename table failed caused by canceled. - test = &tests[21] - renameTableArgs := []interface{}{dbInfo.ID, model.NewCIStr("t2"), dbInfo.Name} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, renameTableArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().Name.L, "t") - - // test rename table successful. - test = &tests[22] - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, renameTableArgs) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().Name.L, "t2") - - // test modify table charset failed caused by canceled. - test = &tests[23] - modifyTableCharsetArgs := []interface{}{"utf8mb4", "utf8mb4_bin"} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().Charset, "utf8") - require.Equal(s.T(), changedTable.Meta().Collate, "utf8_bin") - - // test modify table charset successfully. - test = &tests[24] - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.Equal(s.T(), changedTable.Meta().Charset, "utf8mb4") - require.Equal(s.T(), changedTable.Meta().Collate, "utf8mb4_bin") - - // test truncate table partition failed caused by canceled. - test = &tests[25] - truncateTblPartitionArgs := []interface{}{[]int64{partitionTblInfo.Partition.Definitions[0].ID}} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, partitionTblInfo.ID) - require.True(s.T(), changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID) - - // test truncate table partition charset successfully. - test = &tests[26] - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, partitionTblInfo.ID) - require.False(s.T(), changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID) - - // test modify schema charset failed caused by canceled. - test = &tests[27] - charsetAndCollate := []interface{}{"utf8mb4", "utf8mb4_bin"} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate, &test.cancelState) - require.NoError(s.T(), checkErr) - dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) - require.NoError(s.T(), err) - require.Equal(s.T(), dbInfo.Charset, "") - require.Equal(s.T(), dbInfo.Collate, "") - - // test modify table charset successfully. - test = &tests[28] - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate) - require.NoError(s.T(), checkErr) - dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) - require.NoError(s.T(), err) - require.Equal(s.T(), dbInfo.Charset, "utf8mb4") - require.Equal(s.T(), dbInfo.Collate, "utf8mb4_bin") - - // for adding primary key - tblInfo = changedTable.Meta() - updateTest(&tests[29]) - idxOrigName = "primary" - validArgs = []interface{}{false, model.NewCIStr(idxOrigName), - []*ast.IndexPartSpecification{{ - Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, - Length: -1, - }}, nil} - cancelState = model.StateNone - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[30]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[31]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[32]) - testCreatePrimaryKey(s.T(), ctx, d, dbInfo, tblInfo, "c1") - require.NoError(s.T(), checkErr) - txn, err = ctx.Txn(true) - require.NoError(s.T(), err) - require.Nil(s.T(), txn.Commit(context.Background())) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for dropping primary key - updateTest(&tests[33]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionDropPrimaryKey, validArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkDropIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[34]) - testDropIndex(s.T(), ctx, d, dbInfo, tblInfo, idxOrigName) - require.NoError(s.T(), checkErr) - s.checkDropIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for add columns - updateTest(&tests[35]) - addingColNames := []string{"colA", "colB", "colC", "colD", "colE", "colF"} - cols := make([]*table.Column, len(addingColNames)) - for i, addingColName := range addingColNames { - newColumnDef := &ast.ColumnDef{ - Name: &ast.ColumnName{Name: model.NewCIStr(addingColName)}, - Tp: &types.FieldType{Tp: mysql.TypeLonglong}, - Options: []*ast.ColumnOption{}, - } - col, _, err := buildColumnAndConstraint(ctx, 0, newColumnDef, nil, mysql.DefaultCharset, "") - require.NoError(s.T(), err) - cols[i] = col - } - offsets := make([]int, len(cols)) - positions := make([]*ast.ColumnPosition, len(cols)) - for i := range positions { - positions[i] = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} - } - ifNotExists := make([]bool, len(cols)) - - addColumnArgs = []interface{}{cols, positions, offsets, ifNotExists} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[36]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[37]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[38]) - testAddColumns(s.T(), ctx, d, dbInfo, tblInfo, addColumnArgs) - require.NoError(s.T(), checkErr) - s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, addingColNames, true) - - // for drop columns - updateTest(&tests[39]) - dropColNames := []string{"colA", "colB"} - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(s.T(), ctx, d, dbInfo, tblInfo, dropColNames, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - updateTest(&tests[40]) - dropColNames = []string{"colC", "colD"} - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(s.T(), ctx, d, dbInfo, tblInfo, dropColNames, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - updateTest(&tests[41]) - dropColNames = []string{"colE", "colF"} - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(s.T(), ctx, d, dbInfo, tblInfo, dropColNames, false) - require.NoError(s.T(), checkErr) - s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - // test alter index visibility failed caused by canceled. - indexName := "idx_c3" - testCreateIndex(s.T(), ctx, d, dbInfo, tblInfo, false, indexName, "c3") - require.NoError(s.T(), checkErr) - txn, err = ctx.Txn(true) - require.NoError(s.T(), err) - require.Nil(s.T(), txn.Commit(context.Background())) - s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, indexName, true) - - updateTest(&tests[42]) - alterIndexVisibility := []interface{}{model.NewCIStr(indexName), true} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility, &test.cancelState) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.True(s.T(), checkIdxVisibility(changedTable, indexName, false)) - - // cancel alter index visibility successfully - updateTest(&tests[43]) - alterIndexVisibility = []interface{}{model.NewCIStr(indexName), true} - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility) - require.NoError(s.T(), checkErr) - changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) - require.True(s.T(), checkIdxVisibility(changedTable, indexName, true)) - - // test exchange partition failed caused by canceled - pt := testTableInfoWithPartition(s.T(), d, "pt", 5) - nt, err := testTableInfo(d, "nt", 5) - require.NoError(s.T(), err) - testCreateTable(s.T(), ctx, d, dbInfo, pt) - testCreateTable(s.T(), ctx, d, dbInfo, nt) - - updateTest(&tests[44]) - defID := pt.Partition.Definitions[0].ID - exchangeTablePartition := []interface{}{defID, dbInfo.ID, pt.ID, "p0", true} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, nt.ID, test.act, exchangeTablePartition, &test.cancelState) - require.NoError(s.T(), checkErr) - changedNtTable := testGetTable(s.T(), d, dbInfo.ID, nt.ID) - changedPtTable := testGetTable(s.T(), d, dbInfo.ID, pt.ID) - require.True(s.T(), changedNtTable.Meta().ID == nt.ID) - require.True(s.T(), changedPtTable.Meta().Partition.Definitions[0].ID == pt.Partition.Definitions[0].ID) - - // cancel exchange partition successfully - updateTest(&tests[45]) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, nt.ID, test.act, exchangeTablePartition) - require.NoError(s.T(), checkErr) - changedNtTable = testGetTable(s.T(), d, dbInfo.ID, pt.Partition.Definitions[0].ID) - changedPtTable = testGetTable(s.T(), d, dbInfo.ID, pt.ID) - require.False(s.T(), changedNtTable.Meta().ID == nt.ID) - require.True(s.T(), changedPtTable.Meta().Partition.Definitions[0].ID == nt.ID) - - // Cancel add table partition. - baseTableInfo := testTableInfoWithPartitionLessThan(s.T(), d, "empty_table", 5, "1000") - testCreateTable(s.T(), ctx, d, dbInfo, baseTableInfo) - - cancelState = model.StateNone - updateTest(&tests[46]) - addedPartInfo := testAddedNewTablePartitionInfo(s.T(), d, baseTableInfo, "p1", "maxvalue") - addPartitionArgs := []interface{}{addedPartInfo} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable := testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 1) - - updateTest(&tests[47]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 1) - - updateTest(&tests[48]) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 2) - require.Equal(s.T(), baseTable.Meta().Partition.Definitions[1].ID, addedPartInfo.Definitions[0].ID) - require.Equal(s.T(), baseTable.Meta().Partition.Definitions[1].LessThan[0], addedPartInfo.Definitions[0].LessThan[0]) - - // Cancel modify column which should reorg the data. - require.Nil(s.T(), failpoint.Enable("github.com/pingcap/tidb/ddl/skipMockContextDoExec", `return(true)`)) - baseTableInfo = testTableInfoWith2IndexOnFirstColumn(s.T(), d, "modify-table", 2) - // This will cost 2 global id, one for table id, the other for the job id. - testCreateTable(s.T(), ctx, d, dbInfo, baseTableInfo) - - cancelState = model.StateNone - newCol := baseTableInfo.Columns[0].Clone() - // change type from long to tinyint. - newCol.FieldType = *types.NewFieldType(mysql.TypeTiny) - // change from null to not null - newCol.FieldType.Flag |= mysql.NotNullFlag - newCol.FieldType.Flen = 2 - - originColName := baseTableInfo.Columns[0].Name - pos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} - - updateTest(&tests[49]) - modifyColumnArgs = []interface{}{&newCol, originColName, pos, mysql.TypeNull, 0} - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) - require.Equal(s.T(), mysql.HasNotNullFlag(baseTable.Meta().Columns[0].FieldType.Flag), false) - - updateTest(&tests[50]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) - - updateTest(&tests[51]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) - - updateTest(&tests[52]) - doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) - - updateTest(&tests[53]) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs) - require.NoError(s.T(), checkErr) - baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeTiny) - require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(1)) - require.Nil(s.T(), failpoint.Disable("github.com/pingcap/tidb/ddl/skipMockContextDoExec")) - - // for drop indexes - updateTest(&tests[54]) - ifExists := make([]bool, 2) - idxNames := []model.CIStr{model.NewCIStr("i1"), model.NewCIStr("i2")} - dropIndexesArgs := []interface{}{idxNames, ifExists} - tableInfo := createTestTableForDropIndexes(s.T(), ctx, d, dbInfo, "test-drop-indexes", 6) - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(d, dbInfo.ID, tableInfo.ID, idxNames, true) - - updateTest(&tests[55]) - idxNames = []model.CIStr{model.NewCIStr("i3"), model.NewCIStr("i4")} - dropIndexesArgs = []interface{}{idxNames, ifExists} - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(d, dbInfo.ID, tableInfo.ID, idxNames, true) - - updateTest(&tests[56]) - idxNames = []model.CIStr{model.NewCIStr("i5"), model.NewCIStr("i6")} - dropIndexesArgs = []interface{}{idxNames, ifExists} - doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(d, dbInfo.ID, tableInfo.ID, idxNames, true) -} - -func (s *testDDLSerialSuiteToVerify) checkDropIndexes(d *ddl, schemaID int64, tableID int64, idxNames []model.CIStr, success bool) { - for _, idxName := range idxNames { - checkIdxExist(s.T(), d, schemaID, tableID, idxName.O, !success) - } -} - -func doDDLJobErrWithSchemaState(ctx sessionctx.Context, ddl *ddl, t *testing.T, schemaID, tableID int64, tp model.ActionType, - args []interface{}, state *model.SchemaState) *model.Job { - job := &model.Job{ - SchemaID: schemaID, - TableID: tableID, - Type: tp, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - // TODO: check error detail - ctx.SetValue(sessionctx.QueryString, "skip") - require.Error(t, ddl.DoDDLJob(ctx, job)) - testCheckJobCancelled(t, ddl.store, job, state) - - return job -} - -func doDDLJobSuccess(ctx sessionctx.Context, ddl DDL, t *testing.T, schemaID, tableID int64, tp model.ActionType, - args []interface{}) { - job := &model.Job{ - SchemaID: schemaID, - TableID: tableID, - Type: tp, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - ctx.SetValue(sessionctx.QueryString, "skip") - err := ddl.DoDDLJob(ctx, job) - require.NoError(t, err) -} - -func testDropColumns(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colNames []string, isError bool) *model.Job { - job := buildDropColumnsJob(dbInfo, tblInfo, colNames) - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - if isError { - require.Error(t, err) - return nil - } - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func buildDropColumnsJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colNames []string) *model.Job { - columnNames := make([]model.CIStr, len(colNames)) - ifExists := make([]bool, len(colNames)) - for i, colName := range colNames { - columnNames[i] = model.NewCIStr(colName) - } - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropColumns, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{columnNames, ifExists}, - } - return job -} - -func buildDropColumnJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropColumn, - BinlogInfo: &model.HistoryInfo{}, - MultiSchemaInfo: &model.MultiSchemaInfo{}, - Args: []interface{}{model.NewCIStr(colName)}, - } -} - -func testDropColumn(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string, isError bool) *model.Job { - job := buildDropColumnJob(dbInfo, tblInfo, colName) - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - if isError { - require.Error(t, err) - return nil - } - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} diff --git a/ddl/cancel_test.go b/ddl/cancel_test.go new file mode 100644 index 0000000000000..199a75346e608 --- /dev/null +++ b/ddl/cancel_test.go @@ -0,0 +1,302 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +type testCancelJob struct { + sql string + ok bool + cancelState model.SchemaState + onJobBefore bool + onJobUpdate bool + prepareSQL []string +} + +var allTestCase = []testCancelJob{ + // Add index. + {"create unique index c3_index on t_partition (c1)", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t_partition add primary key c3_index (c1)", true, model.StateWriteReorganization, true, true, nil}, + // Add primary key + {"alter table t add primary key idx_pc2 (c2)", true, model.StateNone, true, false, nil}, + {"alter table t add primary key idx_pc2 (c2)", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t add primary key idx_pc2 (c2)", true, model.StateWriteOnly, true, true, nil}, + {"alter table t add primary key idx_pc2 (c2)", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t add primary key idx_pc2 (c2)", false, model.StatePublic, false, true, nil}, + // Drop primary key + {"alter table t drop primary key", true, model.StatePublic, true, false, nil}, + {"alter table t drop primary key", false, model.StateWriteOnly, true, false, nil}, + {"alter table t drop primary key", false, model.StateWriteOnly, true, false, []string{"alter table t add primary key idx_pc2 (c2)"}}, + {"alter table t drop primary key", false, model.StateDeleteOnly, true, false, []string{"alter table t add primary key idx_pc2 (c2)"}}, + {"alter table t drop primary key", false, model.StateDeleteOnly, false, true, []string{"alter table t add primary key idx_pc2 (c2)"}}, + // Add unique key + {"alter table t add unique index idx_uc2 (c2)", true, model.StateNone, true, false, nil}, + {"alter table t add unique index idx_uc2 (c2)", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t add unique index idx_uc2 (c2)", true, model.StateWriteOnly, true, true, nil}, + {"alter table t add unique index idx_uc2 (c2)", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t add unique index idx_uc2 (c2)", false, model.StatePublic, false, true, nil}, + {"alter table t add index idx_c2(c2)", true, model.StateNone, true, false, nil}, + {"alter table t add index idx_c2(c2)", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t add index idx_c2(c2)", true, model.StateWriteOnly, true, true, nil}, + {"alter table t add index idx_cx2(c2)", false, model.StatePublic, false, true, nil}, + // Add column. + {"alter table t add column c4 bigint", true, model.StateNone, true, false, nil}, + {"alter table t add column c4 bigint", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t add column c4 bigint", true, model.StateWriteOnly, true, true, nil}, + {"alter table t add column c4 bigint", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t add column c4 bigint", false, model.StatePublic, false, true, nil}, + // Create table. + {"create table test_create_table(a int)", true, model.StateNone, true, false, nil}, + {"create table test_create_table(a int)", false, model.StatePublic, false, true, nil}, + // Drop table. + {"drop table test_create_table", true, model.StatePublic, true, false, nil}, + {"drop table test_create_table", false, model.StateWriteOnly, true, true, []string{"create table if not exists test_create_table(a int)"}}, + {"drop table test_create_table", false, model.StateDeleteOnly, true, true, []string{"create table if not exists test_create_table(a int)"}}, + {"drop table test_create_table", false, model.StateNone, false, true, []string{"create table if not exists test_create_table(a int)"}}, + // Create schema. + {"create database test_create_db", true, model.StateNone, true, false, nil}, + {"create database test_create_db", false, model.StatePublic, false, true, nil}, + // Drop schema. + {"drop database test_create_db", true, model.StatePublic, true, false, nil}, + {"drop database test_create_db", false, model.StateWriteOnly, true, true, []string{"create database if not exists test_create_db"}}, + {"drop database test_create_db", false, model.StateDeleteOnly, true, true, []string{"create database if not exists test_create_db"}}, + {"drop database test_create_db", false, model.StateNone, false, true, []string{"create database if not exists test_create_db"}}, + // Drop column. + {"alter table t drop column c3", true, model.StatePublic, true, false, nil}, + {"alter table t drop column c3", false, model.StateDeleteOnly, true, false, nil}, + {"alter table t drop column c3", false, model.StateDeleteOnly, false, true, []string{"alter table t add column c3 bigint"}}, + {"alter table t drop column c3", false, model.StateWriteOnly, true, true, []string{"alter table t add column c3 bigint"}}, + {"alter table t drop column c3", false, model.StateDeleteReorganization, true, true, []string{"alter table t add column c3 bigint"}}, + {"alter table t drop column c3", false, model.StateNone, false, true, []string{"alter table t add column c3 bigint"}}, + // Drop column with index. + {"alter table t drop column c3", true, model.StatePublic, true, false, []string{"alter table t add column c3 bigint", "alter table t add index idx_c3(c3)"}}, + {"alter table t drop column c3", false, model.StateDeleteOnly, true, false, nil}, + {"alter table t drop column c3", false, model.StateDeleteOnly, false, true, []string{"alter table t add column c3 bigint", "alter table t add index idx_c3(c3)"}}, + {"alter table t drop column c3", false, model.StateWriteOnly, true, true, []string{"alter table t add column c3 bigint", "alter table t add index idx_c3(c3)"}}, + {"alter table t drop column c3", false, model.StateDeleteReorganization, true, true, []string{"alter table t add column c3 bigint", "alter table t add index idx_c3(c3)"}}, + {"alter table t drop column c3", false, model.StateNone, false, true, []string{"alter table t add column c3 bigint", "alter table t add index idx_c3(c3)"}}, + // rebase auto ID. + {"alter table t_rebase auto_increment = 6000", true, model.StateNone, true, false, []string{"create table t_rebase (c1 bigint auto_increment primary key, c2 bigint);"}}, + {"alter table t_rebase auto_increment = 9000", false, model.StatePublic, false, true, nil}, + // Shard row ID, + {"alter table t_auto shard_row_id_bits = 5", true, model.StateNone, true, false, []string{"create table t_auto (c1 int not null auto_increment unique) shard_row_id_bits = 0"}}, + {"alter table t_auto shard_row_id_bits = 8", false, model.StatePublic, false, true, nil}, + // Modify column, no reorg. + {"alter table t modify column c11 mediumint", true, model.StateNone, true, false, nil}, + {"alter table t modify column c11 int", false, model.StatePublic, false, true, nil}, + // TODO: test cancel during second model.StateNone + {"alter table t modify column mayNullCol bigint default 1 not null", true, model.StateNone, true, false, []string{"alter table t add column mayNullCol bigint default 1"}}, + {"alter table t modify column mayNullCol bigint default 1 not null", true, model.StateNone, false, true, nil}, + {"alter table t modify column mayNullCol bigint default 1 not null", false, model.StatePublic, false, true, nil}, + // Modify column, reorg. + {"alter table t modify column c11 char(10)", true, model.StateNone, true, false, nil}, + {"alter table t modify column c11 char(10)", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t modify column c11 char(10)", true, model.StateWriteOnly, true, true, nil}, + {"alter table t modify column c11 char(10)", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t modify column c11 char(10)", false, model.StatePublic, false, true, nil}, + // Add foreign key. + {"alter table t add constraint fk foreign key a(c1) references t_ref(c1)", true, model.StateNone, true, false, []string{"create table t_ref (c1 int, c2 int, c3 int, c11 tinyint);"}}, + {"alter table t add constraint fk foreign key a(c1) references t_ref(c1)", false, model.StatePublic, false, true, nil}, + // Drop foreign key. + {"alter table t drop foreign key fk", true, model.StatePublic, true, false, nil}, + {"alter table t drop foreign key fk", false, model.StateNone, false, true, nil}, + // Rename table. + {"rename table t_rename1 to t_rename11", true, model.StateNone, true, false, []string{"create table t_rename1 (c1 bigint , c2 bigint);", "create table t_rename2 (c1 bigint , c2 bigint);"}}, + {"rename table t_rename1 to t_rename11", false, model.StatePublic, false, true, nil}, + // Rename tables. + {"rename table t_rename11 to t_rename111, t_rename2 to t_rename22", true, model.StateNone, true, false, nil}, + {"rename table t_rename11 to t_rename111, t_rename2 to t_rename22", false, model.StatePublic, false, true, nil}, + // Modify table charset and collate. + {"alter table t_cs convert to charset utf8mb4", true, model.StateNone, true, false, []string{"create table t_cs(a varchar(10)) charset utf8"}}, + {"alter table t_cs convert to charset utf8mb4", false, model.StatePublic, false, true, nil}, + // Modify schema charset and collate. + {"alter database db_coll charset utf8mb4 collate utf8mb4_bin", true, model.StateNone, true, false, []string{"create database db_coll default charset utf8 collate utf8_bin"}}, + {"alter database db_coll charset utf8mb4 collate utf8mb4_bin", false, model.StatePublic, false, true, nil}, + // Truncate partition. + {"alter table t_partition truncate partition p3", true, model.StateNone, true, false, nil}, + {"alter table t_partition truncate partition p3", false, model.StatePublic, false, true, nil}, + // Add columns. + {"alter table t add column c41 bigint, add column c42 bigint", true, model.StateNone, true, false, nil}, + {"alter table t add column c41 bigint, add column c42 bigint", true, model.StateDeleteOnly, true, true, nil}, + {"alter table t add column c41 bigint, add column c42 bigint", true, model.StateWriteOnly, true, true, nil}, + {"alter table t add column c41 bigint, add column c42 bigint", true, model.StateWriteReorganization, true, true, nil}, + {"alter table t add column c41 bigint, add column c42 bigint", false, model.StatePublic, false, true, nil}, + // Drop columns. + // TODO: fix schema state. + {"alter table t drop column c41, drop column c42", true, model.StateNone, true, false, nil}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteOnly, true, false, nil}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteOnly, false, true, []string{"alter table t add column c41 bigint, add column c42 bigint"}}, + {"alter table t drop column c41, drop column c42", false, model.StateWriteOnly, true, true, []string{"alter table t add column c41 bigint, add column c42 bigint"}}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteReorganization, true, true, []string{"alter table t add column c41 bigint, add column c42 bigint"}}, + {"alter table t drop column c41, drop column c42", false, model.StatePublic, false, true, []string{"alter table t add column c41 bigint, add column c42 bigint"}}, + // Drop columns with index. + // TODO: fix schema state. + {"alter table t drop column c41, drop column c42", true, model.StateNone, true, false, []string{"alter table t add column c41 bigint, add column c42 bigint", "alter table t add index drop_columns_idx(c41)"}}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteOnly, true, false, nil}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteOnly, false, true, []string{"alter table t add column c41 bigint, add column c42 bigint", "alter table t add index drop_columns_idx(c41)"}}, + {"alter table t drop column c41, drop column c42", false, model.StateWriteOnly, true, true, []string{"alter table t add column c41 bigint, add column c42 bigint", "alter table t add index drop_columns_idx(c41)"}}, + {"alter table t drop column c41, drop column c42", false, model.StateDeleteReorganization, true, true, []string{"alter table t add column c41 bigint, add column c42 bigint", "alter table t add index drop_columns_idx(c41)"}}, + {"alter table t drop column c41, drop column c42", false, model.StatePublic, false, true, []string{"alter table t add column c41 bigint, add column c42 bigint", "alter table t add index drop_columns_idx(c41)"}}, + // Alter index visibility. + {"alter table t alter index idx_v invisible", true, model.StateNone, true, false, []string{"alter table t add index idx_v(c1)"}}, + {"alter table t alter index idx_v invisible", false, model.StatePublic, false, true, nil}, + // Exchange partition. + {"alter table t_partition exchange partition p0 with table t_partition2", true, model.StateNone, true, false, []string{"create table t_partition2(c1 int, c2 int, c3 int)", "set @@tidb_enable_exchange_partition=1"}}, + {"alter table t_partition exchange partition p0 with table t_partition2", false, model.StatePublic, false, true, nil}, + // Add partition. + {"alter table t_partition add partition (partition p6 values less than (8192))", true, model.StateNone, true, false, nil}, + {"alter table t_partition add partition (partition p6 values less than (8192))", true, model.StateReplicaOnly, true, true, nil}, + {"alter table t_partition add partition (partition p6 values less than (8192))", false, model.StatePublic, false, true, nil}, + // Drop partition. + {"alter table t_partition drop partition p6", true, model.StatePublic, true, false, nil}, + {"alter table t_partition drop partition p6", false, model.StateDeleteOnly, true, false, nil}, + {"alter table t_partition drop partition p6", false, model.StateDeleteOnly, false, true, []string{"alter table t_partition add partition (partition p6 values less than (8192))"}}, + {"alter table t_partition drop partition p6", false, model.StateDeleteReorganization, true, true, []string{"alter table t_partition add partition (partition p6 values less than (8192))"}}, + {"alter table t_partition drop partition p6", false, model.StateNone, true, true, []string{"alter table t_partition add partition (partition p6 values less than (8192))"}}, + // Drop indexes. + // TODO: fix schema state. + {"alter table t drop index mul_idx1, drop index mul_idx2", true, model.StateNone, true, false, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateWriteOnly, true, false, nil}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateWriteOnly, true, false, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateDeleteOnly, true, false, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateDeleteOnly, false, true, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateDeleteReorganization, true, false, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + {"alter table t drop index mul_idx1, drop index mul_idx2", false, model.StateDeleteReorganization, false, true, []string{"alter table t add index mul_idx1(c1)", "alter table t add index mul_idx2(c1)"}}, + // Alter db placement. + {"alter database db_placement placement policy = 'alter_x'", true, model.StateNone, true, false, []string{"create placement policy alter_x PRIMARY_REGION=\"cn-east-1\", REGIONS=\"cn-east-1\";", "create database db_placement"}}, + {"alter database db_placement placement policy = 'alter_x'", false, model.StatePublic, false, true, nil}, + // Rename index. + {"alter table t rename index rename_idx1 to rename_idx2", true, model.StateNone, true, false, []string{"alter table t add index rename_idx1(c1)"}}, + {"alter table t rename index rename_idx1 to rename_idx2", false, model.StatePublic, false, true, nil}, +} + +func cancelSuccess(rs *testkit.Result) bool { + return strings.Contains(rs.Rows()[0][1].(string), "success") +} + +func TestCancel(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, 100*time.Millisecond) + defer clean() + tk := testkit.NewTestKit(t, store) + tkCancel := testkit.NewTestKit(t, store) + + // Prepare schema. + tk.MustExec("use test") + tk.MustExec("drop table if exists t_partition;") + tk.MustExec(`create table t_partition ( + c1 int, c2 int, c3 int + ) + partition by range( c1 ) ( + partition p0 values less than (1024), + partition p1 values less than (2048), + partition p2 values less than (3072), + partition p3 values less than (4096), + partition p4 values less than (7096) + );`) + tk.MustExec(`create table t ( + c1 int, c2 int, c3 int, c11 tinyint + );`) + + // Prepare data. + for i := 0; i <= 2048; i++ { + tk.MustExec(fmt.Sprintf("insert into t_partition values(%d, %d, %d)", i*3, i*2, i)) + tk.MustExec(fmt.Sprintf("insert into t(c1, c2, c3) values(%d, %d, %d)", i*3, i*2, i)) + } + + // Change some configurations. + ddl.ReorgWaitTimeout = 10 * time.Microsecond + tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 8") + + hook := &ddl.TestDDLCallback{Do: dom} + i := 0 + cancel := false + cancelResult := false + cancelWhenReorgNotStart := false + + hookFunc := func(job *model.Job) { + if job.SchemaState == allTestCase[i].cancelState && !cancel { + if !cancelWhenReorgNotStart && job.SchemaState == model.StateWriteReorganization && job.MayNeedReorg() && job.RowCount == 0 { + return + } + rs := tkCancel.MustQuery(fmt.Sprintf("admin cancel ddl jobs %d", job.ID)) + cancelResult = cancelSuccess(rs) + cancel = true + } + } + dom.DDL().SetHook(hook) + + restHook := func(h *ddl.TestDDLCallback) { + h.OnJobRunBeforeExported = nil + h.OnJobUpdatedExported = nil + } + registHook := func(h *ddl.TestDDLCallback, onJobRunBefore bool) { + if onJobRunBefore { + h.OnJobRunBeforeExported = hookFunc + } else { + h.OnJobUpdatedExported = hookFunc + } + } + + for j, tc := range allTestCase { + i = j + msg := fmt.Sprintf("sql: %s, state: %s", tc.sql, tc.cancelState) + if tc.onJobBefore { + restHook(hook) + for _, prepareSQL := range tc.prepareSQL { + tk.MustExec(prepareSQL) + } + + cancel = false + cancelWhenReorgNotStart = true + registHook(hook, true) + if tc.ok { + tk.MustGetErrCode(tc.sql, errno.ErrCancelledDDLJob) + } else { + tk.MustExec(tc.sql) + } + if cancel { + require.Equal(t, tc.ok, cancelResult, msg) + } + } + if tc.onJobUpdate { + restHook(hook) + for _, prepareSQL := range tc.prepareSQL { + tk.MustExec(prepareSQL) + } + cancel = false + cancelWhenReorgNotStart = false + registHook(hook, false) + if tc.ok { + tk.MustGetErrCode(tc.sql, errno.ErrCancelledDDLJob) + } else { + tk.MustExec(tc.sql) + } + if cancel { + require.Equal(t, tc.ok, cancelResult, msg) + } + } + } +} diff --git a/ddl/column.go b/ddl/column.go index ea225a355afa4..61c55e0b2de33 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -144,7 +144,7 @@ func checkAddColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.Colu func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { // Handle the rolling back job. if job.IsRollingback() { - ver, err = onDropColumn(t, job) + ver, err = onDropColumn(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -183,7 +183,7 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) case model.StateNone: // none -> delete only columnInfo.State = model.StateDeleteOnly - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != columnInfo.State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -191,7 +191,7 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) case model.StateDeleteOnly: // delete only -> write only columnInfo.State = model.StateWriteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -200,7 +200,7 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) case model.StateWriteOnly: // write only -> reorganization columnInfo.State = model.StateWriteReorganization - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -211,7 +211,7 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) // Adjust table column offset. tblInfo.MoveColumnInfo(columnInfo.Offset, offset) columnInfo.State = model.StatePublic - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -285,7 +285,7 @@ func setIndicesState(indexInfos []*model.IndexInfo, state model.SchemaState) { func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { // Handle the rolling back job. if job.IsRollingback() { - ver, err = onDropColumns(t, job) + ver, err = onDropColumns(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -331,7 +331,7 @@ func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error case model.StateNone: // none -> delete only setColumnsState(columnInfos, model.StateDeleteOnly) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != columnInfos[0].State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != columnInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -339,7 +339,7 @@ func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error case model.StateDeleteOnly: // delete only -> write only setColumnsState(columnInfos, model.StateWriteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -347,7 +347,7 @@ func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error case model.StateWriteOnly: // write only -> reorganization setColumnsState(columnInfos, model.StateWriteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -375,7 +375,7 @@ func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error tblInfo.MoveColumnInfo(len(tblInfo.Columns)-1, offsets[i]) } setColumnsState(columnInfos, model.StatePublic) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -389,7 +389,7 @@ func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error return ver, errors.Trace(err) } -func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, colInfos, delCount, idxInfos, err := checkDropColumns(t, job) if err != nil { return ver, errors.Trace(err) @@ -411,7 +411,7 @@ func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } } - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != colInfos[0].State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != colInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -428,7 +428,7 @@ func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { } tblInfo.Indices = newIndices } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -437,7 +437,7 @@ func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { case model.StateDeleteOnly: // delete only -> reorganization setColumnsState(colInfos, model.StateDeleteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -447,7 +447,7 @@ func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { // All reorganization jobs are done, drop this column. tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-delCount] setColumnsState(colInfos, model.StateNone) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -520,7 +520,7 @@ func checkDropColumnForStatePublic(tblInfo *model.TableInfo, colInfo *model.Colu // When the dropping column has not-null flag and it hasn't the default value, we can backfill the column value like "add column". // NOTE: If the state of StateWriteOnly can be rollbacked, we'd better reconsider the original default value. // And we need consider the column without not-null flag. - if colInfo.GetOriginDefaultValue() == nil && mysql.HasNotNullFlag(colInfo.Flag) { + if colInfo.GetOriginDefaultValue() == nil && mysql.HasNotNullFlag(colInfo.GetFlag()) { // If the column is timestamp default current_timestamp, and DDL owner is new version TiDB that set column.Version to 1, // then old TiDB update record in the column write only stage will uses the wrong default value of the dropping column. // Because new version of the column default value is UTC time, but old version TiDB will think the default value is the time in system timezone. @@ -536,7 +536,7 @@ func checkDropColumnForStatePublic(tblInfo *model.TableInfo, colInfo *model.Colu return nil } -func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, colInfo, idxInfos, err := checkDropColumn(t, job) if err != nil { return ver, errors.Trace(err) @@ -552,11 +552,10 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { if err != nil { return ver, errors.Trace(err) } - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != colInfo.State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateWriteOnly case model.StateWriteOnly: // write only -> delete only colInfo.State = model.StateDeleteOnly @@ -569,26 +568,24 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { } tblInfo.Indices = newIndices } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) } job.Args = append(job.Args, indexInfosToIDList(idxInfos)) - job.SchemaState = model.StateDeleteOnly case model.StateDeleteOnly: // delete only -> reorganization colInfo.State = model.StateDeleteReorganization - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateDeleteReorganization case model.StateDeleteReorganization: // reorganization -> absent // All reorganization jobs are done, drop this column. tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] colInfo.State = model.StateNone - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -602,8 +599,9 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.Args = append(job.Args, getPartitionIDs(tblInfo)) } default: - err = dbterror.ErrInvalidDDLJob.GenWithStackByArgs("table", tblInfo.State) + return ver, errors.Trace(dbterror.ErrInvalidDDLJob.GenWithStackByArgs("table", tblInfo.State)) } + job.SchemaState = colInfo.State return ver, errors.Trace(err) } @@ -645,7 +643,7 @@ func checkDropColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.Col return tblInfo, colInfo, idxInfos, nil } -func onSetDefaultValue(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onSetDefaultValue(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { newCol := &model.ColumnInfo{} err := job.DecodeArgs(newCol) if err != nil { @@ -653,56 +651,56 @@ func onSetDefaultValue(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } - return updateColumnDefaultValue(t, job, newCol, &newCol.Name) + return updateColumnDefaultValue(d, t, job, newCol, &newCol.Name) } func needChangeColumnData(oldCol, newCol *model.ColumnInfo) bool { - toUnsigned := mysql.HasUnsignedFlag(newCol.Flag) - originUnsigned := mysql.HasUnsignedFlag(oldCol.Flag) + toUnsigned := mysql.HasUnsignedFlag(newCol.GetFlag()) + originUnsigned := mysql.HasUnsignedFlag(oldCol.GetFlag()) needTruncationOrToggleSign := func() bool { - return (newCol.Flen > 0 && newCol.Flen < oldCol.Flen) || (toUnsigned != originUnsigned) + return (newCol.GetFlen() > 0 && newCol.GetFlen() < oldCol.GetFlen()) || (toUnsigned != originUnsigned) } // Ignore the potential max display length represented by integer's flen, use default flen instead. - defaultOldColFlen, _ := mysql.GetDefaultFieldLengthAndDecimal(oldCol.Tp) - defaultNewColFlen, _ := mysql.GetDefaultFieldLengthAndDecimal(newCol.Tp) + defaultOldColFlen, _ := mysql.GetDefaultFieldLengthAndDecimal(oldCol.GetType()) + defaultNewColFlen, _ := mysql.GetDefaultFieldLengthAndDecimal(newCol.GetType()) needTruncationOrToggleSignForInteger := func() bool { return (defaultNewColFlen > 0 && defaultNewColFlen < defaultOldColFlen) || (toUnsigned != originUnsigned) } // Deal with the same type. - if oldCol.Tp == newCol.Tp { - switch oldCol.Tp { + if oldCol.GetType() == newCol.GetType() { + switch oldCol.GetType() { case mysql.TypeNewDecimal: // Since type decimal will encode the precision, frac, negative(signed) and wordBuf into storage together, there is no short // cut to eliminate data reorg change for column type change between decimal. - return oldCol.Flen != newCol.Flen || oldCol.Decimal != newCol.Decimal || toUnsigned != originUnsigned + return oldCol.GetFlen() != newCol.GetFlen() || oldCol.GetDecimal() != newCol.GetDecimal() || toUnsigned != originUnsigned case mysql.TypeEnum, mysql.TypeSet: - return isElemsChangedToModifyColumn(oldCol.Elems, newCol.Elems) + return isElemsChangedToModifyColumn(oldCol.GetElems(), newCol.GetElems()) case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: return toUnsigned != originUnsigned case mysql.TypeString: // Due to the behavior of padding \x00 at binary type, always change column data when binary length changed if types.IsBinaryStr(&oldCol.FieldType) { - return newCol.Flen != oldCol.Flen + return newCol.GetFlen() != oldCol.GetFlen() } } return needTruncationOrToggleSign() } - if convertBetweenCharAndVarchar(oldCol.Tp, newCol.Tp) { + if convertBetweenCharAndVarchar(oldCol.GetType(), newCol.GetType()) { return true } // Deal with the different type. - switch oldCol.Tp { + switch oldCol.GetType() { case mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString, mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: - switch newCol.Tp { + switch newCol.GetType() { case mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString, mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: return needTruncationOrToggleSign() } case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: - switch newCol.Tp { + switch newCol.GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: return needTruncationOrToggleSignForInteger() } @@ -809,10 +807,10 @@ func (w *worker) onModifyColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in if job.IsRollingback() { // For those column-type-change jobs which don't reorg the data. if !needChangeColumnData(oldCol, modifyInfo.newCol) { - return rollbackModifyColumnJob(t, tblInfo, job, modifyInfo.newCol, oldCol, modifyInfo.modifyColumnTp) + return rollbackModifyColumnJob(d, t, tblInfo, job, modifyInfo.newCol, oldCol, modifyInfo.modifyColumnTp) } // For those column-type-change jobs which reorg the data. - return rollbackModifyColumnJobWithData(t, tblInfo, job, oldCol, modifyInfo) + return rollbackModifyColumnJobWithData(d, t, tblInfo, job, oldCol, modifyInfo) } // If we want to rename the column name, we need to check whether it already exists. @@ -850,7 +848,7 @@ func (w *worker) onModifyColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in if modifyInfo.changingCol == nil { changingColPos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} newColName := model.NewCIStr(genChangingColumnUniqueName(tblInfo, oldCol)) - if mysql.HasPriKeyFlag(oldCol.Flag) { + if mysql.HasPriKeyFlag(oldCol.GetFlag()) { job.State = model.JobStateCancelled msg := "this column has primary key flag" return ver, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) @@ -882,8 +880,8 @@ func (w *worker) onModifyColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in newIdxChangingCol := newIdxInfo.Columns[offsets[i]] newIdxChangingCol.Name = newColName newIdxChangingCol.Offset = modifyInfo.changingCol.Offset - canPrefix := types.IsTypePrefixable(modifyInfo.changingCol.Tp) - if !canPrefix || (canPrefix && modifyInfo.changingCol.Flen < newIdxChangingCol.Length) { + canPrefix := types.IsTypePrefixable(modifyInfo.changingCol.GetType()) + if !canPrefix || (canPrefix && modifyInfo.changingCol.GetFlen() < newIdxChangingCol.Length) { newIdxChangingCol.Length = types.UnspecifiedLength } modifyInfo.changingIdxs = append(modifyInfo.changingIdxs, newIdxInfo) @@ -898,13 +896,13 @@ func (w *worker) onModifyColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in } // rollbackModifyColumnJobWithData is used to rollback modify-column job which need to reorg the data. -func rollbackModifyColumnJobWithData(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, oldCol *model.ColumnInfo, modifyInfo *modifyingColInfo) (ver int64, err error) { +func rollbackModifyColumnJobWithData(d *ddlCtx, t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, oldCol *model.ColumnInfo, modifyInfo *modifyingColInfo) (ver int64, err error) { // If the not-null change is included, we should clean the flag info in oldCol. if modifyInfo.modifyColumnTp == mysql.TypeNull { // Reset NotNullFlag flag. - tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.NotNullFlag + tblInfo.Columns[oldCol.Offset].SetFlag(oldCol.GetFlag() &^ mysql.NotNullFlag) // Reset PreventNullInsertFlag flag. - tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.PreventNullInsertFlag + tblInfo.Columns[oldCol.Offset].SetFlag(oldCol.GetFlag() &^ mysql.PreventNullInsertFlag) } if modifyInfo.changingCol != nil { // changingCol isn't nil means the job has been in the mid state. These appended changingCol and changingIndex should @@ -912,7 +910,7 @@ func rollbackModifyColumnJobWithData(t *meta.Meta, tblInfo *model.TableInfo, job tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-len(modifyInfo.changingIdxs)] } - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -937,9 +935,9 @@ func (w *worker) doModifyColumnTypeWithData( switch changingCol.State { case model.StateNone: // Column from null to not null. - if !mysql.HasNotNullFlag(oldCol.Flag) && mysql.HasNotNullFlag(changingCol.Flag) { + if !mysql.HasNotNullFlag(oldCol.GetFlag()) && mysql.HasNotNullFlag(changingCol.GetFlag()) { // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. - err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.Tp != changingCol.Tp) + err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.GetType() != changingCol.GetType()) if err != nil { if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback @@ -965,7 +963,7 @@ func (w *worker) doModifyColumnTypeWithData( } } }) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != changingCol.State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) } @@ -976,9 +974,9 @@ func (w *worker) doModifyColumnTypeWithData( job.Args = append(job.Args, changingCol, changingIdxs) case model.StateDeleteOnly: // Column from null to not null. - if !mysql.HasNotNullFlag(oldCol.Flag) && mysql.HasNotNullFlag(changingCol.Flag) { + if !mysql.HasNotNullFlag(oldCol.GetFlag()) && mysql.HasNotNullFlag(changingCol.GetFlag()) { // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. - err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.Tp != changingCol.Tp) + err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.GetType() != changingCol.GetType()) if err != nil { if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback @@ -988,7 +986,7 @@ func (w *worker) doModifyColumnTypeWithData( } // delete only -> write only updateChangingObjState(changingCol, changingIdxs, model.StateWriteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) } @@ -996,7 +994,7 @@ func (w *worker) doModifyColumnTypeWithData( case model.StateWriteOnly: // write only -> reorganization updateChangingObjState(changingCol, changingIdxs, model.StateWriteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) } @@ -1024,7 +1022,7 @@ func (w *worker) doModifyColumnTypeWithData( } updateChangingObjState(changingCol, changingIdxs, model.StatePublic) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) } @@ -1429,8 +1427,8 @@ func (w *updateColumnWorker) getRowRecord(handle kv.Handle, recordKey []byte, ra w.sessCtx.GetSessionVars().StmtCtx.SetWarnings(oldWarn) val := w.rowMap[w.oldColInfo.ID] col := w.newColInfo - if val.Kind() == types.KindNull && col.FieldType.Tp == mysql.TypeTimestamp && mysql.HasNotNullFlag(col.Flag) { - if v, err := expression.GetTimeCurrentTimestamp(w.sessCtx, col.Tp, col.Decimal); err == nil { + if val.Kind() == types.KindNull && col.FieldType.GetType() == mysql.TypeTimestamp && mysql.HasNotNullFlag(col.GetFlag()) { + if v, err := expression.GetTimeCurrentTimestamp(w.sessCtx, col.GetType(), col.GetDecimal()); err == nil { // convert null value to timestamp should be substituted with current timestamp if NOT_NULL flag is set. w.rowMap[w.oldColInfo.ID] = v } @@ -1567,8 +1565,8 @@ func (w *worker) doModifyColumn( return ver, dbterror.ErrKeyColumnDoesNotExits.GenWithStack("column %s id %d does not exist, this column may have been updated by other DDL ran in parallel", oldCol.Name, newCol.ID) } // Column from null to not null. - if !mysql.HasNotNullFlag(oldCol.Flag) && mysql.HasNotNullFlag(newCol.Flag) { - noPreventNullFlag := !mysql.HasPreventNullInsertFlag(oldCol.Flag) + if !mysql.HasNotNullFlag(oldCol.GetFlag()) && mysql.HasNotNullFlag(newCol.GetFlag()) { + noPreventNullFlag := !mysql.HasPreventNullInsertFlag(oldCol.GetFlag()) // lease = 0 means it's in an integration test. In this case we don't delay so the test won't run too slowly. // We need to check after the flag is set @@ -1577,7 +1575,7 @@ func (w *worker) doModifyColumn( } // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. - err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, newCol, oldCol.Tp != newCol.Tp) + err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, newCol, oldCol.GetType() != newCol.GetType()) if err != nil { if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback @@ -1586,7 +1584,7 @@ func (w *worker) doModifyColumn( } // The column should get into prevent null status first. if noPreventNullFlag { - return updateVersionAndTableInfoWithCheck(t, job, tblInfo, true) + return updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, true) } } @@ -1595,7 +1593,7 @@ func (w *worker) doModifyColumn( return ver, errors.Trace(err) } - ver, err := updateVersionAndTableInfoWithCheck(t, job, tblInfo, true) + ver, err := updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, true) if err != nil { // Modified the type definition of 'null' to 'not null' before this, so rollBack the job when an error occurs. job.State = model.JobStateRollingback @@ -1646,7 +1644,7 @@ func checkNewAutoRandomBits(idAccessors meta.AutoIDAccessors, oldCol *model.Colu newLayout := autoid.NewShardIDLayout(&newCol.FieldType, newAutoRandBits) idAcc := idAccessors.RandomID() - convertedFromAutoInc := mysql.HasAutoIncrementFlag(oldCol.Flag) + convertedFromAutoInc := mysql.HasAutoIncrementFlag(oldCol.GetFlag()) if convertedFromAutoInc { idAcc = idAccessors.IncrementID(tblInfoVer) } @@ -1675,7 +1673,7 @@ func checkNewAutoRandomBits(idAccessors meta.AutoIDAccessors, oldCol *model.Colu func applyNewAutoRandomBits(d *ddlCtx, m *meta.Meta, dbInfo *model.DBInfo, tblInfo *model.TableInfo, oldCol *model.ColumnInfo, newAutoRandBits uint64) error { tblInfo.AutoRandomBits = newAutoRandBits - needMigrateFromAutoIncToAutoRand := mysql.HasAutoIncrementFlag(oldCol.Flag) + needMigrateFromAutoIncToAutoRand := mysql.HasAutoIncrementFlag(oldCol.GetFlag()) if !needMigrateFromAutoIncToAutoRand { return nil } @@ -1704,7 +1702,7 @@ func applyNewAutoRandomBits(d *ddlCtx, m *meta.Meta, dbInfo *model.DBInfo, func checkForNullValue(ctx context.Context, sctx sessionctx.Context, isDataTruncated bool, schema, table model.CIStr, newCol *model.ColumnInfo, oldCols ...*model.ColumnInfo) error { needCheckNullValue := false for _, oldCol := range oldCols { - if oldCol.Tp != mysql.TypeTimestamp && newCol.Tp == mysql.TypeTimestamp { + if oldCol.GetType() != mysql.TypeTimestamp && newCol.GetType() == mysql.TypeTimestamp { // special case for convert null value of non-timestamp type to timestamp type, null value will be substituted with current timestamp. continue } @@ -1741,7 +1739,7 @@ func checkForNullValue(ctx context.Context, sctx sessionctx.Context, isDataTrunc return nil } -func updateColumnDefaultValue(t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldColName *model.CIStr) (ver int64, _ error) { +func updateColumnDefaultValue(d *ddlCtx, t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldColName *model.CIStr) (ver int64, _ error) { tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) @@ -1754,9 +1752,9 @@ func updateColumnDefaultValue(t *meta.Meta, job *model.Job, newCol *model.Column // The newCol's offset may be the value of the old schema version, so we can't use newCol directly. oldCol.DefaultValue = newCol.DefaultValue oldCol.DefaultValueBit = newCol.DefaultValueBit - oldCol.Flag = newCol.Flag + oldCol.SetFlag(newCol.GetFlag()) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -1827,14 +1825,14 @@ func checkAddColumnTooManyColumns(colNum int) error { } // rollbackModifyColumnJob rollbacks the job when an error occurs. -func rollbackModifyColumnJob(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, newCol, oldCol *model.ColumnInfo, modifyColumnTp byte) (ver int64, _ error) { +func rollbackModifyColumnJob(d *ddlCtx, t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, newCol, oldCol *model.ColumnInfo, modifyColumnTp byte) (ver int64, _ error) { var err error if oldCol.ID == newCol.ID && modifyColumnTp == mysql.TypeNull { // field NotNullFlag flag reset. - tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.NotNullFlag + tblInfo.Columns[oldCol.Offset].SetFlag(oldCol.GetFlag() &^ mysql.NotNullFlag) // field PreventNullInsertFlag flag reset. - tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.PreventNullInsertFlag - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + tblInfo.Columns[oldCol.Offset].SetFlag(oldCol.GetFlag() &^ mysql.PreventNullInsertFlag) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1872,7 +1870,7 @@ func modifyColsFromNull2NotNull(w *worker, dbInfo *model.DBInfo, tblInfo *model. // Prevent this field from inserting null values. for _, col := range cols { - col.Flag |= mysql.PreventNullInsertFlag + col.AddFlag(mysql.PreventNullInsertFlag) } return nil } @@ -1880,15 +1878,15 @@ func modifyColsFromNull2NotNull(w *worker, dbInfo *model.DBInfo, tblInfo *model. func generateOriginDefaultValue(col *model.ColumnInfo, ctx sessionctx.Context) (interface{}, error) { var err error odValue := col.GetDefaultValue() - if odValue == nil && mysql.HasNotNullFlag(col.Flag) { - switch col.Tp { + if odValue == nil && mysql.HasNotNullFlag(col.GetFlag()) { + switch col.GetType() { // Just use enum field's first element for OriginDefaultValue. case mysql.TypeEnum: - defEnum, verr := types.ParseEnumValue(col.FieldType.Elems, 1) + defEnum, verr := types.ParseEnumValue(col.GetElems(), 1) if verr != nil { return nil, errors.Trace(verr) } - defVal := types.NewCollateMysqlEnumDatum(defEnum, col.Collate) + defVal := types.NewCollateMysqlEnumDatum(defEnum, col.GetCollate()) return defVal.ToString() default: zeroVal := table.GetZeroValue(col) @@ -1906,10 +1904,10 @@ func generateOriginDefaultValue(col *model.ColumnInfo, ctx sessionctx.Context) ( } else { t, _ = expression.GetStmtTimestamp(ctx) } - if col.Tp == mysql.TypeTimestamp { - odValue = types.NewTime(types.FromGoTime(t.UTC()), col.Tp, col.Decimal).String() - } else if col.Tp == mysql.TypeDatetime { - odValue = types.NewTime(types.FromGoTime(t), col.Tp, col.Decimal).String() + if col.GetType() == mysql.TypeTimestamp { + odValue = types.NewTime(types.FromGoTime(t.UTC()), col.GetType(), col.GetDecimal()).String() + } else if col.GetType() == mysql.TypeDatetime { + odValue = types.NewTime(types.FromGoTime(t), col.GetType(), col.GetDecimal()).String() } } return odValue, nil diff --git a/ddl/column_change_test.go b/ddl/column_change_test.go index 7510fd96e3181..436559bd2fe3b 100644 --- a/ddl/column_change_test.go +++ b/ddl/column_change_test.go @@ -97,7 +97,7 @@ func TestColumnAdd(t *testing.T) { tc.OnJobUpdatedExported = func(job *model.Job) { jobID = job.ID tbl := external.GetTableByName(t, internal, "test", "t") - if job.SchemaState != model.StateNone { + if job.SchemaState != model.StatePublic { for _, col := range tbl.Cols() { require.NotEqualf(t, col.ID, dropCol.ID, "column is not dropped") } diff --git a/ddl/column_modify_test.go b/ddl/column_modify_test.go index d0dedc8667818..e9d5f4ed53764 100644 --- a/ddl/column_modify_test.go +++ b/ddl/column_modify_test.go @@ -39,7 +39,6 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -168,8 +167,8 @@ AddLoop: require.NoError(t, err) tblInfo := tbl.Meta() colC := tblInfo.Columns[2] - require.Equal(t, mysql.TypeTimestamp, colC.Tp) - require.False(t, mysql.HasNotNullFlag(colC.Flag)) + require.Equal(t, mysql.TypeTimestamp, colC.GetType()) + require.False(t, mysql.HasNotNullFlag(colC.GetFlag())) // add datetime type column tk.MustExec("create table test_on_update_d (c1 int, c2 datetime);") tk.MustExec("alter table test_on_update_d add column c3 datetime on update current_timestamp;") @@ -178,8 +177,8 @@ AddLoop: require.NoError(t, err) tblInfo = tbl.Meta() colC = tblInfo.Columns[2] - require.Equal(t, mysql.TypeDatetime, colC.Tp) - require.False(t, mysql.HasNotNullFlag(colC.Flag)) + require.Equal(t, mysql.TypeDatetime, colC.GetType()) + require.False(t, mysql.HasNotNullFlag(colC.GetFlag())) // add year type column tk.MustExec("create table test_on_update_e (c1 int);") @@ -316,7 +315,7 @@ func TestChangeColumn(t *testing.T) { require.NoError(t, err) tblInfo := tbl.Meta() colD := tblInfo.Columns[2] - require.True(t, mysql.HasNoDefaultValueFlag(colD.Flag)) + require.True(t, mysql.HasNoDefaultValueFlag(colD.GetFlag())) // for the following definitions: 'not null', 'null', 'default value' and 'comment' tk.MustExec("alter table t3 change b b varchar(20) null default 'c' comment 'my comment'") is = domain.GetDomain(tk.Session()).InfoSchema() @@ -325,7 +324,7 @@ func TestChangeColumn(t *testing.T) { tblInfo = tbl.Meta() colB := tblInfo.Columns[1] require.Equal(t, "my comment", colB.Comment) - require.False(t, mysql.HasNotNullFlag(colB.Flag)) + require.False(t, mysql.HasNotNullFlag(colB.GetFlag())) tk.MustExec("insert into t3 set aa = 3, dd = 5") tk.MustQuery("select b from t3").Check(testkit.Rows("a", "b", "c")) // for timestamp @@ -337,7 +336,7 @@ func TestChangeColumn(t *testing.T) { tblInfo = tbl.Meta() colC := tblInfo.Columns[3] require.Equal(t, "col c comment", colC.Comment) - require.False(t, mysql.HasNotNullFlag(colC.Flag)) + require.False(t, mysql.HasNotNullFlag(colC.GetFlag())) // for enum tk.MustExec("alter table t3 add column en enum('a', 'b', 'c') not null default 'a'") // https://github.com/pingcap/tidb/issues/23488 @@ -440,199 +439,6 @@ func TestRenameColumn(t *testing.T) { tk.MustExec("drop table test_rename_column") } -// TestCancelDropColumn tests cancel ddl job which type is drop column. -func TestCancelDropColumn(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - - tk.MustExec("create table test_drop_column(c1 int, c2 int)") - defer tk.MustExec("drop table test_drop_column;") - testCases := []struct { - needAddColumn bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {true, model.JobStateQueueing, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionDropColumn && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - - originalHook := dom.DDL().GetHook() - dom.DDL().SetHook(hook) - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddColumn { - tk.MustExec("alter table test_drop_column add column c3 int") - tk.MustExec("alter table test_drop_column add index idx_c3(c3)") - } - - err := tk.ExecToErr("alter table test_drop_column drop column c3") - var col1 *table.Column - var idx1 table.Index - tbl := external.GetTableByName(t, tk, "test", "test_drop_column") - for _, col := range tbl.Cols() { - if strings.EqualFold(col.Name.L, "c3") { - col1 = col - break - } - } - for _, idx := range tbl.Indices() { - if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { - idx1 = idx - break - } - } - if testCase.cancelSucc { - require.NoError(t, checkErr) - require.NotNil(t, col1) - require.Equal(t, "c3", col1.Name.L) - require.NotNil(t, idx1) - require.Equal(t, "idx_c3", idx1.Meta().Name.L) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - } else { - require.Nil(t, col1) - require.Nil(t, col1) - require.NoError(t, err) - require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - } - } - dom.DDL().SetHook(originalHook) - tk.MustExec("alter table test_drop_column add column c3 int") - tk.MustExec("alter table test_drop_column drop column c3") -} - -// TestCancelDropColumns tests cancel ddl job which type is drop multi-columns. -func TestCancelDropColumns(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - - tk.MustExec("create table test_drop_column(c1 int, c2 int)") - defer tk.MustExec("drop table test_drop_column;") - testCases := []struct { - needAddColumn bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {true, model.JobStateQueueing, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionDropColumns && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - - originalHook := dom.DDL().GetHook() - dom.DDL().SetHook(hook) - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddColumn { - tk.MustExec("alter table test_drop_column add column c3 int, add column c4 int") - tk.MustExec("alter table test_drop_column add index idx_c3(c3)") - } - err := tk.ExecToErr("alter table test_drop_column drop column c3, drop column c4") - tbl := external.GetTableByName(t, tk, "test", "test_drop_column") - col3 := table.FindCol(tbl.Cols(), "c3") - col4 := table.FindCol(tbl.Cols(), "c4") - var idx3 table.Index - for _, idx := range tbl.Indices() { - if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { - idx3 = idx - break - } - } - if testCase.cancelSucc { - require.NoError(t, checkErr) - require.NotNil(t, col3) - require.NotNil(t, col4) - require.NotNil(t, idx3) - require.Equal(t, "c3", col3.Name.L) - require.Equal(t, "c4", col4.Name.L) - require.Equal(t, "idx_c3", idx3.Meta().Name.L) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - } else { - require.Nil(t, col3) - require.Nil(t, col4) - require.Nil(t, idx3) - require.NoError(t, err) - require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - } - } - dom.DDL().SetHook(originalHook) - tk.MustExec("alter table test_drop_column add column c3 int, add column c4 int") - tk.MustExec("alter table test_drop_column drop column c3, drop column c4") -} - func TestVirtualColumnDDL(t *testing.T) { store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) defer clean() @@ -822,7 +628,7 @@ func TestColumnModifyingDefinition(t *testing.T) { c2 = col } } - require.True(t, mysql.HasNotNullFlag(c2.Flag)) + require.True(t, mysql.HasNotNullFlag(c2.GetFlag())) tk.MustExec("drop table if exists test2;") tk.MustExec("create table test2 (c1 int, c2 int, c3 int default 1, index (c1));") @@ -1024,7 +830,7 @@ func TestCheckConvertToCharacter(t *testing.T) { tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8 collate utf8_bin", errno.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8mb4 collate utf8mb4_bin", errno.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table t modify column a varchar(10) charset latin1 collate latin1_bin", errno.ErrUnsupportedDDLOperation) - require.Equal(t, "binary", tbl.Cols()[0].Charset) + require.Equal(t, "binary", tbl.Cols()[0].GetCharset()) } func TestAddMultiColumnsIndex(t *testing.T) { @@ -1203,16 +1009,16 @@ func TestColumnTypeChangeGenUniqueChangingName(t *testing.T) { tbl = external.GetTableByName(t, tk, "test", "t") require.Len(t, tbl.Meta().Columns, 4) require.Equal(t, "c1", tbl.Meta().Columns[0].Name.O) - require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[0].Tp) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[0].GetType()) require.Equal(t, 0, tbl.Meta().Columns[0].Offset) require.Equal(t, "_col$_c1", tbl.Meta().Columns[1].Name.O) - require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[1].Tp) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[1].GetType()) require.Equal(t, 1, tbl.Meta().Columns[1].Offset) require.Equal(t, "_col$__col$_c1_0", tbl.Meta().Columns[2].Name.O) - require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[2].Tp) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[2].GetType()) require.Equal(t, 2, tbl.Meta().Columns[2].Offset) require.Equal(t, "_col$__col$__col$_c1_0_0", tbl.Meta().Columns[3].Name.O) - require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[3].Tp) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[3].GetType()) require.Equal(t, 3, tbl.Meta().Columns[3].Offset) tk.MustExec("drop table if exists t") @@ -1243,16 +1049,17 @@ func TestWriteReorgForColumnTypeChangeOnAmendTxn(t *testing.T) { }() hook := &ddl.TestDDLCallback{Do: dom} times := 0 - hook.OnJobUpdatedExported = func(job *model.Job) { - if job.Type != model.ActionModifyColumn || checkErr != nil || - (job.SchemaState != startColState && job.SchemaState != commitColState) { + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type != model.ActionModifyColumn || checkErr != nil || job.SchemaState != startColState { return } - if job.SchemaState == startColState { - tk1.MustExec("use test") - tk1.MustExec("begin pessimistic;") - tk1.MustExec("insert into t1 values(101, 102, 103)") + tk1.MustExec("use test") + tk1.MustExec("begin pessimistic;") + tk1.MustExec("insert into t1 values(101, 102, 103)") + } + hook.OnJobUpdatedExported = func(job *model.Job) { + if job.Type != model.ActionModifyColumn || checkErr != nil || job.SchemaState != commitColState { return } if times == 0 { diff --git a/ddl/column_test.go b/ddl/column_test.go index 0f142967b9cfe..f9023607ad99d 100644 --- a/ddl/column_test.go +++ b/ddl/column_test.go @@ -97,14 +97,15 @@ func testDropColumnInternal(tk *testkit.TestKit, t *testing.T, ctx sessionctx.Co return id } -func testDropTable(tk *testkit.TestKit, t *testing.T, tblName string, dom *domain.Domain) int64 { +func testDropTable(tk *testkit.TestKit, t *testing.T, dbName, tblName string, dom *domain.Domain) int64 { sql := fmt.Sprintf("drop table %s ", tblName) + tk.MustExec("use " + dbName) tk.MustExec(sql) idi, _ := strconv.Atoi(tk.MustQuery("admin show ddl jobs 1;").Rows()[0][0].(string)) id := int64(idi) require.NoError(t, dom.Reload()) - _, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr(tblName)) + _, err := dom.InfoSchema().TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName)) require.Error(t, err) return id } @@ -304,7 +305,7 @@ func TestColumnBasic(t *testing.T) { jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c6", true, dom) testCheckJobDone(t, store, jobID, false) - testDropTable(tk, t, "t1", dom) + testDropTable(tk, t, "test", "t1", dom) } func checkColumnKVExist(ctx sessionctx.Context, t table.Table, handle kv.Handle, col *table.Column, columnValue interface{}, isExist bool) error { @@ -694,7 +695,7 @@ func TestAddColumn(t *testing.T) { require.True(t, checkOK) - jobID = testDropTable(tk, t, "t1", dom) + jobID = testDropTable(tk, t, "test", "t1", dom) testCheckJobDone(t, store, jobID, false) } @@ -770,7 +771,7 @@ func TestAddColumns(t *testing.T) { require.NoError(t, hErr) require.True(t, ok) - jobID = testDropTable(tk, t, "t1", dom) + jobID = testDropTable(tk, t, "test", "t1", dom) testCheckJobDone(t, store, jobID, false) } @@ -832,7 +833,7 @@ func TestDropColumnInColumnTest(t *testing.T) { require.NoError(t, hErr) require.True(t, ok) - jobID = testDropTable(tk, t, "t1", dom) + jobID = testDropTable(tk, t, "test", "t1", dom) testCheckJobDone(t, store, jobID, false) } @@ -897,7 +898,7 @@ func TestDropColumns(t *testing.T) { require.NoError(t, hErr) require.True(t, ok) - jobID = testDropTable(tk, t, "t1", dom) + jobID = testDropTable(tk, t, "test", "t1", dom) testCheckJobDone(t, store, jobID, false) } diff --git a/ddl/column_type_change_test.go b/ddl/column_type_change_test.go index 40dfd475a72ae..5509c95af1391 100644 --- a/ddl/column_type_change_test.go +++ b/ddl/column_type_change_test.go @@ -151,7 +151,7 @@ func TestColumnTypeChangeStateBetweenInteger(t *testing.T) { } else if len(tbl.(*tables.TableCommon).Columns) != 3 { // changingCols has been added into meta. checkErr = errors.New("len(cols) is not right") - } else if external.GetModifyColumn(t, internalTK, "test", "t", "c2", true).Flag&mysql.PreventNullInsertFlag == uint(0) { + } else if external.GetModifyColumn(t, internalTK, "test", "t", "c2", true).GetFlag()&mysql.PreventNullInsertFlag == uint(0) { checkErr = errors.New("old col's flag is not right") } else if external.GetModifyColumn(t, internalTK, "test", "t", "_Col$_c2_0", true) == nil { checkErr = errors.New("changingCol is nil") @@ -171,9 +171,9 @@ func TestColumnTypeChangeStateBetweenInteger(t *testing.T) { require.Equal(t, 2, len(tbl.Cols())) col := external.GetModifyColumn(t, tk, "test", "t", "c2", false) require.NotNil(t, col) - require.Equal(t, true, mysql.HasNotNullFlag(col.Flag)) - require.NotEqual(t, 0, col.Flag&mysql.NoDefaultValueFlag) - require.Equal(t, mysql.TypeTiny, col.Tp) + require.Equal(t, true, mysql.HasNotNullFlag(col.GetFlag())) + require.NotEqual(t, 0, col.GetFlag()&mysql.NoDefaultValueFlag) + require.Equal(t, mysql.TypeTiny, col.GetType()) require.Nil(t, col.ChangeStateInfo) tk.MustQuery("select * from t").Check(testkit.Rows("1 1")) } @@ -242,8 +242,8 @@ func assertRollBackedColUnchanged(t *testing.T, tk *testkit.TestKit) { require.Equal(t, 2, len(tbl.Cols())) col := external.GetModifyColumn(t, tk, "test", "t", "c2", false) require.NotNil(t, col) - require.Equal(t, uint(0), col.Flag) - require.Equal(t, mysql.TypeLonglong, col.Tp) + require.Equal(t, uint(0), col.GetFlag()) + require.Equal(t, mysql.TypeLonglong, col.GetType()) require.Nil(t, col.ChangeStateInfo) tk.MustQuery("select * from t").Check(testkit.Rows("1 1")) } @@ -280,37 +280,37 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify a varchar(10)") modifiedColumn := external.GetModifyColumn(t, tk, "test", "t", "a", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeVarchar, modifiedColumn.Tp) + require.Equal(t, mysql.TypeVarchar, modifiedColumn.GetType()) tk.MustQuery("select a from t").Check(testkit.Rows("1")) tk.MustExec("alter table t modify b char(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeString, modifiedColumn.Tp) + require.Equal(t, mysql.TypeString, modifiedColumn.GetType()) tk.MustQuery("select b from t").Check(testkit.Rows("11")) tk.MustExec("alter table t modify c binary(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeString, modifiedColumn.Tp) + require.Equal(t, mysql.TypeString, modifiedColumn.GetType()) tk.MustQuery("select c from t").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00")) tk.MustExec("alter table t modify d varbinary(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeVarchar, modifiedColumn.Tp) + require.Equal(t, mysql.TypeVarchar, modifiedColumn.GetType()) tk.MustQuery("select d from t").Check(testkit.Rows("1111")) tk.MustExec("alter table t modify e blob(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "e", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.Tp) + require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.GetType()) tk.MustQuery("select e from t").Check(testkit.Rows("11111")) tk.MustExec("alter table t modify f text(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "f", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.Tp) + require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.GetType()) tk.MustQuery("select f from t").Check(testkit.Rows("111111")) // integer to decimal @@ -318,7 +318,7 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify a decimal(2,1)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeNewDecimal, modifiedColumn.Tp) + require.Equal(t, mysql.TypeNewDecimal, modifiedColumn.GetType()) tk.MustQuery("select a from t").Check(testkit.Rows("1.0")) // integer to year @@ -326,21 +326,21 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify b year") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeYear, modifiedColumn.Tp) + require.Equal(t, mysql.TypeYear, modifiedColumn.GetType()) tk.MustQuery("select b from t").Check(testkit.Rows("2011")) // integer to time tk.MustExec("alter table t modify c time") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeDuration, modifiedColumn.Tp) + require.Equal(t, mysql.TypeDuration, modifiedColumn.GetType()) tk.MustQuery("select c from t").Check(testkit.Rows("00:01:11")) // integer to date (mysql will throw `Incorrect date value: '1111' for column 'd' at row 1` error) tk.MustExec("alter table t modify d date") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeDate, modifiedColumn.Tp) + require.Equal(t, mysql.TypeDate, modifiedColumn.GetType()) tk.MustQuery("select d from t").Check(testkit.Rows("2000-11-11")) // the given number will be left-forward used. // integer to timestamp (according to what timezone you have set) @@ -348,14 +348,14 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("set @@session.time_zone=UTC") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "e", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeTimestamp, modifiedColumn.Tp) + require.Equal(t, mysql.TypeTimestamp, modifiedColumn.GetType()) tk.MustQuery("select e from t").Check(testkit.Rows("2001-11-10 16:00:00")) // the given number will be left-forward used. // integer to datetime tk.MustExec("alter table t modify f datetime") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "f", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeDatetime, modifiedColumn.Tp) + require.Equal(t, mysql.TypeDatetime, modifiedColumn.GetType()) tk.MustQuery("select f from t").Check(testkit.Rows("2011-11-11 00:00:00")) // the given number will be left-forward used. // integer to floating-point values @@ -363,20 +363,20 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify a float") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeFloat, modifiedColumn.Tp) + require.Equal(t, mysql.TypeFloat, modifiedColumn.GetType()) tk.MustQuery("select a from t").Check(testkit.Rows("1")) tk.MustExec("alter table t modify b double") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeDouble, modifiedColumn.Tp) + require.Equal(t, mysql.TypeDouble, modifiedColumn.GetType()) tk.MustQuery("select b from t").Check(testkit.Rows("11")) // integer to bit tk.MustExec("alter table t modify c bit(10)") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeBit, modifiedColumn.Tp) + require.Equal(t, mysql.TypeBit, modifiedColumn.GetType()) // 111 will be stored ad 0x00,0110,1111 = 0x6F, which will be shown as ASCII('o')=111 as well. tk.MustQuery("select c from t").Check(testkit.Rows("\x00o")) @@ -384,7 +384,7 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify d json") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeJSON, modifiedColumn.Tp) + require.Equal(t, mysql.TypeJSON, modifiedColumn.GetType()) tk.MustQuery("select d from t").Check(testkit.Rows("1111")) // integer to enum @@ -393,14 +393,14 @@ func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { tk.MustExec("alter table t modify a enum(\"a\", \"b\")") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeEnum, modifiedColumn.Tp) + require.Equal(t, mysql.TypeEnum, modifiedColumn.GetType()) tk.MustQuery("select a from t").Check(testkit.Rows("a")) // TiDB take integer as the set element offset to cast. tk.MustExec("alter table t modify b set(\"a\", \"b\")") modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) require.NotNil(t, modifiedColumn) - require.Equal(t, mysql.TypeSet, modifiedColumn.Tp) + require.Equal(t, mysql.TypeSet, modifiedColumn.GetType()) tk.MustQuery("select b from t").Check(testkit.Rows("a")) // TiDB can't take integer as the enum element string to cast, while the MySQL can. @@ -1838,13 +1838,13 @@ func TestChangingAttributeOfColumnWithFK(t *testing.T) { // For column with FK, alter action can be performed for changing null/not null, default value, comment and so on, but column type. tk.MustExec("alter table orders modify user_id int null;") tbl := external.GetTableByName(t, tk, "test", "orders") - require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag)) + require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].GetFlag())) prepare() tk.MustExec("alter table orders change user_id user_id2 int null") tbl = external.GetTableByName(t, tk, "test", "orders") require.Equal(t, "user_id2", tbl.Meta().Columns[1].Name.L) - require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag)) + require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].GetFlag())) prepare() tk.MustExec("alter table orders modify user_id int default -1 comment \"haha\"") diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 67be5b2de9331..889655231ba16 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -822,16 +822,15 @@ func (s *stateChangeSuite) runTestInSchemaState( callback := &ddl.TestDDLCallback{Do: s.dom} prevState := model.StateNone var checkErr error - times := 0 se, err := session.CreateSession(s.store) s.Require().NoError(err) _, err = se.Execute(context.Background(), "use test_db_state") s.Require().NoError(err) cbFunc := func(job *model.Job) { - if job.SchemaState == prevState || checkErr != nil || times >= 3 { + if job.SchemaState == prevState || checkErr != nil { return } - times++ + prevState = job.SchemaState if job.SchemaState != state { return } diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 75f4aeebdee49..1e2762ce47a46 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -27,6 +27,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/infoschema" @@ -678,66 +679,31 @@ func TestTableDDLWithTimeType(t *testing.T) { } func TestUpdateMultipleTable(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() tk := testkit.NewTestKit(t, store) - tk.MustExec("create database umt_db") - tk.MustExec("use umt_db") + tk.MustExec("use test") tk.MustExec("create table t1 (c1 int, c2 int)") tk.MustExec("insert t1 values (1, 1), (2, 2)") tk.MustExec("create table t2 (c1 int, c2 int)") tk.MustExec("insert t2 values (1, 3), (2, 5)") - ctx := tk.Session() - dom := domain.GetDomain(ctx) - is := dom.InfoSchema() - db, ok := is.SchemaByName(model.NewCIStr("umt_db")) - require.True(t, ok) - t1Tbl, err := is.TableByName(model.NewCIStr("umt_db"), model.NewCIStr("t1")) - require.NoError(t, err) - t1Info := t1Tbl.Meta() - - // Add a new column in write only state. - newColumn := &model.ColumnInfo{ - ID: 100, - Name: model.NewCIStr("c3"), - Offset: 2, - DefaultValue: 9, - OriginDefaultValue: 9, - FieldType: *types.NewFieldType(mysql.TypeLonglong), - State: model.StateWriteOnly, + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + d := dom.DDL() + hook := &ddl.TestDDLCallback{Do: dom} + hook.OnJobUpdatedExported = func(job *model.Job) { + if job.SchemaState == model.StateWriteOnly { + tk2.MustExec("update t1, t2 set t1.c1 = 8, t2.c2 = 10 where t1.c2 = t2.c1") + tk2.MustQuery("select * from t1").Check(testkit.Rows("8 1", "8 2")) + tk2.MustQuery("select * from t2").Check(testkit.Rows("1 10", "2 10")) + } } - t1Info.Columns = append(t1Info.Columns, newColumn) - - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - _, err = m.GenSchemaVersion() - require.NoError(t, err) - require.Nil(t, m.UpdateTable(db.ID, t1Info)) - return nil - }) - require.NoError(t, err) - err = dom.Reload() - require.NoError(t, err) - - tk.MustExec("update t1, t2 set t1.c1 = 8, t2.c2 = 10 where t1.c2 = t2.c1") - tk.MustQuery("select * from t1").Check(testkit.Rows("8 1", "8 2")) - tk.MustQuery("select * from t2").Check(testkit.Rows("1 10", "2 10")) + d.SetHook(hook) - newColumn.State = model.StatePublic - - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - _, err = m.GenSchemaVersion() - require.NoError(t, err) - require.Nil(t, m.UpdateTable(db.ID, t1Info)) - return nil - }) - require.NoError(t, err) - err = dom.Reload() - require.NoError(t, err) + tk.MustExec("alter table t1 add column c3 bigint default 9") tk.MustQuery("select * from t1").Check(testkit.Rows("8 1 9", "8 2 9")) - tk.MustExec("drop database umt_db") } func TestNullGeneratedColumn(t *testing.T) { @@ -819,8 +785,8 @@ func TestChangingTableCharset(t *testing.T) { require.Equal(t, chs, tbl.Meta().Charset) require.Equal(t, coll, tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { - require.Equal(t, chs, col.Charset) - require.Equal(t, coll, col.Collate) + require.Equal(t, chs, col.GetCharset()) + require.Equal(t, coll, col.GetCollate()) } } checkCharset(charset.CharsetUTF8MB4, charset.CollationUTF8MB4) @@ -877,15 +843,15 @@ func TestChangingTableCharset(t *testing.T) { // Test when column charset is "". tbl = external.GetTableByName(t, tk, "test", "t") tblInfo = tbl.Meta().Clone() - tblInfo.Columns[0].Charset = "" - tblInfo.Columns[0].Collate = "" + tblInfo.Columns[0].SetCharset("") + tblInfo.Columns[0].SetCollate("") updateTableInfo(tblInfo) // check table charset is "" tk.MustExec("alter table t drop column b;") // load latest schema. tbl = external.GetTableByName(t, tk, "test", "t") require.NotNil(t, tbl) - require.Equal(t, "", tbl.Meta().Columns[0].Charset) - require.Equal(t, "", tbl.Meta().Columns[0].Collate) + require.Equal(t, "", tbl.Meta().Columns[0].GetCharset()) + require.Equal(t, "", tbl.Meta().Columns[0].GetCollate()) tk.MustExec("alter table t convert to charset utf8mb4;") checkCharset(charset.CharsetUTF8MB4, charset.CollationUTF8MB4) @@ -907,8 +873,8 @@ func TestChangingTableCharset(t *testing.T) { require.Equal(t, "utf8mb4_bin", tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { // Column charset and collate should remain unchanged. - require.Equal(t, "utf8", col.Charset) - require.Equal(t, "utf8_bin", col.Collate) + require.Equal(t, "utf8", col.GetCharset()) + require.Equal(t, "utf8_bin", col.GetCollate()) } tk.MustExec("drop table t") @@ -919,9 +885,9 @@ func TestChangingTableCharset(t *testing.T) { require.Equal(t, "utf8", tbl.Meta().Charset) require.Equal(t, "utf8_general_ci", tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { - require.Equal(t, "utf8", col.Charset) + require.Equal(t, "utf8", col.GetCharset()) // Column collate should remain unchanged. - require.Equal(t, "utf8_unicode_ci", col.Collate) + require.Equal(t, "utf8_unicode_ci", col.GetCollate()) } } @@ -1091,7 +1057,7 @@ func TestCaseInsensitiveCharsetAndCollate(t *testing.T) { tbl := external.GetTableByName(t, tk, "test_charset_collate", "t5") tblInfo := tbl.Meta().Clone() require.Equal(t, "utf8mb4", tblInfo.Charset) - require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].GetCharset()) tblInfo.Version = model.TableInfoVersion2 tblInfo.Charset = "UTF8MB4" @@ -1115,7 +1081,7 @@ func TestCaseInsensitiveCharsetAndCollate(t *testing.T) { tblInfo = external.GetTableByName(t, tk, "test_charset_collate", "t5").Meta() require.Equal(t, "utf8mb4", tblInfo.Charset) - require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].GetCharset()) // For model.TableInfoVersion3, it is believed that all charsets / collations are lower-cased, do not do case-convert tblInfo = tblInfo.Clone() @@ -1126,7 +1092,7 @@ func TestCaseInsensitiveCharsetAndCollate(t *testing.T) { tblInfo = external.GetTableByName(t, tk, "test_charset_collate", "t5").Meta() require.Equal(t, "UTF8MB4", tblInfo.Charset) - require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].GetCharset()) } func TestZeroFillCreateTable(t *testing.T) { @@ -1149,11 +1115,11 @@ func TestZeroFillCreateTable(t *testing.T) { } } require.NotNil(t, yearCol) - require.Equal(t, mysql.TypeYear, yearCol.Tp) - require.True(t, mysql.HasUnsignedFlag(yearCol.Flag)) + require.Equal(t, mysql.TypeYear, yearCol.GetType()) + require.True(t, mysql.HasUnsignedFlag(yearCol.GetFlag())) require.NotNil(t, zCol) - require.True(t, mysql.HasUnsignedFlag(zCol.Flag)) + require.True(t, mysql.HasUnsignedFlag(zCol.GetFlag())) } func TestBitDefaultValue(t *testing.T) { @@ -1382,7 +1348,7 @@ func TestResolveCharset(t *testing.T) { is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("resolve_charset")) require.NoError(t, err) - require.Equal(t, "latin1", tbl.Cols()[0].Charset) + require.Equal(t, "latin1", tbl.Cols()[0].GetCharset()) tk.MustExec("INSERT INTO resolve_charset VALUES('鰈')") tk.MustExec("create database resolve_charset charset binary") @@ -1392,14 +1358,14 @@ func TestResolveCharset(t *testing.T) { is = domain.GetDomain(ctx).InfoSchema() tbl, err = is.TableByName(model.NewCIStr("resolve_charset"), model.NewCIStr("resolve_charset")) require.NoError(t, err) - require.Equal(t, "latin1", tbl.Cols()[0].Charset) + require.Equal(t, "latin1", tbl.Cols()[0].GetCharset()) require.Equal(t, "latin1", tbl.Meta().Charset) tk.MustExec(`CREATE TABLE resolve_charset1 (a varchar(255) DEFAULT NULL)`) is = domain.GetDomain(ctx).InfoSchema() tbl, err = is.TableByName(model.NewCIStr("resolve_charset"), model.NewCIStr("resolve_charset1")) require.NoError(t, err) - require.Equal(t, "binary", tbl.Cols()[0].Charset) + require.Equal(t, "binary", tbl.Cols()[0].GetCharset()) require.Equal(t, "binary", tbl.Meta().Charset) } @@ -1615,7 +1581,7 @@ func TestAlterColumn(t *testing.T) { require.NoError(t, err) tblInfo := tbl.Meta() colA := tblInfo.Columns[0] - hasNoDefault := mysql.HasNoDefaultValueFlag(colA.Flag) + hasNoDefault := mysql.HasNoDefaultValueFlag(colA.GetFlag()) require.False(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column a set default 222") tk.MustExec("insert into test_alter_column set b = 'b', c = 'bb'") @@ -1625,7 +1591,7 @@ func TestAlterColumn(t *testing.T) { require.NoError(t, err) tblInfo = tbl.Meta() colA = tblInfo.Columns[0] - hasNoDefault = mysql.HasNoDefaultValueFlag(colA.Flag) + hasNoDefault = mysql.HasNoDefaultValueFlag(colA.GetFlag()) require.False(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column b set default null") tk.MustExec("insert into test_alter_column set c = 'cc'") @@ -1635,7 +1601,7 @@ func TestAlterColumn(t *testing.T) { require.NoError(t, err) tblInfo = tbl.Meta() colC := tblInfo.Columns[2] - hasNoDefault = mysql.HasNoDefaultValueFlag(colC.Flag) + hasNoDefault = mysql.HasNoDefaultValueFlag(colC.GetFlag()) require.True(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column c set default 'xx'") tk.MustExec("insert into test_alter_column set a = 123") @@ -1645,7 +1611,7 @@ func TestAlterColumn(t *testing.T) { require.NoError(t, err) tblInfo = tbl.Meta() colC = tblInfo.Columns[2] - hasNoDefault = mysql.HasNoDefaultValueFlag(colC.Flag) + hasNoDefault = mysql.HasNoDefaultValueFlag(colC.GetFlag()) require.False(t, hasNoDefault) // TODO: After fix issue 2606. // tk.MustExec( "alter table test_alter_column alter column d set default null") @@ -1959,8 +1925,8 @@ func TestTreatOldVersionUTF8AsUTF8MB4(t *testing.T) { }) tk.MustExec("alter table t modify column a varchar(10) character set utf8mb4") // change column charset. tbl = external.GetTableByName(t, tk, "test", "t") - require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].Charset) - require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].Collate) + require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].GetCharset()) + require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].GetCollate()) require.Equal(t, model.ColumnInfoVersion0, tbl.Meta().Columns[0].Version) tk.MustExec("insert into t set a= x'f09f8c80'") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + @@ -1970,8 +1936,8 @@ func TestTreatOldVersionUTF8AsUTF8MB4(t *testing.T) { // Test for change column should not modify the column version. tk.MustExec("alter table t change column a a varchar(20)") // change column. tbl = external.GetTableByName(t, tk, "test", "t") - require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].Charset) - require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].Collate) + require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].GetCharset()) + require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].GetCollate()) require.Equal(t, model.ColumnInfoVersion0, tbl.Meta().Columns[0].Version) // Test for v2.1.5 and v2.1.6 that table version is 1 but column version is 0. @@ -1981,8 +1947,8 @@ func TestTreatOldVersionUTF8AsUTF8MB4(t *testing.T) { tblInfo.Collate = charset.CollationUTF8 tblInfo.Version = model.TableInfoVersion1 tblInfo.Columns[0].Version = model.ColumnInfoVersion0 - tblInfo.Columns[0].Charset = charset.CharsetUTF8 - tblInfo.Columns[0].Collate = charset.CollationUTF8 + tblInfo.Columns[0].SetCharset(charset.CharsetUTF8) + tblInfo.Columns[0].SetCollate(charset.CollationUTF8) updateTableInfo(tblInfo) require.True(t, config.GetGlobalConfig().TreatOldVersionUTF8AsUTF8MB4) tk.MustExec("alter table t change column b b varchar(20) character set ascii") // reload schema. @@ -2373,7 +2339,7 @@ func TestAddExpressionIndex(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true @@ -2456,7 +2422,7 @@ func TestCreateExpressionIndexError(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true @@ -3376,7 +3342,7 @@ func TestDropTemporaryTable(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true diff --git a/ddl/db_partition_test.go b/ddl/db_partition_test.go index 58a644a6ff3ce..4955772a34bf8 100644 --- a/ddl/db_partition_test.go +++ b/ddl/db_partition_test.go @@ -24,7 +24,6 @@ import ( "testing" "time" - "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" @@ -47,11 +46,9 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" - "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -2183,7 +2180,7 @@ func TestExchangePartitionExpressIndex(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true @@ -2779,167 +2776,6 @@ LOOP: tk.MustExec("drop table partition_drop_idx;") } -func TestPartitionCancelAddPrimaryKey(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - idxName := "primary" - addIdxSQL := "alter table t1 add primary key c3_index (c1);" - testPartitionCancelAddIndex(t, store, dom.DDL(), 50*time.Millisecond, idxName, addIdxSQL) -} - -func TestPartitionCancelAddIndex(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - idxName := "c3_index" - addIdxSQL := "create unique index c3_index on t1 (c1)" - testPartitionCancelAddIndex(t, store, dom.DDL(), 50*time.Millisecond, idxName, addIdxSQL) -} - -func batchInsertT(tk *testkit.TestKit, tbl string, start, end int) { - dml := fmt.Sprintf("insert into %s values", tbl) - for i := start; i < end; i++ { - dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) - if i != end-1 { - dml += "," - } - } - tk.MustExec(dml) -} - -func testPartitionCancelAddIndex(t *testing.T, store kv.Storage, d ddl.DDL, lease time.Duration, idxName, addIdxSQL string) { - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t1;") - tk.MustExec(`create table t1 ( - c1 int, c2 int, c3 int - ) - partition by range( c1 ) ( - partition p0 values less than (1024), - partition p1 values less than (2048), - partition p2 values less than (3072), - partition p3 values less than (4096), - partition p4 values less than (maxvalue) - );`) - count := defaultBatchSize * 32 - // add some rows - for i := 0; i < count; i += defaultBatchSize { - batchInsertT(tk, "t1", i, i+defaultBatchSize) - } - - var checkErr error - hook := &ddl.TestDDLCallback{} - originBatchSize := tk.MustQuery("select @@global.tidb_ddl_reorg_batch_size") - // Set batch size to lower try to slow down add-index reorganization, This if for hook to cancel this ddl job. - tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 32") - defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", originBatchSize.Rows()[0][0])) - hook.OnJobUpdatedExported, _, checkErr = backgroundExecOnJobUpdatedExportedT(t, tk, store, hook, idxName) - originHook := d.GetHook() - defer d.SetHook(originHook) - jobIDExt := wrapJobIDExtCallback(hook) - d.SetHook(jobIDExt) - done := make(chan error, 1) - go backgroundExec(store, addIdxSQL, done) - - times := 0 - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - require.Nil(t, checkErr) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - break LOOP - case <-ticker.C: - if times >= 10 { - break - } - step := 10 - rand.Seed(time.Now().Unix()) - // delete some rows, and add some data - for i := count; i < count+step; i++ { - n := rand.Intn(count) - tk.MustExec("delete from t1 where c1 = ?", n) - tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) - } - count += step - times++ - } - } - tk.MustExec("drop table t1") -} - -func backgroundExecOnJobUpdatedExportedT(t *testing.T, tk *testkit.TestKit, store kv.Storage, hook *ddl.TestDDLCallback, idxName string) ( - func(*model.Job), *model.IndexInfo, error) { - var checkErr error - first := true - c3IdxInfo := &model.IndexInfo{} - hook.OnJobUpdatedExported = func(job *model.Job) { - addIndexNotFirstReorg := (job.Type == model.ActionAddIndex || job.Type == model.ActionAddPrimaryKey) && - job.SchemaState == model.StateWriteReorganization && job.SnapshotVer != 0 - // If the action is adding index and the state is writing reorganization, it want to test the case of cancelling the job when backfilling indexes. - // When the job satisfies this case of addIndexNotFirstReorg, the worker will start to backfill indexes. - if !addIndexNotFirstReorg { - // Get the index's meta. - if c3IdxInfo.ID != 0 { - return - } - tt := external.GetTableByName(t, tk, "test", "t1") - for _, index := range tt.Indices() { - if !tables.IsIndexWritable(index) { - continue - } - if index.Meta().Name.L == idxName { - *c3IdxInfo = *index.Meta() - } - } - return - } - // The job satisfies the case of addIndexNotFirst for the first time, the worker hasn't finished a batch of backfill indexes. - if first { - first = false - return - } - if checkErr != nil { - return - } - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - jobIDs := []int64{job.ID} - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - // It only tests cancel one DDL job. - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - txn, err = hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - err = txn.Commit(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } - } - return hook.OnJobUpdatedExported, c3IdxInfo, checkErr -} - func TestPartitionAddPrimaryKey(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -3348,7 +3184,7 @@ func TestCommitWhenSchemaChange(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.Experimental.AllowsExpressionIndex = true }) store, clean := testkit.CreateMockStoreWithSchemaLease(t, time.Second) diff --git a/ddl/db_rename_test.go b/ddl/db_rename_test.go index b84d22e63a31c..5017beb99615c 100644 --- a/ddl/db_rename_test.go +++ b/ddl/db_rename_test.go @@ -15,21 +15,14 @@ package ddl_test import ( - "context" "fmt" - "strings" "testing" - "github.com/pingcap/errors" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/testkit/external" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -58,61 +51,6 @@ func TestRenameIndex(t *testing.T) { tk.MustGetErrCode("alter table t rename key k3 to K2", errno.ErrDupKeyName) } -// TestCancelRenameIndex tests cancel ddl job which type is rename index. -func TestCancelRenameIndex(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create database if not exists test_rename_index") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(c1 int, c2 int)") - defer tk.MustExec("drop table t;") - for i := 0; i < 100; i++ { - tk.MustExec("insert into t values (?, ?)", i, i) - } - tk.MustExec("alter table t add index idx_c2(c2)") - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionRenameIndex && job.State == model.JobStateQueueing { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := dom.DDL().GetHook() - dom.DDL().SetHook(hook) - tk.MustGetErrMsg("alter table t rename index idx_c2 to idx_c3", "[ddl:8214]Cancelled DDL job") - require.NoError(t, checkErr) - dom.DDL().SetHook(originalHook) - tt := external.GetTableByName(t, tk, "test", "t") - for _, idx := range tt.Indices() { - require.False(t, strings.EqualFold(idx.Meta().Name.L, "idx_c3")) - } - tk.MustExec("alter table t rename index idx_c2 to idx_c3") -} - // See issue: https://github.com/pingcap/tidb/issues/29752 // Ref https://dev.mysql.com/doc/refman/8.0/en/rename-table.html func TestRenameTableWithLocked(t *testing.T) { @@ -146,15 +84,15 @@ func TestRenameTableWithLocked(t *testing.T) { func TestRenameTable2(t *testing.T) { isAlterTable := false - testRenameTable(t, "rename table %s to %s", isAlterTable) + renameTableTest(t, "rename table %s to %s", isAlterTable) } func TestAlterTableRenameTable(t *testing.T) { isAlterTable := true - testRenameTable(t, "alter table %s rename to %s", isAlterTable) + renameTableTest(t, "alter table %s rename to %s", isAlterTable) } -func testRenameTable(t *testing.T, sql string, isAlterTable bool) { +func renameTableTest(t *testing.T, sql string, isAlterTable bool) { store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) diff --git a/ddl/db_table_test.go b/ddl/db_table_test.go index 146aa01e38608..46126f73c2320 100644 --- a/ddl/db_table_test.go +++ b/ddl/db_table_test.go @@ -40,108 +40,9 @@ import ( "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) -// TestCancelDropTable tests cancel ddl job which type is drop table. -func TestCancelDropTableAndSchema(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - tk := testkit.NewTestKit(t, store) - testCases := []struct { - needAddTableOrDB bool - action model.ActionType - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - // Check drop table. - // model.JobStateNone means the jobs is canceled before the first run. - {true, model.ActionDropTable, model.JobStateQueueing, model.StateNone, true}, - {false, model.ActionDropTable, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.ActionDropTable, model.JobStateRunning, model.StateDeleteOnly, false}, - - // Check drop database. - {true, model.ActionDropSchema, model.JobStateQueueing, model.StateNone, true}, - {false, model.ActionDropSchema, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.ActionDropSchema, model.JobStateRunning, model.StateDeleteOnly, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - var jobID int64 - testCase := &testCases[0] - tk.MustExec("create database if not exists test_drop_db") - dbInfo, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("test_drop_db")) - require.True(t, ok) - - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState && job.SchemaID == dbInfo.ID { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originHook := dom.DDL().GetHook() - defer dom.DDL().SetHook(originHook) - dom.DDL().SetHook(hook) - var err error - sql := "" - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddTableOrDB { - tk.MustExec("create database if not exists test_drop_db") - tk.MustExec("use test_drop_db") - tk.MustExec("create table if not exists t(c1 int, c2 int)") - } - - dbInfo, ok = dom.InfoSchema().SchemaByName(model.NewCIStr("test_drop_db")) - require.True(t, ok) - - if testCase.action == model.ActionDropTable { - sql = "drop table t;" - } else if testCase.action == model.ActionDropSchema { - sql = "drop database test_drop_db;" - } - - _, err = tk.Exec(sql) - if testCase.cancelSucc { - require.Nil(t, checkErr) - require.Error(t, err) - require.Equal(t, "[ddl:8214]Cancelled DDL job", err.Error()) - tk.MustExec("insert into t values (?, ?)", i, i) - } else { - require.NoError(t, err) - require.NotNil(t, checkErr) - require.Equal(t, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error(), checkErr.Error()) - _, err = tk.Exec("insert into t values (?, ?)", i, i) - require.Error(t, err) - } - } -} - func TestTableForeignKey(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -412,107 +313,6 @@ func TestCreateTableWithEnumCol(t *testing.T) { tk.MustQuery("select * from t_enum").Check(testkit.Rows("c")) } -// TestCancelAddTableAndDropTablePartition tests cancel ddl job which type is add/drop table partition. -func TestCancelAddTableAndDropTablePartition(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("create database if not exists test_partition_table") - tk.MustExec("use test_partition_table") - tk.MustExec("drop table if exists t_part") - tk.MustExec(`create table t_part (a int key) - partition by range(a) ( - partition p0 values less than (10), - partition p1 values less than (20) - );`) - defer tk.MustExec("drop table t_part;") - base := 10 - for i := 0; i < base; i++ { - tk.MustExec("insert into t_part values (?)", i) - } - - testCases := []struct { - action model.ActionType - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {model.ActionAddTablePartition, model.JobStateQueueing, model.StateNone, true}, - {model.ActionDropTablePartition, model.JobStateQueueing, model.StateNone, true}, - // Add table partition now can be cancelled in ReplicaOnly state. - {model.ActionAddTablePartition, model.JobStateRunning, model.StateReplicaOnly, true}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - testCase := &testCases[0] - var jobID int64 - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := dom.DDL().GetHook() - dom.DDL().SetHook(hook) - - var err error - sql := "" - for i := range testCases { - testCase = &testCases[i] - if testCase.action == model.ActionAddTablePartition { - sql = `alter table t_part add partition ( - partition p2 values less than (30) - );` - } else if testCase.action == model.ActionDropTablePartition { - sql = "alter table t_part drop partition p1;" - } - _, err = tk.Exec(sql) - if testCase.cancelSucc { - require.Nil(t, checkErr) - require.Error(t, err) - require.Equal(t, "[ddl:8214]Cancelled DDL job", err.Error()) - tk.MustExec("insert into t_part values (?)", i+base) - - ctx := tk.Session() - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_partition_table"), model.NewCIStr("t_part")) - require.NoError(t, err) - partitionInfo := tbl.Meta().GetPartitionInfo() - require.NotNil(t, partitionInfo) - require.Len(t, partitionInfo.AddingDefinitions, 0) - } else { - require.NoError(t, err) - require.NoError(t, checkErr) - require.Equal(t, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error(), checkErr.Error()) - tk.MustExec("insert into t_part values (?)", i) - - } - } - dom.DDL().SetHook(originalHook) -} - func TestAlterTableWithValidation(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/ddl/db_test.go b/ddl/db_test.go index d848ba542efe2..0f3f4378d69b8 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -17,6 +17,7 @@ package ddl_test import ( "context" "fmt" + "math" "sort" "strconv" "strings" @@ -26,9 +27,11 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/ddl" ddlutil "github.com/pingcap/tidb/ddl/util" + "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -39,10 +42,13 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tidb/util/sqlexec" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" + "github.com/tikv/client-go/v2/tikv" ) const ( @@ -345,7 +351,7 @@ func TestIssue23473(t *testing.T) { tk.MustExec("alter table t_23473 change column k k bigint") tbl := external.GetTableByName(t, tk, "test", "t_23473") - require.True(t, mysql.HasNoDefaultValueFlag(tbl.Cols()[0].Flag)) + require.True(t, mysql.HasNoDefaultValueFlag(tbl.Cols()[0].GetFlag())) } func TestDropCheck(t *testing.T) { @@ -558,14 +564,14 @@ func TestAutoConvertBlobTypeByLength(t *testing.T) { tbl, exist := dom.InfoSchema().TableByID(tableID) require.True(t, exist) - require.Equal(t, tbl.Cols()[0].Tp, mysql.TypeTinyBlob) - require.Equal(t, tbl.Cols()[0].Flen, 255) - require.Equal(t, tbl.Cols()[1].Tp, mysql.TypeBlob) - require.Equal(t, tbl.Cols()[1].Flen, 65535) - require.Equal(t, tbl.Cols()[2].Tp, mysql.TypeMediumBlob) - require.Equal(t, tbl.Cols()[2].Flen, 16777215) - require.Equal(t, tbl.Cols()[3].Tp, mysql.TypeLongBlob) - require.Equal(t, tbl.Cols()[3].Flen, 4294967295) + require.Equal(t, tbl.Cols()[0].GetType(), mysql.TypeTinyBlob) + require.Equal(t, tbl.Cols()[0].GetFlen(), 255) + require.Equal(t, tbl.Cols()[1].GetType(), mysql.TypeBlob) + require.Equal(t, tbl.Cols()[1].GetFlen(), 65535) + require.Equal(t, tbl.Cols()[2].GetType(), mysql.TypeMediumBlob) + require.Equal(t, tbl.Cols()[2].GetFlen(), 16777215) + require.Equal(t, tbl.Cols()[3].GetType(), mysql.TypeLongBlob) + require.Equal(t, tbl.Cols()[3].GetFlen(), 4294967295) } func TestAddExpressionIndexRollback(t *testing.T) { @@ -652,6 +658,96 @@ func TestDropTableOnTiKVDiskFull(t *testing.T) { tk.MustExec("drop table test_disk_full_drop_table;") } +func TestComment(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists ct, ct1") + + validComment := strings.Repeat("a", 1024) + invalidComment := strings.Repeat("b", 1025) + validTableComment := strings.Repeat("a", 2048) + invalidTableComment := strings.Repeat("b", 2049) + + // test table comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer) COMMENT = '" + validTableComment + "'") + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustExec("ALTER TABLE t COMMENT = '" + validTableComment + "'") + + // test column comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer NOT NULL COMMENT '" + validComment + "')") + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustExec("ALTER TABLE t ADD COLUMN c1 integer COMMENT '" + validComment + "'") + + // test index comment + tk.MustExec("create table ct (c int, d int, e int, key (c) comment '" + validComment + "')") + tk.MustExec("create index i on ct (d) comment '" + validComment + "'") + tk.MustExec("alter table ct add key (e) comment '" + validComment + "'") + + // test table partition comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (0) COMMENT '" + validComment + "')") + tk.MustExec("ALTER TABLE t ADD PARTITION (PARTITION p1 VALUES LESS THAN (1000000) COMMENT '" + validComment + "')") + + // test table comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustGetErrCode("CREATE TABLE t (c integer) COMMENT = '"+invalidTableComment+"'", errno.ErrTooLongTableComment) + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustGetErrCode("ALTER TABLE t COMMENT = '"+invalidTableComment+"'", errno.ErrTooLongTableComment) + + // test column comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustGetErrCode("CREATE TABLE t (c integer NOT NULL COMMENT '"+invalidComment+"')", errno.ErrTooLongFieldComment) + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustGetErrCode("ALTER TABLE t ADD COLUMN c1 integer COMMENT '"+invalidComment+"'", errno.ErrTooLongFieldComment) + + // test index comment + tk.MustGetErrCode("create table ct1 (c int, key (c) comment '"+invalidComment+"')", errno.ErrTooLongIndexComment) + tk.MustGetErrCode("create index i1 on ct (d) comment '"+invalidComment+"'", errno.ErrTooLongIndexComment) + tk.MustGetErrCode("alter table ct add key (e) comment '"+invalidComment+"'", errno.ErrTooLongIndexComment) + + // test table partition comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustGetErrCode("CREATE TABLE t (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (0) COMMENT '"+invalidComment+"')", errno.ErrTooLongTablePartitionComment) + tk.MustExec("CREATE TABLE t (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (0) COMMENT '" + validComment + "')") + tk.MustGetErrCode("ALTER TABLE t ADD PARTITION (PARTITION p1 VALUES LESS THAN (1000000) COMMENT '"+invalidComment+"')", errno.ErrTooLongTablePartitionComment) + + tk.MustExec("set @@sql_mode=''") + + // test table comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer) COMMENT = '" + invalidTableComment + "'") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1628|Comment for table 't' is too long (max = 2048)")) + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustExec("ALTER TABLE t COMMENT = '" + invalidTableComment + "'") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1628|Comment for table 't' is too long (max = 2048)")) + + // test column comment + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer NOT NULL COMMENT '" + invalidComment + "')") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1629|Comment for field 'c' is too long (max = 1024)")) + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("CREATE TABLE t (c integer)") + tk.MustExec("ALTER TABLE t ADD COLUMN c1 integer COMMENT '" + invalidComment + "'") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1629|Comment for field 'c1' is too long (max = 1024)")) + + // test index comment + tk.MustExec("create table ct1 (c int, d int, e int, key (c) comment '" + invalidComment + "')") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1688|Comment for index 'c' is too long (max = 1024)")) + tk.MustExec("create index i1 on ct1 (d) comment '" + invalidComment + "b" + "'") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1688|Comment for index 'i1' is too long (max = 1024)")) + tk.MustExec("alter table ct1 add key (e) comment '" + invalidComment + "'") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1688|Comment for index 'e' is too long (max = 1024)")) + + tk.MustExec("drop table if exists ct, ct1") +} + func TestRebaseAutoID(t *testing.T) { require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() @@ -697,7 +793,7 @@ func TestProcessColumnFlags(t *testing.T) { tbl := external.GetTableByName(t, tk, "test", "t") for _, col := range tbl.Cols() { if strings.EqualFold(col.Name.L, n) { - require.True(t, f(col.Flag)) + require.True(t, f(col.GetFlag())) break } } @@ -1158,3 +1254,189 @@ func TestCancelJobWriteConflict(t *testing.T) { result := tk2.ResultSetToResultWithCtx(context.Background(), rs[0], "cancel ddl job fails") result.Check(testkit.Rows(fmt.Sprintf("%d successful", jobID))) } + +func TestSnapshotVersion(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + + dd := dom.DDL() + ddl.DisableTiFlashPoll(dd) + require.Equal(t, dbTestLease, dd.GetLease()) + + snapTS := oracle.GoTimeToTS(time.Now()) + tk.MustExec("create database test2") + tk.MustExec("use test2") + tk.MustExec("create table t(a int)") + + is := dom.InfoSchema() + require.NotNil(t, is) + + // For updating the self schema version. + goCtx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + err := dd.SchemaSyncer().OwnerCheckAllVersions(goCtx, is.SchemaMetaVersion()) + cancel() + require.NoError(t, err) + + snapIs, err := dom.GetSnapshotInfoSchema(snapTS) + require.NotNil(t, snapIs) + require.NoError(t, err) + + // Make sure that the self schema version doesn't be changed. + goCtx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond) + err = dd.SchemaSyncer().OwnerCheckAllVersions(goCtx, is.SchemaMetaVersion()) + cancel() + require.NoError(t, err) + + // for GetSnapshotInfoSchema + currSnapTS := oracle.GoTimeToTS(time.Now()) + currSnapIs, err := dom.GetSnapshotInfoSchema(currSnapTS) + require.NoError(t, err) + require.NotNil(t, currSnapTS) + require.Equal(t, is.SchemaMetaVersion(), currSnapIs.SchemaMetaVersion()) + + // for GetSnapshotMeta + dbInfo, ok := currSnapIs.SchemaByName(model.NewCIStr("test2")) + require.True(t, ok) + + tbl, err := currSnapIs.TableByName(model.NewCIStr("test2"), model.NewCIStr("t")) + require.NoError(t, err) + + m, err := dom.GetSnapshotMeta(snapTS) + require.NoError(t, err) + + tblInfo1, err := m.GetTable(dbInfo.ID, tbl.Meta().ID) + require.True(t, meta.ErrDBNotExists.Equal(err)) + require.Nil(t, tblInfo1) + + m, err = dom.GetSnapshotMeta(currSnapTS) + require.NoError(t, err) + + tblInfo2, err := m.GetTable(dbInfo.ID, tbl.Meta().ID) + require.NoError(t, err) + require.Equal(t, tblInfo2, tbl.Meta()) +} + +func TestSchemaValidator(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + + dd := dom.DDL() + ddl.DisableTiFlashPoll(dd) + require.Equal(t, dbTestLease, dd.GetLease()) + + tk.MustExec("create table test.t(a int)") + + err := dom.Reload() + require.NoError(t, err) + schemaVer := dom.InfoSchema().SchemaMetaVersion() + ver, err := store.CurrentVersion(kv.GlobalTxnScope) + require.NoError(t, err) + + ts := ver.Ver + _, res := dom.SchemaValidator.Check(ts, schemaVer, nil) + require.Equal(t, domain.ResultSucc, res) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/ErrorMockReloadFailed", `return(true)`)) + + err = dom.Reload() + require.Error(t, err) + _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) + require.Equal(t, domain.ResultSucc, res) + time.Sleep(dbTestLease) + + ver, err = store.CurrentVersion(kv.GlobalTxnScope) + require.NoError(t, err) + ts = ver.Ver + _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) + require.Equal(t, domain.ResultUnknown, res) + + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/ErrorMockReloadFailed")) + err = dom.Reload() + require.NoError(t, err) + + _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) + require.Equal(t, domain.ResultSucc, res) + + // For schema check, it tests for getting the result of "ResultUnknown". + is := dom.InfoSchema() + schemaChecker := domain.NewSchemaChecker(dom, is.SchemaMetaVersion(), nil) + // Make sure it will retry one time and doesn't take a long time. + domain.SchemaOutOfDateRetryTimes.Store(1) + domain.SchemaOutOfDateRetryInterval.Store(time.Millisecond * 1) + dom.SchemaValidator.Stop() + _, err = schemaChecker.Check(uint64(123456)) + require.EqualError(t, err, domain.ErrInfoSchemaExpired.Error()) +} + +func TestLogAndShowSlowLog(t *testing.T) { + _, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + + dom.LogSlowQuery(&domain.SlowQueryInfo{SQL: "aaa", Duration: time.Second, Internal: true}) + dom.LogSlowQuery(&domain.SlowQueryInfo{SQL: "bbb", Duration: 3 * time.Second}) + dom.LogSlowQuery(&domain.SlowQueryInfo{SQL: "ccc", Duration: 2 * time.Second}) + // Collecting slow queries is asynchronous, wait a while to ensure it's done. + time.Sleep(5 * time.Millisecond) + + result := dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 2}) + require.Len(t, result, 2) + require.Equal(t, "bbb", result[0].SQL) + require.Equal(t, 3*time.Second, result[0].Duration) + require.Equal(t, "ccc", result[1].SQL) + require.Equal(t, 2*time.Second, result[1].Duration) + + result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 2, Kind: ast.ShowSlowKindInternal}) + require.Len(t, result, 1) + require.Equal(t, "aaa", result[0].SQL) + require.Equal(t, time.Second, result[0].Duration) + require.True(t, result[0].Internal) + + result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 4, Kind: ast.ShowSlowKindAll}) + require.Len(t, result, 3) + require.Equal(t, "bbb", result[0].SQL) + require.Equal(t, 3*time.Second, result[0].Duration) + require.Equal(t, "ccc", result[1].SQL) + require.Equal(t, 2*time.Second, result[1].Duration) + require.Equal(t, "aaa", result[2].SQL) + require.Equal(t, time.Second, result[2].Duration) + require.True(t, result[2].Internal) + + result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowRecent, Count: 2}) + require.Len(t, result, 2) + require.Equal(t, "ccc", result[0].SQL) + require.Equal(t, 2*time.Second, result[0].Duration) + require.Equal(t, "bbb", result[1].SQL) + require.Equal(t, 3*time.Second, result[1].Duration) +} + +func TestReportingMinStartTimestamp(t *testing.T) { + _, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + + infoSyncer := dom.InfoSyncer() + sm := &testkit.MockSessionManager{ + PS: make([]*util.ProcessInfo, 0), + } + infoSyncer.SetSessionManager(sm) + beforeTS := oracle.GoTimeToTS(time.Now()) + infoSyncer.ReportMinStartTS(dom.Store()) + afterTS := oracle.GoTimeToTS(time.Now()) + require.False(t, infoSyncer.GetMinStartTS() > beforeTS && infoSyncer.GetMinStartTS() < afterTS) + + now := time.Now() + validTS := oracle.GoTimeToLowerLimitStartTS(now.Add(time.Minute), tikv.MaxTxnTimeUse) + lowerLimit := oracle.GoTimeToLowerLimitStartTS(now, tikv.MaxTxnTimeUse) + sm.PS = []*util.ProcessInfo{ + {CurTxnStartTS: 0}, + {CurTxnStartTS: math.MaxUint64}, + {CurTxnStartTS: lowerLimit}, + {CurTxnStartTS: validTS}, + } + infoSyncer.SetSessionManager(sm) + infoSyncer.ReportMinStartTS(dom.Store()) + require.Equal(t, validTS, infoSyncer.GetMinStartTS()) +} diff --git a/ddl/ddl.go b/ddl/ddl.go index 36474a3ee089e..c825e6935cf87 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -561,29 +561,13 @@ func getJobCheckInterval(job *model.Job, i int) (time.Duration, bool) { } } -// mayNeedReorg indicates that this job may need to reorganize the data. -func mayNeedReorg(job *model.Job) bool { - switch job.Type { - case model.ActionAddIndex, model.ActionAddPrimaryKey: - return true - case model.ActionModifyColumn: - if len(job.CtxVars) > 0 { - needReorg, ok := job.CtxVars[0].(bool) - return ok && needReorg - } - return false - default: - return false - } -} - func (d *ddl) asyncNotifyWorker(job *model.Job) { // If the workers don't run, we needn't notify workers. if !RunWorker { return } var worker *worker - if mayNeedReorg(job) { + if job.MayNeedReorg() { worker = d.workers[addIdxWorker] } else { worker = d.workers[generalWorker] diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 258d7940ac8b0..a7ffbdddd7143 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -28,7 +28,6 @@ import ( "time" "unicode/utf8" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" @@ -58,6 +57,7 @@ import ( "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/domainutil" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tidb/util/set" "github.com/pingcap/tidb/util/sqlexec" @@ -331,7 +331,7 @@ func (d *ddl) ModifySchemaSetTiFlashReplica(sctx sessionctx.Context, stmt *ast.A charsetOk := true // Ban setting replica count for tables which has charset not supported by TiFlash for _, col := range tbl.Cols() { - _, ok := charset.TiFlashSupportedCharsets[col.Charset] + _, ok := charset.TiFlashSupportedCharsets[col.GetCharset()] if !ok { charsetOk = false break @@ -527,10 +527,11 @@ func (d *ddl) DropSchema(ctx sessionctx.Context, schema model.CIStr) (err error) return errors.Trace(infoschema.ErrDatabaseNotExists) } job := &model.Job{ - SchemaID: old.ID, - SchemaName: old.Name.L, - Type: model.ActionDropSchema, - BinlogInfo: &model.HistoryInfo{}, + SchemaID: old.ID, + SchemaName: old.Name.L, + SchemaState: old.State, + Type: model.ActionDropSchema, + BinlogInfo: &model.HistoryInfo{}, } err = d.DoDDLJob(ctx, job) @@ -585,9 +586,9 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra if !ok { continue } - c.Flag |= mysql.PriKeyFlag + c.AddFlag(mysql.PriKeyFlag) // Primary key can not be NULL. - c.Flag |= mysql.NotNullFlag + c.AddFlag(mysql.NotNullFlag) setNoDefaultValueFlag(c, c.DefaultValue != nil) } case ast.ConstraintUniq, ast.ConstraintUniqIndex, ast.ConstraintUniqKey: @@ -605,9 +606,9 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra // the flag should be MultipleKeyFlag. // See https://dev.mysql.com/doc/refman/5.7/en/show-columns.html if len(v.Keys) > 1 { - c.Flag |= mysql.MultipleKeyFlag + c.AddFlag(mysql.MultipleKeyFlag) } else { - c.Flag |= mysql.UniqueKeyFlag + c.AddFlag(mysql.UniqueKeyFlag) } } } @@ -622,7 +623,7 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra } if i == 0 { // Only the first column can be set. - c.Flag |= mysql.MultipleKeyFlag + c.AddFlag(mysql.MultipleKeyFlag) } } } @@ -693,11 +694,11 @@ func ResolveCharsetCollation(charsetOpts ...ast.CharsetOpt) (string, string, err // CREATE TABLE t (a VARCHAR(255) BINARY) CHARSET utf8 COLLATE utf8_general_ci; // The 'BINARY' sets the column collation to *_bin according to the table charset. func OverwriteCollationWithBinaryFlag(colDef *ast.ColumnDef, chs, coll string) (newChs string, newColl string) { - ignoreBinFlag := colDef.Tp.Charset != "" && (colDef.Tp.Collate != "" || containsColumnOption(colDef, ast.ColumnOptionCollate)) + ignoreBinFlag := colDef.Tp.GetCharset() != "" && (colDef.Tp.GetCollate() != "" || containsColumnOption(colDef, ast.ColumnOptionCollate)) if ignoreBinFlag { return chs, coll } - needOverwriteBinColl := types.IsString(colDef.Tp.Tp) && mysql.HasBinaryFlag(colDef.Tp.Flag) + needOverwriteBinColl := types.IsString(colDef.Tp.GetType()) && mysql.HasBinaryFlag(colDef.Tp.GetFlag()) if needOverwriteBinColl { newColl, err := charset.GetDefaultCollation(chs) if err != nil { @@ -720,25 +721,25 @@ func typesNeedCharset(tp byte) bool { func setCharsetCollationFlenDecimal(tp *types.FieldType, colName, colCharset, colCollate string, sessVars *variable.SessionVars) error { var err error - if typesNeedCharset(tp.Tp) { - tp.Charset = colCharset - tp.Collate = colCollate + if typesNeedCharset(tp.GetType()) { + tp.SetCharset(colCharset) + tp.SetCollate(colCollate) } else { - tp.Charset = charset.CharsetBin - tp.Collate = charset.CharsetBin + tp.SetCharset(charset.CharsetBin) + tp.SetCollate(charset.CharsetBin) } // Use default value for flen or decimal when they are unspecified. - defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(tp.Tp) - if tp.Decimal == types.UnspecifiedLength { - tp.Decimal = defaultDecimal + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(tp.GetType()) + if tp.GetDecimal() == types.UnspecifiedLength { + tp.SetDecimal(defaultDecimal) } - if tp.Flen == types.UnspecifiedLength { - tp.Flen = defaultFlen - if mysql.HasUnsignedFlag(tp.Flag) && tp.Tp != mysql.TypeLonglong && mysql.IsIntegerType(tp.Tp) { + if tp.GetFlen() == types.UnspecifiedLength { + tp.SetFlen(defaultFlen) + if mysql.HasUnsignedFlag(tp.GetFlag()) && tp.GetType() != mysql.TypeLonglong && mysql.IsIntegerType(tp.GetType()) { // Issue #4684: the flen of unsigned integer(except bigint) is 1 digit shorter than signed integer // because it has no prefix "+" or "-" character. - tp.Flen-- + tp.SetFlen(tp.GetFlen() - 1) } } else { // Adjust the field type for blob/text types if the flen is set. @@ -794,17 +795,17 @@ func buildColumnAndConstraint( // In NO_ZERO_DATE SQL mode, TIMESTAMP/DATE/DATETIME type can't have zero date like '0000-00-00' or '0000-00-00 00:00:00'. func checkColumnDefaultValue(ctx sessionctx.Context, col *table.Column, value interface{}) (bool, interface{}, error) { hasDefaultValue := true - if value != nil && (col.Tp == mysql.TypeJSON || - col.Tp == mysql.TypeTinyBlob || col.Tp == mysql.TypeMediumBlob || - col.Tp == mysql.TypeLongBlob || col.Tp == mysql.TypeBlob) { + if value != nil && (col.GetType() == mysql.TypeJSON || + col.GetType() == mysql.TypeTinyBlob || col.GetType() == mysql.TypeMediumBlob || + col.GetType() == mysql.TypeLongBlob || col.GetType() == mysql.TypeBlob) { // In non-strict SQL mode. if !ctx.GetSessionVars().SQLMode.HasStrictMode() && value == "" { - if col.Tp == mysql.TypeBlob || col.Tp == mysql.TypeLongBlob { + if col.GetType() == mysql.TypeBlob || col.GetType() == mysql.TypeLongBlob { // The TEXT/BLOB default value can be ignored. hasDefaultValue = false } // In non-strict SQL mode, if the column type is json and the default value is null, it is initialized to an empty array. - if col.Tp == mysql.TypeJSON { + if col.GetType() == mysql.TypeJSON { value = `null` } sc := ctx.GetSessionVars().StmtCtx @@ -815,9 +816,9 @@ func checkColumnDefaultValue(ctx sessionctx.Context, col *table.Column, value in return hasDefaultValue, value, dbterror.ErrBlobCantHaveDefault.GenWithStackByArgs(col.Name.O) } if value != nil && ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() && - ctx.GetSessionVars().SQLMode.HasStrictMode() && types.IsTypeTime(col.Tp) { + ctx.GetSessionVars().SQLMode.HasStrictMode() && types.IsTypeTime(col.GetType()) { if vv, ok := value.(string); ok { - timeValue, err := expression.GetTimeValue(ctx, vv, col.Tp, col.Decimal) + timeValue, err := expression.GetTimeValue(ctx, vv, col.GetType(), col.GetDecimal()) if err != nil { return hasDefaultValue, value, errors.Trace(err) } @@ -830,19 +831,19 @@ func checkColumnDefaultValue(ctx sessionctx.Context, col *table.Column, value in } func checkSequenceDefaultValue(col *table.Column) error { - if mysql.IsIntegerType(col.Tp) { + if mysql.IsIntegerType(col.GetType()) { return nil } return dbterror.ErrColumnTypeUnsupportedNextValue.GenWithStackByArgs(col.ColumnInfo.Name.O) } func convertTimestampDefaultValToUTC(ctx sessionctx.Context, defaultVal interface{}, col *table.Column) (interface{}, error) { - if defaultVal == nil || col.Tp != mysql.TypeTimestamp { + if defaultVal == nil || col.GetType() != mysql.TypeTimestamp { return defaultVal, nil } if vv, ok := defaultVal.(string); ok { if vv != types.ZeroDatetimeStr && !strings.EqualFold(vv, ast.CurrentTimestamp) { - t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.Tp, col.Decimal) + t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.GetType(), col.GetDecimal()) if err != nil { return defaultVal, errors.Trace(err) } @@ -867,28 +868,28 @@ func isExplicitTimeStamp() bool { // processColumnFlags is used by columnDefToCol and processColumnOptions. It is intended to unify behaviors on `create/add` and `modify/change` statements. Check tidb#issue#19342. func processColumnFlags(col *table.Column) { if col.FieldType.EvalType().IsStringKind() { - if col.Charset == charset.CharsetBin { - col.Flag |= mysql.BinaryFlag + if col.GetCharset() == charset.CharsetBin { + col.AddFlag(mysql.BinaryFlag) } else { - col.Flag &= ^mysql.BinaryFlag + col.DelFlag(mysql.BinaryFlag) } } - if col.Tp == mysql.TypeBit { + if col.GetType() == mysql.TypeBit { // For BIT field, it's charset is binary but does not have binary flag. - col.Flag &= ^mysql.BinaryFlag - col.Flag |= mysql.UnsignedFlag + col.DelFlag(mysql.BinaryFlag) + col.AddFlag(mysql.UnsignedFlag) } - if col.Tp == mysql.TypeYear { + if col.GetType() == mysql.TypeYear { // For Year field, it's charset is binary but does not have binary flag. - col.Flag &= ^mysql.BinaryFlag - col.Flag |= mysql.ZerofillFlag + col.DelFlag(mysql.BinaryFlag) + col.AddFlag(mysql.ZerofillFlag) } // If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to the column. // See https://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html for more details. // But some types like bit and year, won't show its unsigned flag in `show create table`. - if mysql.HasZerofillFlag(col.Flag) { - col.Flag |= mysql.UnsignedFlag + if mysql.HasZerofillFlag(col.GetFlag()) { + col.AddFlag(mysql.UnsignedFlag) } } @@ -898,22 +899,22 @@ func adjustBlobTypesFlen(tp *types.FieldType, colCharset string) error { if err != nil { return err } - l := tp.Flen * cs.Maxlen - if tp.Tp == mysql.TypeBlob { + l := tp.GetFlen() * cs.Maxlen + if tp.GetType() == mysql.TypeBlob { if l <= tinyBlobMaxLength { - logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to TINYBLOB", tp.Flen)) - tp.Flen = tinyBlobMaxLength - tp.Tp = mysql.TypeTinyBlob + logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to TINYBLOB", tp.GetFlen())) + tp.SetFlen(tinyBlobMaxLength) + tp.SetType(mysql.TypeTinyBlob) } else if l <= blobMaxLength { - tp.Flen = blobMaxLength + tp.SetFlen(blobMaxLength) } else if l <= mediumBlobMaxLength { - logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to MEDIUMBLOB", tp.Flen)) - tp.Flen = mediumBlobMaxLength - tp.Tp = mysql.TypeMediumBlob + logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to MEDIUMBLOB", tp.GetFlen())) + tp.SetFlen(mediumBlobMaxLength) + tp.SetType(mysql.TypeMediumBlob) } else if l <= longBlobMaxLength { - logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to LONGBLOB", tp.Flen)) - tp.Flen = longBlobMaxLength - tp.Tp = mysql.TypeLongBlob + logutil.BgLogger().Info(fmt.Sprintf("Automatically convert BLOB(%d) to LONGBLOB", tp.GetFlen())) + tp.SetFlen(longBlobMaxLength) + tp.SetType(mysql.TypeLongBlob) } } return nil @@ -933,10 +934,8 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o if !isExplicitTimeStamp() { // Check and set TimestampFlag, OnUpdateNowFlag and NotNullFlag. - if col.Tp == mysql.TypeTimestamp { - col.Flag |= mysql.TimestampFlag - col.Flag |= mysql.OnUpdateNowFlag - col.Flag |= mysql.NotNullFlag + if col.GetType() == mysql.TypeTimestamp { + col.AddFlag(mysql.TimestampFlag | mysql.OnUpdateNowFlag | mysql.NotNullFlag) } } var err error @@ -961,30 +960,29 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o for _, v := range colDef.Options { switch v.Tp { case ast.ColumnOptionNotNull: - col.Flag |= mysql.NotNullFlag + col.AddFlag(mysql.NotNullFlag) case ast.ColumnOptionNull: - col.Flag &= ^mysql.NotNullFlag + col.DelFlag(mysql.NotNullFlag) removeOnUpdateNowFlag(col) hasNullFlag = true case ast.ColumnOptionAutoIncrement: - col.Flag |= mysql.AutoIncrementFlag - col.Flag |= mysql.NotNullFlag + col.AddFlag(mysql.AutoIncrementFlag | mysql.NotNullFlag) case ast.ColumnOptionPrimaryKey: // Check PriKeyFlag first to avoid extra duplicate constraints. - if col.Flag&mysql.PriKeyFlag == 0 { + if col.GetFlag()&mysql.PriKeyFlag == 0 { constraint := &ast.Constraint{Tp: ast.ConstraintPrimaryKey, Keys: keys, Option: &ast.IndexOption{PrimaryKeyTp: v.PrimaryKeyTp}} constraints = append(constraints, constraint) - col.Flag |= mysql.PriKeyFlag + col.AddFlag(mysql.PriKeyFlag) // Add NotNullFlag early so that processColumnFlags() can see it. - col.Flag |= mysql.NotNullFlag + col.AddFlag(mysql.NotNullFlag) } case ast.ColumnOptionUniqKey: // Check UniqueFlag first to avoid extra duplicate constraints. - if col.Flag&mysql.UniqueFlag == 0 { + if col.GetFlag()&mysql.UniqueFlag == 0 { constraint := &ast.Constraint{Tp: ast.ConstraintUniqKey, Keys: keys} constraints = append(constraints, constraint) - col.Flag |= mysql.UniqueKeyFlag + col.AddFlag(mysql.UniqueKeyFlag) } case ast.ColumnOptionDefaultValue: hasDefaultValue, err = setDefaultValue(ctx, col, v) @@ -994,14 +992,14 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o removeOnUpdateNowFlag(col) case ast.ColumnOptionOnUpdate: // TODO: Support other time functions. - if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { + if col.GetType() == mysql.TypeTimestamp || col.GetType() == mysql.TypeDatetime { if !expression.IsValidCurrentTimestampExpr(v.Expr, colDef.Tp) { return nil, nil, dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { return nil, nil, dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } - col.Flag |= mysql.OnUpdateNowFlag + col.AddFlag(mysql.OnUpdateNowFlag) setOnUpdateNow = true case ast.ColumnOptionComment: err := setColumnComment(ctx, col, v) @@ -1020,7 +1018,7 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o col.Dependences = dependColNames case ast.ColumnOptionCollate: if field_types.HasCharset(colDef.Tp) { - col.FieldType.Collate = v.StrValue + col.FieldType.SetCollate(v.StrValue) } case ast.ColumnOptionFulltext: ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrTableCantHandleFt.GenWithStackByArgs()) @@ -1040,7 +1038,7 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o func getFuncCallDefaultValue(col *table.Column, option *ast.ColumnOption, expr *ast.FuncCallExpr) (interface{}, bool, error) { switch expr.FnName.L { case ast.CurrentTimestamp: - tp, fsp := col.FieldType.Tp, col.FieldType.Decimal + tp, fsp := col.FieldType.GetType(), col.FieldType.GetDecimal() if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { defaultFsp := 0 if len(expr.Args) == 1 { @@ -1083,7 +1081,7 @@ func getFuncCallDefaultValue(col *table.Column, option *ast.ColumnOption, expr * // 2: get specific default value for the other column. func getDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.ColumnOption) (interface{}, bool, error) { // handle default value with function call - tp, fsp := col.FieldType.Tp, col.FieldType.Decimal + tp, fsp := col.FieldType.GetType(), col.FieldType.GetDecimal() if x, ok := option.Expr.(*ast.FuncCallExpr); ok { val, isSeqExpr, err := getFuncCallDefaultValue(col, option, x) if val != nil || isSeqExpr || err != nil { @@ -1131,7 +1129,7 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.Colu if tp == mysql.TypeBit || tp == mysql.TypeString || tp == mysql.TypeVarchar || tp == mysql.TypeVarString || tp == mysql.TypeEnum || tp == mysql.TypeSet { // For BinaryLiteral or bit fields, we decode the default value to utf8 string. - str, err := v.GetBinaryStringDecoded(nil, col.Charset) + str, err := v.GetBinaryStringDecoded(nil, col.GetCharset()) if err != nil { // Overwrite the decoding error with invalid default value error. err = dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) @@ -1182,17 +1180,17 @@ func getSequenceDefaultValue(c *ast.ColumnOption) (expr string, err error) { // getSetDefaultValue gets the default value for the set type. See https://dev.mysql.com/doc/refman/5.7/en/set.html. func getSetDefaultValue(v types.Datum, col *table.Column) (string, error) { if v.Kind() == types.KindInt64 { - setCnt := len(col.Elems) + setCnt := len(col.GetElems()) maxLimit := int64(1< maxLimit { return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } - setVal, err := types.ParseSetValue(col.Elems, uint64(val)) + setVal, err := types.ParseSetValue(col.GetElems(), uint64(val)) if err != nil { return "", errors.Trace(err) } - v.SetMysqlSet(setVal, col.Collate) + v.SetMysqlSet(setVal, col.GetCollate()) return v.ToString() } @@ -1203,11 +1201,11 @@ func getSetDefaultValue(v types.Datum, col *table.Column) (string, error) { if str == "" { return str, nil } - setVal, err := types.ParseSetName(col.Elems, str, col.Collate) + setVal, err := types.ParseSetName(col.GetElems(), str, col.GetCollate()) if err != nil { return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } - v.SetMysqlSet(setVal, col.Collate) + v.SetMysqlSet(setVal, col.GetCollate()) return v.ToString() } @@ -1216,14 +1214,14 @@ func getSetDefaultValue(v types.Datum, col *table.Column) (string, error) { func getEnumDefaultValue(v types.Datum, col *table.Column) (string, error) { if v.Kind() == types.KindInt64 { val := v.GetInt64() - if val < 1 || val > int64(len(col.Elems)) { + if val < 1 || val > int64(len(col.GetElems())) { return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } - enumVal, err := types.ParseEnumValue(col.Elems, uint64(val)) + enumVal, err := types.ParseEnumValue(col.GetElems(), uint64(val)) if err != nil { return "", errors.Trace(err) } - v.SetMysqlEnum(enumVal, col.Collate) + v.SetMysqlEnum(enumVal, col.GetCollate()) return v.ToString() } str, err := v.ToString() @@ -1233,11 +1231,11 @@ func getEnumDefaultValue(v types.Datum, col *table.Column) (string, error) { // Ref: https://dev.mysql.com/doc/refman/8.0/en/enum.html // Trailing spaces are automatically deleted from ENUM member values in the table definition when a table is created. str = strings.TrimRight(str, " ") - enumVal, err := types.ParseEnumName(col.Elems, str, col.Collate) + enumVal, err := types.ParseEnumName(col.GetElems(), str, col.GetCollate()) if err != nil { return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } - v.SetMysqlEnum(enumVal, col.Collate) + v.SetMysqlEnum(enumVal, col.GetCollate()) return v.ToString() } @@ -1245,8 +1243,8 @@ func getEnumDefaultValue(v types.Datum, col *table.Column) (string, error) { func removeOnUpdateNowFlag(c *table.Column) { // For timestamp Col, if it is set null or default value, // OnUpdateNowFlag should be removed. - if mysql.HasTimestampFlag(c.Flag) { - c.Flag &= ^mysql.OnUpdateNowFlag + if mysql.HasTimestampFlag(c.GetFlag()) { + c.DelFlag(mysql.OnUpdateNowFlag) } } @@ -1265,7 +1263,7 @@ func setYearDefaultValue(c *table.Column, hasDefaultValue bool) { return } - if c.Tp == mysql.TypeYear && mysql.HasNotNullFlag(c.Flag) { + if c.GetType() == mysql.TypeYear && mysql.HasNotNullFlag(c.GetFlag()) { if err := c.SetDefaultValue("0000"); err != nil { logutil.BgLogger().Error("set default value failed", zap.Error(err)) } @@ -1278,7 +1276,7 @@ func setTimestampDefaultValue(c *table.Column, hasDefaultValue bool, setOnUpdate } // For timestamp Col, if is not set default value or not set null, use current timestamp. - if mysql.HasTimestampFlag(c.Flag) && mysql.HasNotNullFlag(c.Flag) { + if mysql.HasTimestampFlag(c.GetFlag()) && mysql.HasNotNullFlag(c.GetFlag()) { if setOnUpdateNow { if err := c.SetDefaultValue(types.ZeroDatetimeStr); err != nil { logutil.BgLogger().Error("set default value failed", zap.Error(err)) @@ -1296,13 +1294,13 @@ func setNoDefaultValueFlag(c *table.Column, hasDefaultValue bool) { return } - if !mysql.HasNotNullFlag(c.Flag) { + if !mysql.HasNotNullFlag(c.GetFlag()) { return } // Check if it is an `AUTO_INCREMENT` field or `TIMESTAMP` field. - if !mysql.HasAutoIncrementFlag(c.Flag) && !mysql.HasTimestampFlag(c.Flag) { - c.Flag |= mysql.NoDefaultValueFlag + if !mysql.HasAutoIncrementFlag(c.GetFlag()) && !mysql.HasTimestampFlag(c.GetFlag()) { + c.AddFlag(mysql.NoDefaultValueFlag) } } @@ -1321,12 +1319,12 @@ func checkDefaultValue(ctx sessionctx.Context, c *table.Column, hasDefaultValue return nil } // Primary key default null is invalid. - if mysql.HasPriKeyFlag(c.Flag) { + if mysql.HasPriKeyFlag(c.GetFlag()) { return dbterror.ErrPrimaryCantHaveNull } // Set not null but default null is invalid. - if mysql.HasNotNullFlag(c.Flag) { + if mysql.HasNotNullFlag(c.GetFlag()) { return types.ErrInvalidDefault.GenWithStackByArgs(c.Name) } @@ -1336,40 +1334,40 @@ func checkDefaultValue(ctx sessionctx.Context, c *table.Column, hasDefaultValue // checkPriKeyConstraint check all parts of a PRIMARY KEY must be NOT NULL func checkPriKeyConstraint(col *table.Column, hasDefaultValue, hasNullFlag bool, outPriKeyConstraint *ast.Constraint) error { // Primary key should not be null. - if mysql.HasPriKeyFlag(col.Flag) && hasDefaultValue && col.GetDefaultValue() == nil { + if mysql.HasPriKeyFlag(col.GetFlag()) && hasDefaultValue && col.GetDefaultValue() == nil { return types.ErrInvalidDefault.GenWithStackByArgs(col.Name) } // Set primary key flag for outer primary key constraint. // Such as: create table t1 (id int , age int, primary key(id)) - if !mysql.HasPriKeyFlag(col.Flag) && outPriKeyConstraint != nil { + if !mysql.HasPriKeyFlag(col.GetFlag()) && outPriKeyConstraint != nil { for _, key := range outPriKeyConstraint.Keys { if key.Expr == nil && key.Column.Name.L != col.Name.L { continue } - col.Flag |= mysql.PriKeyFlag + col.AddFlag(mysql.PriKeyFlag) break } } // Primary key should not be null. - if mysql.HasPriKeyFlag(col.Flag) && hasNullFlag { + if mysql.HasPriKeyFlag(col.GetFlag()) && hasNullFlag { return dbterror.ErrPrimaryCantHaveNull } return nil } func checkColumnValueConstraint(col *table.Column, collation string) error { - if col.Tp != mysql.TypeEnum && col.Tp != mysql.TypeSet { + if col.GetType() != mysql.TypeEnum && col.GetType() != mysql.TypeSet { return nil } - valueMap := make(map[string]bool, len(col.Elems)) + valueMap := make(map[string]bool, len(col.GetElems())) ctor := collate.GetCollator(collation) enumLengthLimit := config.GetGlobalConfig().EnableEnumLengthLimit - desc, err := charset.GetCharsetInfo(col.Charset) + desc, err := charset.GetCharsetInfo(col.GetCharset()) if err != nil { return errors.Trace(err) } - for i := range col.Elems { - val := string(ctor.Key(col.Elems[i])) + for i := range col.GetElems() { + val := string(ctor.Key(col.GetElems()[i])) // According to MySQL 8.0 Refman: // The maximum supported length of an individual ENUM element is M <= 255 and (M x w) <= 1020, // where M is the element literal length and w is the number of bytes required for the maximum-length character in the character set. @@ -1379,10 +1377,10 @@ func checkColumnValueConstraint(col *table.Column, collation string) error { } if _, ok := valueMap[val]; ok { tpStr := "ENUM" - if col.Tp == mysql.TypeSet { + if col.GetType() == mysql.TypeSet { tpStr = "SET" } - return types.ErrDuplicatedValueInType.GenWithStackByArgs(col.Name, col.Elems[i], tpStr) + return types.ErrDuplicatedValueInType.GenWithStackByArgs(col.Name, col.GetElems()[i], tpStr) } valueMap[val] = true } @@ -1500,8 +1498,8 @@ func checkColumnsAttributes(colDefs []*model.ColumnInfo) error { } func checkColumnFieldLength(col *table.Column) error { - if col.Tp == mysql.TypeVarchar { - if err := IsTooBigFieldLength(col.Flen, col.Name.O, col.Charset); err != nil { + if col.GetType() == mysql.TypeVarchar { + if err := IsTooBigFieldLength(col.GetFlen(), col.Name.O, col.GetCharset()); err != nil { return errors.Trace(err) } } @@ -1525,14 +1523,14 @@ func IsTooBigFieldLength(colDefTpFlen int, colDefName, setCharset string) error // checkColumnAttributes check attributes for single column. func checkColumnAttributes(colName string, tp *types.FieldType) error { - switch tp.Tp { + switch tp.GetType() { case mysql.TypeNewDecimal, mysql.TypeDouble, mysql.TypeFloat: - if tp.Flen < tp.Decimal { + if tp.GetFlen() < tp.GetDecimal() { return types.ErrMBiggerThanD.GenWithStackByArgs(colName) } case mysql.TypeDatetime, mysql.TypeDuration, mysql.TypeTimestamp: - if tp.Decimal != types.UnspecifiedFsp && (tp.Decimal < types.MinFsp || tp.Decimal > types.MaxFsp) { - return types.ErrTooBigPrecision.GenWithStackByArgs(tp.Decimal, colName, types.MaxFsp) + if tp.GetDecimal() != types.UnspecifiedFsp && (tp.GetDecimal() < types.MinFsp || tp.GetDecimal() > types.MaxFsp) { + return types.ErrTooBigPrecision.GenWithStackByArgs(tp.GetDecimal(), colName, types.MaxFsp) } } return nil @@ -1662,7 +1660,7 @@ func getPrimaryKey(tblInfo *model.TableInfo) *model.IndexInfo { skip = true break } - if !mysql.HasNotNullFlag(col.Flag) { + if !mysql.HasNotNullFlag(col.GetFlag()) { allColNotNull = false break } @@ -1682,9 +1680,9 @@ func setTableAutoRandomBits(ctx sessionctx.Context, tbInfo *model.TableInfo, col pkColName := tbInfo.GetPkName() for _, col := range colDefs { if containsColumnOption(col, ast.ColumnOptionAutoRandom) { - if col.Tp.Tp != mysql.TypeLonglong { + if col.Tp.GetType() != mysql.TypeLonglong { return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs( - fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(col.Tp.Tp))) + fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(col.Tp.GetType()))) } if !tbInfo.PKIsHandle || col.Name.Name.L != pkColName.L { errMsg := fmt.Sprintf(autoid.AutoRandomPKisNotHandleErrMsg, col.Name.Name.O) @@ -1841,7 +1839,7 @@ func buildTableInfo( } // set index type. if constr.Option != nil { - idxInfo.Comment, err = validateCommentLength(ctx.GetSessionVars(), idxInfo.Name.String(), constr.Option) + idxInfo.Comment, err = validateCommentLength(ctx.GetSessionVars(), idxInfo.Name.String(), &constr.Option.Comment, dbterror.ErrTooLongIndexComment) if err != nil { return nil, errors.Trace(err) } @@ -1886,7 +1884,7 @@ func isSingleIntPK(constr *ast.Constraint, lastCol *model.ColumnInfo) bool { if len(constr.Keys) != 1 { return false } - switch lastCol.Tp { + switch lastCol.GetType() { case mysql.TypeLong, mysql.TypeLonglong, mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24: return true @@ -2137,6 +2135,10 @@ func buildTableInfoWithStmt(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCh return nil, errors.Trace(err) } + if _, err = validateCommentLength(ctx.GetSessionVars(), tbInfo.Name.L, &tbInfo.Comment, dbterror.ErrTooLongTableComment); err != nil { + return nil, errors.Trace(err) + } + if tbInfo.TempTableType == model.TempTableNone && tbInfo.PlacementPolicyRef == nil && placementPolicyRef != nil { // Set the defaults from Schema. Note: they are mutual exclusive! tbInfo.PlacementPolicyRef = placementPolicyRef @@ -2659,7 +2661,7 @@ func checkColumnsPartitionType(tbInfo *model.TableInfo) error { // DATE and DATETIME // CHAR, VARCHAR, BINARY, and VARBINARY // See https://dev.mysql.com/doc/mysql-partitioning-excerpt/5.7/en/partitioning-columns.html - switch colInfo.FieldType.Tp { + switch colInfo.FieldType.GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeDuration: case mysql.TypeVarchar, mysql.TypeString: @@ -2737,11 +2739,11 @@ func parseAndEvalBoolExpr(ctx sessionctx.Context, l, r string, colInfo *model.Co if err != nil { return false, err } - e, err := expression.NewFunctionBase(ctx, ast.GT, types.NewFieldType(mysql.TypeLonglong), lexpr, rexpr) + e, err := expression.NewFunctionBase(ctx, ast.GT, field_types.NewFieldType(mysql.TypeLonglong), lexpr, rexpr) if err != nil { return false, err } - e.SetCharsetAndCollation(colInfo.Charset, colInfo.Collate) + e.SetCharsetAndCollation(colInfo.GetCharset(), colInfo.GetCollate()) res, _, err1 := e.EvalInt(ctx, chunk.Row{}) if err1 != nil { return false, err1 @@ -2869,8 +2871,8 @@ func isIgnorableSpec(tp ast.AlterTableType) bool { // getCharsetAndCollateInColumnDef will iterate collate in the options, validate it by checking the charset // of column definition. If there's no collate in the option, the default collate of column's charset will be used. func getCharsetAndCollateInColumnDef(def *ast.ColumnDef) (chs, coll string, err error) { - chs = def.Tp.Charset - coll = def.Tp.Collate + chs = def.Tp.GetCharset() + coll = def.Tp.GetCollate() if chs != "" && coll == "" { if coll, err = charset.GetDefaultCollation(chs); err != nil { return "", "", errors.Trace(err) @@ -3256,7 +3258,7 @@ func (d *ddl) RebaseAutoID(ctx sessionctx.Context, ident ast.Ident, newBase int6 } var autoRandColTp types.FieldType for _, c := range tbInfo.Columns { - if mysql.HasPriKeyFlag(c.Flag) { + if mysql.HasPriKeyFlag(c.GetFlag()) { autoRandColTp = c.FieldType break } @@ -3312,7 +3314,7 @@ func adjustNewBaseToNextGlobalID(ctx sessionctx.Context, t table.Table, tp autoi // If the user sends SQL `alter table t1 auto_increment = 100` to TiDB-B, // and TiDB-B finds 100 < 30001 but returns without any handling, // then TiDB-A may still allocate 99 for auto_increment column. This doesn't make sense for the user. - return int64(mathutil.MaxUint64(uint64(newBase), uint64(autoID))), nil + return int64(mathutil.Max(uint64(newBase), uint64(autoID))), nil } // ShardRowID shards the implicit row ID by adding shard value to the row ID's first few bits. @@ -3787,13 +3789,14 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec * } job := &model.Job{ - SchemaID: schema.ID, - TableID: meta.ID, - SchemaName: schema.Name.L, - TableName: meta.Name.L, - Type: model.ActionDropTablePartition, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{partNames}, + SchemaID: schema.ID, + TableID: meta.ID, + SchemaName: schema.Name.L, + SchemaState: model.StatePublic, + TableName: meta.Name.L, + Type: model.ActionDropTablePartition, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{partNames}, } err = d.DoDDLJob(ctx, job) @@ -3810,22 +3813,22 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec * func checkFieldTypeCompatible(ft *types.FieldType, other *types.FieldType) bool { // int(1) could match the type with int(8) - partialEqual := ft.Tp == other.Tp && - ft.Decimal == other.Decimal && - ft.Charset == other.Charset && - ft.Collate == other.Collate && - (ft.Flen == other.Flen || ft.StorageLength() != types.VarStorageLen) && - mysql.HasUnsignedFlag(ft.Flag) == mysql.HasUnsignedFlag(other.Flag) && - mysql.HasAutoIncrementFlag(ft.Flag) == mysql.HasAutoIncrementFlag(other.Flag) && - mysql.HasNotNullFlag(ft.Flag) == mysql.HasNotNullFlag(other.Flag) && - mysql.HasZerofillFlag(ft.Flag) == mysql.HasZerofillFlag(other.Flag) && - mysql.HasBinaryFlag(ft.Flag) == mysql.HasBinaryFlag(other.Flag) && - mysql.HasPriKeyFlag(ft.Flag) == mysql.HasPriKeyFlag(other.Flag) - if !partialEqual || len(ft.Elems) != len(other.Elems) { + partialEqual := ft.GetType() == other.GetType() && + ft.GetDecimal() == other.GetDecimal() && + ft.GetCharset() == other.GetCharset() && + ft.GetCollate() == other.GetCollate() && + (ft.GetFlen() == other.GetFlen() || ft.StorageLength() != types.VarStorageLen) && + mysql.HasUnsignedFlag(ft.GetFlag()) == mysql.HasUnsignedFlag(other.GetFlag()) && + mysql.HasAutoIncrementFlag(ft.GetFlag()) == mysql.HasAutoIncrementFlag(other.GetFlag()) && + mysql.HasNotNullFlag(ft.GetFlag()) == mysql.HasNotNullFlag(other.GetFlag()) && + mysql.HasZerofillFlag(ft.GetFlag()) == mysql.HasZerofillFlag(other.GetFlag()) && + mysql.HasBinaryFlag(ft.GetFlag()) == mysql.HasBinaryFlag(other.GetFlag()) && + mysql.HasPriKeyFlag(ft.GetFlag()) == mysql.HasPriKeyFlag(other.GetFlag()) + if !partialEqual || len(ft.GetElems()) != len(other.GetElems()) { return false } - for i := range ft.Elems { - if ft.Elems[i] != other.Elems[i] { + for i := range ft.GetElems() { + if ft.GetElems()[i] != other.GetElems()[i] { return false } } @@ -4032,6 +4035,7 @@ func (d *ddl) DropColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTa Type: model.ActionDropColumn, BinlogInfo: &model.HistoryInfo{}, MultiSchemaInfo: multiSchemaInfo, + SchemaState: model.StatePublic, Args: []interface{}{colName}, } @@ -4198,16 +4202,16 @@ func checkModifyTypes(ctx sessionctx.Context, origin *types.FieldType, to *types if !canReorg { return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(err.Error())) } - if mysql.HasPriKeyFlag(origin.Flag) { + if mysql.HasPriKeyFlag(origin.GetFlag()) { msg := "this column has primary key flag" return dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) } } - err = checkModifyCharsetAndCollation(to.Charset, to.Collate, origin.Charset, origin.Collate, needRewriteCollationData) + err = checkModifyCharsetAndCollation(to.GetCharset(), to.GetCollate(), origin.GetCharset(), origin.GetCollate(), needRewriteCollationData) if err != nil { - if to.Charset == charset.CharsetGBK || origin.Charset == charset.CharsetGBK { + if to.GetCharset() == charset.CharsetGBK || origin.GetCharset() == charset.CharsetGBK { return errors.Trace(err) } // column type change can handle the charset change between these two types in the process of the reorg. @@ -4253,8 +4257,8 @@ func setDefaultValueWithBinaryPadding(col *table.Column, value interface{}) erro // https://dev.mysql.com/doc/refman/8.0/en/binary-varbinary.html // Set the default value for binary type should append the paddings. if value != nil { - if col.Tp == mysql.TypeString && types.IsBinaryStr(&col.FieldType) && len(value.(string)) < col.Flen { - padding := make([]byte, col.Flen-len(value.(string))) + if col.GetType() == mysql.TypeString && types.IsBinaryStr(&col.FieldType) && len(value.(string)) < col.GetFlen() { + padding := make([]byte, col.GetFlen()-len(value.(string))) col.DefaultValue = string(append([]byte(col.DefaultValue.(string)), padding...)) } } @@ -4266,7 +4270,10 @@ func setColumnComment(ctx sessionctx.Context, col *table.Column, option *ast.Col if err != nil { return errors.Trace(err) } - col.Comment, err = value.ToString() + if col.Comment, err = value.ToString(); err != nil { + return errors.Trace(err) + } + col.Comment, err = validateCommentLength(ctx.GetSessionVars(), col.Name.L, &col.Comment, dbterror.ErrTooLongFieldComment) return errors.Trace(err) } @@ -4293,24 +4300,24 @@ func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []* return errors.Trace(err) } case ast.ColumnOptionNotNull: - col.Flag |= mysql.NotNullFlag + col.AddFlag(mysql.NotNullFlag) case ast.ColumnOptionNull: hasNullFlag = true - col.Flag &= ^mysql.NotNullFlag + col.DelFlag(mysql.NotNullFlag) case ast.ColumnOptionAutoIncrement: - col.Flag |= mysql.AutoIncrementFlag + col.AddFlag(mysql.AutoIncrementFlag) case ast.ColumnOptionPrimaryKey, ast.ColumnOptionUniqKey: return dbterror.ErrUnsupportedModifyColumn.GenWithStack("can't change column constraint - %v", opt.Tp) case ast.ColumnOptionOnUpdate: // TODO: Support other time functions. - if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { + if col.GetType() == mysql.TypeTimestamp || col.GetType() == mysql.TypeDatetime { if !expression.IsValidCurrentTimestampExpr(opt.Expr, &col.FieldType) { return dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { return dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } - col.Flag |= mysql.OnUpdateNowFlag + col.AddFlag(mysql.OnUpdateNowFlag) setOnUpdateNow = true case ast.ColumnOptionGenerated: sb.Reset() @@ -4326,7 +4333,7 @@ func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []* col.Dependences[colName.Name.L] = struct{}{} } case ast.ColumnOptionCollate: - col.Collate = opt.StrValue + col.SetCollate(opt.StrValue) case ast.ColumnOptionReference: return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't modify with references")) case ast.ColumnOptionFulltext: @@ -4355,7 +4362,7 @@ func processAndCheckDefaultValueAndColumn(ctx sessionctx.Context, col *table.Col if err != nil { return errors.Trace(err) } - if err = checkColumnValueConstraint(col, col.Collate); err != nil { + if err = checkColumnValueConstraint(col, col.GetCollate()); err != nil { return errors.Trace(err) } if err = checkDefaultValue(ctx, col, hasDefaultValue); err != nil { @@ -4429,9 +4436,9 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex // TODO: Remove it when all table versions are greater than or equal to TableInfoVersion1. // If newCol's charset is empty and the table's version less than TableInfoVersion1, // we will not modify the charset of the column. This behavior is not compatible with MySQL. - if len(newCol.FieldType.Charset) == 0 && t.Meta().Version < model.TableInfoVersion1 { - chs = col.FieldType.Charset - coll = col.FieldType.Collate + if len(newCol.FieldType.GetCharset()) == 0 && t.Meta().Version < model.TableInfoVersion1 { + chs = col.FieldType.GetCharset() + coll = col.FieldType.GetCollate() } else { chs, coll, err = getCharsetAndCollateInColumnDef(specNewColumn) if err != nil { @@ -4456,16 +4463,16 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex if fkInfo := getColumnForeignKeyInfo(originalColName.L, t.Meta().ForeignKeys); fkInfo != nil { // For now we strongly ban the all column type change for column with foreign key. // Actually MySQL support change column with foreign key from varchar(m) -> varchar(m+t) and t > 0. - if newCol.Tp != col.Tp || newCol.Flen != col.Flen || newCol.Decimal != col.Decimal { + if newCol.GetType() != col.GetType() || newCol.GetFlen() != col.GetFlen() || newCol.GetDecimal() != col.GetDecimal() { return nil, dbterror.ErrFKIncompatibleColumns.GenWithStackByArgs(originalColName, fkInfo.Name) } } // Copy index related options to the new spec. - indexFlags := col.FieldType.Flag & (mysql.PriKeyFlag | mysql.UniqueKeyFlag | mysql.MultipleKeyFlag) - newCol.FieldType.Flag |= indexFlags - if mysql.HasPriKeyFlag(col.FieldType.Flag) { - newCol.FieldType.Flag |= mysql.NotNullFlag + indexFlags := col.FieldType.GetFlag() & (mysql.PriKeyFlag | mysql.UniqueKeyFlag | mysql.MultipleKeyFlag) + newCol.FieldType.AddFlag(indexFlags) + if mysql.HasPriKeyFlag(col.FieldType.GetFlag()) { + newCol.FieldType.AddFlag(mysql.NotNullFlag) // TODO: If user explicitly set NULL, we should throw error ErrPrimaryCantHaveNull. } @@ -4476,7 +4483,7 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex if err = checkModifyTypes(sctx, &col.FieldType, &newCol.FieldType, isColumnWithIndex(col.Name.L, t.Meta().Indices)); err != nil { if strings.Contains(err.Error(), "Unsupported modifying collation") { colErrMsg := "Unsupported modifying collation of column '%s' from '%s' to '%s' when index is defined on it." - err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, newCol.Collate) + err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.GetCollate(), newCol.GetCollate()) } return nil, errors.Trace(err) } @@ -4491,17 +4498,17 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex } // We don't support modifying column from not_auto_increment to auto_increment. - if !mysql.HasAutoIncrementFlag(col.Flag) && mysql.HasAutoIncrementFlag(newCol.Flag) { + if !mysql.HasAutoIncrementFlag(col.GetFlag()) && mysql.HasAutoIncrementFlag(newCol.GetFlag()) { return nil, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't set auto_increment") } // Disallow modifying column from auto_increment to not auto_increment if the session variable `AllowRemoveAutoInc` is false. - if !sctx.GetSessionVars().AllowRemoveAutoInc && mysql.HasAutoIncrementFlag(col.Flag) && !mysql.HasAutoIncrementFlag(newCol.Flag) { + if !sctx.GetSessionVars().AllowRemoveAutoInc && mysql.HasAutoIncrementFlag(col.GetFlag()) && !mysql.HasAutoIncrementFlag(newCol.GetFlag()) { return nil, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't remove auto_increment without @@tidb_allow_remove_auto_inc enabled") } // We support modifying the type definitions of 'null' to 'not null' now. var modifyColumnTp byte - if !mysql.HasNotNullFlag(col.Flag) && mysql.HasNotNullFlag(newCol.Flag) { + if !mysql.HasNotNullFlag(col.GetFlag()) && mysql.HasNotNullFlag(newCol.GetFlag()) { if err = checkForNullValue(ctx, sctx, true, ident.Schema, ident.Name, newCol.ColumnInfo, col.ColumnInfo); err != nil { return nil, errors.Trace(err) } @@ -4614,7 +4621,7 @@ func checkIndexInModifiableColumns(columns []*model.ColumnInfo, idxColumns []*mo } prefixLength := types.UnspecifiedLength - if types.IsTypePrefixable(col.FieldType.Tp) && col.FieldType.Flen > ic.Length { + if types.IsTypePrefixable(col.FieldType.GetType()) && col.FieldType.GetFlen() > ic.Length { // When the index column is changed, prefix length is only valid // if the type is still prefixable and larger than old prefix length. prefixLength = ic.Length @@ -4641,7 +4648,7 @@ func checkAutoRandom(tableInfo *model.TableInfo, originCol *table.Column, specNe case oldRandBits < newRandBits: addingAutoRandom := oldRandBits == 0 if addingAutoRandom { - convFromAutoInc := mysql.HasAutoIncrementFlag(originCol.Flag) && originCol.IsPKHandleColumn(tableInfo) + convFromAutoInc := mysql.HasAutoIncrementFlag(originCol.GetFlag()) && originCol.IsPKHandleColumn(tableInfo) if !convFromAutoInc { return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterChangeFromAutoInc) } @@ -4662,11 +4669,11 @@ func checkAutoRandom(tableInfo *model.TableInfo, originCol *table.Column, specNe modifyingAutoRandCol := oldRandBits > 0 || newRandBits > 0 if modifyingAutoRandCol { // Disallow changing the column field type. - if originCol.Tp != specNewColumn.Tp.Tp { + if originCol.GetType() != specNewColumn.Tp.GetType() { return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomModifyColTypeErrMsg) } - if originCol.Tp != mysql.TypeLonglong { - return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(originCol.Tp))) + if originCol.GetType() != mysql.TypeLonglong { + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(originCol.GetType()))) } // Disallow changing from auto_random to auto_increment column. if containsColumnOption(specNewColumn, ast.ColumnOptionAutoIncrement) { @@ -4840,7 +4847,7 @@ func (d *ddl) AlterColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt col := table.ToColumn(oldCol.Clone()) // Clean the NoDefaultValueFlag value. - col.Flag &= ^mysql.NoDefaultValueFlag + col.DelFlag(mysql.NoDefaultValueFlag) if len(specNewColumn.Options) == 0 { err = col.SetDefaultValue(nil) if err != nil { @@ -4887,6 +4894,9 @@ func (d *ddl) AlterTableComment(ctx sessionctx.Context, ident ast.Ident, spec *a if err != nil { return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name)) } + if _, err = validateCommentLength(ctx.GetSessionVars(), ident.Name.L, &spec.Comment, dbterror.ErrTooLongTableComment); err != nil { + return errors.Trace(err) + } job := &model.Job{ SchemaID: schema.ID, @@ -5005,9 +5015,9 @@ func (d *ddl) AlterTableSetTiFlashReplica(ctx sessionctx.Context, ident ast.Iden // Ban setting replica count for tables which has charset not supported by TiFlash for _, col := range tb.Cols() { - _, ok := charset.TiFlashSupportedCharsets[col.Charset] + _, ok := charset.TiFlashSupportedCharsets[col.GetCharset()] if !ok { - return dbterror.ErrAlterReplicaForUnsupportedCharsetTable.GenWithStackByArgs(col.Charset) + return dbterror.ErrAlterReplicaForUnsupportedCharsetTable.GenWithStackByArgs(col.GetCharset()) } } @@ -5072,7 +5082,7 @@ func (d *ddl) AlterTableAddStatistics(ctx sessionctx.Context, ident ast.Ident, s if col == nil { return infoschema.ErrColumnNotExists.GenWithStackByArgs(colName.Name, ident.Name) } - if stats.StatsType == ast.StatsTypeCorrelation && tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.Flag) { + if stats.StatsType == ast.StatsTypeCorrelation && tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.GetFlag()) { ctx.GetSessionVars().StmtCtx.AppendWarning(errors.New("No need to create correlation statistics on the integer primary key column")) return nil } @@ -5158,10 +5168,10 @@ func checkAlterTableCharset(tblInfo *model.TableInfo, dbInfo *model.DBInfo, toCh // nothing to do. doNothing = true for _, col := range tblInfo.Columns { - if col.Charset == charset.CharsetBin { + if col.GetCharset() == charset.CharsetBin { continue } - if col.Charset == toCharset && col.Collate == toCollate { + if col.GetCharset() == toCharset && col.GetCollate() == toCollate { continue } doNothing = false @@ -5190,21 +5200,21 @@ func checkAlterTableCharset(tblInfo *model.TableInfo, dbInfo *model.DBInfo, toCh } for _, col := range tblInfo.Columns { - if col.Tp == mysql.TypeVarchar { - if err = IsTooBigFieldLength(col.Flen, col.Name.O, toCharset); err != nil { + if col.GetType() == mysql.TypeVarchar { + if err = IsTooBigFieldLength(col.GetFlen(), col.Name.O, toCharset); err != nil { return doNothing, err } } - if col.Charset == charset.CharsetBin { + if col.GetCharset() == charset.CharsetBin { continue } - if len(col.Charset) == 0 { + if len(col.GetCharset()) == 0 { continue } - if err = checkModifyCharsetAndCollation(toCharset, toCollate, col.Charset, col.Collate, isColumnWithIndex(col.Name.L, tblInfo.Indices)); err != nil { + if err = checkModifyCharsetAndCollation(toCharset, toCollate, col.GetCharset(), col.GetCollate(), isColumnWithIndex(col.Name.L, tblInfo.Indices)); err != nil { if strings.Contains(err.Error(), "Unsupported modifying collation") { colErrMsg := "Unsupported converting collation of column '%s' from '%s' to '%s' when index is defined on it." - err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, toCollate) + err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.GetCollate(), toCollate) } return doNothing, err } @@ -5270,12 +5280,13 @@ func (d *ddl) DropTable(ctx sessionctx.Context, ti ast.Ident) (err error) { } job := &model.Job{ - SchemaID: schema.ID, - TableID: tb.Meta().ID, - SchemaName: schema.Name.L, - TableName: tb.Meta().Name.L, - Type: model.ActionDropTable, - BinlogInfo: &model.HistoryInfo{}, + SchemaID: schema.ID, + TableID: tb.Meta().ID, + SchemaName: schema.Name.L, + SchemaState: schema.State, + TableName: tb.Meta().Name.L, + Type: model.ActionDropTable, + BinlogInfo: &model.HistoryInfo{}, } err = d.DoDDLJob(ctx, job) @@ -5304,12 +5315,13 @@ func (d *ddl) DropView(ctx sessionctx.Context, ti ast.Ident) (err error) { } job := &model.Job{ - SchemaID: schema.ID, - TableID: tb.Meta().ID, - SchemaName: schema.Name.L, - TableName: tb.Meta().Name.L, - Type: model.ActionDropView, - BinlogInfo: &model.HistoryInfo{}, + SchemaID: schema.ID, + TableID: tb.Meta().ID, + SchemaName: schema.Name.L, + SchemaState: tb.Meta().State, + TableName: tb.Meta().Name.L, + Type: model.ActionDropView, + BinlogInfo: &model.HistoryInfo{}, } err = d.DoDDLJob(ctx, job) @@ -5476,6 +5488,13 @@ func extractTblInfos(is infoschema.InfoSchema, oldIdent, newIdent ast.Ident, isA // oldIdent is equal to newIdent, do nothing return nil, 0, nil } + //View can be renamed only in the same schema. Compatible with mysql + if is.TableIsView(oldIdent.Schema, oldIdent.Name) { + if oldIdent.Schema != newIdent.Schema { + return nil, 0, infoschema.ErrForbidSchemaChange.GenWithStackByArgs(oldIdent.Schema, newIdent.Schema) + } + } + newSchema, ok := is.SchemaByName(newIdent.Schema) if !ok { return nil, 0, dbterror.ErrErrorOnRename.GenWithStackByArgs( @@ -5612,8 +5631,10 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m } // May be truncate comment here, when index comment too long and sql_mode is't strict. - if _, err = validateCommentLength(ctx.GetSessionVars(), indexName.String(), indexOption); err != nil { - return errors.Trace(err) + if indexOption != nil { + if _, err = validateCommentLength(ctx.GetSessionVars(), indexName.String(), &indexOption.Comment, dbterror.ErrTooLongIndexComment); err != nil { + return errors.Trace(err) + } } tzName, tzOffset := ddlutil.GetTimeZone(ctx) @@ -5694,13 +5715,11 @@ func buildHiddenColumnInfo(ctx sessionctx.Context, indexPartSpecifications []*as FieldType: *expr.GetType(), } // Reset some flag, it may be caused by wrong type infer. But it's not easy to fix them all, so reset them here for safety. - colInfo.Flag &= ^mysql.PriKeyFlag - colInfo.Flag &= ^mysql.UniqueKeyFlag - colInfo.Flag &= ^mysql.AutoIncrementFlag + colInfo.DelFlag(mysql.PriKeyFlag | mysql.UniqueKeyFlag | mysql.AutoIncrementFlag) - if colInfo.Tp == mysql.TypeDatetime || colInfo.Tp == mysql.TypeDate || colInfo.Tp == mysql.TypeTimestamp || colInfo.Tp == mysql.TypeDuration { - if colInfo.FieldType.Decimal == types.UnspecifiedLength { - colInfo.FieldType.Decimal = int(types.MaxFsp) + if colInfo.GetType() == mysql.TypeDatetime || colInfo.GetType() == mysql.TypeDate || colInfo.GetType() == mysql.TypeTimestamp || colInfo.GetType() == mysql.TypeDuration { + if colInfo.FieldType.GetDecimal() == types.UnspecifiedLength { + colInfo.FieldType.SetDecimal(types.MaxFsp) } } checkDependencies := make(map[string]struct{}) @@ -5806,8 +5825,10 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde } } // May be truncate comment here, when index comment too long and sql_mode is't strict. - if _, err = validateCommentLength(ctx.GetSessionVars(), indexName.String(), indexOption); err != nil { - return errors.Trace(err) + if indexOption != nil { + if _, err = validateCommentLength(ctx.GetSessionVars(), indexName.String(), &indexOption.Comment, dbterror.ErrTooLongIndexComment); err != nil { + return errors.Trace(err) + } } tzName, tzOffset := ddlutil.GetTimeZone(ctx) @@ -5967,13 +5988,14 @@ func (d *ddl) DropForeignKey(ctx sessionctx.Context, ti ast.Ident, fkName model. } job := &model.Job{ - SchemaID: schema.ID, - TableID: t.Meta().ID, - SchemaName: schema.Name.L, - TableName: t.Meta().Name.L, - Type: model.ActionDropForeignKey, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{fkName}, + SchemaID: schema.ID, + TableID: t.Meta().ID, + SchemaName: schema.Name.L, + SchemaState: model.StatePublic, + TableName: t.Meta().Name.L, + Type: model.ActionDropForeignKey, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{fkName}, } err = d.DoDDLJob(ctx, job) @@ -6023,13 +6045,14 @@ func (d *ddl) DropIndex(ctx sessionctx.Context, ti ast.Ident, indexName model.CI } job := &model.Job{ - SchemaID: schema.ID, - TableID: t.Meta().ID, - SchemaName: schema.Name.L, - TableName: t.Meta().Name.L, - Type: jobTp, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{indexName}, + SchemaID: schema.ID, + TableID: t.Meta().ID, + SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, + Type: jobTp, + BinlogInfo: &model.HistoryInfo{}, + SchemaState: indexInfo.State, + Args: []interface{}{indexName}, } err = d.DoDDLJob(ctx, job) @@ -6138,24 +6161,34 @@ func isDroppableColumn(multiSchemaChange bool, tblInfo *model.TableInfo, colName return nil } -// validateCommentLength checks comment length of table, column, index and partition. +// validateCommentLength checks comment length of table, column, or index // If comment length is more than the standard length truncate it // and store the comment length upto the standard comment length size. -func validateCommentLength(vars *variable.SessionVars, indexName string, indexOption *ast.IndexOption) (string, error) { - if indexOption == nil { +func validateCommentLength(vars *variable.SessionVars, name string, comment *string, errTooLongComment *terror.Error) (string, error) { + if comment == nil { return "", nil } maxLen := MaxCommentLength - if len(indexOption.Comment) > maxLen { - err := dbterror.ErrTooLongIndexComment.GenWithStackByArgs(indexName, maxLen) + // The maximum length of table comment in MySQL 5.7 is 2048 + // Other comment is 1024 + switch errTooLongComment { + case dbterror.ErrTooLongTableComment: + maxLen *= 2 + case dbterror.ErrTooLongFieldComment, dbterror.ErrTooLongIndexComment, dbterror.ErrTooLongTablePartitionComment: + break + default: + // add more types of terror.Error if need + } + if len(*comment) > maxLen { + err := errTooLongComment.GenWithStackByArgs(name, maxLen) if vars.StrictSQLMode { return "", err } vars.StmtCtx.AppendWarning(err) - indexOption.Comment = indexOption.Comment[:maxLen] + *comment = (*comment)[:maxLen] } - return indexOption.Comment, nil + return *comment, nil } // buildAddedPartitionInfo build alter table add partition info @@ -6203,7 +6236,7 @@ func checkColumnsTypeAndValuesMatch(ctx sessionctx.Context, meta *model.TableInf } // Check val.ConvertTo(colType) doesn't work, so we need this case by case check. vkind := val.Kind() - switch colType.Tp { + switch colType.GetType() { case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeDuration: switch vkind { case types.KindString, types.KindBytes: @@ -6273,7 +6306,7 @@ func (d *ddl) LockTables(ctx sessionctx.Context, stmt *ast.LockTablesStmt) error } unlockTables := ctx.GetAllTableLocks() - arg := &lockTablesArg{ + arg := &LockTablesArg{ LockTables: lockTables, UnlockTables: unlockTables, SessionInfo: sessionInfo, @@ -6301,7 +6334,7 @@ func (d *ddl) UnlockTables(ctx sessionctx.Context, unlockTables []model.TableLoc if len(unlockTables) == 0 { return nil } - arg := &lockTablesArg{ + arg := &LockTablesArg{ UnlockTables: unlockTables, SessionInfo: model.SessionInfo{ ServerID: d.GetID(), @@ -6329,7 +6362,7 @@ func (d *ddl) CleanDeadTableLock(unlockTables []model.TableLockTpInfo, se model. if len(unlockTables) == 0 { return nil } - arg := &lockTablesArg{ + arg := &LockTablesArg{ UnlockTables: unlockTables, SessionInfo: se, } @@ -6396,7 +6429,7 @@ func (d *ddl) CleanupTableLock(ctx sessionctx.Context, tables []*ast.TableName) return nil } - arg := &lockTablesArg{ + arg := &LockTablesArg{ UnlockTables: cleanupTables, IsCleanup: true, } @@ -6415,7 +6448,8 @@ func (d *ddl) CleanupTableLock(ctx sessionctx.Context, tables []*ast.TableName) return errors.Trace(err) } -type lockTablesArg struct { +// LockTablesArg is the argument for LockTables, export for test. +type LockTablesArg struct { LockTables []model.TableLockTpInfo IndexOfLock int UnlockTables []model.TableLockTpInfo @@ -6457,10 +6491,10 @@ func (d *ddl) RepairTable(ctx sessionctx.Context, table *ast.TableName, createSt if old == nil { return dbterror.ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " has lost") } - if newOne.Tp != old.Tp { + if newOne.GetType() != old.GetType() { return dbterror.ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " type should be the same") } - if newOne.Flen != old.Flen { + if newOne.GetFlen() != old.GetFlen() { logutil.BgLogger().Warn("[ddl] admin repair table : Column " + newOne.Name.L + " flen is not equal to the old one") } newTableInfo.Columns[i].ID = old.ID @@ -6594,12 +6628,13 @@ func (d *ddl) DropSequence(ctx sessionctx.Context, ti ast.Ident, ifExists bool) } job := &model.Job{ - SchemaID: schema.ID, - TableID: tbl.Meta().ID, - SchemaName: schema.Name.L, - TableName: tbl.Meta().Name.L, - Type: model.ActionDropSequence, - BinlogInfo: &model.HistoryInfo{}, + SchemaID: schema.ID, + TableID: tbl.Meta().ID, + SchemaName: schema.Name.L, + SchemaState: tbl.Meta().State, + TableName: tbl.Meta().Name.L, + Type: model.ActionDropSequence, + BinlogInfo: &model.HistoryInfo{}, } err = d.DoDDLJob(ctx, job) @@ -6945,7 +6980,7 @@ func (d *ddl) DropPlacementPolicy(ctx sessionctx.Context, stmt *ast.DropPlacemen return err } - if err = checkPlacementPolicyNotInUseFromInfoSchema(is, policy); err != nil { + if err = CheckPlacementPolicyNotInUseFromInfoSchema(is, policy); err != nil { return err } @@ -7109,14 +7144,14 @@ func (d *ddl) AlterTableNoCache(ctx sessionctx.Context, ti ast.Ident) (err error // checkTooBigFieldLengthAndTryAutoConvert will check whether the field length is too big // in non-strict mode and varchar column. If it is, will try to adjust to blob or text, see issue #30328 func checkTooBigFieldLengthAndTryAutoConvert(tp *types.FieldType, colName string, sessVars *variable.SessionVars) error { - if sessVars != nil && !sessVars.SQLMode.HasStrictMode() && tp.Tp == mysql.TypeVarchar { - err := IsTooBigFieldLength(tp.Flen, colName, tp.Charset) + if sessVars != nil && !sessVars.SQLMode.HasStrictMode() && tp.GetType() == mysql.TypeVarchar { + err := IsTooBigFieldLength(tp.GetFlen(), colName, tp.GetCharset()) if err != nil && terror.ErrorEqual(types.ErrTooBigFieldLength, err) { - tp.Tp = mysql.TypeBlob - if err = adjustBlobTypesFlen(tp, tp.Charset); err != nil { + tp.SetType(mysql.TypeBlob) + if err = adjustBlobTypesFlen(tp, tp.GetCharset()); err != nil { return err } - if tp.Charset == charset.CharsetBin { + if tp.GetCharset() == charset.CharsetBin { sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colName, "VARBINARY", "BLOB")) } else { sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colName, "VARCHAR", "TEXT")) diff --git a/ddl/ddl_error_test.go b/ddl/ddl_error_test.go index b771ea273014d..59c982a24254f 100644 --- a/ddl/ddl_error_test.go +++ b/ddl/ddl_error_test.go @@ -20,6 +20,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" ) @@ -186,3 +187,32 @@ func TestCreateDatabaseError(t *testing.T) { tk.MustExec("create database db1;") require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) } + +func TestRenameViewOverDifferentSchemaError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + //init + tk.MustExec("use test") + tk.MustExec("drop database if exists test_2;") + tk.MustExec("drop table if exists table_1;") + tk.MustExec("drop view if exists view_1;") + + tk.MustExec("create database test_2;") + tk.MustExec("create table table_1 (a int);") + tk.MustExec("create view view_1 as select a from table_1;") + + //different schema + tk.MustGetErrCode("rename table test.view_1 to test_2.view_1;", errno.ErrForbidSchemaChange) + tk.MustGetErrMsg("rename table test.view_1 to test_2.view_1;", + infoschema.ErrForbidSchemaChange.GenWithStackByArgs("test", "test_2").Error(), + ) + tk.MustGetErrMsg("rename table test.view_1 to test_2.view_1;", + "[schema:1450]Changing schema from 'test' to 'test_2' is not allowed.", + ) + + //same schema + tk.MustExec("rename table test.view_1 to test.view_1000;") + +} diff --git a/ddl/ddl_test.go b/ddl/ddl_test.go index e0140f318d4ee..c1491ce264815 100644 --- a/ddl/ddl_test.go +++ b/ddl/ddl_test.go @@ -16,6 +16,7 @@ package ddl import ( "context" + "fmt" "testing" "time" @@ -29,12 +30,16 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) +const testLease = 5 * time.Millisecond + type DDLForTest interface { // SetInterceptor sets the interceptor. SetInterceptor(h Interceptor) @@ -108,10 +113,6 @@ func checkEqualTable(t *testing.T, t1, t2 *model.TableInfo) { require.Equal(t, t1.AutoIncID, t2.AutoIncID) } -func checkHistoryJob(t *testing.T, job *model.Job) { - require.Equal(t, job.State, model.JobStateSynced) -} - func checkHistoryJobArgs(t *testing.T, ctx sessionctx.Context, id int64, args *historyJobArgs) { txn, err := ctx.Txn(true) require.NoError(t, err) @@ -135,99 +136,6 @@ func checkHistoryJobArgs(t *testing.T, ctx sessionctx.Context, id int64, args *h } } -func buildCreateIdxJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddIndex, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{unique, model.NewCIStr(indexName), - []*ast.IndexPartSpecification{{ - Column: &ast.ColumnName{Name: model.NewCIStr(colName)}, - Length: types.UnspecifiedLength}}}, - } -} - -func testCreatePrimaryKey(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { - job := buildCreateIdxJob(dbInfo, tblInfo, true, "primary", colName) - job.Type = model.ActionAddPrimaryKey - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func testCreateIndex(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { - job := buildCreateIdxJob(dbInfo, tblInfo, unique, indexName, colName) - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func testAddColumn(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, args []interface{}) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddColumn, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func testAddColumns(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, args []interface{}) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddColumns, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func buildDropIdxJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName string) *model.Job { - tp := model.ActionDropIndex - if indexName == "primary" { - tp = model.ActionDropPrimaryKey - } - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: tp, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{model.NewCIStr(indexName)}, - } -} - -func testDropIndex(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName string) *model.Job { - job := buildDropIdxJob(dbInfo, tblInfo, indexName) - - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - func TestGetIntervalFromPolicy(t *testing.T) { policy := []time.Duration{ 1 * time.Second, @@ -499,7 +407,7 @@ func TestNotifyDDLJob(t *testing.T) { d1.asyncNotifyWorker(job) job.Type = model.ActionCreateTable d1.asyncNotifyWorker(job) - testCheckOwner(t, d1, false) + require.False(t, d1.OwnerManager().IsOwner()) select { case <-d1.workers[addIdxWorker].ddlJobCh: require.FailNow(t, "should not get the add index job notification") @@ -508,3 +416,271 @@ func TestNotifyDDLJob(t *testing.T) { default: } } + +func testSchemaInfo(d *ddl, name string) (*model.DBInfo, error) { + dbInfo := &model.DBInfo{ + Name: model.NewCIStr(name), + } + genIDs, err := d.genGlobalIDs(1) + if err != nil { + return nil, err + } + dbInfo.ID = genIDs[0] + return dbInfo, nil +} + +func testCreateSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) *model.Job { + job := &model.Job{ + SchemaID: dbInfo.ID, + Type: model.ActionCreateSchema, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{dbInfo}, + } + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) + + v := getSchemaVer(t, ctx) + dbInfo.State = model.StatePublic + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo}) + dbInfo.State = model.StateNone + return job +} + +func buildDropSchemaJob(dbInfo *model.DBInfo) *model.Job { + return &model.Job{ + SchemaID: dbInfo.ID, + Type: model.ActionDropSchema, + BinlogInfo: &model.HistoryInfo{}, + } +} + +func testDropSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) (*model.Job, int64) { + job := buildDropSchemaJob(dbInfo) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + ver := getSchemaVer(t, ctx) + return job, ver +} + +func isDDLJobDone(test *testing.T, t *meta.Meta) bool { + job, err := t.GetDDLJobByIdx(0) + require.NoError(test, err) + if job == nil { + return true + } + + time.Sleep(testLease) + return false +} + +func testCheckSchemaState(test *testing.T, d *ddl, dbInfo *model.DBInfo, state model.SchemaState) { + isDropped := true + + for { + err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + t := meta.NewMeta(txn) + info, err := t.GetDatabase(dbInfo.ID) + require.NoError(test, err) + + if state == model.StateNone { + isDropped = isDDLJobDone(test, t) + if !isDropped { + return nil + } + require.Nil(test, info) + return nil + } + + require.Equal(test, info.Name, dbInfo.Name) + require.Equal(test, info.State, state) + return nil + }) + require.NoError(test, err) + + if isDropped { + break + } + } +} + +type testCtxKeyType int + +func (k testCtxKeyType) String() string { + return "test_ctx_key" +} + +const testCtxKey testCtxKeyType = 0 + +func TestReorg(t *testing.T) { + tests := []struct { + isCommonHandle bool + handle kv.Handle + startKey kv.Handle + endKey kv.Handle + }{ + { + false, + kv.IntHandle(100), + kv.IntHandle(1), + kv.IntHandle(0), + }, + { + true, + testutil.MustNewCommonHandle(t, "a", 100, "string"), + testutil.MustNewCommonHandle(t, 100, "string"), + testutil.MustNewCommonHandle(t, 101, "string"), + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("isCommandHandle(%v)", test.isCommonHandle), func(t *testing.T) { + store := createMockStore(t) + defer func() { + require.NoError(t, store.Close()) + }() + + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + err := d.Stop() + require.NoError(t, err) + }() + + time.Sleep(testLease) + + ctx := testNewContext(d) + + ctx.SetValue(testCtxKey, 1) + require.Equal(t, ctx.Value(testCtxKey), 1) + ctx.ClearValue(testCtxKey) + + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err := ctx.Txn(true) + require.NoError(t, err) + err = txn.Set([]byte("a"), []byte("b")) + require.NoError(t, err) + err = txn.Rollback() + require.NoError(t, err) + + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + err = txn.Set([]byte("a"), []byte("b")) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + + rowCount := int64(10) + handle := test.handle + f := func() error { + d.generalWorker().reorgCtx.setRowCount(rowCount) + d.generalWorker().reorgCtx.setNextKey(handle.Encoded()) + time.Sleep(1*ReorgWaitTimeout + 100*time.Millisecond) + return nil + } + job := &model.Job{ + ID: 1, + SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. + } + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + m := meta.NewMeta(txn) + e := &meta.Element{ID: 333, TypeKey: meta.IndexElementKey} + rInfo := &reorgInfo{ + Job: job, + currElement: e, + } + mockTbl := tables.MockTableFromMeta(&model.TableInfo{IsCommonHandle: test.isCommonHandle, CommonHandleVersion: 1}) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) + require.Error(t, err) + + // The longest to wait for 5 seconds to make sure the function of f is returned. + for i := 0; i < 1000; i++ { + time.Sleep(5 * time.Millisecond) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) + if err == nil { + require.Equal(t, job.RowCount, rowCount) + require.Equal(t, d.generalWorker().reorgCtx.rowCount, int64(0)) + + // Test whether reorgInfo's Handle is update. + err = txn.Commit(context.Background()) + require.NoError(t, err) + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + + m = meta.NewMeta(txn) + info, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, nil) + require.NoError(t, err1) + require.Equal(t, info.StartKey, kv.Key(handle.Encoded())) + require.Equal(t, info.currElement, e) + _, doneHandle, _ := d.generalWorker().reorgCtx.getRowCountAndKey() + require.Nil(t, doneHandle) + break + } + } + require.NoError(t, err) + + job = &model.Job{ + ID: 2, + SchemaID: 1, + Type: model.ActionCreateSchema, + Args: []interface{}{model.NewCIStr("test")}, + SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. + } + + element := &meta.Element{ID: 123, TypeKey: meta.ColumnElementKey} + info := &reorgInfo{ + Job: job, + d: d.ddlCtx, + currElement: element, + StartKey: test.startKey.Encoded(), + EndKey: test.endKey.Encoded(), + PhysicalTableID: 456, + } + err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + var err1 error + _, err1 = getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) + require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err1)) + require.Equal(t, job.SnapshotVer, uint64(0)) + return nil + }) + require.NoError(t, err) + job.SnapshotVer = uint64(1) + err = info.UpdateReorgMeta(info.StartKey) + require.NoError(t, err) + err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + info1, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) + require.NoError(t, err1) + require.Equal(t, info1.currElement, info.currElement) + require.Equal(t, info1.StartKey, info.StartKey) + require.Equal(t, info1.EndKey, info.EndKey) + require.Equal(t, info1.PhysicalTableID, info.PhysicalTableID) + return nil + }) + require.NoError(t, err) + + err = d.Stop() + require.NoError(t, err) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, func() error { + time.Sleep(4 * testLease) + return nil + }) + require.Error(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + }) + } +} diff --git a/ddl/ddl_tiflash_api.go b/ddl/ddl_tiflash_api.go index 5638cc4bbb39d..6ef17755a5fcd 100644 --- a/ddl/ddl_tiflash_api.go +++ b/ddl/ddl_tiflash_api.go @@ -343,7 +343,7 @@ func updateTiFlashStores(pollTiFlashContext *TiFlashManagementContext) error { } } } - logutil.BgLogger().Info("updateTiFlashStores finished", zap.Int("TiFlash store count", len(pollTiFlashContext.TiFlashStores))) + logutil.BgLogger().Debug("updateTiFlashStores finished", zap.Int("TiFlash store count", len(pollTiFlashContext.TiFlashStores))) return nil } diff --git a/ddl/ddl_worker.go b/ddl/ddl_worker.go index 6bbf0beae14ee..cae3be063dd60 100644 --- a/ddl/ddl_worker.go +++ b/ddl/ddl_worker.go @@ -37,7 +37,6 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" tidbutil "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/resourcegrouptag" @@ -240,7 +239,7 @@ func buildJobDependence(t *meta.Meta, curJob *model.Job) error { // Jobs in the same queue are ordered. If we want to find a job's dependency-job, we need to look for // it from the other queue. So if the job is "ActionAddIndex" job, we need find its dependency-job from DefaultJobList. jobListKey := meta.DefaultJobListKey - if !mayNeedReorg(curJob) { + if !curJob.MayNeedReorg() { jobListKey = meta.AddIndexJobListKey } jobs, err := t.GetAllDDLJobsInQueue(jobListKey) @@ -306,7 +305,7 @@ func (d *ddl) addBatchDDLJobs(tasks []*limitJobTask) { return errors.Trace(err) } jobListKey := meta.DefaultJobListKey - if mayNeedReorg(job) { + if job.MayNeedReorg() { jobListKey = meta.AddIndexJobListKey } failpoint.Inject("MockModifyJobArg", func(val failpoint.Value) { @@ -542,9 +541,9 @@ func (w *JobContext) setDDLLabelForTopSQL(job *model.Job) { if job.Query != w.cacheSQL || w.cacheDigest == nil { w.cacheNormalizedSQL, w.cacheDigest = parser.NormalizeDigest(job.Query) w.cacheSQL = job.Query - w.ddlJobCtx = topsql.AttachSQLInfo(context.Background(), w.cacheNormalizedSQL, w.cacheDigest, "", nil, false) + w.ddlJobCtx = topsql.AttachAndRegisterSQLInfo(context.Background(), w.cacheNormalizedSQL, w.cacheDigest, false) } else { - topsql.AttachSQLInfo(w.ddlJobCtx, w.cacheNormalizedSQL, w.cacheDigest, "", nil, false) + topsql.AttachAndRegisterSQLInfo(w.ddlJobCtx, w.cacheNormalizedSQL, w.cacheDigest, false) } } @@ -800,7 +799,7 @@ func (w *worker) countForError(err error, job *model.Job) error { logutil.Logger(w.logCtx).Error("[ddl] load DDL global variable failed", zap.Error(err1)) } // Check error limit to avoid falling into an infinite loop. - if job.ErrorCount > variable.GetDDLErrorCountLimit() && job.State == model.JobStateRunning && admin.IsJobRollbackable(job) { + if job.ErrorCount > variable.GetDDLErrorCountLimit() && job.State == model.JobStateRunning && job.IsRollbackable() { logutil.Logger(w.logCtx).Warn("[ddl] DDL job error count exceed the limit, cancelling it now", zap.Int64("jobID", job.ID), zap.Int64("errorCountLimit", variable.GetDDLErrorCountLimit())) job.State = model.JobStateCancelling } @@ -846,11 +845,11 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, case model.ActionCreateSchema: ver, err = onCreateSchema(d, t, job) case model.ActionModifySchemaCharsetAndCollate: - ver, err = onModifySchemaCharsetAndCollate(t, job) + ver, err = onModifySchemaCharsetAndCollate(d, t, job) case model.ActionDropSchema: ver, err = onDropSchema(d, t, job) case model.ActionModifySchemaDefaultPlacement: - ver, err = onModifySchemaDefaultPlacement(t, job) + ver, err = onModifySchemaDefaultPlacement(d, t, job) case model.ActionCreateTable: ver, err = onCreateTable(d, t, job) case model.ActionCreateTables: @@ -860,7 +859,7 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, case model.ActionCreateView: ver, err = onCreateView(d, t, job) case model.ActionDropTable, model.ActionDropView, model.ActionDropSequence: - ver, err = onDropTableOrView(t, job) + ver, err = onDropTableOrView(d, t, job) case model.ActionDropTablePartition: ver, err = w.onDropTablePartition(d, t, job) case model.ActionTruncateTablePartition: @@ -872,81 +871,81 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, case model.ActionAddColumns: ver, err = onAddColumns(d, t, job) case model.ActionDropColumn: - ver, err = onDropColumn(t, job) + ver, err = onDropColumn(d, t, job) case model.ActionDropColumns: - ver, err = onDropColumns(t, job) + ver, err = onDropColumns(d, t, job) case model.ActionModifyColumn: ver, err = w.onModifyColumn(d, t, job) case model.ActionSetDefaultValue: - ver, err = onSetDefaultValue(t, job) + ver, err = onSetDefaultValue(d, t, job) case model.ActionAddIndex: ver, err = w.onCreateIndex(d, t, job, false) case model.ActionAddPrimaryKey: ver, err = w.onCreateIndex(d, t, job, true) case model.ActionDropIndex, model.ActionDropPrimaryKey: - ver, err = onDropIndex(t, job) + ver, err = onDropIndex(d, t, job) case model.ActionDropIndexes: - ver, err = onDropIndexes(t, job) + ver, err = onDropIndexes(d, t, job) case model.ActionRenameIndex: - ver, err = onRenameIndex(t, job) + ver, err = onRenameIndex(d, t, job) case model.ActionAddForeignKey: - ver, err = onCreateForeignKey(t, job) + ver, err = onCreateForeignKey(d, t, job) case model.ActionDropForeignKey: - ver, err = onDropForeignKey(t, job) + ver, err = onDropForeignKey(d, t, job) case model.ActionTruncateTable: ver, err = onTruncateTable(d, t, job) case model.ActionRebaseAutoID: - ver, err = onRebaseRowIDType(d.store, t, job) + ver, err = onRebaseRowIDType(d, t, job) case model.ActionRebaseAutoRandomBase: - ver, err = onRebaseAutoRandomType(d.store, t, job) + ver, err = onRebaseAutoRandomType(d, t, job) case model.ActionRenameTable: ver, err = onRenameTable(d, t, job) case model.ActionShardRowID: ver, err = w.onShardRowID(d, t, job) case model.ActionModifyTableComment: - ver, err = onModifyTableComment(t, job) + ver, err = onModifyTableComment(d, t, job) case model.ActionModifyTableAutoIdCache: - ver, err = onModifyTableAutoIDCache(t, job) + ver, err = onModifyTableAutoIDCache(d, t, job) case model.ActionAddTablePartition: ver, err = w.onAddTablePartition(d, t, job) case model.ActionModifyTableCharsetAndCollate: - ver, err = onModifyTableCharsetAndCollate(t, job) + ver, err = onModifyTableCharsetAndCollate(d, t, job) case model.ActionRecoverTable: ver, err = w.onRecoverTable(d, t, job) case model.ActionLockTable: - ver, err = onLockTables(t, job) + ver, err = onLockTables(d, t, job) case model.ActionUnlockTable: - ver, err = onUnlockTables(t, job) + ver, err = onUnlockTables(d, t, job) case model.ActionSetTiFlashReplica: - ver, err = w.onSetTableFlashReplica(t, job) + ver, err = w.onSetTableFlashReplica(d, t, job) case model.ActionUpdateTiFlashReplicaStatus: - ver, err = onUpdateFlashReplicaStatus(t, job) + ver, err = onUpdateFlashReplicaStatus(d, t, job) case model.ActionCreateSequence: ver, err = onCreateSequence(d, t, job) case model.ActionAlterIndexVisibility: - ver, err = onAlterIndexVisibility(t, job) + ver, err = onAlterIndexVisibility(d, t, job) case model.ActionAlterSequence: - ver, err = onAlterSequence(t, job) + ver, err = onAlterSequence(d, t, job) case model.ActionRenameTables: ver, err = onRenameTables(d, t, job) case model.ActionAlterTableAttributes: - ver, err = onAlterTableAttributes(t, job) + ver, err = onAlterTableAttributes(d, t, job) case model.ActionAlterTablePartitionAttributes: - ver, err = onAlterTablePartitionAttributes(t, job) + ver, err = onAlterTablePartitionAttributes(d, t, job) case model.ActionCreatePlacementPolicy: ver, err = onCreatePlacementPolicy(d, t, job) case model.ActionDropPlacementPolicy: ver, err = onDropPlacementPolicy(d, t, job) case model.ActionAlterPlacementPolicy: - ver, err = onAlterPlacementPolicy(t, job) + ver, err = onAlterPlacementPolicy(d, t, job) case model.ActionAlterTablePartitionPlacement: - ver, err = onAlterTablePartitionPlacement(t, job) + ver, err = onAlterTablePartitionPlacement(d, t, job) case model.ActionAlterTablePlacement: ver, err = onAlterTablePlacement(d, t, job) case model.ActionAlterCacheTable: - ver, err = onAlterCacheTable(t, job) + ver, err = onAlterCacheTable(d, t, job) case model.ActionAlterNoCacheTable: - ver, err = onAlterNoCacheTable(t, job) + ver, err = onAlterNoCacheTable(d, t, job) default: // Invalid job, cancel it. job.State = model.JobStateCancelled @@ -1068,7 +1067,7 @@ func buildPlacementAffects(oldIDs []int64, newIDs []int64) []*model.AffectedOpti } // updateSchemaVersion increments the schema version by 1 and sets SchemaDiff. -func updateSchemaVersion(t *meta.Meta, job *model.Job) (int64, error) { +func updateSchemaVersion(_ *ddlCtx, t *meta.Meta, job *model.Job) (int64, error) { schemaVersion, err := t.GenSchemaVersion() if err != nil { return 0, errors.Trace(err) @@ -1080,7 +1079,7 @@ func updateSchemaVersion(t *meta.Meta, job *model.Job) (int64, error) { } switch job.Type { case model.ActionCreateTables: - tableInfos := []*model.TableInfo{} + var tableInfos []*model.TableInfo err = job.DecodeArgs(&tableInfos) if err != nil { return 0, errors.Trace(err) @@ -1128,11 +1127,10 @@ func updateSchemaVersion(t *meta.Meta, job *model.Job) (int64, error) { } diff.TableID = job.TableID case model.ActionRenameTables: - oldSchemaIDs := []int64{} - newSchemaIDs := []int64{} - tableNames := []*model.CIStr{} - tableIDs := []int64{} - oldSchemaNames := []*model.CIStr{} + var ( + oldSchemaIDs, newSchemaIDs, tableIDs []int64 + tableNames, oldSchemaNames []*model.CIStr + ) err = job.DecodeArgs(&oldSchemaIDs, &newSchemaIDs, &tableNames, &tableIDs, &oldSchemaNames) if err != nil { return 0, errors.Trace(err) diff --git a/ddl/foreign_key.go b/ddl/foreign_key.go index f7b1ba5a1086b..b81e2729af379 100644 --- a/ddl/foreign_key.go +++ b/ddl/foreign_key.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/tidb/util/dbterror" ) -func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onCreateForeignKey(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { schemaID := job.SchemaID tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { @@ -44,7 +44,7 @@ func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { // We just support record the foreign key, so we just make it public. // none -> public fkInfo.State = model.StatePublic - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != fkInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != fkInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -56,7 +56,7 @@ func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { } } -func onDropForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropForeignKey(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { schemaID := job.SchemaID tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { @@ -100,12 +100,13 @@ func onDropForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { // We just support record the foreign key, so we just make it none. // public -> none fkInfo.State = model.StateNone - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != fkInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != fkInfo.State) if err != nil { return ver, errors.Trace(err) } // Finish this job. job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) + job.SchemaState = fkInfo.State return ver, nil default: return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("foreign key", fkInfo.State) diff --git a/ddl/foreign_key_test.go b/ddl/foreign_key_test.go index 43f8b7d065429..1986ac78878f0 100644 --- a/ddl/foreign_key_test.go +++ b/ddl/foreign_key_test.go @@ -12,28 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" "strings" "sync" "testing" - "time" "github.com/pingcap/errors" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" ) -const testLease = 5 * time.Millisecond - -func testCreateForeignKey(t *testing.T, d *ddl, ctx sessionctx.Context, dbInfo *model.DBInfo, tblInfo *model.TableInfo, fkName string, keys []string, refTable string, refKeys []string, onDelete ast.ReferOptionType, onUpdate ast.ReferOptionType) *model.Job { +func testCreateForeignKey(t *testing.T, d ddl.DDL, ctx sessionctx.Context, dbInfo *model.DBInfo, tblInfo *model.TableInfo, fkName string, keys []string, refTable string, refKeys []string, onDelete ast.ReferOptionType, onUpdate ast.ReferOptionType) *model.Job { FKName := model.NewCIStr(fkName) Keys := make([]model.CIStr, len(keys)) for i, key := range keys { @@ -71,7 +68,7 @@ func testCreateForeignKey(t *testing.T, d *ddl, ctx sessionctx.Context, dbInfo * return job } -func testDropForeignKey(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, foreignKeyName string) *model.Job { +func testDropForeignKey(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo, tblInfo *model.TableInfo, foreignKeyName string) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, TableID: tblInfo.ID, @@ -101,53 +98,31 @@ func getForeignKey(t table.Table, name string) *model.FKInfo { } func TestForeignKey(t *testing.T) { - store := createMockStore(t) - defer func() { - err := store.Close() - require.NoError(t, err) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - err := d.Stop() - require.NoError(t, err) - }() + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - dbInfo, err := testSchemaInfo(d, "test_foreign") + d := dom.DDL() + dbInfo, err := testSchemaInfo(store, "test_foreign") require.NoError(t, err) - ctx := testNewContext(d) - testCreateSchema(t, ctx, d, dbInfo) - tblInfo, err := testTableInfo(d, "t", 3) - require.NoError(t, err) - - err = ctx.NewTxn(context.Background()) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), dom.DDL(), dbInfo) + tblInfo, err := testTableInfo(store, "t", 3) require.NoError(t, err) - testCreateTable(t, ctx, d, dbInfo, tblInfo) - - txn, err := ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) + testCreateTable(t, testkit.NewTestKit(t, store).Session(), d, dbInfo, tblInfo) // fix data race var mu sync.Mutex checkOK := false var hookErr error - tc := &TestDDLCallback{} - tc.onJobUpdated = func(job *model.Job) { + tc := &ddl.TestDDLCallback{} + tc.OnJobUpdatedExported = func(job *model.Job) { if job.State != model.JobStateDone { return } mu.Lock() defer mu.Unlock() var t table.Table - t, err = testGetTableWithError(d, dbInfo.ID, tblInfo.ID) + t, err = testGetTableWithError(store, dbInfo.ID, tblInfo.ID) if err != nil { hookErr = errors.Trace(err) return @@ -163,11 +138,9 @@ func TestForeignKey(t *testing.T) { defer d.SetHook(originalHook) d.SetHook(tc) + ctx := testkit.NewTestKit(t, store).Session() job := testCreateForeignKey(t, d, ctx, dbInfo, tblInfo, "c1_fk", []string{"c1"}, "t2", []string{"c1"}, ast.ReferOptionCascade, ast.ReferOptionSetNull) - testCheckJobDone(t, d, job, true) - txn, err = ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) + testCheckJobDone(t, store, job.ID, true) require.NoError(t, err) mu.Lock() hErr := hookErr @@ -182,15 +155,15 @@ func TestForeignKey(t *testing.T) { checkOK = false mu.Unlock() // fix data race pr/#9491 - tc2 := &TestDDLCallback{} - tc2.onJobUpdated = func(job *model.Job) { + tc2 := &ddl.TestDDLCallback{} + tc2.OnJobUpdatedExported = func(job *model.Job) { if job.State != model.JobStateDone { return } mu.Lock() defer mu.Unlock() var t table.Table - t, err = testGetTableWithError(d, dbInfo.ID, tblInfo.ID) + t, err = testGetTableWithError(store, dbInfo.ID, tblInfo.ID) if err != nil { hookErr = errors.Trace(err) return @@ -205,38 +178,18 @@ func TestForeignKey(t *testing.T) { d.SetHook(tc2) job = testDropForeignKey(t, ctx, d, dbInfo, tblInfo, "c1_fk") - testCheckJobDone(t, d, job, false) + testCheckJobDone(t, store, job.ID, false) mu.Lock() hErr = hookErr ok = checkOK mu.Unlock() require.NoError(t, hErr) require.True(t, ok) + d.SetHook(originalHook) - err = ctx.NewTxn(context.Background()) - require.NoError(t, err) - - job = testDropTable(t, ctx, d, dbInfo, tblInfo) - testCheckJobDone(t, d, job, false) + tk := testkit.NewTestKit(t, store) + jobID := testDropTable(tk, t, dbInfo.Name.L, tblInfo.Name.L, dom) + testCheckJobDone(t, store, jobID, false) - txn, err = ctx.Txn(true) require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) -} - -func testCheckJobDone(t *testing.T, d *ddl, job *model.Job, isAdd bool) { - require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - historyJob, err := m.GetHistoryDDLJob(job.ID) - require.NoError(t, err) - checkHistoryJob(t, historyJob) - if isAdd { - require.Equal(t, historyJob.SchemaState, model.StatePublic) - } else { - require.Equal(t, historyJob.SchemaState, model.StateNone) - } - - return nil - })) } diff --git a/ddl/index.go b/ddl/index.go index d9be5497aae07..f4d74028256d8 100644 --- a/ddl/index.go +++ b/ddl/index.go @@ -122,7 +122,7 @@ func checkIndexPrefixLength(columns []*model.ColumnInfo, idxColumns []*model.Ind } func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { - if col.Flen == 0 && (types.IsTypeChar(col.FieldType.Tp) || types.IsTypeVarchar(col.FieldType.Tp)) { + if col.GetFlen() == 0 && (types.IsTypeChar(col.FieldType.GetType()) || types.IsTypeVarchar(col.FieldType.GetType())) { if col.Hidden { return errors.Trace(dbterror.ErrWrongKeyColumnFunctionalIndex.GenWithStackByArgs(col.GeneratedExprString)) } @@ -130,7 +130,7 @@ func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { } // JSON column cannot index. - if col.FieldType.Tp == mysql.TypeJSON { + if col.FieldType.GetType() == mysql.TypeJSON { if col.Hidden { return dbterror.ErrFunctionalIndexOnJSONOrGeometryFunction } @@ -138,7 +138,7 @@ func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { } // Length must be specified and non-zero for BLOB and TEXT column indexes. - if types.IsTypeBlob(col.FieldType.Tp) { + if types.IsTypeBlob(col.FieldType.GetType()) { if indexColumnLen == types.UnspecifiedLength { if col.Hidden { return dbterror.ErrFunctionalIndexOnBlob @@ -151,14 +151,14 @@ func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { } // Length can only be specified for specifiable types. - if indexColumnLen != types.UnspecifiedLength && !types.IsTypePrefixable(col.FieldType.Tp) { + if indexColumnLen != types.UnspecifiedLength && !types.IsTypePrefixable(col.FieldType.GetType()) { return errors.Trace(dbterror.ErrIncorrectPrefixKey) } // Key length must be shorter or equal to the column length. if indexColumnLen != types.UnspecifiedLength && - types.IsTypeChar(col.FieldType.Tp) { - if col.Flen < indexColumnLen { + types.IsTypeChar(col.FieldType.GetType()) { + if col.GetFlen() < indexColumnLen { return errors.Trace(dbterror.ErrIncorrectPrefixKey) } // Length must be non-zero for char. @@ -167,8 +167,8 @@ func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { } } - if types.IsString(col.FieldType.Tp) { - desc, err := charset.GetCharsetInfo(col.Charset) + if types.IsString(col.FieldType.GetType()) { + desc, err := charset.GetCharsetInfo(col.GetCharset()) if err != nil { return err } @@ -186,22 +186,22 @@ func getIndexColumnLength(col *model.ColumnInfo, colLen int) (int, error) { length := types.UnspecifiedLength if colLen != types.UnspecifiedLength { length = colLen - } else if col.Flen != types.UnspecifiedLength { - length = col.Flen + } else if col.GetFlen() != types.UnspecifiedLength { + length = col.GetFlen() } - switch col.Tp { + switch col.GetType() { case mysql.TypeBit: return (length + 7) >> 3, nil case mysql.TypeVarchar, mysql.TypeString, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob: // Different charsets occupy different numbers of bytes on each character. - desc, err := charset.GetCharsetInfo(col.Charset) + desc, err := charset.GetCharsetInfo(col.GetCharset()) if err != nil { - return 0, dbterror.ErrUnsupportedCharset.GenWithStackByArgs(col.Charset, col.Collate) + return 0, dbterror.ErrUnsupportedCharset.GenWithStackByArgs(col.GetCharset(), col.GetCollate()) } return desc.Maxlen * length, nil case mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeShort: - return mysql.DefaultLengthOfMysqlTypes[col.Tp], nil + return mysql.DefaultLengthOfMysqlTypes[col.GetType()], nil case mysql.TypeFloat: if length <= mysql.MaxFloatPrecisionLength { return mysql.DefaultLengthOfMysqlTypes[mysql.TypeFloat], nil @@ -210,13 +210,13 @@ func getIndexColumnLength(col *model.ColumnInfo, colLen int) (int, error) { case mysql.TypeNewDecimal: return calcBytesLengthForDecimal(length), nil case mysql.TypeYear, mysql.TypeDate, mysql.TypeDuration, mysql.TypeDatetime, mysql.TypeTimestamp: - return mysql.DefaultLengthOfMysqlTypes[col.Tp], nil + return mysql.DefaultLengthOfMysqlTypes[col.GetType()], nil default: return length, nil } } -// Decimal using a binary format that packs nine decimal (base 10) digits into four bytes. +// decimal using a binary format that packs nine decimal (base 10) digits into four bytes. func calcBytesLengthForDecimal(m int) int { return (m / 9 * 4) + ((m%9)+1)/2 } @@ -243,28 +243,28 @@ func buildIndexInfo(tblInfo *model.TableInfo, indexName model.CIStr, indexPartSp func addIndexColumnFlag(tblInfo *model.TableInfo, indexInfo *model.IndexInfo) { if indexInfo.Primary { for _, col := range indexInfo.Columns { - tblInfo.Columns[col.Offset].Flag |= mysql.PriKeyFlag + tblInfo.Columns[col.Offset].AddFlag(mysql.PriKeyFlag) } return } col := indexInfo.Columns[0] if indexInfo.Unique && len(indexInfo.Columns) == 1 { - tblInfo.Columns[col.Offset].Flag |= mysql.UniqueKeyFlag + tblInfo.Columns[col.Offset].AddFlag(mysql.UniqueKeyFlag) } else { - tblInfo.Columns[col.Offset].Flag |= mysql.MultipleKeyFlag + tblInfo.Columns[col.Offset].AddFlag(mysql.MultipleKeyFlag) } } func dropIndexColumnFlag(tblInfo *model.TableInfo, indexInfo *model.IndexInfo) { if indexInfo.Primary { for _, col := range indexInfo.Columns { - tblInfo.Columns[col.Offset].Flag &= ^mysql.PriKeyFlag + tblInfo.Columns[col.Offset].DelFlag(mysql.PriKeyFlag) } } else if indexInfo.Unique && len(indexInfo.Columns) == 1 { - tblInfo.Columns[indexInfo.Columns[0].Offset].Flag &= ^mysql.UniqueKeyFlag + tblInfo.Columns[indexInfo.Columns[0].Offset].DelFlag(mysql.UniqueKeyFlag) } else { - tblInfo.Columns[indexInfo.Columns[0].Offset].Flag &= ^mysql.MultipleKeyFlag + tblInfo.Columns[indexInfo.Columns[0].Offset].DelFlag(mysql.MultipleKeyFlag) } col := indexInfo.Columns[0] @@ -299,7 +299,7 @@ func validateRenameIndex(from, to model.CIStr, tbl *model.TableInfo) (ignore boo return false, nil } -func onRenameIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onRenameIndex(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, from, to, err := checkRenameIndex(t, job) if err != nil || tblInfo == nil { return ver, errors.Trace(err) @@ -310,7 +310,7 @@ func onRenameIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { idx := tblInfo.FindIndexByName(from.L) idx.Name = to - if ver, err = updateVersionAndTableInfo(t, job, tblInfo, true); err != nil { + if ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } @@ -327,14 +327,14 @@ func validateAlterIndexVisibility(indexName model.CIStr, invisible bool, tbl *mo return false, nil } -func onAlterIndexVisibility(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onAlterIndexVisibility(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, from, invisible, err := checkAlterIndexVisibility(t, job) if err != nil || tblInfo == nil { return ver, errors.Trace(err) } idx := tblInfo.FindIndexByName(from.L) idx.Invisible = invisible - if ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, true); err != nil { + if ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, true); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } @@ -346,14 +346,14 @@ func getNullColInfos(tblInfo *model.TableInfo, indexInfo *model.IndexInfo) ([]*m nullCols := make([]*model.ColumnInfo, 0, len(indexInfo.Columns)) for _, colName := range indexInfo.Columns { col := model.FindColumnInfo(tblInfo.Columns, colName.Name.L) - if !mysql.HasNotNullFlag(col.Flag) || mysql.HasPreventNullInsertFlag(col.Flag) { + if !mysql.HasNotNullFlag(col.GetFlag()) || mysql.HasPreventNullInsertFlag(col.GetFlag()) { nullCols = append(nullCols, col) } } return nullCols, nil } -func checkPrimaryKeyNotNull(w *worker, sqlMode mysql.SQLMode, t *meta.Meta, job *model.Job, +func checkPrimaryKeyNotNull(d *ddlCtx, w *worker, sqlMode mysql.SQLMode, t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, indexInfo *model.IndexInfo) (warnings []string, err error) { if !indexInfo.Primary { return nil, nil @@ -375,7 +375,7 @@ func checkPrimaryKeyNotNull(w *worker, sqlMode mysql.SQLMode, t *meta.Meta, job if err == nil { return nil, nil } - _, err = convertAddIdxJob2RollbackJob(t, job, tblInfo, indexInfo, err) + _, err = convertAddIdxJob2RollbackJob(d, t, job, tblInfo, indexInfo, err) // TODO: Support non-strict mode. // warnings = append(warnings, ErrWarnDataTruncated.GenWithStackByArgs(oldCol.Name.L, 0).Error()) return nil, err @@ -392,7 +392,7 @@ func updateHiddenColumns(tblInfo *model.TableInfo, idxInfo *model.IndexInfo, sta func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK bool) (ver int64, err error) { // Handle the rolling back job. if job.IsRollingback() { - ver, err = onDropIndex(t, job) + ver, err = onDropIndex(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -518,7 +518,7 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo // none -> delete only indexInfo.State = model.StateDeleteOnly updateHiddenColumns(tblInfo, indexInfo, model.StatePublic) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, err } @@ -527,11 +527,11 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo case model.StateDeleteOnly: // delete only -> write only indexInfo.State = model.StateWriteOnly - _, err = checkPrimaryKeyNotNull(w, sqlMode, t, job, tblInfo, indexInfo) + _, err = checkPrimaryKeyNotNull(d, w, sqlMode, t, job, tblInfo, indexInfo) if err != nil { break } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, err } @@ -539,11 +539,11 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo case model.StateWriteOnly: // write only -> reorganization indexInfo.State = model.StateWriteReorganization - _, err = checkPrimaryKeyNotNull(w, sqlMode, t, job, tblInfo, indexInfo) + _, err = checkPrimaryKeyNotNull(d, w, sqlMode, t, job, tblInfo, indexInfo) if err != nil { break } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, err } @@ -571,7 +571,7 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo return ver, errors.Trace(err) } } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -608,7 +608,7 @@ func doReorgWorkForCreateIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Jo } if kv.ErrKeyExists.Equal(err) || dbterror.ErrCancelledDDLJob.Equal(err) || dbterror.ErrCantDecodeRecord.Equal(err) { logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err)) - ver, err = convertAddIdxJob2RollbackJob(t, job, tbl.Meta(), indexInfo, err) + ver, err = convertAddIdxJob2RollbackJob(d, t, job, tbl.Meta(), indexInfo, err) if err1 := t.RemoveDDLReorgHandle(job, reorgInfo.elements); err1 != nil { logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback, RemoveDDLReorgHandle failed", zap.String("job", job.String()), zap.Error(err1)) } @@ -622,7 +622,7 @@ func doReorgWorkForCreateIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Jo return true, ver, errors.Trace(err) } -func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropIndex(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, indexInfo, err := checkDropIndex(t, job) if err != nil { return ver, errors.Trace(err) @@ -643,29 +643,27 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { case model.StatePublic: // public -> write only indexInfo.State = model.StateWriteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateWriteOnly case model.StateWriteOnly: // write only -> delete only indexInfo.State = model.StateDeleteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateDeleteOnly case model.StateDeleteOnly: // delete only -> reorganization indexInfo.State = model.StateDeleteReorganization - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateDeleteReorganization case model.StateDeleteReorganization: // reorganization -> absent + indexInfo.State = model.StateNone if len(dependentHiddenCols) > 0 { firstHiddenOffset := dependentHiddenCols[0].Offset for i := 0; i < len(dependentHiddenCols); i++ { @@ -673,7 +671,6 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { adjustColumnInfoInDropColumn(tblInfo, firstHiddenOffset) } } - newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) for _, idx := range tblInfo.Indices { if idx.Name.L != indexInfo.Name.L { @@ -691,7 +688,7 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { } }) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != model.StateNone) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != model.StateNone) if err != nil { return ver, errors.Trace(err) } @@ -707,8 +704,9 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.Args = append(job.Args, indexInfo.ID, getPartitionIDs(tblInfo)) } default: - err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) + return ver, errors.Trace(dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State)) } + job.SchemaState = indexInfo.State return ver, errors.Trace(err) } @@ -746,7 +744,7 @@ func checkDropIndex(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.Inde return tblInfo, indexInfo, nil } -func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropIndexes(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, indexNames, ifExists, err := getSchemaInfos(t, job) if err != nil { return ver, errors.Trace(err) @@ -783,7 +781,7 @@ func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { for _, colInfo := range dependentHiddenCols { adjustColumnInfoInDropColumn(tblInfo, colInfo.Offset) } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -792,7 +790,7 @@ func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { // write only -> delete only setIndicesState(indexInfos, model.StateDeleteOnly) setColumnsState(dependentHiddenCols, model.StateDeleteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -801,7 +799,7 @@ func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { // delete only -> reorganization setIndicesState(indexInfos, model.StateDeleteReorganization) setColumnsState(dependentHiddenCols, model.StateDeleteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -830,7 +828,7 @@ func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-len(dependentHiddenCols)] - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != model.StateNone) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, originalState != model.StateNone) if err != nil { return ver, errors.Trace(err) } @@ -932,7 +930,7 @@ func checkInvisibleIndexesOnPK(tblInfo *model.TableInfo, indexInfos []*model.Ind func checkDropIndexOnAutoIncrementColumn(tblInfo *model.TableInfo, indexInfo *model.IndexInfo) error { cols := tblInfo.Columns for _, idxCol := range indexInfo.Columns { - flag := cols[idxCol.Offset].Flag + flag := cols[idxCol.Offset].GetFlag() if !mysql.HasAutoIncrementFlag(flag) { continue } diff --git a/ddl/index_modify_test.go b/ddl/index_modify_test.go index 8a615fb4de80a..ca1b9033aa892 100644 --- a/ddl/index_modify_test.go +++ b/ddl/index_modify_test.go @@ -29,11 +29,9 @@ import ( "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" testddlutil "github.com/pingcap/tidb/ddl/testutil" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" @@ -42,10 +40,8 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/dbterror" - "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -677,214 +673,6 @@ func TestAddIndexWithPK(t *testing.T) { } } -func TestCancelAddPrimaryKey(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) - defer clean() - idxName := "primary" - addIdxSQL := "alter table t1 add primary key idx_c2 (c2);" - testCancelAddIndex(t, store, dom, idxName, addIdxSQL) - - // Check the column's flag when the "add primary key" failed. - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - require.NoError(t, tk.Session().NewTxn(context.Background())) - tbl := external.GetTableByName(t, tk, "test", "t1") - col1Flag := tbl.Cols()[1].Flag - require.True(t, !mysql.HasNotNullFlag(col1Flag) && !mysql.HasPreventNullInsertFlag(col1Flag) && mysql.HasUnsignedFlag(col1Flag)) -} - -func TestCancelAddIndex(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) - defer clean() - idxName := "c3_index" - addIdxSQL := "create unique index c3_index on t1 (c3)" - testCancelAddIndex(t, store, dom, idxName, addIdxSQL) -} - -func testCancelAddIndex(t *testing.T, store kv.Storage, dom *domain.Domain, idxName, addIdxSQL string) { - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create table t1 (c1 int, c2 int unsigned, c3 int, unique key(c1))") - - d := dom.DDL() - - // defaultBatchSize is equal to ddl.defaultBatchSize - count := defaultBatchSize * 32 - start := 0 - for i := start; i < count; i += defaultBatchSize { - batchInsert(tk, "t1", i, i+defaultBatchSize) - } - - hook := &ddl.TestDDLCallback{Do: dom} - originBatchSize := tk.MustQuery("select @@global.tidb_ddl_reorg_batch_size") - // Set batch size to lower try to slow down add-index reorganization, This if for hook to cancel this ddl job. - tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 32") - defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", originBatchSize.Rows()[0][0])) - // let hook.OnJobUpdatedExported has chance to cancel the job. - // the hook.OnJobUpdatedExported is called when the job is updated, runReorgJob will wait ddl.ReorgWaitTimeout, then return the ddl.runDDLJob. - // After that ddl call d.hook.OnJobUpdated(job), so that we can canceled the job in this test case. - var checkErr error - hook.OnJobUpdatedExported, _, checkErr = backgroundExecOnJobUpdatedExported(t, tk, store, hook, idxName) - originalHook := d.GetHook() - jobIDExt := wrapJobIDExtCallback(hook) - d.SetHook(jobIDExt) - done := make(chan error, 1) - go backgroundExec(store, addIdxSQL, done) - - times := 0 - ticker := time.NewTicker(indexModifyLease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - require.NoError(t, checkErr) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - break LOOP - case <-ticker.C: - if times >= 10 { - break - } - step := 5 - // delete some rows, and add some data - for i := count; i < count+step; i++ { - n := rand.Intn(count) - tk.MustExec("delete from t1 where c1 = ?", n) - tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) - } - count += step - times++ - } - } - d.SetHook(originalHook) -} - -func backgroundExecOnJobUpdatedExported(t *testing.T, tk *testkit.TestKit, store kv.Storage, hook *ddl.TestDDLCallback, idxName string) (func(*model.Job), *model.IndexInfo, error) { - var checkErr error - first := true - c3IdxInfo := &model.IndexInfo{} - hook.OnJobUpdatedExported = func(job *model.Job) { - addIndexNotFirstReorg := (job.Type == model.ActionAddIndex || job.Type == model.ActionAddPrimaryKey) && - job.SchemaState == model.StateWriteReorganization && job.SnapshotVer != 0 - // If the action is adding index and the state is writing reorganization, it want to test the case of cancelling the job when backfilling indexes. - // When the job satisfies this case of addIndexNotFirstReorg, the worker will start to backfill indexes. - if !addIndexNotFirstReorg { - // Get the index's meta. - if c3IdxInfo.ID != 0 { - return - } - tbl := external.GetTableByName(t, tk, "test", "t1") - for _, index := range tbl.Indices() { - if !tables.IsIndexWritable(index) { - continue - } - if index.Meta().Name.L == idxName { - *c3IdxInfo = *index.Meta() - } - } - return - } - // The job satisfies the case of addIndexNotFirst for the first time, the worker hasn't finished a batch of backfill indexes. - if first { - first = false - return - } - if checkErr != nil { - return - } - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - jobIDs := []int64{job.ID} - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - // It only tests cancel one DDL job. - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - txn, err = hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - err = txn.Commit(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } - } - return hook.OnJobUpdatedExported, c3IdxInfo, checkErr -} - -// TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started. -func TestCancelAddIndex1(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create table t(c1 int, c2 int)") - for i := 0; i < 50; i++ { - tk.MustExec("insert into t values (?, ?)", i, i) - } - - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - - checkErr = txn.Commit(context.Background()) - } - } - originalHook := dom.DDL().GetHook() - dom.DDL().SetHook(hook) - err := tk.ExecToErr("alter table t add index idx_c2(c2)") - require.NoError(t, checkErr) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - - dom.DDL().SetHook(originalHook) - tbl := external.GetTableByName(t, tk, "test", "t") - for _, idx := range tbl.Indices() { - require.False(t, strings.EqualFold(idx.Meta().Name.L, "idx_c2")) - } - tk.MustExec("alter table t add index idx_c2(c2)") - tk.MustExec("alter table t drop index idx_c2") -} - func TestAddGlobalIndex(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { @@ -1018,7 +806,7 @@ func checkGlobalIndexRow( } func TestDropIndexes(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) defer clean() // drop multiple indexes createSQL := "create table test_drop_indexes (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));" @@ -1038,7 +826,6 @@ func TestDropIndexes(t *testing.T) { testDropIndexesIfExists(t, store) testDropIndexesFromPartitionedTable(t, store) - testCancelDropIndexes(t, store, dom.DDL()) } func testDropIndexes(t *testing.T, store kv.Storage, createSQL, dropIdxSQL string, idxNames []string) { @@ -1128,100 +915,6 @@ func testDropIndexesFromPartitionedTable(t *testing.T, store kv.Storage) { tk.MustExec("alter table test_drop_indexes_from_partitioned_table drop column c1, drop column if exists c1;") } -func testCancelDropIndexes(t *testing.T, store kv.Storage, d ddl.DDL) { - indexesName := []string{"idx_c1", "idx_c2"} - addIdxesSQL := "alter table t add index idx_c1 (c1);alter table t add index idx_c2 (c2);" - dropIdxesSQL := "alter table t drop index idx_c1;alter table t drop index idx_c2;" - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(c1 int, c2 int)") - defer tk.MustExec("drop table t;") - for i := 0; i < 5; i++ { - tk.MustExec("insert into t values (?, ?)", i, i) - } - testCases := []struct { - needAddIndex bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - // model.JobStateNone means the jobs is canceled before the first run. - // if we cancel successfully, we need to set needAddIndex to false in the next test case. Otherwise, set needAddIndex to true. - {true, model.JobStateQueueing, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if (job.Type == model.ActionDropIndex || job.Type == model.ActionDropPrimaryKey) && - job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobID = job.ID - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := d.GetHook() - d.SetHook(hook) - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddIndex { - tk.MustExec(addIdxesSQL) - } - err := tk.ExecToErr(dropIdxesSQL) - tbl := external.GetTableByName(t, tk, "test", "t") - - var indexInfos []*model.IndexInfo - for _, idxName := range indexesName { - indexInfo := tbl.Meta().FindIndexByName(idxName) - if indexInfo != nil { - indexInfos = append(indexInfos, indexInfo) - } - } - - if testCase.cancelSucc { - require.NoError(t, checkErr) - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - require.NotNil(t, indexInfos) - require.Equal(t, model.StatePublic, indexInfos[0].State) - } else { - require.NoError(t, err) - require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - require.Nil(t, indexInfos) - } - } - d.SetHook(originalHook) - tk.MustExec(addIdxesSQL) - tk.MustExec(dropIdxesSQL) -} - func TestDropPrimaryKey(t *testing.T) { store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) defer clean() diff --git a/ddl/integration_test.go b/ddl/integration_test.go index 0ecd18baa2660..34edd8dfe34d6 100644 --- a/ddl/integration_test.go +++ b/ddl/integration_test.go @@ -118,13 +118,6 @@ func TestDDLStatementsBackFill(t *testing.T) { } } -func TestSchema(t *testing.T) { - _, clean := testkit.CreateMockStore(t) - defer clean() - - ddl.ExportTestSchema(t) -} - func TestDDLOnCachedTable(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/ddl/main_test.go b/ddl/main_test.go index c944d92799902..16e547954ea50 100644 --- a/ddl/main_test.go +++ b/ddl/main_test.go @@ -26,7 +26,6 @@ import ( "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/meta/autoid" - "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/util/testbridge" "github.com/tikv/client-go/v2/tikv" "go.uber.org/goleak" @@ -46,7 +45,7 @@ func TestMain(m *testing.M) { config.UpdateGlobal(func(conf *config.Config) { // Test for table lock. conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 + conf.Instance.SlowThreshold = 10000 conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true @@ -66,24 +65,3 @@ func TestMain(m *testing.M) { goleak.VerifyTestMain(m, opts...) } - -func wrapJobIDExtCallback(oldCallback ddl.Callback) *testDDLJobIDCallback { - return &testDDLJobIDCallback{ - Callback: oldCallback, - jobID: 0, - } -} - -type testDDLJobIDCallback struct { - ddl.Callback - jobID int64 -} - -func (t *testDDLJobIDCallback) OnJobUpdated(job *model.Job) { - if t.jobID == 0 { - t.jobID = job.ID - } - if t.Callback != nil { - t.Callback.OnJobUpdated(job) - } -} diff --git a/ddl/modify_column_test.go b/ddl/modify_column_test.go index 8c68b74b25aad..6e428c40be379 100644 --- a/ddl/modify_column_test.go +++ b/ddl/modify_column_test.go @@ -21,7 +21,6 @@ import ( "testing" "time" - "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/errno" @@ -30,10 +29,8 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -229,8 +226,8 @@ func TestModifyColumnNullToNotNull(t *testing.T) { require.EqualError(t, checkErr, "[table:1048]Column 'c2' cannot be null") c2 := external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) - require.True(t, mysql.HasNotNullFlag(c2.Flag)) - require.False(t, mysql.HasPreventNullInsertFlag(c2.Flag)) + require.True(t, mysql.HasNotNullFlag(c2.GetFlag())) + require.False(t, mysql.HasPreventNullInsertFlag(c2.GetFlag())) err = tk1.ExecToErr("insert into t1 values ();") require.EqualError(t, err, "[table:1364]Field 'c2' doesn't have a default value") } @@ -285,12 +282,12 @@ func TestModifyColumnNullToNotNullWithChangingVal(t *testing.T) { require.EqualError(t, checkErr, "[table:1048]Column 'c2' cannot be null") c2 := external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) - require.True(t, mysql.HasNotNullFlag(c2.Flag)) - require.False(t, mysql.HasPreventNullInsertFlag(c2.Flag)) + require.True(t, mysql.HasNotNullFlag(c2.GetFlag())) + require.False(t, mysql.HasPreventNullInsertFlag(c2.GetFlag())) require.EqualError(t, tk1.ExecToErr("insert into t1 values ()"), "[table:1364]Field 'c2' doesn't have a default value") c2 = external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) - require.Equal(t, mysql.TypeTiny, c2.FieldType.Tp) + require.Equal(t, mysql.TypeTiny, c2.FieldType.GetType()) } func TestModifyColumnBetweenStringTypes(t *testing.T) { @@ -304,7 +301,7 @@ func TestModifyColumnBetweenStringTypes(t *testing.T) { tk.MustExec("insert into tt values ('111'),('10000');") tk.MustExec("alter table tt change a a varchar(5);") mvc := external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, 5, mvc.FieldType.Flen) + require.Equal(t, 5, mvc.FieldType.GetFlen()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) tk.MustGetErrMsg("alter table tt change a a varchar(4);", "[types:1265]Data truncated for column 'a', value is '10000'") tk.MustExec("alter table tt change a a varchar(100);") @@ -316,7 +313,7 @@ func TestModifyColumnBetweenStringTypes(t *testing.T) { tk.MustExec("insert into tt values ('111'),('10000');") tk.MustExec("alter table tt change a a char(5);") mc := external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, 5, mc.FieldType.Flen) + require.Equal(t, 5, mc.FieldType.GetFlen()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") tk.MustExec("alter table tt change a a char(100);") @@ -328,7 +325,7 @@ func TestModifyColumnBetweenStringTypes(t *testing.T) { tk.MustExec("insert into tt values ('111'),('10000');") tk.MustGetErrMsg("alter table tt change a a binary(5);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") mb := external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, 10, mb.FieldType.Flen) + require.Equal(t, 10, mb.FieldType.GetFlen()) tk.MustQuery("select * from tt").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00", "10000\x00\x00\x00\x00\x00")) tk.MustGetErrMsg("alter table tt change a a binary(4);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") tk.MustExec("alter table tt change a a binary(12);") @@ -341,7 +338,7 @@ func TestModifyColumnBetweenStringTypes(t *testing.T) { tk.MustExec("insert into tt values ('111'),('10000');") tk.MustExec("alter table tt change a a varbinary(5);") mvb := external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, 5, mvb.FieldType.Flen) + require.Equal(t, 5, mvb.FieldType.GetFlen()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) tk.MustGetErrMsg("alter table tt change a a varbinary(4);", "[types:1265]Data truncated for column 'a', value is '10000'") tk.MustExec("alter table tt change a a varbinary(12);") @@ -355,34 +352,34 @@ func TestModifyColumnBetweenStringTypes(t *testing.T) { tk.MustExec("alter table tt change a a char(10);") c2 := external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, mysql.TypeString, c2.FieldType.Tp) - require.Equal(t, 10, c2.FieldType.Flen) + require.Equal(t, mysql.TypeString, c2.FieldType.GetType()) + require.Equal(t, 10, c2.FieldType.GetFlen()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") // char to text tk.MustExec("alter table tt change a a text;") c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, mysql.TypeBlob, c2.FieldType.Tp) + require.Equal(t, mysql.TypeBlob, c2.FieldType.GetType()) // text to set tk.MustGetErrMsg("alter table tt change a a set('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") tk.MustExec("alter table tt change a a set('111', '10000');") c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, mysql.TypeSet, c2.FieldType.Tp) + require.Equal(t, mysql.TypeSet, c2.FieldType.GetType()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) // set to set tk.MustExec("alter table tt change a a set('10000', '111');") c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, mysql.TypeSet, c2.FieldType.Tp) + require.Equal(t, mysql.TypeSet, c2.FieldType.GetType()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) // set to enum tk.MustGetErrMsg("alter table tt change a a enum('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") tk.MustExec("alter table tt change a a enum('111', '10000');") c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) - require.Equal(t, mysql.TypeEnum, c2.FieldType.Tp) + require.Equal(t, mysql.TypeEnum, c2.FieldType.GetType()) tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) tk.MustExec("alter table tt change a a enum('10000', '111');") tk.MustQuery("select * from tt where a = 1").Check(testkit.Rows("10000")) @@ -908,82 +905,3 @@ func TestModifyColumnTypeWhenInterception(t *testing.T) { res := tk.MustQuery("show warnings") require.Len(t, res.Rows(), count) } - -func TestModifyColumnRollBack(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int default 1, index (c1))") - - var c2 *table.Column - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - hook.OnJobUpdatedExported = func(job *model.Job) { - if checkErr != nil { - return - } - - tbl := external.GetTableByName(t, tk, "test", "t1") - for _, col := range tbl.Cols() { - if col.Name.L == "c2" { - c2 = col - } - } - if mysql.HasPreventNullInsertFlag(c2.Flag) { - tk.MustGetErrCode("insert into t1(c2) values (null);", errno.ErrBadNull) - } - - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - - jobIDs := []int64{job.ID} - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - // It only tests cancel one DDL job. - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - - txn, err = hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - err = txn.Commit(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } - } - - dom.DDL().SetHook(hook) - done := make(chan error, 1) - go backgroundExec(store, "alter table test.t1 change c2 c2 bigint not null;", done) - - err := <-done - require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") - tk.MustExec("insert into t1(c2) values (null);") - - tbl := external.GetTableByName(t, tk, "test", "t1") //nolint:typecheck - for _, col := range tbl.Cols() { - if col.Name.L == "c2" { - c2 = col - } - } - require.False(t, mysql.HasNotNullFlag(c2.Flag)) - tk.MustExec("drop table t1") -} diff --git a/ddl/partition.go b/ddl/partition.go index 9f39e1212dc5a..d024ef47b4b43 100644 --- a/ddl/partition.go +++ b/ddl/partition.go @@ -22,7 +22,6 @@ import ( "strings" "time" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/metapb" @@ -51,6 +50,7 @@ import ( "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/slice" "github.com/pingcap/tidb/util/sqlexec" "github.com/tikv/client-go/v2/tikv" @@ -121,7 +121,7 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v // move the adding definition into tableInfo. updateAddingPartitionInfo(partInfo, tblInfo) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -172,7 +172,7 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v // be finished. Otherwise the query to this partition will be blocked. needRetry, err := checkPartitionReplica(tblInfo.TiFlashReplica.Count, addingDefinitions, d) if err != nil { - ver, err = convertAddTablePartitionJob2RollbackJob(t, job, err, tblInfo) + ver, err = convertAddTablePartitionJob2RollbackJob(d, t, job, err, tblInfo) return ver, err } if needRetry { @@ -193,7 +193,7 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v // For normal and replica finished table, move the `addingDefinitions` into `Definitions`. updatePartitionInfo(tblInfo) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -625,7 +625,11 @@ func buildRangePartitionDefinitions(ctx sessionctx.Context, defs []*ast.Partitio } } comment, _ := def.Comment() - err := checkTooLongTable(def.Name) + comment, err := validateCommentLength(ctx.GetSessionVars(), def.Name.L, &comment, dbterror.ErrTooLongTablePartitionComment) + if err != nil { + return nil, err + } + err = checkTooLongTable(def.Name) if err != nil { return nil, err } @@ -657,7 +661,7 @@ func buildRangePartitionDefinitions(ctx sessionctx.Context, defs []*ast.Partitio func checkPartitionValuesIsInt(ctx sessionctx.Context, def *ast.PartitionDefinition, exprs []ast.ExprNode, tbInfo *model.TableInfo) error { tp := types.NewFieldType(mysql.TypeLonglong) if isColUnsigned(tbInfo.Columns, tbInfo.Partition) { - tp.Flag |= mysql.UnsignedFlag + tp.AddFlag(mysql.UnsignedFlag) } for _, exp := range exprs { if _, ok := exp.(*ast.MaxValueExpr); ok { @@ -670,7 +674,7 @@ func checkPartitionValuesIsInt(ctx sessionctx.Context, def *ast.PartitionDefinit switch val.Kind() { case types.KindUint64, types.KindNull: case types.KindInt64: - if mysql.HasUnsignedFlag(tp.Flag) && val.GetInt64() < 0 { + if mysql.HasUnsignedFlag(tp.GetFlag()) && val.GetInt64() < 0 { return dbterror.ErrPartitionConstDomain.GenWithStackByArgs() } default: @@ -876,7 +880,7 @@ func formatListPartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) if len(pi.Columns) == 0 { tp := types.NewFieldType(mysql.TypeLonglong) if isColUnsigned(tblInfo.Columns, tblInfo.Partition) { - tp.Flag |= mysql.UnsignedFlag + tp.AddFlag(mysql.UnsignedFlag) } colTps = []*types.FieldType{tp} } else { @@ -913,7 +917,7 @@ func formatListPartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) defs[i].InValues[j][k] = s } if colTps[k].EvalType() == types.ETString { - s = string(hack.String(collate.GetCollator(cols[k].Collate).Key(s))) + s = string(hack.String(collate.GetCollator(cols[k].GetCollate()).Key(s))) } s = strings.ReplaceAll(s, ",", `\,`) inValueStrs = append(inValueStrs, s) @@ -1105,7 +1109,7 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( return ver, err } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1115,10 +1119,6 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( } var physicalTableIDs []int64 - if job.State == model.JobStateRunning && job.SchemaState == model.StateNone { - // Manually set first state. - job.SchemaState = model.StatePublic - } // In order to skip maintaining the state check in partitionDefinition, TiDB use droppingDefinition instead of state field. // So here using `job.SchemaState` to judge what the stage of this job is. originalState := job.SchemaState @@ -1143,13 +1143,13 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( } job.SchemaState = model.StateDeleteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != job.SchemaState) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != job.SchemaState) case model.StateDeleteOnly: // This state is not a real 'DeleteOnly' state, because tidb does not maintaining the state check in partitionDefinition. // Insert this state to confirm all servers can not see the old partitions when reorg is running, // so that no new data will be inserted into old partitions when reorganizing. job.SchemaState = model.StateDeleteReorganization - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != job.SchemaState) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != job.SchemaState) case model.StateDeleteReorganization: oldTblInfo := getTableInfoWithDroppingPartitions(tblInfo) physicalTableIDs = getPartitionIDsFromDefinitions(tblInfo.Partition.DroppingDefinitions) @@ -1195,10 +1195,11 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( tblInfo.Partition.DroppingDefinitions = nil // used by ApplyDiff in updateSchemaVersion job.CtxVars = []interface{}{physicalTableIDs} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } + job.SchemaState = model.StateNone job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) asyncNotifyEvent(d, &util.Event{Tp: model.ActionDropTablePartition, TableInfo: tblInfo, PartInfo: &model.PartitionInfo{Definitions: tblInfo.Partition.Definitions}}) // A background job will be created to delete old partition data. @@ -1321,7 +1322,7 @@ func onTruncateTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, e newIDs[i] = newPartitions[i].ID } job.CtxVars = []interface{}{oldIDs, newIDs} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1458,9 +1459,9 @@ func (w *worker) onExchangeTablePartition(d *ddlCtx, t *meta.Meta, job *model.Jo // Set both tables to the maximum auto IDs between normal table and partitioned table. newAutoIDs := meta.AutoIDGroup{ - RowID: mathutil.MaxInt64(ptAutoIDs.RowID, ntAutoIDs.RowID), - IncrementID: mathutil.MaxInt64(ptAutoIDs.IncrementID, ntAutoIDs.IncrementID), - RandomID: mathutil.MaxInt64(ptAutoIDs.RandomID, ntAutoIDs.RandomID), + RowID: mathutil.Max(ptAutoIDs.RowID, ntAutoIDs.RowID), + IncrementID: mathutil.Max(ptAutoIDs.IncrementID, ntAutoIDs.IncrementID), + RandomID: mathutil.Max(ptAutoIDs.RandomID, ntAutoIDs.RandomID), } err = t.GetAutoIDAccessors(ptSchemaID, pt.ID).Put(newAutoIDs) if err != nil { @@ -1523,7 +1524,7 @@ func (w *worker) onExchangeTablePartition(d *ddlCtx, t *meta.Meta, job *model.Jo return ver, errors.Wrapf(err, "failed to notify PD the label rules") } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -1946,7 +1947,7 @@ func (cns columnNameSlice) At(i int) string { // isColUnsigned returns true if the partitioning key column is unsigned. func isColUnsigned(cols []*model.ColumnInfo, pi *model.PartitionInfo) bool { for _, col := range cols { - isUnsigned := mysql.HasUnsignedFlag(col.Flag) + isUnsigned := mysql.HasUnsignedFlag(col.GetFlag()) if isUnsigned && strings.Contains(strings.ToLower(pi.Expr), col.Name.L) { return true } @@ -2097,7 +2098,7 @@ func collectArgsType(tblInfo *model.TableInfo, exprs ...ast.ExprNode) ([]byte, e if columnInfo == nil { return nil, errors.Trace(dbterror.ErrBadField.GenWithStackByArgs(col.Name.Name.L, "partition function")) } - ts = append(ts, columnInfo.Tp) + ts = append(ts, columnInfo.GetType()) } return ts, nil diff --git a/ddl/partition_test.go b/ddl/partition_test.go index 4484dcb07dde8..7bbccee4189d8 100644 --- a/ddl/partition_test.go +++ b/ddl/partition_test.go @@ -12,65 +12,57 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( - "context" "testing" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) func TestDropAndTruncatePartition(t *testing.T) { - store, err := mockstore.NewMockStore() - require.NoError(t, err) - defer func() { - require.NoError(t, store.Close()) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() - dbInfo, err := testSchemaInfo(d, "test_partition") + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + + d := domain.DDL() + dbInfo, err := testSchemaInfo(store, "test_partition") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo) // generate 5 partition in tableInfo. - tblInfo, partIDs := buildTableInfoWithPartition(t, d) - ctx := testNewContext(d) + tblInfo, partIDs := buildTableInfoWithPartition(t, store) + ctx := testkit.NewTestKit(t, store).Session() testCreateTable(t, ctx, d, dbInfo, tblInfo) testDropPartition(t, ctx, d, dbInfo, tblInfo, []string{"p0", "p1"}) testTruncatePartition(t, ctx, d, dbInfo, tblInfo, []int64{partIDs[3], partIDs[4]}) } -func buildTableInfoWithPartition(t *testing.T, d *ddl) (*model.TableInfo, []int64) { +func buildTableInfoWithPartition(t *testing.T, store kv.Storage) (*model.TableInfo, []int64) { tbl := &model.TableInfo{ Name: model.NewCIStr("t"), } + tbl.MaxColumnID++ col := &model.ColumnInfo{ Name: model.NewCIStr("c"), Offset: 0, State: model.StatePublic, FieldType: *types.NewFieldType(mysql.TypeLong), - ID: allocateColumnID(tbl), + ID: tbl.MaxColumnID, } - genIDs, err := d.genGlobalIDs(1) + genIDs, err := genGlobalIDs(store, 1) require.NoError(t, err) tbl.ID = genIDs[0] tbl.Columns = []*model.ColumnInfo{col} tbl.Charset = "utf8" tbl.Collate = "utf8_bin" - partIDs, err := d.genGlobalIDs(5) + partIDs, err := genGlobalIDs(store, 5) require.NoError(t, err) partInfo := &model.PartitionInfo{ Type: model.PartitionTypeRange, @@ -110,15 +102,16 @@ func buildTableInfoWithPartition(t *testing.T, d *ddl) (*model.TableInfo, []int6 func buildDropPartitionJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, partNames []string) *model.Job { return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropTablePartition, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{partNames}, + SchemaID: dbInfo.ID, + TableID: tblInfo.ID, + SchemaState: model.StatePublic, + Type: model.ActionDropTablePartition, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{partNames}, } } -func testDropPartition(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, partNames []string) *model.Job { +func testDropPartition(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo, tblInfo *model.TableInfo, partNames []string) *model.Job { job := buildDropPartitionJob(dbInfo, tblInfo, partNames) ctx.SetValue(sessionctx.QueryString, "skip") err := d.DoDDLJob(ctx, job) @@ -138,7 +131,7 @@ func buildTruncatePartitionJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, p } } -func testTruncatePartition(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, pids []int64) *model.Job { +func testTruncatePartition(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo, tblInfo *model.TableInfo, pids []int64) *model.Job { job := buildTruncatePartitionJob(dbInfo, tblInfo, pids) ctx.SetValue(sessionctx.QueryString, "skip") err := d.DoDDLJob(ctx, job) diff --git a/ddl/placement_policy.go b/ddl/placement_policy.go index 601b382cbeadf..e38797fb22a9e 100644 --- a/ddl/placement_policy.go +++ b/ddl/placement_policy.go @@ -61,7 +61,7 @@ func onCreatePlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64 } job.SchemaID = replacePolicy.ID - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -80,7 +80,7 @@ func onCreatePlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64 } job.SchemaID = policyInfo.ID - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -198,7 +198,7 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, if err != nil { return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -211,7 +211,7 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, if err != nil { return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -222,7 +222,7 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, if err = t.DropPolicy(policyInfo.ID); err != nil { return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -234,7 +234,7 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, return ver, errors.Trace(err) } -func onAlterPlacementPolicy(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onAlterPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { alterPolicy := &model.PolicyInfo{} if err := job.DecodeArgs(alterPolicy); err != nil { job.State = model.JobStateCancelled @@ -259,7 +259,7 @@ func onAlterPlacementPolicy(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -320,13 +320,14 @@ func checkPlacementPolicyNotInUse(d *ddlCtx, t *meta.Meta, policy *model.PolicyI } is := d.infoCache.GetLatest() if is.SchemaMetaVersion() == currVer { - return checkPlacementPolicyNotInUseFromInfoSchema(is, policy) + return CheckPlacementPolicyNotInUseFromInfoSchema(is, policy) } - return checkPlacementPolicyNotInUseFromMeta(t, policy) + return CheckPlacementPolicyNotInUseFromMeta(t, policy) } -func checkPlacementPolicyNotInUseFromInfoSchema(is infoschema.InfoSchema, policy *model.PolicyInfo) error { +// CheckPlacementPolicyNotInUseFromInfoSchema export for test. +func CheckPlacementPolicyNotInUseFromInfoSchema(is infoschema.InfoSchema, policy *model.PolicyInfo) error { for _, dbInfo := range is.AllSchemas() { if ref := dbInfo.PlacementPolicyRef; ref != nil && ref.ID == policy.ID { return dbterror.ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) @@ -375,7 +376,8 @@ func getPlacementPolicyDependedObjectsIDs(t *meta.Meta, policy *model.PolicyInfo return dbIDs, partIDs, tblInfos, nil } -func checkPlacementPolicyNotInUseFromMeta(t *meta.Meta, policy *model.PolicyInfo) error { +// CheckPlacementPolicyNotInUseFromMeta export for test. +func CheckPlacementPolicyNotInUseFromMeta(t *meta.Meta, policy *model.PolicyInfo) error { schemas, err := t.ListDatabases() if err != nil { return err diff --git a/ddl/placement_policy_ddl_test.go b/ddl/placement_policy_ddl_test.go index 79db746a8463c..6525ad6a2b092 100644 --- a/ddl/placement_policy_ddl_test.go +++ b/ddl/placement_policy_ddl_test.go @@ -11,33 +11,35 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" "testing" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/dbterror" "github.com/stretchr/testify/require" ) -func testPlacementPolicyInfo(t *testing.T, d *ddl, name string, settings *model.PlacementSettings) *model.PolicyInfo { +func testPlacementPolicyInfo(t *testing.T, store kv.Storage, name string, settings *model.PlacementSettings) *model.PolicyInfo { policy := &model.PolicyInfo{ Name: model.NewCIStr(name), PlacementSettings: settings, } - genIDs, err := d.genGlobalIDs(1) + genIDs, err := genGlobalIDs(store, 1) require.NoError(t, err) policy.ID = genIDs[0] return policy } -func testCreatePlacementPolicy(t *testing.T, ctx sessionctx.Context, d *ddl, policyInfo *model.PolicyInfo) *model.Job { +func testCreatePlacementPolicy(t *testing.T, ctx sessionctx.Context, d ddl.DDL, policyInfo *model.PolicyInfo) *model.Job { job := &model.Job{ SchemaName: policyInfo.Name.L, Type: model.ActionCreatePlacementPolicy, @@ -56,69 +58,62 @@ func testCreatePlacementPolicy(t *testing.T, ctx sessionctx.Context, d *ddl, pol } func TestPlacementPolicyInUse(t *testing.T) { - store := createMockStore(t) - defer func() { - require.NoError(t, store.Close()) - }() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + d := dom.DDL() - ctx := context.Background() - d, err := testNewDDLAndStart(ctx, WithStore(store)) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() - sctx := testNewContext(d) + sctx := testkit.NewTestKit(t, store).Session() - db1, err := testSchemaInfo(d, "db1") + db1, err := testSchemaInfo(store, "db1") require.NoError(t, err) testCreateSchema(t, sctx, d, db1) db1.State = model.StatePublic - db2, err := testSchemaInfo(d, "db2") + db2, err := testSchemaInfo(store, "db2") require.NoError(t, err) testCreateSchema(t, sctx, d, db2) db2.State = model.StatePublic policySettings := &model.PlacementSettings{PrimaryRegion: "r1", Regions: "r1,r2"} - p1 := testPlacementPolicyInfo(t, d, "p1", policySettings) - p2 := testPlacementPolicyInfo(t, d, "p2", policySettings) - p3 := testPlacementPolicyInfo(t, d, "p3", policySettings) - p4 := testPlacementPolicyInfo(t, d, "p4", policySettings) - p5 := testPlacementPolicyInfo(t, d, "p5", policySettings) + p1 := testPlacementPolicyInfo(t, store, "p1", policySettings) + p2 := testPlacementPolicyInfo(t, store, "p2", policySettings) + p3 := testPlacementPolicyInfo(t, store, "p3", policySettings) + p4 := testPlacementPolicyInfo(t, store, "p4", policySettings) + p5 := testPlacementPolicyInfo(t, store, "p5", policySettings) testCreatePlacementPolicy(t, sctx, d, p1) testCreatePlacementPolicy(t, sctx, d, p2) testCreatePlacementPolicy(t, sctx, d, p3) testCreatePlacementPolicy(t, sctx, d, p4) testCreatePlacementPolicy(t, sctx, d, p5) - t1, err := testTableInfo(d, "t1", 1) + t1, err := testTableInfo(store, "t1", 1) require.NoError(t, err) t1.PlacementPolicyRef = &model.PolicyRefInfo{ID: p1.ID, Name: p1.Name} testCreateTable(t, sctx, d, db1, t1) t1.State = model.StatePublic db1.Tables = append(db1.Tables, t1) - t2, err := testTableInfo(d, "t2", 1) + t2, err := testTableInfo(store, "t2", 1) require.NoError(t, err) t2.PlacementPolicyRef = &model.PolicyRefInfo{ID: p1.ID, Name: p1.Name} testCreateTable(t, sctx, d, db2, t2) t2.State = model.StatePublic db2.Tables = append(db2.Tables, t2) - t3, err := testTableInfo(d, "t3", 1) + t3, err := testTableInfo(store, "t3", 1) require.NoError(t, err) t3.PlacementPolicyRef = &model.PolicyRefInfo{ID: p2.ID, Name: p2.Name} testCreateTable(t, sctx, d, db1, t3) t3.State = model.StatePublic db1.Tables = append(db1.Tables, t3) - dbP, err := testSchemaInfo(d, "db_p") + dbP, err := testSchemaInfo(store, "db_p") require.NoError(t, err) dbP.PlacementPolicyRef = &model.PolicyRefInfo{ID: p4.ID, Name: p4.Name} dbP.State = model.StatePublic testCreateSchema(t, sctx, d, dbP) - t4 := testTableInfoWithPartition(t, d, "t4", 1) + t4 := testTableInfoWithPartition(t, store, "t4", 1) t4.Partition.Definitions[0].PlacementPolicyRef = &model.PolicyRefInfo{ID: p5.ID, Name: p5.Name} testCreateTable(t, sctx, d, db1, t4) t4.State = model.StatePublic @@ -133,18 +128,39 @@ func TestPlacementPolicyInUse(t *testing.T) { is := builder.Build() for _, policy := range []*model.PolicyInfo{p1, p2, p4, p5} { - require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromInfoSchema(is, policy))) - require.NoError(t, kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { + require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(ddl.CheckPlacementPolicyNotInUseFromInfoSchema(is, policy))) + require.NoError(t, kv.RunInNewTxn(context.Background(), sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) - require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromMeta(m, policy))) + require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(ddl.CheckPlacementPolicyNotInUseFromMeta(m, policy))) return nil })) } - require.NoError(t, checkPlacementPolicyNotInUseFromInfoSchema(is, p3)) - require.NoError(t, kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { + require.NoError(t, ddl.CheckPlacementPolicyNotInUseFromInfoSchema(is, p3)) + require.NoError(t, kv.RunInNewTxn(context.Background(), sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) - require.NoError(t, checkPlacementPolicyNotInUseFromMeta(m, p3)) + require.NoError(t, ddl.CheckPlacementPolicyNotInUseFromMeta(m, p3)) return nil })) } + +// testTableInfoWithPartition creates a test table with num int columns and with no index. +func testTableInfoWithPartition(t *testing.T, store kv.Storage, name string, num int) *model.TableInfo { + tblInfo, err := testTableInfo(store, name, num) + require.NoError(t, err) + genIDs, err := genGlobalIDs(store, 1) + require.NoError(t, err) + pid := genIDs[0] + tblInfo.Partition = &model.PartitionInfo{ + Type: model.PartitionTypeRange, + Expr: tblInfo.Columns[0].Name.L, + Enable: true, + Definitions: []model.PartitionDefinition{{ + ID: pid, + Name: model.NewCIStr("p0"), + LessThan: []string{"maxvalue"}, + }}, + } + + return tblInfo +} diff --git a/ddl/reorg.go b/ddl/reorg.go index 7c3445f375d37..6f8039c99c3e3 100644 --- a/ddl/reorg.go +++ b/ddl/reorg.go @@ -241,6 +241,11 @@ func (w *worker) runReorgJob(t *meta.Meta, reorgInfo *reorgInfo, tblInfo *model. // wait reorganization job done or timeout select { case err := <-w.reorgCtx.doneCh: + // Since job is cancelled,we don't care about its partial counts. + if w.reorgCtx.isReorgCanceled() || terror.ErrorEqual(err, dbterror.ErrCancelledDDLJob) { + w.reorgCtx.clean() + return dbterror.ErrCancelledDDLJob + } rowCount, _, _ := w.reorgCtx.getRowCountAndKey() logutil.BgLogger().Info("[ddl] run reorg job done", zap.Int64("handled rows", rowCount)) // Update a job's RowCount. @@ -250,6 +255,8 @@ func (w *worker) runReorgJob(t *meta.Meta, reorgInfo *reorgInfo, tblInfo *model. w.mergeWarningsIntoJob(job) w.reorgCtx.clean() + // For other errors, even err is not nil here, we still wait the partial counts to be collected. + // since in the next round, the startKey is brand new which is stored by last time. if err != nil { return errors.Trace(err) } @@ -483,7 +490,7 @@ func (dc *ddlCtx) GetTableMaxHandle(ctx *JobContext, startTS uint64, tbl table.P switch { case tblInfo.PKIsHandle: for _, col := range tbl.Meta().Columns { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { handleCols = []*model.ColumnInfo{col} break } diff --git a/ddl/reorg_test.go b/ddl/reorg_test.go index 192d5de89d8c2..2fc35b06b02c7 100644 --- a/ddl/reorg_test.go +++ b/ddl/reorg_test.go @@ -12,258 +12,70 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" - "fmt" "testing" - "time" + "github.com/ngaut/pools" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/testkit/testutil" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) -type testCtxKeyType int - -func (k testCtxKeyType) String() string { - return "test_ctx_key" -} - -const testCtxKey testCtxKeyType = 0 - -func TestReorg(t *testing.T) { - tests := []struct { - isCommonHandle bool - handle kv.Handle - startKey kv.Handle - endKey kv.Handle - }{ - { - false, - kv.IntHandle(100), - kv.IntHandle(1), - kv.IntHandle(0), - }, - { - true, - testutil.MustNewCommonHandle(t, "a", 100, "string"), - testutil.MustNewCommonHandle(t, 100, "string"), - testutil.MustNewCommonHandle(t, 101, "string"), - }, - } - - for _, test := range tests { - t.Run(fmt.Sprintf("isCommandHandle(%v)", test.isCommonHandle), func(t *testing.T) { - store := createMockStore(t) - defer func() { - require.NoError(t, store.Close()) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - err := d.Stop() - require.NoError(t, err) - }() - - time.Sleep(testLease) - - ctx := testNewContext(d) - - ctx.SetValue(testCtxKey, 1) - require.Equal(t, ctx.Value(testCtxKey), 1) - ctx.ClearValue(testCtxKey) - - err = ctx.NewTxn(context.Background()) - require.NoError(t, err) - txn, err := ctx.Txn(true) - require.NoError(t, err) - err = txn.Set([]byte("a"), []byte("b")) - require.NoError(t, err) - err = txn.Rollback() - require.NoError(t, err) - - err = ctx.NewTxn(context.Background()) - require.NoError(t, err) - txn, err = ctx.Txn(true) - require.NoError(t, err) - err = txn.Set([]byte("a"), []byte("b")) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) - - rowCount := int64(10) - handle := test.handle - f := func() error { - d.generalWorker().reorgCtx.setRowCount(rowCount) - d.generalWorker().reorgCtx.setNextKey(handle.Encoded()) - time.Sleep(1*ReorgWaitTimeout + 100*time.Millisecond) - return nil - } - job := &model.Job{ - ID: 1, - SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. - } - err = ctx.NewTxn(context.Background()) - require.NoError(t, err) - txn, err = ctx.Txn(true) - require.NoError(t, err) - m := meta.NewMeta(txn) - e := &meta.Element{ID: 333, TypeKey: meta.IndexElementKey} - rInfo := &reorgInfo{ - Job: job, - currElement: e, - } - mockTbl := tables.MockTableFromMeta(&model.TableInfo{IsCommonHandle: test.isCommonHandle, CommonHandleVersion: 1}) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) - require.Error(t, err) - - // The longest to wait for 5 seconds to make sure the function of f is returned. - for i := 0; i < 1000; i++ { - time.Sleep(5 * time.Millisecond) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) - if err == nil { - require.Equal(t, job.RowCount, rowCount) - require.Equal(t, d.generalWorker().reorgCtx.rowCount, int64(0)) - - // Test whether reorgInfo's Handle is update. - err = txn.Commit(context.Background()) - require.NoError(t, err) - err = ctx.NewTxn(context.Background()) - require.NoError(t, err) - - m = meta.NewMeta(txn) - info, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, nil) - require.NoError(t, err1) - require.Equal(t, info.StartKey, kv.Key(handle.Encoded())) - require.Equal(t, info.currElement, e) - _, doneHandle, _ := d.generalWorker().reorgCtx.getRowCountAndKey() - require.Nil(t, doneHandle) - break - } - } - require.NoError(t, err) - - job = &model.Job{ - ID: 2, - SchemaID: 1, - Type: model.ActionCreateSchema, - Args: []interface{}{model.NewCIStr("test")}, - SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. - } - - element := &meta.Element{ID: 123, TypeKey: meta.ColumnElementKey} - info := &reorgInfo{ - Job: job, - d: d.ddlCtx, - currElement: element, - StartKey: test.startKey.Encoded(), - EndKey: test.endKey.Encoded(), - PhysicalTableID: 456, - } - err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - var err1 error - _, err1 = getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) - require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err1)) - require.Equal(t, job.SnapshotVer, uint64(0)) - return nil - }) - require.NoError(t, err) - job.SnapshotVer = uint64(1) - err = info.UpdateReorgMeta(info.StartKey) - require.NoError(t, err) - err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - info1, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) - require.NoError(t, err1) - require.Equal(t, info1.currElement, info.currElement) - require.Equal(t, info1.StartKey, info.StartKey) - require.Equal(t, info1.EndKey, info.EndKey) - require.Equal(t, info1.PhysicalTableID, info.PhysicalTableID) - return nil - }) - require.NoError(t, err) - - err = d.Stop() - require.NoError(t, err) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, func() error { - time.Sleep(4 * testLease) - return nil - }) - require.Error(t, err) - txn, err = ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) - }) - } -} - func TestReorgOwner(t *testing.T) { - store := createMockStore(t) - defer func() { - require.NoError(t, store.Close()) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - d1, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - err := d1.Stop() - require.NoError(t, err) - }() + d1 := domain.DDL() - ctx := testNewContext(d1) + ctx := testkit.NewTestKit(t, store).Session() - testCheckOwner(t, d1, true) + require.True(t, d1.OwnerManager().IsOwner()) - d2, err := testNewDDLAndStart( + domain.InfoCache() + d2 := ddl.NewDDL( context.Background(), - WithStore(store), - WithLease(testLease), + ddl.WithEtcdClient(domain.EtcdClient()), + ddl.WithInfoCache(domain.InfoCache()), + ddl.WithStore(store), + ddl.WithLease(testLease), ) + + err := d2.Start(pools.NewResourcePool(func() (pools.Resource, error) { + return testkit.NewTestKit(t, store).Session(), nil + }, 2, 2, 5)) require.NoError(t, err) + defer func() { err := d2.Stop() require.NoError(t, err) }() - dbInfo, err := testSchemaInfo(d1, "test_reorg") + dbInfo, err := testSchemaInfo(store, "test_reorg") require.NoError(t, err) testCreateSchema(t, ctx, d1, dbInfo) - tblInfo, err := testTableInfo(d1, "t", 3) + tblInfo, err := testTableInfo(store, "t", 3) require.NoError(t, err) testCreateTable(t, ctx, d1, dbInfo, tblInfo) - tbl := testGetTable(t, d1, dbInfo.ID, tblInfo.ID) + tbl, err := testGetTableWithError(store, dbInfo.ID, tblInfo.ID) + require.NoError(t, err) num := 10 for i := 0; i < num; i++ { _, err := tbl.AddRecord(ctx, types.MakeDatums(i, i, i)) require.NoError(t, err) } + require.NoError(t, ctx.CommitTxn(context.Background())) - txn, err := ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) - - tc := &TestDDLCallback{} - tc.onJobRunBefore = func(job *model.Job) { + tc := &ddl.TestDDLCallback{} + tc.OnJobRunBeforeExported = func(job *model.Job) { if job.SchemaState == model.StateDeleteReorganization { err = d1.Stop() require.NoError(t, err) @@ -274,7 +86,7 @@ func TestReorgOwner(t *testing.T) { testDropSchema(t, ctx, d1, dbInfo) - err = kv.RunInNewTxn(context.Background(), d1.store, false, func(ctx context.Context, txn kv.Transaction) error { + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) db, err1 := m.GetDatabase(dbInfo.ID) require.NoError(t, err1) @@ -283,7 +95,3 @@ func TestReorgOwner(t *testing.T) { }) require.NoError(t, err) } - -func testCheckOwner(t *testing.T, d *ddl, expectedVal bool) { - require.Equal(t, d.isOwner(), expectedVal) -} diff --git a/ddl/repair_table_test.go b/ddl/repair_table_test.go index b24ddae15b387..f3b8ff7ed72e1 100644 --- a/ddl/repair_table_test.go +++ b/ddl/repair_table_test.go @@ -145,10 +145,10 @@ func TestRepairTable(t *testing.T) { require.Equal(t, originTableInfo.Columns[0].ID, repairTable.Meta().Indices[0].ID) require.Equal(t, originTableInfo.AutoIncID, repairTable.Meta().AutoIncID) - require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[0].Tp) - require.Equal(t, mysql.TypeVarchar, repairTable.Meta().Columns[1].Tp) - require.Equal(t, 5, repairTable.Meta().Columns[1].Flen) - require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[2].Tp) + require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[0].GetType()) + require.Equal(t, mysql.TypeVarchar, repairTable.Meta().Columns[1].GetType()) + require.Equal(t, 5, repairTable.Meta().Columns[1].GetFlen()) + require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[2].GetType()) // Exec the show create table statement to make sure new tableInfo has been set. result := tk.MustQuery("show create table origin") diff --git a/ddl/restart_test.go b/ddl/restart_test.go index cd1e330cd3fa7..bee184e93ca86 100644 --- a/ddl/restart_test.go +++ b/ddl/restart_test.go @@ -12,19 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. //go:build !race -// +build !race package ddl import ( "context" "errors" + "fmt" "testing" "time" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -128,7 +132,7 @@ func TestSchemaResume(t *testing.T) { require.NoError(t, d1.Stop()) }() - testCheckOwner(t, d1, true) + require.True(t, d1.OwnerManager().IsOwner()) dbInfo, err := testSchemaInfo(d1, "test_restart") require.NoError(t, err) @@ -229,7 +233,7 @@ func TestTableResume(t *testing.T) { testDropSchema(t, testNewContext(d), d, dbInfo) }() - testCheckOwner(t, d, true) + require.True(t, d.OwnerManager().IsOwner()) tblInfo, err := testTableInfo(d, "t1", 3) require.NoError(t, err) @@ -252,3 +256,51 @@ func TestTableResume(t *testing.T) { testRunInterruptedJob(t, d, job) testCheckTableState(t, d, dbInfo, tblInfo, model.StateNone) } + +// testTableInfo creates a test table with num int columns and with no index. +func testTableInfo(d *ddl, name string, num int) (*model.TableInfo, error) { + tblInfo := &model.TableInfo{ + Name: model.NewCIStr(name), + } + genIDs, err := d.genGlobalIDs(1) + + if err != nil { + return nil, err + } + tblInfo.ID = genIDs[0] + + cols := make([]*model.ColumnInfo, num) + for i := range cols { + col := &model.ColumnInfo{ + Name: model.NewCIStr(fmt.Sprintf("c%d", i+1)), + Offset: i, + DefaultValue: i + 1, + State: model.StatePublic, + } + + col.FieldType = *types.NewFieldType(mysql.TypeLong) + col.ID = allocateColumnID(tblInfo) + cols[i] = col + } + tblInfo.Columns = cols + tblInfo.Charset = "utf8" + tblInfo.Collate = "utf8_bin" + return tblInfo, nil +} + +func testCheckTableState(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { + require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + info, err := m.GetTable(dbInfo.ID, tblInfo.ID) + require.NoError(t, err) + + if state == model.StateNone { + require.NoError(t, err) + return nil + } + + require.Equal(t, info.Name, tblInfo.Name) + require.Equal(t, info.State, state) + return nil + })) +} diff --git a/ddl/rollingback.go b/ddl/rollingback.go index e99a7be9b90a4..7ff3c6088970f 100644 --- a/ddl/rollingback.go +++ b/ddl/rollingback.go @@ -37,13 +37,13 @@ func updateColsNull2NotNull(tblInfo *model.TableInfo, indexInfo *model.IndexInfo } for _, col := range nullCols { - col.Flag |= mysql.NotNullFlag - col.Flag &^= mysql.PreventNullInsertFlag + col.AddFlag(mysql.NotNullFlag) + col.DelFlag(mysql.PreventNullInsertFlag) } return nil } -func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, indexInfo *model.IndexInfo, err error) (int64, error) { +func convertAddIdxJob2RollbackJob(d *ddlCtx, t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, indexInfo *model.IndexInfo, err error) (int64, error) { failpoint.Inject("mockConvertAddIdxJob2RollbackJobError", func(val failpoint.Value) { if val.(bool) { failpoint.Return(0, errors.New("mock convert add index job to rollback job error")) @@ -56,7 +56,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T } for _, col := range nullCols { // Field PreventNullInsertFlag flag reset. - col.Flag &^= mysql.PreventNullInsertFlag + col.DelFlag(mysql.PreventNullInsertFlag) } } @@ -69,7 +69,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T originalState := indexInfo.State indexInfo.State = model.StateDeleteOnly job.SchemaState = model.StateDeleteOnly - ver, err1 := updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err1 := updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err1 != nil { return ver, errors.Trace(err1) } @@ -79,7 +79,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T // convertNotStartAddIdxJob2RollbackJob converts the add index job that are not started workers to rollingbackJob, // to rollback add index operations. job.SnapshotVer == 0 indicates the workers are not started. -func convertNotStartAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, occuredErr error) (ver int64, err error) { +func convertNotStartAddIdxJob2RollbackJob(d *ddlCtx, t *meta.Meta, job *model.Job, occuredErr error) (ver int64, err error) { schemaID := job.SchemaID tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { @@ -103,7 +103,7 @@ func convertNotStartAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, occuredE job.State = model.JobStateCancelled return ver, dbterror.ErrCancelledDDLJob } - return convertAddIdxJob2RollbackJob(t, job, tblInfo, indexInfo, occuredErr) + return convertAddIdxJob2RollbackJob(d, t, job, tblInfo, indexInfo, occuredErr) } // rollingbackModifyColumn change the modifying-column job into rolling back state. @@ -128,7 +128,7 @@ func rollingbackModifyColumn(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) if job.SchemaState == model.StateNone { // When change null to not null, although state is unchanged with none, the oldCol flag's has been changed to preNullInsertFlag. // To roll back this kind of normal job, it is necessary to mark the state as JobStateRollingback to restore the old col's flag. - if jp.modifyColumnTp == mysql.TypeNull && tblInfo.Columns[oldCol.Offset].Flag|mysql.PreventNullInsertFlag != 0 { + if jp.modifyColumnTp == mysql.TypeNull && tblInfo.Columns[oldCol.Offset].GetFlag()|mysql.PreventNullInsertFlag != 0 { job.State = model.JobStateRollingback return ver, dbterror.ErrCancelledDDLJob } @@ -151,7 +151,7 @@ func rollingbackModifyColumn(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) return ver, dbterror.ErrCancelledDDLJob } -func rollingbackAddColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { +func rollingbackAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tblInfo, columnInfo, col, _, _, err := checkAddColumn(t, job) if err != nil { return ver, errors.Trace(err) @@ -166,7 +166,7 @@ func rollingbackAddColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { job.SchemaState = model.StateDeleteOnly job.Args = []interface{}{col.Name} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -175,7 +175,7 @@ func rollingbackAddColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { return ver, dbterror.ErrCancelledDDLJob } -func rollingbackAddColumns(t *meta.Meta, job *model.Job) (ver int64, err error) { +func rollingbackAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tblInfo, columnInfos, _, _, _, _, err := checkAddColumns(t, job) if err != nil { return ver, errors.Trace(err) @@ -195,7 +195,7 @@ func rollingbackAddColumns(t *meta.Meta, job *model.Job) (ver int64, err error) job.SchemaState = model.StateDeleteOnly job.Args = []interface{}{colNames, ifExists} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != columnInfos[0].State) if err != nil { return ver, errors.Trace(err) } @@ -287,7 +287,7 @@ func rollingbackDropIndex(t *meta.Meta, job *model.Job) (ver int64, err error) { } } -func rollingbackDropIndexes(t *meta.Meta, job *model.Job) (ver int64, err error) { +func rollingbackDropIndexes(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tblInfo, indexNames, ifExists, err := getSchemaInfos(t, job) if err != nil { return ver, errors.Trace(err) @@ -303,7 +303,7 @@ func rollingbackDropIndexes(t *meta.Meta, job *model.Job) (ver int64, err error) switch indexInfo.State { case model.StateWriteOnly, model.StateDeleteOnly, model.StateDeleteReorganization, model.StateNone: // We can not rollback now, so just continue to drop index. - // Normally won't fetch here, because there is a check when canceling DDL jobs. See function: IsJobRollbackable. + // Normally won't fetch here, because there is a check when canceling DDL jobs. See function: IsRollbackable. job.State = model.JobStateRunning return ver, nil case model.StatePublic: @@ -316,7 +316,7 @@ func rollingbackDropIndexes(t *meta.Meta, job *model.Job) (ver int64, err error) } job.SchemaState = indexInfo.State - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) } @@ -333,19 +333,19 @@ func rollingbackAddIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, isP ver, err = w.onCreateIndex(d, t, job, isPK) } else { // add index workers are not started, remove the indexInfo in tableInfo. - ver, err = convertNotStartAddIdxJob2RollbackJob(t, job, dbterror.ErrCancelledDDLJob) + ver, err = convertNotStartAddIdxJob2RollbackJob(d, t, job, dbterror.ErrCancelledDDLJob) } return } -func convertAddTablePartitionJob2RollbackJob(t *meta.Meta, job *model.Job, otherwiseErr error, tblInfo *model.TableInfo) (ver int64, err error) { +func convertAddTablePartitionJob2RollbackJob(d *ddlCtx, t *meta.Meta, job *model.Job, otherwiseErr error, tblInfo *model.TableInfo) (ver int64, err error) { addingDefinitions := tblInfo.Partition.AddingDefinitions partNames := make([]string, 0, len(addingDefinitions)) for _, pd := range addingDefinitions { partNames = append(partNames, pd.Name.L) } job.Args = []interface{}{partNames} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -353,7 +353,7 @@ func convertAddTablePartitionJob2RollbackJob(t *meta.Meta, job *model.Job, other return ver, errors.Trace(otherwiseErr) } -func rollingbackAddTablePartition(t *meta.Meta, job *model.Job) (ver int64, err error) { +func rollingbackAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tblInfo, _, addingDefinitions, err := checkAddPartition(t, job) if err != nil { return ver, errors.Trace(err) @@ -364,7 +364,7 @@ func rollingbackAddTablePartition(t *meta.Meta, job *model.Job) (ver int64, err return ver, errors.Trace(dbterror.ErrCancelledDDLJob) } // addingDefinitions is also in tblInfo, here pass the tblInfo as parameter directly. - return convertAddTablePartitionJob2RollbackJob(t, job, dbterror.ErrCancelledDDLJob, tblInfo) + return convertAddTablePartitionJob2RollbackJob(d, t, job, dbterror.ErrCancelledDDLJob, tblInfo) } func rollingbackDropTableOrView(t *meta.Meta, job *model.Job) error { @@ -387,7 +387,7 @@ func rollingbackDropTablePartition(t *meta.Meta, job *model.Job) (ver int64, err if err != nil { return ver, errors.Trace(err) } - return cancelOnlyNotHandledJob(job) + return cancelOnlyNotHandledJob(job, model.StatePublic) } func rollingbackDropSchema(t *meta.Meta, job *model.Job) error { @@ -420,9 +420,9 @@ func rollingbackRenameIndex(t *meta.Meta, job *model.Job) (ver int64, err error) return ver, errors.Trace(err) } -func cancelOnlyNotHandledJob(job *model.Job) (ver int64, err error) { +func cancelOnlyNotHandledJob(job *model.Job, initialState model.SchemaState) (ver int64, err error) { // We can only cancel the not handled job. - if job.SchemaState == model.StateNone { + if job.SchemaState == initialState { job.State = model.JobStateCancelled return ver, dbterror.ErrCancelledDDLJob } @@ -437,21 +437,21 @@ func rollingbackTruncateTable(t *meta.Meta, job *model.Job) (ver int64, err erro if err != nil { return ver, errors.Trace(err) } - return cancelOnlyNotHandledJob(job) + return cancelOnlyNotHandledJob(job, model.StateNone) } func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { switch job.Type { case model.ActionAddColumn: - ver, err = rollingbackAddColumn(t, job) + ver, err = rollingbackAddColumn(d, t, job) case model.ActionAddColumns: - ver, err = rollingbackAddColumns(t, job) + ver, err = rollingbackAddColumns(d, t, job) case model.ActionAddIndex: ver, err = rollingbackAddIndex(w, d, t, job, false) case model.ActionAddPrimaryKey: ver, err = rollingbackAddIndex(w, d, t, job, true) case model.ActionAddTablePartition: - ver, err = rollingbackAddTablePartition(t, job) + ver, err = rollingbackAddTablePartition(d, t, job) case model.ActionDropColumn: ver, err = rollingbackDropColumn(t, job) case model.ActionDropColumns: @@ -459,7 +459,7 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) case model.ActionDropIndex, model.ActionDropPrimaryKey: ver, err = rollingbackDropIndex(t, job) case model.ActionDropIndexes: - ver, err = rollingbackDropIndexes(t, job) + ver, err = rollingbackDropIndexes(d, t, job) case model.ActionDropTable, model.ActionDropView, model.ActionDropSequence: err = rollingbackDropTableOrView(t, job) case model.ActionDropTablePartition: @@ -472,13 +472,15 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) ver, err = rollingbackTruncateTable(t, job) case model.ActionModifyColumn: ver, err = rollingbackModifyColumn(w, d, t, job) + case model.ActionDropForeignKey: + ver, err = cancelOnlyNotHandledJob(job, model.StatePublic) case model.ActionRebaseAutoID, model.ActionShardRowID, model.ActionAddForeignKey, - model.ActionDropForeignKey, model.ActionRenameTable, model.ActionRenameTables, + model.ActionRenameTable, model.ActionRenameTables, model.ActionModifyTableCharsetAndCollate, model.ActionTruncateTablePartition, model.ActionModifySchemaCharsetAndCollate, model.ActionRepairTable, model.ActionModifyTableAutoIdCache, model.ActionAlterIndexVisibility, model.ActionExchangeTablePartition, model.ActionModifySchemaDefaultPlacement: - ver, err = cancelOnlyNotHandledJob(job) + ver, err = cancelOnlyNotHandledJob(job, model.StateNone) default: job.State = model.JobStateCancelled err = dbterror.ErrCancelledDDLJob diff --git a/ddl/schema.go b/ddl/schema.go index 53acfb77cd072..9fff2c5a77338 100644 --- a/ddl/schema.go +++ b/ddl/schema.go @@ -47,7 +47,7 @@ func onCreateSchema(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -111,7 +111,7 @@ func checkSchemaNotExistsFromStore(t *meta.Meta, schemaID int64, dbInfo *model.D return nil } -func onModifySchemaCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onModifySchemaCharsetAndCollate(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var toCharset, toCollate string if err := job.DecodeArgs(&toCharset, &toCollate); err != nil { job.State = model.JobStateCancelled @@ -134,14 +134,14 @@ func onModifySchemaCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ if err = t.UpdateDatabase(dbInfo); err != nil { return ver, errors.Trace(err) } - if ver, err = updateSchemaVersion(t, job); err != nil { + if ver, err = updateSchemaVersion(d, t, job); err != nil { return ver, errors.Trace(err) } job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, dbInfo) return ver, nil } -func onModifySchemaDefaultPlacement(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onModifySchemaDefaultPlacement(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var placementPolicyRef *model.PolicyRefInfo if err := job.DecodeArgs(&placementPolicyRef); err != nil { job.State = model.JobStateCancelled @@ -170,7 +170,7 @@ func onModifySchemaDefaultPlacement(t *meta.Meta, job *model.Job) (ver int64, _ if err = t.UpdateDatabase(dbInfo); err != nil { return ver, errors.Trace(err) } - if ver, err = updateSchemaVersion(t, job); err != nil { + if ver, err = updateSchemaVersion(d, t, job); err != nil { return ver, errors.Trace(err) } job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, dbInfo) @@ -183,7 +183,7 @@ func onDropSchema(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -211,9 +211,6 @@ func onDropSchema(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) job.State = model.JobStateCancelled return ver, errors.Trace(err) } - - // Update the job state when all affairs done. - job.SchemaState = model.StateWriteOnly case model.StateWriteOnly: // write only -> delete only dbInfo.State = model.StateDeleteOnly @@ -221,8 +218,6 @@ func onDropSchema(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) if err != nil { return ver, errors.Trace(err) } - // Update the job state when all affairs done. - job.SchemaState = model.StateDeleteOnly case model.StateDeleteOnly: dbInfo.State = model.StateNone var tables []*model.TableInfo @@ -246,9 +241,9 @@ func onDropSchema(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) job.FinishDBJob(model.JobStateDone, model.StateNone, ver, dbInfo) default: // We can't enter here. - err = errors.Errorf("invalid db state %v", dbInfo.State) + return ver, errors.Trace(errors.Errorf("invalid db state %v", dbInfo.State)) } - + job.SchemaState = dbInfo.State return ver, errors.Trace(err) } diff --git a/ddl/schema_test.go b/ddl/schema_test.go index 0b99510974589..3b67262fbdb3d 100644 --- a/ddl/schema_test.go +++ b/ddl/schema_test.go @@ -12,29 +12,113 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" + "fmt" "testing" "time" - "github.com/pingcap/errors" + "github.com/ngaut/pools" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) -func testSchemaInfo(d *ddl, name string) (*model.DBInfo, error) { +func testCreateTable(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { + job := &model.Job{ + SchemaID: dbInfo.ID, + TableID: tblInfo.ID, + Type: model.ActionCreateTable, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{tblInfo}, + } + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + + v := getSchemaVer(t, ctx) + tblInfo.State = model.StatePublic + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + tblInfo.State = model.StateNone + return job +} + +func testCheckTableState(t *testing.T, store kv.Storage, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { + require.NoError(t, kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + info, err := m.GetTable(dbInfo.ID, tblInfo.ID) + require.NoError(t, err) + + if state == model.StateNone { + require.NoError(t, err) + return nil + } + + require.Equal(t, info.Name, tblInfo.Name) + require.Equal(t, info.State, state) + return nil + })) +} + +// testTableInfo creates a test table with num int columns and with no index. +func testTableInfo(store kv.Storage, name string, num int) (*model.TableInfo, error) { + tblInfo := &model.TableInfo{ + Name: model.NewCIStr(name), + } + genIDs, err := genGlobalIDs(store, 1) + + if err != nil { + return nil, err + } + tblInfo.ID = genIDs[0] + + cols := make([]*model.ColumnInfo, num) + for i := range cols { + col := &model.ColumnInfo{ + Name: model.NewCIStr(fmt.Sprintf("c%d", i+1)), + Offset: i, + DefaultValue: i + 1, + State: model.StatePublic, + } + + col.FieldType = *types.NewFieldType(mysql.TypeLong) + tblInfo.MaxColumnID++ + col.ID = tblInfo.MaxColumnID + cols[i] = col + } + tblInfo.Columns = cols + tblInfo.Charset = "utf8" + tblInfo.Collate = "utf8_bin" + return tblInfo, nil +} + +func genGlobalIDs(store kv.Storage, count int) ([]int64, error) { + var ret []int64 + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + var err error + ret, err = m.GenGlobalIDs(count) + return err + }) + return ret, err +} + +func testSchemaInfo(store kv.Storage, name string) (*model.DBInfo, error) { dbInfo := &model.DBInfo{ Name: model.NewCIStr(name), } - genIDs, err := d.genGlobalIDs(1) + + genIDs, err := genGlobalIDs(store, 1) if err != nil { return nil, err } @@ -42,7 +126,7 @@ func testSchemaInfo(d *ddl, name string) (*model.DBInfo, error) { return dbInfo, nil } -func testCreateSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) *model.Job { +func testCreateSchema(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, Type: model.ActionCreateSchema, @@ -67,7 +151,7 @@ func buildDropSchemaJob(dbInfo *model.DBInfo) *model.Job { } } -func testDropSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) (*model.Job, int64) { +func testDropSchema(t *testing.T, ctx sessionctx.Context, d ddl.DDL, dbInfo *model.DBInfo) (*model.Job, int64) { job := buildDropSchemaJob(dbInfo) ctx.SetValue(sessionctx.QueryString, "skip") err := d.DoDDLJob(ctx, job) @@ -87,11 +171,11 @@ func isDDLJobDone(test *testing.T, t *meta.Meta) bool { return false } -func testCheckSchemaState(test *testing.T, d *ddl, dbInfo *model.DBInfo, state model.SchemaState) { +func testCheckSchemaState(test *testing.T, store kv.Storage, dbInfo *model.DBInfo, state model.SchemaState) { isDropped := true for { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) info, err := t.GetDatabase(dbInfo.ID) require.NoError(test, err) @@ -117,60 +201,51 @@ func testCheckSchemaState(test *testing.T, d *ddl, dbInfo *model.DBInfo, state m } } -func ExportTestSchema(t *testing.T) { - store := createMockStore(t) - defer func() { - err := store.Close() - require.NoError(t, err) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - err := d.Stop() - require.NoError(t, err) - }() - ctx := testNewContext(d) - dbInfo, err := testSchemaInfo(d, "test_schema") +func TestSchema(t *testing.T) { + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + + dbInfo, err := testSchemaInfo(store, "test_schema") require.NoError(t, err) // create a database. - job := testCreateSchema(t, ctx, d, dbInfo) - testCheckSchemaState(t, d, dbInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) + tk := testkit.NewTestKit(t, store) + d := domain.DDL() + job := testCreateSchema(t, tk.Session(), d, dbInfo) + testCheckSchemaState(t, store, dbInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) /*** to drop the schema with two tables. ***/ // create table t with 100 records. - tblInfo1, err := testTableInfo(d, "t", 3) + tblInfo1, err := testTableInfo(store, "t", 3) require.NoError(t, err) - tJob1 := testCreateTable(t, ctx, d, dbInfo, tblInfo1) - testCheckTableState(t, d, dbInfo, tblInfo1, model.StatePublic) - testCheckJobDone(t, d, tJob1, true) - tbl1 := testGetTable(t, d, dbInfo.ID, tblInfo1.ID) + tJob1 := testCreateTable(t, tk.Session(), d, dbInfo, tblInfo1) + testCheckTableState(t, store, dbInfo, tblInfo1, model.StatePublic) + testCheckJobDone(t, store, tJob1.ID, true) + tbl1 := testGetTable(t, domain, tblInfo1.ID) for i := 1; i <= 100; i++ { - _, err := tbl1.AddRecord(ctx, types.MakeDatums(i, i, i)) + _, err := tbl1.AddRecord(tk.Session(), types.MakeDatums(i, i, i)) require.NoError(t, err) } // create table t1 with 1034 records. - tblInfo2, err := testTableInfo(d, "t1", 3) + tblInfo2, err := testTableInfo(store, "t1", 3) require.NoError(t, err) - tJob2 := testCreateTable(t, ctx, d, dbInfo, tblInfo2) - testCheckTableState(t, d, dbInfo, tblInfo2, model.StatePublic) - testCheckJobDone(t, d, tJob2, true) - tbl2 := testGetTable(t, d, dbInfo.ID, tblInfo2.ID) + tk2 := testkit.NewTestKit(t, store) + tJob2 := testCreateTable(t, tk2.Session(), d, dbInfo, tblInfo2) + testCheckTableState(t, store, dbInfo, tblInfo2, model.StatePublic) + testCheckJobDone(t, store, tJob2.ID, true) + tbl2 := testGetTable(t, domain, tblInfo2.ID) for i := 1; i <= 1034; i++ { - _, err := tbl2.AddRecord(ctx, types.MakeDatums(i, i, i)) + _, err := tbl2.AddRecord(tk2.Session(), types.MakeDatums(i, i, i)) require.NoError(t, err) } - job, v := testDropSchema(t, ctx, d, dbInfo) - testCheckSchemaState(t, d, dbInfo, model.StateNone) + tk3 := testkit.NewTestKit(t, store) + job, v := testDropSchema(t, tk3.Session(), d, dbInfo) + testCheckSchemaState(t, store, dbInfo, model.StateNone) ids := make(map[int64]struct{}) ids[tblInfo1.ID] = struct{}{} ids[tblInfo2.ID] = struct{}{} - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo, tblIDs: ids}) + checkHistoryJobArgs(t, tk3.Session(), job.ID, &historyJobArgs{ver: v, db: dbInfo, tblIDs: ids}) // Drop a non-existent database. job = &model.Job{ @@ -178,88 +253,62 @@ func ExportTestSchema(t *testing.T) { Type: model.ActionDropSchema, BinlogInfo: &model.HistoryInfo{}, } + ctx := testkit.NewTestKit(t, store).Session() ctx.SetValue(sessionctx.QueryString, "skip") err = d.DoDDLJob(ctx, job) require.True(t, terror.ErrorEqual(err, infoschema.ErrDatabaseDropExists), "err %v", err) // Drop a database without a table. - dbInfo1, err := testSchemaInfo(d, "test1") + dbInfo1, err := testSchemaInfo(store, "test1") require.NoError(t, err) job = testCreateSchema(t, ctx, d, dbInfo1) - testCheckSchemaState(t, d, dbInfo1, model.StatePublic) - testCheckJobDone(t, d, job, true) + testCheckSchemaState(t, store, dbInfo1, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) job, _ = testDropSchema(t, ctx, d, dbInfo1) - testCheckSchemaState(t, d, dbInfo1, model.StateNone) - testCheckJobDone(t, d, job, false) + testCheckSchemaState(t, store, dbInfo1, model.StateNone) + testCheckJobDone(t, store, job.ID, false) } func TestSchemaWaitJob(t *testing.T) { - store := createMockStore(t) - defer func() { - err := store.Close() - require.NoError(t, err) - }() - - d1, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - err := d1.Stop() - require.NoError(t, err) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - testCheckOwner(t, d1, true) + require.True(t, domain.DDL().OwnerManager().IsOwner()) - d2, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease*4), + d2 := ddl.NewDDL(context.Background(), + ddl.WithEtcdClient(domain.EtcdClient()), + ddl.WithStore(store), + ddl.WithInfoCache(domain.InfoCache()), + ddl.WithLease(testLease), ) + err := d2.Start(pools.NewResourcePool(func() (pools.Resource, error) { + return testkit.NewTestKit(t, store).Session(), nil + }, 2, 2, 5)) require.NoError(t, err) defer func() { err := d2.Stop() require.NoError(t, err) }() - ctx := testNewContext(d2) // d2 must not be owner. - d2.ownerManager.RetireOwner() + d2.OwnerManager().RetireOwner() - dbInfo, err := testSchemaInfo(d2, "test_schema") + dbInfo, err := testSchemaInfo(store, "test_schema") require.NoError(t, err) - testCreateSchema(t, ctx, d2, dbInfo) - testCheckSchemaState(t, d2, dbInfo, model.StatePublic) + se := testkit.NewTestKit(t, store).Session() + testCreateSchema(t, se, d2, dbInfo) + testCheckSchemaState(t, store, dbInfo, model.StatePublic) // d2 must not be owner. - require.False(t, d2.ownerManager.IsOwner()) + require.False(t, d2.OwnerManager().IsOwner()) - genIDs, err := d2.genGlobalIDs(1) + genIDs, err := genGlobalIDs(store, 1) require.NoError(t, err) schemaID := genIDs[0] - doDDLJobErr(t, schemaID, 0, model.ActionCreateSchema, []interface{}{dbInfo}, ctx, d2) -} - -func testGetSchemaInfoWithError(d *ddl, schemaID int64) (*model.DBInfo, error) { - var dbInfo *model.DBInfo - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - var err1 error - dbInfo, err1 = t.GetDatabase(schemaID) - if err1 != nil { - return errors.Trace(err1) - } - return nil - }) - if err != nil { - return nil, errors.Trace(err) - } - return dbInfo, nil + doDDLJobErr(t, schemaID, 0, model.ActionCreateSchema, []interface{}{dbInfo}, se, d2, store) } -func doDDLJobErr(t *testing.T, schemaID, tableID int64, tp model.ActionType, args []interface{}, ctx sessionctx.Context, d *ddl) *model.Job { +func doDDLJobErr(t *testing.T, schemaID, tableID int64, tp model.ActionType, args []interface{}, ctx sessionctx.Context, d ddl.DDL, store kv.Storage) *model.Job { job := &model.Job{ SchemaID: schemaID, TableID: tableID, @@ -269,7 +318,7 @@ func doDDLJobErr(t *testing.T, schemaID, tableID int64, tp model.ActionType, arg } // TODO: check error detail require.Error(t, d.DoDDLJob(ctx, job)) - testCheckJobCancelled(t, d.store, job, nil) + testCheckJobCancelled(t, store, job, nil) return job } diff --git a/ddl/sequence.go b/ddl/sequence.go index e2ba2d620cc6b..ceea68d90810b 100644 --- a/ddl/sequence.go +++ b/ddl/sequence.go @@ -18,7 +18,6 @@ import ( "math" "reflect" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/infoschema" @@ -26,7 +25,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/util/dbterror" - math2 "github.com/pingcap/tidb/util/math" + "github.com/pingcap/tidb/util/mathutil" ) func onCreateSequence(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { @@ -47,7 +46,7 @@ func onCreateSequence(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ err return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -123,7 +122,7 @@ func handleSequenceOptions(seqOptions []*ast.SequenceOption, sequenceInfo *model sequenceInfo.MinValue = model.DefaultPositiveSequenceMinValue } if !startSetFlag { - sequenceInfo.Start = mathutil.MaxInt64(sequenceInfo.MinValue, model.DefaultPositiveSequenceStartValue) + sequenceInfo.Start = mathutil.Max(sequenceInfo.MinValue, model.DefaultPositiveSequenceStartValue) } if !maxSetFlag { sequenceInfo.MaxValue = model.DefaultPositiveSequenceMaxValue @@ -133,7 +132,7 @@ func handleSequenceOptions(seqOptions []*ast.SequenceOption, sequenceInfo *model sequenceInfo.MaxValue = model.DefaultNegativeSequenceMaxValue } if !startSetFlag { - sequenceInfo.Start = mathutil.MinInt64(sequenceInfo.MaxValue, model.DefaultNegativeSequenceStartValue) + sequenceInfo.Start = mathutil.Min(sequenceInfo.MaxValue, model.DefaultNegativeSequenceStartValue) } if !minSetFlag { sequenceInfo.MinValue = model.DefaultNegativeSequenceMinValue @@ -153,7 +152,7 @@ func validateSequenceOptions(seqInfo *model.SequenceInfo) bool { // Cache value should be bigger than 0. return false } - maxIncrement = math2.Abs(seqInfo.Increment) + maxIncrement = mathutil.Abs(seqInfo.Increment) return seqInfo.MaxValue >= seqInfo.Start && seqInfo.MaxValue > seqInfo.MinValue && @@ -235,7 +234,7 @@ func alterSequenceOptions(sequenceOptions []*ast.SequenceOption, ident ast.Ident return false, 0, nil } -func onAlterSequence(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onAlterSequence(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { schemaID := job.SchemaID var ( sequenceOpts []*ast.SequenceOption @@ -277,7 +276,7 @@ func onAlterSequence(t *meta.Meta, job *model.Job) (ver int64, _ error) { } // Store the sequence info into kv. - ver, err = updateVersionAndTableInfo(t, job, tblInfo, shouldUpdateVer) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, shouldUpdateVer) if err != nil { return ver, errors.Trace(err) } diff --git a/ddl/serial_test.go b/ddl/serial_test.go index 73d08a441e8ee..821400f685952 100644 --- a/ddl/serial_test.go +++ b/ddl/serial_test.go @@ -24,7 +24,6 @@ import ( "testing" "time" - "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" @@ -45,10 +44,8 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/external" - "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/gcutil" - "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" ) @@ -89,7 +86,7 @@ func TestIssue23872(t *testing.T) { require.NoError(t, err) cols := rs.Fields() require.NoError(t, rs.Close()) - require.Equal(t, test.flag, cols[0].Column.Flag) + require.Equal(t, test.flag, cols[0].Column.GetFlag()) } } @@ -134,14 +131,14 @@ func TestCreateTableWithLike(t *testing.T) { require.Nil(t, tbl1Info.ForeignKeys) require.True(t, tbl1Info.PKIsHandle) col := tbl1Info.Columns[0] - hasNotNull := mysql.HasNotNullFlag(col.Flag) + hasNotNull := mysql.HasNotNullFlag(col.GetFlag()) require.True(t, hasNotNull) tbl2, err := is.TableByName(model.NewCIStr("ctwl_db"), model.NewCIStr("t2")) require.NoError(t, err) tbl2Info := tbl2.Meta() require.Nil(t, tbl2Info.ForeignKeys) require.True(t, tbl2Info.PKIsHandle) - require.True(t, mysql.HasNotNullFlag(tbl2Info.Columns[0].Flag)) + require.True(t, mysql.HasNotNullFlag(tbl2Info.Columns[0].GetFlag())) // for different databases tk.MustExec("create database ctwl_db1") @@ -443,6 +440,8 @@ func TestCancelAddIndexPanic(t *testing.T) { tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(c1 int, c2 int)") + + tkCancel := testkit.NewTestKit(t, store) defer tk.MustExec("drop table t") for i := 0; i < 5; i++ { tk.MustExec("insert into t values (?, ?)", i, i) @@ -451,37 +450,10 @@ func TestCancelAddIndexPanic(t *testing.T) { oldReorgWaitTimeout := ddl.ReorgWaitTimeout ddl.ReorgWaitTimeout = 50 * time.Millisecond defer func() { ddl.ReorgWaitTimeout = oldReorgWaitTimeout }() - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} hook.OnJobRunBeforeExported = func(job *model.Job) { if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization && job.SnapshotVer != 0 { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - txn, err = hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - checkErr = txn.Commit(context.Background()) + tkCancel.MustQuery(fmt.Sprintf("admin cancel ddl jobs %d", job.ID)) } } dom.DDL().SetHook(hook) @@ -492,10 +464,7 @@ func TestCancelAddIndexPanic(t *testing.T) { require.NoError(t, checkErr) require.Error(t, err) errMsg := err.Error() - // Cancelling the job can either succeed or not, it depends on whether the cancelled job takes affect. - // For now, there's no way to guarantee that cancelling will always take effect. - // TODO: After issue #17904 is fixed, there is no need to tolerate it here. - require.True(t, strings.HasPrefix(errMsg, "[ddl:8214]Cancelled DDL job") || strings.HasPrefix(errMsg, "[ddl:8211]DDL job rollback")) + require.True(t, strings.HasPrefix(errMsg, "[ddl:8214]Cancelled DDL job")) } func TestRecoverTableByJobID(t *testing.T) { diff --git a/ddl/stat_test.go b/ddl/stat_test.go index d721cbfa7b39f..363fac7e9b59c 100644 --- a/ddl/stat_test.go +++ b/ddl/stat_test.go @@ -12,43 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" "testing" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) func TestDDLStatsInfo(t *testing.T) { - store := createMockStore(t) - defer func() { - require.NoError(t, store.Close()) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + d := domain.DDL() - dbInfo, err := testSchemaInfo(d, "test_stat") + dbInfo, err := testSchemaInfo(store, "test_stat") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo) - tblInfo, err := testTableInfo(d, "t", 2) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo) + tblInfo, err := testTableInfo(store, "t", 2) require.NoError(t, err) - ctx := testNewContext(d) + ctx := testkit.NewTestKit(t, store).Session() testCreateTable(t, ctx, d, dbInfo, tblInfo) - m := testGetTable(t, d, dbInfo.ID, tblInfo.ID) + m := testGetTable(t, domain, tblInfo.ID) // insert t values (1, 1), (2, 2), (3, 3) _, err = m.AddRecord(ctx, types.MakeDatums(1, 1)) require.NoError(t, err) @@ -56,10 +49,7 @@ func TestDDLStatsInfo(t *testing.T) { require.NoError(t, err) _, err = m.AddRecord(ctx, types.MakeDatums(3, 3)) require.NoError(t, err) - txn, err := ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) + require.NoError(t, ctx.CommitTxn(context.Background())) job := buildCreateIdxJob(dbInfo, tblInfo, true, "idx", "c1") @@ -75,12 +65,14 @@ func TestDDLStatsInfo(t *testing.T) { }() exit := false + // a copy of ddl.ddlJobReorgHandle + ddlJobReorgHandle := "ddl_job_reorg_handle" for !exit { select { case err := <-done: require.NoError(t, err) exit = true - case wg := <-TestCheckWorkerNumCh: + case wg := <-ddl.TestCheckWorkerNumCh: varMap, err := d.Stats(nil) wg.Done() require.NoError(t, err) @@ -88,3 +80,16 @@ func TestDDLStatsInfo(t *testing.T) { } } } + +func buildCreateIdxJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { + return &model.Job{ + SchemaID: dbInfo.ID, + TableID: tblInfo.ID, + Type: model.ActionAddIndex, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{unique, model.NewCIStr(indexName), + []*ast.IndexPartSpecification{{ + Column: &ast.ColumnName{Name: model.NewCIStr(colName)}, + Length: types.UnspecifiedLength}}}, + } +} diff --git a/ddl/table.go b/ddl/table.go index dbbbcd1653f86..53de0becd51ec 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -145,7 +145,7 @@ func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -184,7 +184,7 @@ func onCreateTables(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, error) { args[i] = tbInfo } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -243,7 +243,7 @@ func onCreateView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) return ver, errors.Trace(err) } } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -275,7 +275,7 @@ func onCreateView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) } } -func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropTableOrView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, err := checkTableExistAndCancelNonExistJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) @@ -286,39 +286,37 @@ func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) { case model.StatePublic: // public -> write only tblInfo.State = model.StateWriteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != tblInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != tblInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateWriteOnly case model.StateWriteOnly: // write only -> delete only tblInfo.State = model.StateDeleteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != tblInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != tblInfo.State) if err != nil { return ver, errors.Trace(err) } - job.SchemaState = model.StateDeleteOnly case model.StateDeleteOnly: tblInfo.State = model.StateNone oldIDs := getPartitionIDs(tblInfo) ruleIDs := append(getPartitionRuleIDs(job.SchemaName, tblInfo), fmt.Sprintf(label.TableIDFormat, label.IDPrefix, job.SchemaName, tblInfo.Name.L)) job.CtxVars = []interface{}{oldIDs} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != tblInfo.State) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, originalState != tblInfo.State) if err != nil { return ver, errors.Trace(err) } if tblInfo.IsSequence() { if err = t.DropSequence(job.SchemaID, job.TableID); err != nil { - break + return ver, errors.Trace(err) } } else { if err = t.DropTableOrView(job.SchemaID, job.TableID); err != nil { - break + return ver, errors.Trace(err) } if err = t.GetAutoIDAccessors(job.SchemaID, job.TableID).Del(); err != nil { - break + return ver, errors.Trace(err) } } // Placement rules cannot be removed immediately after drop table / truncate table, because the @@ -329,9 +327,9 @@ func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) { startKey := tablecodec.EncodeTablePrefix(job.TableID) job.Args = append(job.Args, startKey, oldIDs, ruleIDs) default: - err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) + return ver, errors.Trace(dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State)) } - + job.SchemaState = tblInfo.State return ver, errors.Trace(err) } @@ -412,7 +410,7 @@ func (w *worker) onRecoverTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in job.SchemaState = model.StateWriteOnly tblInfo.State = model.StateWriteOnly - ver, err = updateVersionAndTableInfo(t, job, tblInfo, false) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, false) if err != nil { return ver, errors.Trace(err) } @@ -471,7 +469,7 @@ func (w *worker) onRecoverTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in } job.CtxVars = []interface{}{tids} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -733,7 +731,7 @@ func onTruncateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ erro } }) - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -744,15 +742,15 @@ func onTruncateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ erro return ver, nil } -func onRebaseRowIDType(store kv.Storage, t *meta.Meta, job *model.Job) (ver int64, _ error) { - return onRebaseAutoID(store, t, job, autoid.RowIDAllocType) +func onRebaseRowIDType(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { + return onRebaseAutoID(d, d.store, t, job, autoid.RowIDAllocType) } -func onRebaseAutoRandomType(store kv.Storage, t *meta.Meta, job *model.Job) (ver int64, _ error) { - return onRebaseAutoID(store, t, job, autoid.AutoRandomType) +func onRebaseAutoRandomType(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { + return onRebaseAutoID(d, d.store, t, job, autoid.AutoRandomType) } -func onRebaseAutoID(store kv.Storage, t *meta.Meta, job *model.Job, tp autoid.AllocatorType) (ver int64, _ error) { +func onRebaseAutoID(d *ddlCtx, store kv.Storage, t *meta.Meta, job *model.Job, tp autoid.AllocatorType) (ver int64, _ error) { schemaID := job.SchemaID var ( newBase int64 @@ -793,7 +791,7 @@ func onRebaseAutoID(store kv.Storage, t *meta.Meta, job *model.Job, tp autoid.Al return ver, errors.Trace(err) } } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -801,7 +799,7 @@ func onRebaseAutoID(store kv.Storage, t *meta.Meta, job *model.Job, tp autoid.Al return ver, nil } -func onModifyTableAutoIDCache(t *meta.Meta, job *model.Job) (int64, error) { +func onModifyTableAutoIDCache(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, error) { var cache int64 if err := job.DecodeArgs(&cache); err != nil { job.State = model.JobStateCancelled @@ -814,7 +812,7 @@ func onModifyTableAutoIDCache(t *meta.Meta, job *model.Job) (int64, error) { } tblInfo.AutoIdCache = cache - ver, err := updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err := updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -850,7 +848,7 @@ func (w *worker) onShardRowID(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int6 // MaxShardRowIDBits use to check the overflow of auto ID. tblInfo.MaxShardRowIDBits = shardRowIDBits } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -901,7 +899,7 @@ func onRenameTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) return ver, errors.Trace(err) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -933,7 +931,7 @@ func onRenameTables(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error tblInfos = append(tblInfos, tblInfo) } - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -997,7 +995,7 @@ func checkAndRenameTables(t *meta.Meta, job *model.Job, oldSchemaID, newSchemaID return ver, tblInfo, nil } -func onModifyTableComment(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onModifyTableComment(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var comment string if err := job.DecodeArgs(&comment); err != nil { job.State = model.JobStateCancelled @@ -1010,7 +1008,7 @@ func onModifyTableComment(t *meta.Meta, job *model.Job) (ver int64, _ error) { } tblInfo.Comment = comment - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1018,7 +1016,7 @@ func onModifyTableComment(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, nil } -func onModifyTableCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onModifyTableCharsetAndCollate(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var toCharset, toCollate string var needsOverwriteCols bool if err := job.DecodeArgs(&toCharset, &toCollate, &needsOverwriteCols); err != nil { @@ -1050,16 +1048,16 @@ func onModifyTableCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ // update column charset. for _, col := range tblInfo.Columns { if field_types.HasCharset(&col.FieldType) { - col.Charset = toCharset - col.Collate = toCollate + col.SetCharset(toCharset) + col.SetCollate(toCollate) } else { - col.Charset = charset.CharsetBin - col.Collate = charset.CharsetBin + col.SetCharset(charset.CharsetBin) + col.SetCollate(charset.CharsetBin) } } } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1067,7 +1065,7 @@ func onModifyTableCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ return ver, nil } -func (w *worker) onSetTableFlashReplica(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func (w *worker) onSetTableFlashReplica(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var replicaInfo ast.TiFlashReplicaSpec if err := job.DecodeArgs(&replicaInfo); err != nil { job.State = model.JobStateCancelled @@ -1123,7 +1121,7 @@ func (w *worker) onSetTableFlashReplica(t *meta.Meta, job *model.Job) (ver int64 tblInfo.TiFlashReplica = nil } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1141,7 +1139,7 @@ func (w *worker) checkTiFlashReplicaCount(replicaCount uint64) error { return checkTiFlashReplicaCount(ctx, replicaCount) } -func onUpdateFlashReplicaStatus(t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onUpdateFlashReplicaStatus(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { var available bool var physicalID int64 if err := job.DecodeArgs(&available, &physicalID); err != nil { @@ -1189,7 +1187,7 @@ func onUpdateFlashReplicaStatus(t *meta.Meta, job *model.Job) (ver int64, _ erro return ver, errors.Errorf("unknown physical ID %v in table %v", physicalID, tblInfo.Name.O) } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1258,18 +1256,18 @@ func checkTableNotExistsFromStore(t *meta.Meta, schemaID int64, tableName string } // updateVersionAndTableInfoWithCheck checks table info validate and updates the schema version and the table information -func updateVersionAndTableInfoWithCheck(t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, shouldUpdateVer bool) ( +func updateVersionAndTableInfoWithCheck(d *ddlCtx, t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, shouldUpdateVer bool) ( ver int64, err error) { err = checkTableInfoValid(tblInfo) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } - return updateVersionAndTableInfo(t, job, tblInfo, shouldUpdateVer) + return updateVersionAndTableInfo(d, t, job, tblInfo, shouldUpdateVer) } // updateVersionAndTableInfo updates the schema version and the table information. -func updateVersionAndTableInfo(t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, shouldUpdateVer bool) ( +func updateVersionAndTableInfo(d *ddlCtx, t *meta.Meta, job *model.Job, tblInfo *model.TableInfo, shouldUpdateVer bool) ( ver int64, err error) { failpoint.Inject("mockUpdateVersionAndTableInfoErr", func(val failpoint.Value) { switch val.(int) { @@ -1284,7 +1282,7 @@ func updateVersionAndTableInfo(t *meta.Meta, job *model.Job, tblInfo *model.Tabl } }) if shouldUpdateVer { - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return 0, errors.Trace(err) } @@ -1317,7 +1315,7 @@ func onRepairTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) // When in repair mode, the repaired table in a server is not access to user, // the table after repairing will be removed from repair list. Other server left // behind alive may need to restart to get the latest schema version. - ver, err = updateSchemaVersion(t, job) + ver, err = updateSchemaVersion(d, t, job) if err != nil { return ver, errors.Trace(err) } @@ -1339,7 +1337,7 @@ func onRepairTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) } } -func onAlterTableAttributes(t *meta.Meta, job *model.Job) (ver int64, err error) { +func onAlterTableAttributes(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { rule := label.NewRule() err = job.DecodeArgs(rule) if err != nil { @@ -1362,7 +1360,7 @@ func onAlterTableAttributes(t *meta.Meta, job *model.Job) (ver int64, err error) job.State = model.JobStateCancelled return 0, errors.Wrapf(err, "failed to notify PD the label rules") } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1371,7 +1369,7 @@ func onAlterTableAttributes(t *meta.Meta, job *model.Job) (ver int64, err error) return ver, nil } -func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, err error) { +func onAlterTablePartitionAttributes(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { var partitionID int64 rule := label.NewRule() err = job.DecodeArgs(&partitionID, rule) @@ -1400,7 +1398,7 @@ func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, e job.State = model.JobStateCancelled return 0, errors.Wrapf(err, "failed to notify PD the label rules") } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1409,7 +1407,7 @@ func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, e return ver, nil } -func onAlterTablePartitionPlacement(t *meta.Meta, job *model.Job) (ver int64, err error) { +func onAlterTablePartitionPlacement(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { var partitionID int64 policyRefInfo := &model.PolicyRefInfo{} err = job.DecodeArgs(&partitionID, &policyRefInfo) @@ -1446,7 +1444,7 @@ func onAlterTablePartitionPlacement(t *meta.Meta, job *model.Job) (ver int64, er return 0, errors.Trace(table.ErrUnknownPartition.GenWithStackByArgs("drop?", tblInfo.Name.O)) } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1503,7 +1501,7 @@ func onAlterTablePlacement(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, oldTableEnablesPlacement := tblInfo.PlacementPolicyRef != nil tblInfo.PlacementPolicyRef = policyRefInfo - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -1574,7 +1572,7 @@ func updateLabelRules(job *model.Job, tblInfo *model.TableInfo, oldRules map[str return infosync.UpdateLabelRules(context.TODO(), patch) } -func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { +func onAlterCacheTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tbInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, errors.Trace(err) @@ -1597,14 +1595,14 @@ func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { case model.TableCacheStatusDisable: // disable -> switching tbInfo.TableCacheStatusType = model.TableCacheStatusSwitching - ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tbInfo, true) if err != nil { return ver, err } case model.TableCacheStatusSwitching: // switching -> enable tbInfo.TableCacheStatusType = model.TableCacheStatusEnable - ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tbInfo, true) if err != nil { return ver, err } @@ -1617,7 +1615,7 @@ func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { return ver, err } -func onAlterNoCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { +func onAlterNoCacheTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { tbInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, errors.Trace(err) @@ -1632,14 +1630,14 @@ func onAlterNoCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { case model.TableCacheStatusEnable: // enable -> switching tbInfo.TableCacheStatusType = model.TableCacheStatusSwitching - ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tbInfo, true) if err != nil { return ver, err } case model.TableCacheStatusSwitching: // switching -> disable tbInfo.TableCacheStatusType = model.TableCacheStatusDisable - ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfoWithCheck(d, t, job, tbInfo, true) if err != nil { return ver, err } diff --git a/ddl/table_lock.go b/ddl/table_lock.go index ec4d00b6dbb55..f6dc766768a7f 100644 --- a/ddl/table_lock.go +++ b/ddl/table_lock.go @@ -22,8 +22,8 @@ import ( "github.com/pingcap/tidb/util/dbterror" ) -func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { - arg := &lockTablesArg{} +func onLockTables(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { + arg := &LockTablesArg{} if err := job.DecodeArgs(arg); err != nil { // Invalid arguments, cancel this job. job.State = model.JobStateCancelled @@ -32,7 +32,7 @@ func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { // Unlock table first. if arg.IndexOfUnlock < len(arg.UnlockTables) { - return unlockTables(t, job, arg) + return unlockTables(d, t, job, arg) } // Check table locked by other, this can be only checked at the first time. @@ -75,13 +75,13 @@ func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { // none -> pre_lock tbInfo.Lock.State = model.TableLockStatePreLock tbInfo.Lock.TS = t.StartTS - ver, err = updateVersionAndTableInfo(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tbInfo, true) // If the state of the lock is public, it means the lock is a read lock and already locked by other session, // so this request of lock table doesn't need pre-lock state, just update the TS and table info is ok. case model.TableLockStatePreLock, model.TableLockStatePublic: tbInfo.Lock.State = model.TableLockStatePublic tbInfo.Lock.TS = t.StartTS - ver, err = updateVersionAndTableInfo(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tbInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -111,7 +111,7 @@ func findSessionInfoIndex(sessions []model.SessionInfo, sessionInfo model.Sessio } // lockTable uses to check table locked and acquire the table lock for the request session. -func lockTable(tbInfo *model.TableInfo, idx int, arg *lockTablesArg) error { +func lockTable(tbInfo *model.TableInfo, idx int, arg *LockTablesArg) error { if !tbInfo.IsLocked() { tbInfo.Lock = &model.TableLockInfo{ Tp: arg.LockTables[idx].Tp, @@ -167,7 +167,7 @@ func checkTableLocked(tbInfo *model.TableInfo, lockTp model.TableLockType, sessi } // unlockTables uses unlock a batch of table lock one by one. -func unlockTables(t *meta.Meta, job *model.Job, arg *lockTablesArg) (ver int64, err error) { +func unlockTables(d *ddlCtx, t *meta.Meta, job *model.Job, arg *LockTablesArg) (ver int64, err error) { if arg.IndexOfUnlock >= len(arg.UnlockTables) { return ver, nil } @@ -186,7 +186,7 @@ func unlockTables(t *meta.Meta, job *model.Job, arg *lockTablesArg) (ver int64, needUpdateTableInfo := unlockTable(tbInfo, arg) if needUpdateTableInfo { - ver, err = updateVersionAndTableInfo(t, job, tbInfo, true) + ver, err = updateVersionAndTableInfo(d, t, job, tbInfo, true) if err != nil { return ver, errors.Trace(err) } @@ -198,7 +198,7 @@ func unlockTables(t *meta.Meta, job *model.Job, arg *lockTablesArg) (ver int64, } // unlockTable uses to unlock table lock that hold by the session. -func unlockTable(tbInfo *model.TableInfo, arg *lockTablesArg) (needUpdateTableInfo bool) { +func unlockTable(tbInfo *model.TableInfo, arg *LockTablesArg) (needUpdateTableInfo bool) { if !tbInfo.IsLocked() { return false } @@ -222,15 +222,15 @@ func unlockTable(tbInfo *model.TableInfo, arg *lockTablesArg) (needUpdateTableIn return true } -func onUnlockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { - arg := &lockTablesArg{} +func onUnlockTables(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { + arg := &LockTablesArg{} if err := job.DecodeArgs(arg); err != nil { // Invalid arguments, cancel this job. job.State = model.JobStateCancelled return ver, errors.Trace(err) } - ver, err = unlockTables(t, job, arg) + ver, err = unlockTables(d, t, job, arg) if arg.IndexOfUnlock == len(arg.UnlockTables) { job.FinishTableJob(model.JobStateDone, model.StateNone, ver, nil) } diff --git a/ddl/table_test.go b/ddl/table_test.go index 105c80479f3fa..9b5f4f02eb470 100644 --- a/ddl/table_test.go +++ b/ddl/table_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" @@ -20,13 +20,14 @@ import ( "testing" "github.com/pingcap/errors" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) @@ -34,7 +35,7 @@ import ( func testRenameTable( t *testing.T, ctx sessionctx.Context, - d *ddl, + d ddl.DDL, newSchemaID, oldSchemaID int64, oldSchemaName model.CIStr, tblInfo *model.TableInfo, @@ -56,7 +57,7 @@ func testRenameTable( return job } -func testRenameTables(t *testing.T, ctx sessionctx.Context, d *ddl, oldSchemaIDs, newSchemaIDs []int64, newTableNames []*model.CIStr, oldTableIDs []int64, oldSchemaNames, oldTableNames []*model.CIStr) *model.Job { +func testRenameTables(t *testing.T, ctx sessionctx.Context, d ddl.DDL, oldSchemaIDs, newSchemaIDs []int64, newTableNames []*model.CIStr, oldTableIDs []int64, oldSchemaNames, oldTableNames []*model.CIStr) *model.Job { job := &model.Job{ Type: model.ActionRenameTables, BinlogInfo: &model.HistoryInfo{}, @@ -70,8 +71,8 @@ func testRenameTables(t *testing.T, ctx sessionctx.Context, d *ddl, oldSchemaIDs return job } -func testLockTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo, lockTp model.TableLockType) *model.Job { - arg := &lockTablesArg{ +func testLockTable(t *testing.T, ctx sessionctx.Context, d ddl.DDL, newSchemaID int64, tblInfo *model.TableInfo, lockTp model.TableLockType) *model.Job { + arg := &ddl.LockTablesArg{ LockTables: []model.TableLockTpInfo{{SchemaID: newSchemaID, TableID: tblInfo.ID, Tp: lockTp}}, SessionInfo: model.SessionInfo{ ServerID: d.GetID(), @@ -94,8 +95,8 @@ func testLockTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int return job } -func checkTableLockedTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, serverID string, sessionID uint64, lockTp model.TableLockType) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { +func checkTableLockedTest(t *testing.T, store kv.Storage, dbInfo *model.DBInfo, tblInfo *model.TableInfo, serverID string, sessionID uint64, lockTp model.TableLockType) { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { tt := meta.NewMeta(txn) info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) require.NoError(t, err) @@ -113,8 +114,8 @@ func checkTableLockedTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *m require.NoError(t, err) } -func testTruncateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - genIDs, err := d.genGlobalIDs(1) +func testTruncateTable(t *testing.T, ctx sessionctx.Context, store kv.Storage, d ddl.DDL, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { + genIDs, err := genGlobalIDs(store, 1) require.NoError(t, err) newTableID := genIDs[0] job := &model.Job{ @@ -134,9 +135,9 @@ func testTruncateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *mod return job } -func testGetTableWithError(d *ddl, schemaID, tableID int64) (table.Table, error) { +func testGetTableWithError(store kv.Storage, schemaID, tableID int64) (table.Table, error) { var tblInfo *model.TableInfo - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) var err1 error tblInfo, err1 = t.GetTable(schemaID, tableID) @@ -151,7 +152,7 @@ func testGetTableWithError(d *ddl, schemaID, tableID int64) (table.Table, error) if tblInfo == nil { return nil, errors.New("table not found") } - alloc := autoid.NewAllocator(d.store, schemaID, tblInfo.ID, false, autoid.RowIDAllocType) + alloc := autoid.NewAllocator(store, schemaID, tblInfo.ID, false, autoid.RowIDAllocType) tbl, err := table.TableFromMeta(autoid.NewAllocators(alloc), tblInfo) if err != nil { return nil, errors.Trace(err) @@ -160,86 +161,75 @@ func testGetTableWithError(d *ddl, schemaID, tableID int64) (table.Table, error) } func TestTable(t *testing.T) { - store, err := mockstore.NewMockStore() - require.NoError(t, err) - defer func() { - require.NoError(t, store.Close()) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - dbInfo, err := testSchemaInfo(d, "test_table") + d := domain.DDL() + dbInfo, err := testSchemaInfo(store, "test_table") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), domain.DDL(), dbInfo) - ctx := testNewContext(d) + ctx := testkit.NewTestKit(t, store).Session() - tblInfo, err := testTableInfo(d, "t", 3) + tblInfo, err := testTableInfo(store, "t", 3) require.NoError(t, err) job := testCreateTable(t, ctx, d, dbInfo, tblInfo) - testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) + testCheckTableState(t, store, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) // Create an existing table. - newTblInfo, err := testTableInfo(d, "t", 3) + newTblInfo, err := testTableInfo(store, "t", 3) require.NoError(t, err) - doDDLJobErr(t, dbInfo.ID, newTblInfo.ID, model.ActionCreateTable, []interface{}{newTblInfo}, ctx, d) + doDDLJobErr(t, dbInfo.ID, newTblInfo.ID, model.ActionCreateTable, []interface{}{newTblInfo}, ctx, d, store) count := 2000 - tbl := testGetTable(t, d, dbInfo.ID, tblInfo.ID) + tbl := testGetTable(t, domain, tblInfo.ID) for i := 1; i <= count; i++ { _, err := tbl.AddRecord(ctx, types.MakeDatums(i, i, i)) require.NoError(t, err) } - job = testDropTable(t, ctx, d, dbInfo, tblInfo) - testCheckJobDone(t, d, job, false) + jobID := testDropTable(testkit.NewTestKit(t, store), t, dbInfo.Name.L, tblInfo.Name.L, domain) + testCheckJobDone(t, store, jobID, false) // for truncate table - tblInfo, err = testTableInfo(d, "tt", 3) + tblInfo, err = testTableInfo(store, "tt", 3) require.NoError(t, err) job = testCreateTable(t, ctx, d, dbInfo, tblInfo) - testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) - job = testTruncateTable(t, ctx, d, dbInfo, tblInfo) - testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) + testCheckTableState(t, store, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) + job = testTruncateTable(t, ctx, store, d, dbInfo, tblInfo) + testCheckTableState(t, store, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) // for rename table - dbInfo1, err := testSchemaInfo(d, "test_rename_table") + dbInfo1, err := testSchemaInfo(store, "test_rename_table") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo1) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo1) job = testRenameTable(t, ctx, d, dbInfo1.ID, dbInfo.ID, dbInfo.Name, tblInfo) - testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) + testCheckTableState(t, store, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) job = testLockTable(t, ctx, d, dbInfo1.ID, tblInfo, model.TableLockWrite) - testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) - checkTableLockedTest(t, d, dbInfo1, tblInfo, d.GetID(), ctx.GetSessionVars().ConnectionID, model.TableLockWrite) + testCheckTableState(t, store, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) + checkTableLockedTest(t, store, dbInfo1, tblInfo, d.GetID(), ctx.GetSessionVars().ConnectionID, model.TableLockWrite) // for alter cache table job = testAlterCacheTable(t, ctx, d, dbInfo1.ID, tblInfo) - testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) - checkTableCacheTest(t, d, dbInfo1, tblInfo) + testCheckTableState(t, store, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) + checkTableCacheTest(t, store, dbInfo1, tblInfo) // for alter no cache table job = testAlterNoCacheTable(t, ctx, d, dbInfo1.ID, tblInfo) - testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) - checkTableNoCacheTest(t, d, dbInfo1, tblInfo) + testCheckTableState(t, store, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) + checkTableNoCacheTest(t, store, dbInfo1, tblInfo) - testDropSchema(t, testNewContext(d), d, dbInfo) + testDropSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo) } -func checkTableCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { - require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { +func checkTableCacheTest(t *testing.T, store kv.Storage, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { + require.NoError(t, kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { tt := meta.NewMeta(txn) info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) require.NoError(t, err) @@ -250,8 +240,8 @@ func checkTableCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *mo })) } -func checkTableNoCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { - require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { +func checkTableNoCacheTest(t *testing.T, store kv.Storage, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { + require.NoError(t, kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { tt := meta.NewMeta(txn) info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) require.NoError(t, err) @@ -261,7 +251,7 @@ func checkTableNoCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo * })) } -func testAlterCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { +func testAlterCacheTable(t *testing.T, ctx sessionctx.Context, d ddl.DDL, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { job := &model.Job{ SchemaID: newSchemaID, TableID: tblInfo.ID, @@ -278,7 +268,7 @@ func testAlterCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchema return job } -func testAlterNoCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { +func testAlterNoCacheTable(t *testing.T, ctx sessionctx.Context, d ddl.DDL, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { job := &model.Job{ SchemaID: newSchemaID, TableID: tblInfo.ID, @@ -295,39 +285,29 @@ func testAlterNoCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSche } func TestRenameTables(t *testing.T) { - store, err := mockstore.NewMockStore() - defer func() { - require.NoError(t, store.Close()) - }() - require.NoError(t, err) - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + + d := domain.DDL() - dbInfo, err := testSchemaInfo(d, "test_table") + dbInfo, err := testSchemaInfo(store, "test_table") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo) - ctx := testNewContext(d) + ctx := testkit.NewTestKit(t, store).Session() var tblInfos = make([]*model.TableInfo, 0, 2) var newTblInfos = make([]*model.TableInfo, 0, 2) for i := 1; i < 3; i++ { tableName := fmt.Sprintf("t%d", i) - tblInfo, err := testTableInfo(d, tableName, 3) + tblInfo, err := testTableInfo(store, tableName, 3) require.NoError(t, err) job := testCreateTable(t, ctx, d, dbInfo, tblInfo) - testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) - testCheckJobDone(t, d, job, true) + testCheckTableState(t, store, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, store, job.ID, true) tblInfos = append(tblInfos, tblInfo) newTableName := fmt.Sprintf("tt%d", i) - tblInfo, err = testTableInfo(d, newTableName, 3) + tblInfo, err = testTableInfo(store, newTableName, 3) require.NoError(t, err) newTblInfos = append(newTblInfos, tblInfo) } @@ -335,36 +315,27 @@ func TestRenameTables(t *testing.T) { job := testRenameTables(t, ctx, d, []int64{dbInfo.ID, dbInfo.ID}, []int64{dbInfo.ID, dbInfo.ID}, []*model.CIStr{&newTblInfos[0].Name, &newTblInfos[1].Name}, []int64{tblInfos[0].ID, tblInfos[1].ID}, []*model.CIStr{&dbInfo.Name, &dbInfo.Name}, []*model.CIStr{&tblInfos[0].Name, &tblInfos[1].Name}) txn, _ := ctx.Txn(true) - historyJob, _ := meta.NewMeta(txn).GetHistoryDDLJob(job.ID) + historyJob, err := meta.NewMeta(txn).GetHistoryDDLJob(job.ID) + require.NoError(t, err) wantTblInfos := historyJob.BinlogInfo.MultipleTableInfos require.Equal(t, wantTblInfos[0].Name.L, "tt1") require.Equal(t, wantTblInfos[1].Name.L, "tt2") } func TestCreateTables(t *testing.T) { - store, err := mockstore.NewMockStore() - require.NoError(t, err) - defer func() { - require.NoError(t, store.Close()) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - require.NoError(t, err) - defer func() { - require.NoError(t, d.Stop()) - }() + store, domain, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + + d := domain.DDL() - dbInfo, err := testSchemaInfo(d, "test_table") + dbInfo, err := testSchemaInfo(store, "test_table") require.NoError(t, err) - testCreateSchema(t, testNewContext(d), d, dbInfo) + testCreateSchema(t, testkit.NewTestKit(t, store).Session(), d, dbInfo) - ctx := testNewContext(d) + ctx := testkit.NewTestKit(t, store).Session() var infos []*model.TableInfo - genIDs, err := d.genGlobalIDs(3) + genIDs, err := genGlobalIDs(store, 3) require.NoError(t, err) infos = append(infos, &model.TableInfo{ @@ -390,7 +361,7 @@ func TestCreateTables(t *testing.T) { err = d.DoDDLJob(ctx, job) require.NoError(t, err) - testGetTable(t, d, dbInfo.ID, genIDs[0]) - testGetTable(t, d, dbInfo.ID, genIDs[1]) - testGetTable(t, d, dbInfo.ID, genIDs[2]) + testGetTable(t, domain, genIDs[0]) + testGetTable(t, domain, genIDs[1]) + testGetTable(t, domain, genIDs[2]) } diff --git a/ddl/util_test.go b/ddl/util_test.go deleted file mode 100644 index 37b0fa638c325..0000000000000 --- a/ddl/util_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ddl - -import ( - "context" - "fmt" - "testing" - - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/types" - "github.com/stretchr/testify/require" -) - -func testTableInfoWith2IndexOnFirstColumn(t *testing.T, d *ddl, name string, num int) *model.TableInfo { - normalInfo, err := testTableInfo(d, name, num) - require.NoError(t, err) - idxs := make([]*model.IndexInfo, 0, 2) - for i := range idxs { - idx := &model.IndexInfo{ - Name: model.NewCIStr(fmt.Sprintf("i%d", i+1)), - State: model.StatePublic, - Columns: []*model.IndexColumn{{Name: model.NewCIStr("c1")}}, - } - idxs = append(idxs, idx) - } - normalInfo.Indices = idxs - normalInfo.Columns[0].FieldType.Flen = 11 - return normalInfo -} - -// testTableInfo creates a test table with num int columns and with no index. -func testTableInfo(d *ddl, name string, num int) (*model.TableInfo, error) { - tblInfo := &model.TableInfo{ - Name: model.NewCIStr(name), - } - genIDs, err := d.genGlobalIDs(1) - - if err != nil { - return nil, err - } - tblInfo.ID = genIDs[0] - - cols := make([]*model.ColumnInfo, num) - for i := range cols { - col := &model.ColumnInfo{ - Name: model.NewCIStr(fmt.Sprintf("c%d", i+1)), - Offset: i, - DefaultValue: i + 1, - State: model.StatePublic, - } - - col.FieldType = *types.NewFieldType(mysql.TypeLong) - col.ID = allocateColumnID(tblInfo) - cols[i] = col - } - tblInfo.Columns = cols - tblInfo.Charset = "utf8" - tblInfo.Collate = "utf8_bin" - return tblInfo, nil -} - -// testTableInfoWithPartition creates a test table with num int columns and with no index. -func testTableInfoWithPartition(t *testing.T, d *ddl, name string, num int) *model.TableInfo { - tblInfo, err := testTableInfo(d, name, num) - require.NoError(t, err) - genIDs, err := d.genGlobalIDs(1) - require.NoError(t, err) - pid := genIDs[0] - tblInfo.Partition = &model.PartitionInfo{ - Type: model.PartitionTypeRange, - Expr: tblInfo.Columns[0].Name.L, - Enable: true, - Definitions: []model.PartitionDefinition{{ - ID: pid, - Name: model.NewCIStr("p0"), - LessThan: []string{"maxvalue"}, - }}, - } - - return tblInfo -} - -// testTableInfoWithPartitionLessThan creates a test table with num int columns and one partition specified with lessthan. -func testTableInfoWithPartitionLessThan(t *testing.T, d *ddl, name string, num int, lessthan string) *model.TableInfo { - tblInfo := testTableInfoWithPartition(t, d, name, num) - tblInfo.Partition.Definitions[0].LessThan = []string{lessthan} - return tblInfo -} - -func testAddedNewTablePartitionInfo(t *testing.T, d *ddl, tblInfo *model.TableInfo, partName, lessthan string) *model.PartitionInfo { - genIDs, err := d.genGlobalIDs(1) - require.NoError(t, err) - pid := genIDs[0] - // the new added partition should change the partition state to state none at the beginning. - return &model.PartitionInfo{ - Type: model.PartitionTypeRange, - Expr: tblInfo.Columns[0].Name.L, - Enable: true, - Definitions: []model.PartitionDefinition{{ - ID: pid, - Name: model.NewCIStr(partName), - LessThan: []string{lessthan}, - }}, - } -} - -func testCreateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionCreateTable, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{tblInfo}, - } - ctx.SetValue(sessionctx.QueryString, "skip") - err := d.DoDDLJob(ctx, job) - require.NoError(t, err) - - v := getSchemaVer(t, ctx) - tblInfo.State = model.StatePublic - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - tblInfo.State = model.StateNone - return job -} - -func testDropTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropTable, - BinlogInfo: &model.HistoryInfo{}, - } - ctx.SetValue(sessionctx.QueryString, "skip") - require.NoError(t, d.DoDDLJob(ctx, job)) - - v := getSchemaVer(t, ctx) - checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func testCheckTableState(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { - require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - info, err := m.GetTable(dbInfo.ID, tblInfo.ID) - require.NoError(t, err) - - if state == model.StateNone { - require.NoError(t, err) - return nil - } - - require.Equal(t, info.Name, tblInfo.Name) - require.Equal(t, info.State, state) - return nil - })) -} - -func testGetTable(t *testing.T, d *ddl, schemaID int64, tableID int64) table.Table { - tbl, err := testGetTableWithError(d, schemaID, tableID) - require.NoError(t, err) - return tbl -} - -// for drop indexes -func createTestTableForDropIndexes(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, name string, num int) *model.TableInfo { - tableInfo, err := testTableInfo(d, name, num) - require.NoError(t, err) - var idxs []*model.IndexInfo - for i := 0; i < num; i++ { - idxName := model.NewCIStr(fmt.Sprintf("i%d", i+1)) - idx := &model.IndexInfo{ - Name: idxName, - State: model.StatePublic, - Columns: []*model.IndexColumn{{Name: model.NewCIStr(fmt.Sprintf("c%d", i+1))}}, - } - idxs = append(idxs, idx) - } - tableInfo.Indices = idxs - testCreateTable(t, ctx, d, dbInfo, tableInfo) - return tableInfo -} diff --git a/distsql/distsql.go b/distsql/distsql.go index 06104f0e368f9..cb2bbfaef5ff4 100644 --- a/distsql/distsql.go +++ b/distsql/distsql.go @@ -28,7 +28,6 @@ import ( "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/logutil" - topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/pingcap/tidb/util/trxevents" "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/tikvrpc/interceptor" @@ -96,7 +95,7 @@ func Select(ctx context.Context, sctx sessionctx.Context, kvReq *kv.Request, fie SessionMemTracker: sctx.GetSessionVars().StmtCtx.MemTracker, EnabledRateLimitAction: enabledRateLimitAction, EventCb: eventCb, - EnableCollectExecutionInfo: config.GetGlobalConfig().EnableCollectExecutionInfo, + EnableCollectExecutionInfo: config.GetGlobalConfig().Instance.EnableCollectExecutionInfo, } resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars, option) if resp == nil { @@ -257,7 +256,7 @@ func init() { // WithSQLKvExecCounterInterceptor binds an interceptor for client-go to count the // number of SQL executions of each TiKV (if any). func WithSQLKvExecCounterInterceptor(ctx context.Context, stmtCtx *stmtctx.StatementContext) context.Context { - if topsqlstate.TopSQLEnabled() && stmtCtx.KvExecCounter != nil { + if stmtCtx.KvExecCounter != nil { // Unlike calling Transaction or Snapshot interface, in distsql package we directly // face tikv Request. So we need to manually bind RPCInterceptor to ctx. Instead of // calling SetRPCInterceptor on Transaction or Snapshot. diff --git a/distsql/distsql_test.go b/distsql/distsql_test.go index 15d9919cca0ba..c7506923075af 100644 --- a/distsql/distsql_test.go +++ b/distsql/distsql_test.go @@ -20,7 +20,6 @@ import ( "testing" "time" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" @@ -33,6 +32,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/disk" "github.com/pingcap/tidb/util/execdetails" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tipb/go-tipb" @@ -249,7 +249,7 @@ func (resp *mockResponse) Next(context.Context) (kv.ResultSubset, error) { colTypes := make([]*types.FieldType, 4) for i := 0; i < 4; i++ { - colTypes[i] = &types.FieldType{Tp: mysql.TypeLonglong} + colTypes[i] = types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP() } chk := chunk.New(colTypes, numRows, numRows) @@ -325,15 +325,10 @@ func createSelectNormalByBenchmarkTest(batch, totalRows int, ctx sessionctx.Cont Build() // 4 int64 types. + ftb := types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeLonglong).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxIntWidth).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin) colTypes := []*types.FieldType{ - { - Tp: mysql.TypeLonglong, - Flen: mysql.MaxIntWidth, - Decimal: 0, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }, + ftb.BuildP(), } colTypes = append(colTypes, colTypes[0]) colTypes = append(colTypes, colTypes[0]) @@ -400,15 +395,10 @@ func createSelectNormal(t *testing.T, batch, totalRows int, planIDs []int, sctx require.NoError(t, err) // 4 int64 types. + ftb := types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeLonglong).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxIntWidth).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin) colTypes := []*types.FieldType{ - { - Tp: mysql.TypeLonglong, - Flen: mysql.MaxIntWidth, - Decimal: 0, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }, + ftb.BuildP(), } colTypes = append(colTypes, colTypes[0]) colTypes = append(colTypes, colTypes[0]) diff --git a/distsql/request_builder.go b/distsql/request_builder.go index e36a7086761e3..313df4cab23e4 100644 --- a/distsql/request_builder.go +++ b/distsql/request_builder.go @@ -36,8 +36,8 @@ import ( "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" - topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/pingcap/tipb/go-tipb" + "github.com/tikv/client-go/v2/tikvrpc" ) // RequestBuilder is used to build a "kv.Request". @@ -263,7 +263,7 @@ func (builder *RequestBuilder) SetFromSessionVars(sv *variable.SessionVars) *Req builder.Request.TaskID = sv.StmtCtx.TaskID builder.Request.Priority = builder.getKVPriority(sv) builder.Request.ReplicaRead = replicaReadType - builder.SetResourceGroupTagger(sv.StmtCtx) + builder.SetResourceGroupTagger(sv.StmtCtx.GetResourceGroupTagger()) return builder } @@ -306,10 +306,8 @@ func (builder *RequestBuilder) SetFromInfoSchema(pis interface{}) *RequestBuilde } // SetResourceGroupTagger sets the request resource group tagger. -func (builder *RequestBuilder) SetResourceGroupTagger(sc *stmtctx.StatementContext) *RequestBuilder { - if topsqlstate.TopSQLEnabled() { - builder.Request.ResourceGroupTagger = sc.GetResourceGroupTagger() - } +func (builder *RequestBuilder) SetResourceGroupTagger(tagger tikvrpc.ResourceGroupTagger) *RequestBuilder { + builder.Request.ResourceGroupTagger = tagger return builder } diff --git a/distsql/request_builder_test.go b/distsql/request_builder_test.go index 8d571656fadd4..3a2c7e60b200f 100644 --- a/distsql/request_builder_test.go +++ b/distsql/request_builder_test.go @@ -274,6 +274,7 @@ func TestRequestBuilder1(t *testing.T) { ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) } @@ -355,6 +356,7 @@ func TestRequestBuilder2(t *testing.T) { ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) } @@ -402,6 +404,7 @@ func TestRequestBuilder3(t *testing.T) { ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) } @@ -449,6 +452,7 @@ func TestRequestBuilder4(t *testing.T) { ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) } @@ -559,6 +563,7 @@ func TestRequestBuilder7(t *testing.T) { ReplicaRead: replicaRead.replicaReadType, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) }) } @@ -581,6 +586,7 @@ func TestRequestBuilder8(t *testing.T) { SchemaVar: 0, ReadReplicaScope: kv.GlobalReplicaScope, } + actual.ResourceGroupTagger = nil require.Equal(t, expect, actual) } diff --git a/docs/design/2020-06-24-placement-rules-in-sql.md b/docs/design/2020-06-24-placement-rules-in-sql.md index 5ca760585f61c..207e6a8a4a2eb 100644 --- a/docs/design/2020-06-24-placement-rules-in-sql.md +++ b/docs/design/2020-06-24-placement-rules-in-sql.md @@ -112,7 +112,7 @@ Behavior notes: - Placement policies are globally unique names. Thus, a policy named `companyplacementpolicy` can apply to the db `test` as well as `userdb`. The namespace does not overlap with other DB objects. - Placement Policy names are case insensitive, and follow the same rules as tables/other identifiers for length (64 chars) and special characters. - The full placement policy can be seen with `SHOW CREATE PLACEMENT POLICY x`. This is useful for shorthand usage by DBAs, and consistent with other database objects. -- It is possible to update the definition of a placement policy with `ALTER PLACEMENT POLICY x LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,+region=us-east-2:1}";` This is modeled on the statement `ALTER VIEW` (where the view needs to be redefined). When `ALTER PLACEMENT POLICY x` is executed, all tables that use this placement policy will need to be updated in PD. +- It is possible to update the definition of a placement policy with `ALTER PLACEMENT POLICY x LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1}";` This is modeled on the statement `ALTER VIEW` (where the view needs to be redefined). When `ALTER PLACEMENT POLICY x` is executed, all tables that use this placement policy will need to be updated in PD. - The statement `RENAME PLACEMENT POLICY x TO y` renames a placement policy. The `SHOW CREATE TABLE` output of all databases, tables and partitions that used this placement policy should be updated to the new name. #### Advanced Placement @@ -124,22 +124,13 @@ Consider the case where a user wants to allocate placement based on the label `d ALTER PLACEMENT POLICY `standardplacement` CONSTRAINTS="[+disk=ssd]"; ``` -The following two placement policies are considered equal: +When the constraints are specified as a dictionary (`{}`) numeric counts for each region must be specified and `FOLLOWERS=n` is disallowed: ```sql -CREATE PLACEMENT POLICY `standardplacement1` PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2" FOLLOWERS=4; -CREATE PLACEMENT POLICY `standardplacement2` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWERS_CONSTRAINTS="[+region=us-east-1,+region=us-east-2]" FOLLOWERS=4; -``` - -When the constraints is specified as a dictionary (`{}`) numeric counts for each region must be specified and `FOLLOWERS=n` is disallowed. The special `+any` constraint permits additional followers to be added with no constraints: - -```sql -ALTER PLACEMENT POLICY `standardplacement3` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,+region=us-east-2:1,+region=us-west-1:1,+any:1}"; +ALTER PLACEMENT POLICY `standardplacement3` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1,+region=us-west-1: 1}"; ``` -The placement policy above has 4 followers: -- 1 each in the regions us-east-1, us-east-2 and us-west-1 -- 1 that has no constraints and may reside in any location (including the previously specified regions) +The placement policy above has 3 followers: 1 each in the regions us-east-1, us-east-2 and us-west-1. Behavior notes: @@ -311,7 +302,7 @@ The constraints syntax (described as "Advanced Placement" above) allows placemen `CONSTRAINTS` should be a string and in one of these formats: - List: `[{+|-}key=value,...]`, e.g. `[+region=us-east-1,-disk=hdd]` -- Dictionary: `{"{+|-}key=value,...":count,...}`, e.g. `{"+region=us-east-1,-disk=hdd":1, +region=us-east-2:2}` +- Dictionary: `{"{+|-}key=value,...":count,...}`, e.g. `{"+region=us-east-1,-disk=hdd": 1, +region=us-east-2: 2}` The prefix `+` indicates that data can only be placed on the stores whose labels contain such labels, and `-` indicates that data can’t be placed on the stores whose labels contain such labels. For example, `+region=us-east-1,+region=us-east-2` indicates to place data only in `us-east-1` and `us-east-2` regions. @@ -326,19 +317,19 @@ Then `+region=us-east-1` matches this store while `+disk=ssd` doesn't. In the dictionary format, `count` must be specified, which indicates a quantity which must match. When the prefix is `-`, the `count` is still meaningful. -For example, `FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}"` indicates to place at least 1 follower in `us-east-1`, 2 replicas in anywhere but `us-east-2` (by definition this will be `us-east-1` since there are no other regions available). +For example, `FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,-region=us-east-2: 2}"` indicates to place at least 1 follower in `us-east-1`, 2 replicas in anywhere but `us-east-2` (by definition this will be `us-east-1` since there are no other regions available). In the list format, `count` is not specified. The number of followers for each constraint is not limited, but the total number of instances should still conform to the definition. -For example, `FOLLOWER_CONSTRAINTS="[+region=us-east-1,+region=us-east-2]" FOLLOWERS=3` indicates to place 3 followers on either `us-east-1` or `us-east-1`. There may be 2 replicas on `us-east-1` and 1 in `us-east-2`, or 2 in `us-east-2` and 1 in `us-east-1`. It's up to PD (see "Schedule Property" for additional details). +For example, `FOLLOWER_CONSTRAINTS="[+region=us-east-1]" FOLLOWERS=3` indicates to place 3 followers on either `us-east-1`. Label constraints can be implemented by defining `label_constraints` field in PD placement rule configuration. `+` and `-` correspond to property `op`. Specifically, `+` is equivalent to `in` and `-` is equivalent to `notIn`. -For example, `+region=us-east-1,+region=us-east-2,-disk=hdd` is equivalent to: +For example, `+region=us-east-1,-disk=hdd` is equivalent to: ``` "label_constraints": [ - {"key": "region", "op": "in", "values": ["us-east-1", "us-east-2"]}, + {"key": "region", "op": "in", "values": ["us-east-1"]}, {"key": "disk", "op": "notIn", "values": ["hdd"]} ] ``` @@ -351,28 +342,25 @@ The roles `FOLLOWERS` and `LEARNERS` also support an optional count in *list* fo ```sql CREATE PLACEMENT POLICY `standardplacement1` PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2" FOLLOWERS=4; -CREATE PLACEMENT POLICY `standardplacement2` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWERS_CONSTRAINTS="[+region=us-east-1,+region=us-east-2]" FOLLOWERS=4; +CREATE PLACEMENT POLICY `standardplacement2` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="[+region=us-east-2]" FOLLOWERS=4; ``` If the constraints is specified as a dictionary (e.g. `{"+region=us-east-1":1}`) the count is not applicable and an error is returned: ```sql -FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=3; -- technically accurate, but an error -FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=2; -- an error +FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,-region=us-east-2: 2}" FOLLOWERS=3; -- technically accurate, but an error +FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,-region=us-east-2: 2}" FOLLOWERS=2; -- an error ``` -For dictionary format, the count is inferred by the constraint. The following constraint creates 4 followers: +For dictionary format, the count is inferred by the constraint. The following constraint creates 3 followers: ```sql -FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2,+any:1}" +FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,-region=us-east-2: 2}" ``` Explanation: - 1 follower in `us-east-1` - 2 followers not in `us-east-2` -- 1 follower in any region (a special label of `+any`) - -`+any` changes an earlier proposal where the `FOLLOWERS` count could also be specified. This has been removed to reduce the risk of discrepancies and misconfiguration. See also "Policy Validation" below. #### Schedule Property @@ -380,7 +368,6 @@ When using either the syntactic sugar or list format for placement rules, PD is ```sql CREATE PLACEMENT POLICY `standardplacement1` PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2" FOLLOWERS=4; -CREATE PLACEMENT POLICY `standardplacement2` LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWERS_CONSTRAINTS="[+region=us-east-1,+region=us-east-2]" FOLLOWERS=4; ``` - Are each of the followers split equally in us-east-1 and us-east-2? @@ -413,14 +400,12 @@ When placement policies are specified, they should be validated for correctness: 2. A policy that is impossible based on the current topology (region=us-east-1 and followers=2, but there is only 1 store in us-east-1) should be a warning. This allows for some transitional topologies. 3. If the constraints are specified as a dictionary, specifying the count (i.e. `FOLLOWERS=n`) is prohibited. -#### Skipping Policy Validation +#### Skipping Placement Options -It should be possible to skip policy validation. This can be seen as similar to skipping foreign key checks, which is often used by logical dumpers: +It should be possible to skip placement options. This can be seen as similar to skipping foreign key checks, which is often used by logical dumpers: ```sql -SET FOREIGN_KEY_CHECKS=0; SET tidb_placement_mode='IGNORE'; - CREATE TABLE t3 (a int) PLACEMENT POLICY `mycompanypolicy`; ``` @@ -434,17 +419,11 @@ The following two policies are not identical: ```sql CREATE PLACEMENT POLICY p1 FOLLOWER_CONSTRAINTS="[+region=us-east-1,+region=us-east-2]" FOLLOWERS=2; -CREATE PLACEMENT POLICY p2 FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:1}"; +CREATE PLACEMENT POLICY p2 FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,-region=us-east-2: 1}"; ``` This is because p2 explicitly requires a follower count of 1 per region, whereas p1 allows for 2 in any of the above (see "Schedule Property" above for an explanation). -This is useful in the case that you want to ensure that `FOLLOWERS=2` exists in any of a list of zones: - -```sql -CREATE PLACEMENT POLICY p2 FOLLOWER_CONSTRAINTS="[+region=us-east-1,+region=us-east-2,+region=us-west-1]" FOLLOWERS=2; -``` - ### Additional Semantics #### Partitioned Tables @@ -643,7 +622,7 @@ However, an object (database, table, partition) may have multiple rules for a si ```sql CREATE PLACEMENT POLICY p1 - FOLLOWER_CONSTRAINTS="{+region=us-east-1:2,+region=us-east-2:1}"; + FOLLOWER_CONSTRAINTS="{+region=us-east-1: 2,+region=us-east-2: 1}"; CREATE TABLE t1 (a int) PLACEMENT POLICY p1; ``` @@ -815,7 +794,7 @@ In such a way, the most granular rule always works. This optimization is straight forward: ```sql -CREATE PLACEMENT POLICY local_stale_reads FOLLOWER_CONSTRAINTS="{+us-east-1:1,+us-east-2:1,+us-west-1:1,+us-west-2:1}"; +CREATE PLACEMENT POLICY local_stale_reads FOLLOWER_CONSTRAINTS="{+us-east-1: 1,+us-east-2: 1,+us-west-1: 1,+us-west-2: 1}"; CREATE TABLE t (a int, b int) PLACEMENT POLICY=`local_stale_reads`; ``` diff --git a/docs/design/2022-03-09-optimize-gc-for-internal-transaction.md b/docs/design/2022-03-09-optimize-gc-for-internal-transaction.md new file mode 100644 index 0000000000000..662491b451b43 --- /dev/null +++ b/docs/design/2022-03-09-optimize-gc-for-internal-transaction.md @@ -0,0 +1,139 @@ +# Optimize GC Advance For Internal Transactions + +- Author(s): [Michael](https://github.com/TonsnakeLin) +- Tracking Issue: https://github.com/pingcap/tidb/issues/32725 + +## Introduction + +This document describes the design of the feature "optimize gc advance for internal transaction", which adds the startTS(start timestamp) of all internal transactions to the gc(garbage collect) safepoint calculation process. + +## Motivation or Background + +TiDB advances gc safepoint every `tidb_gc_run_interval` time with the value `now - tidb_gc_life_time`. If there is a long time transaction from user client lives more than `tidb_gc_life_time`, the safepoint can't be advanced until the transaction is finished or lives over 24 hours. This mechanism ensures the continuous advancement of gc safepoint and ensures that the data active transactions need to access will not be cleared. + +However, Internal transactions run in TiDB don't comply with the mechanism above. If the internal transaction lives more than `tidb_gc_life_time`, it may fail because the data it needs to access was cleared. This design aims to resolve the problem that internal transaction run failed because data is cleared by the gc mechanism. + +## Detailed Design + +`Design Summary` describes the main processes of safepoint calculation and what job this design did. + +### Design Summary + +Currently here are two kinds of internal transactions. one is run by internal session, the other is run by function `RunInNewTxn`. This design aims to take account of all internal transactions when calculate gc safepoint. + +The design stores internal sessions to session manager and stores the internal transactions to `globalInnerTxnTsBox` so that it can get startTS of internal transactions when calculates gc safepoint. + +#### Calculate GC SafePoint + +Currently, the processes TiDB calculates safepoint is as bellow, it is implemented in `(is *InfoSyncer) ReportMinStartTS` + +- Get current timestamp from PD, save it to variable `now`, get timestamp that is 24 hours earlier than `now`, save it to variable `startTSLowerLimit` +- Get all user client sessions, save them to slice `processlist` +- Traverse `processlist` to get startTS from every client session and compare the `startTS` with `now` to get the minimum timestamp which is after `startTSLowerLimit` , save it as minStartTS which is gc safepoint. + +This design add extra processes in `(is *InfoSyncer) ReportMinStartTS` to take account of internal transactions startTS when calculates gc safepoint. The new processes TiDB calculates safepoint is as bellow. + - Get current timestamp from PD, save it to variable `now`, get timestamp that is earlier than `now` which is specified by system variable `tidb_gc_txn_max_wait_time`, save it to variable `startTSLowerLimit` +- Get all user client sessions, save them to slice `processlist` +- Get the startTS of every internal transaction run by internal session, save it to slice `InnerSessionStartTSList` +- Get the startTS of every internal transaction run by `RunInNewTxn`, save it to map `innerTxnStartTsMap` +- Traverse `processlist` to get startTS from every client session and compare the `startTS` with `now` to get the minimum timestamp which is after `startTSLowerLimit` , save it as `minStartTS`. +- Traverse `InnerSessionStartTSList` to get startTS and compare with `minStartTS` to get the minimum timestamp which is after `startTSLowerLimit` , save it also as `minStartTS`. +- Traverse `innerTxnStartTsMap` to get startTS and compare with `minStartTS` to get the minimum timestamp which is after `startTSLowerLimit` , save it also as `minStartTS` which is gc safepoint. + +#### Store And Delete Internal Sessions + +TiDB gets an internal session from a session pool implemented in `(s *session) getInternalSession`, when the transaction finished,it puts the session to the pool. It stores the session to session manager when gets an internal session, delete the session from session manager when returns the session to a pool. + +#### Store And Delete Internal Transactions + +The internal transactions here are executed by function `RunInNewTxn`. It stores the transaction to `globalInnerTxnTsBox` at the transaction's beginning and deletes the transaction at the end. +### Data Structure Design + +#### SessionManager + +TiDB manages client sessions by SessionManager interface. This design expands the SessionManager interface to manage internal sessions too. + +```go +type SessionManager interface { + // Put the internal session pointer to the map in the SessionManager + StoreInternalSession(se interface{}) + // Delete the internal session pointer from the map in the SessionManager + DeleteInternalSession(se interface{}) + // Get all startTS of every transactions running in the current internal sessions + GetInternalSessionStartTSList() []uint64 +} +``` + +#### innerTxnStartTsBox + +This design defines a global variable `globalInnerTxnTsBox` to manage internal transactions run by function `RunInNewTxn`. The map `innerTxnStartTsBox.innerTxnStartTsMap` stores all the internal transaction startTS. + +```go +var globalInnerTxnTsBox = innerTxnStartTsBox{ + innerTSLock: sync.Mutex{}, + innerTxnStartTsMap: make(map[uint64]struct{}, 256), +} + +type innerTxnStartTsBox struct { + innerTSLock sync.Mutex + innerTxnStartTsMap map[uint64]struct{} +} +``` + +### Functional design + +#### Store And Delete Internal Sessions + +TiDB gets an internal session from a session pool implemented in `(s *session) getInternalSession`, when the transaction finished,it puts the session to the pool. This design stores the internal session to session manger in the function `(s *session) getInternalSession` and deletes the internal session from session manager in the callback returned by `getInternalSession`. It calls the function `infosync.DeleteInternalSession()` to delete the internal session from session manager and calls the function `infosync.StoreInternalSession` to add the internal session to session manger. + +```go +func (s *session) getInternalSession(execOption sqlexec.ExecOption) (*session, func(), error) { + tmp, err := s.sysSessionPool().Get() + se := tmp.(*session) + // Put the internal session to the map of SessionManager + infosync.StoreInternalSession(se) + return se, func() { + // Delete the internal session to the map of SessionManager + infosync.DeleteInternalSession(se) + s.sysSessionPool().Put(tmp) + } +} +``` + +#### Store And Delete Internal Transactions + +The internal transactions here are executed by function `RunInNewTxn`. It stores the internal transaction startTS by function `wrapStoreInterTxnTS()` and deletes the transaction startTS by function `wrapDeleteInterTxnTS()`. + +```go +// RunInNewTxn will run the f in a new transaction environment. +func RunInNewTxn(ctx context.Context, store Storage, retryable bool, f func(ctx context.Context, txn Transaction) error) error { + defer func() { + wrapDeleteInterTxnTS(originalTxnTS) + }() + for i := uint(0); i < maxRetryCnt; i++ { + txn, err = store.Begin() + if i == 0 { + originalTxnTS = txn.StartTS() + wrapStoreInterTxnTS(originalTxnTS) + } + err = txn.Commit(ctx) + ... + } +} +``` + +#### Calculate GC Safepoint + +`ReportMinStartTS` calculates the minimum startTS of ongoing transactions (except the ones that exceed the limit), and it's result is useful for calculating the safepoint, which is gc_worker's work.This design add some code in the function `ReportMinStartTS` to consider internal transactions when calculates the minimum startTS. + +```go +func (is *InfoSyncer) ReportMinStartTS(store kv.Storage) {} +``` + +## Compatibility + +This feature does not affect compatibility. + +## Unresolved Questions + +Currently, It prints a log message such as "An internal transaction running by RunInNewTxn lasts more than 1 minute" when an internal transaction lasts more than 1 minute. In the future, we should print more detail messages in the log and add some monitor data showed on the grafana panel. diff --git a/docs/design/2022-03-16-functional-dependency.md b/docs/design/2022-03-16-functional-dependency.md new file mode 100644 index 0000000000000..821045a968036 --- /dev/null +++ b/docs/design/2022-03-16-functional-dependency.md @@ -0,0 +1,147 @@ +# Functional Dependency + +- Author(s): [AilinKid](https://github.com/AilinKid) (Lingxiang Tai) [winoros](https://github.com/winoros) (Yiding Cui) +- Last updated: 2022-03-16 +- Motivation Issue: https://github.com/pingcap/tidb/issues/29766 +- Related Document: https://pingcap.feishu.cn/docs/doccndyrRWfcGALhjcyVhOrxWYd + +## Table of Contents + +* [Introduction](#introduction) +* [Motivation And Background](#motivation-And-background) +* [Detail Design](#detail-design) + * [Implementation Overview](#implementation-overview) + * [How to store functional dependency](#how-to-store-functional-dependency) + * [How to maintain functional dependency](#how-to-maintain-functional-dependency) + * [How to integrate functional dependency with TiDB arch](#how-to-integrate-functional-dependency-with-tidb-arch) + * [Operator Overview](#operator-overview) + * [Logical Datasource](#logical-datasource) + * [Logical Selection](#logical-selection) + * [Logical Projection](#logical-projection) + * [Logical Aggregation](#logical-aggregation) + * [Logical Join](#logical-join) +* [Investigation](#investigation) +* [Unresolved Questions](#unresolved-questions) + +## Introduction + +Functional Dependency (abbreviated as FD below) is a traditional relation concept with a history as long as database itself. In relational database theory, a functional dependency is a constraint between two sets of attributes in a relation from a database. In other words, a functional dependency is a constraint between two attributes in a relation. + +Given a relation R and sets of attributes X,Y ∈ R, X is said to functionally determine Y (written as X → Y) if and only if each X value in R is associated with precisely one Y value in R; R is then said to satisfy the functional dependency X → Y. In other words, a dependency FD: X → Y means that the values of Y are determined by the values of X. Two tuples sharing the same values of X will necessarily have the same values of Y. + +## Motivation And Background + +Since we have already known the dependencies between sets of attributes (columns) after the FD has been built, we can make use of this relationship to do optimization in many scenarios. Eg: in only-full-group-by mode, for non-aggregated columns in the select list, as long as it is functionally dependent on the group-by clause columns, then we can consider it legal. Otherwise, extracting the constant, equivalence, dependency relationship between columns everytime we use it is tricky and costly. + +After trials and errors of only-full-group-by check, TiDB ultimately seeks to use functional dependency to solve its only-full-group-by check problem completely. Besides, functional dependency can also be applied to many other scenarios to reduce complexity, for example, distinct elimination with/without order by, selectivity for the correlated column and so on. + +## Detail Design + +### Implementation Overview + +* How to store functional dependency +* How to maintain functional dependency +* How to integrate functional dependency with TiDB arch + +#### How to store functional dependency + +Generally speaking, functional dependencies essentially store the relationship between columns. According to the paper [Exploiting functional dependence in query optimization](https://cs.uwaterloo.ca/research/tr/2000/11/CS-2000-11.thesis.pdf), this relationship can be constant, equivalence, strict and lax. Except constant is a unary, all others can be regarded as binary relationships. Therefore, we can use graph theory to store functional dependencies, maintaining edge sets between point-set and point-set, and attaching equivalence, strict and lax attributes as a label on each edge. For unary constant property, we can still save it as an edge, and since constant has no starting point-set, let's regard it as a headless edge. + +* equivalence: {a} == {b} +* strict FD: {a} -> {b} +* lax FD: {a} ~> {b} +* constant: { } -> {b} + +For computation convenience, we can optimize equivalence as {a,b} == {a,b}, so we don't have to search from both directions when confirming whether a point is in the equivalence set. + +#### How to maintain functional dependency + +For the open-sourced MySQL, the construction and maintenance of FD are still relatively heavy. It uses sub-queries as logical units and uses nested methods to recursively advance FD. For each logical unit, the source for where FD is derived is relatively simple, basically from three elements there: `GROUP BY` clause, `WHERE` clause and the datasource (join/table). However, according to the paper [CS-2000-11.thesis.pdf](https://cs.uwaterloo.ca/research/tr/2000/11/CS-2000-11.thesis.pdf), TiDB chooses to build FDs based on logical operators as an alternative, without the boundary restrictions of logical sub-queries. + +Example: + +```sql +create table t1(a int, c int) +create table t2(a int, b int) +explain select t1.a, count(t2.b), t1.c from t1 join t2 on t2.a=t1.a where t1.c=1 group by t2.a; +``` + +Result: + +```sql +mysql> explain select t1.a, count(t2.b), t1.c from t1 join t2 on t2.a=t1.a where t1.c=1 group by t2.a; ++----------------------------------+----------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++----------------------------------+----------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------+ +| Projection_9 | 12.49 | root | | test.t1.a, Column#7, test.t1.c | +| └─HashAgg_10 | 12.49 | root | | group by:test.t2.a, funcs:count(test.t2.b)->Column#7, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.c)->test.t1.c | +| └─HashJoin_12 | 12.49 | root | | inner join, equal:[eq(test.t1.a, test.t2.a)] | +| ├─TableReader_15(Build) | 9.99 | root | | data:Selection_14 | +| │ └─Selection_14 | 9.99 | cop[tikv] | | eq(test.t1.c, 1), not(isnull(test.t1.a)) | +| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─TableReader_18(Probe) | 9990.00 | root | | data:Selection_17 | +| └─Selection_17 | 9990.00 | cop[tikv] | | not(isnull(test.t2.a)) | +| └─TableFullScan_16 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | ++----------------------------------+----------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------+ +9 rows in set (0.00 sec) +``` + +Analysis: + +When building the FD through these logical operators, we call `ExtractFD()` recursively from the root node of the logical plan tree. When the call down to the leaf node (actually source table for both join side), for the inner side, the FD from the datasource of base table of t2 are nil because they have no basic key constraint. While for outer side, since there is a filter on the datasource of base table t1, we got FD as {} -> {t1.c}. Because t1.c can only be constant 1 behind the filter. Up to next level, the join condition t1=t2 will build the equivalence for point-set of {t1.a, t2.a} == {t1.a, t2.a}. Finally, when arriving the root aggregate node, we will build strict FD from group-by point-set {t2.a} to select aggregate function {count(t2.b)} reasonably. Consequently, we get FD as {} -> {t1.c} & {t1.a, t2.a} == {t1.a, t2.a} & {t2.a} -> {count(t2.b)}. + +Application: + +For the only-full-group-by check of building phase, after getting the FD as illustrated in the last subchapter, we can easily identify from the select list that t1.a is equivalent to the group-by column t2.a, count(t2.b) is strictly functional dependent on group-by column t2.a and t.c is definitely constant after the filter is passed. So it can pass only-full-group-by check here. For more sophisticated cases with recursive sub-queries, maintenance work of this kind of FD architecture will be automatical and reasonable because we're just pulling the request from the top node of the entire logical plan tree, and all things happen naturally. + +#### How to integrate functional dependency with TiDB arch + +Where to put this stuff in and when should the FD collection work be done? In FD logic, the relationship between columns is not limited to base col, but also between expressions, even sub-queries. We need to be able to identify sameness between cols, expressions and even better to have a unique id to tag them. When joining different tables, there are maybe some columns with the same name from different sources, we should still utilize this unified unique id to identify and distinguish them. Obviously, the expression tree after ast rewrite has this convenient functionality, and plus we need to utilize FD functionality to check validation when building a logical plan, so eventually we can only perform FD collection while building the logical plan stage. + +As illustrated above, tidb chooses the collect FD in units of logical operators. So for the first step, integrating FD collection logic for some meaningful logic operators is necessary, such as: datasource, join, apply, selection, projection and so on. For other meaningless logical operator like sort, it will not make any difference to FD collected from its child operator, so just output what it got from its child. The most important things in FD construction chain are from various join keys, join conditions, join types, selection predicates and group-by clause. Let's break it down and take it one by one in next chapter. + +### Operator Overview + +* Logical Datasource +* Logical Selection +* Logical Projection +* Logical Aggregation +* Logical Join + +#### Logical Datasource + +The logical datasource is the place where the most basic FD is generated. The natural FD is generated from the primary key and candidate key (unique) of the table, corresponding to strict FD and lax FD respectively. Of course, the not null attribute of the column is also a very important role. Because all rows related to null value can be rejected by that not null attribute, so that the related lax FD can become strict FD yet. + +#### Logical Selection + +As you can see from the sql example above, logical selection from where/having clause can be used to filter data. The selected data will have the properties constrained by this predicate. Most common FDs constructed from selection are constant, not null and equivalence, corresponding to t.a=1, t.a=1 and t.a = t.b respectively. The reason why t.a=1 can generate both constant and not null relationship is that in the expression calculation, if t.a is null, then null=1 will be calculated as null, and when the result of the predicate in where is null, this row will be rejected. So after the data is pulled from this filter, t.a mustn't be null and must be 1 only. For most operators, null value rejection characteristic is with them, which means that if a parameter on the any side of an operator is null, then the final result is null (just like what t.a=1 is shown here). + +#### Logical Projection + +Logical projection can be described simply because it does not generate FD itself, but truncate some useless FD sets according to the projected columns. For example, providing that the FD graph has {a} -> {b} & {b} -> {c}, when only the {a,c} columns are selected in the projection, we need to maintain the closure and transitive properties of this functional dependency graph, generating the remaining {a} -> {c} functional dependencies for the rest FD graph when column b is projected out. + +#### Logical Aggregation + +Logical aggregation mainly builds related FDs around the columns or expressions in the group by clause. It should be noted that if there is no group by clause but agg functions, all rows should be implicitly regarded as one group. Columns or expressions from group by clause naturally functional determine these aggregate expressions. But for others, they're waited to be judged, that's what and where only-full-group-by check does. + +#### Logical Join + +Logical join must be the most difficult part to infer with, because the presence of join key values, the variability of join conditions, and the difference of join types will all lead to the diversity of FD inference. For inner join, the final data comes first from cartesian product of inner and outer join side, and then pull the result through the filter generated from the inner join predicate (same as what selection does in where clause). Since reducing row data does not affect the presence of FD in that join side, data after the cartesian product can retain all FDs of operators at both sides of the join. But when data pulled through filters, it is necessary to add the FD generated by the inner join conditions. + +For outer join, we need to consider more, because outer join will choose the connection method based on the position of the join conditions and the presence of the join key. + +* only inner side condition --- apply inner filter after the cartesian product is made, which means no supplied-null row will be appended on the inner side if any row is preserved; or all rows are supplied-null if all rows are filtered out. +* has outer condition or join key --- apply all of this filter as matching judgement on the process of cartesian product, which means supplied-null row will be appended on the inner side when matching is failed. + +Although both cases will keep all rows from the outer side, but how to derive FDs from both sides depends on where the conditions come from, what the columns used by the conditions are, and what the attributes the conditions can provide. We can treat the former one as an inner join, but for the latter one, we can only keep the FD from the outer table of join, and inner side's FD and filter FD has many complicated rules to infer with, we are not going to expand all of this here. + +## References + +- [MySQL source code](https://github.com/mysql/mysql-server/blob/8.0/sql/aggregate_check.h) +- [Exploiting functional dependence in query optimization](https://cs.uwaterloo.ca/research/tr/2000/11/CS-2000-11.thesis.pdf). +- [functional dependency reduce](https://www.inf.usi.ch/faculty/soule/teaching/2014-spring/cover.pdf). +- [Canonical Cover of Functional Dependencies in DBMS](https://www.geeksforgeeks.org/canonical-cover-of-functional-dependencies-in-dbms/) + +## Unresolved Questions + +- None diff --git a/domain/db_test.go b/domain/db_test.go index 990ec2ad41a70..50d69f04f587f 100644 --- a/domain/db_test.go +++ b/domain/db_test.go @@ -19,7 +19,11 @@ import ( "testing" "time" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/server" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/stretchr/testify/require" @@ -56,3 +60,61 @@ func TestDomainSession(t *testing.T) { _, err = se.Execute(context.Background(), "create global binding for select * from t where i>100 using select * from t use index(index_t) where i>100") require.NoError(t, err) } + +func TestNormalSessionPool(t *testing.T) { + lease := 100 * time.Millisecond + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + err := store.Close() + require.NoError(t, err) + }() + session.SetSchemaLease(lease) + domain, err := session.BootstrapSession(store) + require.NoError(t, err) + defer domain.Close() + info, err1 := infosync.GlobalInfoSyncerInit(context.Background(), "t", func() uint64 { return 1 }, nil, true) + require.NoError(t, err1) + svr, err := server.NewServer(config.GetGlobalConfig(), nil) + require.NoError(t, err) + svr.SetDomain(domain) + svr.InitGlobalConnID(domain.ServerID) + info.SetSessionManager(svr) + + pool := domain.SysSessionPool() + se, err := pool.Get() + require.NoError(t, err) + require.NotEmpty(t, se) + require.Equal(t, svr.InternalSessionExists(se), true) + + pool.Put(se) + require.Equal(t, svr.InternalSessionExists(se), false) +} + +func TestAbnormalSessionPool(t *testing.T) { + lease := 100 * time.Millisecond + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + err := store.Close() + require.NoError(t, err) + }() + session.SetSchemaLease(lease) + domain, err := session.BootstrapSession(store) + require.NoError(t, err) + defer domain.Close() + info, err1 := infosync.GlobalInfoSyncerInit(context.Background(), "t", func() uint64 { return 1 }, nil, true) + require.NoError(t, err1) + svr, err := server.NewServer(config.GetGlobalConfig(), nil) + require.NoError(t, err) + svr.SetDomain(domain) + svr.InitGlobalConnID(domain.ServerID) + info.SetSessionManager(svr) + + pool := domain.SysSessionPool() + failpoint.Enable("github.com/pingcap/tidb/domain/mockSessionPoolReturnError", "return") + se, err := pool.Get() + require.Error(t, err) + failpoint.Disable("github.com/pingcap/tidb/domain/mockSessionPoolReturnError") + require.Equal(t, svr.InternalSessionExists(se), false) +} diff --git a/domain/domain.go b/domain/domain.go index 9272f7bd6be0a..9d8b22f8547ae 100644 --- a/domain/domain.go +++ b/domain/domain.go @@ -102,6 +102,16 @@ type Domain struct { sysProcesses SysProcesses } +// InfoCache export for test. +func (do *Domain) InfoCache() *infoschema.InfoCache { + return do.infoCache +} + +// EtcdClient export for test. +func (do *Domain) EtcdClient() *clientv3.Client { + return do.etcdClient +} + // loadInfoSchema loads infoschema at startTS. // It returns: // 1. the needed infoschema @@ -898,12 +908,24 @@ func (p *sessionPool) Get() (resource pools.Resource, err error) { default: resource, err = p.factory() } + + // Put the internal session to the map of SessionManager + failpoint.Inject("mockSessionPoolReturnError", func() { + err = errors.New("mockSessionPoolReturnError") + }) + + if nil == err { + infosync.StoreInternalSession(resource) + } + return } func (p *sessionPool) Put(resource pools.Resource) { p.mu.RLock() defer p.mu.RUnlock() + // Delete the internal session to the map of SessionManager + infosync.DeleteInternalSession(resource) if p.mu.closed { resource.Close() return @@ -1247,7 +1269,7 @@ func (do *Domain) StatsHandle() *handle.Handle { // CreateStatsHandle is used only for test. func (do *Domain) CreateStatsHandle(ctx sessionctx.Context) error { - h, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses) + h, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses, do.ServerID) if err != nil { return err } @@ -1286,7 +1308,7 @@ func (do *Domain) LoadAndUpdateStatsLoop(ctxs []sessionctx.Context) error { // It should be called only once in BootstrapSession. func (do *Domain) UpdateTableStatsLoop(ctx sessionctx.Context) error { ctx.GetSessionVars().InRestrictedSQL = true - statsHandle, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses) + statsHandle, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses, do.ServerID) if err != nil { return err } diff --git a/domain/domain_test.go b/domain/domain_test.go index ff85c1074cc3c..b5783a2b97013 100644 --- a/domain/domain_test.go +++ b/domain/domain_test.go @@ -17,7 +17,6 @@ package domain import ( "context" "crypto/tls" - "math" "net" "runtime" "testing" @@ -29,20 +28,14 @@ import ( "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/session/txninfo" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/mock" dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/require" - "github.com/tikv/client-go/v2/oracle" - "github.com/tikv/client-go/v2/tikv" "go.etcd.io/etcd/tests/v3/integration" ) @@ -156,164 +149,17 @@ func TestInfo(t *testing.T) { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/infosync/FailPlacement")) } -func TestDomain(t *testing.T) { +func TestStatWorkRecoverFromPanic(t *testing.T) { store, err := mockstore.NewMockStore() require.NoError(t, err) ddlLease := 80 * time.Millisecond dom := NewDomain(store, ddlLease, 0, 0, 0, mockFactory, nil) - err = dom.Init(ddlLease, sysMockFactory) - require.NoError(t, err) - - ctx := mock.NewContext() - ctx.Store = dom.Store() - dd := dom.DDL() - ddl.DisableTiFlashPoll(dd) - require.NotNil(t, dd) - require.Equal(t, 80*time.Millisecond, dd.GetLease()) - - snapTS := oracle.GoTimeToTS(time.Now()) - cs := &ast.CharsetOpt{ - Chs: "utf8", - Col: "utf8_bin", - } - ctx.SetValue(sessionctx.QueryString, "skip") - err = dd.CreateSchema(ctx, model.NewCIStr("aaa"), cs, nil) - require.NoError(t, err) - - // Test for fetchSchemasWithTables when "tables" isn't nil. - ctx.SetValue(sessionctx.QueryString, "skip") - err = dd.CreateTable(ctx, &ast.CreateTableStmt{Table: &ast.TableName{ - Schema: model.NewCIStr("aaa"), - Name: model.NewCIStr("tbl")}}) - require.NoError(t, err) - - is := dom.InfoSchema() - require.NotNil(t, is) - - // for updating the self schema version - goCtx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - err = dd.SchemaSyncer().OwnerCheckAllVersions(goCtx, is.SchemaMetaVersion()) - cancel() - require.NoError(t, err) - - snapIs, err := dom.GetSnapshotInfoSchema(snapTS) - require.NotNil(t, snapIs) - require.NoError(t, err) - - // Make sure that the self schema version doesn't be changed. - goCtx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond) - err = dd.SchemaSyncer().OwnerCheckAllVersions(goCtx, is.SchemaMetaVersion()) - cancel() - require.NoError(t, err) - - // for GetSnapshotInfoSchema - currSnapTS := oracle.GoTimeToTS(time.Now()) - currSnapIs, err := dom.GetSnapshotInfoSchema(currSnapTS) - require.NoError(t, err) - require.NotNil(t, currSnapTS) - require.Equal(t, is.SchemaMetaVersion(), currSnapIs.SchemaMetaVersion()) - - // for GetSnapshotMeta - dbInfo, ok := currSnapIs.SchemaByName(model.NewCIStr("aaa")) - require.True(t, ok) - - tbl, err := currSnapIs.TableByName(model.NewCIStr("aaa"), model.NewCIStr("tbl")) - require.NoError(t, err) - - m, err := dom.GetSnapshotMeta(snapTS) - require.NoError(t, err) - - tblInfo1, err := m.GetTable(dbInfo.ID, tbl.Meta().ID) - require.True(t, meta.ErrDBNotExists.Equal(err)) - require.Nil(t, tblInfo1) - - m, err = dom.GetSnapshotMeta(currSnapTS) - require.NoError(t, err) - - tblInfo2, err := m.GetTable(dbInfo.ID, tbl.Meta().ID) - require.NoError(t, err) - require.Equal(t, tblInfo2, tbl.Meta()) - - // Test for tryLoadSchemaDiffs when "isTooOldSchema" is false. - ctx.SetValue(sessionctx.QueryString, "skip") - err = dd.CreateSchema(ctx, model.NewCIStr("bbb"), cs, nil) - require.NoError(t, err) - - err = dom.Reload() - require.NoError(t, err) - - // for schemaValidator - schemaVer := dom.SchemaValidator.(*schemaValidator).LatestSchemaVersion() - ver, err := store.CurrentVersion(kv.GlobalTxnScope) - require.NoError(t, err) - - ts := ver.Ver - _, res := dom.SchemaValidator.Check(ts, schemaVer, nil) - require.Equal(t, ResultSucc, res) - - require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/ErrorMockReloadFailed", `return(true)`)) - - err = dom.Reload() - require.Error(t, err) - _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) - require.Equal(t, ResultSucc, res) - time.Sleep(ddlLease) - - ver, err = store.CurrentVersion(kv.GlobalTxnScope) - require.NoError(t, err) - ts = ver.Ver - _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) - require.Equal(t, ResultUnknown, res) - - require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/ErrorMockReloadFailed")) - err = dom.Reload() - require.NoError(t, err) - - _, res = dom.SchemaValidator.Check(ts, schemaVer, nil) - require.Equal(t, ResultSucc, res) - - // For slow query. - dom.LogSlowQuery(&SlowQueryInfo{SQL: "aaa", Duration: time.Second, Internal: true}) - dom.LogSlowQuery(&SlowQueryInfo{SQL: "bbb", Duration: 3 * time.Second}) - dom.LogSlowQuery(&SlowQueryInfo{SQL: "ccc", Duration: 2 * time.Second}) - // Collecting slow queries is asynchronous, wait a while to ensure it's done. - time.Sleep(5 * time.Millisecond) - - result := dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 2}) - require.Len(t, result, 2) - require.Equal(t, "bbb", result[0].SQL) - require.Equal(t, 3*time.Second, result[0].Duration) - require.Equal(t, "ccc", result[1].SQL) - require.Equal(t, 2*time.Second, result[1].Duration) - - result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 2, Kind: ast.ShowSlowKindInternal}) - require.Len(t, result, 1) - require.Equal(t, "aaa", result[0].SQL) - require.Equal(t, time.Second, result[0].Duration) - require.True(t, result[0].Internal) - - result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowTop, Count: 4, Kind: ast.ShowSlowKindAll}) - require.Len(t, result, 3) - require.Equal(t, "bbb", result[0].SQL) - require.Equal(t, 3*time.Second, result[0].Duration) - require.Equal(t, "ccc", result[1].SQL) - require.Equal(t, 2*time.Second, result[1].Duration) - require.Equal(t, "aaa", result[2].SQL) - require.Equal(t, time.Second, result[2].Duration) - require.True(t, result[2].Internal) - - result = dom.ShowSlowQuery(&ast.ShowSlow{Tp: ast.ShowSlowRecent, Count: 2}) - require.Len(t, result, 2) - require.Equal(t, "ccc", result[0].SQL) - require.Equal(t, 2*time.Second, result[0].Duration) - require.Equal(t, "bbb", result[1].SQL) - require.Equal(t, 3*time.Second, result[1].Duration) metrics.PanicCounter.Reset() // Since the stats lease is 0 now, so create a new ticker will panic. // Test that they can recover from panic correctly. - dom.updateStatsWorker(ctx, nil) + dom.updateStatsWorker(mock.NewContext(), nil) dom.autoAnalyzeWorker(nil) counter := metrics.PanicCounter.WithLabelValues(metrics.LabelDomain) pb := &dto.Metric{} @@ -324,46 +170,6 @@ func TestDomain(t *testing.T) { scope := dom.GetScope("status") require.Equal(t, variable.DefaultStatusVarScopeFlag, scope) - // For schema check, it tests for getting the result of "ResultUnknown". - schemaChecker := NewSchemaChecker(dom, is.SchemaMetaVersion(), nil) - originalRetryTime := SchemaOutOfDateRetryTimes.Load() - originalRetryInterval := SchemaOutOfDateRetryInterval.Load() - // Make sure it will retry one time and doesn't take a long time. - SchemaOutOfDateRetryTimes.Store(1) - SchemaOutOfDateRetryInterval.Store(time.Millisecond * 1) - defer func() { - SchemaOutOfDateRetryTimes.Store(originalRetryTime) - SchemaOutOfDateRetryInterval.Store(originalRetryInterval) - }() - dom.SchemaValidator.Stop() - _, err = schemaChecker.Check(uint64(123456)) - require.EqualError(t, err, ErrInfoSchemaExpired.Error()) - dom.SchemaValidator.Reset() - - // Test for reporting min start timestamp. - infoSyncer := dom.InfoSyncer() - sm := &mockSessionManager{ - PS: make([]*util.ProcessInfo, 0), - } - infoSyncer.SetSessionManager(sm) - beforeTS := oracle.GoTimeToTS(time.Now()) - infoSyncer.ReportMinStartTS(dom.Store()) - afterTS := oracle.GoTimeToTS(time.Now()) - require.False(t, infoSyncer.GetMinStartTS() > beforeTS && infoSyncer.GetMinStartTS() < afterTS) - - now := time.Now() - validTS := oracle.GoTimeToLowerLimitStartTS(now.Add(time.Minute), tikv.MaxTxnTimeUse) - lowerLimit := oracle.GoTimeToLowerLimitStartTS(now, tikv.MaxTxnTimeUse) - sm.PS = []*util.ProcessInfo{ - {CurTxnStartTS: 0}, - {CurTxnStartTS: math.MaxUint64}, - {CurTxnStartTS: lowerLimit}, - {CurTxnStartTS: validTS}, - } - infoSyncer.SetSessionManager(sm) - infoSyncer.ReportMinStartTS(dom.Store()) - require.Equal(t, validTS, infoSyncer.GetMinStartTS()) - err = store.Close() require.NoError(t, err) @@ -409,46 +215,3 @@ func (mebd *mockEtcdBackend) TLSConfig() *tls.Config { return nil } func (mebd *mockEtcdBackend) StartGCWorker() error { panic("not implemented") } - -type mockSessionManager struct { - PS []*util.ProcessInfo -} - -func (msm *mockSessionManager) ShowTxnList() []*txninfo.TxnInfo { - panic("unimplemented!") -} - -func (msm *mockSessionManager) ShowProcessList() map[uint64]*util.ProcessInfo { - ret := make(map[uint64]*util.ProcessInfo) - for _, item := range msm.PS { - ret[item.ID] = item - } - return ret -} - -func (msm *mockSessionManager) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) { - for _, item := range msm.PS { - if item.ID == id { - return item, true - } - } - return &util.ProcessInfo{}, false -} - -func (msm *mockSessionManager) Kill(uint64, bool) {} - -func (msm *mockSessionManager) KillAllConnections() {} - -func (msm *mockSessionManager) UpdateTLSConfig(*tls.Config) {} - -func (msm *mockSessionManager) ServerID() uint64 { - return 1 -} - -func (msm *mockSessionManager) StoreInternalSession(se interface{}) {} - -func (msm *mockSessionManager) DeleteInternalSession(se interface{}) {} - -func (msm *mockSessionManager) GetInternalSessionStartTSList() []uint64 { - return nil -} diff --git a/domain/schema_validator.go b/domain/schema_validator.go index bbdf8f8d6641e..ebda832ea5b43 100644 --- a/domain/schema_validator.go +++ b/domain/schema_validator.go @@ -94,13 +94,6 @@ func (s *schemaValidator) IsStarted() bool { return isStarted } -func (s *schemaValidator) LatestSchemaVersion() int64 { - s.mux.RLock() - latestSchemaVer := s.latestSchemaVer - s.mux.RUnlock() - return latestSchemaVer -} - func (s *schemaValidator) Stop() { logutil.BgLogger().Info("the schema validator stops") metrics.LoadSchemaCounter.WithLabelValues(metrics.SchemaValidatorStop).Inc() diff --git a/domain/sysvar_cache.go b/domain/sysvar_cache.go index a0389b7e4bff4..5f3862567056e 100644 --- a/domain/sysvar_cache.go +++ b/domain/sysvar_cache.go @@ -25,9 +25,6 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/stmtsummary" - topsqlstate "github.com/pingcap/tidb/util/topsql/state" - storekv "github.com/tikv/client-go/v2/kv" pd "github.com/tikv/pd/client" "go.uber.org/zap" ) @@ -142,9 +139,24 @@ func (do *Domain) rebuildSysVarCache(ctx sessionctx.Context) error { } if sv.HasGlobalScope() { newGlobalCache[sv.Name] = sVal + + // Call the SetGlobal func for this sysvar if it exists. + // SET GLOBAL only calls the SetGlobal func on the calling instances. + // This ensures it is run on all tidb servers. + // This does not apply to INSTANCE scoped vars (HasGlobalScope() is false) + if sv.SetGlobal != nil && !sv.SkipSysvarCache() { + sVal = sv.ValidateWithRelaxedValidation(ctx.GetSessionVars(), sVal, variable.ScopeGlobal) + err = sv.SetGlobal(ctx.GetSessionVars(), sVal) + if err != nil { + logutil.BgLogger().Error(fmt.Sprintf("load global variable %s error", sv.Name), zap.Error(err)) + } + } } - // Propagate any changes to the server scoped variables - do.checkEnableServerGlobalVar(sv.Name, sVal) + + // Some PD options need to be checked outside of the SetGlobal func. + // This is also done for the SET GLOBAL caller in executor/set.go, + // but here we check for other tidb instances. + do.checkPDClientDynamicOption(sv.Name, sVal) } logutil.BgLogger().Debug("rebuilding sysvar cache") @@ -156,19 +168,10 @@ func (do *Domain) rebuildSysVarCache(ctx sessionctx.Context) error { return nil } -// checkEnableServerGlobalVar processes variables that acts in server and global level. -// This is required because the SetGlobal function on the sysvar struct only executes on -// the initiating tidb-server. There is no current method to say "run this function on all -// tidb servers when the value of this variable changes". If you do not require changes to -// be applied on all servers, use a getter/setter instead! You don't need to add to this list. -func (do *Domain) checkEnableServerGlobalVar(name, sVal string) { - var err error +func (do *Domain) checkPDClientDynamicOption(name, sVal string) { switch name { - case variable.TiDBMemQuotaBindingCache: - variable.MemQuotaBindingCache.Store(variable.TidbOptInt64(sVal, variable.DefTiDBMemQuotaBindingCache)) case variable.TiDBTSOClientBatchMaxWaitTime: - var val float64 - val, err = strconv.ParseFloat(sVal, 64) + val, err := strconv.ParseFloat(sVal, 64) if err != nil { break } @@ -179,82 +182,11 @@ func (do *Domain) checkEnableServerGlobalVar(name, sVal string) { variable.MaxTSOBatchWaitInterval.Store(val) case variable.TiDBEnableTSOFollowerProxy: val := variable.TiDBOptOn(sVal) - err = do.SetPDClientDynamicOption(pd.EnableTSOFollowerProxy, val) + err := do.SetPDClientDynamicOption(pd.EnableTSOFollowerProxy, val) if err != nil { break } variable.EnableTSOFollowerProxy.Store(val) - case variable.TiDBEnableLocalTxn: - variable.EnableLocalTxn.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBEnableStmtSummary: - err = stmtsummary.StmtSummaryByDigestMap.SetEnabled(variable.TiDBOptOn(sVal)) - case variable.TiDBStmtSummaryInternalQuery: - err = stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(variable.TiDBOptOn(sVal)) - case variable.TiDBStmtSummaryRefreshInterval: - err = stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(variable.TidbOptInt64(sVal, variable.DefTiDBStmtSummaryRefreshInterval)) - case variable.TiDBStmtSummaryHistorySize: - err = stmtsummary.StmtSummaryByDigestMap.SetHistorySize(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryHistorySize)) - case variable.TiDBStmtSummaryMaxStmtCount: - err = stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(uint(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryMaxStmtCount))) - case variable.TiDBStmtSummaryMaxSQLLength: - err = stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryMaxSQLLength)) - case variable.TiDBTopSQLMaxTimeSeriesCount: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - topsqlstate.GlobalState.MaxStatementCount.Store(val) - case variable.TiDBTopSQLMaxMetaCount: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - topsqlstate.GlobalState.MaxCollect.Store(val) - case variable.TiDBRestrictedReadOnly: - variable.RestrictedReadOnly.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBSuperReadOnly: - variable.VarTiDBSuperReadOnly.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBStoreLimit: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - storekv.StoreLimit.Store(val) - case variable.TiDBTableCacheLease: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - variable.TableCacheLease.Store(val) - case variable.TiDBGCMaxWaitTime: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - variable.GCMaxWaitTime.Store(val) - case variable.TiDBPersistAnalyzeOptions: - variable.PersistAnalyzeOptions.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBEnableColumnTracking: - variable.EnableColumnTracking.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBStatsLoadSyncWait: - var val int64 - val, err = strconv.ParseInt(sVal, 10, 64) - if err != nil { - break - } - variable.StatsLoadSyncWait.Store(val) - case variable.TiDBStatsLoadPseudoTimeout: - variable.StatsLoadPseudoTimeout.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBTxnCommitBatchSize: - storekv.TxnCommitBatchSize.Store(uint64(variable.TidbOptInt64(sVal, int64(storekv.DefTxnCommitBatchSize)))) - } - if err != nil { - logutil.BgLogger().Error(fmt.Sprintf("load global variable %s error", name), zap.Error(err)) } } diff --git a/dumpling/export/config.go b/dumpling/export/config.go index 726c9fcf23afc..d8aecbaf670ea 100644 --- a/dumpling/export/config.go +++ b/dumpling/export/config.go @@ -81,6 +81,7 @@ type Config struct { storage.BackendOptions ExtStorage storage.ExternalStorage `json:"-"` + specifiedTables bool AllowCleartextPasswords bool SortByPk bool NoViews bool @@ -122,21 +123,20 @@ type Config struct { CsvDelimiter string Databases []string - TableFilter filter.Filter `json:"-"` - Where string - FileType string - ServerInfo version.ServerInfo - Logger *zap.Logger `json:"-"` - OutputFileTemplate *template.Template `json:"-"` - Rows uint64 - ReadTimeout time.Duration - TiDBMemQuotaQuery uint64 - FileSize uint64 - StatementSize uint64 - SessionParams map[string]interface{} - Labels prometheus.Labels `json:"-"` - Tables DatabaseTables - + TableFilter filter.Filter `json:"-"` + Where string + FileType string + ServerInfo version.ServerInfo + Logger *zap.Logger `json:"-"` + OutputFileTemplate *template.Template `json:"-"` + Rows uint64 + ReadTimeout time.Duration + TiDBMemQuotaQuery uint64 + FileSize uint64 + StatementSize uint64 + SessionParams map[string]interface{} + Labels prometheus.Labels `json:"-"` + Tables DatabaseTables CollationCompatible string } @@ -182,6 +182,7 @@ func DefaultConfig() *Config { OutputFileTemplate: DefaultOutputFileTemplate, PosAfterConnect: false, CollationCompatible: LooseCollationCompatible, + specifiedTables: false, } } @@ -456,6 +457,12 @@ func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error { return errors.Trace(err) } + conf.specifiedTables = len(tablesList) > 0 + conf.Tables, err = GetConfTables(tablesList) + if err != nil { + return errors.Trace(err) + } + conf.TableFilter, err = ParseTableFilter(tablesList, filters) if err != nil { return errors.Errorf("failed to parse filter: %s", err) @@ -536,6 +543,25 @@ func ParseTableFilter(tablesList, filters []string) (filter.Filter, error) { return filter.NewTablesFilter(tableNames...), nil } +func GetConfTables(tablesList []string) (DatabaseTables, error) { + dbTables := DatabaseTables{} + var ( + tablename string + avgRowLength uint64 + ) + avgRowLength = 0 + for _, tablename = range tablesList { + parts := strings.SplitN(tablename, ".", 2) + if len(parts) < 2 { + return nil, errors.Errorf("--tables-list only accepts qualified table names, but `%s` lacks a dot", tablename) + } + dbName := parts[0] + tbName := parts[1] + dbTables[dbName] = append(dbTables[dbName], &TableInfo{tbName, avgRowLength, TableTypeBase}) + } + return dbTables, nil +} + // ParseCompressType parses compressType string to storage.CompressType func ParseCompressType(compressType string) (storage.CompressType, error) { switch compressType { diff --git a/dumpling/export/config_test.go b/dumpling/export/config_test.go index a0e34b208292d..b799d25487fe6 100644 --- a/dumpling/export/config_test.go +++ b/dumpling/export/config_test.go @@ -3,6 +3,7 @@ package export import ( + "fmt" "testing" "github.com/pingcap/tidb/br/pkg/version" @@ -32,3 +33,22 @@ func TestMatchMysqlBugVersion(t *testing.T) { require.Equalf(t, x.expected, matchMysqlBugversion(x.serverInfo), "server info: %s", x.serverInfo) } } + +func TestGetConfTables(t *testing.T) { + tablesList := []string{"db1t1", "db2.t1"} + _, err := GetConfTables(tablesList) + require.EqualError(t, err, fmt.Sprintf("--tables-list only accepts qualified table names, but `%s` lacks a dot", tablesList[0])) + + tablesList = []string{"db1.t1", "db2t1"} + _, err = GetConfTables(tablesList) + require.EqualError(t, err, fmt.Sprintf("--tables-list only accepts qualified table names, but `%s` lacks a dot", tablesList[1])) + + tablesList = []string{"db1.t1", "db2.t1"} + expectedDBTables := NewDatabaseTables(). + AppendTables("db1", []string{"t1"}, []uint64{0}). + AppendTables("db2", []string{"t1"}, []uint64{0}) + actualDBTables, err := GetConfTables(tablesList) + require.NoError(t, err) + require.Equal(t, expectedDBTables, actualDBTables) + +} diff --git a/dumpling/export/consistency.go b/dumpling/export/consistency.go index ef8ba9f31bbe8..8f3552fa4abfe 100644 --- a/dumpling/export/consistency.go +++ b/dumpling/export/consistency.go @@ -145,7 +145,7 @@ func (c *ConsistencyLockDumpingTables) Setup(tctx *tcontext.Context) error { } } return errors.Trace(err) - }, newLockTablesBackoffer(tctx, blockList)) + }, newLockTablesBackoffer(tctx, blockList, c.conf)) } // TearDown implements ConsistencyController.TearDown diff --git a/dumpling/export/dump.go b/dumpling/export/dump.go index 0e1087e9eebb3..e2e9e81a3cdc9 100755 --- a/dumpling/export/dump.go +++ b/dumpling/export/dump.go @@ -536,17 +536,17 @@ func adjustColumnsCollation(tctx *tcontext.Context, createStmt *ast.CreateTableS } } fieldType := col.Tp - if fieldType.Collate != "" { + if fieldType.GetCollate() != "" { continue } - if fieldType.Charset != "" { + if fieldType.GetCharset() != "" { // just have charset - collation, ok := charsetAndDefaultCollationMap[strings.ToLower(fieldType.Charset)] + collation, ok := charsetAndDefaultCollationMap[strings.ToLower(fieldType.GetCharset())] if !ok { - tctx.L().Warn("not found charset default collation for column.", zap.String("table", createStmt.Table.Name.String()), zap.String("column", col.Name.String()), zap.String("charset", strings.ToLower(fieldType.Charset))) + tctx.L().Warn("not found charset default collation for column.", zap.String("table", createStmt.Table.Name.String()), zap.String("column", col.Name.String()), zap.String("charset", strings.ToLower(fieldType.GetCharset()))) continue } - fieldType.Collate = collation + fieldType.SetCollate(collation) } } } @@ -1086,6 +1086,9 @@ func getListTableTypeByConf(conf *Config) listTableType { } func prepareTableListToDump(tctx *tcontext.Context, conf *Config, db *sql.Conn) error { + if conf.specifiedTables { + return nil + } databases, err := prepareDumpingDatabases(tctx, conf, db) if err != nil { return err diff --git a/dumpling/export/retry.go b/dumpling/export/retry.go index b1866c06065d7..f2bd998df8ccb 100644 --- a/dumpling/export/retry.go +++ b/dumpling/export/retry.go @@ -88,7 +88,14 @@ func (b *noopBackoffer) Reset() { b.attempt = 1 } -func newLockTablesBackoffer(tctx *tcontext.Context, blockList map[string]map[string]interface{}) *lockTablesBackoffer { +func newLockTablesBackoffer(tctx *tcontext.Context, blockList map[string]map[string]interface{}, conf *Config) *lockTablesBackoffer { + if conf.specifiedTables { + return &lockTablesBackoffer{ + tctx: tctx, + attempt: 1, + blockList: blockList, + } + } return &lockTablesBackoffer{ tctx: tctx, attempt: lockTablesRetryTime, diff --git a/dumpling/export/sql_test.go b/dumpling/export/sql_test.go index 82ba0addeab49..74df4557c6caf 100644 --- a/dumpling/export/sql_test.go +++ b/dumpling/export/sql_test.go @@ -11,8 +11,6 @@ import ( "fmt" "io" "os" - "path" - "runtime" "strconv" "strings" "testing" @@ -1306,9 +1304,7 @@ func buildMockNewRows(mock sqlmock.Sqlmock, columns []string, driverValues [][]d } func readRegionCsvDriverValues(t *testing.T) [][]driver.Value { - // nolint: dogsled - _, filename, _, _ := runtime.Caller(0) - csvFilename := path.Join(path.Dir(filename), "region_results.csv") + csvFilename := "region_results.csv" file, err := os.Open(csvFilename) require.NoError(t, err) csvReader := csv.NewReader(file) diff --git a/dumpling/tests/_utils/run_services b/dumpling/tests/_utils/run_services index d7a18f4bfa74a..363e39c8fef66 100755 --- a/dumpling/tests/_utils/run_services +++ b/dumpling/tests/_utils/run_services @@ -36,7 +36,6 @@ start_services() { cat > "$DUMPLING_TEST_DIR/tidb.toml" < maxQueryLen { + maxQueryLen := variable.QueryLogMaxLen.Load() + if maxQueryLen <= 0 { + return QueryReplacer.Replace(sql) // no limit + } + if int32(length) > maxQueryLen { sql = fmt.Sprintf("%.*q(len:%d)", maxQueryLen, sql, length) } return QueryReplacer.Replace(sql) @@ -1010,8 +1023,8 @@ func (a *ExecStmt) LogSlowQuery(txnTS uint64, succ bool, hasMoreResults bool) { level := log.GetLevel() cfg := config.GetGlobalConfig() costTime := time.Since(sessVars.StartTime) + sessVars.DurationParse - threshold := time.Duration(atomic.LoadUint64(&cfg.Log.SlowThreshold)) * time.Millisecond - enable := cfg.Log.EnableSlowLog.Load() + threshold := time.Duration(atomic.LoadUint64(&cfg.Instance.SlowThreshold)) * time.Millisecond + enable := cfg.Instance.EnableSlowLog.Load() // if the level is Debug, or trace is enabled, print slow logs anyway force := level <= zapcore.DebugLevel || trace.IsEnabled() if (!enable || costTime < threshold) && !force { @@ -1055,7 +1068,7 @@ func (a *ExecStmt) LogSlowQuery(txnTS uint64, succ bool, hasMoreResults bool) { statsInfos := plannercore.GetStatsInfo(a.Plan) memMax := sessVars.StmtCtx.MemTracker.MaxConsumed() diskMax := sessVars.StmtCtx.DiskTracker.MaxConsumed() - _, planDigest := getPlanDigest(a.Ctx, a.Plan) + _, planDigest := getPlanDigest(sessVars.StmtCtx, a.Plan) slowItems := &variable.SlowQueryLogItems{ TxnTS: txnTS, SQL: sql.String(), @@ -1152,7 +1165,7 @@ func GetResultRowsCount(sctx sessionctx.Context, p plannercore.Plan) int64 { // getPlanTree will try to get the select plan tree if the plan is select or the select plan of delete/update/insert statement. func getPlanTree(sctx sessionctx.Context, p plannercore.Plan) string { cfg := config.GetGlobalConfig() - if atomic.LoadUint32(&cfg.Log.RecordPlanInSlowLog) == 0 { + if atomic.LoadUint32(&cfg.Instance.RecordPlanInSlowLog) == 0 { return "" } planTree, _ := getEncodedPlan(sctx, p, false) @@ -1163,8 +1176,7 @@ func getPlanTree(sctx sessionctx.Context, p plannercore.Plan) string { } // getPlanDigest will try to get the select plan tree if the plan is select or the select plan of delete/update/insert statement. -func getPlanDigest(sctx sessionctx.Context, p plannercore.Plan) (string, *parser.Digest) { - sc := sctx.GetSessionVars().StmtCtx +func getPlanDigest(sc *stmtctx.StatementContext, p plannercore.Plan) (string, *parser.Digest) { normalized, planDigest := sc.GetPlanDigest() if len(normalized) > 0 && planDigest != nil { return normalized, planDigest @@ -1253,11 +1265,11 @@ func (a *ExecStmt) SummaryStmt(succ bool) { var planDigestGen func() string if a.Plan.TP() == plancodec.TypePointGet { planDigestGen = func() string { - _, planDigest := getPlanDigest(a.Ctx, a.Plan) + _, planDigest := getPlanDigest(stmtCtx, a.Plan) return planDigest.String() } } else { - _, tmp := getPlanDigest(a.Ctx, a.Plan) + _, tmp := getPlanDigest(stmtCtx, a.Plan) planDigest = tmp.String() } @@ -1337,17 +1349,50 @@ func (a *ExecStmt) GetTextToLog() string { return sql } -func (a *ExecStmt) observeStmtBeginForTopSQL() { +func (a *ExecStmt) observeStmtBeginForTopSQL(ctx context.Context) context.Context { vars := a.Ctx.GetSessionVars() - if vars == nil { - return + sc := vars.StmtCtx + normalizedSQL, sqlDigest := sc.SQLDigest() + normalizedPlan, planDigest := getPlanDigest(sc, a.Plan) + var sqlDigestByte, planDigestByte []byte + if sqlDigest != nil { + sqlDigestByte = sqlDigest.Bytes() } - if stats := a.Ctx.GetStmtStats(); stats != nil && topsqlstate.TopSQLEnabled() { - sqlDigest, planDigest := a.getSQLPlanDigest() - stats.OnExecutionBegin(sqlDigest, planDigest) + if planDigest != nil { + planDigestByte = planDigest.Bytes() + } + stats := a.Ctx.GetStmtStats() + if !topsqlstate.TopSQLEnabled() { + // To reduce the performance impact on fast plan. + // Drop them does not cause notable accuracy issue in TopSQL. + if IsFastPlan(a.Plan) { + return ctx + } + // Always attach the SQL and plan info uses to catch the running SQL when Top SQL is enabled in execution. + if stats != nil { + stats.OnExecutionBegin(sqlDigestByte, planDigestByte) + // This is a special logic prepared for TiKV's SQLExecCount. + sc.KvExecCounter = stats.CreateKvExecCounter(sqlDigestByte, planDigestByte) + } + return topsql.AttachSQLAndPlanInfo(ctx, sqlDigest, planDigest) + } + + if stats != nil { + stats.OnExecutionBegin(sqlDigestByte, planDigestByte) // This is a special logic prepared for TiKV's SQLExecCount. - vars.StmtCtx.KvExecCounter = stats.CreateKvExecCounter(sqlDigest, planDigest) + sc.KvExecCounter = stats.CreateKvExecCounter(sqlDigestByte, planDigestByte) + } + + isSQLRegistered := sc.IsSQLRegistered.Load() + if !isSQLRegistered { + topsql.RegisterSQL(normalizedSQL, sqlDigest, vars.InRestrictedSQL) + } + sc.IsSQLAndPlanRegistered.Store(true) + if len(normalizedPlan) == 0 { + return ctx } + topsql.RegisterPlan(normalizedPlan, planDigest) + return topsql.AttachSQLAndPlanInfo(ctx, sqlDigest, planDigest) } func (a *ExecStmt) observeStmtFinishedForTopSQL() { diff --git a/executor/adapter_test.go b/executor/adapter_test.go index aea11b207baac..88847012aaa46 100644 --- a/executor/adapter_test.go +++ b/executor/adapter_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" ) @@ -40,3 +42,14 @@ func TestQueryTime(t *testing.T) { costTime = time.Since(tk.Session().GetSessionVars().StartTime) require.Less(t, costTime, time.Second) } + +func TestFormatSQL(t *testing.T) { + val := executor.FormatSQL("aaaa") + require.Equal(t, "aaaa", val.String()) + variable.QueryLogMaxLen.Store(0) + val = executor.FormatSQL("aaaaaaaaaaaaaaaaaaaa") + require.Equal(t, "aaaaaaaaaaaaaaaaaaaa", val.String()) + variable.QueryLogMaxLen.Store(5) + val = executor.FormatSQL("aaaaaaaaaaaaaaaaaaaa") + require.Equal(t, "\"aaaaa\"(len:20)", val.String()) +} diff --git a/executor/admin_test.go b/executor/admin_test.go index 3a89fdb0894b1..151340eebe12b 100644 --- a/executor/admin_test.go +++ b/executor/admin_test.go @@ -1086,10 +1086,11 @@ func (h *logHook) checkLogCount(t *testing.T, expected int) { require.Len(t, logsStr, expected) } -func withLogHook(ctx context.Context, msgFilter string) (newCtx context.Context, hook *logHook) { +func withLogHook(ctx context.Context, t *testing.T, msgFilter string) (newCtx context.Context, hook *logHook) { conf := &log.Config{Level: os.Getenv("log_level"), File: log.FileLogConfig{}} _, r, _ := log.InitLogger(conf) - enc := log.NewTextEncoder(&config.GetGlobalConfig().Log.ToLogConfig().Config) + enc, err := log.NewTextEncoder(&config.GetGlobalConfig().Log.ToLogConfig().Config) + require.NoError(t, err) hook = &logHook{r.Core, nil, enc, msgFilter} logger := zap.New(hook) newCtx = context.WithValue(ctx, logutil.CtxLogKey, logger) @@ -1111,7 +1112,7 @@ func TestCheckFailReport(t *testing.T) { require.NoError(t, tk.uniqueIndex.Delete(tk.sctx, txn, types.MakeDatums(1), kv.IntHandle(1))) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 1, index-values:\"\" != record-values:\"handle: 1, values: [KindInt64 1]\"", err.Error()) @@ -1135,7 +1136,7 @@ func TestCheckFailReport(t *testing.T) { require.NoError(t, tk.plainIndex.Delete(tk.sctx, txn, []types.Datum{types.NewStringDatum("10")}, kv.IntHandle(1))) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: k2, handle: 1, index-values:\"\" != record-values:\"handle: 1, values: [KindString 10]\"", err.Error()) @@ -1159,7 +1160,7 @@ func TestCheckFailReport(t *testing.T) { require.NoError(t, err) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: k2, handle: 1, index-values:\"handle: 1, values: [KindString 100 KindInt64 1]\" != record-values:\"\"", err.Error()) @@ -1175,7 +1176,7 @@ func TestCheckFailReport(t *testing.T) { logEntry.checkFieldNotEmpty(t, "index_mvcc") // test inconsistency check in index lookup - ctx, hook = withLogHook(tk.ctx, "") + ctx, hook = withLogHook(tk.ctx, t, "") rs, err := tk.Exec(ctx, "select * from admin_test use index(k2) where c3 = '100'") require.NoError(t, err) _, err = session.GetRows4Test(ctx, testkit.TryRetrieveSession(ctx), rs) @@ -1204,7 +1205,7 @@ func TestCheckFailReport(t *testing.T) { require.NoError(t, err) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 1, index-values:\"handle: 1, values: [KindInt64 10 KindInt64 1]\" != record-values:\"\"", err.Error()) @@ -1220,7 +1221,7 @@ func TestCheckFailReport(t *testing.T) { logEntry.checkFieldNotEmpty(t, "index_mvcc") // test inconsistency check in point-get - ctx, hook = withLogHook(tk.ctx, "") + ctx, hook = withLogHook(tk.ctx, t, "") rs, err := tk.Exec(ctx, "select * from admin_test use index(uk1) where c2 = 10") require.NoError(t, err) _, err = session.GetRows4Test(ctx, testkit.TryRetrieveSession(ctx), rs) @@ -1249,7 +1250,7 @@ func TestCheckFailReport(t *testing.T) { _, err = tk.uniqueIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewIntDatum(20)}, kv.IntHandle(1), nil) require.NoError(t, err) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[executor:8134]data inconsistency in table: admin_test, index: uk1, col: c2, handle: \"1\", index-values:\"KindInt64 20\" != record-values:\"KindInt64 10\", compare err:", err.Error()) @@ -1277,7 +1278,7 @@ func TestCheckFailReport(t *testing.T) { _, err = tk.plainIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewStringDatum("200")}, kv.IntHandle(1), nil) require.NoError(t, err) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, "[executor:8134]data inconsistency in table: admin_test, index: k2, col: c3, handle: \"1\", index-values:\"KindString 200\" != record-values:\"KindString 100\", compare err:", err.Error()) @@ -1307,14 +1308,14 @@ func TestCheckFailReport(t *testing.T) { txn, err := store.Begin() require.NoError(t, err) encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.NewBytesDatum([]byte{1, 0, 1, 0, 0, 1, 1})) - require.Nil(t, err) + require.NoError(t, err) hd, err := kv.NewCommonHandle(encoded) require.NoError(t, err) _, err = tk.uniqueIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewBytesDatum([]byte{1, 1, 0, 1, 1, 1, 1, 0})}, hd, nil) require.NoError(t, err) require.NoError(t, txn.Commit(tk.ctx)) - ctx, hook := withLogHook(tk.ctx, "inconsistency") + ctx, hook := withLogHook(tk.ctx, t, "inconsistency") _, err = tk.Exec(ctx, "admin check table admin_test") require.Error(t, err) require.Equal(t, `[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 282574488403969, index-values:"handle: 282574488403969, values: [KindInt64 282578800083201 KindInt64 282574488403969]" != record-values:""`, err.Error()) diff --git a/executor/aggfuncs/aggfunc_test.go b/executor/aggfuncs/aggfunc_test.go index d106f6b824e62..80a37d0f6b4d9 100644 --- a/executor/aggfuncs/aggfunc_test.go +++ b/executor/aggfuncs/aggfunc_test.go @@ -131,7 +131,7 @@ func approxCountDistinctUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types. continue } oldMemUsage := p.MemUsage() - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeLonglong: val := row.GetInt64(0) *(*int64)(unsafe.Pointer(&buf[0])) = val @@ -139,7 +139,7 @@ func approxCountDistinctUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types. val := row.GetString(0) buf = codec.EncodeCompactBytes(buf, hack.Slice(val)) default: - return memDeltas, errors.Errorf("unsupported type - %v", dataType.Tp) + return memDeltas, errors.Errorf("unsupported type - %v", dataType.GetType()) } x := farm.Hash64(buf) @@ -162,7 +162,7 @@ func distinctUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) } val := "" memDelta := int64(0) - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeLonglong: val = strconv.FormatInt(row.GetInt64(0), 10) memDelta = aggfuncs.DefInt64Size @@ -199,7 +199,7 @@ func distinctUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) val = string(bytes) memDelta = int64(len(val)) default: - return memDeltas, errors.Errorf("unsupported type - %v", dataType.Tp) + return memDeltas, errors.Errorf("unsupported type - %v", dataType.GetType()) } if valSet.Exist(val) { memDeltas = append(memDeltas, int64(0)) @@ -250,7 +250,7 @@ func defaultMultiArgsMemDeltaGens(srcChk *chunk.Chunk, dataTypes []*types.FieldT memDelta += int64(len(key)) memDelta += aggfuncs.DefInterfaceSize - switch dataTypes[1].Tp { + switch dataTypes[1].GetType() { case mysql.TypeLonglong: memDelta += aggfuncs.DefUint64Size case mysql.TypeDouble: @@ -269,7 +269,7 @@ func defaultMultiArgsMemDeltaGens(srcChk *chunk.Chunk, dataTypes []*types.FieldT case mysql.TypeNewDecimal: memDelta += aggfuncs.DefMyDecimalSize default: - return memDeltas, errors.Errorf("unsupported type - %v", dataTypes[1].Tp) + return memDeltas, errors.Errorf("unsupported type - %v", dataTypes[1].GetType()) } memDeltas = append(memDeltas, memDelta) } @@ -318,7 +318,7 @@ func testMergePartialResult(t *testing.T, p aggTest) { iter := chunk.NewIterator4Chunk(srcChk) args := []expression.Expression{&expression.Column{RetType: p.dataType, Index: 0}} - ctor := collate.GetCollator(p.dataType.Collate) + ctor := collate.GetCollator(p.dataType.GetCollate()) if p.funcName == ast.AggFuncGroupConcat { args = append(args, &expression.Constant{Value: types.NewStringDatum(separator), RetType: types.NewFieldType(mysql.TypeString)}) } @@ -449,7 +449,7 @@ func testMultiArgsMergePartialResult(t *testing.T, ctx sessionctx.Context, p mul {Expr: args[0], Desc: true}, } } - ctor := collate.GetCollator(args[0].GetType().Collate) + ctor := collate.GetCollator(args[0].GetType().GetCollate()) partialDesc, finalDesc := desc.Split([]int{0, 1}) // build partial func for partial phase. @@ -535,7 +535,7 @@ func buildMultiArgsAggTesterWithFieldType(funcName string, fts []*types.FieldTyp } func getDataGenFunc(ft *types.FieldType) func(i int) types.Datum { - switch ft.Tp { + switch ft.GetType() { case mysql.TypeLonglong: return func(i int) types.Datum { return types.NewIntDatum(int64(i)) } case mysql.TypeFloat: @@ -556,13 +556,13 @@ func getDataGenFunc(ft *types.FieldType) func(i int) types.Datum { elems := []string{"e", "d", "c", "b", "a"} return func(i int) types.Datum { e, _ := types.ParseEnumValue(elems, uint64(i+1)) - return types.NewCollateMysqlEnumDatum(e, ft.Collate) + return types.NewCollateMysqlEnumDatum(e, ft.GetCollate()) } case mysql.TypeSet: elems := []string{"e", "d", "c", "b", "a"} return func(i int) types.Datum { e, _ := types.ParseSetValue(elems, uint64(i+1)) - return types.NewMysqlSetDatum(e, ft.Collate) + return types.NewMysqlSetDatum(e, ft.GetCollate()) } } return nil @@ -573,7 +573,7 @@ func testAggFunc(t *testing.T, p aggTest) { ctx := mock.NewContext() args := []expression.Expression{&expression.Column{RetType: p.dataType, Index: 0}} - ctor := collate.GetCollator(p.dataType.Collate) + ctor := collate.GetCollator(p.dataType.GetCollate()) if p.funcName == ast.AggFuncGroupConcat { args = append(args, &expression.Constant{Value: types.NewStringDatum(separator), RetType: types.NewFieldType(mysql.TypeString)}) } @@ -662,7 +662,7 @@ func testAggFuncWithoutDistinct(t *testing.T, p aggTest) { srcChk := p.genSrcChk() args := []expression.Expression{&expression.Column{RetType: p.dataType, Index: 0}} - ctor := collate.GetCollator(p.dataType.Collate) + ctor := collate.GetCollator(p.dataType.GetCollate()) if p.funcName == ast.AggFuncGroupConcat { args = append(args, &expression.Constant{Value: types.NewStringDatum(separator), RetType: types.NewFieldType(mysql.TypeString)}) } @@ -754,7 +754,7 @@ func testMultiArgsAggFunc(t *testing.T, ctx sessionctx.Context, p multiArgsAggTe {Expr: args[0], Desc: true}, } } - ctor := collate.GetCollator(args[0].GetType().Collate) + ctor := collate.GetCollator(args[0].GetType().GetCollate()) finalFunc := aggfuncs.Build(ctx, desc, 0) finalPr, _ := finalFunc.AllocPartialResult() resultChk := chunk.NewChunkWithCapacity([]*types.FieldType{desc.RetTp}, 1) diff --git a/executor/aggfuncs/builder.go b/executor/aggfuncs/builder.go index 4da578936d96e..f7b600fe3d066 100644 --- a/executor/aggfuncs/builder.go +++ b/executor/aggfuncs/builder.go @@ -119,7 +119,7 @@ func buildApproxCountDistinct(aggFuncDesc *aggregation.AggFuncDesc, ordinal int) // In partition table, union need to compute partial result into partial result. // We can detect and handle this case by checking whether return type is string. - switch aggFuncDesc.RetTp.Tp { + switch aggFuncDesc.RetTp.GetType() { case mysql.TypeLonglong: switch aggFuncDesc.Mode { case aggregation.CompleteMode: @@ -159,7 +159,7 @@ func buildApproxPercentile(sctx sessionctx.Context, aggFuncDesc *aggregation.Agg base := basePercentile{percent: int(percent), baseAggFunc: baseAggFunc{args: aggFuncDesc.Args, ordinal: ordinal}} evalType := aggFuncDesc.Args[0].GetType().EvalType() - if aggFuncDesc.Args[0].GetType().Tp == mysql.TypeBit { + if aggFuncDesc.Args[0].GetType().GetType() == mysql.TypeBit { evalType = types.ETString // same as other aggregate function } switch aggFuncDesc.Mode { @@ -205,7 +205,7 @@ func buildCount(aggFuncDesc *aggregation.AggFuncDesc, ordinal int) AggFunc { // optimize with single column // TODO: because Time and JSON does not have `hashcode()` or similar method // so they're in exception for now. - // TODO: add hashCode method for all evaluate types (Decimal, Time, Duration, JSON). + // TODO: add hashCode method for all evaluate types (decimal, Time, Duration, JSON). // https://github.com/pingcap/tidb/issues/15857 switch aggFuncDesc.Args[0].GetType().EvalType() { case types.ETInt: @@ -314,7 +314,7 @@ func buildAvg(ctx sessionctx.Context, aggFuncDesc *aggregation.AggFuncDesc, ordi // Build avg functions which consume the partial result of other avg // functions and update their partial results. case aggregation.Partial2Mode, aggregation.FinalMode: - switch aggFuncDesc.RetTp.Tp { + switch aggFuncDesc.RetTp.GetType() { case mysql.TypeNewDecimal: return &avgPartial4Decimal{baseAvgDecimal{base}} case mysql.TypeDouble: @@ -332,13 +332,13 @@ func buildFirstRow(aggFuncDesc *aggregation.AggFuncDesc, ordinal int) AggFunc { retTp: aggFuncDesc.RetTp, } evalType, fieldType := aggFuncDesc.RetTp.EvalType(), aggFuncDesc.RetTp - if fieldType.Tp == mysql.TypeBit { + if fieldType.GetType() == mysql.TypeBit { evalType = types.ETString } switch aggFuncDesc.Mode { case aggregation.DedupMode: default: - switch fieldType.Tp { + switch fieldType.GetType() { case mysql.TypeEnum: return &firstRow4Enum{base} case mysql.TypeSet: @@ -349,7 +349,7 @@ func buildFirstRow(aggFuncDesc *aggregation.AggFuncDesc, ordinal int) AggFunc { case types.ETInt: return &firstRow4Int{base} case types.ETReal: - switch fieldType.Tp { + switch fieldType.GetType() { case mysql.TypeFloat: return &firstRow4Float32{base} case mysql.TypeDouble: @@ -379,16 +379,16 @@ func buildMaxMin(aggFuncDesc *aggregation.AggFuncDesc, ordinal int, isMax bool) retTp: aggFuncDesc.RetTp, }, isMax: isMax, - collator: collate.GetCollator(aggFuncDesc.RetTp.Collate), + collator: collate.GetCollator(aggFuncDesc.RetTp.GetCollate()), } evalType, fieldType := aggFuncDesc.RetTp.EvalType(), aggFuncDesc.RetTp - if fieldType.Tp == mysql.TypeBit { + if fieldType.GetType() == mysql.TypeBit { evalType = types.ETString } switch aggFuncDesc.Mode { case aggregation.DedupMode: default: - switch fieldType.Tp { + switch fieldType.GetType() { case mysql.TypeEnum: return &maxMin4Enum{base} case mysql.TypeSet: @@ -397,12 +397,12 @@ func buildMaxMin(aggFuncDesc *aggregation.AggFuncDesc, ordinal int, isMax bool) switch evalType { case types.ETInt: - if mysql.HasUnsignedFlag(fieldType.Flag) { + if mysql.HasUnsignedFlag(fieldType.GetFlag()) { return &maxMin4Uint{base} } return &maxMin4Int{base} case types.ETReal: - switch fieldType.Tp { + switch fieldType.GetType() { case mysql.TypeFloat: return &maxMin4Float32{base} case mysql.TypeDouble: diff --git a/executor/aggfuncs/func_avg.go b/executor/aggfuncs/func_avg.go index 15713eedab880..6652af722301d 100644 --- a/executor/aggfuncs/func_avg.go +++ b/executor/aggfuncs/func_avg.go @@ -77,7 +77,7 @@ func (e *baseAvgDecimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Par if e.retTp == nil { return errors.New("e.retTp of avg should not be nil") } - frac := e.retTp.Decimal + frac := e.retTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } @@ -272,7 +272,7 @@ func (e *avgOriginal4DistinctDecimal) AppendFinalResult2Chunk(sctx sessionctx.Co if e.retTp == nil { return errors.New("e.retTp of avg should not be nil") } - frac := e.retTp.Decimal + frac := e.retTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } diff --git a/executor/aggfuncs/func_count_distinct.go b/executor/aggfuncs/func_count_distinct.go index db32ce134c364..729727d7d51fe 100644 --- a/executor/aggfuncs/func_count_distinct.go +++ b/executor/aggfuncs/func_count_distinct.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/hack" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/set" "github.com/pingcap/tidb/util/stringutil" ) @@ -268,7 +269,7 @@ func (e *countOriginalWithDistinct4String) AppendFinalResult2Chunk(sctx sessionc func (e *countOriginalWithDistinct4String) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup []chunk.Row, pr PartialResult) (memDelta int64, err error) { p := (*partialResult4CountDistinctString)(pr) - collator := collate.GetCollator(e.args[0].GetType().Collate) + collator := collate.GetCollator(e.args[0].GetType().GetCollate()) for _, row := range rowsInGroup { input, isNull, err := e.args[0].EvalString(sctx, row) @@ -322,9 +323,9 @@ func (e *countOriginalWithDistinct) UpdatePartialResult(sctx sessionctx.Context, encodedBytes := make([]byte, 0) collators := make([]collate.Collator, 0, len(e.args)) for _, arg := range e.args { - collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + collators = append(collators, collate.GetCollator(arg.GetType().GetCollate())) } - // Decimal struct is the biggest type we will use. + // decimal struct is the biggest type we will use. buf := make([]byte, types.MyDecimalStructSize) for _, row := range rowsInGroup { @@ -540,14 +541,6 @@ func (p *partialResult4ApproxCountDistinct) reset() { p.alloc(uniquesHashSetInitialSizeDegree) } -func max(a, b uint8) uint8 { - if a > b { - return a - } - - return b -} - func (p *partialResult4ApproxCountDistinct) bufSize() uint32 { return uint32(1) << p.sizeDegree } @@ -601,7 +594,7 @@ func (p *partialResult4ApproxCountDistinct) readAndMerge(rb []byte) error { } if p.bufSize() < uint32(rhsSize) { - newSizeDegree := max(uniquesHashSetInitialSizeDegree, uint8(math.Log2(float64(rhsSize-1)))+2) + newSizeDegree := mathutil.Max(uniquesHashSetInitialSizeDegree, uint8(math.Log2(float64(rhsSize-1)))+2) p.resize(newSizeDegree) } @@ -787,11 +780,11 @@ type approxCountDistinctOriginal struct { func (e *approxCountDistinctOriginal) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup []chunk.Row, pr PartialResult) (memDelta int64, err error) { p := (*partialResult4ApproxCountDistinct)(pr) encodedBytes := make([]byte, 0) - // Decimal struct is the biggest type we will use. + // decimal struct is the biggest type we will use. buf := make([]byte, types.MyDecimalStructSize) collators := make([]collate.Collator, 0, len(e.args)) for _, arg := range e.args { - collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + collators = append(collators, collate.GetCollator(arg.GetType().GetCollate())) } for _, row := range rowsInGroup { diff --git a/executor/aggfuncs/func_first_row.go b/executor/aggfuncs/func_first_row.go index 88f9d2bf75c5e..ffe3d1df9520e 100644 --- a/executor/aggfuncs/func_first_row.go +++ b/executor/aggfuncs/func_first_row.go @@ -481,7 +481,7 @@ func (e *firstRow4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr P if e.retTp == nil { return errors.New("e.retTp of first_row should not be nil") } - frac := e.retTp.Decimal + frac := e.retTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } diff --git a/executor/aggfuncs/func_first_row_test.go b/executor/aggfuncs/func_first_row_test.go index 2e75edd59e874..f12fbd72dc93a 100644 --- a/executor/aggfuncs/func_first_row_test.go +++ b/executor/aggfuncs/func_first_row_test.go @@ -86,7 +86,7 @@ func firstRowUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) memDeltas = append(memDeltas, int64(0)) continue } - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeString: val := row.GetString(0) memDeltas = append(memDeltas, int64(len(val))) diff --git a/executor/aggfuncs/func_group_concat.go b/executor/aggfuncs/func_group_concat.go index 4cb3993be65ad..d6f58481936c5 100644 --- a/executor/aggfuncs/func_group_concat.go +++ b/executor/aggfuncs/func_group_concat.go @@ -223,7 +223,7 @@ func (e *groupConcatDistinct) UpdatePartialResult(sctx sessionctx.Context, rowsI collators := make([]collate.Collator, 0, len(e.args)) for _, arg := range e.args { - collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + collators = append(collators, collate.GetCollator(arg.GetType().GetCollate())) } for _, row := range rowsInGroup { @@ -415,7 +415,7 @@ func (e *groupConcatOrder) AllocPartialResult() (pr PartialResult, memDelta int6 ctors := make([]collate.Collator, 0, len(e.byItems)) for i, byItem := range e.byItems { desc[i] = byItem.Desc - ctors = append(ctors, collate.GetCollator(byItem.Expr.GetType().Collate)) + ctors = append(ctors, collate.GetCollator(byItem.Expr.GetType().GetCollate())) } p := &partialResult4GroupConcatOrder{ topN: &topNRows{ @@ -520,7 +520,7 @@ func (e *groupConcatDistinctOrder) AllocPartialResult() (pr PartialResult, memDe ctors := make([]collate.Collator, 0, len(e.byItems)) for i, byItem := range e.byItems { desc[i] = byItem.Desc - ctors = append(ctors, collate.GetCollator(byItem.Expr.GetType().Collate)) + ctors = append(ctors, collate.GetCollator(byItem.Expr.GetType().GetCollate())) } valSet, setSize := set.NewStringSetWithMemoryUsage() p := &partialResult4GroupConcatOrderDistinct{ @@ -552,7 +552,7 @@ func (e *groupConcatDistinctOrder) UpdatePartialResult(sctx sessionctx.Context, collators := make([]collate.Collator, 0, len(e.args)) for _, arg := range e.args { - collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + collators = append(collators, collate.GetCollator(arg.GetType().GetCollate())) } for _, row := range rowsInGroup { diff --git a/executor/aggfuncs/func_json_arrayagg_test.go b/executor/aggfuncs/func_json_arrayagg_test.go index 1649037dc6b39..4baad8b430094 100644 --- a/executor/aggfuncs/func_json_arrayagg_test.go +++ b/executor/aggfuncs/func_json_arrayagg_test.go @@ -100,7 +100,7 @@ func jsonArrayaggMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (m memDelta := int64(0) memDelta += aggfuncs.DefInterfaceSize - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeLonglong: memDelta += aggfuncs.DefUint64Size case mysql.TypeDouble: @@ -119,7 +119,7 @@ func jsonArrayaggMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (m case mysql.TypeNewDecimal: memDelta += aggfuncs.DefMyDecimalSize default: - return memDeltas, errors.Errorf("unsupported type - %v", dataType.Tp) + return memDeltas, errors.Errorf("unsupported type - %v", dataType.GetType()) } memDeltas = append(memDeltas, memDelta) } diff --git a/executor/aggfuncs/func_max_min.go b/executor/aggfuncs/func_max_min.go index 73e49264472fb..3a0a558b37123 100644 --- a/executor/aggfuncs/func_max_min.go +++ b/executor/aggfuncs/func_max_min.go @@ -818,7 +818,7 @@ func (e *maxMin4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Par if e.retTp == nil { return errors.New("e.retTp of max or min should not be nil") } - frac := e.retTp.Decimal + frac := e.retTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } @@ -1002,7 +1002,7 @@ func (e *maxMin4String) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup p.isNull = false continue } - cmp := types.CompareString(input, p.val, tp.Collate) + cmp := types.CompareString(input, p.val, tp.GetCollate()) if e.isMax && cmp == 1 || !e.isMax && cmp == -1 { oldMem := len(p.val) newMem := len(input) @@ -1023,7 +1023,7 @@ func (e *maxMin4String) MergePartialResult(sctx sessionctx.Context, src, dst Par return 0, nil } tp := e.args[0].GetType() - cmp := types.CompareString(p1.val, p2.val, tp.Collate) + cmp := types.CompareString(p1.val, p2.val, tp.GetCollate()) if e.isMax && cmp > 0 || !e.isMax && cmp < 0 { p2.val, p2.isNull = p1.val, false } @@ -1039,7 +1039,7 @@ func (e *maxMin4StringSliding) AllocPartialResult() (pr PartialResult, memDelta p, memDelta := e.maxMin4String.AllocPartialResult() tp := e.args[0].GetType() (*partialResult4MaxMinString)(p).deque = NewDeque(e.isMax, func(i, j interface{}) int { - return types.CompareString(i.(string), j.(string), tp.Collate) + return types.CompareString(i.(string), j.(string), tp.GetCollate()) }) return p, memDelta + DefMaxMinDequeSize } diff --git a/executor/aggfuncs/func_max_min_test.go b/executor/aggfuncs/func_max_min_test.go index fea0e78d5f5ef..5851319fe6d7e 100644 --- a/executor/aggfuncs/func_max_min_test.go +++ b/executor/aggfuncs/func_max_min_test.go @@ -43,7 +43,7 @@ func maxMinUpdateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType, is if row.IsNull(0) { continue } - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeString: curVal := row.GetString(0) if i == 0 { @@ -104,7 +104,7 @@ func TestMergePartialResult4MaxMin(t *testing.T) { setED, _ := types.ParseSet(elems, "e,d", mysql.DefaultCollationName) // setED.Value == 3 unsignedType := types.NewFieldType(mysql.TypeLonglong) - unsignedType.Flag |= mysql.UnsignedFlag + unsignedType.AddFlag(mysql.UnsignedFlag) tests := []aggTest{ buildAggTester(ast.AggFuncMax, mysql.TypeLonglong, 5, 4, 4, 4), buildAggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, 4, 4, 4), @@ -140,7 +140,7 @@ func TestMergePartialResult4MaxMin(t *testing.T) { func TestMaxMin(t *testing.T) { unsignedType := types.NewFieldType(mysql.TypeLonglong) - unsignedType.Flag |= mysql.UnsignedFlag + unsignedType.AddFlag(mysql.UnsignedFlag) tests := []aggTest{ buildAggTester(ast.AggFuncMax, mysql.TypeLonglong, 5, nil, 4), buildAggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, nil, 4), diff --git a/executor/aggfuncs/func_sum.go b/executor/aggfuncs/func_sum.go index 0e153a51d98d2..7ba5fda02390a 100644 --- a/executor/aggfuncs/func_sum.go +++ b/executor/aggfuncs/func_sum.go @@ -174,7 +174,7 @@ func (e *sum4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Partia if e.retTp == nil { return errors.New("e.retTp of sum should not be nil") } - frac := e.retTp.Decimal + frac := e.retTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } diff --git a/executor/aggfuncs/func_value.go b/executor/aggfuncs/func_value.go index 76527b1e0bf14..0260594ec21a5 100644 --- a/executor/aggfuncs/func_value.go +++ b/executor/aggfuncs/func_value.go @@ -211,14 +211,14 @@ func (v *value4JSON) appendResult(chk *chunk.Chunk, colIdx int) { func buildValueEvaluator(tp *types.FieldType) (ve valueEvaluator, memDelta int64) { evalType := tp.EvalType() - if tp.Tp == mysql.TypeBit { + if tp.GetType() == mysql.TypeBit { evalType = types.ETString } switch evalType { case types.ETInt: return &value4Int{}, DefValue4IntSize case types.ETReal: - switch tp.Tp { + switch tp.GetType() { case mysql.TypeFloat: return &value4Float32{}, DefValue4Float32Size case mysql.TypeDouble: diff --git a/executor/aggfuncs/func_value_test.go b/executor/aggfuncs/func_value_test.go index b1e322821af9e..cb7e6b5b9311f 100644 --- a/executor/aggfuncs/func_value_test.go +++ b/executor/aggfuncs/func_value_test.go @@ -25,7 +25,7 @@ import ( ) func getEvaluatedMemDelta(row *chunk.Row, dataType *types.FieldType) (memDelta int64) { - switch dataType.Tp { + switch dataType.GetType() { case mysql.TypeString: memDelta = int64(len(row.GetString(0))) case mysql.TypeJSON: diff --git a/executor/aggfuncs/window_func_test.go b/executor/aggfuncs/window_func_test.go index f1854a890c12e..8c9928962a31c 100644 --- a/executor/aggfuncs/window_func_test.go +++ b/executor/aggfuncs/window_func_test.go @@ -77,7 +77,7 @@ func testWindowFunc(t *testing.T, p windowTest) { err = finalFunc.AppendFinalResult2Chunk(ctx, finalPr, resultChk) require.NoError(t, err) dt := resultChk.GetRow(0).GetDatum(0, desc.RetTp) - result, err := dt.Compare(ctx.GetSessionVars().StmtCtx, &p.results[i], collate.GetCollator(desc.RetTp.Collate)) + result, err := dt.Compare(ctx.GetSessionVars().StmtCtx, &p.results[i], collate.GetCollator(desc.RetTp.GetCollate())) require.NoError(t, err) require.Equal(t, 0, result) resultChk.Reset() diff --git a/executor/aggregate.go b/executor/aggregate.go index 8a6b83d089e58..9a0be36a5ccd4 100644 --- a/executor/aggregate.go +++ b/executor/aggregate.go @@ -23,7 +23,6 @@ import ( "sync/atomic" "time" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" @@ -41,6 +40,7 @@ import ( "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/set" "github.com/twmb/murmur3" @@ -62,13 +62,6 @@ type baseHashAggWorker struct { BInMap int // indicate there are 2^BInMap buckets in Golang Map. } -const ( - // ref https://github.com/golang/go/blob/go1.15.6/src/reflect/type.go#L2162. - // defBucketMemoryUsage = bucketSize*(1+unsafe.Sizeof(string) + unsafe.Sizeof(slice))+2*ptrSize - // The bucket size may be changed by golang implement in the future. - defBucketMemoryUsage = 8*(1+16+24) + 16 -) - func newBaseHashAggWorker(ctx sessionctx.Context, finishCh <-chan struct{}, aggFuncs []aggfuncs.AggFunc, maxChunkSize int, memTrack *memory.Tracker) baseHashAggWorker { baseWorker := baseHashAggWorker{ @@ -332,7 +325,7 @@ func (e *HashAggExec) initForUnparallelExec() { e.partialResultMap = make(aggPartialResultMapper) e.bInMap = 0 failpoint.Inject("ConsumeRandomPanic", nil) - e.memTracker.Consume(defBucketMemoryUsage*(1< bucketNum * loadFactor. The memory usage will doubled. if len(mapper) > (1< bucketNum * loadFactor. The memory usage will doubled. if len(e.partialResultMap) > (1< (select b from t) from t group by c") @@ -779,8 +786,7 @@ func TestOnlyFullGroupBy(t *testing.T) { tk.MustQuery("select t.*, x.* from t, x where t.b = x.b and t.d = x.d group by t.b, t.d") tk.MustQuery("select t.*, x.* from t, x where t.b = x.a group by t.b, t.d") tk.MustQuery("select t.b, x.* from t, x where t.b = x.a group by t.b") - err = tk.ExecToErr("select t.*, x.* from t, x where t.c = x.a group by t.b, t.c") - require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err) + tk.MustQuery("select t.*, x.* from t, x where t.c = x.a group by t.b, t.c") // test functional dependency derived from keys in join tk.MustQuery("select t.*, x.* from t inner join x on t.a = x.a group by t.a") tk.MustQuery("select t.*, x.* from t inner join x on (t.b = x.b and t.d = x.d) group by t.b, x.d") @@ -794,11 +800,10 @@ func TestOnlyFullGroupBy(t *testing.T) { err = tk.ExecToErr("select t.b, x.* from t right join x on t.b = x.b group by t.b, x.d") require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err) - // FixMe: test functional dependency of derived table - // tk.MustQuery("select * from (select * from t) as e group by a") - // tk.MustQuery("select * from (select * from t) as e group by b,d") - // err = tk.ExecToErr("select * from (select * from t) as e group by b,c") - // require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err) + tk.MustQuery("select * from (select * from t) as e group by a") + tk.MustQuery("select * from (select * from t) as e group by b,d") + err = tk.ExecToErr("select * from (select * from t) as e group by b,c") + require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err) // test order by tk.MustQuery("select c from t group by c,d order by d") diff --git a/executor/analyze.go b/executor/analyze.go index 493bce1b59b62..11290edf94151 100644 --- a/executor/analyze.go +++ b/executor/analyze.go @@ -28,7 +28,6 @@ import ( "sync/atomic" "time" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/distsql" @@ -45,6 +44,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" + "github.com/pingcap/tidb/statistics/handle" derr "github.com/pingcap/tidb/store/driver/error" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" @@ -54,6 +54,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/timeutil" @@ -103,7 +104,8 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { AddNewAnalyzeJob(e.ctx, task.job) } failpoint.Inject("mockKillPendingAnalyzeJob", func() { - domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + dom := domain.GetDomain(e.ctx) + dom.SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID(dom.ServerID)) }) for _, task := range e.tasks { taskCh <- task @@ -200,7 +202,8 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { } } failpoint.Inject("mockKillFinishedAnalyzeJob", func() { - domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + dom := domain.GetDomain(e.ctx) + dom.SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID(dom.ServerID)) }) if err != nil { return err @@ -240,7 +243,10 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { if err != nil { e.ctx.GetSessionVars().StmtCtx.AppendWarning(err) } - return statsHandle.Update(e.ctx.GetInfoSchema().(infoschema.InfoSchema)) + if e.ctx.GetSessionVars().InRestrictedSQL { + return statsHandle.Update(e.ctx.GetInfoSchema().(infoschema.InfoSchema)) + } + return statsHandle.Update(e.ctx.GetInfoSchema().(infoschema.InfoSchema), handle.WithTableStatsByQuery()) } func (e *AnalyzeExec) saveAnalyzeOptsV2() error { @@ -482,7 +488,7 @@ func (e *AnalyzeIndexExec) fetchAnalyzeResult(ranges []*ranger.Range, isNullRang } else { kvReqBuilder = builder.SetIndexRangesForTables(e.ctx.GetSessionVars().StmtCtx, []int64{e.tableID.GetStatisticsID()}, e.idxInfo.ID, ranges) } - kvReqBuilder.SetResourceGroupTagger(e.ctx.GetSessionVars().StmtCtx) + kvReqBuilder.SetResourceGroupTagger(e.ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) kvReq, err := kvReqBuilder. SetAnalyzeRequest(e.analyzePB). SetStartTS(e.snapshot). @@ -586,7 +592,8 @@ func (e *AnalyzeIndexExec) buildStatsFromResult(result distsql.SelectResult, nee } for { failpoint.Inject("mockKillRunningAnalyzeIndexJob", func() { - domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + dom := domain.GetDomain(e.ctx) + dom.SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID(dom.ServerID)) }) if atomic.LoadUint32(&e.ctx.GetSessionVars().Killed) == 1 { return nil, nil, nil, nil, errors.Trace(ErrQueryInterrupted) @@ -675,7 +682,7 @@ func analyzeColumnsPushdown(colExec *AnalyzeColumnsExec) *statistics.AnalyzeResu var ranges []*ranger.Range if hc := colExec.handleCols; hc != nil { if hc.IsInt() { - ranges = ranger.FullIntRange(mysql.HasUnsignedFlag(hc.GetCol(0).RetType.Flag)) + ranges = ranger.FullIntRange(mysql.HasUnsignedFlag(hc.GetCol(0).RetType.GetFlag())) } else { ranges = ranger.FullNotNullRange() } @@ -854,7 +861,7 @@ func (e *AnalyzeColumnsExec) open(ranges []*ranger.Range) error { func (e *AnalyzeColumnsExec) buildResp(ranges []*ranger.Range) (distsql.SelectResult, error) { var builder distsql.RequestBuilder reqBuilder := builder.SetHandleRangesForTables(e.ctx.GetSessionVars().StmtCtx, []int64{e.TableID.GetStatisticsID()}, e.handleCols != nil && !e.handleCols.IsInt(), ranges, nil) - builder.SetResourceGroupTagger(e.ctx.GetSessionVars().StmtCtx) + builder.SetResourceGroupTagger(e.ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) // Always set KeepOrder of the request to be true, in order to compute // correct `correlation` of columns. kvReq, err := reqBuilder. @@ -915,7 +922,8 @@ func readDataAndSendTask(ctx sessionctx.Context, handler *tableResultHandler, me defer close(mergeTaskCh) for { failpoint.Inject("mockKillRunningV2AnalyzeJob", func() { - domain.GetDomain(ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + dom := domain.GetDomain(ctx) + dom.SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID(dom.ServerID)) }) if atomic.LoadUint32(&ctx.GetSessionVars().Killed) == 1 { return errors.Trace(ErrQueryInterrupted) @@ -1379,8 +1387,8 @@ workLoop: // When it's new collation data, we need to use its collate key instead of original value because only // the collate key can ensure the correct ordering. // This is also corresponding to similar operation in (*statistics.Column).GetColumnRowCount(). - if ft.EvalType() == types.ETString && ft.Tp != mysql.TypeEnum && ft.Tp != mysql.TypeSet { - val.SetBytes(collate.GetCollator(ft.Collate).Key(val.GetString())) + if ft.EvalType() == types.ETString && ft.GetType() != mysql.TypeEnum && ft.GetType() != mysql.TypeSet { + val.SetBytes(collate.GetCollator(ft.GetCollate()).Key(val.GetString())) } sampleItems = append(sampleItems, &statistics.SampleItem{ Value: val, @@ -1489,7 +1497,8 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo } for { failpoint.Inject("mockKillRunningV1AnalyzeJob", func() { - domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + dom := domain.GetDomain(e.ctx) + dom.SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID(dom.ServerID)) }) if atomic.LoadUint32(&e.ctx.GetSessionVars().Killed) == 1 { return nil, nil, nil, nil, nil, errors.Trace(ErrQueryInterrupted) @@ -2143,7 +2152,7 @@ func (e *AnalyzeFastExec) runTasks() ([]*statistics.Histogram, []*statistics.CMS }) collector.CalcTotalSize() // Adjust the row count in case the count of `tblStats` is not accurate and too small. - rowCount = mathutil.MaxInt64(rowCount, int64(len(collector.Samples))) + rowCount = mathutil.Max(rowCount, int64(len(collector.Samples))) // Scale the total column size. if len(collector.Samples) > 0 { collector.TotalSize *= rowCount / int64(len(collector.Samples)) @@ -2284,7 +2293,7 @@ type analyzePKIncrementalExec struct { func analyzePKIncremental(colExec *analyzePKIncrementalExec) *statistics.AnalyzeResults { var maxVal types.Datum pkInfo := colExec.handleCols.GetCol(0) - if mysql.HasUnsignedFlag(pkInfo.RetType.Flag) { + if mysql.HasUnsignedFlag(pkInfo.RetType.GetFlag()) { maxVal = types.NewUintDatum(math.MaxUint64) } else { maxVal = types.NewIntDatum(math.MaxInt64) diff --git a/executor/analyze_test.go b/executor/analyze_test.go index 9b15adfcaeb12..fe8a25ece4a11 100644 --- a/executor/analyze_test.go +++ b/executor/analyze_test.go @@ -353,7 +353,7 @@ func TestAnalyzeFastSample(t *testing.T) { var colsInfo []*model.ColumnInfo // nolint: prealloc var indicesInfo []*model.IndexInfo for _, col := range tblInfo.Columns { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { continue } colsInfo = append(colsInfo, col) @@ -2163,6 +2163,35 @@ func TestAnalyzeColumnsWithDynamicPartitionTable(t *testing.T) { } } +func TestIssue34228(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec(`USE test`) + tk.MustExec(`DROP TABLE IF EXISTS Issue34228`) + tk.MustExec(`CREATE TABLE Issue34228 (id bigint NOT NULL, dt datetime NOT NULL) PARTITION BY RANGE COLUMNS(dt) (PARTITION p202201 VALUES LESS THAN ("2022-02-01"), PARTITION p202202 VALUES LESS THAN ("2022-03-01"))`) + tk.MustExec(`INSERT INTO Issue34228 VALUES (1, '2022-02-01 00:00:02'), (2, '2022-02-01 00:00:02')`) + tk.MustExec(`SET @@global.tidb_analyze_version = 1`) + tk.MustExec(`SET @@session.tidb_partition_prune_mode = 'static'`) + tk.MustExec(`ANALYZE TABLE Issue34228`) + tk.MustExec(`SET @@session.tidb_partition_prune_mode = 'dynamic'`) + tk.MustExec(`ANALYZE TABLE Issue34228`) + tk.MustQuery(`SELECT * FROM Issue34228`).Sort().Check(testkit.Rows("1 2022-02-01 00:00:02", "2 2022-02-01 00:00:02")) + // Needs a second run to hit the issue + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec(`USE test`) + tk2.MustExec(`DROP TABLE IF EXISTS Issue34228`) + tk2.MustExec(`CREATE TABLE Issue34228 (id bigint NOT NULL, dt datetime NOT NULL) PARTITION BY RANGE COLUMNS(dt) (PARTITION p202201 VALUES LESS THAN ("2022-02-01"), PARTITION p202202 VALUES LESS THAN ("2022-03-01"))`) + tk2.MustExec(`INSERT INTO Issue34228 VALUES (1, '2022-02-01 00:00:02'), (2, '2022-02-01 00:00:02')`) + tk2.MustExec(`SET @@global.tidb_analyze_version = 1`) + tk2.MustExec(`SET @@session.tidb_partition_prune_mode = 'static'`) + tk2.MustExec(`ANALYZE TABLE Issue34228`) + tk2.MustExec(`SET @@session.tidb_partition_prune_mode = 'dynamic'`) + tk2.MustExec(`ANALYZE TABLE Issue34228`) + tk2.MustQuery(`SELECT * FROM Issue34228`).Sort().Check(testkit.Rows("1 2022-02-01 00:00:02", "2 2022-02-01 00:00:02")) +} + func TestAnalyzeColumnsWithStaticPartitionTable(t *testing.T) { for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { func(choice model.ColumnChoice) { diff --git a/executor/apply_cache.go b/executor/apply_cache.go index d30020b3cc6b1..4d60b7a1f1239 100644 --- a/executor/apply_cache.go +++ b/executor/apply_cache.go @@ -17,10 +17,10 @@ package executor import ( "sync" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/kvcache" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" ) diff --git a/executor/batch_point_get.go b/executor/batch_point_get.go index d8c7f596d47cf..0ce745d172e4a 100644 --- a/executor/batch_point_get.go +++ b/executor/batch_point_get.go @@ -38,7 +38,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil/consistency" - "github.com/pingcap/tidb/util/math" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/rowcodec" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" ) @@ -377,7 +377,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error { return e.handles[i].Compare(e.handles[j]) < 0 } - if e.tblInfo.PKIsHandle && mysql.HasUnsignedFlag(e.tblInfo.GetPkColInfo().Flag) { + if e.tblInfo.PKIsHandle && mysql.HasUnsignedFlag(e.tblInfo.GetPkColInfo().GetFlag()) { uintComparator := func(i, h kv.Handle) int { if !i.IsInt() || !h.IsInt() { panic(fmt.Sprintf("both handles need be IntHandle, but got %T and %T ", i, h)) @@ -589,7 +589,7 @@ func getPhysID(tblInfo *model.TableInfo, partitionExpr *tables.PartitionExpr, in switch pi.Type { case model.PartitionTypeHash: - partIdx := math.Abs(intVal % int64(pi.Num)) + partIdx := mathutil.Abs(intVal % int64(pi.Num)) return pi.Definitions[partIdx].ID, nil case model.PartitionTypeRange: // we've check the type assertions in func TryFastPlan @@ -597,7 +597,7 @@ func getPhysID(tblInfo *model.TableInfo, partitionExpr *tables.PartitionExpr, in if !ok { return 0, errors.Errorf("unsupported partition type in BatchGet") } - unsigned := mysql.HasUnsignedFlag(col.GetType().Flag) + unsigned := mysql.HasUnsignedFlag(col.GetType().GetFlag()) ranges := partitionExpr.ForRangePruning length := len(ranges.LessThan) partIdx := sort.Search(length, func(i int) bool { diff --git a/executor/benchmark_test.go b/executor/benchmark_test.go index a36ad9eba5f39..1853c44971db0 100644 --- a/executor/benchmark_test.go +++ b/executor/benchmark_test.go @@ -153,7 +153,7 @@ func (mds *mockDataSource) genColDatums(col int) (results []interface{}) { if order { sort.Slice(results, func(i, j int) bool { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return results[i].(int64) < results[j].(int64) case mysql.TypeDouble: @@ -170,7 +170,7 @@ func (mds *mockDataSource) genColDatums(col int) (results []interface{}) { } func (mds *mockDataSource) randDatum(typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(rand.Int()) case mysql.TypeFloat: @@ -226,7 +226,7 @@ func buildMockDataSource(opt mockDataSourceParameters) *mockDataSource { idx := i / m.maxChunkSize retTypes := retTypes(m) for colIdx := 0; colIdx < len(rTypes); colIdx++ { - switch retTypes[colIdx].Tp { + switch retTypes[colIdx].GetType() { case mysql.TypeLong, mysql.TypeLonglong: m.genData[idx].AppendInt64(colIdx, colData[colIdx][i].(int64)) case mysql.TypeFloat: @@ -292,7 +292,7 @@ func buildHashAggExecutor(ctx sessionctx.Context, src Executor, schema *expressi plan.SetSchema(schema) plan.Init(ctx, nil, 0) plan.SetChildren(nil) - b := newExecutorBuilder(ctx, nil, nil, 0, false, oracle.GlobalTxnScope) + b := newExecutorBuilder(ctx, nil, nil, oracle.GlobalTxnScope) exec := b.build(plan) hashAgg := exec.(*HashAggExec) hashAgg.children[0] = src @@ -344,7 +344,7 @@ func buildStreamAggExecutor(ctx sessionctx.Context, srcExec Executor, schema *ex plan = sg } - b := newExecutorBuilder(ctx, nil, nil, 0, false, oracle.GlobalTxnScope) + b := newExecutorBuilder(ctx, nil, nil, oracle.GlobalTxnScope) return b.build(plan) } @@ -577,7 +577,7 @@ func buildWindowExecutor(ctx sessionctx.Context, windowFunc string, funcs int, f plan = win } - b := newExecutorBuilder(ctx, nil, nil, 0, false, oracle.GlobalTxnScope) + b := newExecutorBuilder(ctx, nil, nil, oracle.GlobalTxnScope) exec := b.build(plan) return exec } @@ -824,7 +824,7 @@ func baseBenchmarkWindowFunctionsWithSlidingWindow(b *testing.B, frameType ast.F cas.ndv = ndv cas.windowFunc = windowFunc.aggFunc cas.frame = frame - cas.columns[0].RetType.Tp = windowFunc.aggColTypes + cas.columns[0].RetType.SetType(windowFunc.aggColTypes) cas.pipelined = pipelined b.Run(fmt.Sprintf("%v", cas), func(b *testing.B) { benchmarkWindowExecWithCase(b, cas) @@ -950,7 +950,7 @@ func benchmarkHashJoinExecWithCase(b *testing.B, casTest *hashJoinTestCase) { rows: casTest.rows, ctx: casTest.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeVarString: @@ -1151,7 +1151,7 @@ func benchmarkBuildHashTableForList(b *testing.B, casTest *hashJoinTestCase) { rows: casTest.rows, ctx: casTest.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeVarString: @@ -1288,7 +1288,7 @@ func (tc indexJoinTestCase) getMockDataSourceOptByRows(rows int) mockDataSourceP rows: rows, ctx: tc.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeDouble: @@ -1317,7 +1317,7 @@ func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, keyOff2IdxOff[i] = i } - readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope). + readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, oracle.GlobalTxnScope). newDataReaderBuilder(&mockPhysicalIndexReader{e: innerDS}) if err != nil { return nil, err @@ -1391,7 +1391,7 @@ func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, inne outerCompareFuncs = append(outerCompareFuncs, expression.GetCmpFunction(nil, outerJoinKeys[i], outerJoinKeys[i])) } - readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope). + readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, oracle.GlobalTxnScope). newDataReaderBuilder(&mockPhysicalIndexReader{e: innerDS}) if err != nil { return nil, err @@ -1701,7 +1701,7 @@ func newMergeJoinBenchmark(numOuterRows, numInnerDup, numInnerRedundant int) (tc rows: numOuterRows, ctx: tc.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeDouble: @@ -1720,7 +1720,7 @@ func newMergeJoinBenchmark(numOuterRows, numInnerDup, numInnerRedundant int) (tc ctx: tc.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { row = row / numInnerDup - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeDouble: diff --git a/executor/builder.go b/executor/builder.go index 009f65b8b4570..1053e086b4dba 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -27,7 +27,6 @@ import ( "time" "unsafe" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/diagnosticspb" @@ -47,6 +46,8 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/table" @@ -60,6 +61,7 @@ import ( "github.com/pingcap/tidb/util/cteutil" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/rowcodec" @@ -117,16 +119,27 @@ type CTEStorages struct { IterInTbl cteutil.Storage } -func newExecutorBuilder(ctx sessionctx.Context, is infoschema.InfoSchema, ti *TelemetryInfo, snapshotTS uint64, isStaleness bool, replicaReadScope string) *executorBuilder { - return &executorBuilder{ +func newExecutorBuilder(ctx sessionctx.Context, is infoschema.InfoSchema, ti *TelemetryInfo, replicaReadScope string) *executorBuilder { + b := &executorBuilder{ ctx: ctx, is: is, Ti: ti, - snapshotTSCached: isStaleness, - snapshotTS: snapshotTS, - isStaleness: isStaleness, + isStaleness: staleread.IsStmtStaleness(ctx), readReplicaScope: replicaReadScope, } + + txnManager := sessiontxn.GetTxnManager(ctx) + if provider, ok := txnManager.GetContextProvider().(*sessiontxn.SimpleTxnContextProvider); ok { + provider.GetReadTSFunc = b.getReadTS + provider.GetForUpdateTSFunc = func() (uint64, error) { + if b.forUpdateTS != 0 { + return b.forUpdateTS, nil + } + return b.getReadTS() + } + } + + return b } // MockPhysicalPlan is used to return a specified executor in when build. @@ -143,9 +156,9 @@ type MockExecutorBuilder struct { } // NewMockExecutorBuilderForTest is ONLY used in test. -func NewMockExecutorBuilderForTest(ctx sessionctx.Context, is infoschema.InfoSchema, ti *TelemetryInfo, snapshotTS uint64, isStaleness bool, replicaReadScope string) *MockExecutorBuilder { +func NewMockExecutorBuilderForTest(ctx sessionctx.Context, is infoschema.InfoSchema, ti *TelemetryInfo, replicaReadScope string) *MockExecutorBuilder { return &MockExecutorBuilder{ - executorBuilder: newExecutorBuilder(ctx, is, ti, snapshotTS, isStaleness, replicaReadScope)} + executorBuilder: newExecutorBuilder(ctx, is, ti, replicaReadScope)} } // Build builds an executor tree according to `p`. @@ -686,7 +699,7 @@ func (b *executorBuilder) buildLimit(v *plannercore.PhysicalLimit) Executor { if b.err != nil { return nil } - n := int(mathutil.MinUint64(v.Count, uint64(b.ctx.GetSessionVars().MaxChunkSize))) + n := int(mathutil.Min(v.Count, uint64(b.ctx.GetSessionVars().MaxChunkSize))) base := newBaseExecutor(b.ctx, v.Schema(), v.ID(), childExec) base.initCap = n e := &LimitExec{ @@ -733,10 +746,6 @@ func (b *executorBuilder) buildExecute(v *plannercore.Execute) Executor { failpoint.Inject("assertStaleReadValuesSameWithExecuteAndBuilder", func() { // This fail point is used to assert the behavior after refactoring is exactly the same with the previous implement. // Some variables in `plannercore.Execute` is deprecated and only be used for asserting now. - if b.snapshotTS != v.SnapshotTS { - panic(fmt.Sprintf("%d != %d", b.snapshotTS, v.SnapshotTS)) - } - if b.isStaleness != v.IsStaleness { panic(fmt.Sprintf("%v != %v", b.isStaleness, v.IsStaleness)) } @@ -746,7 +755,7 @@ func (b *executorBuilder) buildExecute(v *plannercore.Execute) Executor { } if v.SnapshotTS != 0 { - is, err := domain.GetDomain(b.ctx).GetSnapshotInfoSchema(b.snapshotTS) + is, err := domain.GetDomain(b.ctx).GetSnapshotInfoSchema(v.SnapshotTS) if err != nil { panic(err) } @@ -754,13 +763,28 @@ func (b *executorBuilder) buildExecute(v *plannercore.Execute) Executor { if b.is.SchemaMetaVersion() != is.SchemaMetaVersion() { panic(fmt.Sprintf("%d != %d", b.is.SchemaMetaVersion(), is.SchemaMetaVersion())) } + + ts, err := sessiontxn.GetTxnManager(b.ctx).GetReadTS() + if err != nil { + panic(e) + } + + if v.SnapshotTS != ts { + panic(fmt.Sprintf("%d != %d", ts, v.SnapshotTS)) + } } }) failpoint.Inject("assertExecutePrepareStatementStalenessOption", func(val failpoint.Value) { vs := strings.Split(val.(string), "_") assertTS, assertTxnScope := vs[0], vs[1] - if strconv.FormatUint(b.snapshotTS, 10) != assertTS || + staleread.AssertStmtStaleness(b.ctx, true) + ts, err := sessiontxn.GetTxnManager(b.ctx).GetReadTS() + if err != nil { + panic(e) + } + + if strconv.FormatUint(ts, 10) != assertTS || assertTxnScope != b.readReplicaScope { panic("execute prepare statement have wrong staleness option") } @@ -1102,7 +1126,7 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco us.collators = make([]collate.Collator, 0, len(us.columns)) for _, tp := range retTypes(us) { - us.collators = append(us.collators, collate.GetCollator(tp.Collate)) + us.collators = append(us.collators, collate.GetCollator(tp.GetCollate())) } startTS, err := b.getSnapshotTS() @@ -1352,18 +1376,20 @@ func (b *executorBuilder) buildHashJoin(v *plannercore.PhysicalHashJoin) Executo leftTypes, rightTypes := make([]*types.FieldType, 0, len(v.LeftJoinKeys)), make([]*types.FieldType, 0, len(v.RightJoinKeys)) for i, col := range v.LeftJoinKeys { leftTypes = append(leftTypes, leftExecTypes[col.Index].Clone()) - leftTypes[i].Flag = col.RetType.Flag + leftTypes[i].SetFlag(col.RetType.GetFlag()) } for i, col := range v.RightJoinKeys { rightTypes = append(rightTypes, rightExecTypes[col.Index].Clone()) - rightTypes[i].Flag = col.RetType.Flag + rightTypes[i].SetFlag(col.RetType.GetFlag()) } // consider collations for i := range v.EqualConditions { chs, coll := v.EqualConditions[i].CharsetAndCollation() - leftTypes[i].Charset, leftTypes[i].Collate = chs, coll - rightTypes[i].Charset, rightTypes[i].Collate = chs, coll + leftTypes[i].SetCharset(chs) + leftTypes[i].SetCollate(coll) + rightTypes[i].SetCharset(chs) + rightTypes[i].SetCollate(coll) } if leftIsBuildSide { e.buildTypes, e.probeTypes = leftTypes, rightTypes @@ -1541,11 +1567,11 @@ func (b *executorBuilder) getSnapshotTS() (uint64, error) { return b.dataReaderTS, nil } - if (b.inInsertStmt || b.inUpdateStmt || b.inDeleteStmt || b.inSelectLockStmt) && b.forUpdateTS != 0 { - return b.forUpdateTS, nil + txnManager := sessiontxn.GetTxnManager(b.ctx) + if b.inInsertStmt || b.inUpdateStmt || b.inDeleteStmt || b.inSelectLockStmt { + return txnManager.GetForUpdateTS() } - - return b.getReadTS() + return txnManager.GetReadTS() } // getReadTS returns the ts used by select (without for-update clause). The return value is affected by the isolation level @@ -1557,6 +1583,11 @@ func (b *executorBuilder) getReadTS() (uint64, error) { // logics. However for `IndexLookUpMergeJoin` and `IndexLookUpHashJoin`, it requires caching the // snapshotTS and and may even use it after the txn being destroyed. In this case, mark // `snapshotTSCached` to skip `refreshForUpdateTSForRC`. + failpoint.Inject("assertNotStaleReadForExecutorGetReadTS", func() { + // after refactoring stale read will use its own context provider + staleread.AssertStmtStaleness(b.ctx, false) + }) + if b.snapshotTSCached { return b.snapshotTS, nil } @@ -2937,18 +2968,18 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) for i, col := range innerPlan.Schema().Columns { innerTypes[i] = col.RetType.Clone() // The `innerTypes` would be called for `Datum.ConvertTo` when converting the columns from outer table - // to build hash map or construct lookup keys. So we need to modify its Flen otherwise there would be + // to build hash map or construct lookup keys. So we need to modify its flen otherwise there would be // truncate error. See issue https://github.com/pingcap/tidb/issues/21232 for example. if innerTypes[i].EvalType() == types.ETString { - innerTypes[i].Flen = types.UnspecifiedLength + innerTypes[i].SetFlen(types.UnspecifiedLength) } } // Use the probe table's collation. for i, col := range v.OuterHashKeys { outerTypes[col.Index] = outerTypes[col.Index].Clone() - outerTypes[col.Index].Collate = innerTypes[v.InnerHashKeys[i].Index].Collate - outerTypes[col.Index].Flag = col.RetType.Flag + outerTypes[col.Index].SetCollate(innerTypes[v.InnerHashKeys[i].Index].GetCollate()) + outerTypes[col.Index].SetFlag(col.RetType.GetFlag()) } // We should use JoinKey to construct the type information using by hashing, instead of using the child's schema directly. @@ -2959,11 +2990,11 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) outerHashTypes := make([]*types.FieldType, len(v.OuterHashKeys)) for i, col := range v.InnerHashKeys { innerHashTypes[i] = innerTypes[col.Index].Clone() - innerHashTypes[i].Flag = col.RetType.Flag + innerHashTypes[i].SetFlag(col.RetType.GetFlag()) } for i, col := range v.OuterHashKeys { outerHashTypes[i] = outerTypes[col.Index].Clone() - outerHashTypes[i].Flag = col.RetType.Flag + outerHashTypes[i].SetFlag(col.RetType.GetFlag()) } var ( @@ -3037,7 +3068,7 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) for i := 0; i < len(v.InnerJoinKeys); i++ { innerKeyCols[i] = v.InnerJoinKeys[i].Index innerKeyColIDs[i] = v.InnerJoinKeys[i].ID - keyCollators = append(keyCollators, collate.GetCollator(v.InnerJoinKeys[i].RetType.Collate)) + keyCollators = append(keyCollators, collate.GetCollator(v.InnerJoinKeys[i].RetType.GetCollate())) } e.outerCtx.keyCols = outerKeyCols e.innerCtx.keyCols = innerKeyCols @@ -3051,7 +3082,7 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) } for i := 0; i < len(v.InnerHashKeys); i++ { innerHashCols[i] = v.InnerHashKeys[i].Index - hashCollators = append(hashCollators, collate.GetCollator(v.InnerHashKeys[i].RetType.Collate)) + hashCollators = append(hashCollators, collate.GetCollator(v.InnerHashKeys[i].RetType.GetCollate())) } e.outerCtx.hashCols = outerHashCols e.innerCtx.hashCols = innerHashCols @@ -3073,10 +3104,10 @@ func (b *executorBuilder) buildIndexLookUpMergeJoin(v *plannercore.PhysicalIndex for i, col := range innerPlan.Schema().Columns { innerTypes[i] = col.RetType.Clone() // The `innerTypes` would be called for `Datum.ConvertTo` when converting the columns from outer table - // to build hash map or construct lookup keys. So we need to modify its Flen otherwise there would be + // to build hash map or construct lookup keys. So we need to modify its flen otherwise there would be // truncate error. See issue https://github.com/pingcap/tidb/issues/21232 for example. if innerTypes[i].EvalType() == types.ETString { - innerTypes[i].Flen = types.UnspecifiedLength + innerTypes[i].SetFlen(types.UnspecifiedLength) } } var ( @@ -3110,7 +3141,7 @@ func (b *executorBuilder) buildIndexLookUpMergeJoin(v *plannercore.PhysicalIndex keyCollators := make([]collate.Collator, 0, len(v.InnerJoinKeys)) for i := 0; i < len(v.InnerJoinKeys); i++ { innerKeyCols[i] = v.InnerJoinKeys[i].Index - keyCollators = append(keyCollators, collate.GetCollator(v.InnerJoinKeys[i].RetType.Collate)) + keyCollators = append(keyCollators, collate.GetCollator(v.InnerJoinKeys[i].RetType.GetCollate())) } executorCounterIndexLookUpJoin.Inc() @@ -3384,11 +3415,14 @@ func keyColumnsIncludeAllPartitionColumns(keyColumns []int, pe *tables.Partition return true } -func prunePartitionForInnerExecutor(ctx sessionctx.Context, tbl table.Table, schema *expression.Schema, partitionInfo *plannercore.PartitionInfo, +func (builder *dataReaderBuilder) prunePartitionForInnerExecutor(tbl table.Table, schema *expression.Schema, partitionInfo *plannercore.PartitionInfo, lookUpContent []*indexJoinLookUpContent) (usedPartition []table.PhysicalTable, canPrune bool, contentPos []int64, err error) { partitionTbl := tbl.(table.PartitionedTable) + + // In index join, this is called by multiple goroutines simultaneously, but partitionPruning is not thread-safe. + // Use once.Do to avoid DATA RACE here. // TODO: condition based pruning can be do in advance. - condPruneResult, err := partitionPruning(ctx, partitionTbl, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) + condPruneResult, err := builder.partitionPruning(partitionTbl, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) if err != nil { return nil, false, nil, err } @@ -3441,7 +3475,7 @@ func prunePartitionForInnerExecutor(ctx sessionctx.Context, tbl table.Table, sch for i, date := range content.keys { locateKey[keyColOffsets[i]] = date } - p, err := partitionTbl.GetPartitionByRow(ctx, locateKey) + p, err := partitionTbl.GetPartitionByRow(builder.ctx, locateKey) if err != nil { return nil, false, nil, err } @@ -3886,6 +3920,11 @@ type dataReaderBuilder struct { *executorBuilder selectResultHook // for testing + once struct { + sync.Once + condPruneResult []table.PhysicalTable + err error + } } type mockPhysicalIndexReader struct { @@ -3985,7 +4024,7 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte return nil, err } partitionInfo := &v.PartitionInfo - usedPartitionList, err := partitionPruning(e.ctx, pt, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) + usedPartitionList, err := builder.partitionPruning(pt, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) if err != nil { return nil, err } @@ -4189,7 +4228,7 @@ func (builder *dataReaderBuilder) buildIndexReaderForIndexJoin(ctx context.Conte } tbl, _ := builder.executorBuilder.is.TableByID(tbInfo.ID) - usedPartition, canPrune, contentPos, err := prunePartitionForInnerExecutor(builder.executorBuilder.ctx, tbl, e.Schema(), &v.PartitionInfo, lookUpContents) + usedPartition, canPrune, contentPos, err := builder.prunePartitionForInnerExecutor(tbl, e.Schema(), &v.PartitionInfo, lookUpContents) if err != nil { return nil, err } @@ -4235,7 +4274,7 @@ func (builder *dataReaderBuilder) buildIndexLookUpReaderForIndexJoin(ctx context return e, err } tbl, _ := builder.executorBuilder.is.TableByID(tbInfo.ID) - usedPartition, canPrune, contentPos, err := prunePartitionForInnerExecutor(builder.executorBuilder.ctx, tbl, e.Schema(), &v.PartitionInfo, lookUpContents) + usedPartition, canPrune, contentPos, err := builder.prunePartitionForInnerExecutor(tbl, e.Schema(), &v.PartitionInfo, lookUpContents) if err != nil { return nil, err } @@ -4612,7 +4651,7 @@ func NewRowDecoder(ctx sessionctx.Context, schema *expression.Schema, tbl *model reqCols := make([]rowcodec.ColInfo, len(schema.Columns)) for i := range schema.Columns { idx, col := i, schema.Columns[i] - isPK := (tbl.PKIsHandle && mysql.HasPriKeyFlag(col.RetType.Flag)) || col.ID == model.ExtraHandleID + isPK := (tbl.PKIsHandle && mysql.HasPriKeyFlag(col.RetType.GetFlag())) || col.ID == model.ExtraHandleID if isPK { pkCols = append(pkCols, col.ID) } @@ -4762,6 +4801,16 @@ func (b *executorBuilder) buildAdminResetTelemetryID(v *plannercore.AdminResetTe return &AdminResetTelemetryIDExec{baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID())} } +func (builder *dataReaderBuilder) partitionPruning(tbl table.PartitionedTable, conds []expression.Expression, partitionNames []model.CIStr, + columns []*expression.Column, columnNames types.NameSlice) ([]table.PhysicalTable, error) { + builder.once.Do(func() { + condPruneResult, err := partitionPruning(builder.executorBuilder.ctx, tbl, conds, partitionNames, columns, columnNames) + builder.once.condPruneResult = condPruneResult + builder.once.err = err + }) + return builder.once.condPruneResult, builder.once.err +} + func partitionPruning(ctx sessionctx.Context, tbl table.PartitionedTable, conds []expression.Expression, partitionNames []model.CIStr, columns []*expression.Column, columnNames types.NameSlice) ([]table.PhysicalTable, error) { idxArr, err := plannercore.PartitionPruning(ctx, tbl, conds, partitionNames, columns, columnNames) diff --git a/executor/checksum.go b/executor/checksum.go index 013fd3be2226f..4c62176b9116f 100644 --- a/executor/checksum.go +++ b/executor/checksum.go @@ -241,7 +241,7 @@ func (c *checksumContext) buildTableRequest(ctx sessionctx.Context, tableID int6 } var builder distsql.RequestBuilder - builder.SetResourceGroupTagger(ctx.GetSessionVars().StmtCtx) + builder.SetResourceGroupTagger(ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) return builder.SetHandleRanges(ctx.GetSessionVars().StmtCtx, tableID, c.TableInfo.IsCommonHandle, ranges, nil). SetChecksumRequest(checksum). SetStartTS(c.StartTs). @@ -258,7 +258,7 @@ func (c *checksumContext) buildIndexRequest(ctx sessionctx.Context, tableID int6 ranges := ranger.FullRange() var builder distsql.RequestBuilder - builder.SetResourceGroupTagger(ctx.GetSessionVars().StmtCtx) + builder.SetResourceGroupTagger(ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) return builder.SetIndexRanges(ctx.GetSessionVars().StmtCtx, tableID, indexInfo.ID, ranges). SetChecksumRequest(checksum). SetStartTS(c.StartTs). diff --git a/executor/cluster_table_test.go b/executor/cluster_table_test.go index 1cbb2bf3763e8..d981c8f9b6639 100644 --- a/executor/cluster_table_test.go +++ b/executor/cluster_table_test.go @@ -37,7 +37,7 @@ import ( ) func createRPCServer(t *testing.T, dom *domain.Domain) *grpc.Server { - sm := &mockSessionManager1{} + sm := &testkit.MockSessionManager{} sm.PS = append(sm.PS, &util.ProcessInfo{ ID: 1, User: "root", diff --git a/executor/collation_test.go b/executor/collation_test.go index d4b957ee413d6..e32d9aaa633e3 100644 --- a/executor/collation_test.go +++ b/executor/collation_test.go @@ -26,7 +26,7 @@ import ( ) func TestVecGroupChecker(t *testing.T) { - tp := &types.FieldType{Tp: mysql.TypeVarchar} + tp := types.NewFieldTypeBuilderP().SetType(mysql.TypeVarchar).BuildP() col0 := &expression.Column{ RetType: tp, Index: 0, @@ -43,7 +43,7 @@ func TestVecGroupChecker(t *testing.T) { chk.Column(0).AppendString("À") chk.Column(0).AppendString("A") - tp.Collate = "bin" + tp.SetCollate("bin") groupChecker.reset() _, err := groupChecker.splitIntoGroups(chk) require.NoError(t, err) @@ -54,7 +54,7 @@ func TestVecGroupChecker(t *testing.T) { } require.True(t, groupChecker.isExhausted()) - tp.Collate = "utf8_general_ci" + tp.SetCollate("utf8_general_ci") groupChecker.reset() _, err = groupChecker.splitIntoGroups(chk) require.NoError(t, err) @@ -65,7 +65,7 @@ func TestVecGroupChecker(t *testing.T) { } require.True(t, groupChecker.isExhausted()) - tp.Collate = "utf8_unicode_ci" + tp.SetCollate("utf8_unicode_ci") groupChecker.reset() _, err = groupChecker.splitIntoGroups(chk) require.NoError(t, err) @@ -77,8 +77,8 @@ func TestVecGroupChecker(t *testing.T) { require.True(t, groupChecker.isExhausted()) // test padding - tp.Collate = "utf8_bin" - tp.Flen = 6 + tp.SetCollate("utf8_bin") + tp.SetFlen(6) chk.Reset() chk.Column(0).AppendString("a") chk.Column(0).AppendString("a ") diff --git a/executor/compiler.go b/executor/compiler.go index 37bc939eb57c1..af678b58bffa3 100644 --- a/executor/compiler.go +++ b/executor/compiler.go @@ -16,7 +16,6 @@ package executor import ( "context" - "fmt" "github.com/opentracing/opentracing-go" "github.com/pingcap/failpoint" @@ -28,6 +27,7 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/sessiontxn/staleread" ) var ( @@ -71,6 +71,10 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (*ExecStm failpoint.Inject("assertTxnManagerInCompile", func() { sessiontxn.RecordAssert(c.Ctx, "assertTxnManagerInCompile", true) sessiontxn.AssertTxnManagerInfoSchema(c.Ctx, ret.InfoSchema) + if ret.LastSnapshotTS != 0 { + staleread.AssertStmtStaleness(c.Ctx, true) + sessiontxn.AssertTxnManagerReadTS(c.Ctx, ret.LastSnapshotTS) + } }) is := sessiontxn.GetTxnManager(c.Ctx).GetTxnInfoSchema() @@ -80,11 +84,7 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (*ExecStm } failpoint.Inject("assertStmtCtxIsStaleness", func(val failpoint.Value) { - expected := val.(bool) - got := c.Ctx.GetSessionVars().StmtCtx.IsStaleness - if got != expected { - panic(fmt.Sprintf("stmtctx isStaleness wrong, expected:%v, got:%v", expected, got)) - } + staleread.AssertStmtStaleness(c.Ctx, val.(bool)) }) CountStmtNode(stmtNode, c.Ctx.GetSessionVars().InRestrictedSQL) @@ -94,8 +94,6 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (*ExecStm } return &ExecStmt{ GoCtx: ctx, - SnapshotTS: ret.LastSnapshotTS, - IsStaleness: ret.IsStaleness, ReplicaReadScope: ret.ReadReplicaScope, InfoSchema: is, Plan: finalPlan, @@ -380,7 +378,7 @@ func GetStmtLabel(stmtNode ast.StmtNode) string { case *ast.LoadDataStmt: return "LoadData" case *ast.RollbackStmt: - return "RollBack" + return "Rollback" case *ast.SelectStmt: return "Select" case *ast.SetStmt, *ast.SetPwdStmt: diff --git a/executor/concurrent_map.go b/executor/concurrent_map.go index 191c890621dc8..68747b4766ba2 100644 --- a/executor/concurrent_map.go +++ b/executor/concurrent_map.go @@ -16,6 +16,8 @@ package executor import ( "sync" + + "github.com/pingcap/tidb/util/hack" ) // ShardCount controls the shard maps within the concurrent map @@ -28,14 +30,15 @@ type concurrentMap []*concurrentMapShared // A "thread" safe string to anything map. type concurrentMapShared struct { items map[uint64]*entry - sync.RWMutex // Read Write mutex, guards access to internal map. + sync.RWMutex // Read Write mutex, guards access to internal map. + bInMap int64 // indicate there are 2^bInMap buckets in items } // newConcurrentMap creates a new concurrent map. func newConcurrentMap() concurrentMap { m := make(concurrentMap, ShardCount) for i := 0; i < ShardCount; i++ { - m[i] = &concurrentMapShared{items: make(map[uint64]*entry)} + m[i] = &concurrentMapShared{items: make(map[uint64]*entry), bInMap: 0} } return m } @@ -46,17 +49,18 @@ func (m concurrentMap) getShard(hashKey uint64) *concurrentMapShared { } // Insert inserts a value in a shard safely -func (m concurrentMap) Insert(key uint64, value *entry) { +func (m concurrentMap) Insert(key uint64, value *entry) (memDelta int64) { shard := m.getShard(key) shard.Lock() - v, ok := shard.items[key] - if !ok { - shard.items[key] = value - } else { - value.next = v - shard.items[key] = value + oldValue := shard.items[key] + value.next = oldValue + shard.items[key] = value + if len(shard.items) > (1< 0 { + topsql.RegisterPlan(normalizedPlan, planDigest) + } +} + // ResetUpdateStmtCtx resets statement context for UpdateStmt. func ResetUpdateStmtCtx(sc *stmtctx.StatementContext, stmt *ast.UpdateStmt, vars *variable.SessionVars) { sc.InUpdateStmt = true @@ -1982,7 +1999,7 @@ func FillVirtualColumnValue(virtualRetTypes []*types.FieldType, virtualColumnInd return err } // Handle the bad null error. - if (mysql.HasNotNullFlag(columns[idx].Flag) || mysql.HasPreventNullInsertFlag(columns[idx].Flag)) && castDatum.IsNull() { + if (mysql.HasNotNullFlag(columns[idx].GetFlag()) || mysql.HasPreventNullInsertFlag(columns[idx].GetFlag())) && castDatum.IsNull() { castDatum = table.GetZeroValue(columns[idx]) } virCols.AppendDatum(i, &castDatum) @@ -1993,7 +2010,7 @@ func FillVirtualColumnValue(virtualRetTypes []*types.FieldType, virtualColumnInd } func setOptionForTopSQL(sc *stmtctx.StatementContext, snapshot kv.Snapshot) { - if snapshot == nil || !topsqlstate.TopSQLEnabled() { + if snapshot == nil { return } snapshot.SetOption(kv.ResourceGroupTagger, sc.GetResourceGroupTagger()) diff --git a/executor/executor_failpoint_test.go b/executor/executor_failpoint_test.go index fc0ab306fd157..0ae0977a3af07 100644 --- a/executor/executor_failpoint_test.go +++ b/executor/executor_failpoint_test.go @@ -269,12 +269,13 @@ func TestCollectCopRuntimeStats(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("create table t1 (a int, b int)") + time.Sleep(1 * time.Second) tk.MustExec("set tidb_enable_collect_execution_info=1;") require.NoError(t, failpoint.Enable("tikvclient/tikvStoreRespResult", `return(true)`)) rows := tk.MustQuery("explain analyze select * from t1").Rows() require.Len(t, rows, 2) explain := fmt.Sprintf("%v", rows[0]) - require.Regexp(t, ".*rpc_num: 2, .*regionMiss:.*", explain) + require.Regexp(t, ".*rpc_num: .*, .*regionMiss:.*", explain) require.NoError(t, failpoint.Disable("tikvclient/tikvStoreRespResult")) } diff --git a/executor/executor_issue_test.go b/executor/executor_issue_test.go index a844a4666734c..eb13f6a0bbd19 100644 --- a/executor/executor_issue_test.go +++ b/executor/executor_issue_test.go @@ -332,19 +332,19 @@ func TestIssue28650(t *testing.T) { } func TestIssue30289(t *testing.T) { + fpName := "github.com/pingcap/tidb/executor/issue30289" store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - fpName := "github.com/pingcap/tidb/executor/issue30289" + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") require.NoError(t, failpoint.Enable(fpName, `return(true)`)) defer func() { require.NoError(t, failpoint.Disable(fpName)) }() - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") err := tk.QueryToErr("select /*+ hash_join(t1) */ * from t t1 join t t2 on t1.a=t2.a") - require.Regexp(t, "issue30289 build return error", err.Error()) + require.EqualError(t, err, "issue30289 build return error") } func TestIssue29498(t *testing.T) { @@ -434,7 +434,7 @@ func TestIndexJoin31494(t *testing.T) { insertStr += fmt.Sprintf(", (%d, %d, %d)", i, i, i) } tk.MustExec(insertStr) - sm := &mockSessionManager1{ + sm := &testkit.MockSessionManager{ PS: make([]*util.ProcessInfo, 0), } tk.Session().SetSessionManager(sm) @@ -460,7 +460,7 @@ func TestIndexJoin31494(t *testing.T) { func TestFix31038(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { - conf.EnableCollectExecutionInfo = false + conf.Instance.EnableCollectExecutionInfo = false }) store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/executor/executor_legacy_test.go b/executor/executor_legacy_test.go deleted file mode 100644 index 3ff3e2176a012..0000000000000 --- a/executor/executor_legacy_test.go +++ /dev/null @@ -1,1626 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package executor_test - -import ( - "context" - "fmt" - "strconv" - "strings" - "testing" - "time" - - . "github.com/pingcap/check" - "github.com/pingcap/errors" - "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/domain/infosync" - "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/parser" - "github.com/pingcap/tidb/parser/auth" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/planner" - plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" - "github.com/tikv/client-go/v2/oracle" - "github.com/tikv/client-go/v2/testutils" -) - -func TestT(t *testing.T) { - CustomVerboseFlag = true - *CustomParallelSuiteFlag = true - - TestingT(t) -} - -var _ = Suite(&testSuite{&baseTestSuite{}}) -var _ = Suite(&testSuiteP2{&baseTestSuite{}}) -var _ = Suite(&testSuite2{&baseTestSuite{}}) -var _ = Suite(&testSuite3{&baseTestSuite{}}) - -type testSuite struct{ *baseTestSuite } -type testSuiteP2 struct{ *baseTestSuite } - -type baseTestSuite struct { - cluster testutils.Cluster - store kv.Storage - domain *domain.Domain - *parser.Parser -} - -func (s *baseTestSuite) SetUpSuite(c *C) { - s.Parser = parser.New() - store, err := mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - s.store = store - session.SetSchemaLease(0) - session.DisableStats4Test() - d, err := session.BootstrapSession(s.store) - c.Assert(err, IsNil) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - se.Close() - d.SetStatsUpdating(true) - s.domain = d -} - -func (s *baseTestSuite) TearDownSuite(c *C) { - s.domain.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testSuite) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } -} - -func (s *testSuite3) TestAdmin(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists admin_test") - tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1))") - tk.MustExec("insert admin_test (c1) values (1),(2),(NULL)") - - ctx := context.Background() - // cancel DDL jobs test - r, err := tk.Exec("admin cancel ddl jobs 1") - c.Assert(err, IsNil, Commentf("err %v", err)) - req := r.NewChunk(nil) - err = r.Next(ctx, req) - c.Assert(err, IsNil) - row := req.GetRow(0) - c.Assert(row.Len(), Equals, 2) - c.Assert(row.GetString(0), Equals, "1") - c.Assert(row.GetString(1), Matches, "*DDL Job:1 not found") - - // show ddl test; - r, err = tk.Exec("admin show ddl") - c.Assert(err, IsNil) - req = r.NewChunk(nil) - err = r.Next(ctx, req) - c.Assert(err, IsNil) - row = req.GetRow(0) - c.Assert(row.Len(), Equals, 6) - txn, err := s.store.Begin() - c.Assert(err, IsNil) - ddlInfo, err := admin.GetDDLInfo(txn) - c.Assert(err, IsNil) - c.Assert(row.GetInt64(0), Equals, ddlInfo.SchemaVer) - // TODO: Pass this test. - // rowOwnerInfos := strings.Split(row.Data[1].GetString(), ",") - // ownerInfos := strings.Split(ddlInfo.Owner.String(), ",") - // c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0]) - serverInfo, err := infosync.GetServerInfoByID(ctx, row.GetString(1)) - c.Assert(err, IsNil) - c.Assert(row.GetString(2), Equals, serverInfo.IP+":"+ - strconv.FormatUint(uint64(serverInfo.Port), 10)) - c.Assert(row.GetString(3), Equals, "") - req = r.NewChunk(nil) - err = r.Next(ctx, req) - c.Assert(err, IsNil) - c.Assert(req.NumRows() == 0, IsTrue) - err = txn.Rollback() - c.Assert(err, IsNil) - - // show DDL jobs test - r, err = tk.Exec("admin show ddl jobs") - c.Assert(err, IsNil) - req = r.NewChunk(nil) - err = r.Next(ctx, req) - c.Assert(err, IsNil) - row = req.GetRow(0) - c.Assert(row.Len(), Equals, 12) - txn, err = s.store.Begin() - c.Assert(err, IsNil) - historyJobs, err := admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) - c.Assert(len(historyJobs), Greater, 1) - c.Assert(len(row.GetString(1)), Greater, 0) - c.Assert(err, IsNil) - c.Assert(row.GetInt64(0), Equals, historyJobs[0].ID) - c.Assert(err, IsNil) - - r, err = tk.Exec("admin show ddl jobs 20") - c.Assert(err, IsNil) - req = r.NewChunk(nil) - err = r.Next(ctx, req) - c.Assert(err, IsNil) - row = req.GetRow(0) - c.Assert(row.Len(), Equals, 12) - c.Assert(row.GetInt64(0), Equals, historyJobs[0].ID) - c.Assert(err, IsNil) - - // show DDL job queries test - tk.MustExec("use test") - tk.MustExec("drop table if exists admin_test2") - tk.MustExec("create table admin_test2 (c1 int, c2 int, c3 int default 1, index (c1))") - result := tk.MustQuery(`admin show ddl job queries 1, 1, 1`) - result.Check(testkit.Rows()) - result = tk.MustQuery(`admin show ddl job queries 1, 2, 3, 4`) - result.Check(testkit.Rows()) - historyJobs, err = admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) - result = tk.MustQuery(fmt.Sprintf("admin show ddl job queries %d", historyJobs[0].ID)) - result.Check(testkit.Rows(historyJobs[0].Query)) - c.Assert(err, IsNil) - - // check table test - tk.MustExec("create table admin_test1 (c1 int, c2 int default 1, index (c1))") - tk.MustExec("insert admin_test1 (c1) values (21),(22)") - r, err = tk.Exec("admin check table admin_test, admin_test1") - c.Assert(err, IsNil) - c.Assert(r, IsNil) - // error table name - err = tk.ExecToErr("admin check table admin_test_error") - c.Assert(err, NotNil) - // different index values - sctx := tk.Se.(sessionctx.Context) - dom := domain.GetDomain(sctx) - is := dom.InfoSchema() - c.Assert(is, NotNil) - tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("admin_test")) - c.Assert(err, IsNil) - c.Assert(tb.Indices(), HasLen, 1) - _, err = tb.Indices()[0].Create(mock.NewContext(), txn, types.MakeDatums(int64(10)), kv.IntHandle(1), nil) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - errAdmin := tk.ExecToErr("admin check table admin_test") - c.Assert(errAdmin, NotNil) - - if config.CheckTableBeforeDrop { - err = tk.ExecToErr("drop table admin_test") - c.Assert(err.Error(), Equals, errAdmin.Error()) - - // Drop inconsistency index. - tk.MustExec("alter table admin_test drop index c1") - tk.MustExec("admin check table admin_test") - } - // checksum table test - tk.MustExec("create table checksum_with_index (id int, count int, PRIMARY KEY(id), KEY(count))") - tk.MustExec("create table checksum_without_index (id int, count int, PRIMARY KEY(id))") - r, err = tk.Exec("admin checksum table checksum_with_index, checksum_without_index") - c.Assert(err, IsNil) - res := tk.ResultSetToResult(r, Commentf("admin checksum table")) - // Mocktikv returns 1 for every table/index scan, then we will xor the checksums of a table. - // For "checksum_with_index", we have two checksums, so the result will be 1^1 = 0. - // For "checksum_without_index", we only have one checksum, so the result will be 1. - res.Sort().Check(testkit.Rows("test checksum_with_index 0 2 2", "test checksum_without_index 1 1 1")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("CREATE TABLE t1 (c2 BOOL, PRIMARY KEY (c2));") - tk.MustExec("INSERT INTO t1 SET c2 = '0';") - tk.MustExec("ALTER TABLE t1 ADD COLUMN c3 DATETIME NULL DEFAULT '2668-02-03 17:19:31';") - tk.MustExec("ALTER TABLE t1 ADD INDEX idx2 (c3);") - tk.MustExec("ALTER TABLE t1 ADD COLUMN c4 bit(10) default 127;") - tk.MustExec("ALTER TABLE t1 ADD INDEX idx3 (c4);") - tk.MustExec("admin check table t1;") - - // Test admin show ddl jobs table name after table has been droped. - tk.MustExec("drop table if exists t1;") - re := tk.MustQuery("admin show ddl jobs 1") - rows := re.Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][2], Equals, "t1") - - // Test for reverse scan get history ddl jobs when ddl history jobs queue has multiple regions. - txn, err = s.store.Begin() - c.Assert(err, IsNil) - historyJobs, err = admin.GetHistoryDDLJobs(txn, 20) - c.Assert(err, IsNil) - - // Split region for history ddl job queues. - m := meta.NewMeta(txn) - startKey := meta.DDLJobHistoryKey(m, 0) - endKey := meta.DDLJobHistoryKey(m, historyJobs[0].ID) - s.cluster.SplitKeys(startKey, endKey, int(historyJobs[0].ID/5)) - - historyJobs2, err := admin.GetHistoryDDLJobs(txn, 20) - c.Assert(err, IsNil) - c.Assert(historyJobs, DeepEquals, historyJobs2) -} - -func (s *testSuiteP2) TestAdminShowDDLJobs(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_admin_show_ddl_jobs") - tk.MustExec("use test_admin_show_ddl_jobs") - tk.MustExec("create table t (a int);") - - re := tk.MustQuery("admin show ddl jobs 1") - row := re.Rows()[0] - c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") - jobID, err := strconv.Atoi(row[0].(string)) - c.Assert(err, IsNil) - - err = kv.RunInNewTxn(context.Background(), s.store, true, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - job, err := t.GetHistoryDDLJob(int64(jobID)) - c.Assert(err, IsNil) - c.Assert(job, NotNil) - // Test for compatibility. Old TiDB version doesn't have SchemaName field, and the BinlogInfo maybe nil. - // See PR: 11561. - job.BinlogInfo = nil - job.SchemaName = "" - err = t.AddHistoryDDLJob(job, true) - c.Assert(err, IsNil) - return nil - }) - c.Assert(err, IsNil) - - re = tk.MustQuery("admin show ddl jobs 1") - row = re.Rows()[0] - c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") - - re = tk.MustQuery("admin show ddl jobs 1 where job_type='create table'") - row = re.Rows()[0] - c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") - c.Assert(row[10], Equals, "") - - // Test the START_TIME and END_TIME field. - tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) - re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") - row = re.Rows()[0] - createTime, err := types.ParseDatetime(nil, row[8].(string)) - c.Assert(err, IsNil) - startTime, err := types.ParseDatetime(nil, row[9].(string)) - c.Assert(err, IsNil) - endTime, err := types.ParseDatetime(nil, row[10].(string)) - c.Assert(err, IsNil) - tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) - re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") - row2 := re.Rows()[0] - c.Assert(row[8], Not(Equals), row2[8]) - c.Assert(row[9], Not(Equals), row2[9]) - c.Assert(row[10], Not(Equals), row2[10]) - createTime2, err := types.ParseDatetime(nil, row2[8].(string)) - c.Assert(err, IsNil) - startTime2, err := types.ParseDatetime(nil, row2[9].(string)) - c.Assert(err, IsNil) - endTime2, err := types.ParseDatetime(nil, row2[10].(string)) - c.Assert(err, IsNil) - loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) - loc2, err := time.LoadLocation("Europe/Amsterdam") - c.Assert(err, IsNil) - t, err := createTime.GoTime(loc) - c.Assert(err, IsNil) - t2, err := createTime2.GoTime(loc2) - c.Assert(err, IsNil) - c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) - t, err = startTime.GoTime(loc) - c.Assert(err, IsNil) - t2, err = startTime2.GoTime(loc2) - c.Assert(err, IsNil) - c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) - t, err = endTime.GoTime(loc) - c.Assert(err, IsNil) - t2, err = endTime2.GoTime(loc2) - c.Assert(err, IsNil) - c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) -} - -func (s *testSuiteP2) TestAdminShowDDLJobsInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_admin_show_ddl_jobs") - tk.MustExec("drop placement policy if exists x") - tk.MustExec("drop placement policy if exists y") - defer func() { - tk.MustExec("drop database if exists test_admin_show_ddl_jobs") - tk.MustExec("drop placement policy if exists x") - tk.MustExec("drop placement policy if exists y") - }() - - // Test for issue: https://github.com/pingcap/tidb/issues/29915 - tk.MustExec("create placement policy x followers=4;") - tk.MustExec("create placement policy y " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2") - tk.MustExec("create database if not exists test_admin_show_ddl_jobs") - tk.MustExec("use test_admin_show_ddl_jobs") - - tk.MustExec("create table t (a int);") - tk.MustExec("create table t1 (a int);") - - tk.MustExec("alter table t placement policy x;") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table placement") - - tk.MustExec("rename table t to tt, t1 to tt1") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "rename tables") - - tk.MustExec("create table tt2 (c int) PARTITION BY RANGE (c) " + - "(PARTITION p0 VALUES LESS THAN (6)," + - "PARTITION p1 VALUES LESS THAN (11)," + - "PARTITION p2 VALUES LESS THAN (16)," + - "PARTITION p3 VALUES LESS THAN (21));") - tk.MustExec("alter table tt2 partition p0 placement policy y") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table partition placement") - - tk.MustExec("alter table tt1 cache") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table cache") - tk.MustExec("alter table tt1 nocache") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table nocache") -} - -func (s *testSuiteP2) TestAdminChecksumOfPartitionedTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("USE test;") - tk.MustExec("DROP TABLE IF EXISTS admin_checksum_partition_test;") - tk.MustExec("CREATE TABLE admin_checksum_partition_test (a INT) PARTITION BY HASH(a) PARTITIONS 4;") - tk.MustExec("INSERT INTO admin_checksum_partition_test VALUES (1), (2);") - - r := tk.MustQuery("ADMIN CHECKSUM TABLE admin_checksum_partition_test;") - r.Check(testkit.Rows("test admin_checksum_partition_test 1 5 5")) -} - -func (s *testSuiteP2) TestUnion(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - testSQL := `drop table if exists union_test; create table union_test(id int);` - tk.MustExec(testSQL) - - testSQL = `drop table if exists union_test;` - tk.MustExec(testSQL) - testSQL = `create table union_test(id int);` - tk.MustExec(testSQL) - testSQL = `insert union_test values (1),(2)` - tk.MustExec(testSQL) - - testSQL = `select * from (select id from union_test union select id from union_test) t order by id;` - r := tk.MustQuery(testSQL) - r.Check(testkit.Rows("1", "2")) - - r = tk.MustQuery("select 1 union all select 1") - r.Check(testkit.Rows("1", "1")) - - r = tk.MustQuery("select 1 union all select 1 union select 1") - r.Check(testkit.Rows("1")) - - r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1") - r.Check(testkit.Rows("1")) - - r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1, 1") - r.Check(testkit.Rows("2")) - - r = tk.MustQuery("select id from union_test union all (select 1) order by id desc") - r.Check(testkit.Rows("2", "1", "1")) - - r = tk.MustQuery("select id as a from union_test union (select 1) order by a desc") - r.Check(testkit.Rows("2", "1")) - - r = tk.MustQuery(`select null as a union (select "abc") order by a`) - r.Check(testkit.Rows("", "abc")) - - r = tk.MustQuery(`select "abc" as a union (select 1) order by a`) - r.Check(testkit.Rows("1", "abc")) - - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c int, d int)") - tk.MustExec("insert t1 values (NULL, 1)") - tk.MustExec("insert t1 values (1, 1)") - tk.MustExec("insert t1 values (1, 2)") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2 (c int, d int)") - tk.MustExec("insert t2 values (1, 3)") - tk.MustExec("insert t2 values (1, 1)") - tk.MustExec("drop table if exists t3") - tk.MustExec("create table t3 (c int, d int)") - tk.MustExec("insert t3 values (3, 2)") - tk.MustExec("insert t3 values (4, 3)") - r = tk.MustQuery(`select sum(c1), c2 from (select c c1, d c2 from t1 union all select d c1, c c2 from t2 union all select c c1, d c2 from t3) x group by c2 order by c2`) - r.Check(testkit.Rows("5 1", "4 2", "4 3")) - - tk.MustExec("drop table if exists t1, t2, t3") - tk.MustExec("create table t1 (a int primary key)") - tk.MustExec("create table t2 (a int primary key)") - tk.MustExec("create table t3 (a int primary key)") - tk.MustExec("insert t1 values (7), (8)") - tk.MustExec("insert t2 values (1), (9)") - tk.MustExec("insert t3 values (2), (3)") - r = tk.MustQuery("select * from t1 union all select * from t2 union all (select * from t3) order by a limit 2") - r.Check(testkit.Rows("1", "2")) - - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1 (a int)") - tk.MustExec("create table t2 (a int)") - tk.MustExec("insert t1 values (2), (1)") - tk.MustExec("insert t2 values (3), (4)") - r = tk.MustQuery("select * from t1 union all (select * from t2) order by a limit 1") - r.Check(testkit.Rows("1")) - r = tk.MustQuery("select (select * from t1 where a != t.a union all (select * from t2 where a != t.a) order by a limit 1) from t1 t") - r.Check(testkit.Rows("1", "2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (id int unsigned primary key auto_increment, c1 int, c2 int, index c1_c2 (c1, c2))") - tk.MustExec("insert into t (c1, c2) values (1, 1)") - tk.MustExec("insert into t (c1, c2) values (1, 2)") - tk.MustExec("insert into t (c1, c2) values (2, 3)") - r = tk.MustQuery("select * from (select * from t where t.c1 = 1 union select * from t where t.id = 1) s order by s.id") - r.Check(testkit.Rows("1 1 1", "2 1 2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (f1 DATE)") - tk.MustExec("INSERT INTO t VALUES ('1978-11-26')") - r = tk.MustQuery("SELECT f1+0 FROM t UNION SELECT f1+0 FROM t") - r.Check(testkit.Rows("19781126")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a int, b int)") - tk.MustExec("INSERT INTO t VALUES ('1', '1')") - r = tk.MustQuery("select b from (SELECT * FROM t UNION ALL SELECT a, b FROM t order by a) t") - r.Check(testkit.Rows("1", "1")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a DECIMAL(4,2))") - tk.MustExec("INSERT INTO t VALUE(12.34)") - r = tk.MustQuery("SELECT 1 AS c UNION select a FROM t") - r.Sort().Check(testkit.Rows("1.00", "12.34")) - - // #issue3771 - r = tk.MustQuery("SELECT 'a' UNION SELECT CONCAT('a', -4)") - r.Sort().Check(testkit.Rows("a", "a-4")) - - // test race - tk.MustQuery("SELECT @x:=0 UNION ALL SELECT @x:=0 UNION ALL SELECT @x") - - // test field tp - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("CREATE TABLE t1 (a date)") - tk.MustExec("CREATE TABLE t2 (a date)") - tk.MustExec("SELECT a from t1 UNION select a FROM t2") - tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` date DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Move from session test. - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1 (c double);") - tk.MustExec("create table t2 (c double);") - tk.MustExec("insert into t1 value (73);") - tk.MustExec("insert into t2 value (930);") - // If set unspecified column flen to 0, it will cause bug in union. - // This test is used to prevent the bug reappear. - tk.MustQuery("select c from t1 union (select c from t2) order by c").Check(testkit.Rows("73", "930")) - - // issue 5703 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a date)") - tk.MustExec("insert into t value ('2017-01-01'), ('2017-01-02')") - r = tk.MustQuery("(select a from t where a < 0) union (select a from t where a > 0) order by a") - r.Check(testkit.Rows("2017-01-01", "2017-01-02")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t value(0),(0)") - tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1")) - tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10")) - tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10")) - tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4")) - - err := tk.ExecToErr("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp") - c.Assert(err, NotNil) - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) - - err = tk.ExecToErr("select 1 from (select a from t order by a union all select a from t limit 1) tmp") - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) - - _, err = tk.Exec("(select a from t order by a) union all select a from t limit 1 union all select a from t limit 1") - c.Assert(terror.ErrorEqual(err, plannercore.ErrWrongUsage), IsTrue, Commentf("err %v", err)) - - _, err = tk.Exec("(select a from t limit 1) union all select a from t limit 1") - c.Assert(err, IsNil) - _, err = tk.Exec("(select a from t order by a) union all select a from t order by a") - c.Assert(err, IsNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t value(1),(2),(3)") - - tk.MustQuery("(select a from t order by a limit 2) union all (select a from t order by a desc limit 2) order by a desc limit 1,2").Check(testkit.Rows("2", "2")) - tk.MustQuery("select a from t union all select a from t order by a desc limit 5").Check(testkit.Rows("3", "3", "2", "2", "1")) - tk.MustQuery("(select a from t order by a desc limit 2) union all select a from t group by a order by a").Check(testkit.Rows("1", "2", "2", "3", "3")) - tk.MustQuery("(select a from t order by a desc limit 2) union all select 33 as a order by a desc limit 2").Check(testkit.Rows("33", "3")) - - tk.MustQuery("select 1 union select 1 union all select 1").Check(testkit.Rows("1", "1")) - tk.MustQuery("select 1 union all select 1 union select 1").Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t1, t2") - tk.MustExec(`create table t1(a bigint, b bigint);`) - tk.MustExec(`create table t2(a bigint, b bigint);`) - tk.MustExec(`insert into t1 values(1, 1);`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t2 values(1, 1);`) - tk.MustExec(`set @@tidb_init_chunk_size=2;`) - tk.MustExec(`set @@sql_mode="";`) - tk.MustQuery(`select count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("128")) - tk.MustQuery(`select tmp.a, count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("1 128")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int)") - tk.MustExec("insert into t value(1 ,2)") - tk.MustQuery("select a, b from (select a, 0 as d, b from t union all select a, 0 as d, b from t) test;").Check(testkit.Rows("1 2", "1 2")) - - // #issue 8141 - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(a int, b int)") - tk.MustExec("insert into t1 value(1,2),(1,1),(2,2),(2,2),(3,2),(3,2)") - tk.MustExec("set @@tidb_init_chunk_size=2;") - tk.MustQuery("select count(*) from (select a as c, a as d from t1 union all select a, b from t1) t;").Check(testkit.Rows("12")) - - // #issue 8189 and #issue 8199 - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") - tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") - tk.MustExec("insert into t2 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustQuery("select a from t1 union select a from t1 order by (select a+1);").Check(testkit.Rows("1", "2", "3")) - - // #issue 8201 - for i := 0; i < 4; i++ { - tk.MustQuery("SELECT(SELECT 0 AS a FROM dual UNION SELECT 1 AS a FROM dual ORDER BY a ASC LIMIT 1) AS dev").Check(testkit.Rows("0")) - } - - // #issue 8231 - tk.MustExec("drop table if exists t1") - tk.MustExec("CREATE TABLE t1 (uid int(1))") - tk.MustExec("INSERT INTO t1 SELECT 150") - tk.MustQuery("SELECT 'a' UNION SELECT uid FROM t1 order by 1 desc;").Check(testkit.Rows("a", "150")) - - // #issue 8196 - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") - tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") - tk.MustExec("insert into t2 values(3,'c'),(4,'d'),(5,'f'),(6,'e')") - tk.MustExec("analyze table t1") - tk.MustExec("analyze table t2") - _, err = tk.Exec("(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b") - c.Assert(err.Error(), Equals, "[planner:1250]Table 't1' from one of the SELECTs cannot be used in global ORDER clause") - - // #issue 9900 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b decimal(6, 3))") - tk.MustExec("insert into t values(1, 1.000)") - tk.MustQuery("select count(distinct a), sum(distinct a), avg(distinct a) from (select a from t union all select b from t) tmp;").Check(testkit.Rows("1 1.000 1.0000000")) - - // #issue 23832 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a bit(20), b float, c double, d int)") - tk.MustExec("insert into t values(10, 10, 10, 10), (1, -1, 2, -2), (2, -2, 1, 1), (2, 1.1, 2.1, 10.1)") - tk.MustQuery("select a from t union select 10 order by a").Check(testkit.Rows("1", "2", "10")) -} - -func (s *testSuite2) TestUnionLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists union_limit") - tk.MustExec("create table union_limit (id int) partition by hash(id) partitions 30") - for i := 0; i < 60; i++ { - tk.MustExec(fmt.Sprintf("insert into union_limit values (%d)", i)) - } - // Cover the code for worker count limit in the union executor. - tk.MustQuery("select * from union_limit limit 10") -} - -func (s *testSuiteP2) TestToPBExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values (1.1, 1.1)") - tk.MustExec("insert t values (2.4, 2.4)") - tk.MustExec("insert t values (3.3, 2.7)") - result := tk.MustQuery("select * from t where a < 2.399999") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where a > 1.5") - result.Check(testkit.Rows("2.400000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where a <= 1.1") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where b >= 3") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where not (b = 1)") - result.Check(testkit.Rows("2.400000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where b&1 = a|1") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where b != 2 and b <=> 3") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where b in (3)") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where b not in (1, 2)") - result.Check(testkit.Rows("3.300000 3")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a varchar(255), b int)") - tk.MustExec("insert t values ('abc123', 1)") - tk.MustExec("insert t values ('ab123', 2)") - result = tk.MustQuery("select * from t where a like 'ab%'") - result.Check(testkit.Rows("abc123 1", "ab123 2")) - result = tk.MustQuery("select * from t where a like 'ab_12'") - result.Check(nil) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key)") - tk.MustExec("insert t values (1)") - tk.MustExec("insert t values (2)") - result = tk.MustQuery("select * from t where not (a = 1)") - result.Check(testkit.Rows("2")) - result = tk.MustQuery("select * from t where not(not (a = 1))") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select * from t where not(a != 1 and a != 2)") - result.Check(testkit.Rows("1", "2")) -} - -func (s *testSuiteP2) TestDatumXAPI(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values (1.1, 1.1)") - tk.MustExec("insert t values (2.2, 2.2)") - tk.MustExec("insert t values (3.3, 2.7)") - result := tk.MustQuery("select * from t where a > 1.5") - result.Check(testkit.Rows("2.200000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where b > 1.5") - result.Check(testkit.Rows("2.200000 2", "3.300000 3")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a time(3), b time, index idx_a (a))") - tk.MustExec("insert t values ('11:11:11', '11:11:11')") - tk.MustExec("insert t values ('11:11:12', '11:11:12')") - tk.MustExec("insert t values ('11:11:13', '11:11:13')") - result = tk.MustQuery("select * from t where a > '11:11:11.5'") - result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) - result = tk.MustQuery("select * from t where b > '11:11:11.5'") - result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) -} - -func (s *testSuiteP2) TestSQLMode(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a tinyint not null)") - tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") - _, err := tk.Exec("insert t values ()") - c.Check(err, NotNil) - - _, err = tk.Exec("insert t values ('1000')") - c.Check(err, NotNil) - - tk.MustExec("create table if not exists tdouble (a double(3,2))") - _, err = tk.Exec("insert tdouble values (10.23)") - c.Check(err, NotNil) - - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values ()") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value")) - tk.MustExec("insert t values (null)") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert ignore t values (null)") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert t select null") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert t values (1000)") - tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "0", "127")) - - tk.MustExec("insert tdouble values (10.23)") - tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99")) - - tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") - tk.MustExec("set @@global.sql_mode = ''") - - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - tk2.MustExec("drop table if exists t2") - tk2.MustExec("create table t2 (a varchar(3))") - tk2.MustExec("insert t2 values ('abcd')") - tk2.MustQuery("select * from t2").Check(testkit.Rows("abc")) - - // session1 is still in strict mode. - _, err = tk.Exec("insert t2 values ('abcd')") - c.Check(err, NotNil) - // Restore original global strict mode. - tk.MustExec("set @@global.sql_mode = 'STRICT_TRANS_TABLES'") -} - -func (s *testSuiteP2) TestTableDual(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - result := tk.MustQuery("Select 1") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select 1 from dual") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select count(*) from dual") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select 1 from dual where 1") - result.Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int primary key)") - tk.MustQuery("select t1.* from t t1, t t2 where t1.a=t2.a and 1=0").Check(testkit.Rows()) -} - -func (s *testSuiteP2) TestTableScan(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use information_schema") - result := tk.MustQuery("select * from schemata") - // There must be these tables: information_schema, mysql, performance_schema and test. - c.Assert(len(result.Rows()), GreaterEqual, 4) - tk.MustExec("use test") - tk.MustExec("create database mytest") - rowStr1 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mysql", "utf8mb4", "utf8mb4_bin", nil, nil) - rowStr2 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mytest", "utf8mb4", "utf8mb4_bin", nil, nil) - tk.MustExec("use information_schema") - result = tk.MustQuery("select * from schemata where schema_name = 'mysql'") - result.Check(testkit.Rows(rowStr1)) - result = tk.MustQuery("select * from schemata where schema_name like 'my%'") - result.Check(testkit.Rows(rowStr1, rowStr2)) - result = tk.MustQuery("select 1 from tables limit 1") - result.Check(testkit.Rows("1")) -} - -func (s *testSuiteP2) TestAdapterStatement(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) - se.GetSessionVars().TxnCtx.InfoSchema = domain.GetDomain(se).InfoSchema() - compiler := &executor.Compiler{Ctx: se} - stmtNode, err := s.ParseOneStmt("select 1", "", "") - c.Check(err, IsNil) - stmt, err := compiler.Compile(context.TODO(), stmtNode) - c.Check(err, IsNil) - c.Check(stmt.OriginText(), Equals, "select 1") - - stmtNode, err = s.ParseOneStmt("create table test.t (a int)", "", "") - c.Check(err, IsNil) - stmt, err = compiler.Compile(context.TODO(), stmtNode) - c.Check(err, IsNil) - c.Check(stmt.OriginText(), Equals, "create table test.t (a int)") -} - -func (s *testSuiteP2) TestIsPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use mysql") - ctx := tk.Se.(sessionctx.Context) - tests := map[string]bool{ - "select * from help_topic where name='aaa'": false, - "select 1 from help_topic where name='aaa'": false, - "select * from help_topic where help_topic_id=1": true, - "select * from help_topic where help_category_id=1": false, - } - - for sqlStr, result := range tests { - stmtNode, err := s.ParseOneStmt(sqlStr, "", "") - c.Check(err, IsNil) - preprocessorReturn := &plannercore.PreprocessorReturn{} - err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) - c.Check(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) - c.Check(err, IsNil) - ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) - c.Assert(err, IsNil) - c.Assert(ret, Equals, result) - } -} - -func (s *testSuiteP2) TestClusteredIndexIsPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_cluster_index_is_point_get;") - tk.MustExec("create database test_cluster_index_is_point_get;") - tk.MustExec("use test_cluster_index_is_point_get;") - - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a varchar(255), b int, c char(10), primary key (c, a));") - ctx := tk.Se.(sessionctx.Context) - - tests := map[string]bool{ - "select 1 from t where a='x'": false, - "select * from t where c='x'": false, - "select * from t where a='x' and c='x'": true, - "select * from t where a='x' and c='x' and b=1": false, - } - for sqlStr, result := range tests { - stmtNode, err := s.ParseOneStmt(sqlStr, "", "") - c.Check(err, IsNil) - preprocessorReturn := &plannercore.PreprocessorReturn{} - err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) - c.Check(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) - c.Check(err, IsNil) - ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) - c.Assert(err, IsNil) - c.Assert(ret, Equals, result) - } -} - -func (s *testSuiteP2) TestRow(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c int, d int)") - tk.MustExec("insert t values (1, 1)") - tk.MustExec("insert t values (1, 3)") - tk.MustExec("insert t values (2, 1)") - tk.MustExec("insert t values (2, 3)") - result := tk.MustQuery("select * from t where (c, d) < (2,2)") - result.Check(testkit.Rows("1 1", "1 3", "2 1")) - result = tk.MustQuery("select * from t where (1,2,3) > (3,2,1)") - result.Check(testkit.Rows()) - result = tk.MustQuery("select * from t where row(1,2,3) > (3,2,1)") - result.Check(testkit.Rows()) - result = tk.MustQuery("select * from t where (c, d) = (select * from t where (c,d) = (1,1))") - result.Check(testkit.Rows("1 1")) - result = tk.MustQuery("select * from t where (c, d) = (select * from t k where (t.c,t.d) = (c,d))") - result.Check(testkit.Rows("1 1", "1 3", "2 1", "2 3")) - result = tk.MustQuery("select (1, 2, 3) < (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 3)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 1, 4)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (2, 3, 4) >= (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) = (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) != (2, 3, 4)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select row(1, 1) in (row(1, 1))") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 0) in (row(1, 1))") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select row(1, 1) in (select 1, 1)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 1) > row(1, 0)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 1) > (select 1, 0)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select 1 > (select 1)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (select 1)") - result.Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int)") - tk.MustExec("insert t1 values (1,2),(1,null)") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2 (c int, d int)") - tk.MustExec("insert t2 values (0,0)") - - tk.MustQuery("select * from t2 where (1,2) in (select * from t1)").Check(testkit.Rows("0 0")) - tk.MustQuery("select * from t2 where (1,2) not in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (1,1) not in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (1,null) in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (null,null) in (select * from t1)").Check(testkit.Rows()) - - tk.MustExec("delete from t1 where a=1 and b=2") - tk.MustQuery("select (1,1) in (select * from t2) from t1").Check(testkit.Rows("0")) - tk.MustQuery("select (1,1) not in (select * from t2) from t1").Check(testkit.Rows("1")) - tk.MustQuery("select (1,1) in (select 1,1 from t2) from t1").Check(testkit.Rows("1")) - tk.MustQuery("select (1,1) not in (select 1,1 from t2) from t1").Check(testkit.Rows("0")) - - // MySQL 5.7 returns 1 for these 2 queries, which is wrong. - tk.MustQuery("select (1,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) - tk.MustQuery("select (t1.a,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) - - tk.MustQuery("select (1,null) in (select * from t1)").Check(testkit.Rows("")) - tk.MustQuery("select (1,null) not in (select * from t1)").Check(testkit.Rows("")) -} - -func (s *testSuiteP2) TestColumnName(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c int, d int)") - // disable only full group by - tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") - rs, err := tk.Exec("select 1 + c, count(*) from t") - c.Check(err, IsNil) - fields := rs.Fields() - c.Check(len(fields), Equals, 2) - c.Check(fields[0].Column.Name.L, Equals, "1 + c") - c.Check(fields[0].ColumnAsName.L, Equals, "1 + c") - c.Check(fields[1].Column.Name.L, Equals, "count(*)") - c.Check(fields[1].ColumnAsName.L, Equals, "count(*)") - c.Assert(rs.Close(), IsNil) - rs, err = tk.Exec("select (c) > all (select c from t) from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.L, Equals, "(c) > all (select c from t)") - c.Check(fields[0].ColumnAsName.L, Equals, "(c) > all (select c from t)") - c.Assert(rs.Close(), IsNil) - tk.MustExec("begin") - tk.MustExec("insert t values(1,1)") - rs, err = tk.Exec("select c d, d c from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(len(fields), Equals, 2) - c.Check(fields[0].Column.Name.L, Equals, "c") - c.Check(fields[0].ColumnAsName.L, Equals, "d") - c.Check(fields[1].Column.Name.L, Equals, "d") - c.Check(fields[1].ColumnAsName.L, Equals, "c") - c.Assert(rs.Close(), IsNil) - // Test case for query a column of a table. - // In this case, all attributes have values. - rs, err = tk.Exec("select c as a from t as t2") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(fields[0].Column.Name.L, Equals, "c") - c.Check(fields[0].ColumnAsName.L, Equals, "a") - c.Check(fields[0].Table.Name.L, Equals, "t") - c.Check(fields[0].TableAsName.L, Equals, "t2") - c.Check(fields[0].DBName.L, Equals, "test") - c.Assert(rs.Close(), IsNil) - // Test case for query a expression which only using constant inputs. - // In this case, the table, org_table and database attributes will all be empty. - rs, err = tk.Exec("select hour(1) as a from t as t2") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(fields[0].Column.Name.L, Equals, "a") - c.Check(fields[0].ColumnAsName.L, Equals, "a") - c.Check(fields[0].Table.Name.L, Equals, "") - c.Check(fields[0].TableAsName.L, Equals, "") - c.Check(fields[0].DBName.L, Equals, "") - c.Assert(rs.Close(), IsNil) - // Test case for query a column wrapped with parentheses and unary plus. - // In this case, the column name should be its original name. - rs, err = tk.Exec("select (c), (+c), +(c), +(+(c)), ++c from t") - c.Check(err, IsNil) - fields = rs.Fields() - for i := 0; i < 5; i++ { - c.Check(fields[i].Column.Name.L, Equals, "c") - c.Check(fields[i].ColumnAsName.L, Equals, "c") - } - c.Assert(rs.Close(), IsNil) - - // Test issue https://github.com/pingcap/tidb/issues/9639 . - // Both window function and expression appear in final result field. - tk.MustExec("set @@tidb_enable_window_function = 1") - rs, err = tk.Exec("select 1+1, row_number() over() num from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].Column.Name.L, Equals, "1+1") - c.Assert(fields[0].ColumnAsName.L, Equals, "1+1") - c.Assert(fields[1].Column.Name.L, Equals, "num") - c.Assert(fields[1].ColumnAsName.L, Equals, "num") - tk.MustExec("set @@tidb_enable_window_function = 0") - c.Assert(rs.Close(), IsNil) - - rs, err = tk.Exec("select if(1,c,c) from t;") - c.Check(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].Column.Name.L, Equals, "if(1,c,c)") - // It's a compatibility issue. Should be empty instead. - c.Assert(fields[0].ColumnAsName.L, Equals, "if(1,c,c)") - c.Assert(rs.Close(), IsNil) -} - -func (s *testSuiteP2) TestSelectVar(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (d int)") - tk.MustExec("insert into t values(1), (2), (1)") - // This behavior is different from MySQL. - result := tk.MustQuery("select @a, @a := d+1 from t") - result.Check(testkit.Rows(" 2", "2 3", "3 2")) - // Test for PR #10658. - tk.MustExec("select SQL_BIG_RESULT d from t group by d") - tk.MustExec("select SQL_SMALL_RESULT d from t group by d") - tk.MustExec("select SQL_BUFFER_RESULT d from t group by d") -} - -func (s *testSuiteP2) TestHistoryRead(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists history_read") - tk.MustExec("create table history_read (a int)") - tk.MustExec("insert history_read values (1)") - - // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. - safePointName := "tikv_gc_safe_point" - safePointValue := "20060102-15:04:05 -0700" - safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" - updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') - ON DUPLICATE KEY - UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) - tk.MustExec(updateSafePoint) - - // Set snapshot to a time before save point will fail. - _, err := tk.Exec("set @@tidb_snapshot = '2006-01-01 15:04:05.999999'") - c.Assert(terror.ErrorEqual(err, variable.ErrSnapshotTooOld), IsTrue, Commentf("err %v", err)) - // SnapshotTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - - // Setting snapshot to a time in the future will fail. (One day before the 2038 problem) - _, err = tk.Exec("set @@tidb_snapshot = '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") - // SnapshotTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - - curVer1, _ := s.store.CurrentVersion(kv.GlobalTxnScope) - time.Sleep(time.Millisecond) - snapshotTime := time.Now() - time.Sleep(time.Millisecond) - curVer2, _ := s.store.CurrentVersion(kv.GlobalTxnScope) - tk.MustExec("insert history_read values (2)") - tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) - tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") - ctx := tk.Se.(sessionctx.Context) - snapshotTS := ctx.GetSessionVars().SnapshotTS - c.Assert(snapshotTS, Greater, curVer1.Ver) - c.Assert(snapshotTS, Less, curVer2.Ver) - tk.MustQuery("select * from history_read").Check(testkit.Rows("1")) - _, err = tk.Exec("insert history_read values (2)") - c.Assert(err, NotNil) - _, err = tk.Exec("update history_read set a = 3 where a = 1") - c.Assert(err, NotNil) - _, err = tk.Exec("delete from history_read where a = 1") - c.Assert(err, NotNil) - tk.MustExec("set @@tidb_snapshot = ''") - tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) - tk.MustExec("insert history_read values (3)") - tk.MustExec("update history_read set a = 4 where a = 3") - tk.MustExec("delete from history_read where a = 1") - - time.Sleep(time.Millisecond) - snapshotTime = time.Now() - time.Sleep(time.Millisecond) - tk.MustExec("alter table history_read add column b int") - tk.MustExec("insert history_read values (8, 8), (9, 9)") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) - tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) - tsoStr := strconv.FormatUint(oracle.GoTimeToTS(snapshotTime), 10) - - tk.MustExec("set @@tidb_snapshot = '" + tsoStr + "'") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) - - tk.MustExec("set @@tidb_snapshot = ''") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) -} - -func (s *testSuite2) TestLowResolutionTSORead(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@autocommit=1") - tk.MustExec("use test") - tk.MustExec("drop table if exists low_resolution_tso") - tk.MustExec("create table low_resolution_tso(a int)") - tk.MustExec("insert low_resolution_tso values (1)") - - // enable low resolution tso - c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsFalse) - _, err := tk.Exec("set @@tidb_low_resolution_tso = 'on'") - c.Assert(err, IsNil) - c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsTrue) - - time.Sleep(3 * time.Second) - tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("1")) - _, err = tk.Exec("update low_resolution_tso set a = 2") - c.Assert(err, NotNil) - tk.MustExec("set @@tidb_low_resolution_tso = 'off'") - tk.MustExec("update low_resolution_tso set a = 2") - tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("2")) -} - -func (s *testSuite2) TestStaleReadFutureTime(c *C) { - tk := testkit.NewTestKit(c, s.store) - // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) - _, err := tk.Exec("set @@tx_read_ts = '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") - // TxnReadTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) -} - -func (s *testSuite3) TestYearTypeDeleteIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a YEAR, PRIMARY KEY(a));") - tk.MustExec("insert into t set a = '2151';") - tk.MustExec("delete from t;") - tk.MustExec("admin check table t") -} - -func (s *testSuite3) TestForSelectScopeInUnion(c *C) { - // A union B for update, the "for update" option belongs to union statement, so - // it should works on both A and B. - tk1 := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - tk1.MustExec("drop table if exists t") - tk1.MustExec("create table t(a int)") - tk1.MustExec("insert into t values (1)") - - tk1.MustExec("begin") - // 'For update' would act on the second select. - tk1.MustQuery("select 1 as a union select a from t for update") - - tk2.MustExec("use test") - tk2.MustExec("update t set a = a + 1") - - // As tk1 use select 'for update', it should detect conflict and fail. - _, err := tk1.Exec("commit") - c.Assert(err, NotNil) - - tk1.MustExec("begin") - tk1.MustQuery("select 1 as a union select a from t limit 5 for update") - tk1.MustQuery("select 1 as a union select a from t order by a for update") - - tk2.MustExec("update t set a = a + 1") - - _, err = tk1.Exec("commit") - c.Assert(err, NotNil) -} - -func (s *testSuite3) TestUnsignedDecimalOverflow(c *C) { - tests := []struct { - input interface{} - hasErr bool - err string - }{{ - -1, - true, - "Out of range value for column", - }, { - "-1.1e-1", - true, - "Out of range value for column", - }, { - -1.1, - true, - "Out of range value for column", - }, { - -0, - false, - "", - }, - } - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a decimal(10,2) unsigned)") - for _, t := range tests { - res, err := tk.Exec("insert into t values (?)", t.input) - if res != nil { - defer res.Close() - } - if t.hasErr { - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), t.err), IsTrue) - } else { - c.Assert(err, IsNil) - } - if res != nil { - c.Assert(res.Close(), IsNil) - } - } - - tk.MustExec("set sql_mode=''") - tk.MustExec("delete from t") - tk.MustExec("insert into t values (?)", -1) - r := tk.MustQuery("select a from t limit 1") - r.Check(testkit.Rows("0.00")) -} - -func (s *testSuite3) TestIndexJoinTableDualPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists a") - tk.MustExec("create table a (f1 int, f2 varchar(32), primary key (f1))") - tk.MustExec("insert into a (f1,f2) values (1,'a'), (2,'b'), (3,'c')") - // TODO here: index join cause the data race of txn. - tk.MustQuery("select /*+ inl_merge_join(a) */ a.* from a inner join (select 1 as k1,'k2-1' as k2) as k on a.f1=k.k1;"). - Check(testkit.Rows("1 a")) -} - -func (s *testSuite3) TestSortLeftJoinWithNullColumnInRightChildPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1(a int)") - tk.MustExec("create table t2(a int)") - tk.MustExec("insert into t1(a) select 1;") - tk.MustQuery("select b.n from t1 left join (select a as a, null as n from t2) b on b.a = t1.a order by t1.a"). - Check(testkit.Rows("")) -} - -func (s *testSuite3) TestMaxOneRow(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t1`) - tk.MustExec(`drop table if exists t2`) - tk.MustExec(`create table t1(a double, b double);`) - tk.MustExec(`create table t2(a double, b double);`) - tk.MustExec(`insert into t1 values(1, 1), (2, 2), (3, 3);`) - tk.MustExec(`insert into t2 values(0, 0);`) - tk.MustExec(`set @@tidb_init_chunk_size=1;`) - rs, err := tk.Exec(`select (select t1.a from t1 where t1.a > t2.a) as a from t2;`) - c.Assert(err, IsNil) - - err = rs.Next(context.TODO(), rs.NewChunk(nil)) - c.Assert(err.Error(), Equals, "[executor:1242]Subquery returns more than 1 row") - - c.Assert(rs.Close(), IsNil) -} - -func (s *testSuiteP2) TestCurrentTimestampValueSelection(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t,t1") - - tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))") - tk.MustExec("insert into t (id) values (1)") - rs := tk.MustQuery("select t0, t1, t2 from t where id = 1") - t0 := rs.Rows()[0][0].(string) - t1 := rs.Rows()[0][1].(string) - t2 := rs.Rows()[0][2].(string) - c.Assert(len(strings.Split(t0, ".")), Equals, 1) - c.Assert(len(strings.Split(t1, ".")[1]), Equals, 1) - c.Assert(len(strings.Split(t2, ".")[1]), Equals, 2) - tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1")) - tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1")) - tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1")) - time.Sleep(time.Second) - tk.MustExec("update t set t0 = now() where id = 1") - rs = tk.MustQuery("select t2 from t where id = 1") - newT2 := rs.Rows()[0][0].(string) - c.Assert(newT2 != t2, IsTrue) - - tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))") - tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))") - rs = tk.MustQuery("select a, b, c from t1 where id = 1") - a := rs.Rows()[0][0].(string) - b := rs.Rows()[0][1].(string) - d := rs.Rows()[0][2].(string) - c.Assert(len(strings.Split(a, ".")), Equals, 1) - c.Assert(strings.Split(b, ".")[1], Equals, "00") - c.Assert(len(strings.Split(d, ".")[1]), Equals, 3) -} - -func (s *testSuite3) TestRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - tk.MustExec(`create table t(a varchar(10), b varchar(10), c varchar(1), index idx(a, b, c));`) - tk.MustExec(`insert into t values('a', 'b', 'c');`) - tk.MustExec(`insert into t values('a', 'b', 'c');`) - tk.MustQuery(`select b, _tidb_rowid from t use index(idx) where a = 'a';`).Check(testkit.Rows( - `b 1`, - `b 2`, - )) - tk.MustExec(`begin;`) - tk.MustExec(`select * from t for update`) - tk.MustQuery(`select distinct b from t use index(idx) where a = 'a';`).Check(testkit.Rows(`b`)) - tk.MustExec(`commit;`) - - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t(a varchar(5) primary key)`) - tk.MustExec(`insert into t values('a')`) - tk.MustQuery("select *, _tidb_rowid from t use index(`primary`) where _tidb_rowid=1").Check(testkit.Rows("a 1")) -} - -func (s *testSuite3) TestDoSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t(a int)`) - _, err := tk.Exec(`do 1 in (select * from t)`) - c.Assert(err, IsNil, Commentf("err %v", err)) - tk.MustExec(`insert into t values(1)`) - r, err := tk.Exec(`do 1 in (select * from t)`) - c.Assert(err, IsNil, Commentf("err %v", err)) - c.Assert(r, IsNil, Commentf("result of Do not empty")) -} - -func (s *testSuite3) TestSubqueryTableAlias(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - - tk.MustExec("set sql_mode = ''") - tk.MustGetErrCode("select a, b from (select 1 a) ``, (select 2 b) ``;", mysql.ErrDerivedMustHaveAlias) - tk.MustGetErrCode("select a, b from (select 1 a) `x`, (select 2 b) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select a, b from (select 1 a), (select 2 b);", mysql.ErrDerivedMustHaveAlias) - // ambiguous column name - tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrDerivedMustHaveAlias) - tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrDerivedMustHaveAlias) - - tk.MustExec("set sql_mode = 'oracle';") - tk.MustQuery("select a, b from (select 1 a) ``, (select 2 b) ``;").Check(testkit.Rows("1 2")) - tk.MustQuery("select a, b from (select 1 a) `x`, (select 2 b) `x`;").Check(testkit.Rows("1 2")) - tk.MustQuery("select a, b from (select 1 a), (select 2 b);").Check(testkit.Rows("1 2")) - // ambiguous column name - tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrNonUniq) - tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) - tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) - tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrNonUniq) -} - -func (s *testSuite3) TestSelectHashPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists th`) - tk.MustExec("set @@session.tidb_enable_table_partition = '1';") - tk.MustExec(`create table th (a int, b int) partition by hash(a) partitions 3;`) - defer tk.MustExec(`drop table if exists th`) - tk.MustExec(`insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);`) - tk.MustExec("insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8);") - tk.MustQuery("select b from th order by a").Check(testkit.Rows("-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8")) - tk.MustQuery(" select * from th where a=-2;").Check(testkit.Rows("-2 -2")) - tk.MustQuery(" select * from th where a=5;").Check(testkit.Rows("5 5")) -} - -func (s *testSuite) TestSelectView(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table view_t (a int,b int)") - tk.MustExec("insert into view_t values(1,2)") - tk.MustExec("create definer='root'@'localhost' view view1 as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view2(c,d) as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view3(c,d) as select a,b from view_t") - tk.MustExec("create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb;") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(c int,d int)") - err := tk.ExecToErr("select * from view1") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") - err = tk.ExecToErr("select * from view2") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") - err = tk.ExecToErr("select * from view3") - c.Assert(err.Error(), Equals, plannercore.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error()) - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(a int,b int,c int)") - tk.MustExec("insert into view_t values(1,2,3)") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("alter table view_t drop column a") - tk.MustExec("alter table view_t add column a int after b") - tk.MustExec("update view_t set a=1;") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("drop table view_t;") - tk.MustExec("drop view view1,view2,view3,view4;") - - tk.MustExec("set @@tidb_enable_window_function = 1") - defer func() { - tk.MustExec("set @@tidb_enable_window_function = 0") - }() - tk.MustExec("create table t(a int, b int)") - tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") - result := tk.MustQuery("select * from v") - result.Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) - tk.MustExec("drop view v;") -} - -type testSuite2 struct { - *baseTestSuite -} - -func (s *testSuite2) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -type testSuite3 struct { - *baseTestSuite -} - -func (s *testSuite3) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -func (s *testSuiteP2) TestStrToDateBuiltin(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%!') from dual`).Check(testkit.Rows("2019-01-01")) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) - tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('a18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('69/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('70/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) - tk.MustQuery(`select str_to_date('8/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) - tk.MustQuery(`select str_to_date('8/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) - tk.MustQuery(`select str_to_date('18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('a18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('69/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('70/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) - tk.MustQuery(`select str_to_date('018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("0018-10-22")) - tk.MustQuery(`select str_to_date('2018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('018/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18/10/22','%y0/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18/10/22','%Y0/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18a/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18a/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('20188/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018510522','%Y5%m5%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018^10^22','%Y^%m^%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018@10@22','%Y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018%10%22','%Y%%m%%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018(10(22','%Y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018\10\22','%Y\%m\%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018=10=22','%Y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018+10+22','%Y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018_10_22','%Y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('69510522','%y5%m5%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('69^10^22','%y^%m^%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('18@10@22','%y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18%10%22','%y%%m%%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18(10(22','%y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18\10\22','%y\%m\%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18+10+22','%y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18=10=22','%y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18_10_22','%y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 11:22:33 PM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 23:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33 AM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 00:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 12:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 00:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 00:22:33")) -} - -func (s *testSuiteP2) TestAddDateBuiltinWithWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") - result := tk.MustQuery(`select date_add('2001-01-00', interval -2 hour);`) - result.Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '2001-01-00'")) -} - -func (s *testSuiteP2) TestStrToDateBuiltinWithWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") - tk.MustExec("use test") - tk.MustQuery(`SELECT STR_TO_DATE('0000-1-01', '%Y-%m-%d');`).Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1411 Incorrect datetime value: '0000-1-01' for function str_to_date")) -} - -func (s *testSuiteP2) TestReadPartitionedTable(c *C) { - // Test three reader on partitioned table. - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists pt") - tk.MustExec("create table pt (a int, b int, index i_b(b)) partition by range (a) (partition p1 values less than (2), partition p2 values less than (4), partition p3 values less than (6))") - for i := 0; i < 6; i++ { - tk.MustExec(fmt.Sprintf("insert into pt values(%d, %d)", i, i)) - } - // Table reader - tk.MustQuery("select * from pt order by a").Check(testkit.Rows("0 0", "1 1", "2 2", "3 3", "4 4", "5 5")) - // Index reader - tk.MustQuery("select b from pt where b = 3").Check(testkit.Rows("3")) - // Index lookup - tk.MustQuery("select a from pt where b = 3").Check(testkit.Rows("3")) -} - -func (s *testSuiteP2) TestIssue10435(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(i int, j int, k int)") - tk.MustExec("insert into t1 VALUES (1,1,1),(2,2,2),(3,3,3),(4,4,4)") - tk.MustExec("INSERT INTO t1 SELECT 10*i,j,5*j FROM t1 UNION SELECT 20*i,j,5*j FROM t1 UNION SELECT 30*i,j,5*j FROM t1") - - tk.MustExec("set @@session.tidb_enable_window_function=1") - tk.MustQuery("SELECT SUM(i) OVER W FROM t1 WINDOW w AS (PARTITION BY j ORDER BY i) ORDER BY 1+SUM(i) OVER w").Check( - testkit.Rows("1", "2", "3", "4", "11", "22", "31", "33", "44", "61", "62", "93", "122", "124", "183", "244"), - ) -} - -func (s *testSuite) TestSummaryFailedUpdate(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int as(-a))") - tk.MustExec("insert into t(a) values(1), (3), (7)") - sm := &mockSessionManager1{ - PS: make([]*util.ProcessInfo, 0), - } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionCancel - }) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("set @@tidb_mem_quota_query=1") - err := tk.ExecToErr("update t set t.a = t.a - 1 where t.a in (select a from t where a < 4)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - tk.MustExec("set @@tidb_mem_quota_query=1000000000") - tk.MustQuery("select stmt_type from information_schema.statements_summary where digest_text = 'update `t` set `t` . `a` = `t` . `a` - ? where `t` . `a` in ( select `a` from `t` where `a` < ? )'").Check(testkit.Rows("Update")) -} diff --git a/executor/executor_pkg_test.go b/executor/executor_pkg_test.go index 053ec6c4230db..f8212dd6ff1ba 100644 --- a/executor/executor_pkg_test.go +++ b/executor/executor_pkg_test.go @@ -171,8 +171,13 @@ func buildSchema(names []string, ftypes []byte) *expression.Schema { tp = ftypes[0] } fieldType := types.NewFieldType(tp) - fieldType.Flen, fieldType.Decimal = mysql.GetDefaultFieldLengthAndDecimal(tp) - fieldType.Charset, fieldType.Collate = types.DefaultCharsetForType(tp) + flen, decimal := mysql.GetDefaultFieldLengthAndDecimal(tp) + fieldType.SetFlen(flen) + fieldType.SetDecimal(decimal) + + charset, collate := types.DefaultCharsetForType(tp) + fieldType.SetCharset(charset) + fieldType.SetCollate(collate) col.RetType = fieldType schema.Append(col) } @@ -433,13 +438,13 @@ func TestSortSpillDisk(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true - conf.MemQuotaQuery = 1 }) require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)")) defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill")) }() ctx := mock.NewContext() + ctx.GetSessionVars().MemQuota.MemQuotaQuery = 1 ctx.GetSessionVars().InitChunkSize = variable.DefMaxChunkSize ctx.GetSessionVars().MaxChunkSize = variable.DefMaxChunkSize ctx.GetSessionVars().StmtCtx.MemTracker = memory.NewTracker(-1, -1) diff --git a/executor/executor_required_rows_test.go b/executor/executor_required_rows_test.go index 8330a0f691876..54d10179c0d5c 100644 --- a/executor/executor_required_rows_test.go +++ b/executor/executor_required_rows_test.go @@ -22,7 +22,6 @@ import ( "testing" "time" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/parser/ast" @@ -35,6 +34,7 @@ import ( "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/disk" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" @@ -107,7 +107,7 @@ func (r *requiredRowsDataSource) genOneRow() chunk.Row { } func defaultGenerator(valType *types.FieldType) interface{} { - switch valType.Tp { + switch valType.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(rand.Int()) case mysql.TypeDouble: @@ -400,7 +400,7 @@ func TestSelectionRequiredRows(t *testing.T) { gen01 := func() func(valType *types.FieldType) interface{} { closureCount := 0 return func(valType *types.FieldType) interface{} { - switch valType.Tp { + switch valType.GetType() { case mysql.TypeLong, mysql.TypeLonglong: ret := int64(closureCount % 2) closureCount++ @@ -607,7 +607,7 @@ func divGenerator(factor int) func(valType *types.FieldType) interface{} { closureCountInt := 0 closureCountDouble := 0 return func(valType *types.FieldType) interface{} { - switch valType.Tp { + switch valType.GetType() { case mysql.TypeLong, mysql.TypeLonglong: ret := int64(closureCountInt / factor) closureCountInt++ @@ -683,7 +683,7 @@ func TestStreamAggRequiredRows(t *testing.T) { func TestMergeJoinRequiredRows(t *testing.T) { justReturn1 := func(valType *types.FieldType) interface{} { - switch valType.Tp { + switch valType.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(1) case mysql.TypeDouble: @@ -757,7 +757,7 @@ func genTestChunk4VecGroupChecker(chkRows []int, sameNum int) (expr []expression expr = make([]expression.Expression, 1) expr[0] = &expression.Column{ - RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flen: mysql.MaxIntWidth}, + RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlen(mysql.MaxIntWidth).BuildP(), Index: 0, } return @@ -846,7 +846,7 @@ func buildMergeJoinExec(ctx sessionctx.Context, joinType plannercore.JoinType, i j.CompareFuncs = append(j.CompareFuncs, expression.GetCmpFunction(nil, j.LeftJoinKeys[i], j.RightJoinKeys[i])) } - b := newExecutorBuilder(ctx, nil, nil, 0, false, oracle.GlobalTxnScope) + b := newExecutorBuilder(ctx, nil, nil, oracle.GlobalTxnScope) return b.build(j) } @@ -870,7 +870,7 @@ func TestVecGroupCheckerDATARACE(t *testing.T) { for _, mType := range mTypes { exprs := make([]expression.Expression, 1) exprs[0] = &expression.Column{ - RetType: &types.FieldType{Tp: mType}, + RetType: types.NewFieldTypeBuilderP().SetType(mType).BuildP(), Index: 0, } vgc := newVecGroupChecker(ctx, exprs) diff --git a/executor/executor_test.go b/executor/executor_test.go index 44b6be5eac64e..36d6801296506 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -28,31 +28,38 @@ import ( "time" "github.com/golang/protobuf/proto" + "github.com/pingcap/errors" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/planner" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" error2 "github.com/pingcap/tidb/store/driver/error" + "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/mock" @@ -60,6 +67,8 @@ import ( "github.com/pingcap/tidb/util/timeutil" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" + "github.com/tikv/client-go/v2/testutils" ) func checkFileName(s string) bool { @@ -3145,7 +3154,7 @@ func TestIssue19148(t *testing.T) { is := domain.GetDomain(tk.Session()).InfoSchema() tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) require.NoError(t, err) - require.Zero(t, tblInfo.Meta().Columns[0].Flag) + require.Zero(t, tblInfo.Meta().Columns[0].GetFlag()) } func TestIssue19667(t *testing.T) { @@ -3458,7 +3467,7 @@ func TestUnreasonablyClose(t *testing.T) { &plannercore.PhysicalShuffle{}, &plannercore.PhysicalUnionAll{}, } - executorBuilder := executor.NewMockExecutorBuilderForTest(tk.Session(), is, nil, math.MaxUint64, false, "global") + executorBuilder := executor.NewMockExecutorBuilderForTest(tk.Session(), is, nil, oracle.GlobalTxnScope) opsNeedsCoveredMask := uint64(1<", row[10]) + + // Test the START_TIME and END_TIME field. + tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) + re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") + row = re.Rows()[0] + createTime, err := types.ParseDatetime(nil, row[8].(string)) + require.NoError(t, err) + startTime, err := types.ParseDatetime(nil, row[9].(string)) + require.NoError(t, err) + endTime, err := types.ParseDatetime(nil, row[10].(string)) + require.NoError(t, err) + tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) + re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") + row2 := re.Rows()[0] + require.NotEqual(t, row[8], row2[8]) + require.NotEqual(t, row[9], row2[9]) + require.NotEqual(t, row[10], row2[10]) + createTime2, err := types.ParseDatetime(nil, row2[8].(string)) + require.NoError(t, err) + startTime2, err := types.ParseDatetime(nil, row2[9].(string)) + require.NoError(t, err) + endTime2, err := types.ParseDatetime(nil, row2[10].(string)) + require.NoError(t, err) + loc, err := time.LoadLocation("Asia/Shanghai") + require.NoError(t, err) + loc2, err := time.LoadLocation("Europe/Amsterdam") + require.NoError(t, err) + tt, err := createTime.GoTime(loc) + require.NoError(t, err) + t2, err := createTime2.GoTime(loc2) + require.NoError(t, err) + require.Equal(t, t2.In(time.UTC), tt.In(time.UTC)) + tt, err = startTime.GoTime(loc) + require.NoError(t, err) + t2, err = startTime2.GoTime(loc2) + require.NoError(t, err) + require.Equal(t, t2.In(time.UTC), tt.In(time.UTC)) + tt, err = endTime.GoTime(loc) + require.NoError(t, err) + t2, err = endTime2.GoTime(loc2) + require.NoError(t, err) + require.Equal(t, t2.In(time.UTC), tt.In(time.UTC)) +} + +func TestAdminShowDDLJobsInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + // Test for issue: https://github.com/pingcap/tidb/issues/29915 + tk.MustExec("create placement policy x followers=4;") + tk.MustExec("create placement policy y " + + "PRIMARY_REGION=\"cn-east-1\" " + + "REGIONS=\"cn-east-1, cn-east-2\" " + + "FOLLOWERS=2") + tk.MustExec("create database if not exists test_admin_show_ddl_jobs") + tk.MustExec("use test_admin_show_ddl_jobs") + + tk.MustExec("create table t (a int);") + tk.MustExec("create table t1 (a int);") + + tk.MustExec("alter table t placement policy x;") + require.Equal(t, "alter table placement", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3]) + + tk.MustExec("rename table t to tt, t1 to tt1") + require.Equal(t, "rename tables", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3]) + + tk.MustExec("create table tt2 (c int) PARTITION BY RANGE (c) " + + "(PARTITION p0 VALUES LESS THAN (6)," + + "PARTITION p1 VALUES LESS THAN (11)," + + "PARTITION p2 VALUES LESS THAN (16)," + + "PARTITION p3 VALUES LESS THAN (21));") + tk.MustExec("alter table tt2 partition p0 placement policy y") + require.Equal(t, "alter table partition placement", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3]) + + tk.MustExec("alter table tt1 cache") + require.Equal(t, "alter table cache", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3]) + tk.MustExec("alter table tt1 nocache") + require.Equal(t, "alter table nocache", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3]) +} + +func TestAdminChecksumOfPartitionedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("USE test;") + tk.MustExec("DROP TABLE IF EXISTS admin_checksum_partition_test;") + tk.MustExec("CREATE TABLE admin_checksum_partition_test (a INT) PARTITION BY HASH(a) PARTITIONS 4;") + tk.MustExec("INSERT INTO admin_checksum_partition_test VALUES (1), (2);") + + r := tk.MustQuery("ADMIN CHECKSUM TABLE admin_checksum_partition_test;") + r.Check(testkit.Rows("test admin_checksum_partition_test 1 5 5")) +} + +func TestUnion2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + testSQL := `drop table if exists union_test; create table union_test(id int);` + tk.MustExec(testSQL) + + testSQL = `drop table if exists union_test;` + tk.MustExec(testSQL) + testSQL = `create table union_test(id int);` + tk.MustExec(testSQL) + testSQL = `insert union_test values (1),(2)` + tk.MustExec(testSQL) + + testSQL = `select * from (select id from union_test union select id from union_test) t order by id;` + r := tk.MustQuery(testSQL) + r.Check(testkit.Rows("1", "2")) + + r = tk.MustQuery("select 1 union all select 1") + r.Check(testkit.Rows("1", "1")) + + r = tk.MustQuery("select 1 union all select 1 union select 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1, 1") + r.Check(testkit.Rows("2")) + + r = tk.MustQuery("select id from union_test union all (select 1) order by id desc") + r.Check(testkit.Rows("2", "1", "1")) + + r = tk.MustQuery("select id as a from union_test union (select 1) order by a desc") + r.Check(testkit.Rows("2", "1")) + + r = tk.MustQuery(`select null as a union (select "abc") order by a`) + r.Check(testkit.Rows("", "abc")) + + r = tk.MustQuery(`select "abc" as a union (select 1) order by a`) + r.Check(testkit.Rows("1", "abc")) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c int, d int)") + tk.MustExec("insert t1 values (NULL, 1)") + tk.MustExec("insert t1 values (1, 1)") + tk.MustExec("insert t1 values (1, 2)") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2 (c int, d int)") + tk.MustExec("insert t2 values (1, 3)") + tk.MustExec("insert t2 values (1, 1)") + tk.MustExec("drop table if exists t3") + tk.MustExec("create table t3 (c int, d int)") + tk.MustExec("insert t3 values (3, 2)") + tk.MustExec("insert t3 values (4, 3)") + r = tk.MustQuery(`select sum(c1), c2 from (select c c1, d c2 from t1 union all select d c1, c c2 from t2 union all select c c1, d c2 from t3) x group by c2 order by c2`) + r.Check(testkit.Rows("5 1", "4 2", "4 3")) + + tk.MustExec("drop table if exists t1, t2, t3") + tk.MustExec("create table t1 (a int primary key)") + tk.MustExec("create table t2 (a int primary key)") + tk.MustExec("create table t3 (a int primary key)") + tk.MustExec("insert t1 values (7), (8)") + tk.MustExec("insert t2 values (1), (9)") + tk.MustExec("insert t3 values (2), (3)") + r = tk.MustQuery("select * from t1 union all select * from t2 union all (select * from t3) order by a limit 2") + r.Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (a int)") + tk.MustExec("create table t2 (a int)") + tk.MustExec("insert t1 values (2), (1)") + tk.MustExec("insert t2 values (3), (4)") + r = tk.MustQuery("select * from t1 union all (select * from t2) order by a limit 1") + r.Check(testkit.Rows("1")) + r = tk.MustQuery("select (select * from t1 where a != t.a union all (select * from t2 where a != t.a) order by a limit 1) from t1 t") + r.Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int unsigned primary key auto_increment, c1 int, c2 int, index c1_c2 (c1, c2))") + tk.MustExec("insert into t (c1, c2) values (1, 1)") + tk.MustExec("insert into t (c1, c2) values (1, 2)") + tk.MustExec("insert into t (c1, c2) values (2, 3)") + r = tk.MustQuery("select * from (select * from t where t.c1 = 1 union select * from t where t.id = 1) s order by s.id") + r.Check(testkit.Rows("1 1 1", "2 1 2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (f1 DATE)") + tk.MustExec("INSERT INTO t VALUES ('1978-11-26')") + r = tk.MustQuery("SELECT f1+0 FROM t UNION SELECT f1+0 FROM t") + r.Check(testkit.Rows("19781126")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a int, b int)") + tk.MustExec("INSERT INTO t VALUES ('1', '1')") + r = tk.MustQuery("select b from (SELECT * FROM t UNION ALL SELECT a, b FROM t order by a) t") + r.Check(testkit.Rows("1", "1")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a DECIMAL(4,2))") + tk.MustExec("INSERT INTO t VALUE(12.34)") + r = tk.MustQuery("SELECT 1 AS c UNION select a FROM t") + r.Sort().Check(testkit.Rows("1.00", "12.34")) + + // #issue3771 + r = tk.MustQuery("SELECT 'a' UNION SELECT CONCAT('a', -4)") + r.Sort().Check(testkit.Rows("a", "a-4")) + + // test race + tk.MustQuery("SELECT @x:=0 UNION ALL SELECT @x:=0 UNION ALL SELECT @x") + + // test field tp + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("CREATE TABLE t1 (a date)") + tk.MustExec("CREATE TABLE t2 (a date)") + tk.MustExec("SELECT a from t1 UNION select a FROM t2") + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` date DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // Move from session test. + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (c double);") + tk.MustExec("create table t2 (c double);") + tk.MustExec("insert into t1 value (73);") + tk.MustExec("insert into t2 value (930);") + // If set unspecified column flen to 0, it will cause bug in union. + // This test is used to prevent the bug reappear. + tk.MustQuery("select c from t1 union (select c from t2) order by c").Check(testkit.Rows("73", "930")) + + // issue 5703 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a date)") + tk.MustExec("insert into t value ('2017-01-01'), ('2017-01-02')") + r = tk.MustQuery("(select a from t where a < 0) union (select a from t where a > 0) order by a") + r.Check(testkit.Rows("2017-01-01", "2017-01-02")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t value(0),(0)") + tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1")) + tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10")) + tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10")) + tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4")) + + err := tk.ExecToErr("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp") + require.Error(t, err) + terr := errors.Cause(err).(*terror.Error) + require.Equal(t, errors.ErrCode(mysql.ErrWrongUsage), terr.Code()) + + err = tk.ExecToErr("select 1 from (select a from t order by a union all select a from t limit 1) tmp") + require.Error(t, err) + terr = errors.Cause(err).(*terror.Error) + require.Equal(t, errors.ErrCode(mysql.ErrWrongUsage), terr.Code()) + + _, err = tk.Exec("(select a from t order by a) union all select a from t limit 1 union all select a from t limit 1") + require.Truef(t, terror.ErrorEqual(err, plannercore.ErrWrongUsage), "err %v", err) + + _, err = tk.Exec("(select a from t limit 1) union all select a from t limit 1") + require.NoError(t, err) + _, err = tk.Exec("(select a from t order by a) union all select a from t order by a") + require.NoError(t, err) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t value(1),(2),(3)") + + tk.MustQuery("(select a from t order by a limit 2) union all (select a from t order by a desc limit 2) order by a desc limit 1,2").Check(testkit.Rows("2", "2")) + tk.MustQuery("select a from t union all select a from t order by a desc limit 5").Check(testkit.Rows("3", "3", "2", "2", "1")) + tk.MustQuery("(select a from t order by a desc limit 2) union all select a from t group by a order by a").Check(testkit.Rows("1", "2", "2", "3", "3")) + tk.MustQuery("(select a from t order by a desc limit 2) union all select 33 as a order by a desc limit 2").Check(testkit.Rows("33", "3")) + + tk.MustQuery("select 1 union select 1 union all select 1").Check(testkit.Rows("1", "1")) + tk.MustQuery("select 1 union all select 1 union select 1").Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec(`create table t1(a bigint, b bigint);`) + tk.MustExec(`create table t2(a bigint, b bigint);`) + tk.MustExec(`insert into t1 values(1, 1);`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t2 values(1, 1);`) + tk.MustExec(`set @@tidb_init_chunk_size=2;`) + tk.MustExec(`set @@sql_mode="";`) + tk.MustQuery(`select count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("128")) + tk.MustQuery(`select tmp.a, count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("1 128")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t value(1 ,2)") + tk.MustQuery("select a, b from (select a, 0 as d, b from t union all select a, 0 as d, b from t) test;").Check(testkit.Rows("1 2", "1 2")) + + // #issue 8141 + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("insert into t1 value(1,2),(1,1),(2,2),(2,2),(3,2),(3,2)") + tk.MustExec("set @@tidb_init_chunk_size=2;") + tk.MustQuery("select count(*) from (select a as c, a as d from t1 union all select a, b from t1) t;").Check(testkit.Rows("12")) + + // #issue 8189 and #issue 8199 + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") + tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") + tk.MustExec("insert into t2 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustQuery("select a from t1 union select a from t1 order by (select a+1);").Check(testkit.Rows("1", "2", "3")) + + // #issue 8201 + for i := 0; i < 4; i++ { + tk.MustQuery("SELECT(SELECT 0 AS a FROM dual UNION SELECT 1 AS a FROM dual ORDER BY a ASC LIMIT 1) AS dev").Check(testkit.Rows("0")) + } + + // #issue 8231 + tk.MustExec("drop table if exists t1") + tk.MustExec("CREATE TABLE t1 (uid int(1))") + tk.MustExec("INSERT INTO t1 SELECT 150") + tk.MustQuery("SELECT 'a' UNION SELECT uid FROM t1 order by 1 desc;").Check(testkit.Rows("a", "150")) + + // #issue 8196 + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") + tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") + tk.MustExec("insert into t2 values(3,'c'),(4,'d'),(5,'f'),(6,'e')") + tk.MustExec("analyze table t1") + tk.MustExec("analyze table t2") + _, err = tk.Exec("(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b") + require.Equal(t, "[planner:1250]Table 't1' from one of the SELECTs cannot be used in global ORDER clause", err.Error()) + + // #issue 9900 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b decimal(6, 3))") + tk.MustExec("insert into t values(1, 1.000)") + tk.MustQuery("select count(distinct a), sum(distinct a), avg(distinct a) from (select a from t union all select b from t) tmp;").Check(testkit.Rows("1 1.000 1.0000000")) + + // #issue 23832 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a bit(20), b float, c double, d int)") + tk.MustExec("insert into t values(10, 10, 10, 10), (1, -1, 2, -2), (2, -2, 1, 1), (2, 1.1, 2.1, 10.1)") + tk.MustQuery("select a from t union select 10 order by a").Check(testkit.Rows("1", "2", "10")) +} + +func TestUnionLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists union_limit") + tk.MustExec("create table union_limit (id int) partition by hash(id) partitions 30") + for i := 0; i < 60; i++ { + tk.MustExec(fmt.Sprintf("insert into union_limit values (%d)", i)) + } + // Cover the code for worker count limit in the union executor. + tk.MustQuery("select * from union_limit limit 10") +} + +func TestLowResolutionTSORead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@autocommit=1") + tk.MustExec("use test") + tk.MustExec("create table low_resolution_tso(a int)") + tk.MustExec("insert low_resolution_tso values (1)") + + // enable low resolution tso + require.False(t, tk.Session().GetSessionVars().LowResolutionTSO) + tk.MustExec("set @@tidb_low_resolution_tso = 'on'") + require.True(t, tk.Session().GetSessionVars().LowResolutionTSO) + + time.Sleep(3 * time.Second) + tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("1")) + err := tk.ExecToErr("update low_resolution_tso set a = 2") + require.Error(t, err) + tk.MustExec("set @@tidb_low_resolution_tso = 'off'") + tk.MustExec("update low_resolution_tso set a = 2") + tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("2")) +} + +func TestStaleReadAtFutureTime(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) + tk.MustGetErrMsg("set @@tx_read_ts = '2038-01-18 03:14:07'", "cannot set read timestamp to a future time") + // TxnReadTS Is not updated if check failed. + require.Zero(t, tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) +} + +func TestYearTypeDeleteIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a YEAR, PRIMARY KEY(a));") + tk.MustExec("insert into t set a = '2151';") + tk.MustExec("delete from t;") + tk.MustExec("admin check table t") +} + +func TestToPBExpr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values (1.1, 1.1)") + tk.MustExec("insert t values (2.4, 2.4)") + tk.MustExec("insert t values (3.3, 2.7)") + result := tk.MustQuery("select * from t where a < 2.399999") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where a > 1.5") + result.Check(testkit.Rows("2.400000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where a <= 1.1") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where b >= 3") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where not (b = 1)") + result.Check(testkit.Rows("2.400000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where b&1 = a|1") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where b != 2 and b <=> 3") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where b in (3)") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where b not in (1, 2)") + result.Check(testkit.Rows("3.300000 3")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a varchar(255), b int)") + tk.MustExec("insert t values ('abc123', 1)") + tk.MustExec("insert t values ('ab123', 2)") + result = tk.MustQuery("select * from t where a like 'ab%'") + result.Check(testkit.Rows("abc123 1", "ab123 2")) + result = tk.MustQuery("select * from t where a like 'ab_12'") + result.Check(nil) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int primary key)") + tk.MustExec("insert t values (1)") + tk.MustExec("insert t values (2)") + result = tk.MustQuery("select * from t where not (a = 1)") + result.Check(testkit.Rows("2")) + result = tk.MustQuery("select * from t where not(not (a = 1))") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select * from t where not(a != 1 and a != 2)") + result.Check(testkit.Rows("1", "2")) +} + +func TestDatumXAPI(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values (1.1, 1.1)") + tk.MustExec("insert t values (2.2, 2.2)") + tk.MustExec("insert t values (3.3, 2.7)") + result := tk.MustQuery("select * from t where a > 1.5") + result.Check(testkit.Rows("2.200000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where b > 1.5") + result.Check(testkit.Rows("2.200000 2", "3.300000 3")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a time(3), b time, index idx_a (a))") + tk.MustExec("insert t values ('11:11:11', '11:11:11')") + tk.MustExec("insert t values ('11:11:12', '11:11:12')") + tk.MustExec("insert t values ('11:11:13', '11:11:13')") + result = tk.MustQuery("select * from t where a > '11:11:11.5'") + result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) + result = tk.MustQuery("select * from t where b > '11:11:11.5'") + result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) +} + +func TestSQLMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a tinyint not null)") + tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") + _, err := tk.Exec("insert t values ()") + require.Error(t, err) + + _, err = tk.Exec("insert t values ('1000')") + require.Error(t, err) + + tk.MustExec("create table if not exists tdouble (a double(3,2))") + _, err = tk.Exec("insert tdouble values (10.23)") + require.Error(t, err) + + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values ()") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value")) + tk.MustExec("insert t values (null)") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert ignore t values (null)") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert t select null") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert t values (1000)") + tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "0", "127")) + + tk.MustExec("insert tdouble values (10.23)") + tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99")) + + tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") + tk.MustExec("set @@global.sql_mode = ''") + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("drop table if exists t2") + tk2.MustExec("create table t2 (a varchar(3))") + tk2.MustExec("insert t2 values ('abcd')") + tk2.MustQuery("select * from t2").Check(testkit.Rows("abc")) + + // session1 is still in strict mode. + _, err = tk.Exec("insert t2 values ('abcd')") + require.Error(t, err) + // Restore original global strict mode. + tk.MustExec("set @@global.sql_mode = 'STRICT_TRANS_TABLES'") +} + +func TestTableDual(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + result := tk.MustQuery("Select 1") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select 1 from dual") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select count(*) from dual") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select 1 from dual where 1") + result.Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int primary key)") + tk.MustQuery("select t1.* from t t1, t t2 where t1.a=t2.a and 1=0").Check(testkit.Rows()) +} + +func TestTableScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use information_schema") + result := tk.MustQuery("select * from schemata") + // There must be these tables: information_schema, mysql, performance_schema and test. + require.GreaterOrEqual(t, len(result.Rows()), 4) + tk.MustExec("use test") + tk.MustExec("create database mytest") + rowStr1 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mysql", "utf8mb4", "utf8mb4_bin", nil, nil) + rowStr2 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mytest", "utf8mb4", "utf8mb4_bin", nil, nil) + tk.MustExec("use information_schema") + result = tk.MustQuery("select * from schemata where schema_name = 'mysql'") + result.Check(testkit.Rows(rowStr1)) + result = tk.MustQuery("select * from schemata where schema_name like 'my%'") + result.Check(testkit.Rows(rowStr1, rowStr2)) + result = tk.MustQuery("select 1 from tables limit 1") + result.Check(testkit.Rows("1")) +} + +func TestAdapterStatement(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.Session().GetSessionVars().TxnCtx.InfoSchema = domain.GetDomain(tk.Session()).InfoSchema() + compiler := &executor.Compiler{Ctx: tk.Session()} + s := parser.New() + stmtNode, err := s.ParseOneStmt("select 1", "", "") + require.NoError(t, err) + stmt, err := compiler.Compile(context.TODO(), stmtNode) + require.NoError(t, err) + require.Equal(t, "select 1", stmt.OriginText()) + + stmtNode, err = s.ParseOneStmt("create table test.t (a int)", "", "") + require.NoError(t, err) + stmt, err = compiler.Compile(context.TODO(), stmtNode) + require.NoError(t, err) + require.Equal(t, "create table test.t (a int)", stmt.OriginText()) +} + +func TestIsPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql") + ctx := tk.Session().(sessionctx.Context) + tests := map[string]bool{ + "select * from help_topic where name='aaa'": false, + "select 1 from help_topic where name='aaa'": false, + "select * from help_topic where help_topic_id=1": true, + "select * from help_topic where help_category_id=1": false, + } + s := parser.New() + for sqlStr, result := range tests { + stmtNode, err := s.ParseOneStmt(sqlStr, "", "") + require.NoError(t, err) + preprocessorReturn := &plannercore.PreprocessorReturn{} + err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) + require.NoError(t, err) + ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) + require.NoError(t, err) + require.Equal(t, result, ret) + } +} + +func TestClusteredIndexIsPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists test_cluster_index_is_point_get;") + tk.MustExec("create database test_cluster_index_is_point_get;") + tk.MustExec("use test_cluster_index_is_point_get;") + + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a varchar(255), b int, c char(10), primary key (c, a));") + ctx := tk.Session().(sessionctx.Context) + + tests := map[string]bool{ + "select 1 from t where a='x'": false, + "select * from t where c='x'": false, + "select * from t where a='x' and c='x'": true, + "select * from t where a='x' and c='x' and b=1": false, + } + s := parser.New() + for sqlStr, result := range tests { + stmtNode, err := s.ParseOneStmt(sqlStr, "", "") + require.NoError(t, err) + preprocessorReturn := &plannercore.PreprocessorReturn{} + err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) + require.NoError(t, err) + ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) + require.NoError(t, err) + require.Equal(t, result, ret) + } +} + +func TestRow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c int, d int)") + tk.MustExec("insert t values (1, 1)") + tk.MustExec("insert t values (1, 3)") + tk.MustExec("insert t values (2, 1)") + tk.MustExec("insert t values (2, 3)") + result := tk.MustQuery("select * from t where (c, d) < (2,2)") + result.Check(testkit.Rows("1 1", "1 3", "2 1")) + result = tk.MustQuery("select * from t where (1,2,3) > (3,2,1)") + result.Check(testkit.Rows()) + result = tk.MustQuery("select * from t where row(1,2,3) > (3,2,1)") + result.Check(testkit.Rows()) + result = tk.MustQuery("select * from t where (c, d) = (select * from t where (c,d) = (1,1))") + result.Check(testkit.Rows("1 1")) + result = tk.MustQuery("select * from t where (c, d) = (select * from t k where (t.c,t.d) = (c,d))") + result.Check(testkit.Rows("1 1", "1 3", "2 1", "2 3")) + result = tk.MustQuery("select (1, 2, 3) < (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 3)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 1, 4)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (2, 3, 4) >= (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) = (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) != (2, 3, 4)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select row(1, 1) in (row(1, 1))") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 0) in (row(1, 1))") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select row(1, 1) in (select 1, 1)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 1) > row(1, 0)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 1) > (select 1, 0)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select 1 > (select 1)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (select 1)") + result.Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("insert t1 values (1,2),(1,null)") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2 (c int, d int)") + tk.MustExec("insert t2 values (0,0)") + + tk.MustQuery("select * from t2 where (1,2) in (select * from t1)").Check(testkit.Rows("0 0")) + tk.MustQuery("select * from t2 where (1,2) not in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (1,1) not in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (1,null) in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (null,null) in (select * from t1)").Check(testkit.Rows()) + + tk.MustExec("delete from t1 where a=1 and b=2") + tk.MustQuery("select (1,1) in (select * from t2) from t1").Check(testkit.Rows("0")) + tk.MustQuery("select (1,1) not in (select * from t2) from t1").Check(testkit.Rows("1")) + tk.MustQuery("select (1,1) in (select 1,1 from t2) from t1").Check(testkit.Rows("1")) + tk.MustQuery("select (1,1) not in (select 1,1 from t2) from t1").Check(testkit.Rows("0")) + + // MySQL 5.7 returns 1 for these 2 queries, which is wrong. + tk.MustQuery("select (1,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) + tk.MustQuery("select (t1.a,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) + + tk.MustQuery("select (1,null) in (select * from t1)").Check(testkit.Rows("")) + tk.MustQuery("select (1,null) not in (select * from t1)").Check(testkit.Rows("")) +} + +func TestColumnName(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c int, d int)") + // disable only full group by + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") + rs, err := tk.Exec("select 1 + c, count(*) from t") + require.NoError(t, err) + fields := rs.Fields() + require.Len(t, fields, 2) + require.Equal(t, "1 + c", fields[0].Column.Name.L) + require.Equal(t, "1 + c", fields[0].ColumnAsName.L) + require.Equal(t, "count(*)", fields[1].Column.Name.L) + require.Equal(t, "count(*)", fields[1].ColumnAsName.L) + require.NoError(t, rs.Close()) + rs, err = tk.Exec("select (c) > all (select c from t) from t") + require.NoError(t, err) + fields = rs.Fields() + require.Len(t, fields, 1) + require.Equal(t, "(c) > all (select c from t)", fields[0].Column.Name.L) + require.Equal(t, "(c) > all (select c from t)", fields[0].ColumnAsName.L) + require.NoError(t, rs.Close()) + tk.MustExec("begin") + tk.MustExec("insert t values(1,1)") + rs, err = tk.Exec("select c d, d c from t") + require.NoError(t, err) + fields = rs.Fields() + require.Len(t, fields, 2) + require.Equal(t, "c", fields[0].Column.Name.L) + require.Equal(t, "d", fields[0].ColumnAsName.L) + require.Equal(t, "d", fields[1].Column.Name.L) + require.Equal(t, "c", fields[1].ColumnAsName.L) + require.NoError(t, rs.Close()) + // Test case for query a column of a table. + // In this case, all attributes have values. + rs, err = tk.Exec("select c as a from t as t2") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "c", fields[0].Column.Name.L) + require.Equal(t, "a", fields[0].ColumnAsName.L) + require.Equal(t, "t", fields[0].Table.Name.L) + require.Equal(t, "t2", fields[0].TableAsName.L) + require.Equal(t, "test", fields[0].DBName.L) + require.Nil(t, rs.Close()) + // Test case for query a expression which only using constant inputs. + // In this case, the table, org_table and database attributes will all be empty. + rs, err = tk.Exec("select hour(1) as a from t as t2") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "a", fields[0].Column.Name.L) + require.Equal(t, "a", fields[0].ColumnAsName.L) + require.Equal(t, "", fields[0].Table.Name.L) + require.Equal(t, "", fields[0].TableAsName.L) + require.Equal(t, "", fields[0].DBName.L) + require.Nil(t, rs.Close()) + // Test case for query a column wrapped with parentheses and unary plus. + // In this case, the column name should be its original name. + rs, err = tk.Exec("select (c), (+c), +(c), +(+(c)), ++c from t") + require.NoError(t, err) + fields = rs.Fields() + for i := 0; i < 5; i++ { + require.Equal(t, "c", fields[i].Column.Name.L) + require.Equal(t, "c", fields[i].ColumnAsName.L) + } + require.Nil(t, rs.Close()) + + // Test issue https://github.com/pingcap/tidb/issues/9639 . + // Both window function and expression appear in final result field. + tk.MustExec("set @@tidb_enable_window_function = 1") + rs, err = tk.Exec("select 1+1, row_number() over() num from t") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "1+1", fields[0].Column.Name.L) + require.Equal(t, "1+1", fields[0].ColumnAsName.L) + require.Equal(t, "num", fields[1].Column.Name.L) + require.Equal(t, "num", fields[1].ColumnAsName.L) + tk.MustExec("set @@tidb_enable_window_function = 0") + require.Nil(t, rs.Close()) + + rs, err = tk.Exec("select if(1,c,c) from t;") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "if(1,c,c)", fields[0].Column.Name.L) + // It's a compatibility issue. Should be empty instead. + require.Equal(t, "if(1,c,c)", fields[0].ColumnAsName.L) + require.Nil(t, rs.Close()) +} + +func TestSelectVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (d int)") + tk.MustExec("insert into t values(1), (2), (1)") + // This behavior is different from MySQL. + result := tk.MustQuery("select @a, @a := d+1 from t") + result.Check(testkit.Rows(" 2", "2 3", "3 2")) + // Test for PR #10658. + tk.MustExec("select SQL_BIG_RESULT d from t group by d") + tk.MustExec("select SQL_SMALL_RESULT d from t group by d") + tk.MustExec("select SQL_BUFFER_RESULT d from t group by d") +} + +func TestHistoryRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists history_read") + tk.MustExec("create table history_read (a int)") + tk.MustExec("insert history_read values (1)") + + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20060102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + + // Set snapshot to a time before save point will fail. + _, err := tk.Exec("set @@tidb_snapshot = '2006-01-01 15:04:05.999999'") + require.True(t, terror.ErrorEqual(err, variable.ErrSnapshotTooOld), "err %v", err) + // SnapshotTS Is not updated if check failed. + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + + // Setting snapshot to a time in the future will fail. (One day before the 2038 problem) + _, err = tk.Exec("set @@tidb_snapshot = '2038-01-18 03:14:07'") + require.Regexp(t, "cannot set read timestamp to a future time", err) + // SnapshotTS Is not updated if check failed. + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + + curVer1, _ := store.CurrentVersion(kv.GlobalTxnScope) + time.Sleep(time.Millisecond) + snapshotTime := time.Now() + time.Sleep(time.Millisecond) + curVer2, _ := store.CurrentVersion(kv.GlobalTxnScope) + tk.MustExec("insert history_read values (2)") + tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) + tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") + ctx := tk.Session().(sessionctx.Context) + snapshotTS := ctx.GetSessionVars().SnapshotTS + require.Greater(t, snapshotTS, curVer1.Ver) + require.Less(t, snapshotTS, curVer2.Ver) + tk.MustQuery("select * from history_read").Check(testkit.Rows("1")) + _, err = tk.Exec("insert history_read values (2)") + require.Error(t, err) + _, err = tk.Exec("update history_read set a = 3 where a = 1") + require.Error(t, err) + _, err = tk.Exec("delete from history_read where a = 1") + require.Error(t, err) + tk.MustExec("set @@tidb_snapshot = ''") + tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) + tk.MustExec("insert history_read values (3)") + tk.MustExec("update history_read set a = 4 where a = 3") + tk.MustExec("delete from history_read where a = 1") + + time.Sleep(time.Millisecond) + snapshotTime = time.Now() + time.Sleep(time.Millisecond) + tk.MustExec("alter table history_read add column b int") + tk.MustExec("insert history_read values (8, 8), (9, 9)") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) + tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) + tsoStr := strconv.FormatUint(oracle.GoTimeToTS(snapshotTime), 10) + + tk.MustExec("set @@tidb_snapshot = '" + tsoStr + "'") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) + + tk.MustExec("set @@tidb_snapshot = ''") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) +} + +func TestCurrentTimestampValueSelection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t,t1") + + tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))") + tk.MustExec("insert into t (id) values (1)") + rs := tk.MustQuery("select t0, t1, t2 from t where id = 1") + t0 := rs.Rows()[0][0].(string) + t1 := rs.Rows()[0][1].(string) + t2 := rs.Rows()[0][2].(string) + require.Equal(t, 1, len(strings.Split(t0, "."))) + require.Equal(t, 1, len(strings.Split(t1, ".")[1])) + require.Equal(t, 2, len(strings.Split(t2, ".")[1])) + tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1")) + time.Sleep(time.Second) + tk.MustExec("update t set t0 = now() where id = 1") + rs = tk.MustQuery("select t2 from t where id = 1") + newT2 := rs.Rows()[0][0].(string) + require.True(t, newT2 != t2) + + tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))") + tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))") + rs = tk.MustQuery("select a, b, c from t1 where id = 1") + a := rs.Rows()[0][0].(string) + b := rs.Rows()[0][1].(string) + d := rs.Rows()[0][2].(string) + require.Equal(t, 1, len(strings.Split(a, "."))) + require.Equal(t, "00", strings.Split(b, ".")[1]) + require.Equal(t, 3, len(strings.Split(d, ".")[1])) +} + +func TestStrToDateBuiltin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%!') from dual`).Check(testkit.Rows("2019-01-01")) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) + tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('a18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('69/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('70/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) + tk.MustQuery(`select str_to_date('8/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) + tk.MustQuery(`select str_to_date('8/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) + tk.MustQuery(`select str_to_date('18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('a18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('69/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('70/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) + tk.MustQuery(`select str_to_date('018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("0018-10-22")) + tk.MustQuery(`select str_to_date('2018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('018/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18/10/22','%y0/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18/10/22','%Y0/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18a/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18a/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('20188/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018510522','%Y5%m5%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018^10^22','%Y^%m^%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018@10@22','%Y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018%10%22','%Y%%m%%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018(10(22','%Y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018\10\22','%Y\%m\%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018=10=22','%Y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018+10+22','%Y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018_10_22','%Y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('69510522','%y5%m5%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('69^10^22','%y^%m^%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('18@10@22','%y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18%10%22','%y%%m%%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18(10(22','%y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18\10\22','%y\%m\%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18+10+22','%y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18=10=22','%y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18_10_22','%y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 11:22:33 PM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 23:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33 AM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 00:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 12:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 00:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 00:22:33")) +} + +func TestAddDateBuiltinWithWarnings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") + result := tk.MustQuery(`select date_add('2001-01-00', interval -2 hour);`) + result.Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '2001-01-00'")) +} + +func TestStrToDateBuiltinWithWarnings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") + tk.MustExec("use test") + tk.MustQuery(`SELECT STR_TO_DATE('0000-1-01', '%Y-%m-%d');`).Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1411 Incorrect datetime value: '0000-1-01' for function str_to_date")) +} + +func TestReadPartitionedTable(t *testing.T) { + // Test three reader on partitioned table. + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists pt") + tk.MustExec("create table pt (a int, b int, index i_b(b)) partition by range (a) (partition p1 values less than (2), partition p2 values less than (4), partition p3 values less than (6))") + for i := 0; i < 6; i++ { + tk.MustExec(fmt.Sprintf("insert into pt values(%d, %d)", i, i)) + } + // Table reader + tk.MustQuery("select * from pt order by a").Check(testkit.Rows("0 0", "1 1", "2 2", "3 3", "4 4", "5 5")) + // Index reader + tk.MustQuery("select b from pt where b = 3").Check(testkit.Rows("3")) + // Index lookup + tk.MustQuery("select a from pt where b = 3").Check(testkit.Rows("3")) +} + +func TestIssue10435(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(i int, j int, k int)") + tk.MustExec("insert into t1 VALUES (1,1,1),(2,2,2),(3,3,3),(4,4,4)") + tk.MustExec("INSERT INTO t1 SELECT 10*i,j,5*j FROM t1 UNION SELECT 20*i,j,5*j FROM t1 UNION SELECT 30*i,j,5*j FROM t1") + + tk.MustExec("set @@session.tidb_enable_window_function=1") + tk.MustQuery("SELECT SUM(i) OVER W FROM t1 WINDOW w AS (PARTITION BY j ORDER BY i) ORDER BY 1+SUM(i) OVER w").Check( + testkit.Rows("1", "2", "3", "4", "11", "22", "31", "33", "44", "61", "62", "93", "122", "124", "183", "244"), + ) +} + +func TestAdmin(t *testing.T) { + var cluster testutils.Cluster + store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + })) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists admin_test") + tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1))") + tk.MustExec("insert admin_test (c1) values (1),(2),(NULL)") + + ctx := context.Background() + // cancel DDL jobs test + r, err := tk.Exec("admin cancel ddl jobs 1") + require.NoError(t, err) + req := r.NewChunk(nil) + err = r.Next(ctx, req) + require.NoError(t, err) + row := req.GetRow(0) + require.Equal(t, 2, row.Len()) + require.Equal(t, "1", row.GetString(0)) + require.Regexp(t, ".*DDL Job:1 not found", row.GetString(1)) + + // show ddl test; + r, err = tk.Exec("admin show ddl") + require.NoError(t, err) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + require.NoError(t, err) + row = req.GetRow(0) + require.Equal(t, 6, row.Len()) + txn, err := store.Begin() + require.NoError(t, err) + ddlInfo, err := admin.GetDDLInfo(txn) + require.NoError(t, err) + require.Equal(t, ddlInfo.SchemaVer, row.GetInt64(0)) + // TODO: Pass this test. + // rowOwnerInfos := strings.Split(row.Data[1].GetString(), ",") + // ownerInfos := strings.Split(ddlInfo.Owner.String(), ",") + // c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0]) + serverInfo, err := infosync.GetServerInfoByID(ctx, row.GetString(1)) + require.NoError(t, err) + require.Equal(t, serverInfo.IP+":"+strconv.FormatUint(uint64(serverInfo.Port), 10), row.GetString(2)) + require.Equal(t, "", row.GetString(3)) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + require.NoError(t, err) + require.Zero(t, req.NumRows()) + err = txn.Rollback() + require.NoError(t, err) + + // show DDL jobs test + r, err = tk.Exec("admin show ddl jobs") + require.NoError(t, err) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + require.NoError(t, err) + row = req.GetRow(0) + require.Equal(t, 12, row.Len()) + txn, err = store.Begin() + require.NoError(t, err) + historyJobs, err := admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) + require.Greater(t, len(historyJobs), 1) + require.Greater(t, len(row.GetString(1)), 0) + require.NoError(t, err) + require.Equal(t, historyJobs[0].ID, row.GetInt64(0)) + require.NoError(t, err) + + r, err = tk.Exec("admin show ddl jobs 20") + require.NoError(t, err) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + require.NoError(t, err) + row = req.GetRow(0) + require.Equal(t, 12, row.Len()) + require.Equal(t, historyJobs[0].ID, row.GetInt64(0)) + require.NoError(t, err) + + // show DDL job queries test + tk.MustExec("use test") + tk.MustExec("drop table if exists admin_test2") + tk.MustExec("create table admin_test2 (c1 int, c2 int, c3 int default 1, index (c1))") + result := tk.MustQuery(`admin show ddl job queries 1, 1, 1`) + result.Check(testkit.Rows()) + result = tk.MustQuery(`admin show ddl job queries 1, 2, 3, 4`) + result.Check(testkit.Rows()) + historyJobs, err = admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) + result = tk.MustQuery(fmt.Sprintf("admin show ddl job queries %d", historyJobs[0].ID)) + result.Check(testkit.Rows(historyJobs[0].Query)) + require.NoError(t, err) + + // check table test + tk.MustExec("create table admin_test1 (c1 int, c2 int default 1, index (c1))") + tk.MustExec("insert admin_test1 (c1) values (21),(22)") + r, err = tk.Exec("admin check table admin_test, admin_test1") + require.NoError(t, err) + require.Nil(t, r) + // error table name + require.Error(t, tk.ExecToErr("admin check table admin_test_error")) + // different index values + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + require.NotNil(t, is) + tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("admin_test")) + require.NoError(t, err) + require.Len(t, tb.Indices(), 1) + _, err = tb.Indices()[0].Create(mock.NewContext(), txn, types.MakeDatums(int64(10)), kv.IntHandle(1), nil) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + errAdmin := tk.ExecToErr("admin check table admin_test") + require.Error(t, errAdmin) + + if config.CheckTableBeforeDrop { + tk.MustGetErrMsg("drop table admin_test", errAdmin.Error()) + + // Drop inconsistency index. + tk.MustExec("alter table admin_test drop index c1") + tk.MustExec("admin check table admin_test") + } + // checksum table test + tk.MustExec("create table checksum_with_index (id int, count int, PRIMARY KEY(id), KEY(count))") + tk.MustExec("create table checksum_without_index (id int, count int, PRIMARY KEY(id))") + r, err = tk.Exec("admin checksum table checksum_with_index, checksum_without_index") + require.NoError(t, err) + res := tk.ResultSetToResult(r, "admin checksum table") + // Mocktikv returns 1 for every table/index scan, then we will xor the checksums of a table. + // For "checksum_with_index", we have two checksums, so the result will be 1^1 = 0. + // For "checksum_without_index", we only have one checksum, so the result will be 1. + res.Sort().Check(testkit.Rows("test checksum_with_index 0 2 2", "test checksum_without_index 1 1 1")) + + tk.MustExec("drop table if exists t1;") + tk.MustExec("CREATE TABLE t1 (c2 BOOL, PRIMARY KEY (c2));") + tk.MustExec("INSERT INTO t1 SET c2 = '0';") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c3 DATETIME NULL DEFAULT '2668-02-03 17:19:31';") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx2 (c3);") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c4 bit(10) default 127;") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx3 (c4);") + tk.MustExec("admin check table t1;") + + // Test admin show ddl jobs table name after table has been droped. + tk.MustExec("drop table if exists t1;") + re := tk.MustQuery("admin show ddl jobs 1") + rows := re.Rows() + require.Len(t, rows, 1) + require.Equal(t, "t1", rows[0][2]) + + // Test for reverse scan get history ddl jobs when ddl history jobs queue has multiple regions. + txn, err = store.Begin() + require.NoError(t, err) + historyJobs, err = admin.GetHistoryDDLJobs(txn, 20) + require.NoError(t, err) + + // Split region for history ddl job queues. + m := meta.NewMeta(txn) + startKey := meta.DDLJobHistoryKey(m, 0) + endKey := meta.DDLJobHistoryKey(m, historyJobs[0].ID) + cluster.SplitKeys(startKey, endKey, int(historyJobs[0].ID/5)) + + historyJobs2, err := admin.GetHistoryDDLJobs(txn, 20) + require.NoError(t, err) + require.Equal(t, historyJobs2, historyJobs) +} + +func TestForSelectScopeInUnion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + // A union B for update, the "for update" option belongs to union statement, so + // it should works on both A and B. + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec("drop table if exists t") + tk1.MustExec("create table t(a int)") + tk1.MustExec("insert into t values (1)") + + tk1.MustExec("begin") + // 'For update' would act on the second select. + tk1.MustQuery("select 1 as a union select a from t for update") + + tk2.MustExec("use test") + tk2.MustExec("update t set a = a + 1") + + // As tk1 use select 'for update', it should detect conflict and fail. + _, err := tk1.Exec("commit") + require.Error(t, err) + + tk1.MustExec("begin") + tk1.MustQuery("select 1 as a union select a from t limit 5 for update") + tk1.MustQuery("select 1 as a union select a from t order by a for update") + + tk2.MustExec("update t set a = a + 1") + + _, err = tk1.Exec("commit") + require.Error(t, err) +} + +func TestUnsignedDecimalOverflow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tests := []struct { + input interface{} + hasErr bool + err string + }{{ + -1, + true, + "Out of range value for column", + }, { + "-1.1e-1", + true, + "Out of range value for column", + }, { + -1.1, + true, + "Out of range value for column", + }, { + -0, + false, + "", + }, + } + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a decimal(10,2) unsigned)") + for _, test := range tests { + err := tk.ExecToErr("insert into t values (?)", test.input) + if test.hasErr { + require.Error(t, err) + require.Contains(t, err.Error(), test.err) + } else { + require.NoError(t, err) + } + } + + tk.MustExec("set sql_mode=''") + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?)", -1) + tk.MustQuery("select a from t limit 1").Check(testkit.Rows("0.00")) +} + +func TestIndexJoinTableDualPanic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists a") + tk.MustExec("create table a (f1 int, f2 varchar(32), primary key (f1))") + tk.MustExec("insert into a (f1,f2) values (1,'a'), (2,'b'), (3,'c')") + // TODO here: index join cause the data race of txn. + tk.MustQuery("select /*+ inl_merge_join(a) */ a.* from a inner join (select 1 as k1,'k2-1' as k2) as k on a.f1=k.k1;"). + Check(testkit.Rows("1 a")) +} + +func TestSortLeftJoinWithNullColumnInRightChildPanic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int)") + tk.MustExec("create table t2(a int)") + tk.MustExec("insert into t1(a) select 1;") + tk.MustQuery("select b.n from t1 left join (select a as a, null as n from t2) b on b.a = t1.a order by t1.a"). + Check(testkit.Rows("")) +} + +func TestMaxOneRow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t1`) + tk.MustExec(`drop table if exists t2`) + tk.MustExec(`create table t1(a double, b double);`) + tk.MustExec(`create table t2(a double, b double);`) + tk.MustExec(`insert into t1 values(1, 1), (2, 2), (3, 3);`) + tk.MustExec(`insert into t2 values(0, 0);`) + tk.MustExec(`set @@tidb_init_chunk_size=1;`) + rs, err := tk.Exec(`select (select t1.a from t1 where t1.a > t2.a) as a from t2;`) + require.NoError(t, err) + + err = rs.Next(context.TODO(), rs.NewChunk(nil)) + require.Error(t, err) + require.Equal(t, "[executor:1242]Subquery returns more than 1 row", err.Error()) + require.NoError(t, rs.Close()) +} + +func TestRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.MustExec(`create table t(a varchar(10), b varchar(10), c varchar(1), index idx(a, b, c));`) + tk.MustExec(`insert into t values('a', 'b', 'c');`) + tk.MustExec(`insert into t values('a', 'b', 'c');`) + tk.MustQuery(`select b, _tidb_rowid from t use index(idx) where a = 'a';`).Check(testkit.Rows( + `b 1`, + `b 2`, + )) + tk.MustExec(`begin;`) + tk.MustExec(`select * from t for update`) + tk.MustQuery(`select distinct b from t use index(idx) where a = 'a';`).Check(testkit.Rows(`b`)) + tk.MustExec(`commit;`) + + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a varchar(5) primary key)`) + tk.MustExec(`insert into t values('a')`) + tk.MustQuery("select *, _tidb_rowid from t use index(`primary`) where _tidb_rowid=1").Check(testkit.Rows("a 1")) +} + +func TestDoSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int)`) + tk.MustExec(`do 1 in (select * from t)`) + tk.MustExec(`insert into t values(1)`) + r, err := tk.Exec(`do 1 in (select * from t)`) + require.NoError(t, err) + require.Nil(t, r) +} + +func TestSubqueryTableAlias(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + + tk.MustExec("set sql_mode = ''") + tk.MustGetErrCode("select a, b from (select 1 a) ``, (select 2 b) ``;", mysql.ErrDerivedMustHaveAlias) + tk.MustGetErrCode("select a, b from (select 1 a) `x`, (select 2 b) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select a, b from (select 1 a), (select 2 b);", mysql.ErrDerivedMustHaveAlias) + // ambiguous column name + tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrDerivedMustHaveAlias) + tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrDerivedMustHaveAlias) + + tk.MustExec("set sql_mode = 'oracle';") + tk.MustQuery("select a, b from (select 1 a) ``, (select 2 b) ``;").Check(testkit.Rows("1 2")) + tk.MustQuery("select a, b from (select 1 a) `x`, (select 2 b) `x`;").Check(testkit.Rows("1 2")) + tk.MustQuery("select a, b from (select 1 a), (select 2 b);").Check(testkit.Rows("1 2")) + // ambiguous column name + tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrNonUniq) + tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) + tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) + tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrNonUniq) +} + +func TestSelectHashPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists th`) + tk.MustExec("set @@session.tidb_enable_table_partition = '1';") + tk.MustExec(`create table th (a int, b int) partition by hash(a) partitions 3;`) + defer tk.MustExec(`drop table if exists th`) + tk.MustExec(`insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);`) + tk.MustExec("insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8);") + tk.MustQuery("select b from th order by a").Check(testkit.Rows("-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8")) + tk.MustQuery(" select * from th where a=-2;").Check(testkit.Rows("-2 -2")) + tk.MustQuery(" select * from th where a=5;").Check(testkit.Rows("5 5")) +} + +func TestSelectView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table view_t (a int,b int)") + tk.MustExec("insert into view_t values(1,2)") + tk.MustExec("create definer='root'@'localhost' view view1 as select * from view_t") + tk.MustExec("create definer='root'@'localhost' view view2(c,d) as select * from view_t") + tk.MustExec("create definer='root'@'localhost' view view3(c,d) as select a,b from view_t") + tk.MustExec("create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb;") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("drop table view_t;") + tk.MustExec("create table view_t(c int,d int)") + tk.MustGetErrMsg("select * from view1", "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + tk.MustGetErrMsg("select * from view2", "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + tk.MustGetErrMsg("select * from view3", plannercore.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error()) + tk.MustExec("drop table view_t;") + tk.MustExec("create table view_t(a int,b int,c int)") + tk.MustExec("insert into view_t values(1,2,3)") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("alter table view_t drop column a") + tk.MustExec("alter table view_t add column a int after b") + tk.MustExec("update view_t set a=1;") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("drop table view_t;") + tk.MustExec("drop view view1,view2,view3,view4;") + + tk.MustExec("set @@tidb_enable_window_function = 1") + defer func() { + tk.MustExec("set @@tidb_enable_window_function = 0") + }() + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") + result := tk.MustQuery("select * from v") + result.Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) + tk.MustExec("drop view v;") +} + +func TestSummaryFailedUpdate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int as(-a))") + tk.MustExec("insert into t(a) values(1), (3), (7)") + sm := &testkit.MockSessionManager{ + PS: make([]*util.ProcessInfo, 0), + } + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionCancel + }) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("set @@tidb_mem_quota_query=1") + tk.MustMatchErrMsg("update t set t.a = t.a - 1 where t.a in (select a from t where a < 4)", "Out Of Memory Quota!.*") + tk.MustExec("set @@tidb_mem_quota_query=1000000000") + tk.MustQuery("select stmt_type from information_schema.statements_summary where digest_text = 'update `t` set `t` . `a` = `t` . `a` - ? where `t` . `a` in ( select `a` from `t` where `a` < ? )'").Check(testkit.Rows("Update")) +} + +func TestIsFastPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int primary key, a int)") + + cases := []struct { + sql string + isFastPlan bool + }{ + {"select a from t where id=1", true}, + {"select a+id from t where id=1", true}, + {"select 1", true}, + {"select @@autocommit", true}, + {"set @@autocommit=1", true}, + {"set @a=1", true}, + {"select * from t where a=1", false}, + {"select * from t", false}, + } + + for _, ca := range cases { + if strings.HasPrefix(ca.sql, "select") { + tk.MustQuery(ca.sql) + } else { + tk.MustExec(ca.sql) + } + info := tk.Session().ShowProcess() + require.NotNil(t, info) + p, ok := info.Plan.(plannercore.Plan) + require.True(t, ok) + ok = executor.IsFastPlan(p) + require.Equal(t, ca.isFastPlan, ok) + } +} diff --git a/executor/explain.go b/executor/explain.go index 9871c291929e4..57d4261cf6745 100644 --- a/executor/explain.go +++ b/executor/explain.go @@ -17,10 +17,10 @@ package executor import ( "context" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) // ExplainExec represents an explain executor. diff --git a/executor/explainfor_test.go b/executor/explainfor_test.go index a80d34756fa69..54e49d194a22c 100644 --- a/executor/explainfor_test.go +++ b/executor/explainfor_test.go @@ -16,7 +16,6 @@ package executor_test import ( "bytes" - "crypto/tls" "fmt" "math" "strconv" @@ -25,7 +24,6 @@ import ( "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" @@ -33,48 +31,6 @@ import ( "github.com/stretchr/testify/require" ) -// mockSessionManager is a mocked session manager which is used for test. -type mockSessionManager1 struct { - PS []*util.ProcessInfo -} - -func (msm *mockSessionManager1) ShowTxnList() []*txninfo.TxnInfo { - return nil -} - -// ShowProcessList implements the SessionManager.ShowProcessList interface. -func (msm *mockSessionManager1) ShowProcessList() map[uint64]*util.ProcessInfo { - ret := make(map[uint64]*util.ProcessInfo) - for _, item := range msm.PS { - ret[item.ID] = item - } - return ret -} - -func (msm *mockSessionManager1) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) { - for _, item := range msm.PS { - if item.ID == id { - return item, true - } - } - return &util.ProcessInfo{}, false -} - -func (msm *mockSessionManager1) StoreInternalSession(se interface{}) { -} - -func (msm *mockSessionManager1) DeleteInternalSession(se interface{}) { -} - -func (msm *mockSessionManager1) GetInternalSessionStartTSList() []uint64 { - return nil -} - -func (msm *mockSessionManager1) Kill(_ uint64, _ bool) {} -func (msm *mockSessionManager1) KillAllConnections() {} -func (msm *mockSessionManager1) UpdateTLSConfig(_ *tls.Config) {} -func (msm *mockSessionManager1) ServerID() uint64 { return 1 } - func TestExplainFor(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -94,8 +50,8 @@ func TestExplainFor(t *testing.T) { tkRoot.MustQuery("select * from t1;") tkRootProcess := tkRoot.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) - tkUser.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + tkUser.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tkRoot.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Check(testkit.Rows( "TableReader_5 10000.00 root data:TableFullScan_4", "└─TableFullScan_4 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", @@ -104,8 +60,8 @@ func TestExplainFor(t *testing.T) { check := func() { tkRootProcess = tkRoot.Session().ShowProcess() ps = []*util.ProcessInfo{tkRootProcess} - tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) - tkUser.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + tkUser.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows := tkRoot.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Rows() require.Len(t, rows, 2) require.Len(t, rows[0], 9) @@ -136,7 +92,7 @@ func TestExplainFor(t *testing.T) { tkRootProcess.Plan = nil ps = []*util.ProcessInfo{tkRootProcess} - tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tkRoot.MustExec(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)) } @@ -153,8 +109,8 @@ func TestExplainForVerbose(t *testing.T) { tk.MustQuery("select * from t1;") tkRootProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + tk2.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rs := tk.MustQuery("explain format = 'verbose' select * from t1").Rows() rs2 := tk2.MustQuery(fmt.Sprintf("explain format = 'verbose' for connection %d", tkRootProcess.ID)).Rows() @@ -169,8 +125,8 @@ func TestExplainForVerbose(t *testing.T) { tk.MustQuery("select * from t2;") tkRootProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkRootProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + tk2.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rs = tk.MustQuery("explain format = 'verbose' select * from t2").Rows() rs2 = tk2.MustQuery(fmt.Sprintf("explain format = 'verbose' for connection %d", tkRootProcess.ID)).Rows() require.Len(t, rs, len(rs2)) @@ -202,8 +158,8 @@ func TestIssue11124(t *testing.T) { tk.MustQuery("select t1.id from kankan1 t1 left join kankan2 t2 on t1.id = t2.id where (case when t1.name='b' then 'case2' when t1.name='a' then 'case1' else NULL end) = 'case1'") tkRootProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + tk2.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rs := tk.MustQuery("explain select t1.id from kankan1 t1 left join kankan2 t2 on t1.id = t2.id where (case when t1.name='b' then 'case2' when t1.name='a' then 'case1' else NULL end) = 'case1'").Rows() rs2 := tk2.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Rows() @@ -317,7 +273,7 @@ func TestExplainForConnPlanCache(t *testing.T) { // single test tk1.MustExec(executeQuery) - tk2.Session().SetSessionManager(&mockSessionManager1{ + tk2.Session().SetSessionManager(&testkit.MockSessionManager{ PS: []*util.ProcessInfo{tk1.Session().ShowProcess()}, }) tk2.MustQuery(explainQuery).Check(explainResult) @@ -337,7 +293,7 @@ func TestExplainForConnPlanCache(t *testing.T) { wg.Run(func() { for i := 0; i < repeats; i++ { - tk2.Session().SetSessionManager(&mockSessionManager1{ + tk2.Session().SetSessionManager(&testkit.MockSessionManager{ PS: []*util.ProcessInfo{tk1.Session().ShowProcess()}, }) tk2.MustQuery(explainQuery).Check(explainResult) @@ -395,7 +351,7 @@ func TestExplainDotForExplainPlan(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain format=\"dot\" for connection %s", connID)).Check(nil) } @@ -412,7 +368,7 @@ func TestExplainDotForQuery(t *testing.T) { tk.MustQuery("select 1") tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) expected := tk2.MustQuery("explain format=\"dot\" select 1").Rows() got := tk.MustQuery(fmt.Sprintf("explain format=\"dot\" for connection %s", connID)).Rows() @@ -541,7 +497,7 @@ func TestPointGetUserVarPlanCache(t *testing.T) { )) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use idx_a `Projection_9 1.00 root test.t1.a, test.t1.b, test.t2.a, test.t2.b`, `└─IndexJoin_17 1.00 root inner join, inner:TableReader_13, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)`, @@ -557,7 +513,7 @@ func TestPointGetUserVarPlanCache(t *testing.T) { )) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use idx_a `Projection_9 1.00 root test.t1.a, test.t1.b, test.t2.a, test.t2.b`, `└─IndexJoin_17 1.00 root inner join, inner:TableReader_13, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)`, @@ -598,7 +554,7 @@ func TestExpressionIndexPreparePlanCache(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 4) require.Regexp(t, ".*expression_index.*", res.Rows()[2][3]) @@ -642,7 +598,7 @@ func TestIssue28259(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 3) require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) @@ -654,7 +610,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 4) require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) @@ -678,7 +634,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 5) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -692,7 +648,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 5) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -724,7 +680,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 6) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -739,7 +695,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 6) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -768,7 +724,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 5) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -783,7 +739,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 5) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -814,7 +770,7 @@ func TestIssue28259(t *testing.T) { tk.MustQuery("execute stmt using @a,@b;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 4) require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) @@ -852,7 +808,7 @@ func TestIssue28696(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 6) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -910,7 +866,7 @@ func TestIndexMerge4PlanCache(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 7) require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) @@ -930,7 +886,7 @@ func TestIndexMerge4PlanCache(t *testing.T) { tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Len(t, res.Rows(), 6) require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) @@ -951,7 +907,7 @@ func TestIndexMerge4PlanCache(t *testing.T) { tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Regexp(t, ".*IndexMerge.*", res.Rows()[1][0]) @@ -960,7 +916,7 @@ func TestIndexMerge4PlanCache(t *testing.T) { tk.MustQuery("execute stmt using @b;").Check(testkit.Rows("3 ddcdsaf 3")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Regexp(t, ".*IndexMerge.*", res.Rows()[1][0]) @@ -1152,7 +1108,7 @@ func TestSPM4PlanCache(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Regexp(t, ".*TableReader.*", res.Rows()[0][0]) require.Regexp(t, ".*TableFullScan.*", res.Rows()[1][0]) @@ -1170,7 +1126,7 @@ func TestSPM4PlanCache(t *testing.T) { tk.MustQuery("execute stmt;").Check(testkit.Rows()) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) // We can use the new binding. require.Regexp(t, ".*IndexReader.*", res.Rows()[0][0]) diff --git a/executor/grant.go b/executor/grant.go index cbe15b2c350d0..e64c25c53745c 100644 --- a/executor/grant.go +++ b/executor/grant.go @@ -739,11 +739,11 @@ func getTablePriv(ctx sessionctx.Context, name string, host string, db string, t return "", "", errors.Errorf("get table privilege fail for %s %s %s %s", name, host, db, tbl) } row := rows[0] - if fields[0].Column.Tp == mysql.TypeSet { + if fields[0].Column.GetType() == mysql.TypeSet { tablePriv := row.GetSet(0) tPriv = tablePriv.Name } - if fields[1].Column.Tp == mysql.TypeSet { + if fields[1].Column.GetType() == mysql.TypeSet { columnPriv := row.GetSet(1) cPriv = columnPriv.Name } @@ -765,7 +765,7 @@ func getColumnPriv(ctx sessionctx.Context, name string, host string, db string, return "", errors.Errorf("get column privilege fail for %s %s %s %s %s", name, host, db, tbl, col) } cPriv := "" - if fields[0].Column.Tp == mysql.TypeSet { + if fields[0].Column.GetType() == mysql.TypeSet { setVal := rows[0].GetSet(0) cPriv = setVal.Name } diff --git a/executor/hash_table.go b/executor/hash_table.go index 5476c5901e4f1..f4439d6cd7bac 100644 --- a/executor/hash_table.go +++ b/executor/hash_table.go @@ -20,6 +20,7 @@ import ( "hash/fnv" "sync/atomic" "time" + "unsafe" "github.com/pingcap/errors" "github.com/pingcap/tidb/sessionctx" @@ -29,6 +30,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/disk" "github.com/pingcap/tidb/util/execdetails" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/memory" ) @@ -83,6 +85,7 @@ type hashRowContainer struct { hashTable baseHashTable rowContainer *chunk.RowContainer + memTracker *memory.Tracker } func newHashRowContainer(sCtx sessionctx.Context, estCount int, hCtx *hashContext, allTypes []*types.FieldType) *hashRowContainer { @@ -94,7 +97,9 @@ func newHashRowContainer(sCtx sessionctx.Context, estCount int, hCtx *hashContex stat: new(hashStatistic), hashTable: newConcurrentMapHashTable(), rowContainer: rc, + memTracker: memory.NewTracker(memory.LabelForRowContainer, -1), } + rc.GetMemTracker().AttachTo(c.GetMemTracker()) return c } @@ -186,6 +191,7 @@ func (c *hashRowContainer) PutChunkSelected(chk *chunk.Chunk, selected, ignoreNu rowPtr := chunk.RowPtr{ChkIdx: chkIdx, RowIdx: uint32(i)} c.hashTable.Put(key, rowPtr) } + c.GetMemTracker().Consume(c.hashTable.GetAndCleanMemoryDelta()) return nil } @@ -219,7 +225,7 @@ func (c *hashRowContainer) Close() error { } // GetMemTracker returns the underlying memory usage tracker in hashRowContainer. -func (c *hashRowContainer) GetMemTracker() *memory.Tracker { return c.rowContainer.GetMemTracker() } +func (c *hashRowContainer) GetMemTracker() *memory.Tracker { return c.memTracker } // GetDiskTracker returns the underlying disk usage tracker in hashRowContainer. func (c *hashRowContainer) GetDiskTracker() *disk.Tracker { return c.rowContainer.GetDiskTracker() } @@ -251,7 +257,7 @@ func newEntryStore() *entryStore { return es } -func (es *entryStore) GetStore() (e *entry) { +func (es *entryStore) GetStore() (e *entry, memDelta int64) { sliceIdx := uint32(len(es.slices) - 1) slice := es.slices[sliceIdx] if es.cursor >= cap(slice) { @@ -263,6 +269,7 @@ func (es *entryStore) GetStore() (e *entry) { es.slices = append(es.slices, slice) sliceIdx++ es.cursor = 0 + memDelta = int64(unsafe.Sizeof(entry{})) * int64(size) } e = &es.slices[sliceIdx][es.cursor] es.cursor++ @@ -273,6 +280,9 @@ type baseHashTable interface { Put(hashKey uint64, rowPtr chunk.RowPtr) Get(hashKey uint64) (rowPtrs []chunk.RowPtr) Len() uint64 + // GetAndCleanMemoryDelta gets and cleans the memDelta of the baseHashTable. Memory delta will be cleared after each fetch. + // It indicates the memory delta of the baseHashTable since the last calling GetAndCleanMemoryDelta(). + GetAndCleanMemoryDelta() int64 } // TODO (fangzhuhe) remove unsafeHashTable later if it not used anymore @@ -283,6 +293,9 @@ type unsafeHashTable struct { hashMap map[uint64]*entry entryStore *entryStore length uint64 + + bInMap int64 // indicate there are 2^bInMap buckets in hashMap + memDelta int64 // the memory delta of the unsafeHashTable since the last calling GetAndCleanMemoryDelta() } // newUnsafeHashTable creates a new unsafeHashTable. estCount means the estimated size of the hashMap. @@ -297,11 +310,16 @@ func newUnsafeHashTable(estCount int) *unsafeHashTable { // Put puts the key/rowPtr pairs to the unsafeHashTable, multiple rowPtrs are stored in a list. func (ht *unsafeHashTable) Put(hashKey uint64, rowPtr chunk.RowPtr) { oldEntry := ht.hashMap[hashKey] - newEntry := ht.entryStore.GetStore() + newEntry, memDelta := ht.entryStore.GetStore() newEntry.ptr = rowPtr newEntry.next = oldEntry ht.hashMap[hashKey] = newEntry + if len(ht.hashMap) > (1< 0) + require.Equal(t, spill, rowContainer.rowContainer.GetMemTracker().BytesConsumed() == 0) + require.Equal(t, !spill, rowContainer.rowContainer.GetMemTracker().BytesConsumed() > 0) + require.True(t, rowContainer.GetMemTracker().BytesConsumed() > 0) // hashtable need memory if rowContainer.alreadySpilledSafeForTest() { require.NotNil(t, rowContainer.GetDiskTracker()) require.True(t, rowContainer.GetDiskTracker().BytesConsumed() > 0) @@ -162,3 +165,19 @@ func testHashRowContainer(t *testing.T, hashFunc func() hash.Hash64, spill bool) require.Equal(t, chk1.GetRow(1).GetDatumRow(colTypes), matched[1].GetDatumRow(colTypes)) return rowContainer, copiedRC } + +func TestConcurrentMapHashTableMemoryUsage(t *testing.T) { + m := newConcurrentMapHashTable() + const iterations = 1024 * hack.LoadFactorNum / hack.LoadFactorDen // 6656 + wg := &sync.WaitGroup{} + wg.Add(2) + // Note: Now concurrentMapHashTable doesn't support inserting in parallel. + for i := 0; i < iterations; i++ { + // Add entry to map. + m.Put(uint64(i*ShardCount), chunk.RowPtr{ChkIdx: uint32(i), RowIdx: uint32(i)}) + } + mapMemoryExpected := int64(1024) * hack.DefBucketMemoryUsageForMapIntToPtr + entryMemoryExpected := 16 * int64(64+128+256+512+1024+2048+4096) + require.Equal(t, mapMemoryExpected+entryMemoryExpected, m.GetAndCleanMemoryDelta()) + require.Equal(t, int64(0), m.GetAndCleanMemoryDelta()) +} diff --git a/executor/index_lookup_join.go b/executor/index_lookup_join.go index 994385566dde3..6961a22a5c8ab 100644 --- a/executor/index_lookup_join.go +++ b/executor/index_lookup_join.go @@ -619,7 +619,7 @@ func (iw *innerWorker) constructDatumLookupKey(task *lookUpJoinTask, chkIdx, row } innerColType := iw.rowTypes[iw.hashCols[i]] innerValue, err := outerValue.ConvertTo(sc, innerColType) - if err != nil && !(terror.ErrorEqual(err, types.ErrTruncated) && (innerColType.Tp == mysql.TypeSet || innerColType.Tp == mysql.TypeEnum)) { + if err != nil && !(terror.ErrorEqual(err, types.ErrTruncated) && (innerColType.GetType() == mysql.TypeSet || innerColType.GetType() == mysql.TypeEnum)) { // If the converted outerValue overflows or invalid to innerValue, we don't need to lookup it. if terror.ErrorEqual(err, types.ErrOverflow) || terror.ErrorEqual(err, types.ErrWarnDataOutOfRange) { return nil, nil, nil diff --git a/executor/index_lookup_merge_join.go b/executor/index_lookup_merge_join.go index d0ff14924e90a..10a8aa457d120 100644 --- a/executor/index_lookup_merge_join.go +++ b/executor/index_lookup_merge_join.go @@ -676,7 +676,7 @@ func (imw *innerMergeWorker) constructDatumLookupKey(task *lookUpMergeJoinTask, if terror.ErrorEqual(err, types.ErrOverflow) || terror.ErrorEqual(err, types.ErrWarnDataOutOfRange) { return nil, nil } - if terror.ErrorEqual(err, types.ErrTruncated) && (innerColType.Tp == mysql.TypeSet || innerColType.Tp == mysql.TypeEnum) { + if terror.ErrorEqual(err, types.ErrTruncated) && (innerColType.GetType() == mysql.TypeSet || innerColType.GetType() == mysql.TypeEnum) { return nil, nil } return nil, err diff --git a/executor/index_merge_reader.go b/executor/index_merge_reader.go index 66dde5b0e743a..660eaa71499b3 100644 --- a/executor/index_merge_reader.go +++ b/executor/index_merge_reader.go @@ -24,7 +24,6 @@ import ( "time" "unsafe" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/distsql" @@ -39,6 +38,7 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tipb/go-tipb" diff --git a/executor/index_merge_reader_test.go b/executor/index_merge_reader_test.go index fb484898ccdfa..288b2388fb459 100644 --- a/executor/index_merge_reader_test.go +++ b/executor/index_merge_reader_test.go @@ -205,7 +205,7 @@ func TestIndexMergeWithPreparedStmt(t *testing.T) { tk.MustExec("prepare stmt1 from 'select /*+ use_index_merge(t1) */ count(1) from t1 where c1 < ? or c2 < ?';") tk.MustExec("set @a = 10;") tk.MustQuery("execute stmt1 using @a, @a;").Check(testkit.Rows("10")) - tk.Session().SetSessionManager(&mockSessionManager1{ + tk.Session().SetSessionManager(&testkit.MockSessionManager{ PS: []*util.ProcessInfo{tk.Session().ShowProcess()}, }) explainStr := "explain for connection " + strconv.FormatUint(tk.Session().ShowProcess().ID, 10) diff --git a/executor/infoschema_cluster_table_test.go b/executor/infoschema_cluster_table_test.go index 7c3108fd1686e..95ab9f271b538 100644 --- a/executor/infoschema_cluster_table_test.go +++ b/executor/infoschema_cluster_table_test.go @@ -19,6 +19,7 @@ import ( "fmt" "net" "net/http/httptest" + "strconv" "strings" "testing" "time" @@ -329,7 +330,8 @@ func (s *infosSchemaClusterTableSuite) TestTableStorageStats() { "test 2", )) rows := tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql';").Rows() - s.Require().Len(rows, 31) + result := 32 + s.Require().Len(rows, result) // More tests about the privileges. tk.MustExec("create user 'testuser'@'localhost'") @@ -355,12 +357,12 @@ func (s *infosSchemaClusterTableSuite) TestTableStorageStats() { Hostname: "localhost", }, nil, nil)) - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("31")) + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows(strconv.Itoa(result))) s.Require().True(tk.Session().Auth(&auth.UserIdentity{ Username: "testuser3", Hostname: "localhost", }, nil, nil)) - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("31")) + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows(strconv.Itoa(result))) } diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index 79e592aa6a40a..8131402ab8991 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -28,7 +28,6 @@ import ( "sync" "time" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/deadlock" @@ -63,6 +62,7 @@ import ( "github.com/pingcap/tidb/util/deadlockhistory" "github.com/pingcap/tidb/util/keydecoder" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/resourcegrouptag" "github.com/pingcap/tidb/util/sem" @@ -382,7 +382,7 @@ func (e *memtableRetriever) setDataForStatisticsInTable(schema *model.DBInfo, ta var rows [][]types.Datum if table.PKIsHandle { for _, col := range table.Columns { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { record := types.MakeDatums( infoschema.CatalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA @@ -419,7 +419,7 @@ func (e *memtableRetriever) setDataForStatisticsInTable(schema *model.DBInfo, ta for i, key := range index.Columns { col := nameToCol[key.Name.L] nullable := "YES" - if mysql.HasNotNullFlag(col.Flag) { + if mysql.HasNotNullFlag(col.GetFlag()) { nullable = "" } @@ -743,47 +743,47 @@ ForColumnsTag: } var charMaxLen, charOctLen, numericPrecision, numericScale, datetimePrecision interface{} - colLen, decimal := col.Flen, col.Decimal - defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(col.Tp) + colLen, decimal := col.GetFlen(), col.GetDecimal() + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(col.GetType()) if decimal == types.UnspecifiedLength { decimal = defaultDecimal } if colLen == types.UnspecifiedLength { colLen = defaultFlen } - if col.Tp == mysql.TypeSet { + if col.GetType() == mysql.TypeSet { // Example: In MySQL set('a','bc','def','ghij') has length 13, because // len('a')+len('bc')+len('def')+len('ghij')+len(ThreeComma)=13 // Reference link: https://bugs.mysql.com/bug.php?id=22613 colLen = 0 - for _, ele := range col.Elems { + for _, ele := range col.GetElems() { colLen += len(ele) } - if len(col.Elems) != 0 { - colLen += (len(col.Elems) - 1) + if len(col.GetElems()) != 0 { + colLen += (len(col.GetElems()) - 1) } charMaxLen = colLen - charOctLen = calcCharOctLength(colLen, col.Charset) - } else if col.Tp == mysql.TypeEnum { + charOctLen = calcCharOctLength(colLen, col.GetCharset()) + } else if col.GetType() == mysql.TypeEnum { // Example: In MySQL enum('a', 'ab', 'cdef') has length 4, because // the longest string in the enum is 'cdef' // Reference link: https://bugs.mysql.com/bug.php?id=22613 colLen = 0 - for _, ele := range col.Elems { + for _, ele := range col.GetElems() { if len(ele) > colLen { colLen = len(ele) } } charMaxLen = colLen - charOctLen = calcCharOctLength(colLen, col.Charset) - } else if types.IsString(col.Tp) { + charOctLen = calcCharOctLength(colLen, col.GetCharset()) + } else if types.IsString(col.GetType()) { charMaxLen = colLen - charOctLen = calcCharOctLength(colLen, col.Charset) - } else if types.IsTypeFractionable(col.Tp) { + charOctLen = calcCharOctLength(colLen, col.GetCharset()) + } else if types.IsTypeFractionable(col.GetType()) { datetimePrecision = decimal - } else if types.IsTypeNumeric(col.Tp) { + } else if types.IsTypeNumeric(col.GetType()) { numericPrecision = colLen - if col.Tp != mysql.TypeFloat && col.Tp != mysql.TypeDouble { + if col.GetType() != mysql.TypeFloat && col.GetType() != mysql.TypeDouble { numericScale = decimal } else if decimal != -1 { numericScale = decimal @@ -794,31 +794,31 @@ ForColumnsTag: var columnDefault interface{} if columnDesc.DefaultValue != nil { columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue) - if col.Tp == mysql.TypeBit { + if col.GetType() == mysql.TypeBit { defaultStr := fmt.Sprintf("%v", columnDesc.DefaultValue) defaultValBinaryLiteral := types.BinaryLiteral(defaultStr) columnDefault = defaultValBinaryLiteral.ToBitLiteralString(true) } } record := types.MakeDatums( - infoschema.CatalogVal, // TABLE_CATALOG - schema.Name.O, // TABLE_SCHEMA - tbl.Name.O, // TABLE_NAME - col.Name.O, // COLUMN_NAME - i+1, // ORIGINAL_POSITION - columnDefault, // COLUMN_DEFAULT - columnDesc.Null, // IS_NULLABLE - types.TypeToStr(col.Tp, col.Charset), // DATA_TYPE - charMaxLen, // CHARACTER_MAXIMUM_LENGTH - charOctLen, // CHARACTER_OCTET_LENGTH - numericPrecision, // NUMERIC_PRECISION - numericScale, // NUMERIC_SCALE - datetimePrecision, // DATETIME_PRECISION - columnDesc.Charset, // CHARACTER_SET_NAME - columnDesc.Collation, // COLLATION_NAME - columnType, // COLUMN_TYPE - columnDesc.Key, // COLUMN_KEY - columnDesc.Extra, // EXTRA + infoschema.CatalogVal, // TABLE_CATALOG + schema.Name.O, // TABLE_SCHEMA + tbl.Name.O, // TABLE_NAME + col.Name.O, // COLUMN_NAME + i+1, // ORIGINAL_POSITION + columnDefault, // COLUMN_DEFAULT + columnDesc.Null, // IS_NULLABLE + types.TypeToStr(col.GetType(), col.GetCharset()), // DATA_TYPE + charMaxLen, // CHARACTER_MAXIMUM_LENGTH + charOctLen, // CHARACTER_OCTET_LENGTH + numericPrecision, // NUMERIC_PRECISION + numericScale, // NUMERIC_SCALE + datetimePrecision, // DATETIME_PRECISION + columnDesc.Charset, // CHARACTER_SET_NAME + columnDesc.Collation, // COLLATION_NAME + columnType, // COLUMN_TYPE + columnDesc.Key, // COLUMN_KEY + columnDesc.Extra, // EXTRA strings.ToLower(privileges.PrivToString(priv, mysql.AllColumnPrivs, mysql.Priv2Str)), // PRIVILEGES columnDesc.Comment, // COLUMN_COMMENT col.GeneratedExprString, // GENERATION_EXPRESSION @@ -996,7 +996,7 @@ func (e *memtableRetriever) setDataFromIndexes(ctx sessionctx.Context, schemas [ if tb.PKIsHandle { var pkCol *model.ColumnInfo for _, col := range tb.Cols() { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { pkCol = col break } @@ -1399,7 +1399,7 @@ func keyColumnUsageInTable(schema *model.DBInfo, table *model.TableInfo) [][]typ var rows [][]types.Datum if table.PKIsHandle { for _, col := range table.Columns { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { record := types.MakeDatums( infoschema.CatalogVal, // CONSTRAINT_CATALOG schema.Name.O, // CONSTRAINT_SCHEMA @@ -2810,9 +2810,9 @@ func (e *TiFlashSystemTableRetriever) dataForTiFlashSystemTables(ctx sessionctx. if column.Name.O == "TIFLASH_INSTANCE" { continue } - if column.Tp == mysql.TypeVarchar { + if column.GetType() == mysql.TypeVarchar { row[index].SetString(fields[index], mysql.DefaultCollationName) - } else if column.Tp == mysql.TypeLonglong { + } else if column.GetType() == mysql.TypeLonglong { if fields[index] == notNumber { continue } @@ -2821,7 +2821,7 @@ func (e *TiFlashSystemTableRetriever) dataForTiFlashSystemTables(ctx sessionctx. return nil, errors.Trace(err) } row[index].SetInt64(value) - } else if column.Tp == mysql.TypeDouble { + } else if column.GetType() == mysql.TypeDouble { if fields[index] == notNumber { continue } @@ -2863,6 +2863,24 @@ func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context, is info "end_key": "7480000000000000ff3a5f720000000000fa", }), }, + { + ID: "invalidIDtest", + Labels: []label.Label{{Key: "merge_option", Value: "allow"}, {Key: "db", Value: "test"}, {Key: "table", Value: "test_label"}}, + RuleType: "key-range", + Data: convert(map[string]interface{}{ + "start_key": "7480000000000000ff395f720000000000fa", + "end_key": "7480000000000000ff3a5f720000000000fa", + }), + }, + { + ID: "schema/test/test_label", + Labels: []label.Label{{Key: "merge_option", Value: "allow"}, {Key: "db", Value: "test"}, {Key: "table", Value: "test_label"}}, + RuleType: "key-range", + Data: convert(map[string]interface{}{ + "start_key": "aaaaa", + "end_key": "bbbbb", + }), + }, } err = nil skipValidateTable = true @@ -2877,11 +2895,13 @@ func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context, is info skip := true dbName, tableName, partitionName, err := checkRule(rule) if err != nil { - return err + logutil.BgLogger().Warn("check table-rule failed", zap.String("ID", rule.ID), zap.Error(err)) + continue } tableID, err := decodeTableIDFromRule(rule) if err != nil { - return err + logutil.BgLogger().Warn("decode table ID from rule failed", zap.String("ID", rule.ID), zap.Error(err)) + continue } if !skipValidateTable && tableOrPartitionNotExist(dbName, tableName, partitionName, is, tableID) { diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index 9bf6d6136fcc6..edf947f8abac7 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -638,3 +638,61 @@ func TestTablesPKType(t *testing.T) { tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_common'").Check(testkit.Rows("CLUSTERED")) tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'INFORMATION_SCHEMA' and table_name = 'TABLES'").Check(testkit.Rows("NONCLUSTERED")) } + +// https://github.com/pingcap/tidb/issues/32459. +func TestJoinSystemTableContainsView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a timestamp, b int);") + tk.MustExec("insert into t values (null, 100);") + tk.MustExec("create view v as select * from t;") + // This is used by grafana when TiDB is specified as the data source. + // See https://github.com/grafana/grafana/blob/e86b6662a187c77656f72bef3b0022bf5ced8b98/public/app/plugins/datasource/mysql/meta_query.ts#L31 + for i := 0; i < 10; i++ { + tk.MustQuery(` +SELECT + table_name as table_name, + ( SELECT + column_name as column_name + FROM information_schema.columns c + WHERE + c.table_schema = t.table_schema AND + c.table_name = t.table_name AND + c.data_type IN ('timestamp', 'datetime') + ORDER BY ordinal_position LIMIT 1 + ) AS time_column, + ( SELECT + column_name AS column_name + FROM information_schema.columns c + WHERE + c.table_schema = t.table_schema AND + c.table_name = t.table_name AND + c.data_type IN('float', 'int', 'bigint') + ORDER BY ordinal_position LIMIT 1 + ) AS value_column + FROM information_schema.tables t + WHERE + t.table_schema = database() AND + EXISTS + ( SELECT 1 + FROM information_schema.columns c + WHERE + c.table_schema = t.table_schema AND + c.table_name = t.table_name AND + c.data_type IN ('timestamp', 'datetime') + ) AND + EXISTS + ( SELECT 1 + FROM information_schema.columns c + WHERE + c.table_schema = t.table_schema AND + c.table_name = t.table_name AND + c.data_type IN('float', 'int', 'bigint') + ) + LIMIT 1 +; +`).Check(testkit.Rows("t a b")) + } +} diff --git a/executor/insert_common.go b/executor/insert_common.go index 5c7a804ea3da6..37669c425b67d 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -297,7 +297,7 @@ func (e *InsertValues) handleErr(col *table.Column, val *types.Datum, rowIdx int colName string ) if col != nil { - colTp = col.Tp + colTp = col.GetType() colName = col.Name.String() } @@ -405,7 +405,7 @@ func (e *InsertValues) setValueForRefColumn(row []types.Datum, hasValue []bool) d, err := e.getColDefaultValue(i, c) if err == nil { row[i] = d - if !mysql.HasAutoIncrementFlag(c.Flag) { + if !mysql.HasAutoIncrementFlag(c.GetFlag()) { // It is an interesting behavior in MySQL. // If the value of auto ID is not explicit, MySQL use 0 value for auto ID when it is // evaluated by another column, but it should be used once only. @@ -559,7 +559,7 @@ func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.D // fillColValue fills the column value if it is not set in the insert statement. func (e *InsertValues) fillColValue(ctx context.Context, datum types.Datum, idx int, column *table.Column, hasValue bool) (types.Datum, error) { - if mysql.HasAutoIncrementFlag(column.Flag) { + if mysql.HasAutoIncrementFlag(column.GetFlag()) { if e.lazyFillAutoID { // Handle hasValue info in autoIncrement column previously for lazy handle. if !hasValue { @@ -624,7 +624,7 @@ func (e *InsertValues) fillRow(ctx context.Context, row []types.Datum, hasValue if row[i], err = e.fillColValue(ctx, row[i], i, c, hasValue[i]); err != nil { return nil, err } - if !e.lazyFillAutoID || (e.lazyFillAutoID && !mysql.HasAutoIncrementFlag(c.Flag)) { + if !e.lazyFillAutoID || (e.lazyFillAutoID && !mysql.HasAutoIncrementFlag(c.GetFlag())) { if err = c.HandleBadNull(&row[i], e.ctx.GetSessionVars().StmtCtx); err != nil { return nil, err } @@ -674,7 +674,7 @@ func (e *InsertValues) isAutoNull(ctx context.Context, d types.Datum, col *table func findAutoIncrementColumn(t table.Table) (col *table.Column, offsetInRow int, found bool) { for i, c := range t.Cols() { - if mysql.HasAutoIncrementFlag(c.Flag) { + if mysql.HasAutoIncrementFlag(c.GetFlag()) { return c, i, true } } @@ -682,7 +682,7 @@ func findAutoIncrementColumn(t table.Table) (col *table.Column, offsetInRow int, } func setDatumAutoIDAndCast(ctx sessionctx.Context, d *types.Datum, id int64, col *table.Column) error { - d.SetAutoID(id, col.Flag) + d.SetAutoID(id, col.GetFlag()) var err error *d, err = table.CastValue(ctx, *d, col.ToInfo(), false, false) if err == nil && d.GetInt64() < id { @@ -845,7 +845,7 @@ func (e *InsertValues) adjustAutoIncrementDatum(ctx context.Context, d types.Dat func getAutoRecordID(d types.Datum, target *types.FieldType, isInsert bool) (int64, error) { var recordID int64 - switch target.Tp { + switch target.GetType() { case mysql.TypeFloat, mysql.TypeDouble: f := d.GetFloat64() if isInsert { @@ -856,7 +856,7 @@ func getAutoRecordID(d types.Datum, target *types.FieldType, isInsert bool) (int case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: recordID = d.GetInt64() default: - return 0, errors.Errorf("unexpected field type [%v]", target.Tp) + return 0, errors.Errorf("unexpected field type [%v]", target.GetType()) } return recordID, nil diff --git a/executor/join_pkg_test.go b/executor/join_pkg_test.go index b7500ecf144b8..88e41f4e9979a 100644 --- a/executor/join_pkg_test.go +++ b/executor/join_pkg_test.go @@ -42,7 +42,7 @@ func TestJoinExec(t *testing.T) { rows: casTest.rows, ctx: casTest.ctx, genDataFunc: func(row int, typ *types.FieldType) interface{} { - switch typ.Tp { + switch typ.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(row) case mysql.TypeDouble: diff --git a/executor/join_test.go b/executor/join_test.go index f6fe0b23ecf7b..81c2f52596094 100644 --- a/executor/join_test.go +++ b/executor/join_test.go @@ -69,7 +69,7 @@ func TestJoinInDisk(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - sm := &mockSessionManager1{ + sm := &testkit.MockSessionManager{ PS: make([]*util.ProcessInfo, 0), } tk.Session().SetSessionManager(sm) diff --git a/executor/joiner_test.go b/executor/joiner_test.go index ff87d271fdcfd..77777d89c966c 100644 --- a/executor/joiner_test.go +++ b/executor/joiner_test.go @@ -81,7 +81,7 @@ func genTestChunk(maxChunkSize int, numRows int, fields []*types.FieldType) *chu for numRows > 0 { numRows-- for col, field := range fields { - switch field.Tp { + switch field.GetType() { case mysql.TypeLong: chk.AppendInt64(col, 0) case mysql.TypeFloat: diff --git a/executor/load_data.go b/executor/load_data.go index 5344a14fe8948..87ceb964f7e03 100644 --- a/executor/load_data.go +++ b/executor/load_data.go @@ -596,8 +596,8 @@ func (e *LoadDataInfo) colsToRow(ctx context.Context, cols []field) []types.Datu } // If some columns is missing and their type is time and has not null flag, they should be set as current time. - if types.IsTypeTime(e.FieldMappings[i].Column.Tp) && mysql.HasNotNullFlag(e.FieldMappings[i].Column.Flag) { - row = append(row, types.NewTimeDatum(types.CurrentTime(e.FieldMappings[i].Column.Tp))) + if types.IsTypeTime(e.FieldMappings[i].Column.GetType()) && mysql.HasNotNullFlag(e.FieldMappings[i].Column.GetFlag()) { + row = append(row, types.NewTimeDatum(types.CurrentTime(e.FieldMappings[i].Column.GetType()))) continue } diff --git a/executor/main_test.go b/executor/main_test.go index cf07e9c411b94..0ce6dae10889e 100644 --- a/executor/main_test.go +++ b/executor/main_test.go @@ -47,7 +47,7 @@ func TestMain(m *testing.M) { autoid.SetStep(5000) config.UpdateGlobal(func(conf *config.Config) { - conf.Log.SlowThreshold = 30000 // 30s + conf.Instance.SlowThreshold = 30000 // 30s conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true diff --git a/executor/mem_reader.go b/executor/mem_reader.go index 1c4b29290b325..e1e9ea100ee5c 100644 --- a/executor/mem_reader.go +++ b/executor/mem_reader.go @@ -103,7 +103,7 @@ func (m *memIndexReader) getMemRows(ctx context.Context) ([][]types.Datum, error switch { case m.table.PKIsHandle: for _, col := range m.table.Columns { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { tps = append(tps, &col.FieldType) break } @@ -146,7 +146,7 @@ func (m *memIndexReader) getMemRows(ctx context.Context) ([][]types.Datum, error func (m *memIndexReader) decodeIndexKeyValue(key, value []byte, tps []*types.FieldType) ([]types.Datum, error) { hdStatus := tablecodec.HandleDefault - if mysql.HasUnsignedFlag(tps[len(tps)-1].Flag) { + if mysql.HasUnsignedFlag(tps[len(tps)-1].GetFlag()) { hdStatus = tablecodec.HandleIsUnsigned } colInfos := tables.BuildRowcodecColInfoForIndexColumns(m.index, m.table) @@ -205,7 +205,7 @@ func buildMemTableReader(ctx context.Context, us *UnionScanExec, tblReader *Tabl col := us.columns[i] colInfo = append(colInfo, rowcodec.ColInfo{ ID: col.ID, - IsPKHandle: us.table.Meta().PKIsHandle && mysql.HasPriKeyFlag(col.Flag), + IsPKHandle: us.table.Meta().PKIsHandle && mysql.HasPriKeyFlag(col.GetFlag()), Ft: rowcodec.FieldTypeFromModelColumn(col), }) } @@ -330,9 +330,9 @@ func (m *memTableReader) getRowData(handle kv.Handle, value []byte) ([][]byte, e } } } - } else if (pkIsHandle && mysql.HasPriKeyFlag(col.Flag)) || id == model.ExtraHandleID { + } else if (pkIsHandle && mysql.HasPriKeyFlag(col.GetFlag())) || id == model.ExtraHandleID { var handleDatum types.Datum - if mysql.HasUnsignedFlag(col.Flag) { + if mysql.HasUnsignedFlag(col.GetFlag()) { // PK column is Unsigned. handleDatum = types.NewUintDatum(uint64(handle.IntValue())) } else { @@ -761,7 +761,7 @@ func getColIDAndPkColIDs(table table.Table, columns []*model.ColumnInfo) (map[in col := columns[i] colInfos = append(colInfos, rowcodec.ColInfo{ ID: col.ID, - IsPKHandle: tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.Flag), + IsPKHandle: tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.GetFlag()), Ft: rowcodec.FieldTypeFromModelColumn(col), }) } diff --git a/executor/merge_join_test.go b/executor/merge_join_test.go index 9d62becef77b9..fc460f63edbcc 100644 --- a/executor/merge_join_test.go +++ b/executor/merge_join_test.go @@ -253,7 +253,7 @@ func TestShuffleMergeJoinInDisk(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - sm := &mockSessionManager1{ + sm := &testkit.MockSessionManager{ PS: make([]*util.ProcessInfo, 0), } tk.Session().SetSessionManager(sm) @@ -295,7 +295,7 @@ func TestMergeJoinInDisk(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - sm := &mockSessionManager1{ + sm := &testkit.MockSessionManager{ PS: make([]*util.ProcessInfo, 0), } tk.Session().SetSessionManager(sm) diff --git a/executor/parallel_apply_test.go b/executor/parallel_apply_test.go index 1d775fcc2218a..63e439cbc661f 100644 --- a/executor/parallel_apply_test.go +++ b/executor/parallel_apply_test.go @@ -66,6 +66,12 @@ func TestParallelApplyPlan(t *testing.T) { q2 := "select * from t t0 where t0.b <= (select max(t1.b) from t t1 where t1.b > (select max(b) from t t2 where t1.a > t2.a and t0.a > t2.a));" checkApplyPlan(t, tk, q2, 1) // only the outside apply can be parallel tk.MustQuery(q2).Sort().Check(testkit.Rows("1 1", "2 2", "3 3", "4 4", "5 5", "6 6", "7 7", "8 8", "9 9")) + q3 := "select t1.b from t t1 where t1.b > (select max(b) from t t2 where t1.a > t2.a) order by t1.a" + checkApplyPlan(t, tk, q3, 0) + tk.MustExec("alter table t add index idx(a)") + checkApplyPlan(t, tk, q3, 1) + tk.MustQuery(q3).Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Parallel Apply rejects the possible order properties of its outer child currently")) } func TestApplyColumnType(t *testing.T) { diff --git a/executor/partition_table_test.go b/executor/partition_table_test.go index cb7b2d7633583..c740dec5d93b1 100644 --- a/executor/partition_table_test.go +++ b/executor/partition_table_test.go @@ -3524,13 +3524,12 @@ func TestPartitionTableExplain(t *testing.T) { " └─IndexReader 1.00 root index:IndexFullScan", " └─IndexFullScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) keep order:false")) tk.MustQuery(`explain format = 'brief' select * from t partition (p1),t2 where t2.a = 1 and t2.b = t.b`).Check(testkit.Rows( - "IndexJoin 1.00 root inner join, inner:IndexReader, outer key:testpartitiontableexplain.t2.b, inner key:testpartitiontableexplain.t.b, equal cond:eq(testpartitiontableexplain.t2.b, testpartitiontableexplain.t.b)", + "HashJoin 1.00 root inner join, equal:[eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)]", "├─TableReader(Build) 1.00 root data:Selection", "│ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", "│ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", - "└─IndexReader(Probe) 1.00 root index:Selection", - " └─Selection 1.00 cop[tikv] not(isnull(testpartitiontableexplain.t.b))", - " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range: decided by [eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)], keep order:false")) + "└─IndexReader(Probe) 1.00 root index:IndexFullScan", + " └─IndexFullScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) keep order:false")) tk.MustQuery(`explain format = 'brief' select * from t,t2 where t2.a = 1 and t2.b = t.b and t.a = 1`).Check(testkit.Rows( "HashJoin 1.00 root inner join, equal:[eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)]", "├─TableReader(Build) 1.00 root data:Selection", diff --git a/executor/pipelined_window.go b/executor/pipelined_window.go index 7e8f6a0ed5c5e..1a72864bcf225 100644 --- a/executor/pipelined_window.go +++ b/executor/pipelined_window.go @@ -17,7 +17,6 @@ package executor import ( "context" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/executor/aggfuncs" "github.com/pingcap/tidb/expression" @@ -25,6 +24,7 @@ import ( "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) type dataInfo struct { @@ -258,7 +258,7 @@ func (e *PipelinedWindowExec) getStart(ctx sessionctx.Context) (uint64, error) { } if e.isRangeFrame { var start uint64 - for start = mathutil.MaxUint64(e.lastStartRow, e.stagedStartRow); start < e.rowCnt; start++ { + for start = mathutil.Max(e.lastStartRow, e.stagedStartRow); start < e.rowCnt; start++ { var res int64 var err error for i := range e.orderByCols { @@ -298,7 +298,7 @@ func (e *PipelinedWindowExec) getEnd(ctx sessionctx.Context) (uint64, error) { } if e.isRangeFrame { var end uint64 - for end = mathutil.MaxUint64(e.lastEndRow, e.stagedEndRow); end < e.rowCnt; end++ { + for end = mathutil.Max(e.lastEndRow, e.stagedEndRow); end < e.rowCnt; end++ { var res int64 var err error for i := range e.orderByCols { @@ -412,7 +412,7 @@ func (e *PipelinedWindowExec) produce(ctx sessionctx.Context, chk *chunk.Chunk, produced++ remained-- } - extend := mathutil.MinUint64Val(e.curRowIdx, e.lastEndRow, e.lastStartRow) + extend := mathutil.Min(e.curRowIdx, e.lastEndRow, e.lastStartRow) if extend > e.rowStart { numDrop := extend - e.rowStart e.dropped += numDrop diff --git a/executor/point_get.go b/executor/point_get.go index ea58e8c6fce49..f33ba20b5dd5a 100644 --- a/executor/point_get.go +++ b/executor/point_get.go @@ -498,22 +498,22 @@ func EncodeUniqueIndexValuesForKey(ctx sessionctx.Context, tblInfo *model.TableI // table.CastValue will append 0x0 if the string value's length is smaller than the BINARY column's length. // So we don't use CastValue for string value for now. // TODO: merge two if branch. - if colInfo.Tp == mysql.TypeString || colInfo.Tp == mysql.TypeVarString || colInfo.Tp == mysql.TypeVarchar { + if colInfo.GetType() == mysql.TypeString || colInfo.GetType() == mysql.TypeVarString || colInfo.GetType() == mysql.TypeVarchar { var str string str, err = idxVals[i].ToString() - idxVals[i].SetString(str, colInfo.FieldType.Collate) - } else if colInfo.Tp == mysql.TypeEnum && (idxVals[i].Kind() == types.KindString || idxVals[i].Kind() == types.KindBytes || idxVals[i].Kind() == types.KindBinaryLiteral) { + idxVals[i].SetString(str, colInfo.FieldType.GetCollate()) + } else if colInfo.GetType() == mysql.TypeEnum && (idxVals[i].Kind() == types.KindString || idxVals[i].Kind() == types.KindBytes || idxVals[i].Kind() == types.KindBinaryLiteral) { var str string var e types.Enum str, err = idxVals[i].ToString() if err != nil { return nil, kv.ErrNotExist } - e, err = types.ParseEnumName(colInfo.FieldType.Elems, str, colInfo.FieldType.Collate) + e, err = types.ParseEnumName(colInfo.FieldType.GetElems(), str, colInfo.FieldType.GetCollate()) if err != nil { return nil, kv.ErrNotExist } - idxVals[i].SetMysqlEnum(e, colInfo.FieldType.Collate) + idxVals[i].SetMysqlEnum(e, colInfo.FieldType.GetCollate()) } else { // If a truncated error or an overflow error is thrown when converting the type of `idxVal[i]` to // the type of `colInfo`, the `idxVal` does not exist in the `idxInfo` for sure. @@ -595,7 +595,7 @@ func decodeOldRowValToChunk(sctx sessionctx.Context, schema *expression.Schema, func tryDecodeFromHandle(tblInfo *model.TableInfo, schemaColIdx int, col *expression.Column, handle kv.Handle, chk *chunk.Chunk, decoder *codec.Decoder, pkCols []int64, prefixColIDs []int64) (bool, error) { - if tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.RetType.Flag) { + if tblInfo.PKIsHandle && mysql.HasPriKeyFlag(col.RetType.GetFlag()) { chk.AppendInt64(schemaColIdx, handle.IntValue()) return true, nil } @@ -607,7 +607,7 @@ func tryDecodeFromHandle(tblInfo *model.TableInfo, schemaColIdx int, col *expres return false, nil } // Try to decode common handle. - if mysql.HasPriKeyFlag(col.RetType.Flag) { + if mysql.HasPriKeyFlag(col.RetType.GetFlag()) { for i, hid := range pkCols { if col.ID == hid && notPKPrefixCol(hid, prefixColIDs) { _, err := decoder.DecodeOne(handle.EncodedCol(i), schemaColIdx, col.RetType) diff --git a/executor/prepared.go b/executor/prepared.go index f81d2482f979c..66dd5c38ee073 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -32,6 +32,7 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" "github.com/pingcap/tidb/util" @@ -197,7 +198,8 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { } normalizedSQL, digest := parser.NormalizeDigest(prepared.Stmt.Text()) if topsqlstate.TopSQLEnabled() { - ctx = topsql.AttachSQLInfo(ctx, normalizedSQL, digest, "", nil, vars.InRestrictedSQL) + e.ctx.GetSessionVars().StmtCtx.IsSQLRegistered.Store(true) + ctx = topsql.AttachAndRegisterSQLInfo(ctx, normalizedSQL, digest, vars.InRestrictedSQL) } var ( @@ -367,6 +369,10 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, failpoint.Inject("assertTxnManagerInCompile", func() { sessiontxn.RecordAssert(sctx, "assertTxnManagerInCompile", true) sessiontxn.AssertTxnManagerInfoSchema(sctx, is) + staleread.AssertStmtStaleness(sctx, snapshotTS != 0) + if snapshotTS != 0 { + sessiontxn.AssertTxnManagerReadTS(sctx, snapshotTS) + } }) stmt := &ExecStmt{ @@ -377,8 +383,6 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, Ctx: sctx, OutputNames: names, Ti: &TelemetryInfo{}, - IsStaleness: isStaleness, - SnapshotTS: snapshotTS, ReplicaReadScope: replicaReadScope, } if preparedPointer, ok := sctx.GetSessionVars().PreparedStmts[ID]; ok { diff --git a/executor/prepared_test.go b/executor/prepared_test.go index ceb216d5f102b..9fbdaf3b4c50f 100644 --- a/executor/prepared_test.go +++ b/executor/prepared_test.go @@ -174,7 +174,7 @@ func TestPreparedNullParam(t *testing.T) { tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( "TableDual_5 0.00 root rows:0")) } @@ -217,7 +217,7 @@ func TestIssue29850(t *testing.T) { tk.MustQuery(`execute stmt using @w_id, @c_d_id, @c_id`).Check(testkit.Rows()) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use PointGet `Projection_7 0.00 root test.customer.c_discount, test.customer.c_last, test.customer.c_credit, test.warehouse.w_tax`, `└─MergeJoin_8 0.00 root inner join, left key:test.customer.c_w_id, right key:test.warehouse.w_id`, @@ -233,7 +233,7 @@ func TestIssue29850(t *testing.T) { tk.MustQuery(`execute stmt using @a1, @a1`).Check(testkit.Rows("1")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // cannot use PointGet since it contains a range condition `Selection_7 1.00 root ge(test.t.a, 1), le(test.t.a, 1)`, `└─TableReader_6 1.00 root data:TableRangeScan_5`, @@ -245,7 +245,7 @@ func TestIssue29850(t *testing.T) { tk.MustQuery(`execute stmt using @a1, @a1`).Check(testkit.Rows("1")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // cannot use PointGet since it contains a or condition `Selection_7 1.00 root or(eq(test.t.a, 1), eq(test.t.a, 1))`, `└─TableReader_6 1.00 root data:TableRangeScan_5`, @@ -277,7 +277,7 @@ func TestIssue28064(t *testing.T) { tk.MustExec("execute stmt1 using @a, @b, @c;") tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) rows.Check(testkit.Rows("Selection_8 0.00 root eq(test.t28064.a, 123), eq(test.t28064.b, 234), eq(test.t28064.c, 345)", "└─IndexLookUp_7 0.00 root ", @@ -316,7 +316,7 @@ func TestPreparePlanCache4Blacklist(t *testing.T) { tk.MustExec("execute stmt;") tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) require.Contains(t, res.Rows()[1][0], "TopN") @@ -331,7 +331,7 @@ func TestPreparePlanCache4Blacklist(t *testing.T) { tk.MustExec("execute stmt;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) // Plans that have been cached will not be affected by the blacklist. require.Contains(t, res.Rows()[1][0], "TopN") @@ -346,7 +346,7 @@ func TestPreparePlanCache4Blacklist(t *testing.T) { tk.MustExec("execute stmt;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) require.Equal(t, 3, len(res.Rows())) require.Contains(t, res.Rows()[1][0], "Selection") @@ -364,7 +364,7 @@ func TestPreparePlanCache4Blacklist(t *testing.T) { tk.MustExec("execute stmt;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) // The expressions can still be pushed down to tikv. require.Equal(t, 3, len(res.Rows())) @@ -413,7 +413,7 @@ func TestPlanCacheClusterIndex(t *testing.T) { tk.MustQuery("execute stmt1 using @v1,@v2").Check(testkit.Rows("3 3 333")) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() require.Equal(t, 0, strings.Index(rows[len(rows)-1][4].(string), `range:("3" "2","3" +inf]`)) // For point get @@ -431,7 +431,7 @@ func TestPlanCacheClusterIndex(t *testing.T) { tk.MustQuery("execute stmt2 using @v1,@v2").Check(testkit.Rows("3 3 333")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() require.Equal(t, 0, strings.Index(rows[len(rows)-1][0].(string), `Point_Get`)) // For CBO point get and batch point get @@ -459,7 +459,7 @@ func TestPlanCacheClusterIndex(t *testing.T) { tk.MustQuery(`execute stmt1 using @v2`).Check(testkit.Rows("b 2 2 2")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() require.True(t, strings.Contains(rows[3][0].(string), `TableRangeScan`)) @@ -565,7 +565,7 @@ func TestPlanCacheWithDifferentVariableTypes(t *testing.T) { tk.MustQuery(exec.ExecuteSQL) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) plan := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) testdata.OnRecord(func() { output[i].Executes[j].SQL = exec.ExecuteSQL @@ -976,7 +976,7 @@ func TestIssue29101(t *testing.T) { tk.MustQuery(`execute s1 using @a,@b,@c`).Check(testkit.Rows()) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use IndexJoin `Projection_6 1.00 root test.customer.c_discount, test.customer.c_last, test.customer.c_credit, test.warehouse.w_tax`, `└─IndexJoin_14 1.00 root inner join, inner:TableReader_10, outer key:test.customer.c_w_id, inner key:test.warehouse.w_id, equal cond:eq(test.customer.c_w_id, test.warehouse.w_id)`, @@ -1004,7 +1004,7 @@ func TestIssue29101(t *testing.T) { tk.MustExec(`execute s1 using @a,@b,@c,@c,@a,@d`) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use index-join `StreamAgg_9 1.00 root funcs:count(distinct test.stock.s_i_id)->Column#11`, `└─IndexJoin_14 0.03 root inner join, inner:IndexLookUp_13, outer key:test.order_line.ol_i_id, inner key:test.stock.s_i_id, equal cond:eq(test.order_line.ol_i_id, test.stock.s_i_id)`, @@ -1091,7 +1091,7 @@ func TestParameterPushDown(t *testing.T) { tk.MustQuery(tt.SQL) tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) plan := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)) testdata.OnRecord(func() { @@ -1189,7 +1189,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustExec("execute stmt;") tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Equal(t, 4, len(res.Rows())) require.Contains(t, res.Rows()[0][0], "IndexMerge") @@ -1198,7 +1198,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustExec("execute stmt;") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Equal(t, 4, len(res.Rows())) require.Contains(t, res.Rows()[0][0], "IndexMerge") @@ -1216,7 +1216,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Contains(t, res.Rows()[1][0], "Apply") require.Contains(t, res.Rows()[1][5], "Concurrency") @@ -1225,7 +1225,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Contains(t, res.Rows()[1][0], "Apply") executionInfo := fmt.Sprintf("%v", res.Rows()[1][4]) @@ -1246,7 +1246,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Contains(t, res.Rows()[1][0], "Apply") require.Contains(t, res.Rows()[1][5], "cache:ON") @@ -1255,7 +1255,7 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) require.Contains(t, res.Rows()[1][0], "Apply") executionInfo = fmt.Sprintf("%v", res.Rows()[1][5]) @@ -1325,7 +1325,7 @@ func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { tk.MustQuery("execute stmt") tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() require.Equal(t, "cop[tikv]", rows[len(rows)-1][2]) @@ -1333,7 +1333,7 @@ func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { tk.MustExec("execute stmt") tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() require.Equal(t, rows[len(rows)-1][2], "cop[tiflash]") diff --git a/executor/projection.go b/executor/projection.go index 4a680010fcb7d..f43d264ebc74a 100644 --- a/executor/projection.go +++ b/executor/projection.go @@ -25,7 +25,6 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" @@ -452,8 +451,7 @@ func recoveryProjection(output *projectionOutput, r interface{}) { if output != nil { output.done <- errors.Errorf("%v", r) } - buf := util.GetStack() - logutil.BgLogger().Error("projection executor panicked", zap.String("error", fmt.Sprintf("%v", r)), zap.String("stack", string(buf))) + logutil.BgLogger().Error("projection executor panicked", zap.String("error", fmt.Sprintf("%v", r)), zap.Stack("stack")) } func readProjectionInput(inputCh <-chan *projectionInput, finishCh <-chan struct{}) *projectionInput { diff --git a/executor/select_into.go b/executor/select_into.go index 78c210b3a4dde..d526edec874f4 100644 --- a/executor/select_into.go +++ b/executor/select_into.go @@ -163,11 +163,11 @@ func (s *SelectIntoExec) dumpToOutfile() error { s.enclosed = false } s.fieldBuf = s.fieldBuf[:0] - switch col.GetType().Tp { + switch col.GetType().GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeYear: s.fieldBuf = strconv.AppendInt(s.fieldBuf, row.GetInt64(j), 10) case mysql.TypeLonglong: - if mysql.HasUnsignedFlag(col.GetType().Flag) { + if mysql.HasUnsignedFlag(col.GetType().GetFlag()) { s.fieldBuf = strconv.AppendUint(s.fieldBuf, row.GetUint64(j), 10) } else { s.fieldBuf = strconv.AppendInt(s.fieldBuf, row.GetInt64(j), 10) @@ -187,7 +187,7 @@ func (s *SelectIntoExec) dumpToOutfile() error { case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: s.fieldBuf = append(s.fieldBuf, row.GetTime(j).String()...) case mysql.TypeDuration: - s.fieldBuf = append(s.fieldBuf, row.GetDuration(j, col.GetType().Decimal).String()...) + s.fieldBuf = append(s.fieldBuf, row.GetDuration(j, col.GetType().GetDecimal()).String()...) case mysql.TypeEnum: s.fieldBuf = append(s.fieldBuf, row.GetEnum(j).String()...) case mysql.TypeSet: @@ -240,8 +240,8 @@ const ( // DumpRealOutfile dumps a real number to lineBuf. func DumpRealOutfile(realBuf, lineBuf []byte, v float64, tp *types.FieldType) ([]byte, []byte) { prec := types.UnspecifiedLength - if tp.Decimal > 0 && tp.Decimal != mysql.NotFixedDec { - prec = tp.Decimal + if tp.GetDecimal() > 0 && tp.GetDecimal() != mysql.NotFixedDec { + prec = tp.GetDecimal() } absV := math.Abs(v) if prec == types.UnspecifiedLength && (absV >= expFormatBig || (absV != 0 && absV < expFormatSmall)) { diff --git a/executor/select_into_test.go b/executor/select_into_test.go index 616dcd30c45d6..57b2f790a83bb 100644 --- a/executor/select_into_test.go +++ b/executor/select_into_test.go @@ -255,7 +255,7 @@ func TestDumpReal(t *testing.T) { } for _, testCase := range cases { tp := types.NewFieldType(mysql.TypeDouble) - tp.Decimal = testCase.dec + tp.SetDecimal(testCase.dec) _, buf := executor.DumpRealOutfile(nil, nil, testCase.val, tp) require.Equal(t, testCase.result, string(buf)) } diff --git a/executor/set_config.go b/executor/set_config.go index 2d8f4d7e2e385..6313c9152d57f 100644 --- a/executor/set_config.go +++ b/executor/set_config.go @@ -186,7 +186,7 @@ func ConvertConfigItem2JSON(ctx sessionctx.Context, key string, val expression.E var i int64 i, isNull, err = val.EvalInt(ctx, chunk.Row{}) if err == nil && !isNull { - if mysql.HasIsBooleanFlag(val.GetType().Flag) { + if mysql.HasIsBooleanFlag(val.GetType().GetFlag()) { str = "true" if i == 0 { str = "false" diff --git a/executor/set_test.go b/executor/set_test.go index 9f2d12b9316bf..89068e58cdd27 100644 --- a/executor/set_test.go +++ b/executor/set_test.go @@ -136,8 +136,8 @@ func TestSetVar(t *testing.T) { tk.MustExec("set character_set_results = NULL") tk.MustQuery("select @@character_set_results").Check(testkit.Rows("")) - tk.MustExec("set @@session.ddl_slow_threshold=12345") - tk.MustQuery("select @@session.ddl_slow_threshold").Check(testkit.Rows("12345")) + tk.MustExec("set @@global.ddl_slow_threshold=12345") + tk.MustQuery("select @@global.ddl_slow_threshold").Check(testkit.Rows("12345")) require.Equal(t, uint32(12345), variable.DDLSlowOprThreshold) tk.MustExec("set session ddl_slow_threshold=\"54321\"") tk.MustQuery("show variables like 'ddl_slow_threshold'").Check(testkit.Rows("ddl_slow_threshold 54321")) @@ -221,17 +221,16 @@ func TestSetVar(t *testing.T) { tk.MustExec("set @@tidb_pprof_sql_cpu = 1") tk.MustExec("set @@tidb_pprof_sql_cpu = 0") - tk.MustExec(`set tidb_force_priority = "no_priority"`) - tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) - tk.MustExec(`set tidb_force_priority = "low_priority"`) - tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("LOW_PRIORITY")) - tk.MustExec(`set tidb_force_priority = "high_priority"`) - tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("HIGH_PRIORITY")) - tk.MustExec(`set tidb_force_priority = "delayed"`) - tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("DELAYED")) - tk.MustExec(`set tidb_force_priority = "abc"`) - tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) - require.Error(t, tk.ExecToErr(`set global tidb_force_priority = ""`)) + tk.MustExec(`set @@global.tidb_force_priority = "no_priority"`) + tk.MustQuery(`select @@global.tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) + tk.MustExec(`set @@global.tidb_force_priority = "low_priority"`) + tk.MustQuery(`select @@global.tidb_force_priority;`).Check(testkit.Rows("LOW_PRIORITY")) + tk.MustExec(`set @@global.tidb_force_priority = "high_priority"`) + tk.MustQuery(`select @@global.tidb_force_priority;`).Check(testkit.Rows("HIGH_PRIORITY")) + tk.MustExec(`set @@global.tidb_force_priority = "delayed"`) + tk.MustQuery(`select @@global.tidb_force_priority;`).Check(testkit.Rows("DELAYED")) + tk.MustExec(`set @@global.tidb_force_priority = "abc"`) + tk.MustQuery(`select @@global.tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) tk.MustExec("set tidb_constraint_check_in_place = 1") tk.MustQuery(`select @@session.tidb_constraint_check_in_place;`).Check(testkit.Rows("1")) @@ -594,6 +593,14 @@ func TestSetVar(t *testing.T) { tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("0")) tk.MustQuery("show global variables like 'tidb_ignore_prepared_cache_close_stmt'").Check(testkit.Rows("tidb_ignore_prepared_cache_close_stmt OFF")) + // test for tidb_enable_new_cost_interface + tk.MustQuery("select @@global.tidb_enable_new_cost_interface").Check(testkit.Rows("0")) // default value is 0 + tk.MustExec("set global tidb_enable_new_cost_interface=1") + tk.MustQuery("select @@global.tidb_enable_new_cost_interface").Check(testkit.Rows("1")) + tk.MustQuery("show global variables like 'tidb_enable_new_cost_interface'").Check(testkit.Rows()) // hidden + tk.MustExec("set global tidb_enable_new_cost_interface=0") + tk.MustQuery("select @@global.tidb_enable_new_cost_interface").Check(testkit.Rows("0")) + // test for tidb_remove_orderby_in_subquery tk.MustQuery("select @@session.tidb_remove_orderby_in_subquery").Check(testkit.Rows("0")) // default value is 0 tk.MustExec("set session tidb_remove_orderby_in_subquery=1") @@ -601,6 +608,24 @@ func TestSetVar(t *testing.T) { tk.MustQuery("select @@global.tidb_remove_orderby_in_subquery").Check(testkit.Rows("0")) // default value is 0 tk.MustExec("set global tidb_remove_orderby_in_subquery=1") tk.MustQuery("select @@global.tidb_remove_orderby_in_subquery").Check(testkit.Rows("1")) + + // the value of max_allowed_packet should be a multiple of 1024 + tk.MustExec("set @@global.max_allowed_packet=16385") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_allowed_packet value: '16385'")) + result := tk.MustQuery("select @@global.max_allowed_packet;") + result.Check(testkit.Rows("16384")) + tk.MustExec("set @@global.max_allowed_packet=2047") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_allowed_packet value: '2047'")) + result = tk.MustQuery("select @@global.max_allowed_packet;") + result.Check(testkit.Rows("1024")) + tk.MustExec("set @@global.max_allowed_packet=0") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_allowed_packet value: '0'")) + result = tk.MustQuery("select @@global.max_allowed_packet;") + result.Check(testkit.Rows("1024")) + + // for read-only instance scoped system variables. + tk.MustGetErrCode("set @@global.plugin_load = ''", errno.ErrIncorrectGlobalLocalVar) + tk.MustGetErrCode("set @@global.plugin_dir = ''", errno.ErrIncorrectGlobalLocalVar) } func TestTruncateIncorrectIntSessionVar(t *testing.T) { @@ -898,6 +923,9 @@ func TestValidateSetVar(t *testing.T) { err = tk.ExecToErr("set @@global.max_allowed_packet='hello'") require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) + err = tk.ExecToErr("set @@max_allowed_packet=default") + require.True(t, terror.ErrorEqual(err, variable.ErrReadOnly)) + tk.MustExec("set @@global.max_connect_errors=18446744073709551615") tk.MustExec("set @@global.max_connect_errors=-1") @@ -1308,28 +1336,16 @@ func TestEnableNoopFunctionsVar(t *testing.T) { tk.MustQuery(`select @@global.tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - err := tk.ExecToErr(`select get_lock('lock1', 2);`) - require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) - err = tk.ExecToErr(`select release_lock('lock1');`) - require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) - // change session var to 1 tk.MustExec(`set tidb_enable_noop_functions=1;`) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("ON")) tk.MustQuery(`select @@global.tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - tk.MustQuery(`select get_lock("lock", 10)`).Check(testkit.Rows("1")) - tk.MustQuery(`select release_lock("lock")`).Check(testkit.Rows("1")) // restore to 0 tk.MustExec(`set tidb_enable_noop_functions=0;`) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) tk.MustQuery(`select @@global.tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - err = tk.ExecToErr(`select get_lock('lock2', 10);`) - require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) - err = tk.ExecToErr(`select release_lock('lock2');`) - require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) - // set test require.Error(t, tk.ExecToErr(`set tidb_enable_noop_functions='abc'`)) require.Error(t, tk.ExecToErr(`set tidb_enable_noop_functions=11`)) @@ -1340,7 +1356,7 @@ func TestEnableNoopFunctionsVar(t *testing.T) { tk.MustExec(`set tidb_enable_noop_functions=0;`) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - err = tk.ExecToErr("SET SESSION tx_read_only = 1") + err := tk.ExecToErr("SET SESSION tx_read_only = 1") require.True(t, terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) tk.MustExec("SET SESSION tx_read_only = 0") @@ -1435,6 +1451,30 @@ func TestDefaultBehavior(t *testing.T) { tk.MustExec("SET GLOBAL sql_mode = DEFAULT") } +func TestTiDBReadOnly(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + // turn on tidb_restricted_read_only should turn on tidb_super_read_only + tk.MustExec("SET GLOBAL tidb_restricted_read_only = ON") + tk.MustQuery("SELECT @@GLOBAL.tidb_super_read_only").Check(testkit.Rows("1")) + + // can't turn off tidb_super_read_only if tidb_restricted_read_only is on + err := tk.ExecToErr("SET GLOBAL tidb_super_read_only = OFF") + require.Error(t, err) + require.Equal(t, "can't turn off tidb_super_read_only when tidb_restricted_read_only is on", err.Error()) + + // turn off tidb_restricted_read_only won't affect tidb_super_read_only + tk.MustExec("SET GLOBAL tidb_restricted_read_only = OFF") + tk.MustQuery("SELECT @@GLOBAL.tidb_restricted_read_only").Check(testkit.Rows("0")) + tk.MustQuery("SELECT @@GLOBAL.tidb_super_read_only").Check(testkit.Rows("1")) + + // it is ok to turn off tidb_super_read_only now + tk.MustExec("SET GLOBAL tidb_super_read_only = OFF") + tk.MustQuery("SELECT @@GLOBAL.tidb_super_read_only").Check(testkit.Rows("0")) +} + func TestRemovedSysVars(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1513,7 +1553,7 @@ func TestSetClusterConfigJSONData(t *testing.T) { var d types.MyDecimal require.NoError(t, d.FromFloat64(123.456)) tyBool := types.NewFieldType(mysql.TypeTiny) - tyBool.Flag |= mysql.IsBooleanFlag + tyBool.AddFlag(mysql.IsBooleanFlag) cases := []struct { val expression.Expression result string diff --git a/executor/show.go b/executor/show.go index 5e6c9afc93070..b4196d02bbe6e 100644 --- a/executor/show.go +++ b/executor/show.go @@ -24,7 +24,6 @@ import ( "strings" "time" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" @@ -61,6 +60,7 @@ import ( "github.com/pingcap/tidb/util/format" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/hint" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/set" @@ -108,12 +108,12 @@ func (e *ShowExec) Next(ctx context.Context, req *chunk.Chunk) error { iter := chunk.NewIterator4Chunk(e.result) for colIdx := 0; colIdx < e.Schema().Len(); colIdx++ { retType := e.Schema().Columns[colIdx].RetType - if !types.IsTypeVarchar(retType.Tp) { + if !types.IsTypeVarchar(retType.GetType()) { continue } for row := iter.Begin(); row != iter.End(); row = iter.Next() { - if valLen := len(row.GetString(colIdx)); retType.Flen < valLen { - retType.Flen = valLen + if valLen := len(row.GetString(colIdx)); retType.GetFlen() < valLen { + retType.SetFlen(valLen) } } } @@ -603,14 +603,14 @@ func (e *ShowExec) fetchShowColumns(ctx context.Context) error { // SHOW COLUMNS result expects string value defaultValStr := fmt.Sprintf("%v", desc.DefaultValue) // If column is timestamp, and default value is not current_timestamp, should convert the default value to the current session time zone. - if col.Tp == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr && !strings.HasPrefix(strings.ToUpper(defaultValStr), strings.ToUpper(ast.CurrentTimestamp)) { + if col.GetType() == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr && !strings.HasPrefix(strings.ToUpper(defaultValStr), strings.ToUpper(ast.CurrentTimestamp)) { timeValue, err := table.GetColDefaultValue(e.ctx, col.ToInfo()) if err != nil { return errors.Trace(err) } defaultValStr = timeValue.GetMysqlTime().String() } - if col.Tp == mysql.TypeBit { + if col.GetType() == mysql.TypeBit { defaultValBinaryLiteral := types.BinaryLiteral(defaultValStr) columnDefault = defaultValBinaryLiteral.ToBitLiteralString(true) } else { @@ -661,7 +661,7 @@ func (e *ShowExec) fetchShowIndex() error { if tb.Meta().PKIsHandle { var pkCol *table.Column for _, col := range tb.Cols() { - if mysql.HasPriKeyFlag(col.Flag) { + if mysql.HasPriKeyFlag(col.GetFlag()) { pkCol = col break } @@ -707,7 +707,7 @@ func (e *ShowExec) fetchShowIndex() error { tblCol := tb.Meta().Columns[col.Offset] nullVal := "YES" - if mysql.HasNotNullFlag(tblCol.Flag) { + if mysql.HasNotNullFlag(tblCol.GetFlag()) { nullVal = "" } @@ -924,16 +924,16 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T buf.WriteString(",\n") } fmt.Fprintf(buf, " %s %s", stringutil.Escape(col.Name.O, sqlMode), col.GetTypeDesc()) - if col.Charset != "binary" { - if col.Charset != tblCharset { - fmt.Fprintf(buf, " CHARACTER SET %s", col.Charset) + if col.GetCharset() != "binary" { + if col.GetCharset() != tblCharset { + fmt.Fprintf(buf, " CHARACTER SET %s", col.GetCharset()) } - if col.Collate != tblCollate { - fmt.Fprintf(buf, " COLLATE %s", col.Collate) + if col.GetCollate() != tblCollate { + fmt.Fprintf(buf, " COLLATE %s", col.GetCollate()) } else { - defcol, err := charset.GetDefaultCollation(col.Charset) - if err == nil && defcol != col.Collate { - fmt.Fprintf(buf, " COLLATE %s", col.Collate) + defcol, err := charset.GetDefaultCollation(col.GetCharset()) + if err == nil && defcol != col.GetCollate() { + fmt.Fprintf(buf, " COLLATE %s", col.GetCollate()) } } } @@ -946,33 +946,33 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T buf.WriteString(" VIRTUAL") } } - if mysql.HasAutoIncrementFlag(col.Flag) { + if mysql.HasAutoIncrementFlag(col.GetFlag()) { hasAutoIncID = true buf.WriteString(" NOT NULL AUTO_INCREMENT") } else { - if mysql.HasNotNullFlag(col.Flag) { + if mysql.HasNotNullFlag(col.GetFlag()) { buf.WriteString(" NOT NULL") } // default values are not shown for generated columns in MySQL - if !mysql.HasNoDefaultValueFlag(col.Flag) && !col.IsGenerated() { + if !mysql.HasNoDefaultValueFlag(col.GetFlag()) && !col.IsGenerated() { defaultValue := col.GetDefaultValue() switch defaultValue { case nil: - if !mysql.HasNotNullFlag(col.Flag) { - if col.Tp == mysql.TypeTimestamp { + if !mysql.HasNotNullFlag(col.GetFlag()) { + if col.GetType() == mysql.TypeTimestamp { buf.WriteString(" NULL") } buf.WriteString(" DEFAULT NULL") } case "CURRENT_TIMESTAMP": buf.WriteString(" DEFAULT CURRENT_TIMESTAMP") - if col.Decimal > 0 { - buf.WriteString(fmt.Sprintf("(%d)", col.Decimal)) + if col.GetDecimal() > 0 { + buf.WriteString(fmt.Sprintf("(%d)", col.GetDecimal())) } default: defaultValStr := fmt.Sprintf("%v", defaultValue) // If column is timestamp, and default value is not current_timestamp, should convert the default value to the current session time zone. - if col.Tp == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr { + if col.GetType() == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr { timeValue, err := table.GetColDefaultValue(ctx, col) if err != nil { return errors.Trace(err) @@ -980,7 +980,7 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T defaultValStr = timeValue.GetMysqlTime().String() } - if col.Tp == mysql.TypeBit { + if col.GetType() == mysql.TypeBit { defaultValBinaryLiteral := types.BinaryLiteral(defaultValStr) fmt.Fprintf(buf, " DEFAULT %s", defaultValBinaryLiteral.ToBitLiteralString(true)) } else if col.DefaultIsExpr { @@ -990,7 +990,7 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T } } } - if mysql.HasOnUpdateNowFlag(col.Flag) { + if mysql.HasOnUpdateNowFlag(col.GetFlag()) { buf.WriteString(" ON UPDATE CURRENT_TIMESTAMP") buf.WriteString(table.OptionalFsp(&col.FieldType)) } @@ -1004,7 +1004,7 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T if i != len(tableInfo.Cols())-1 { needAddComma = true } - if tableInfo.PKIsHandle && mysql.HasPriKeyFlag(col.Flag) { + if tableInfo.PKIsHandle && mysql.HasPriKeyFlag(col.GetFlag()) { pkCol = col } } @@ -1895,9 +1895,15 @@ func (e *ShowExec) fetchShowBuiltins() error { // Because view's underlying table's column could change or recreate, so view's column type may change over time. // To avoid this situation we need to generate a logical plan and extract current column types from Schema. func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, dbName model.CIStr, tbl *model.TableInfo) error { - if tbl.IsView() { + if !tbl.IsView() { + return nil + } + // We need to run the build plan process in another session because there may be + // multiple goroutines running at the same time while session is not goroutine-safe. + // Take joining system table as an example, `fetchBuildSideRows` and `fetchProbeSideChunks` can be run concurrently. + return runWithSystemSession(sctx, func(s sessionctx.Context) error { // Retrieve view columns info. - planBuilder, _ := plannercore.NewPlanBuilder().Init(sctx, is, &hint.BlockHintProcessor{}) + planBuilder, _ := plannercore.NewPlanBuilder().Init(s, is, &hint.BlockHintProcessor{}) if viewLogicalPlan, err := planBuilder.BuildDataSourceFromView(ctx, dbName, tbl); err == nil { viewSchema := viewLogicalPlan.Schema() viewOutputNames := viewLogicalPlan.OutputNames() @@ -1906,13 +1912,30 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info if idx >= 0 { col.FieldType = *viewSchema.Columns[idx].GetType() } - if col.Tp == mysql.TypeVarString { - col.Tp = mysql.TypeVarchar + if col.GetType() == mysql.TypeVarString { + col.SetType(mysql.TypeVarchar) } } } else { return err } + return nil + }) +} + +func runWithSystemSession(sctx sessionctx.Context, fn func(sessionctx.Context) error) error { + b := &baseExecutor{ctx: sctx} + sysCtx, err := b.getSysSession() + if err != nil { + return err } - return nil + // TODO(tangenta): remove the CurrentDB assignment after + // https://github.com/pingcap/tidb/issues/34090 is fixed. + originDB := sysCtx.GetSessionVars().CurrentDB + sysCtx.GetSessionVars().CurrentDB = sctx.GetSessionVars().CurrentDB + defer func() { + sysCtx.GetSessionVars().CurrentDB = originDB + }() + defer b.releaseSysSession(sysCtx) + return fn(sysCtx) } diff --git a/executor/show_stats.go b/executor/show_stats.go index 7104372496c25..1f8f6fef0048a 100644 --- a/executor/show_stats.go +++ b/executor/show_stats.go @@ -251,7 +251,7 @@ func (e *ShowExec) appendTableForStatsBuckets(dbName, tblName, partitionName str if err != nil { return errors.Trace(err) } - colNameToType[col.Info.Name.O] = col.Histogram.Tp.Tp + colNameToType[col.Info.Name.O] = col.Histogram.Tp.GetType() } for _, idx := range stableIdxsStats(statsTbl.Indices) { idxColumnTypes := make([]byte, 0, len(idx.Info.Columns)) @@ -306,11 +306,11 @@ func (e *ShowExec) appendTableForStatsTopN(dbName, tblName, partitionName string } colNameToType := make(map[string]byte, len(statsTbl.Columns)) for _, col := range stableColsStats(statsTbl.Columns) { - err := e.topNToRows(dbName, tblName, partitionName, col.Info.Name.O, 1, 0, col.TopN, []byte{col.Histogram.Tp.Tp}) + err := e.topNToRows(dbName, tblName, partitionName, col.Info.Name.O, 1, 0, col.TopN, []byte{col.Histogram.Tp.GetType()}) if err != nil { return errors.Trace(err) } - colNameToType[col.Info.Name.O] = col.Histogram.Tp.Tp + colNameToType[col.Info.Name.O] = col.Histogram.Tp.GetType() } for _, idx := range stableIdxsStats(statsTbl.Indices) { idxColumnTypes := make([]byte, 0, len(idx.Info.Columns)) diff --git a/executor/show_test.go b/executor/show_test.go index 2e6f69688b09f..f8772d3a4b50a 100644 --- a/executor/show_test.go +++ b/executor/show_test.go @@ -141,6 +141,11 @@ func TestShowErrors(t *testing.T) { _, _ = tk.Exec(testSQL) tk.MustQuery("show errors").Check(testkit.RowsWithSep("|", "Error|1050|Table 'test.show_errors' already exists")) + + // eliminate previous errors + tk.MustExec("select 1") + _, _ = tk.Exec("create invalid") + tk.MustQuery("show errors").Check(testkit.RowsWithSep("|", "Error|1064|You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 14 near \"invalid\" ")) } func TestShowWarningsForExprPushdown(t *testing.T) { @@ -521,12 +526,12 @@ func TestCollation(t *testing.T) { rs, err := tk.Exec("show collation;") require.NoError(t, err) fields := rs.Fields() - require.Equal(t, mysql.TypeVarchar, fields[0].Column.Tp) - require.Equal(t, mysql.TypeVarchar, fields[1].Column.Tp) - require.Equal(t, mysql.TypeLonglong, fields[2].Column.Tp) - require.Equal(t, mysql.TypeVarchar, fields[3].Column.Tp) - require.Equal(t, mysql.TypeVarchar, fields[4].Column.Tp) - require.Equal(t, mysql.TypeLonglong, fields[5].Column.Tp) + require.Equal(t, mysql.TypeVarchar, fields[0].Column.GetType()) + require.Equal(t, mysql.TypeVarchar, fields[1].Column.GetType()) + require.Equal(t, mysql.TypeLonglong, fields[2].Column.GetType()) + require.Equal(t, mysql.TypeVarchar, fields[3].Column.GetType()) + require.Equal(t, mysql.TypeVarchar, fields[4].Column.GetType()) + require.Equal(t, mysql.TypeLonglong, fields[5].Column.GetType()) } func TestShowTableStatus(t *testing.T) { diff --git a/executor/shuffle_test.go b/executor/shuffle_test.go index 92f96cf74654c..9643fbd6f3a52 100644 --- a/executor/shuffle_test.go +++ b/executor/shuffle_test.go @@ -29,7 +29,7 @@ func TestPartitionRangeSplitter(t *testing.T) { ctx := mock.NewContext() concurrency := 2 - tp := &types.FieldType{Tp: mysql.TypeVarchar} + tp := types.NewFieldTypeBuilderP().SetType(mysql.TypeVarchar).BuildP() col0 := &expression.Column{ RetType: tp, Index: 0, diff --git a/executor/simple.go b/executor/simple.go index 8fbe8ee40498e..88cf258f13fad 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -1608,8 +1608,20 @@ func (e *SimpleExec) executeDropStats(s *ast.DropStatsStmt) (err error) { } func (e *SimpleExec) autoNewTxn() bool { + // Some statements cause an implicit commit + // See https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html switch e.Statement.(type) { - case *ast.CreateUserStmt, *ast.AlterUserStmt, *ast.DropUserStmt, *ast.RenameUserStmt: + // Data definition language (DDL) statements that define or modify database objects. + // (handled in DDL package) + // Statements that implicitly use or modify tables in the mysql database. + case *ast.CreateUserStmt, *ast.AlterUserStmt, *ast.DropUserStmt, *ast.RenameUserStmt, *ast.RevokeRoleStmt, *ast.GrantRoleStmt: + return true + // Transaction-control and locking statements. BEGIN, LOCK TABLES, SET autocommit = 1 (if the value is not already 1), START TRANSACTION, UNLOCK TABLES. + // (handled in other place) + // Data loading statements. LOAD DATA + // (handled in other place) + // Administrative statements. TODO: ANALYZE TABLE, CACHE INDEX, CHECK TABLE, FLUSH, LOAD INDEX INTO CACHE, OPTIMIZE TABLE, REPAIR TABLE, RESET (but not RESET PERSIST). + case *ast.FlushStmt: return true } return false diff --git a/executor/simple_test.go b/executor/simple_test.go index 8cb304e2ef43b..25e769ca68ebe 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -1049,3 +1049,29 @@ func TestUserWithSetNames(t *testing.T) { tk.MustExec("drop user '\xd2\xbb';") } + +func TestStatementsCauseImplicitCommit(t *testing.T) { + // Test some of the implicit commit statements. + // See https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("create table ic (id int primary key)") + + cases := []string{ + "create table xx (id int)", + "create user 'xx'@'127.0.0.1'", + "grant SELECT on test.ic to 'xx'@'127.0.0.1'", + "flush privileges", + "analyze table ic", + } + for i, sql := range cases { + tk.MustExec("begin") + tk.MustExec("insert into ic values (?)", i) + tk.MustExec(sql) + tk.MustQuery("select * from ic where id = ?", i).Check(testkit.Rows(strconv.FormatInt(int64(i), 10))) + // Clean up data + tk.MustExec("delete from ic") + } +} diff --git a/executor/slow_query.go b/executor/slow_query.go index 5d08e568e8712..20b1e4d27f18d 100755 --- a/executor/slow_query.go +++ b/executor/slow_query.go @@ -26,6 +26,7 @@ import ( "sort" "strconv" "strings" + "sync" "sync/atomic" "time" @@ -72,6 +73,7 @@ type slowQueryRetriever struct { memTracker *memory.Tracker lastFetchSize int64 cancel context.CancelFunc + wg sync.WaitGroup } func (e *slowQueryRetriever) retrieve(ctx context.Context, sctx sessionctx.Context) ([][]types.Datum, error) { @@ -156,6 +158,7 @@ func (e *slowQueryRetriever) close() error { if e.cancel != nil { e.cancel() } + e.wg.Wait() return nil } @@ -198,6 +201,7 @@ func (e *slowQueryRetriever) getPreviousFile() *os.File { } func (e *slowQueryRetriever) parseDataForSlowLog(ctx context.Context, sctx sessionctx.Context) { + defer e.wg.Done() file := e.getNextFile() if file == nil { close(e.taskList) @@ -435,7 +439,6 @@ func decomposeToSlowLogTasks(logs []slowLogBlock, num int) [][]string { func (e *slowQueryRetriever) parseSlowLog(ctx context.Context, sctx sessionctx.Context, reader *bufio.Reader, logNum int) { defer close(e.taskList) - var wg util.WaitGroupWrapper offset := offset{offset: 0, length: 0} // To limit the num of go routine concurrent := sctx.GetSessionVars().Concurrency.DistSQLScanConcurrency() @@ -487,11 +490,13 @@ func (e *slowQueryRetriever) parseSlowLog(ctx context.Context, sctx sessionctx.C return case e.taskList <- t: } - wg.Run(func() { + e.wg.Add(1) + go func() { + defer e.wg.Done() result, err := e.parseLog(ctx, sctx, log, start) e.sendParsedSlowLogCh(t, parsedSlowLog{result, err}) <-ch - }) + }() offset.offset = e.fileLine offset.length = 0 select { @@ -501,7 +506,6 @@ func (e *slowQueryRetriever) parseSlowLog(ctx context.Context, sctx sessionctx.C } } } - wg.Wait() } func (e *slowQueryRetriever) sendParsedSlowLogCh(t slowLogTask, re parsedSlowLog) { @@ -1113,6 +1117,7 @@ func readLastLines(ctx context.Context, file *os.File, endCursor int64) ([]strin func (e *slowQueryRetriever) initializeAsyncParsing(ctx context.Context, sctx sessionctx.Context) { e.taskList = make(chan slowLogTask, 1) + e.wg.Add(1) go e.parseDataForSlowLog(ctx, sctx) } diff --git a/executor/slow_query_sql_test.go b/executor/slow_query_sql_test.go index 7731adab29dd2..a1be7d6664576 100644 --- a/executor/slow_query_sql_test.go +++ b/executor/slow_query_sql_test.go @@ -33,7 +33,7 @@ func TestSlowQueryWithoutSlowLog(t *testing.T) { originCfg := config.GetGlobalConfig() newCfg := *originCfg newCfg.Log.SlowQueryFile = "tidb-slow-not-exist.log" - newCfg.Log.SlowThreshold = math.MaxUint64 + newCfg.Instance.SlowThreshold = math.MaxUint64 config.StoreGlobalConfig(&newCfg) defer func() { config.StoreGlobalConfig(originCfg) diff --git a/executor/sort.go b/executor/sort.go index d60f45afc0ca4..83b7bc59264af 100644 --- a/executor/sort.go +++ b/executor/sort.go @@ -20,7 +20,6 @@ import ( "errors" "sort" - "github.com/cznic/mathutil" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/expression" @@ -28,6 +27,7 @@ import ( "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/disk" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" ) diff --git a/executor/sort_test.go b/executor/sort_test.go index d895e93153a26..7ce9589342b3b 100644 --- a/executor/sort_test.go +++ b/executor/sort_test.go @@ -51,7 +51,7 @@ func testSortInDisk(t *testing.T, removeDir bool) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - sm := &mockSessionManager1{ + sm := &testkit.MockSessionManager{ PS: make([]*util.ProcessInfo, 0), } tk.Session().SetSessionManager(sm) diff --git a/executor/split.go b/executor/split.go index 89fa8b78f1879..e31f894849685 100644 --- a/executor/split.go +++ b/executor/split.go @@ -22,7 +22,6 @@ import ( "math" "time" - "github.com/cznic/mathutil" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" @@ -36,6 +35,7 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/mathutil" "github.com/tikv/client-go/v2/tikv" "go.uber.org/zap" ) @@ -538,7 +538,7 @@ func (e *SplitTableRegionExec) calculateIntBoundValue() (lowerValue int64, step isUnsigned := false if e.tableInfo.PKIsHandle { if pkCol := e.tableInfo.GetPkColInfo(); pkCol != nil { - isUnsigned = mysql.HasUnsignedFlag(pkCol.Flag) + isUnsigned = mysql.HasUnsignedFlag(pkCol.GetFlag()) } } if isUnsigned { @@ -629,7 +629,7 @@ func getPhysicalTableRegions(physicalTableID int64, tableInfo *model.TableInfo, // This is used to decode the int handle properly. var hasUnsignedIntHandle bool if pkInfo := tableInfo.GetPkColInfo(); pkInfo != nil { - hasUnsignedIntHandle = mysql.HasUnsignedFlag(pkInfo.Flag) + hasUnsignedIntHandle = mysql.HasUnsignedFlag(pkInfo.GetFlag()) } // for record startKey, endKey := tablecodec.GetTableHandleKeyRange(physicalTableID) diff --git a/executor/stale_txn_test.go b/executor/stale_txn_test.go index 1789e4dd4e612..62255326cbce0 100644 --- a/executor/stale_txn_test.go +++ b/executor/stale_txn_test.go @@ -24,23 +24,26 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" ) -func enableStalereadCommonFailPoint(t *testing.T) func() { +func enableStaleReadCommonFailPoint(t *testing.T) func() { require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder", "return")) require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertNotStaleReadForExecutorGetReadTS", "return")) return func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertNotStaleReadForExecutorGetReadTS")) require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan")) } } func TestExactStalenessTransaction(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() testcases := []struct { name string @@ -105,7 +108,7 @@ func TestExactStalenessTransaction(t *testing.T) { } func TestSelectAsOf(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -263,7 +266,7 @@ func TestSelectAsOf(t *testing.T) { } func TestStaleReadKVRequest(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -361,7 +364,7 @@ func TestStaleReadKVRequest(t *testing.T) { } func TestStalenessAndHistoryRead(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -448,7 +451,7 @@ func TestStalenessAndHistoryRead(t *testing.T) { } func TestTimeBoundedStalenessTxn(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -547,7 +550,7 @@ func TestStalenessTransactionSchemaVer(t *testing.T) { } func TestSetTransactionReadOnlyAsOf(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() t1, err := time.Parse(types.TimeFormat, "2016-09-21 09:53:04") @@ -617,7 +620,7 @@ func TestSetTransactionReadOnlyAsOf(t *testing.T) { } func TestValidateReadOnlyInStalenessTransaction(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() errMsg1 := ".*only support read-only statement during read-only staleness transactions.*" @@ -799,7 +802,7 @@ func TestValidateReadOnlyInStalenessTransaction(t *testing.T) { } func TestSpecialSQLInStalenessTxn(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -857,7 +860,7 @@ func TestSpecialSQLInStalenessTxn(t *testing.T) { } func TestAsOfTimestampCompatibility(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -917,7 +920,7 @@ func TestAsOfTimestampCompatibility(t *testing.T) { } func TestSetTransactionInfoSchema(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -961,7 +964,7 @@ func TestSetTransactionInfoSchema(t *testing.T) { } func TestStaleSelect(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1031,8 +1034,6 @@ func TestStaleReadFutureTime(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int)") // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) _, err := tk.Exec("start transaction read only as of timestamp '2038-01-18 03:14:07'") @@ -1050,7 +1051,7 @@ func TestStaleReadFutureTime(t *testing.T) { } func TestStaleReadPrepare(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1109,7 +1110,7 @@ func TestStaleReadPrepare(t *testing.T) { } func TestStmtCtxStaleFlag(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1202,12 +1203,12 @@ func TestStmtCtxStaleFlag(t *testing.T) { tk.MustExec(testcase.sql) require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/exector/assertStmtCtxIsStaleness")) // assert stale read flag should be false after each statement execution - require.False(t, tk.Session().GetSessionVars().StmtCtx.IsStaleness) + require.False(t, staleread.IsStmtStaleness(tk.Session())) } } func TestStaleSessionQuery(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1250,7 +1251,7 @@ func TestStaleSessionQuery(t *testing.T) { } func TestStaleReadCompatibility(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1299,7 +1300,7 @@ func TestStaleReadCompatibility(t *testing.T) { } func TestStaleReadNoExtraTSORequest(t *testing.T) { - disableCommonFailPoint := enableStalereadCommonFailPoint(t) + disableCommonFailPoint := enableStaleReadCommonFailPoint(t) defer disableCommonFailPoint() store, clean := testkit.CreateMockStore(t) @@ -1363,15 +1364,17 @@ func TestPlanCacheWithStaleReadByBinaryProto(t *testing.T) { tk.MustExec("set @a=now(6)") time.Sleep(time.Second) tk.MustExec("update t1 set v=100 where id=1") + + // issue #31550 stmtID1, _, _, err := se.PrepareStmt("select * from t1 as of timestamp @a where id=1") require.NoError(t, err) - for i := 0; i < 3; i++ { rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID1, nil) require.NoError(t, err) tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) } + // issue #33814 stmtID2, _, _, err := se.PrepareStmt("select * from t1 where id=1") require.NoError(t, err) for i := 0; i < 2; i++ { @@ -1382,7 +1385,6 @@ func TestPlanCacheWithStaleReadByBinaryProto(t *testing.T) { tk.MustExec("set @@tx_read_ts=@a") rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID2, nil) require.NoError(t, err) - // will fail tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) } @@ -1419,3 +1421,23 @@ func TestIssue33728(t *testing.T) { require.Error(t, err) require.Equal(t, "[planner:8135]invalid as of timestamp: as of timestamp cannot be NULL", err.Error()) } + +func TestIssue31954(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (id int primary key, v int)") + tk.MustExec("insert into t1 values(1, 10)") + time.Sleep(time.Millisecond * 100) + tk.MustExec("set @a=now(6)") + time.Sleep(time.Millisecond * 100) + tk.MustExec("update t1 set v=100 where id=1") + + tk.MustQuery("select * from t1 as of timestamp @a where v=(select v from t1 as of timestamp @a where id=1)"). + Check(testkit.Rows("1 10")) + + tk.MustQuery("select (select v from t1 as of timestamp @a where id=1) as v"). + Check(testkit.Rows("10")) +} diff --git a/executor/statement_context_test.go b/executor/statement_context_test.go index 32720bd6cc36b..dc9bcca07ce7f 100644 --- a/executor/statement_context_test.go +++ b/executor/statement_context_test.go @@ -129,11 +129,11 @@ func TestStatementContext(t *testing.T) { require.Error(t, err) require.Truef(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), "err %v", err) config.UpdateGlobal(func(conf *config.Config) { - conf.CheckMb4ValueInUTF8.Store(false) + conf.Instance.CheckMb4ValueInUTF8.Store(false) }) tk.MustExec("insert t1 values (unhex('f09f8c80'))") config.UpdateGlobal(func(conf *config.Config) { - conf.CheckMb4ValueInUTF8.Store(true) + conf.Instance.CheckMb4ValueInUTF8.Store(true) }) _, err = tk.Exec("insert t1 values (unhex('F0A48BAE'))") require.Error(t, err) diff --git a/executor/table_readers_required_rows_test.go b/executor/table_readers_required_rows_test.go index 73044de929a8e..406723b8e51af 100644 --- a/executor/table_readers_required_rows_test.go +++ b/executor/table_readers_required_rows_test.go @@ -20,7 +20,6 @@ import ( "math/rand" "testing" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" @@ -32,6 +31,7 @@ import ( "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" ) @@ -80,7 +80,7 @@ func (r *requiredRowsSelectResult) genOneRow() chunk.Row { } func (r *requiredRowsSelectResult) genValue(valType *types.FieldType) interface{} { - switch valType.Tp { + switch valType.GetType() { case mysql.TypeLong, mysql.TypeLonglong: return int64(rand.Int()) case mysql.TypeDouble: diff --git a/executor/testdata/executor_suite_out.json b/executor/testdata/executor_suite_out.json index d2ad1621f6049..efd3bf3bd7a6d 100644 --- a/executor/testdata/executor_suite_out.json +++ b/executor/testdata/executor_suite_out.json @@ -308,9 +308,10 @@ "HashJoin_7 6400.00 root anti semi join, equal:[nulleq(test.t1.a, test.t3.a)], other cond:nulleq(cast(test.t1.b, decimal(20,0) BINARY), test.t3.b)", "├─TableReader_18(Build) 10000.00 root data:TableFullScan_17", "│ └─TableFullScan_17 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", - "└─HashAgg_10(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", - " └─TableReader_15 10000.00 root data:TableFullScan_14", - " └─TableFullScan_14 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "└─HashAgg_12(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", + " └─TableReader_13 8000.00 root data:HashAgg_8", + " └─HashAgg_8 8000.00 cop[tikv] group by:test.t1.a, test.t1.b, ", + " └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Res": [ "1 1", @@ -324,9 +325,10 @@ "HashJoin_7 6400.00 root semi join, equal:[nulleq(test.t1.a, test.t2.a)], other cond:nulleq(cast(test.t1.b, double BINARY), cast(test.t2.b, double BINARY))", "├─TableReader_18(Build) 10000.00 root data:TableFullScan_17", "│ └─TableFullScan_17 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - "└─HashAgg_10(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", - " └─TableReader_15 10000.00 root data:TableFullScan_14", - " └─TableFullScan_14 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "└─HashAgg_12(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", + " └─TableReader_13 8000.00 root data:HashAgg_8", + " └─HashAgg_8 8000.00 cop[tikv] group by:test.t1.a, test.t1.b, ", + " └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Res": [ "1 1", @@ -392,9 +394,10 @@ "└─HashJoin_14(Probe) 6400.00 root semi join, equal:[nulleq(test.t1.a, test.t2.a)], other cond:nulleq(cast(test.t1.b, double BINARY), cast(test.t2.b, double BINARY))", " ├─TableReader_24(Build) 10000.00 root data:TableFullScan_23", " │ └─TableFullScan_23 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─HashAgg_17(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", - " └─TableReader_22 10000.00 root data:TableFullScan_21", - " └─TableFullScan_21 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + " └─HashAgg_19(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", + " └─TableReader_20 8000.00 root data:HashAgg_15", + " └─HashAgg_15 8000.00 cop[tikv] group by:test.t1.a, test.t1.b, ", + " └─TableFullScan_18 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Res": [ "1 1", @@ -412,9 +415,10 @@ "└─HashJoin_17 6400.00 root semi join, equal:[nulleq(test.t2.a, test.t3.a)], other cond:nulleq(cast(test.t2.b, double BINARY), cast(test.t3.b, double BINARY))", " ├─TableReader_27(Build) 10000.00 root data:TableFullScan_26", " │ └─TableFullScan_26 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", - " └─HashAgg_20(Probe) 8000.00 root group by:test.t2.a, test.t2.b, funcs:firstrow(test.t2.a)->test.t2.a, funcs:firstrow(test.t2.b)->test.t2.b", - " └─TableReader_25 10000.00 root data:TableFullScan_24", - " └─TableFullScan_24 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + " └─HashAgg_22(Probe) 8000.00 root group by:test.t2.a, test.t2.b, funcs:firstrow(test.t2.a)->test.t2.a, funcs:firstrow(test.t2.b)->test.t2.b", + " └─TableReader_23 8000.00 root data:HashAgg_18", + " └─HashAgg_18 8000.00 cop[tikv] group by:test.t2.a, test.t2.b, ", + " └─TableFullScan_21 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Res": [ "1 1", @@ -431,12 +435,14 @@ "├─HashJoin_20(Build) 6400.00 root semi join, equal:[nulleq(test.t2.a, test.t3.a)], other cond:nulleq(cast(test.t2.b, double BINARY), cast(test.t3.b, double BINARY))", "│ ├─TableReader_31(Build) 10000.00 root data:TableFullScan_30", "│ │ └─TableFullScan_30 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", - "│ └─HashAgg_23(Probe) 8000.00 root group by:test.t2.a, test.t2.b, funcs:firstrow(test.t2.a)->test.t2.a, funcs:firstrow(test.t2.b)->test.t2.b", - "│ └─TableReader_28 10000.00 root data:TableFullScan_27", - "│ └─TableFullScan_27 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - "└─HashAgg_14(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", - " └─TableReader_19 10000.00 root data:TableFullScan_18", - " └─TableFullScan_18 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "│ └─HashAgg_25(Probe) 8000.00 root group by:test.t2.a, test.t2.b, funcs:firstrow(test.t2.a)->test.t2.a, funcs:firstrow(test.t2.b)->test.t2.b", + "│ └─TableReader_26 8000.00 root data:HashAgg_21", + "│ └─HashAgg_21 8000.00 cop[tikv] group by:test.t2.a, test.t2.b, ", + "│ └─TableFullScan_24 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─HashAgg_16(Probe) 8000.00 root group by:test.t1.a, test.t1.b, funcs:firstrow(test.t1.a)->test.t1.a, funcs:firstrow(test.t1.b)->test.t1.b", + " └─TableReader_17 8000.00 root data:HashAgg_12", + " └─HashAgg_12 8000.00 cop[tikv] group by:test.t1.a, test.t1.b, ", + " └─TableFullScan_15 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Res": [ "1 1", diff --git a/executor/union_scan.go b/executor/union_scan.go index f57c86ee32cd2..ef1077dfa0580 100644 --- a/executor/union_scan.go +++ b/executor/union_scan.go @@ -162,7 +162,7 @@ func (us *UnionScanExec) Next(ctx context.Context, req *chunk.Chunk) error { return err } // Handle the bad null error. - if (mysql.HasNotNullFlag(us.columns[idx].Flag) || mysql.HasPreventNullInsertFlag(us.columns[idx].Flag)) && castDatum.IsNull() { + if (mysql.HasNotNullFlag(us.columns[idx].GetFlag()) || mysql.HasPreventNullInsertFlag(us.columns[idx].GetFlag())) && castDatum.IsNull() { castDatum = table.GetZeroValue(us.columns[idx]) } mutableRow.SetDatum(idx, castDatum) diff --git a/executor/update.go b/executor/update.go index ed5c76f44c278..faf5b1d15e1bf 100644 --- a/executor/update.go +++ b/executor/update.go @@ -31,7 +31,6 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/memory" - topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" ) @@ -271,14 +270,13 @@ func (e *UpdateExec) updateRows(ctx context.Context) (int, error) { txn.GetSnapshot().SetOption(kv.CollectRuntimeStats, e.stats.SnapshotRuntimeStats) } } - if topsqlstate.TopSQLEnabled() { - txn, err := e.ctx.Txn(true) - if err == nil { - txn.SetOption(kv.ResourceGroupTagger, e.ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) - if e.ctx.GetSessionVars().StmtCtx.KvExecCounter != nil { - // Bind an interceptor for client-go to count the number of SQL executions of each TiKV. - txn.SetOption(kv.RPCInterceptor, e.ctx.GetSessionVars().StmtCtx.KvExecCounter.RPCInterceptor()) - } + txn, err := e.ctx.Txn(true) + if err == nil { + sc := e.ctx.GetSessionVars().StmtCtx + txn.SetOption(kv.ResourceGroupTagger, sc.GetResourceGroupTagger()) + if sc.KvExecCounter != nil { + // Bind an interceptor for client-go to count the number of SQL executions of each TiKV. + txn.SetOption(kv.RPCInterceptor, sc.KvExecCounter.RPCInterceptor()) } } for rowIdx := 0; rowIdx < chk.NumRows(); rowIdx++ { diff --git a/executor/window.go b/executor/window.go index 5a4ca189dcbad..3ce26a03e59cf 100644 --- a/executor/window.go +++ b/executor/window.go @@ -17,7 +17,6 @@ package executor import ( "context" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/executor/aggfuncs" "github.com/pingcap/tidb/expression" @@ -25,6 +24,7 @@ import ( "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) // WindowExec is the executor for window functions. diff --git a/executor/write.go b/executor/write.go index 62013156e63d6..49707f6417bf5 100644 --- a/executor/write.go +++ b/executor/write.go @@ -72,19 +72,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old // because all of them are sorted by their `Offset`, which // causes all writable columns are after public columns. - // 1. Cast modified values. - for i, col := range t.Cols() { - if modified[i] { - // Cast changed fields with respective columns. - v, err := table.CastValue(sctx, newData[i], col.ToInfo(), false, false) - if err != nil { - return false, err - } - newData[i] = v - } - } - - // 2. Handle the bad null error. + // Handle the bad null error. for i, col := range t.Cols() { var err error if err = col.HandleBadNull(&newData[i], sc); err != nil { @@ -92,7 +80,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old } } - // 3. Compare datum, then handle some flags. + // Compare datum, then handle some flags. for i, col := range t.Cols() { // We should use binary collation to compare datum, otherwise the result will be incorrect. cmp, err := newData[i].Compare(sc, &oldData[i], collate.GetBinaryCollator()) @@ -103,7 +91,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old changed = true modified[i] = true // Rebase auto increment id if the field is changed. - if mysql.HasAutoIncrementFlag(col.Flag) { + if mysql.HasAutoIncrementFlag(col.GetFlag()) { recordID, err := getAutoRecordID(newData[i], &col.FieldType, false) if err != nil { return false, err @@ -123,7 +111,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old handleChanged = true } } else { - if mysql.HasOnUpdateNowFlag(col.Flag) && modified[i] { + if mysql.HasOnUpdateNowFlag(col.GetFlag()) && modified[i] { // It's for "UPDATE t SET ts = ts" and ts is a timestamp. onUpdateSpecified[i] = true } @@ -156,10 +144,10 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old return false, nil } - // 4. Fill values into on-update-now fields, only if they are really changed. + // Fill values into on-update-now fields, only if they are really changed. for i, col := range t.Cols() { - if mysql.HasOnUpdateNowFlag(col.Flag) && !modified[i] && !onUpdateSpecified[i] { - if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.Tp, col.Decimal); err == nil { + if mysql.HasOnUpdateNowFlag(col.GetFlag()) && !modified[i] && !onUpdateSpecified[i] { + if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.GetType(), col.GetDecimal()); err == nil { newData[i] = v modified[i] = true } else { @@ -168,7 +156,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old } } - // 5. If handle changed, remove the old then add the new record, otherwise update the record. + // If handle changed, remove the old then add the new record, otherwise update the record. if handleChanged { // For `UPDATE IGNORE`/`INSERT IGNORE ON DUPLICATE KEY UPDATE` // we use the staging buffer so that we don't need to precheck the existence of handle or unique keys by sending diff --git a/expression/aggregation/aggregation.go b/expression/aggregation/aggregation.go index 84380552d7f71..19ab63afb28d3 100644 --- a/expression/aggregation/aggregation.go +++ b/expression/aggregation/aggregation.go @@ -69,9 +69,9 @@ func NewDistAggFunc(expr *tipb.Expr, fieldTps []*types.FieldType, sc *stmtctx.St case tipb.ExprType_GroupConcat: return &concatFunction{aggFunction: newAggFunc(ast.AggFuncGroupConcat, args, false)}, nil case tipb.ExprType_Max: - return &maxMinFunction{aggFunction: newAggFunc(ast.AggFuncMax, args, false), isMax: true, ctor: collate.GetCollator(args[0].GetType().Collate)}, nil + return &maxMinFunction{aggFunction: newAggFunc(ast.AggFuncMax, args, false), isMax: true, ctor: collate.GetCollator(args[0].GetType().GetCollate())}, nil case tipb.ExprType_Min: - return &maxMinFunction{aggFunction: newAggFunc(ast.AggFuncMin, args, false), ctor: collate.GetCollator(args[0].GetType().Collate)}, nil + return &maxMinFunction{aggFunction: newAggFunc(ast.AggFuncMin, args, false), ctor: collate.GetCollator(args[0].GetType().GetCollate())}, nil case tipb.ExprType_First: return &firstRowFunction{aggFunction: newAggFunc(ast.AggFuncFirstRow, args, false)}, nil case tipb.ExprType_Agg_BitOr: @@ -217,7 +217,7 @@ func CheckAggPushDown(aggFunc *AggFuncDesc, storeType kv.StoreType) bool { // CheckAggPushFlash checks whether an agg function can be pushed to flash storage. func CheckAggPushFlash(aggFunc *AggFuncDesc) bool { for _, arg := range aggFunc.Args { - if arg.GetType().Tp == mysql.TypeDuration { + if arg.GetType().GetType() == mysql.TypeDuration { return false } } diff --git a/expression/aggregation/avg.go b/expression/aggregation/avg.go index c1e32c92c847f..a08aeb4f5cc50 100644 --- a/expression/aggregation/avg.go +++ b/expression/aggregation/avg.go @@ -15,12 +15,12 @@ package aggregation import ( - "github.com/cznic/mathutil" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) type avgFunction struct { @@ -82,7 +82,7 @@ func (af *avgFunction) GetResult(evalCtx *AggEvaluateContext) (d types.Datum) { to := new(types.MyDecimal) err := types.DecimalDiv(x, y, to, types.DivFracIncr) terror.Log(err) - frac := af.RetTp.Decimal + frac := af.RetTp.GetDecimal() if frac == -1 { frac = mysql.MaxDecimalScale } diff --git a/expression/aggregation/base_func.go b/expression/aggregation/base_func.go index a185910c82b97..112aac07188eb 100644 --- a/expression/aggregation/base_func.go +++ b/expression/aggregation/base_func.go @@ -20,7 +20,6 @@ import ( "math" "strings" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser/ast" @@ -29,6 +28,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) // baseFuncDesc describes an function signature, only used in planner. @@ -128,10 +128,10 @@ func (a *baseFuncDesc) TypeInfer(ctx sessionctx.Context) error { func (a *baseFuncDesc) typeInfer4Count(ctx sessionctx.Context) { a.RetTp = types.NewFieldType(mysql.TypeLonglong) - a.RetTp.Flen = 21 - a.RetTp.Decimal = 0 + a.RetTp.SetFlen(21) + a.RetTp.SetDecimal(0) // count never returns null - a.RetTp.Flag |= mysql.NotNullFlag + a.RetTp.AddFlag(mysql.NotNullFlag) types.SetBinChsClnFlag(a.RetTp) } @@ -158,22 +158,23 @@ func (a *baseFuncDesc) typeInfer4ApproxPercentile(ctx sessionctx.Context) error return errors.New(fmt.Sprintf("Percentage value %d is out of range [1, 100]", percent)) } - switch a.Args[0].GetType().Tp { + switch a.Args[0].GetType().GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: a.RetTp = types.NewFieldType(mysql.TypeLonglong) case mysql.TypeDouble, mysql.TypeFloat: a.RetTp = types.NewFieldType(mysql.TypeDouble) case mysql.TypeNewDecimal: a.RetTp = types.NewFieldType(mysql.TypeNewDecimal) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxDecimalWidth, a.Args[0].GetType().Decimal - if a.RetTp.Decimal < 0 || a.RetTp.Decimal > mysql.MaxDecimalScale { - a.RetTp.Decimal = mysql.MaxDecimalScale + a.RetTp.SetFlen(mysql.MaxDecimalWidth) + a.RetTp.SetDecimal(a.Args[0].GetType().GetDecimal()) + if a.RetTp.GetDecimal() < 0 || a.RetTp.GetDecimal() > mysql.MaxDecimalScale { + a.RetTp.SetDecimal(mysql.MaxDecimalScale) } case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeNewDate, mysql.TypeTimestamp: a.RetTp = a.Args[0].GetType().Clone() default: a.RetTp = a.Args[0].GetType().Clone() - a.RetTp.Flag &= ^mysql.NotNullFlag + a.RetTp.DelFlag(mysql.NotNullFlag) } return nil } @@ -181,28 +182,32 @@ func (a *baseFuncDesc) typeInfer4ApproxPercentile(ctx sessionctx.Context) error // typeInfer4Sum should return a "decimal", otherwise it returns a "double". // Because child returns integer or decimal type. func (a *baseFuncDesc) typeInfer4Sum(ctx sessionctx.Context) { - switch a.Args[0].GetType().Tp { + switch a.Args[0].GetType().GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeYear: a.RetTp = types.NewFieldType(mysql.TypeNewDecimal) - a.RetTp.Flen, a.RetTp.Decimal = mathutil.Min(a.Args[0].GetType().Flen+21, mysql.MaxDecimalWidth), 0 - if a.Args[0].GetType().Flen < 0 || a.RetTp.Flen > mysql.MaxDecimalWidth { - a.RetTp.Flen = mysql.MaxDecimalWidth + a.RetTp.SetFlen(mathutil.Min(a.Args[0].GetType().GetFlen()+21, mysql.MaxDecimalWidth)) + a.RetTp.SetDecimal(0) + if a.Args[0].GetType().GetFlen() < 0 || a.RetTp.GetFlen() > mysql.MaxDecimalWidth { + a.RetTp.SetFlen(mysql.MaxDecimalWidth) } case mysql.TypeNewDecimal: a.RetTp = types.NewFieldType(mysql.TypeNewDecimal) - a.RetTp.Flen, a.RetTp.Decimal = a.Args[0].GetType().Flen+22, a.Args[0].GetType().Decimal - if a.Args[0].GetType().Flen < 0 || a.RetTp.Flen > mysql.MaxDecimalWidth { - a.RetTp.Flen = mysql.MaxDecimalWidth + a.RetTp.SetFlen(a.Args[0].GetType().GetFlen() + 22) + a.RetTp.SetDecimal(a.Args[0].GetType().GetDecimal()) + if a.Args[0].GetType().GetFlen() < 0 || a.RetTp.GetFlen() > mysql.MaxDecimalWidth { + a.RetTp.SetFlen(mysql.MaxDecimalWidth) } - if a.RetTp.Decimal < 0 || a.RetTp.Decimal > mysql.MaxDecimalScale { - a.RetTp.Decimal = mysql.MaxDecimalScale + if a.RetTp.GetDecimal() < 0 || a.RetTp.GetDecimal() > mysql.MaxDecimalScale { + a.RetTp.SetDecimal(mysql.MaxDecimalScale) } case mysql.TypeDouble, mysql.TypeFloat: a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, a.Args[0].GetType().Decimal + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(a.Args[0].GetType().GetDecimal()) default: a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, types.UnspecifiedLength + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(types.UnspecifiedLength) } types.SetBinChsClnFlag(a.RetTp) } @@ -210,52 +215,58 @@ func (a *baseFuncDesc) typeInfer4Sum(ctx sessionctx.Context) { // TypeInfer4AvgSum infers the type of sum from avg, which should extend the precision of decimal // compatible with mysql. func (a *baseFuncDesc) TypeInfer4AvgSum(avgRetType *types.FieldType) { - if avgRetType.Tp == mysql.TypeNewDecimal { - a.RetTp.Flen = mathutil.Min(mysql.MaxDecimalWidth, a.RetTp.Flen+22) + if avgRetType.GetType() == mysql.TypeNewDecimal { + a.RetTp.SetFlen(mathutil.Min(mysql.MaxDecimalWidth, a.RetTp.GetFlen()+22)) } } // typeInfer4Avg should returns a "decimal", otherwise it returns a "double". // Because child returns integer or decimal type. func (a *baseFuncDesc) typeInfer4Avg(ctx sessionctx.Context) { - switch a.Args[0].GetType().Tp { + switch a.Args[0].GetType().GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: a.RetTp = types.NewFieldType(mysql.TypeNewDecimal) - a.RetTp.Decimal = types.DivFracIncr - flen, _ := mysql.GetDefaultFieldLengthAndDecimal(a.Args[0].GetType().Tp) - a.RetTp.Flen = flen + types.DivFracIncr + a.RetTp.SetDecimal(types.DivFracIncr) + flen, _ := mysql.GetDefaultFieldLengthAndDecimal(a.Args[0].GetType().GetType()) + a.RetTp.SetFlen(flen + types.DivFracIncr) case mysql.TypeYear, mysql.TypeNewDecimal: a.RetTp = types.NewFieldType(mysql.TypeNewDecimal) - if a.Args[0].GetType().Decimal < 0 { - a.RetTp.Decimal = mysql.MaxDecimalScale + if a.Args[0].GetType().GetDecimal() < 0 { + a.RetTp.SetDecimal(mysql.MaxDecimalScale) } else { - a.RetTp.Decimal = mathutil.Min(a.Args[0].GetType().Decimal+types.DivFracIncr, mysql.MaxDecimalScale) + a.RetTp.SetDecimal(mathutil.Min(a.Args[0].GetType().GetDecimal()+types.DivFracIncr, mysql.MaxDecimalScale)) } - a.RetTp.Flen = mathutil.Min(mysql.MaxDecimalWidth, a.Args[0].GetType().Flen+types.DivFracIncr) - if a.Args[0].GetType().Flen < 0 { - a.RetTp.Flen = mysql.MaxDecimalWidth + a.RetTp.SetFlen(mathutil.Min(mysql.MaxDecimalWidth, a.Args[0].GetType().GetFlen()+types.DivFracIncr)) + if a.Args[0].GetType().GetFlen() < 0 { + a.RetTp.SetFlen(mysql.MaxDecimalWidth) } case mysql.TypeDouble, mysql.TypeFloat: a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, a.Args[0].GetType().Decimal + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(a.Args[0].GetType().GetDecimal()) case mysql.TypeDate, mysql.TypeDuration, mysql.TypeDatetime, mysql.TypeTimestamp: a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, 4 + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(4) default: a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, types.UnspecifiedLength + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(types.UnspecifiedLength) } types.SetBinChsClnFlag(a.RetTp) } func (a *baseFuncDesc) typeInfer4GroupConcat(ctx sessionctx.Context) { a.RetTp = types.NewFieldType(mysql.TypeVarString) - a.RetTp.Charset, a.RetTp.Collate = charset.GetDefaultCharsetAndCollate() + charset, collate := charset.GetDefaultCharsetAndCollate() + a.RetTp.SetCharset(charset) + a.RetTp.SetCollate(collate) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxBlobWidth, 0 + a.RetTp.SetFlen(mysql.MaxBlobWidth) + a.RetTp.SetDecimal(0) // TODO: a.Args[i] = expression.WrapWithCastAsString(ctx, a.Args[i]) for i := 0; i < len(a.Args)-1; i++ { - if tp := a.Args[i].GetType(); tp.Tp == mysql.TypeNewDecimal { + if tp := a.Args[i].GetType(); tp.GetType() == mysql.TypeNewDecimal { a.Args[i] = expression.BuildCastFunction(ctx, a.Args[i], tp) } } @@ -264,32 +275,33 @@ func (a *baseFuncDesc) typeInfer4GroupConcat(ctx sessionctx.Context) { func (a *baseFuncDesc) typeInfer4MaxMin(ctx sessionctx.Context) { _, argIsScalaFunc := a.Args[0].(*expression.ScalarFunction) - if argIsScalaFunc && a.Args[0].GetType().Tp == mysql.TypeFloat { + if argIsScalaFunc && a.Args[0].GetType().GetType() == mysql.TypeFloat { // For scalar function, the result of "float32" is set to the "float64" // field in the "Datum". If we do not wrap a cast-as-double function on a.Args[0], // error would happen when extracting the evaluation of a.Args[0] to a ProjectionExec. tp := types.NewFieldType(mysql.TypeDouble) - tp.Flen, tp.Decimal = mysql.MaxRealWidth, types.UnspecifiedLength + tp.SetFlen(mysql.MaxRealWidth) + tp.SetDecimal(types.UnspecifiedLength) types.SetBinChsClnFlag(tp) a.Args[0] = expression.BuildCastFunction(ctx, a.Args[0], tp) } a.RetTp = a.Args[0].GetType() - if (a.Name == ast.AggFuncMax || a.Name == ast.AggFuncMin) && a.RetTp.Tp != mysql.TypeBit { + if (a.Name == ast.AggFuncMax || a.Name == ast.AggFuncMin) && a.RetTp.GetType() != mysql.TypeBit { a.RetTp = a.Args[0].GetType().Clone() - a.RetTp.Flag &^= mysql.NotNullFlag + a.RetTp.DelFlag(mysql.NotNullFlag) } // issue #13027, #13961 - if (a.RetTp.Tp == mysql.TypeEnum || a.RetTp.Tp == mysql.TypeSet) && + if (a.RetTp.GetType() == mysql.TypeEnum || a.RetTp.GetType() == mysql.TypeSet) && (a.Name != ast.AggFuncFirstRow && a.Name != ast.AggFuncMax && a.Name != ast.AggFuncMin) { - a.RetTp = &types.FieldType{Tp: mysql.TypeString, Flen: mysql.MaxFieldCharLength} + a.RetTp = types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(mysql.MaxFieldCharLength).BuildP() } } func (a *baseFuncDesc) typeInfer4BitFuncs(ctx sessionctx.Context) { a.RetTp = types.NewFieldType(mysql.TypeLonglong) - a.RetTp.Flen = 21 + a.RetTp.SetFlen(21) types.SetBinChsClnFlag(a.RetTp) - a.RetTp.Flag |= mysql.UnsignedFlag | mysql.NotNullFlag + a.RetTp.AddFlag(mysql.UnsignedFlag | mysql.NotNullFlag) // TODO: a.Args[0] = expression.WrapWithCastAsInt(ctx, a.Args[0]) } @@ -300,25 +312,27 @@ func (a *baseFuncDesc) typeInfer4JsonFuncs(ctx sessionctx.Context) { func (a *baseFuncDesc) typeInfer4NumberFuncs() { a.RetTp = types.NewFieldType(mysql.TypeLonglong) - a.RetTp.Flen = 21 + a.RetTp.SetFlen(21) types.SetBinChsClnFlag(a.RetTp) } func (a *baseFuncDesc) typeInfer4CumeDist() { a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, mysql.NotFixedDec + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(mysql.NotFixedDec) } func (a *baseFuncDesc) typeInfer4Ntile() { a.RetTp = types.NewFieldType(mysql.TypeLonglong) - a.RetTp.Flen = 21 + a.RetTp.SetFlen(21) types.SetBinChsClnFlag(a.RetTp) - a.RetTp.Flag |= mysql.UnsignedFlag + a.RetTp.AddFlag(mysql.UnsignedFlag) } func (a *baseFuncDesc) typeInfer4PercentRank() { a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flag, a.RetTp.Decimal = mysql.MaxRealWidth, mysql.NotFixedDec + a.RetTp.SetFlag(mysql.MaxRealWidth) + a.RetTp.SetDecimal(mysql.NotFixedDec) } func (a *baseFuncDesc) typeInfer4LeadLag(ctx sessionctx.Context) { @@ -334,7 +348,8 @@ func (a *baseFuncDesc) typeInfer4LeadLag(ctx sessionctx.Context) { func (a *baseFuncDesc) typeInfer4PopOrSamp(ctx sessionctx.Context) { // var_pop/std/var_samp/stddev_samp's return value type is double a.RetTp = types.NewFieldType(mysql.TypeDouble) - a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxRealWidth, types.UnspecifiedLength + a.RetTp.SetFlen(mysql.MaxRealWidth) + a.RetTp.SetDecimal(types.UnspecifiedLength) } // GetDefaultValue gets the default value when the function's input is null. @@ -358,7 +373,7 @@ func (a *baseFuncDesc) GetDefaultValue() (v types.Datum) { case ast.AggFuncCount, ast.AggFuncBitOr, ast.AggFuncBitXor: v = types.NewIntDatum(0) case ast.AggFuncApproxCountDistinct: - if a.RetTp.Tp != mysql.TypeString { + if a.RetTp.GetType() != mysql.TypeString { v = types.NewIntDatum(0) } case ast.AggFuncFirstRow, ast.AggFuncAvg, ast.AggFuncSum, ast.AggFuncMax, @@ -418,10 +433,10 @@ func (a *baseFuncDesc) WrapCastForAggArgs(ctx sessionctx.Context) { if i == 1 && (a.Name == ast.WindowFuncLead || a.Name == ast.WindowFuncLag || a.Name == ast.WindowFuncNthValue) { continue } - if a.Args[i].GetType().Tp == mysql.TypeNull { + if a.Args[i].GetType().GetType() == mysql.TypeNull { continue } - tpOld := a.Args[i].GetType().Tp + tpOld := a.Args[i].GetType().GetType() a.Args[i] = castFunc(ctx, a.Args[i]) if a.Name != ast.AggFuncAvg && a.Name != ast.AggFuncSum { continue @@ -430,20 +445,20 @@ func (a *baseFuncDesc) WrapCastForAggArgs(ctx sessionctx.Context) { // as the type of the aggregation function. The following part set // the type of the argument exactly as the type of the aggregation // function. - // Note: If the `Tp` of argument is the same as the `Tp` of the + // Note: If the `tp` of argument is the same as the `tp` of the // aggregation function, it will not wrap cast function on it // internally. The reason of the special handling for `Column` is // that the `RetType` of `Column` refers to the `infoschema`, so we // need to set a new variable for it to avoid modifying the // definition in `infoschema`. if col, ok := a.Args[i].(*expression.Column); ok { - col.RetType = types.NewFieldType(col.RetType.Tp) + col.RetType = types.NewFieldType(col.RetType.GetType()) } - // originTp is used when the `Tp` of column is TypeFloat32 while + // originTp is used when the `tp` of column is TypeFloat32 while // the type of the aggregation function is TypeFloat64. - originTp := a.Args[i].GetType().Tp + originTp := a.Args[i].GetType().GetType() *(a.Args[i].GetType()) = *(a.RetTp) - a.Args[i].GetType().Tp = originTp + a.Args[i].GetType().SetType(originTp) // refine each mysql integer type to the needed decimal precision for sum if a.Name == ast.AggFuncSum { @@ -453,9 +468,9 @@ func (a *baseFuncDesc) WrapCastForAggArgs(ctx sessionctx.Context) { } func adjustDecimalLenForSumInteger(ft *types.FieldType, tpOld byte) { - if types.IsTypeInteger(tpOld) && ft.Tp == mysql.TypeNewDecimal { + if types.IsTypeInteger(tpOld) && ft.GetType() == mysql.TypeNewDecimal { if flen, err := minimalDecimalLenForHoldingInteger(tpOld); err == nil { - ft.Flen = mathutil.Min(ft.Flen, flen+ft.Decimal) + ft.SetFlen(mathutil.Min(ft.GetFlen(), flen+ft.GetDecimal())) } } } diff --git a/expression/aggregation/concat.go b/expression/aggregation/concat.go index a5f6ae8f0468e..b90af45471c3b 100644 --- a/expression/aggregation/concat.go +++ b/expression/aggregation/concat.go @@ -18,12 +18,12 @@ import ( "bytes" "fmt" - "github.com/cznic/mathutil" "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/mathutil" ) type concatFunction struct { @@ -114,7 +114,7 @@ func (cf *concatFunction) Update(evalCtx *AggEvaluateContext, sc *stmtctx.Statem // GetResult implements Aggregation interface. func (cf *concatFunction) GetResult(evalCtx *AggEvaluateContext) (d types.Datum) { if evalCtx.Buffer != nil { - d.SetString(evalCtx.Buffer.String(), cf.RetTp.Collate) + d.SetString(evalCtx.Buffer.String(), cf.RetTp.GetCollate()) } else { d.SetNull() } diff --git a/expression/aggregation/descriptor.go b/expression/aggregation/descriptor.go index 8882b93ec05d7..115559022279c 100644 --- a/expression/aggregation/descriptor.go +++ b/expression/aggregation/descriptor.go @@ -240,9 +240,9 @@ func (a *AggFuncDesc) GetAggFunc(ctx sessionctx.Context) Aggregation { } return &concatFunction{aggFunction: aggFunc, maxLen: maxLen} case ast.AggFuncMax: - return &maxMinFunction{aggFunction: aggFunc, isMax: true, ctor: collate.GetCollator(a.Args[0].GetType().Collate)} + return &maxMinFunction{aggFunction: aggFunc, isMax: true, ctor: collate.GetCollator(a.Args[0].GetType().GetCollate())} case ast.AggFuncMin: - return &maxMinFunction{aggFunction: aggFunc, isMax: false, ctor: collate.GetCollator(a.Args[0].GetType().Collate)} + return &maxMinFunction{aggFunction: aggFunc, isMax: false, ctor: collate.GetCollator(a.Args[0].GetType().GetCollate())} case ast.AggFuncFirstRow: return &firstRowFunction{aggFunction: aggFunc} case ast.AggFuncBitOr: @@ -311,7 +311,7 @@ func (a *AggFuncDesc) UpdateNotNullFlag4RetType(hasGroupBy, allAggsFirstRow bool } // `select max(a) from empty_tbl` returns `null`, while `select max(a) from empty_tbl group by b` returns empty. case ast.AggFuncMax, ast.AggFuncMin: - if !hasGroupBy && a.RetTp.Tp != mysql.TypeBit { + if !hasGroupBy && a.RetTp.GetType() != mysql.TypeBit { removeNotNull = true } // `select distinct a from empty_tbl` returns empty @@ -329,7 +329,7 @@ func (a *AggFuncDesc) UpdateNotNullFlag4RetType(hasGroupBy, allAggsFirstRow bool } if removeNotNull { a.RetTp = a.RetTp.Clone() - a.RetTp.Flag &^= mysql.NotNullFlag + a.RetTp.DelFlag(mysql.NotNullFlag) } return nil } diff --git a/expression/bench_test.go b/expression/bench_test.go index 5bb0977841f1f..86803ae527008 100644 --- a/expression/bench_test.go +++ b/expression/bench_test.go @@ -39,7 +39,7 @@ import ( "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/benchdaily" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/math" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -63,40 +63,23 @@ func (h *benchHelper) init() { h.ctx.GetSessionVars().MaxChunkSize = numRows h.inputTypes = make([]*types.FieldType, 0, 10) - h.inputTypes = append(h.inputTypes, &types.FieldType{ - Tp: mysql.TypeLonglong, - Flen: mysql.MaxIntWidth, - Decimal: 0, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }) - h.inputTypes = append(h.inputTypes, &types.FieldType{ - Tp: mysql.TypeDouble, - Flen: mysql.MaxRealWidth, - Decimal: types.UnspecifiedLength, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }) - h.inputTypes = append(h.inputTypes, &types.FieldType{ - Tp: mysql.TypeNewDecimal, - Flen: 11, - Decimal: 0, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }) + ftb := types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeLonglong).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxIntWidth).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin) + h.inputTypes = append(h.inputTypes, ftb.BuildP()) + + ftb = types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeDouble).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxRealWidth).SetDecimal(types.UnspecifiedLength).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin) + h.inputTypes = append(h.inputTypes, ftb.BuildP()) + + ftb = types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeNewDecimal).SetFlag(mysql.BinaryFlag).SetFlen(11).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin) + h.inputTypes = append(h.inputTypes, ftb.BuildP()) // Use 20 string columns to show the cache performance. for i := 0; i < 20; i++ { - h.inputTypes = append(h.inputTypes, &types.FieldType{ - Tp: mysql.TypeVarString, - Flen: 0, - Decimal: types.UnspecifiedLength, - Charset: charset.CharsetUTF8, - Collate: charset.CollationUTF8, - }) + ftb = types.NewFieldTypeBuilder() + ftb.SetType(mysql.TypeVarString).SetDecimal(types.UnspecifiedLength).SetCharset(charset.CharsetUTF8).SetCollate(charset.CollationUTF8) + h.inputTypes = append(h.inputTypes, ftb.BuildP()) } h.inputChunk = chunk.NewChunkWithCapacity(h.inputTypes, numRows) @@ -462,8 +445,8 @@ func (g *rangeDurationGener) gen() interface{} { if g.randGen.Float64() < g.nullRation { return nil } - tm := (math.Abs(g.randGen.Int63n(12))*3600 + math.Abs(g.randGen.Int63n(60))*60 + math.Abs(g.randGen.Int63n(60))) * 1000 - tu := (tm + math.Abs(g.randGen.Int63n(1000))) * 1000 + tm := (mathutil.Abs(g.randGen.Int63n(12))*3600 + mathutil.Abs(g.randGen.Int63n(60))*60 + mathutil.Abs(g.randGen.Int63n(60))) * 1000 + tu := (tm + mathutil.Abs(g.randGen.Int63n(1000))) * 1000 return types.Duration{ Duration: time.Duration(tu * 1000)} } @@ -1485,7 +1468,7 @@ func testVectorizedBuiltinFunc(t *testing.T, vecExprCases vecExprBenchCases) { i++ } default: - t.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) + t.Fatalf("evalType=%v is not supported", testCase.retEvalType) } // check warnings @@ -1527,7 +1510,7 @@ func testVectorizedBuiltinFuncForRand(t *testing.T, vecExprCases vecExprBenchCas require.True(t, (0 <= v) && (v < 1)) } default: - t.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) + t.Fatalf("evalType=%v is not supported", testCase.retEvalType) } } } @@ -1630,7 +1613,7 @@ func benchmarkVectorizedBuiltinFunc(b *testing.B, vecExprCases vecExprBenchCases } } default: - b.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) + b.Fatalf("evalType=%v is not supported", testCase.retEvalType) } }) b.Run(baseFuncName+"-NonVecBuiltinFunc", func(b *testing.B) { @@ -1743,7 +1726,7 @@ func benchmarkVectorizedBuiltinFunc(b *testing.B, vecExprCases vecExprBenchCases } } default: - b.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) + b.Fatalf("evalType=%v is not supported", testCase.retEvalType) } }) } diff --git a/expression/builtin.go b/expression/builtin.go index b693d21145223..e6015a7504c31 100644 --- a/expression/builtin.go +++ b/expression/builtin.go @@ -155,70 +155,28 @@ func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Ex var fieldType *types.FieldType switch retType { case types.ETInt: - fieldType = &types.FieldType{ - Tp: mysql.TypeLonglong, - Flen: mysql.MaxIntWidth, - Decimal: 0, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxIntWidth).BuildP() case types.ETReal: - fieldType = &types.FieldType{ - Tp: mysql.TypeDouble, - Flen: mysql.MaxRealWidth, - Decimal: types.UnspecifiedLength, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxRealWidth).SetDecimal(types.UnspecifiedLength).BuildP() case types.ETDecimal: - fieldType = &types.FieldType{ - Tp: mysql.TypeNewDecimal, - Flen: 11, - Decimal: 0, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.BinaryFlag).SetFlen(11).BuildP() case types.ETString: - fieldType = &types.FieldType{ - Tp: mysql.TypeVarString, - Decimal: types.UnspecifiedLength, - Charset: ec.Charset, - Collate: ec.Collation, - Flen: types.UnspecifiedLength, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeVarString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).SetCharset(ec.Charset).SetCollate(ec.Collation).BuildP() case types.ETDatetime: - fieldType = &types.FieldType{ - Tp: mysql.TypeDatetime, - Flen: mysql.MaxDatetimeWidthWithFsp, - Decimal: types.MaxFsp, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeDatetime).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxDatetimeWidthWithFsp).SetDecimal(types.MaxFsp).BuildP() case types.ETTimestamp: - fieldType = &types.FieldType{ - Tp: mysql.TypeTimestamp, - Flen: mysql.MaxDatetimeWidthWithFsp, - Decimal: types.MaxFsp, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeTimestamp).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxDatetimeWidthWithFsp).SetDecimal(types.MaxFsp).BuildP() case types.ETDuration: - fieldType = &types.FieldType{ - Tp: mysql.TypeDuration, - Flen: mysql.MaxDurationWidthWithFsp, - Decimal: types.MaxFsp, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeDuration).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxDurationWidthWithFsp).SetDecimal(types.MaxFsp).BuildP() case types.ETJson: - fieldType = &types.FieldType{ - Tp: mysql.TypeJSON, - Flen: mysql.MaxBlobWidth, - Decimal: 0, - Charset: mysql.DefaultCharset, - Collate: mysql.DefaultCollationName, - Flag: mysql.BinaryFlag, - } + fieldType = types.NewFieldTypeBuilderP().SetType(mysql.TypeJSON).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxBlobWidth).SetCharset(mysql.DefaultCharset).SetCollate(mysql.DefaultCollationName).BuildP() } - if mysql.HasBinaryFlag(fieldType.Flag) && fieldType.Tp != mysql.TypeJSON { - fieldType.Charset, fieldType.Collate = charset.CharsetBin, charset.CollationBin + if mysql.HasBinaryFlag(fieldType.GetFlag()) && fieldType.GetType() != mysql.TypeJSON { + fieldType.SetCharset(charset.CharsetBin) + fieldType.SetCollate(charset.CollationBin) } if _, ok := booleanFunctions[funcName]; ok { - fieldType.Flag |= mysql.IsBooleanFlag + fieldType.AddFlag(mysql.IsBooleanFlag) } bf = baseBuiltinFunc{ bufAllocator: newLocalColumnPool(), @@ -251,8 +209,8 @@ func newBaseBuiltinFuncWithFieldType(ctx sessionctx.Context, tp *types.FieldType ctx: ctx, tp: types.NewFieldType(mysql.TypeUnspecified), } - bf.SetCharsetAndCollation(tp.Charset, tp.Collate) - bf.setCollator(collate.GetCollator(tp.Collate)) + bf.SetCharsetAndCollation(tp.GetCharset(), tp.GetCollate()) + bf.setCollator(collate.GetCollator(tp.GetCollate())) return bf, nil } @@ -357,13 +315,15 @@ func (b *baseBuiltinFunc) isChildrenVectorized() bool { func (b *baseBuiltinFunc) getRetTp() *types.FieldType { switch b.tp.EvalType() { case types.ETString: - if b.tp.Flen >= mysql.MaxBlobWidth { - b.tp.Tp = mysql.TypeLongBlob - } else if b.tp.Flen >= 65536 { - b.tp.Tp = mysql.TypeMediumBlob + if b.tp.GetFlen() >= mysql.MaxBlobWidth { + b.tp.SetType(mysql.TypeLongBlob) + } else if b.tp.GetFlen() >= 65536 { + b.tp.SetType(mysql.TypeMediumBlob) } - if len(b.tp.Charset) <= 0 { - b.tp.Charset, b.tp.Collate = charset.GetDefaultCharsetAndCollate() + if len(b.tp.GetCharset()) <= 0 { + charset, collate := charset.GetDefaultCharsetAndCollate() + b.tp.SetCharset(charset) + b.tp.SetCollate(collate) } } return b.tp @@ -783,8 +743,6 @@ var funcs = map[string]functionClass{ ast.BinToUUID: &binToUUIDFunctionClass{baseFunctionClass{ast.BinToUUID, 1, 2}}, ast.TiDBShard: &tidbShardFunctionClass{baseFunctionClass{ast.TiDBShard, 1, 1}}, - // get_lock() and release_lock() are parsed but do nothing. - // It is used for preventing error in Ruby's activerecord migrations. ast.GetLock: &lockFunctionClass{baseFunctionClass{ast.GetLock, 2, 2}}, ast.ReleaseLock: &releaseLockFunctionClass{baseFunctionClass{ast.ReleaseLock, 1, 1}}, @@ -929,25 +887,25 @@ func GetBuiltinList() []string { } func (b *baseBuiltinFunc) setDecimalAndFlenForDatetime(fsp int) { - b.tp.Decimal = fsp - b.tp.Flen = mysql.MaxDatetimeWidthNoFsp + fsp + b.tp.SetDecimal(fsp) + b.tp.SetFlen(mysql.MaxDatetimeWidthNoFsp + fsp) if fsp > 0 { // Add the length for `.`. - b.tp.Flen++ + b.tp.SetFlen(b.tp.GetFlen() + 1) } } func (b *baseBuiltinFunc) setDecimalAndFlenForDate() { - b.tp.Decimal = 0 - b.tp.Flen = mysql.MaxDateWidth - b.tp.Tp = mysql.TypeDate + b.tp.SetDecimal(0) + b.tp.SetFlen(mysql.MaxDateWidth) + b.tp.SetType(mysql.TypeDate) } func (b *baseBuiltinFunc) setDecimalAndFlenForTime(fsp int) { - b.tp.Decimal = fsp - b.tp.Flen = mysql.MaxDurationWidthNoFsp + fsp + b.tp.SetDecimal(fsp) + b.tp.SetFlen(mysql.MaxDurationWidthNoFsp + fsp) if fsp > 0 { // Add the length for `.`. - b.tp.Flen++ + b.tp.SetFlen(b.tp.GetFlen() + 1) } } diff --git a/expression/builtin_arithmetic.go b/expression/builtin_arithmetic.go index 4bb4927ff1835..3a9f42f3f17e7 100644 --- a/expression/builtin_arithmetic.go +++ b/expression/builtin_arithmetic.go @@ -18,13 +18,12 @@ import ( "fmt" "math" - "github.com/cznic/mathutil" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - math2 "github.com/pingcap/tidb/util/math" + "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tipb/go-tipb" ) @@ -67,13 +66,13 @@ const precIncrement = 4 // numericContextResultType returns types.EvalType for numeric function's parameters. // the returned types.EvalType should be one of: types.ETInt, types.ETDecimal, types.ETReal func numericContextResultType(ft *types.FieldType) types.EvalType { - if types.IsTypeTemporal(ft.Tp) { - if ft.Decimal > 0 { + if types.IsTypeTemporal(ft.GetType()) { + if ft.GetDecimal() > 0 { return types.ETDecimal } return types.ETInt } - if types.IsBinaryStr(ft) || ft.Tp == mysql.TypeBit { + if types.IsBinaryStr(ft) || ft.GetType() == mysql.TypeBit { return types.ETInt } evalTp4Ft := types.ETReal @@ -86,68 +85,70 @@ func numericContextResultType(ft *types.FieldType) types.EvalType { return evalTp4Ft } -// setFlenDecimal4RealOrDecimal is called to set proper `Flen` and `Decimal` of return +// setFlenDecimal4RealOrDecimal is called to set proper `flen` and `decimal` of return // type according to the two input parameter's types. func setFlenDecimal4RealOrDecimal(ctx sessionctx.Context, retTp *types.FieldType, arg0, arg1 Expression, isReal bool, isMultiply bool) { a, b := arg0.GetType(), arg1.GetType() - if a.Decimal != types.UnspecifiedLength && b.Decimal != types.UnspecifiedLength { - retTp.Decimal = a.Decimal + b.Decimal + if a.GetDecimal() != types.UnspecifiedLength && b.GetDecimal() != types.UnspecifiedLength { + retTp.SetDecimal(a.GetDecimal() + b.GetDecimal()) if !isMultiply { - retTp.Decimal = mathutil.Max(a.Decimal, b.Decimal) + retTp.SetDecimal(mathutil.Max(a.GetDecimal(), b.GetDecimal())) } - if !isReal && retTp.Decimal > mysql.MaxDecimalScale { - retTp.Decimal = mysql.MaxDecimalScale + if !isReal && retTp.GetDecimal() > mysql.MaxDecimalScale { + retTp.SetDecimal(mysql.MaxDecimalScale) } - if a.Flen == types.UnspecifiedLength || b.Flen == types.UnspecifiedLength { - retTp.Flen = types.UnspecifiedLength + if a.GetFlen() == types.UnspecifiedLength || b.GetFlen() == types.UnspecifiedLength { + retTp.SetFlen(types.UnspecifiedLength) return } - digitsInt := mathutil.Max(a.Flen-a.Decimal, b.Flen-b.Decimal) + digitsInt := mathutil.Max(a.GetFlen()-a.GetDecimal(), b.GetFlen()-b.GetDecimal()) if isMultiply { - digitsInt = a.Flen - a.Decimal + b.Flen - b.Decimal + digitsInt = a.GetFlen() - a.GetDecimal() + b.GetFlen() - b.GetDecimal() } - retTp.Flen = digitsInt + retTp.Decimal + 1 + retTp.SetFlen(digitsInt + retTp.GetDecimal() + 1) if isReal { - retTp.Flen = mathutil.Min(retTp.Flen, mysql.MaxRealWidth) + retTp.SetFlen(mathutil.Min(retTp.GetFlen(), mysql.MaxRealWidth)) return } - retTp.Flen = mathutil.Min(retTp.Flen, mysql.MaxDecimalWidth) + retTp.SetFlen(mathutil.Min(retTp.GetFlen(), mysql.MaxDecimalWidth)) return } if isReal { - retTp.Flen, retTp.Decimal = types.UnspecifiedLength, types.UnspecifiedLength + retTp.SetFlen(types.UnspecifiedLength) + retTp.SetDecimal(types.UnspecifiedLength) } else { - retTp.Flen, retTp.Decimal = mysql.MaxDecimalWidth, mysql.MaxDecimalScale + retTp.SetFlen(mysql.MaxDecimalWidth) + retTp.SetDecimal(mysql.MaxDecimalScale) } } func (c *arithmeticDivideFunctionClass) setType4DivDecimal(retTp, a, b *types.FieldType) { - var deca, decb = a.Decimal, b.Decimal + var deca, decb = a.GetDecimal(), b.GetDecimal() if deca == types.UnspecifiedFsp { deca = 0 } if decb == types.UnspecifiedFsp { decb = 0 } - retTp.Decimal = deca + precIncrement - if retTp.Decimal > mysql.MaxDecimalScale { - retTp.Decimal = mysql.MaxDecimalScale + retTp.SetDecimal(deca + precIncrement) + if retTp.GetDecimal() > mysql.MaxDecimalScale { + retTp.SetDecimal(mysql.MaxDecimalScale) } - if a.Flen == types.UnspecifiedLength { - retTp.Flen = mysql.MaxDecimalWidth + if a.GetFlen() == types.UnspecifiedLength { + retTp.SetFlen(mysql.MaxDecimalWidth) return } - aPrec := types.DecimalLength2Precision(a.Flen, a.Decimal, mysql.HasUnsignedFlag(a.Flag)) - retTp.Flen = aPrec + decb + precIncrement - retTp.Flen = types.Precision2LengthNoTruncation(retTp.Flen, retTp.Decimal, mysql.HasUnsignedFlag(retTp.Flag)) - if retTp.Flen > mysql.MaxDecimalWidth { - retTp.Flen = mysql.MaxDecimalWidth + aPrec := types.DecimalLength2Precision(a.GetFlen(), a.GetDecimal(), mysql.HasUnsignedFlag(a.GetFlag())) + retTp.SetFlen(aPrec + decb + precIncrement) + retTp.SetFlen(types.Precision2LengthNoTruncation(retTp.GetFlen(), retTp.GetDecimal(), mysql.HasUnsignedFlag(retTp.GetFlag()))) + if retTp.GetFlen() > mysql.MaxDecimalWidth { + retTp.SetFlen(mysql.MaxDecimalWidth) } } func (c *arithmeticDivideFunctionClass) setType4DivReal(retTp *types.FieldType) { - retTp.Decimal = types.UnspecifiedLength - retTp.Flen = mysql.MaxRealWidth + retTp.SetDecimal(types.UnspecifiedLength) + retTp.SetFlen(mysql.MaxRealWidth) } type arithmeticPlusFunctionClass struct { @@ -183,8 +184,8 @@ func (c *arithmeticPlusFunctionClass) getFunction(ctx sessionctx.Context, args [ if err != nil { return nil, err } - if mysql.HasUnsignedFlag(args[0].GetType().Flag) || mysql.HasUnsignedFlag(args[1].GetType().Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(args[0].GetType().GetFlag()) || mysql.HasUnsignedFlag(args[1].GetType().GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticPlusIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_PlusInt) @@ -213,8 +214,8 @@ func (s *builtinArithmeticPlusIntSig) evalInt(row chunk.Row) (val int64, isNull return 0, isNull, err } - isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().GetFlag()) switch { case isLHSUnsigned && isRHSUnsigned: @@ -296,7 +297,7 @@ func (s *builtinArithmeticPlusRealSig) evalReal(row chunk.Row) (float64, bool, e if isLHSNull || isRHSNull { return 0, true, nil } - if !math2.IsFinite(a + b) { + if !mathutil.IsFinite(a + b) { return 0, true, types.ErrOverflow.GenWithStackByArgs("DOUBLE", fmt.Sprintf("(%s + %s)", s.args[0].String(), s.args[1].String())) } return a + b, false, nil @@ -336,8 +337,8 @@ func (c *arithmeticMinusFunctionClass) getFunction(ctx sessionctx.Context, args if err != nil { return nil, err } - if (mysql.HasUnsignedFlag(args[0].GetType().Flag) || mysql.HasUnsignedFlag(args[1].GetType().Flag)) && !ctx.GetSessionVars().SQLMode.HasNoUnsignedSubtractionMode() { - bf.tp.Flag |= mysql.UnsignedFlag + if (mysql.HasUnsignedFlag(args[0].GetType().GetFlag()) || mysql.HasUnsignedFlag(args[1].GetType().GetFlag())) && !ctx.GetSessionVars().SQLMode.HasNoUnsignedSubtractionMode() { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticMinusIntSig{baseBuiltinFunc: bf} sig.setPbCode(tipb.ScalarFuncSig_MinusInt) @@ -364,7 +365,7 @@ func (s *builtinArithmeticMinusRealSig) evalReal(row chunk.Row) (float64, bool, if isNull || err != nil { return 0, isNull, err } - if !math2.IsFinite(a - b) { + if !mathutil.IsFinite(a - b) { return 0, true, types.ErrOverflow.GenWithStackByArgs("DOUBLE", fmt.Sprintf("(%s - %s)", s.args[0].String(), s.args[1].String())) } return a - b, false, nil @@ -421,8 +422,8 @@ func (s *builtinArithmeticMinusIntSig) evalInt(row chunk.Row) (val int64, isNull return 0, isNull, err } forceToSigned := s.ctx.GetSessionVars().SQLMode.HasNoUnsignedSubtractionMode() - isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().GetFlag()) errType := "BIGINT UNSIGNED" signed := forceToSigned || (!isLHSUnsigned && !isRHSUnsigned) @@ -521,8 +522,8 @@ func (c *arithmeticMultiplyFunctionClass) getFunction(ctx sessionctx.Context, ar if err != nil { return nil, err } - if mysql.HasUnsignedFlag(lhsTp.Flag) || mysql.HasUnsignedFlag(rhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) || mysql.HasUnsignedFlag(rhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) sig := &builtinArithmeticMultiplyIntUnsignedSig{bf} sig.setPbCode(tipb.ScalarFuncSig_MultiplyIntUnsigned) return sig, nil @@ -720,8 +721,8 @@ func (s *builtinArithmeticDivideDecimalSig) evalDecimal(row chunk.Row) (*types.M err = sc.HandleTruncate(errTruncatedWrongValue.GenWithStackByArgs("DECIMAL", c)) } else if err == nil { _, frac := c.PrecisionAndFrac() - if frac < s.baseBuiltinFunc.tp.Decimal { - err = c.Round(c, s.baseBuiltinFunc.tp.Decimal, types.ModeHalfUp) + if frac < s.baseBuiltinFunc.tp.GetDecimal() { + err = c.Round(c, s.baseBuiltinFunc.tp.GetDecimal(), types.ModeHalfUp) } } else if err == types.ErrOverflow { err = types.ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%s / %s)", s.args[0].String(), s.args[1].String())) @@ -745,8 +746,8 @@ func (c *arithmeticIntDivideFunctionClass) getFunction(ctx sessionctx.Context, a if err != nil { return nil, err } - if mysql.HasUnsignedFlag(lhsTp.Flag) || mysql.HasUnsignedFlag(rhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) || mysql.HasUnsignedFlag(rhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticIntDivideIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_IntDivideInt) @@ -756,8 +757,8 @@ func (c *arithmeticIntDivideFunctionClass) getFunction(ctx sessionctx.Context, a if err != nil { return nil, err } - if mysql.HasUnsignedFlag(lhsTp.Flag) || mysql.HasUnsignedFlag(rhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) || mysql.HasUnsignedFlag(rhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticIntDivideDecimalSig{bf} sig.setPbCode(tipb.ScalarFuncSig_IntDivideDecimal) @@ -802,8 +803,8 @@ func (s *builtinArithmeticIntDivideIntSig) evalIntWithCtx(sctx sessionctx.Contex ret int64 val uint64 ) - isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().GetFlag()) switch { case isLHSUnsigned && isRHSUnsigned: @@ -847,8 +848,8 @@ func (s *builtinArithmeticIntDivideDecimalSig) evalInt(row chunk.Row) (ret int64 return 0, true, err } - isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().GetFlag()) if isLHSUnsigned || isRHSUnsigned { val, err := c.ToUint() @@ -879,24 +880,24 @@ type arithmeticModFunctionClass struct { } func (c *arithmeticModFunctionClass) setType4ModRealOrDecimal(retTp, a, b *types.FieldType, isDecimal bool) { - if a.Decimal == types.UnspecifiedLength || b.Decimal == types.UnspecifiedLength { - retTp.Decimal = types.UnspecifiedLength + if a.GetDecimal() == types.UnspecifiedLength || b.GetDecimal() == types.UnspecifiedLength { + retTp.SetDecimal(types.UnspecifiedLength) } else { - retTp.Decimal = mathutil.Max(a.Decimal, b.Decimal) - if isDecimal && retTp.Decimal > mysql.MaxDecimalScale { - retTp.Decimal = mysql.MaxDecimalScale + retTp.SetDecimal(mathutil.Max(a.GetDecimal(), b.GetDecimal())) + if isDecimal && retTp.GetDecimal() > mysql.MaxDecimalScale { + retTp.SetDecimal(mysql.MaxDecimalScale) } } - if a.Flen == types.UnspecifiedLength || b.Flen == types.UnspecifiedLength { - retTp.Flen = types.UnspecifiedLength + if a.GetFlen() == types.UnspecifiedLength || b.GetFlen() == types.UnspecifiedLength { + retTp.SetFlen(types.UnspecifiedLength) } else { - retTp.Flen = mathutil.Max(a.Flen, b.Flen) + retTp.SetFlen(mathutil.Max(a.GetFlen(), b.GetFlen())) if isDecimal { - retTp.Flen = mathutil.Min(retTp.Flen, mysql.MaxDecimalWidth) + retTp.SetFlen(mathutil.Min(retTp.GetFlen(), mysql.MaxDecimalWidth)) return } - retTp.Flen = mathutil.Min(retTp.Flen, mysql.MaxRealWidth) + retTp.SetFlen(mathutil.Min(retTp.GetFlen(), mysql.MaxRealWidth)) } } @@ -912,8 +913,8 @@ func (c *arithmeticModFunctionClass) getFunction(ctx sessionctx.Context, args [] return nil, err } c.setType4ModRealOrDecimal(bf.tp, lhsTp, rhsTp, false) - if mysql.HasUnsignedFlag(lhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticModRealSig{bf} sig.setPbCode(tipb.ScalarFuncSig_ModReal) @@ -924,8 +925,8 @@ func (c *arithmeticModFunctionClass) getFunction(ctx sessionctx.Context, args [] return nil, err } c.setType4ModRealOrDecimal(bf.tp, lhsTp, rhsTp, true) - if mysql.HasUnsignedFlag(lhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } sig := &builtinArithmeticModDecimalSig{bf} sig.setPbCode(tipb.ScalarFuncSig_ModDecimal) @@ -935,11 +936,11 @@ func (c *arithmeticModFunctionClass) getFunction(ctx sessionctx.Context, args [] if err != nil { return nil, err } - if mysql.HasUnsignedFlag(lhsTp.Flag) { - bf.tp.Flag |= mysql.UnsignedFlag + if mysql.HasUnsignedFlag(lhsTp.GetFlag()) { + bf.tp.AddFlag(mysql.UnsignedFlag) } - isLHSUnsigned := mysql.HasUnsignedFlag(args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(args[1].GetType().GetFlag()) switch { case isLHSUnsigned && isRHSUnsigned: diff --git a/expression/builtin_arithmetic_test.go b/expression/builtin_arithmetic_test.go index 120ce08754cb1..564da2678ac5d 100644 --- a/expression/builtin_arithmetic_test.go +++ b/expression/builtin_arithmetic_test.go @@ -31,66 +31,65 @@ import ( func TestSetFlenDecimal4RealOrDecimal(t *testing.T) { ret := &types.FieldType{} - a := &types.FieldType{ - Decimal: 1, - Flen: 3, - } - b := &types.FieldType{ - Decimal: 0, - Flen: 2, - } + a := &types.FieldType{} + a.SetDecimal(1) + a.SetFlen(3) + + b := &types.FieldType{} + b.SetDecimal(0) + b.SetFlag(2) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, 4, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, 4, ret.GetFlen()) - b.Flen = 65 + b.SetFlen(65) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, mysql.MaxRealWidth, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, mysql.MaxRealWidth, ret.GetFlen()) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, false, false) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, mysql.MaxDecimalWidth, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, mysql.MaxDecimalWidth, ret.GetFlen()) - b.Flen = types.UnspecifiedLength + b.SetFlen(types.UnspecifiedLength) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, types.UnspecifiedLength, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, types.UnspecifiedLength, ret.GetFlen()) - b.Decimal = types.UnspecifiedLength + b.SetDecimal(types.UnspecifiedLength) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) - require.Equal(t, types.UnspecifiedLength, ret.Decimal) - require.Equal(t, types.UnspecifiedLength, ret.Flen) + require.Equal(t, types.UnspecifiedLength, ret.GetDecimal()) + require.Equal(t, types.UnspecifiedLength, ret.GetFlen()) ret = &types.FieldType{} - a = &types.FieldType{ - Decimal: 1, - Flen: 3, - } - b = &types.FieldType{ - Decimal: 0, - Flen: 2, - } + a = &types.FieldType{} + a.SetDecimal(1) + a.SetFlen(3) + + b = &types.FieldType{} + b.SetDecimal(0) + b.SetFlen(2) + setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, 6, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, 6, ret.GetFlen()) - b.Flen = 65 + b.SetFlen(65) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, mysql.MaxRealWidth, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, mysql.MaxRealWidth, ret.GetFlen()) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, false, true) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, mysql.MaxDecimalWidth, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, mysql.MaxDecimalWidth, ret.GetFlen()) - b.Flen = types.UnspecifiedLength + b.SetFlen(types.UnspecifiedLength) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) - require.Equal(t, 1, ret.Decimal) - require.Equal(t, types.UnspecifiedLength, ret.Flen) + require.Equal(t, 1, ret.GetDecimal()) + require.Equal(t, types.UnspecifiedLength, ret.GetFlen()) - b.Decimal = types.UnspecifiedLength + b.SetDecimal(types.UnspecifiedLength) setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) - require.Equal(t, types.UnspecifiedLength, ret.Decimal) - require.Equal(t, types.UnspecifiedLength, ret.Flen) + require.Equal(t, types.UnspecifiedLength, ret.GetDecimal()) + require.Equal(t, types.UnspecifiedLength, ret.GetFlen()) } func TestArithmeticPlus(t *testing.T) { diff --git a/expression/builtin_arithmetic_vec.go b/expression/builtin_arithmetic_vec.go index 42e076b803dc1..9d35ac25c3945 100644 --- a/expression/builtin_arithmetic_vec.go +++ b/expression/builtin_arithmetic_vec.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - math2 "github.com/pingcap/tidb/util/math" + "github.com/pingcap/tidb/util/mathutil" ) func (b *builtinArithmeticMultiplyRealSig) vectorized() bool { @@ -99,8 +99,8 @@ func (b *builtinArithmeticDivideDecimalSig) vecEvalDecimal(input *chunk.Chunk, r } } else if err == nil { _, frac = to.PrecisionAndFrac() - if frac < b.baseBuiltinFunc.tp.Decimal { - if err = to.Round(&to, b.baseBuiltinFunc.tp.Decimal, types.ModeHalfUp); err != nil { + if frac < b.baseBuiltinFunc.tp.GetDecimal() { + if err = to.Round(&to, b.baseBuiltinFunc.tp.GetDecimal(), types.ModeHalfUp); err != nil { return err } } @@ -320,7 +320,7 @@ func (b *builtinArithmeticMinusRealSig) vecEvalReal(input *chunk.Chunk, result * x := result.Float64s() y := buf.Float64s() for i := 0; i < n; i++ { - if !math2.IsFinite(x[i] - y[i]) { + if !mathutil.IsFinite(x[i] - y[i]) { if result.IsNull(i) { continue } @@ -395,8 +395,8 @@ func (b *builtinArithmeticMinusIntSig) vecEvalInt(input *chunk.Chunk, result *ch resulti64s := result.Int64s() forceToSigned := b.ctx.GetSessionVars().SQLMode.HasNoUnsignedSubtractionMode() - isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().GetFlag()) errType := "BIGINT UNSIGNED" signed := forceToSigned || (!isLHSUnsigned && !isRHSUnsigned) @@ -521,7 +521,7 @@ func (b *builtinArithmeticPlusRealSig) vecEvalReal(input *chunk.Chunk, result *c x := result.Float64s() y := buf.Float64s() for i := 0; i < n; i++ { - if !math2.IsFinite(x[i] + y[i]) { + if !mathutil.IsFinite(x[i] + y[i]) { if result.IsNull(i) { continue } @@ -594,8 +594,8 @@ func (b *builtinArithmeticIntDivideDecimalSig) vecEvalInt(input *chunk.Chunk, re num[i] = buf[i].Decimals() } - isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().GetFlag()) isUnsigned := isLHSUnsigned || isRHSUnsigned result.ResizeInt64(n, false) @@ -757,8 +757,8 @@ func (b *builtinArithmeticIntDivideIntSig) vecEvalInt(input *chunk.Chunk, result rhsI64s := rhsBuf.Int64s() resultI64s := result.Int64s() - isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().GetFlag()) switch { case isLHSUnsigned && isRHSUnsigned: @@ -888,8 +888,8 @@ func (b *builtinArithmeticPlusIntSig) vecEvalInt(input *chunk.Chunk, result *chu rhi64s := rh.Int64s() resulti64s := result.Int64s() - isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) - isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().Flag) + isLHSUnsigned := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) + isRHSUnsigned := mysql.HasUnsignedFlag(b.args[1].GetType().GetFlag()) switch { case isLHSUnsigned && isRHSUnsigned: diff --git a/expression/builtin_arithmetic_vec_test.go b/expression/builtin_arithmetic_vec_test.go index fa6cf5d73b1ae..87b9241e2048b 100644 --- a/expression/builtin_arithmetic_vec_test.go +++ b/expression/builtin_arithmetic_vec_test.go @@ -43,16 +43,17 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}}, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}, geners: []dataGenerator{nil, newRangeDecimalGener(0, 0, 0.2)}}, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeNewDecimal, Flag: mysql.UnsignedFlag}, nil}, - geners: []dataGenerator{newRangeDecimalGener(0, 10000, 0.2), newRangeDecimalGener(0, 10000, 0.2)}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.UnsignedFlag).BuildP(), nil}, + geners: []dataGenerator{newRangeDecimalGener(0, 10000, 0.2), newRangeDecimalGener(0, 10000, 0.2)}, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}, - childrenFieldTypes: []*types.FieldType{nil, {Tp: mysql.TypeNewDecimal, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{nil, types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{newRangeDecimalGener(0, 10000, 0.2), newRangeDecimalGener(0, 10000, 0.2)}, }, // when the final result is at (-1, 0], it should be return 0 instead of the error {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}, - childrenFieldTypes: []*types.FieldType{nil, {Tp: mysql.TypeNewDecimal, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{nil, types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{newRangeDecimalGener(-100, -1, 0.2), newRangeDecimalGener(1000, 2000, 0.2)}, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, @@ -63,8 +64,8 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, childrenFieldTypes: []*types.FieldType{ - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), @@ -72,8 +73,8 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, childrenFieldTypes: []*types.FieldType{ - {Tp: mysql.TypeLonglong}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + types.NewFieldType(mysql.TypeLonglong), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), @@ -81,8 +82,8 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, childrenFieldTypes: []*types.FieldType{ - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong}}, + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldType(mysql.TypeLonglong)}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), @@ -107,24 +108,27 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldType(mysql.TypeLonglong), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(math.MinInt64/2, math.MaxInt64/2), newRangeInt64Gener(0, math.MaxInt64), }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldType(mysql.TypeLonglong)}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(math.MinInt64/2, math.MaxInt64/2), @@ -136,7 +140,10 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ {retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETReal, types.ETReal}}, {retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETDecimal, types.ETDecimal}}, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, geners: []dataGenerator{newRangeInt64Gener(-10000, 10000), newRangeInt64Gener(-10000, 10000)}}, - {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeInt24, Flag: mysql.UnsignedFlag}, {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeInt24).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, 10000), newRangeInt64Gener(0, 10000), @@ -155,24 +162,27 @@ var vecBuiltinArithmeticCases = map[string][]vecExprBenchCase{ }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong}, - {Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldType(mysql.TypeLonglong), + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP()}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), }, }, {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, - childrenFieldTypes: []*types.FieldType{{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, - {Tp: mysql.TypeLonglong}}, + childrenFieldTypes: []*types.FieldType{ + types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), + types.NewFieldType(mysql.TypeLonglong)}, geners: []dataGenerator{ newRangeInt64Gener(0, math.MaxInt64), newRangeInt64Gener(0, math.MaxInt64), diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index a3c8442773565..6a730307abb74 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -15,7 +15,7 @@ // We implement 6 CastAsXXFunctionClass for `cast` built-in functions. // XX means the return type of the `cast` built-in functions. // XX contains the following 6 types: -// Int, Decimal, Real, String, Time, Duration. +// Int, decimal, Real, String, Time, Duration. // We implement 6 CastYYAsXXSig built-in function signatures for every CastAsXXFunctionClass. // builtinCastXXAsYYSig takes a argument of type XX and returns a value of type YY. @@ -292,8 +292,8 @@ func (c *castAsStringFunctionClass) getFunction(ctx sessionctx.Context, args []E argTp := args[0].GetType().EvalType() switch argTp { case types.ETInt: - if bf.tp.Flen == types.UnspecifiedLength { - bf.tp.Flen = args[0].GetType().Flen + if bf.tp.GetFlen() == types.UnspecifiedLength { + bf.tp.SetFlen(args[0].GetType().GetFlen()) } sig = &builtinCastIntAsStringSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CastIntAsString) @@ -315,7 +315,7 @@ func (c *castAsStringFunctionClass) getFunction(ctx sessionctx.Context, args []E case types.ETString: // When cast from binary to some other charsets, we should check if the binary is valid or not. // so we build a from_binary function to do this check. - bf.args[0] = HandleBinaryLiteral(ctx, args[0], &ExprCollation{Charset: c.tp.Charset, Collation: c.tp.Collate}, c.funcName) + bf.args[0] = HandleBinaryLiteral(ctx, args[0], &ExprCollation{Charset: c.tp.GetCharset(), Collation: c.tp.GetCollate()}, c.funcName) sig = &builtinCastStringAsStringSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CastStringAsString) default: @@ -449,7 +449,7 @@ func (c *castAsJSONFunctionClass) getFunction(ctx sessionctx.Context, args []Exp sig.setPbCode(tipb.ScalarFuncSig_CastJsonAsJson) case types.ETString: sig = &builtinCastStringAsJSONSig{bf} - sig.getRetTp().Flag |= mysql.ParseToJSONFlag + sig.getRetTp().AddFlag(mysql.ParseToJSONFlag) sig.setPbCode(tipb.ScalarFuncSig_CastStringAsJson) default: panic("unsupported types.EvalType in castAsJSONFunctionClass") @@ -472,7 +472,7 @@ func (b *builtinCastIntAsIntSig) evalInt(row chunk.Row) (res int64, isNull bool, if isNull || err != nil { return } - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && res < 0 { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && res < 0 { res = 0 } return @@ -493,12 +493,12 @@ func (b *builtinCastIntAsRealSig) evalReal(row chunk.Row) (res float64, isNull b if isNull || err != nil { return res, isNull, err } - if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag); !mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 { + if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()); !mysql.HasUnsignedFlag(b.tp.GetFlag()) && !unsignedArgs0 { res = float64(val) } else if b.inUnion && !unsignedArgs0 && val < 0 { // Round up to 0 if the value is negative but the expression eval type is unsigned in `UNION` statement // NOTE: the following expressions are equal (so choose the more efficient one): - // `b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 && val < 0` + // `b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && !unsignedArgs0 && val < 0` // `b.inUnion && !unsignedArgs0 && val < 0` res = 0 } else { @@ -524,11 +524,11 @@ func (b *builtinCastIntAsDecimalSig) evalDecimal(row chunk.Row) (res *types.MyDe return res, isNull, err } - if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag); !mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 { + if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()); !mysql.HasUnsignedFlag(b.tp.GetFlag()) && !unsignedArgs0 { res = types.NewDecFromInt(val) // Round up to 0 if the value is negative but the expression eval type is unsigned in `UNION` statement // NOTE: the following expressions are equal (so choose the more efficient one): - // `b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 && val < 0` + // `b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && !unsignedArgs0 && val < 0` // `b.inUnion && !unsignedArgs0 && val < 0` } else if b.inUnion && !unsignedArgs0 && val < 0 { res = &types.MyDecimal{} @@ -555,12 +555,12 @@ func (b *builtinCastIntAsStringSig) evalString(row chunk.Row) (res string, isNul return res, isNull, err } tp := b.args[0].GetType() - if !mysql.HasUnsignedFlag(tp.Flag) { + if !mysql.HasUnsignedFlag(tp.GetFlag()) { res = strconv.FormatInt(val, 10) } else { res = strconv.FormatUint(uint64(val), 10) } - if tp.Tp == mysql.TypeYear && res == "0" { + if tp.GetType() == mysql.TypeYear && res == "0" { res = "0000" } res, err = types.ProduceStrWithSpecifiedTp(res, b.tp, b.ctx.GetSessionVars().StmtCtx, false) @@ -586,16 +586,16 @@ func (b *builtinCastIntAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNul return res, isNull, err } - if b.args[0].GetType().Tp == mysql.TypeYear { + if b.args[0].GetType().GetType() == mysql.TypeYear { res, err = types.ParseTimeFromYear(b.ctx.GetSessionVars().StmtCtx, val) } else { - res, err = types.ParseTimeFromNum(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Tp, b.tp.Decimal) + res, err = types.ParseTimeFromNum(b.ctx.GetSessionVars().StmtCtx, val, b.tp.GetType(), b.tp.GetDecimal()) } if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) } @@ -617,7 +617,7 @@ func (b *builtinCastIntAsDurationSig) evalDuration(row chunk.Row) (res types.Dur if isNull || err != nil { return res, isNull, err } - dur, err := types.NumberToDuration(val, b.tp.Decimal) + dur, err := types.NumberToDuration(val, b.tp.GetDecimal()) if err != nil { if types.ErrOverflow.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, err) @@ -645,9 +645,9 @@ func (b *builtinCastIntAsJSONSig) evalJSON(row chunk.Row) (res json.BinaryJSON, if isNull || err != nil { return res, isNull, err } - if mysql.HasIsBooleanFlag(b.args[0].GetType().Flag) { + if mysql.HasIsBooleanFlag(b.args[0].GetType().GetFlag()) { res = json.CreateBinary(val != 0) - } else if mysql.HasUnsignedFlag(b.args[0].GetType().Flag) { + } else if mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) { res = json.CreateBinary(uint64(val)) } else { res = json.CreateBinary(val) @@ -709,7 +709,7 @@ func (b *builtinCastStringAsJSONSig) evalJSON(row chunk.Row) (res json.BinaryJSO if isNull || err != nil { return res, isNull, err } - if mysql.HasParseToJSONFlag(b.tp.Flag) { + if mysql.HasParseToJSONFlag(b.tp.GetFlag()) { res, err = json.ParseBinaryFromString(val) } else { res = json.CreateBinary(val) @@ -769,7 +769,7 @@ func (b *builtinCastRealAsRealSig) Clone() builtinFunc { func (b *builtinCastRealAsRealSig) evalReal(row chunk.Row) (res float64, isNull bool, err error) { res, isNull, err = b.args[0].EvalReal(b.ctx, row) - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && res < 0 { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && res < 0 { res = 0 } return @@ -790,7 +790,7 @@ func (b *builtinCastRealAsIntSig) evalInt(row chunk.Row) (res int64, isNull bool if isNull || err != nil { return res, isNull, err } - if !mysql.HasUnsignedFlag(b.tp.Flag) { + if !mysql.HasUnsignedFlag(b.tp.GetFlag()) { res, err = types.ConvertFloatToInt(val, types.IntergerSignedLowerBound(mysql.TypeLonglong), types.IntergerSignedUpperBound(mysql.TypeLonglong), mysql.TypeLonglong) } else if b.inUnion && val < 0 { res = 0 @@ -856,7 +856,7 @@ func (b *builtinCastRealAsStringSig) evalString(row chunk.Row) (res string, isNu } bits := 64 - if b.args[0].GetType().Tp == mysql.TypeFloat { + if b.args[0].GetType().GetType() == mysql.TypeFloat { // b.args[0].EvalReal() casts the value from float32 to float64, for example: // float32(208.867) is cast to float64(208.86700439) // If we strconv.FormatFloat the value with 64bits, the result is incorrect! @@ -890,11 +890,11 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er return types.ZeroTime, false, nil } sc := b.ctx.GetSessionVars().StmtCtx - res, err := types.ParseTime(sc, fv, b.tp.Tp, b.tp.Decimal) + res, err := types.ParseTime(sc, fv, b.tp.GetType(), b.tp.GetDecimal()) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) } @@ -916,7 +916,7 @@ func (b *builtinCastRealAsDurationSig) evalDuration(row chunk.Row) (res types.Du if isNull || err != nil { return res, isNull, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(val, 'f', -1, 64), b.tp.Decimal) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(val, 'f', -1, 64), b.tp.GetDecimal()) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -943,7 +943,7 @@ func (b *builtinCastDecimalAsDecimalSig) evalDecimal(row chunk.Row) (res *types. return res, isNull, err } res = &types.MyDecimal{} - if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && evalDecimal.IsNegative()) { + if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && evalDecimal.IsNegative()) { *res = *evalDecimal } sc := b.ctx.GetSessionVars().StmtCtx @@ -974,7 +974,7 @@ func (b *builtinCastDecimalAsIntSig) evalInt(row chunk.Row) (res int64, isNull b return 0, true, err } - if !mysql.HasUnsignedFlag(b.tp.Flag) { + if !mysql.HasUnsignedFlag(b.tp.GetFlag()) { res, err = to.ToInt() } else if b.inUnion && to.IsNegative() { res = 0 @@ -1044,7 +1044,7 @@ func (b *builtinCastDecimalAsRealSig) evalReal(row chunk.Row) (res float64, isNu if isNull || err != nil { return res, isNull, err } - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && val.IsNegative() { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && val.IsNegative() { res = 0 } else { res, err = val.ToFloat64() @@ -1068,11 +1068,11 @@ func (b *builtinCastDecimalAsTimeSig) evalTime(row chunk.Row) (res types.Time, i return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTimeFromFloatString(sc, string(val.ToString()), b.tp.Tp, b.tp.Decimal) + res, err = types.ParseTimeFromFloatString(sc, string(val.ToString()), b.tp.GetType(), b.tp.GetDecimal()) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) } @@ -1094,7 +1094,7 @@ func (b *builtinCastDecimalAsDurationSig) evalDuration(row chunk.Row) (res types if isNull || err != nil { return res, true, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(val.ToString()), b.tp.Decimal) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(val.ToString()), b.tp.GetDecimal()) if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) // ErrTruncatedWrongVal needs to be considered NULL. @@ -1187,14 +1187,14 @@ func (b *builtinCastStringAsIntSig) evalInt(row chunk.Row) (res int64, isNull bo ures, err = types.StrToUint(sc, val, true) res = int64(ures) - if err == nil && !mysql.HasUnsignedFlag(b.tp.Flag) && ures > uint64(math.MaxInt64) { + if err == nil && !mysql.HasUnsignedFlag(b.tp.GetFlag()) && ures > uint64(math.MaxInt64) { sc.AppendWarning(types.ErrCastAsSignedOverflow) } - } else if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) { + } else if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) { res = 0 } else { res, err = types.StrToInt(sc, val, true) - if err == nil && mysql.HasUnsignedFlag(b.tp.Flag) { + if err == nil && mysql.HasUnsignedFlag(b.tp.GetFlag()) { // If overflow, don't append this warnings sc.AppendWarning(types.ErrCastNegIntAsUnsigned) } @@ -1233,7 +1233,7 @@ func (b *builtinCastStringAsRealSig) evalReal(row chunk.Row) (res float64, isNul if err != nil { return 0, false, err } - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && res < 0 { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && res < 0 { res = 0 } res, err = types.ProduceFloatWithSpecifiedTp(res, b.tp, sc) @@ -1262,7 +1262,7 @@ func (b *builtinCastStringAsDecimalSig) evalDecimal(row chunk.Row) (res *types.M isNegative := len(val) > 1 && val[0] == '-' res = new(types.MyDecimal) sc := b.ctx.GetSessionVars().StmtCtx - if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && isNegative) { + if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && isNegative) { err = sc.HandleTruncate(res.FromString([]byte(val))) if err != nil { return res, false, err @@ -1288,14 +1288,14 @@ func (b *builtinCastStringAsTimeSig) evalTime(row chunk.Row) (res types.Time, is return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, val, b.tp.Tp, b.tp.Decimal) + res, err = types.ParseTime(sc, val, b.tp.GetType(), b.tp.GetDecimal()) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } if res.IsZero() && b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, res.String())) } - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) } @@ -1317,7 +1317,7 @@ func (b *builtinCastStringAsDurationSig) evalDuration(row chunk.Row) (res types. if isNull || err != nil { return res, isNull, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Decimal) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, val, b.tp.GetDecimal()) if types.ErrTruncatedWrongVal.Equal(err) { sc := b.ctx.GetSessionVars().StmtCtx err = sc.HandleTruncate(err) @@ -1346,14 +1346,14 @@ func (b *builtinCastTimeAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu } sc := b.ctx.GetSessionVars().StmtCtx - if res, err = res.Convert(sc, b.tp.Tp); err != nil { + if res, err = res.Convert(sc, b.tp.GetType()); err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - res, err = res.RoundFrac(sc, b.tp.Decimal) - if b.tp.Tp == mysql.TypeDate { + res, err = res.RoundFrac(sc, b.tp.GetDecimal()) + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) - res.SetType(b.tp.Tp) + res.SetType(b.tp.GetType()) } return res, false, err } @@ -1463,7 +1463,7 @@ func (b *builtinCastTimeAsDurationSig) evalDuration(row chunk.Row) (res types.Du if err != nil { return res, false, err } - res, err = res.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) + res, err = res.RoundFrac(b.tp.GetDecimal(), b.ctx.GetSessionVars().Location()) return res, false, err } @@ -1482,7 +1482,7 @@ func (b *builtinCastDurationAsDurationSig) evalDuration(row chunk.Row) (res type if isNull || err != nil { return res, isNull, err } - res, err = res.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) + res, err = res.RoundFrac(b.tp.GetDecimal(), b.ctx.GetSessionVars().Location()) return res, false, err } @@ -1578,8 +1578,8 @@ func (b *builtinCastDurationAsStringSig) evalString(row chunk.Row) (res string, } func padZeroForBinaryType(s string, tp *types.FieldType, ctx sessionctx.Context) (string, bool, error) { - flen := tp.Flen - if tp.Tp == mysql.TypeString && types.IsBinaryStr(tp) && len(s) < flen { + flen := tp.GetFlen() + if tp.GetType() == mysql.TypeString && types.IsBinaryStr(tp) && len(s) < flen { valStr, _ := ctx.GetSessionVars().GetSystemVar(variable.MaxAllowedPacket) maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64) if err != nil { @@ -1610,11 +1610,11 @@ func (b *builtinCastDurationAsTimeSig) evalTime(row chunk.Row) (res types.Time, return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = val.ConvertToTime(sc, b.tp.Tp) + res, err = val.ConvertToTime(sc, b.tp.GetType()) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - res, err = res.RoundFrac(sc, b.tp.Decimal) + res, err = res.RoundFrac(sc, b.tp.GetDecimal()) return res, false, err } @@ -1648,7 +1648,7 @@ func (b *builtinCastJSONAsIntSig) evalInt(row chunk.Row) (res int64, isNull bool return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ConvertJSONToInt64(sc, val, mysql.HasUnsignedFlag(b.tp.Flag)) + res, err = types.ConvertJSONToInt64(sc, val, mysql.HasUnsignedFlag(b.tp.GetFlag())) return } @@ -1734,11 +1734,11 @@ func (b *builtinCastJSONAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu return res, false, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, s, b.tp.Tp, b.tp.Decimal) + res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal()) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) } @@ -1764,7 +1764,7 @@ func (b *builtinCastJSONAsDurationSig) evalDuration(row chunk.Row) (res types.Du if err != nil { return res, false, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, s, b.tp.Decimal) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, s, b.tp.GetDecimal()) if types.ErrTruncatedWrongVal.Equal(err) { sc := b.ctx.GetSessionVars().StmtCtx err = sc.HandleTruncate(err) @@ -1830,7 +1830,7 @@ func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *Exp if expr.GetType().EvalType() != types.ETString { return expr } - if expr.GetType().Collate == ec.Collation { + if expr.GetType().GetCollate() == ec.Collation { return expr } tp := expr.GetType().Clone() @@ -1841,7 +1841,8 @@ func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *Exp return expr } } - tp.Charset, tp.Collate = ec.Charset, ec.Collation + tp.SetCharset(ec.Charset) + tp.SetCollate(ec.Collation) newExpr := BuildCastFunction(ctx, expr, tp) return newExpr } @@ -1850,8 +1851,8 @@ func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *Exp func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldType) (res Expression) { argType := expr.GetType() // If source argument's nullable, then target type should be nullable - if !mysql.HasNotNullFlag(argType.Flag) { - tp.Flag &= ^mysql.NotNullFlag + if !mysql.HasNotNullFlag(argType.GetFlag()) { + tp.DelFlag(mysql.NotNullFlag) } expr = TryPushCastIntoControlFunctionForHybridType(ctx, expr, tp) var fc functionClass @@ -1870,8 +1871,8 @@ func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldT fc = &castAsJSONFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} case types.ETString: fc = &castAsStringFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} - if expr.GetType().Tp == mysql.TypeBit { - tp.Flen = (expr.GetType().Flen + 7) / 8 + if expr.GetType().GetType() == mysql.TypeBit { + tp.SetFlen((expr.GetType().GetFlen() + 7) / 8) } } f, err := fc.getFunction(ctx, []Expression{expr}) @@ -1893,21 +1894,22 @@ func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldT // WrapWithCastAsInt wraps `expr` with `cast` if the return type of expr is not // type int, otherwise, returns `expr` directly. func WrapWithCastAsInt(ctx sessionctx.Context, expr Expression) Expression { - if expr.GetType().Tp == mysql.TypeEnum { + if expr.GetType().GetType() == mysql.TypeEnum { if col, ok := expr.(*Column); ok { col = col.Clone().(*Column) col.RetType = col.RetType.Clone() expr = col } - expr.GetType().Flag |= mysql.EnumSetAsIntFlag + expr.GetType().AddFlag(mysql.EnumSetAsIntFlag) } if expr.GetType().EvalType() == types.ETInt { return expr } tp := types.NewFieldType(mysql.TypeLonglong) - tp.Flen, tp.Decimal = expr.GetType().Flen, 0 + tp.SetFlen(expr.GetType().GetFlen()) + tp.SetDecimal(0) types.SetBinChsClnFlag(tp) - tp.Flag |= expr.GetType().Flag & mysql.UnsignedFlag + tp.AddFlag(expr.GetType().GetFlag() & mysql.UnsignedFlag) return BuildCastFunction(ctx, expr, tp) } @@ -1918,9 +1920,10 @@ func WrapWithCastAsReal(ctx sessionctx.Context, expr Expression) Expression { return expr } tp := types.NewFieldType(mysql.TypeDouble) - tp.Flen, tp.Decimal = mysql.MaxRealWidth, types.UnspecifiedLength + tp.SetFlen(mysql.MaxRealWidth) + tp.SetDecimal(types.UnspecifiedLength) types.SetBinChsClnFlag(tp) - tp.Flag |= expr.GetType().Flag & mysql.UnsignedFlag + tp.AddFlag(expr.GetType().GetFlag() & mysql.UnsignedFlag) return BuildCastFunction(ctx, expr, tp) } @@ -1931,15 +1934,17 @@ func WrapWithCastAsDecimal(ctx sessionctx.Context, expr Expression) Expression { return expr } tp := types.NewFieldType(mysql.TypeNewDecimal) - tp.Flen, tp.Decimal = expr.GetType().Flen, expr.GetType().Decimal + tp.SetFlen(expr.GetType().GetFlen()) + tp.SetDecimal(expr.GetType().GetDecimal()) + if expr.GetType().EvalType() == types.ETInt { - tp.Flen = mysql.MaxIntWidth + tp.SetFlen(mysql.MaxIntWidth) } - if tp.Flen == types.UnspecifiedLength || tp.Flen > mysql.MaxDecimalWidth { - tp.Flen = mysql.MaxDecimalWidth + if tp.GetFlen() == types.UnspecifiedLength || tp.GetFlen() > mysql.MaxDecimalWidth { + tp.SetFlen(mysql.MaxDecimalWidth) } types.SetBinChsClnFlag(tp) - tp.Flag |= expr.GetType().Flag & mysql.UnsignedFlag + tp.AddFlag(expr.GetType().GetFlag() & mysql.UnsignedFlag) castExpr := BuildCastFunction(ctx, expr, tp) // For const item, we can use find-grained precision and scale by the result. if castExpr.ConstItem(ctx.GetSessionVars().StmtCtx) { @@ -1947,13 +1952,13 @@ func WrapWithCastAsDecimal(ctx sessionctx.Context, expr Expression) Expression { if !isnull && err == nil { precision, frac := val.PrecisionAndFrac() castTp := castExpr.GetType() - castTp.Decimal = frac - castTp.Flen = precision - if castTp.Flen > mysql.MaxDecimalWidth { - castTp.Flen = mysql.MaxDecimalWidth + castTp.SetDecimal(frac) + castTp.SetFlen(precision) + if castTp.GetFlen() > mysql.MaxDecimalWidth { + castTp.SetFlen(mysql.MaxDecimalWidth) } - if castTp.Decimal > mysql.MaxDecimalScale { - castTp.Decimal = mysql.MaxDecimalScale + if castTp.GetDecimal() > mysql.MaxDecimalScale { + castTp.SetDecimal(mysql.MaxDecimalScale) } } } @@ -1967,12 +1972,12 @@ func WrapWithCastAsString(ctx sessionctx.Context, expr Expression) Expression { if exprTp.EvalType() == types.ETString { return expr } - argLen := exprTp.Flen + argLen := exprTp.GetFlen() // If expr is decimal, we should take the decimal point ,negative sign and the leading zero(0.xxx) - // into consideration, so we set `expr.GetType().Flen + 3` as the `argLen`. + // into consideration, so we set `expr.GetType().GetFlen() + 3` as the `argLen`. // Since the length of float and double is not accurate, we do not handle // them. - if exprTp.Tp == mysql.TypeNewDecimal && argLen != types.UnspecifiedFsp { + if exprTp.GetType() == mysql.TypeNewDecimal && argLen != types.UnspecifiedFsp { argLen += 3 } @@ -1980,55 +1985,60 @@ func WrapWithCastAsString(ctx sessionctx.Context, expr Expression) Expression { argLen = mysql.MaxIntWidth // For TypeBit, castAsString will make length as int(( bit_len + 7 ) / 8) bytes due to // TiKV needs the bit's real len during calculating, eg: ascii(bit). - if exprTp.Tp == mysql.TypeBit { - argLen = (exprTp.Flen + 7) / 8 + if exprTp.GetType() == mysql.TypeBit { + argLen = (exprTp.GetFlen() + 7) / 8 } } // Because we can't control the length of cast(float as char) for now, we can't determine the argLen. - if exprTp.Tp == mysql.TypeFloat || exprTp.Tp == mysql.TypeDouble { + if exprTp.GetType() == mysql.TypeFloat || exprTp.GetType() == mysql.TypeDouble { argLen = -1 } tp := types.NewFieldType(mysql.TypeVarString) if expr.Coercibility() == CoercibilityExplicit { - tp.Charset, tp.Collate = expr.CharsetAndCollation() + charset, collate := expr.CharsetAndCollation() + tp.SetCharset(charset) + tp.SetCollate(collate) } else { - tp.Charset, tp.Collate = ctx.GetSessionVars().GetCharsetInfo() + charset, collate := ctx.GetSessionVars().GetCharsetInfo() + tp.SetCharset(charset) + tp.SetCollate(collate) } - tp.Flen, tp.Decimal = argLen, types.UnspecifiedLength + tp.SetFlen(argLen) + tp.SetDecimal(types.UnspecifiedLength) return BuildCastFunction(ctx, expr, tp) } // WrapWithCastAsTime wraps `expr` with `cast` if the return type of expr is not // same as type of the specified `tp` , otherwise, returns `expr` directly. func WrapWithCastAsTime(ctx sessionctx.Context, expr Expression, tp *types.FieldType) Expression { - exprTp := expr.GetType().Tp - if tp.Tp == exprTp { + exprTp := expr.GetType().GetType() + if tp.GetType() == exprTp { return expr - } else if (exprTp == mysql.TypeDate || exprTp == mysql.TypeTimestamp) && tp.Tp == mysql.TypeDatetime { + } else if (exprTp == mysql.TypeDate || exprTp == mysql.TypeTimestamp) && tp.GetType() == mysql.TypeDatetime { return expr } switch x := expr.GetType().EvalType(); x { case types.ETInt: - tp.Decimal = types.MinFsp + tp.SetDecimal(types.MinFsp) case types.ETString, types.ETReal, types.ETJson: - tp.Decimal = types.MaxFsp + tp.SetDecimal(types.MaxFsp) case types.ETDatetime, types.ETTimestamp, types.ETDuration: - tp.Decimal = expr.GetType().Decimal + tp.SetDecimal(expr.GetType().GetDecimal()) case types.ETDecimal: - tp.Decimal = expr.GetType().Decimal - if tp.Decimal > types.MaxFsp { - tp.Decimal = types.MaxFsp + tp.SetDecimal(expr.GetType().GetDecimal()) + if tp.GetDecimal() > types.MaxFsp { + tp.SetDecimal(types.MaxFsp) } default: } - switch tp.Tp { + switch tp.GetType() { case mysql.TypeDate: - tp.Flen = mysql.MaxDateWidth + tp.SetFlen(mysql.MaxDateWidth) case mysql.TypeDatetime, mysql.TypeTimestamp: - tp.Flen = mysql.MaxDatetimeWidthNoFsp - if tp.Decimal > 0 { - tp.Flen = tp.Flen + 1 + tp.Decimal + tp.SetFlen(mysql.MaxDatetimeWidthNoFsp) + if tp.GetDecimal() > 0 { + tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal()) } } types.SetBinChsClnFlag(tp) @@ -2038,19 +2048,19 @@ func WrapWithCastAsTime(ctx sessionctx.Context, expr Expression, tp *types.Field // WrapWithCastAsDuration wraps `expr` with `cast` if the return type of expr is // not type duration, otherwise, returns `expr` directly. func WrapWithCastAsDuration(ctx sessionctx.Context, expr Expression) Expression { - if expr.GetType().Tp == mysql.TypeDuration { + if expr.GetType().GetType() == mysql.TypeDuration { return expr } tp := types.NewFieldType(mysql.TypeDuration) - switch x := expr.GetType(); x.Tp { + switch x := expr.GetType(); x.GetType() { case mysql.TypeDatetime, mysql.TypeTimestamp, mysql.TypeDate: - tp.Decimal = x.Decimal + tp.SetDecimal(x.GetDecimal()) default: - tp.Decimal = types.MaxFsp + tp.SetDecimal(types.MaxFsp) } - tp.Flen = mysql.MaxDurationWidthNoFsp - if tp.Decimal > 0 { - tp.Flen = tp.Flen + 1 + tp.Decimal + tp.SetFlen(mysql.MaxDurationWidthNoFsp) + if tp.GetDecimal() > 0 { + tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal()) } return BuildCastFunction(ctx, expr, tp) } @@ -2058,17 +2068,10 @@ func WrapWithCastAsDuration(ctx sessionctx.Context, expr Expression) Expression // WrapWithCastAsJSON wraps `expr` with `cast` if the return type of expr is not // type json, otherwise, returns `expr` directly. func WrapWithCastAsJSON(ctx sessionctx.Context, expr Expression) Expression { - if expr.GetType().Tp == mysql.TypeJSON && !mysql.HasParseToJSONFlag(expr.GetType().Flag) { + if expr.GetType().GetType() == mysql.TypeJSON && !mysql.HasParseToJSONFlag(expr.GetType().GetFlag()) { return expr } - tp := &types.FieldType{ - Tp: mysql.TypeJSON, - Flen: 12582912, // FIXME: Here the Flen is not trusted. - Decimal: 0, - Charset: mysql.DefaultCharset, - Collate: mysql.DefaultCollationName, - Flag: mysql.BinaryFlag, - } + tp := types.NewFieldTypeBuilderP().SetType(mysql.TypeJSON).SetFlag(mysql.BinaryFlag).SetFlen(12582912).SetCharset(mysql.DefaultCharset).SetCollate(mysql.DefaultCollationName).BuildP() return BuildCastFunction(ctx, expr, tp) } @@ -2097,7 +2100,7 @@ func TryPushCastIntoControlFunctionForHybridType(ctx sessionctx.Context, expr Ex isHybrid := func(ft *types.FieldType) bool { // todo: compatible with mysql control function using bit type. issue 24725 - return ft.Hybrid() && ft.Tp != mysql.TypeBit + return ft.Hybrid() && ft.GetType() != mysql.TypeBit } args := sf.GetArgs() diff --git a/expression/builtin_cast_test.go b/expression/builtin_cast_test.go index f0d498dd110e9..083cf93791ac1 100644 --- a/expression/builtin_cast_test.go +++ b/expression/builtin_cast_test.go @@ -47,11 +47,11 @@ func TestCastFunctions(t *testing.T) { }() tp := types.NewFieldType(mysql.TypeString) - tp.Flen = 5 + tp.SetFlen(5) // cast(str as char(N)), N < len([]rune(str)). // cast("你好world" as char(5)) - tp.Charset = charset.CharsetUTF8 + tp.SetCharset(charset.CharsetUTF8) f := BuildCastFunction(ctx, &Constant{Value: types.NewDatum("你好world"), RetType: tp}, tp) res, err := f.Eval(chunk.Row{}) require.NoError(t, err) @@ -68,9 +68,10 @@ func TestCastFunctions(t *testing.T) { // cast(str as binary(N)), N < len(str). // cast("你好world" as binary(5)) str := "你好world" - tp.Flag |= mysql.BinaryFlag - tp.Charset = charset.CharsetBin - tp.Collate = charset.CollationBin + + tp.AddFlag(mysql.BinaryFlag) + tp.SetCharset(charset.CharsetBin) + tp.SetCollate(charset.CollationBin) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum(str), RetType: types.NewFieldType(mysql.TypeString)}, tp) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -86,7 +87,7 @@ func TestCastFunctions(t *testing.T) { // cast(str as binary(N)), N > len([]byte(str)). // cast("a" as binary(4294967295)) - tp.Flen = 4294967295 + tp.SetFlen(4294967295) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum("a"), RetType: types.NewFieldType(mysql.TypeString)}, tp) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -104,13 +105,7 @@ func TestCastFunctions(t *testing.T) { sc.OverflowAsWarning = true // cast('18446744073709551616' as unsigned); - tp1 := &types.FieldType{ - Tp: mysql.TypeLonglong, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - Flen: mysql.MaxIntWidth, - } + tp1 := types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.BinaryFlag).SetFlen(mysql.MaxIntWidth).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin).BuildP() f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum("18446744073709551616"), RetType: types.NewFieldType(mysql.TypeString)}, tp1) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -120,8 +115,8 @@ func TestCastFunctions(t *testing.T) { lastWarn = warnings[len(warnings)-1] require.Truef(t, terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), "err %v", lastWarn.Err) - originFlag := tp1.Flag - tp1.Flag |= mysql.UnsignedFlag + originFlag := tp1.GetFlag() + tp1.AddFlag(mysql.UnsignedFlag) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum("-1"), RetType: types.NewFieldType(mysql.TypeString)}, tp1) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -130,7 +125,7 @@ func TestCastFunctions(t *testing.T) { warnings = sc.GetWarnings() lastWarn = warnings[len(warnings)-1] require.Truef(t, terror.ErrorEqual(types.ErrCastNegIntAsUnsigned, lastWarn.Err), "err %v", lastWarn.Err) - tp1.Flag = originFlag + tp1.SetFlag(originFlag) previousWarnings := len(sc.GetWarnings()) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum("-1"), RetType: types.NewFieldType(mysql.TypeString)}, tp1) @@ -172,7 +167,7 @@ func TestCastFunctions(t *testing.T) { // cast('18446744073709551616' as signed); mask := ^mysql.UnsignedFlag - tp1.Flag &= mask + tp1.SetFlag(tp1.GetFlag() & mask) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum("18446744073709551616"), RetType: types.NewFieldType(mysql.TypeString)}, tp1) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -215,14 +210,7 @@ func TestCastFunctions(t *testing.T) { // create table t1(s1 time); // insert into t1 values('11:11:11'); // select cast(s1 as decimal(7, 2)) from t1; - ft := &types.FieldType{ - Tp: mysql.TypeNewDecimal, - Flag: mysql.BinaryFlag | mysql.UnsignedFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - Flen: 7, - Decimal: 2, - } + ft := types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.BinaryFlag | mysql.UnsignedFlag).SetFlen(7).SetDecimal(2).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin).BuildP() f = BuildCastFunction(ctx, &Constant{Value: timeDatum, RetType: types.NewFieldType(mysql.TypeDatetime)}, ft) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -239,16 +227,9 @@ func TestCastFunctions(t *testing.T) { // create table tt(a bigint unsigned); // insert into tt values(18446744073709551615); // select cast(a as decimal(65, 0)) from tt; - ft = &types.FieldType{ - Tp: mysql.TypeNewDecimal, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - Flen: 65, - Decimal: 0, - } + ft = types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlag(mysql.BinaryFlag).SetFlen(65).SetCharset(charset.CharsetBin).SetCollate(charset.CollationBin).BuildP() rt := types.NewFieldType(mysql.TypeLonglong) - rt.Flag = mysql.BinaryFlag | mysql.UnsignedFlag + rt.SetFlag(mysql.BinaryFlag | mysql.UnsignedFlag) f = BuildCastFunction(ctx, &Constant{Value: types.NewUintDatum(18446744073709551615), RetType: rt}, ft) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -264,8 +245,8 @@ func TestCastFunctions(t *testing.T) { } // cast(1234 as char(0)) - tp.Flen = 0 - tp.Charset = charset.CharsetUTF8 + tp.SetFlen(0) + tp.SetCharset(charset.CharsetUTF8) f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum(1234), RetType: types.NewFieldType(mysql.TypeString)}, tp) res, err = f.Eval(chunk.Row{}) require.NoError(t, err) @@ -323,8 +304,8 @@ func TestCastFuncSig(t *testing.T) { var sig builtinFunc durationColumn := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} - durationColumn.RetType.Decimal = types.DefaultFsp - // Test cast as Decimal. + durationColumn.RetType.SetDecimal(types.DefaultFsp) + // Test cast as decimal. castToDecCases := []struct { before *Column after *types.MyDecimal @@ -387,7 +368,7 @@ func TestCastFuncSig(t *testing.T) { require.Equal(t, 0, res.Compare(c.after)) } - durationColumn.RetType.Decimal = 1 + durationColumn.RetType.SetDecimal(1) castToDecCases2 := []struct { before *Column flen int @@ -448,7 +429,8 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToDecCases2 { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeNewDecimal) - tp.Flen, tp.Decimal = c.flen, c.decimal + tp.SetFlen(c.flen) + tp.SetDecimal(c.decimal) b, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) decFunc := newBaseBuiltinCastFunc(b, false) @@ -473,7 +455,7 @@ func TestCastFuncSig(t *testing.T) { require.Equal(t, c.after.ToString(), res.ToString()) } - durationColumn.RetType.Decimal = 0 + durationColumn.RetType.SetDecimal(0) // Test cast as int. castToIntCases := []struct { before *Column @@ -661,7 +643,7 @@ func TestCastFuncSig(t *testing.T) { } for i, c := range castToStringCases { tp := types.NewFieldType(mysql.TypeVarString) - tp.Charset = charset.CharsetBin + tp.SetCharset(charset.CharsetBin) args := []Expression{c.before} stringFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) @@ -741,7 +723,8 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToStringCases2 { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeVarString) - tp.Flen, tp.Charset = c.flen, charset.CharsetBin + tp.SetFlen(c.flen) + tp.SetCharset(charset.CharsetBin) stringFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) stringFunc.tp = tp @@ -757,7 +740,7 @@ func TestCastFuncSig(t *testing.T) { case 4: sig = &builtinCastDurationAsStringSig{stringFunc} case 5: - stringFunc.tp.Charset = charset.CharsetUTF8 + stringFunc.tp.SetCharset(charset.CharsetUTF8) sig = &builtinCastStringAsStringSig{stringFunc} } res, isNull, err := sig.evalString(c.row.ToRow()) @@ -817,7 +800,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToTimeCases { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeDatetime) - tp.Decimal = types.DefaultFsp + tp.SetDecimal(types.DefaultFsp) timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) timeFunc.tp = tp @@ -902,7 +885,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToTimeCases2 { args := []Expression{c.before} tp := types.NewFieldType(c.tp) - tp.Decimal = c.fsp + tp.SetDecimal(c.fsp) timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) timeFunc.tp = tp @@ -984,7 +967,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToDurationCases { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeDuration) - tp.Decimal = types.DefaultFsp + tp.SetDecimal(types.DefaultFsp) durationFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) durationFunc.tp = tp @@ -1062,7 +1045,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToDurationCases2 { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeDuration) - tp.Decimal = c.fsp + tp.SetDecimal(c.fsp) durationFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) durationFunc.tp = tp @@ -1130,8 +1113,8 @@ func TestCastJSONAsDecimalSig(t *testing.T) { require.NoError(t, err) decFunc := newBaseBuiltinCastFunc(b, false) decFunc.tp = types.NewFieldType(mysql.TypeNewDecimal) - decFunc.tp.Flen = 60 - decFunc.tp.Decimal = 2 + decFunc.tp.SetFlen(60) + decFunc.tp.SetDecimal(2) sig := &builtinCastJSONAsDecimalSig{decFunc} var tests = []struct { @@ -1161,14 +1144,14 @@ func TestCastJSONAsDecimalSig(t *testing.T) { } } -// TestWrapWithCastAsTypesClasses tests WrapWithCastAsInt/Real/String/Decimal. +// TestWrapWithCastAsTypesClasses tests WrapWithCastAsInt/Real/String/decimal. func TestWrapWithCastAsTypesClasses(t *testing.T) { ctx := createContext(t) durationColumn0 := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} - durationColumn0.RetType.Decimal = types.DefaultFsp + durationColumn0.RetType.SetDecimal(types.DefaultFsp) durationColumn3 := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} - durationColumn3.RetType.Decimal = 3 + durationColumn3.RetType.SetDecimal(3) cases := []struct { expr Expression row chunk.MutRow @@ -1272,7 +1255,7 @@ func TestWrapWithCastAsTypesClasses(t *testing.T) { require.Equal(t, c.stringRes, strRes) } - unsignedIntExpr := &Column{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag, Flen: mysql.MaxIntWidth, Decimal: 0}, Index: 0} + unsignedIntExpr := &Column{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).SetFlen(mysql.MaxIntWidth).BuildP(), Index: 0} // test cast unsigned int as string. strExpr := WrapWithCastAsString(ctx, unsignedIntExpr) @@ -1297,7 +1280,7 @@ func TestWrapWithCastAsTypesClasses(t *testing.T) { // test cast unsigned int as Time. timeExpr := WrapWithCastAsTime(ctx, unsignedIntExpr, types.NewFieldType(mysql.TypeDatetime)) - require.Equal(t, mysql.TypeDatetime, timeExpr.GetType().Tp) + require.Equal(t, mysql.TypeDatetime, timeExpr.GetType().GetType()) timeRes, isNull, err := timeExpr.EvalTime(ctx, chunk.MutRowFromDatums([]types.Datum{types.NewUintDatum(uint64(curTimeInt))}).ToRow()) require.NoError(t, err) require.Equal(t, false, isNull) @@ -1353,7 +1336,7 @@ func TestWrapWithCastAsTime(t *testing.T) { res, isNull, err := expr.EvalTime(ctx, chunk.Row{}) require.NoError(t, err) require.Equal(t, false, isNull) - require.Equal(t, c.tp.Tp, res.Type()) + require.Equal(t, c.tp.GetType(), res.Type()) require.Zerof(t, res.Compare(c.res), "case %d res = %s, expect = %s", d, res, c.res) } } @@ -1428,7 +1411,7 @@ func TestWrapWithCastAsString(t *testing.T) { func TestWrapWithCastAsJSON(t *testing.T) { ctx := createContext(t) - input := &Column{RetType: &types.FieldType{Tp: mysql.TypeJSON}} + input := &Column{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeJSON).BuildP()} expr := WrapWithCastAsJSON(ctx, input) output, ok := expr.(*Column) @@ -1450,7 +1433,7 @@ func TestCastIntAsIntVec(t *testing.T) { } cast.inUnion = true - cast.getRetTp().Flag |= mysql.UnsignedFlag + cast.getRetTp().AddFlag(mysql.UnsignedFlag) require.NoError(t, cast.vecEvalInt(input, result)) i64s = result.Int64s() it = chunk.NewIterator4Chunk(input) @@ -1472,7 +1455,7 @@ func TestCastStringAsDecimalSigWithUnsignedFlagInUnion(t *testing.T) { decFunc := newBaseBuiltinCastFunc(b, true) decFunc.tp = types.NewFieldType(mysql.TypeNewDecimal) // set the `UnsignedFlag` bit - decFunc.tp.Flag |= mysql.UnsignedFlag + decFunc.tp.AddFlag(mysql.UnsignedFlag) cast := &builtinCastStringAsDecimalSig{decFunc} cases := []struct { @@ -1507,70 +1490,70 @@ func TestCastConstAsDecimalFieldType(t *testing.T) { } allTestCase := []testCase{ // test int - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(0)}, 1, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(1)}, 1, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-1)}, 1, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(11111)}, 5, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-11111)}, 5, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(1111111111)}, 10, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-1111111111)}, 10, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(111111111111111)}, 15, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-111111111111111)}, 15, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(9223372036854775807)}, 19, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-9223372036854775808)}, 19, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(0)}, 1, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(1)}, 1, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(-1)}, 1, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(11111)}, 5, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(-11111)}, 5, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(1111111111)}, 10, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(-1111111111)}, 10, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(111111111111111)}, 15, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(-111111111111111)}, 15, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(9223372036854775807)}, 19, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).BuildP(), Value: types.NewIntDatum(-9223372036854775808)}, 19, 0}, // test uint - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(0)}, 1, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(1)}, 1, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(11111)}, 5, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(1111111111)}, 10, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(111111111111111)}, 15, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(9223372036854775807)}, 19, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(18446744073709551615)}, 20, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(0)}, 1, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(1)}, 1, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(11111)}, 5, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(1111111111)}, 10, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(111111111111111)}, 15, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(9223372036854775807)}, 19, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(), Value: types.NewUintDatum(18446744073709551615)}, 20, 0}, // test decimal, use origin fieldType - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 10, Decimal: 5}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 10, 5}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 2, Decimal: 1}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("1"))}, 2, 1}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 30, Decimal: 0}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 30, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlen(10).SetDecimal(5).BuildP(), Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 10, 5}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlen(2).SetDecimal(1).BuildP(), Value: types.NewDecimalDatum(types.NewDecFromStringForTest("1"))}, 2, 1}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeNewDecimal).SetFlen(30).SetDecimal(0).BuildP(), Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 30, 0}, // test real - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1.234)}, 4, 3}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1.23456789)}, 9, 8}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(-1234567890.123456789)}, 17, 7}, // float precision lost - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(-1234567890.1234567890123456789)}, 17, 7}, // float precision lost - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e10)}, 11, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e20)}, 21, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e40)}, 41, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e60)}, 61, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e80)}, 65, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-10)}, 10, 10}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-20)}, 20, 20}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-40)}, 40, 30}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1.234)}, 4, 3}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1.23456789)}, 9, 8}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(-1234567890.123456789)}, 17, 7}, // float precision lost + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(-1234567890.1234567890123456789)}, 17, 7}, // float precision lost + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e10)}, 11, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e20)}, 21, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e40)}, 41, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e60)}, 61, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e80)}, 65, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e-10)}, 10, 10}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e-20)}, 20, 20}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDouble).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewFloat64Datum(1e-40)}, 40, 30}, // test string - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.456")}, 6, 3}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.4560")}, 7, 4}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.456000000")}, 12, 9}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123abcde")}, 3, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("1e80")}, 65, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("1e-40")}, 40, 30}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("-1234567890.123456789")}, 19, 9}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("-1234567890.1234567890123456789")}, 29, 19}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("123.456")}, 6, 3}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("123.4560")}, 7, 4}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("123.456000000")}, 12, 9}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("123abcde")}, 3, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("1e80")}, 65, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("1e-40")}, 40, 30}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("-1234567890.123456789")}, 19, 9}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeString).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(), Value: types.NewStringDatum("-1234567890.1234567890123456789")}, 29, 19}, // test time - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 3))}, 9, 3}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 6))}, 12, 6}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 0))}, 6, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDuration).SetFlen(types.UnspecifiedLength).SetDecimal(3).BuildP(), Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 3))}, 9, 3}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDuration).SetFlen(types.UnspecifiedLength).SetDecimal(6).BuildP(), Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 6))}, 12, 6}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDuration).SetFlen(types.UnspecifiedLength).SetDecimal(0).BuildP(), Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 0))}, 6, 0}, // test timestamp - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 14, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 17, 3}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 20, 6}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeTimestamp).SetFlen(types.UnspecifiedLength).SetDecimal(0).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 14, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeTimestamp).SetFlen(types.UnspecifiedLength).SetDecimal(3).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 17, 3}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeTimestamp).SetFlen(types.UnspecifiedLength).SetDecimal(6).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 20, 6}, // test datetime - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 14, 0}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 17, 3}, - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 20, 6}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDatetime).SetFlen(types.UnspecifiedLength).SetDecimal(0).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 14, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDatetime).SetFlen(types.UnspecifiedLength).SetDecimal(3).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 17, 3}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDatetime).SetFlen(types.UnspecifiedLength).SetDecimal(6).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 20, 6}, // test date - {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDate, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDate, 0))}, 8, 0}, + {&Constant{RetType: types.NewFieldTypeBuilderP().SetType(mysql.TypeDate).SetFlen(types.UnspecifiedLength).SetDecimal(0).BuildP(), Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDate, 0))}, 8, 0}, } ctx := createContext(t) for _, tc := range allTestCase { expr := WrapWithCastAsDecimal(ctx, tc.input) - require.Equal(t, tc.resultFlen, expr.GetType().Flen) - require.Equal(t, tc.resultDecimal, expr.GetType().Decimal) + require.Equal(t, tc.resultFlen, expr.GetType().GetFlen()) + require.Equal(t, tc.resultDecimal, expr.GetType().GetDecimal()) } } diff --git a/expression/builtin_cast_vec.go b/expression/builtin_cast_vec.go index dbaf5c27d3ddf..ee29a768dd702 100644 --- a/expression/builtin_cast_vec.go +++ b/expression/builtin_cast_vec.go @@ -44,7 +44,7 @@ func (b *builtinCastIntAsDurationSig) vecEvalDuration(input *chunk.Chunk, result if result.IsNull(i) { continue } - dur, err := types.NumberToDuration(i64s[i], b.tp.Decimal) + dur, err := types.NumberToDuration(i64s[i], b.tp.GetDecimal()) if err != nil { if types.ErrOverflow.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, err) @@ -71,7 +71,7 @@ func (b *builtinCastIntAsIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.Co if err := b.args[0].VecEvalInt(b.ctx, input, result); err != nil { return err } - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) { i64s := result.Int64s() // the null array of result is set by its child args[0], // so we can skip it here to make this loop simpler to improve its performance. @@ -105,8 +105,8 @@ func (b *builtinCastIntAsRealSig) vecEvalReal(input *chunk.Chunk, result *chunk. i64s := buf.Int64s() rs := result.Float64s() - hasUnsignedFlag0 := mysql.HasUnsignedFlag(b.tp.Flag) - hasUnsignedFlag1 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) + hasUnsignedFlag0 := mysql.HasUnsignedFlag(b.tp.GetFlag()) + hasUnsignedFlag1 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) for i := 0; i < n; i++ { if result.IsNull(i) { @@ -138,7 +138,7 @@ func (b *builtinCastRealAsRealSig) vecEvalReal(input *chunk.Chunk, result *chunk } n := input.NumRows() f64s := result.Float64s() - conditionUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) + conditionUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) if !conditionUnionAndUnsigned { return nil } @@ -205,7 +205,7 @@ func (b *builtinCastRealAsStringSig) vecEvalString(input *chunk.Chunk, result *c } bits := 64 - if b.args[0].GetType().Tp == mysql.TypeFloat { + if b.args[0].GetType().GetType() == mysql.TypeFloat { // b.args[0].EvalReal() casts the value from float32 to float64, for example: // float32(208.867) is cast to float64(208.86700439) // If we strconv.FormatFloat the value with 64bits, the result is incorrect! @@ -335,7 +335,7 @@ func (b *builtinCastDurationAsIntSig) vecEvalInt(input *chunk.Chunk, result *chu i64s := result.Int64s() var duration types.Duration ds := buf.GoDurations() - fsp := b.args[0].GetType().Decimal + fsp := b.args[0].GetType().GetDecimal() for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -376,7 +376,7 @@ func (b *builtinCastIntAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk. times := result.Times() i64s := buf.Int64s() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() var tm types.Time for i := 0; i < n; i++ { @@ -384,10 +384,10 @@ func (b *builtinCastIntAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk. continue } - if b.args[0].GetType().Tp == mysql.TypeYear { + if b.args[0].GetType().GetType() == mysql.TypeYear { tm, err = types.ParseTimeFromYear(stmt, i64s[i]) } else { - tm, err = types.ParseTimeFromNum(stmt, i64s[i], b.tp.Tp, fsp) + tm, err = types.ParseTimeFromNum(stmt, i64s[i], b.tp.GetType(), fsp) } if err != nil { @@ -398,7 +398,7 @@ func (b *builtinCastIntAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk. continue } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) } @@ -483,7 +483,7 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk result.MergeNulls(buf) times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -492,7 +492,7 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk if err != nil { return err } - tm, err := types.ParseTime(stmtCtx, s, b.tp.Tp, fsp) + tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -501,7 +501,7 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk continue } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) } @@ -529,7 +529,7 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times := result.Times() f64s := buf.Float64s() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if buf.IsNull(i) { continue @@ -539,7 +539,7 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times[i] = types.ZeroTime continue } - tm, err := types.ParseTime(stmt, fv, b.tp.Tp, fsp) + tm, err := types.ParseTime(stmt, fv, b.tp.GetType(), fsp) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -548,7 +548,7 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk continue } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) } @@ -568,7 +568,7 @@ func (b *builtinCastDecimalAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, resu n := input.NumRows() decs := result.Decimals() sc := b.ctx.GetSessionVars().StmtCtx - conditionUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) + conditionUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) dec := new(types.MyDecimal) for i := 0; i < n; i++ { if result.IsNull(i) { @@ -608,7 +608,7 @@ func (b *builtinCastDurationAsTimeSig) vecEvalTime(input *chunk.Chunk, result *c ds := buf.GoDurations() times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -616,7 +616,7 @@ func (b *builtinCastDurationAsTimeSig) vecEvalTime(input *chunk.Chunk, result *c duration.Duration = ds[i] duration.Fsp = fsp - tm, err := duration.ConvertToTime(stmtCtx, b.tp.Tp) + tm, err := duration.ConvertToTime(stmtCtx, b.tp.GetType()) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -649,8 +649,8 @@ func (b *builtinCastIntAsStringSig) vecEvalString(input *chunk.Chunk, result *ch } tp := b.args[0].GetType() - isUnsigned := mysql.HasUnsignedFlag(tp.Flag) - isYearType := tp.Tp == mysql.TypeYear + isUnsigned := mysql.HasUnsignedFlag(tp.GetFlag()) + isYearType := tp.GetType() == mysql.TypeYear result.ReserveString(n) i64s := buf.Int64s() for i := 0; i < n; i++ { @@ -704,7 +704,7 @@ func (b *builtinCastRealAsIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.C result.MergeNulls(buf) i64s := result.Int64s() f64s := buf.Float64s() - unsigned := mysql.HasUnsignedFlag(b.tp.Flag) + unsigned := mysql.HasUnsignedFlag(b.tp.GetFlag()) for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -784,7 +784,7 @@ func (b *builtinCastStringAsJSONSig) vecEvalJSON(input *chunk.Chunk, result *chu } result.ReserveJSON(n) - hasParse := mysql.HasParseToJSONFlag(b.tp.Flag) + hasParse := mysql.HasParseToJSONFlag(b.tp.GetFlag()) if hasParse { var res json.BinaryJSON for i := 0; i < n; i++ { @@ -882,7 +882,7 @@ func (b *builtinCastStringAsIntSig) vecEvalInt(input *chunk.Chunk, result *chunk result.MergeNulls(buf) sc := b.ctx.GetSessionVars().StmtCtx i64s := result.Int64s() - isUnsigned := mysql.HasUnsignedFlag(b.tp.Flag) + isUnsigned := mysql.HasUnsignedFlag(b.tp.GetFlag()) unionUnsigned := isUnsigned && b.inUnion for i := 0; i < n; i++ { if result.IsNull(i) { @@ -939,7 +939,7 @@ func (b *builtinCastStringAsDurationSig) vecEvalDuration(input *chunk.Chunk, res if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, buf.GetString(i), b.tp.Decimal) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, buf.GetString(i), b.tp.GetDecimal()) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -977,7 +977,7 @@ func (b *builtinCastDurationAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, res var duration types.Duration ds := buf.GoDurations() sc := b.ctx.GetSessionVars().StmtCtx - fsp := b.args[0].GetType().Decimal + fsp := b.args[0].GetType().GetDecimal() if fsp, err = types.CheckFsp(fsp); err != nil { return err } @@ -1011,8 +1011,8 @@ func (b *builtinCastIntAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, result * return err } - isUnsignedTp := mysql.HasUnsignedFlag(b.tp.Flag) - isUnsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) + isUnsignedTp := mysql.HasUnsignedFlag(b.tp.GetFlag()) + isUnsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) nums := buf.Int64s() result.ResizeDecimal(n, false) result.MergeNulls(buf) @@ -1058,7 +1058,7 @@ func (b *builtinCastIntAsJSONSig) vecEvalJSON(input *chunk.Chunk, result *chunk. } nums := buf.Int64s() result.ReserveJSON(n) - if mysql.HasIsBooleanFlag(b.args[0].GetType().Flag) { + if mysql.HasIsBooleanFlag(b.args[0].GetType().GetFlag()) { for i := 0; i < n; i++ { if buf.IsNull(i) { result.AppendNull() @@ -1066,7 +1066,7 @@ func (b *builtinCastIntAsJSONSig) vecEvalJSON(input *chunk.Chunk, result *chunk. result.AppendJSON(json.CreateBinary(nums[i] != 0)) } } - } else if mysql.HasUnsignedFlag(b.args[0].GetType().Flag) { + } else if mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) { for i := 0; i < n; i++ { if buf.IsNull(i) { result.AppendNull() @@ -1141,7 +1141,7 @@ func (b *builtinCastDurationAsRealSig) vecEvalReal(input *chunk.Chunk, result *c f64s := result.Float64s() var duration types.Duration - fsp := b.args[0].GetType().Decimal + fsp := b.args[0].GetType().GetDecimal() if fsp, err = types.CheckFsp(fsp); err != nil { return err } @@ -1183,7 +1183,7 @@ func (b *builtinCastJSONAsIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.C if result.IsNull(i) { continue } - i64s[i], err = types.ConvertJSONToInt64(sc, buf.GetJSON(i), mysql.HasUnsignedFlag(b.tp.Flag)) + i64s[i], err = types.ConvertJSONToInt64(sc, buf.GetJSON(i), mysql.HasUnsignedFlag(b.tp.GetFlag())) if err != nil { return err } @@ -1213,7 +1213,7 @@ func (b *builtinCastRealAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(f64s[i], 'f', -1, 64), b.tp.Decimal) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(f64s[i], 'f', -1, 64), b.tp.GetDecimal()) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -1257,7 +1257,7 @@ func (b *builtinCastTimeAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if err != nil { return err } - d, err = d.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) + d, err = d.RoundFrac(b.tp.GetDecimal(), b.ctx.GetSessionVars().Location()) if err != nil { return err } @@ -1286,7 +1286,7 @@ func (b *builtinCastDurationAsDurationSig) vecEvalDuration(input *chunk.Chunk, r continue } dur.Duration = v - rd, err = dur.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) + rd, err = dur.RoundFrac(b.tp.GetDecimal(), b.ctx.GetSessionVars().Location()) if err != nil { return err } @@ -1314,7 +1314,7 @@ func (b *builtinCastDurationAsStringSig) vecEvalString(input *chunk.Chunk, resul var isNull bool sc := b.ctx.GetSessionVars().StmtCtx result.ReserveString(n) - fsp := b.args[0].GetType().Decimal + fsp := b.args[0].GetType().GetDecimal() for i := 0; i < n; i++ { if buf.IsNull(i) { result.AppendNull() @@ -1358,7 +1358,7 @@ func (b *builtinCastDecimalAsRealSig) vecEvalReal(input *chunk.Chunk, result *ch d := buf.Decimals() rs := result.Float64s() - inUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) + inUnionAndUnsigned := b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -1403,12 +1403,12 @@ func (b *builtinCastDecimalAsTimeSig) vecEvalTime(input *chunk.Chunk, result *ch times := result.Times() decimals := buf.Decimals() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if buf.IsNull(i) { continue } - tm, err := types.ParseTimeFromFloatString(stmt, string(decimals[i].ToString()), b.tp.Tp, fsp) + tm, err := types.ParseTimeFromFloatString(stmt, string(decimals[i].ToString()), b.tp.GetType(), fsp) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -1417,7 +1417,7 @@ func (b *builtinCastDecimalAsTimeSig) vecEvalTime(input *chunk.Chunk, result *ch continue } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) } @@ -1473,12 +1473,12 @@ func (b *builtinCastTimeAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times := result.Times() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if result.IsNull(i) { continue } - res, err := times[i].Convert(stmt, b.tp.Tp) + res, err := times[i].Convert(stmt, b.tp.GetType()) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -1491,10 +1491,10 @@ func (b *builtinCastTimeAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk return err } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) - times[i].SetType(b.tp.Tp) + times[i].SetType(b.tp.GetType()) } } return nil @@ -1614,7 +1614,7 @@ func (b *builtinCastStringAsRealSig) vecEvalReal(input *chunk.Chunk, result *chu if err != nil { return err } - if b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && res < 0 { + if b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && res < 0 { res = 0 } res, err = types.ProduceFloatWithSpecifiedTp(res, b.tp, sc) @@ -1654,7 +1654,7 @@ func (b *builtinCastStringAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, resul val := strings.TrimSpace(buf.GetString(i)) isNegative := len(val) > 0 && val[0] == '-' dec := new(types.MyDecimal) - if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && isNegative) { + if !(b.inUnion && mysql.HasUnsignedFlag(b.tp.GetFlag()) && isNegative) { if err := stmtCtx.HandleTruncate(dec.FromString([]byte(val))); err != nil { return err } @@ -1687,12 +1687,12 @@ func (b *builtinCastStringAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chu result.MergeNulls(buf) times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := b.tp.Decimal + fsp := b.tp.GetDecimal() for i := 0; i < n; i++ { if result.IsNull(i) { continue } - tm, err := types.ParseTime(stmtCtx, buf.GetString(i), b.tp.Tp, fsp) + tm, err := types.ParseTime(stmtCtx, buf.GetString(i), b.tp.GetType(), fsp) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err @@ -1709,7 +1709,7 @@ func (b *builtinCastStringAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chu continue } times[i] = tm - if b.tp.Tp == mysql.TypeDate { + if b.tp.GetType() == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) } @@ -1748,7 +1748,7 @@ func (b *builtinCastDecimalAsIntSig) vecEvalInt(input *chunk.Chunk, result *chun return err } - if !mysql.HasUnsignedFlag(b.tp.Flag) { + if !mysql.HasUnsignedFlag(b.tp.GetFlag()) { i64s[i], err = to.ToInt() } else if b.inUnion && to.IsNegative() { i64s[i] = 0 @@ -1793,7 +1793,7 @@ func (b *builtinCastDecimalAsDurationSig) vecEvalDuration(input *chunk.Chunk, re if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(args[i].ToString()), b.tp.Decimal) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(args[i].ToString()), b.tp.GetDecimal()) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -1880,7 +1880,7 @@ func (b *builtinCastJSONAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if err != nil { return nil } - dur, err = types.ParseDuration(ctx, s, b.tp.Decimal) + dur, err = types.ParseDuration(ctx, s, b.tp.GetDecimal()) if types.ErrTruncatedWrongVal.Equal(err) { err = ctx.HandleTruncate(err) } diff --git a/expression/builtin_cast_vec_test.go b/expression/builtin_cast_vec_test.go index 20e6395537901..5ecd3ea2c78d9 100644 --- a/expression/builtin_cast_vec_test.go +++ b/expression/builtin_cast_vec_test.go @@ -209,7 +209,7 @@ func TestVectorizedCastStringAsDecimalWithUnsignedFlagInUnion(t *testing.T) { baseCast := newBaseBuiltinCastFunc(baseFunc, true) baseCast.tp = types.NewFieldType(mysql.TypeNewDecimal) // set the `UnsignedFlag` bit - baseCast.tp.Flag |= mysql.UnsignedFlag + baseCast.tp.AddFlag(mysql.UnsignedFlag) cast := &builtinCastStringAsDecimalSig{baseCast} inputs := []*chunk.Chunk{ diff --git a/expression/builtin_compare.go b/expression/builtin_compare.go index 7cf894b966669..5a5f5936ec072 100644 --- a/expression/builtin_compare.go +++ b/expression/builtin_compare.go @@ -125,7 +125,9 @@ func (c *coalesceFunctionClass) getFunction(ctx sessionctx.Context, args []Expre // Use the aggregated field type as retType. resultFieldType := types.AggFieldType(fieldTps) - resultEvalType := types.AggregateEvalType(fieldTps, &resultFieldType.Flag) + var tempType uint + resultEvalType := types.AggregateEvalType(fieldTps, &tempType) + resultFieldType.SetFlag(tempType) retEvalTp := resultFieldType.EvalType() fieldEvalTps := make([]types.EvalType, 0, len(args)) @@ -143,11 +145,12 @@ func (c *coalesceFunctionClass) getFunction(ctx sessionctx.Context, args []Expre return nil, err } - bf.tp.Flag |= resultFieldType.Flag - resultFieldType.Flen, resultFieldType.Decimal = 0, types.UnspecifiedLength + bf.tp.AddFlag(resultFieldType.GetFlag()) + resultFieldType.SetFlen(0) + resultFieldType.SetDecimal(types.UnspecifiedLength) // Set retType to BINARY(0) if all arguments are of type NULL. - if resultFieldType.Tp == mysql.TypeNull { + if resultFieldType.GetType() == mysql.TypeNull { types.SetBinChsClnFlag(bf.tp) } else { maxIntLen := 0 @@ -156,42 +159,42 @@ func (c *coalesceFunctionClass) getFunction(ctx sessionctx.Context, args []Expre // Find the max length of field in `maxFlen`, // and max integer-part length in `maxIntLen`. for _, argTp := range fieldTps { - if argTp.Decimal > resultFieldType.Decimal { - resultFieldType.Decimal = argTp.Decimal + if argTp.GetDecimal() > resultFieldType.GetDecimal() { + resultFieldType.SetDecimal(argTp.GetDecimal()) } - argIntLen := argTp.Flen - if argTp.Decimal > 0 { - argIntLen -= argTp.Decimal + 1 + argIntLen := argTp.GetFlen() + if argTp.GetDecimal() > 0 { + argIntLen -= argTp.GetDecimal() + 1 } // Reduce the sign bit if it is a signed integer/decimal - if !mysql.HasUnsignedFlag(argTp.Flag) { + if !mysql.HasUnsignedFlag(argTp.GetFlag()) { argIntLen-- } if argIntLen > maxIntLen { maxIntLen = argIntLen } - if argTp.Flen > maxFlen || argTp.Flen == types.UnspecifiedLength { - maxFlen = argTp.Flen + if argTp.GetFlen() > maxFlen || argTp.GetFlen() == types.UnspecifiedLength { + maxFlen = argTp.GetFlen() } } // For integer, field length = maxIntLen + (1/0 for sign bit) // For decimal, field length = maxIntLen + maxDecimal + (1/0 for sign bit) if resultEvalType == types.ETInt || resultEvalType == types.ETDecimal { - resultFieldType.Flen = maxIntLen + resultFieldType.Decimal - if resultFieldType.Decimal > 0 { - resultFieldType.Flen++ + resultFieldType.SetFlen(maxIntLen + resultFieldType.GetDecimal()) + if resultFieldType.GetDecimal() > 0 { + resultFieldType.SetFlen(resultFieldType.GetFlen() + 1) } - if !mysql.HasUnsignedFlag(resultFieldType.Flag) { - resultFieldType.Flen++ + if !mysql.HasUnsignedFlag(resultFieldType.GetFlag()) { + resultFieldType.SetFlen(resultFieldType.GetFlen() + 1) } bf.tp = resultFieldType } else { - bf.tp.Flen = maxFlen + bf.tp.SetFlen(maxFlen) } // Set the field length to maxFlen for other types. - if bf.tp.Flen > mysql.MaxDecimalWidth { - bf.tp.Flen = mysql.MaxDecimalWidth + if bf.tp.GetFlen() > mysql.MaxDecimalWidth { + bf.tp.SetFlen(mysql.MaxDecimalWidth) } } @@ -212,7 +215,7 @@ func (c *coalesceFunctionClass) getFunction(ctx sessionctx.Context, args []Expre sig = &builtinCoalesceTimeSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CoalesceTime) case types.ETDuration: - bf.tp.Decimal = fsp + bf.tp.SetDecimal(fsp) sig = &builtinCoalesceDurationSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CoalesceDuration) case types.ETJson: @@ -267,7 +270,7 @@ func (b *builtinCoalesceRealSig) evalReal(row chunk.Row) (res float64, isNull bo return res, isNull, err } -// builtinCoalesceDecimalSig is builtin function coalesce signature which return type Decimal +// builtinCoalesceDecimalSig is builtin function coalesce signature which return type decimal // See http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce type builtinCoalesceDecimalSig struct { baseBuiltinFunc @@ -394,11 +397,11 @@ func ResolveType4Between(args [3]Expression) types.EvalType { hasTemporal := false if cmpTp == types.ETString { - if args[0].GetType().Tp == mysql.TypeDuration { + if args[0].GetType().GetType() == mysql.TypeDuration { cmpTp = types.ETDuration } else { for _, arg := range args { - if types.IsTypeTemporal(arg.GetType().Tp) { + if types.IsTypeTemporal(arg.GetType().GetType()) { hasTemporal = true break } @@ -449,15 +452,15 @@ func resolveType4Extremum(args []Expression) (_ *types.FieldType, fieldTimeType for i := range args { item := args[i].GetType() // Find the temporal value in the arguments but prefer DateTime value. - if types.IsTypeTemporal(item.Tp) { - if temporalItem == nil || item.Tp == mysql.TypeDatetime { + if types.IsTypeTemporal(item.GetType()) { + if temporalItem == nil || item.GetType() == mysql.TypeDatetime { temporalItem = item } } } - if !types.IsTypeTemporal(aggType.Tp) && temporalItem != nil && types.IsTemporalWithDate(temporalItem.Tp) { - if temporalItem.Tp == mysql.TypeDate { + if !types.IsTypeTemporal(aggType.GetType()) && temporalItem != nil && types.IsTemporalWithDate(temporalItem.GetType()) { + if temporalItem.GetType() == mysql.TypeDate { cmpStringMode = GLCmpStringAsDate } else { cmpStringMode = GLCmpStringAsDatetime @@ -466,9 +469,9 @@ func resolveType4Extremum(args []Expression) (_ *types.FieldType, fieldTimeType // TODO: String charset, collation checking are needed. } var timeType = GLRetNoneTemporal - if aggType.Tp == mysql.TypeDate { + if aggType.GetType() == mysql.TypeDate { timeType = GLRetDate - } else if aggType.Tp == mysql.TypeDatetime || aggType.Tp == mysql.TypeTimestamp { + } else if aggType.GetType() == mysql.TypeDatetime || aggType.GetType() == mysql.TypeTimestamp { timeType = GLRetDatetime } return aggType, timeType, cmpStringMode @@ -477,7 +480,7 @@ func resolveType4Extremum(args []Expression) (_ *types.FieldType, fieldTimeType // unsupportedJSONComparison reports warnings while there is a JSON type in least/greatest function's arguments func unsupportedJSONComparison(ctx sessionctx.Context, args []Expression) { for _, arg := range args { - tp := arg.GetType().Tp + tp := arg.GetType().GetType() if tp == mysql.TypeJSON { ctx.GetSessionVars().StmtCtx.AppendWarning(errUnsupportedJSONComparison) break @@ -514,7 +517,7 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre } switch argTp { case types.ETInt: - bf.tp.Flag |= resFieldType.Flag + bf.tp.AddFlag(resFieldType.GetFlag()) sig = &builtinGreatestIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_GreatestInt) case types.ETReal: @@ -546,13 +549,17 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre sig.setPbCode(tipb.ScalarFuncSig_GreatestTime) } } - sig.getRetTp().Flen, sig.getRetTp().Decimal = fixFlenAndDecimalForGreatestAndLeast(args) + + flen, decimal := fixFlenAndDecimalForGreatestAndLeast(args) + sig.getRetTp().SetFlen(flen) + sig.getRetTp().SetDecimal(decimal) + return sig, nil } func fixFlenAndDecimalForGreatestAndLeast(args []Expression) (flen, decimal int) { for _, arg := range args { - argFlen, argDecimal := arg.GetType().Flen, arg.GetType().Decimal + argFlen, argDecimal := arg.GetType().GetFlen(), arg.GetType().GetDecimal() if argFlen > flen { flen = argFlen } @@ -823,7 +830,7 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi } switch argTp { case types.ETInt: - bf.tp.Flag |= resFieldType.Flag + bf.tp.AddFlag(resFieldType.GetFlag()) sig = &builtinLeastIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_LeastInt) case types.ETReal: @@ -855,7 +862,9 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi sig.setPbCode(tipb.ScalarFuncSig_LeastTime) } } - sig.getRetTp().Flen, sig.getRetTp().Decimal = fixFlenAndDecimalForGreatestAndLeast(args) + flen, decimal := fixFlenAndDecimalForGreatestAndLeast(args) + sig.getRetTp().SetFlen(flen) + sig.getRetTp().SetDecimal(decimal) return sig, nil } @@ -1096,7 +1105,7 @@ func (c *intervalFunctionClass) getFunction(ctx sessionctx.Context, args []Expre if tp.EvalType() != types.ETInt { allInt = false } - if !mysql.HasNotNullFlag(tp.Flag) { + if !mysql.HasNotNullFlag(tp.GetFlag()) { hasNullable = true } } @@ -1144,7 +1153,7 @@ func (b *builtinIntervalIntSig) evalInt(row chunk.Row) (int64, bool, error) { if isNull { return -1, false, nil } - isUint1 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag) + isUint1 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()) var idx int if b.hasNullable { idx, err = b.linearSearch(arg0, isUint1, b.args[1:], row) @@ -1158,7 +1167,7 @@ func (b *builtinIntervalIntSig) evalInt(row chunk.Row) (int64, bool, error) { func (b *builtinIntervalIntSig) linearSearch(target int64, isUint1 bool, args []Expression, row chunk.Row) (i int, err error) { i = 0 for ; i < len(args); i++ { - isUint2 := mysql.HasUnsignedFlag(args[i].GetType().Flag) + isUint2 := mysql.HasUnsignedFlag(args[i].GetType().GetFlag()) arg, isNull, err := args[i].EvalInt(b.ctx, row) if err != nil { return 0, err @@ -1199,7 +1208,7 @@ func (b *builtinIntervalIntSig) binSearch(target int64, isUint1 bool, args []Exp if isNull { v = target } - isUint2 := mysql.HasUnsignedFlag(args[mid].GetType().Flag) + isUint2 := mysql.HasUnsignedFlag(args[mid].GetType().GetFlag()) switch { case !isUint1 && !isUint2: cmp = target < v @@ -1298,11 +1307,11 @@ func (c *compareFunctionClass) getDisplayName() string { // getBaseCmpType gets the EvalType that the two args will be treated as when comparing. func getBaseCmpType(lhs, rhs types.EvalType, lft, rft *types.FieldType) types.EvalType { - if lft != nil && rft != nil && (lft.Tp == mysql.TypeUnspecified || rft.Tp == mysql.TypeUnspecified) { - if lft.Tp == rft.Tp { + if lft != nil && rft != nil && (lft.GetType() == mysql.TypeUnspecified || rft.GetType() == mysql.TypeUnspecified) { + if lft.GetType() == rft.GetType() { return types.ETString } - if lft.Tp == mysql.TypeUnspecified { + if lft.GetType() == mysql.TypeUnspecified { lhs = rhs } else { rhs = lhs @@ -1317,8 +1326,8 @@ func getBaseCmpType(lhs, rhs types.EvalType, lft, rft *types.FieldType) types.Ev } else if ((lhs == types.ETInt || (lft != nil && lft.Hybrid())) || lhs == types.ETDecimal) && ((rhs == types.ETInt || (rft != nil && rft.Hybrid())) || rhs == types.ETDecimal) { return types.ETDecimal - } else if lft != nil && rft != nil && (types.IsTemporalWithDate(lft.Tp) && rft.Tp == mysql.TypeYear || - lft.Tp == mysql.TypeYear && types.IsTemporalWithDate(rft.Tp)) { + } else if lft != nil && rft != nil && (types.IsTemporalWithDate(lft.GetType()) && rft.GetType() == mysql.TypeYear || + lft.GetType() == mysql.TypeYear && types.IsTemporalWithDate(rft.GetType())) { return types.ETDatetime } return types.ETReal @@ -1330,19 +1339,19 @@ func GetAccurateCmpType(lhs, rhs Expression) types.EvalType { lhsFieldType, rhsFieldType := lhs.GetType(), rhs.GetType() lhsEvalType, rhsEvalType := lhsFieldType.EvalType(), rhsFieldType.EvalType() cmpType := getBaseCmpType(lhsEvalType, rhsEvalType, lhsFieldType, rhsFieldType) - if (lhsEvalType.IsStringKind() && rhsFieldType.Tp == mysql.TypeJSON) || - (lhsFieldType.Tp == mysql.TypeJSON && rhsEvalType.IsStringKind()) { + if (lhsEvalType.IsStringKind() && rhsFieldType.GetType() == mysql.TypeJSON) || + (lhsFieldType.GetType() == mysql.TypeJSON && rhsEvalType.IsStringKind()) { cmpType = types.ETJson - } else if cmpType == types.ETString && (types.IsTypeTime(lhsFieldType.Tp) || types.IsTypeTime(rhsFieldType.Tp)) { + } else if cmpType == types.ETString && (types.IsTypeTime(lhsFieldType.GetType()) || types.IsTypeTime(rhsFieldType.GetType())) { // date[time] date[time] // string date[time] // compare as time - if lhsFieldType.Tp == rhsFieldType.Tp { + if lhsFieldType.GetType() == rhsFieldType.GetType() { cmpType = lhsFieldType.EvalType() } else { cmpType = types.ETDatetime } - } else if lhsFieldType.Tp == mysql.TypeDuration && rhsFieldType.Tp == mysql.TypeDuration { + } else if lhsFieldType.GetType() == mysql.TypeDuration && rhsFieldType.GetType() == mysql.TypeDuration { // duration duration // compare as duration cmpType = types.ETDuration @@ -1372,7 +1381,7 @@ func GetAccurateCmpType(lhs, rhs Expression) types.EvalType { if !isLHSColumn { col = rhs.(*Column) } - if col.GetType().Tp == mysql.TypeDuration { + if col.GetType().GetType() == mysql.TypeDuration { cmpType = types.ETDuration } } @@ -1409,7 +1418,7 @@ func isTemporalColumn(expr Expression) bool { if _, isCol := expr.(*Column); !isCol { return false } - if !types.IsTypeTime(ft.Tp) && ft.Tp != mysql.TypeDuration { + if !types.IsTypeTime(ft.GetType()) && ft.GetType() != mysql.TypeDuration { return false } return true @@ -1466,7 +1475,7 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT } sc := ctx.GetSessionVars().StmtCtx - if targetFieldType.Tp == mysql.TypeBit { + if targetFieldType.GetType() == mysql.TypeBit { targetFieldType = *types.NewFieldType(mysql.TypeLonglong) } var intDatum types.Datum @@ -1520,11 +1529,11 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT // otherwise, the compare function will be false. // **note** // 1. We compare `doubleDatum` with the `integral part of doubleDatum` rather then intDatum to handle the - // case when `targetFieldType.Tp` is `TypeYear`. - // 2. When `targetFieldType.Tp` is `TypeYear`, we can not compare `doubleDatum` with `intDatum` directly, + // case when `targetFieldType.GetType()` is `TypeYear`. + // 2. When `targetFieldType.GetType()` is `TypeYear`, we can not compare `doubleDatum` with `intDatum` directly, // because we'll convert values in the ranges '0' to '69' and '70' to '99' to YEAR values in the ranges // 2000 to 2069 and 1970 to 1999. - // 3. Suppose the value of `con` is 2, when `targetFieldType.Tp` is `TypeYear`, the value of `doubleDatum` + // 3. Suppose the value of `con` is 2, when `targetFieldType.GetType()` is `TypeYear`, the value of `doubleDatum` // will be 2.0 and the value of `intDatum` will be 2002 in this case. var doubleDatum types.Datum doubleDatum, err = dt.ConvertTo(sc, types.NewFieldType(mysql.TypeDouble)) @@ -1579,12 +1588,12 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express // Why check not null flag // eg: int_col > const_val(which is less than min_int32) // If int_col got null, compare result cannot be true - if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg0Type.Flag)) { + if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg0Type.GetFlag())) { finalArg1 = arg1 } // TODO if the plan doesn't care about whether the result of the function is null or false, we don't need // to check the NotNullFlag, then more optimizations can be enabled. - isExceptional = isExceptional && mysql.HasNotNullFlag(arg0Type.Flag) + isExceptional = isExceptional && mysql.HasNotNullFlag(arg0Type.GetFlag()) if isExceptional && arg1.GetType().EvalType() == types.ETInt { // Judge it is inf or -inf // For int: @@ -1603,12 +1612,12 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express // non-int constant [cmp] int non-constant if arg1IsInt && !arg1IsCon && !arg0IsInt && arg0IsCon { arg0, isExceptional = RefineComparedConstant(ctx, *arg1Type, arg0, symmetricOp[c.op]) - if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg1Type.Flag)) { + if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg1Type.GetFlag())) { finalArg0 = arg0 } // TODO if the plan doesn't care about whether the result of the function is null or false, we don't need // to check the NotNullFlag, then more optimizations can be enabled. - isExceptional = isExceptional && mysql.HasNotNullFlag(arg1Type.Flag) + isExceptional = isExceptional && mysql.HasNotNullFlag(arg1Type.GetFlag()) if isExceptional && arg0.GetType().EvalType() == types.ETInt { if arg0.Value.GetInt64()&1 == 1 { isNegativeInfinite = true @@ -1618,7 +1627,7 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express } } // int constant [cmp] year type - if arg0IsCon && arg0IsInt && arg1Type.Tp == mysql.TypeYear && !arg0.Value.IsNull() { + if arg0IsCon && arg0IsInt && arg1Type.GetType() == mysql.TypeYear && !arg0.Value.IsNull() { adjusted, failed := types.AdjustYear(arg0.Value.GetInt64(), false) if failed == nil { arg0.Value.SetInt64(adjusted) @@ -1626,7 +1635,7 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express } } // year type [cmp] int constant - if arg1IsCon && arg1IsInt && arg0Type.Tp == mysql.TypeYear && !arg1.Value.IsNull() { + if arg1IsCon && arg1IsInt && arg0Type.GetType() == mysql.TypeYear && !arg1.Value.IsNull() { adjusted, failed := types.AdjustYear(arg1.Value.GetInt64(), false) if failed == nil { arg1.Value.SetInt64(adjusted) @@ -1679,19 +1688,19 @@ func (c *compareFunctionClass) refineArgsByUnsignedFlag(ctx sessionctx.Context, if err != nil || isNull || v > 0 { return args } - if mysql.HasUnsignedFlag(con.RetType.Flag) && !mysql.HasUnsignedFlag(col.RetType.Flag) { + if mysql.HasUnsignedFlag(con.RetType.GetFlag()) && !mysql.HasUnsignedFlag(col.RetType.GetFlag()) { op := c.op if i == 1 { op = symmetricOp[c.op] } if op == opcode.EQ || op == opcode.NullEQ { - if _, err := types.ConvertUintToInt(uint64(v), types.IntergerSignedUpperBound(col.RetType.Tp), col.RetType.Tp); err != nil { + if _, err := types.ConvertUintToInt(uint64(v), types.IntergerSignedUpperBound(col.RetType.GetType()), col.RetType.GetType()); err != nil { args[i], args[1-i] = NewOne(), NewZero() return args } } } - if mysql.HasUnsignedFlag(col.RetType.Flag) && mysql.HasNotNullFlag(col.RetType.Flag) && !mysql.HasUnsignedFlag(con.RetType.Flag) { + if mysql.HasUnsignedFlag(col.RetType.GetFlag()) && mysql.HasNotNullFlag(col.RetType.GetFlag()) && !mysql.HasUnsignedFlag(con.RetType.GetFlag()) { op := c.op if i == 1 { op = symmetricOp[c.op] @@ -1738,7 +1747,7 @@ func (c *compareFunctionClass) generateCmpSigs(ctx sessionctx.Context, args []Ex DisableParseJSONFlag4Expr(args[i]) } } - bf.tp.Flen = 1 + bf.tp.SetFlen(1) switch tp { case types.ETInt: switch c.op { @@ -2523,7 +2532,7 @@ func (b *builtinNullEQIntSig) evalInt(row chunk.Row) (val int64, isNull bool, er if err != nil { return 0, isNull1, err } - isUnsigned0, isUnsigned1 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag), mysql.HasUnsignedFlag(b.args[1].GetType().Flag) + isUnsigned0, isUnsigned1 := mysql.HasUnsignedFlag(b.args[0].GetType().GetFlag()), mysql.HasUnsignedFlag(b.args[1].GetType().GetFlag()) var res int64 switch { case isNull0 && isNull1: @@ -2847,7 +2856,7 @@ func CompareInt(sctx sessionctx.Context, lhsArg, rhsArg Expression, lhsRow, rhsR return compareNull(isNull0, isNull1), true, nil } - isUnsigned0, isUnsigned1 := mysql.HasUnsignedFlag(lhsArg.GetType().Flag), mysql.HasUnsignedFlag(rhsArg.GetType().Flag) + isUnsigned0, isUnsigned1 := mysql.HasUnsignedFlag(lhsArg.GetType().GetFlag()), mysql.HasUnsignedFlag(rhsArg.GetType().GetFlag()) var res int switch { case isUnsigned0 && isUnsigned1: diff --git a/expression/builtin_compare_test.go b/expression/builtin_compare_test.go index cd204d25a2459..89439f245dd82 100644 --- a/expression/builtin_compare_test.go +++ b/expression/builtin_compare_test.go @@ -142,8 +142,8 @@ func TestCompare(t *testing.T) { bf, err := funcs[test.funcName].getFunction(ctx, primitiveValsToConstants(ctx, []interface{}{test.arg0, test.arg1})) require.NoError(t, err) args := bf.getArgs() - require.Equal(t, test.tp, args[0].GetType().Tp) - require.Equal(t, test.tp, args[1].GetType().Tp) + require.Equal(t, test.tp, args[0].GetType().GetType()) + require.Equal(t, test.tp, args[1].GetType().GetType()) res, isNil, err := bf.evalInt(chunk.Row{}) require.NoError(t, err) require.False(t, isNil) @@ -155,16 +155,16 @@ func TestCompare(t *testing.T) { bf, err := funcs[ast.LT].getFunction(ctx, []Expression{decimalCol, stringCon}) require.NoError(t, err) args := bf.getArgs() - require.Equal(t, mysql.TypeNewDecimal, args[0].GetType().Tp) - require.Equal(t, mysql.TypeNewDecimal, args[1].GetType().Tp) + require.Equal(t, mysql.TypeNewDecimal, args[0].GetType().GetType()) + require.Equal(t, mysql.TypeNewDecimal, args[1].GetType().GetType()) // test