diff --git a/.golangci.yml b/.golangci.yml index 8818de2bc5d68..cbbdd0448cf87 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,12 +21,10 @@ linters: depguard: rules: main: + list-mode: lax files: - $all - '!$test' - # allow: - # - $gostd - # - github.com deny: - pkg: github.com/OpenPeeDeeP/depguard desc: example to deny some package diff --git a/Makefile b/Makefile index c0f93336bb79b..a447ce7184032 100644 --- a/Makefile +++ b/Makefile @@ -559,7 +559,7 @@ fmt: .PHONY: install-static-check-tools install-static-check-tools: - @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $(GOPATH)/bin v2.1.6 + @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $(GOPATH)/bin v2.6.2 @go install github.com/matrixorigin/linter/cmd/molint@latest @go install github.com/apache/skywalking-eyes/cmd/license-eye@v0.4.0 @@ -568,7 +568,7 @@ static-check: config err-check $(CGO_OPTS) go vet -vettool=`which molint` ./... $(CGO_OPTS) license-eye -c .licenserc.yml header check $(CGO_OPTS) license-eye -c .licenserc.yml dep check - $(CGO_OPTS) golangci-lint run -c .golangci.yml ./... + $(CGO_OPTS) golangci-lint run -v -c .golangci.yml ./... fmtErrs := $(shell grep -onr 'fmt.Errorf' pkg/ --exclude-dir=.git --exclude-dir=vendor \ --exclude=*.pb.go --exclude=system_vars.go --exclude=Makefile) diff --git a/cmd/mo-service/main_test.go b/cmd/mo-service/main_test.go index de632e8ac2eb3..d5a888ad1f276 100644 --- a/cmd/mo-service/main_test.go +++ b/cmd/mo-service/main_test.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build service_test -// +build service_test package main diff --git a/go.mod b/go.mod index 6aca64e78af9d..d613a90f68c28 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/matrixorigin/matrixone // Minimum Go version required -go 1.24.3 +go 1.25.4 require ( github.com/BurntSushi/toml v1.2.1 @@ -242,3 +242,5 @@ replace ( github.com/lni/goutils v1.3.1-0.20220604063047-388d67b4dbc4 => github.com/matrixorigin/goutils v1.3.1-0.20220604063047-388d67b4dbc4 github.com/lni/vfs v0.2.1-0.20220616104132-8852fd867376 => github.com/matrixorigin/vfs v0.2.1-0.20220616104132-8852fd867376 ) + +replace github.com/shoenig/go-m1cpu => github.com/shoenig/go-m1cpu v0.1.7 diff --git a/go.sum b/go.sum index b9282de92dbe0..7459880c23c77 100644 --- a/go.sum +++ b/go.sum @@ -364,7 +364,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -748,10 +747,10 @@ github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh github.com/shirou/gopsutil/v3 v3.22.4/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shoenig/go-m1cpu v0.1.7 h1:C76Yd0ObKR82W4vhfjZiCp0HxcSZ8Nqd84v+HZ0qyI0= +github.com/shoenig/go-m1cpu v0.1.7/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= +github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk= +github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= diff --git a/optools/bvt_ut/Dockerfile b/optools/bvt_ut/Dockerfile index 2e77476792116..a1d96c631b2d8 100644 --- a/optools/bvt_ut/Dockerfile +++ b/optools/bvt_ut/Dockerfile @@ -1,4 +1,4 @@ -FROM matrixorigin/tester:go1.24-jdk8 +FROM matrixorigin/tester:go1.25.4-jdk8 ARG GOPROXY="https://proxy.golang.org,direct" diff --git a/optools/compose_bvt/Dockerfile.tester b/optools/compose_bvt/Dockerfile.tester index 6674aaace2865..1361d1f10a14d 100644 --- a/optools/compose_bvt/Dockerfile.tester +++ b/optools/compose_bvt/Dockerfile.tester @@ -1,4 +1,4 @@ -FROM matrixorigin/tester:go1.24-jdk8 +FROM matrixorigin/tester:go1.25.4-jdk8 WORKDIR / diff --git a/optools/images/Dockerfile b/optools/images/Dockerfile index e4f03a60ee241..c3e761a3cf88c 100644 --- a/optools/images/Dockerfile +++ b/optools/images/Dockerfile @@ -1,4 +1,4 @@ -FROM matrixorigin/golang:1.24-ubuntu22.04 AS builder +FROM matrixorigin/golang:1.25-ubuntu22.04 AS builder # goproxy ARG GOPROXY="https://proxy.golang.org,direct" diff --git a/pkg/bootstrap/versions/v4_0_0/cluster_upgrade_list.go b/pkg/bootstrap/versions/v4_0_0/cluster_upgrade_list.go index 338b3ec9814f7..1a72836a08cf1 100644 --- a/pkg/bootstrap/versions/v4_0_0/cluster_upgrade_list.go +++ b/pkg/bootstrap/versions/v4_0_0/cluster_upgrade_list.go @@ -25,6 +25,10 @@ import ( var clusterUpgEntries = []versions.UpgradeEntry{ upg_mo_iscp_task, upg_create_mo_branch_metadata, + upg_rename_system_stmt_info_4000, + upg_create_system_stmt_info_4000, + upg_rename_system_metrics_metric_4000, + upg_create_system_metrics_metric_4000, } var upg_mo_iscp_task = versions.UpgradeEntry{ @@ -48,3 +52,57 @@ var upg_create_mo_branch_metadata = versions.UpgradeEntry{ return exist, err }, } + +const MO_STATEMENT_4000 = "statement_info_4000" +const RenameStmtInfo_4000 = "ALTER TABLE `system`.`statement_info` RENAME `system`.`statement_info_4000`;" + +const CreateStmtInfo_4000 = "CREATE TABLE `system`.`statement_info` (\n `statement_id` varchar(36) NOT NULL COMMENT 'statement uniq id',\n `transaction_id` varchar(36) NOT NULL COMMENT 'txn uniq id',\n `session_id` varchar(36) NOT NULL COMMENT 'session uniq id',\n `account` varchar(1024) NOT NULL COMMENT 'account name',\n `account_id` int unsigned DEFAULT '0' COMMENT 'account id',\n `user` varchar(1024) NOT NULL COMMENT 'user name',\n `host` varchar(1024) NOT NULL COMMENT 'user client ip',\n `database` varchar(1024) NOT NULL COMMENT 'what database current session stay in.',\n `statement` text NOT NULL COMMENT 'sql statement',\n `statement_tag` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `statement_fingerprint` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `node_uuid` varchar(36) NOT NULL COMMENT 'node uuid, which node gen this data.',\n `node_type` varchar(1024) NOT NULL COMMENT 'node type in MO, val in [DN, CN, LOG]',\n `request_at` datetime(6) NOT NULL COMMENT 'request accept datetime',\n `response_at` datetime(6) NOT NULL COMMENT 'response send datetime',\n `duration` bigint unsigned DEFAULT '0' COMMENT 'exec time, unit: ns',\n `status` varchar(1024) NOT NULL COMMENT 'sql statement running status, enum: Running, Success, Failed',\n `err_code` varchar(1024) DEFAULT '0' COMMENT 'error code info',\n `error` text NOT NULL COMMENT 'error message',\n `exec_plan` text DEFAULT '{}' COMMENT 'statement execution plan',\n `rows_read` bigint DEFAULT '0' COMMENT 'rows read total',\n `bytes_scan` bigint DEFAULT '0' COMMENT 'bytes scan total',\n `stats` text DEFAULT '[]' COMMENT 'global stats info in exec_plan',\n `statement_type` varchar(1024) NOT NULL COMMENT 'statement type, val in [Insert, Delete, Update, Drop Table, Drop User, ...]',\n `query_type` varchar(1024) NOT NULL COMMENT 'query type, val in [DQL, DDL, DML, DCL, TCL]',\n `role_id` bigint DEFAULT '0' COMMENT 'role id',\n `sql_source_type` text NOT NULL COMMENT 'sql statement source type',\n `aggr_count` bigint DEFAULT '0' COMMENT 'the number of statements aggregated',\n `result_count` bigint DEFAULT '0' COMMENT 'the number of rows of sql execution results',\n `connection_id` bigint DEFAULT '0' COMMENT 'connection id',\n `cu` double DEFAULT '0.0' COMMENT 'cu cost'\n) COMMENT='record each statement and stats info[mo_no_del_hint]' CLUSTER BY (`request_at`, `account_id`)" + +// upg_rename_system_stmt_info_4000 do rename table +var upg_rename_system_stmt_info_4000 = versions.UpgradeEntry{ + Schema: catalog.MO_SYSTEM, + TableName: catalog.MO_STATEMENT, + UpgType: versions.CREATE_NEW_TABLE, + UpgSql: RenameStmtInfo_4000, + CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { + return versions.CheckTableDefinition(txn, accountId, catalog.MO_SYSTEM, MO_STATEMENT_4000) + }, +} + +// upg_create_system_stmt_info_4000 do create new table +var upg_create_system_stmt_info_4000 = versions.UpgradeEntry{ + Schema: catalog.MO_SYSTEM, + TableName: catalog.MO_STATEMENT, + UpgType: versions.CREATE_NEW_TABLE, + UpgSql: CreateStmtInfo_4000, + CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { + return versions.CheckTableDefinition(txn, accountId, catalog.MO_SYSTEM, catalog.MO_STATEMENT) + }, +} + +const MO_METRIC_4000 = "metric_4000" +const RenameMetric_4000 = "ALTER TABLE `system_metrics`.`metric` RENAME `system_metrics`.`metric_4000`;" + +const CreateMetric_4000 = "CREATE TABLE `system_metrics`.`metric` (\n `metric_name` varchar(1024) DEFAULT 'sys' COMMENT 'metric name, like: sql_statement_total, server_connections, process_cpu_percent, sys_memory_used, ...',\n `collecttime` datetime(6) NOT NULL COMMENT 'metric data collect time',\n `value` double DEFAULT '0.0' COMMENT 'metric value',\n `node` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node uuid',\n `role` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node role, like: CN, DN, LOG',\n `account` varchar(1024) DEFAULT 'sys' COMMENT 'account name',\n `account_id` int unsigned DEFAULT '0' COMMENT 'account id',\n `type` varchar(1024) NOT NULL COMMENT 'sql type, like: insert, select, ...'\n) COMMENT='metric data' CLUSTER BY (`collecttime`, `account_id`, `metric_name`)" + +// upg_rename_system_metrics_metric_4000 do rename table +var upg_rename_system_metrics_metric_4000 = versions.UpgradeEntry{ + Schema: catalog.MO_SYSTEM_METRICS, + TableName: catalog.MO_METRIC, + UpgType: versions.CREATE_NEW_TABLE, + UpgSql: RenameMetric_4000, + CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { + return versions.CheckTableDefinition(txn, accountId, catalog.MO_SYSTEM_METRICS, MO_METRIC_4000) + }, +} + +// upg_create_system_metrics_metric_4000 do create new table +var upg_create_system_metrics_metric_4000 = versions.UpgradeEntry{ + Schema: catalog.MO_SYSTEM_METRICS, + TableName: catalog.MO_METRIC, + UpgType: versions.CREATE_NEW_TABLE, + UpgSql: CreateMetric_4000, + CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { + return versions.CheckTableDefinition(txn, accountId, catalog.MO_SYSTEM_METRICS, catalog.MO_METRIC) + }, +} diff --git a/pkg/bootstrap/versions/v4_0_0/tenant_upgrade_list.go b/pkg/bootstrap/versions/v4_0_0/tenant_upgrade_list.go index bd7f4d9ac65fc..a955cc1245cbd 100644 --- a/pkg/bootstrap/versions/v4_0_0/tenant_upgrade_list.go +++ b/pkg/bootstrap/versions/v4_0_0/tenant_upgrade_list.go @@ -32,7 +32,7 @@ var enablePartitionMetadata = versions.UpgradeEntry{ UpgType: versions.CREATE_NEW_TABLE, UpgSql: partitionservice.PartitionTableMetadataSQL, CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { - exist, err := versions.CheckTableDefinition(txn, accountId, catalog.MO_CATALOG, partitionservice.PartitionTableMetadataSQL) + exist, err := versions.CheckTableDefinition(txn, accountId, catalog.MO_CATALOG, catalog.MOPartitionMetadata) return exist, err }, } @@ -43,7 +43,7 @@ var enablePartitionTables = versions.UpgradeEntry{ UpgType: versions.CREATE_NEW_TABLE, UpgSql: partitionservice.PartitionTablesSQL, CheckFunc: func(txn executor.TxnExecutor, accountId uint32) (bool, error) { - exist, err := versions.CheckTableDefinition(txn, accountId, catalog.MO_CATALOG, partitionservice.PartitionTablesSQL) + exist, err := versions.CheckTableDefinition(txn, accountId, catalog.MO_CATALOG, catalog.MOPartitionTables) return exist, err }, } diff --git a/pkg/cdc/CDC_USER_GUIDE.md b/pkg/cdc/CDC_USER_GUIDE.md index 48b2a4f630d8b..82dec7fa5dd86 100644 --- a/pkg/cdc/CDC_USER_GUIDE.md +++ b/pkg/cdc/CDC_USER_GUIDE.md @@ -9,20 +9,25 @@ ## Table of Contents 1. [Overview](#overview) -2. [Quick Start](#quick-start) -3. [CREATE CDC - Creating a CDC Task](#create-cdc---creating-a-cdc-task) -4. [SHOW CDC - Viewing CDC Tasks](#show-cdc---viewing-cdc-tasks) -5. [PAUSE CDC - Pausing a CDC Task](#pause-cdc---pausing-a-cdc-task) -6. [RESUME CDC - Resuming a CDC Task](#resume-cdc---resuming-a-cdc-task) -7. [DROP CDC - Dropping a CDC Task](#drop-cdc---dropping-a-cdc-task) -8. [RESTART CDC - Restarting a CDC Task](#restart-cdc---restarting-a-cdc-task) -9. [Monitoring and Error Handling](#monitoring-and-error-handling) -10. [Metrics and Observability](#metrics-and-observability) -11. [Configuration Options Reference](#configuration-options-reference) -12. [Best Practices](#best-practices) -13. [Troubleshooting](#troubleshooting) -14. [Test Scenarios](#test-scenarios) -15. [FAQ](#faq) +2. [System Architecture](#system-architecture) + - [Core Components](#core-components) + - [Component Collaboration](#component-collaboration) + - [Task Lifecycle](#task-lifecycle) + - [Design Intentions](#design-intentions) +3. [Quick Start](#quick-start) +4. [CREATE CDC - Creating a CDC Task](#create-cdc---creating-a-cdc-task) +5. [SHOW CDC - Viewing CDC Tasks](#show-cdc---viewing-cdc-tasks) +6. [PAUSE CDC - Pausing a CDC Task](#pause-cdc---pausing-a-cdc-task) +7. [RESUME CDC - Resuming a CDC Task](#resume-cdc---resuming-a-cdc-task) +8. [DROP CDC - Dropping a CDC Task](#drop-cdc---dropping-a-cdc-task) +9. [RESTART CDC - Restarting a CDC Task](#restart-cdc---restarting-a-cdc-task) +10. [Monitoring and Error Handling](#monitoring-and-error-handling) +11. [Metrics and Observability](#metrics-and-observability) +12. [Configuration Options Reference](#configuration-options-reference) +13. [Best Practices](#best-practices) +14. [Troubleshooting](#troubleshooting) +15. [Test Scenarios](#test-scenarios) +16. [FAQ](#faq) --- @@ -50,6 +55,343 @@ Change Data Capture (CDC) is a data replication feature that captures and synchr --- +## System Architecture + +### Overview + +The CDC system is built on a **pipeline architecture** that processes data changes through multiple stages: reading from source, processing changes, and writing to target. The system is designed for **high reliability**, **automatic recovery**, and **precise state management**. + +### Core Components + +The CDC system consists of five main components that work together to achieve reliable data replication: + +#### 1. TableChangeStream (Stream) + +**Purpose**: The main orchestrator that coordinates the entire data replication pipeline for a single table. + +**Responsibilities**: +- Orchestrates the data replication lifecycle for one table +- Manages tick-based polling intervals (frequency control) +- Coordinates between Reader, Processor, and Sinker components +- Handles error classification and retry decisions +- Manages watermark progression and state persistence +- Implements StaleRead recovery mechanism +- Provides pause/cancel control signal handling + +**Key Behaviors**: +- Runs in a continuous loop, processing one round at a time +- Each round: reads changes → processes → writes → updates watermark +- Automatically retries on retryable errors +- Stops processing on non-retryable errors (requires manual intervention) +- Persists error state to database for recovery after restarts + +**Lifecycle**: +- Created per table when task starts +- Runs until task is paused, dropped, or encounters fatal error +- Cleans up resources on shutdown + +#### 2. Reader (ChangeReader) + +**Purpose**: Reads change data from MatrixOne source database. + +**Responsibilities**: +- Creates transactions to read changes from source tables +- Collects changes within a timestamp range (fromTs to toTs) +- Handles table schema changes and truncation +- Provides change batches (snapshot + incremental) to processor +- Manages transaction lifecycle (begin, read, commit/rollback) + +**Key Behaviors**: +- Uses MatrixOne transaction API to read changes +- Returns changes in batches (snapshot data + incremental changes) +- Handles StaleRead errors (data not yet available at requested timestamp) +- Supports table relation lookups and schema validation + +**Components**: +- **TransactionManager**: Manages transaction lifecycle, coordinates with Sinker for BEGIN/COMMIT/ROLLBACK +- **ChangeCollector**: Collects changes from source tables within timestamp ranges +- **DataProcessor**: Processes change batches and coordinates with Sinker + +#### 3. Sinker (mysqlSinker2) + +**Purpose**: Writes data changes to downstream MySQL-compatible database. + +**Responsibilities**: +- Executes SQL commands (INSERT, UPDATE, DELETE) on target database +- Manages transaction lifecycle on target (BEGIN, COMMIT, ROLLBACK) +- Implements retry mechanism with exponential backoff +- Provides circuit breaker to prevent retry storms +- Handles connection management and reconnection +- Tracks transaction state (IDLE, ACTIVE, COMMITTED, ROLLED_BACK) + +**Key Behaviors**: +- Uses command channel pattern: commands are sent asynchronously, executed by consumer goroutine +- Once error occurs, all subsequent commands are skipped until `ClearError()` +- Producer (Reader) polls `Error()` to detect async failures +- Supports SQL batching and reuse query buffer optimization +- Automatic retry for transient errors (network, timeout, circuit breaker) + +**Transaction State Machine**: +``` +IDLE --SendBegin--> ACTIVE --SendCommit--> COMMITTED --cleanup--> IDLE + ACTIVE --SendRollback--> ROLLED_BACK --cleanup--> IDLE +``` + +#### 4. WatermarkUpdater + +**Purpose**: Manages watermark state (checkpoint) and error persistence. + +**Responsibilities**: +- Maintains per-table watermark (last synchronized timestamp) +- Persists error messages with metadata (retryable flag, retry count, timestamps) +- Provides in-memory cache for fast watermark lookups +- Implements asynchronous job queue for watermark updates (preserves batch processing design) +- Manages circuit breaker state for commit failures +- Clears errors on successful processing + +**Key Behaviors**: +- Watermark represents the last successfully synchronized timestamp +- Errors are persisted with structured format: `R::::` or `N::` +- Uses lazy batch processing: updates are queued and processed asynchronously +- Cache provides fast reads without synchronous SQL queries +- Circuit breaker tracks commit failure patterns + +**Storage**: +- In-memory cache: fast lookups during processing +- Database (`mo_catalog.mo_cdc_watermark`): persistent state, survives restarts + +**Watermark Persistence Design - At-Least-Once Semantics**: + +The watermark persistence is **asynchronous by design** to preserve batch processing performance. This design choice has important implications: + +1. **Asynchronous Persistence**: + - Watermark updates are queued and processed asynchronously via job queue + - This avoids blocking data processing with synchronous database writes + - Improves overall throughput and reduces latency + +2. **Watermark May Lag Behind Actual Progress**: + - The persisted watermark in database may be **lower than the actual synchronized position** + - This is **intentional and safe** due to idempotency guarantees + +3. **Idempotency Guarantee**: + - CDC operations (INSERT, UPDATE, DELETE) are **idempotent** on the target database + - If system restarts before watermark is persisted, it will re-sync from the last persisted watermark + - Re-syncing the same data multiple times is safe and does not cause data corruption + - This ensures **at-least-once delivery** semantics + +4. **Recovery Behavior**: + - On restart, system resumes from the last persisted watermark (which may be lower than actual) + - System will re-process some data that was already synchronized + - This is acceptable because operations are idempotent + - Better to have slight duplication than to lose data + +5. **Error Handling for Watermark Stalls**: + - If watermark cannot advance (e.g., due to persistent errors), system detects this condition + - Watermark stall errors are logged and tracked via metrics + - System will retry and eventually recover when underlying issues are resolved + - See "Watermark Stall Errors" in Error Handling section for details + +**Why This Design**: +- **Performance**: Asynchronous updates avoid blocking the critical data path +- **Reliability**: At-least-once semantics ensure no data loss +- **Simplicity**: Idempotent operations simplify error recovery +- **Trade-off**: Accepts slight data duplication in exchange for better performance and simpler recovery + +#### 5. Task Scheduler (Frontend) + +**Purpose**: Manages task lifecycle and coordinates multiple table streams. + +**Responsibilities**: +- Creates and manages CDC tasks +- Starts/stops table streams based on task state +- Checks error state before starting streams (uses `ShouldRetry` logic) +- Handles task-level operations (pause, resume, restart, drop) +- Monitors task health and state transitions +- Clears errors on resume/restart + +**Key Behaviors**: +- Scans for new tables and creates streams dynamically +- Before starting stream, checks persisted error in watermark table +- Skips tables with non-retryable errors (requires manual intervention) +- Allows retryable errors to continue processing +- Clears all table errors when task is resumed + +### Component Collaboration + +The components work together in a **producer-consumer pipeline**: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Task Scheduler │ +│ - Creates/manages tasks │ +│ - Starts/stops table streams │ +│ - Checks error state before starting │ +└──────────────────────┬──────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ TableChangeStream (per table) │ +│ - Orchestrates pipeline │ +│ - Manages tick-based polling │ +│ - Coordinates components │ +└──────┬───────────────────────────────┬──────────────────────┘ + │ │ + ▼ ▼ +┌──────────────────┐ ┌──────────────────┐ +│ Reader │ │ WatermarkUpdater│ +│ - Read changes │ │ - Manage state │ +│ - Collect data │ │ - Persist errors │ +└──────┬───────────┘ └──────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ TransactionManager + DataProcessor │ +│ - Coordinate transaction lifecycle │ +│ - Process change batches │ +│ - Send commands to Sinker │ +└──────┬──────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Sinker (mysqlSinker2) │ +│ - Execute SQL on target │ +│ - Manage target transactions │ +│ - Retry on transient errors │ +└─────────────────────────────────────────────────────────────┘ +``` + +**Data Flow**: + +1. **TableChangeStream** starts a processing round (tick-based) +2. **Reader** creates transaction and collects changes from source (fromTs to toTs) +3. **DataProcessor** processes change batches: + - Sends BEGIN to Sinker + - Sends INSERT/UPDATE/DELETE commands for each change + - Sends COMMIT to Sinker +4. **Sinker** executes commands on target database: + - Receives commands asynchronously via channel + - Executes SQL with retry mechanism + - Reports errors back to producer +5. **WatermarkUpdater** updates watermark on success: + - Updates in-memory cache + - Queues database update (asynchronous) +6. **TableChangeStream** waits for next tick interval and repeats + +**Error Handling Flow**: + +1. Error occurs in any component (Reader, Sinker, etc.) +2. Error propagates to **TableChangeStream** +3. **TableChangeStream** classifies error (retryable/non-retryable) +4. Error state updated atomically (lastError + retryable flag) +5. Error persisted to **WatermarkUpdater** (with metadata) +6. If retryable: Stream waits for next tick and retries +7. If non-retryable: Stream stops, requires manual intervention +8. On restart: **Task Scheduler** checks persisted error, decides whether to start stream + +### Task Lifecycle + +A CDC task goes through the following states: + +``` +CREATED → STARTING → RUNNING → [PAUSED] → [RUNNING] → CANCELLED + ↓ + [FAILED] → [RUNNING] (after resume) +``` + +**State Transitions**: + +1. **CREATED**: Task is created via `CREATE CDC` command + - Metadata stored in `mo_catalog.mo_cdc_task` + - Initial watermark entries created in `mo_catalog.mo_cdc_watermark` + +2. **STARTING**: Task is being initialized + - Task scheduler scans for tables + - Creates TableChangeStream for each table + - Checks error state before starting streams + +3. **RUNNING**: Task is actively replicating data + - TableChangeStream processes changes in rounds + - Watermarks are updated on successful rounds + - Errors are handled automatically (retryable) or block processing (non-retryable) + +4. **PAUSED**: Task is temporarily stopped + - All table streams are stopped gracefully + - State is preserved (watermarks, errors) + - Can be resumed via `RESUME CDC` command + +5. **FAILED**: Task encountered non-retryable error + - Task remains in RUNNING state but sync is blocked + - Error persists until manually cleared + - Can be recovered via `RESUME CDC` (clears errors) + +6. **CANCELLED**: Task is dropped + - All resources are cleaned up + - Metadata and watermarks are deleted + - Cannot be recovered + +**Control Operations**: + +- **PAUSE**: Gracefully stops all table streams, preserves state +- **RESUME**: Clears all errors, restarts streams from last watermark +- **RESTART**: Stops and immediately restarts, clears errors +- **DROP**: Permanently deletes task and all metadata + +### Design Intentions + +The CDC system is designed with the following principles: + +1. **Reliability First**: + - All state is persisted (watermarks, errors) + - Errors are classified and handled appropriately + - System can recover from any error state via manual intervention + +2. **Automatic Recovery**: + - Transient errors (network, system unavailability) are automatically retried + - Retry mechanism with exponential backoff prevents retry storms + - Circuit breaker protects against persistent failures + +3. **Precise State Management**: + - Watermark represents exact synchronization point + - Errors are tracked with metadata (retryable, count, timestamps) + - State survives system restarts + +4. **Performance Optimization**: + - Asynchronous processing (command channel pattern) + - Batch processing for watermark updates + - SQL reuse query buffer optimization + - In-memory cache for fast watermark lookups + +5. **Flexibility**: + - Supports multiple replication levels (account, database, table) + - Configurable frequency, time ranges, filters + - Optional initial snapshot + +6. **Observability**: + - Structured logging with consistent keys + - Metrics for monitoring and alerting + - Progress tracking per table + +7. **User Control**: + - Manual intervention always possible (resume clears all errors) + - Clear error messages guide troubleshooting + - Task operations (pause/resume/restart) provide full control + +### Component Isolation + +Each component is designed to be **loosely coupled**: + +- **TableChangeStream** doesn't know about downstream MySQL details +- **Sinker** doesn't know about source MatrixOne details +- **WatermarkUpdater** is a shared service, used by all streams +- **Reader** components are independent per table + +This design allows: +- Easy testing (components can be mocked) +- Independent scaling (each table stream is independent) +- Clear error boundaries (errors are contained and handled appropriately) + +--- + ## Quick Start ### Basic Example: Replicate a Single Table @@ -453,19 +795,43 @@ resume cdc task task3; ### Error Clearing -`resume cdc task` automatically clears error messages for all tables, allowing fresh retry attempts. +**`resume cdc task` automatically clears ALL error messages for all tables in the task**, regardless of error type (retryable or non-retryable). This allows fresh retry attempts after fixing underlying issues. +**Behavior:** +- Clears all errors in `mo_catalog.mo_cdc_watermark.err_msg` for the task +- Resets error state for all tables +- Allows system to retry from last watermark +- Works for both retryable and non-retryable errors + +**Use Cases:** +- After fixing network issues +- After restoring downstream MySQL service +- After fixing schema mismatches +- After resolving authentication problems +- After any manual intervention to fix root causes + +**Example:** ```sql -- Before RESUME: check for errors show cdc task replicate_orders; +-- Shows: table1 has error "N:1763362169:rollback failure" + +-- Fix the underlying issue (e.g., restore service, fix schema) -- Resume clears errors and restarts resume cdc task replicate_orders; --- After RESUME: errors are cleared +-- After RESUME: errors are cleared, processing resumes show cdc task replicate_orders; +-- Shows: table1 has no error, processing continues ``` +**Important Notes:** +- Resume clears **all** errors, not just non-retryable ones +- Always fix underlying issues before resuming +- System will retry from last watermark after resume +- If issue persists, error will occur again (can be cleared again) + --- ## DROP CDC - Dropping a CDC Task @@ -561,31 +927,336 @@ resume cdc task task2 'restart'; ### Error Types -#### 1. Retryable Errors +The CDC system automatically classifies errors as **retryable** or **non-retryable** based on error type and context. This classification determines whether the system will automatically retry or require manual intervention. -Automatically retried up to 3 times: -- Network timeouts -- Transient connection failures -- Stale read errors +#### 1. Retryable Errors -**Behavior**: Task continues running, error message shows retry count +**Automatically retried up to 3 times** before requiring manual intervention. + +**MatrixOne System/Network Errors (Highest Priority):** +These errors indicate temporary system unavailability and are always retryable: +- **RPC Timeout**: MatrixOne RPC calls timed out +- **No Available Backend**: No backend services available +- **Backend Cannot Connect**: Cannot connect to remote backend +- **TN Shard Not Found**: Transaction node shard not found (temporary) +- **RPC Error**: Generic RPC communication errors +- **Client/Backend Closed**: Connection closed unexpectedly +- **Context Timeout**: Operation timeout due to system delays + +**Network/Connection Issues:** +- Connection timeouts, connection resets, network errors +- Service unavailable errors +- Network-related begin transaction failures + +**Transaction Errors:** +- **Commit Failures**: Transient network issues during transaction commit +- **Begin Failures (Network-related)**: Network issues when starting transactions + +**Data Source Errors:** +- **Table Relation Errors**: Table truncated or temporarily unavailable (table may be recreated) +- **Watermark Stall Errors**: Snapshot timestamp stuck (temporary condition) + - Occurs when watermark cannot advance for extended period (default threshold: 1 minute) + - System detects this condition and logs warning: `cdc.table_stream.snapshot_not_advanced` + - Error is retryable - system will continue attempting to advance watermark + - Tracked via metrics for monitoring + - Usually resolves automatically when source data becomes available +- **StaleRead Errors**: If recovery is possible (watermark reset succeeds) + +**Sinker Errors (Transient):** +- Circuit breaker errors (indicates temporary overload) +- Timeout errors from downstream MySQL + +**Behavior**: +- Task continues running, error message shows retry count +- Automatic retry up to 3 times (configurable via `WithMaxRetryCount`) +- After max retries, automatically converted to non-retryable +- Error persists in watermark table with format: `R::::` +- Uses exponential backoff between retries (configurable via `WithRetryBackoff`) **Example Error Message**: ``` -retryable error: timeout connecting to target (retry 2/3) +R:2:1763362169:1763362200:internal error: commit failure +``` +- `R`: Retryable +- `2`: Retry count (current attempt) +- `1763362169`: First seen timestamp +- `1763362200`: Last seen timestamp +- `internal error: commit failure`: Error message + +#### Retry Mechanism Details + +**Exponential Backoff Strategy**: + +The CDC system implements exponential backoff for retryable errors to avoid overwhelming the system during transient failures. The backoff delay is calculated based on: +- **Error Type**: Different error types may have different base delays +- **Retry Count**: Delay increases exponentially with each retry attempt +- **Configurable Parameters**: Base delay, maximum delay, and backoff factor + +**Default Configuration**: +- **Max Retry Count**: 3 attempts +- **Base Delay**: 200ms (for most error types) +- **Max Delay**: 30s (caps the exponential growth) +- **Backoff Factor**: 2.0 (doubles delay each retry) + +**Retry Delay Calculation**: +- Retry 1: Base delay (e.g., 200ms) +- Retry 2: Base delay × factor (e.g., 400ms) +- Retry 3: Base delay × factor² (e.g., 800ms) +- Capped at maximum delay (e.g., 30s) + +**Original Error Preservation**: + +To ensure **deterministic error reporting**, the CDC system preserves the **original error** that triggered the retry sequence. This design ensures that: + +1. **Consistent Error Reporting**: The error returned to users and persisted in the database is the original error that caused the retry, not auxiliary errors encountered during retry attempts (e.g., cache lookup failures during cleanup). + +2. **Clear Root Cause**: Users can identify the actual problem (e.g., "commit failure") rather than secondary issues that occurred during retry (e.g., "cache error"). + +3. **Predictable Behavior**: The system behavior is deterministic - the same error condition will always report the same error, regardless of what happens during retry attempts. + +**How It Works**: +- When a retryable error first occurs, it is stored as the **original error** +- During retry attempts, if auxiliary errors occur (e.g., during cleanup operations), they are logged but do not replace the original error +- If a new primary error occurs (different error type), it replaces the original error +- If a fatal (non-retryable) error occurs, it replaces the original error +- When retries are exhausted or a fatal error occurs, the **original error** is returned/persisted + +**Example Scenario**: +``` +1. Commit failure occurs → Original error: "commit failure" +2. Retry attempt 1 → Cleanup encounters cache error → Original error preserved: "commit failure" +3. Retry attempt 2 → Commit failure again → Original error preserved: "commit failure" +4. Retry attempt 3 → Commit failure again → Original error preserved: "commit failure" +5. Max retries exceeded → System stops, reports: "commit failure" (not "cache error") ``` +This ensures that users always see the root cause of the problem, not transient issues that occurred during recovery attempts. + #### 2. Non-Retryable Errors -Require manual intervention: -- Target table not found -- Schema mismatch -- Authentication failures -- Syntax errors +**Require manual intervention** - no automatic retry. + +**System State Errors:** +- **Rollback Failures**: System state may be inconsistent after rollback failure +- **Begin Failures (State-related)**: Cannot start transaction due to state issues (e.g., "transaction already active") + +**Fatal Errors:** +- **Simple Sinker Errors**: Fatal errors before transaction starts (no context indicating transient issue) +- **StaleRead with startTs**: Cannot recover (startTs is set, cannot reset watermark) +- **Target Table Not Found**: Schema mismatch or table deleted permanently +- **Authentication Failures**: Invalid credentials (requires configuration fix) +- **Syntax Errors**: SQL construction failures (requires code fix) + +**Control Signals:** +- Pause/cancel signals (intentional stops) + +**Unknown Errors:** +- Errors that don't match any known pattern (default to non-retryable for safety) + +**Behavior**: +- Task remains in `running` state but sync is blocked for affected tables +- Error persists until manually cleared via `resume cdc task` +- No automatic retry +- Error persists in watermark table with format: `N::` + +**Example Error Message**: +``` +N:1763362169:internal error: rollback failure +``` +- `N`: Non-retryable +- `1763362169`: First seen timestamp +- `internal error: rollback failure`: Error message + +**Max Retry Exceeded Format**: +``` +N:1763362169:max retry exceeded (4): connection timeout +``` +- Auto-converted from retryable after exceeding 3 retries +- Requires manual intervention via `resume cdc task` + +### Error Classification Logic + +The system uses a **priority-based classification** approach to determine if errors are retryable: -**Behavior**: Task remains in `running` state but sync is blocked for affected tables +**Classification Priority (Checked in Order):** -**Resolution**: Fix the issue, then `resume cdc task ` to clear errors +1. **Control Signals** (Non-retryable) + - Pause/cancel signals are always non-retryable (intentional stops) + +2. **MatrixOne System Errors** (Retryable) + - System checks for specific MatrixOne error codes first + - All system/network errors (RPC timeout, backend unavailable, shard not found, etc.) are automatically retryable + - This ensures resilience during temporary MatrixOne system unavailability or network fluctuations + +3. **Context Timeout Errors** (Retryable) + - Operation timeouts due to system delays are retryable + +4. **Error Message Pattern Matching** (Retryable/Non-retryable) + - **Retryable Patterns**: `commit`, `connection`, `timeout`, `network`, `unavailable`, `rpc`, `backend`, `shard`, `relation`, `truncated`, `stuck`, `stall` + - **Non-Retryable Patterns**: `rollback`, `begin` (without network context), simple `sinker error` (without context) + +5. **Default** (Non-retryable) + - Unknown errors default to non-retryable for safety + +**Special Handling:** + +- **Begin Failures**: + - Network-related (contains `connection`, `timeout`, `network`, `unavailable`, `rpc`, `backend`) → **Retryable** + - State-related (e.g., "transaction already active") → **Non-retryable** + +- **Sinker Errors**: + - With transient context (`circuit`, `timeout`) → **Retryable** + - Simple "sinker error" without context → **Non-retryable** + +- **StaleRead Errors**: + - Recovery attempted automatically + - If recovery succeeds → Error is swallowed, processing continues + - If recovery fails → **Non-retryable** + +**Why This Matters:** + +This classification ensures that: +- **Temporary system issues** (network抖动, service unavailability, MatrixOne node failures) are automatically retried +- **Permanent errors** (state inconsistencies, fatal configuration issues) require manual intervention +- **Users can always recover** by using `resume cdc task` to clear any error and retry + +### Error Storage + +Errors are stored in two places for different purposes: + +1. **In-Memory (Runtime)**: + - Tracks the last error that occurred during processing + - Maintains retryable flag for current processing round + - Updated atomically to ensure consistency + - Used for immediate retry decisions + +2. **Persistent (Database)**: + - Stored in `mo_catalog.mo_cdc_watermark.err_msg` column + - Format: `R::::` (retryable) or `N::` (non-retryable) + - Persisted asynchronously to avoid blocking data processing + - Used by task scheduler to decide whether to start table processing + - Survives system restarts + +### Error Consumption + +Errors are consumed at two levels: + +1. **Runtime (During Processing)**: + - When an error occurs, processing round stops immediately + - Error state is persisted to database + - If retryable: Stream waits for next tick interval and retries automatically + - If non-retryable: Stream stops processing, waits for manual intervention + +2. **Startup (Task Scheduler)**: + - Before starting table stream, scheduler checks persisted error in watermark table + - Uses retry decision logic: + - **No error** → Start processing + - **Retryable error with count ≤ 3** → Start processing (continue retrying) + - **Retryable error with count > 3** → Skip table (converted to non-retryable, requires manual clear) + - **Non-retryable error** → Skip table (requires manual clear) + +**Retry Decision Logic:** +- System automatically allows retry for retryable errors up to 3 attempts +- After 3 retries, retryable errors are converted to non-retryable +- Non-retryable errors always require manual intervention via `resume cdc task` + +### Error Lifecycle + +**Stage 1: Error Occurs** +- Error is detected during processing (network issue, commit failure, etc.) +- System immediately classifies error as retryable or non-retryable + +**Stage 2: Error State Update** +- Error state updated atomically (ensures consistency) +- Error persisted to watermark table with metadata (retry count, timestamps) + +**Stage 3: Retry Decision** +- **Retryable errors**: + - Retry count incremented + - If count ≤ 3: Continue processing, retry on next tick + - If count > 3: Convert to non-retryable, stop processing +- **Non-retryable errors**: + - Stop processing immediately + - Require manual intervention + +**Stage 4: Manual Recovery (if needed)** +- User fixes underlying issue (network restored, service back online, etc.) +- User runs `resume cdc task ` to clear error +- System clears all errors for the task +- Processing resumes from last watermark + +**Key Points:** +- All errors (retryable and non-retryable) can be cleared via `resume cdc task` +- System always allows recovery through manual intervention +- Errors persist across system restarts until manually cleared + +### Multi-Level Retry + +The CDC system implements retry at multiple levels for maximum resilience: + +1. **Executor Level (Sinker - Downstream MySQL)**: + - Automatic retry with exponential backoff for SQL execution + - Circuit breaker prevents retry storms + - Retries network errors, MySQL connection issues, and transient SQL errors + - Handles downstream service unavailability + +2. **TableChangeStream Level (Data Processing)**: + - Tick-based retry for retryable errors + - Automatic StaleRead recovery (resets watermark if possible) + - Error state tracking and persistence + - Handles MatrixOne system errors and data source issues + +3. **Task Scheduler Level (Task Management)**: + - Startup check before starting table processing + - Skips tables with non-retryable errors (requires manual intervention) + - Allows retryable errors to continue processing + - Manual recovery via `resume cdc task` + +**Benefits:** +- Network fluctuations are handled automatically at executor level +- System unavailability is handled at table stream level +- Permanent errors are caught early and require manual fix +- Users can always recover via `resume cdc task` + +### Error Resolution + +**For Retryable Errors:** +- Usually resolve automatically within 3 retries +- Monitor retry count in error message (format: `R::...`) +- If error persists after 3 retries: + - Check underlying cause (network, service availability) + - Fix the issue if possible + - Use `resume cdc task` to clear error and retry + +**For Non-Retryable Errors:** +1. **Identify the root cause**: + - Check error message in `show cdc task` output + - Review logs for detailed error context + - Common causes: missing tables, schema mismatches, authentication failures, state inconsistencies + +2. **Fix the underlying issue**: + - Create missing tables + - Fix schema mismatches + - Update credentials + - Resolve state inconsistencies + +3. **Clear error and retry**: + - Run `resume cdc task ` to clear all errors + - System will automatically retry on next scan + - Processing resumes from last watermark + +**Important: All Errors Can Be Cleared** + +- `resume cdc task` clears **all errors** (both retryable and non-retryable) for all tables in the task +- This ensures users can always recover from any error state +- After clearing errors, system will retry from last watermark +- If underlying issue is fixed, processing will succeed +- If underlying issue persists, error will occur again and can be cleared again + +**Best Practice:** +- Always fix the underlying issue before clearing errors +- Monitor error messages to understand root causes +- Use `resume cdc task` as a recovery mechanism after fixing issues ### Debugging with Logs @@ -677,6 +1348,28 @@ where t.state = 'running' order by lag_minutes desc; ``` +#### Detect Snapshot Stalls + +Each table stream tracks whether recent polling rounds failed to advance the snapshot watermark. When this happens, CDC: + +- Increments `mo_cdc_table_snapshot_no_progress_total` for the affected table on every stalled round. +- Sets `mo_cdc_table_stuck` to `1` and records the time in `mo_cdc_table_last_activity_timestamp`. +- Emits throttled warning logs; if the stall exceeds the internal threshold (default 1 minute) the table stream raises a retryable error so the scheduler can retry later. +- Resets counters and gauges automatically once progress resumes. + +```promql +# Tables currently flagged as stalled +mo_cdc_table_stuck == 1 + +# Minutes since last successful progress +(time() - mo_cdc_table_last_activity_timestamp) / 60 + +# Rounds without progress in the last 10 minutes +increase(mo_cdc_table_snapshot_no_progress_total[10m]) > 0 +``` + +> **Note**: The stall threshold and warning interval are configurable (defaults: 1 minute stall threshold, 10 second warning throttle). Adjust your alerting thresholds if you override these values. + ### Common Error Messages | Error Message | Cause | Resolution | @@ -785,6 +1478,7 @@ rate(mo_cdc_task_state_change_total[5m]) | `mo_cdc_watermark_cache_size` | Gauge | `tier` | Number of watermarks in each cache tier | | `mo_cdc_watermark_update_total` | Counter | `table`, `update_type` | Count of watermark updates | | `mo_cdc_watermark_commit_duration_seconds` | Histogram | - | Duration of watermark commits to database | +| `mo_cdc_table_snapshot_no_progress_total` | Counter | `table` | Count of processing rounds where snapshot timestamps failed to advance (stall detection) | **Example Queries**: ```promql @@ -808,6 +1502,9 @@ mo_cdc_watermark_cache_size{tier="committed"} # Watermark commit latency (P99) histogram_quantile(0.99, mo_cdc_watermark_commit_duration_seconds_bucket) +# Snapshot stalls detected in the last 10 minutes +increase(mo_cdc_table_snapshot_no_progress_total[10m]) > 0 + # ⚠️ Planned feature: Watermark Lag Ratio (frequency-agnostic) # mo_cdc_watermark_lag_ratio # <2: normal, 2-5: warning, >5: critical ``` @@ -860,6 +1557,12 @@ avg(mo_cdc_batch_size_rows) | `mo_cdc_table_stream_total` | Gauge | `state` | Number of active table streams | | `mo_cdc_table_stream_round_total` | Counter | `table`, `status` | Count of processing rounds | | `mo_cdc_table_stream_round_duration_seconds` | Histogram | `table` | Duration of processing rounds | +| `mo_cdc_table_stuck` | Gauge | `table` | Whether a table stream is currently flagged as stalled (1 = stuck, 0 = healthy) | +| `mo_cdc_table_last_activity_timestamp` | Gauge | `table` | Unix timestamp when the table stream last made forward progress | +| `mo_cdc_table_stream_retry_total` | Counter | `table`, `error_type`, `outcome` | Count of retry attempts by error type and outcome (`attempted`, `succeeded`, `exhausted`, `failed`) | +| `mo_cdc_table_stream_retry_delay_seconds` | Histogram | `table`, `error_type` | Retry backoff delay duration (exponential backoff) | +| `mo_cdc_table_stream_auxiliary_error_total` | Counter | `table`, `auxiliary_error_type` | Count of auxiliary errors encountered during retries (preserved original error) | +| `mo_cdc_table_stream_original_error_preserved_total` | Counter | `table`, `original_error_type` | Count of times original error was preserved during retries (ensures deterministic error reporting) | **Example Queries**: ```promql @@ -873,6 +1576,31 @@ rate(mo_cdc_table_stream_round_total[5m]) # Processing duration P99 histogram_quantile(0.99, mo_cdc_table_stream_round_duration_seconds_bucket) + +# Tables currently marked as stuck +mo_cdc_table_stuck == 1 + +# Minutes since last successful progress +(time() - mo_cdc_table_last_activity_timestamp) / 60 + +# Retry attempt rate by error type +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="attempted"}[5m])) + +# Retry success rate (retries that eventually succeeded) +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="succeeded"}[5m])) / +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="attempted"}[5m])) + +# Retry exhaustion (retries exceeded max count) +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="exhausted"}[5m])) + +# Average retry backoff delay (P50) +histogram_quantile(0.50, rate(mo_cdc_table_stream_retry_delay_seconds_bucket[5m])) + +# Auxiliary errors (infrastructure errors during retries) +sum by (table, auxiliary_error_type) (rate(mo_cdc_table_stream_auxiliary_error_total[5m])) + +# Original error preservation (ensures deterministic error reporting) +sum by (table, original_error_type) (rate(mo_cdc_table_stream_original_error_preserved_total[5m])) ``` #### Sinker Metrics @@ -975,6 +1703,29 @@ sum(mo_cdc_sinker_transaction_total{status="error"}) sum by (sql_type) (rate(mo_cdc_sinker_sql_total{status="error"}[5m])) ``` +#### Retry Monitoring + +```promql +# Retry Attempt Rate by Error Type +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="attempted"}[5m])) + +# Retry Success Rate +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="succeeded"}[5m])) / +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="attempted"}[5m])) + +# Retry Exhaustion Rate (retries exceeded max count) +sum by (table, error_type) (rate(mo_cdc_table_stream_retry_total{outcome="exhausted"}[5m])) + +# Auxiliary Errors (errors that don't replace original errors) +sum by (table, auxiliary_error_type) (rate(mo_cdc_table_stream_auxiliary_error_total[5m])) + +# Original Error Preservation (ensures deterministic error reporting) +sum by (table, original_error_type) (rate(mo_cdc_table_stream_original_error_preserved_total[5m])) + +# Average Retry Backoff Delay +histogram_quantile(0.50, rate(mo_cdc_table_stream_retry_delay_seconds_bucket[5m])) +``` + ### Alert Rules #### Critical Alerts @@ -1005,7 +1756,21 @@ These alerts indicate immediate action required: # severity: critical # description: "Watermark lag is 5x higher than expected" -# 3. Watermark Stuck (Current Recommended Approach: Group-based) +# 3. High Retry Exhaustion Rate +- alert: CDCHighRetryExhaustion + expr: sum by (table) (rate(mo_cdc_table_stream_retry_total{outcome="exhausted"}[5m])) > 0.1 + for: 5m + severity: warning + description: "Table {{ $labels.table }} has high retry exhaustion rate (>0.1/s). Retries are exceeding max count." + +# 4. Frequent Auxiliary Errors +- alert: CDCFrequentAuxiliaryErrors + expr: sum by (table) (rate(mo_cdc_table_stream_auxiliary_error_total[5m])) > 1 + for: 5m + severity: warning + description: "Table {{ $labels.table }} has frequent auxiliary errors (>1/s). May indicate infrastructure issues during retries." + +# 5. Watermark Stuck (Current Recommended Approach: Group-based) # Use separate rules for different task frequencies if you have task groups # Example for real-time tasks (Frequency < 1 minute): - alert: CDCWatermarkStuck_Realtime @@ -1070,7 +1835,14 @@ These alerts indicate potential issues: severity: warning description: "High error rate detected (>0.01/s)" -# 3. Slow SQL Execution +# 3. High Retry Rate (indicates transient issues) +- alert: CDCHighRetryRate + expr: sum by (table) (rate(mo_cdc_table_stream_retry_total{outcome="attempted"}[5m])) > 5 + for: 5m + severity: warning + description: "Table {{ $labels.table }} has high retry rate (>5/s). May indicate transient infrastructure issues." + +# 4. Slow SQL Execution - alert: CDCSQLSlow expr: histogram_quantile(0.99, mo_cdc_sinker_sql_duration_seconds_bucket) > 1 for: 5m @@ -1227,6 +1999,7 @@ Configure alerts for critical conditions: - ✅ Watermark stuck (`mo_cdc_watermark_lag_seconds > 300`) - ✅ No heartbeat (`rate(mo_cdc_heartbeat_total[5m]) == 0`) - ✅ High error rate (`rate(mo_cdc_task_error_total[5m]) > 0.01`) +- ✅ Snapshot stall detection (`increase(mo_cdc_table_snapshot_no_progress_total[10m]) > 0` or `mo_cdc_table_stuck == 1`) #### 2. Monitor Watermark Lag diff --git a/pkg/cdc/reader_test_helpers.go b/pkg/cdc/reader_test_helpers.go index d73c7cf7fbb47..aaf3094d14c1e 100644 --- a/pkg/cdc/reader_test_helpers.go +++ b/pkg/cdc/reader_test_helpers.go @@ -16,12 +16,10 @@ package cdc import ( "context" - "strings" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" - "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/vm/engine" ) @@ -35,96 +33,10 @@ const ( var _ engine.ChangesHandle = new(testChangesHandle) type testChangesHandle struct { - dbName, tblName string - dbId, tblId uint64 - data []*batch.Batch - mp *mpool.MPool - packer *types.Packer - ownsPacker bool - called int - toTs types.TS -} - -// newTestChangesHandle creates a test ChangesHandle with mock data -func newTestChangesHandle( - dbName, tblName string, - dbId, tblId uint64, - toTs types.TS, - mp *mpool.MPool, - packer *types.Packer, -) *testChangesHandle { - ret := &testChangesHandle{ - dbName: dbName, - tblName: tblName, - dbId: dbId, - tblId: tblId, - mp: mp, - toTs: toTs, - } - - // Always allocate a dedicated packer for the handle to avoid sharing pooled instances - // across goroutines in tests, which can lead to race conditions when the original packer - // is returned to the pool while still in use. - ret.packer = types.NewPacker() - ret.ownsPacker = true - - /* - assume tables looks like: - test.t* - same schema : - create table t1(a int,b int, primary key(a,b)) - */ - - if dbName == "test" && strings.HasPrefix(tblName, "t") { - ret.makeData() - } - return ret -} - -func (changes *testChangesHandle) makeData() { - changes.packer.Reset() - defer func() { - changes.packer.Reset() - }() - //no checkpoint - //insert: - // Correct order: user cols | cpk | commit-ts → a,b,cpk,ts - //delete: - //cpk, ts - for i := 0; i < batchCnt+1; i++ { - bat := allocTestBatch( - []string{ - "a", // User column - "b", // User column - "cpk", // Composite PK - "ts", // Commit timestamp (MUST be last) - }, - []types.Type{ - types.T_int32.ToType(), - types.T_int32.ToType(), - types.T_varchar.ToType(), - types.T_TS.ToType(), - }, - 0, - changes.mp, - ) - bat.SetRowCount(rowCnt) - for j := 0; j < rowCnt; j++ { - //a - _ = vector.AppendFixed(bat.Vecs[0], int32(j), false, changes.mp) - //b - _ = vector.AppendFixed(bat.Vecs[1], int32(j), false, changes.mp) - //cpk - changes.packer.Reset() - changes.packer.EncodeInt32(int32(j)) - changes.packer.EncodeInt32(int32(j)) - _ = vector.AppendBytes(bat.Vecs[2], changes.packer.Bytes(), false, changes.mp) - //ts - _ = vector.AppendFixed(bat.Vecs[3], changes.toTs, false, changes.mp) - } - - changes.data = append(changes.data, bat) - } + data []*batch.Batch + packer *types.Packer + ownsPacker bool + called int } func (changes *testChangesHandle) Next(ctx context.Context, mp *mpool.MPool) (data *batch.Batch, tombstone *batch.Batch, hint engine.ChangesHandle_Hint, err error) { @@ -155,26 +67,3 @@ func (changes *testChangesHandle) Close() error { } return nil } - -// allocTestBatch allocates a test batch with given schema -func allocTestBatch( - attrName []string, - tt []types.Type, - batchSize int, - mp *mpool.MPool, -) *batch.Batch { - batchData := batch.New(attrName) - - //alloc space for vector - for i := 0; i < len(attrName); i++ { - vec := vector.NewVec(tt[i]) - if err := vec.PreExtend(batchSize, mp); err != nil { - panic(err) - } - vec.SetLength(batchSize) - batchData.Vecs[i] = vec - } - - batchData.SetRowCount(batchSize) - return batchData -} diff --git a/pkg/cdc/reader_v2_change_collector.go b/pkg/cdc/reader_v2_change_collector.go index e0a80ef84c982..e2262489c86ac 100644 --- a/pkg/cdc/reader_v2_change_collector.go +++ b/pkg/cdc/reader_v2_change_collector.go @@ -16,6 +16,7 @@ package cdc import ( "context" + "sync" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" @@ -92,6 +93,8 @@ func (cd *ChangeData) Clean(mp *mpool.MPool) { // 2. Provide typed change data (Snapshot/TailWip/TailDone/NoMoreData) // 3. Handle resource cleanup type ChangeCollector struct { + mu sync.RWMutex + // Engine changes handle changesHandle engine.ChangesHandle @@ -142,7 +145,12 @@ func NewChangeCollector( // When both insert and delete batches are nil and no error: // - Type will be ChangeTypeNoMoreData func (cc *ChangeCollector) Next(ctx context.Context) (*ChangeData, error) { - if cc.closed { + cc.mu.RLock() + closed := cc.closed + handle := cc.changesHandle + cc.mu.RUnlock() + + if closed || handle == nil { logutil.Warn( "cdc.change_collector.next_after_close", zap.String("task-id", cc.taskId), @@ -154,7 +162,7 @@ func (cc *ChangeCollector) Next(ctx context.Context) (*ChangeData, error) { } // Call engine's Next - insertBatch, deleteBatch, hint, err := cc.changesHandle.Next(ctx, cc.mp) + insertBatch, deleteBatch, hint, err := handle.Next(ctx, cc.mp) if err != nil { logutil.Error( "cdc.change_collector.next_failed", @@ -213,14 +221,18 @@ func (cc *ChangeCollector) Next(ctx context.Context) (*ChangeData, error) { // Close closes the change collector func (cc *ChangeCollector) Close() error { + cc.mu.Lock() if cc.closed { + cc.mu.Unlock() return nil } - cc.closed = true + handle := cc.changesHandle + cc.changesHandle = nil + cc.mu.Unlock() - if cc.changesHandle != nil { - if err := cc.changesHandle.Close(); err != nil { + if handle != nil { + if err := handle.Close(); err != nil { logutil.Error( "cdc.change_collector.close_failed", zap.String("task-id", cc.taskId), @@ -246,6 +258,8 @@ func (cc *ChangeCollector) Close() error { // IsClosed returns true if the collector is closed func (cc *ChangeCollector) IsClosed() bool { + cc.mu.RLock() + defer cc.mu.RUnlock() return cc.closed } diff --git a/pkg/cdc/reader_v2_change_collector_test.go b/pkg/cdc/reader_v2_change_collector_test.go index 0c156a58852ad..8059d9c380cee 100644 --- a/pkg/cdc/reader_v2_change_collector_test.go +++ b/pkg/cdc/reader_v2_change_collector_test.go @@ -16,7 +16,10 @@ package cdc import ( "context" + "sync" + "sync/atomic" "testing" + "time" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" @@ -24,6 +27,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // mockChangesHandle for testing @@ -48,6 +52,41 @@ func (m *mockChangesHandle) Close() error { return nil } +type collectorBlockingHandle struct { + nextInvoked sync.Once + nextCalled chan struct{} + release chan struct{} + err atomic.Value // stores error + closed atomic.Bool +} + +func newCollectorBlockingHandle() *collectorBlockingHandle { + return &collectorBlockingHandle{ + nextCalled: make(chan struct{}), + release: make(chan struct{}), + } +} + +func (h *collectorBlockingHandle) Next(ctx context.Context, mp *mpool.MPool) (*batch.Batch, *batch.Batch, engine.ChangesHandle_Hint, error) { + h.nextInvoked.Do(func() { close(h.nextCalled) }) + select { + case <-h.release: + if v := h.err.Load(); v != nil { + return nil, nil, engine.ChangesHandle_Snapshot, v.(error) + } + return nil, nil, engine.ChangesHandle_Tail_done, nil + case <-ctx.Done(): + return nil, nil, engine.ChangesHandle_Snapshot, ctx.Err() + } +} + +func (h *collectorBlockingHandle) Close() error { + if h.closed.CompareAndSwap(false, true) { + close(h.release) + } + return nil +} + func TestChangeType_String(t *testing.T) { tests := []struct { name string @@ -263,6 +302,144 @@ func TestChangeCollector_Next_WithError(t *testing.T) { assert.Nil(t, data) } +func TestChangeCollector_Next_UnblocksOnClose(t *testing.T) { + t.Parallel() + + ctx := context.Background() + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + handle := newCollectorBlockingHandle() + fromTs := types.TS{} + toTs := (&fromTs).Next() + cc := NewChangeCollector(handle, mp, fromTs, toTs, 1, "task1", "db1", "table1") + + resultCh := make(chan struct { + data *ChangeData + err error + }, 1) + + go func() { + data, err := cc.Next(ctx) + resultCh <- struct { + data *ChangeData + err error + }{data, err} + }() + + select { + case <-handle.nextCalled: + case <-time.After(2 * time.Second): + t.Fatal("Next did not start") + } + + require.NoError(t, cc.Close()) + + select { + case res := <-resultCh: + require.NoError(t, res.err) + require.NotNil(t, res.data) + assert.Equal(t, ChangeTypeNoMoreData, res.data.Type) + case <-time.After(2 * time.Second): + t.Fatal("Next did not unblock after Close") + } +} + +func TestChangeCollector_Next_ContextCancel(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + handle := newCollectorBlockingHandle() + fromTs := types.TS{} + toTs := (&fromTs).Next() + cc := NewChangeCollector(handle, mp, fromTs, toTs, 1, "task1", "db1", "table1") + + resultCh := make(chan struct { + data *ChangeData + err error + }, 1) + + go func() { + data, err := cc.Next(ctx) + resultCh <- struct { + data *ChangeData + err error + }{data, err} + }() + + select { + case <-handle.nextCalled: + case <-time.After(2 * time.Second): + t.Fatal("Next did not start") + } + + cancel() + + select { + case res := <-resultCh: + require.Error(t, res.err) + assert.ErrorIs(t, res.err, context.Canceled) + assert.Nil(t, res.data) + case <-time.After(2 * time.Second): + t.Fatal("Next did not unblock after context cancel") + } +} + +func TestChangeCollector_Next_ConcurrentCancelAfterData(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + handle := newCollectorBlockingHandle() + + fromTs := types.TS{} + toTs := (&fromTs).Next() + cc := NewChangeCollector(handle, mp, fromTs, toTs, 1, "task1", "db1", "table1") + resultCh := make(chan struct { + data *ChangeData + err error + }, 1) + + go func() { + data, err := cc.Next(ctx) + resultCh <- struct { + data *ChangeData + err error + }{data, err} + }() + + select { + case <-handle.nextCalled: + case <-time.After(2 * time.Second): + t.Fatal("Next did not start") + } + + cancel() + + select { + case res := <-resultCh: + require.Error(t, res.err) + assert.ErrorIs(t, res.err, context.Canceled) + assert.Nil(t, res.data) + case <-time.After(2 * time.Second): + t.Fatal("Next did not unblock after concurrent cancellation") + } + + require.NoError(t, cc.Close()) + require.True(t, cc.IsClosed()) +} + func TestChangeCollector_Next_AfterClose(t *testing.T) { ctx := context.Background() mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) @@ -388,3 +565,59 @@ func TestChangeCollector_GetToTs(t *testing.T) { assert.Equal(t, toTs, cc.GetToTs()) } + +// TestChangeCollector_Next_ConcurrentCloseAndCancel ensures that when Next is blocked, +// concurrent Close and context cancellation do not deadlock and Next returns deterministically. +func TestChangeCollector_Next_ConcurrentCloseAndCancel(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + handle := newCollectorBlockingHandle() + fromTs := types.TS{} + toTs := (&fromTs).Next() + cc := NewChangeCollector(handle, mp, fromTs, toTs, 1, "task1", "db1", "table1") + + resultCh := make(chan struct { + data *ChangeData + err error + }, 1) + + go func() { + data, err := cc.Next(ctx) + resultCh <- struct { + data *ChangeData + err error + }{data, err} + }() + + // Wait until Next has started and is blocked + select { + case <-handle.nextCalled: + case <-time.After(500 * time.Millisecond): + t.Fatal("Next did not start") + } + + // Concurrently cancel and close; order is intentionally racy + cancel() + require.NoError(t, cc.Close()) + + select { + case res := <-resultCh: + // Either returns context.Canceled error or NoMoreData if close wins the race + if res.err != nil { + assert.ErrorIs(t, res.err, context.Canceled) + assert.Nil(t, res.data) + } else { + require.NotNil(t, res.data) + assert.Equal(t, ChangeTypeNoMoreData, res.data.Type) + } + case <-time.After(1 * time.Second): + t.Fatal("Next did not return after concurrent close and cancel") + } +} diff --git a/pkg/cdc/reader_v2_data_processor.go b/pkg/cdc/reader_v2_data_processor.go index 1f201a6c0bb7f..4ce64096418aa 100644 --- a/pkg/cdc/reader_v2_data_processor.go +++ b/pkg/cdc/reader_v2_data_processor.go @@ -16,6 +16,7 @@ package cdc import ( "context" + "sync" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/types" @@ -55,6 +56,9 @@ type DataProcessor struct { insertAtmBatch *AtomicBatch deleteAtmBatch *AtomicBatch + // Mutex for cleanup operations + cleanupMu sync.Mutex + // Configuration initSnapshotSplitTxn bool // Whether to split snapshot into separate transactions @@ -418,7 +422,11 @@ func (dp *DataProcessor) processNoMoreData(ctx context.Context) error { // Cleanup cleans up any remaining resources // This should be called in defer to ensure cleanup even on errors +// This method is safe to call concurrently and is idempotent func (dp *DataProcessor) Cleanup() { + dp.cleanupMu.Lock() + defer dp.cleanupMu.Unlock() + if dp.insertAtmBatch != nil { dp.insertAtmBatch.Close() dp.insertAtmBatch = nil diff --git a/pkg/cdc/reader_v2_data_processor_test.go b/pkg/cdc/reader_v2_data_processor_test.go index 96d8b2c1f5793..9a5fd06d63b1a 100644 --- a/pkg/cdc/reader_v2_data_processor_test.go +++ b/pkg/cdc/reader_v2_data_processor_test.go @@ -16,7 +16,10 @@ package cdc import ( "context" + "math/rand" + "sync" "testing" + "time" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" @@ -25,6 +28,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // mockDataProcessorSinker for testing DataProcessor @@ -42,6 +46,149 @@ func (m *mockDataProcessorSinker) reset() { m.sinkCalls = nil } +type dataProcessorRecordingSinker struct { + *recordingSinker + sinkCalls []*DecoderOutput +} + +func newDataProcessorRecordingSinker() *dataProcessorRecordingSinker { + return &dataProcessorRecordingSinker{ + recordingSinker: newRecordingSinker(), + } +} + +func (s *dataProcessorRecordingSinker) Sink(ctx context.Context, data *DecoderOutput) { + s.mu.Lock() + s.ops = append(s.ops, "sink") + s.sinkCalls = append(s.sinkCalls, data) + s.mu.Unlock() +} + +func (s *dataProcessorRecordingSinker) sinkCallsSnapshot() []*DecoderOutput { + s.mu.Lock() + defer s.mu.Unlock() + cp := make([]*DecoderOutput, len(s.sinkCalls)) + copy(cp, s.sinkCalls) + return cp +} + +type slowDataProcessorSinker struct { + *dataProcessorRecordingSinker + delay time.Duration +} + +func newSlowDataProcessorSinker(delay time.Duration) *slowDataProcessorSinker { + return &slowDataProcessorSinker{ + dataProcessorRecordingSinker: newDataProcessorRecordingSinker(), + delay: delay, + } +} + +func (s *slowDataProcessorSinker) SendBegin() { + time.Sleep(s.delay) + s.record("begin") +} + +func (s *slowDataProcessorSinker) SendCommit() { + time.Sleep(s.delay) + s.record("commit") +} + +func (s *slowDataProcessorSinker) SendRollback() { + time.Sleep(s.delay) + s.record("rollback") +} + +func (s *slowDataProcessorSinker) SendDummy() { + time.Sleep(s.delay / 2) + s.record("dummy") +} + +func (s *slowDataProcessorSinker) Sink(ctx context.Context, data *DecoderOutput) { + time.Sleep(s.delay / 2) + s.dataProcessorRecordingSinker.Sink(ctx, data) +} + +type dataProcessorHarness struct { + dp *DataProcessor + sinker *dataProcessorRecordingSinker + txnMgr *TransactionManager + update *mockWatermarkUpdater + mp *mpool.MPool +} + +func newDataProcessorHarness(t *testing.T, splitSnapshot bool) *dataProcessorHarness { + t.Helper() + + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + t.Cleanup(func() { + mpool.DeleteMPool(mp) + }) + + packerPool := fileservice.NewPool( + 128, + func() *types.Packer { return types.NewPacker() }, + func(packer *types.Packer) { packer.Reset() }, + func(packer *types.Packer) {}, + ) + + sinker := newDataProcessorRecordingSinker() + updater := newMockWatermarkUpdater() + txnMgr := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + dp := NewDataProcessor( + sinker, + txnMgr, + mp, + packerPool, + 1, 0, + 1, 0, + splitSnapshot, + 1, + "task1", + "db1", + "table1", + ) + + return &dataProcessorHarness{ + dp: dp, + sinker: sinker, + txnMgr: txnMgr, + update: updater, + mp: mp, + } +} + +func buildBatch(t *testing.T, mp *mpool.MPool, pkVals []int32, ts types.TS) *batch.Batch { + t.Helper() + + if len(pkVals) == 0 { + return nil + } + + bat := batch.New([]string{"pk", "ts"}) + pkVec := vector.NewVec(types.T_int32.ToType()) + tsVec := vector.NewVec(types.T_TS.ToType()) + + for range pkVals { + if err := vector.AppendFixed(tsVec, ts, false, mp); err != nil { + t.Fatalf("append ts: %v", err) + } + } + + for _, v := range pkVals { + if err := vector.AppendFixed(pkVec, v, false, mp); err != nil { + t.Fatalf("append pk: %v", err) + } + } + + bat.Vecs[0] = pkVec + bat.Vecs[1] = tsVec + bat.SetRowCount(len(pkVals)) + return bat +} + func TestNewDataProcessor(t *testing.T) { mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) assert.NoError(t, err) @@ -416,3 +563,586 @@ func TestDataProcessor_GetAtmBatches(t *testing.T) { assert.NotNil(t, dp.GetInsertAtmBatch()) assert.NotNil(t, dp.GetDeleteAtmBatch()) } + +func TestDataProcessor_ProcessTailDone_BeginFailureRetainsBatches(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + beginErr := moerr.NewInternalError(ctx, "begin failure") + h.sinker.setBeginError(beginErr) + + data := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to), + } + + err := h.dp.ProcessChange(ctx, data) + require.ErrorIs(t, err, beginErr) + + assert.NotNil(t, h.dp.insertAtmBatch) + assert.Equal(t, []string{"begin"}, h.sinker.opsSnapshot()) + assert.Len(t, h.sinker.sinkCallsSnapshot(), 0) +} + +func TestDataProcessor_ProcessTailDone_UpdatesActiveTransaction(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to1 := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to1) + + data1 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to1), + } + require.NoError(t, h.dp.ProcessChange(ctx, data1)) + + tracker := h.txnMgr.GetTracker() + require.NotNil(t, tracker) + + to2 := types.BuildTS(3, 0) + h.dp.SetTransactionRange(to1, to2) + data2 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{2}, to2), + } + require.NoError(t, h.dp.ProcessChange(ctx, data2)) + + require.Equal(t, to2, h.txnMgr.GetTracker().GetToTs()) + assert.Equal(t, []string{"begin", "sink", "sink"}, h.sinker.opsSnapshot()) +} + +func TestDataProcessor_ProcessNoMoreData_CommitFailureRequiresRollback(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to), + })) + + h.sinker.resetOps() + commitErr := moerr.NewInternalError(ctx, "commit failure") + h.sinker.setCommitError(commitErr) + + to2 := types.BuildTS(3, 0) + h.dp.SetTransactionRange(to, to2) + err := h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData}) + require.ErrorIs(t, err, commitErr) + + assert.True(t, h.txnMgr.GetTracker().NeedsRollback()) + assert.Equal(t, []string{"sink", "dummy", "commit", "dummy"}, h.sinker.opsSnapshot()) +} + +func TestDataProcessor_NoMoreData_HeartbeatUpdatesWatermark(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, true) // split snapshot, no txn + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + h.txnMgr.Reset() + + err := h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData}) + require.NoError(t, err) + + assert.True(t, h.update.updateCalled) + + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 1) + assert.True(t, calls[0].noMoreData) + assert.Equal(t, []string{"sink", "dummy"}, h.sinker.opsSnapshot()) +} + +// TestDataProcessor_CommitFail_EnsureCleanup_ThenRecover verifies that when commit fails +// and tracker requires rollback, EnsureCleanup performs rollback and the next round succeeds. +func TestDataProcessor_CommitFail_EnsureCleanup_ThenRecover(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + // Round 1: begin transaction with a TailDone + from := types.BuildTS(1, 0) + to1 := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to1) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to1), + })) + require.NotNil(t, h.txnMgr.GetTracker()) + + // Inject commit failure on NoMoreData + h.sinker.resetOps() + commitErr := moerr.NewInternalError(ctx, "commit failure") + h.sinker.setCommitError(commitErr) + to2 := types.BuildTS(3, 0) + h.dp.SetTransactionRange(to1, to2) + err := h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData}) + require.ErrorIs(t, err, commitErr) + require.True(t, h.txnMgr.GetTracker().NeedsRollback()) + // No rollback yet; EnsureCleanup will handle it + + // EnsureCleanup should rollback and clear NeedsRollback + require.NoError(t, h.txnMgr.EnsureCleanup(ctx)) + require.False(t, h.txnMgr.GetTracker().NeedsRollback()) + ops := h.sinker.opsSnapshot() + require.Contains(t, ops, "clear") + require.Contains(t, ops, "rollback") + require.Contains(t, ops, "dummy") + + // Round 2: clear error and confirm recovery path succeeds + h.sinker.resetOps() + h.sinker.setError(nil) + h.sinker.setCommitError(nil) + // Reset transaction manager state to start a fresh transaction in next round + h.txnMgr.Reset() + + // Start a fresh range and process TailDone then NoMoreData + to3 := types.BuildTS(4, 0) + h.dp.SetTransactionRange(to2, to3) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{2}, to3), + })) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData})) + + // Verify we saw a begin and a commit, and no rollback in this successful round + ops = h.sinker.opsSnapshot() + hasBegin := false + hasCommit := false + hasRollback := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + case "rollback": + hasRollback = true + } + } + require.True(t, hasBegin, "recovery round should begin") + require.True(t, hasCommit, "recovery round should commit") + require.False(t, hasRollback, "recovery round should not rollback") +} + +// TestDataProcessor_RepeatedCommitFailures_EnsureCleanup_Idempotent runs multiple cycles +// of commit failure -> EnsureCleanup -> recovery, to verify cleanup remains correct and idempotent. +func TestDataProcessor_RepeatedCommitFailures_EnsureCleanup_Idempotent(t *testing.T) { + t.Parallel() + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + + for i := 0; i < 3; i++ { + // Begin via TailDone + h.dp.SetTransactionRange(from, to) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{int32(i + 1)}, to), + })) + require.NotNil(t, h.txnMgr.GetTracker()) + + // Inject commit failure on NoMoreData + h.sinker.resetOps() + commitErr := moerr.NewInternalError(ctx, "commit failure") + h.sinker.setCommitError(commitErr) + next := (&to).Next() + h.dp.SetTransactionRange(to, next) + err := h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData}) + require.ErrorIs(t, err, commitErr) + + // EnsureCleanup must rollback once + require.NoError(t, h.txnMgr.EnsureCleanup(ctx)) + require.False(t, h.txnMgr.GetTracker().NeedsRollback()) + ops := h.sinker.opsSnapshot() + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + require.Equal(t, 1, rollbackCount, "each failure cycle should trigger exactly one rollback") + + // Clear errors and reset transaction manager + h.sinker.resetOps() + h.sinker.setCommitError(nil) + h.txnMgr.Reset() + + // Recovery round + h.dp.SetTransactionRange(to, next) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{9}, next), + })) + require.NoError(t, h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData})) + + ops = h.sinker.opsSnapshot() + // Recovery round should not trigger rollback + for _, op := range ops { + require.NotEqual(t, "rollback", op, "recovery round should not rollback") + } + + // Bump to next window + from = to + to = next + } +} + +// TestDataProcessor_RandomizedSequence_WithDelays_NoDeadlock verifies that with +// randomized sequence of Snapshot/TailWip/TailDone/NoMoreData and a slow sinker, +// the processor finishes quickly without deadlocks and preserves basic invariants. +func TestDataProcessor_RandomizedSequence_WithDelays_NoDeadlock(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + sinker := newSlowDataProcessorSinker(3 * time.Millisecond) + updater := newMockWatermarkUpdater() + txnMgr := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + packerPool := fileservice.NewPool( + 128, + func() *types.Packer { return types.NewPacker() }, + func(packer *types.Packer) { packer.Reset() }, + func(packer *types.Packer) {}, + ) + + dp := NewDataProcessor( + sinker, txnMgr, mp, packerPool, + 1, 0, 1, 0, false, + 1, "task1", "db1", "table1", + ) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + dp.SetTransactionRange(from, to) + + // Prepare randomized sequence + r := rand.New(rand.NewSource(42)) + typesSeq := make([]ChangeType, 0, 20) + candidates := []ChangeType{ChangeTypeSnapshot, ChangeTypeTailWip, ChangeTypeTailDone} + for i := 0; i < 10; i++ { + typesSeq = append(typesSeq, candidates[r.Intn(len(candidates))]) + } + // Ensure termination + typesSeq = append(typesSeq, ChangeTypeNoMoreData) + + // Process sequentially (DataProcessor not guaranteed goroutine-safe), + // but with slow sinker to simulate interleaving/latency. + for _, typ := range typesSeq { + switch typ { + case ChangeTypeSnapshot: + b := buildBatch(t, mp, []int32{1}, to) + require.NoError(t, dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeSnapshot, + InsertBatch: b, + })) + case ChangeTypeTailWip: + b := buildBatch(t, mp, []int32{1}, to) + require.NoError(t, dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailWip, + InsertBatch: b, + })) + case ChangeTypeTailDone: + // bump toTs to simulate progress + from = to + to = (&to).Next() + dp.SetTransactionRange(from, to) + b := buildBatch(t, mp, []int32{1}, to) + require.NoError(t, dp.ProcessChange(ctx, &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: b, + })) + } + } + require.NoError(t, dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData})) + + // Invariants: + ops := sinker.opsSnapshot() + begin := 0 + commit := 0 + for _, op := range ops { + if op == "begin" { + begin++ + } + if op == "commit" { + commit++ + } + } + require.LessOrEqual(t, begin, 1, "should not start multiple transactions in this simple randomized run") + require.LessOrEqual(t, commit, 1, "should not commit multiple times in this simple randomized run") +} + +// TestDataProcessor_Cleanup_Concurrent tests concurrent Cleanup calls +// Should be idempotent and not panic +func TestDataProcessor_Cleanup_Concurrent(t *testing.T) { + mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + require.NoError(t, err) + defer mpool.DeleteMPool(mp) + + sinker := &mockDataProcessorSinker{mockSinker: &mockSinker{}} + updater := newMockWatermarkUpdater() + txnMgr := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + packerPool := fileservice.NewPool( + 128, + func() *types.Packer { return types.NewPacker() }, + func(packer *types.Packer) { packer.Reset() }, + func(packer *types.Packer) {}, + ) + + dp := NewDataProcessor( + sinker, txnMgr, mp, packerPool, + 1, 0, 1, 0, false, + 1, "task1", "db1", "table1", + ) + + // Set some atomic batches + dp.insertAtmBatch = NewAtomicBatch(mp) + dp.deleteAtmBatch = NewAtomicBatch(mp) + + // Concurrently call Cleanup + const numGoroutines = 20 + var wg sync.WaitGroup + wg.Add(numGoroutines) + for i := 0; i < numGoroutines; i++ { + go func() { + defer wg.Done() + dp.Cleanup() + }() + } + + wg.Wait() + + // Batches should be cleaned up + require.Nil(t, dp.insertAtmBatch) + require.Nil(t, dp.deleteAtmBatch) +} + +// TestDataProcessor_SinkerErrorRecovery tests that after sinker error is cleared, +// processing can continue normally +func TestDataProcessor_SinkerErrorRecovery(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + // Set sinker error + sinkerErr := moerr.NewInternalError(ctx, "sinker error") + h.sinker.setError(sinkerErr) + + // Try to process - should fail immediately + data := &ChangeData{ + Type: ChangeTypeSnapshot, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to), + } + err := h.dp.ProcessChange(ctx, data) + require.Error(t, err) + require.ErrorIs(t, err, sinkerErr) + + // Clear error + h.sinker.ClearError() + + // Process should succeed now + err = h.dp.ProcessChange(ctx, data) + require.NoError(t, err) + + // Verify sinker was called + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 1) + require.Equal(t, OutputTypeSnapshot, calls[0].outputTyp) +} + +// TestDataProcessor_MultipleTailDone_SameTransaction tests that multiple TailDone +// batches update the same transaction's toTs correctly +func TestDataProcessor_MultipleTailDone_SameTransaction(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to1 := types.BuildTS(2, 0) + to2 := types.BuildTS(3, 0) + to3 := types.BuildTS(4, 0) + + h.dp.SetTransactionRange(from, to1) + + // First TailDone - should begin transaction + data1 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to1), + } + require.NoError(t, h.dp.ProcessChange(ctx, data1)) + + tracker := h.txnMgr.GetTracker() + require.NotNil(t, tracker) + require.Equal(t, to1, tracker.GetToTs()) + + // Second TailDone - should update toTs to to2 + h.dp.SetTransactionRange(to1, to2) + data2 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{2}, to2), + } + require.NoError(t, h.dp.ProcessChange(ctx, data2)) + + require.Equal(t, to2, tracker.GetToTs()) + + // Third TailDone - should update toTs to to3 + h.dp.SetTransactionRange(to2, to3) + data3 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{3}, to3), + } + require.NoError(t, h.dp.ProcessChange(ctx, data3)) + + require.Equal(t, to3, tracker.GetToTs()) + + // Verify all data was sunk + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 3) + for i, call := range calls { + require.Equal(t, OutputTypeTail, call.outputTyp) + require.NotNil(t, call.insertAtmBatch) + // Each TailDone batch is independent - batches are cleared after each sink + require.Equal(t, int64(1), int64(call.insertAtmBatch.RowCount()), "each TailDone batch should have 1 row (batch %d)", i+1) + } + + // Verify only one begin + ops := h.sinker.opsSnapshot() + beginCount := 0 + for _, op := range ops { + if op == "begin" { + beginCount++ + } + } + require.Equal(t, 1, beginCount, "only one begin should occur for multiple TailDone batches") +} + +// TestDataProcessor_TailWipThenTailDone_AccumulatesCorrectly tests that TailWip +// accumulates data and TailDone sends it correctly +func TestDataProcessor_TailWipThenTailDone_AccumulatesCorrectly(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + // Multiple TailWip - should accumulate + data1 := &ChangeData{ + Type: ChangeTypeTailWip, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to), + } + require.NoError(t, h.dp.ProcessChange(ctx, data1)) + + data2 := &ChangeData{ + Type: ChangeTypeTailWip, + InsertBatch: buildBatch(t, h.mp, []int32{2}, to), + } + require.NoError(t, h.dp.ProcessChange(ctx, data2)) + + // Verify batches are accumulating + require.NotNil(t, h.dp.insertAtmBatch) + require.Equal(t, 2, h.dp.insertAtmBatch.RowCount()) + + // TailDone - should send accumulated data + data3 := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{3}, to), + } + require.NoError(t, h.dp.ProcessChange(ctx, data3)) + + // Verify all data was sunk (1+2+3 = 6 rows total) + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 1) + require.Equal(t, OutputTypeTail, calls[0].outputTyp) + require.NotNil(t, calls[0].insertAtmBatch) + require.Equal(t, 3, calls[0].insertAtmBatch.RowCount(), "should have accumulated all TailWip + TailDone rows") + + // Batches should be cleared after sink + require.Nil(t, h.dp.insertAtmBatch) + require.Nil(t, h.dp.deleteAtmBatch) +} + +// TestDataProcessor_BeginFailure_BatchesRetained tests that when BeginTransaction +// fails, batches are retained for retry +func TestDataProcessor_BeginFailure_BatchesRetained(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + // Set begin to fail + beginErr := moerr.NewInternalError(ctx, "begin failure") + h.sinker.setBeginError(beginErr) + + // Process TailDone - should fail at BeginTransaction + data := &ChangeData{ + Type: ChangeTypeTailDone, + InsertBatch: buildBatch(t, h.mp, []int32{1}, to), + } + err := h.dp.ProcessChange(ctx, data) + require.Error(t, err) + require.ErrorIs(t, err, beginErr) + + // Batches should be retained for retry + require.NotNil(t, h.dp.insertAtmBatch) + require.Equal(t, 1, h.dp.insertAtmBatch.RowCount()) + + // No sink calls should occur + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 0) + + // Verify begin was attempted but failed + ops := h.sinker.opsSnapshot() + require.Contains(t, ops, "begin", "begin should be attempted") + require.NotContains(t, ops, "sink", "sink should not be called when begin fails") +} + +// TestDataProcessor_NoMoreData_WithoutActiveTransaction_HeartbeatOnly tests that +// NoMoreData without active transaction only sends heartbeat and updates watermark +func TestDataProcessor_NoMoreData_WithoutActiveTransaction_HeartbeatOnly(t *testing.T) { + ctx := context.Background() + h := newDataProcessorHarness(t, false) + + from := types.BuildTS(1, 0) + to := types.BuildTS(2, 0) + h.dp.SetTransactionRange(from, to) + + // No active transaction (Reset) + h.txnMgr.Reset() + + // Process NoMoreData + err := h.dp.ProcessChange(ctx, &ChangeData{Type: ChangeTypeNoMoreData}) + require.NoError(t, err) + + // Should send heartbeat and update watermark + calls := h.sinker.sinkCallsSnapshot() + require.Len(t, calls, 1) + require.True(t, calls[0].noMoreData) + + ops := h.sinker.opsSnapshot() + require.Contains(t, ops, "sink", "should send heartbeat") + require.Contains(t, ops, "dummy", "should send dummy") + require.NotContains(t, ops, "commit", "should not commit when no active transaction") + + // Watermark should be updated + require.True(t, h.update.updateCalled) +} diff --git a/pkg/cdc/reader_v2_txn_manager.go b/pkg/cdc/reader_v2_txn_manager.go index f395e09ce1a29..759e88f5dcf28 100644 --- a/pkg/cdc/reader_v2_txn_manager.go +++ b/pkg/cdc/reader_v2_txn_manager.go @@ -16,6 +16,7 @@ package cdc import ( "context" + "sync" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/logutil" @@ -28,11 +29,22 @@ import ( // 2. Interact with Sinker (SendBegin/Commit/Rollback) // 3. Interact with WatermarkUpdater (update watermark) // 4. Implement dual-layer safety (tracker + watermark) +// +// Concurrency & Locking: +// - All PUBLIC methods on TransactionManager are serialized by an internal mutex. +// This guarantees safe access and mutation of the internal TransactionTracker. +// - DO NOT call any other PUBLIC TransactionManager API while holding the mutex. +// If a public method needs to rollback while holding the lock, it MUST call +// the private rollbackLocked instead of the public RollbackTransaction to avoid +// re-entrant locking and potential deadlocks. type TransactionManager struct { sinker Sinker watermarkUpdater WatermarkUpdater watermarkKey *WatermarkKey + // Protects tracker and transactional state transitions + mu sync.Mutex + // Current transaction tracker tracker *TransactionTracker @@ -71,6 +83,8 @@ func NewTransactionManager( // BeginTransaction starts a new transaction // This should be called when we have data to send func (tm *TransactionManager) BeginTransaction(ctx context.Context, fromTs, toTs types.TS) error { + tm.mu.Lock() + defer tm.mu.Unlock() if tm.tracker != nil && tm.tracker.NeedsRollback() { logutil.Warn( "cdc.txn_manager.begin_with_unfinished", @@ -80,7 +94,7 @@ func (tm *TransactionManager) BeginTransaction(ctx context.Context, fromTs, toTs zap.String("table", tm.tableName), ) // Rollback previous transaction first - if err := tm.RollbackTransaction(ctx); err != nil { + if err := tm.rollbackLocked(ctx); err != nil { return err } } @@ -126,6 +140,8 @@ func (tm *TransactionManager) BeginTransaction(ctx context.Context, fromTs, toTs // 2. Update watermark (persistent proof) // 3. Mark tracker as committed (memory state) func (tm *TransactionManager) CommitTransaction(ctx context.Context) error { + tm.mu.Lock() + defer tm.mu.Unlock() if tm.tracker == nil { logutil.Warn( "cdc.txn_manager.commit_without_tracker", @@ -216,6 +232,8 @@ func (tm *TransactionManager) CommitTransaction(ctx context.Context) error { // RollbackTransaction rolls back the current transaction func (tm *TransactionManager) RollbackTransaction(ctx context.Context) error { + tm.mu.Lock() + defer tm.mu.Unlock() if tm.tracker == nil { logutil.Warn( "cdc.txn_manager.rollback_without_tracker", @@ -292,6 +310,8 @@ func (tm *TransactionManager) RollbackTransaction(ctx context.Context) error { // Layer 1: Check tracker state (fast, explicit) // Layer 2: Verify watermark (reliable, persistent) func (tm *TransactionManager) EnsureCleanup(ctx context.Context) error { + tm.mu.Lock() + defer tm.mu.Unlock() if tm.tracker == nil { return nil } @@ -305,7 +325,7 @@ func (tm *TransactionManager) EnsureCleanup(ctx context.Context) error { zap.String("db", tm.dbName), zap.String("table", tm.tableName), ) - return tm.RollbackTransaction(ctx) + return tm.rollbackLocked(ctx) } // Layer 2: Verify watermark (dual-layer safety) @@ -324,7 +344,7 @@ func (tm *TransactionManager) EnsureCleanup(ctx context.Context) error { ) // Fallback to tracker state if tm.tracker.hasBegin && !tm.tracker.hasCommitted { - return tm.RollbackTransaction(ctx) + return tm.rollbackLocked(ctx) } return nil } @@ -340,7 +360,7 @@ func (tm *TransactionManager) EnsureCleanup(ctx context.Context) error { zap.String("expected", toTs.ToString()), zap.String("actual", current.ToString()), ) - return tm.RollbackTransaction(ctx) + return tm.rollbackLocked(ctx) } return nil @@ -348,10 +368,90 @@ func (tm *TransactionManager) EnsureCleanup(ctx context.Context) error { // GetTracker returns the current transaction tracker func (tm *TransactionManager) GetTracker() *TransactionTracker { + tm.mu.Lock() + defer tm.mu.Unlock() return tm.tracker } // Reset resets the transaction manager for a new transaction func (tm *TransactionManager) Reset() { + tm.mu.Lock() + defer tm.mu.Unlock() tm.tracker = nil } + +// rollbackLocked rolls back the current transaction. +// NOTE: tm.mu MUST be held by the caller. +// This function is INTERNAL-ONLY and is used to avoid re-entrancy/deadlocks +// when a public method needs to perform a rollback while already holding tm.mu. +func (tm *TransactionManager) rollbackLocked(ctx context.Context) error { + if tm.tracker == nil { + logutil.Warn( + "cdc.txn_manager.rollback_without_tracker", + zap.String("task-id", tm.taskId), + zap.Uint64("account-id", tm.accountId), + zap.String("db", tm.dbName), + zap.String("table", tm.tableName), + ) + return nil + } + + if !tm.tracker.hasBegin { + logutil.Debug( + "cdc.txn_manager.rollback_without_begin", + zap.String("task-id", tm.taskId), + zap.Uint64("account-id", tm.accountId), + zap.String("db", tm.dbName), + zap.String("table", tm.tableName), + ) + return nil + } + + if tm.tracker.hasRolledBack { + logutil.Debug( + "cdc.txn_manager.already_rolled_back", + zap.String("task-id", tm.taskId), + zap.Uint64("account-id", tm.accountId), + zap.String("db", tm.dbName), + zap.String("table", tm.tableName), + ) + return nil + } + + // Clear any previous errors before rollback + tm.sinker.ClearError() + + // Send ROLLBACK to sinker + tm.sinker.SendRollback() + // Send dummy to ensure ROLLBACK is sent + tm.sinker.SendDummy() + + // Check for errors + if err := tm.sinker.Error(); err != nil { + logutil.Error( + "cdc.txn_manager.send_rollback_failed", + zap.String("task-id", tm.taskId), + zap.Uint64("account-id", tm.accountId), + zap.String("db", tm.dbName), + zap.String("table", tm.tableName), + zap.Error(err), + ) + // Mark as rolled back even if it failed + // to avoid infinite retry loops + tm.tracker.MarkRollback() + return err + } + + // Mark tracker as rolled back + tm.tracker.MarkRollback() + + logutil.Debug( + "cdc.txn_manager.rollback_success", + zap.String("task-id", tm.taskId), + zap.Uint64("account-id", tm.accountId), + zap.String("db", tm.dbName), + zap.String("table", tm.tableName), + ) + + return nil +} diff --git a/pkg/cdc/reader_v2_txn_manager_test.go b/pkg/cdc/reader_v2_txn_manager_test.go index 6ec5b57f88a1c..48a69777d0636 100644 --- a/pkg/cdc/reader_v2_txn_manager_test.go +++ b/pkg/cdc/reader_v2_txn_manager_test.go @@ -16,11 +16,15 @@ package cdc import ( "context" + "sync" + "sync/atomic" "testing" + "time" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // mockSinker for testing @@ -78,6 +82,120 @@ func (m *mockSinker) reset() { m.rollbackErr = nil } +type recordingSinker struct { + mu sync.Mutex + ops []string + err error + rollbackErr error + commitErr error + beginErr error +} + +func newRecordingSinker() *recordingSinker { + return &recordingSinker{} +} + +func (s *recordingSinker) record(op string) { + s.mu.Lock() + s.ops = append(s.ops, op) + s.mu.Unlock() +} + +func (s *recordingSinker) opsSnapshot() []string { + s.mu.Lock() + defer s.mu.Unlock() + cp := make([]string, len(s.ops)) + copy(cp, s.ops) + return cp +} + +func (s *recordingSinker) resetOps() { + s.mu.Lock() + s.ops = nil + s.mu.Unlock() +} + +func (s *recordingSinker) setError(err error) { + s.mu.Lock() + s.err = err + s.mu.Unlock() +} + +func (s *recordingSinker) setCommitError(err error) { + s.mu.Lock() + s.commitErr = err + s.mu.Unlock() +} + +func (s *recordingSinker) setRollbackError(err error) { + s.mu.Lock() + s.rollbackErr = err + s.mu.Unlock() +} + +func (s *recordingSinker) setBeginError(err error) { + s.mu.Lock() + s.beginErr = err + s.mu.Unlock() +} + +func (s *recordingSinker) Run(context.Context, *ActiveRoutine) {} +func (s *recordingSinker) Sink(context.Context, *DecoderOutput) {} +func (s *recordingSinker) Close() {} +func (s *recordingSinker) Reset() {} + +func (s *recordingSinker) SendBegin() { + var err error + s.mu.Lock() + s.ops = append(s.ops, "begin") + err = s.beginErr + s.mu.Unlock() + if err != nil { + s.setError(err) + } +} + +func (s *recordingSinker) SendCommit() { + var err error + s.mu.Lock() + s.ops = append(s.ops, "commit") + err = s.commitErr + s.mu.Unlock() + if err != nil { + s.setError(err) + } +} + +func (s *recordingSinker) SendDummy() { + s.record("dummy") +} + +func (s *recordingSinker) SendRollback() { + var rollbackErr error + s.mu.Lock() + rollbackErr = s.rollbackErr + s.mu.Unlock() + + s.record("rollback") + if rollbackErr != nil { + s.setError(rollbackErr) + } +} + +func (s *recordingSinker) Error() error { + s.mu.Lock() + defer s.mu.Unlock() + return s.err +} + +func (s *recordingSinker) ClearError() { + s.record("clear") + s.setError(nil) + // Note: We don't clear commitErr/rollbackErr/beginErr here because + // these are test-injected errors that should persist across retries. + // Only the current error state (s.err) is cleared. +} + // mockWatermarkUpdater for testing type mockWatermarkUpdater struct { watermarks map[string]types.TS @@ -192,6 +310,31 @@ func TestTransactionManager_BeginTransaction_WithError(t *testing.T) { assert.False(t, tm.tracker.hasBegin) } +func TestTransactionManager_BeginTransaction_RollsBackUnfinished(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + oldFrom := types.TS{} + oldTo := (&oldFrom).Next() + pending := NewTransactionTracker(oldFrom, oldTo) + pending.MarkBegin() + tm.tracker = pending + + newFrom := oldTo + newTo := (&newFrom).Next() + err := tm.BeginTransaction(ctx, newFrom, newTo) + require.NoError(t, err) + + require.NotEqual(t, pending, tm.tracker) + require.NotNil(t, tm.tracker) + assert.Equal(t, newFrom, tm.tracker.GetFromTs()) + assert.Equal(t, newTo, tm.tracker.GetToTs()) + + require.Equal(t, []string{"clear", "rollback", "dummy", "begin"}, sinker.opsSnapshot()) +} + func TestTransactionManager_CommitTransaction(t *testing.T) { ctx := context.Background() sinker := &mockSinker{} @@ -263,6 +406,38 @@ func TestTransactionManager_CommitTransaction_WithError(t *testing.T) { assert.True(t, tm.tracker.NeedsRollback()) } +func TestTransactionManager_EnsureCleanup_AfterCommitFailure(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + + commitErr := moerr.NewInternalError(ctx, "commit error") + sinker.setError(commitErr) + + err := tm.CommitTransaction(ctx) + require.ErrorIs(t, err, commitErr) + require.True(t, tm.tracker.NeedsRollback()) + + err = tm.EnsureCleanup(ctx) + require.NoError(t, err) + require.False(t, tm.tracker.NeedsRollback()) + + require.Equal(t, []string{ + "begin", + "commit", + "dummy", + "clear", + "rollback", + "dummy", + }, sinker.opsSnapshot()) + require.NoError(t, sinker.Error()) +} + func TestTransactionManager_RollbackTransaction(t *testing.T) { ctx := context.Background() sinker := &mockSinker{} @@ -430,6 +605,31 @@ func TestTransactionManager_EnsureCleanup_WatermarkMismatch(t *testing.T) { assert.True(t, sinker.rollbackCalled) } +func TestTransactionManager_EnsureCleanup_WatermarkMismatch_Idempotent(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + require.NoError(t, updater.UpdateWatermarkOnly(ctx, tm.watermarkKey, &fromTs)) + + tm.tracker.MarkCommit() + + sinker.resetOps() + + err := tm.EnsureCleanup(ctx) + require.NoError(t, err) + require.False(t, tm.tracker.NeedsRollback()) + require.Equal(t, []string{"clear", "rollback", "dummy"}, sinker.opsSnapshot()) + + err = tm.EnsureCleanup(ctx) + require.NoError(t, err) + require.Equal(t, []string{"clear", "rollback", "dummy"}, sinker.opsSnapshot()) +} + func TestTransactionManager_Reset(t *testing.T) { ctx := context.Background() sinker := &mockSinker{} @@ -449,3 +649,367 @@ func TestTransactionManager_Reset(t *testing.T) { assert.Nil(t, tm.tracker) } + +// TestTransactionManager_BeginTransaction_Concurrent tests concurrent BeginTransaction calls +// Only one should succeed, others should handle rollback of previous transaction +func TestTransactionManager_BeginTransaction_Concurrent(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs1 := (&fromTs).Next() + toTs2 := (&toTs1).Next() + toTs3 := (&toTs2).Next() + + // Begin first transaction + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs1)) + sinker.resetOps() + + // Concurrently start multiple new transactions + const numGoroutines = 10 + var wg sync.WaitGroup + successCount := int32(0) + errCh := make(chan error, numGoroutines) + + wg.Add(numGoroutines) + for i := 0; i < numGoroutines; i++ { + go func(idx int) { + defer wg.Done() + toTs := toTs2 + if idx%2 == 0 { + toTs = toTs3 + } + err := tm.BeginTransaction(ctx, toTs1, toTs) + if err == nil { + atomic.AddInt32(&successCount, 1) + } + errCh <- err + }(i) + } + + wg.Wait() + close(errCh) + + // At least one should succeed, and all should handle rollback properly + require.GreaterOrEqual(t, successCount, int32(1), "at least one BeginTransaction should succeed") + require.LessOrEqual(t, successCount, int32(numGoroutines), "not all should succeed") + + // Verify all errors are nil (rollback succeeded) + for err := range errCh { + require.NoError(t, err, "all BeginTransaction calls should succeed after rollback") + } + + // Verify operations: each successful Begin should have rollback + begin + ops := sinker.opsSnapshot() + rollbackCount := 0 + beginCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } else if op == "begin" { + beginCount++ + } + } + + require.Equal(t, beginCount, int(successCount), "begin count should match success count") + require.GreaterOrEqual(t, rollbackCount, 1, "at least one rollback should occur") +} + +// TestTransactionManager_EnsureCleanup_Concurrent tests concurrent EnsureCleanup calls +// Should be idempotent and not cause duplicate rollbacks +func TestTransactionManager_EnsureCleanup_Concurrent(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + + // Begin transaction but don't commit + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + sinker.resetOps() + + // Concurrently call EnsureCleanup + const numGoroutines = 20 + var wg sync.WaitGroup + errCh := make(chan error, numGoroutines) + + wg.Add(numGoroutines) + for i := 0; i < numGoroutines; i++ { + go func() { + defer wg.Done() + errCh <- tm.EnsureCleanup(ctx) + }() + } + + wg.Wait() + close(errCh) + + // All should succeed + for err := range errCh { + require.NoError(t, err, "all EnsureCleanup calls should succeed") + } + + // Verify only one rollback occurred (idempotent) + ops := sinker.opsSnapshot() + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + + require.Equal(t, 1, rollbackCount, "only one rollback should occur despite concurrent calls") + require.False(t, tm.tracker.NeedsRollback(), "tracker should be clean after EnsureCleanup") +} + +// TestTransactionManager_BeginTransaction_NeedsRollback_RollbackFailure tests that +// when BeginTransaction detects NeedsRollback and attempts rollback, but rollback fails, +// the BeginTransaction should return the rollback error +func TestTransactionManager_BeginTransaction_NeedsRollback_RollbackFailure(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs1 := (&fromTs).Next() + toTs2 := (&toTs1).Next() + + // Begin first transaction (this sets hasBegin=true) + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs1)) + sinker.resetOps() + // Don't commit - tracker should need rollback (hasBegin && !hasCommitted && !hasRolledBack) + require.True(t, tm.tracker.NeedsRollback(), "tracker should need rollback after begin without commit") + + // Set rollback to fail + rollbackErr := moerr.NewInternalError(ctx, "rollback failed") + sinker.setRollbackError(rollbackErr) + + // Try to begin new transaction - should fail due to rollback failure + err := tm.BeginTransaction(ctx, toTs1, toTs2) + require.Error(t, err) + require.ErrorIs(t, err, rollbackErr) + + // Verify rollback was attempted + ops := sinker.opsSnapshot() + require.Contains(t, ops, "rollback", "rollback should be attempted") + require.NotContains(t, ops, "begin", "new begin should not be called due to rollback failure") + + // Tracker should still need rollback (even though rollback failed, it was marked as rolled back to prevent retry loops) + require.False(t, tm.tracker.NeedsRollback(), "tracker should be marked as rolled back even if rollback failed") + require.True(t, tm.tracker.hasRolledBack, "tracker should have hasRolledBack=true after rollback attempt") +} + +// TestTransactionManager_WatermarkMismatch_RollbackFailure tests that when +// EnsureCleanup detects watermark mismatch and attempts rollback, but rollback fails, +// the error is returned and state is consistent +func TestTransactionManager_WatermarkMismatch_RollbackFailure(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + + // Initialize watermark with fromTs (not toTs) + require.NoError(t, updater.UpdateWatermarkOnly(ctx, tm.watermarkKey, &fromTs)) + + // Begin transaction and mark as committed (simulating crash after commit but before watermark update) + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + tm.tracker.MarkCommit() + tm.tracker.MarkWatermarkUpdated() + sinker.resetOps() + + // Set rollback to fail + rollbackErr := moerr.NewInternalError(ctx, "rollback failed") + sinker.setRollbackError(rollbackErr) + + // EnsureCleanup should detect watermark mismatch and attempt rollback + err := tm.EnsureCleanup(ctx) + require.Error(t, err) + require.ErrorIs(t, err, rollbackErr) + + // Verify rollback was attempted + ops := sinker.opsSnapshot() + require.Contains(t, ops, "rollback", "rollback should be attempted") + require.Contains(t, ops, "clear", "clear should be called before rollback") + + // Tracker should still be marked as rolled back (even if rollback failed) + // This prevents infinite retry loops + require.True(t, tm.tracker.hasRolledBack, "tracker should be marked as rolled back even if rollback failed") +} + +// TestTransactionManager_GetFromCacheFails_NeedsRollback_RollbackFailure tests that when +// EnsureCleanup's GetFromCache fails, it falls back to tracker state, but if rollback fails, +// the error is returned +func TestTransactionManager_GetFromCacheFails_NeedsRollback_RollbackFailure(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + + // Begin transaction but don't commit + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + sinker.resetOps() + + // Set GetFromCache to fail + cacheErr := moerr.NewInternalError(ctx, "cache error") + updater.getFromCacheErr = cacheErr + + // Set rollback to fail + rollbackErr := moerr.NewInternalError(ctx, "rollback failed") + sinker.setRollbackError(rollbackErr) + + // EnsureCleanup should fall back to tracker state and attempt rollback + err := tm.EnsureCleanup(ctx) + require.Error(t, err) + require.ErrorIs(t, err, rollbackErr) + + // Verify rollback was attempted + ops := sinker.opsSnapshot() + require.Contains(t, ops, "rollback", "rollback should be attempted") + + // Tracker should be marked as rolled back + require.True(t, tm.tracker.hasRolledBack, "tracker should be marked as rolled back") +} + +// TestTransactionManager_EnsureCleanup_WatermarkMismatch_Concurrent tests concurrent +// EnsureCleanup calls when watermark mismatch is detected, verifying idempotency +func TestTransactionManager_EnsureCleanup_WatermarkMismatch_Concurrent(t *testing.T) { + ctx := context.Background() + sinker := newRecordingSinker() + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs := (&fromTs).Next() + + // Initialize watermark with fromTs (not toTs) + require.NoError(t, updater.UpdateWatermarkOnly(ctx, tm.watermarkKey, &fromTs)) + + // Begin transaction and mark as committed + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs)) + tm.tracker.MarkCommit() + tm.tracker.MarkWatermarkUpdated() + sinker.resetOps() + + // Concurrently call EnsureCleanup + const numGoroutines = 15 + var wg sync.WaitGroup + errCh := make(chan error, numGoroutines) + + wg.Add(numGoroutines) + for i := 0; i < numGoroutines; i++ { + go func() { + defer wg.Done() + errCh <- tm.EnsureCleanup(ctx) + }() + } + + wg.Wait() + close(errCh) + + // All should succeed + for err := range errCh { + require.NoError(t, err, "all EnsureCleanup calls should succeed") + } + + // Verify only one rollback occurred (idempotent) + ops := sinker.opsSnapshot() + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + + require.Equal(t, 1, rollbackCount, "only one rollback should occur despite concurrent calls and watermark mismatch") + require.False(t, tm.tracker.NeedsRollback(), "tracker should be clean after EnsureCleanup") +} + +// slowRecordingSinker injects small delays to simulate slow downstream without causing deadlocks. +type slowRecordingSinker struct { + *recordingSinker + delay time.Duration +} + +func newSlowRecordingSinker(delay time.Duration) *slowRecordingSinker { + return &slowRecordingSinker{ + recordingSinker: newRecordingSinker(), + delay: delay, + } +} + +func (s *slowRecordingSinker) SendBegin() { + time.Sleep(s.delay) + s.record("begin") +} + +func (s *slowRecordingSinker) SendCommit() { + time.Sleep(s.delay) + s.record("commit") +} + +func (s *slowRecordingSinker) SendRollback() { + time.Sleep(s.delay) + s.record("rollback") +} + +func (s *slowRecordingSinker) SendDummy() { + time.Sleep(s.delay / 2) + s.record("dummy") +} + +// TestTransactionManager_SlowSinker_NoDeadlock ensures that even with a slow sinker, +// concurrent begins do not deadlock; at worst, they serialize and take slightly longer. +func TestTransactionManager_SlowSinker_NoDeadlock(t *testing.T) { + t.Parallel() + ctx := context.Background() + sinker := newSlowRecordingSinker(5 * time.Millisecond) + updater := newMockWatermarkUpdater() + tm := NewTransactionManager(sinker, updater, 1, "task1", "db1", "table1") + + fromTs := types.TS{} + toTs1 := (&fromTs).Next() + toTs2 := (&toTs1).Next() + + require.NoError(t, tm.BeginTransaction(ctx, fromTs, toTs1)) + sinker.resetOps() + + const numGoroutines = 8 + var wg sync.WaitGroup + wg.Add(numGoroutines) + + done := make(chan struct{}) + start := time.Now() + + for i := 0; i < numGoroutines; i++ { + go func() { + defer wg.Done() + // Repeatedly attempt begin on a new range; should not deadlock + _ = tm.BeginTransaction(ctx, toTs1, toTs2) + }() + } + + go func() { + wg.Wait() + close(done) + }() + + select { + case <-done: + // Completed; assert time bound is reasonable (no deadlock) + elapsed := time.Since(start) + require.Less(t, elapsed, 500*time.Millisecond, "should not take too long; no deadlock expected") + case <-time.After(2 * time.Second): + t.Fatal("timeout indicates potential deadlock with slow sinker") + } +} diff --git a/pkg/cdc/sinker_v2.go b/pkg/cdc/sinker_v2.go index 589b29a14e2a3..b7b30bf34d093 100644 --- a/pkg/cdc/sinker_v2.go +++ b/pkg/cdc/sinker_v2.go @@ -553,20 +553,44 @@ func (s *mysqlSinker2) handleInsertDeleteBatch(ctx context.Context, cmd *Command start := time.Now() insertRows := 0 deleteRows := 0 + insertTotalRows := 0 + deleteTotalRows := 0 + insertDuplicates := 0 + deleteDuplicates := 0 if cmd.InsertAtmBatch != nil { insertRows = cmd.InsertAtmBatch.RowCount() + insertTotalRows = cmd.InsertAtmBatch.TotalRows() + insertDuplicates = cmd.InsertAtmBatch.DuplicateRows() } if cmd.DeleteAtmBatch != nil { deleteRows = cmd.DeleteAtmBatch.RowCount() + deleteTotalRows = cmd.DeleteAtmBatch.TotalRows() + deleteDuplicates = cmd.DeleteAtmBatch.DuplicateRows() } - logutil.Info("cdc.mysql_sinker2.insert_delete_batch_start", - zap.String("table", s.dbTblInfo.String()), - zap.Int("insert-rows", insertRows), - zap.Int("delete-rows", deleteRows), - zap.String("from-ts", cmd.Meta.FromTs.ToString()), - zap.String("to-ts", cmd.Meta.ToTs.ToString())) + if logutil.GetSkip1Logger().Core().Enabled(zap.DebugLevel) { + startFields := []zap.Field{ + zap.String("table", s.dbTblInfo.String()), + zap.Int("insert-rows", insertRows), + zap.Int("delete-rows", deleteRows), + zap.String("from-ts", cmd.Meta.FromTs.ToString()), + zap.String("to-ts", cmd.Meta.ToTs.ToString()), + } + if insertTotalRows != insertRows || insertDuplicates > 0 { + startFields = append(startFields, + zap.Int("insert-total-rows", insertTotalRows), + zap.Int("insert-duplicates", insertDuplicates), + ) + } + if deleteTotalRows != deleteRows || deleteDuplicates > 0 { + startFields = append(startFields, + zap.Int("delete-total-rows", deleteTotalRows), + zap.Int("delete-duplicates", deleteDuplicates), + ) + } + logutil.Debug("cdc.mysql_sinker2.insert_delete_batch_start", startFields...) + } // Build and execute INSERT SQL if cmd.InsertAtmBatch != nil && cmd.InsertAtmBatch.RowCount() > 0 { @@ -649,11 +673,27 @@ func (s *mysqlSinker2) handleInsertDeleteBatch(ctx context.Context, cmd *Command } } - logutil.Info("cdc.mysql_sinker2.insert_delete_batch_complete", - zap.String("table", s.dbTblInfo.String()), - zap.Int("insert-rows", insertRows), - zap.Int("delete-rows", deleteRows), - zap.Duration("total-duration", time.Since(start))) + if logutil.GetSkip1Logger().Core().Enabled(zap.DebugLevel) { + completeFields := []zap.Field{ + zap.String("table", s.dbTblInfo.String()), + zap.Int("insert-rows", insertRows), + zap.Int("delete-rows", deleteRows), + zap.Duration("total-duration", time.Since(start)), + } + if insertTotalRows != insertRows || insertDuplicates > 0 { + completeFields = append(completeFields, + zap.Int("insert-total-rows", insertTotalRows), + zap.Int("insert-duplicates", insertDuplicates), + ) + } + if deleteTotalRows != deleteRows || deleteDuplicates > 0 { + completeFields = append(completeFields, + zap.Int("delete-total-rows", deleteTotalRows), + zap.Int("delete-duplicates", deleteDuplicates), + ) + } + logutil.Debug("cdc.mysql_sinker2.insert_delete_batch_complete", completeFields...) + } // Clean up atomic batches after processing if cmd.InsertAtmBatch != nil { @@ -710,7 +750,7 @@ func (s *mysqlSinker2) Sink(ctx context.Context, data *DecoderOutput) { return } - if data.toTs.LE(&watermark) { + if data.toTs.LT(&watermark) { logutil.Error("cdc.mysql_sinker2.unexpected_watermark", zap.String("table", s.dbTblInfo.String()), zap.String("toTs", data.toTs.ToString()), diff --git a/pkg/cdc/sinker_v2_test.go b/pkg/cdc/sinker_v2_test.go index f836b62018441..55243c7695a7b 100644 --- a/pkg/cdc/sinker_v2_test.go +++ b/pkg/cdc/sinker_v2_test.go @@ -16,17 +16,21 @@ package cdc import ( "context" + "database/sql" + "fmt" "sync" "testing" "time" "github.com/DATA-DOG/go-sqlmock" + "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/prashantv/gostub" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -624,3 +628,584 @@ func TestMysqlSinker2_HandleInsertBatch(t *testing.T) { // Skipping complex async workflow tests for now // Will be tested through integration tests with reader + +// TestCreateMysqlSinker2 verifies CreateMysqlSinker2 handles various scenarios +func TestCreateMysqlSinker2(t *testing.T) { + tableDef := &plan.TableDef{ + Name: "test_table", + DbName: "test_db", + Cols: []*plan.ColDef{ + { + Name: "id", + Typ: plan.Type{Id: int32(types.T_int32)}, + Default: &plan.Default{ + NullAbility: true, + }, + }, + { + Name: "name", + Typ: plan.Type{Id: int32(types.T_varchar)}, + Default: &plan.Default{ + NullAbility: true, + }, + }, + }, + Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, + Name2ColIndex: map[string]int32{"id": 0, "name": 1}, + } + + t.Run("SuccessPath", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + // Mock all SQL executions - ExecSQL uses "fakeSql" as placeholder + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SourceDbName: "src_db", + SourceTblName: "src_table", + SinkDbName: "sink_db", + SinkTblName: "sink_table", + IdChanged: false, + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.NoError(t, err) + assert.NotNil(t, sinker) + assert.NoError(t, mock.ExpectationsWereMet()) + sinker.Close() + }) + + t.Run("SuccessPath_WithIdChanged", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + // Mock all SQL executions including DROP TABLE + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SourceDbName: "src_db", + SourceTblName: "src_table", + SinkDbName: "sink_db", + SinkTblName: "sink_table", + IdChanged: true, + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.NoError(t, err) + assert.NotNil(t, sinker) + assert.False(t, dbTblInfo.IdChanged, "IdChanged should be reset") + assert.NoError(t, mock.ExpectationsWereMet()) + sinker.Close() + }) + + t.Run("NewExecutorFails", func(t *testing.T) { + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return nil, moerr.NewInternalErrorNoCtx("connection failed") + }) + defer stub.Reset() + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "connection failed") + }) + + t.Run("CreateDatabaseFails", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnError(moerr.NewInternalErrorNoCtx("create database failed")) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "create database failed") + assert.NoError(t, mock.ExpectationsWereMet()) + }) + + t.Run("UseDatabaseFails", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnError(moerr.NewInternalErrorNoCtx("use database failed")) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "use database failed") + assert.NoError(t, mock.ExpectationsWereMet()) + }) + + t.Run("DropTableFails", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnError(moerr.NewInternalErrorNoCtx("drop table failed")) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + IdChanged: true, + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "drop table failed") + assert.NoError(t, mock.ExpectationsWereMet()) + }) + + t.Run("CreateTableFails", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnError(moerr.NewInternalErrorNoCtx("create table failed")) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "create table failed") + assert.NoError(t, mock.ExpectationsWereMet()) + }) + + t.Run("ClusterTableNotSupported", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + clusterTableDef := &plan.TableDef{ + Name: "cluster_table", + DbName: "test_db", + TableType: catalog.SystemClusterRel, + Cols: []*plan.ColDef{ + {Name: "id", Typ: plan.Type{Id: int32(types.T_int32)}}, + }, + Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, + Name2ColIndex: map[string]int32{"id": 0}, + } + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + clusterTableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "cluster table is not supported") + }) + + t.Run("ExternalTableNotSupported", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + externalTableDef := &plan.TableDef{ + Name: "external_table", + DbName: "test_db", + TableType: catalog.SystemExternalRel, + Cols: []*plan.ColDef{ + {Name: "id", Typ: plan.Type{Id: int32(types.T_int32)}}, + }, + Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, + Name2ColIndex: map[string]int32{"id": 0}, + } + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + externalTableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + assert.Error(t, err) + assert.Nil(t, sinker) + assert.Contains(t, err.Error(), "external table is not supported") + }) + + t.Run("ConcurrentCreation", func(t *testing.T) { + // Test concurrent creation with sequential execution to avoid stub conflicts + // Each test creates its own mock and stub, but we run them sequentially + // to avoid global stub conflicts in gostub + const numTests = 5 + errors := make([]error, numTests) + sinkers := make([]Sinker, numTests) + + for i := 0; i < numTests; i++ { + db, mock, err := sqlmock.New() + require.NoError(t, err) + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + defer db.Close() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SourceDbName: fmt.Sprintf("src_db_%d", i), + SourceTblName: fmt.Sprintf("src_table_%d", i), + SinkDbName: fmt.Sprintf("sink_db_%d", i), + SinkTblName: fmt.Sprintf("sink_table_%d", i), + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + uint64(i), + fmt.Sprintf("task-%d", i), + dbTblInfo, + nil, + tableDef, + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + errors[i] = err + sinkers[i] = sinker + + if err == nil { + assert.NoError(t, mock.ExpectationsWereMet()) + } + } + + for i := 0; i < numTests; i++ { + assert.NoError(t, errors[i], "test %d should succeed", i) + if sinkers[i] != nil { + sinkers[i].Close() + } + } + }) + + t.Run("NilTableDef", func(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer db.Close() + + stub := gostub.Stub(&OpenDbConn, func(user, password, ip string, port int, timeout string) (*sql.DB, error) { + return db, nil + }) + defer stub.Reset() + + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec("fakeSql").WillReturnResult(sqlmock.NewResult(0, 0)) + + sinkUri := UriInfo{ + SinkTyp: CDCSinkType_MySQL, + User: "test_user", + Password: "test_pass", + Ip: "127.0.0.1", + Port: 3306, + } + + dbTblInfo := &DbTableInfo{ + SinkDbName: "sink_db", + SinkTblName: "sink_table", + } + + sinker, err := CreateMysqlSinker2( + sinkUri, + 1, + "task-1", + dbTblInfo, + nil, + nil, // nil tableDef + 0, + 1*time.Second, + NewCdcActiveRoutine(), + 1024*1024, + CDCDefaultSendSqlTimeout, + ) + + // Should handle nil tableDef gracefully + if err == nil { + assert.NotNil(t, sinker) + sinker.Close() + } + }) +} diff --git a/pkg/cdc/table_change_stream.go b/pkg/cdc/table_change_stream.go index 7f58e7387f116..46c9f117f33f5 100644 --- a/pkg/cdc/table_change_stream.go +++ b/pkg/cdc/table_change_stream.go @@ -16,6 +16,9 @@ package cdc import ( "context" + "errors" + "math" + "strings" "sync" "sync/atomic" "time" @@ -86,12 +89,112 @@ type TableChangeStream struct { delCompositedPkColIdx int // State - lastError error - retryable bool - hasSucceeded atomic.Bool // Tracks if reader has successfully processed data at least once + stateMu sync.Mutex // Protects lastError, retryable, and cleanupRollbackErr for consistency + lastError error + retryable bool // Protected by stateMu, updated together with lastError + cleanupRollbackErr error // Set by processWithTxn defer if rollback fails (protected by stateMu) + hasSucceeded atomic.Bool // Tracks if reader has successfully processed data at least once + + // Retry state with exponential backoff + retryCount int // Current retry count for the same error type + lastErrorType string // Last error type for tracking consecutive errors + nextRetryDelay time.Duration // Next retry delay (exponential backoff) + lastErrorTime time.Time // When last error occurred + originalError error // Original error that triggered retry (preserved during retries) + originalErrType string // Type of original error (for error type consistency check) // Observability progressTracker *ProgressTracker + + // Watermark stall detection + watermarkStallThreshold time.Duration + noProgressWarningInterval time.Duration + lastWatermarkAdvance time.Time + noProgressSince time.Time + lastNoProgressWarning time.Time + + // Retry configuration + maxRetryCount int // Max retry count before converting to non-retryable + retryBackoffBase time.Duration // Base delay for exponential backoff + retryBackoffMax time.Duration // Max delay for exponential backoff + retryBackoffFactor float64 // Factor for exponential backoff +} + +type TableChangeStreamOption func(*tableChangeStreamOptions) + +type tableChangeStreamOptions struct { + watermarkStallThreshold time.Duration + noProgressWarningInterval time.Duration + maxRetryCount int // Max retry count before converting to non-retryable + retryBackoffBase time.Duration // Base delay for exponential backoff + retryBackoffMax time.Duration // Max delay for exponential backoff + retryBackoffFactor float64 // Factor for exponential backoff +} + +const ( + defaultWatermarkStallThreshold = time.Minute + defaultNoProgressWarningInterval = 10 * time.Second + defaultMaxRetryCount = 3 + defaultRetryBackoffBase = 200 * time.Millisecond + defaultRetryBackoffMax = 30 * time.Second + defaultRetryBackoffFactor = 2.0 +) + +func defaultTableChangeStreamOptions() *tableChangeStreamOptions { + opts := &tableChangeStreamOptions{} + opts.fillDefaults() + return opts +} + +func (opts *tableChangeStreamOptions) fillDefaults() { + if opts.watermarkStallThreshold <= 0 { + opts.watermarkStallThreshold = defaultWatermarkStallThreshold + } + if opts.noProgressWarningInterval <= 0 { + opts.noProgressWarningInterval = defaultNoProgressWarningInterval + } + if opts.maxRetryCount <= 0 { + opts.maxRetryCount = defaultMaxRetryCount + } + if opts.retryBackoffBase <= 0 { + opts.retryBackoffBase = defaultRetryBackoffBase + } + if opts.retryBackoffMax <= 0 { + opts.retryBackoffMax = defaultRetryBackoffMax + } + if opts.retryBackoffFactor <= 1.0 { + opts.retryBackoffFactor = defaultRetryBackoffFactor + } +} + +// WithWatermarkStallThreshold configures how long snapshot stagnation is tolerated before surfacing an error. +func WithWatermarkStallThreshold(threshold time.Duration) TableChangeStreamOption { + return func(opts *tableChangeStreamOptions) { + opts.watermarkStallThreshold = threshold + } +} + +// WithNoProgressWarningInterval configures how frequently warnings are emitted when snapshot timestamps stall. +func WithNoProgressWarningInterval(interval time.Duration) TableChangeStreamOption { + return func(opts *tableChangeStreamOptions) { + opts.noProgressWarningInterval = interval + } +} + +// WithMaxRetryCount configures the maximum retry count before converting retryable errors to non-retryable. +func WithMaxRetryCount(count int) TableChangeStreamOption { + return func(opts *tableChangeStreamOptions) { + opts.maxRetryCount = count + } +} + +// WithRetryBackoff configures exponential backoff parameters for retryable errors. +func WithRetryBackoff(base, max time.Duration, factor float64) TableChangeStreamOption { + return func(opts *tableChangeStreamOptions) { + opts.retryBackoffBase = base + opts.retryBackoffMax = max + opts.retryBackoffFactor = factor + } } // NewTableChangeStream creates a new table change stream @@ -111,12 +214,21 @@ var NewTableChangeStream = func( startTs, endTs types.TS, noFull bool, frequency time.Duration, + options ...TableChangeStreamOption, ) *TableChangeStream { // Parse frequency if frequency <= 0 { frequency = DefaultFrequency } + opts := defaultTableChangeStreamOptions() + for _, opt := range options { + if opt != nil { + opt(opts) + } + } + opts.fillDefaults() + // Create watermark key watermarkKey := &WatermarkKey{ AccountId: accountId, @@ -179,34 +291,46 @@ var NewTableChangeStream = func( } stream := &TableChangeStream{ - txnManager: txnManager, - dataProcessor: dataProcessor, - cnTxnClient: cnTxnClient, - cnEngine: cnEngine, - mp: mp, - packerPool: packerPool, - accountId: accountId, - taskId: taskId, - tableInfo: tableInfo, - tableDef: tableDef, - sinker: sinker, - watermarkUpdater: watermarkUpdater, - watermarkKey: watermarkKey, - tick: time.NewTicker(frequency), - frequency: frequency, - runningReaders: runningReaders, - runningReaderKey: GenDbTblKey(tableInfo.SourceDbName, tableInfo.SourceTblName), - initSnapshotSplitTxn: initSnapshotSplitTxn, - startTs: startTs, - endTs: endTs, - noFull: noFull, - insTsColIdx: insTsColIdx, - insCompositedPkColIdx: insCompositedPkColIdx, - delTsColIdx: delTsColIdx, - delCompositedPkColIdx: delCompositedPkColIdx, - progressTracker: progressTracker, + txnManager: txnManager, + dataProcessor: dataProcessor, + cnTxnClient: cnTxnClient, + cnEngine: cnEngine, + mp: mp, + packerPool: packerPool, + accountId: accountId, + taskId: taskId, + tableInfo: tableInfo, + tableDef: tableDef, + sinker: sinker, + watermarkUpdater: watermarkUpdater, + watermarkKey: watermarkKey, + tick: time.NewTicker(frequency), + frequency: frequency, + runningReaders: runningReaders, + runningReaderKey: GenDbTblKey(tableInfo.SourceDbName, tableInfo.SourceTblName), + initSnapshotSplitTxn: initSnapshotSplitTxn, + startTs: startTs, + endTs: endTs, + noFull: noFull, + insTsColIdx: insTsColIdx, + insCompositedPkColIdx: insCompositedPkColIdx, + delTsColIdx: delTsColIdx, + delCompositedPkColIdx: delCompositedPkColIdx, + progressTracker: progressTracker, + watermarkStallThreshold: opts.watermarkStallThreshold, + noProgressWarningInterval: opts.noProgressWarningInterval, + lastWatermarkAdvance: time.Now(), + // Retry configuration (stored for access in retry logic) + maxRetryCount: opts.maxRetryCount, + retryBackoffBase: opts.retryBackoffBase, + retryBackoffMax: opts.retryBackoffMax, + retryBackoffFactor: opts.retryBackoffFactor, } + tableLabel := progressTracker.tableKey() + v2.CdcTableStuckGauge.WithLabelValues(tableLabel).Set(0) + v2.CdcTableLastActivityTimestamp.WithLabelValues(tableLabel).Set(float64(time.Now().Unix())) + stream.start.Add(1) return stream } @@ -320,7 +444,21 @@ func (s *TableChangeStream) Run(ctx context.Context, ar *ActiveRoutine) { err := s.processOneRound(streamCtx, ar) if err != nil { - s.lastError = err + // Update lastError and retryable atomically for consistency + s.updateErrorState(err) + + // Check if cleanup failed with rollback error (set by processWithTxn defer) + // If so, override retryable to false even if main error is retryable + s.stateMu.Lock() + if s.cleanupRollbackErr != nil { + s.retryable = false + } + retryable := s.retryable + retryCount := s.retryCount + nextRetryDelay := s.nextRetryDelay + errType := s.lastErrorType + s.stateMu.Unlock() + s.progressTracker.SetState("error") s.progressTracker.RecordError(err) s.progressTracker.EndRound(false, err) @@ -328,11 +466,89 @@ func (s *TableChangeStream) Run(ctx context.Context, ar *ActiveRoutine) { logutil.Error( "cdc.table_stream.process_failed", zap.String("table", s.tableInfo.String()), - zap.Bool("retryable", s.retryable), + zap.Bool("retryable", retryable), + zap.Int("retry-count", retryCount), + zap.String("error-type", errType), + zap.Duration("next-retry-delay", nextRetryDelay), zap.Duration("round-duration", time.Since(roundStart)), zap.Error(err), ) - return + + // Record retry metrics + tableLabel := s.tableInfo.String() + v2.CdcTableStreamRetryCounter.WithLabelValues(tableLabel, errType, "attempted").Inc() + if nextRetryDelay > 0 { + v2.CdcTableStreamRetryDelayHistogram.WithLabelValues(tableLabel, errType).Observe(nextRetryDelay.Seconds()) + } + + // If non-retryable or exceeded max retry count, stop processing + if !retryable || retryCount > s.maxRetryCount { + // Ensure cleanup is called before stopping (processWithTxn's defer should have already called it, + // but we call it again here to be safe, especially for the case where retryCount > maxRetryCount) + // This ensures sinker errors are cleared even if we stop due to exceeding max retry count + _ = s.txnManager.EnsureCleanup(streamCtx) + + // Preserve original error for deterministic error reporting + // This ensures the error that triggered retry is preserved in lastError, + // not auxiliary errors encountered during retry attempts + s.stateMu.Lock() + originalErr := s.originalError + originalErrType := s.originalErrType + if originalErr != nil { + // Restore original error to lastError for final error reporting + s.lastError = originalErr + // Record that original error was preserved + tableLabel := s.tableInfo.String() + v2.CdcTableStreamOriginalErrorPreservedCounter.WithLabelValues(tableLabel, originalErrType).Inc() + } + s.stateMu.Unlock() + + // Record retry exhaustion + tableLabel := s.tableInfo.String() + if retryCount > s.maxRetryCount { + v2.CdcTableStreamRetryCounter.WithLabelValues(tableLabel, errType, "exhausted").Inc() + } else { + v2.CdcTableStreamRetryCounter.WithLabelValues(tableLabel, errType, "failed").Inc() + } + return + } + + // Apply exponential backoff: wait before next retry + // Use nextRetryDelay if calculated, otherwise use frequency + backoffDelay := nextRetryDelay + if backoffDelay <= 0 { + backoffDelay = s.frequency + } + + logutil.Info( + "cdc.table_stream.retry_with_backoff", + zap.String("table", s.tableInfo.String()), + zap.Int("retry-count", retryCount), + zap.String("error-type", errType), + zap.Duration("backoff-delay", backoffDelay), + ) + + // Reset tick with backoff delay + s.tick.Reset(backoffDelay) + // Continue loop to wait for next tick + continue + } + + // Success: reset retry state and use normal frequency + s.stateMu.Lock() + hadRetries := s.retryCount > 0 + lastErrType := s.lastErrorType + s.retryCount = 0 + s.lastErrorType = "" + s.nextRetryDelay = 0 + s.originalError = nil // Clear original error on success + s.originalErrType = "" // Clear original error type on success + s.stateMu.Unlock() + + // Record successful retry if there were previous retries + if hadRetries && lastErrType != "" { + tableLabel := s.tableInfo.String() + v2.CdcTableStreamRetryCounter.WithLabelValues(tableLabel, lastErrType, "succeeded").Inc() } logutil.Debug( @@ -385,13 +601,19 @@ func (s *TableChangeStream) cleanup(ctx context.Context) { } // Persist error message if any - if s.lastError != nil { + // Read lastError and retryable atomically for consistency + s.stateMu.Lock() + lastError := s.lastError + retryable := s.retryable + s.stateMu.Unlock() + + if lastError != nil { errorCtx := &ErrorContext{ - IsRetryable: s.retryable, - IsPauseOrCancel: IsPauseOrCancelError(s.lastError.Error()), + IsRetryable: retryable, + IsPauseOrCancel: IsPauseOrCancelError(lastError.Error()), } - if err := s.watermarkUpdater.UpdateWatermarkErrMsg(ctx, s.watermarkKey, s.lastError.Error(), errorCtx); err != nil { + if err := s.watermarkUpdater.UpdateWatermarkErrMsg(ctx, s.watermarkKey, lastError.Error(), errorCtx); err != nil { logutil.Error( "cdc.table_stream.update_watermark_errmsg_failed", zap.String("table", s.tableInfo.String()), @@ -478,6 +700,11 @@ func (s *TableChangeStream) forceNextInterval(wait time.Duration) { // processOneRound processes one round of change streaming func (s *TableChangeStream) processOneRound(ctx context.Context, ar *ActiveRoutine) error { + // Clear previous cleanup rollback error + s.stateMu.Lock() + s.cleanupRollbackErr = nil + s.stateMu.Unlock() + // Create transaction operator txnOp, err := GetTxnOp(ctx, s.cnEngine, s.cnTxnClient, "tableChangeStream") if err != nil { @@ -498,16 +725,351 @@ func (s *TableChangeStream) processOneRound(ctx context.Context, ar *ActiveRouti defer put.Put() // Process with transaction + // Note: processWithTxn's defer will set cleanupRollbackErr if rollback fails err = s.processWithTxn(ctx, txnOp, packer, ar) + // Check if cleanup failed with rollback error (set by processWithTxn's defer) + s.stateMu.Lock() + cleanupRollbackErr := s.cleanupRollbackErr + s.stateMu.Unlock() + // Handle StaleRead error if moerr.IsMoErrCode(err, moerr.ErrStaleRead) { - return s.handleStaleRead(ctx, txnOp) + recoveryErr := s.handleStaleRead(ctx, txnOp) + // If recovery succeeded (nil), mark as retryable and continue + if recoveryErr == nil { + // Recovery succeeded - mark as retryable for scheduler to retry + s.stateMu.Lock() + s.retryable = true + s.stateMu.Unlock() + return nil // Swallow error, continue processing + } + // Recovery failed - return error (will be marked non-retryable in determineRetryable) + return recoveryErr + } + + // If cleanup failed with rollback error, mark as non-retryable but return original error + // (test expects original error to be returned, but retryable should be false) + if cleanupRollbackErr != nil { + // Update error state to mark as non-retryable, but keep original error + s.stateMu.Lock() + s.retryable = false + s.stateMu.Unlock() + // Return original error (not cleanup error) as expected by tests + return err } return err } +// updateErrorState updates lastError and retryable atomically +// Also tracks retry count and error type for exponential backoff +// Design: Preserves original error during retries to ensure deterministic error reporting +func (s *TableChangeStream) updateErrorState(err error) { + if err == nil { + return + } + retryable := s.determineRetryable(err) + errType := s.classifyErrorType(err) + + s.stateMu.Lock() + defer s.stateMu.Unlock() + + // If retryable is already true (e.g., from successful StaleRead recovery), + // and new error is a control signal (pause/cancel), preserve the retryable state. + // This ensures that successful recovery states are not overwritten by control signals. + if s.retryable && IsPauseOrCancelError(err.Error()) { + // Preserve retryable = true, but still update lastError + s.lastError = err + return + } + + // Preserve original error during retries to ensure deterministic error reporting + // Priority order: + // 1. Check if it's an auxiliary error first (should never replace original, even if non-retryable) + // 2. If no original error exists, set as original + // 3. If non-retryable and not auxiliary, replace original (fatal error takes precedence) + // 4. If different error type (new primary error), replace original + isAuxiliaryError := s.isAuxiliaryError(err, errType) + if isAuxiliaryError { + // Auxiliary error: preserve original error, don't update originalError + // But still update lastError for logging and state tracking + s.lastError = err + s.retryable = retryable + // Don't update retry count for auxiliary errors + // Record auxiliary error metric + tableLabel := s.tableInfo.String() + v2.CdcTableStreamAuxiliaryErrorCounter.WithLabelValues(tableLabel, errType).Inc() + return + } + + if s.originalError == nil { + // First error: set as original + s.originalError = err + s.originalErrType = errType + } else if !retryable { + // Non-retryable error (and not auxiliary): replace original (fatal error takes precedence) + s.originalError = err + s.originalErrType = errType + } else if s.originalErrType != errType { + // Different error type: new primary error, replace original + s.originalError = err + s.originalErrType = errType + s.retryCount = 1 + s.lastErrorType = errType + s.lastErrorTime = time.Now() + s.nextRetryDelay = s.calculateBackoffDelay(errType, s.retryCount) + s.lastError = err + s.retryable = retryable + return + } + // Same error type as original: continue retry with same original error + + // Update error state + s.lastError = err + s.retryable = retryable + + // Track retry count and error type for exponential backoff + if retryable { + // If same error type, increment retry count + if s.lastErrorType == errType { + s.retryCount++ + } else { + // Different error type, reset retry count + s.retryCount = 1 + s.lastErrorType = errType + } + s.lastErrorTime = time.Now() + + // Calculate next retry delay based on error type and retry count + s.nextRetryDelay = s.calculateBackoffDelay(errType, s.retryCount) + } else { + // Non-retryable error, reset retry state + s.retryCount = 0 + s.lastErrorType = "" + s.nextRetryDelay = 0 + } +} + +// isAuxiliaryError checks if an error is an auxiliary error that occurs during cleanup/retry +// and should not replace the original error. Examples: GetFromCache failures during EnsureCleanup +func (s *TableChangeStream) isAuxiliaryError(err error, errType string) bool { + if err == nil { + return false + } + errMsg := err.Error() + + // Errors that occur during cleanup/auxiliary operations should not replace original error + // These are typically infrastructure errors that happen during retry attempts + auxiliaryPatterns := []string{ + "get_from_cache", + "cache error", + "ensure_cleanup", + } + + for _, pattern := range auxiliaryPatterns { + if strings.Contains(strings.ToLower(errMsg), pattern) { + return true + } + } + + return false +} + +// determineRetryable determines if an error is retryable based on error type and context +func (s *TableChangeStream) determineRetryable(err error) bool { + if err == nil { + return false + } + + errMsg := err.Error() + + // Control signals (pause/cancel) are not retryable + if IsPauseOrCancelError(errMsg) { + return false + } + + // Check for MatrixOne system/network errors first (before string matching) + // These errors indicate temporary system unavailability and should be retryable + if moerr.IsMoErrCode(err, moerr.ErrRPCTimeout) || + moerr.IsMoErrCode(err, moerr.ErrNoAvailableBackend) || + moerr.IsMoErrCode(err, moerr.ErrBackendCannotConnect) || + moerr.IsMoErrCode(err, moerr.ErrTNShardNotFound) || + moerr.IsMoErrCode(err, moerr.ErrRpcError) || + moerr.IsMoErrCode(err, moerr.ErrClientClosed) || + moerr.IsMoErrCode(err, moerr.ErrBackendClosed) { + return true + } + + // Check for context timeout errors (system/network issues) + if errors.Is(err, context.DeadlineExceeded) { + return true + } + + // StaleRead errors are retryable if recovery is possible + if moerr.IsMoErrCode(err, moerr.ErrStaleRead) { + // If startTs is set and noFull is false, StaleRead is fatal (handled in handleStaleRead) + // If handleStaleRead returns nil, recovery succeeded (retryable) + // If handleStaleRead returns error, recovery failed (non-retryable) + return false // Will be updated in handleStaleRead, but default to false for safety + } + + // Table relation errors (table truncated, etc.) are retryable + if strings.Contains(errMsg, "relation") || strings.Contains(errMsg, "truncated") { + return true + } + + // Watermark stall errors are retryable + if strings.Contains(errMsg, "stuck") || strings.Contains(errMsg, "stall") { + return true + } + + // Commit failures are retryable (usually transient network issues) + if strings.Contains(errMsg, "commit") { + return true + } + + // Connection issues are retryable (check before begin/rollback to catch network errors) + if strings.Contains(errMsg, "connection") || strings.Contains(errMsg, "timeout") || + strings.Contains(errMsg, "network") || strings.Contains(errMsg, "unavailable") || + strings.Contains(errMsg, "rpc") || strings.Contains(errMsg, "backend") || + strings.Contains(errMsg, "shard") { + return true + } + + // Begin failures: retryable if network-related, non-retryable if state-related + if strings.Contains(errMsg, "begin") { + // Network-related begin failures are retryable + if strings.Contains(errMsg, "connection") || strings.Contains(errMsg, "timeout") || + strings.Contains(errMsg, "network") || strings.Contains(errMsg, "unavailable") || + strings.Contains(errMsg, "rpc") || strings.Contains(errMsg, "backend") { + return true + } + // State-related begin failures (e.g., "transaction already active") are non-retryable + return false + } + + // Rollback failures are non-retryable (system state may be inconsistent) + // These are handled by default case (non-retryable) + + // Simple "sinker error" without context (usually fatal, occurs before transaction starts) + // is non-retryable. Only retryable if it has more context indicating transient issues. + if strings.Contains(errMsg, "sinker") { + // If it's just "sinker error" without more context, it's likely fatal + // But if it has context like "circuit breaker", it might be retryable + if strings.Contains(errMsg, "circuit") || strings.Contains(errMsg, "timeout") { + return true + } + // Default: simple sinker error is non-retryable (fatal) + return false + } + + // Default: non-retryable for unknown errors + return false +} + +// classifyErrorType classifies error into categories for different retry strategies +func (s *TableChangeStream) classifyErrorType(err error) string { + if err == nil { + return "" + } + + errMsg := err.Error() + + // Network/system errors - fast retry with shorter backoff + if moerr.IsMoErrCode(err, moerr.ErrRPCTimeout) || + moerr.IsMoErrCode(err, moerr.ErrNoAvailableBackend) || + moerr.IsMoErrCode(err, moerr.ErrBackendCannotConnect) || + moerr.IsMoErrCode(err, moerr.ErrTNShardNotFound) || + moerr.IsMoErrCode(err, moerr.ErrRpcError) || + moerr.IsMoErrCode(err, moerr.ErrClientClosed) || + moerr.IsMoErrCode(err, moerr.ErrBackendClosed) || + errors.Is(err, context.DeadlineExceeded) || + strings.Contains(errMsg, "connection") || + strings.Contains(errMsg, "timeout") || + strings.Contains(errMsg, "network") || + strings.Contains(errMsg, "unavailable") || + strings.Contains(errMsg, "rpc") || + strings.Contains(errMsg, "backend") { + return "network" + } + + // Commit errors - medium retry with moderate backoff + if strings.Contains(errMsg, "commit") { + return "commit" + } + + // StaleRead errors - fast retry (usually resolves quickly) + if moerr.IsMoErrCode(err, moerr.ErrStaleRead) { + return "stale_read" + } + + // Table relation errors - slow retry (may need table recreation) + if strings.Contains(errMsg, "relation") || strings.Contains(errMsg, "truncated") { + return "table_relation" + } + + // Watermark stall errors - slow retry (may need time for data availability) + if strings.Contains(errMsg, "stuck") || strings.Contains(errMsg, "stall") { + return "watermark_stall" + } + + // Sinker errors with context - medium retry + if strings.Contains(errMsg, "sinker") { + if strings.Contains(errMsg, "circuit") || strings.Contains(errMsg, "timeout") { + return "sinker_transient" + } + return "sinker" + } + + // Default category + return "unknown" +} + +// calculateBackoffDelay calculates exponential backoff delay based on error type and retry count +// Different error types use different backoff strategies +func (s *TableChangeStream) calculateBackoffDelay(errType string, retryCount int) time.Duration { + base := s.retryBackoffBase + max := s.retryBackoffMax + factor := s.retryBackoffFactor + + // Adjust base delay based on error type + switch errType { + case "network": + // Network errors: fast retry (shorter base delay) + base = base / 2 // 100ms default + max = max / 2 // 15s default + case "stale_read": + // StaleRead errors: very fast retry (usually resolves quickly) + base = base / 4 // 50ms default + max = max / 4 // 7.5s default + case "commit": + // Commit errors: medium retry (standard backoff) + // Use default values + case "table_relation", "watermark_stall": + // Table/watermark errors: slow retry (longer backoff, may need time) + base = base * 2 // 400ms default + max = max * 2 // 60s default + case "sinker_transient": + // Sinker transient errors: medium retry + // Use default values + default: + // Unknown errors: standard backoff + // Use default values + } + + // Calculate exponential backoff: base * (factor ^ (retryCount - 1)) + delay := float64(base) * math.Pow(factor, float64(retryCount-1)) + result := time.Duration(delay) + + // Cap at max + if result > max { + result = max + } + + return result +} + // clearErrorOnFirstSuccess clears error message on first successful data processing // This preserves lazy batch processing design (asynchronous, eventual consistency) func (s *TableChangeStream) clearErrorOnFirstSuccess(ctx context.Context) { @@ -532,13 +1094,12 @@ func (s *TableChangeStream) processWithTxn( txnOp client.TxnOperator, packer *types.Packer, ar *ActiveRoutine, -) error { +) (err error) { // Get relation s.progressTracker.SetState("reading") _, _, rel, err := GetRelationById(ctx, s.cnEngine, txnOp, s.tableInfo.SourceTblId) if err != nil { - // Table may have been truncated - s.retryable = true + // Table may have been truncated - retryable will be determined in processOneRound return err } @@ -567,6 +1128,12 @@ func (s *TableChangeStream) processWithTxn( toTs = s.endTs } + if !toTs.GT(&fromTs) { + return s.handleSnapshotNoProgress(ctx, fromTs, toTs) + } + + s.resetWatermarkStallState() + // Start tracking this round s.progressTracker.StartRound(fromTs, toTs) s.progressTracker.SetTargetWatermark(toTs) @@ -620,6 +1187,13 @@ func (s *TableChangeStream) processWithTxn( zap.String("table", s.tableInfo.String()), zap.Error(cleanupErr), ) + // Rollback failure makes the error non-retryable (system state may be inconsistent) + // Store it for processOneRound to return + if strings.Contains(cleanupErr.Error(), "rollback") { + s.stateMu.Lock() + s.cleanupRollbackErr = cleanupErr + s.stateMu.Unlock() + } } } }() @@ -697,6 +1271,7 @@ func (s *TableChangeStream) processWithTxn( s.progressTracker.EndRound(true, nil) s.progressTracker.UpdateWatermark(toTs) s.progressTracker.RecordTransaction() + s.onWatermarkAdvanced() logutil.Debug( "cdc.table_stream.round_complete", @@ -720,11 +1295,74 @@ func (s *TableChangeStream) processWithTxn( } } +func (s *TableChangeStream) handleSnapshotNoProgress(ctx context.Context, fromTs, snapshotTs types.TS) error { + now := time.Now() + tableLabel := s.progressTracker.tableKey() + + s.progressTracker.RecordRetry() + v2.CdcTableNoProgressCounter.WithLabelValues(tableLabel).Inc() + v2.CdcTableLastActivityTimestamp.WithLabelValues(tableLabel).Set(float64(now.Unix())) + + if s.noProgressSince.IsZero() { + s.noProgressSince = now + } + + stalledFor := now.Sub(s.noProgressSince) + v2.CdcTableStuckGauge.WithLabelValues(tableLabel).Set(1) + + if s.lastNoProgressWarning.IsZero() || + now.Sub(s.lastNoProgressWarning) >= s.noProgressWarningInterval { + logutil.Warn( + "cdc.table_stream.snapshot_not_advanced", + zap.String("table", s.tableInfo.String()), + zap.String("from-ts", fromTs.ToString()), + zap.String("snapshot-ts", snapshotTs.ToString()), + zap.Duration("stall-duration", stalledFor), + zap.Duration("threshold", s.watermarkStallThreshold), + ) + s.lastNoProgressWarning = now + } + + if stalledFor >= s.watermarkStallThreshold { + err := moerr.NewInternalErrorf( + ctx, + "CDC tableChangeStream %s snapshot timestamp stuck for %v (threshold %v)", + s.tableInfo.String(), + stalledFor, + s.watermarkStallThreshold, + ) + // Update error state atomically (for both direct calls and through processOneRound) + s.updateErrorState(err) + return err + } + + return nil +} + +func (s *TableChangeStream) resetWatermarkStallState() { + if s.noProgressSince.IsZero() && s.lastNoProgressWarning.IsZero() { + return + } + + s.noProgressSince = time.Time{} + s.lastNoProgressWarning = time.Time{} + v2.CdcTableStuckGauge.WithLabelValues(s.progressTracker.tableKey()).Set(0) +} + +func (s *TableChangeStream) onWatermarkAdvanced() { + now := time.Now() + s.lastWatermarkAdvance = now + s.resetWatermarkStallState() + v2.CdcTableLastActivityTimestamp.WithLabelValues( + s.progressTracker.tableKey(), + ).Set(float64(now.Unix())) +} + // handleStaleRead handles StaleRead error by resetting watermark +// Returns error with retryable flag determined by recoverability func (s *TableChangeStream) handleStaleRead(ctx context.Context, txnOp client.TxnOperator) error { - // If startTs is set and noFull is false, StaleRead is fatal + // If startTs is set and noFull is false, StaleRead is fatal (non-retryable) if !s.noFull && !s.startTs.IsEmpty() { - s.retryable = false return moerr.NewInternalErrorf( ctx, "CDC tableChangeStream %s stale read with startTs %s set, cannot recover", @@ -750,6 +1388,13 @@ func (s *TableChangeStream) handleStaleRead(ctx context.Context, txnOp client.Tx zap.String("watermark", watermark.ToString()), zap.Error(err), ) + // Recovery failed - non-retryable + return moerr.NewInternalErrorf( + ctx, + "CDC tableChangeStream %s stale read recovery failed to update watermark: %v", + s.tableInfo.String(), + err, + ) } logutil.Info( @@ -761,11 +1406,18 @@ func (s *TableChangeStream) handleStaleRead(ctx context.Context, txnOp client.Tx // Force next interval s.forceNextInterval(DefaultFrequency) - // Mark as retryable and swallow error - s.retryable = true + // Recovery succeeded - return nil to swallow error + // retryable will be set to true in processOneRound return nil } +// GetRetryable returns the retryable flag in a thread-safe way +func (s *TableChangeStream) GetRetryable() bool { + s.stateMu.Lock() + defer s.stateMu.Unlock() + return s.retryable +} + // Close closes the change stream func (s *TableChangeStream) Close() { s.cancelRun() diff --git a/pkg/cdc/table_change_stream_test.go b/pkg/cdc/table_change_stream_test.go index c4eec29174b94..69e61069f3425 100644 --- a/pkg/cdc/table_change_stream_test.go +++ b/pkg/cdc/table_change_stream_test.go @@ -16,6 +16,8 @@ package cdc import ( "context" + "errors" + "strings" "sync" "sync/atomic" "testing" @@ -25,20 +27,25 @@ import ( "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/fileservice" + lock "github.com/matrixorigin/matrixone/pkg/pb/lock" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" + txnpb "github.com/matrixorigin/matrixone/pkg/pb/txn" "github.com/matrixorigin/matrixone/pkg/txn/client" + "github.com/matrixorigin/matrixone/pkg/txn/rpc" + v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/prashantv/gostub" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestNewTableChangeStream(t *testing.T) { - mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) - assert.NoError(t, err) - defer mpool.DeleteMPool(mp) - +// Helper function to create a test stream with minimal setup +func createTestStream(mp *mpool.MPool, tableInfo *DbTableInfo, opts ...TableChangeStreamOption) *TableChangeStream { sinker := &mockDataProcessorSinker{mockSinker: &mockSinker{}} updater := newMockWatermarkUpdater() packerPool := fileservice.NewPool( @@ -51,158 +58,265 @@ func TestNewTableChangeStream(t *testing.T) { tableDef := &plan.TableDef{ Cols: []*plan.ColDef{ {Name: "id"}, - {Name: "name"}, {Name: "ts"}, }, Pkey: &plan.PrimaryKeyDef{ Names: []string{"id"}, }, Name2ColIndex: map[string]int32{ - "id": 0, - "name": 1, - "ts": 2, + "id": 0, + "ts": 1, }, } - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "table1", - SourceTblId: 1, + return NewTableChangeStream( + nil, nil, mp, packerPool, + 1, "task1", tableInfo, sinker, updater, tableDef, + false, &sync.Map{}, types.TS{}, types.TS{}, false, 0, + opts..., + ) +} + +type watermarkUpdaterStub struct { + mu sync.Mutex + watermarks map[string]types.TS + errMsgs []string + updateErrFn func(call int) error + removeErr error + skipRemove bool + getFromCacheHook func() error + updateCalls atomic.Int32 + updateNotifies chan struct{} +} + +func newWatermarkUpdaterStub() *watermarkUpdaterStub { + return &watermarkUpdaterStub{ + watermarks: make(map[string]types.TS), + errMsgs: make([]string, 0), } +} - runningReaders := &sync.Map{} - startTs := types.TS{} - endTs := (&startTs).Next() +func (m *watermarkUpdaterStub) withUpdateError(fn func(call int) error) *watermarkUpdaterStub { + m.updateErrFn = fn + return m +} - stream := NewTableChangeStream( - nil, // cnTxnClient - nil, // cnEngine - mp, - packerPool, - 1, // accountId - "task1", - tableInfo, - sinker, - updater, - tableDef, - false, // initSnapshotSplitTxn - runningReaders, - startTs, - endTs, - false, // noFull - 200*time.Millisecond, - ) +func (m *watermarkUpdaterStub) RemoveCachedWM(ctx context.Context, key *WatermarkKey) error { + if m.skipRemove { + return nil + } + if err := m.removeErr; err != nil { + return err + } + m.mu.Lock() + delete(m.watermarks, m.keyString(key)) + m.mu.Unlock() + return nil +} - assert.NotNil(t, stream) - assert.Equal(t, mp, stream.mp) - assert.Equal(t, sinker, stream.sinker) - assert.Equal(t, updater, stream.watermarkUpdater) - assert.Equal(t, uint64(1), stream.accountId) - assert.Equal(t, "task1", stream.taskId) - assert.Equal(t, tableInfo, stream.tableInfo) - assert.Equal(t, tableDef, stream.tableDef) - assert.NotNil(t, stream.txnManager) - assert.NotNil(t, stream.dataProcessor) - assert.Equal(t, 200*time.Millisecond, stream.frequency) - assert.Equal(t, 2, stream.insTsColIdx) // len(Cols)-1 - assert.Equal(t, 0, stream.insCompositedPkColIdx) // single PK - assert.Equal(t, 1, stream.delTsColIdx) - assert.Equal(t, 0, stream.delCompositedPkColIdx) -} - -func TestNewTableChangeStream_CompositePK(t *testing.T) { - mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) - assert.NoError(t, err) - defer mpool.DeleteMPool(mp) +func (m *watermarkUpdaterStub) UpdateWatermarkErrMsg(ctx context.Context, key *WatermarkKey, errMsg string, errorCtx *ErrorContext) error { + m.mu.Lock() + m.errMsgs = append(m.errMsgs, errMsg) + m.mu.Unlock() + return nil +} - sinker := &mockDataProcessorSinker{mockSinker: &mockSinker{}} - updater := newMockWatermarkUpdater() - packerPool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) {}, - ) +func (m *watermarkUpdaterStub) GetFromCache(ctx context.Context, key *WatermarkKey) (types.TS, error) { + if hook := m.getFromCacheHook; hook != nil { + if err := hook(); err != nil { + return types.TS{}, err + } + } + m.mu.Lock() + defer m.mu.Unlock() + ts, ok := m.watermarks[m.keyString(key)] + if !ok { + return types.TS{}, moerr.NewInternalError(ctx, "watermark not found") + } + return ts, nil +} - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "id"}, - {Name: "name"}, - {Name: "cpk"}, // Composite PK column - {Name: "ts"}, - }, - Pkey: &plan.PrimaryKeyDef{ - Names: []string{"id", "name"}, // Composite PK - }, - Name2ColIndex: map[string]int32{ - "id": 0, - "name": 1, - "cpk": 2, - "ts": 3, - }, +func (m *watermarkUpdaterStub) setGetFromCacheHook(fn func() error) { + m.getFromCacheHook = fn +} + +func (m *watermarkUpdaterStub) setSkipRemove(skip bool) { + m.skipRemove = skip +} + +func (m *watermarkUpdaterStub) GetOrAddCommitted(ctx context.Context, key *WatermarkKey, watermark *types.TS) (types.TS, error) { + m.mu.Lock() + defer m.mu.Unlock() + keyStr := m.keyString(key) + if ts, ok := m.watermarks[keyStr]; ok { + return ts, nil + } + m.watermarks[keyStr] = *watermark + return *watermark, nil +} + +func (m *watermarkUpdaterStub) UpdateWatermarkOnly(ctx context.Context, key *WatermarkKey, watermark *types.TS) error { + call := int(m.updateCalls.Add(1)) + if m.updateNotifies != nil { + select { + case m.updateNotifies <- struct{}{}: + default: + } + } + if m.updateErrFn != nil { + if err := m.updateErrFn(call); err != nil { + return err + } + } + m.mu.Lock() + m.watermarks[m.keyString(key)] = *watermark + m.mu.Unlock() + return nil +} + +func (m *watermarkUpdaterStub) IsCircuitBreakerOpen(key *WatermarkKey) bool { + return false +} + +func (m *watermarkUpdaterStub) GetCommitFailureCount(key *WatermarkKey) uint32 { + return 0 +} + +func (m *watermarkUpdaterStub) keyString(key *WatermarkKey) string { + if key == nil { + return "" } + return key.TaskId + ":" + key.DBName + ":" + key.TableName +} + +func readGaugeValue(t *testing.T, gauge prometheus.Gauge) float64 { + t.Helper() + var metric dto.Metric + require.NoError(t, gauge.Write(&metric)) + return metric.GetGauge().GetValue() +} + +func readCounterValue(t *testing.T, counter prometheus.Counter) float64 { + t.Helper() + var metric dto.Metric + require.NoError(t, counter.Write(&metric)) + return metric.GetCounter().GetValue() +} + +func TestTableChangeStream_HandleSnapshotNoProgress_WarningAndReset(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "table1", - SourceTblId: 1, + SourceDbName: "db_warn", + SourceTblName: "t_warn", } - stream := NewTableChangeStream( - nil, nil, mp, packerPool, - 1, "task1", tableInfo, sinker, updater, tableDef, - false, &sync.Map{}, types.TS{}, types.TS{}, false, 0, + stream := createTestStream( + mp, + tableInfo, + WithWatermarkStallThreshold(time.Minute), + WithNoProgressWarningInterval(time.Nanosecond), ) - assert.NotNil(t, stream) - assert.Equal(t, 3, stream.insTsColIdx) // len(Cols)-1 - assert.Equal(t, 2, stream.insCompositedPkColIdx) // Composite PK col -} + tableLabel := stream.progressTracker.tableKey() + beforeCounter := readCounterValue(t, v2.CdcTableNoProgressCounter.WithLabelValues(tableLabel)) + beforeStuck := readGaugeValue(t, v2.CdcTableStuckGauge.WithLabelValues(tableLabel)) + assert.Equal(t, 0.0, beforeStuck) -func TestTableChangeStream_ForceNextInterval(t *testing.T) { - mp, err := mpool.NewMPool("test", 0, mpool.NoFixed) + fromTs := types.BuildTS(100, 0) + err := stream.handleSnapshotNoProgress(context.Background(), fromTs, fromTs) assert.NoError(t, err) - defer mpool.DeleteMPool(mp) + assert.False(t, stream.noProgressSince.IsZero(), "noProgressSince should be initialized") - stream := createTestStream(mp, &DbTableInfo{}) + afterCounter := readCounterValue(t, v2.CdcTableNoProgressCounter.WithLabelValues(tableLabel)) + assert.Equal(t, beforeCounter+1, afterCounter) - assert.False(t, stream.force) + afterStuck := readGaugeValue(t, v2.CdcTableStuckGauge.WithLabelValues(tableLabel)) + assert.Equal(t, 1.0, afterStuck) - stream.forceNextInterval(100 * time.Millisecond) + stream.onWatermarkAdvanced() + assert.True(t, stream.noProgressSince.IsZero(), "noProgressSince should reset after progress") + assert.True(t, stream.lastNoProgressWarning.IsZero(), "last warning timestamp should reset") - assert.True(t, stream.force) + resetStuck := readGaugeValue(t, v2.CdcTableStuckGauge.WithLabelValues(tableLabel)) + assert.Equal(t, 0.0, resetStuck) } -// Helper function to create a test stream with minimal setup -func createTestStream(mp *mpool.MPool, tableInfo *DbTableInfo) *TableChangeStream { - sinker := &mockDataProcessorSinker{mockSinker: &mockSinker{}} - updater := newMockWatermarkUpdater() - packerPool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) {}, +func TestTableChangeStream_HandleSnapshotNoProgress_ThresholdExceeded(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + tableInfo := &DbTableInfo{ + SourceDbName: "db_err", + SourceTblName: "t_err", + } + + stream := createTestStream( + mp, + tableInfo, + WithWatermarkStallThreshold(10*time.Millisecond), + WithNoProgressWarningInterval(time.Nanosecond), ) - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "id"}, - {Name: "ts"}, - }, - Pkey: &plan.PrimaryKeyDef{ - Names: []string{"id"}, - }, - Name2ColIndex: map[string]int32{ - "id": 0, - "ts": 1, - }, + stream.noProgressSince = time.Now().Add(-2 * stream.watermarkStallThreshold) + + fromTs := types.BuildTS(200, 0) + err := stream.handleSnapshotNoProgress(context.Background(), fromTs, fromTs) + assert.Error(t, err) + require.True(t, stream.GetRetryable(), "stalled snapshot should mark stream retryable") + assert.Contains(t, err.Error(), "snapshot timestamp stuck") + + // Clean up metric state for subsequent tests + stream.onWatermarkAdvanced() +} + +func TestTableChangeStream_HandleSnapshotNoProgress_WarningThrottle(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + tableInfo := &DbTableInfo{ + SourceDbName: "db_throttle", + SourceTblName: "t_throttle", } - return NewTableChangeStream( - nil, nil, mp, packerPool, - 1, "task1", tableInfo, sinker, updater, tableDef, - false, &sync.Map{}, types.TS{}, types.TS{}, false, 0, + const interval = 50 * time.Millisecond + + stream := createTestStream( + mp, + tableInfo, + WithWatermarkStallThreshold(time.Minute), + WithNoProgressWarningInterval(interval), ) + + fromTs := types.BuildTS(300, 0) + + err := stream.handleSnapshotNoProgress(context.Background(), fromTs, fromTs) + require.NoError(t, err) + require.False(t, stream.lastNoProgressWarning.IsZero(), "first warning timestamp should be recorded") + firstWarning := stream.lastNoProgressWarning + + err = stream.handleSnapshotNoProgress(context.Background(), fromTs, fromTs) + require.NoError(t, err, "second invocation before interval should still be treated as warning") + assert.Equal(t, firstWarning, stream.lastNoProgressWarning, "warning timestamp should not advance before interval elapses") + + deadline := firstWarning.Add(interval) + wait := time.Until(deadline) + if wait > 0 { + timer := time.NewTimer(wait) + defer timer.Stop() + select { + case <-timer.C: + case <-time.After(20 * interval): + t.Fatalf("warning interval did not elapse within timeout") + } + } + + err = stream.handleSnapshotNoProgress(context.Background(), fromTs, fromTs) + require.NoError(t, err) + assert.True(t, stream.lastNoProgressWarning.After(firstWarning), "warning timestamp should advance after interval") + + stream.onWatermarkAdvanced() } // ============================================================================ @@ -210,697 +324,2104 @@ func createTestStream(mp *mpool.MPool, tableInfo *DbTableInfo) *TableChangeStrea // Note: Uses testChangesHandle from reader_test.go // ============================================================================ -// Test Run() integration with mocked dependencies -func TestTableChangeStream_Run_Integration(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() +// Test Run() with duplicate reader (should exit immediately) +func TestTableChangeStream_Run_DuplicateReader(t *testing.T) { + runningReaders := &sync.Map{} - mp := mpool.MustNewZero() - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, - ) + h1 := newTableStreamHarness(t, withHarnessRunningReaders(runningReaders)) + defer h1.Close() - var packer *types.Packer - put := pool.Get(&packer) - defer put.Put() - - // Setup stubs - stub1 := gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - return nil, nil - }) - defer stub1.Reset() - - stub2 := gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}) - defer stub2.Reset() - - stub3 := gostub.Stub(&GetTxn, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator) error { - return nil - }) - defer stub3.Reset() - - stub4 := gostub.Stub(&GetRelationById, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator, tableId uint64) (dbName string, tblName string, rel engine.Relation, err error) { - return "", "", nil, nil - }) - defer stub4.Reset() - - stub5 := gostub.Stub(&GetSnapshotTS, - func(txnOp client.TxnOperator) timestamp.Timestamp { - return timestamp.Timestamp{ - PhysicalTime: 100, - LogicalTime: 0, - } - }) - defer stub5.Reset() + ready := make(chan struct{}) + h1.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return &blockingChangesHandle{ready: ready}, nil + }) - stub6 := gostub.Stub(&CollectChanges, - func(ctx context.Context, rel engine.Relation, fromTs, toTs types.TS, mp *mpool.MPool) (engine.ChangesHandle, error) { - return newTestChangesHandle("test", "t1", 20, 23, types.TS{}, mp, packer), nil - }) - defer stub6.Reset() + ar1 := h1.NewActiveRoutine() + errCh1, done1 := h1.RunStreamAsync(ar1) + defer done1() + + require.Eventually(t, func() bool { + select { + case <-ready: + return true + default: + _, ok := runningReaders.Load(h1.Stream().runningReaderKey) + return ok + } + }, time.Second, 10*time.Millisecond, "first stream should register as running") - stub7 := gostub.Stub(&EnterRunSql, func(client.TxnOperator) {}) - defer stub7.Reset() + stored, ok := runningReaders.Load(h1.Stream().runningReaderKey) + require.True(t, ok, "first stream should occupy running readers slot") + require.Equal(t, h1.Stream(), stored) - stub8 := gostub.Stub(&ExitRunSql, func(client.TxnOperator) {}) - defer stub8.Reset() + h2 := newTableStreamHarness(t, withHarnessRunningReaders(runningReaders)) + defer h2.Close() - // Create watermark updater - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() + ar2 := h2.NewActiveRoutine() + err := h2.RunStream(ar2) + require.NoError(t, err, "duplicate reader should exit gracefully without error") - // Create table definition - // Column order MUST match batch layout: user cols | cpk | commit-ts - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "a"}, // User column - {Name: "b"}, // User column - {Name: "cpk"}, // Composite PK column - {Name: "ts"}, // Commit timestamp (MUST be last) - }, - Pkey: &plan.PrimaryKeyDef{ - Names: []string{"a", "b"}, - }, - Name2ColIndex: map[string]int32{ - "a": 0, - "b": 1, - "cpk": 2, - "ts": 3, - }, + stored, ok = runningReaders.Load(h1.Stream().runningReaderKey) + require.True(t, ok, "running reader entry should remain owned by first stream") + require.Equal(t, h1.Stream(), stored, "duplicate reader must not replace existing entry") + + done1() + + var runErr error + select { + case runErr = <-errCh1: + case <-time.After(2 * time.Second): + t.Fatal("first stream did not exit after cancellation") } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) + } +} - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, +// Integration: commit failure triggers EnsureCleanup rollback, then recovery succeeds +func TestTableChangeStream_CommitFailure_EnsureCleanup_ThenRecover(t *testing.T) { + updaterStub := newWatermarkUpdaterStub() + noopStop := func() {} + h := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessFrequency(1*time.Millisecond), + ) + defer h.Close() + + // Prepare initial watermark to a low value + key := h.Stream().txnManager.watermarkKey + initial := types.BuildTS(1, 0) + _, _ = updaterStub.GetOrAddCommitted(h.Context(), key, &initial) + + // First run: snapshot + tail_done, inject commit error + snap1 := createTestBatch(t, h.MP(), types.BuildTS(2, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: snap1, hint: engine.ChangesHandle_Snapshot}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + h.Sinker().setCommitError(commitErr) + + ar1 := h.NewActiveRoutine() + err := h.RunStream(ar1) + require.Error(t, err) + require.ErrorIs(t, err, commitErr) + + // Ensure cleanup should have been invoked via defer and performed one rollback + ops := h.Sinker().opsSnapshot() + hasCommit := false + rollbackCount := 0 + for _, op := range ops { + if op == "commit" { + hasCommit = true + } + if op == "rollback" { + rollbackCount++ + } } + require.True(t, hasCommit, "commit should have been attempted") + require.GreaterOrEqual(t, rollbackCount, 1, "EnsureCleanup should trigger rollback") - sinker := NewConsoleSinker(nil, nil) - runningReaders := &sync.Map{} + // Second run: use a fresh harness to avoid reusing internal goroutine counters + h2 := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessFrequency(1*time.Millisecond), + ) + defer h2.Close() + h2.Sinker().reset() + // Use pausable handle to deterministically exit within one round: + // start blocked, then cancel context and unblock to let Run exit immediately. + proceed := make(chan struct{}) + ph := &pausableChangesHandle{proceed: proceed} + h2.SetCollectHandleSequence(ph) + + ar2 := h2.NewActiveRoutine() + errCh, _ := h2.RunStreamAsync(ar2) + // Trigger stop signals then unblock collector to finish the round + h2.Cancel() + close(proceed) + var runErr error + select { + case runErr = <-errCh: + case <-time.After(3 * time.Second): + t.Fatal("second stream did not finish in time") + } + require.NoError(t, runErr) - stream := NewTableChangeStream( - nil, // cnTxnClient - nil, // cnEngine - mp, - pool, - 1, // accountId - "task1", - tableInfo, - sinker, - updater, - tableDef, - false, // initSnapshotSplitTxn - runningReaders, - types.TS{}, - types.TS{}, - false, // noFull - 300*time.Millisecond, + ops = h2.Sinker().opsSnapshot() + rollbackCount = 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + // Second run is cancellation-driven fast exit; it must not rollback. + require.Equal(t, 0, rollbackCount, "second run should not rollback") +} + +// Recovery path: successful begin/commit after a clean setup (no cancellation) +func TestTableChangeStream_Recovery_BeginCommit(t *testing.T) { + updaterStub := newWatermarkUpdaterStub() + noopStop := func() {} + h := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessFrequency(1*time.Millisecond), ) + defer h.Close() + + // Initialize a committed watermark + key := h.Stream().txnManager.watermarkKey + initial := types.BuildTS(1, 0) + _, _ = updaterStub.GetOrAddCommitted(h.Context(), key, &initial) + + // Provide one snapshot batch then a tail_done marker to commit + snap := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: snap, hint: engine.ChangesHandle_Snapshot}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) - // Run in background - go stream.Run(ctx, NewCdcActiveRoutine()) + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + // Wait for begin and commit operations to occur + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + for _, op := range ops { + if op == "begin" { + hasBegin = true + } + if op == "commit" { + hasCommit = true + } + } + return hasBegin && hasCommit + }, 300*time.Millisecond, 10*time.Millisecond, "should see begin and commit operations") + + // Cancel to exit gracefully + h.Cancel() + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(time.Second): + t.Fatal("stream did not exit after cancellation") + } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) + } - // Ensure the stream goroutine is running, then cancel immediately - stream.start.Wait() - cancel() + ops := h.Sinker().opsSnapshot() + begin := 0 + commit := 0 + rollback := 0 + for _, op := range ops { + switch op { + case "begin": + begin++ + case "commit": + commit++ + case "rollback": + rollback++ + } + } + require.GreaterOrEqual(t, begin, 1, "should begin at least once") + require.GreaterOrEqual(t, commit, 1, "should commit at least once") + require.Equal(t, 0, rollback, "recovery path should not rollback") + require.False(t, h.Stream().GetRetryable()) +} - // Wait for completion - stream.Wait() +type blockingChangesHandle struct { + ready chan struct{} + once sync.Once +} - // Verify runningReaders is cleaned up - count := 0 - runningReaders.Range(func(_, _ interface{}) bool { - count++ - return true +func (h *blockingChangesHandle) Next(ctx context.Context, _ *mpool.MPool) (*batch.Batch, *batch.Batch, engine.ChangesHandle_Hint, error) { + h.once.Do(func() { + close(h.ready) }) - assert.Equal(t, 0, count, "runningReaders should be empty after Run exits") + <-ctx.Done() + return nil, nil, engine.ChangesHandle_Tail_done, ctx.Err() } -// Test Run() with duplicate reader (should exit immediately) -func TestTableChangeStream_Run_DuplicateReader(t *testing.T) { - ctx := context.Background() - mp := mpool.MustNewZero() +func (h *blockingChangesHandle) Close() error { return nil } - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", +type pausableChangesHandle struct { + ready chan<- struct{} + proceed <-chan struct{} + once sync.Once + done bool +} + +func newPausableChangesHandle(ready chan<- struct{}, proceed <-chan struct{}) *pausableChangesHandle { + return &pausableChangesHandle{ + ready: ready, + proceed: proceed, + } +} + +func (h *pausableChangesHandle) Next(ctx context.Context, _ *mpool.MPool) (*batch.Batch, *batch.Batch, engine.ChangesHandle_Hint, error) { + h.once.Do(func() { + select { + case h.ready <- struct{}{}: + default: + } + }) + + select { + case <-ctx.Done(): + return nil, nil, engine.ChangesHandle_Tail_done, ctx.Err() + case <-h.proceed: + } + + if h.done { + return nil, nil, engine.ChangesHandle_Tail_done, nil + } + h.done = true + return nil, nil, engine.ChangesHandle_Tail_done, nil +} + +func (h *pausableChangesHandle) Close() error { + return nil +} + +type changeBatch struct { + insert *batch.Batch + delete *batch.Batch + hint engine.ChangesHandle_Hint +} + +type immediateChangesHandle struct { + mu sync.Mutex + batches []changeBatch + nextIdx int + closed bool +} + +func newImmediateChangesHandle(batches []changeBatch) *immediateChangesHandle { + return &immediateChangesHandle{batches: batches} +} + +func (h *immediateChangesHandle) Next(ctx context.Context, _ *mpool.MPool) (*batch.Batch, *batch.Batch, engine.ChangesHandle_Hint, error) { + h.mu.Lock() + defer h.mu.Unlock() + + if h.closed { + return nil, nil, engine.ChangesHandle_Tail_done, nil } - runningReaders := &sync.Map{} + if len(h.batches) == 0 || h.nextIdx >= len(h.batches) { + h.closed = true + return nil, nil, engine.ChangesHandle_Tail_done, nil + } + + b := h.batches[h.nextIdx] + h.nextIdx++ + return b.insert, b.delete, b.hint, nil +} + +func (h *immediateChangesHandle) Close() error { + h.mu.Lock() + defer h.mu.Unlock() + h.closed = true + return nil +} + +// Test StaleRead retry logic +func TestTableChangeStream_StaleRead_Retry(t *testing.T) { + h := newTableStreamHarness( + t, + withHarnessNoFull(true), + withHarnessFrequency(5*time.Millisecond), + ) + defer h.Close() + + var snapshotCalls atomic.Int32 + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + call := snapshotCalls.Add(1) + ts := timestamp.Timestamp{PhysicalTime: 100} + if call >= 2 { + ts.PhysicalTime = 200 + } + return ts + }) + + var collectCalls atomic.Int32 + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + if collectCalls.Add(1) == 1 { + return nil, moerr.NewErrStaleReadNoCtx("db1", "t1") + } + bat := createTestBatch(t, h.MP(), toTs, []int32{1}) + return newImmediateChangesHandle([]changeBatch{ + {insert: bat, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }), nil + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + require.Eventually(t, func() bool { + return len(h.CollectCallsSnapshot()) >= 2 + }, 2*time.Second, 10*time.Millisecond, "should see stale read recovery with multiple collect calls") + + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + for _, op := range ops { + if op == "begin" || op == "sink" { + return true + } + } + return false + }, 2*time.Second, 10*time.Millisecond, "stream should process data successfully after stale read recovery") + + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(time.Second): + t.Fatal("table change stream run did not terminate") + } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled, "if error, should be context.Canceled") + } + + require.Equal(t, 1, h.Sinker().ResetCountSnapshot(), "sinker should be reset exactly once on stale read recovery") + require.GreaterOrEqual(t, len(h.CollectCallsSnapshot()), 2, "should have multiple collect calls after stale read recovery") + require.True(t, h.Stream().GetRetryable(), "stale read should mark stream retryable") +} + +func TestTableChangeStream_SinkerResetRecovery(t *testing.T) { + h := newTableStreamHarness( + t, + withHarnessNoFull(true), + withHarnessFrequency(5*time.Millisecond), + ) + defer h.Close() + + var snapshotCalls atomic.Int32 + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + call := snapshotCalls.Add(1) + ts := timestamp.Timestamp{PhysicalTime: 100} + if call >= 2 { + ts.PhysicalTime = 200 + } + return ts + }) + + var collectCalls atomic.Int32 + initialSinkerErr := moerr.NewInternalError(h.Context(), "sinker failure") + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + if collectCalls.Add(1) == 1 { + h.Sinker().setError(initialSinkerErr) + return nil, moerr.NewErrStaleReadNoCtx("db1", "t1") + } + bat := createTestBatch(t, h.MP(), toTs, []int32{1}) + return newImmediateChangesHandle([]changeBatch{ + {insert: bat, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }), nil + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + require.Eventually(t, func() bool { + return collectCalls.Load() >= 2 + }, 2*time.Second, 10*time.Millisecond, "stale read should trigger another collect attempt") + + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + } + } + return hasBegin && hasCommit + }, 2*time.Second, 10*time.Millisecond, "stream should process data successfully after reset") + + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(time.Second): + t.Fatal("table change stream run did not terminate") + } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled, "context cancellation is acceptable after shutdown") + } + + require.Equal(t, 1, h.Sinker().ResetCountSnapshot(), "sinker should reset exactly once after stale read recovery") + require.NoError(t, h.Sinker().Error(), "sinker error should be cleared by reset") + require.GreaterOrEqual(t, len(h.CollectCallsSnapshot()), 2, "multiple collect attempts expected") + require.True(t, h.Stream().GetRetryable(), "recovery should keep stream retryable") + + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker) + require.True(t, tracker.IsCompleted(), "tracker should reach completed state after recovery") +} + +// Test StaleRead with startTs set (should fail, not retry) +func TestTableChangeStream_StaleRead_NoRetryWithStartTs(t *testing.T) { + startTs := types.BuildTS(1, 0) + h := newTableStreamHarness( + t, + withHarnessStartTs(startTs), + ) + defer h.Close() + + staleErr := moerr.NewErrStaleReadNoCtx("db1", "t1") + h.SetCollectError(staleErr) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Contains(t, err.Error(), "cannot recover") + require.False(t, h.Stream().GetRetryable(), "stale read with startTs should not be retryable") + require.Equal(t, 0, h.Sinker().ResetCountSnapshot(), "sinker reset should not occur on fatal stale read") +} + +func TestTableChangeStream_StaleReadRetry_WatermarkUpdateFailure(t *testing.T) { + ctx, cancel := context.WithTimeoutCause(context.Background(), 2*time.Second, moerr.CauseFinishTxnOp) + defer cancel() + + failureErr := moerr.NewInternalError(ctx, "inject update failure") + updater := newWatermarkUpdaterStub(). + withUpdateError(func(int) error { return failureErr }) + + h := newTableStreamHarness( + t, + withHarnessNoFull(true), + withHarnessWatermarkUpdater(updater, nil), + ) + defer h.Close() + + zero := types.TS{} + _, _ = updater.GetOrAddCommitted(context.Background(), h.Stream().watermarkKey, &zero) + + staleErr := moerr.NewErrStaleReadNoCtx("db1", "t1") + h.SetCollectError(staleErr) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Contains(t, err.Error(), "stale read recovery failed to update watermark") + require.False(t, h.Stream().GetRetryable(), "watermark update failure should not be retryable") + require.Equal(t, int32(1), updater.updateCalls.Load(), "UpdateWatermarkOnly should be invoked exactly once") + require.Len(t, h.CollectCallsSnapshot(), 1) +} + +func TestTableChangeStream_StaleReadRetry_MultipleAttempts(t *testing.T) { + updater := newWatermarkUpdaterStub() + h := newTableStreamHarness( + t, + withHarnessNoFull(true), + withHarnessWatermarkUpdater(updater, nil), + withHarnessFrequency(5*time.Millisecond), + ) + defer h.Close() + + zero := types.TS{} + _, _ = updater.GetOrAddCommitted(context.Background(), h.Stream().watermarkKey, &zero) + + var collectCount atomic.Int32 + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + attempt := int(collectCount.Add(1)) + if attempt <= 3 { + return nil, moerr.NewErrStaleReadNoCtx("db1", "t1") + } + if attempt == 4 { + tail := createTestBatch(t, h.MP(), toTs, []int32{int32(attempt)}) + return newImmediateChangesHandle([]changeBatch{ + {insert: tail, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }), nil + } + return newImmediateChangesHandle(nil), nil + }) + + var snapshotCalls atomic.Int32 + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + call := snapshotCalls.Add(1) + return timestamp.Timestamp{PhysicalTime: int64(100 + call*50)} + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + require.Eventually(t, func() bool { + return collectCount.Load() >= 4 + }, 2*time.Second, 10*time.Millisecond, "expected multiple stale read retries before success") + + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) + } + + require.GreaterOrEqual(t, collectCount.Load(), int32(4)) + require.GreaterOrEqual(t, updater.updateCalls.Load(), int32(3)) + require.True(t, h.Stream().GetRetryable(), "successful recovery should keep retryable flag true") + require.Equal(t, 3, h.Sinker().ResetCountSnapshot(), "sinker should reset for each stale read") +} + +// Test end-to-end with real change processing +// Test context cancellation +func TestTableChangeStream_Run_ContextCancel(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + tail := createTestBatch(t, h.MP(), types.BuildTS(10, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tail, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + require.Eventually(t, func() bool { + return len(h.CollectCallsSnapshot()) > 0 + }, time.Second, 10*time.Millisecond, "stream should begin collecting before cancellation") + + opsBefore := h.Sinker().opsSnapshot() + + h.Cancel() + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("stream did not stop after context cancellation") + } + + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) + } + + require.False(t, h.Stream().GetRetryable(), "cancel should not mark stream retryable") + require.Equal(t, opsBefore, h.Sinker().opsSnapshot(), "cancel should not produce additional sink operations") +} + +// Test ActiveRoutine Pause +func TestTableChangeStream_Run_Pause(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + ready := make(chan struct{}) + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return &blockingChangesHandle{ready: ready}, nil + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + select { + case <-ready: + case <-time.After(2 * time.Second): + t.Fatal("collector did not block as expected") + } + + ar.ClosePause() + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("Stream did not stop after pause") + } + + require.Error(t, runErr) + if !errors.Is(runErr, context.Canceled) { + require.Contains(t, runErr.Error(), "paused") + } + + require.False(t, h.Stream().GetRetryable(), "pause should not mark stream retryable") + require.Empty(t, h.Sinker().opsSnapshot(), "pause should abort before any sink operations") +} + +func TestTableChangeStream_ConcurrentStopSignalsCleanup(t *testing.T) { + runningReaders := &sync.Map{} + + updater := newWatermarkUpdaterStub() + h := newTableStreamHarness( + t, + withHarnessRunningReaders(runningReaders), + withHarnessWatermarkUpdater(updater, nil), + ) + defer h.Close() + zero := types.TS{} + _, _ = updater.GetOrAddCommitted(context.Background(), h.Stream().watermarkKey, &zero) + + blockReady := make(chan struct{}, 1) + proceed := make(chan struct{}) + + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return newPausableChangesHandle(blockReady, proceed), nil + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + select { + case <-blockReady: + case <-time.After(time.Second): + t.Fatal("collector did not reach blocking point") + } + + // Issue all stop signals. + ar.ClosePause() + ar.CloseCancel() + h.Cancel() + h.Stream().Close() + + // Unblock collector so Run can exit. + close(proceed) + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(time.Second): + t.Fatal("stream did not terminate after concurrent stop signals") + } + if runErr != nil { + require.True(t, errors.Is(runErr, context.Canceled) || strings.Contains(runErr.Error(), "paused"), + "unexpected error: %v", runErr) + } + + h.Stream().Wait() + _, ok := runningReaders.Load(h.Stream().runningReaderKey) + require.False(t, ok, "runningReaders should be cleaned up") + + // Second run: ensure duplicate readers can start after cleanup. + updater2 := newWatermarkUpdaterStub() + h2 := newTableStreamHarness( + t, + withHarnessRunningReaders(runningReaders), + withHarnessWatermarkUpdater(updater2, nil), + ) + defer h2.Close() + _, _ = updater2.GetOrAddCommitted(context.Background(), h2.Stream().watermarkKey, &zero) + + blockReady2 := make(chan struct{}, 1) + proceed2 := make(chan struct{}) + + h2.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return newPausableChangesHandle(blockReady2, proceed2), nil + }) + + ar2 := h2.NewActiveRoutine() + errCh2, done2 := h2.RunStreamAsync(ar2) + + select { + case <-blockReady2: + case <-time.After(time.Second): + t.Fatal("second collector did not reach blocking point") + } + + h2.Cancel() + close(proceed2) + done2() + + var runErr2 error + select { + case runErr2 = <-errCh2: + case <-time.After(time.Second): + t.Fatal("second stream did not terminate after cancellation") + } + if runErr2 != nil { + require.True(t, errors.Is(runErr2, context.Canceled) || strings.Contains(runErr2.Error(), "paused"), + "unexpected error: %v", runErr2) + } + + h2.Stream().Wait() + _, ok = runningReaders.Load(h2.Stream().runningReaderKey) + require.False(t, ok, "runningReaders should be empty after second stream exits") +} + +// Integration tests for TableChangeStream + DataProcessor + TransactionManager pipeline +func TestTableChangeStream_DataProcessorSinkerError(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + sinkerErr := moerr.NewInternalError(h.Context(), "sinker error") + h.Sinker().setError(sinkerErr) + + snapshot := createTestBatch(t, h.MP(), types.BuildTS(1, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: snapshot, hint: engine.ChangesHandle_Snapshot}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Equal(t, sinkerErr, err) + require.Equal(t, sinkerErr, h.Sinker().Error(), "sinker error should remain set for inspection") + require.False(t, h.Stream().GetRetryable(), "fatal sinker error should not mark stream retryable") + require.Equal(t, 0, h.Sinker().ResetCountSnapshot(), "no resets expected when error occurs before transaction start") + + ops := h.Sinker().opsSnapshot() + require.NotContains(t, ops, "begin", "Begin should not be called when sinker already has an error") + require.NotContains(t, ops, "rollback", "No transaction started, rollback not expected") + require.Empty(t, ops, "sinker should not record operations when it starts with an error") + + require.Nil(t, h.Stream().txnManager.GetTracker(), "tracker should remain nil when no transaction begins") +} + +func TestTableChangeStream_EnsureCleanupOnCollectorError(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + collectErr := moerr.NewInternalError(h.Context(), "collector error") + h.SetCollectError(collectErr) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + defer done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(time.Second): + t.Fatal("table change stream run did not complete") + } + + require.Error(t, runErr) + require.Equal(t, collectErr, runErr) + + ops := h.Sinker().opsSnapshot() + require.NotContains(t, ops, "begin") + require.NotContains(t, ops, "commit") + require.NotContains(t, ops, "rollback") + require.Equal(t, 0, h.Sinker().ResetCountSnapshot()) + + require.Nil(t, h.Stream().txnManager.GetTracker()) + require.False(t, h.Stream().GetRetryable(), "collector error should not be retryable") +} + +func TestTableChangeStream_TailDoneUpdatesTransactionToTs(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + tail1 := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + tail2 := createTestBatch(t, h.MP(), types.BuildTS(150, 0), []int32{2}) + h.SetCollectBatches([]changeBatch{ + {insert: tail1, hint: engine.ChangesHandle_Tail_done}, + {insert: tail2, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + for _, op := range ops { + if op == "commit" { + return true + } + } + return false + }, 2*time.Second, 10*time.Millisecond, "expected sinker to observe commit for tail-done batches") + + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + + require.NoError(t, runErr) + + ops := h.Sinker().opsSnapshot() + beginCount := 0 + for _, op := range ops { + if op == "begin" { + beginCount++ + } + } + require.Equal(t, 1, beginCount, "Should have only one BEGIN for multiple TailDone batches") + require.Contains(t, ops, "commit", "Should commit after NoMoreData") + require.Equal(t, 0, h.Sinker().ResetCountSnapshot(), "no sinker resets expected for successful tail processing") + + if tracker := h.Stream().txnManager.GetTracker(); tracker != nil { + require.True(t, tracker.IsCompleted(), "transaction tracker should be marked complete") + toTs := tracker.GetToTs() + require.False(t, (&toTs).IsEmpty(), "tracker toTs should be recorded") + } + + calls := h.Sinker().sinkCallsSnapshot() + require.GreaterOrEqual(t, len(calls), 1) + finalToTs := calls[len(calls)-1].toTs + + stats := h.Stream().progressTracker.GetStats() + require.Equal(t, "idle", stats["state"], "progress tracker should return to idle after completion") + require.Equal(t, finalToTs.ToString(), stats["current_watermark"]) + require.EqualValues(t, initialSyncStateSuccess, stats["initial_sync_state"], "initial sync should complete successfully") + require.EqualValues(t, 1, stats["total_transactions"], "exactly one transaction should be committed") +} + +func TestTableChangeStream_CommitFailureTriggersEnsureCleanup(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + h.Sinker().setCommitError(commitErr) + + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + defer done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + + require.Error(t, runErr) + require.Equal(t, commitErr, runErr) + + var ops []string + require.Eventually(t, func() bool { + ops = h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + hasClear := false + hasRollback := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + case "clear": + hasClear = true + case "rollback": + hasRollback = true + } + } + return hasBegin && hasCommit && hasClear && hasRollback + }, time.Second, 10*time.Millisecond, "EnsureCleanup should clear error and rollback") + + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + require.Equal(t, 1, rollbackCount, "rollback should occur exactly once") + // Note: With retry mechanism, sinker may still have error after retries, + // but EnsureCleanup should have been called (verified by ops above). + // The error state may persist because commitErr is re-injected on each retry. + // What matters is that EnsureCleanup was called and rollback occurred. + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker) + require.False(t, tracker.NeedsRollback(), "tracker should be clean after EnsureCleanup") +} + +func TestTableChangeStream_BeginFailureDoesNotRollback(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + beginErr := moerr.NewInternalError(h.Context(), "begin failure") + h.Sinker().setBeginError(beginErr) + + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Equal(t, beginErr, err) + require.Equal(t, beginErr, h.Sinker().Error(), "sinker error should remain set after begin failure") + // "begin failure" without network context is non-retryable (state-related) + require.False(t, h.Stream().GetRetryable(), "state-related begin failure should not mark stream retryable") + + ops := h.Sinker().opsSnapshot() + require.Contains(t, ops, "begin", "Begin should be attempted even though it fails") + require.NotContains(t, ops, "commit", "Commit should not be attempted after begin failure") + require.NotContains(t, ops, "rollback", "Rollback should not occur when begin fails before start") + + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker, "tracker should be created even if begin fails") + require.False(t, tracker.NeedsRollback(), "tracker should not require rollback when begin fails") + require.False(t, tracker.IsCompleted(), "tracker should remain incomplete after begin failure") +} + +func TestTableChangeStream_BeginFailure_NetworkError_Retryable(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + // Network-related begin failure should be retryable + beginErr := moerr.NewInternalError(h.Context(), "begin transaction failed: connection timeout") + h.Sinker().setBeginError(beginErr) + + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Equal(t, beginErr, err) + // Network-related begin failure should be retryable + require.True(t, h.Stream().GetRetryable(), "network-related begin failure should mark stream retryable") +} + +func TestTableChangeStream_BeginFailure_ServiceUnavailable_Retryable(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + // Service unavailable begin failure should be retryable + beginErr := moerr.NewInternalError(h.Context(), "begin transaction failed: service unavailable") + h.Sinker().setBeginError(beginErr) + + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + err := h.RunStream(ar) + + require.Error(t, err) + require.Equal(t, beginErr, err) + // Service unavailable begin failure should be retryable + require.True(t, h.Stream().GetRetryable(), "service unavailable begin failure should mark stream retryable") +} + +func TestTableChangeStream_EnsureCleanup_WatermarkMismatch(t *testing.T) { + // Create a custom watermark updater stub that returns a different watermark + // than what the tracker expects, simulating a watermark mismatch scenario + updaterStub := newWatermarkUpdaterStub() + updaterStub.setSkipRemove(true) + + // Create harness with custom watermark updater + h := newTableStreamHarness( + t, + withHarnessWatermarkUpdater(updaterStub, func() {}), + ) + defer h.Close() + + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + ts := timestamp.Timestamp{PhysicalTime: 200} + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts + } + return ts + }) + + ctx := context.Background() + initialWatermark := types.BuildTS(100, 0) + key := h.Stream().watermarkKey + require.NoError(t, updaterStub.UpdateWatermarkOnly(ctx, key, &initialWatermark)) + + // Set up commit failure + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + h.Sinker().setCommitError(commitErr) + + // Create batch with toTs = 200, but watermark in cache is still 100 + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(200, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + // Run stream - commit will fail, and EnsureCleanup should detect watermark mismatch + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + defer done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + + require.Error(t, runErr) + require.Equal(t, commitErr, runErr) + + // Wait for EnsureCleanup to complete + var ops []string + require.Eventually(t, func() bool { + ops = h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + hasRollback := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + case "rollback": + hasRollback = true + } + } + return hasBegin && hasCommit && hasRollback + }, time.Second, 10*time.Millisecond, "EnsureCleanup should detect watermark mismatch and trigger rollback") + + // Verify rollback occurred due to watermark mismatch + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + require.GreaterOrEqual(t, rollbackCount, 1, "rollback should occur due to watermark mismatch") + + // Verify tracker is cleaned up + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker, "tracker should exist after EnsureCleanup") + require.False(t, tracker.NeedsRollback(), "tracker should be clean after rollback") + + // Verify watermark in cache is still 100 (not updated due to commit failure) + cachedWatermark, err := updaterStub.GetFromCache(ctx, key) + require.NoError(t, err) + require.Equal(t, initialWatermark.ToString(), cachedWatermark.ToString(), "watermark should remain unchanged after commit failure") +} + +func TestTableChangeStream_EnsureCleanup_GetFromCacheFails(t *testing.T) { + // Create a custom watermark updater stub that fails on GetFromCache + updaterStub := newWatermarkUpdaterStub() + getFromCacheErr := moerr.NewInternalError(context.Background(), "cache error") + updaterStub.setSkipRemove(true) + + // Create harness with custom watermark updater + h := newTableStreamHarness( + t, + withHarnessWatermarkUpdater(updaterStub, func() {}), + ) + defer h.Close() + + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + ts := timestamp.Timestamp{PhysicalTime: 200} + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts + } + return ts + }) + + // Set up commit failure + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + h.Sinker().setCommitError(commitErr) + + var callCount atomic.Int32 + updaterStub.setGetFromCacheHook(func() error { + call := callCount.Add(1) + if call >= 3 { + return getFromCacheErr + } + return nil + }) + + // Create batch + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(200, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + // Run stream - commit will fail, and EnsureCleanup should handle GetFromCache failure + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + defer done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + + require.Error(t, runErr) + // With the original error preservation mechanism, the system should always return + // the original error (commit failure) that triggered the retry, not auxiliary errors + // (like cache error) encountered during retry attempts. This ensures deterministic + // error reporting. + require.Equal(t, commitErr, runErr, + "error should be the original commit failure, not auxiliary cache error, got: %v", runErr) + + // Wait for EnsureCleanup to complete + // When GetFromCache fails, EnsureCleanup should fallback to tracker state + var ops []string + require.Eventually(t, func() bool { + ops = h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + hasRollback := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + case "rollback": + hasRollback = true + } + } + return hasBegin && hasCommit && hasRollback + }, time.Second, 10*time.Millisecond, "EnsureCleanup should fallback to tracker state when GetFromCache fails") + + // Verify rollback occurred (fallback to tracker state) + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + require.GreaterOrEqual(t, rollbackCount, 1, "rollback should occur when GetFromCache fails and tracker needs rollback") + + // Verify tracker is cleaned up + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker, "tracker should exist after EnsureCleanup") + require.False(t, tracker.NeedsRollback(), "tracker should be clean after rollback") +} + +func TestTableChangeStream_RollbackFailure(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + rollbackErr := moerr.NewInternalError(h.Context(), "rollback failure") + h.Sinker().setCommitError(commitErr) + h.Sinker().setRollbackError(rollbackErr) + + tailBatch := createTestBatch(t, h.MP(), types.BuildTS(200, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: tailBatch, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + defer done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("table change stream run did not complete") + } + + require.Error(t, runErr) + require.Equal(t, commitErr, runErr, "original commit error should propagate even if rollback fails") + require.False(t, h.Stream().GetRetryable(), "rollback failure should not mark stream retryable") + + var ops []string + require.Eventually(t, func() bool { + ops = h.Sinker().opsSnapshot() + hasBegin := false + hasCommit := false + hasClear := false + hasRollback := false + hasDummy := false + for _, op := range ops { + switch op { + case "begin": + hasBegin = true + case "commit": + hasCommit = true + case "clear": + hasClear = true + case "rollback": + hasRollback = true + case "dummy": + hasDummy = true + } + } + return hasBegin && hasCommit && hasClear && hasRollback && hasDummy + }, time.Second, 10*time.Millisecond, "EnsureCleanup should attempt rollback even if it fails") + + require.Equal(t, rollbackErr, h.Sinker().Error(), "sinker should retain rollback error for inspection") + + rollbackCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + } + require.Equal(t, 1, rollbackCount, "rollback should still be invoked exactly once") + + tracker := h.Stream().txnManager.GetTracker() + require.NotNil(t, tracker) + require.False(t, tracker.NeedsRollback(), "tracker should consider rollback done even if sinker failed") + require.True(t, tracker.IsCompleted(), "tracker should mark transaction as completed after rollback attempt") +} + +// TestTableChangeStream_FullPipeline_RandomDelaysAndErrors verifies the entire pipeline +// under random delays and error injections, ensuring orderliness, idempotency, and consistency. +// This test uses pausableChangesHandle, watermarkUpdaterStub, and error injection to simulate +// realistic failure scenarios including StaleRead, commit failures, and rollback failures. +func TestTableChangeStream_FullPipeline_RandomDelaysAndErrors(t *testing.T) { + updaterStub := newWatermarkUpdaterStub() + noopStop := func() {} + h := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessFrequency(1*time.Millisecond), + withHarnessNoFull(true), + ) + defer h.Close() + + // Initialize watermark + key := h.Stream().txnManager.watermarkKey + initial := types.BuildTS(1, 0) + _, _ = updaterStub.GetOrAddCommitted(h.Context(), key, &initial) + + // Track operation order and counts for verification + var ( + collectCalls atomic.Int32 + staleReadInjected atomic.Bool + commitFailInjected atomic.Bool + rollbackFailInjected atomic.Bool + ) + + // Inject StaleRead error on first collect, then succeed + h.SetCollectFactory(func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + call := collectCalls.Add(1) + if call == 1 { + staleReadInjected.Store(true) + return nil, moerr.NewErrStaleReadNoCtx("db1", "t1") + } + // After stale read recovery, provide data + bat := createTestBatch(t, h.MP(), toTs, []int32{int32(call)}) + return newImmediateChangesHandle([]changeBatch{ + {insert: bat, hint: engine.ChangesHandle_Tail_done}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }), nil + }) + + // Update snapshot TS after stale read recovery + var snapshotCalls atomic.Int32 + h.SetGetSnapshotTS(func(op client.TxnOperator) timestamp.Timestamp { + call := snapshotCalls.Add(1) + ts := timestamp.Timestamp{PhysicalTime: 100 + int64(call*50)} + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts + } + return ts + }) + + // Inject commit failure on first commit attempt, then succeed + commitErr := moerr.NewInternalError(h.Context(), "commit failure") + h.Sinker().setCommitError(commitErr) + commitFailInjected.Store(true) + + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) + + // Wait for stale read recovery (multiple collect calls) + require.Eventually(t, func() bool { + return collectCalls.Load() >= 2 + }, 2*time.Second, 10*time.Millisecond, "should see stale read recovery") + + // Wait for commit attempt (which will fail) + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + for _, op := range ops { + if op == "commit" { + return true + } + } + return false + }, 2*time.Second, 10*time.Millisecond, "should see commit attempt") + + // Clear commit error and inject rollback failure, then clear it + rollbackErr := moerr.NewInternalError(h.Context(), "rollback failure") + h.Sinker().setCommitError(nil) + h.Sinker().setRollbackError(rollbackErr) + rollbackFailInjected.Store(true) + + // Wait for rollback attempt (which will fail) + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + for _, op := range ops { + if op == "rollback" { + return true + } + } + return false + }, 2*time.Second, 10*time.Millisecond, "should see rollback attempt") + + // Verify that we've seen the expected error scenarios + // The stream should be retryable and have attempted rollback + require.Eventually(t, func() bool { + return h.Stream().GetRetryable() + }, 500*time.Millisecond, 10*time.Millisecond, "stream should be retryable after stale read and commit failure") + + // Cancel to exit + h.Cancel() + done() + + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("stream did not exit after cancellation") + } + // The stream may return either the commit failure error or context.Canceled + if runErr != nil { + if !errors.Is(runErr, context.Canceled) { + // If not canceled, it should be the commit failure error + require.Contains(t, runErr.Error(), "commit failure", "if not canceled, should be commit failure") + } + } + + // Verify orderliness: begin should always come before commit/rollback + ops := h.Sinker().opsSnapshot() + lastBeginIdx := -1 + lastCommitIdx := -1 + lastRollbackIdx := -1 + for i, op := range ops { + switch op { + case "begin": + lastBeginIdx = i + case "commit": + lastCommitIdx = i + case "rollback": + lastRollbackIdx = i + } + } + if lastCommitIdx >= 0 && lastBeginIdx >= 0 { + require.Greater(t, lastCommitIdx, lastBeginIdx, "commit should come after begin") + } + if lastRollbackIdx >= 0 && lastBeginIdx >= 0 { + require.Greater(t, lastRollbackIdx, lastBeginIdx, "rollback should come after begin") + } + + // Verify idempotency: EnsureCleanup should be idempotent + // Count rollbacks - should be at least one, but not excessive + rollbackCount := 0 + beginCount := 0 + for _, op := range ops { + if op == "rollback" { + rollbackCount++ + } + if op == "begin" { + beginCount++ + } + } + require.GreaterOrEqual(t, rollbackCount, 1, "should have at least one rollback after commit failure") + require.GreaterOrEqual(t, beginCount, 1, "should have at least one begin") + + // Verify consistency: retryable flag and sinker reset + require.True(t, h.Stream().GetRetryable(), "stream should be retryable after stale read recovery") + require.GreaterOrEqual(t, h.Sinker().ResetCountSnapshot(), 1, "sinker should reset at least once for stale read") + + // Verify all error injections occurred + require.True(t, staleReadInjected.Load(), "stale read should have been injected") + require.True(t, commitFailInjected.Load(), "commit failure should have been injected") + require.True(t, rollbackFailInjected.Load(), "rollback failure should have been injected") + + // Verify tracker state is consistent (may be nil if cleanup completed) + tracker := h.Stream().txnManager.GetTracker() + if tracker != nil { + // After EnsureCleanup, tracker should not need rollback (even if rollback failed) + require.False(t, tracker.NeedsRollback(), "tracker should be marked as not needing rollback after EnsureCleanup") + } +} + +type noopTxnOperator struct { + meta txnpb.TxnMeta + options txnpb.TxnOptions + workspace client.Workspace + snapshot timestamp.Timestamp +} + +func newNoopTxnOperator() *noopTxnOperator { + return &noopTxnOperator{} +} + +func (n *noopTxnOperator) GetOverview() client.TxnOverview { + return client.TxnOverview{} +} + +func (n *noopTxnOperator) CloneSnapshotOp(snapshot timestamp.Timestamp) client.TxnOperator { + op := newNoopTxnOperator() + op.snapshot = snapshot + return op +} + +func (n *noopTxnOperator) IsSnapOp() bool { + return false +} + +func (n *noopTxnOperator) Txn() txnpb.TxnMeta { + return n.meta +} + +func (n *noopTxnOperator) TxnOptions() txnpb.TxnOptions { + return n.options +} + +func (n *noopTxnOperator) TxnRef() *txnpb.TxnMeta { + return &n.meta +} + +func (n *noopTxnOperator) Snapshot() (txnpb.CNTxnSnapshot, error) { + return txnpb.CNTxnSnapshot{}, nil +} + +func (n *noopTxnOperator) UpdateSnapshot(ctx context.Context, ts timestamp.Timestamp) error { + n.snapshot = ts + return nil +} + +func (n *noopTxnOperator) SnapshotTS() timestamp.Timestamp { + return n.snapshot +} + +func (n *noopTxnOperator) CreateTS() timestamp.Timestamp { + return timestamp.Timestamp{} +} + +func (n *noopTxnOperator) Status() txnpb.TxnStatus { + return txnpb.TxnStatus(0) +} + +func (n *noopTxnOperator) ApplySnapshot(data []byte) error { + return nil +} + +func (n *noopTxnOperator) Read(ctx context.Context, ops []txnpb.TxnRequest) (*rpc.SendResult, error) { + return nil, nil +} + +func (n *noopTxnOperator) Write(ctx context.Context, ops []txnpb.TxnRequest) (*rpc.SendResult, error) { + return nil, nil +} + +func (n *noopTxnOperator) WriteAndCommit(ctx context.Context, ops []txnpb.TxnRequest) (*rpc.SendResult, error) { + return nil, nil +} + +func (n *noopTxnOperator) Commit(ctx context.Context) error { + return nil +} + +func (n *noopTxnOperator) Rollback(ctx context.Context) error { + return nil +} + +func (n *noopTxnOperator) AddLockTable(locktable lock.LockTable) error { + return nil +} + +func (n *noopTxnOperator) HasLockTable(table uint64) bool { + return false +} + +func (n *noopTxnOperator) AddWaitLock(tableID uint64, rows [][]byte, opt lock.LockOptions) uint64 { + return 0 +} + +func (n *noopTxnOperator) RemoveWaitLock(key uint64) {} + +func (n *noopTxnOperator) LockSkipped(tableID uint64, mode lock.LockMode) bool { + return false +} + +func (n *noopTxnOperator) GetWaitActiveCost() time.Duration { + return 0 +} + +func (n *noopTxnOperator) AddWorkspace(workspace client.Workspace) { + n.workspace = workspace +} + +func (n *noopTxnOperator) GetWorkspace() client.Workspace { + return n.workspace +} + +func (n *noopTxnOperator) AppendEventCallback(event client.EventType, callbacks ...client.TxnEventCallback) { +} + +func (n *noopTxnOperator) Debug(ctx context.Context, ops []txnpb.TxnRequest) (*rpc.SendResult, error) { + return nil, nil +} + +func (n *noopTxnOperator) NextSequence() uint64 { + return 0 +} + +func (n *noopTxnOperator) EnterRunSql() {} +func (n *noopTxnOperator) ExitRunSql() {} +func (n *noopTxnOperator) EnterIncrStmt() {} +func (n *noopTxnOperator) ExitIncrStmt() {} +func (n *noopTxnOperator) EnterRollbackStmt() {} +func (n *noopTxnOperator) ExitRollbackStmt() {} +func (n *noopTxnOperator) SetFootPrints(int, bool) {} +func (n *noopTxnOperator) Set(key string, value any) {} +func (n *noopTxnOperator) Get(key string) (any, bool) { + return nil, false +} +func (n *noopTxnOperator) Delete(key string) {} + +// tableStreamHarnessConfig captures the configurable parts of the test harness +// so individual test cases can focus on behavior rather than boilerplate setup. +type tableStreamHarnessConfig struct { + initSnapshotSplitTxn bool + noFull bool + startTs types.TS + endTs types.TS + frequency time.Duration + tableDef *plan.TableDef + tableInfo *DbTableInfo + watermarkUpdater WatermarkUpdater + updaterStop func() + runningReaders *sync.Map + // Retry configuration for testing (use shorter delays to speed up tests) + retryOptions []TableChangeStreamOption +} + +func defaultTableStreamHarnessConfig() tableStreamHarnessConfig { + return tableStreamHarnessConfig{ + initSnapshotSplitTxn: false, + noFull: false, + startTs: types.TS{}, + endTs: types.TS{}, + frequency: 50 * time.Millisecond, + runningReaders: &sync.Map{}, + tableDef: &plan.TableDef{ + Cols: []*plan.ColDef{ + {Name: "id"}, + {Name: "ts"}, + }, + Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, + Name2ColIndex: map[string]int32{ + "id": 0, + "ts": 1, + }, + }, + tableInfo: &DbTableInfo{ + SourceDbName: "db1", + SourceTblName: "t1", + SourceTblId: 1, + }, + } +} + +type tableStreamHarnessOption func(*tableStreamHarnessConfig) + +func withHarnessNoFull(noFull bool) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.noFull = noFull + } +} + +func withHarnessStartTs(ts types.TS) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.startTs = ts + } +} + +func withHarnessEndTs(ts types.TS) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.endTs = ts + } +} + +func withHarnessFrequency(freq time.Duration) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.frequency = freq + } +} + +func withHarnessWatermarkUpdater(updater WatermarkUpdater, stop func()) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.watermarkUpdater = updater + cfg.updaterStop = stop + } +} + +func withHarnessRunningReaders(readers *sync.Map) tableStreamHarnessOption { + return func(cfg *tableStreamHarnessConfig) { + cfg.runningReaders = readers + } +} + +type tableStreamHarness struct { + t *testing.T + + ctx context.Context + cancel context.CancelFunc - stream1 := createTestStream(mp, tableInfo) - stream1.runningReaders = runningReaders + mp *mpool.MPool + packerPool *fileservice.Pool[*types.Packer] - stream2 := createTestStream(mp, tableInfo) - stream2.runningReaders = runningReaders + sinker *tableStreamRecordingSinker + updater WatermarkUpdater + updaterStop func() + stream *TableChangeStream - // Start first stream - key := GenDbTblKey(tableInfo.SourceDbName, tableInfo.SourceTblName) - runningReaders.Store(key, stream1) + stubs []*gostub.Stubs + closeOnce sync.Once - // Second stream should exit immediately - ar := NewCdcActiveRoutine() - stream2.Run(ctx, ar) + getTxnOp func(context.Context, engine.Engine, client.TxnClient, string) (client.TxnOperator, error) + finishTxnOp func(context.Context, error, client.TxnOperator, engine.Engine) + getTxn func(context.Context, engine.Engine, client.TxnOperator) error + getRelation func(context.Context, engine.Engine, client.TxnOperator, uint64) (string, string, engine.Relation, error) + getSnapshotTS func(client.TxnOperator) timestamp.Timestamp + enterRunSql func(client.TxnOperator) + exitRunSql func(client.TxnOperator) + collectFactory func(fromTs, toTs types.TS) (engine.ChangesHandle, error) - // Verify first stream is still in runningReaders - _, exists := runningReaders.Load(key) - assert.True(t, exists) + collectCallsMu sync.Mutex + collectCalls []collectInvocation } -// Regression test: Pause must not hang when collector blocks on context cancellation. -func TestTableChangeStream_PauseDrainsBlockedCollector(t *testing.T) { - ctx := context.Background() +type collectInvocation struct { + from types.TS + to types.TS +} + +func newTableStreamHarness(t *testing.T, opts ...tableStreamHarnessOption) *tableStreamHarness { + t.Helper() + cfg := defaultTableStreamHarnessConfig() + for _, opt := range opts { + opt(&cfg) + } + + ctx, cancel := context.WithCancel(context.Background()) mp := mpool.MustNewZero() - pool := fileservice.NewPool( + packerPool := fileservice.NewPool( 128, func() *types.Packer { return types.NewPacker() }, func(packer *types.Packer) { packer.Reset() }, func(packer *types.Packer) { packer.Close() }, ) - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "a"}, - {Name: "ts"}, - }, - Pkey: &plan.PrimaryKeyDef{Names: []string{"a"}}, - Name2ColIndex: map[string]int32{ - "a": 0, - "ts": 1, - }, + sinker := newTableStreamRecordingSinker() + + var ( + updater WatermarkUpdater + updaterStop func() + ) + if cfg.watermarkUpdater != nil { + updater = cfg.watermarkUpdater + updaterStop = cfg.updaterStop + } else { + defaultUpdater, _ := InitCDCWatermarkUpdaterForTest(t) + defaultUpdater.Start() + updater = defaultUpdater + updaterStop = defaultUpdater.Stop } - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, + runningReaders := cfg.runningReaders + if runningReaders == nil { + runningReaders = &sync.Map{} } - // Prepare stubs for transactional helpers - stubs := []*gostub.Stubs{ - gostub.Stub(&GetTxnOp, func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - return nil, nil - }), - gostub.Stub(&FinishTxnOp, func(context.Context, error, client.TxnOperator, engine.Engine) {}), - gostub.Stub(&GetTxn, func(context.Context, engine.Engine, client.TxnOperator) error { return nil }), - gostub.Stub(&GetRelationById, func(context.Context, engine.Engine, client.TxnOperator, uint64) (string, string, engine.Relation, error) { - return "", "", nil, nil - }), - gostub.Stub(&GetSnapshotTS, func(client.TxnOperator) timestamp.Timestamp { - return timestamp.Timestamp{PhysicalTime: 1} - }), - gostub.Stub(&EnterRunSql, func(client.TxnOperator) {}), - gostub.Stub(&ExitRunSql, func(client.TxnOperator) {}), - } - defer func() { - for _, stub := range stubs { - stub.Reset() + // Apply default test retry options (very short delays for faster tests) if not provided + retryOptions := cfg.retryOptions + if len(retryOptions) == 0 { + // Use minimal backoff for tests to speed up execution: + // - Base: 5ms (vs 200ms in production) + // - Max: 20ms (vs 30s in production) + // - Factor: 2.0 (same as production) + // This allows testing retry logic without long waits + retryOptions = []TableChangeStreamOption{ + WithMaxRetryCount(3), + WithRetryBackoff(5*time.Millisecond, 20*time.Millisecond, 2.0), } - }() - - blockingHandleReady := make(chan struct{}) - collectStub := gostub.Stub(&CollectChanges, func(context.Context, engine.Relation, types.TS, types.TS, *mpool.MPool) (engine.ChangesHandle, error) { - return &blockingChangesHandle{ready: blockingHandleReady}, nil - }) - defer collectStub.Reset() - - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() + } stream := NewTableChangeStream( nil, nil, mp, - pool, + packerPool, 1, "task1", - tableInfo, - NewConsoleSinker(nil, nil), + cfg.tableInfo, + sinker, updater, - tableDef, - false, - &sync.Map{}, - types.TS{}, - types.TS{}, - false, - 200*time.Millisecond, + cfg.tableDef, + cfg.initSnapshotSplitTxn, + runningReaders, + cfg.startTs, + cfg.endTs, + cfg.noFull, + cfg.frequency, + retryOptions..., ) - ar := NewCdcActiveRoutine() - go stream.Run(ctx, ar) + h := &tableStreamHarness{ + t: t, + ctx: ctx, + cancel: cancel, + mp: mp, + packerPool: packerPool, + sinker: sinker, + updater: updater, + updaterStop: updaterStop, + stream: stream, + } - select { - case <-blockingHandleReady: - case <-time.After(2 * time.Second): - t.Fatalf("collector did not block as expected") + if cfg.watermarkUpdater != nil { + zero := types.TS{} + _, _ = updater.GetOrAddCommitted(context.Background(), stream.watermarkKey, &zero) } - done := make(chan struct{}) - go func() { - stream.Wait() - close(done) - }() + h.getTxnOp = func(context.Context, engine.Engine, client.TxnClient, string) (client.TxnOperator, error) { + return newNoopTxnOperator(), nil + } + h.finishTxnOp = func(context.Context, error, client.TxnOperator, engine.Engine) {} + h.getTxn = func(context.Context, engine.Engine, client.TxnOperator) error { return nil } + h.getRelation = func(context.Context, engine.Engine, client.TxnOperator, uint64) (string, string, engine.Relation, error) { + return "", "", nil, nil + } + h.getSnapshotTS = func(op client.TxnOperator) timestamp.Timestamp { + ts := timestamp.Timestamp{PhysicalTime: 100} + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts + } + return ts + } + h.enterRunSql = func(client.TxnOperator) {} + h.exitRunSql = func(client.TxnOperator) {} + h.collectFactory = func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return newImmediateChangesHandle(nil), nil + } - ar.ClosePause() - stream.Close() + h.installStubs() + t.Cleanup(h.Close) + return h +} - select { - case <-done: - case <-time.After(2 * time.Second): - t.Fatalf("stream wait did not finish after pause") - } +func (h *tableStreamHarness) installStubs() { + h.addStub(gostub.Stub(&GetTxnOp, func(ctx context.Context, eng engine.Engine, cli client.TxnClient, purpose string) (client.TxnOperator, error) { + return h.getTxnOp(ctx, eng, cli, purpose) + })) + h.addStub(gostub.Stub(&FinishTxnOp, func(ctx context.Context, err error, op client.TxnOperator, eng engine.Engine) { + h.finishTxnOp(ctx, err, op, eng) + })) + h.addStub(gostub.Stub(&GetTxn, func(ctx context.Context, eng engine.Engine, op client.TxnOperator) error { + return h.getTxn(ctx, eng, op) + })) + h.addStub(gostub.Stub(&GetRelationById, func(ctx context.Context, eng engine.Engine, op client.TxnOperator, tableId uint64) (string, string, engine.Relation, error) { + return h.getRelation(ctx, eng, op, tableId) + })) + h.addStub(gostub.Stub(&GetSnapshotTS, func(op client.TxnOperator) timestamp.Timestamp { + return h.getSnapshotTS(op) + })) + h.addStub(gostub.Stub(&EnterRunSql, func(op client.TxnOperator) { + h.enterRunSql(op) + })) + h.addStub(gostub.Stub(&ExitRunSql, func(op client.TxnOperator) { + h.exitRunSql(op) + })) + h.addStub(gostub.Stub(&CollectChanges, func(ctx context.Context, rel engine.Relation, fromTs, toTs types.TS, mp *mpool.MPool) (engine.ChangesHandle, error) { + h.collectCallsMu.Lock() + h.collectCalls = append(h.collectCalls, collectInvocation{from: fromTs, to: toTs}) + h.collectCallsMu.Unlock() + return h.collectFactory(fromTs, toTs) + })) } -type blockingChangesHandle struct { - ready chan struct{} - once sync.Once +func (h *tableStreamHarness) addStub(stub *gostub.Stubs) { + h.stubs = append(h.stubs, stub) } -func (h *blockingChangesHandle) Next(ctx context.Context, _ *mpool.MPool) (*batch.Batch, *batch.Batch, engine.ChangesHandle_Hint, error) { - h.once.Do(func() { - close(h.ready) +func (h *tableStreamHarness) Close() { + h.closeOnce.Do(func() { + h.cancel() + h.stream.Close() + h.stream.Wait() + for _, stub := range h.stubs { + stub.Reset() + } + if h.updaterStop != nil { + h.updaterStop() + } else if u, ok := h.updater.(*CDCWatermarkUpdater); ok { + u.Stop() + } + if h.mp != nil { + mpool.DeleteMPool(h.mp) + h.mp = nil + } }) - <-ctx.Done() - return nil, nil, engine.ChangesHandle_Tail_done, ctx.Err() } -func (h *blockingChangesHandle) Close() error { return nil } +func (h *tableStreamHarness) Context() context.Context { + return h.ctx +} -// Test StaleRead retry logic -func TestTableChangeStream_StaleRead_Retry(t *testing.T) { - ctx, cancel := context.WithTimeoutCause(context.Background(), 2*time.Second, moerr.CauseFinishTxnOp) +func (h *tableStreamHarness) Stream() *TableChangeStream { + return h.stream +} - mp := mpool.MustNewZero() - var wg sync.WaitGroup - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, - ) +func (h *tableStreamHarness) MP() *mpool.MPool { + return h.mp +} - var packer *types.Packer - put := pool.Get(&packer) - - // Track read attempts - var readCount atomic.Int32 - readDone := make(chan struct{}, 10) - - // Setup stubs - stub1 := gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - return nil, nil - }) - - stub2 := gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}) - - stub3 := gostub.Stub(&GetTxn, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator) error { - return nil - }) - - stub4 := gostub.Stub(&GetRelationById, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator, tableId uint64) (dbName string, tblName string, rel engine.Relation, err error) { - count := readCount.Load() - if count == 0 { - // First attempt: StaleRead error - readDone <- struct{}{} - readCount.Add(1) - return "", "", nil, moerr.NewErrStaleReadNoCtx("", "test stale read") - } - // Second attempt: Success - readDone <- struct{}{} - readCount.Add(1) - return "", "", nil, nil - }) +func (h *tableStreamHarness) Sinker() *tableStreamRecordingSinker { + return h.sinker +} - stub5 := gostub.Stub(&GetSnapshotTS, - func(txnOp client.TxnOperator) timestamp.Timestamp { - return timestamp.Timestamp{ - PhysicalTime: 100, - LogicalTime: 0, - } - }) - - stub6 := gostub.Stub(&CollectChanges, - func(ctx context.Context, rel engine.Relation, fromTs, toTs types.TS, mp *mpool.MPool) (engine.ChangesHandle, error) { - return newTestChangesHandle("test", "t1", 20, 23, types.TS{}, mp, packer), nil - }) - - stub7 := gostub.Stub(&EnterRunSql, func(client.TxnOperator) {}) - - stub8 := gostub.Stub(&ExitRunSql, func(client.TxnOperator) {}) - stubs := []*gostub.Stubs{stub1, stub2, stub3, stub4, stub5, stub6, stub7, stub8} - defer func() { - cancel() - wg.Wait() - put.Put() - for _, stub := range stubs { - stub.Reset() - } - }() +func (h *tableStreamHarness) WatermarkUpdater() WatermarkUpdater { + return h.updater +} - // Create watermark updater - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() +func (h *tableStreamHarness) Cancel() { + h.cancel() +} - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "ts"}, - {Name: "a"}, - {Name: "b"}, - {Name: "cpk"}, - }, - Pkey: &plan.PrimaryKeyDef{ - Names: []string{"a", "b"}, - }, - Name2ColIndex: map[string]int32{ - "ts": 0, - "a": 1, - "b": 2, - "cpk": 3, - }, - } +func (h *tableStreamHarness) RunStream(ar *ActiveRoutine) error { + h.stream.Run(h.ctx, ar) + return h.stream.lastError +} - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, +func (h *tableStreamHarness) RunStreamAsync(ar *ActiveRoutine) (<-chan error, func()) { + errCh := make(chan error, 1) + done := func() { + h.Cancel() + h.stream.Close() } - - sinker := NewConsoleSinker(nil, nil) - - stream := NewTableChangeStream( - nil, nil, mp, pool, - 1, "task1", tableInfo, - sinker, updater, tableDef, - false, &sync.Map{}, - types.TS{}, types.TS{}, // No time range limit - true, // noFull = true (allows StaleRead retry) - 50*time.Millisecond, - ) - - // Run in background - wg.Add(1) go func() { - defer wg.Done() - stream.Run(ctx, NewCdcActiveRoutine()) + h.stream.Run(h.ctx, ar) + errCh <- h.stream.lastError + close(errCh) }() + return errCh, done +} - // Wait for first attempt (StaleRead) - select { - case <-readDone: - t.Log("First read attempt (should get StaleRead)") - case <-time.After(1 * time.Second): - t.Fatal("Timeout waiting for first read") +func (h *tableStreamHarness) SetGetTxnOp(fn func(context.Context, engine.Engine, client.TxnClient, string) (client.TxnOperator, error)) { + if fn == nil { + fn = func(context.Context, engine.Engine, client.TxnClient, string) (client.TxnOperator, error) { + return newNoopTxnOperator(), nil + } } + h.getTxnOp = fn +} - // Wait for retry attempt (should succeed) - select { - case <-readDone: - t.Log("Second read attempt (retry after StaleRead)") - case <-time.After(1 * time.Second): - t.Fatal("Timeout waiting for retry") +func (h *tableStreamHarness) SetFinishTxnOp(fn func(context.Context, error, client.TxnOperator, engine.Engine)) { + if fn == nil { + fn = func(context.Context, error, client.TxnOperator, engine.Engine) {} } - - // Verify retry happened - assert.GreaterOrEqual(t, readCount.Load(), int32(2), "Should have at least 2 read attempts (initial + retry)") - cancel() + h.finishTxnOp = fn } -// Test StaleRead with startTs set (should fail, not retry) -func TestTableChangeStream_StaleRead_NoRetryWithStartTs(t *testing.T) { - ctx, cancel := context.WithTimeoutCause(context.Background(), 2*time.Second, moerr.CauseFinishTxnOp) - defer cancel() - - mp := mpool.MustNewZero() - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, - ) +func (h *tableStreamHarness) SetGetTxn(fn func(context.Context, engine.Engine, client.TxnOperator) error) { + if fn == nil { + fn = func(context.Context, engine.Engine, client.TxnOperator) error { return nil } + } + h.getTxn = fn +} - // Track call count to avoid infinite loop - var callCount atomic.Int32 +func (h *tableStreamHarness) SetGetRelation(fn func(context.Context, engine.Engine, client.TxnOperator, uint64) (string, string, engine.Relation, error)) { + if fn == nil { + fn = func(context.Context, engine.Engine, client.TxnOperator, uint64) (string, string, engine.Relation, error) { + return "", "", nil, nil + } + } + h.getRelation = fn +} - // Setup stubs - stub1 := gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - return nil, nil - }) - defer stub1.Reset() - - stub2 := gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}) - defer stub2.Reset() - - stub3 := gostub.Stub(&GetTxn, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator) error { - return nil - }) - defer stub3.Reset() - - stub4 := gostub.Stub(&GetRelationById, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator, tableId uint64) (dbName string, tblName string, rel engine.Relation, err error) { - // Only return StaleRead on first call, then return a different error to stop the loop - if callCount.Add(1) == 1 { - return "", "", nil, moerr.NewErrStaleReadNoCtx("", "test stale read") +func (h *tableStreamHarness) SetGetSnapshotTS(fn func(client.TxnOperator) timestamp.Timestamp) { + if fn == nil { + fn = func(op client.TxnOperator) timestamp.Timestamp { + ts := timestamp.Timestamp{PhysicalTime: 100} + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts } - // Return a different error to break the loop - return "", "", nil, moerr.NewInternalError(ctx, "stopping test") - }) - defer stub4.Reset() - - stub5 := gostub.Stub(&GetSnapshotTS, - func(txnOp client.TxnOperator) timestamp.Timestamp { - return timestamp.Timestamp{PhysicalTime: 100} - }) - defer stub5.Reset() - - stub6 := gostub.Stub(&EnterRunSql, func(client.TxnOperator) {}) - defer stub6.Reset() - - stub7 := gostub.Stub(&ExitRunSql, func(client.TxnOperator) {}) - defer stub7.Reset() - - // Use simple mock watermark updater (avoid complex mock SQL executor) - updater := newMockWatermarkUpdater() - startTs := types.BuildTS(1, 0) - - // Initialize watermark - wKey := &WatermarkKey{ - AccountId: 1, - TaskId: "task1", - DBName: "db1", - TableName: "t1", + return ts + } } - _, _ = updater.GetOrAddCommitted(context.Background(), wKey, &startTs) - - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{{Name: "id"}, {Name: "ts"}}, - Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, - Name2ColIndex: map[string]int32{"id": 0, "ts": 1}, + h.getSnapshotTS = func(op client.TxnOperator) timestamp.Timestamp { + ts := fn(op) + if noop, ok := op.(*noopTxnOperator); ok { + noop.snapshot = ts + } + return ts } +} - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, +func (h *tableStreamHarness) SetEnterRunSql(fn func(client.TxnOperator)) { + if fn == nil { + fn = func(client.TxnOperator) {} } + h.enterRunSql = fn +} - sinker := NewConsoleSinker(nil, nil) - - stream := NewTableChangeStream( - nil, nil, mp, pool, - 1, "task1", tableInfo, - sinker, updater, tableDef, - false, &sync.Map{}, - startTs, types.TS{}, // startTs is set - false, // noFull = false (StaleRead should NOT retry) - 50*time.Millisecond, - ) - - // Run should exit quickly due to fatal StaleRead error - stream.Run(ctx, NewCdcActiveRoutine()) +func (h *tableStreamHarness) SetExitRunSql(fn func(client.TxnOperator)) { + if fn == nil { + fn = func(client.TxnOperator) {} + } + h.exitRunSql = fn +} - // Verify error was set and NOT retryable - assert.NotNil(t, stream.lastError, "Should have error") - assert.False(t, stream.retryable, "Should NOT be retryable") - assert.Contains(t, stream.lastError.Error(), "cannot recover", "Error should indicate cannot recover") +func (h *tableStreamHarness) SetCollectFactory(factory func(fromTs, toTs types.TS) (engine.ChangesHandle, error)) { + if factory == nil { + factory = func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return newImmediateChangesHandle(nil), nil + } + } + h.collectFactory = factory } -// Test end-to-end with real change processing -func TestTableChangeStream_EndToEnd(t *testing.T) { - ctx, cancel := context.WithTimeoutCause(context.Background(), 2*time.Second, moerr.CauseFinishTxnOp) - defer cancel() +func (h *tableStreamHarness) SetCollectBatches(batches []changeBatch) { + h.collectFactory = func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + cp := make([]changeBatch, len(batches)) + copy(cp, batches) + return newImmediateChangesHandle(cp), nil + } +} - mp := mpool.MustNewZero() - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, - ) +func (h *tableStreamHarness) SetCollectError(err error) { + h.collectFactory = func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + return nil, err + } +} - var packer *types.Packer - put := pool.Get(&packer) - defer put.Put() - - // Setup stubs - stub1 := gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - return nil, nil - }) - defer stub1.Reset() - - stub2 := gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}) - defer stub2.Reset() - - stub3 := gostub.Stub(&GetTxn, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator) error { - return nil - }) - defer stub3.Reset() - - stub4 := gostub.Stub(&GetRelationById, - func(ctx context.Context, cnEngine engine.Engine, txnOp client.TxnOperator, tableId uint64) (dbName string, tblName string, rel engine.Relation, err error) { - return "", "", nil, nil - }) - defer stub4.Reset() - - stub5 := gostub.Stub(&GetSnapshotTS, - func(txnOp client.TxnOperator) timestamp.Timestamp { - return timestamp.Timestamp{ - PhysicalTime: 100, - LogicalTime: 0, - } - }) - defer stub5.Reset() +func (h *tableStreamHarness) SetCollectHandleSequence(handles ...engine.ChangesHandle) { + var mu sync.Mutex + idx := 0 + h.collectFactory = func(fromTs, toTs types.TS) (engine.ChangesHandle, error) { + mu.Lock() + defer mu.Unlock() + if idx >= len(handles) { + return newImmediateChangesHandle(nil), nil + } + handle := handles[idx] + idx++ + return handle, nil + } +} - stub6 := gostub.Stub(&CollectChanges, - func(ctx context.Context, rel engine.Relation, fromTs, toTs types.TS, mp *mpool.MPool) (engine.ChangesHandle, error) { - return newTestChangesHandle("test", "t1", 20, 23, types.TS{}, mp, packer), nil - }) - defer stub6.Reset() +func (h *tableStreamHarness) CollectCallsSnapshot() []collectInvocation { + h.collectCallsMu.Lock() + defer h.collectCallsMu.Unlock() + cp := make([]collectInvocation, len(h.collectCalls)) + copy(cp, h.collectCalls) + return cp +} - stub7 := gostub.Stub(&EnterRunSql, func(client.TxnOperator) {}) - defer stub7.Reset() +func (h *tableStreamHarness) ResetCollectCalls() { + h.collectCallsMu.Lock() + h.collectCalls = nil + h.collectCallsMu.Unlock() +} - stub8 := gostub.Stub(&ExitRunSql, func(client.TxnOperator) {}) - defer stub8.Reset() +func (h *tableStreamHarness) NewActiveRoutine() *ActiveRoutine { + return NewCdcActiveRoutine() +} - // Create watermark updater - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() +// Helper types and functions for integration tests - // Create table definition - // Column order MUST match batch layout: user cols | cpk | commit-ts - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{ - {Name: "a"}, // User column - {Name: "b"}, // User column - {Name: "cpk"}, // Composite PK column - {Name: "ts"}, // Commit timestamp (MUST be last) - }, - Pkey: &plan.PrimaryKeyDef{ - Names: []string{"a", "b"}, - }, - Name2ColIndex: map[string]int32{ - "a": 0, - "b": 1, - "cpk": 2, - "ts": 3, - }, - } +func createTestBatch(t *testing.T, mp *mpool.MPool, ts types.TS, ids []int32) *batch.Batch { + bat := batch.New([]string{"id", "ts"}) + idVec := vector.NewVec(types.T_int32.ToType()) + tsVec := vector.NewVec(types.T_TS.ToType()) - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, + for _, id := range ids { + _ = vector.AppendFixed(idVec, id, false, mp) + _ = vector.AppendFixed(tsVec, ts, false, mp) } - // Use console sinker for simplicity - sinker := NewConsoleSinker(nil, nil) - - // Initialize watermark - wKey := &WatermarkKey{ - AccountId: 1, - TaskId: "task1", - DBName: "db1", - TableName: "t1", - } - initialTs := types.TS{} - _, err := updater.GetOrAddCommitted(context.Background(), wKey, &initialTs) - assert.NoError(t, err) - - stream := NewTableChangeStream( - nil, nil, mp, pool, - 1, "task1", tableInfo, - sinker, updater, tableDef, - false, &sync.Map{}, - types.TS{}, types.TS{}, - false, - 300*time.Millisecond, - ) + bat.Vecs[0] = idVec + bat.Vecs[1] = tsVec + bat.SetRowCount(len(ids)) + return bat +} - // Run and wait - ar := NewCdcActiveRoutine() - go stream.Run(ctx, ar) - stream.Wait() +type tableStreamRecordingSinker struct { + *recordingSinker + sinkCalls []*DecoderOutput + resetCnt int +} - // Verify stream completed (no panic, graceful exit) - // Note: In this test, context timeout causes graceful exit before watermark update - // The key validation is that the test completes without panic or hang - t.Log("Stream completed end-to-end test successfully") +func newTableStreamRecordingSinker() *tableStreamRecordingSinker { + return &tableStreamRecordingSinker{recordingSinker: newRecordingSinker()} } -// Test context cancellation -func TestTableChangeStream_Run_ContextCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) +func (s *tableStreamRecordingSinker) Sink(ctx context.Context, data *DecoderOutput) { + s.record("sink") + s.mu.Lock() + s.sinkCalls = append(s.sinkCalls, data) + s.mu.Unlock() +} - mp := mpool.MustNewZero() - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, - ) +func (s *tableStreamRecordingSinker) Reset() { + s.recordingSinker.Reset() + s.recordingSinker.ClearError() + s.mu.Lock() + s.resetCnt++ + s.mu.Unlock() +} - // Setup minimal stubs - stub1 := gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - // Simulate slow operation to allow cancellation - time.Sleep(100 * time.Millisecond) - return nil, nil - }) - defer stub1.Reset() +func (s *tableStreamRecordingSinker) reset() { + s.mu.Lock() + s.err = nil + s.rollbackErr = nil + s.commitErr = nil + s.beginErr = nil + s.sinkCalls = nil + s.resetCnt = 0 + s.mu.Unlock() + s.resetOps() +} - stub2 := gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}) - defer stub2.Reset() +func (s *tableStreamRecordingSinker) sinkCallsSnapshot() []*DecoderOutput { + s.mu.Lock() + defer s.mu.Unlock() + copyCalls := make([]*DecoderOutput, len(s.sinkCalls)) + copy(copyCalls, s.sinkCalls) + return copyCalls +} - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() +func (s *tableStreamRecordingSinker) ResetCountSnapshot() int { + s.mu.Lock() + defer s.mu.Unlock() + return s.resetCnt +} - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{{Name: "id"}, {Name: "ts"}}, - Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, - Name2ColIndex: map[string]int32{"id": 0, "ts": 1}, - } +// TestTableChangeStream_GetTableInfo verifies GetTableInfo returns correct table information +func TestTableChangeStream_GetTableInfo(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) tableInfo := &DbTableInfo{ SourceDbName: "db1", @@ -908,129 +2429,151 @@ func TestTableChangeStream_Run_ContextCancel(t *testing.T) { SourceTblId: 1, } - sinker := NewConsoleSinker(nil, nil) + stream := createTestStream(mp, tableInfo) + info := stream.GetTableInfo() - stream := NewTableChangeStream( - nil, nil, mp, pool, - 1, "task1", tableInfo, - sinker, updater, tableDef, - false, &sync.Map{}, - types.TS{}, types.TS{}, - false, - 50*time.Millisecond, - ) + require.NotNil(t, info) + require.Equal(t, tableInfo.SourceDbName, info.SourceDbName) + require.Equal(t, tableInfo.SourceTblName, info.SourceTblName) + require.Equal(t, tableInfo.SourceTblId, info.SourceTblId) +} - // Run in background - started := make(chan struct{}) - go func() { - close(started) - stream.Run(ctx, NewCdcActiveRoutine()) - }() +// TestTableChangeStream_GetRelationByIdFailure verifies handling of GetRelationById failure +// (e.g., table truncated scenario) +func TestTableChangeStream_GetRelationByIdFailure(t *testing.T) { + h := newTableStreamHarness(t) + defer h.Close() + + relErr := moerr.NewInternalError(h.Context(), "table not found or truncated") + h.SetGetRelation(func(ctx context.Context, eng engine.Engine, op client.TxnOperator, tableId uint64) (string, string, engine.Relation, error) { + return "", "", nil, relErr + }) - <-started - time.Sleep(50 * time.Millisecond) + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) - // Cancel context - cancel() + require.Eventually(t, func() bool { + return h.Stream().GetRetryable() + }, 2*time.Second, 10*time.Millisecond, "stream should be marked retryable on relation error") - // Wait for stream to stop - done := make(chan struct{}) - go func() { - stream.Wait() - close(done) - }() + h.Cancel() + done() + var runErr error select { - case <-done: - t.Log("Stream stopped gracefully after context cancellation") + case runErr = <-errCh: case <-time.After(2 * time.Second): - t.Fatal("Stream did not stop after context cancellation") + t.Fatal("stream did not exit") } + + require.Error(t, runErr) + require.True(t, h.Stream().GetRetryable(), "relation error should mark stream retryable") } -// Test ActiveRoutine Pause -func TestTableChangeStream_Run_Pause(t *testing.T) { - ctx := context.Background() +// TestTableChangeStream_ReachedEndTs verifies graceful termination when endTs is reached +func TestTableChangeStream_ReachedEndTs(t *testing.T) { + updaterStub := newWatermarkUpdaterStub() + noopStop := func() {} + endTs := types.BuildTS(100, 0) - mp := mpool.MustNewZero() - pool := fileservice.NewPool( - 128, - func() *types.Packer { return types.NewPacker() }, - func(packer *types.Packer) { packer.Reset() }, - func(packer *types.Packer) { packer.Close() }, + h := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessEndTs(endTs), + withHarnessFrequency(1*time.Millisecond), ) + defer h.Close() - var wg sync.WaitGroup - defer wg.Wait() + // Initialize watermark to endTs (stream should detect and exit) + key := h.Stream().txnManager.watermarkKey + _, _ = updaterStub.GetOrAddCommitted(h.Context(), key, &endTs) - stubs := []*gostub.Stubs{ - gostub.Stub(&GetTxnOp, - func(_ context.Context, _ engine.Engine, _ client.TxnClient, _ string) (client.TxnOperator, error) { - time.Sleep(100 * time.Millisecond) - return nil, nil - }), - gostub.Stub(&FinishTxnOp, - func(ctx context.Context, inputErr error, txnOp client.TxnOperator, cnEngine engine.Engine) {}), - } - defer func() { - for _, stub := range stubs { - stub.Reset() - } - }() + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) - updater, _ := InitCDCWatermarkUpdaterForTest(t) - updater.Start() - defer updater.Stop() + // Stream should detect endTs quickly and exit, but we'll cancel after a short wait + // to ensure test completes quickly + select { + case <-time.After(200 * time.Millisecond): + // Timeout reached, cancel to exit + h.Cancel() + case err := <-errCh: + // Stream exited early (detected endTs) + require.NoError(t, err, "stream should exit gracefully when endTs is reached") + done() + return + } + done() - tableDef := &plan.TableDef{ - Cols: []*plan.ColDef{{Name: "id"}, {Name: "ts"}}, - Pkey: &plan.PrimaryKeyDef{Names: []string{"id"}}, - Name2ColIndex: map[string]int32{"id": 0, "ts": 1}, + var runErr error + select { + case runErr = <-errCh: + case <-time.After(2 * time.Second): + t.Fatal("stream did not exit") } - tableInfo := &DbTableInfo{ - SourceDbName: "db1", - SourceTblName: "t1", - SourceTblId: 1, + // Stream should exit gracefully (either nil or context.Canceled) + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) } + require.False(t, h.Stream().GetRetryable(), "reaching endTs should not mark stream retryable") +} - sinker := NewConsoleSinker(nil, nil) - ar := NewCdcActiveRoutine() +// TestTableChangeStream_CalculateInitialDelay_GetLastSyncTimeFailure verifies +// calculateInitialDelay handles getLastSyncTime failure gracefully (non-fatal) +func TestTableChangeStream_CalculateInitialDelay_GetLastSyncTimeFailure(t *testing.T) { + updaterStub := newWatermarkUpdaterStub() + noopStop := func() {} - stream := NewTableChangeStream( - nil, nil, mp, pool, - 1, "task1", tableInfo, - sinker, updater, tableDef, - false, &sync.Map{}, - types.TS{}, types.TS{}, - false, - 50*time.Millisecond, + h := newTableStreamHarness(t, + withHarnessWatermarkUpdater(updaterStub, noopStop), + withHarnessFrequency(1*time.Millisecond), ) + defer h.Close() - // Run in background - started := make(chan struct{}) - runDone := make(chan struct{}) - wg.Add(1) - go func() { - defer wg.Done() - close(started) - stream.Run(ctx, ar) - close(runDone) - }() + // Initialize watermark first + key := h.Stream().txnManager.watermarkKey + initial := types.BuildTS(1, 0) + _, _ = updaterStub.GetOrAddCommitted(h.Context(), key, &initial) + + // Inject GetFromCache error only for the first call (simulating getLastSyncTime failure) + // Subsequent calls should succeed + var callCount atomic.Int32 + updaterStub.setGetFromCacheHook(func() error { + call := callCount.Add(1) + if call == 1 { + // First call fails (getLastSyncTime in calculateInitialDelay) + return moerr.NewInternalError(context.Background(), "cache error") + } + // Subsequent calls succeed (processWithTxn needs it) + return nil + }) + + // Provide data so stream can process + snap := createTestBatch(t, h.MP(), types.BuildTS(100, 0), []int32{1}) + h.SetCollectBatches([]changeBatch{ + {insert: snap, hint: engine.ChangesHandle_Snapshot}, + {insert: nil, hint: engine.ChangesHandle_Tail_done}, + }) - <-started - time.Sleep(50 * time.Millisecond) + ar := h.NewActiveRoutine() + errCh, done := h.RunStreamAsync(ar) - // Pause - ar.ClosePause() + // Stream should continue processing despite getLastSyncTime failure in calculateInitialDelay + require.Eventually(t, func() bool { + ops := h.Sinker().opsSnapshot() + return len(ops) > 0 + }, 2*time.Second, 10*time.Millisecond, "stream should continue processing despite getLastSyncTime failure") - // Wait for stream to stop + h.Cancel() + done() + + var runErr error select { - case <-runDone: - t.Log("Stream stopped gracefully after pause") + case runErr = <-errCh: case <-time.After(2 * time.Second): - t.Fatal("Stream did not stop after pause") + t.Fatal("stream did not exit") + } + if runErr != nil { + require.ErrorIs(t, runErr, context.Canceled) } - - stream.Wait() } diff --git a/pkg/cdc/table_scanner.go b/pkg/cdc/table_scanner.go index 9bac5057401f0..b53deb1e44765 100644 --- a/pkg/cdc/table_scanner.go +++ b/pkg/cdc/table_scanner.go @@ -17,9 +17,11 @@ package cdc import ( "context" "fmt" + "runtime/debug" "slices" "strings" "sync" + "sync/atomic" "time" "github.com/matrixorigin/matrixone/pkg/objectio" @@ -37,10 +39,10 @@ import ( ) const ( - defaultSlowThreshold = 10 * time.Minute - defaultPrintInterval = 5 * time.Minute - defaultWatermarkCleanupPeriod = 5 * time.Minute - defaultCleanupWarnThreshold = 5 * time.Second + DefaultSlowThreshold = 10 * time.Minute + DefaultPrintInterval = 5 * time.Minute + DefaultWatermarkCleanupPeriod = 5 * time.Minute + DefaultCleanupWarnThreshold = 5 * time.Second ) type TableDetectorOptions struct { @@ -52,24 +54,24 @@ type TableDetectorOptions struct { func normalizeTableDetectorOptions(opts *TableDetectorOptions) { if opts.SlowThreshold <= 0 { - opts.SlowThreshold = defaultSlowThreshold + opts.SlowThreshold = DefaultSlowThreshold } if opts.PrintInterval <= 0 { - opts.PrintInterval = defaultPrintInterval + opts.PrintInterval = DefaultPrintInterval } if opts.CleanupPeriod <= 0 { - opts.CleanupPeriod = defaultWatermarkCleanupPeriod + opts.CleanupPeriod = DefaultWatermarkCleanupPeriod } if opts.CleanupWarnThreshold <= 0 { - opts.CleanupWarnThreshold = defaultCleanupWarnThreshold + opts.CleanupWarnThreshold = DefaultCleanupWarnThreshold } } var defaultTableDetectorOptions = TableDetectorOptions{ - SlowThreshold: defaultSlowThreshold, - PrintInterval: defaultPrintInterval, - CleanupPeriod: defaultWatermarkCleanupPeriod, - CleanupWarnThreshold: defaultCleanupWarnThreshold, + SlowThreshold: DefaultSlowThreshold, + PrintInterval: DefaultPrintInterval, + CleanupPeriod: DefaultWatermarkCleanupPeriod, + CleanupWarnThreshold: DefaultCleanupWarnThreshold, } type TableDetectorOption func(*TableDetectorOptions) @@ -112,6 +114,8 @@ var ( once sync.Once ) +var cdcScanTableInjected = objectio.CDCScanTableInjected + var getSqlExecutor = func(cnUUID string) executor.SQLExecutor { v, _ := runtime.ServiceRuntime(cnUUID).GetGlobalVariables(runtime.InternalSQLExecutor) return v.(executor.SQLExecutor) @@ -130,7 +134,9 @@ func newTableDetector(exec executor.SQLExecutor, opts ...TableDetectorOption) *T CallBackTableName: make(map[string][]string), SubscribedTableNames: make(map[string][]string), cdcStateManager: NewCDCStateManager(), - options: options, + cleanupPeriod: options.CleanupPeriod, + cleanupWarn: options.CleanupWarnThreshold, + nowFn: time.Now, } td.scanTableFn = td.scanTable return td @@ -138,7 +144,22 @@ func newTableDetector(exec executor.SQLExecutor, opts ...TableDetectorOption) *T var GetTableDetector = func(cnUUID string) *TableDetector { once.Do(func() { - detector = newTableDetector(getSqlExecutor(cnUUID)) + detector = &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + exec: getSqlExecutor(cnUUID), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cdcStateManager: NewCDCStateManager(), + cleanupPeriod: DefaultWatermarkCleanupPeriod, + cleanupWarn: DefaultCleanupWarnThreshold, + nowFn: time.Now, + } + detector.scanTableFn = detector.scanTable }) // Defensive: Ensure scanTableFn is always set (for testing scenarios) @@ -264,8 +285,6 @@ func (s *CDCStateManager) PrintActiveRunners(slowThreshold time.Duration) { } type TableDetector struct { - sync.Mutex - Mp map[uint32]TblMap Callbacks map[string]TableCallback exec executor.SQLExecutor @@ -291,12 +310,34 @@ type TableDetector struct { lastMp map[uint32]TblMap mu sync.Mutex cdcStateManager *CDCStateManager - options TableDetectorOptions + cleanupPeriod time.Duration + cleanupWarn time.Duration + nowFn func() time.Time + + loopRunning atomic.Bool + loopSeq atomic.Uint64 + currentLoop uint64 +} + +// RegisterIfAbsent registers the task only if it has not been registered before. +// Returns true when registration succeeds, false if the task already exists. +func (s *TableDetector) RegisterIfAbsent(id string, accountId uint32, dbs []string, tables []string, cb TableCallback) bool { + s.mu.Lock() + if _, exists := s.Callbacks[id]; exists { + s.mu.Unlock() + return false + } + startLoop := s.registerLocked(id, accountId, dbs, tables, cb) + s.mu.Unlock() + + if startLoop { + s.startScanLoop() + } + return true } -func (s *TableDetector) Register(id string, accountId uint32, dbs []string, tables []string, cb TableCallback) { - s.Lock() - defer s.Unlock() +func (s *TableDetector) registerLocked(id string, accountId uint32, dbs []string, tables []string, cb TableCallback) bool { + startLoop := len(s.Callbacks) == 0 s.SubscribedAccountIds[accountId] = append(s.SubscribedAccountIds[accountId], id) s.CallBackAccountId[id] = accountId @@ -311,27 +352,26 @@ func (s *TableDetector) Register(id string, accountId uint32, dbs []string, tabl } s.CallBackTableName[id] = tables - if len(s.Callbacks) == 0 { - ctx, cancel := context.WithCancel( - defines.AttachAccountId( - context.Background(), - catalog.System_Account, - ), - ) - s.cancel = cancel - go s.scanTableLoop(ctx) - } s.Callbacks[id] = cb logutil.Debug( "cdc.table_detector.register", zap.String("task-id", id), zap.Uint32("account-id", accountId), ) + return startLoop +} + +// IsTaskRegistered checks if a task is already registered +func (s *TableDetector) IsTaskRegistered(id string) bool { + s.mu.Lock() + defer s.mu.Unlock() + _, exists := s.Callbacks[id] + return exists } func (s *TableDetector) UnRegister(id string) { - s.Lock() - defer s.Unlock() + s.mu.Lock() + defer s.mu.Unlock() if accountID, ok := s.CallBackAccountId[id]; ok { if tasks, ok := s.SubscribedAccountIds[accountID]; ok { @@ -381,12 +421,56 @@ func (s *TableDetector) UnRegister(id string) { ) } +func (s *TableDetector) startScanLoop() { + if s.loopRunning.Load() { + return + } + + ctx, newCancel := context.WithCancel( + defines.AttachAccountId( + context.Background(), + catalog.System_Account, + ), + ) + + if !s.loopRunning.CompareAndSwap(false, true) { + newCancel() + return + } + + loopID := s.loopSeq.Add(1) + var previous context.CancelFunc + s.mu.Lock() + previous = s.cancel + s.cancel = newCancel + s.currentLoop = loopID + s.mu.Unlock() + + if previous != nil { + previous() + } + + go s.runScanLoop(ctx, newCancel, loopID) +} + +func (s *TableDetector) runScanLoop(ctx context.Context, cancel context.CancelFunc, loopID uint64) { + defer func() { + s.mu.Lock() + if s.currentLoop == loopID { + s.cancel = nil + } + s.mu.Unlock() + s.loopRunning.Store(false) + }() + s.scanTableLoop(ctx) +} + func (s *TableDetector) scanTableLoop(ctx context.Context) { logutil.Debug("cdc.table_detector.scan_start") defer logutil.Debug("cdc.table_detector.scan_end") var tickerDuration, retryTickerDuration time.Duration - if msg, injected := objectio.CDCScanTableInjected(); injected || msg == "fast scan" { + if msg, injected := cdcScanTableInjected(); injected || msg == "fast scan" { tickerDuration = 1 * time.Millisecond retryTickerDuration = 1 * time.Millisecond } else { @@ -399,26 +483,26 @@ func (s *TableDetector) scanTableLoop(ctx context.Context) { retryTicker := time.NewTicker(retryTickerDuration) defer retryTicker.Stop() - printInterval := s.options.PrintInterval + printInterval := DefaultPrintInterval if printInterval <= 0 { logutil.Warn( "cdc.table_detector.print_interval_invalid", zap.Duration("interval", printInterval), - zap.Duration("fallback", defaultPrintInterval), + zap.Duration("fallback", DefaultPrintInterval), ) - printInterval = defaultPrintInterval + printInterval = DefaultPrintInterval } printStateTicker := time.NewTicker(printInterval) defer printStateTicker.Stop() - cleanupPeriod := s.options.CleanupPeriod + cleanupPeriod := s.cleanupPeriod if cleanupPeriod <= 0 { logutil.Warn( "cdc.table_detector.cleanup_period_invalid", zap.Duration("period", cleanupPeriod), - zap.Duration("fallback", defaultWatermarkCleanupPeriod), + zap.Duration("fallback", DefaultWatermarkCleanupPeriod), ) - cleanupPeriod = defaultWatermarkCleanupPeriod + cleanupPeriod = DefaultWatermarkCleanupPeriod } cleanupTicker := time.NewTicker(cleanupPeriod) defer cleanupTicker.Stop() @@ -448,7 +532,7 @@ func (s *TableDetector) scanTableLoop(ctx context.Context) { go s.processCallback(ctx, lastMp) case <-printStateTicker.C: - s.cdcStateManager.PrintActiveRunners(s.options.SlowThreshold) + s.cdcStateManager.PrintActiveRunners(DefaultSlowThreshold) case <-cleanupTicker.C: s.cleanupOrphanWatermarks(ctx) } @@ -477,28 +561,58 @@ func (s *TableDetector) scanAndProcess(ctx context.Context) { func (s *TableDetector) processCallback(ctx context.Context, tables map[uint32]TblMap) { s.mu.Lock() + if s.handling { + s.mu.Unlock() + return + } s.handling = true + callbacks := make([]TableCallback, 0, len(s.Callbacks)) + for _, cb := range s.Callbacks { + callbacks = append(callbacks, cb) + } s.mu.Unlock() var err error - for _, cb := range s.Callbacks { - err = cb(tables) - } + var panicVal any + defer func() { + if r := recover(); r != nil { + panicVal = r + err = moerr.NewInternalErrorNoCtx(fmt.Sprintf("callback panic: %v", r)) + logutil.Error( + "cdc.table_detector.callback_panic", + zap.Any("panic", r), + zap.ByteString("stack", debug.Stack()), + ) + } - s.mu.Lock() - defer s.mu.Unlock() + s.mu.Lock() + if err != nil { + logutil.Warn("cdc.table_detector.callback_failed", zap.Error(err)) + } else { + logutil.Debug("cdc.table_detector.callback_success") + s.lastMp = nil + } + s.handling = false + s.mu.Unlock() - if err != nil { - logutil.Debug("cdc.table_detector.callback_failed", zap.Error(err)) - } else { - logutil.Debug("cdc.table_detector.callback_success") - s.lastMp = nil - } + if panicVal != nil { + panic(panicVal) + } + }() - s.handling = false + for _, cb := range callbacks { + if cbErr := cb(tables); cbErr != nil { + err = cbErr + } + } } func (s *TableDetector) cleanupOrphanWatermarks(ctx context.Context) { + if s.exec == nil { + logutil.Debug("cdc.table_detector.cleanup_watermark_skip", zap.String("reason", "executor nil")) + return + } + sql := CDCSQLBuilder.DeleteOrphanWatermarkSQL() cleanupCtx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() @@ -507,7 +621,7 @@ func (s *TableDetector) cleanupOrphanWatermarks(ctx context.Context) { "cdc.table_detector.cleanup_watermark_execute", zap.String("sql", sql), ) - start := time.Now() + start := s.now() res, err := s.exec.Exec( cleanupCtx, sql, @@ -522,19 +636,19 @@ func (s *TableDetector) cleanupOrphanWatermarks(ctx context.Context) { logutil.Error( "cdc.table_detector.cleanup_watermark_failed", zap.Error(err), - zap.Duration("duration", time.Since(start)), + zap.Duration("duration", s.now().Sub(start)), ) return } if res.AffectedRows > 0 { - duration := time.Since(start) + duration := s.now().Sub(start) fields := []zap.Field{ zap.Uint64("deleted-rows", res.AffectedRows), zap.Duration("duration", duration), zap.String("sql", sql), } - if duration > s.options.CleanupWarnThreshold { + if duration > s.cleanupWarn { logutil.Warn( "cdc.table_detector.cleanup_watermark_slow", fields..., @@ -548,9 +662,21 @@ func (s *TableDetector) cleanupOrphanWatermarks(ctx context.Context) { } } +func (s *TableDetector) now() time.Time { + if s.nowFn != nil { + return s.nowFn() + } + return time.Now() +} + func (s *TableDetector) Close() { - if s.cancel != nil { - s.cancel() + s.mu.Lock() + cancel := s.cancel + s.cancel = nil + s.mu.Unlock() + + if cancel != nil { + cancel() } } @@ -564,11 +690,11 @@ func (s *TableDetector) scanTable() error { mp = make(map[uint32]TblMap) ) - s.Lock() + s.mu.Lock() if len(s.SubscribedAccountIds) == 0 || len(s.SubscribedDbNames) == 0 || len(s.SubscribedTableNames) == 0 { s.Mp = mp - s.Unlock() + s.mu.Unlock() return nil } var i int @@ -601,7 +727,7 @@ func (s *TableDetector) scanTable() error { if tableNames != "*" { tableNames = AddSingleQuotesJoin(tableNamesSlice) } - s.Unlock() + s.mu.Unlock() result, err := s.exec.Exec( ctx, @@ -658,8 +784,8 @@ func (s *TableDetector) scanTable() error { }) // replace the old table map - s.Lock() + s.mu.Lock() s.Mp = mp - s.Unlock() + s.mu.Unlock() return nil } diff --git a/pkg/cdc/table_scanner_test.go b/pkg/cdc/table_scanner_test.go index 318927b2e67d1..ec5e64a8b0008 100644 --- a/pkg/cdc/table_scanner_test.go +++ b/pkg/cdc/table_scanner_test.go @@ -16,7 +16,10 @@ package cdc import ( "context" + "fmt" "strings" + "sync" + "sync/atomic" "testing" "time" @@ -32,6 +35,7 @@ import ( mock_executor "github.com/matrixorigin/matrixone/pkg/util/executor/test" "github.com/prashantv/gostub" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetTableScanner(t *testing.T) { @@ -54,10 +58,10 @@ func TestApplyTableDetectorOptions(t *testing.T) { assert.Equal(t, 4*time.Millisecond, opts.CleanupWarnThreshold) defaultOpts := applyTableDetectorOptions() - assert.Equal(t, defaultSlowThreshold, defaultOpts.SlowThreshold) - assert.Equal(t, defaultPrintInterval, defaultOpts.PrintInterval) - assert.Equal(t, defaultWatermarkCleanupPeriod, defaultOpts.CleanupPeriod) - assert.Equal(t, defaultCleanupWarnThreshold, defaultOpts.CleanupWarnThreshold) + assert.Equal(t, DefaultSlowThreshold, defaultOpts.SlowThreshold) + assert.Equal(t, DefaultPrintInterval, defaultOpts.PrintInterval) + assert.Equal(t, DefaultWatermarkCleanupPeriod, defaultOpts.CleanupPeriod) + assert.Equal(t, DefaultCleanupWarnThreshold, defaultOpts.CleanupWarnThreshold) } func TestTableScanner1(t *testing.T) { @@ -80,19 +84,28 @@ func TestTableScanner1(t *testing.T) { mockSqlExecutor := mock_executor.NewMockSQLExecutor(ctrl) mockSqlExecutor.EXPECT().Exec(gomock.Any(), gomock.Any(), gomock.Any()).Return(res, nil) - td := newTableDetector( - mockSqlExecutor, - WithTableDetectorCleanupPeriod(time.Hour), - ) + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + exec: mockSqlExecutor, + cleanupPeriod: time.Hour, + cleanupWarn: DefaultCleanupWarnThreshold, + } defer td.Close() - td.Register("id1", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return nil }) + assert.True(t, td.RegisterIfAbsent("id1", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return nil })) assert.Equal(t, 1, len(td.Callbacks)) - td.Register("id2", 2, []string{"db2"}, []string{"tbl2"}, func(mp map[uint32]TblMap) error { return nil }) + assert.True(t, td.RegisterIfAbsent("id2", 2, []string{"db2"}, []string{"tbl2"}, func(mp map[uint32]TblMap) error { return nil })) assert.Equal(t, 2, len(td.Callbacks)) assert.Equal(t, 2, len(td.SubscribedAccountIds)) - td.Register("id3", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return nil }) + assert.True(t, td.RegisterIfAbsent("id3", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return nil })) assert.Equal(t, 3, len(td.Callbacks)) assert.Equal(t, 2, len(td.SubscribedAccountIds)) assert.Equal(t, 2, len(td.SubscribedDbNames["db1"])) @@ -113,7 +126,7 @@ func TestTableScanner1(t *testing.T) { assert.Equal(t, 0, len(td.SubscribedAccountIds)) assert.Equal(t, 0, len(td.SubscribedDbNames)) - td.Register("id4", 1, []string{"db4"}, []string{"tbl4"}, func(mp map[uint32]TblMap) error { return nil }) + assert.True(t, td.RegisterIfAbsent("id4", 1, []string{"db4"}, []string{"tbl4"}, func(mp map[uint32]TblMap) error { return nil })) assert.Equal(t, 1, len(td.Callbacks)) assert.Equal(t, 1, len(td.SubscribedAccountIds)) @@ -140,6 +153,530 @@ func TestTableScanner1(t *testing.T) { assert.Equal(t, 0, len(td.Mp)) } +func TestTableDetectorRegisterStartsScanAsync(t *testing.T) { + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + td.scanTableFn = func() error { return nil } + defer td.Close() + + errCh := make(chan error, 1) + registered := make(chan struct{}) + go func() { + if !td.RegisterIfAbsent("async-task", 1, []string{"db"}, []string{"tbl"}, func(map[uint32]TblMap) error { return nil }) { + errCh <- moerr.NewInternalErrorNoCtx("RegisterIfAbsent failed for async-task") + } + close(registered) + }() + + select { + case <-registered: + case <-time.After(2 * time.Second): + t.Fatalf("register blocked while starting scan loop") + } + + select { + case err := <-errCh: + t.Fatalf("unexpected registration failure: %v", err) + default: + } + + td.mu.Lock() + cancelSet := td.cancel != nil + td.mu.Unlock() + + if !cancelSet { + t.Fatalf("expected cancel function to be set after registration") + } +} + +func TestTableDetectorScanLoopSingleInstance(t *testing.T) { + fault.Enable() + defer fault.Disable() + rmFn, err := objectio.InjectCDCScanTable("fast scan") + require.NoError(t, err) + defer func() { + if rmFn != nil { + _, _ = rmFn() + } + }() + + var scanCalls atomic.Int32 + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + td.scanTableFn = func() error { + scanCalls.Add(1) + return nil + } + defer td.Close() + + if !td.RegisterIfAbsent("task-0", 1, []string{"db"}, []string{"tbl"}, func(map[uint32]TblMap) error { return nil }) { + t.Fatalf("RegisterIfAbsent failed for first task") + } + + waitUntil(t, func() bool { return scanCalls.Load() > 0 }, 500*time.Millisecond, "scan loop did not start") + + firstSeq := td.loopSeq.Load() + if firstSeq != 1 { + t.Fatalf("expected loopSeq 1, got %d", firstSeq) + } + + for i := 1; i < 5; i++ { + id := fmt.Sprintf("task-%d", i) + if !td.RegisterIfAbsent(id, uint32(i+1), []string{"db"}, []string{"tbl"}, func(map[uint32]TblMap) error { return nil }) { + t.Fatalf("RegisterIfAbsent failed for %s", id) + } + } + + time.Sleep(50 * time.Millisecond) + if td.loopSeq.Load() != firstSeq { + t.Fatalf("expected loopSeq to remain %d, got %d", firstSeq, td.loopSeq.Load()) + } + + td.Close() + waitUntil(t, func() bool { return !td.loopRunning.Load() }, time.Second, "scan loop did not stop after Close") +} + +func TestTableDetectorProcessCallbackNoReentry(t *testing.T) { + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + defer td.Close() + + block := make(chan struct{}) + release := make(chan struct{}) + var count atomic.Int32 + + cb := func(map[uint32]TblMap) error { + count.Add(1) + select { + case <-block: + default: + close(block) + } + <-release + return nil + } + + require.True(t, td.RegisterIfAbsent("task", 1, []string{"db"}, []string{"tbl"}, cb)) + tables := map[uint32]TblMap{ + 1: {"db.tbl": {SourceDbName: "db", SourceTblName: "tbl"}}, + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + td.processCallback(context.Background(), tables) + }() + + <-block + done := make(chan struct{}) + go func() { + td.processCallback(context.Background(), tables) + close(done) + }() + + <-done + if got := count.Load(); got != 1 { + t.Fatalf("callback executed %d times", got) + } + + close(release) + wg.Wait() +} + +func TestTableDetectorRegisterDuringCallback(t *testing.T) { + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + defer td.Close() + + enter := make(chan struct{}) + release := make(chan struct{}) + var firstCount, secondCount atomic.Int32 + + first := func(map[uint32]TblMap) error { + firstCount.Add(1) + select { + case <-enter: + default: + close(enter) + } + <-release + return nil + } + + second := func(map[uint32]TblMap) error { + secondCount.Add(1) + return nil + } + + require.True(t, td.RegisterIfAbsent("task-1", 1, []string{"db"}, []string{"tbl"}, first)) + + tables := map[uint32]TblMap{ + 1: {"db.tbl": {SourceDbName: "db", SourceTblName: "tbl"}}, + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + td.processCallback(context.Background(), tables) + }() + + <-enter + regDone := make(chan struct{}) + go func() { + did := td.RegisterIfAbsent("task-2", 1, []string{"db"}, []string{"tbl"}, second) + if !did { + panic("register failed") + } + close(regDone) + }() + + <-regDone + close(release) + wg.Wait() + + // Next callback invocation should execute both callbacks. + td.processCallback(context.Background(), tables) + + if firstCount.Load() != 2 { + t.Fatalf("unexpected first count: %d", firstCount.Load()) + } + if secondCount.Load() != 1 { + t.Fatalf("unexpected second count: %d", secondCount.Load()) + } +} + +func TestTableDetectorProcessCallbackErrorResetsState(t *testing.T) { + d := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + defer d.Close() + + var count atomic.Int32 + cb := func(map[uint32]TblMap) error { + count.Add(1) + return moerr.NewInternalErrorNoCtx("boom") + } + + require.True(t, d.RegisterIfAbsent("task", 1, []string{"db"}, []string{"tbl"}, cb)) + tables := map[uint32]TblMap{1: {"db.tbl": {SourceDbName: "db", SourceTblName: "tbl"}}} + + d.mu.Lock() + d.lastMp = tables + d.mu.Unlock() + + d.processCallback(context.Background(), tables) + d.processCallback(context.Background(), tables) + + if count.Load() != 2 { + t.Fatalf("callback count %d", count.Load()) + } + if d.handling { + t.Fatalf("handling flag not reset") + } + if d.lastMp == nil { + t.Fatalf("lastMp should be retained on error") + } +} + +func TestTableDetectorProcessCallbackPanicHandled(t *testing.T) { + d := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + defer d.Close() + + require.True(t, d.RegisterIfAbsent("task", 1, []string{"db"}, []string{"tbl"}, func(map[uint32]TblMap) error { + panic("panic in callback") + })) + + tables := map[uint32]TblMap{1: {"db.tbl": {SourceDbName: "db", SourceTblName: "tbl"}}} + + func() { + defer func() { _ = recover() }() + d.processCallback(context.Background(), tables) + }() + + if d.handling { + t.Fatalf("handling flag not reset after panic") + } +} + +func TestTableDetectorCloseWhileCallbackRunning(t *testing.T) { + d := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + defer d.Close() + + fault.Enable() + defer fault.Disable() + rmFn, err := objectio.InjectCDCScanTable("fast scan") + require.NoError(t, err) + defer func() { + if rmFn != nil { + _, _ = rmFn() + } + }() + + block := make(chan struct{}) + release := make(chan struct{}) + + require.True(t, d.RegisterIfAbsent("task", 1, []string{"db"}, []string{"tbl"}, func(map[uint32]TblMap) error { + close(block) + <-release + return nil + })) + + tables := map[uint32]TblMap{1: {"db.tbl": {SourceDbName: "db", SourceTblName: "tbl"}}} + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + d.processCallback(context.Background(), tables) + }() + + <-block + d.Close() + close(release) + wg.Wait() + + d.mu.Lock() + if d.handling { + d.mu.Unlock() + t.Fatalf("handling flag not reset after close") + } + d.mu.Unlock() + + require.Eventually(t, func() bool { + d.mu.Lock() + defer d.mu.Unlock() + return d.cancel == nil && !d.loopRunning.Load() + }, 5*time.Second, 10*time.Millisecond, "detector not fully closed") +} + +func TestTableDetectorConcurrentRegisterUnregister(t *testing.T) { + fault.Enable() + defer fault.Disable() + rmFn, err := objectio.InjectCDCScanTable("fast scan") + require.NoError(t, err) + defer func() { + if rmFn != nil { + _, _ = rmFn() + } + }() + + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + td.scanTableFn = func() error { return nil } + defer td.Close() + + const workers = 16 + var wg sync.WaitGroup + wg.Add(workers) + errCh := make(chan error, workers) + + for i := 0; i < workers; i++ { + go func(idx int) { + defer wg.Done() + id := fmt.Sprintf("task-%d", idx) + if !td.RegisterIfAbsent(id, uint32(idx+1), []string{fmt.Sprintf("db%d", idx)}, []string{fmt.Sprintf("tbl%d", idx)}, func(map[uint32]TblMap) error { return nil }) { + errCh <- moerr.NewInternalErrorNoCtx(fmt.Sprintf("register failed for %s", id)) + return + } + time.Sleep(time.Duration(idx%4) * 5 * time.Millisecond) + td.UnRegister(id) + }(i) + } + + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + + select { + case <-done: + case <-time.After(2 * time.Second): + t.Fatalf("concurrent register/unregister timed out") + } + + close(errCh) + for err := range errCh { + t.Fatalf("unexpected error: %v", err) + } + + waitUntil(t, func() bool { + td.mu.Lock() + defer td.mu.Unlock() + return len(td.Callbacks) == 0 && + len(td.SubscribedAccountIds) == 0 && + len(td.SubscribedDbNames) == 0 && + len(td.SubscribedTableNames) == 0 + }, 500*time.Millisecond, "callbacks or subscriptions not cleaned up") + + td.Close() + waitUntil(t, func() bool { return !td.loopRunning.Load() }, time.Second, "scan loop did not stop after Close") +} + +func waitUntil(t *testing.T, cond func() bool, timeout time.Duration, msg string) { + t.Helper() + deadline := time.Now().Add(timeout) + for { + if cond() { + return + } + if time.Now().After(deadline) { + t.Fatalf("timeout waiting for condition: %s", msg) + } + time.Sleep(5 * time.Millisecond) + } +} + +func TestTableDetectorConcurrentRegister(t *testing.T) { + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + cleanupPeriod: time.Second, + cleanupWarn: time.Second, + nowFn: time.Now, + } + td.scanTableFn = func() error { return nil } + defer td.Close() + + const concurrency = 8 + var wg sync.WaitGroup + wg.Add(concurrency) + errCh := make(chan error, concurrency) + for i := 0; i < concurrency; i++ { + go func(idx int) { + defer wg.Done() + taskID := fmt.Sprintf("task-%d", idx) + db := fmt.Sprintf("db%d", idx) + table := fmt.Sprintf("tbl%d", idx) + if !td.RegisterIfAbsent(taskID, uint32(idx+1), []string{db}, []string{table}, func(map[uint32]TblMap) error { + return nil + }) { + errCh <- moerr.NewInternalErrorNoCtx(fmt.Sprintf("duplicate registration for %s", taskID)) + } + }(i) + } + + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + + select { + case <-done: + case <-time.After(2 * time.Second): + t.Fatalf("concurrent register blocked") + } + + close(errCh) + for err := range errCh { + t.Fatalf("unexpected duplicate: %v", err) + } + + td.mu.Lock() + defer td.mu.Unlock() + if len(td.Callbacks) != concurrency { + t.Fatalf("expected %d callbacks, got %d", concurrency, len(td.Callbacks)) + } +} + func Test_CollectTableInfoSQL(t *testing.T) { var builder cdcSQLBuilder sql := builder.CollectTableInfoSQL("1,2,3", "*", "*") @@ -161,10 +698,19 @@ func TestScanAndProcess(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - td := newTableDetector( - nil, - WithTableDetectorCleanupPeriod(time.Hour), - ) + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + exec: nil, + cleanupPeriod: time.Hour, + cleanupWarn: DefaultCleanupWarnThreshold, + } defer td.Close() tables := map[uint32]TblMap{ @@ -207,11 +753,20 @@ func TestProcessCallBack(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - td := newTableDetector( - nil, - WithTableDetectorCleanupPeriod(time.Hour), - ) - td.lastMp = make(map[uint32]TblMap) + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + exec: nil, + lastMp: make(map[uint32]TblMap), + cleanupPeriod: time.Hour, + cleanupWarn: DefaultCleanupWarnThreshold, + } defer td.Close() tables := map[uint32]TblMap{ @@ -226,7 +781,7 @@ func TestProcessCallBack(t *testing.T) { }, }, } - td.Register("id1", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return moerr.NewInternalErrorNoCtx("ERR") }) + assert.True(t, td.RegisterIfAbsent("id1", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return moerr.NewInternalErrorNoCtx("ERR") })) assert.Equal(t, 1, len(td.Callbacks)) td.mu.Lock() td.lastMp = tables @@ -335,14 +890,23 @@ func TestTableScanner_UpdateTableInfo(t *testing.T) { gomock.Any(), ).Return(res2, nil) - td := newTableDetector( - mockSqlExecutor, - WithTableDetectorCleanupPeriod(time.Hour), - ) + td := &TableDetector{ + Mp: make(map[uint32]TblMap), + Callbacks: make(map[string]TableCallback), + CallBackAccountId: make(map[string]uint32), + SubscribedAccountIds: make(map[uint32][]string), + CallBackDbName: make(map[string][]string), + SubscribedDbNames: make(map[string][]string), + CallBackTableName: make(map[string][]string), + SubscribedTableNames: make(map[string][]string), + exec: mockSqlExecutor, + cleanupPeriod: time.Hour, + cleanupWarn: DefaultCleanupWarnThreshold, + } defer td.Close() - td.Register("test-task", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { + assert.True(t, td.RegisterIfAbsent("test-task", 1, []string{"db1"}, []string{"tbl1"}, func(mp map[uint32]TblMap) error { return nil - }) + })) err := td.scanTable() assert.NoError(t, err) diff --git a/pkg/cdc/testutil.go b/pkg/cdc/testutil.go index c616443295055..d082fc8075bbb 100644 --- a/pkg/cdc/testutil.go +++ b/pkg/cdc/testutil.go @@ -605,7 +605,15 @@ func (m *mockSQLExecutor) Insert( // pkColumnIds: [1, 0] pkColumnIds := make([]int, len(pkColumns)) for i, pk := range pkColumns { - pkColumnIds[i] = columnsIdMap[columnIds[pk]] + fullColIdx, ok := columnIds[pk] + if !ok { + return moerr.NewInternalErrorNoCtxf("primary key column %s not found in table columns", pk) + } + inputColIdx, ok := columnsIdMap[fullColIdx] + if !ok { + return moerr.NewInternalErrorNoCtxf("primary key column %s not found in input columns", pk) + } + pkColumnIds[i] = inputColIdx } // insert mode check: @@ -652,6 +660,9 @@ func (m *mockSQLExecutor) Insert( for _, tuple := range tuples { pkValues = pkValues[:0] for _, id := range pkColumnIds { + if id >= len(tuple) { + return moerr.NewInternalErrorNoCtxf("primary key column index %d out of range (tuple length: %d)", id, len(tuple)) + } pkValues = append(pkValues, tuple[id]) } pkValue := strings.Join(pkValues, ",") @@ -661,8 +672,23 @@ func (m *mockSQLExecutor) Insert( continue } oldRow := tableData[offset] + // Only update columns that are present in the input tuple + // i is the input column index, columns[i] is the column name + // columnIds[columns[i]] is the full column index in the table for i, cell := range tuple { - oldRow[columnsIdMap[i]] = cell + if i >= len(columns) { + return moerr.NewInternalErrorNoCtxf("tuple index %d out of range (columns length: %d)", i, len(columns)) + } + columnName := columns[i] + fullColIdx, ok := columnIds[columnName] + if !ok { + // Column not found in table - skip (shouldn't happen if SQL is correct) + continue + } + if fullColIdx >= len(oldRow) { + return moerr.NewInternalErrorNoCtxf("column index %d out of range (row length: %d)", fullColIdx, len(oldRow)) + } + oldRow[fullColIdx] = cell } tableData[offset] = oldRow } @@ -724,7 +750,7 @@ func initMockSQLExecutorForWatermarkUpdater(t *testing.T) *mockSQLExecutor { ie.CreateTable( "mo_catalog", "mo_cdc_watermark", - []string{"account_id", "task_id", "db_name", "table_name", "err_msg"}, + []string{"account_id", "task_id", "db_name", "table_name", "watermark", "err_msg"}, []string{"account_id", "task_id", "db_name", "table_name"}, ) return ie diff --git a/pkg/cdc/types.go b/pkg/cdc/types.go index 4064e1bdf9708..c29b27f26cd77 100644 --- a/pkg/cdc/types.go +++ b/pkg/cdc/types.go @@ -310,6 +310,10 @@ type AtomicBatch struct { Mp *mpool.MPool Batches []*batch.Batch Rows *btree.BTreeG[AtomicBatchRow] + + totalRows int + duplicateRows int + duplicateLogged bool } func NewAtomicBatch(mp *mpool.MPool) *AtomicBatch { @@ -343,22 +347,24 @@ func (row AtomicBatchRow) Less(other AtomicBatchRow) bool { } func (bat *AtomicBatch) RowCount() int { - c := 0 - for _, b := range bat.Batches { - rows := 0 - if b != nil && len(b.Vecs) > 0 { - rows = b.Vecs[0].Length() - } - c += rows - } - - if c != bat.Rows.Len() { - logutil.Error("cdc.atomic_batch.row_count_mismatch", - zap.Int("batch-rows", c), - zap.Int("btree-rows", bat.Rows.Len()), + unique := bat.Rows.Len() + if bat.duplicateRows > 0 && !bat.duplicateLogged { + logutil.Warn("cdc.atomic_batch.dedup", + zap.Int("unique-rows", unique), + zap.Int("total-rows", bat.totalRows), + zap.Int("duplicate-rows", bat.duplicateRows), ) + bat.duplicateLogged = true } - return c + return unique +} + +func (bat *AtomicBatch) TotalRows() int { + return bat.totalRows +} + +func (bat *AtomicBatch) DuplicateRows() int { + return bat.duplicateRows } func (bat *AtomicBatch) Allocated() int { @@ -398,7 +404,11 @@ func (bat *AtomicBatch) Append( Offset: i, Src: batch, } - bat.Rows.Set(row) + _, replaced := bat.Rows.Set(row) + bat.totalRows++ + if replaced { + bat.duplicateRows++ + } } bat.Batches = append(bat.Batches, batch) @@ -415,6 +425,9 @@ func (bat *AtomicBatch) Close() { } bat.Batches = nil bat.Mp = nil + bat.totalRows = 0 + bat.duplicateRows = 0 + bat.duplicateLogged = false } func (bat *AtomicBatch) GetRowIterator() RowIterator { diff --git a/pkg/cdc/types_test.go b/pkg/cdc/types_test.go index 878395728a009..c117b26051611 100644 --- a/pkg/cdc/types_test.go +++ b/pkg/cdc/types_test.go @@ -203,6 +203,27 @@ func Test_atomicBatchRowIter(t *testing.T) { iter.Close() } +func TestAtomicBatch_RowCountDeduplicates(t *testing.T) { + bat := NewAtomicBatch(testutil.TestUtilMp) + ts := types.BuildTS(10, 2) + + createBatch := func(pk int32) *batch.Batch { + b := batch.New([]string{"pk", "ts"}) + b.Vecs[0] = testutil.MakeInt32Vector([]int32{pk}, nil) + b.Vecs[1] = testutil.MakeTSVector([]types.TS{ts}, nil) + return b + } + + bat.Append(types.NewPacker(), createBatch(42), 1, 0) + bat.Append(types.NewPacker(), createBatch(42), 1, 0) // duplicate pk+ts + bat.Append(types.NewPacker(), createBatch(43), 1, 0) // unique pk + + assert.Equal(t, 2, bat.RowCount()) + assert.Equal(t, 3, bat.TotalRows()) + assert.Equal(t, 1, bat.DuplicateRows()) + assert.Equal(t, 2, bat.Rows.Len()) +} + func TestDbTableInfo_String(t *testing.T) { type fields struct { SourceDbName string diff --git a/pkg/cdc/watermark_updater.go b/pkg/cdc/watermark_updater.go index 7e7ae167d5c4a..369cd8deeea81 100644 --- a/pkg/cdc/watermark_updater.go +++ b/pkg/cdc/watermark_updater.go @@ -59,6 +59,7 @@ package cdc import ( "context" + "errors" "fmt" "strings" "sync" @@ -90,6 +91,7 @@ const ( const ( watermarkCommitMaxRetries = 3 watermarkCircuitBreakPeriod = 30 * time.Second + fallbackLogThrottleWindow = time.Second ) var cdcWatermarkUpdater atomic.Pointer[CDCWatermarkUpdater] @@ -313,6 +315,8 @@ type CDCWatermarkUpdater struct { errorTimes atomic.Uint64 lastExportTime time.Time } + + fallbackLog sync.Map } func NewCDCWatermarkUpdater( @@ -430,21 +434,45 @@ func (u *CDCWatermarkUpdater) onJobs(jobs ...any) { u.committingBuffer = append(u.committingBuffer, job) case JT_CDC_UpdateWMErrMsg: if _, err := u.GetFromCache(context.Background(), job.Key); err != nil { - job.DoneWithErr(err) - continue + if !errors.Is(err, ErrNoWatermarkFound) { + job.DoneWithErr(err) + continue + } + if _, exists := u.readKeysBuffer[*job.Key]; !exists { + u.readKeysBuffer[*job.Key] = WatermarkResult{} + } } u.committingErrMsgBuffer = append(u.committingErrMsgBuffer, job) case JT_CDC_RemoveCachedWM: + var inCommitted bool u.Lock() if _, ok := u.cacheCommitted[*job.Key]; ok { delete(u.cacheCommitted, *job.Key) - job.DoneWithErr(nil) + inCommitted = true } + delete(u.cacheUncommitted, *job.Key) + delete(u.cacheCommitting, *job.Key) + delete(u.errorMetadataCache, *job.Key) + if openedAt, opened := u.commitCircuitOpen[*job.Key]; opened { + if time.Since(openedAt) < watermarkCircuitBreakPeriod { + v2.CdcWatermarkCircuitEventCounter.WithLabelValues("reset").Inc() + v2.CdcWatermarkCircuitOpenGauge.Dec() + } + delete(u.commitCircuitOpen, *job.Key) + } + delete(u.commitFailureCount, *job.Key) u.Unlock() - logutil.Info( - "cdc.watermark.remove_cached_success", + + job.DoneWithErr(nil) + + fields := []zap.Field{ zap.String("key", job.Key.String()), - ) + } + if inCommitted { + logutil.Info("cdc.watermark.remove_cached_success", fields...) + } else { + logutil.Info("cdc.watermark.remove_cached_skip", fields...) + } default: logutil.Fatal("unknown job type", zap.Int("job-type", int(job.Type()))) } @@ -529,6 +557,11 @@ func (u *CDCWatermarkUpdater) execReadWM() (errMsg string, err error) { // the jobs in the addCommittedBuffer will be processed in the `execAddWM` u.Lock() defer u.Unlock() + for key, result := range u.readKeysBuffer { + if result.Ok { + u.cacheCommitted[key] = result.Watermark + } + } for i, job := range u.getOrAddCommittedBuffer { if u.readKeysBuffer[*job.Key].Ok { u.cacheCommitted[*job.Key] = u.readKeysBuffer[*job.Key].Watermark @@ -891,6 +924,17 @@ func (u *CDCWatermarkUpdater) UpdateWatermarkErrMsg( job := NewUpdateWMErrMsgJob(ctx, key, "") if _, err = u.queue.Enqueue(job); err != nil { + if errors.Is(err, sm.ErrClose) { + if u.shouldLogFallback(key) { + logutil.Info( + "cdc.watermark.update_errmsg_fallback", + zap.String("key", key.String()), + zap.Bool("clear", true), + zap.Bool("retryable", false), + ) + } + return nil + } return } job.WaitDone() @@ -982,6 +1026,18 @@ func (u *CDCWatermarkUpdater) UpdateWatermarkErrMsg( job := NewUpdateWMErrMsgJob(ctx, key, formattedMsg) if _, err = u.queue.Enqueue(job); err != nil { + if errors.Is(err, sm.ErrClose) { + if u.shouldLogFallback(key) { + logutil.Info( + "cdc.watermark.update_errmsg_fallback", + zap.String("key", key.String()), + zap.Bool("clear", false), + zap.Bool("retryable", newMetadata.IsRetryable), + zap.Int("retry-count", newMetadata.RetryCount), + ) + } + return nil + } return } job.WaitDone() @@ -1047,22 +1103,77 @@ func (u *CDCWatermarkUpdater) RemoveCachedWM( key *WatermarkKey, ) (err error) { if err = u.ForceFlush(ctx); err != nil { - logutil.Error( + logutil.Warn( "cdc.watermark.remove.force_flush_failed", zap.String("key", key.String()), zap.Error(err), ) - return + // Continue even if flush fails } job := NewRemoveCachedWMJob(ctx, key) if _, err = u.queue.Enqueue(job); err != nil { - return + if errors.Is(err, sm.ErrClose) { + u.removeCachedWMSynchronously(key, true) + return nil + } + job.DoneWithErr(err) + return err } job.WaitDone() err = job.GetResult().Err return } +func (u *CDCWatermarkUpdater) removeCachedWMSynchronously(key *WatermarkKey, logSkip bool) { + var inCommitted bool + u.Lock() + if _, ok := u.cacheCommitted[*key]; ok { + delete(u.cacheCommitted, *key) + inCommitted = true + } + delete(u.cacheUncommitted, *key) + delete(u.cacheCommitting, *key) + delete(u.errorMetadataCache, *key) + if openedAt, opened := u.commitCircuitOpen[*key]; opened { + if time.Since(openedAt) < watermarkCircuitBreakPeriod { + v2.CdcWatermarkCircuitEventCounter.WithLabelValues("reset").Inc() + v2.CdcWatermarkCircuitOpenGauge.Dec() + } + delete(u.commitCircuitOpen, *key) + } + delete(u.commitFailureCount, *key) + u.Unlock() + + if !u.shouldLogFallback(key) { + return + } + + fields := []zap.Field{ + zap.String("key", key.String()), + zap.Bool("fallback", true), + } + if inCommitted { + logutil.Info("cdc.watermark.remove_cached_success", fields...) + } else if logSkip { + logutil.Info("cdc.watermark.remove_cached_skip", fields...) + } +} + +func (u *CDCWatermarkUpdater) shouldLogFallback(key *WatermarkKey) bool { + if key == nil { + return true + } + now := time.Now() + ks := key.String() + if prev, ok := u.fallbackLog.Load(ks); ok { + if elapsed := now.Sub(prev.(time.Time)); elapsed < fallbackLogThrottleWindow { + return false + } + } + u.fallbackLog.Store(ks, now) + return true +} + func (u *CDCWatermarkUpdater) ForceFlush(ctx context.Context) (err error) { job := NewCommittingWMJob(ctx) if err = u.customized.scheduleJob(job); err != nil { @@ -1132,6 +1243,25 @@ func (u *CDCWatermarkUpdater) GetOrAddCommitted( job := NewGetOrAddCommittedWMJob(ctx, key, watermark) if _, err = u.queue.Enqueue(job); err != nil { + if errors.Is(err, sm.ErrClose) { + if watermark != nil { + u.Lock() + u.cacheCommitted[*key] = *watermark + u.Unlock() + ret = *watermark + } + if u.shouldLogFallback(key) { + fields := []zap.Field{ + zap.String("key", key.String()), + zap.Bool("fallback", true), + } + if watermark != nil { + fields = append(fields, zap.String("watermark", watermark.ToString())) + } + logutil.Info("cdc.watermark.get_or_add_fallback", fields...) + } + return ret, nil + } return } job.WaitDone() diff --git a/pkg/cdc/watermark_updater_retry_test.go b/pkg/cdc/watermark_updater_retry_test.go index 9cb75e893e601..154504087934d 100644 --- a/pkg/cdc/watermark_updater_retry_test.go +++ b/pkg/cdc/watermark_updater_retry_test.go @@ -45,10 +45,16 @@ func waitForErrorMetadata(t *testing.T, fetcher watermarkRowFetcher, key *Waterm "mo_cdc_watermark", []string{fmt.Sprintf("%d", key.AccountId), key.TaskId, key.DBName, key.TableName}, ) - if err != nil || len(tuple) < 5 { + // Table now has 6 columns: account_id, task_id, db_name, table_name, watermark, err_msg + if err != nil || len(tuple) < 6 { + return false + } + // err_msg is at index 5 (watermark is at index 4) + msg = strings.Trim(tuple[5], "'") + // Skip if err_msg is empty (no error yet) + if msg == "" { return false } - msg = strings.Trim(tuple[4], "'") meta = ParseErrorMetadata(msg) if cond == nil { return meta != nil diff --git a/pkg/cdc/watermark_updater_test.go b/pkg/cdc/watermark_updater_test.go index 859ae0c6b53b3..17a9bef595e6b 100644 --- a/pkg/cdc/watermark_updater_test.go +++ b/pkg/cdc/watermark_updater_test.go @@ -319,6 +319,177 @@ func TestWatermarkUpdater_ForceFlushCircuitBreakerIntegration(t *testing.T) { require.Greater(t, exec.execCalls, prevCalls) } +func TestWatermarkUpdater_RemoveCachedWM_Idempotent(t *testing.T) { + exec := &retryableMockExecutor{} + var syncOption UpdateOption = func(u *CDCWatermarkUpdater) { + u.customized.scheduleJob = func(job *UpdaterJob) error { + u.onJobs(job) + return nil + } + u.customized.cronJob = func(ctx context.Context) {} + } + updater := NewCDCWatermarkUpdater("remove-idempotent", exec, syncOption) + + ctx := context.Background() + key := WatermarkKey{ + AccountId: 5, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + ts := types.BuildTS(50, 1) + + require.NoError(t, updater.UpdateWatermarkOnly(ctx, &key, &ts)) + require.NoError(t, updater.ForceFlush(ctx)) + require.NoError(t, updater.RemoveCachedWM(ctx, &key)) + + updater.RLock() + _, committedExists := updater.cacheCommitted[key] + _, uncommittedExists := updater.cacheUncommitted[key] + _, committingExists := updater.cacheCommitting[key] + _, errMetaExists := updater.errorMetadataCache[key] + updater.RUnlock() + + require.False(t, committedExists) + require.False(t, uncommittedExists) + require.False(t, committingExists) + require.False(t, errMetaExists) + + require.NoError(t, updater.RemoveCachedWM(ctx, &key)) +} + +func TestWatermarkUpdater_RemoveCachedWM_NoExisting(t *testing.T) { + exec := &retryableMockExecutor{} + var syncOption UpdateOption = func(u *CDCWatermarkUpdater) { + u.customized.scheduleJob = func(job *UpdaterJob) error { + u.onJobs(job) + return nil + } + u.customized.cronJob = func(ctx context.Context) {} + } + updater := NewCDCWatermarkUpdater("remove-noexisting", exec, syncOption) + + ctx := context.Background() + key := WatermarkKey{ + AccountId: 6, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + + require.NoError(t, updater.RemoveCachedWM(ctx, &key)) +} + +func TestWatermarkUpdater_RemoveCachedWM_AfterStopUsesFallback(t *testing.T) { + exec := &retryableMockExecutor{} + updater := NewCDCWatermarkUpdater("remove-after-stop", exec) + updater.Start() + updater.Stop() + + ctx := context.Background() + key := WatermarkKey{ + AccountId: 7, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + ts := types.BuildTS(70, 2) + now := time.Now() + + updater.Lock() + updater.cacheCommitted[key] = ts + updater.cacheUncommitted[key] = ts + updater.cacheCommitting[key] = ts + updater.errorMetadataCache[key] = &ErrorMetadata{ + IsRetryable: true, + RetryCount: 3, + FirstSeen: now, + LastSeen: now, + Message: "fallback cleanup", + } + updater.commitCircuitOpen[key] = now + updater.commitFailureCount[key] = 2 + updater.Unlock() + + require.NoError(t, updater.RemoveCachedWM(ctx, &key)) + + updater.RLock() + _, inCommitted := updater.cacheCommitted[key] + _, inUncommitted := updater.cacheUncommitted[key] + _, inCommitting := updater.cacheCommitting[key] + _, hasErrMeta := updater.errorMetadataCache[key] + _, circuitOpen := updater.commitCircuitOpen[key] + _, failureCount := updater.commitFailureCount[key] + updater.RUnlock() + + require.False(t, inCommitted) + require.False(t, inUncommitted) + require.False(t, inCommitting) + require.False(t, hasErrMeta) + require.False(t, circuitOpen) + require.False(t, failureCount) + + _, logExists := updater.fallbackLog.Load(key.String()) + require.True(t, logExists) +} + +func TestWatermarkUpdater_UpdateErrMsg_AfterStopUsesFallback(t *testing.T) { + exec := &retryableMockExecutor{} + updater := NewCDCWatermarkUpdater("update-errmsg-after-stop", exec) + updater.Start() + updater.Stop() + + ctx := context.Background() + key := WatermarkKey{ + AccountId: 9, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + + require.NoError(t, updater.UpdateWatermarkErrMsg(ctx, &key, "retryable error:temporary", nil)) + + updater.RLock() + meta, exists := updater.errorMetadataCache[key] + updater.RUnlock() + require.True(t, exists) + require.True(t, meta.IsRetryable) + require.Equal(t, 1, meta.RetryCount) + + require.NoError(t, updater.UpdateWatermarkErrMsg(ctx, &key, "", nil)) + + updater.RLock() + _, exists = updater.errorMetadataCache[key] + updater.RUnlock() + require.False(t, exists) +} + +func TestWatermarkUpdater_GetOrAddCommitted_AfterStopUsesFallback(t *testing.T) { + exec := &retryableMockExecutor{} + updater := NewCDCWatermarkUpdater("get-or-add-after-stop", exec) + updater.Start() + updater.Stop() + + ctx := context.Background() + key := WatermarkKey{ + AccountId: 10, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + ts := types.BuildTS(80, 3) + + ret, err := updater.GetOrAddCommitted(ctx, &key, &ts) + require.NoError(t, err) + require.True(t, ret.Equal(&ts)) + + updater.RLock() + committed, ok := updater.cacheCommitted[key] + updater.RUnlock() + require.True(t, ok) + require.True(t, committed.Equal(&ts)) +} + func TestWatermarkUpdater_CircuitBreakerHelpers(t *testing.T) { exec := &retryableMockExecutor{failRemaining: watermarkCommitMaxRetries} var syncOption UpdateOption = func(u *CDCWatermarkUpdater) { @@ -1297,8 +1468,7 @@ func TestCDCWatermarkUpdater_UpdateWatermarkErrMsg(t *testing.T) { "err1", nil, // Legacy format ) - // should be error because the watermark is not found - assert.Error(t, err) + assert.NoError(t, err) ts := types.BuildTS(1, 1) ret, err := u.GetOrAddCommitted( @@ -1323,18 +1493,44 @@ func TestCDCWatermarkUpdater_UpdateWatermarkErrMsg(t *testing.T) { []string{fmt.Sprintf("%d", key.AccountId), key.TaskId, key.DBName, key.TableName}, ) assert.NoError(t, err) - assert.Len(t, tuple, 5) + // Table now has 6 columns: account_id, task_id, db_name, table_name, watermark, err_msg + assert.Len(t, tuple, 6) assert.Equal(t, fmt.Sprintf("%d", key.AccountId), tuple[0]) assert.Equal(t, key.TaskId, tuple[1]) assert.Equal(t, key.DBName, tuple[2]) assert.Equal(t, key.TableName, tuple[3]) + // tuple[4] is watermark + // tuple[5] is err_msg // Error message is now formatted as "N:timestamp:message" (non-retryable) // Note: In "N:timestamp:message" format, retry count is always 0 (not tracked for non-retryable) - formattedErrMsg := tuple[4] + formattedErrMsg := tuple[5] metadata := ParseErrorMetadata(formattedErrMsg) require.NotNil(t, metadata) assert.False(t, metadata.IsRetryable) assert.Equal(t, 0, metadata.RetryCount) // Non-retryable format doesn't track retry count assert.Contains(t, metadata.Message, "err1") } + +func TestCDCWatermarkUpdater_RemoveThenUpdateErrMsg(t *testing.T) { + ctx := context.Background() + updater, _ := InitCDCWatermarkUpdaterForTest(t) + updater.Start() + defer updater.Stop() + + key := &WatermarkKey{ + AccountId: 1, + TaskId: "task", + DBName: "db", + TableName: "tbl", + } + wm := types.BuildTS(100, 0) + + require.NoError(t, updater.UpdateWatermarkOnly(ctx, key, &wm)) + require.NoError(t, updater.ForceFlush(ctx)) + require.NoError(t, updater.RemoveCachedWM(ctx, key)) + + // UpdateWatermarkErrMsg is expected to succeed even after RemoveCachedWM; current implementation returns ErrNoWatermarkFound. + err := updater.UpdateWatermarkErrMsg(ctx, key, "boom", nil) + require.NoError(t, err) +} diff --git a/pkg/common/bloomfilter/bloomfilter.go b/pkg/common/bloomfilter/bloomfilter.go index ce2a3f54f8f30..4d4b2926e0f38 100644 --- a/pkg/common/bloomfilter/bloomfilter.go +++ b/pkg/common/bloomfilter/bloomfilter.go @@ -15,8 +15,13 @@ package bloomfilter import ( + "bytes" + + "github.com/matrixorigin/matrixone/pkg/common/bitmap" "github.com/matrixorigin/matrixone/pkg/common/hashmap" + "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/container/hashtable" + "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" ) @@ -114,6 +119,81 @@ func (bf *BloomFilter) TestAndAdd(v *vector.Vector, callBack func(bool, int)) { } +// Marshal encodes BloomFilter into byte sequence for transmission via runtime filter message within the same CN. +// Encoding format: +// +// [seedCount:uint32][seeds...:uint64][bitmapLen:uint32][bitmapBytes...] +func (bf *BloomFilter) Marshal() ([]byte, error) { + var buf bytes.Buffer + + seedCount := uint32(len(bf.hashSeed)) + buf.Write(types.EncodeUint32(&seedCount)) + for i := 0; i < int(seedCount); i++ { + buf.Write(types.EncodeUint64(&bf.hashSeed[i])) + } + + bmBytes := bf.bitmap.Marshal() + bmLen := uint32(len(bmBytes)) + buf.Write(types.EncodeUint32(&bmLen)) + buf.Write(bmBytes) + + return buf.Bytes(), nil +} + +// Unmarshal restores BloomFilter from byte sequence. +// Initializes internal structures (keys / states / vals / addVals) based on encoded seedCount and bitmap. +func (bf *BloomFilter) Unmarshal(data []byte) error { + if len(data) < 4 { + return moerr.NewInternalErrorNoCtx("invalid bloomfilter data") + } + + seedCount := int(types.DecodeUint32(data[:4])) + data = data[4:] + + if seedCount <= 0 { + return moerr.NewInternalErrorNoCtx("invalid bloomfilter seed count") + } + + hashSeed := make([]uint64, seedCount) + for i := 0; i < seedCount; i++ { + if len(data) < 8 { + return moerr.NewInternalErrorNoCtx("invalid bloomfilter data (seed truncated)") + } + hashSeed[i] = types.DecodeUint64(data[:8]) + data = data[8:] + } + + if len(data) < 4 { + return moerr.NewInternalErrorNoCtx("invalid bloomfilter data (no bitmap length)") + } + bmLen := int(types.DecodeUint32(data[:4])) + data = data[4:] + if bmLen < 0 || len(data) < bmLen { + return moerr.NewInternalErrorNoCtx("invalid bloomfilter data (bitmap truncated)") + } + + var bm bitmap.Bitmap + bm.Unmarshal(data[:bmLen]) + + // Reinitialize internal auxiliary structures for subsequent Test/TestAndAdd + vals := make([][]uint64, hashmap.UnitLimit) + keys := make([][]byte, hashmap.UnitLimit) + states := make([][3]uint64, hashmap.UnitLimit) + for j := 0; j < hashmap.UnitLimit; j++ { + vals[j] = make([]uint64, seedCount*3) + } + + bf.bitmap = bm + bf.hashSeed = hashSeed + bf.keys = keys + bf.states = states + bf.vals = vals + bf.addVals = make([]uint64, hashmap.UnitLimit*3*seedCount) + bf.valLength = len(hashSeed) * 3 + + return nil +} + // for an incoming vector, compute the hash value of each of its elements, and manipulate it with func tf.fn func (bf *BloomFilter) handle(v *vector.Vector, callBack func(int, int)) { length := v.Length() diff --git a/pkg/common/bloomfilter/bloomfilter_test.go b/pkg/common/bloomfilter/bloomfilter_test.go index a147f51b75d63..9a704e72898d7 100644 --- a/pkg/common/bloomfilter/bloomfilter_test.go +++ b/pkg/common/bloomfilter/bloomfilter_test.go @@ -111,3 +111,157 @@ func BenchmarkBloomFiltrerTestAndAdd(b *testing.B) { } } } + +func TestMarshal(t *testing.T) { + mp := mpool.MustNewZero() + vec := testutil.NewVector(testCount, types.New(types.T_int64, 0, 0), mp, false, nil) + defer vec.Free(mp) + + bf := New(testCount, testRate) + bf.Add(vec) + + data, err := bf.Marshal() + require.NoError(t, err) + require.NotNil(t, data) + require.Greater(t, len(data), 0) + + // Verify basic structure: should have at least seedCount (4 bytes) + some seeds + bitmapLen (4 bytes) + bitmap data + require.GreaterOrEqual(t, len(data), 8, "marshaled data should have at least seedCount and bitmapLen") +} + +func TestUnmarshal(t *testing.T) { + mp := mpool.MustNewZero() + vec := testutil.NewVector(testCount, types.New(types.T_int64, 0, 0), mp, false, nil) + defer vec.Free(mp) + + // Test normal case: marshal and unmarshal + bf1 := New(testCount, testRate) + bf1.Add(vec) + + data, err := bf1.Marshal() + require.NoError(t, err) + + bf2 := BloomFilter{} + err = bf2.Unmarshal(data) + require.NoError(t, err) + + // Verify that unmarshaled filter has same functionality + allFound := true + bf2.Test(vec, func(exists bool, _ int) { + allFound = allFound && exists + }) + require.True(t, allFound, "unmarshaled filter should find all added elements") + + // Test error cases + tests := []struct { + name string + data []byte + wantErr bool + }{ + { + name: "empty data", + data: []byte{}, + wantErr: true, + }, + { + name: "data too short (< 4 bytes)", + data: []byte{1, 2, 3}, + wantErr: true, + }, + { + name: "invalid seed count (0)", + data: []byte{0, 0, 0, 0}, // seedCount = 0 + wantErr: true, + }, + { + name: "seed data truncated", + data: []byte{1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}, // seedCount=1, but only 7 bytes for seed (need 8) + wantErr: true, + }, + { + name: "no bitmap length", + data: []byte{1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}, // seedCount=1, one seed, but no bitmapLen + wantErr: true, + }, + { + name: "bitmap data truncated", + data: []byte{1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 0, 0, 0, 1, 2, 3}, // seedCount=1, one seed, bitmapLen=10, but only 3 bytes + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := BloomFilter{} + err := bf.Unmarshal(tt.data) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMarshalUnmarshal(t *testing.T) { + mp := mpool.MustNewZero() + vecs := make([]*vector.Vector, vecCount) + for i := 0; i < vecCount; i++ { + vecs[i] = testutil.NewVector(testCount/vecCount, types.New(types.T_int64, 0, 0), mp, false, nil) + } + defer func() { + for i := 0; i < vecCount; i++ { + vecs[i].Free(mp) + } + }() + + // Create and populate original filter + bf1 := New(testCount, testRate) + for j := 0; j < vecCount; j++ { + bf1.Add(vecs[j]) + } + + // Marshal + data, err := bf1.Marshal() + require.NoError(t, err) + require.NotNil(t, data) + + // Unmarshal into new filter + bf2 := BloomFilter{} + err = bf2.Unmarshal(data) + require.NoError(t, err) + + // Verify both filters behave the same + testVec := testutil.NewVector(testCount/vecCount, types.New(types.T_int64, 0, 0), mp, false, nil) + defer testVec.Free(mp) + + // Test original filter + allFound1 := true + bf1.Test(testVec, func(exists bool, _ int) { + allFound1 = allFound1 && exists + }) + + // Test unmarshaled filter + allFound2 := true + bf2.Test(testVec, func(exists bool, _ int) { + allFound2 = allFound2 && exists + }) + + require.Equal(t, allFound1, allFound2, "original and unmarshaled filters should behave the same") + + // Test with new data that wasn't added + newVec := testutil.NewVector(testCount*2, types.New(types.T_int64, 0, 0), mp, false, nil) + defer newVec.Free(mp) + + allFoundNew1 := true + bf1.Test(newVec, func(exists bool, _ int) { + allFoundNew1 = allFoundNew1 && exists + }) + + allFoundNew2 := true + bf2.Test(newVec, func(exists bool, _ int) { + allFoundNew2 = allFoundNew2 && exists + }) + + require.Equal(t, allFoundNew1, allFoundNew2, "original and unmarshaled filters should behave the same for new data") +} diff --git a/pkg/common/malloc/c_allocator_cgo_disabled.go b/pkg/common/malloc/c_allocator_cgo_disabled.go index 9878e686de8a4..51a05ba21592a 100644 --- a/pkg/common/malloc/c_allocator_cgo_disabled.go +++ b/pkg/common/malloc/c_allocator_cgo_disabled.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !cgo -// +build !cgo package malloc diff --git a/pkg/common/system/notify_ignore.go b/pkg/common/system/notify_ignore.go index 3c1f7f6d48e3d..99ba6db6869a2 100644 --- a/pkg/common/system/notify_ignore.go +++ b/pkg/common/system/notify_ignore.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux -// +build !linux package system diff --git a/pkg/common/system/notify_linux.go b/pkg/common/system/notify_linux.go index 33027392f5836..56d32369cb63b 100644 --- a/pkg/common/system/notify_linux.go +++ b/pkg/common/system/notify_linux.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build linux -// +build linux package system diff --git a/pkg/container/types/datetime.go b/pkg/container/types/datetime.go index c6911f93a3d2e..c12e3dc905c12 100644 --- a/pkg/container/types/datetime.go +++ b/pkg/container/types/datetime.go @@ -64,8 +64,23 @@ func (dt Datetime) String2(scale int32) string { hour, minute, sec := dt.Clock() if scale > 0 { msec := int64(dt) % MicroSecsPerSec + // Format microseconds as 6 digits (max precision we store) msecInstr := fmt.Sprintf("%06d", msec) - msecInstr = msecInstr[:scale] + // For scale > 6, pad with zeros to the right (e.g., scale 9: "000001" -> "000001000") + if scale > 6 { + // Pad to 9 digits by appending zeros + for len(msecInstr) < 9 { + msecInstr = msecInstr + "0" + } + // Truncate to requested scale (max 9) + if scale > 9 { + scale = 9 + } + msecInstr = msecInstr[:scale] + } else { + // For scale <= 6, truncate from the right + msecInstr = msecInstr[:scale] + } return fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d"+"."+msecInstr, y, m, d, hour, minute, sec) } @@ -101,7 +116,7 @@ func ParseDatetime(s string, scale int32) (Datetime, error) { var carry uint32 = 0 var err error - if s[4] == '-' || s[4] == '/' { + if s[4] == '-' || s[4] == '/' || s[4] == ':' { var num int64 var unum uint64 strArr := strings.Split(s, " ") @@ -109,7 +124,9 @@ func ParseDatetime(s string, scale int32) (Datetime, error) { return -1, moerr.NewInvalidInputNoCtxf("invalid datetime value %s", s) } // solve year/month/day - front := strings.Split(strArr[0], s[4:5]) + // Use the separator found at position 4 (between year and month) + dateSep := s[4:5] + front := strings.Split(strArr[0], dateSep) if len(front) != 3 { return -1, moerr.NewInvalidInputNoCtxf("invalid datetime value %s", s) } @@ -251,19 +268,41 @@ func (dt Datetime) ToDate() Date { // We need to truncate the part after scale position when cast // between different scale. func (dt Datetime) ToTime(scale int32) Time { - if scale == 6 { - return Time(dt % microSecsPerDay) + // Get today's date (the base date used when converting TIME to DATETIME) + todayDate := Today(time.UTC) + todayDatetime := todayDate.ToDatetime() + + // Get the date portion of the datetime + datePart := dt.ToDate() + baseDatetime := datePart.ToDatetime() + + // Calculate time difference from the base date + // If the datetime's date is today or tomorrow (within 1 day), use today as base + // This preserves times > 24 hours that came from ADDTIME with TIME inputs + var timeDiff int64 + dateDiff := int64(datePart) - int64(todayDate) + if dateDiff >= 0 && dateDiff <= 1 { + // Date is today or tomorrow, calculate from today's date + timeDiff = int64(dt) - int64(todayDatetime) + } else { + // Date is far from today, use the date portion of the datetime + timeDiff = int64(dt) - int64(baseDatetime) } - // truncate the date part - ms := dt % microSecsPerDay + // Time type only supports up to 6 digits of microsecond precision + // For scale > 6, use scale 6 (full microsecond precision) + if scale >= 6 { + return Time(timeDiff) + } - base := ms / scaleVal[scale] - if ms%scaleVal[scale]/scaleVal[scale+1] >= 5 { // check carry + // truncate the time part + scaleValInt := int64(scaleVal[scale]) + base := timeDiff / scaleValInt + if scale < 6 && timeDiff%scaleValInt/int64(scaleVal[scale+1]) >= 5 { // check carry base += 1 } - return Time(base * scaleVal[scale]) + return Time(base * scaleValInt) } // TruncateToScale truncates a datetime to the given scale (0-6). @@ -271,8 +310,10 @@ func (dt Datetime) ToTime(scale int32) Time { // - 0: seconds (no fractional part) // - 1-5: fractional seconds with corresponding precision // - 6: microseconds (full precision, no truncation) +// - >6: treated as scale 6 (full precision) func (dt Datetime) TruncateToScale(scale int32) Datetime { - if scale == 6 { + // For scale >= 6, return full precision (no truncation) + if scale >= 6 { return dt } @@ -284,7 +325,7 @@ func (dt Datetime) TruncateToScale(scale int32) Datetime { divisor := scaleVal[scale] base := microPart / divisor // Round up if the next digit >= 5 - if microPart%divisor/scaleVal[scale+1] >= 5 { + if scale < 6 && microPart%divisor/scaleVal[scale+1] >= 5 { base += 1 } diff --git a/pkg/container/types/datetime_test.go b/pkg/container/types/datetime_test.go index 2ffc6b4a24af5..f40fc926dc2d3 100644 --- a/pkg/container/types/datetime_test.go +++ b/pkg/container/types/datetime_test.go @@ -276,6 +276,22 @@ func TestParseDatetime(t *testing.T) { want: "", wantErr: true, }, + // 5. colon separator format (MySQL compatible) + { + name: "colon separator yyyy:mm:dd hh:mm:ss", + args: "2000:01:01 00:00:00", + want: "2000-01-01 00:00:00.000000", + }, + { + name: "colon separator with microseconds", + args: "2000:01:01 00:00:00.000001", + want: "2000-01-01 00:00:00.000001", + }, + { + name: "colon separator with milliseconds", + args: "2000:01:01 12:34:56.123456", + want: "2000-01-01 12:34:56.123456", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -467,3 +483,82 @@ func TestDatetime_String2_NoNewline(t *testing.T) { }) } } + +// TestDatetime_ToTime tests the ToTime method with various scales, including edge cases +// This test ensures that ToTime handles scale > 6 correctly without array bounds issues +func TestDatetime_ToTime(t *testing.T) { + // Test datetime: 2007-12-31 23:59:59.123456 + dt := DatetimeFromClock(2007, 12, 31, 23, 59, 59, 123456) + + testCases := []struct { + name string + datetime Datetime + scale int32 + expected string // Expected time string representation + }{ + { + name: "scale 0 - seconds only", + datetime: dt, + scale: 0, + expected: "23:59:59", + }, + { + name: "scale 1 - 0.1 seconds", + datetime: dt, + scale: 1, + expected: "23:59:59.1", + }, + { + name: "scale 3 - milliseconds", + datetime: dt, + scale: 3, + expected: "23:59:59.123", + }, + { + name: "scale 6 - microseconds", + datetime: dt, + scale: 6, + expected: "23:59:59.123456", + }, + { + name: "scale 7 - should use scale 6 (no panic)", + datetime: dt, + scale: 7, + expected: "23:59:59.1234560", // String2 now supports scale > 6 with padding + }, + { + name: "scale 9 - should use scale 6 (no panic)", + datetime: dt, + scale: 9, + expected: "23:59:59.123456000", // String2 now supports scale > 6 with padding + }, + { + name: "scale 9 with ADDTIME result - should not panic", + // Simulate ADDTIME result with scale 9 + datetime: DatetimeFromClock(2008, 1, 2, 1, 1, 1, 1), + scale: 9, + expected: "01:01:01.000001000", // String2 now supports scale > 6 with padding + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // This should not panic even with scale > 6 + result := tc.datetime.ToTime(tc.scale) + actual := result.String2(tc.scale) + require.Equal(t, tc.expected, actual, "ToTime(%d) should produce correct time string", tc.scale) + }) + } + + // Test the exact case that caused the panic: TIME(ADDTIME(...)) + // ADDTIME('12:30:45', '01:15:30') produces a datetime with scale 9 + time1, _ := ParseTime("12:30:45", 6) + time2, _ := ParseTime("01:15:30", 6) + // Simulate ADDTIME result: convert time to datetime and add + dt1 := time1.ToDatetime(9) // This creates a datetime with scale 9 + dt2 := time2.ToDatetime(9) + resultDt := Datetime(int64(dt1) + int64(dt2)) + // Convert back to TIME - this should not panic + resultTime := resultDt.ToTime(9) + require.Equal(t, "13:46:15.000000", resultTime.String2(6), "TIME(ADDTIME(...)) should work correctly") +} diff --git a/pkg/container/types/encoding.go b/pkg/container/types/encoding.go index ed1b01855f4f9..6d12fa23a4d26 100644 --- a/pkg/container/types/encoding.go +++ b/pkg/container/types/encoding.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !debug -// +build !debug package types diff --git a/pkg/container/types/time.go b/pkg/container/types/time.go index 50853ac4eb89b..d46574613a281 100644 --- a/pkg/container/types/time.go +++ b/pkg/container/types/time.go @@ -50,8 +50,23 @@ func (t Time) String2(scale int32) string { symbol = "-" } if scale > 0 { + // Format microseconds as 6 digits (max precision we store) msecInstr := fmt.Sprintf("%06d", ms) - msecInstr = msecInstr[:scale] + // For scale > 6, pad with zeros to the right (e.g., scale 9: "000001" -> "000001000") + if scale > 6 { + // Pad to 9 digits by appending zeros + for len(msecInstr) < 9 { + msecInstr = msecInstr + "0" + } + // Truncate to requested scale (max 9) + if scale > 9 { + scale = 9 + } + msecInstr = msecInstr[:scale] + } else { + // For scale <= 6, truncate from the right + msecInstr = msecInstr[:scale] + } return fmt.Sprintf("%s%02d:%02d:%02d"+"."+msecInstr, symbol, h, m, s) } return fmt.Sprintf("%s%02d:%02d:%02d", symbol, h, m, s) @@ -66,8 +81,22 @@ func (t Time) NumericString(scale int32) string { symbol = "-" } if scale > 0 { + // Format microseconds as 6 digits (max precision we store) msecInstr := fmt.Sprintf("%06d", ms) - msecInstr = msecInstr[:scale] + // For scale > 6, pad with zeros to the right + // TIME only stores 6 digits of microsecond precision, so we pad with zeros + // to match the requested DECIMAL scale (which can be up to 38) + if scale > 6 { + // Pad to requested scale by appending zeros + for len(msecInstr) < int(scale) { + msecInstr = msecInstr + "0" + } + // Use the full padded string (scale digits) + // No truncation needed since we padded to exactly scale length + } else { + // For scale <= 6, truncate from the right + msecInstr = msecInstr[:scale] + } return fmt.Sprintf("%s%02d%02d%02d"+"."+msecInstr, symbol, h, m, s) } return fmt.Sprintf("%s%02d%02d%02d", symbol, h, m, s) @@ -118,12 +147,12 @@ func ParseTime(s string, scale int32) (Time, error) { return Time(0), nil } - if s[0] == '-' { + if timeString[0] == '-' { isNegative = true timeString = timeString[1:] } - timeParts := strings.Split(s, " ") + timeParts := strings.Split(timeString, " ") if len(timeParts) > 1 { day, _ = strconv.ParseUint(timeParts[0], 10, 64) if day > MaxHourInTime/maxHourInDay { @@ -267,8 +296,10 @@ func (t Time) ToInt64() int64 { // - 0: seconds (no fractional part) // - 1-5: fractional seconds with corresponding precision // - 6: microseconds (full precision, no truncation) +// - >6: treated as scale 6 (full precision) func (t Time) TruncateToScale(scale int32) Time { - if scale == 6 { + // For scale >= 6, return full precision (no truncation) + if scale >= 6 { return t } @@ -289,7 +320,7 @@ func (t Time) TruncateToScale(scale int32) Time { base := int64(microPart) / divisor // Round up if the next digit >= 5 - if int64(microPart)%divisor/(divisor/10) >= 5 { + if scale < 6 && int64(microPart)%divisor/(divisor/10) >= 5 { base += 1 } @@ -374,14 +405,16 @@ func (t Time) ToDatetime(scale int32) Datetime { // TODO: Get today date from local time zone setting? d := Today(time.UTC) dt := d.ToDatetime() - if scale == 6 { + // Time type only supports up to 6 digits of microsecond precision + // For scale >= 6, use scale 6 (full microsecond precision) + if scale >= 6 { return Datetime(int64(dt) + int64(t)) } // TODO: add the valid check newTime := Datetime(int64(dt) + int64(t)) base := newTime / scaleVal[scale] - if newTime%scaleVal[scale]/scaleVal[scale+1] >= 5 { // check carry + if scale < 6 && newTime%scaleVal[scale]/scaleVal[scale+1] >= 5 { // check carry base += 1 } return base * scaleVal[scale] diff --git a/pkg/container/types/time_test.go b/pkg/container/types/time_test.go index 1bade7b4caefb..7af73a827daa9 100644 --- a/pkg/container/types/time_test.go +++ b/pkg/container/types/time_test.go @@ -172,6 +172,28 @@ func TestTime_ParseTimeFromString(t *testing.T) { scale: 3, isErr: false, }, + // ==================== Time format with days: d hh:mm:ss(.msec) ==================== + { + name: "TestParse-DaysFormat-NoPrecision", + inputStr: "1 1:1:1", + expected: TimeFromClock(false, 25, 1, 1, 0), // 1 day + 1 hour = 25 hours + scale: 0, + isErr: false, + }, + { + name: "TestParse-DaysFormat-WithMicroseconds", + inputStr: "1 1:1:1.000002", + expected: TimeFromClock(false, 25, 1, 1, 2), // 1 day + 1 hour + 2 microseconds + scale: 6, + isErr: false, + }, + { + name: "TestParse-DaysFormat-WithMilliseconds", + inputStr: "2 12:30:45.123456", + expected: TimeFromClock(false, 60, 30, 45, 123456), // 2 days + 12 hours = 60 hours + scale: 6, + isErr: false, + }, { name: "TestParse3-Precision", // 11:22:33 @@ -529,3 +551,211 @@ func TestTime_NumericString_NoNewline(t *testing.T) { }) } } + +// TestTime_NumericString_ScaleGreaterThan6 tests NumericString with scale > 6 +// This test ensures that scale > 6 does not cause panic and handles correctly +func TestTime_NumericString_ScaleGreaterThan6(t *testing.T) { + testCases := []struct { + name string + time Time + scale int32 + expected string // Expected output format + shouldPanic bool + }{ + { + name: "scale 7 - should pad with zeros", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 7, + expected: "112233.1234560", + shouldPanic: false, + }, + { + name: "scale 8 - should pad with zeros", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 8, + expected: "112233.12345600", + shouldPanic: false, + }, + { + name: "scale 9 - should pad with zeros", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 9, + expected: "112233.123456000", + shouldPanic: false, + }, + { + name: "scale 10 - should pad to 10 digits", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 10, + expected: "112233.1234560000", // Should pad to 10 digits (DECIMAL can support up to 38) + shouldPanic: false, + }, + { + name: "scale 20 - should pad to 20 digits", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 20, + expected: "112233.12345600000000000000", // Should pad to 20 digits + shouldPanic: false, + }, + { + name: "scale 7 with zero microseconds", + time: TimeFromClock(false, 11, 22, 33, 0), + scale: 7, + expected: "112233.0000000", + shouldPanic: false, + }, + { + name: "scale 7 with single microsecond", + time: TimeFromClock(false, 11, 22, 33, 1), + scale: 7, + expected: "112233.0000010", + shouldPanic: false, + }, + { + name: "scale 7 negative time", + time: TimeFromClock(true, 11, 22, 33, 123456), + scale: 7, + expected: "-112233.1234560", + shouldPanic: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.shouldPanic { + require.Panics(t, func() { + tc.time.NumericString(tc.scale) + }, "NumericString should panic with scale > 6") + } else { + // This should not panic + result := tc.time.NumericString(tc.scale) + require.NotPanics(t, func() { + tc.time.NumericString(tc.scale) + }, "NumericString should not panic with scale > 6") + require.Equal(t, tc.expected, result, "NumericString output should match expected format") + // Ensure no newline character in the output + require.NotContains(t, result, "\n", "NumericString output should not contain newline") + require.NotContains(t, result, "\r", "NumericString output should not contain carriage return") + } + }) + } +} + +// TestTime_TruncateToScale_ScaleGreaterThan6 tests TruncateToScale with scale > 6 +// This test ensures that scale > 6 does not cause panic and handles correctly +func TestTime_TruncateToScale_ScaleGreaterThan6(t *testing.T) { + testCases := []struct { + name string + time Time + scale int32 + expected Time // Expected result (should be same as input for scale >= 6) + }{ + { + name: "scale 7 - should return full precision", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 7, + expected: TimeFromClock(false, 11, 22, 33, 123456), // Should return same as input + }, + { + name: "scale 9 - should return full precision", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 9, + expected: TimeFromClock(false, 11, 22, 33, 123456), // Should return same as input + }, + { + name: "scale 10 - should return full precision", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 10, + expected: TimeFromClock(false, 11, 22, 33, 123456), // Should return same as input + }, + { + name: "scale 7 with zero microseconds", + time: TimeFromClock(false, 11, 22, 33, 0), + scale: 7, + expected: TimeFromClock(false, 11, 22, 33, 0), + }, + { + name: "scale 7 negative time", + time: TimeFromClock(true, 11, 22, 33, 123456), + scale: 7, + expected: TimeFromClock(true, 11, 22, 33, 123456), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // This should not panic even with scale > 6 + result := tc.time.TruncateToScale(tc.scale) + require.NotPanics(t, func() { + tc.time.TruncateToScale(tc.scale) + }, "TruncateToScale should not panic with scale > 6") + require.Equal(t, tc.expected, result, "TruncateToScale(%d) should return full precision for scale >= 6", tc.scale) + }) + } +} + +// TestTime_ToDecimal_ScaleGreaterThan6 tests ToDecimal64 and ToDecimal128 with scale > 6 +// These methods call NumericString internally, so they should handle scale > 6 correctly +func TestTime_ToDecimal_ScaleGreaterThan6(t *testing.T) { + testCases := []struct { + name string + time Time + scale int32 + shouldPanic bool + }{ + { + name: "ToDecimal64 with scale 7", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 7, + shouldPanic: false, + }, + { + name: "ToDecimal64 with scale 9", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 9, + shouldPanic: false, + }, + { + name: "ToDecimal128 with scale 7", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 7, + shouldPanic: false, + }, + { + name: "ToDecimal128 with scale 9", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 9, + shouldPanic: false, + }, + { + name: "ToDecimal64 with scale 10", + time: TimeFromClock(false, 11, 22, 33, 123456), + scale: 10, + shouldPanic: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.shouldPanic { + require.Panics(t, func() { + _, _ = tc.time.ToDecimal64(context.TODO(), 38, tc.scale) + }, "ToDecimal64 should panic with scale > 6") + require.Panics(t, func() { + _, _ = tc.time.ToDecimal128(context.TODO(), 38, tc.scale) + }, "ToDecimal128 should panic with scale > 6") + } else { + // These should not panic + require.NotPanics(t, func() { + _, err := tc.time.ToDecimal64(context.TODO(), 38, tc.scale) + require.NoError(t, err, "ToDecimal64 should not error with scale > 6") + }, "ToDecimal64 should not panic with scale > 6") + + require.NotPanics(t, func() { + _, err := tc.time.ToDecimal128(context.TODO(), 38, tc.scale) + require.NoError(t, err, "ToDecimal128 should not error with scale > 6") + }, "ToDecimal128 should not panic with scale > 6") + } + }) + } +} diff --git a/pkg/container/vector/vector_test.go b/pkg/container/vector/vector_test.go index 3b0397e8146c1..c992cf1b160dd 100644 --- a/pkg/container/vector/vector_test.go +++ b/pkg/container/vector/vector_test.go @@ -19,6 +19,7 @@ import ( "slices" "strings" "testing" + "time" "golang.org/x/exp/rand" @@ -2855,9 +2856,21 @@ func TestRowToString(t *testing.T) { } { // timestamp v := NewVec(types.T_timestamp.ToType()) - err := AppendFixedList(v, []types.Timestamp{1, types.Timestamp(types.DatetimeFromClock(1970, 1, 1, 0, 0, 0, 0)), 3, 4}, nil, mp) - require.NoError(t, err) - require.Equal(t, "1970-01-01 00:00:00", v.RowToString(1)) + // Use FromClockZone with UTC to create timestamp that will display correctly + // RowToString uses time.Local, so we need to create timestamp that accounts for local timezone + // If we want to display "1970-01-01 00:00:00" in local time, we need to create timestamp + // that represents that time in local timezone + utc := time.UTC + ts := types.FromClockZone(utc, 1970, 1, 1, 0, 0, 0, 0) + err := AppendFixedList(v, []types.Timestamp{1, ts, 3, 4}, nil, mp) + require.NoError(t, err) + // RowToString uses time.Local, so the displayed time will be in local timezone + // If local timezone is UTC+8, UTC time 1970-01-01 00:00:00 will display as 1970-01-01 08:00:00 + // So we need to adjust the expected value based on local timezone offset + _, offset := time.Now().In(time.Local).Zone() + expectedHour := offset / 3600 + expectedStr := fmt.Sprintf("1970-01-01 %02d:00:00", expectedHour) + require.Equal(t, expectedStr, v.RowToString(1)) v.Free(mp) require.Equal(t, int64(0), mp.CurrNB()) } diff --git a/pkg/defines/type.go b/pkg/defines/type.go index 8f5302b295ed9..993d874117351 100644 --- a/pkg/defines/type.go +++ b/pkg/defines/type.go @@ -249,6 +249,10 @@ type VarScopeKey struct{} // Determine if it is a stored procedure type InSp struct{} +// IvfBloomFilter carries BloomFilter bytes for ivf entries scan in internal SQL executor. +// This key is set on context when invoking internal SQL from ivf_search. +type IvfBloomFilter struct{} + // PkCheckByTN whether TN does primary key uniqueness check against transaction's workspace or not. type PkCheckByTN struct{} diff --git a/pkg/frontend/cdc_cancel_concurrent_test.go b/pkg/frontend/cdc_cancel_concurrent_test.go index 82e709a2bb95c..46bdf23986d38 100644 --- a/pkg/frontend/cdc_cancel_concurrent_test.go +++ b/pkg/frontend/cdc_cancel_concurrent_test.go @@ -53,9 +53,9 @@ func createMockTableDetector() *cdc.TableDetector { })) } - // Call Register to properly initialize cancel field + // Call RegisterIfAbsent to properly initialize cancel field // This starts scanTableLoop, which is safe because scanTableFn is no-op - detector.Register("__test_permanent_dummy__", 1, []string{}, []string{}, func(map[uint32]cdc.TblMap) error { + detector.RegisterIfAbsent("__test_permanent_dummy__", 1, []string{}, []string{}, func(map[uint32]cdc.TblMap) error { return nil // Dummy callback }) diff --git a/pkg/frontend/cdc_dao.go b/pkg/frontend/cdc_dao.go index 6b3866bec7759..43c8de036a217 100644 --- a/pkg/frontend/cdc_dao.go +++ b/pkg/frontend/cdc_dao.go @@ -123,11 +123,21 @@ func (t *CDCDao) CreateTask( var ( details *task.Details + ts taskservice.TaskService ) if details, err = opts.BuildTaskDetails(); err != nil { return } + // Get TaskService - handle nil case gracefully instead of panicking + if t.ts == nil && t.ses != nil { + t.ts = getPu(t.ses.GetService()).TaskService + } + if t.ts == nil { + return moerr.NewInternalError(ctx, "TaskService is not available. CDC task creation requires TaskService to be initialized.") + } + ts = t.ts + creatTaskJob := func( ctx context.Context, tx taskservice.SqlExecutor, @@ -145,7 +155,7 @@ func (t *CDCDao) CreateTask( return int(rowsAffected), nil } - _, err = t.MustGetTaskService().AddCDCTask( + _, err = ts.AddCDCTask( ctx, opts.BuildTaskMetadata(), details, creatTaskJob, ) return diff --git a/pkg/frontend/cdc_exector.go b/pkg/frontend/cdc_exector.go index 6c35a5d2608a7..e54bf79f18689 100644 --- a/pkg/frontend/cdc_exector.go +++ b/pkg/frontend/cdc_exector.go @@ -181,48 +181,52 @@ func (exec *CDCTaskExecutor) Start(rootCtx context.Context) (err error) { taskName := exec.spec.TaskName cnUUID := exec.cnUUID accountId := uint32(exec.spec.Accounts[0].GetId()) + detector := cdc.GetTableDetector(cnUUID) + var ( + registered bool + enteredStarting bool + ) - // Transition to Starting state (skip if already Starting, e.g., from Resume) - if exec.stateMachine.State() != StateStarting { - if err = exec.stateMachine.Transition(TransitionStart); err != nil { - return moerr.NewInternalErrorf(rootCtx, "cannot start: %v", err) - } + // Check if this task is already registered in TableDetector + // This prevents duplicate task execution when taskservice schedules the same task twice + if detector.IsTaskRegistered(taskId) { + logutil.Warn( + "cdc.frontend.task.already_registered", + zap.String("task-id", taskId), + zap.String("task-name", taskName), + zap.String("cn-uuid", cnUUID), + zap.Uint32("account-id", accountId), + zap.String("reason", "task is already registered in TableDetector, skipping duplicate start"), + ) + return moerr.NewInternalErrorf(rootCtx, "task %s is already running", taskId) } - logutil.Info( - "cdc.frontend.task.start", - zap.String("task-id", taskId), - zap.String("task-name", taskName), - zap.String("cn-uuid", cnUUID), - zap.Uint32("account-id", accountId), - zap.String("state", exec.stateMachine.State().String()), - ) - defer func() { if err != nil { - // Transition to Failed state - if setFailErr := exec.stateMachine.SetFailed(err.Error()); setFailErr != nil { - logutil.Warn( - "cdc.frontend.task.set_state_failed", - zap.String("target-state", StateFailed.String()), - zap.Error(setFailErr), - ) + if registered { + detector.UnRegister(taskId) } - // Metrics: task failed - v2.CdcTaskTotalGauge.WithLabelValues("failed").Inc() - v2.CdcTaskErrorCounter.WithLabelValues("start_failed", "false").Inc() + // Transition to Failed state only if we entered Starting state + if enteredStarting { + if setFailErr := exec.stateMachine.SetFailed(err.Error()); setFailErr != nil { + logutil.Warn( + "cdc.frontend.task.set_state_failed", + zap.String("target-state", StateFailed.String()), + zap.Error(setFailErr), + ) + } + + // Metrics: task failed + v2.CdcTaskTotalGauge.WithLabelValues("failed").Inc() + v2.CdcTaskErrorCounter.WithLabelValues("start_failed", "false").Inc() + } // if Start failed, there will be some dangle goroutines(watermarkUpdater, reader, sinker...) // need to close them to avoid goroutine leak exec.activeRoutine.ClosePause() exec.activeRoutine.CloseCancel() - // UnRegister from TableDetector if already registered - if exec.stateMachine.IsRunning() { - cdc.GetTableDetector(cnUUID).UnRegister(taskId) - } - updateErrMsgErr := exec.updateErrMsg(rootCtx, err.Error()) logutil.Error( "cdc.frontend.task.start_failed", @@ -276,7 +280,37 @@ func (exec *CDCTaskExecutor) Start(rootCtx context.Context) (err error) { exec.watermarkUpdater = cdc.GetCDCWatermarkUpdater(exec.cnUUID, exec.ie) // register to table scanner - cdc.GetTableDetector(cnUUID).Register(taskId, accountId, dbs, tables, exec.handleNewTables) + if !detector.RegisterIfAbsent(taskId, accountId, dbs, tables, exec.handleNewTables) { + logutil.Warn( + "cdc.frontend.task.duplicate_registration_detected", + zap.String("task-id", taskId), + zap.String("task-name", taskName), + zap.String("cn-uuid", cnUUID), + zap.Uint32("account-id", accountId), + zap.String("reason", "RegisterIfAbsent rejected duplicate task"), + ) + return moerr.NewInternalErrorf(ctx, "task %s is already running", taskId) + } + registered = true + + // Transition to Starting state (skip if already Starting, e.g., from Resume) + if exec.stateMachine.State() != StateStarting { + if err = exec.stateMachine.Transition(TransitionStart); err != nil { + detector.UnRegister(taskId) + registered = false + return moerr.NewInternalErrorf(ctx, "cannot start: %v", err) + } + } + enteredStarting = true + + logutil.Info( + "cdc.frontend.task.start", + zap.String("task-id", taskId), + zap.String("task-name", taskName), + zap.String("cn-uuid", cnUUID), + zap.Uint32("account-id", accountId), + zap.String("state", exec.stateMachine.State().String()), + ) // Transition to Running state if err = exec.stateMachine.Transition(TransitionStartSuccess); err != nil { @@ -1050,7 +1084,7 @@ func (exec *CDCTaskExecutor) addExecPipelineForTable( // step 4. start goroutines (sinker first, then reader) // Note: Reader will register itself in runningReaders during Run() - // to prevent duplicate readers (see TableChangeStream.Run line 207) + // to prevent duplicate readers (see TableChangeStream.Run line 287) go sinker.Run(ctx, exec.activeRoutine) go reader.Run(ctx, exec.activeRoutine) diff --git a/pkg/frontend/cdc_handle.go b/pkg/frontend/cdc_handle.go index 6d4e68902febf..18fafe7151757 100644 --- a/pkg/frontend/cdc_handle.go +++ b/pkg/frontend/cdc_handle.go @@ -57,7 +57,22 @@ func handleResumeCdc(ses *Session, execCtx *ExecCtx, st *tree.ResumeCDC) error { } func handleRestartCdc(ses *Session, execCtx *ExecCtx, st *tree.RestartCDC) error { - return handleUpdateCDCTaskRequest(execCtx.reqCtx, ses, st) + logutil.Info("cdc.restart.handle_restart.start", + zap.String("task-name", st.TaskName.String()), + zap.String("service", ses.GetService()), + ) + err := handleUpdateCDCTaskRequest(execCtx.reqCtx, ses, st) + if err != nil { + logutil.Error("cdc.restart.handle_restart.failed", + zap.String("task-name", st.TaskName.String()), + zap.Error(err), + ) + } else { + logutil.Info("cdc.restart.handle_restart.success", + zap.String("task-name", st.TaskName.String()), + ) + } + return err } func handleShowCdc( @@ -152,6 +167,7 @@ func handleUpdateCDCTaskRequest( operation = "restart" taskName = updateReq.TaskName.String() if len(taskName) == 0 { + logutil.Error("cdc.restart.invalid_task_name") return moerr.NewInternalError(ctx, "invalid restart cdc task name") } conds = append( @@ -160,6 +176,11 @@ func handleUpdateCDCTaskRequest( taskservice.WithTaskType(taskservice.EQ, task.TaskType_CreateCdc.String()), taskservice.WithTaskName(taskservice.EQ, taskName), ) + logutil.Info("cdc.restart.parsed_request", + zap.String("task-name", taskName), + zap.Uint32("account-id", accountId), + zap.Int("condition-count", len(conds)), + ) default: return moerr.NewInternalErrorf( ctx, @@ -195,11 +216,29 @@ func doUpdateCDCTask( service string, conds ...taskservice.Condition, ) (err error) { + logutil.Info("cdc.do_update_task.start", + zap.String("target-status", targetTaskStatus.String()), + zap.Uint64("account-id", accountId), + zap.String("task-name", taskName), + zap.String("service", service), + zap.Int("condition-count", len(conds)), + ) + ts := getPu(service).TaskService if ts == nil { + logutil.Warn("cdc.do_update_task.task_service_nil", + zap.String("task-name", taskName), + zap.String("target-status", targetTaskStatus.String()), + ) return nil } - _, err = ts.UpdateCDCTask(ctx, + + logutil.Info("cdc.do_update_task.calling_update", + zap.String("task-name", taskName), + zap.String("target-status", targetTaskStatus.String()), + ) + + affectedCount, err := ts.UpdateCDCTask(ctx, targetTaskStatus, func( ctx context.Context, @@ -207,6 +246,11 @@ func doUpdateCDCTask( keys map[taskservice.CDCTaskKey]struct{}, tx taskservice.SqlExecutor, ) (int, error) { + logutil.Info("cdc.do_update_task.pre_update_callback", + zap.String("task-name", taskName), + zap.String("target-status", targetStatus.String()), + zap.Int("key-count", len(keys)), + ) return onPreUpdateCDCTasks( ctx, targetStatus, @@ -218,6 +262,21 @@ func doUpdateCDCTask( }, conds..., ) + + if err != nil { + logutil.Error("cdc.do_update_task.failed", + zap.String("task-name", taskName), + zap.String("target-status", targetTaskStatus.String()), + zap.Int("affected-count", affectedCount), + zap.Error(err), + ) + } else { + logutil.Info("cdc.do_update_task.success", + zap.String("task-name", taskName), + zap.String("target-status", targetTaskStatus.String()), + zap.Int("affected-count", affectedCount), + ) + } return } @@ -229,27 +288,86 @@ func onPreUpdateCDCTasks( accountId uint64, taskName string, ) (affectedCdcRow int, err error) { + logutil.Info("cdc.on_pre_update.start", + zap.String("target-status", targetTaskStatus.String()), + zap.Uint64("account-id", accountId), + zap.String("task-name", taskName), + zap.Int("input-key-count", len(keys)), + ) + var ( cnt int64 dao = NewCDCDao(nil, WithSQLExecutor(tx)) ) + + logutil.Info("cdc.on_pre_update.get_task_keys.start", + zap.String("task-name", taskName), + zap.Uint64("account-id", accountId), + ) + if cnt, err = dao.GetTaskKeys( ctx, accountId, taskName, keys, ); err != nil { + logutil.Error("cdc.on_pre_update.get_task_keys.failed", + zap.String("task-name", taskName), + zap.Uint64("account-id", accountId), + zap.Error(err), + ) return } + + logutil.Info("cdc.on_pre_update.get_task_keys.success", + zap.String("task-name", taskName), + zap.Int64("task-count", cnt), + zap.Int("key-count", len(keys)), + ) + affectedCdcRow = int(cnt) //Cancel cdc task if targetTaskStatus == task.TaskStatus_CancelRequested { - var deleteRes DeleteCDCArtifactsResult - if deleteRes, err = dao.DeleteTaskAndWatermark(ctx, accountId, taskName, keys); err != nil { + logutil.Info("cdc.on_pre_update.cancel_task.start", + zap.String("task-name", taskName), + ) + //deleting mo_cdc_task + if cnt, err = dao.DeleteTaskByName( + ctx, accountId, taskName, + ); err != nil { + logutil.Error("cdc.on_pre_update.delete_task.failed", + zap.String("task-name", taskName), + zap.Error(err), + ) + return + } + logutil.Info("cdc.on_pre_update.delete_task.success", + zap.String("task-name", taskName), + zap.Int64("deleted-rows", cnt), + ) + affectedCdcRow += int(cnt) + + //delete mo_cdc_watermark + if cnt, err = dao.DeleteManyWatermark( + ctx, keys, + ); err != nil { + logutil.Error("cdc.on_pre_update.delete_watermark.failed", + zap.String("task-name", taskName), + zap.Int("key-count", len(keys)), + zap.Error(err), + ) return } - affectedCdcRow += int(deleteRes.TaskRows + deleteRes.WatermarkRows) + logutil.Info("cdc.on_pre_update.delete_watermark.success", + zap.String("task-name", taskName), + zap.Int64("deleted-watermarks", cnt), + ) + affectedCdcRow += int(cnt) + logutil.Info("cdc.on_pre_update.cancel_task.complete", + zap.String("task-name", taskName), + zap.Int("total-affected-rows", affectedCdcRow), + ) return } @@ -269,16 +387,39 @@ func onPreUpdateCDCTasks( targetCDCStatus = cdc.CDCState_Running } + logutil.Info("cdc.on_pre_update.update_task_status.start", + zap.String("task-name", taskName), + zap.String("target-task-status", targetTaskStatus.String()), + zap.String("target-cdc-status", targetCDCStatus), + ) + if cnt, err = dao.PrepareUpdateTask( ctx, accountId, taskName, targetCDCStatus, ); err != nil { + logutil.Error("cdc.on_pre_update.update_task_status.failed", + zap.String("task-name", taskName), + zap.String("target-cdc-status", targetCDCStatus), + zap.Error(err), + ) return } + logutil.Info("cdc.on_pre_update.update_task_status.success", + zap.String("task-name", taskName), + zap.String("target-cdc-status", targetCDCStatus), + zap.Int64("updated-rows", cnt), + ) + affectedCdcRow += int(cnt) + logutil.Info("cdc.on_pre_update.complete", + zap.String("task-name", taskName), + zap.String("target-status", targetTaskStatus.String()), + zap.Int("total-affected-rows", affectedCdcRow), + ) + return } diff --git a/pkg/frontend/cdc_test.go b/pkg/frontend/cdc_test.go index b9daaa30751ed..8aad005775224 100644 --- a/pkg/frontend/cdc_test.go +++ b/pkg/frontend/cdc_test.go @@ -86,8 +86,8 @@ func createMockTableDetectorForTest() func(cnUUID string) *cdc.TableDetector { })) } - // Call Register to properly initialize cancel field - detector.Register("__test_permanent_dummy__", 1, []string{}, []string{}, func(map[uint32]cdc.TblMap) error { + // Call RegisterIfAbsent to properly initialize cancel field + detector.RegisterIfAbsent("__test_permanent_dummy__", 1, []string{}, []string{}, func(map[uint32]cdc.TblMap) error { return nil }) diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index f85cee3eb42ae..4a37c847c3a27 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -221,6 +221,7 @@ var RecordStatement = func(ctx context.Context, ses *Session, proc *process.Proc stm.ConnectionId = ses.GetConnectionID() stm.Account = tenant.GetTenant() + stm.AccountID = tenant.GetTenantID() stm.RoleId = tenant.GetDefaultRoleID() //stm.RoleId = proc.GetSessionInfo().RoleId stm.User = tenant.GetUser() @@ -288,7 +289,7 @@ var RecordParseErrorStatement = func(ctx context.Context, ses *Session, proc *pr if tenant == nil { tenant, _ = GetTenantInfo(ctx, "internal") } - incStatementErrorsCounter(tenant.GetTenant(), nil) + incStatementErrorsCounter(tenant.GetTenant(), tenant.GetTenantID(), nil) return ctx, nil } @@ -2255,19 +2256,19 @@ func parseSql(execCtx *ExecCtx, p *mysql.MySQLParser) (stmts []tree.Statement, e return p.Parse(execCtx.reqCtx, execCtx.input.getSql(), lctn) } -func incTransactionCounter(tenant string) { - metric.TransactionCounter(tenant).Inc() +func incTransactionCounter(tenant string, tenantId uint32) { + metric.TransactionCounter(tenant, tenantId).Inc() } -func incTransactionErrorsCounter(tenant string, t metric.SQLType) { +func incTransactionErrorsCounter(tenant string, tenantId uint32, t metric.SQLType) { if t == metric.SQLTypeRollback { return } - metric.TransactionErrorsCounter(tenant, t).Inc() + metric.TransactionErrorsCounter(tenant, tenantId, t).Inc() } -func incStatementErrorsCounter(tenant string, stmt tree.Statement) { - metric.StatementErrorsCounter(tenant, getStatementType(stmt).GetQueryType()).Inc() +func incStatementErrorsCounter(tenant string, tenantId uint32, stmt tree.Statement) { + metric.StatementErrorsCounter(tenant, tenantId, getStatementType(stmt).GetQueryType()).Inc() } // authenticateUserCanExecuteStatement checks the user can execute the statement diff --git a/pkg/frontend/routine.go b/pkg/frontend/routine.go index 7b80278f271ee..519d019f25204 100644 --- a/pkg/frontend/routine.go +++ b/pkg/frontend/routine.go @@ -291,7 +291,7 @@ func (rt *Routine) handleRequest(req *Request) error { tenantCtx := defines.AttachAccount(nodeCtx, tenant.GetTenantID(), tenant.GetUserID(), tenant.GetDefaultRoleID()) rt.increaseCount(func() { - metric.ConnectionCounter(ses.GetTenantInfo().GetTenant()).Inc() + metric.ConnectionCounter(ses.GetTenantInfo().GetTenant(), ses.GetTenantInfo().GetTenantID()).Inc() }) execCtx.reqCtx = tenantCtx @@ -340,7 +340,7 @@ func (rt *Routine) handleRequest(req *Request) error { if quit { rt.decreaseCount(func() { - metric.ConnectionCounter(ses.GetTenantInfo().GetTenant()).Dec() + metric.ConnectionCounter(ses.GetTenantInfo().GetTenant(), ses.GetTenantInfo().GetTenantID()).Dec() }) //ensure cleaning the transaction diff --git a/pkg/frontend/routine_manager.go b/pkg/frontend/routine_manager.go index 9f8cfcdfdc6a0..5554a284d213b 100644 --- a/pkg/frontend/routine_manager.go +++ b/pkg/frontend/routine_manager.go @@ -313,10 +313,12 @@ func (rm *RoutineManager) Closed(rs *Conn) { rt.decreaseCount(func() { account := ses.GetTenantInfo() accountName := sysAccountName + accountId := uint32(0) if account != nil { accountName = account.GetTenant() + accountId = account.GetTenantID() } - metric.ConnectionCounter(accountName).Dec() + metric.ConnectionCounter(accountName, accountId).Dec() rm.accountRoutine.deleteRoutine(int64(account.GetTenantID()), rt) }) rm.sessionManager.RemoveSession(ses) diff --git a/pkg/frontend/routine_test.go b/pkg/frontend/routine_test.go index c929e33a7b88d..86f1789c7ebd3 100644 --- a/pkg/frontend/routine_test.go +++ b/pkg/frontend/routine_test.go @@ -225,7 +225,7 @@ func Test_ConnectionCount(t *testing.T) { mo.handleConn(ctx, serverConn) }() - cCounter := metric.ConnectionCounter(sysAccountName) + cCounter := metric.ConnectionCounter(sysAccountName, 0) cCounter.Set(0) conn1, err = openDbConn(t, 6001) diff --git a/pkg/frontend/txn.go b/pkg/frontend/txn.go index 9500610e29eab..b368063bd8f17 100644 --- a/pkg/frontend/txn.go +++ b/pkg/frontend/txn.go @@ -46,7 +46,12 @@ var ( func rollbackTxnFunc(ses FeSession, execErr error, execCtx *ExecCtx) error { execCtx.ses.EnterFPrint(FPRollbackTxn) defer execCtx.ses.ExitFPrint(FPRollbackTxn) - incStatementErrorsCounter(execCtx.tenant, execCtx.stmt) + tenantInfo := execCtx.ses.GetTenantInfo() + tenantId := uint32(0) + if tenantInfo != nil { + tenantId = tenantInfo.GetTenantID() + } + incStatementErrorsCounter(execCtx.tenant, tenantId, execCtx.stmt) /* Cases | set Autocommit = 1/0 | BEGIN statement | --------------------------------------------------- @@ -317,7 +322,12 @@ func (th *TxnHandler) createUnsafe(execCtx *ExecCtx) error { defer func() { if err != nil { tenant := execCtx.tenant - incTransactionErrorsCounter(tenant, metric.SQLTypeBegin) + tenantInfo := execCtx.ses.GetTenantInfo() + tenantId := uint32(0) + if tenantInfo != nil { + tenantId = tenantInfo.GetTenantID() + } + incTransactionErrorsCounter(tenant, tenantId, metric.SQLTypeBegin) } }() err = th.createTxnOpUnsafe(execCtx) @@ -509,9 +519,14 @@ func (th *TxnHandler) commitUnsafe(execCtx *ExecCtx) error { defer func() { // metric count tenant := execCtx.ses.GetTenantName() - incTransactionCounter(tenant) + tenantInfo := execCtx.ses.GetTenantInfo() + tenantId := uint32(0) + if tenantInfo != nil { + tenantId = tenantInfo.GetTenantID() + } + incTransactionCounter(tenant, tenantId) if err != nil { - incTransactionErrorsCounter(tenant, metric.SQLTypeCommit) + incTransactionErrorsCounter(tenant, tenantId, metric.SQLTypeCommit) } }() @@ -633,10 +648,15 @@ func (th *TxnHandler) rollbackUnsafe(execCtx *ExecCtx) error { defer func() { // metric count tenant := execCtx.ses.GetTenantName() - incTransactionCounter(tenant) - incTransactionErrorsCounter(tenant, metric.SQLTypeOther) // exec rollback cnt + tenantInfo := execCtx.ses.GetTenantInfo() + tenantId := uint32(0) + if tenantInfo != nil { + tenantId = tenantInfo.GetTenantID() + } + incTransactionCounter(tenant, tenantId) + incTransactionErrorsCounter(tenant, tenantId, metric.SQLTypeOther) // exec rollback cnt if err != nil { - incTransactionErrorsCounter(tenant, metric.SQLTypeRollback) + incTransactionErrorsCounter(tenant, tenantId, metric.SQLTypeRollback) } }() if execCtx.ses.GetLogLevel().Enabled(zap.DebugLevel) { diff --git a/pkg/logservice/netstat_linux.go b/pkg/logservice/netstat_linux.go index f4953d564107d..3d8ce9f15a0e2 100644 --- a/pkg/logservice/netstat_linux.go +++ b/pkg/logservice/netstat_linux.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build linux -// +build linux package logservice diff --git a/pkg/objectio/types.go b/pkg/objectio/types.go index ae757d7fad9ea..3f0240c743956 100644 --- a/pkg/objectio/types.go +++ b/pkg/objectio/types.go @@ -20,9 +20,9 @@ import ( "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" - "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/matrixorigin/matrixone/pkg/vectorindex/metric" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/index" ) @@ -42,13 +42,14 @@ type ColumnMetaFetcher interface { MustGetColumn(seqnum uint16) ColumnMeta } -type ReadFilterSearchFuncType func(*vector.Vector) []int64 +type ReadFilterSearchFuncType func(containers.Vectors) []int64 type BlockReadFilter struct { HasFakePK bool Valid bool SortedSearchFunc ReadFilterSearchFuncType UnSortedSearchFunc ReadFilterSearchFuncType + Cleanup func() // Cleanup function to release resources (e.g., reusableTempVec) } func (f BlockReadFilter) DecideSearchFunc(isSortedBlk bool) ReadFilterSearchFuncType { diff --git a/pkg/pb/plan/plan.pb.go b/pkg/pb/plan/plan.pb.go index 9266463bc40a5..c0069e73d4a35 100644 --- a/pkg/pb/plan/plan.pb.go +++ b/pkg/pb/plan/plan.pb.go @@ -2694,7 +2694,6 @@ func (m *Function) GetArgs() []*Expr { type Expr struct { Typ Type `protobuf:"bytes,1,opt,name=typ,proto3" json:"typ"` // Types that are valid to be assigned to Expr: - // // *Expr_Lit // *Expr_P // *Expr_V @@ -4603,7 +4602,6 @@ func (m *TableDef) GetFeatureFlag() uint64 { // XXX: Deprecated and to be removed soon. type TableDef_DefType struct { // Types that are valid to be assigned to Def: - // // *TableDef_DefType_Properties Def isTableDef_DefType_Def `protobuf_oneof:"def"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -4873,18 +4871,18 @@ func (m *HashMapStats) GetRanges() []float64 { } type Stats struct { - // for scan, number of blocks to read from S3 + //for scan, number of blocks to read from S3 BlockNum int32 `protobuf:"varint,1,opt,name=block_num,json=blockNum,proto3" json:"block_num,omitempty"` - // for scan, cost of reading from S3, basically the read lines - // for other nodes, it means the estimated cost of current node + //for scan, cost of reading from S3, basically the read lines + //for other nodes, it means the estimated cost of current node Cost float64 `protobuf:"fixed64,2,opt,name=cost,proto3" json:"cost,omitempty"` - // number of output lines + //number of output lines Outcnt float64 `protobuf:"fixed64,3,opt,name=outcnt,proto3" json:"outcnt,omitempty"` // average size of one row Rowsize float64 `protobuf:"fixed64,4,opt,name=rowsize,proto3" json:"rowsize,omitempty"` - // for scan, this means total count of all table, before filtering + //for scan, this means total count of all table, before filtering TableCnt float64 `protobuf:"fixed64,5,opt,name=table_cnt,json=tableCnt,proto3" json:"table_cnt,omitempty"` - // for scan, selectivity means outcnt divide total count + //for scan, selectivity means outcnt divide total count Selectivity float64 `protobuf:"fixed64,6,opt,name=selectivity,proto3" json:"selectivity,omitempty"` ForceOneCN bool `protobuf:"varint,7,opt,name=forceOneCN,proto3" json:"forceOneCN,omitempty"` Dop int32 `protobuf:"varint,8,opt,name=dop,proto3" json:"dop,omitempty"` @@ -6366,6 +6364,7 @@ type Node struct { // LIMIT Limit *Expr `protobuf:"bytes,15,opt,name=limit,proto3" json:"limit,omitempty"` Offset *Expr `protobuf:"bytes,16,opt,name=offset,proto3" json:"offset,omitempty"` + RankOption *RankOption `protobuf:"bytes,89,opt,name=rank_option,json=rankOption,proto3" json:"rank_option,omitempty"` TableDef *TableDef `protobuf:"bytes,17,opt,name=table_def,json=tableDef,proto3" json:"table_def,omitempty"` ObjRef *ObjectRef `protobuf:"bytes,18,opt,name=obj_ref,json=objRef,proto3" json:"obj_ref,omitempty"` ParentObjRef *ObjectRef `protobuf:"bytes,19,opt,name=parent_obj_ref,json=parentObjRef,proto3" json:"parent_obj_ref,omitempty"` @@ -6410,7 +6409,7 @@ type Node struct { OnUpdateExprs []*Expr `protobuf:"bytes,55,rep,name=onUpdateExprs,proto3" json:"onUpdateExprs,omitempty"` Fuzzymessage *OriginTableMessageForFuzzy `protobuf:"bytes,56,opt,name=fuzzymessage,proto3" json:"fuzzymessage,omitempty"` IfInsertFromUnique bool `protobuf:"varint,57,opt,name=ifInsertFromUnique,proto3" json:"ifInsertFromUnique,omitempty"` - // for message + //for message SendMsgList []MsgHeader `protobuf:"bytes,58,rep,name=send_msg_list,json=sendMsgList,proto3" json:"send_msg_list"` RecvMsgList []MsgHeader `protobuf:"bytes,59,rep,name=recv_msg_list,json=recvMsgList,proto3" json:"recv_msg_list"` DedupJoinCtx *DedupJoinCtx `protobuf:"bytes,60,opt,name=dedup_join_ctx,json=dedupJoinCtx,proto3" json:"dedup_join_ctx,omitempty"` @@ -6575,6 +6574,13 @@ func (m *Node) GetOffset() *Expr { return nil } +func (m *Node) GetRankOption() *RankOption { + if m != nil { + return m.RankOption + } + return nil +} + func (m *Node) GetTableDef() *TableDef { if m != nil { return m.TableDef @@ -7653,6 +7659,7 @@ type RuntimeFilterSpec struct { UpperLimit int32 `protobuf:"varint,3,opt,name=upper_limit,json=upperLimit,proto3" json:"upper_limit,omitempty"` Expr *Expr `protobuf:"bytes,4,opt,name=expr,proto3" json:"expr,omitempty"` NotOnPk bool `protobuf:"varint,5,opt,name=not_on_pk,json=notOnPk,proto3" json:"not_on_pk,omitempty"` + UseBloomFilter bool `protobuf:"varint,6,opt,name=use_bloom_filter,json=useBloomFilter,proto3" json:"use_bloom_filter,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7726,6 +7733,13 @@ func (m *RuntimeFilterSpec) GetNotOnPk() bool { return false } +func (m *RuntimeFilterSpec) GetUseBloomFilter() bool { + if m != nil { + return m.UseBloomFilter + } + return false +} + type IdList struct { List []int64 `protobuf:"varint,1,rep,packed,name=list,proto3" json:"list,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -8113,7 +8127,7 @@ type Query struct { LoadTag bool `protobuf:"varint,6,opt,name=loadTag,proto3" json:"loadTag,omitempty"` // load write S3 LoadWriteS3 bool `protobuf:"varint,7,opt,name=loadWriteS3,proto3" json:"loadWriteS3,omitempty"` - // detectSqls are sqls detect fk self refer constraint + //detectSqls are sqls detect fk self refer constraint DetectSqls []string `protobuf:"bytes,8,rep,name=detectSqls,proto3" json:"detectSqls,omitempty"` BackgroundQueries []*Query `protobuf:"bytes,9,rep,name=background_queries,json=backgroundQueries,proto3" json:"background_queries,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -8218,10 +8232,9 @@ func (m *Query) GetBackgroundQueries() []*Query { } type TransationControl struct { - // TransationControl type + //TransationControl type TclType TransationControl_TclType `protobuf:"varint,1,opt,name=tcl_type,json=tclType,proto3,enum=plan.TransationControl_TclType" json:"tcl_type,omitempty"` // Types that are valid to be assigned to Action: - // // *TransationControl_Begin // *TransationControl_Commit // *TransationControl_Rollback @@ -8471,7 +8484,6 @@ func (m *TransationRollback) GetCompletionType() TransationCompletionType { type Plan struct { // Types that are valid to be assigned to Plan: - // // *Plan_Query // *Plan_Tcl // *Plan_Ddl @@ -8648,10 +8660,9 @@ func (m *Column) GetColumn() []*Expr { } type DataControl struct { - // DataDefinition type + //DataDefinition type DclType DataControl_DclType `protobuf:"varint,1,opt,name=dcl_type,json=dclType,proto3,enum=plan.DataControl_DclType" json:"dcl_type,omitempty"` // Types that are valid to be assigned to Control: - // // *DataControl_SetVariables // *DataControl_Prepare // *DataControl_Execute @@ -8785,14 +8796,13 @@ func (*DataControl) XXX_OneofWrappers() []interface{} { } type DataDefinition struct { - // DataDefinition type + //DataDefinition type DdlType DataDefinition_DdlType `protobuf:"varint,1,opt,name=ddl_type,json=ddlType,proto3,enum=plan.DataDefinition_DdlType" json:"ddl_type,omitempty"` - // other show statement we will rewrite to a select statement - // then we will get a Query - // eg: 'show databases' will rewrite to 'select md.datname as `Database` from mo_database md' + //other show statement we will rewrite to a select statement + //then we will get a Query + //eg: 'show databases' will rewrite to 'select md.datname as `Database` from mo_database md' Query *Query `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"` // Types that are valid to be assigned to Definition: - // // *DataDefinition_CreateDatabase // *DataDefinition_AlterDatabase // *DataDefinition_DropDatabase @@ -10681,7 +10691,7 @@ type AlterTable struct { CreateTmpTableSql string `protobuf:"bytes,7,opt,name=create_tmp_table_sql,json=createTmpTableSql,proto3" json:"create_tmp_table_sql,omitempty"` InsertTmpDataSql string `protobuf:"bytes,8,opt,name=insert_tmp_data_sql,json=insertTmpDataSql,proto3" json:"insert_tmp_data_sql,omitempty"` ChangeTblColIdMap map[uint64]*ColDef `protobuf:"bytes,9,rep,name=change_tbl_colId_map,json=changeTblColIdMap,proto3" json:"change_tbl_colId_map,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // detect fk self refer constraint + //detect fk self refer constraint DetectSqls []string `protobuf:"bytes,10,rep,name=detectSqls,proto3" json:"detectSqls,omitempty"` // alter table may insert fk records related to this table // into mo_foreign_keys @@ -10835,7 +10845,6 @@ func (m *AlterTable) GetAlterPartition() *AlterPartitionOption { type AlterTable_Action struct { // Types that are valid to be assigned to Action: - // // *AlterTable_Action_Drop // *AlterTable_Action_AddFk // *AlterTable_Action_AddIndex @@ -11065,7 +11074,7 @@ type DropTable struct { // drop table may delete fk records related to this table // into mo_foreign_keys UpdateFkSqls []string `protobuf:"bytes,11,rep,name=updateFkSqls,proto3" json:"updateFkSqls,omitempty"` - // fk child table id that refers to me + //fk child table id that refers to me FkChildTblsReferToMe []uint64 `protobuf:"varint,12,rep,packed,name=fkChildTblsReferToMe,proto3" json:"fkChildTblsReferToMe,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -13122,6 +13131,53 @@ func (m *AlterPartitionOption) GetPartitionDefs() []*PartitionDef { return nil } +type RankOption struct { + Mode string `protobuf:"bytes,1,opt,name=mode,proto3" json:"mode,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RankOption) Reset() { *m = RankOption{} } +func (m *RankOption) String() string { return proto.CompactTextString(m) } +func (*RankOption) ProtoMessage() {} +func (*RankOption) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{133} +} +func (m *RankOption) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RankOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RankOption.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RankOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_RankOption.Merge(m, src) +} +func (m *RankOption) XXX_Size() int { + return m.ProtoSize() +} +func (m *RankOption) XXX_DiscardUnknown() { + xxx_messageInfo_RankOption.DiscardUnknown(m) +} + +var xxx_messageInfo_RankOption proto.InternalMessageInfo + +func (m *RankOption) GetMode() string { + if m != nil { + return m.Mode + } + return "" +} + func init() { proto.RegisterEnum("plan.CompressType", CompressType_name, CompressType_value) proto.RegisterEnum("plan.ShuffleType", ShuffleType_name, ShuffleType_value) @@ -13293,807 +13349,812 @@ func init() { proto.RegisterType((*DropCDC)(nil), "plan.DropCDC") proto.RegisterType((*CloneTable)(nil), "plan.CloneTable") proto.RegisterType((*AlterPartitionOption)(nil), "plan.AlterPartitionOption") + proto.RegisterType((*RankOption)(nil), "plan.RankOption") } func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } var fileDescriptor_2d655ab2f7683c23 = []byte{ - // 12720 bytes of a gzipped FileDescriptorProto + // 12775 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0xbd, 0x5d, 0x6c, 0x1b, 0x59, 0x96, 0x18, 0x2c, 0x8a, 0xff, 0x87, 0x14, 0x55, 0xba, 0x96, 0x6d, 0xfa, 0xa7, 0x6d, 0xb9, 0xec, 0x76, 0xbb, 0xdd, 0xdd, 0x76, 0xb7, 0xdd, 0x3f, 0xee, 0xd9, 0x99, 0x9d, 0xa1, 0x48, 0xca, 0x62, 0x9b, 0x22, 0x35, 0x45, 0xca, 0xee, 0x9e, 0xfd, 0x16, 0x85, 0x22, 0xab, 0x28, 0x55, 0xab, 0x58, 0xc5, 0xae, 0x2a, 0x5a, 0x52, 0x03, 0x8b, 0x6f, 0xf0, 0x7d, 0xc0, 0xfe, 0x24, 0x8f, 0xc1, 0x6e, - 0xf2, 0x90, 0x05, 0x26, 0x0b, 0x2c, 0x12, 0x04, 0x1b, 0x20, 0x09, 0x36, 0xd8, 0xe4, 0x39, 0x2f, - 0x9b, 0x04, 0x59, 0x04, 0x08, 0x90, 0x20, 0x09, 0xb0, 0x09, 0x26, 0xc8, 0x63, 0x90, 0x04, 0xc9, - 0x53, 0x5e, 0x12, 0x9c, 0x73, 0x6f, 0x15, 0x6f, 0x91, 0x94, 0xdd, 0xdd, 0x33, 0x0b, 0x24, 0x2f, - 0x52, 0xdd, 0xf3, 0x73, 0xff, 0xef, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0x25, 0xc0, 0xc4, 0x31, 0xdc, - 0x07, 0x13, 0xdf, 0x0b, 0x3d, 0x96, 0xc1, 0xef, 0xab, 0xef, 0x1d, 0xda, 0xe1, 0xd1, 0x74, 0xf0, - 0x60, 0xe8, 0x8d, 0x1f, 0x1e, 0x7a, 0x87, 0xde, 0x43, 0x42, 0x0e, 0xa6, 0x23, 0x4a, 0x51, 0x82, - 0xbe, 0x38, 0xd3, 0x55, 0x70, 0xbc, 0xe1, 0xb1, 0xf8, 0x5e, 0x0f, 0xed, 0xb1, 0x15, 0x84, 0xc6, - 0x78, 0xc2, 0x01, 0xea, 0x9f, 0xa4, 0x20, 0xd3, 0x3f, 0x9b, 0x58, 0xac, 0x02, 0xab, 0xb6, 0x59, - 0x4d, 0x6d, 0xa5, 0xee, 0x65, 0xb5, 0x55, 0xdb, 0x64, 0x5b, 0x50, 0x72, 0xbd, 0xb0, 0x33, 0x75, - 0x1c, 0x63, 0xe0, 0x58, 0xd5, 0xd5, 0xad, 0xd4, 0xbd, 0x82, 0x26, 0x83, 0xd8, 0x35, 0x28, 0x1a, - 0xd3, 0xd0, 0xd3, 0x6d, 0x77, 0xe8, 0x57, 0xd3, 0x84, 0x2f, 0x20, 0xa0, 0xe5, 0x0e, 0x7d, 0xb6, - 0x09, 0xd9, 0x13, 0xdb, 0x0c, 0x8f, 0xaa, 0x19, 0xca, 0x91, 0x27, 0x10, 0x1a, 0x0c, 0x0d, 0xc7, - 0xaa, 0x66, 0x39, 0x94, 0x12, 0x08, 0x0d, 0xa9, 0x90, 0xdc, 0x56, 0xea, 0x5e, 0x51, 0xe3, 0x09, - 0x76, 0x03, 0xc0, 0x72, 0xa7, 0xe3, 0x97, 0x86, 0x33, 0xb5, 0x82, 0x6a, 0x9e, 0x50, 0x12, 0x44, - 0xfd, 0x21, 0x14, 0xc7, 0xc1, 0xe1, 0xae, 0x65, 0x98, 0x96, 0xcf, 0x2e, 0x43, 0x7e, 0x1c, 0x1c, - 0xea, 0xa1, 0x71, 0x28, 0x9a, 0x90, 0x1b, 0x07, 0x87, 0x7d, 0xe3, 0x90, 0x5d, 0x81, 0x02, 0x21, - 0xce, 0x26, 0xbc, 0x0d, 0x59, 0x0d, 0x09, 0xb1, 0xc5, 0xea, 0xef, 0xe4, 0x20, 0xdf, 0xb6, 0x43, - 0xcb, 0x37, 0x1c, 0x76, 0x09, 0x72, 0x76, 0xe0, 0x4e, 0x1d, 0x87, 0xd8, 0x0b, 0x9a, 0x48, 0xb1, - 0x4b, 0x90, 0xb5, 0x9f, 0xbc, 0x34, 0x1c, 0xce, 0xbb, 0xbb, 0xa2, 0xf1, 0x24, 0xab, 0x42, 0xce, - 0xfe, 0xe0, 0x63, 0x44, 0xa4, 0x05, 0x42, 0xa4, 0x09, 0xf3, 0xf8, 0x11, 0x62, 0x32, 0x31, 0x86, - 0xd2, 0x84, 0xf9, 0xf8, 0x43, 0xc4, 0x60, 0xeb, 0xd3, 0x84, 0xa1, 0x34, 0x96, 0x32, 0xa5, 0x52, - 0xb0, 0x03, 0xd6, 0xb0, 0x94, 0x69, 0x54, 0xca, 0x94, 0x97, 0x92, 0x17, 0x08, 0x91, 0x26, 0x0c, - 0x2f, 0xa5, 0x10, 0x63, 0xe2, 0x52, 0xa6, 0xbc, 0x94, 0xe2, 0x56, 0xea, 0x5e, 0x86, 0x30, 0xbc, - 0x94, 0x4d, 0xc8, 0x98, 0x08, 0x87, 0xad, 0xd4, 0xbd, 0xd4, 0xee, 0x8a, 0x46, 0x29, 0x84, 0x06, - 0x08, 0x2d, 0x61, 0x07, 0x23, 0x34, 0x10, 0xd0, 0x01, 0x42, 0xcb, 0xd8, 0x1b, 0x08, 0x1d, 0x08, - 0xe8, 0x08, 0xa1, 0x6b, 0x5b, 0xa9, 0x7b, 0xab, 0x08, 0xc5, 0x14, 0xbb, 0x0a, 0x79, 0xd3, 0x08, - 0x2d, 0x44, 0x54, 0x44, 0x93, 0x23, 0x00, 0xe2, 0x70, 0xc6, 0x21, 0x6e, 0x5d, 0x34, 0x3a, 0x02, - 0x30, 0x15, 0x4a, 0x48, 0x16, 0xe1, 0x15, 0x81, 0x97, 0x81, 0xec, 0x23, 0x28, 0x9b, 0xd6, 0xd0, - 0x1e, 0x1b, 0x0e, 0x6f, 0xd3, 0xc6, 0x56, 0xea, 0x5e, 0xe9, 0xd1, 0xfa, 0x03, 0x5a, 0x13, 0x31, - 0x66, 0x77, 0x45, 0x4b, 0x90, 0xb1, 0x27, 0xb0, 0x26, 0xd2, 0x1f, 0x3c, 0xa2, 0x8e, 0x65, 0xc4, - 0xa7, 0x24, 0xf8, 0x3e, 0x78, 0xf4, 0x64, 0x77, 0x45, 0x4b, 0x12, 0xb2, 0x3b, 0x50, 0x8e, 0x97, - 0x08, 0x32, 0x5e, 0x10, 0xb5, 0x4a, 0x40, 0xb1, 0x59, 0x5f, 0x06, 0x9e, 0x8b, 0x04, 0x9b, 0xa2, - 0xdf, 0x22, 0x00, 0xdb, 0x02, 0x30, 0xad, 0x91, 0x31, 0x75, 0x42, 0x44, 0x5f, 0x14, 0x1d, 0x28, - 0xc1, 0xd8, 0x0d, 0x28, 0x4e, 0x27, 0xd8, 0xca, 0xe7, 0x86, 0x53, 0xbd, 0x24, 0x08, 0x66, 0x20, - 0xcc, 0x1d, 0xe7, 0x39, 0x62, 0x2f, 0x8b, 0xd1, 0x8d, 0x00, 0x38, 0xbc, 0x2f, 0xad, 0x21, 0xa2, - 0xaa, 0xa2, 0x60, 0x91, 0xc6, 0x55, 0x64, 0x07, 0xdb, 0xb6, 0x5b, 0xbd, 0x42, 0x33, 0x98, 0x27, - 0xd8, 0x75, 0x48, 0x07, 0xfe, 0xb0, 0x7a, 0x95, 0xda, 0x0f, 0xbc, 0xfd, 0xcd, 0xd3, 0x89, 0xaf, - 0x21, 0x78, 0x3b, 0x0f, 0x59, 0x5a, 0x4d, 0xea, 0x75, 0x28, 0xec, 0x1b, 0xbe, 0x31, 0xd6, 0xac, - 0x11, 0x53, 0x20, 0x3d, 0xf1, 0x02, 0xb1, 0x8e, 0xf0, 0x53, 0x6d, 0x43, 0xee, 0xb9, 0xe1, 0x23, - 0x8e, 0x41, 0xc6, 0x35, 0xc6, 0x16, 0x21, 0x8b, 0x1a, 0x7d, 0xe3, 0xda, 0x09, 0xce, 0x82, 0xd0, - 0x1a, 0x0b, 0x21, 0x21, 0x52, 0x08, 0x3f, 0x74, 0xbc, 0x81, 0x58, 0x23, 0x05, 0x4d, 0xa4, 0xd4, - 0xff, 0x2f, 0x05, 0xb9, 0xba, 0xe7, 0x60, 0x76, 0x97, 0x21, 0xef, 0x5b, 0x8e, 0x3e, 0x2b, 0x2e, - 0xe7, 0x5b, 0xce, 0xbe, 0x17, 0x20, 0x62, 0xe8, 0x71, 0x04, 0x5f, 0xb5, 0xb9, 0xa1, 0x47, 0x88, - 0xa8, 0x02, 0x69, 0xa9, 0x02, 0x57, 0xa0, 0x10, 0x0e, 0x1c, 0x9d, 0xe0, 0x19, 0x82, 0xe7, 0xc3, - 0x81, 0xd3, 0x41, 0xd4, 0x65, 0xc8, 0x9b, 0x03, 0x8e, 0xc9, 0x12, 0x26, 0x67, 0x0e, 0x10, 0xa1, - 0x7e, 0x0a, 0x45, 0xcd, 0x38, 0x11, 0xd5, 0xb8, 0x08, 0x39, 0xcc, 0x40, 0xc8, 0xbf, 0x8c, 0x96, - 0x0d, 0x07, 0x4e, 0xcb, 0x44, 0x30, 0x56, 0xc2, 0x36, 0xa9, 0x0e, 0x19, 0x2d, 0x3b, 0xf4, 0x9c, - 0x96, 0xa9, 0xf6, 0x01, 0xea, 0x9e, 0xef, 0x7f, 0xe7, 0x26, 0x6c, 0x42, 0xd6, 0xb4, 0x26, 0xe1, - 0x11, 0x17, 0x1d, 0x1a, 0x4f, 0xa8, 0xf7, 0xa1, 0x80, 0xe3, 0xd2, 0xb6, 0x83, 0x90, 0xdd, 0x80, - 0x8c, 0x63, 0x07, 0x61, 0x35, 0xb5, 0x95, 0x9e, 0x1b, 0x35, 0x82, 0xab, 0x5b, 0x50, 0xd8, 0x33, - 0x4e, 0x9f, 0xe3, 0xc8, 0x61, 0x6e, 0x34, 0x84, 0x62, 0x48, 0xc4, 0x78, 0x96, 0x01, 0xfa, 0x86, - 0x7f, 0x68, 0x85, 0x24, 0xe9, 0xfe, 0x7b, 0x0a, 0x4a, 0xbd, 0xe9, 0xe0, 0xab, 0xa9, 0xe5, 0x9f, - 0x61, 0x9d, 0xef, 0x41, 0x3a, 0x3c, 0x9b, 0x10, 0x47, 0xe5, 0xd1, 0x25, 0x9e, 0xbd, 0x84, 0x7f, - 0x80, 0x4c, 0x1a, 0x92, 0x60, 0x23, 0x5c, 0xcf, 0xb4, 0xa2, 0x3e, 0xc8, 0x6a, 0x39, 0x4c, 0xb6, - 0x4c, 0xdc, 0x2e, 0xbc, 0x89, 0x18, 0x85, 0x55, 0x6f, 0xc2, 0xb6, 0x20, 0x3b, 0x3c, 0xb2, 0x1d, - 0x93, 0x06, 0x20, 0x59, 0x67, 0x8e, 0xc0, 0x51, 0xf2, 0xbd, 0x13, 0x3d, 0xb0, 0xbf, 0x8e, 0xc4, - 0x7f, 0xde, 0xf7, 0x4e, 0x7a, 0xf6, 0xd7, 0x96, 0xda, 0x17, 0x7b, 0x10, 0x40, 0xae, 0x57, 0xaf, - 0xb5, 0x6b, 0x9a, 0xb2, 0x82, 0xdf, 0xcd, 0xcf, 0x5b, 0xbd, 0x7e, 0x4f, 0x49, 0xb1, 0x0a, 0x40, - 0xa7, 0xdb, 0xd7, 0x45, 0x7a, 0x95, 0xe5, 0x60, 0xb5, 0xd5, 0x51, 0xd2, 0x48, 0x83, 0xf0, 0x56, - 0x47, 0xc9, 0xb0, 0x3c, 0xa4, 0x6b, 0x9d, 0x2f, 0x94, 0x2c, 0x7d, 0xb4, 0xdb, 0x4a, 0x4e, 0xfd, - 0xb3, 0x55, 0x28, 0x76, 0x07, 0x5f, 0x5a, 0xc3, 0x10, 0xdb, 0x8c, 0xb3, 0xd4, 0xf2, 0x5f, 0x5a, - 0x3e, 0x35, 0x3b, 0xad, 0x89, 0x14, 0x36, 0xc4, 0x1c, 0x50, 0xe3, 0xd2, 0xda, 0xaa, 0x39, 0x20, - 0xba, 0xe1, 0x91, 0x35, 0x36, 0xa8, 0x71, 0x48, 0x47, 0x29, 0x5c, 0x15, 0xde, 0xe0, 0x4b, 0x6a, - 0x5e, 0x5a, 0xc3, 0x4f, 0x76, 0x13, 0x4a, 0x3c, 0x0f, 0x79, 0x7e, 0x01, 0x07, 0xcd, 0x4f, 0xbe, - 0x9c, 0x3c, 0xf9, 0x88, 0x93, 0x72, 0xe5, 0x48, 0xb1, 0xb7, 0x71, 0x50, 0x47, 0xcc, 0x68, 0x6f, - 0xf0, 0x25, 0xc7, 0x16, 0xf8, 0x8c, 0xf6, 0x06, 0x5f, 0x12, 0xea, 0x1d, 0xd8, 0x08, 0xa6, 0x83, - 0x60, 0xe8, 0xdb, 0x93, 0xd0, 0xf6, 0x5c, 0x4e, 0x53, 0x24, 0x1a, 0x45, 0x46, 0x10, 0xf1, 0x3d, - 0x28, 0x4c, 0xa6, 0x03, 0xdd, 0x76, 0x47, 0x1e, 0x89, 0xfd, 0xd2, 0xa3, 0x35, 0x3e, 0x30, 0xfb, - 0xd3, 0x41, 0xcb, 0x1d, 0x79, 0x5a, 0x7e, 0xc2, 0x3f, 0x98, 0x0a, 0x6b, 0xae, 0x17, 0xea, 0xa8, - 0x2a, 0xe8, 0x63, 0x2b, 0x34, 0x68, 0x3f, 0xe0, 0x1b, 0x7e, 0xdb, 0x1b, 0x1e, 0xef, 0x59, 0xa1, - 0xa1, 0xde, 0x85, 0xbc, 0xe0, 0xc3, 0xbd, 0x3f, 0xb4, 0x5c, 0xc3, 0x0d, 0xf5, 0x58, 0x69, 0x28, - 0x70, 0x40, 0xcb, 0x54, 0xff, 0x38, 0x05, 0x4a, 0x4f, 0xaa, 0x0a, 0x32, 0x2f, 0x95, 0x1c, 0x6f, - 0x00, 0x18, 0xc3, 0xa1, 0x37, 0xe5, 0xd9, 0xf0, 0x09, 0x56, 0x14, 0x90, 0x96, 0x29, 0xf7, 0x5f, - 0x3a, 0xd1, 0x7f, 0xb7, 0xa0, 0x1c, 0xf1, 0x49, 0x8b, 0xbe, 0x24, 0x60, 0x51, 0x0f, 0x06, 0xd3, - 0xc4, 0xca, 0xcf, 0x07, 0x53, 0xce, 0x7d, 0x09, 0x72, 0xa4, 0x61, 0x04, 0xd1, 0xa8, 0xf0, 0x94, - 0xfa, 0xaf, 0x53, 0xb0, 0xd6, 0x72, 0x4d, 0xeb, 0xb4, 0x37, 0x34, 0xdc, 0xa8, 0x53, 0xec, 0x40, - 0xb7, 0x11, 0xa6, 0x07, 0x43, 0xc3, 0x15, 0xca, 0x41, 0xc9, 0x0e, 0x62, 0x3a, 0x6c, 0x03, 0x27, - 0xa0, 0xa2, 0x56, 0x29, 0xc7, 0x22, 0x41, 0xa8, 0xb0, 0xbb, 0xb0, 0x3e, 0xb0, 0x1c, 0xcf, 0x3d, - 0xd4, 0x43, 0x4f, 0xe7, 0x5a, 0x0e, 0x6f, 0xcb, 0x1a, 0x07, 0xf7, 0xbd, 0x3e, 0x69, 0x3b, 0x9b, - 0x90, 0x9d, 0x18, 0x7e, 0x18, 0x54, 0x33, 0x5b, 0x69, 0x5c, 0xc6, 0x94, 0xc0, 0x6e, 0xb6, 0x03, - 0x7d, 0xea, 0xda, 0x5f, 0x4d, 0x79, 0x33, 0x0a, 0x5a, 0xc1, 0x0e, 0x0e, 0x28, 0xcd, 0xee, 0x81, - 0xc2, 0x4b, 0xa6, 0x6c, 0xe5, 0x79, 0x56, 0x21, 0x38, 0x65, 0x4c, 0xc2, 0xee, 0x2f, 0xad, 0x42, - 0x61, 0x67, 0xea, 0x0e, 0x71, 0x30, 0xd8, 0x6d, 0xc8, 0x8c, 0xa6, 0xee, 0x90, 0xda, 0x12, 0x6f, - 0xa5, 0xf1, 0x3a, 0xd1, 0x08, 0x89, 0x12, 0xc8, 0xf0, 0x0f, 0x51, 0x72, 0x2d, 0x48, 0x20, 0x84, - 0xab, 0xff, 0x30, 0xc5, 0x73, 0xdc, 0x71, 0x8c, 0x43, 0x56, 0x80, 0x4c, 0xa7, 0xdb, 0x69, 0x2a, - 0x2b, 0xac, 0x0c, 0x85, 0x56, 0xa7, 0xdf, 0xd4, 0x3a, 0xb5, 0xb6, 0x92, 0xa2, 0xe5, 0xdc, 0xaf, - 0x6d, 0xb7, 0x9b, 0xca, 0x2a, 0x62, 0x9e, 0x77, 0xdb, 0xb5, 0x7e, 0xab, 0xdd, 0x54, 0x32, 0x1c, - 0xa3, 0xb5, 0xea, 0x7d, 0xa5, 0xc0, 0x14, 0x28, 0xef, 0x6b, 0xdd, 0xc6, 0x41, 0xbd, 0xa9, 0x77, - 0x0e, 0xda, 0x6d, 0x45, 0x61, 0x17, 0x60, 0x3d, 0x86, 0x74, 0x39, 0x70, 0x0b, 0x59, 0x9e, 0xd7, - 0xb4, 0x9a, 0xf6, 0x54, 0xf9, 0x11, 0x2b, 0x40, 0xba, 0xf6, 0xf4, 0xa9, 0xf2, 0x53, 0x94, 0x0c, - 0xc5, 0x17, 0xad, 0x8e, 0xfe, 0xbc, 0xd6, 0x3e, 0x68, 0x2a, 0x3f, 0x5d, 0x8d, 0xd2, 0x5d, 0xad, - 0xd1, 0xd4, 0x94, 0x9f, 0x66, 0xd8, 0x06, 0x94, 0x7f, 0xd2, 0xed, 0x34, 0xf7, 0x6a, 0xfb, 0xfb, - 0x54, 0x91, 0x9f, 0x16, 0xd4, 0xff, 0x9c, 0x81, 0x0c, 0xb6, 0x84, 0xa9, 0x33, 0x29, 0x18, 0x37, - 0x11, 0xc5, 0xd0, 0x76, 0xe6, 0x4f, 0xff, 0xfc, 0xe6, 0x0a, 0x97, 0x7f, 0xb7, 0x20, 0xed, 0xd8, - 0x21, 0x0d, 0x6b, 0xbc, 0x76, 0x84, 0xce, 0xb8, 0xbb, 0xa2, 0x21, 0x8e, 0xdd, 0x80, 0x14, 0x17, - 0x84, 0xa5, 0x47, 0x15, 0xb1, 0xb8, 0xc4, 0x4e, 0xba, 0xbb, 0xa2, 0xa5, 0x26, 0xec, 0x3a, 0xa4, - 0x5e, 0x0a, 0xa9, 0x58, 0xe6, 0x78, 0xbe, 0x97, 0x22, 0xf6, 0x25, 0xdb, 0x82, 0xf4, 0xd0, 0xe3, - 0x1a, 0x61, 0x8c, 0xe7, 0x3b, 0x0b, 0xe6, 0x3f, 0xf4, 0x1c, 0x76, 0x1b, 0xd2, 0xbe, 0x71, 0x42, - 0x23, 0x1b, 0x0f, 0x57, 0xbc, 0x75, 0x21, 0x91, 0x6f, 0x9c, 0x60, 0x25, 0x46, 0x24, 0x47, 0xe2, - 0x4a, 0x44, 0xe3, 0x8d, 0xc5, 0x8c, 0xd8, 0x16, 0xa4, 0x4e, 0x48, 0x92, 0xc4, 0x4a, 0xd0, 0x0b, - 0xdb, 0x35, 0xbd, 0x93, 0xde, 0xc4, 0x1a, 0x22, 0xc5, 0x09, 0x7b, 0x13, 0xd2, 0xc1, 0x74, 0x40, - 0x92, 0xa4, 0xf4, 0x68, 0x63, 0x61, 0x4f, 0xc0, 0x82, 0x82, 0xe9, 0x80, 0xdd, 0x85, 0xcc, 0xd0, - 0xf3, 0x7d, 0x21, 0x4d, 0x94, 0xa8, 0xc2, 0xd1, 0x76, 0x88, 0x4a, 0x21, 0xe2, 0xb1, 0xc0, 0x90, - 0x64, 0x48, 0x4c, 0x34, 0xdb, 0x8f, 0xb0, 0xc0, 0x90, 0xdd, 0x11, 0x9b, 0x5c, 0x59, 0xae, 0x75, - 0xb4, 0x05, 0x62, 0x3e, 0x88, 0xc5, 0x41, 0x1a, 0x1b, 0xa7, 0xa4, 0x71, 0xc6, 0x44, 0xd1, 0xde, - 0x87, 0x75, 0x1a, 0x1b, 0xa7, 0xec, 0x0e, 0xa4, 0x5f, 0x5a, 0x43, 0x52, 0x3e, 0xe3, 0xd2, 0xc4, - 0x20, 0x3d, 0xa7, 0xe6, 0x21, 0x9a, 0xe6, 0xbd, 0xe7, 0x98, 0xa4, 0x87, 0xc6, 0x63, 0xb9, 0xe3, - 0x39, 0xe6, 0x73, 0x1a, 0x4b, 0x42, 0xe2, 0x96, 0x6f, 0x4c, 0x4f, 0x51, 0x1a, 0x29, 0x7c, 0x73, - 0x36, 0xa6, 0xa7, 0x2d, 0x13, 0x85, 0xbf, 0x6b, 0xbe, 0x24, 0xed, 0x33, 0xa5, 0xe1, 0x27, 0x9a, - 0x47, 0x81, 0xe5, 0x58, 0xc3, 0xd0, 0x7e, 0x69, 0x87, 0x67, 0xa4, 0x5f, 0xa6, 0x34, 0x19, 0xb4, - 0x9d, 0x83, 0x8c, 0x75, 0x3a, 0xf1, 0xd5, 0x5d, 0xc8, 0x8b, 0x52, 0x16, 0x6c, 0xac, 0x2b, 0x50, - 0xb0, 0x03, 0x7d, 0xe8, 0xb9, 0x41, 0x28, 0x74, 0xa7, 0xbc, 0x1d, 0xd4, 0x31, 0x89, 0xe2, 0xd2, - 0x34, 0x42, 0xbe, 0x09, 0x95, 0x35, 0xfa, 0x56, 0x1f, 0x01, 0xcc, 0x9a, 0x85, 0x75, 0x72, 0x2c, - 0x37, 0x52, 0xd3, 0x1c, 0xcb, 0x8d, 0x79, 0x56, 0x25, 0x9e, 0x2b, 0x50, 0x8c, 0x35, 0x63, 0x56, - 0x86, 0x94, 0x21, 0xb6, 0xbf, 0x94, 0xa1, 0xde, 0x43, 0x45, 0x35, 0xd2, 0x7d, 0x93, 0x38, 0x4c, - 0x45, 0x9b, 0x62, 0x6a, 0xa0, 0x7e, 0x1f, 0xca, 0x9a, 0x15, 0x4c, 0x9d, 0xb0, 0xee, 0x39, 0x0d, - 0x6b, 0xc4, 0xde, 0x05, 0x88, 0xd3, 0x81, 0xd0, 0x52, 0x66, 0x73, 0xb7, 0x61, 0x8d, 0x34, 0x09, - 0xaf, 0xfe, 0xad, 0x0c, 0xe9, 0x7b, 0x0d, 0xae, 0x68, 0x09, 0x8d, 0x2a, 0x25, 0x69, 0x54, 0xf1, - 0xde, 0xb0, 0x9a, 0xd4, 0x2a, 0x8f, 0x6c, 0xd3, 0xb4, 0xdc, 0x48, 0x7b, 0xe4, 0x29, 0x1c, 0x6c, - 0xc3, 0x39, 0xa4, 0x05, 0x55, 0x79, 0xc4, 0xa2, 0x42, 0xc7, 0x13, 0xdf, 0x0a, 0x02, 0xae, 0xb7, - 0x18, 0xce, 0x61, 0xb4, 0xb6, 0xb3, 0xaf, 0x5a, 0xdb, 0x57, 0xa0, 0x80, 0x5b, 0x1e, 0x59, 0x7d, - 0x39, 0xde, 0xfb, 0xc2, 0xbc, 0x65, 0x6f, 0x41, 0x5e, 0xe8, 0xeb, 0x62, 0x51, 0x89, 0xe9, 0xd2, - 0xe0, 0x40, 0x2d, 0xc2, 0xb2, 0x2a, 0x2a, 0x79, 0xe3, 0xb1, 0xe5, 0x86, 0xd1, 0x3e, 0x2d, 0x92, - 0xec, 0x1d, 0x28, 0x7a, 0xae, 0xce, 0x95, 0x7a, 0xb1, 0xaa, 0xc4, 0xf4, 0xed, 0xba, 0x07, 0x04, - 0xd5, 0x0a, 0x9e, 0xf8, 0xc2, 0xaa, 0x38, 0xde, 0x89, 0x3e, 0x34, 0x7c, 0x93, 0x56, 0x56, 0x41, - 0xcb, 0x3b, 0xde, 0x49, 0xdd, 0xf0, 0x4d, 0xae, 0xb7, 0x7c, 0xe5, 0x4e, 0xc7, 0xb4, 0x9a, 0xd6, - 0x34, 0x91, 0x62, 0xd7, 0xa1, 0x38, 0x74, 0xa6, 0x41, 0x68, 0xf9, 0xdb, 0x67, 0xdc, 0x4c, 0xd3, - 0x66, 0x00, 0xac, 0xd7, 0xc4, 0xb7, 0xc7, 0x86, 0x7f, 0x46, 0x4b, 0xa7, 0xa0, 0x45, 0x49, 0xda, - 0x68, 0x8e, 0x6d, 0xf3, 0x94, 0xdb, 0x6a, 0x1a, 0x4f, 0x20, 0xfd, 0x11, 0x59, 0xd2, 0x01, 0xad, - 0x8f, 0x82, 0x16, 0x25, 0x69, 0x1c, 0xe8, 0x93, 0x56, 0x44, 0x51, 0x13, 0xa9, 0x84, 0xd2, 0xbd, - 0x71, 0xae, 0xd2, 0xcd, 0xe6, 0xf5, 0x1e, 0xcf, 0xb7, 0x0f, 0x6d, 0xa1, 0xb5, 0x5c, 0xe0, 0x7a, - 0x0f, 0x07, 0xd1, 0x46, 0xf5, 0x15, 0xe4, 0x45, 0x17, 0xe3, 0x0e, 0x84, 0xcb, 0x27, 0x29, 0x9e, - 0xf9, 0x0e, 0x84, 0x70, 0x76, 0x1b, 0xd6, 0x44, 0x5e, 0x41, 0xe8, 0xdb, 0xee, 0xa1, 0x98, 0x3c, - 0x65, 0x0e, 0xec, 0x11, 0x0c, 0x15, 0x05, 0x1c, 0x5e, 0xdd, 0x18, 0xd8, 0x0e, 0x2e, 0xd3, 0xb4, - 0x50, 0x6a, 0xa6, 0x8e, 0x53, 0xe3, 0x20, 0xb5, 0x0b, 0x85, 0x68, 0x40, 0x7e, 0x29, 0x65, 0xaa, - 0xbf, 0x99, 0x82, 0x12, 0xa9, 0x07, 0x5d, 0x52, 0x7e, 0xd8, 0xbb, 0xc0, 0x86, 0xbe, 0x65, 0x84, - 0x96, 0x6e, 0x9d, 0x86, 0xbe, 0x21, 0x94, 0x00, 0xae, 0x49, 0x28, 0x1c, 0xd3, 0x44, 0x04, 0xd7, - 0x03, 0x6e, 0x42, 0x69, 0x62, 0xf8, 0x41, 0xa4, 0x54, 0xf2, 0x02, 0x80, 0x83, 0x84, 0x4a, 0xa7, - 0xb8, 0x87, 0xbe, 0x31, 0xd6, 0x43, 0xef, 0xd8, 0x72, 0xb9, 0x3a, 0xcd, 0x0d, 0x89, 0x0a, 0xc1, - 0xfb, 0x08, 0x26, 0xad, 0xfa, 0xdf, 0xa6, 0x60, 0x6d, 0x9f, 0x8f, 0xfa, 0x33, 0xeb, 0xac, 0xc1, - 0xad, 0xb7, 0x61, 0xb4, 0x62, 0x33, 0x1a, 0x7d, 0xb3, 0x1b, 0x50, 0x9a, 0x1c, 0x5b, 0x67, 0x7a, - 0xc2, 0xd2, 0x29, 0x22, 0xa8, 0x4e, 0x6b, 0xf3, 0x6d, 0xc8, 0x79, 0xd4, 0x10, 0xb1, 0xc7, 0x89, - 0xad, 0x41, 0x6a, 0xa1, 0x26, 0x08, 0x50, 0x5d, 0x8a, 0xb3, 0x92, 0xf5, 0x32, 0x91, 0x19, 0x55, - 0x7f, 0x13, 0xb2, 0x88, 0x0a, 0xaa, 0x59, 0xae, 0xe7, 0x50, 0x82, 0xbd, 0x0f, 0x6b, 0x43, 0x6f, - 0x3c, 0xd1, 0x23, 0x76, 0xb1, 0xdb, 0x25, 0x65, 0x4a, 0x09, 0x49, 0xf6, 0x79, 0x5e, 0xea, 0xef, - 0xa5, 0xa1, 0x40, 0x75, 0x10, 0x62, 0xc5, 0x36, 0x4f, 0x23, 0xb1, 0x52, 0xd4, 0xb2, 0xb6, 0x89, - 0x52, 0xfb, 0x35, 0xaa, 0x59, 0xac, 0x72, 0xa5, 0x65, 0x95, 0xeb, 0x12, 0xe4, 0x84, 0xbe, 0x95, - 0xe1, 0x72, 0x67, 0x7a, 0xbe, 0xb6, 0x95, 0x5d, 0xa6, 0x6d, 0xe1, 0x10, 0x72, 0x1a, 0xeb, 0x14, - 0xf7, 0x37, 0x2e, 0x5a, 0x80, 0x40, 0x4d, 0x84, 0xc8, 0x42, 0x23, 0x9f, 0x14, 0x1a, 0x55, 0xc8, - 0xbf, 0xb4, 0x03, 0x1b, 0x27, 0x48, 0x81, 0x2f, 0x43, 0x91, 0x94, 0x86, 0xa1, 0xf8, 0xba, 0x61, - 0x88, 0x9b, 0x6d, 0x38, 0x87, 0x5c, 0xed, 0x8f, 0x9a, 0x5d, 0x73, 0x0e, 0x3d, 0xf6, 0x01, 0x5c, - 0x9c, 0xa1, 0x45, 0x6b, 0xc8, 0x3d, 0x46, 0x1e, 0x20, 0x8d, 0xc5, 0x94, 0xd4, 0x22, 0xb2, 0xcb, - 0xee, 0xc3, 0x86, 0xc4, 0x32, 0x41, 0xf5, 0x26, 0x20, 0x99, 0x53, 0xd4, 0xd6, 0x63, 0x72, 0xd2, - 0x7a, 0x02, 0xf5, 0x9f, 0xac, 0xc2, 0xda, 0x8e, 0xe7, 0x5b, 0xf6, 0xa1, 0x3b, 0x9b, 0x75, 0x0b, - 0x9a, 0x7f, 0x34, 0x13, 0x57, 0xa5, 0x99, 0x78, 0x13, 0x4a, 0x23, 0xce, 0xa8, 0x87, 0x03, 0xee, - 0x34, 0xc8, 0x68, 0x20, 0x40, 0xfd, 0x81, 0x83, 0xab, 0x39, 0x22, 0x20, 0xe6, 0x0c, 0x31, 0x47, - 0x4c, 0xb8, 0xd7, 0xb0, 0xef, 0x91, 0xd4, 0x35, 0x2d, 0xc7, 0x0a, 0xf9, 0xf0, 0x54, 0x1e, 0xbd, - 0x11, 0xed, 0xf4, 0x52, 0x9d, 0x1e, 0x68, 0xd6, 0xa8, 0x46, 0xea, 0x11, 0x0a, 0xe1, 0x06, 0x91, - 0x0b, 0x5e, 0x21, 0xb1, 0x73, 0xdf, 0x90, 0x97, 0x4b, 0x0e, 0xb5, 0x0f, 0xc5, 0x18, 0x8c, 0xba, - 0xae, 0xd6, 0x14, 0xfa, 0xed, 0x0a, 0x2b, 0x41, 0xbe, 0x5e, 0xeb, 0xd5, 0x6b, 0x8d, 0xa6, 0x92, - 0x42, 0x54, 0xaf, 0xd9, 0xe7, 0x3a, 0xed, 0x2a, 0x5b, 0x87, 0x12, 0xa6, 0x1a, 0xcd, 0x9d, 0xda, - 0x41, 0xbb, 0xaf, 0xa4, 0xd9, 0x1a, 0x14, 0x3b, 0x5d, 0xbd, 0x56, 0xef, 0xb7, 0xba, 0x1d, 0x25, - 0xa3, 0xfe, 0x08, 0x0a, 0xf5, 0x23, 0x6b, 0x78, 0x7c, 0x5e, 0x2f, 0x92, 0xd1, 0x6d, 0x0d, 0x8f, - 0x85, 0x7e, 0x3a, 0x67, 0x74, 0x5b, 0xc3, 0x63, 0xb5, 0x09, 0xc5, 0x7d, 0xc3, 0x0f, 0x6d, 0xaa, - 0xd7, 0x13, 0x58, 0x8b, 0x13, 0x0d, 0x6b, 0x14, 0xed, 0xdc, 0x2c, 0xd6, 0x5a, 0x63, 0x94, 0x96, - 0x24, 0x54, 0xdf, 0x85, 0xb2, 0x0c, 0x60, 0xd7, 0x21, 0x6d, 0x5a, 0xa3, 0x25, 0x72, 0x12, 0xc1, - 0xea, 0x73, 0x28, 0xd7, 0xa3, 0x9d, 0xe8, 0xbc, 0xaa, 0x3f, 0x82, 0x0a, 0xad, 0xf8, 0xe1, 0x20, - 0x5a, 0xf2, 0xab, 0x4b, 0x96, 0x7c, 0x19, 0x69, 0xea, 0x03, 0xb1, 0xe6, 0x3f, 0x82, 0xd2, 0xbe, - 0xef, 0x4d, 0x2c, 0x3f, 0xa4, 0x6c, 0x15, 0x48, 0x1f, 0x5b, 0x67, 0x22, 0x57, 0xfc, 0x9c, 0xf9, - 0x42, 0x56, 0x65, 0x5f, 0xc8, 0x23, 0x28, 0x44, 0x6c, 0xdf, 0x98, 0xe7, 0x87, 0x28, 0x3a, 0x89, - 0xc7, 0xb6, 0x02, 0x2c, 0xec, 0x01, 0xc0, 0x24, 0x06, 0x88, 0x8e, 0x8b, 0xd4, 0x7d, 0x91, 0xb9, - 0x26, 0x51, 0xa8, 0x6f, 0x40, 0xfe, 0xb9, 0x6d, 0x9d, 0x88, 0xe6, 0xbf, 0xb4, 0xad, 0x93, 0xa8, - 0xf9, 0xf8, 0xad, 0xfe, 0xe5, 0x22, 0x14, 0x68, 0x7d, 0x35, 0xce, 0x77, 0x3f, 0x7d, 0x1b, 0xad, - 0x68, 0x4b, 0xac, 0xa7, 0xcc, 0x12, 0x5d, 0x8c, 0xaf, 0xae, 0x37, 0x00, 0xa4, 0xb5, 0xce, 0x25, - 0x57, 0x31, 0x8c, 0x97, 0x38, 0xaa, 0x13, 0xb4, 0x17, 0x05, 0x5f, 0x39, 0xc2, 0x8a, 0x9c, 0x01, - 0xd8, 0x03, 0xbe, 0xd9, 0x93, 0xdd, 0xc8, 0x15, 0xa2, 0x0b, 0x91, 0x52, 0x3f, 0x70, 0xac, 0xc8, - 0xd4, 0x20, 0x0d, 0x00, 0x13, 0x24, 0xc7, 0x2c, 0x3f, 0x40, 0x71, 0x45, 0xfe, 0x69, 0x2d, 0x4a, - 0xb2, 0xb7, 0x20, 0x83, 0x42, 0x5e, 0x98, 0x06, 0x17, 0xa2, 0x1e, 0x94, 0x76, 0x29, 0x8d, 0x08, - 0xd8, 0x3d, 0xc8, 0x93, 0x68, 0xb1, 0x50, 0xd2, 0x48, 0xbd, 0x1d, 0x09, 0x7d, 0x2d, 0x42, 0xb3, - 0xb7, 0x21, 0x3b, 0x3a, 0xb6, 0xce, 0x82, 0xea, 0x1a, 0xd1, 0x5d, 0x58, 0xb2, 0x66, 0x35, 0x4e, - 0xc1, 0xee, 0x40, 0xc5, 0xb7, 0x46, 0x3a, 0x39, 0xa4, 0x50, 0xc8, 0x04, 0xd5, 0x0a, 0xc9, 0x90, - 0xb2, 0x6f, 0x8d, 0xea, 0x08, 0xec, 0x0f, 0x9c, 0x80, 0xdd, 0x85, 0x1c, 0xad, 0x1e, 0xd4, 0x85, - 0xa4, 0x92, 0xa3, 0xa5, 0xa8, 0x09, 0x2c, 0xfb, 0x00, 0x40, 0x68, 0x5c, 0xfa, 0xe0, 0x8c, 0x1c, - 0xb9, 0xf1, 0x62, 0x92, 0xe7, 0xbf, 0xac, 0x97, 0xbd, 0x05, 0x59, 0x9c, 0x24, 0x41, 0xf5, 0x32, - 0xe5, 0xbc, 0x91, 0x9c, 0x41, 0x54, 0x53, 0xc2, 0xb3, 0x7b, 0x50, 0xc0, 0x89, 0xa2, 0xe3, 0x70, - 0x54, 0x65, 0x15, 0x54, 0xcc, 0x2a, 0xdc, 0x19, 0xac, 0x93, 0xde, 0x57, 0x0e, 0xbb, 0x0f, 0x19, - 0x13, 0x17, 0xf3, 0x15, 0xca, 0xf1, 0x92, 0x34, 0x2e, 0x28, 0xac, 0x1a, 0xd6, 0x88, 0xb4, 0x62, - 0xa2, 0x61, 0xbb, 0x50, 0xc1, 0x69, 0xf4, 0x88, 0x36, 0x7b, 0xec, 0xbe, 0xea, 0x55, 0xe2, 0xba, - 0x35, 0xc7, 0xd5, 0x11, 0x44, 0xd4, 0xd9, 0x4d, 0x37, 0xf4, 0xcf, 0xb4, 0x35, 0x57, 0x86, 0xb1, - 0xab, 0x68, 0xba, 0xb4, 0xbd, 0xe1, 0xb1, 0x65, 0x56, 0xaf, 0x45, 0x8e, 0x09, 0x9e, 0x66, 0x9f, - 0xc2, 0x1a, 0x4d, 0x2c, 0x4c, 0x62, 0xe1, 0xd5, 0xeb, 0x24, 0x4c, 0xe5, 0x29, 0x13, 0xa1, 0xb4, - 0x24, 0x25, 0x8a, 0x78, 0x3b, 0xd0, 0x43, 0x6b, 0x3c, 0xf1, 0x7c, 0x54, 0x5e, 0xdf, 0x88, 0x1c, - 0x2e, 0xfd, 0x08, 0x84, 0x1b, 0x71, 0x7c, 0xec, 0xa4, 0x7b, 0xa3, 0x51, 0x60, 0x85, 0xd5, 0x1b, - 0xb4, 0x6e, 0x2a, 0xd1, 0xe9, 0x53, 0x97, 0xa0, 0xb4, 0x11, 0x06, 0xba, 0x79, 0xe6, 0x1a, 0x63, - 0x7b, 0x58, 0xbd, 0xc9, 0x75, 0x64, 0x3b, 0x68, 0x70, 0x80, 0xac, 0xa6, 0x6e, 0x25, 0xd4, 0xd4, - 0x0b, 0x90, 0x35, 0x07, 0xb8, 0x1c, 0x6f, 0x51, 0xb6, 0x19, 0x73, 0xd0, 0x32, 0xd9, 0x7b, 0x50, - 0x9c, 0x44, 0x22, 0xb0, 0xaa, 0xca, 0xc6, 0x78, 0x2c, 0x19, 0xb5, 0x19, 0x05, 0xda, 0x87, 0x3b, - 0x96, 0x11, 0x4e, 0x7d, 0x6b, 0xc7, 0x31, 0x0e, 0xab, 0xb7, 0x29, 0x27, 0x19, 0x74, 0xf5, 0x29, - 0xe9, 0xba, 0xd4, 0xea, 0x8f, 0xe6, 0x84, 0x4b, 0x62, 0x69, 0x48, 0x52, 0x68, 0x77, 0x45, 0x96, - 0x31, 0xdb, 0x59, 0x92, 0xc2, 0x57, 0x7f, 0x04, 0x6c, 0x71, 0xbc, 0x5e, 0x27, 0xe9, 0xb2, 0x42, - 0xd2, 0x7d, 0x6f, 0xf5, 0x49, 0x4a, 0x7d, 0x0e, 0x6b, 0x89, 0x85, 0xbc, 0x54, 0x62, 0x73, 0x75, - 0xc9, 0x18, 0x0b, 0xf3, 0x92, 0x27, 0x84, 0x87, 0x2a, 0xb0, 0xdd, 0x43, 0xe1, 0xd9, 0xa2, 0x89, - 0xd0, 0xa3, 0xb4, 0xfa, 0x67, 0x69, 0x28, 0xef, 0x1a, 0xc1, 0xd1, 0x9e, 0x31, 0xe9, 0x85, 0x46, - 0x18, 0xe0, 0xf0, 0x1e, 0x19, 0xc1, 0xd1, 0xd8, 0x98, 0x70, 0xc5, 0x35, 0xc5, 0xcd, 0x66, 0x01, - 0x43, 0xad, 0x15, 0x27, 0x16, 0x26, 0xbb, 0xee, 0xfe, 0x33, 0x61, 0x13, 0xc7, 0x69, 0x14, 0x2b, - 0xc1, 0xd1, 0x74, 0x34, 0x8a, 0x8b, 0x8a, 0x92, 0xec, 0x0e, 0xac, 0x89, 0x4f, 0xd2, 0x5a, 0x4f, - 0xc5, 0xb1, 0x63, 0x12, 0xc8, 0x1e, 0x43, 0x49, 0x00, 0xfa, 0x91, 0x10, 0xac, 0xc4, 0xbe, 0x8e, - 0x19, 0x42, 0x93, 0xa9, 0xd8, 0x8f, 0xe1, 0xa2, 0x94, 0xdc, 0xf1, 0xfc, 0xbd, 0xa9, 0x13, 0xda, - 0xf5, 0x8e, 0x50, 0x11, 0xae, 0x2d, 0xb0, 0xcf, 0x48, 0xb4, 0xe5, 0x9c, 0xc9, 0xda, 0xee, 0xd9, - 0x2e, 0xc9, 0xd4, 0xb4, 0x96, 0x04, 0xce, 0x51, 0x19, 0xa7, 0x24, 0x4a, 0x93, 0x54, 0xc6, 0x29, - 0x2e, 0x36, 0x01, 0xd8, 0xb3, 0xc2, 0x23, 0xcf, 0x24, 0xfd, 0x30, 0x5e, 0x6c, 0x3d, 0x19, 0xa5, - 0x25, 0x29, 0xb1, 0x3b, 0xd1, 0x12, 0x1a, 0xba, 0x21, 0x69, 0x89, 0x69, 0x2d, 0x4a, 0xe2, 0x36, - 0xe3, 0x1b, 0xee, 0xa1, 0x15, 0x54, 0x4b, 0x5b, 0xe9, 0x7b, 0x29, 0x4d, 0xa4, 0xd4, 0x3f, 0x5c, - 0x85, 0x2c, 0x1f, 0xc9, 0x6b, 0x50, 0x1c, 0x90, 0xb3, 0x18, 0x2d, 0x53, 0xe1, 0x00, 0x26, 0x40, - 0x67, 0x3a, 0xe6, 0xda, 0x9d, 0xf0, 0x69, 0xa4, 0x34, 0xfa, 0xc6, 0x2c, 0xbd, 0x69, 0x88, 0x65, - 0xa5, 0x09, 0x2a, 0x52, 0x58, 0x09, 0xdf, 0x3b, 0xa1, 0xd9, 0x90, 0x21, 0x44, 0x94, 0x24, 0x1f, - 0x33, 0xed, 0x58, 0xc8, 0x94, 0x25, 0x5c, 0x81, 0x00, 0x75, 0x37, 0x9c, 0xf7, 0xbf, 0xe4, 0x16, - 0xfc, 0x2f, 0xec, 0x06, 0xa0, 0xee, 0x38, 0xb4, 0xba, 0xae, 0x55, 0xef, 0x50, 0x0f, 0x17, 0x34, - 0x09, 0x82, 0x0b, 0xc4, 0xf4, 0x26, 0xd4, 0xa9, 0x59, 0x0d, 0x3f, 0xd9, 0xc7, 0xf1, 0xec, 0xa4, - 0x36, 0x0a, 0x4d, 0x5b, 0x48, 0x74, 0x79, 0x1e, 0x6b, 0x09, 0x3a, 0xcc, 0x09, 0xc5, 0x34, 0xd7, - 0xb4, 0xf1, 0x53, 0x6d, 0x02, 0x68, 0xde, 0x49, 0x60, 0x85, 0xe4, 0x68, 0xbc, 0x4c, 0x4d, 0x4c, - 0x1c, 0x11, 0x79, 0x27, 0xfb, 0x5e, 0x10, 0xdb, 0x9b, 0xab, 0xcb, 0xed, 0x4d, 0xf5, 0x21, 0xe4, - 0x71, 0x0f, 0x37, 0x42, 0x83, 0xdd, 0x11, 0xbe, 0x1d, 0xae, 0x79, 0x08, 0x27, 0xd7, 0xac, 0x0c, - 0xe1, 0xed, 0x69, 0x47, 0xe5, 0x12, 0xcf, 0x2d, 0xc9, 0xdc, 0x8b, 0xf7, 0x0f, 0x91, 0xa1, 0xd0, - 0x0a, 0xae, 0x41, 0x11, 0xab, 0x46, 0x7e, 0x73, 0x21, 0x17, 0x0a, 0xbe, 0x77, 0x52, 0xc7, 0xb4, - 0xfa, 0xef, 0x52, 0x50, 0xea, 0xfa, 0x26, 0x6e, 0x5c, 0xbd, 0x89, 0x35, 0x7c, 0xad, 0x79, 0x8c, - 0x3a, 0x84, 0xe7, 0x38, 0x06, 0x89, 0x48, 0x61, 0x6e, 0xc5, 0x00, 0xf6, 0x01, 0x64, 0x46, 0x28, - 0x0a, 0xd3, 0xb2, 0x66, 0x2d, 0x65, 0x1f, 0x7d, 0xa3, 0x70, 0xd4, 0x88, 0x54, 0xfd, 0xb5, 0xb8, - 0x7c, 0xf2, 0x33, 0xcb, 0xde, 0xe5, 0x15, 0x3a, 0xe7, 0xe9, 0xd5, 0x95, 0x14, 0x2b, 0x40, 0xa6, - 0xd1, 0xec, 0xd5, 0xb9, 0x3e, 0x8d, 0x9a, 0x75, 0x4f, 0xdf, 0x69, 0x69, 0xbd, 0xbe, 0x92, 0xa1, - 0x83, 0x23, 0x02, 0xb4, 0x6b, 0xbd, 0xbe, 0x52, 0x60, 0x00, 0xb9, 0x83, 0x4e, 0xeb, 0xc7, 0x07, - 0x4d, 0x45, 0x51, 0xff, 0x65, 0x0a, 0x60, 0xe6, 0x04, 0x65, 0xef, 0x40, 0xe9, 0x84, 0x52, 0xba, - 0xe4, 0x1d, 0x97, 0xdb, 0x08, 0x1c, 0x4d, 0xfa, 0xcd, 0x7b, 0x50, 0x8e, 0x45, 0x3d, 0xee, 0xfd, - 0x8b, 0x6e, 0xf2, 0x52, 0x8c, 0xdf, 0x3e, 0x63, 0xef, 0x42, 0xc1, 0xc3, 0x76, 0x20, 0x69, 0x5a, - 0xde, 0xf8, 0xa5, 0xe6, 0x6b, 0x79, 0x8f, 0x27, 0x50, 0x47, 0x18, 0xf9, 0x91, 0xf9, 0x1c, 0x93, - 0xee, 0x20, 0xa8, 0xee, 0x18, 0xd3, 0xc0, 0xd2, 0x38, 0x3e, 0x96, 0xd2, 0xd9, 0x99, 0x94, 0x56, - 0x7f, 0x02, 0x95, 0x9e, 0x31, 0x9e, 0x70, 0x59, 0x4e, 0x0d, 0x63, 0x90, 0xc1, 0x39, 0x21, 0xa6, - 0x1e, 0x7d, 0xe3, 0xa2, 0xdb, 0xb7, 0xfc, 0xa1, 0xe5, 0x46, 0x6b, 0x34, 0x4a, 0xa2, 0xf8, 0x3d, - 0x40, 0x69, 0xae, 0x79, 0x27, 0x91, 0x38, 0x8f, 0xd2, 0xea, 0x1f, 0xa5, 0xa0, 0x24, 0x55, 0x83, - 0x3d, 0x84, 0x0c, 0x29, 0x93, 0x29, 0x59, 0x10, 0x4a, 0x04, 0xfc, 0x9b, 0xab, 0x1f, 0x48, 0xc8, - 0xee, 0x42, 0x36, 0x08, 0x0d, 0x3f, 0xf2, 0xa7, 0x2b, 0x12, 0xc7, 0xb6, 0x37, 0x75, 0x4d, 0x8d, - 0xa3, 0x99, 0x0a, 0x69, 0xcb, 0x35, 0x85, 0xc3, 0x61, 0x91, 0x0a, 0x91, 0xea, 0x16, 0x14, 0xe3, - 0xec, 0x71, 0x0a, 0x68, 0xdd, 0x17, 0x3d, 0x65, 0x85, 0x15, 0x21, 0xab, 0xd5, 0x3a, 0x4f, 0x9b, - 0x4a, 0x4a, 0xfd, 0xe3, 0x14, 0xc0, 0x8c, 0x8b, 0x3d, 0x48, 0xd4, 0xf6, 0xea, 0x7c, 0xae, 0x0f, - 0xe8, 0xaf, 0x54, 0xd9, 0xeb, 0x50, 0x9c, 0xba, 0x04, 0xb4, 0x4c, 0xb1, 0x13, 0xcd, 0x00, 0x68, - 0x01, 0x45, 0xd1, 0x1f, 0x73, 0x16, 0xd0, 0x4b, 0xc3, 0x51, 0xbf, 0x07, 0xc5, 0x38, 0x3b, 0x34, - 0xea, 0x76, 0xba, 0xed, 0x76, 0xf7, 0x45, 0xab, 0xf3, 0x54, 0x59, 0xc1, 0xe4, 0xbe, 0xd6, 0xac, - 0x37, 0x1b, 0x98, 0x4c, 0xe1, 0x9c, 0xad, 0x1f, 0x68, 0x5a, 0xb3, 0xd3, 0xd7, 0xb5, 0xee, 0x0b, - 0x65, 0x55, 0xfd, 0xff, 0x33, 0xb0, 0xd1, 0x75, 0x1b, 0xd3, 0x89, 0x63, 0x0f, 0x8d, 0xd0, 0x7a, - 0x66, 0x9d, 0xd5, 0xc3, 0x53, 0xdc, 0x7d, 0x8d, 0x30, 0xf4, 0xf9, 0x62, 0x2e, 0x6a, 0x3c, 0xc1, - 0x9d, 0x12, 0x81, 0xe5, 0x87, 0xe4, 0x73, 0x91, 0x57, 0x71, 0x85, 0xc3, 0xeb, 0x9e, 0x43, 0x6b, - 0x99, 0xfd, 0x00, 0x2e, 0x72, 0x47, 0x06, 0xa7, 0x44, 0x05, 0x56, 0xa7, 0xc5, 0x9c, 0x5e, 0x98, - 0xba, 0x8c, 0x13, 0x22, 0x2b, 0x92, 0x91, 0x08, 0xbb, 0x09, 0xa5, 0x19, 0x7b, 0x74, 0x48, 0x05, - 0x31, 0x21, 0xd5, 0x04, 0x0d, 0xef, 0xa8, 0xd6, 0xba, 0x6d, 0x9e, 0x92, 0x8b, 0x27, 0xab, 0x55, - 0xbc, 0x59, 0x63, 0x70, 0x13, 0xfe, 0x1c, 0x36, 0x12, 0x94, 0x54, 0x8b, 0x1c, 0xd5, 0xe2, 0xdd, - 0xc8, 0x41, 0x3a, 0xd7, 0x7a, 0x19, 0x82, 0xd5, 0xe1, 0x1a, 0xe9, 0xba, 0x97, 0x84, 0x0a, 0x5d, - 0xc4, 0x3e, 0x74, 0x3d, 0xdf, 0x12, 0x02, 0xbf, 0x60, 0x07, 0x2d, 0x4a, 0xcf, 0xec, 0x1f, 0xe9, - 0x50, 0x95, 0xef, 0x2f, 0xd1, 0x79, 0x21, 0x47, 0xdb, 0x7c, 0x07, 0xcd, 0x68, 0x79, 0x4a, 0xb7, - 0x4c, 0x76, 0x5b, 0xa8, 0xb3, 0x7a, 0x64, 0xd2, 0x00, 0x99, 0x34, 0x65, 0x02, 0x3e, 0xe7, 0xb0, - 0xab, 0x1d, 0xd8, 0x5c, 0x56, 0xc9, 0x25, 0x6a, 0xd8, 0x96, 0xac, 0x86, 0xcd, 0x19, 0xed, 0x33, - 0x95, 0xec, 0xef, 0xa6, 0xa0, 0xdc, 0xb0, 0xcc, 0xe9, 0xe4, 0x33, 0xcf, 0x76, 0x71, 0x02, 0x7c, - 0x08, 0x65, 0xcf, 0x31, 0x69, 0xf4, 0xa4, 0xd8, 0x80, 0xc4, 0x89, 0x91, 0x70, 0x6e, 0x83, 0xe7, - 0x98, 0x75, 0xcf, 0xa1, 0x48, 0x82, 0xf7, 0xe0, 0x02, 0x77, 0x68, 0x08, 0xff, 0xde, 0x29, 0x67, - 0x5e, 0xa5, 0x91, 0x51, 0x38, 0x8a, 0x2b, 0x47, 0x44, 0xfe, 0x2b, 0xb0, 0x29, 0x91, 0xe3, 0xc8, - 0x70, 0xfa, 0xc5, 0x49, 0xb2, 0x11, 0xf3, 0x46, 0x47, 0x36, 0xea, 0x6f, 0xad, 0x42, 0x91, 0xbb, - 0x43, 0xb0, 0xbe, 0xf7, 0x20, 0xef, 0x0d, 0xbe, 0xd4, 0xfd, 0xd8, 0x4d, 0xb0, 0x70, 0xd2, 0x98, - 0xf3, 0x06, 0x5f, 0x6a, 0xd6, 0x88, 0xbd, 0x13, 0xed, 0xf3, 0xa6, 0x35, 0x12, 0x9d, 0x52, 0x49, - 0xda, 0x23, 0x62, 0xdf, 0x47, 0x5b, 0xf9, 0x31, 0x94, 0x66, 0x33, 0x3e, 0xa8, 0xe6, 0xcf, 0xef, - 0x85, 0x78, 0x01, 0x04, 0xc8, 0xc4, 0x5d, 0x42, 0x9c, 0xa9, 0x70, 0x3e, 0x13, 0x27, 0x23, 0xa6, - 0x4f, 0xa1, 0x32, 0x93, 0xf1, 0xc4, 0x57, 0x3c, 0x97, 0x6f, 0x2d, 0xa6, 0xa4, 0x13, 0x8f, 0xbf, - 0x97, 0x82, 0x62, 0x8b, 0x17, 0x1f, 0x9e, 0xb2, 0x5b, 0x90, 0x7e, 0x45, 0x2f, 0x20, 0x8e, 0xdd, - 0x87, 0x0d, 0xc3, 0x34, 0x75, 0x63, 0x34, 0xb2, 0x86, 0xa1, 0x65, 0xea, 0xa8, 0x02, 0x09, 0x99, - 0xb3, 0x6e, 0x98, 0x66, 0x4d, 0xc0, 0x49, 0x76, 0xe3, 0x9a, 0x0f, 0xf4, 0xc8, 0xf0, 0x9c, 0x1d, - 0x29, 0x17, 0xb4, 0x8a, 0x1d, 0x08, 0xbb, 0x93, 0xfb, 0x92, 0x13, 0x1d, 0x9b, 0x79, 0x75, 0xc7, - 0xaa, 0xbf, 0xbb, 0x0a, 0xa0, 0x59, 0x13, 0xc7, 0x18, 0x5a, 0xff, 0xd7, 0x54, 0x1a, 0xc5, 0x52, - 0x3c, 0xb0, 0xae, 0x19, 0x85, 0x60, 0x44, 0x83, 0xe8, 0x9a, 0xec, 0x47, 0xf0, 0x86, 0x6f, 0x9d, - 0xf8, 0x76, 0x68, 0xe9, 0x23, 0xdf, 0x1b, 0xeb, 0x09, 0xc9, 0x83, 0x0b, 0xb3, 0x48, 0x95, 0xb8, - 0x22, 0x88, 0x76, 0x7c, 0x6f, 0x9c, 0x94, 0x3e, 0xea, 0x1f, 0x95, 0xa0, 0x54, 0x73, 0x0d, 0xe7, - 0xec, 0x6b, 0x8b, 0x62, 0x02, 0xc8, 0xbb, 0x3a, 0x99, 0x86, 0xbc, 0xb9, 0xfc, 0xc0, 0xac, 0x48, - 0x10, 0x6a, 0xe8, 0x4d, 0x28, 0x79, 0xd3, 0x30, 0xc6, 0xf3, 0x23, 0x34, 0xe0, 0x20, 0x22, 0x88, - 0xf9, 0x63, 0xcf, 0x7d, 0xc4, 0x4f, 0xe6, 0xcf, 0x8c, 0x3f, 0x56, 0x89, 0x63, 0x7e, 0x22, 0x40, - 0x69, 0x64, 0x8f, 0xa9, 0xc1, 0xc1, 0x74, 0x6c, 0xf1, 0x46, 0xa7, 0x79, 0x7c, 0x5a, 0x5d, 0xc0, - 0x30, 0x97, 0xb1, 0x35, 0xf6, 0xfc, 0x33, 0x9e, 0x4b, 0x8e, 0xe7, 0xc2, 0x41, 0x94, 0xcb, 0xbb, - 0xc0, 0x4e, 0x0c, 0x3b, 0xd4, 0x93, 0x59, 0x71, 0x33, 0x44, 0x41, 0x4c, 0x5f, 0xce, 0xee, 0x12, - 0xe4, 0x4c, 0x3b, 0x38, 0x6e, 0x75, 0x85, 0x09, 0x22, 0x52, 0xd8, 0x96, 0x60, 0x68, 0xa0, 0x06, - 0x14, 0x5a, 0x5c, 0x5d, 0x4e, 0x6b, 0x45, 0x84, 0x6c, 0x23, 0x00, 0x77, 0x50, 0xd7, 0x0a, 0x4f, - 0x3c, 0x1f, 0x39, 0xb9, 0x85, 0x31, 0x03, 0xa0, 0xa6, 0x81, 0xa4, 0x58, 0x10, 0x79, 0x83, 0xd2, - 0x5a, 0x9c, 0x46, 0xdd, 0x9d, 0x2f, 0x5f, 0xc2, 0x96, 0x79, 0xf5, 0x67, 0x10, 0x76, 0x07, 0x2a, - 0x54, 0x7d, 0xb2, 0x40, 0xb0, 0x0d, 0x74, 0xca, 0x95, 0xd6, 0xca, 0x08, 0x25, 0x67, 0x02, 0x52, - 0x7d, 0x0a, 0x57, 0x12, 0xed, 0xd3, 0x0d, 0xdf, 0x37, 0xce, 0xf4, 0xb1, 0xf1, 0xa5, 0xe7, 0x93, - 0xe3, 0x27, 0xad, 0x5d, 0x92, 0xbb, 0xad, 0x86, 0xe8, 0x3d, 0xc4, 0x9e, 0xcb, 0x6a, 0xbb, 0x9e, - 0x4f, 0x5e, 0xa1, 0xa5, 0xac, 0x88, 0x25, 0x17, 0x06, 0x0d, 0x30, 0x99, 0x43, 0x01, 0x8f, 0x6b, - 0xd4, 0x4a, 0x04, 0xdb, 0x26, 0x10, 0x1a, 0x04, 0xc1, 0x63, 0x2e, 0x59, 0x37, 0x44, 0x90, 0xd1, - 0x63, 0x92, 0xbf, 0x1c, 0x71, 0x64, 0x19, 0x26, 0x9d, 0x9c, 0x11, 0x62, 0xd7, 0x32, 0xe8, 0x5c, - 0x3a, 0x78, 0xac, 0x4f, 0xa6, 0x21, 0x0f, 0x48, 0xd4, 0xb2, 0xc1, 0xe3, 0xfd, 0x69, 0x28, 0xc0, - 0x87, 0x56, 0x48, 0x61, 0x88, 0x04, 0x7e, 0x6a, 0x85, 0xb8, 0x11, 0x06, 0x8f, 0x23, 0x2f, 0xf8, - 0x45, 0xd1, 0xb7, 0x8f, 0x85, 0x9b, 0x5b, 0x85, 0xb5, 0x18, 0xa9, 0x8f, 0xa7, 0x3c, 0x02, 0x31, - 0xad, 0x95, 0x22, 0x82, 0xbd, 0xa9, 0x83, 0x03, 0x3b, 0x34, 0x86, 0x47, 0x96, 0xee, 0x63, 0x55, - 0x2e, 0xf3, 0xa1, 0x23, 0x88, 0x86, 0xb5, 0xb9, 0x06, 0x3c, 0xa1, 0x1f, 0xd9, 0x21, 0x79, 0xa7, - 0xd2, 0x5a, 0x81, 0x00, 0xbb, 0x76, 0x88, 0x62, 0x81, 0x23, 0xc5, 0x0c, 0xa4, 0x2c, 0xae, 0x10, - 0xd1, 0x3a, 0x21, 0xf6, 0x08, 0x4e, 0x19, 0xdd, 0x03, 0x25, 0x41, 0x8b, 0xf9, 0x5d, 0x25, 0xd2, - 0x8a, 0x44, 0x8a, 0xb9, 0xde, 0x05, 0xce, 0xac, 0xe3, 0xd4, 0xe3, 0x79, 0x5e, 0xe3, 0xe6, 0x30, - 0x81, 0x1b, 0x76, 0x70, 0x4c, 0x39, 0xde, 0x81, 0x8a, 0x44, 0x87, 0xf9, 0x5d, 0xe7, 0x33, 0x23, - 0x26, 0x4b, 0xd4, 0xd1, 0xb7, 0xc6, 0x5e, 0x28, 0x9a, 0xf9, 0x86, 0x54, 0x47, 0x8d, 0xe0, 0xc9, - 0x3a, 0x0a, 0x5a, 0xcc, 0xf3, 0x86, 0x54, 0x47, 0x4e, 0x8a, 0xb9, 0xde, 0x82, 0x32, 0x4a, 0x91, - 0xd0, 0x72, 0xf9, 0xe2, 0xbf, 0xc9, 0x3b, 0x56, 0xc0, 0x68, 0xf5, 0xdf, 0x82, 0x32, 0xef, 0x79, - 0x21, 0x2e, 0xb7, 0x38, 0x89, 0x80, 0x45, 0x02, 0x42, 0xf4, 0xc6, 0xd8, 0x76, 0xc9, 0x05, 0x95, - 0xd6, 0x8a, 0x1c, 0xb2, 0x67, 0xbb, 0x32, 0xda, 0x38, 0x25, 0x47, 0xd4, 0x0c, 0x6d, 0x9c, 0xd2, - 0x92, 0x9c, 0xd8, 0x8e, 0xc3, 0x17, 0xfe, 0x6d, 0xb1, 0x24, 0x11, 0xd2, 0x13, 0x36, 0x35, 0x47, - 0x63, 0xde, 0x77, 0xc4, 0xcc, 0x40, 0x00, 0x66, 0x3d, 0x43, 0x1a, 0xa7, 0xd5, 0x37, 0x65, 0xa4, - 0x71, 0x2a, 0x04, 0x13, 0x56, 0x9a, 0x78, 0xef, 0xc6, 0x82, 0x09, 0x41, 0xc8, 0x2d, 0x13, 0x18, - 0xa7, 0xd5, 0xb7, 0x92, 0x04, 0xc6, 0x29, 0xd9, 0x9a, 0x96, 0x61, 0xf2, 0x9a, 0xdd, 0xe3, 0xd9, - 0x23, 0x80, 0x2a, 0xb6, 0x05, 0xe5, 0xe0, 0xb1, 0x3e, 0xc3, 0xbf, 0xcd, 0xd9, 0x83, 0xc7, 0x5a, - 0x44, 0x71, 0x07, 0x2a, 0xf1, 0xd8, 0x73, 0x9a, 0xfb, 0x7c, 0x64, 0x4d, 0x31, 0xf6, 0x74, 0xe8, - 0xf9, 0xd3, 0x14, 0x5c, 0xed, 0xd2, 0x71, 0x2c, 0x6d, 0x17, 0x7b, 0x56, 0x10, 0x18, 0x87, 0xd6, - 0x8e, 0xe7, 0xef, 0x4c, 0xbf, 0xfe, 0xfa, 0x8c, 0xdd, 0x83, 0xf5, 0x7d, 0xc3, 0xb7, 0xdc, 0x30, - 0x3e, 0xae, 0x13, 0xaa, 0xd9, 0x3c, 0x98, 0x3d, 0x01, 0x85, 0x83, 0x0e, 0x62, 0x25, 0x57, 0x98, - 0x79, 0x49, 0xef, 0xfa, 0x02, 0x95, 0xfa, 0x3f, 0x6f, 0x41, 0xa6, 0xe3, 0x99, 0x16, 0x7b, 0x1f, - 0x8a, 0x14, 0x3c, 0x29, 0x99, 0x1d, 0xc2, 0x2d, 0x83, 0x68, 0xfa, 0x43, 0xf6, 0x46, 0xc1, 0x15, - 0x5f, 0xe7, 0x87, 0x5b, 0xde, 0x22, 0xcb, 0x89, 0xce, 0x2a, 0x71, 0x47, 0x2c, 0x09, 0xef, 0x0e, - 0x39, 0x23, 0x38, 0x06, 0xe5, 0x29, 0xf9, 0xb5, 0x7d, 0xcb, 0x25, 0xfd, 0x3c, 0xab, 0xc5, 0x69, - 0xb2, 0x57, 0x7d, 0x0f, 0x77, 0x6f, 0x2e, 0x75, 0xb2, 0x4b, 0xec, 0x55, 0x8e, 0x27, 0x31, 0xf4, - 0x3e, 0x14, 0xbf, 0xf4, 0x6c, 0x97, 0x57, 0x3c, 0xb7, 0x50, 0x71, 0x54, 0x49, 0x79, 0xc5, 0xbf, - 0x14, 0x5f, 0xec, 0x36, 0xe4, 0x3d, 0x97, 0xe7, 0x9d, 0x5f, 0xc8, 0x3b, 0xe7, 0xb9, 0x6d, 0x1e, - 0xcb, 0xb3, 0x66, 0x07, 0xba, 0x6f, 0x1f, 0x1e, 0x85, 0x3a, 0x72, 0x8a, 0x33, 0xce, 0x92, 0x1d, - 0x68, 0x08, 0xc3, 0x6c, 0xd1, 0x0c, 0x1f, 0xd9, 0x0e, 0x2a, 0x09, 0x94, 0x59, 0x71, 0x21, 0x33, - 0xe0, 0x68, 0xca, 0xf0, 0x4d, 0x28, 0x1c, 0xfa, 0xde, 0x74, 0x82, 0x76, 0x35, 0x2c, 0x50, 0xe6, - 0x09, 0xb7, 0x7d, 0x86, 0x5b, 0x26, 0x7d, 0xda, 0xee, 0xa1, 0x4e, 0x2e, 0x88, 0xd2, 0x56, 0xfa, - 0x5e, 0x41, 0x2b, 0x47, 0x40, 0x72, 0x2e, 0xbc, 0x09, 0x05, 0xe3, 0xf0, 0x50, 0x17, 0x21, 0x49, - 0x0b, 0x79, 0x19, 0x87, 0x87, 0x54, 0xe4, 0x03, 0x58, 0x3b, 0xb1, 0x5d, 0x3d, 0x98, 0x58, 0x43, - 0x4e, 0xbb, 0xb6, 0xd8, 0x95, 0x27, 0xb6, 0x8b, 0x96, 0x37, 0xd1, 0xcb, 0xa6, 0x7f, 0xe5, 0xb5, - 0xa6, 0xff, 0x16, 0x64, 0x1d, 0x7b, 0x6c, 0x87, 0x22, 0x48, 0x29, 0x61, 0x1b, 0x10, 0x82, 0xa9, - 0x90, 0x13, 0x3e, 0x6f, 0x65, 0x81, 0x44, 0x60, 0x92, 0x2a, 0xd4, 0xc6, 0x6b, 0x54, 0x28, 0x49, - 0x4f, 0x67, 0xaf, 0xd6, 0xd3, 0x3f, 0x22, 0x85, 0xd8, 0x72, 0x43, 0x3d, 0x62, 0xb8, 0xb0, 0x9c, - 0xa1, 0xcc, 0xc9, 0xba, 0x9c, 0xed, 0x03, 0x28, 0xf9, 0xe4, 0x93, 0xd2, 0xc9, 0x81, 0xb5, 0x29, - 0x1b, 0xf5, 0x33, 0x67, 0x95, 0x06, 0xfe, 0xcc, 0x71, 0x55, 0x83, 0xf5, 0x59, 0xd0, 0x25, 0x8f, - 0x5e, 0xbd, 0x28, 0x3b, 0xc5, 0x13, 0x51, 0x9a, 0x91, 0x0a, 0x6e, 0x27, 0x42, 0x37, 0x6f, 0xc3, - 0x1a, 0x0f, 0xb7, 0xe0, 0x87, 0xe2, 0x01, 0xed, 0x72, 0x45, 0xad, 0x4c, 0x40, 0x7e, 0x60, 0x1e, - 0xb0, 0x07, 0x00, 0x91, 0xfa, 0x18, 0x9e, 0xd2, 0x36, 0x17, 0xb7, 0x86, 0xef, 0x85, 0xf5, 0xf0, - 0x54, 0x2b, 0x9a, 0xd1, 0x27, 0x4a, 0xef, 0x81, 0xed, 0x9a, 0x38, 0x8f, 0x42, 0xe3, 0x30, 0xa8, - 0x56, 0x69, 0x99, 0x95, 0x04, 0xac, 0x6f, 0x1c, 0x06, 0x68, 0xa6, 0x19, 0x5c, 0x5b, 0xe4, 0xf5, - 0xbe, 0x22, 0xfb, 0x70, 0x24, 0x3d, 0x52, 0x2b, 0x19, 0x92, 0x52, 0xf9, 0x09, 0xb0, 0xe8, 0x7c, - 0x4d, 0xb2, 0xba, 0xae, 0x2e, 0x4c, 0xad, 0x75, 0x71, 0xc0, 0x16, 0x47, 0x8a, 0xdf, 0x84, 0x52, - 0xe0, 0x4d, 0xfd, 0xa1, 0xa5, 0x07, 0xa1, 0x35, 0xa9, 0x5e, 0xa3, 0x0a, 0x01, 0x07, 0xf5, 0x42, - 0x6b, 0xc2, 0x3e, 0x81, 0xb5, 0xa4, 0xd6, 0x7d, 0x7d, 0xc9, 0x31, 0x15, 0x4d, 0x0b, 0xad, 0x3c, - 0x94, 0xf5, 0xf0, 0xdb, 0x3c, 0x20, 0x98, 0xb6, 0x38, 0x62, 0xe4, 0x47, 0x31, 0x65, 0xd7, 0x0b, - 0xeb, 0x11, 0x0c, 0x3b, 0x30, 0xb2, 0xc6, 0xc2, 0x53, 0xda, 0x15, 0xe3, 0x0e, 0x8c, 0xed, 0x1f, - 0xd4, 0x6e, 0x23, 0x53, 0x08, 0xe7, 0x02, 0xb7, 0x31, 0x88, 0xe1, 0x66, 0x62, 0x2e, 0xc4, 0xc6, - 0x87, 0x06, 0xfe, 0xcc, 0x10, 0xf9, 0x04, 0x2a, 0xdc, 0xd1, 0x1c, 0x2f, 0xa3, 0xad, 0xf3, 0x96, - 0x51, 0x99, 0x08, 0x05, 0x04, 0x25, 0x09, 0x67, 0xe4, 0x2b, 0xea, 0xd6, 0xa2, 0x43, 0x8f, 0xd0, - 0x6d, 0x5a, 0x56, 0x4f, 0xa0, 0x32, 0xf1, 0x71, 0xc8, 0xe2, 0xc6, 0xa8, 0x72, 0x3f, 0xed, 0xfb, - 0xd6, 0xac, 0x3d, 0xe5, 0x89, 0x94, 0x62, 0x3f, 0x84, 0x0d, 0x89, 0x73, 0x7a, 0x4c, 0xcc, 0xb7, - 0x89, 0x79, 0x73, 0x8e, 0xf9, 0xe0, 0x18, 0xd9, 0x2b, 0x93, 0x44, 0x9a, 0xd5, 0xe6, 0x3c, 0x27, - 0x68, 0x95, 0xdc, 0x21, 0xfe, 0xcb, 0xe7, 0xb8, 0x43, 0x12, 0x2e, 0x95, 0x67, 0xfc, 0x64, 0xa7, - 0x15, 0x34, 0x5d, 0x93, 0x36, 0xed, 0x82, 0xc6, 0x13, 0xec, 0x31, 0x94, 0xb9, 0x7e, 0x4c, 0x81, - 0x97, 0x41, 0xf5, 0xae, 0xec, 0x3a, 0x26, 0x25, 0x99, 0x10, 0x5a, 0xc9, 0x89, 0xbf, 0x03, 0xf6, - 0x31, 0x6c, 0xf0, 0x5e, 0x93, 0xa5, 0xf0, 0x5b, 0x8b, 0x13, 0x91, 0x88, 0x76, 0x66, 0xa2, 0x58, - 0x83, 0x2b, 0xfe, 0xd4, 0x25, 0x9d, 0x59, 0x70, 0x4e, 0x7c, 0x6f, 0x60, 0x71, 0xfe, 0x7b, 0xc4, - 0x2f, 0x9a, 0xa3, 0x71, 0x32, 0xce, 0x4b, 0xe3, 0x76, 0xc9, 0x97, 0x41, 0xfb, 0xc8, 0x77, 0x4e, - 0x9e, 0x83, 0xa9, 0xed, 0x98, 0x3c, 0xcf, 0xb7, 0xbf, 0x4d, 0x9e, 0xdb, 0xc8, 0x47, 0x79, 0x32, - 0xc8, 0x4c, 0xa7, 0xb6, 0x49, 0xba, 0x43, 0x59, 0xa3, 0x6f, 0xf6, 0x26, 0x54, 0x7c, 0x6b, 0x38, - 0xf5, 0x03, 0xfb, 0xa5, 0xa5, 0x07, 0xb6, 0x7b, 0x5c, 0x7d, 0x87, 0xfa, 0x71, 0x2d, 0x86, 0xf6, - 0x6c, 0xf7, 0x18, 0x27, 0xaf, 0x75, 0x1a, 0x5a, 0xbe, 0xcb, 0x63, 0xc1, 0xdf, 0x95, 0x27, 0x6f, - 0x93, 0x10, 0x28, 0x7d, 0x34, 0xb0, 0xe2, 0xef, 0xb9, 0xc9, 0x11, 0xf0, 0xc9, 0xf1, 0xe0, 0x1b, - 0x4d, 0x8e, 0x1e, 0x4d, 0x8e, 0xbb, 0x50, 0xb0, 0xdd, 0xd0, 0xf2, 0x5f, 0x1a, 0x4e, 0xf5, 0xe1, - 0xc2, 0x0c, 0x8e, 0x71, 0xec, 0x0e, 0xe4, 0x03, 0xc7, 0x46, 0x29, 0x54, 0x7d, 0x7f, 0x81, 0x2c, - 0x42, 0xb1, 0x7b, 0x50, 0x8c, 0xaf, 0x31, 0x55, 0x3f, 0x58, 0xa0, 0x9b, 0x21, 0xd9, 0x0d, 0xc8, - 0x9c, 0xe0, 0x84, 0x7a, 0xb4, 0xe8, 0xea, 0x47, 0x38, 0x6a, 0x08, 0x23, 0xd4, 0x14, 0x49, 0x43, - 0x78, 0xbc, 0xa0, 0x21, 0xec, 0xd8, 0x8e, 0xc3, 0x35, 0x84, 0x91, 0xf8, 0xc2, 0xfd, 0x95, 0x38, - 0xb0, 0x25, 0x1f, 0x2e, 0xee, 0xaf, 0x88, 0x7b, 0x4e, 0x17, 0xbe, 0x4a, 0x01, 0xf9, 0xaf, 0xb9, - 0x1b, 0xfe, 0x23, 0xb9, 0xaf, 0x92, 0x8e, 0x6d, 0x0d, 0x82, 0x38, 0x8d, 0x6a, 0xaf, 0xf0, 0xde, - 0xdb, 0xe6, 0x69, 0xf5, 0x63, 0x7e, 0x93, 0x80, 0x43, 0x5a, 0xe6, 0x29, 0x7b, 0x1f, 0xd6, 0xa2, - 0x50, 0x1d, 0x2c, 0x2e, 0xa8, 0x7e, 0xb2, 0x50, 0x83, 0x24, 0x01, 0x6b, 0x40, 0x79, 0x84, 0x1a, - 0xe3, 0x98, 0x2b, 0x90, 0xd5, 0x27, 0x54, 0x91, 0xad, 0x48, 0xe8, 0x9c, 0xa7, 0x60, 0x6a, 0x09, - 0x2e, 0xf6, 0x00, 0x98, 0x3d, 0xe2, 0xe3, 0xb9, 0xe3, 0x7b, 0x63, 0xae, 0x24, 0x56, 0x3f, 0xa5, - 0xd9, 0xb5, 0x04, 0x43, 0x87, 0x79, 0x96, 0x6b, 0xea, 0xe3, 0x40, 0x68, 0x22, 0xdf, 0xa3, 0x7a, - 0x0a, 0x91, 0x1a, 0x5f, 0x77, 0x14, 0x5b, 0x5e, 0x09, 0x69, 0xf7, 0x02, 0xae, 0x98, 0x7c, 0x0a, - 0x38, 0x5d, 0x5f, 0xce, 0x58, 0x7f, 0xe5, 0x95, 0xac, 0x48, 0x1b, 0xb1, 0x3e, 0x81, 0x8a, 0x69, - 0x99, 0xd3, 0x09, 0x29, 0x65, 0x34, 0x45, 0xbf, 0x2f, 0x0b, 0x3f, 0xd9, 0x0d, 0xa9, 0x95, 0x4d, - 0xd9, 0x29, 0xf9, 0x09, 0xac, 0x47, 0xfe, 0xc2, 0x50, 0xb8, 0x16, 0x7f, 0x20, 0x17, 0x1b, 0xbb, - 0x03, 0xb5, 0xb5, 0x69, 0xf4, 0x49, 0x45, 0x3e, 0x86, 0x35, 0xda, 0xdb, 0x03, 0xd7, 0x98, 0x04, - 0x47, 0x5e, 0x58, 0xfd, 0x55, 0x59, 0x4d, 0xe9, 0x09, 0xa8, 0x56, 0x46, 0xa2, 0x28, 0x85, 0x5b, - 0xd2, 0x6c, 0x9d, 0x0e, 0x43, 0xab, 0xfa, 0x43, 0xbe, 0x25, 0xc5, 0xc0, 0x7a, 0x68, 0xb1, 0xc7, - 0x00, 0xc6, 0x64, 0xe2, 0x9c, 0xf1, 0xa9, 0xf9, 0x23, 0x9a, 0x9a, 0x9b, 0xd2, 0xd4, 0xac, 0x21, - 0x92, 0xe6, 0x66, 0xd1, 0x88, 0x3e, 0xd9, 0x23, 0x28, 0x4f, 0xbc, 0x20, 0xd4, 0xcd, 0xb1, 0x43, - 0xed, 0xaf, 0xc9, 0x6b, 0x7b, 0xdf, 0x0b, 0xc2, 0xc6, 0xd8, 0xa1, 0x8d, 0x69, 0x12, 0x7f, 0xb3, - 0x36, 0x5c, 0x48, 0xc8, 0x6d, 0x83, 0x8e, 0xce, 0xab, 0xdb, 0x54, 0xe2, 0x75, 0xa9, 0x44, 0x49, - 0x7e, 0x8b, 0xb8, 0xb1, 0x0d, 0x6f, 0x1e, 0x44, 0xd6, 0x0d, 0x8d, 0x41, 0x1c, 0x3c, 0x59, 0xe7, - 0x0a, 0x0b, 0x41, 0xa3, 0xe8, 0xc9, 0x27, 0xb0, 0x3e, 0xa3, 0xc2, 0x06, 0x06, 0xd5, 0x86, 0x3c, - 0x93, 0xa5, 0x10, 0xe7, 0xb5, 0x88, 0x11, 0x61, 0x01, 0xf5, 0x9d, 0xe7, 0x38, 0xd3, 0x89, 0x10, - 0xa5, 0xd5, 0xa6, 0xe8, 0x3b, 0x02, 0x72, 0x29, 0x29, 0x19, 0x80, 0xd6, 0xb8, 0xba, 0x23, 0x1b, - 0x80, 0xd6, 0x58, 0xfd, 0x67, 0x59, 0x28, 0x44, 0x26, 0x0b, 0x2b, 0x41, 0xfe, 0xa0, 0xf3, 0xac, - 0xd3, 0x7d, 0xd1, 0xe1, 0x57, 0xb5, 0x6a, 0xbd, 0x5e, 0x53, 0xeb, 0x2b, 0x26, 0xab, 0x00, 0xd0, - 0x65, 0x0c, 0xbd, 0x57, 0xaf, 0x75, 0xf8, 0xd5, 0x2d, 0xba, 0x02, 0xc2, 0xd3, 0xab, 0x6c, 0x03, - 0xd6, 0x76, 0x0e, 0x3a, 0x14, 0xe0, 0xc6, 0x41, 0x69, 0x04, 0x35, 0x3f, 0xe7, 0xc7, 0x7a, 0x1c, - 0x94, 0x41, 0xd0, 0x5e, 0xad, 0xdf, 0xd4, 0x5a, 0x11, 0x28, 0x4b, 0xb1, 0x72, 0xdd, 0x03, 0xad, - 0x2e, 0x72, 0xca, 0xb1, 0x8b, 0xb0, 0x11, 0xb3, 0x45, 0x59, 0x2a, 0x79, 0xac, 0xd9, 0xbe, 0xd6, - 0xfd, 0xac, 0x59, 0xef, 0x2b, 0x40, 0x67, 0x84, 0x4f, 0x9f, 0x2a, 0x25, 0x56, 0x86, 0x42, 0xa3, - 0xd5, 0xeb, 0xb7, 0x3a, 0xf5, 0xbe, 0x52, 0xc6, 0x0a, 0xef, 0xb4, 0xda, 0xfd, 0xa6, 0xa6, 0xac, - 0xb1, 0x02, 0x64, 0x3e, 0xeb, 0xb6, 0x3a, 0x4a, 0x85, 0x2e, 0xa5, 0xd4, 0xf6, 0xf6, 0xdb, 0x4d, - 0x65, 0x1d, 0xa1, 0xbd, 0xae, 0xd6, 0x57, 0x14, 0x84, 0xbe, 0x68, 0x75, 0x1a, 0xdd, 0x17, 0xca, - 0x06, 0x2b, 0x42, 0xf6, 0xa0, 0x83, 0xc5, 0x30, 0xb6, 0x06, 0x45, 0xfa, 0xd4, 0x6b, 0xed, 0xb6, - 0x72, 0x41, 0x3a, 0x58, 0xdc, 0x44, 0x14, 0x1d, 0x53, 0xf6, 0xb0, 0x0e, 0x17, 0xb1, 0x2d, 0x71, - 0x92, 0xa8, 0x2f, 0x61, 0x3e, 0x7b, 0xad, 0xce, 0x41, 0x4f, 0xb9, 0x8c, 0xc4, 0xf4, 0x49, 0x98, - 0x2a, 0xe6, 0xd3, 0xea, 0x50, 0x57, 0xde, 0xc0, 0xef, 0x46, 0xb3, 0xdd, 0xec, 0x37, 0x95, 0x9b, - 0xd8, 0x2a, 0xad, 0xb9, 0xdf, 0xae, 0xd5, 0x9b, 0xca, 0x16, 0x26, 0xda, 0xdd, 0xfa, 0x33, 0xbd, - 0xbb, 0xaf, 0xdc, 0x62, 0x9b, 0xa0, 0x74, 0x3b, 0x7a, 0xe3, 0x60, 0xbf, 0xdd, 0xaa, 0xd7, 0xfa, - 0x4d, 0xfd, 0x59, 0xf3, 0x0b, 0x45, 0xc5, 0x6e, 0xdf, 0xd7, 0x9a, 0xba, 0xc8, 0xeb, 0x36, 0x53, - 0xa0, 0xbc, 0x73, 0xf0, 0x93, 0x9f, 0x7c, 0xa1, 0x8b, 0x76, 0xbf, 0x89, 0xd5, 0x9a, 0x51, 0xe8, - 0x07, 0xcf, 0x94, 0xbb, 0x73, 0xa0, 0xde, 0x33, 0xe5, 0x2d, 0xec, 0xb7, 0x68, 0x20, 0x94, 0x7b, - 0x48, 0xa0, 0x35, 0xeb, 0x07, 0x5a, 0xaf, 0xf5, 0xbc, 0xa9, 0xd7, 0xfb, 0x4d, 0xe5, 0x6d, 0xea, - 0xa8, 0x56, 0xe7, 0x99, 0x72, 0x1f, 0x5b, 0x82, 0x5f, 0x7c, 0x78, 0xde, 0x61, 0x0c, 0x2a, 0x33, - 0x5a, 0x82, 0xbd, 0x8b, 0x24, 0xdb, 0x5a, 0xb7, 0xd6, 0xa8, 0xd7, 0x7a, 0x7d, 0xe5, 0x3d, 0xec, - 0x86, 0xde, 0x7e, 0xbb, 0xd5, 0x57, 0x1e, 0x60, 0x5b, 0x9f, 0xd6, 0xfa, 0xbb, 0x4d, 0x4d, 0x79, - 0x88, 0x23, 0xdd, 0x6f, 0xed, 0x35, 0x75, 0xd1, 0xed, 0x8f, 0xb0, 0x8c, 0x9d, 0x56, 0xbb, 0xad, - 0x3c, 0xa6, 0xb3, 0xb3, 0x9a, 0xd6, 0x6f, 0xd1, 0x58, 0x7f, 0x88, 0x19, 0xd4, 0xf6, 0xf7, 0xdb, - 0x5f, 0x28, 0x1f, 0x61, 0x03, 0xf7, 0x0e, 0xda, 0xfd, 0x96, 0x7e, 0xb0, 0xdf, 0xa8, 0xf5, 0x9b, - 0xca, 0xc7, 0x34, 0x11, 0xba, 0xbd, 0x7e, 0x63, 0xaf, 0xad, 0x7c, 0x42, 0x79, 0xd2, 0x34, 0xac, - 0xb7, 0xbb, 0x9d, 0xa6, 0xf2, 0x44, 0xfd, 0x0d, 0x28, 0x44, 0x66, 0x2c, 0x66, 0xd3, 0xea, 0x74, - 0x9a, 0x9a, 0xb2, 0x82, 0x45, 0xb5, 0x9b, 0x3b, 0x7d, 0x25, 0x45, 0x07, 0x89, 0xad, 0xa7, 0xbb, - 0x7d, 0x65, 0x15, 0x3f, 0xbb, 0x07, 0xd8, 0x6b, 0x69, 0x6a, 0x6e, 0x73, 0xaf, 0xa5, 0x64, 0xf0, - 0xab, 0xd6, 0xe9, 0xb7, 0x94, 0x2c, 0xcd, 0x9b, 0x56, 0xe7, 0x69, 0xbb, 0xa9, 0xe4, 0x10, 0xba, - 0x57, 0xd3, 0x9e, 0x29, 0x79, 0x9e, 0x69, 0xa3, 0xf9, 0xb9, 0x52, 0x60, 0x39, 0x58, 0x6d, 0x3f, - 0x52, 0x8a, 0x08, 0x6a, 0x34, 0x1b, 0x07, 0xfb, 0x0a, 0xa8, 0xf7, 0x20, 0x5f, 0x3b, 0x3c, 0xdc, - 0xf3, 0x4c, 0x3a, 0xbb, 0xdc, 0x39, 0x68, 0xb7, 0xf9, 0x3a, 0xda, 0xee, 0xf6, 0xfb, 0xdd, 0x3d, - 0x25, 0x85, 0x33, 0xb7, 0xdf, 0xdd, 0x57, 0x56, 0xd5, 0x16, 0x14, 0xa2, 0xdd, 0x54, 0xba, 0x68, - 0x55, 0x80, 0xcc, 0xbe, 0xd6, 0x7c, 0xce, 0x4f, 0xbf, 0x3b, 0xcd, 0xcf, 0xb1, 0x9a, 0xf8, 0x85, - 0x19, 0xa5, 0xb1, 0x20, 0x7e, 0x23, 0x8a, 0x6e, 0x5a, 0xb5, 0x5b, 0x9d, 0x66, 0x4d, 0x53, 0xb2, - 0xea, 0x47, 0x89, 0x83, 0x45, 0x21, 0x78, 0xb0, 0xf8, 0x5a, 0x4b, 0x14, 0xdf, 0x7a, 0xda, 0xe9, - 0x6a, 0x4d, 0x7e, 0x75, 0x4b, 0x74, 0xe4, 0xaa, 0xfa, 0x0e, 0x14, 0x63, 0xa1, 0x89, 0x13, 0xab, - 0xae, 0x75, 0x7b, 0x3d, 0xde, 0xef, 0x2b, 0x98, 0xa6, 0xbe, 0xe1, 0xe9, 0x94, 0xda, 0x83, 0x8d, - 0x48, 0x5e, 0x53, 0x54, 0x3b, 0x99, 0x37, 0x9b, 0x90, 0x6d, 0x5b, 0x2f, 0x2d, 0x27, 0x0a, 0xcf, - 0xa6, 0x04, 0x42, 0xbb, 0x83, 0x2f, 0x5b, 0xf1, 0xed, 0x5a, 0x4a, 0xa0, 0x82, 0xd6, 0x91, 0x2e, - 0xf8, 0xd2, 0xb5, 0x80, 0xdf, 0x4d, 0x41, 0x21, 0xde, 0x05, 0xee, 0xc0, 0x6a, 0xbf, 0x27, 0x0e, - 0x26, 0x36, 0x1f, 0xcc, 0xde, 0x33, 0xe8, 0x47, 0x5f, 0xda, 0x6a, 0xbf, 0xc7, 0xde, 0x85, 0x1c, - 0xbf, 0x8f, 0x28, 0x4e, 0x94, 0x36, 0x93, 0x3b, 0x4b, 0x9f, 0x70, 0x9a, 0xa0, 0x61, 0x1f, 0x41, - 0x31, 0xae, 0xad, 0x70, 0xb1, 0x5c, 0x4e, 0x32, 0xc4, 0x68, 0x6d, 0x46, 0xa9, 0xb6, 0xa1, 0x92, - 0xcc, 0x90, 0xdd, 0x00, 0xe0, 0x59, 0x4a, 0xae, 0x25, 0x09, 0xc2, 0xae, 0x42, 0x74, 0x4d, 0xb2, - 0x41, 0x15, 0x5b, 0x8b, 0xaf, 0x4d, 0x36, 0xd4, 0xbf, 0x9e, 0x06, 0x98, 0xe9, 0x91, 0xd8, 0x11, - 0xb1, 0xe3, 0x28, 0x2b, 0xce, 0xa4, 0xaf, 0x41, 0xd1, 0xf1, 0x0c, 0x53, 0x7e, 0xce, 0xa0, 0x80, - 0x00, 0x1a, 0x1a, 0xf9, 0xca, 0x50, 0x91, 0x07, 0x84, 0xb0, 0x4b, 0x90, 0x1b, 0x79, 0xfe, 0xd8, - 0x08, 0x45, 0x2c, 0xbe, 0x48, 0xe1, 0x76, 0xc0, 0xcf, 0x49, 0x51, 0x9b, 0x76, 0x29, 0x1c, 0x1f, - 0xc7, 0xa0, 0x2c, 0x80, 0x6d, 0x84, 0xa1, 0x71, 0x69, 0xb9, 0x43, 0xc7, 0x0b, 0x2c, 0x13, 0xed, - 0xae, 0x1c, 0xa9, 0xcc, 0x10, 0x81, 0xb6, 0xcf, 0x78, 0x6b, 0xfd, 0xb1, 0xed, 0x1a, 0xa1, 0x38, - 0x3d, 0xa0, 0xd6, 0x46, 0x10, 0xac, 0xee, 0x97, 0x81, 0x27, 0xfc, 0x48, 0xfc, 0xc8, 0xb5, 0x80, - 0x00, 0xaa, 0xee, 0x1b, 0x00, 0x56, 0x30, 0x34, 0x26, 0x3c, 0xf3, 0x22, 0x65, 0x5e, 0x14, 0x90, - 0xed, 0x33, 0xd6, 0x86, 0x4a, 0x7f, 0x80, 0xdb, 0x97, 0xd7, 0x30, 0x42, 0xa3, 0xee, 0x39, 0xc2, - 0xc3, 0x73, 0x67, 0x5e, 0xe1, 0x7e, 0x90, 0x24, 0xe3, 0x67, 0xc3, 0x73, 0xbc, 0x57, 0x6b, 0x70, - 0x61, 0x09, 0xd9, 0xb7, 0x0a, 0x92, 0x73, 0xa2, 0xd1, 0xa9, 0x85, 0x21, 0x5d, 0x7f, 0x89, 0x77, - 0xea, 0x54, 0x14, 0xc4, 0xcf, 0x37, 0xe9, 0x6b, 0x14, 0x06, 0x23, 0xe2, 0x2b, 0xc5, 0x20, 0xc5, - 0x71, 0x93, 0x77, 0x61, 0x1d, 0x91, 0x23, 0xdb, 0x72, 0x4c, 0x41, 0xc2, 0x6f, 0x6f, 0xac, 0x0d, - 0x3d, 0x67, 0x07, 0xa1, 0x44, 0xa7, 0xfe, 0xd5, 0x2c, 0xc0, 0xcc, 0x46, 0x4b, 0x1c, 0x4f, 0xa7, - 0x92, 0xc7, 0xd3, 0x8f, 0xe0, 0x92, 0xb8, 0xdb, 0x13, 0x9f, 0xf1, 0xda, 0xae, 0x3e, 0x30, 0xa2, - 0x48, 0x00, 0x26, 0xb0, 0xfc, 0x98, 0xb7, 0xe5, 0x6e, 0x1b, 0xa8, 0xf1, 0xad, 0xcb, 0x3c, 0xe1, - 0xd9, 0x24, 0x19, 0xc9, 0x20, 0xeb, 0x11, 0x33, 0xf6, 0xfe, 0xd9, 0x84, 0xbd, 0x0f, 0x17, 0x7d, - 0x6b, 0xe4, 0x5b, 0xc1, 0x91, 0x1e, 0x06, 0x72, 0x61, 0x3c, 0xe0, 0x6e, 0x43, 0x20, 0xfb, 0x41, - 0x5c, 0xd6, 0xfb, 0x70, 0x51, 0x58, 0x6f, 0x73, 0xd5, 0xe3, 0x97, 0xc0, 0x37, 0x38, 0x52, 0xae, - 0xdd, 0x1b, 0x00, 0xc2, 0x70, 0x8d, 0x1e, 0x05, 0x29, 0x68, 0x45, 0x6e, 0xa4, 0x8a, 0xab, 0xb2, - 0x64, 0x7d, 0x8a, 0xb3, 0x3b, 0x9e, 0x60, 0x2a, 0x64, 0x50, 0x9c, 0xd2, 0x39, 0x53, 0xe5, 0x51, - 0xe5, 0x01, 0x3d, 0x7a, 0x42, 0x57, 0x97, 0x3d, 0xd3, 0xd2, 0x08, 0xc7, 0xde, 0x83, 0x0b, 0x72, - 0xb3, 0xa3, 0x7b, 0xfb, 0x25, 0xaa, 0x88, 0x32, 0x6b, 0xa8, 0xc6, 0x6f, 0xf0, 0xbf, 0x03, 0x4c, - 0xaa, 0x79, 0x44, 0x5d, 0x26, 0xea, 0xf5, 0xb8, 0xda, 0x82, 0xf8, 0x2d, 0xa0, 0x2a, 0x72, 0xb7, - 0xfe, 0xda, 0xa2, 0xa9, 0x86, 0x48, 0xf2, 0xef, 0xbf, 0x0f, 0x17, 0x67, 0xad, 0xd3, 0x8d, 0x50, - 0x0f, 0x8f, 0x2c, 0xdd, 0x72, 0x4d, 0xba, 0x90, 0x55, 0xd0, 0x36, 0xe2, 0x86, 0xd6, 0xc2, 0xfe, - 0x91, 0x85, 0xc6, 0x96, 0xe4, 0xa2, 0x5b, 0x7f, 0xb5, 0x8b, 0xee, 0x63, 0xa8, 0x26, 0xce, 0xac, - 0xe5, 0xee, 0xe6, 0x17, 0x1a, 0x37, 0xe5, 0x93, 0xea, 0xb8, 0xc7, 0xef, 0xc3, 0xc6, 0x91, 0x11, - 0xe8, 0x09, 0x5e, 0xf2, 0x1c, 0x16, 0xb4, 0xf5, 0x23, 0x23, 0xd8, 0x97, 0x78, 0xd4, 0xdf, 0x4f, - 0x41, 0x25, 0x69, 0xb5, 0xf2, 0x0b, 0x2d, 0xce, 0x74, 0xec, 0xf2, 0xf0, 0x94, 0xac, 0x16, 0x25, - 0x71, 0x2d, 0x4c, 0x8e, 0x75, 0x9e, 0x8a, 0xd6, 0xc2, 0xe4, 0xb8, 0x4e, 0x69, 0xf6, 0x36, 0xe4, - 0x27, 0xc7, 0x5c, 0x38, 0x9c, 0x37, 0xfb, 0x72, 0x13, 0x1e, 0x17, 0xfc, 0x36, 0xe4, 0xa7, 0x82, - 0x34, 0x73, 0x1e, 0xe9, 0x94, 0x48, 0xd5, 0x7f, 0xbe, 0x0a, 0x65, 0xd9, 0x5f, 0xf3, 0x4d, 0x8e, - 0xb2, 0xbf, 0x55, 0x08, 0xc2, 0x16, 0x85, 0x09, 0xea, 0x14, 0x84, 0x8c, 0xfd, 0xc4, 0xcf, 0xb1, - 0xe1, 0xc8, 0x08, 0x6a, 0xd3, 0xd0, 0xab, 0x7b, 0xfc, 0xf8, 0xcc, 0x73, 0xa2, 0xe0, 0x64, 0xbe, - 0x32, 0x50, 0x26, 0x88, 0xb8, 0xe4, 0xf7, 0xc5, 0xdd, 0x07, 0xba, 0xed, 0x44, 0xe1, 0x2f, 0xd9, - 0x85, 0xf9, 0x52, 0x8e, 0x2e, 0x3b, 0x51, 0x64, 0xcb, 0x23, 0x58, 0x9f, 0x45, 0x9a, 0x47, 0x11, - 0x33, 0xf3, 0x2c, 0x6b, 0x71, 0x98, 0xb9, 0xb8, 0xde, 0xbc, 0x66, 0x07, 0xba, 0xe7, 0x98, 0xd1, - 0x95, 0x96, 0x7c, 0xe4, 0x6d, 0xef, 0x3a, 0xa6, 0xb8, 0xf0, 0xc6, 0x69, 0x5c, 0xeb, 0x24, 0xa2, - 0x89, 0x3d, 0xf2, 0x1d, 0xeb, 0x44, 0x5c, 0x6d, 0xf9, 0xc3, 0x14, 0x6c, 0x2c, 0xf8, 0x57, 0x50, - 0x72, 0xce, 0x1e, 0xdb, 0xc1, 0x4f, 0x76, 0x0b, 0xca, 0x63, 0x23, 0x1c, 0x1e, 0xe9, 0x13, 0xdf, - 0x1a, 0xd9, 0xa7, 0xd1, 0x8b, 0x41, 0x04, 0xdb, 0x27, 0x10, 0x45, 0x11, 0x4d, 0x26, 0xe4, 0x55, - 0x1a, 0xdb, 0xa1, 0x10, 0x7c, 0x40, 0x20, 0xee, 0x86, 0x8b, 0x22, 0x0c, 0x33, 0xe7, 0x44, 0x18, - 0x5e, 0x85, 0xa2, 0xeb, 0x85, 0xba, 0xe7, 0xea, 0x93, 0x63, 0x71, 0x1f, 0x3e, 0xef, 0x7a, 0x61, - 0xd7, 0xdd, 0x3f, 0x56, 0xaf, 0x43, 0xae, 0x15, 0xfb, 0x78, 0xe2, 0x10, 0x99, 0xb4, 0x78, 0x32, - 0xc3, 0x83, 0x62, 0x9d, 0x9e, 0xdf, 0xd8, 0x33, 0x26, 0xec, 0x3e, 0xa4, 0xc7, 0xc6, 0x44, 0x84, - 0xd0, 0x54, 0xe3, 0xe3, 0x1c, 0x8e, 0x7d, 0xb0, 0x67, 0x4c, 0xf8, 0x26, 0x82, 0x44, 0x57, 0x3f, - 0x86, 0x42, 0x04, 0xf8, 0x56, 0xdb, 0xc5, 0xbf, 0x5a, 0x85, 0x62, 0x43, 0xf6, 0x1c, 0xa3, 0xb9, - 0x1b, 0xfa, 0x53, 0x17, 0x75, 0xaf, 0xe8, 0x21, 0x81, 0xa1, 0xe1, 0xf6, 0x05, 0x28, 0x9a, 0xa6, - 0xab, 0xaf, 0x98, 0xa6, 0xd7, 0x01, 0x7c, 0x72, 0x71, 0x90, 0x97, 0x23, 0x1d, 0x87, 0x6b, 0xb6, - 0xcc, 0x96, 0x79, 0xba, 0x3c, 0x1e, 0x23, 0xf3, 0xcd, 0xe3, 0x31, 0xb2, 0x4b, 0xe3, 0x31, 0xee, - 0xce, 0xb6, 0x0a, 0x9c, 0xae, 0x58, 0x70, 0x91, 0x6f, 0x58, 0x93, 0xf8, 0xd6, 0x06, 0x96, 0xfe, - 0x3d, 0xa8, 0x44, 0xad, 0x13, 0xf9, 0x41, 0xe2, 0xa2, 0x88, 0xc0, 0x71, 0x57, 0xf3, 0x5a, 0x28, - 0x27, 0x93, 0xcb, 0xaf, 0xf4, 0x9a, 0x40, 0x95, 0xbf, 0x91, 0x02, 0x26, 0x4c, 0xf2, 0x9d, 0xa9, - 0xe3, 0xf4, 0xad, 0x53, 0x5a, 0xe5, 0xf7, 0x61, 0x43, 0x78, 0xc2, 0xa5, 0x30, 0x2f, 0x71, 0xb6, - 0xc7, 0x11, 0xb3, 0xb3, 0xbd, 0x65, 0x77, 0xf9, 0x56, 0x97, 0xde, 0xe5, 0x5b, 0x7e, 0x47, 0xf0, - 0x26, 0x94, 0xe4, 0x9b, 0x70, 0x5c, 0xb5, 0x02, 0x63, 0x76, 0x09, 0xee, 0xdf, 0xac, 0x02, 0xcc, - 0xdc, 0x06, 0xbf, 0xec, 0x60, 0x9a, 0x25, 0x43, 0x92, 0x5e, 0x36, 0x24, 0xf7, 0x40, 0x91, 0xe9, - 0xa4, 0x2b, 0x99, 0x95, 0x19, 0x61, 0xa4, 0xb2, 0xd8, 0x81, 0x7c, 0x6d, 0x8e, 0x22, 0xe7, 0x44, - 0xc0, 0x80, 0x08, 0xab, 0x23, 0x79, 0x2a, 0x76, 0xe3, 0x82, 0x1d, 0x70, 0xf9, 0xca, 0x3e, 0x85, - 0x2b, 0x31, 0xa7, 0x7e, 0x62, 0x87, 0x47, 0xde, 0x34, 0x14, 0x2e, 0x86, 0x40, 0x48, 0x9c, 0x4b, - 0x51, 0x4e, 0x2f, 0x38, 0x9a, 0x4b, 0x91, 0x00, 0x95, 0xee, 0xd1, 0xd4, 0x71, 0xf4, 0xd0, 0x3a, - 0x0d, 0xc5, 0xdb, 0x04, 0xd5, 0x84, 0xc7, 0x45, 0x1a, 0x5e, 0xad, 0x30, 0x12, 0x09, 0xf5, 0x1f, - 0xa4, 0x21, 0xfb, 0xe3, 0xa9, 0xe5, 0x9f, 0xb1, 0x8f, 0xa1, 0x18, 0x84, 0xe3, 0x50, 0x3e, 0x5f, - 0xbd, 0xc2, 0x33, 0x20, 0x3c, 0x1d, 0x8f, 0x5a, 0x63, 0xcb, 0x0d, 0xb9, 0x2b, 0x12, 0x69, 0x69, - 0x33, 0xd9, 0x84, 0x6c, 0x10, 0x5a, 0x93, 0x40, 0x84, 0xc1, 0xf1, 0x04, 0xdb, 0x82, 0xac, 0xeb, - 0x99, 0x56, 0x90, 0x0c, 0x76, 0xeb, 0xa0, 0xf6, 0xc0, 0x11, 0x4c, 0x85, 0x5c, 0x3c, 0xe2, 0x0b, - 0x67, 0x9c, 0x1c, 0x43, 0xd7, 0x17, 0x2c, 0xc3, 0xb4, 0xdd, 0xc3, 0xe8, 0x8a, 0x6b, 0x9c, 0xc6, - 0x6d, 0x92, 0x94, 0x75, 0xe3, 0x30, 0xba, 0x6f, 0x2e, 0x92, 0x6c, 0x0b, 0x4a, 0xf8, 0xf9, 0xc2, - 0xb7, 0x43, 0xab, 0xf7, 0x38, 0x92, 0xd4, 0x12, 0x08, 0x55, 0x6d, 0xd3, 0x0a, 0xad, 0x61, 0xd8, - 0xfb, 0x4a, 0x44, 0xb0, 0x51, 0xa0, 0x53, 0x04, 0x61, 0xdf, 0x03, 0x36, 0x30, 0x86, 0xc7, 0x87, - 0xbe, 0x37, 0x75, 0x4d, 0xfd, 0xab, 0xa9, 0xe5, 0xdb, 0x56, 0x14, 0xb1, 0x56, 0x92, 0x3a, 0x45, - 0xdb, 0x98, 0x91, 0xfd, 0x98, 0x53, 0xa9, 0x26, 0xac, 0x25, 0xba, 0x6a, 0xc1, 0xbb, 0xd3, 0x6b, - 0xb6, 0x9b, 0xf5, 0x3e, 0x37, 0x0b, 0x85, 0x4b, 0x61, 0x55, 0x76, 0x49, 0xa4, 0x25, 0x5f, 0x45, - 0x46, 0xb2, 0x1d, 0xb3, 0xe4, 0xe9, 0x68, 0x6a, 0x4f, 0x9b, 0x4a, 0x4e, 0xfd, 0x83, 0x55, 0xd8, - 0xe8, 0xfb, 0x86, 0x1b, 0x18, 0x5c, 0x93, 0x70, 0x43, 0xdf, 0x73, 0xd8, 0xf7, 0xa0, 0x10, 0x0e, - 0x1d, 0x79, 0x08, 0x6f, 0x46, 0x02, 0x63, 0x8e, 0xf4, 0x41, 0x7f, 0xc8, 0x7d, 0xca, 0xf9, 0x90, - 0x7f, 0xb0, 0xf7, 0x20, 0x3b, 0xb0, 0x0e, 0x6d, 0x57, 0xc8, 0xcc, 0x8b, 0xf3, 0x8c, 0xdb, 0x88, - 0xdc, 0x5d, 0xd1, 0x38, 0x15, 0x7b, 0x1f, 0x72, 0x43, 0x6f, 0x1c, 0x6d, 0x3c, 0xb3, 0xab, 0x52, - 0x52, 0x41, 0x88, 0xdd, 0x5d, 0xd1, 0x04, 0x1d, 0xfb, 0x18, 0x0a, 0xbe, 0xe7, 0x38, 0xd8, 0x63, - 0x62, 0x4b, 0xaa, 0xce, 0xf3, 0x68, 0x02, 0xbf, 0xbb, 0xa2, 0xc5, 0xb4, 0xea, 0x03, 0xc8, 0x8b, - 0xca, 0x62, 0x07, 0x6c, 0x37, 0x9f, 0xb6, 0x44, 0x47, 0xd6, 0xbb, 0x7b, 0x7b, 0xad, 0x3e, 0xbf, - 0x07, 0xaa, 0x75, 0xdb, 0xed, 0xed, 0x5a, 0xfd, 0x99, 0xb2, 0xba, 0x5d, 0x80, 0x1c, 0xf7, 0x1e, - 0xaa, 0xbf, 0x99, 0x82, 0xf5, 0xb9, 0x06, 0xb0, 0x27, 0x90, 0x19, 0xa3, 0x66, 0xcb, 0xbb, 0xe7, - 0xce, 0xd2, 0x56, 0x4a, 0x69, 0xae, 0xef, 0x22, 0x87, 0xfa, 0x29, 0x54, 0x92, 0x70, 0xc9, 0x83, - 0xb0, 0x06, 0x45, 0xad, 0x59, 0x6b, 0xe8, 0xdd, 0x0e, 0xda, 0xed, 0x68, 0xc7, 0x53, 0xf2, 0x85, - 0xd6, 0x22, 0xa3, 0xff, 0xd7, 0x40, 0x99, 0xef, 0x18, 0xf6, 0x14, 0x6d, 0x97, 0xf1, 0xc4, 0xb1, - 0x48, 0x45, 0x94, 0x86, 0xec, 0xc6, 0x92, 0x9e, 0x14, 0x64, 0x34, 0x62, 0x95, 0x61, 0x22, 0xad, - 0xfe, 0x3a, 0xb0, 0xc5, 0x1e, 0xfc, 0xe5, 0x65, 0xff, 0x3f, 0x52, 0x90, 0xd9, 0x77, 0x0c, 0x97, - 0xdd, 0x86, 0x2c, 0xbd, 0x5f, 0x22, 0x24, 0xaf, 0xbc, 0x0e, 0x70, 0x5a, 0x10, 0x8e, 0xbd, 0x03, - 0xe9, 0x70, 0x18, 0x5d, 0x3f, 0xbd, 0x7c, 0xce, 0xe4, 0xdb, 0x5d, 0xd1, 0x90, 0x8a, 0xdd, 0x83, - 0xb4, 0x69, 0x46, 0x61, 0xdf, 0xc2, 0xa7, 0x80, 0x16, 0x65, 0xc3, 0x1a, 0xd9, 0xae, 0x2d, 0xde, - 0x5b, 0x41, 0x12, 0xf6, 0x26, 0xa4, 0xcd, 0xa1, 0x93, 0x8c, 0xe1, 0xe7, 0xb6, 0x67, 0x9c, 0xa1, - 0x39, 0x74, 0x50, 0x03, 0x0b, 0xfd, 0x33, 0xdd, 0x9f, 0xba, 0x14, 0xc7, 0x16, 0x08, 0xab, 0xa8, - 0x84, 0xfa, 0xc7, 0x94, 0x82, 0xe1, 0x02, 0x71, 0x8f, 0x6d, 0xe2, 0x5b, 0x13, 0xc3, 0x8f, 0xed, - 0x21, 0x3b, 0xd8, 0xe7, 0x80, 0xed, 0x1c, 0xd0, 0xb3, 0x90, 0xea, 0xbb, 0xf4, 0xb8, 0x06, 0x2a, - 0xd6, 0x6a, 0xf4, 0xb5, 0xe4, 0x05, 0x31, 0x81, 0x51, 0xff, 0x3c, 0x0d, 0x25, 0xa9, 0x3e, 0xec, - 0x43, 0x28, 0x98, 0xc9, 0x85, 0x78, 0x65, 0xa1, 0xd2, 0x0f, 0x1a, 0xd1, 0x12, 0x34, 0xc5, 0xf4, - 0xa6, 0x03, 0x8b, 0x50, 0x7f, 0x69, 0xf8, 0x36, 0x7f, 0x52, 0x69, 0x55, 0x3e, 0x39, 0xe8, 0x59, - 0xe1, 0xf3, 0x08, 0xb3, 0xbb, 0xa2, 0x95, 0x03, 0x29, 0x4d, 0xda, 0xbf, 0x68, 0x52, 0x3a, 0xf1, - 0x34, 0x15, 0x07, 0xee, 0xae, 0x68, 0x11, 0x1e, 0x49, 0xad, 0x53, 0x6b, 0x38, 0x0d, 0x23, 0xed, - 0x7f, 0x2d, 0x6a, 0x10, 0x01, 0xe9, 0x7d, 0x3c, 0xfe, 0xc9, 0x1e, 0xa1, 0x9c, 0x34, 0x1c, 0xc7, - 0x23, 0x35, 0x2b, 0x2b, 0xfb, 0xf1, 0x1b, 0x31, 0x9c, 0xbf, 0xc7, 0x17, 0xa5, 0xd8, 0x5d, 0xc8, - 0x7a, 0xe1, 0x91, 0x15, 0xe9, 0xd4, 0xd1, 0x33, 0x1d, 0x08, 0x6a, 0xd4, 0xdb, 0x38, 0x53, 0x08, - 0xad, 0xfe, 0x2c, 0x05, 0x79, 0xd1, 0x03, 0x6c, 0x03, 0xd6, 0x7a, 0xcd, 0xbe, 0xfe, 0xbc, 0xa6, - 0xb5, 0x6a, 0xdb, 0xed, 0xa6, 0xb8, 0x7a, 0xf0, 0x54, 0xab, 0x75, 0x84, 0x9c, 0xd4, 0x9a, 0xcf, - 0xbb, 0xcf, 0x9a, 0xdc, 0x2d, 0xd7, 0x68, 0x76, 0xbe, 0x50, 0xd2, 0xdc, 0x35, 0xdd, 0xdc, 0xaf, - 0x69, 0x28, 0x25, 0x4b, 0x90, 0x6f, 0x7e, 0xde, 0xac, 0x1f, 0x90, 0x98, 0xac, 0x00, 0x34, 0x9a, - 0xb5, 0x76, 0xbb, 0x5b, 0x47, 0xb1, 0x99, 0x63, 0x0c, 0x2a, 0x75, 0xad, 0x59, 0xeb, 0x37, 0xf5, - 0x5a, 0xbd, 0xde, 0x3d, 0xe8, 0xf4, 0x95, 0x3c, 0x96, 0x58, 0x6b, 0xf7, 0x9b, 0x5a, 0x0c, 0xa2, - 0xa7, 0x93, 0x1a, 0x5a, 0x77, 0x3f, 0x86, 0x14, 0xb7, 0x8b, 0x68, 0x89, 0xd1, 0x58, 0xa9, 0xff, - 0x68, 0x03, 0x2a, 0xc9, 0xa9, 0xc9, 0x3e, 0x81, 0x82, 0x69, 0x26, 0xc6, 0xf8, 0xfa, 0xb2, 0x29, - 0xfc, 0xa0, 0x61, 0x46, 0xc3, 0xcc, 0x3f, 0xd8, 0xad, 0x68, 0x21, 0xad, 0x2e, 0x2c, 0xa4, 0x68, - 0x19, 0xfd, 0x10, 0xd6, 0xc5, 0x33, 0x17, 0xa6, 0x11, 0x1a, 0x03, 0x23, 0xb0, 0x92, 0xab, 0xa4, - 0x4e, 0xc8, 0x86, 0xc0, 0xed, 0xae, 0x68, 0x95, 0x61, 0x02, 0xc2, 0xbe, 0x0f, 0x15, 0x83, 0x8c, - 0xed, 0x98, 0x3f, 0x23, 0x2b, 0x90, 0x35, 0xc4, 0x49, 0xec, 0x6b, 0x86, 0x0c, 0xc0, 0x89, 0x68, - 0xfa, 0xde, 0x64, 0xc6, 0x9c, 0x4d, 0x1c, 0x61, 0xf9, 0xde, 0x44, 0xe2, 0x2d, 0x9b, 0x52, 0x9a, - 0x7d, 0x0c, 0x65, 0x51, 0xf3, 0x99, 0xc3, 0x21, 0x5e, 0xb2, 0xbc, 0xda, 0xa4, 0x10, 0xee, 0xae, - 0x68, 0xa5, 0xe1, 0x2c, 0xc9, 0x1e, 0xa3, 0x16, 0x38, 0x53, 0x9f, 0xf3, 0xf2, 0x5c, 0xa3, 0xda, - 0x46, 0x5c, 0x60, 0xc4, 0x29, 0xf6, 0x3e, 0x00, 0xd5, 0x93, 0xf3, 0x14, 0x12, 0x21, 0x27, 0xbe, - 0x37, 0x89, 0x58, 0x8a, 0x66, 0x94, 0x90, 0xaa, 0xc7, 0xdd, 0x45, 0xc5, 0xc5, 0xea, 0x91, 0xcb, - 0x68, 0x56, 0x3d, 0xee, 0x69, 0x8a, 0xab, 0xc7, 0xd9, 0x60, 0xa1, 0x7a, 0x11, 0x17, 0xaf, 0x1e, - 0x67, 0x8a, 0xaa, 0xc7, 0x79, 0x4a, 0xf3, 0xd5, 0x8b, 0x58, 0xa8, 0x7a, 0x9c, 0xe3, 0xfb, 0x0b, - 0x7a, 0x7f, 0xf9, 0x5c, 0xbd, 0x1f, 0x87, 0x2d, 0xa9, 0xf9, 0x7f, 0x1f, 0x2a, 0xc1, 0x91, 0x77, - 0x22, 0x09, 0x90, 0x35, 0x99, 0xbb, 0x77, 0xe4, 0x9d, 0xc8, 0x12, 0x64, 0x2d, 0x90, 0x01, 0x58, - 0x5b, 0xde, 0x44, 0xba, 0x5f, 0x5f, 0x91, 0x6b, 0x4b, 0x2d, 0x7c, 0x6e, 0x5b, 0x27, 0x58, 0x5b, - 0x23, 0x4a, 0x60, 0xa7, 0xcc, 0x9c, 0x2f, 0x81, 0x70, 0xa7, 0x24, 0x42, 0x22, 0x44, 0x49, 0x10, - 0xbb, 0x61, 0x02, 0x9c, 0x5b, 0x53, 0x57, 0x66, 0x53, 0xe4, 0xb9, 0x75, 0xe0, 0x26, 0x18, 0xcb, - 0x9c, 0x54, 0xb0, 0xce, 0x56, 0x45, 0x60, 0x7d, 0x35, 0xb5, 0xdc, 0xa1, 0x25, 0x02, 0xb2, 0x12, - 0xab, 0xa2, 0x27, 0x70, 0xb3, 0x55, 0x11, 0x41, 0xe2, 0x79, 0x1d, 0xb3, 0xb3, 0xf9, 0x79, 0x2d, - 0x31, 0xd3, 0xbc, 0x8e, 0x59, 0xe3, 0x05, 0x15, 0xf3, 0x5e, 0x58, 0x58, 0x50, 0x12, 0x33, 0x5f, - 0x50, 0x31, 0xf7, 0x63, 0x10, 0xb3, 0x89, 0x77, 0x6e, 0x22, 0x6c, 0x8b, 0xd7, 0x5a, 0xf4, 0x2e, - 0x0c, 0xe3, 0x14, 0xce, 0x55, 0xdf, 0x42, 0x3b, 0x43, 0x4c, 0x85, 0x8b, 0xf2, 0x5c, 0xd5, 0x08, - 0x13, 0x2f, 0x25, 0x7f, 0x96, 0x94, 0x0a, 0x9b, 0xd8, 0xa1, 0x5f, 0x35, 0x17, 0x0b, 0xdb, 0xb7, - 0x43, 0x7f, 0x56, 0x18, 0xa6, 0xd8, 0x7b, 0x40, 0xd3, 0x90, 0xb3, 0x58, 0xb2, 0xe8, 0xc6, 0x6e, - 0x11, 0x0c, 0x05, 0x53, 0x7c, 0xe3, 0x64, 0x11, 0x65, 0x0c, 0xcd, 0x61, 0x75, 0x24, 0x4f, 0x16, - 0x5e, 0x44, 0xbd, 0x51, 0xc7, 0xc9, 0xc2, 0x89, 0xea, 0xe6, 0x90, 0xdd, 0x07, 0xe2, 0x26, 0xfa, - 0xc3, 0xc4, 0x33, 0x50, 0xbe, 0x37, 0xe1, 0xd4, 0x79, 0x24, 0x40, 0x5a, 0x6c, 0x81, 0xe3, 0xb9, - 0x51, 0xc3, 0x8f, 0x12, 0x2d, 0x40, 0x44, 0x2c, 0x0c, 0x86, 0x71, 0x4a, 0xfd, 0xed, 0x1c, 0xe4, - 0x85, 0xac, 0x65, 0x17, 0x60, 0x5d, 0x88, 0xfc, 0x46, 0xad, 0x5f, 0xdb, 0xae, 0xf5, 0x50, 0x49, - 0x63, 0x50, 0xe1, 0x32, 0x3f, 0x86, 0xa5, 0x70, 0x1f, 0x20, 0xa1, 0x1f, 0x83, 0x56, 0x71, 0x1f, - 0x10, 0xbc, 0xfc, 0xb9, 0xbd, 0x34, 0x5b, 0x87, 0x12, 0x67, 0xe4, 0x00, 0xba, 0x09, 0x49, 0x5c, - 0x3c, 0x9d, 0x95, 0x58, 0xf8, 0x29, 0x55, 0x6e, 0xc6, 0xc2, 0x01, 0xf9, 0x98, 0x25, 0x3a, 0xc6, - 0x62, 0x50, 0xe9, 0x6b, 0x07, 0x9d, 0xfa, 0xac, 0x9c, 0x22, 0xdd, 0x5e, 0xe3, 0xd9, 0x3c, 0x6f, - 0x35, 0x5f, 0x28, 0x80, 0x4c, 0x3c, 0x17, 0x4a, 0x97, 0x50, 0xcd, 0xa4, 0x4c, 0x28, 0x59, 0x66, - 0x97, 0xe1, 0x42, 0x6f, 0xb7, 0xfb, 0x42, 0xe7, 0x4c, 0x71, 0x13, 0xd6, 0xd8, 0x26, 0x28, 0x12, - 0x82, 0x67, 0x5f, 0xc1, 0x22, 0x09, 0x1a, 0x11, 0xf6, 0x94, 0x75, 0x3a, 0x08, 0x46, 0x58, 0x9f, - 0xef, 0xbb, 0x0a, 0x36, 0x85, 0xb3, 0x76, 0xdb, 0x07, 0x7b, 0x9d, 0x9e, 0xb2, 0x81, 0x95, 0x20, - 0x08, 0xaf, 0x39, 0x8b, 0xb3, 0x99, 0xed, 0xd6, 0x17, 0x68, 0x03, 0x47, 0xd8, 0x8b, 0x9a, 0xd6, - 0x69, 0x75, 0x9e, 0xf6, 0x94, 0xcd, 0x38, 0xe7, 0xa6, 0xa6, 0x75, 0xb5, 0x9e, 0x72, 0x31, 0x06, - 0xf4, 0xfa, 0xb5, 0xfe, 0x41, 0x4f, 0xb9, 0x14, 0xd7, 0x72, 0x5f, 0xeb, 0xd6, 0x9b, 0xbd, 0x5e, - 0xbb, 0xd5, 0xeb, 0x2b, 0x97, 0xd9, 0x45, 0xd8, 0x98, 0xd5, 0x28, 0x22, 0xae, 0x4a, 0x15, 0xd5, - 0x9e, 0x36, 0xfb, 0xca, 0x95, 0xb8, 0x1a, 0xf5, 0x6e, 0xbb, 0x5d, 0xa3, 0x23, 0xcc, 0xab, 0x48, - 0x44, 0x67, 0xb9, 0xa2, 0x35, 0xd7, 0xb0, 0x5e, 0x07, 0x1d, 0x19, 0x74, 0x5d, 0x9a, 0x1a, 0xbd, - 0xe6, 0x8f, 0x0f, 0x9a, 0x9d, 0x7a, 0x53, 0x79, 0x63, 0x36, 0x35, 0x62, 0xd8, 0x8d, 0x78, 0x6a, - 0xc4, 0xa0, 0x9b, 0x71, 0x99, 0x11, 0xa8, 0xa7, 0x6c, 0x61, 0x7e, 0xa2, 0x1e, 0x9d, 0x4e, 0xb3, - 0xde, 0xc7, 0xb6, 0xde, 0x8a, 0x7b, 0xf1, 0x60, 0xff, 0xa9, 0x56, 0x6b, 0x34, 0x15, 0x15, 0x21, - 0x5a, 0xb3, 0x53, 0xdb, 0x8b, 0x46, 0xfb, 0xb6, 0x34, 0xda, 0xfb, 0xad, 0xbe, 0xa6, 0xdc, 0x89, - 0x47, 0x97, 0x92, 0x6f, 0xb2, 0x6b, 0x70, 0x59, 0x9e, 0x87, 0xfa, 0x8b, 0x56, 0x7f, 0x57, 0x9c, - 0xb8, 0xde, 0xe5, 0x27, 0x87, 0x84, 0xac, 0x37, 0xea, 0xfc, 0x68, 0x99, 0x78, 0x31, 0x75, 0x6f, - 0xbb, 0x4c, 0xaf, 0x26, 0x0b, 0x05, 0x44, 0xfd, 0x0c, 0x98, 0xfc, 0x80, 0xa8, 0x78, 0x49, 0x8b, - 0x41, 0x66, 0xe4, 0x7b, 0xe3, 0xe8, 0x55, 0x02, 0xfc, 0x46, 0xcb, 0x79, 0x32, 0x1d, 0xd0, 0x89, - 0xe6, 0xec, 0xd6, 0xb1, 0x0c, 0x52, 0xff, 0x4e, 0x0a, 0x2a, 0x49, 0xe5, 0x83, 0xdc, 0x9e, 0x23, - 0xdd, 0xf5, 0x42, 0xfe, 0x44, 0x53, 0x10, 0xbf, 0xeb, 0x39, 0xea, 0x78, 0x21, 0xbd, 0xd1, 0x44, - 0x86, 0x7c, 0xac, 0x4b, 0xf0, 0x5c, 0xe3, 0x34, 0x6b, 0xc1, 0x85, 0xc4, 0x1b, 0xac, 0x89, 0x07, - 0xb2, 0xaa, 0xf1, 0xdb, 0x89, 0x73, 0xf5, 0xd7, 0x58, 0xb0, 0xd8, 0x26, 0x71, 0x77, 0x3c, 0x33, - 0xbb, 0x3b, 0xbe, 0x0b, 0x6b, 0x09, 0x5d, 0x87, 0xfc, 0x2f, 0xa3, 0x64, 0x4d, 0x0b, 0xf6, 0xe8, - 0xf5, 0xd5, 0x54, 0xff, 0x76, 0x0a, 0xca, 0xb2, 0xe6, 0xf3, 0x9d, 0x73, 0xa2, 0x7b, 0x56, 0xe2, - 0x5b, 0xb7, 0xcd, 0xe8, 0x69, 0xa6, 0x08, 0xd4, 0xa2, 0xd7, 0xe2, 0xb9, 0x07, 0x79, 0xe7, 0xb8, - 0x17, 0x37, 0x47, 0x06, 0xb1, 0x1b, 0x00, 0x74, 0xeb, 0x74, 0xe7, 0x19, 0x12, 0x88, 0x9b, 0x5a, - 0x33, 0x88, 0x7a, 0x13, 0x8a, 0x3b, 0xc7, 0x51, 0x9c, 0x8b, 0xfc, 0x50, 0x59, 0x91, 0x5f, 0x55, - 0x57, 0xff, 0x24, 0x05, 0x95, 0xd9, 0xa3, 0x2e, 0x74, 0xae, 0xcc, 0xdf, 0xee, 0xe5, 0xd3, 0x61, - 0xd5, 0x1c, 0xcc, 0x1e, 0x92, 0x5f, 0x95, 0x1f, 0x92, 0xbf, 0x2d, 0x32, 0x4b, 0xcb, 0x22, 0x3f, - 0x2e, 0x4b, 0x5c, 0x84, 0x7f, 0x0c, 0x65, 0xfc, 0xaf, 0x59, 0x23, 0xcb, 0xf7, 0xad, 0xe8, 0x19, - 0xe3, 0x05, 0xe2, 0x04, 0x11, 0xd9, 0x78, 0xd6, 0x48, 0xa8, 0x9a, 0x4b, 0xdf, 0x9d, 0xa1, 0xf7, - 0x90, 0xfe, 0x6b, 0x1a, 0x4a, 0x92, 0x1e, 0xf9, 0x8d, 0xa6, 0xdf, 0x75, 0x28, 0xce, 0x5e, 0x41, - 0x11, 0xb7, 0x8f, 0x63, 0x40, 0x62, 0xac, 0xd2, 0x73, 0x63, 0x55, 0x85, 0xbc, 0x08, 0x9f, 0x15, - 0xce, 0xdf, 0x28, 0x99, 0x74, 0xb3, 0x66, 0x5f, 0x73, 0xca, 0xf1, 0x01, 0x94, 0x25, 0x1f, 0x69, - 0x20, 0x6e, 0xe8, 0xce, 0xd3, 0x97, 0x66, 0xfe, 0xd2, 0x80, 0x5d, 0x84, 0xdc, 0xe8, 0x58, 0x37, - 0x07, 0xfc, 0x5a, 0x66, 0x51, 0xcb, 0x8e, 0x8e, 0x1b, 0x03, 0x3a, 0x03, 0x1a, 0xc5, 0xaa, 0x13, - 0xf7, 0x5c, 0x15, 0x46, 0x91, 0x82, 0x74, 0x0f, 0xf2, 0xa3, 0x63, 0xf9, 0x7a, 0xe5, 0x42, 0x97, - 0xe7, 0x46, 0xc7, 0x74, 0x1f, 0xf3, 0x21, 0x6c, 0x8a, 0xfd, 0xdb, 0x08, 0x74, 0xfe, 0xd0, 0x03, - 0xbd, 0x8e, 0xc3, 0x9f, 0x2d, 0xdb, 0xe0, 0xb8, 0x5a, 0xd0, 0x23, 0x0c, 0xce, 0x38, 0x15, 0xca, - 0xd2, 0x04, 0xe4, 0xcf, 0x08, 0x15, 0xb5, 0x04, 0x8c, 0x3d, 0x81, 0xf2, 0xe8, 0x98, 0x0f, 0x68, - 0xdf, 0xdb, 0xb3, 0x44, 0x34, 0xff, 0xe6, 0xfc, 0x50, 0xd2, 0xc1, 0x7f, 0x82, 0x92, 0x5d, 0x82, - 0x9c, 0x66, 0x9c, 0xf4, 0x7e, 0xdc, 0x26, 0x25, 0xb2, 0xa8, 0x89, 0xd4, 0x67, 0x99, 0x42, 0x45, - 0x59, 0x57, 0xff, 0x71, 0x0a, 0x2a, 0x33, 0x1b, 0x00, 0x17, 0x21, 0xbb, 0x2f, 0x3f, 0xba, 0x5d, - 0x9d, 0x37, 0x13, 0x90, 0xe4, 0x41, 0xff, 0x6c, 0xc2, 0x9f, 0xa6, 0x5c, 0xf6, 0xf4, 0xd3, 0x32, - 0xa7, 0x75, 0x7a, 0xe9, 0x73, 0xbf, 0x4f, 0x21, 0xdd, 0x3f, 0x9b, 0x70, 0x7f, 0x13, 0x6e, 0x89, - 0xdc, 0x36, 0xe5, 0x9b, 0x21, 0x45, 0x96, 0x3c, 0x6b, 0x7e, 0xc1, 0x5f, 0x4b, 0xd8, 0xd7, 0x5a, - 0x7b, 0x35, 0xed, 0x0b, 0x0a, 0x1a, 0x22, 0xa5, 0x61, 0xa7, 0xab, 0x35, 0x5b, 0x4f, 0x3b, 0x04, - 0xc8, 0x90, 0x37, 0x6a, 0x56, 0xc5, 0x9a, 0x69, 0xee, 0x1c, 0xcb, 0xaf, 0xe6, 0xa4, 0x12, 0xaf, - 0xe6, 0x24, 0x2f, 0x58, 0xaf, 0xce, 0x5f, 0xb0, 0x66, 0xf1, 0x2a, 0x8c, 0x97, 0x34, 0x7b, 0x0b, - 0x32, 0xa3, 0x63, 0xeb, 0x2c, 0x69, 0xe8, 0x25, 0x17, 0x10, 0x11, 0xa8, 0x3f, 0x4f, 0x01, 0x4b, - 0x54, 0x84, 0xdb, 0x1e, 0xdf, 0xb5, 0x2e, 0x9f, 0x40, 0x55, 0xbc, 0xe3, 0xc8, 0xa9, 0x24, 0x2f, - 0xb9, 0xe8, 0xd2, 0x8b, 0xde, 0x2c, 0xc4, 0x73, 0xf6, 0x3a, 0x15, 0x7b, 0x08, 0xfc, 0x21, 0x3d, - 0x8a, 0x13, 0xc9, 0x9c, 0x63, 0x27, 0x6a, 0x33, 0x9a, 0xd9, 0xcb, 0x79, 0xf2, 0x8b, 0x80, 0xdc, - 0xc1, 0xbe, 0x3e, 0x1b, 0x35, 0x5a, 0xf3, 0xea, 0xef, 0xa5, 0xe0, 0x42, 0x72, 0x42, 0xfc, 0x62, - 0xad, 0x4c, 0x3e, 0x7f, 0x98, 0x9e, 0x7f, 0xfe, 0x70, 0xd9, 0x7c, 0xca, 0x2c, 0x9d, 0x4f, 0xbf, - 0x95, 0x82, 0x4d, 0xa9, 0xf7, 0x67, 0xd6, 0xe2, 0x5f, 0x50, 0xcd, 0xa4, 0x57, 0x10, 0x33, 0x89, - 0x57, 0x10, 0xd5, 0x3f, 0x48, 0xc1, 0xa5, 0xb9, 0x9a, 0x68, 0xd6, 0x5f, 0x68, 0x5d, 0x92, 0xaf, - 0x25, 0x92, 0x93, 0x9f, 0xc7, 0xb9, 0xf2, 0x9b, 0xb9, 0x2c, 0xf9, 0xfc, 0x21, 0xdd, 0x83, 0xff, - 0x10, 0x36, 0x66, 0x75, 0xac, 0x8b, 0x97, 0x1d, 0x6f, 0x42, 0xc9, 0xb5, 0x4e, 0xf4, 0xe8, 0xdd, - 0x47, 0x11, 0x19, 0xe4, 0x5a, 0x27, 0x82, 0x40, 0xdd, 0x91, 0x05, 0x46, 0xfc, 0x08, 0xbc, 0x63, - 0x26, 0x42, 0x4c, 0x3c, 0xc7, 0x8c, 0x50, 0x98, 0x9b, 0xd4, 0xa2, 0xbc, 0x6b, 0x9d, 0xd0, 0x60, - 0x9d, 0x88, 0x7c, 0x6a, 0xa6, 0x29, 0x8e, 0xd9, 0x97, 0x3d, 0xe6, 0x74, 0x05, 0x0a, 0x13, 0x3f, - 0xd1, 0x25, 0xf9, 0x89, 0xcf, 0x8b, 0xbd, 0x23, 0xe2, 0x8e, 0xce, 0x3b, 0x92, 0xe7, 0x91, 0x48, - 0xe2, 0x47, 0x22, 0x32, 0xb3, 0x1f, 0x89, 0xf8, 0x48, 0xc8, 0x0a, 0x32, 0x8e, 0x78, 0xc9, 0x0a, - 0xa4, 0x6d, 0xf3, 0x94, 0x0a, 0x5e, 0xd3, 0xf0, 0x93, 0xd4, 0x1d, 0xeb, 0x2b, 0x11, 0xfa, 0x84, - 0x9f, 0xea, 0x36, 0x94, 0xb4, 0x84, 0x25, 0x58, 0x96, 0x9c, 0x2a, 0x41, 0xf2, 0xbd, 0x9b, 0x59, - 0x07, 0x69, 0xa5, 0x99, 0x4f, 0x25, 0x50, 0x03, 0x21, 0x1d, 0x9e, 0x1b, 0xfe, 0xf0, 0xc8, 0xf0, - 0xdb, 0x96, 0x7b, 0x18, 0x1e, 0x61, 0x97, 0x73, 0x5f, 0xa7, 0xdc, 0x85, 0xc0, 0x41, 0xd1, 0xd0, - 0x63, 0x2f, 0x3a, 0x44, 0x1e, 0x3d, 0x3f, 0xef, 0x5a, 0x27, 0x82, 0xff, 0x0d, 0x00, 0xec, 0x7f, - 0x81, 0xe6, 0x27, 0x6c, 0x45, 0xcf, 0x31, 0x39, 0x5a, 0xdd, 0x10, 0xed, 0x15, 0xf7, 0x56, 0x1a, - 0xd6, 0x48, 0x75, 0xc4, 0xc8, 0xf3, 0x06, 0x89, 0x4e, 0xf8, 0x4e, 0xc3, 0xc8, 0x6e, 0x41, 0x39, - 0x32, 0xdb, 0xe9, 0x89, 0x25, 0x5e, 0x7c, 0x29, 0x82, 0x75, 0xa6, 0x63, 0xf5, 0xf7, 0xd3, 0x50, - 0xae, 0xf1, 0x20, 0x94, 0xc9, 0x59, 0x77, 0x12, 0xb2, 0x5f, 0x87, 0x8b, 0xc1, 0xb1, 0x3d, 0x11, - 0xef, 0xc5, 0x53, 0xec, 0x07, 0x05, 0x01, 0x8b, 0x4e, 0xbc, 0x2f, 0x75, 0xa2, 0x60, 0x79, 0xd0, - 0x3b, 0xb6, 0x27, 0x3c, 0xf6, 0xbc, 0x65, 0x9e, 0x52, 0xa0, 0x37, 0x3f, 0xfa, 0x66, 0xc1, 0x02, - 0x82, 0x2e, 0x0e, 0x63, 0xf6, 0x93, 0x63, 0x91, 0xad, 0x38, 0xe1, 0x47, 0xe0, 0xfe, 0x31, 0xa7, - 0xb9, 0x0f, 0x1b, 0xfc, 0xba, 0xc9, 0xe2, 0x2e, 0xb5, 0xce, 0x11, 0xb3, 0xf9, 0xdd, 0x83, 0x0d, - 0xca, 0x4f, 0xbc, 0xe3, 0xa7, 0x0f, 0xbd, 0xc9, 0x99, 0x38, 0x59, 0x7b, 0xeb, 0x9c, 0xaa, 0xb6, - 0x38, 0x29, 0x82, 0xc4, 0x1b, 0x20, 0x41, 0x12, 0x7a, 0xb5, 0x09, 0x97, 0xcf, 0x69, 0xd3, 0xeb, - 0x4e, 0xef, 0x0b, 0xd2, 0xe9, 0xfd, 0xd5, 0x6d, 0xd8, 0x5c, 0x56, 0xde, 0xb7, 0xc9, 0x43, 0xfd, - 0x4f, 0x65, 0x80, 0xd9, 0x8c, 0x4d, 0xe8, 0x6c, 0xa9, 0x39, 0x9d, 0xed, 0x5b, 0xc5, 0x9f, 0x7c, - 0x08, 0x15, 0xec, 0x2a, 0x7d, 0xc6, 0x91, 0x5e, 0xca, 0x51, 0x46, 0xaa, 0xfe, 0xec, 0x9e, 0xdf, - 0xe2, 0x89, 0x7f, 0x66, 0xe9, 0x89, 0xff, 0x07, 0x90, 0xe7, 0xa7, 0x51, 0x81, 0xb8, 0x27, 0x7a, - 0x79, 0x7e, 0xf5, 0x3d, 0x10, 0x71, 0xec, 0x11, 0x1d, 0x6b, 0x42, 0x05, 0xe5, 0xa3, 0x6f, 0x87, - 0x47, 0x63, 0xf9, 0xd6, 0xe8, 0x8d, 0x45, 0xce, 0x88, 0x8c, 0xbf, 0xfe, 0x67, 0xc8, 0x49, 0x49, - 0xc5, 0x0b, 0xc7, 0xc2, 0x45, 0x4a, 0x2a, 0x5e, 0x5e, 0x56, 0xf1, 0xfa, 0x63, 0xee, 0x18, 0x45, - 0x15, 0xef, 0x3d, 0xb8, 0x20, 0xee, 0xd6, 0x20, 0x03, 0x76, 0x27, 0xd1, 0xf3, 0x50, 0x43, 0xf1, - 0x34, 0x4e, 0x7f, 0x4c, 0x06, 0x10, 0x92, 0x7f, 0x0e, 0x9b, 0xc3, 0x23, 0xc3, 0x3d, 0xb4, 0xf4, - 0x70, 0xe0, 0xe8, 0xf4, 0xf6, 0xb8, 0x3e, 0x36, 0x26, 0x42, 0xf3, 0x7c, 0x6b, 0xa1, 0xb2, 0x75, - 0x22, 0xee, 0x0f, 0x1c, 0x8a, 0x95, 0x8a, 0xe3, 0x42, 0x36, 0x86, 0xf3, 0xf0, 0xb9, 0xe3, 0x59, - 0x58, 0x38, 0x9e, 0x9d, 0xd7, 0x45, 0x4b, 0x4b, 0x74, 0xd1, 0x99, 0x46, 0x59, 0x96, 0x35, 0x4a, - 0xf6, 0x2e, 0xe4, 0xc5, 0x85, 0x45, 0xe1, 0x1c, 0x65, 0x8b, 0xab, 0x43, 0x8b, 0x48, 0xb0, 0xa4, - 0x28, 0x58, 0x80, 0xee, 0x2c, 0x57, 0x78, 0x49, 0x32, 0x8c, 0x6d, 0x0b, 0xcf, 0x60, 0x1c, 0xd7, - 0x25, 0x1c, 0xa1, 0x57, 0xa5, 0x8c, 0x63, 0x9c, 0x30, 0x5e, 0xe7, 0x38, 0xae, 0xfe, 0xb7, 0x2c, - 0xe4, 0x44, 0x08, 0xf1, 0x7d, 0xc8, 0x98, 0xbe, 0x37, 0x89, 0x63, 0x72, 0x97, 0xa8, 0xb6, 0xf4, - 0x73, 0x53, 0xa8, 0x05, 0x3f, 0x80, 0x9c, 0x61, 0x9a, 0xfa, 0xe8, 0x38, 0x79, 0x68, 0x3b, 0xa7, - 0x65, 0xee, 0xae, 0x68, 0x59, 0x83, 0xd4, 0xcd, 0x4f, 0xa0, 0x88, 0xf4, 0xb3, 0x48, 0xc9, 0xd2, - 0xa2, 0xee, 0x1c, 0xe9, 0x83, 0xbb, 0x2b, 0x5a, 0xc1, 0x88, 0x74, 0xc3, 0x1f, 0x24, 0xdd, 0xdf, - 0x99, 0x85, 0x06, 0xce, 0x29, 0x33, 0x73, 0x8e, 0xf0, 0x5f, 0x05, 0xee, 0x0f, 0x8d, 0x77, 0xec, - 0xac, 0x7c, 0x3e, 0xb8, 0xb0, 0xbf, 0xef, 0xae, 0x68, 0x7c, 0xdf, 0x8a, 0xf6, 0xfb, 0x8f, 0x22, - 0xd7, 0x74, 0xfc, 0xb3, 0x1c, 0x4b, 0x7a, 0x06, 0xc5, 0x60, 0xec, 0x9f, 0x26, 0x99, 0x88, 0x6c, - 0xa6, 0x19, 0x05, 0xcc, 0xe5, 0x17, 0xd8, 0xe2, 0x5d, 0x9d, 0xd8, 0xe2, 0x2d, 0xfe, 0x09, 0x94, - 0xb8, 0xa7, 0x92, 0xf3, 0x15, 0x16, 0xba, 0x76, 0xb6, 0x29, 0xd3, 0xd9, 0xd7, 0x6c, 0x8b, 0xae, - 0x47, 0xed, 0xf4, 0x2d, 0xf9, 0x78, 0xe1, 0xfa, 0xd2, 0x8e, 0xd2, 0xe2, 0x93, 0x06, 0xde, 0x58, - 0x8d, 0xf3, 0xb0, 0x36, 0x6c, 0x0a, 0x3f, 0x3c, 0xdf, 0x80, 0xa3, 0x3d, 0x13, 0x16, 0xc6, 0x2b, - 0xb1, 0x43, 0xef, 0xae, 0x68, 0xcc, 0x58, 0xdc, 0xb7, 0xeb, 0xb0, 0x11, 0x55, 0x89, 0x5f, 0x15, - 0x9d, 0x45, 0x05, 0xc9, 0x4d, 0x9a, 0xed, 0xbb, 0xbb, 0x2b, 0xda, 0xba, 0x91, 0x04, 0xb1, 0x16, - 0x5c, 0x88, 0x32, 0x21, 0x7f, 0xb4, 0xe8, 0x99, 0xf2, 0xc2, 0x28, 0xca, 0x7b, 0xf5, 0xee, 0x8a, - 0xb6, 0x61, 0xcc, 0x03, 0x67, 0xa7, 0xf3, 0x57, 0x35, 0xb8, 0xb4, 0x5c, 0x24, 0xc8, 0xfb, 0x42, - 0x86, 0xef, 0x0b, 0x6a, 0xf2, 0x99, 0xa7, 0xe4, 0xa3, 0x01, 0xd2, 0x2e, 0xf1, 0x23, 0x58, 0x4b, - 0xc8, 0x44, 0x56, 0x82, 0x7c, 0xf4, 0x20, 0x34, 0xc5, 0xf9, 0xd7, 0xbb, 0xfb, 0x5f, 0x28, 0x29, - 0x04, 0xb7, 0x3a, 0xbd, 0x7e, 0xad, 0x23, 0x62, 0x2f, 0x5a, 0x1d, 0x11, 0x7b, 0xa1, 0xfe, 0xb5, - 0x34, 0x14, 0xe3, 0xb3, 0xa3, 0xef, 0xee, 0xe3, 0x89, 0x9d, 0x27, 0x69, 0xd9, 0x79, 0x32, 0x67, - 0xc0, 0xf0, 0xb7, 0xdb, 0xf9, 0xf3, 0x5f, 0xeb, 0x49, 0x33, 0x21, 0x58, 0xbc, 0x6b, 0x9c, 0xfd, - 0x86, 0x77, 0x8d, 0xe5, 0xe8, 0xe6, 0x5c, 0x32, 0xba, 0x79, 0xee, 0x51, 0xf0, 0x3c, 0x3d, 0xd7, - 0x2b, 0x3f, 0x0a, 0x4e, 0xbf, 0xdc, 0xf7, 0xdc, 0xb6, 0x4e, 0x44, 0x38, 0xb0, 0x48, 0x25, 0xb7, - 0x54, 0x78, 0xcd, 0x96, 0xfa, 0x4d, 0xc4, 0xf3, 0x23, 0xd8, 0x1c, 0x1d, 0xc7, 0x8f, 0x04, 0xcf, - 0x5c, 0x06, 0x65, 0xaa, 0xd2, 0x52, 0x9c, 0xfa, 0x57, 0x52, 0x00, 0xb3, 0xc3, 0x92, 0x5f, 0xd8, - 0xef, 0x28, 0xb9, 0x76, 0xd2, 0xaf, 0x70, 0xed, 0xbc, 0xee, 0xa9, 0xa7, 0xaf, 0xa0, 0x18, 0x1f, - 0x8f, 0x7d, 0xf7, 0xf9, 0xf2, 0xad, 0x8a, 0xfc, 0x8d, 0xc8, 0x07, 0x1b, 0x9f, 0x2f, 0xfd, 0xa2, - 0x7d, 0x91, 0x28, 0x3e, 0xfd, 0x9a, 0xe2, 0x4f, 0xb9, 0x23, 0x34, 0x2e, 0xfc, 0x97, 0xbc, 0x48, - 0xe4, 0xf9, 0x9b, 0x49, 0xcc, 0x5f, 0x75, 0x2a, 0xbc, 0xb9, 0xbf, 0x78, 0xd1, 0xdf, 0xaa, 0xc1, - 0xff, 0x25, 0x15, 0xb9, 0x1c, 0xe3, 0xe7, 0x9a, 0xcf, 0x55, 0x3e, 0x97, 0x7b, 0x4d, 0xbf, 0x4d, - 0x71, 0xaf, 0x74, 0xa8, 0x64, 0x5e, 0xe5, 0x50, 0x79, 0x0b, 0xb2, 0x7c, 0xdb, 0xc9, 0x9e, 0xe7, - 0x4c, 0xe1, 0xf8, 0xd7, 0xfe, 0xa8, 0x82, 0xaa, 0x0a, 0x65, 0x9b, 0xb7, 0x77, 0x33, 0xca, 0x37, - 0xfa, 0x41, 0x08, 0xba, 0x54, 0xf1, 0xff, 0x70, 0x41, 0xf9, 0x5d, 0xbb, 0xe4, 0xd5, 0xae, 0x02, - 0xf5, 0x7f, 0xa5, 0x60, 0x2d, 0x71, 0xdc, 0xfd, 0x1d, 0x8a, 0x58, 0x2a, 0x6e, 0xd3, 0xff, 0x07, - 0x89, 0xdb, 0x44, 0xa4, 0x68, 0x21, 0x19, 0x29, 0x8a, 0xe2, 0xae, 0x9c, 0x30, 0x25, 0x96, 0x19, - 0x1d, 0xa9, 0xa5, 0x46, 0xc7, 0x8d, 0xf8, 0xa7, 0xe0, 0x5a, 0x0d, 0x1e, 0x98, 0xb9, 0xa6, 0x49, - 0x10, 0xf6, 0x29, 0x5c, 0x11, 0xc6, 0x3c, 0xef, 0x1f, 0x6f, 0xa4, 0xc7, 0x3f, 0x14, 0x27, 0x8c, - 0xe3, 0x4b, 0x9c, 0x80, 0xff, 0x24, 0xc6, 0xa8, 0x16, 0x61, 0xd5, 0x16, 0xac, 0x25, 0xe2, 0x08, - 0xa4, 0x1f, 0xa6, 0x4c, 0xc9, 0x3f, 0x4c, 0xc9, 0xb6, 0x20, 0x7b, 0x72, 0x64, 0xf9, 0xd6, 0x92, - 0xe7, 0x5c, 0x39, 0x42, 0xfd, 0x3e, 0x94, 0xe5, 0x98, 0x26, 0xf6, 0x2e, 0x64, 0xed, 0xd0, 0x1a, - 0x47, 0x6e, 0x8a, 0x4b, 0x8b, 0x61, 0x4f, 0xad, 0xd0, 0x1a, 0x6b, 0x9c, 0x48, 0xfd, 0x59, 0x0a, - 0x94, 0x79, 0x9c, 0xf4, 0xeb, 0x99, 0xa9, 0x73, 0x7e, 0x3d, 0x73, 0x35, 0x51, 0xc9, 0x65, 0x3f, - 0x80, 0x19, 0x3f, 0x29, 0x99, 0x39, 0xe7, 0x49, 0x49, 0x76, 0x17, 0x0a, 0xbe, 0x45, 0x3f, 0x4d, - 0x68, 0x2e, 0xb9, 0x6c, 0x10, 0xe3, 0xd4, 0xdf, 0x49, 0x41, 0x5e, 0x04, 0x60, 0x2d, 0xf5, 0x1b, - 0xbd, 0x0d, 0x79, 0xfe, 0x33, 0x85, 0xd1, 0x63, 0x48, 0x0b, 0xd1, 0xcc, 0x11, 0x9e, 0xdd, 0xe0, - 0x61, 0x69, 0x49, 0x3f, 0xd2, 0xbe, 0x63, 0xb8, 0x1a, 0xc1, 0xc5, 0x2f, 0xdd, 0x18, 0x63, 0x71, - 0x8f, 0x99, 0x3f, 0x59, 0x04, 0x04, 0xa2, 0x2b, 0xcb, 0xea, 0x0f, 0x20, 0x2f, 0x02, 0xbc, 0x96, - 0x56, 0xe5, 0x75, 0x3f, 0x51, 0xb7, 0x05, 0x30, 0x8b, 0xf8, 0x5a, 0x96, 0x83, 0x7a, 0x1f, 0x0a, - 0x51, 0x90, 0x17, 0xce, 0xbf, 0x59, 0xd1, 0xe2, 0x16, 0x8b, 0x5c, 0x19, 0x47, 0x3c, 0x91, 0xde, - 0xf6, 0x86, 0xc7, 0xe4, 0xd9, 0x7d, 0x08, 0x74, 0xa5, 0xa7, 0xbf, 0xf0, 0xb6, 0x53, 0xf2, 0x7d, - 0xfb, 0x98, 0x88, 0xdd, 0x87, 0x58, 0x5e, 0xbe, 0xce, 0xc4, 0x57, 0x6b, 0xd1, 0xe5, 0x2f, 0x9a, - 0x65, 0x8f, 0x85, 0x07, 0xb3, 0x4d, 0xef, 0xc9, 0xa5, 0xe4, 0x5f, 0x39, 0x48, 0xd4, 0x49, 0x93, - 0xc8, 0xd4, 0x0a, 0x94, 0xe5, 0xc8, 0x14, 0xb5, 0x06, 0x1b, 0x7b, 0x56, 0x68, 0xa0, 0xfc, 0x89, - 0x1e, 0xc9, 0xe1, 0xf3, 0x17, 0x3f, 0x92, 0xf3, 0x77, 0x9e, 0x4e, 0xe3, 0x44, 0xea, 0xcf, 0x32, - 0xa0, 0xcc, 0xe3, 0x5e, 0x75, 0x11, 0xee, 0x26, 0x94, 0x3c, 0x9a, 0x17, 0x89, 0xdf, 0x32, 0xe2, - 0x20, 0x29, 0xec, 0x3c, 0xf1, 0x83, 0x16, 0x05, 0x3b, 0xd8, 0xe5, 0x3f, 0x69, 0x71, 0x99, 0xdf, - 0x7a, 0x72, 0xbc, 0x21, 0x4d, 0xeb, 0x32, 0x5d, 0x72, 0x6a, 0x7b, 0x43, 0xba, 0x5f, 0x27, 0xbc, - 0x04, 0x3c, 0x5c, 0xb2, 0xac, 0x15, 0x84, 0x6b, 0x80, 0x0e, 0x9b, 0x44, 0x30, 0x7a, 0x18, 0x88, - 0x1b, 0x8b, 0x05, 0x0e, 0xe8, 0x07, 0xd1, 0x43, 0xdc, 0x43, 0xf1, 0xc3, 0x3b, 0x69, 0x7a, 0x88, - 0xbb, 0xee, 0xd2, 0xf5, 0x3a, 0xfa, 0x9d, 0xa8, 0xa1, 0xf8, 0x1d, 0x2f, 0xf1, 0x14, 0x3a, 0xa2, - 0x6e, 0xf3, 0x9f, 0x26, 0xf2, 0xad, 0x20, 0xe0, 0xaf, 0x8e, 0x15, 0xc5, 0x7b, 0x72, 0x02, 0x18, - 0xbf, 0xda, 0x28, 0x7e, 0x18, 0x0a, 0x49, 0x40, 0xbc, 0x7d, 0xc6, 0x7f, 0x16, 0x0a, 0x09, 0xae, - 0x40, 0xe1, 0x6b, 0xcf, 0xb5, 0xc8, 0xdb, 0x50, 0xa2, 0x5a, 0xe5, 0x31, 0xbd, 0x67, 0x4c, 0xd4, - 0x7f, 0x9a, 0x82, 0xcd, 0xf9, 0x5e, 0xa5, 0x09, 0x53, 0x86, 0x42, 0xbd, 0xdb, 0xd6, 0x3b, 0xb5, - 0xbd, 0xa6, 0xb2, 0xc2, 0xd6, 0xa1, 0xd4, 0xdd, 0xfe, 0xac, 0x59, 0xef, 0x73, 0x40, 0x8a, 0xae, - 0x99, 0xf7, 0xf4, 0xdd, 0x56, 0xa3, 0xd1, 0xec, 0x70, 0x93, 0xa0, 0xbb, 0xfd, 0x99, 0xde, 0xee, - 0xd6, 0xf9, 0xef, 0xc8, 0x44, 0x07, 0xf1, 0x3d, 0x25, 0x43, 0xc7, 0xf4, 0x14, 0x9d, 0x8d, 0xc9, - 0x2c, 0x0f, 0x3e, 0x7e, 0xd1, 0xd3, 0xeb, 0x9d, 0xbe, 0x92, 0xc3, 0x54, 0xe7, 0xa0, 0xdd, 0xa6, - 0x14, 0x45, 0x19, 0xd6, 0xbb, 0x7b, 0xfb, 0x5a, 0xb3, 0xd7, 0xd3, 0x7b, 0xad, 0x9f, 0x34, 0x95, - 0x02, 0x95, 0xac, 0xb5, 0x9e, 0xb6, 0x3a, 0x1c, 0x50, 0x64, 0x79, 0x48, 0xef, 0xb5, 0x3a, 0xfc, - 0x7a, 0xfd, 0x5e, 0xed, 0x73, 0xa5, 0x84, 0x1f, 0xbd, 0x83, 0x3d, 0xa5, 0xac, 0xfe, 0xfb, 0x74, - 0xa4, 0xf0, 0x52, 0xcc, 0xcd, 0x37, 0x51, 0xf2, 0x96, 0x9d, 0x75, 0x6d, 0x42, 0xd6, 0xa1, 0x0b, - 0xc3, 0xe2, 0x27, 0x72, 0x29, 0xf1, 0x4d, 0x7e, 0xf6, 0xf3, 0x36, 0xac, 0xc5, 0x07, 0xd5, 0xd2, - 0xdb, 0xd8, 0xe5, 0x08, 0xb8, 0xe4, 0x44, 0x20, 0xb7, 0xe4, 0x44, 0x60, 0x62, 0x87, 0x68, 0xcc, - 0xa2, 0x48, 0xe5, 0x13, 0xa5, 0x88, 0x10, 0xfe, 0x83, 0xbb, 0xd7, 0x80, 0x12, 0xfa, 0xd4, 0xb5, - 0xa3, 0x1f, 0x7d, 0x2b, 0x20, 0xe0, 0xc0, 0xb5, 0xc3, 0xf9, 0x83, 0xf2, 0xe2, 0xc2, 0x41, 0xb9, - 0xbc, 0xf7, 0x42, 0x72, 0xef, 0x4d, 0xfe, 0x1a, 0x2a, 0xff, 0xb5, 0x37, 0xe9, 0xd7, 0x50, 0xdf, - 0x05, 0x36, 0x9c, 0xfa, 0xf4, 0xfe, 0x96, 0x44, 0x56, 0x26, 0x32, 0x45, 0x60, 0xe2, 0x4d, 0x8f, - 0xbd, 0x05, 0xeb, 0x73, 0xd4, 0xe4, 0x3c, 0x2a, 0x6a, 0x95, 0x24, 0x29, 0x7b, 0x00, 0x17, 0xc4, - 0xd4, 0x4d, 0xf4, 0xad, 0xb8, 0x8c, 0xc8, 0x51, 0xb5, 0x59, 0x0f, 0xab, 0xbf, 0x02, 0x85, 0x28, - 0xbc, 0xea, 0xd5, 0xba, 0xec, 0x92, 0x71, 0x55, 0xff, 0xfe, 0x2a, 0x14, 0xe3, 0x60, 0xab, 0x6f, - 0x34, 0x3b, 0xe8, 0x47, 0x00, 0x82, 0x63, 0x59, 0x82, 0x14, 0x10, 0x10, 0x8d, 0x94, 0xb8, 0xf3, - 0x33, 0xf5, 0xed, 0x48, 0x21, 0xe3, 0x90, 0x03, 0xdf, 0xa6, 0xe7, 0x2c, 0x6c, 0x57, 0xba, 0x36, - 0x58, 0xd4, 0x0a, 0x08, 0xa0, 0xd5, 0x75, 0x05, 0xe8, 0x9b, 0x38, 0xa3, 0x1f, 0x88, 0xb5, 0xdd, - 0x63, 0xe4, 0x3b, 0xe7, 0x07, 0x62, 0xe9, 0x27, 0x0c, 0x78, 0xa4, 0x07, 0x3f, 0xdf, 0x8e, 0x7e, - 0x70, 0xeb, 0x1a, 0x14, 0xa7, 0xf1, 0x2f, 0xb6, 0x89, 0x19, 0x31, 0x8d, 0x7e, 0xaf, 0x2d, 0x39, - 0xaa, 0xc5, 0xf9, 0x51, 0x9d, 0x9f, 0xd3, 0xb0, 0x30, 0xa7, 0xd5, 0x10, 0xf2, 0x22, 0xe0, 0xec, - 0xd5, 0x1d, 0xfe, 0xca, 0xae, 0x52, 0x20, 0x6d, 0x38, 0xd1, 0x5d, 0x45, 0xfc, 0x9c, 0xab, 0x58, - 0x66, 0xae, 0x62, 0xea, 0xdf, 0x5c, 0x05, 0x98, 0x05, 0xae, 0xb1, 0xf7, 0xe6, 0x82, 0x64, 0x53, - 0x0b, 0xbb, 0xfa, 0x5c, 0x6c, 0xec, 0xdc, 0xfb, 0x2e, 0xab, 0xdf, 0xe0, 0x7d, 0x97, 0x47, 0xb0, - 0x16, 0xf8, 0xc3, 0xd7, 0xfa, 0xb5, 0x4b, 0x81, 0x3f, 0x8c, 0xdd, 0xda, 0x0f, 0x01, 0x93, 0xf4, - 0x22, 0xdd, 0xcc, 0x0e, 0x5d, 0x50, 0x4a, 0x8a, 0x81, 0x3f, 0xec, 0x0e, 0xbe, 0x6c, 0xf0, 0x8b, - 0x56, 0x66, 0x10, 0xea, 0xcb, 0xa4, 0xc4, 0xba, 0x19, 0x84, 0x0d, 0x59, 0x50, 0xdc, 0x81, 0x0a, - 0xd2, 0x2e, 0x08, 0x8b, 0xb2, 0x19, 0xcc, 0xce, 0x31, 0xd4, 0xdf, 0x8e, 0x8e, 0x47, 0xe7, 0x5c, - 0xa6, 0xec, 0x63, 0x61, 0x67, 0x4b, 0x3a, 0x42, 0x75, 0x99, 0x87, 0x95, 0xbf, 0x46, 0x13, 0x93, - 0x2e, 0xfe, 0x4e, 0xd7, 0xea, 0x37, 0xfc, 0x9d, 0xae, 0xfb, 0xb7, 0xa0, 0x2c, 0xff, 0x16, 0x26, - 0x5d, 0xf7, 0xf0, 0x5c, 0x8b, 0xff, 0x5a, 0x42, 0xfb, 0xeb, 0x0f, 0x95, 0xd4, 0x7d, 0x15, 0x4a, - 0xd2, 0x6f, 0x95, 0x20, 0xc5, 0xae, 0x11, 0x1c, 0x89, 0x97, 0xf3, 0x0d, 0xf7, 0xd0, 0x52, 0x52, - 0xf7, 0xef, 0xa2, 0xc6, 0x2c, 0xff, 0x52, 0x08, 0x40, 0xae, 0xe3, 0xf9, 0x63, 0xc3, 0x11, 0x74, - 0xd6, 0x34, 0x40, 0xba, 0x87, 0x70, 0x71, 0xe9, 0xef, 0x9e, 0xd0, 0x9d, 0x21, 0x7b, 0x3c, 0x71, - 0x2c, 0x7e, 0xed, 0x65, 0xf7, 0x6c, 0xe0, 0xdb, 0xa6, 0x92, 0xba, 0xff, 0x24, 0xba, 0x43, 0x1f, - 0x95, 0xdd, 0xee, 0xd6, 0x1a, 0x7c, 0x73, 0x8b, 0xdf, 0x72, 0xe9, 0x6f, 0xf3, 0x57, 0xf1, 0xb5, - 0x66, 0xef, 0xa0, 0xdd, 0x17, 0xef, 0xc6, 0xdc, 0xff, 0x11, 0x54, 0xcf, 0xbb, 0xff, 0x81, 0x35, - 0xaa, 0xef, 0xd6, 0xe8, 0x8e, 0x0d, 0x6e, 0x66, 0x5d, 0x9d, 0xa7, 0x52, 0xfc, 0x8a, 0x52, 0xbb, - 0x49, 0x41, 0x92, 0xf7, 0x7f, 0x9a, 0x92, 0x54, 0xb8, 0x28, 0x86, 0x3f, 0x06, 0x88, 0x6e, 0x92, - 0x41, 0x9a, 0x65, 0x98, 0x4a, 0x8a, 0x5d, 0x02, 0x96, 0x00, 0xb5, 0xbd, 0xa1, 0xe1, 0x28, 0xab, - 0x14, 0x0e, 0x19, 0xc1, 0xe9, 0x96, 0x96, 0x92, 0x66, 0x6f, 0xc0, 0x95, 0x18, 0xd6, 0xf6, 0x4e, - 0xf6, 0x7d, 0xdb, 0xf3, 0xed, 0xf0, 0x8c, 0xa3, 0x33, 0xf7, 0xff, 0x5f, 0x71, 0x4e, 0x99, 0x18, - 0x79, 0x2c, 0xa0, 0x66, 0x9a, 0x33, 0x18, 0x09, 0x1b, 0x65, 0x85, 0x5d, 0x86, 0x0b, 0x24, 0x69, - 0xe7, 0x10, 0x29, 0x76, 0x0d, 0x2e, 0x47, 0x76, 0xe6, 0x3c, 0x72, 0x15, 0x91, 0x9a, 0x45, 0xa1, - 0x74, 0x0b, 0xc8, 0xf4, 0xf6, 0x0f, 0xff, 0xf4, 0xe7, 0x37, 0x52, 0xff, 0xe2, 0xe7, 0x37, 0x52, - 0xff, 0xe1, 0xe7, 0x37, 0x56, 0x7e, 0xf6, 0x1f, 0x6f, 0xa4, 0x7e, 0xf2, 0xde, 0xa1, 0x1d, 0x1e, - 0x4d, 0x07, 0x0f, 0x86, 0xde, 0xf8, 0xe1, 0xd8, 0x08, 0x7d, 0xfb, 0x94, 0x8b, 0xfc, 0x28, 0xe1, - 0x5a, 0x0f, 0x27, 0xc7, 0x87, 0x0f, 0x27, 0x83, 0x87, 0x38, 0xf9, 0x06, 0xb9, 0x89, 0xef, 0x85, - 0xde, 0xe3, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x80, 0x47, 0x44, 0xe9, 0x95, 0x84, 0x00, 0x00, + 0xf2, 0x90, 0x05, 0x26, 0x0b, 0x04, 0x09, 0x82, 0x5d, 0x20, 0x09, 0x36, 0xd8, 0xe4, 0x39, 0x2f, + 0x9b, 0x04, 0xd9, 0x04, 0x08, 0x90, 0x20, 0x09, 0xb0, 0x09, 0x26, 0xc8, 0x63, 0x90, 0x04, 0xc9, + 0x7b, 0x82, 0x73, 0xee, 0xad, 0xe2, 0x2d, 0x92, 0xb2, 0xbb, 0x7b, 0x66, 0x81, 0xe4, 0x45, 0xaa, + 0x7b, 0x7e, 0xee, 0xff, 0x3d, 0xf7, 0x9c, 0x73, 0xcf, 0xbd, 0x04, 0x98, 0x38, 0x86, 0xfb, 0x60, + 0xe2, 0x7b, 0xa1, 0xc7, 0x32, 0xf8, 0x7d, 0xf5, 0xbd, 0x43, 0x3b, 0x3c, 0x9a, 0x0e, 0x1e, 0x0c, + 0xbd, 0xf1, 0xc3, 0x43, 0xef, 0xd0, 0x7b, 0x48, 0xc8, 0xc1, 0x74, 0x44, 0x29, 0x4a, 0xd0, 0x17, + 0x67, 0xba, 0x0a, 0x8e, 0x37, 0x3c, 0x16, 0xdf, 0xeb, 0xa1, 0x3d, 0xb6, 0x82, 0xd0, 0x18, 0x4f, + 0x38, 0x40, 0xfd, 0x93, 0x14, 0x64, 0xfa, 0x67, 0x13, 0x8b, 0x55, 0x60, 0xd5, 0x36, 0xab, 0xa9, + 0xad, 0xd4, 0xbd, 0xac, 0xb6, 0x6a, 0x9b, 0x6c, 0x0b, 0x4a, 0xae, 0x17, 0x76, 0xa6, 0x8e, 0x63, + 0x0c, 0x1c, 0xab, 0xba, 0xba, 0x95, 0xba, 0x57, 0xd0, 0x64, 0x10, 0xbb, 0x06, 0x45, 0x63, 0x1a, + 0x7a, 0xba, 0xed, 0x0e, 0xfd, 0x6a, 0x9a, 0xf0, 0x05, 0x04, 0xb4, 0xdc, 0xa1, 0xcf, 0x36, 0x21, + 0x7b, 0x62, 0x9b, 0xe1, 0x51, 0x35, 0x43, 0x39, 0xf2, 0x04, 0x42, 0x83, 0xa1, 0xe1, 0x58, 0xd5, + 0x2c, 0x87, 0x52, 0x02, 0xa1, 0x21, 0x15, 0x92, 0xdb, 0x4a, 0xdd, 0x2b, 0x6a, 0x3c, 0xc1, 0x6e, + 0x00, 0x58, 0xee, 0x74, 0xfc, 0xd2, 0x70, 0xa6, 0x56, 0x50, 0xcd, 0x13, 0x4a, 0x82, 0xa8, 0x3f, + 0x84, 0xe2, 0x38, 0x38, 0xdc, 0xb5, 0x0c, 0xd3, 0xf2, 0xd9, 0x65, 0xc8, 0x8f, 0x83, 0x43, 0x3d, + 0x34, 0x0e, 0x45, 0x13, 0x72, 0xe3, 0xe0, 0xb0, 0x6f, 0x1c, 0xb2, 0x2b, 0x50, 0x20, 0xc4, 0xd9, + 0x84, 0xb7, 0x21, 0xab, 0x21, 0x21, 0xb6, 0x58, 0xfd, 0x9d, 0x1c, 0xe4, 0xdb, 0x76, 0x68, 0xf9, + 0x86, 0xc3, 0x2e, 0x41, 0xce, 0x0e, 0xdc, 0xa9, 0xe3, 0x10, 0x7b, 0x41, 0x13, 0x29, 0x76, 0x09, + 0xb2, 0xf6, 0x93, 0x97, 0x86, 0xc3, 0x79, 0x77, 0x57, 0x34, 0x9e, 0x64, 0x55, 0xc8, 0xd9, 0x1f, + 0x7c, 0x8c, 0x88, 0xb4, 0x40, 0x88, 0x34, 0x61, 0x1e, 0x3f, 0x42, 0x4c, 0x26, 0xc6, 0x50, 0x9a, + 0x30, 0x1f, 0x7f, 0x88, 0x18, 0x6c, 0x7d, 0x9a, 0x30, 0x94, 0xc6, 0x52, 0xa6, 0x54, 0x0a, 0x76, + 0xc0, 0x1a, 0x96, 0x32, 0x8d, 0x4a, 0x99, 0xf2, 0x52, 0xf2, 0x02, 0x21, 0xd2, 0x84, 0xe1, 0xa5, + 0x14, 0x62, 0x4c, 0x5c, 0xca, 0x94, 0x97, 0x52, 0xdc, 0x4a, 0xdd, 0xcb, 0x10, 0x86, 0x97, 0xb2, + 0x09, 0x19, 0x13, 0xe1, 0xb0, 0x95, 0xba, 0x97, 0xda, 0x5d, 0xd1, 0x28, 0x85, 0xd0, 0x00, 0xa1, + 0x25, 0xec, 0x60, 0x84, 0x06, 0x02, 0x3a, 0x40, 0x68, 0x19, 0x7b, 0x03, 0xa1, 0x03, 0x01, 0x1d, + 0x21, 0x74, 0x6d, 0x2b, 0x75, 0x6f, 0x15, 0xa1, 0x98, 0x62, 0x57, 0x21, 0x6f, 0x1a, 0xa1, 0x85, + 0x88, 0x8a, 0x68, 0x72, 0x04, 0x40, 0x1c, 0xce, 0x38, 0xc4, 0xad, 0x8b, 0x46, 0x47, 0x00, 0xa6, + 0x42, 0x09, 0xc9, 0x22, 0xbc, 0x22, 0xf0, 0x32, 0x90, 0x7d, 0x04, 0x65, 0xd3, 0x1a, 0xda, 0x63, + 0xc3, 0xe1, 0x6d, 0xda, 0xd8, 0x4a, 0xdd, 0x2b, 0x3d, 0x5a, 0x7f, 0x40, 0x6b, 0x22, 0xc6, 0xec, + 0xae, 0x68, 0x09, 0x32, 0xf6, 0x04, 0xd6, 0x44, 0xfa, 0x83, 0x47, 0xd4, 0xb1, 0x8c, 0xf8, 0x94, + 0x04, 0xdf, 0x07, 0x8f, 0x9e, 0xec, 0xae, 0x68, 0x49, 0x42, 0x76, 0x07, 0xca, 0xf1, 0x12, 0x41, + 0xc6, 0x0b, 0xa2, 0x56, 0x09, 0x28, 0x36, 0xeb, 0xcb, 0xc0, 0x73, 0x91, 0x60, 0x53, 0xf4, 0x5b, + 0x04, 0x60, 0x5b, 0x00, 0xa6, 0x35, 0x32, 0xa6, 0x4e, 0x88, 0xe8, 0x8b, 0xa2, 0x03, 0x25, 0x18, + 0xbb, 0x01, 0xc5, 0xe9, 0x04, 0x5b, 0xf9, 0xdc, 0x70, 0xaa, 0x97, 0x04, 0xc1, 0x0c, 0x84, 0xb9, + 0xe3, 0x3c, 0x47, 0xec, 0x65, 0x31, 0xba, 0x11, 0x00, 0x87, 0xf7, 0xa5, 0x35, 0x44, 0x54, 0x55, + 0x14, 0x2c, 0xd2, 0xb8, 0x8a, 0xec, 0x60, 0xdb, 0x76, 0xab, 0x57, 0x68, 0x06, 0xf3, 0x04, 0xbb, + 0x0e, 0xe9, 0xc0, 0x1f, 0x56, 0xaf, 0x52, 0xfb, 0x81, 0xb7, 0xbf, 0x79, 0x3a, 0xf1, 0x35, 0x04, + 0x6f, 0xe7, 0x21, 0x4b, 0xab, 0x49, 0xbd, 0x0e, 0x85, 0x7d, 0xc3, 0x37, 0xc6, 0x9a, 0x35, 0x62, + 0x0a, 0xa4, 0x27, 0x5e, 0x20, 0xd6, 0x11, 0x7e, 0xaa, 0x6d, 0xc8, 0x3d, 0x37, 0x7c, 0xc4, 0x31, + 0xc8, 0xb8, 0xc6, 0xd8, 0x22, 0x64, 0x51, 0xa3, 0x6f, 0x5c, 0x3b, 0xc1, 0x59, 0x10, 0x5a, 0x63, + 0x21, 0x24, 0x44, 0x0a, 0xe1, 0x87, 0x8e, 0x37, 0x10, 0x6b, 0xa4, 0xa0, 0x89, 0x94, 0xfa, 0xff, + 0xa5, 0x20, 0x57, 0xf7, 0x1c, 0xcc, 0xee, 0x32, 0xe4, 0x7d, 0xcb, 0xd1, 0x67, 0xc5, 0xe5, 0x7c, + 0xcb, 0xd9, 0xf7, 0x02, 0x44, 0x0c, 0x3d, 0x8e, 0xe0, 0xab, 0x36, 0x37, 0xf4, 0x08, 0x11, 0x55, + 0x20, 0x2d, 0x55, 0xe0, 0x0a, 0x14, 0xc2, 0x81, 0xa3, 0x13, 0x3c, 0x43, 0xf0, 0x7c, 0x38, 0x70, + 0x3a, 0x88, 0xba, 0x0c, 0x79, 0x73, 0xc0, 0x31, 0x59, 0xc2, 0xe4, 0xcc, 0x01, 0x22, 0xd4, 0x4f, + 0xa1, 0xa8, 0x19, 0x27, 0xa2, 0x1a, 0x17, 0x21, 0x87, 0x19, 0x08, 0xf9, 0x97, 0xd1, 0xb2, 0xe1, + 0xc0, 0x69, 0x99, 0x08, 0xc6, 0x4a, 0xd8, 0x26, 0xd5, 0x21, 0xa3, 0x65, 0x87, 0x9e, 0xd3, 0x32, + 0xd5, 0x3e, 0x40, 0xdd, 0xf3, 0xfd, 0xef, 0xdc, 0x84, 0x4d, 0xc8, 0x9a, 0xd6, 0x24, 0x3c, 0xe2, + 0xa2, 0x43, 0xe3, 0x09, 0xf5, 0x3e, 0x14, 0x70, 0x5c, 0xda, 0x76, 0x10, 0xb2, 0x1b, 0x90, 0x71, + 0xec, 0x20, 0xac, 0xa6, 0xb6, 0xd2, 0x73, 0xa3, 0x46, 0x70, 0x75, 0x0b, 0x0a, 0x7b, 0xc6, 0xe9, + 0x73, 0x1c, 0x39, 0xcc, 0x8d, 0x86, 0x50, 0x0c, 0x89, 0x18, 0xcf, 0x32, 0x40, 0xdf, 0xf0, 0x0f, + 0xad, 0x90, 0x24, 0xdd, 0xff, 0x48, 0x41, 0xa9, 0x37, 0x1d, 0x7c, 0x35, 0xb5, 0xfc, 0x33, 0xac, + 0xf3, 0x3d, 0x48, 0x87, 0x67, 0x13, 0xe2, 0xa8, 0x3c, 0xba, 0xc4, 0xb3, 0x97, 0xf0, 0x0f, 0x90, + 0x49, 0x43, 0x12, 0x6c, 0x84, 0xeb, 0x99, 0x56, 0xd4, 0x07, 0x59, 0x2d, 0x87, 0xc9, 0x96, 0x89, + 0xdb, 0x85, 0x37, 0x11, 0xa3, 0xb0, 0xea, 0x4d, 0xd8, 0x16, 0x64, 0x87, 0x47, 0xb6, 0x63, 0xd2, + 0x00, 0x24, 0xeb, 0xcc, 0x11, 0x38, 0x4a, 0xbe, 0x77, 0xa2, 0x07, 0xf6, 0xd7, 0x91, 0xf8, 0xcf, + 0xfb, 0xde, 0x49, 0xcf, 0xfe, 0xda, 0x52, 0xfb, 0x62, 0x0f, 0x02, 0xc8, 0xf5, 0xea, 0xb5, 0x76, + 0x4d, 0x53, 0x56, 0xf0, 0xbb, 0xf9, 0x79, 0xab, 0xd7, 0xef, 0x29, 0x29, 0x56, 0x01, 0xe8, 0x74, + 0xfb, 0xba, 0x48, 0xaf, 0xb2, 0x1c, 0xac, 0xb6, 0x3a, 0x4a, 0x1a, 0x69, 0x10, 0xde, 0xea, 0x28, + 0x19, 0x96, 0x87, 0x74, 0xad, 0xf3, 0x85, 0x92, 0xa5, 0x8f, 0x76, 0x5b, 0xc9, 0xa9, 0x7f, 0xb6, + 0x0a, 0xc5, 0xee, 0xe0, 0x4b, 0x6b, 0x18, 0x62, 0x9b, 0x71, 0x96, 0x5a, 0xfe, 0x4b, 0xcb, 0xa7, + 0x66, 0xa7, 0x35, 0x91, 0xc2, 0x86, 0x98, 0x03, 0x6a, 0x5c, 0x5a, 0x5b, 0x35, 0x07, 0x44, 0x37, + 0x3c, 0xb2, 0xc6, 0x06, 0x35, 0x0e, 0xe9, 0x28, 0x85, 0xab, 0xc2, 0x1b, 0x7c, 0x49, 0xcd, 0x4b, + 0x6b, 0xf8, 0xc9, 0x6e, 0x42, 0x89, 0xe7, 0x21, 0xcf, 0x2f, 0xe0, 0xa0, 0xf9, 0xc9, 0x97, 0x93, + 0x27, 0x1f, 0x71, 0x52, 0xae, 0x1c, 0x29, 0xf6, 0x36, 0x0e, 0xea, 0x88, 0x19, 0xed, 0x0d, 0xbe, + 0xe4, 0xd8, 0x02, 0x9f, 0xd1, 0xde, 0xe0, 0x4b, 0x42, 0xbd, 0x03, 0x1b, 0xc1, 0x74, 0x10, 0x0c, + 0x7d, 0x7b, 0x12, 0xda, 0x9e, 0xcb, 0x69, 0x8a, 0x44, 0xa3, 0xc8, 0x08, 0x22, 0xbe, 0x07, 0x85, + 0xc9, 0x74, 0xa0, 0xdb, 0xee, 0xc8, 0x23, 0xb1, 0x5f, 0x7a, 0xb4, 0xc6, 0x07, 0x66, 0x7f, 0x3a, + 0x68, 0xb9, 0x23, 0x4f, 0xcb, 0x4f, 0xf8, 0x07, 0x53, 0x61, 0xcd, 0xf5, 0x42, 0x1d, 0x55, 0x05, + 0x7d, 0x6c, 0x85, 0x06, 0xed, 0x07, 0x7c, 0xc3, 0x6f, 0x7b, 0xc3, 0xe3, 0x3d, 0x2b, 0x34, 0xd4, + 0xbb, 0x90, 0x17, 0x7c, 0xb8, 0xf7, 0x87, 0x96, 0x6b, 0xb8, 0xa1, 0x1e, 0x2b, 0x0d, 0x05, 0x0e, + 0x68, 0x99, 0xea, 0x1f, 0xa7, 0x40, 0xe9, 0x49, 0x55, 0x41, 0xe6, 0xa5, 0x92, 0xe3, 0x0d, 0x00, + 0x63, 0x38, 0xf4, 0xa6, 0x3c, 0x1b, 0x3e, 0xc1, 0x8a, 0x02, 0xd2, 0x32, 0xe5, 0xfe, 0x4b, 0x27, + 0xfa, 0xef, 0x16, 0x94, 0x23, 0x3e, 0x69, 0xd1, 0x97, 0x04, 0x2c, 0xea, 0xc1, 0x60, 0x9a, 0x58, + 0xf9, 0xf9, 0x60, 0xca, 0xb9, 0x2f, 0x41, 0x8e, 0x34, 0x8c, 0x20, 0x1a, 0x15, 0x9e, 0x52, 0xff, + 0x4d, 0x0a, 0xd6, 0x5a, 0xae, 0x69, 0x9d, 0xf6, 0x86, 0x86, 0x1b, 0x75, 0x8a, 0x1d, 0xe8, 0x36, + 0xc2, 0xf4, 0x60, 0x68, 0xb8, 0x42, 0x39, 0x28, 0xd9, 0x41, 0x4c, 0x87, 0x6d, 0xe0, 0x04, 0x54, + 0xd4, 0x2a, 0xe5, 0x58, 0x24, 0x08, 0x15, 0x76, 0x17, 0xd6, 0x07, 0x96, 0xe3, 0xb9, 0x87, 0x7a, + 0xe8, 0xe9, 0x5c, 0xcb, 0xe1, 0x6d, 0x59, 0xe3, 0xe0, 0xbe, 0xd7, 0x27, 0x6d, 0x67, 0x13, 0xb2, + 0x13, 0xc3, 0x0f, 0x83, 0x6a, 0x66, 0x2b, 0x8d, 0xcb, 0x98, 0x12, 0xd8, 0xcd, 0x76, 0xa0, 0x4f, + 0x5d, 0xfb, 0xab, 0x29, 0x6f, 0x46, 0x41, 0x2b, 0xd8, 0xc1, 0x01, 0xa5, 0xd9, 0x3d, 0x50, 0x78, + 0xc9, 0x94, 0xad, 0x3c, 0xcf, 0x2a, 0x04, 0xa7, 0x8c, 0x49, 0xd8, 0xfd, 0xa5, 0x55, 0x28, 0xec, + 0x4c, 0xdd, 0x21, 0x0e, 0x06, 0xbb, 0x0d, 0x99, 0xd1, 0xd4, 0x1d, 0x52, 0x5b, 0xe2, 0xad, 0x34, + 0x5e, 0x27, 0x1a, 0x21, 0x51, 0x02, 0x19, 0xfe, 0x21, 0x4a, 0xae, 0x05, 0x09, 0x84, 0x70, 0xf5, + 0x1f, 0xa6, 0x78, 0x8e, 0x3b, 0x8e, 0x71, 0xc8, 0x0a, 0x90, 0xe9, 0x74, 0x3b, 0x4d, 0x65, 0x85, + 0x95, 0xa1, 0xd0, 0xea, 0xf4, 0x9b, 0x5a, 0xa7, 0xd6, 0x56, 0x52, 0xb4, 0x9c, 0xfb, 0xb5, 0xed, + 0x76, 0x53, 0x59, 0x45, 0xcc, 0xf3, 0x6e, 0xbb, 0xd6, 0x6f, 0xb5, 0x9b, 0x4a, 0x86, 0x63, 0xb4, + 0x56, 0xbd, 0xaf, 0x14, 0x98, 0x02, 0xe5, 0x7d, 0xad, 0xdb, 0x38, 0xa8, 0x37, 0xf5, 0xce, 0x41, + 0xbb, 0xad, 0x28, 0xec, 0x02, 0xac, 0xc7, 0x90, 0x2e, 0x07, 0x6e, 0x21, 0xcb, 0xf3, 0x9a, 0x56, + 0xd3, 0x9e, 0x2a, 0x3f, 0x62, 0x05, 0x48, 0xd7, 0x9e, 0x3e, 0x55, 0x7e, 0x8a, 0x92, 0xa1, 0xf8, + 0xa2, 0xd5, 0xd1, 0x9f, 0xd7, 0xda, 0x07, 0x4d, 0xe5, 0xa7, 0xab, 0x51, 0xba, 0xab, 0x35, 0x9a, + 0x9a, 0xf2, 0xd3, 0x0c, 0xdb, 0x80, 0xf2, 0x4f, 0xba, 0x9d, 0xe6, 0x5e, 0x6d, 0x7f, 0x9f, 0x2a, + 0xf2, 0xd3, 0x82, 0xfa, 0x5f, 0x32, 0x90, 0xc1, 0x96, 0x30, 0x75, 0x26, 0x05, 0xe3, 0x26, 0xa2, + 0x18, 0xda, 0xce, 0xfc, 0xe9, 0x9f, 0xdf, 0x5c, 0xe1, 0xf2, 0xef, 0x16, 0xa4, 0x1d, 0x3b, 0xa4, + 0x61, 0x8d, 0xd7, 0x8e, 0xd0, 0x19, 0x77, 0x57, 0x34, 0xc4, 0xb1, 0x1b, 0x90, 0xe2, 0x82, 0xb0, + 0xf4, 0xa8, 0x22, 0x16, 0x97, 0xd8, 0x49, 0x77, 0x57, 0xb4, 0xd4, 0x84, 0x5d, 0x87, 0xd4, 0x4b, + 0x21, 0x15, 0xcb, 0x1c, 0xcf, 0xf7, 0x52, 0xc4, 0xbe, 0x64, 0x5b, 0x90, 0x1e, 0x7a, 0x5c, 0x23, + 0x8c, 0xf1, 0x7c, 0x67, 0xc1, 0xfc, 0x87, 0x9e, 0xc3, 0x6e, 0x43, 0xda, 0x37, 0x4e, 0x68, 0x64, + 0xe3, 0xe1, 0x8a, 0xb7, 0x2e, 0x24, 0xf2, 0x8d, 0x13, 0xac, 0xc4, 0x88, 0xe4, 0x48, 0x5c, 0x89, + 0x68, 0xbc, 0xb1, 0x98, 0x11, 0xdb, 0x82, 0xd4, 0x09, 0x49, 0x92, 0x58, 0x09, 0x7a, 0x61, 0xbb, + 0xa6, 0x77, 0xd2, 0x9b, 0x58, 0x43, 0xa4, 0x38, 0x61, 0x6f, 0x42, 0x3a, 0x98, 0x0e, 0x48, 0x92, + 0x94, 0x1e, 0x6d, 0x2c, 0xec, 0x09, 0x58, 0x50, 0x30, 0x1d, 0xb0, 0xbb, 0x90, 0x19, 0x7a, 0xbe, + 0x2f, 0xa4, 0x89, 0x12, 0x55, 0x38, 0xda, 0x0e, 0x51, 0x29, 0x44, 0x3c, 0x16, 0x18, 0x92, 0x0c, + 0x89, 0x89, 0x66, 0xfb, 0x11, 0x16, 0x18, 0xb2, 0x3b, 0x62, 0x93, 0x2b, 0xcb, 0xb5, 0x8e, 0xb6, + 0x40, 0xcc, 0x07, 0xb1, 0x38, 0x48, 0x63, 0xe3, 0x94, 0x34, 0xce, 0x98, 0x28, 0xda, 0xfb, 0xb0, + 0x4e, 0x63, 0xe3, 0x94, 0xdd, 0x81, 0xf4, 0x4b, 0x6b, 0x48, 0xca, 0x67, 0x5c, 0x9a, 0x18, 0xa4, + 0xe7, 0xd4, 0x3c, 0x44, 0xd3, 0xbc, 0xf7, 0x1c, 0x93, 0xf4, 0xd0, 0x78, 0x2c, 0x77, 0x3c, 0xc7, + 0x7c, 0x4e, 0x63, 0x49, 0x48, 0xdc, 0xf2, 0x8d, 0xe9, 0x29, 0x4a, 0x23, 0x85, 0x6f, 0xce, 0xc6, + 0xf4, 0xb4, 0x65, 0xa2, 0xf0, 0x77, 0xcd, 0x97, 0xa4, 0x7d, 0xa6, 0x34, 0xfc, 0x44, 0xf3, 0x28, + 0xb0, 0x1c, 0x6b, 0x18, 0xda, 0x2f, 0xed, 0xf0, 0x8c, 0xf4, 0xcb, 0x94, 0x26, 0x83, 0xb6, 0x73, + 0x90, 0xb1, 0x4e, 0x27, 0xbe, 0xba, 0x0b, 0x79, 0x51, 0xca, 0x82, 0x8d, 0x75, 0x05, 0x0a, 0x76, + 0xa0, 0x0f, 0x3d, 0x37, 0x08, 0x85, 0xee, 0x94, 0xb7, 0x83, 0x3a, 0x26, 0x51, 0x5c, 0x9a, 0x46, + 0xc8, 0x37, 0xa1, 0xb2, 0x46, 0xdf, 0xea, 0x23, 0x80, 0x59, 0xb3, 0xb0, 0x4e, 0x8e, 0xe5, 0x46, + 0x6a, 0x9a, 0x63, 0xb9, 0x31, 0xcf, 0xaa, 0xc4, 0x73, 0x05, 0x8a, 0xb1, 0x66, 0xcc, 0xca, 0x90, + 0x32, 0xc4, 0xf6, 0x97, 0x32, 0xd4, 0x7b, 0xa8, 0xa8, 0x46, 0xba, 0x6f, 0x12, 0x87, 0xa9, 0x68, + 0x53, 0x4c, 0x0d, 0xd4, 0xef, 0x43, 0x59, 0xb3, 0x82, 0xa9, 0x13, 0xd6, 0x3d, 0xa7, 0x61, 0x8d, + 0xd8, 0xbb, 0x00, 0x71, 0x3a, 0x10, 0x5a, 0xca, 0x6c, 0xee, 0x36, 0xac, 0x91, 0x26, 0xe1, 0xd5, + 0xbf, 0x9d, 0x21, 0x7d, 0xaf, 0xc1, 0x15, 0x2d, 0xa1, 0x51, 0xa5, 0x24, 0x8d, 0x2a, 0xde, 0x1b, + 0x56, 0x93, 0x5a, 0xe5, 0x91, 0x6d, 0x9a, 0x96, 0x1b, 0x69, 0x8f, 0x3c, 0x85, 0x83, 0x6d, 0x38, + 0x87, 0xb4, 0xa0, 0x2a, 0x8f, 0x58, 0x54, 0xe8, 0x78, 0xe2, 0x5b, 0x41, 0xc0, 0xf5, 0x16, 0xc3, + 0x39, 0x8c, 0xd6, 0x76, 0xf6, 0x55, 0x6b, 0xfb, 0x0a, 0x14, 0x70, 0xcb, 0x23, 0xab, 0x2f, 0xc7, + 0x7b, 0x5f, 0x98, 0xb7, 0xec, 0x2d, 0xc8, 0x0b, 0x7d, 0x5d, 0x2c, 0x2a, 0x31, 0x5d, 0x1a, 0x1c, + 0xa8, 0x45, 0x58, 0x56, 0x45, 0x25, 0x6f, 0x3c, 0xb6, 0xdc, 0x30, 0xda, 0xa7, 0x45, 0x92, 0xbd, + 0x03, 0x45, 0xcf, 0xd5, 0xb9, 0x52, 0x2f, 0x56, 0x95, 0x98, 0xbe, 0x5d, 0xf7, 0x80, 0xa0, 0x5a, + 0xc1, 0x13, 0x5f, 0x58, 0x15, 0xc7, 0x3b, 0xd1, 0x87, 0x86, 0x6f, 0xd2, 0xca, 0x2a, 0x68, 0x79, + 0xc7, 0x3b, 0xa9, 0x1b, 0xbe, 0xc9, 0xf5, 0x96, 0xaf, 0xdc, 0xe9, 0x98, 0x56, 0xd3, 0x9a, 0x26, + 0x52, 0xec, 0x3a, 0x14, 0x87, 0xce, 0x34, 0x08, 0x2d, 0x7f, 0xfb, 0x8c, 0x9b, 0x69, 0xda, 0x0c, + 0x80, 0xf5, 0x9a, 0xf8, 0xf6, 0xd8, 0xf0, 0xcf, 0x68, 0xe9, 0x14, 0xb4, 0x28, 0x49, 0x1b, 0xcd, + 0xb1, 0x6d, 0x9e, 0x72, 0x5b, 0x4d, 0xe3, 0x09, 0xa4, 0x3f, 0x22, 0x4b, 0x3a, 0xa0, 0xf5, 0x51, + 0xd0, 0xa2, 0x24, 0x8d, 0x03, 0x7d, 0xd2, 0x8a, 0x28, 0x6a, 0x22, 0x95, 0x50, 0xba, 0x37, 0xce, + 0x55, 0xba, 0xd9, 0xbc, 0xde, 0xe3, 0xf9, 0xf6, 0xa1, 0x2d, 0xb4, 0x96, 0x0b, 0x5c, 0xef, 0xe1, + 0x20, 0xda, 0xa8, 0xbe, 0x82, 0xbc, 0xe8, 0x62, 0xdc, 0x81, 0x70, 0xf9, 0x24, 0xc5, 0x33, 0xdf, + 0x81, 0x10, 0xce, 0x6e, 0xc3, 0x9a, 0xc8, 0x2b, 0x08, 0x7d, 0xdb, 0x3d, 0x14, 0x93, 0xa7, 0xcc, + 0x81, 0x3d, 0x82, 0xa1, 0xa2, 0x80, 0xc3, 0xab, 0x1b, 0x03, 0xdb, 0xc1, 0x65, 0x9a, 0x16, 0x4a, + 0xcd, 0xd4, 0x71, 0x6a, 0x1c, 0xa4, 0x76, 0xa1, 0x10, 0x0d, 0xc8, 0x2f, 0xa5, 0x4c, 0xf5, 0x37, + 0x53, 0x50, 0x22, 0xf5, 0xa0, 0x4b, 0xca, 0x0f, 0x7b, 0x17, 0xd8, 0xd0, 0xb7, 0x8c, 0xd0, 0xd2, + 0xad, 0xd3, 0xd0, 0x37, 0x84, 0x12, 0xc0, 0x35, 0x09, 0x85, 0x63, 0x9a, 0x88, 0xe0, 0x7a, 0xc0, + 0x4d, 0x28, 0x4d, 0x0c, 0x3f, 0x88, 0x94, 0x4a, 0x5e, 0x00, 0x70, 0x90, 0x50, 0xe9, 0x14, 0xf7, + 0xd0, 0x37, 0xc6, 0x7a, 0xe8, 0x1d, 0x5b, 0x2e, 0x57, 0xa7, 0xb9, 0x21, 0x51, 0x21, 0x78, 0x1f, + 0xc1, 0xa4, 0x55, 0xff, 0xbb, 0x14, 0xac, 0xed, 0xf3, 0x51, 0x7f, 0x66, 0x9d, 0x35, 0xb8, 0xf5, + 0x36, 0x8c, 0x56, 0x6c, 0x46, 0xa3, 0x6f, 0x76, 0x03, 0x4a, 0x93, 0x63, 0xeb, 0x4c, 0x4f, 0x58, + 0x3a, 0x45, 0x04, 0xd5, 0x69, 0x6d, 0xbe, 0x0d, 0x39, 0x8f, 0x1a, 0x22, 0xf6, 0x38, 0xb1, 0x35, + 0x48, 0x2d, 0xd4, 0x04, 0x01, 0xaa, 0x4b, 0x71, 0x56, 0xb2, 0x5e, 0x26, 0x32, 0xa3, 0xea, 0x6f, + 0x42, 0x16, 0x51, 0x41, 0x35, 0xcb, 0xf5, 0x1c, 0x4a, 0xb0, 0xf7, 0x61, 0x6d, 0xe8, 0x8d, 0x27, + 0x7a, 0xc4, 0x2e, 0x76, 0xbb, 0xa4, 0x4c, 0x29, 0x21, 0xc9, 0x3e, 0xcf, 0x4b, 0xfd, 0xbd, 0x34, + 0x14, 0xa8, 0x0e, 0x42, 0xac, 0xd8, 0xe6, 0x69, 0x24, 0x56, 0x8a, 0x5a, 0xd6, 0x36, 0x51, 0x6a, + 0xbf, 0x46, 0x35, 0x8b, 0x55, 0xae, 0xb4, 0xac, 0x72, 0x5d, 0x82, 0x9c, 0xd0, 0xb7, 0x32, 0x5c, + 0xee, 0x4c, 0xcf, 0xd7, 0xb6, 0xb2, 0xcb, 0xb4, 0x2d, 0x1c, 0x42, 0x4e, 0x63, 0x9d, 0xe2, 0xfe, + 0xc6, 0x45, 0x0b, 0x10, 0xa8, 0x89, 0x10, 0x59, 0x68, 0xe4, 0x93, 0x42, 0xa3, 0x0a, 0xf9, 0x97, + 0x76, 0x60, 0xe3, 0x04, 0x29, 0xf0, 0x65, 0x28, 0x92, 0xd2, 0x30, 0x14, 0x5f, 0x37, 0x0c, 0x71, + 0xb3, 0x0d, 0xe7, 0x90, 0xab, 0xfd, 0x51, 0xb3, 0x6b, 0xce, 0xa1, 0xc7, 0x3e, 0x80, 0x8b, 0x33, + 0xb4, 0x68, 0x0d, 0xb9, 0xc7, 0xc8, 0x03, 0xa4, 0xb1, 0x98, 0x92, 0x5a, 0x44, 0x76, 0xd9, 0x7d, + 0xd8, 0x90, 0x58, 0x26, 0xa8, 0xde, 0x04, 0x24, 0x73, 0x8a, 0xda, 0x7a, 0x4c, 0x4e, 0x5a, 0x4f, + 0xa0, 0xfe, 0x93, 0x55, 0x58, 0xdb, 0xf1, 0x7c, 0xcb, 0x3e, 0x74, 0x67, 0xb3, 0x6e, 0x41, 0xf3, + 0x8f, 0x66, 0xe2, 0xaa, 0x34, 0x13, 0x6f, 0x42, 0x69, 0xc4, 0x19, 0xf5, 0x70, 0xc0, 0x9d, 0x06, + 0x19, 0x0d, 0x04, 0xa8, 0x3f, 0x70, 0x70, 0x35, 0x47, 0x04, 0xc4, 0x9c, 0x21, 0xe6, 0x88, 0x09, + 0xf7, 0x1a, 0xf6, 0x3d, 0x92, 0xba, 0xa6, 0xe5, 0x58, 0x21, 0x1f, 0x9e, 0xca, 0xa3, 0x37, 0xa2, + 0x9d, 0x5e, 0xaa, 0xd3, 0x03, 0xcd, 0x1a, 0xd5, 0x48, 0x3d, 0x42, 0x21, 0xdc, 0x20, 0x72, 0xc1, + 0x2b, 0x24, 0x76, 0xee, 0x1b, 0xf2, 0x72, 0xc9, 0xa1, 0xf6, 0xa1, 0x18, 0x83, 0x51, 0xd7, 0xd5, + 0x9a, 0x42, 0xbf, 0x5d, 0x61, 0x25, 0xc8, 0xd7, 0x6b, 0xbd, 0x7a, 0xad, 0xd1, 0x54, 0x52, 0x88, + 0xea, 0x35, 0xfb, 0x5c, 0xa7, 0x5d, 0x65, 0xeb, 0x50, 0xc2, 0x54, 0xa3, 0xb9, 0x53, 0x3b, 0x68, + 0xf7, 0x95, 0x34, 0x5b, 0x83, 0x62, 0xa7, 0xab, 0xd7, 0xea, 0xfd, 0x56, 0xb7, 0xa3, 0x64, 0xd4, + 0x1f, 0x41, 0xa1, 0x7e, 0x64, 0x0d, 0x8f, 0xcf, 0xeb, 0x45, 0x32, 0xba, 0xad, 0xe1, 0xb1, 0xd0, + 0x4f, 0xe7, 0x8c, 0x6e, 0x6b, 0x78, 0xac, 0x36, 0xa1, 0xb8, 0x6f, 0xf8, 0xa1, 0x4d, 0xf5, 0x7a, + 0x02, 0x6b, 0x71, 0xa2, 0x61, 0x8d, 0xa2, 0x9d, 0x9b, 0xc5, 0x5a, 0x6b, 0x8c, 0xd2, 0x92, 0x84, + 0xea, 0xbb, 0x50, 0x96, 0x01, 0xec, 0x3a, 0xa4, 0x4d, 0x6b, 0xb4, 0x44, 0x4e, 0x22, 0x58, 0x7d, + 0x0e, 0xe5, 0x7a, 0xb4, 0x13, 0x9d, 0x57, 0xf5, 0x47, 0x50, 0xa1, 0x15, 0x3f, 0x1c, 0x44, 0x4b, + 0x7e, 0x75, 0xc9, 0x92, 0x2f, 0x23, 0x4d, 0x7d, 0x20, 0xd6, 0xfc, 0x47, 0x50, 0xda, 0xf7, 0xbd, + 0x89, 0xe5, 0x87, 0x94, 0xad, 0x02, 0xe9, 0x63, 0xeb, 0x4c, 0xe4, 0x8a, 0x9f, 0x33, 0x5f, 0xc8, + 0xaa, 0xec, 0x0b, 0x79, 0x04, 0x85, 0x88, 0xed, 0x1b, 0xf3, 0xfc, 0x10, 0x45, 0x27, 0xf1, 0xd8, + 0x56, 0x80, 0x85, 0x3d, 0x00, 0x98, 0xc4, 0x00, 0xd1, 0x71, 0x91, 0xba, 0x2f, 0x32, 0xd7, 0x24, + 0x0a, 0xf5, 0x0d, 0xc8, 0x3f, 0xb7, 0xad, 0x13, 0xd1, 0xfc, 0x97, 0xb6, 0x75, 0x12, 0x35, 0x1f, + 0xbf, 0xd5, 0xbf, 0x5c, 0x84, 0x02, 0xad, 0xaf, 0xc6, 0xf9, 0xee, 0xa7, 0x6f, 0xa3, 0x15, 0x6d, + 0x89, 0xf5, 0x94, 0x59, 0xa2, 0x8b, 0xf1, 0xd5, 0xf5, 0x06, 0x80, 0xb4, 0xd6, 0xb9, 0xe4, 0x2a, + 0x86, 0xf1, 0x12, 0x47, 0x75, 0x82, 0xf6, 0xa2, 0xe0, 0x2b, 0x47, 0x58, 0x91, 0x33, 0x00, 0x7b, + 0xc0, 0x37, 0x7b, 0xb2, 0x1b, 0xb9, 0x42, 0x74, 0x21, 0x52, 0xea, 0x07, 0x8e, 0x15, 0x99, 0x1a, + 0xa4, 0x01, 0x60, 0x82, 0xe4, 0x98, 0xe5, 0x07, 0x28, 0xae, 0xc8, 0x3f, 0xad, 0x45, 0x49, 0xf6, + 0x16, 0x64, 0x50, 0xc8, 0x0b, 0xd3, 0xe0, 0x42, 0xd4, 0x83, 0xd2, 0x2e, 0xa5, 0x11, 0x01, 0xbb, + 0x07, 0x79, 0x12, 0x2d, 0x16, 0x4a, 0x1a, 0xa9, 0xb7, 0x23, 0xa1, 0xaf, 0x45, 0x68, 0xf6, 0x36, + 0x64, 0x47, 0xc7, 0xd6, 0x59, 0x50, 0x5d, 0x23, 0xba, 0x0b, 0x4b, 0xd6, 0xac, 0xc6, 0x29, 0xd8, + 0x1d, 0xa8, 0xf8, 0xd6, 0x48, 0x27, 0x87, 0x14, 0x0a, 0x99, 0xa0, 0x5a, 0x21, 0x19, 0x52, 0xf6, + 0xad, 0x51, 0x1d, 0x81, 0xfd, 0x81, 0x13, 0xb0, 0xbb, 0x90, 0xa3, 0xd5, 0x83, 0xba, 0x90, 0x54, + 0x72, 0xb4, 0x14, 0x35, 0x81, 0x65, 0x1f, 0x00, 0x08, 0x8d, 0x4b, 0x1f, 0x9c, 0x91, 0x23, 0x37, + 0x5e, 0x4c, 0xf2, 0xfc, 0x97, 0xf5, 0xb2, 0xb7, 0x20, 0x8b, 0x93, 0x24, 0xa8, 0x5e, 0xa6, 0x9c, + 0x37, 0x92, 0x33, 0x88, 0x6a, 0x4a, 0x78, 0x76, 0x0f, 0x0a, 0x38, 0x51, 0x74, 0x1c, 0x8e, 0xaa, + 0xac, 0x82, 0x8a, 0x59, 0x85, 0x3b, 0x83, 0x75, 0xd2, 0xfb, 0xca, 0x61, 0xf7, 0x21, 0x63, 0xe2, + 0x62, 0xbe, 0x42, 0x39, 0x5e, 0x92, 0xc6, 0x05, 0x85, 0x55, 0xc3, 0x1a, 0x91, 0x56, 0x4c, 0x34, + 0x6c, 0x17, 0x2a, 0x38, 0x8d, 0x1e, 0xd1, 0x66, 0x8f, 0xdd, 0x57, 0xbd, 0x4a, 0x5c, 0xb7, 0xe6, + 0xb8, 0x3a, 0x82, 0x88, 0x3a, 0xbb, 0xe9, 0x86, 0xfe, 0x99, 0xb6, 0xe6, 0xca, 0x30, 0x76, 0x15, + 0x4d, 0x97, 0xb6, 0x37, 0x3c, 0xb6, 0xcc, 0xea, 0xb5, 0xc8, 0x31, 0xc1, 0xd3, 0xec, 0x53, 0x58, + 0xa3, 0x89, 0x85, 0x49, 0x2c, 0xbc, 0x7a, 0x9d, 0x84, 0xa9, 0x3c, 0x65, 0x22, 0x94, 0x96, 0xa4, + 0x44, 0x11, 0x6f, 0x07, 0x7a, 0x68, 0x8d, 0x27, 0x9e, 0x8f, 0xca, 0xeb, 0x1b, 0x91, 0xc3, 0xa5, + 0x1f, 0x81, 0x70, 0x23, 0x8e, 0x8f, 0x9d, 0x74, 0x6f, 0x34, 0x0a, 0xac, 0xb0, 0x7a, 0x83, 0xd6, + 0x4d, 0x25, 0x3a, 0x7d, 0xea, 0x12, 0x94, 0x36, 0xc2, 0x40, 0x37, 0xcf, 0x5c, 0x63, 0x6c, 0x0f, + 0xab, 0x37, 0xb9, 0x8e, 0x6c, 0x07, 0x0d, 0x0e, 0x90, 0xd5, 0xd4, 0xad, 0x84, 0x9a, 0x7a, 0x01, + 0xb2, 0xe6, 0x00, 0x97, 0xe3, 0x2d, 0xca, 0x36, 0x63, 0x0e, 0x5a, 0x26, 0x7b, 0x0f, 0x8a, 0x93, + 0x48, 0x04, 0x56, 0x55, 0xd9, 0x18, 0x8f, 0x25, 0xa3, 0x36, 0xa3, 0x40, 0xfb, 0x70, 0xc7, 0x32, + 0xc2, 0xa9, 0x6f, 0xed, 0x38, 0xc6, 0x61, 0xf5, 0x36, 0xe5, 0x24, 0x83, 0xae, 0x3e, 0x25, 0x5d, + 0x97, 0x5a, 0xfd, 0xd1, 0x9c, 0x70, 0x49, 0x2c, 0x0d, 0x49, 0x0a, 0xed, 0xae, 0xc8, 0x32, 0x66, + 0x3b, 0x4b, 0x52, 0xf8, 0xea, 0x8f, 0x80, 0x2d, 0x8e, 0xd7, 0xeb, 0x24, 0x5d, 0x56, 0x48, 0xba, + 0xef, 0xad, 0x3e, 0x49, 0xa9, 0xcf, 0x61, 0x2d, 0xb1, 0x90, 0x97, 0x4a, 0x6c, 0xae, 0x2e, 0x19, + 0x63, 0x61, 0x5e, 0xf2, 0x84, 0xf0, 0x50, 0x05, 0xb6, 0x7b, 0x28, 0x3c, 0x5b, 0x34, 0x11, 0x7a, + 0x94, 0x56, 0xff, 0x2c, 0x0d, 0xe5, 0x5d, 0x23, 0x38, 0xda, 0x33, 0x26, 0xbd, 0xd0, 0x08, 0x03, + 0x1c, 0xde, 0x23, 0x23, 0x38, 0x1a, 0x1b, 0x13, 0xae, 0xb8, 0xa6, 0xb8, 0xd9, 0x2c, 0x60, 0xa8, + 0xb5, 0xe2, 0xc4, 0xc2, 0x64, 0xd7, 0xdd, 0x7f, 0x26, 0x6c, 0xe2, 0x38, 0x8d, 0x62, 0x25, 0x38, + 0x9a, 0x8e, 0x46, 0x71, 0x51, 0x51, 0x92, 0xdd, 0x81, 0x35, 0xf1, 0x49, 0x5a, 0xeb, 0xa9, 0x38, + 0x76, 0x4c, 0x02, 0xd9, 0x63, 0x28, 0x09, 0x40, 0x3f, 0x12, 0x82, 0x95, 0xd8, 0xd7, 0x31, 0x43, + 0x68, 0x32, 0x15, 0xfb, 0x31, 0x5c, 0x94, 0x92, 0x3b, 0x9e, 0xbf, 0x37, 0x75, 0x42, 0xbb, 0xde, + 0x11, 0x2a, 0xc2, 0xb5, 0x05, 0xf6, 0x19, 0x89, 0xb6, 0x9c, 0x33, 0x59, 0xdb, 0x3d, 0xdb, 0x25, + 0x99, 0x9a, 0xd6, 0x92, 0xc0, 0x39, 0x2a, 0xe3, 0x94, 0x44, 0x69, 0x92, 0xca, 0x38, 0xc5, 0xc5, + 0x26, 0x00, 0x7b, 0x56, 0x78, 0xe4, 0x99, 0xa4, 0x1f, 0xc6, 0x8b, 0xad, 0x27, 0xa3, 0xb4, 0x24, + 0x25, 0x76, 0x27, 0x5a, 0x42, 0x43, 0x37, 0x24, 0x2d, 0x31, 0xad, 0x45, 0x49, 0xdc, 0x66, 0x7c, + 0xc3, 0x3d, 0xb4, 0x82, 0x6a, 0x69, 0x2b, 0x7d, 0x2f, 0xa5, 0x89, 0x94, 0xfa, 0x37, 0x57, 0x21, + 0xcb, 0x47, 0xf2, 0x1a, 0x14, 0x07, 0xe4, 0x2c, 0x46, 0xcb, 0x54, 0x38, 0x80, 0x09, 0xd0, 0x99, + 0x8e, 0xb9, 0x76, 0x27, 0x7c, 0x1a, 0x29, 0x8d, 0xbe, 0x31, 0x4b, 0x6f, 0x1a, 0x62, 0x59, 0x69, + 0x82, 0x8a, 0x14, 0x56, 0xc2, 0xf7, 0x4e, 0x68, 0x36, 0x64, 0x08, 0x11, 0x25, 0xc9, 0xc7, 0x4c, + 0x3b, 0x16, 0x32, 0x65, 0x09, 0x57, 0x20, 0x40, 0xdd, 0x0d, 0xe7, 0xfd, 0x2f, 0xb9, 0x05, 0xff, + 0x0b, 0xbb, 0x01, 0xa8, 0x3b, 0x0e, 0xad, 0xae, 0x6b, 0xd5, 0x3b, 0xd4, 0xc3, 0x05, 0x4d, 0x82, + 0xe0, 0x02, 0x31, 0xbd, 0x09, 0x75, 0x6a, 0x56, 0xc3, 0x4f, 0xf6, 0x71, 0x3c, 0x3b, 0xa9, 0x8d, + 0x42, 0xd3, 0x16, 0x12, 0x5d, 0x9e, 0xc7, 0x5a, 0x82, 0x0e, 0x73, 0x42, 0x31, 0xcd, 0x35, 0x6d, + 0xfc, 0x54, 0x9b, 0x00, 0x9a, 0x77, 0x12, 0x58, 0x21, 0x39, 0x1a, 0x2f, 0x53, 0x13, 0x13, 0x47, + 0x44, 0xde, 0xc9, 0xbe, 0x17, 0xc4, 0xf6, 0xe6, 0xea, 0x72, 0x7b, 0x53, 0x7d, 0x08, 0x79, 0xdc, + 0xc3, 0x8d, 0xd0, 0x60, 0x77, 0x84, 0x6f, 0x87, 0x6b, 0x1e, 0xc2, 0xc9, 0x35, 0x2b, 0x43, 0x78, + 0x7b, 0xda, 0x51, 0xb9, 0xc4, 0x73, 0x4b, 0x32, 0xf7, 0xe2, 0xfd, 0x43, 0x64, 0x28, 0xb4, 0x82, + 0x6b, 0x50, 0xc4, 0xaa, 0x91, 0xdf, 0x5c, 0xc8, 0x85, 0x82, 0xef, 0x9d, 0xd4, 0x31, 0xad, 0xfe, + 0xfb, 0x14, 0x94, 0xba, 0xbe, 0x89, 0x1b, 0x57, 0x6f, 0x62, 0x0d, 0x5f, 0x6b, 0x1e, 0xa3, 0x0e, + 0xe1, 0x39, 0x8e, 0x41, 0x22, 0x52, 0x98, 0x5b, 0x31, 0x80, 0x7d, 0x00, 0x99, 0x11, 0x8a, 0xc2, + 0xb4, 0xac, 0x59, 0x4b, 0xd9, 0x47, 0xdf, 0x28, 0x1c, 0x35, 0x22, 0x55, 0x7f, 0x2d, 0x2e, 0x9f, + 0xfc, 0xcc, 0xb2, 0x77, 0x79, 0x85, 0xce, 0x79, 0x7a, 0x75, 0x25, 0xc5, 0x0a, 0x90, 0x69, 0x34, + 0x7b, 0x75, 0xae, 0x4f, 0xa3, 0x66, 0xdd, 0xd3, 0x77, 0x5a, 0x5a, 0xaf, 0xaf, 0x64, 0xe8, 0xe0, + 0x88, 0x00, 0xed, 0x5a, 0xaf, 0xaf, 0x14, 0x18, 0x40, 0xee, 0xa0, 0xd3, 0xfa, 0xf1, 0x41, 0x53, + 0x51, 0xd4, 0x7f, 0x95, 0x02, 0x98, 0x39, 0x41, 0xd9, 0x3b, 0x50, 0x3a, 0xa1, 0x94, 0x2e, 0x79, + 0xc7, 0xe5, 0x36, 0x02, 0x47, 0x93, 0x7e, 0xf3, 0x1e, 0x94, 0x63, 0x51, 0x8f, 0x7b, 0xff, 0xa2, + 0x9b, 0xbc, 0x14, 0xe3, 0xb7, 0xcf, 0xd8, 0xbb, 0x50, 0xf0, 0xb0, 0x1d, 0x48, 0x9a, 0x96, 0x37, + 0x7e, 0xa9, 0xf9, 0x5a, 0xde, 0xe3, 0x09, 0xd4, 0x11, 0x46, 0x7e, 0x64, 0x3e, 0xc7, 0xa4, 0x3b, + 0x08, 0xaa, 0x3b, 0xc6, 0x34, 0xb0, 0x34, 0x8e, 0x8f, 0xa5, 0x74, 0x76, 0x26, 0xa5, 0xd5, 0x9f, + 0x40, 0xa5, 0x67, 0x8c, 0x27, 0x5c, 0x96, 0x53, 0xc3, 0x18, 0x64, 0x70, 0x4e, 0x88, 0xa9, 0x47, + 0xdf, 0xb8, 0xe8, 0xf6, 0x2d, 0x7f, 0x68, 0xb9, 0xd1, 0x1a, 0x8d, 0x92, 0x28, 0x7e, 0x0f, 0x50, + 0x9a, 0x6b, 0xde, 0x49, 0x24, 0xce, 0xa3, 0xb4, 0xfa, 0x87, 0x29, 0x28, 0x49, 0xd5, 0x60, 0x0f, + 0x21, 0x43, 0xca, 0x64, 0x4a, 0x16, 0x84, 0x12, 0x01, 0xff, 0xe6, 0xea, 0x07, 0x12, 0xb2, 0xbb, + 0x90, 0x0d, 0x42, 0xc3, 0x8f, 0xfc, 0xe9, 0x8a, 0xc4, 0xb1, 0xed, 0x4d, 0x5d, 0x53, 0xe3, 0x68, + 0xa6, 0x42, 0xda, 0x72, 0x4d, 0xe1, 0x70, 0x58, 0xa4, 0x42, 0xa4, 0xba, 0x05, 0xc5, 0x38, 0x7b, + 0x9c, 0x02, 0x5a, 0xf7, 0x45, 0x4f, 0x59, 0x61, 0x45, 0xc8, 0x6a, 0xb5, 0xce, 0xd3, 0xa6, 0x92, + 0x52, 0xff, 0x38, 0x05, 0x30, 0xe3, 0x62, 0x0f, 0x12, 0xb5, 0xbd, 0x3a, 0x9f, 0xeb, 0x03, 0xfa, + 0x2b, 0x55, 0xf6, 0x3a, 0x14, 0xa7, 0x2e, 0x01, 0x2d, 0x53, 0xec, 0x44, 0x33, 0x00, 0x5a, 0x40, + 0x51, 0xf4, 0xc7, 0x9c, 0x05, 0xf4, 0xd2, 0x70, 0xd4, 0xef, 0x41, 0x31, 0xce, 0x0e, 0x8d, 0xba, + 0x9d, 0x6e, 0xbb, 0xdd, 0x7d, 0xd1, 0xea, 0x3c, 0x55, 0x56, 0x30, 0xb9, 0xaf, 0x35, 0xeb, 0xcd, + 0x06, 0x26, 0x53, 0x38, 0x67, 0xeb, 0x07, 0x9a, 0xd6, 0xec, 0xf4, 0x75, 0xad, 0xfb, 0x42, 0x59, + 0x55, 0xff, 0xff, 0x0c, 0x6c, 0x74, 0xdd, 0xc6, 0x74, 0xe2, 0xd8, 0x43, 0x23, 0xb4, 0x9e, 0x59, + 0x67, 0xf5, 0xf0, 0x14, 0x77, 0x5f, 0x23, 0x0c, 0x7d, 0xbe, 0x98, 0x8b, 0x1a, 0x4f, 0x70, 0xa7, + 0x44, 0x60, 0xf9, 0x21, 0xf9, 0x5c, 0xe4, 0x55, 0x5c, 0xe1, 0xf0, 0xba, 0xe7, 0xd0, 0x5a, 0x66, + 0x3f, 0x80, 0x8b, 0xdc, 0x91, 0xc1, 0x29, 0x51, 0x81, 0xd5, 0x69, 0x31, 0xa7, 0x17, 0xa6, 0x2e, + 0xe3, 0x84, 0xc8, 0x8a, 0x64, 0x24, 0xc2, 0x6e, 0x42, 0x69, 0xc6, 0x1e, 0x1d, 0x52, 0x41, 0x4c, + 0x48, 0x35, 0x41, 0xc3, 0x3b, 0xaa, 0xb5, 0x6e, 0x9b, 0xa7, 0xe4, 0xe2, 0xc9, 0x6a, 0x15, 0x6f, + 0xd6, 0x18, 0xdc, 0x84, 0x3f, 0x87, 0x8d, 0x04, 0x25, 0xd5, 0x22, 0x47, 0xb5, 0x78, 0x37, 0x72, + 0x90, 0xce, 0xb5, 0x5e, 0x86, 0x60, 0x75, 0xb8, 0x46, 0xba, 0xee, 0x25, 0xa1, 0x42, 0x17, 0xb1, + 0x0f, 0x5d, 0xcf, 0xb7, 0x84, 0xc0, 0x2f, 0xd8, 0x41, 0x8b, 0xd2, 0x33, 0xfb, 0x47, 0x3a, 0x54, + 0xe5, 0xfb, 0x4b, 0x74, 0x5e, 0xc8, 0xd1, 0x36, 0xdf, 0x41, 0x33, 0x5a, 0x9e, 0xd2, 0x2d, 0x93, + 0xdd, 0x16, 0xea, 0xac, 0x1e, 0x99, 0x34, 0x40, 0x26, 0x4d, 0x99, 0x80, 0xcf, 0x39, 0xec, 0x6a, + 0x07, 0x36, 0x97, 0x55, 0x72, 0x89, 0x1a, 0xb6, 0x25, 0xab, 0x61, 0x73, 0x46, 0xfb, 0x4c, 0x25, + 0xfb, 0xbb, 0x29, 0x28, 0x37, 0x2c, 0x73, 0x3a, 0xf9, 0xcc, 0xb3, 0x5d, 0x9c, 0x00, 0x1f, 0x42, + 0xd9, 0x73, 0x4c, 0x1a, 0x3d, 0x29, 0x36, 0x20, 0x71, 0x62, 0x24, 0x9c, 0xdb, 0xe0, 0x39, 0x66, + 0xdd, 0x73, 0x28, 0x92, 0xe0, 0x3d, 0xb8, 0xc0, 0x1d, 0x1a, 0xc2, 0xbf, 0x77, 0xca, 0x99, 0x57, + 0x69, 0x64, 0x14, 0x8e, 0xe2, 0xca, 0x11, 0x91, 0xff, 0x0a, 0x6c, 0x4a, 0xe4, 0x38, 0x32, 0x9c, + 0x7e, 0x71, 0x92, 0x6c, 0xc4, 0xbc, 0xd1, 0x91, 0x8d, 0xfa, 0x5b, 0xab, 0x50, 0xe4, 0xee, 0x10, + 0xac, 0xef, 0x3d, 0xc8, 0x7b, 0x83, 0x2f, 0x75, 0x3f, 0x76, 0x13, 0x2c, 0x9c, 0x34, 0xe6, 0xbc, + 0xc1, 0x97, 0x9a, 0x35, 0x62, 0xef, 0x44, 0xfb, 0xbc, 0x69, 0x8d, 0x44, 0xa7, 0x54, 0x92, 0xf6, + 0x88, 0xd8, 0xf7, 0xd1, 0x56, 0x7e, 0x0c, 0xa5, 0xd9, 0x8c, 0x0f, 0xaa, 0xf9, 0xf3, 0x7b, 0x21, + 0x5e, 0x00, 0x01, 0x32, 0x71, 0x97, 0x10, 0x67, 0x2a, 0x9c, 0xcf, 0xc4, 0xc9, 0x88, 0xe9, 0x53, + 0xa8, 0xcc, 0x64, 0x3c, 0xf1, 0x15, 0xcf, 0xe5, 0x5b, 0x8b, 0x29, 0xe9, 0xc4, 0xe3, 0xef, 0xa5, + 0xa0, 0xd8, 0xe2, 0xc5, 0x87, 0xa7, 0xec, 0x16, 0xa4, 0x5f, 0xd1, 0x0b, 0x88, 0x63, 0xf7, 0x61, + 0xc3, 0x30, 0x4d, 0xdd, 0x18, 0x8d, 0xac, 0x61, 0x68, 0x99, 0x3a, 0xaa, 0x40, 0x42, 0xe6, 0xac, + 0x1b, 0xa6, 0x59, 0x13, 0x70, 0x92, 0xdd, 0xb8, 0xe6, 0x03, 0x3d, 0x32, 0x3c, 0x67, 0x47, 0xca, + 0x05, 0xad, 0x62, 0x07, 0xc2, 0xee, 0xe4, 0xbe, 0xe4, 0x44, 0xc7, 0x66, 0x5e, 0xdd, 0xb1, 0xea, + 0xef, 0xae, 0x02, 0x68, 0xd6, 0xc4, 0x31, 0x86, 0xd6, 0xff, 0x35, 0x95, 0x46, 0xb1, 0x14, 0x0f, + 0xac, 0x6b, 0x46, 0x21, 0x18, 0xd1, 0x20, 0xba, 0x26, 0xfb, 0x11, 0xbc, 0xe1, 0x5b, 0x27, 0xbe, + 0x1d, 0x5a, 0xfa, 0xc8, 0xf7, 0xc6, 0x7a, 0x42, 0xf2, 0xe0, 0xc2, 0x2c, 0x52, 0x25, 0xae, 0x08, + 0xa2, 0x1d, 0xdf, 0x1b, 0x27, 0xa5, 0x8f, 0xfa, 0x87, 0x25, 0x28, 0xd5, 0x5c, 0xc3, 0x39, 0xfb, + 0xda, 0xa2, 0x98, 0x00, 0xf2, 0xae, 0x4e, 0xa6, 0x21, 0x6f, 0x2e, 0x3f, 0x30, 0x2b, 0x12, 0x84, + 0x1a, 0x7a, 0x13, 0x4a, 0xde, 0x34, 0x8c, 0xf1, 0xfc, 0x08, 0x0d, 0x38, 0x88, 0x08, 0x62, 0xfe, + 0xd8, 0x73, 0x1f, 0xf1, 0x93, 0xf9, 0x33, 0xe3, 0x8f, 0x55, 0xe2, 0x98, 0x9f, 0x08, 0x50, 0x1a, + 0xd9, 0x63, 0x6a, 0x70, 0x30, 0x1d, 0x5b, 0xbc, 0xd1, 0x69, 0x1e, 0x9f, 0x56, 0x17, 0x30, 0xcc, + 0x65, 0x6c, 0x8d, 0x3d, 0xff, 0x8c, 0xe7, 0x92, 0xe3, 0xb9, 0x70, 0x10, 0xe5, 0xf2, 0x2e, 0xb0, + 0x13, 0xc3, 0x0e, 0xf5, 0x64, 0x56, 0xdc, 0x0c, 0x51, 0x10, 0xd3, 0x97, 0xb3, 0xbb, 0x04, 0x39, + 0xd3, 0x0e, 0x8e, 0x5b, 0x5d, 0x61, 0x82, 0x88, 0x14, 0xb6, 0x25, 0x18, 0x1a, 0xa8, 0x01, 0x85, + 0x16, 0x57, 0x97, 0xd3, 0x5a, 0x11, 0x21, 0xdb, 0x08, 0xc0, 0x1d, 0xd4, 0xb5, 0xc2, 0x13, 0xcf, + 0x47, 0x4e, 0x6e, 0x61, 0xcc, 0x00, 0xa8, 0x69, 0x20, 0x29, 0x16, 0x44, 0xde, 0xa0, 0xb4, 0x16, + 0xa7, 0x51, 0x77, 0xe7, 0xcb, 0x97, 0xb0, 0x65, 0x5e, 0xfd, 0x19, 0x84, 0xdd, 0x81, 0x0a, 0x55, + 0x9f, 0x2c, 0x10, 0x6c, 0x03, 0x9d, 0x72, 0xa5, 0xb5, 0x32, 0x42, 0xc9, 0x99, 0x80, 0x54, 0x9f, + 0xc2, 0x95, 0x44, 0xfb, 0x74, 0xc3, 0xf7, 0x8d, 0x33, 0x7d, 0x6c, 0x7c, 0xe9, 0xf9, 0xe4, 0xf8, + 0x49, 0x6b, 0x97, 0xe4, 0x6e, 0xab, 0x21, 0x7a, 0x0f, 0xb1, 0xe7, 0xb2, 0xda, 0xae, 0xe7, 0x93, + 0x57, 0x68, 0x29, 0x2b, 0x62, 0xc9, 0x85, 0x41, 0x03, 0x4c, 0xe6, 0x50, 0xc0, 0xe3, 0x1a, 0xb5, + 0x12, 0xc1, 0xb6, 0x09, 0x84, 0x06, 0x41, 0xf0, 0x98, 0x4b, 0xd6, 0x0d, 0x11, 0x64, 0xf4, 0x98, + 0xe4, 0x2f, 0x47, 0x1c, 0x59, 0x86, 0x49, 0x27, 0x67, 0x84, 0xd8, 0xb5, 0x0c, 0x3a, 0x97, 0x0e, + 0x1e, 0xeb, 0x93, 0x69, 0xc8, 0x03, 0x12, 0xb5, 0x6c, 0xf0, 0x78, 0x7f, 0x1a, 0x0a, 0xf0, 0xa1, + 0x15, 0x52, 0x18, 0x22, 0x81, 0x9f, 0x5a, 0x21, 0x6e, 0x84, 0xc1, 0xe3, 0xc8, 0x0b, 0x7e, 0x51, + 0xf4, 0xed, 0x63, 0xe1, 0xe6, 0x56, 0x61, 0x2d, 0x46, 0xea, 0xe3, 0x29, 0x8f, 0x40, 0x4c, 0x6b, + 0xa5, 0x88, 0x60, 0x6f, 0xea, 0xe0, 0xc0, 0x0e, 0x8d, 0xe1, 0x91, 0xa5, 0xfb, 0x58, 0x95, 0xcb, + 0x7c, 0xe8, 0x08, 0xa2, 0x61, 0x6d, 0xae, 0x01, 0x4f, 0xe8, 0x47, 0x76, 0x48, 0xde, 0xa9, 0xb4, + 0x56, 0x20, 0xc0, 0xae, 0x1d, 0xa2, 0x58, 0xe0, 0x48, 0x31, 0x03, 0x29, 0x8b, 0x2b, 0x44, 0xb4, + 0x4e, 0x88, 0x3d, 0x82, 0x53, 0x46, 0xf7, 0x40, 0x49, 0xd0, 0x62, 0x7e, 0x57, 0x89, 0xb4, 0x22, + 0x91, 0x62, 0xae, 0x77, 0x81, 0x33, 0xeb, 0x38, 0xf5, 0x78, 0x9e, 0xd7, 0xb8, 0x39, 0x4c, 0xe0, + 0x86, 0x1d, 0x1c, 0x53, 0x8e, 0x77, 0xa0, 0x22, 0xd1, 0x61, 0x7e, 0xd7, 0xf9, 0xcc, 0x88, 0xc9, + 0x12, 0x75, 0xf4, 0xad, 0xb1, 0x17, 0x8a, 0x66, 0xbe, 0x21, 0xd5, 0x51, 0x23, 0x78, 0xb2, 0x8e, + 0x82, 0x16, 0xf3, 0xbc, 0x21, 0xd5, 0x91, 0x93, 0x62, 0xae, 0xb7, 0xa0, 0x8c, 0x52, 0x24, 0xb4, + 0x5c, 0xbe, 0xf8, 0x6f, 0xf2, 0x8e, 0x15, 0x30, 0x5a, 0xfd, 0xb7, 0xa0, 0xcc, 0x7b, 0x5e, 0x88, + 0xcb, 0x2d, 0x4e, 0x22, 0x60, 0x91, 0x80, 0x10, 0xbd, 0x31, 0xb6, 0x5d, 0x72, 0x41, 0xa5, 0xb5, + 0x22, 0x87, 0xec, 0xd9, 0xae, 0x8c, 0x36, 0x4e, 0xc9, 0x11, 0x35, 0x43, 0x1b, 0xa7, 0xb4, 0x24, + 0x27, 0xb6, 0xe3, 0xf0, 0x85, 0x7f, 0x5b, 0x2c, 0x49, 0x84, 0xf4, 0x84, 0x4d, 0xcd, 0xd1, 0x98, + 0xf7, 0x1d, 0x31, 0x33, 0x10, 0x80, 0x59, 0xcf, 0x90, 0xc6, 0x69, 0xf5, 0x4d, 0x19, 0x69, 0x9c, + 0x0a, 0xc1, 0x84, 0x95, 0x26, 0xde, 0xbb, 0xb1, 0x60, 0x42, 0x10, 0x72, 0xcb, 0x04, 0xc6, 0x69, + 0xf5, 0xad, 0x24, 0x81, 0x71, 0x4a, 0xb6, 0xa6, 0x65, 0x98, 0xbc, 0x66, 0xf7, 0x78, 0xf6, 0x08, + 0xa0, 0x8a, 0x6d, 0x41, 0x39, 0x78, 0xac, 0xcf, 0xf0, 0x6f, 0x73, 0xf6, 0xe0, 0xb1, 0x16, 0x51, + 0xdc, 0x81, 0x4a, 0x3c, 0xf6, 0x9c, 0xe6, 0x3e, 0x1f, 0x59, 0x53, 0x8c, 0x3d, 0x1d, 0x7a, 0xfe, + 0x34, 0x05, 0x57, 0xbb, 0x74, 0x1c, 0x4b, 0xdb, 0xc5, 0x9e, 0x15, 0x04, 0xc6, 0xa1, 0xb5, 0xe3, + 0xf9, 0x3b, 0xd3, 0xaf, 0xbf, 0x3e, 0x63, 0xf7, 0x60, 0x7d, 0xdf, 0xf0, 0x2d, 0x37, 0x8c, 0x8f, + 0xeb, 0x84, 0x6a, 0x36, 0x0f, 0x66, 0x4f, 0x40, 0xe1, 0xa0, 0x83, 0x58, 0xc9, 0x15, 0x66, 0x5e, + 0xd2, 0xbb, 0xbe, 0x40, 0xa5, 0xfe, 0x91, 0x0a, 0x99, 0x8e, 0x67, 0x5a, 0xec, 0x7d, 0x28, 0x52, + 0xf0, 0xa4, 0x64, 0x76, 0x08, 0xb7, 0x0c, 0xa2, 0xe9, 0x0f, 0xd9, 0x1b, 0x05, 0x57, 0x7c, 0x9d, + 0x1f, 0x6e, 0x79, 0x8b, 0x2c, 0x27, 0x3a, 0xab, 0xc4, 0x1d, 0xb1, 0x24, 0xbc, 0x3b, 0xe4, 0x8c, + 0xe0, 0x18, 0x94, 0xa7, 0xe4, 0xd7, 0xf6, 0x2d, 0x97, 0xf4, 0xf3, 0xac, 0x16, 0xa7, 0xc9, 0x5e, + 0xf5, 0x3d, 0xdc, 0xbd, 0xb9, 0xd4, 0xc9, 0x2e, 0xb1, 0x57, 0x39, 0x9e, 0xc4, 0xd0, 0xfb, 0x50, + 0xfc, 0xd2, 0xb3, 0x5d, 0x5e, 0xf1, 0xdc, 0x42, 0xc5, 0x51, 0x25, 0xe5, 0x15, 0xff, 0x52, 0x7c, + 0xb1, 0xdb, 0x90, 0xf7, 0x5c, 0x9e, 0x77, 0x7e, 0x21, 0xef, 0x9c, 0xe7, 0xb6, 0x79, 0x2c, 0xcf, + 0x9a, 0x1d, 0xe8, 0xbe, 0x7d, 0x78, 0x14, 0xea, 0xc8, 0x29, 0xce, 0x38, 0x4b, 0x76, 0xa0, 0x21, + 0x0c, 0xb3, 0x45, 0x33, 0x7c, 0x64, 0x3b, 0xa8, 0x24, 0x50, 0x66, 0xc5, 0x85, 0xcc, 0x80, 0xa3, + 0x29, 0xc3, 0x37, 0xa1, 0x70, 0xe8, 0x7b, 0xd3, 0x09, 0xda, 0xd5, 0xb0, 0x40, 0x99, 0x27, 0xdc, + 0xf6, 0x19, 0x6e, 0x99, 0xf4, 0x69, 0xbb, 0x87, 0x3a, 0xb9, 0x20, 0x4a, 0x5b, 0xe9, 0x7b, 0x05, + 0xad, 0x1c, 0x01, 0xc9, 0xb9, 0xf0, 0x26, 0x14, 0x8c, 0xc3, 0x43, 0x5d, 0x84, 0x24, 0x2d, 0xe4, + 0x65, 0x1c, 0x1e, 0x52, 0x91, 0x0f, 0x60, 0xed, 0xc4, 0x76, 0xf5, 0x60, 0x62, 0x0d, 0x39, 0xed, + 0xda, 0x62, 0x57, 0x9e, 0xd8, 0x2e, 0x5a, 0xde, 0x44, 0x2f, 0x9b, 0xfe, 0x95, 0xd7, 0x9a, 0xfe, + 0x5b, 0x90, 0x75, 0xec, 0xb1, 0x1d, 0x8a, 0x20, 0xa5, 0x84, 0x6d, 0x40, 0x08, 0xa6, 0x42, 0x4e, + 0xf8, 0xbc, 0x95, 0x05, 0x12, 0x81, 0x61, 0x1f, 0x40, 0xc9, 0x37, 0xdc, 0x63, 0x5d, 0x1c, 0x18, + 0x7f, 0x21, 0x9b, 0xd1, 0x9a, 0xe1, 0x1e, 0x8b, 0xf3, 0x62, 0xf0, 0xe3, 0xef, 0xa4, 0xd6, 0xb5, + 0xf1, 0x1a, 0xad, 0x4b, 0x52, 0xed, 0xd9, 0xab, 0x55, 0xfb, 0x8f, 0x48, 0x87, 0xb6, 0xdc, 0x50, + 0x8f, 0x18, 0x2e, 0x2c, 0x67, 0x28, 0x73, 0xb2, 0x2e, 0x67, 0xc3, 0x06, 0x90, 0x1b, 0x4b, 0x27, + 0x9f, 0xd7, 0x66, 0xa2, 0x01, 0xb1, 0x7f, 0x4b, 0x03, 0x7f, 0xe6, 0xeb, 0xaa, 0xc1, 0xfa, 0x2c, + 0x4e, 0x93, 0x07, 0xbc, 0x5e, 0x94, 0xfd, 0xe8, 0x89, 0xc0, 0xce, 0x48, 0x6b, 0xb7, 0x13, 0xd1, + 0x9e, 0xb7, 0x61, 0x8d, 0x47, 0x68, 0xf0, 0x7e, 0x0b, 0x68, 0x63, 0x2c, 0x6a, 0x65, 0x02, 0xf2, + 0x7e, 0x0a, 0xd8, 0x03, 0x80, 0x48, 0xe3, 0x0c, 0x4f, 0x69, 0x67, 0x8c, 0x5b, 0xc3, 0xb7, 0xcf, + 0x7a, 0x78, 0xaa, 0x15, 0xcd, 0xe8, 0x13, 0x05, 0xfe, 0xc0, 0x76, 0x4d, 0x9c, 0x7a, 0xa1, 0x71, + 0x18, 0x54, 0xab, 0xb4, 0x32, 0x4b, 0x02, 0xd6, 0x37, 0x0e, 0x03, 0xb4, 0xec, 0x0c, 0xae, 0x60, + 0xf2, 0x7a, 0x5f, 0x91, 0xdd, 0x3e, 0x92, 0xea, 0xa9, 0x95, 0x0c, 0x49, 0x0f, 0xfd, 0x04, 0x58, + 0x74, 0x24, 0x27, 0x19, 0x6a, 0x57, 0x17, 0x66, 0xe3, 0xba, 0x38, 0x93, 0x8b, 0x83, 0xcb, 0x6f, + 0x42, 0x29, 0xf0, 0xa6, 0xfe, 0xd0, 0xd2, 0x83, 0xd0, 0x9a, 0x54, 0xaf, 0x51, 0x85, 0x80, 0x83, + 0x7a, 0xa1, 0x35, 0x61, 0x9f, 0xc0, 0x5a, 0x52, 0x51, 0xbf, 0xbe, 0xe4, 0x64, 0x8b, 0xa6, 0x85, + 0x56, 0x1e, 0xca, 0xaa, 0xfb, 0x6d, 0x1e, 0x43, 0x4c, 0xbb, 0x22, 0x31, 0xf2, 0xd3, 0x9b, 0xb2, + 0xeb, 0x85, 0xf5, 0x08, 0x86, 0x1d, 0x18, 0x19, 0x70, 0xe1, 0x29, 0x6d, 0xa4, 0x71, 0x07, 0xc6, + 0x26, 0x13, 0x2a, 0xc4, 0x91, 0xf5, 0x84, 0x73, 0x81, 0x9b, 0x25, 0xc4, 0x70, 0x33, 0x31, 0x17, + 0x62, 0x7b, 0x45, 0x03, 0x7f, 0x66, 0xbb, 0x7c, 0x02, 0x15, 0xee, 0x9b, 0x8e, 0x57, 0xde, 0xd6, + 0x79, 0x2b, 0xaf, 0x4c, 0x84, 0x02, 0x82, 0xc2, 0x87, 0x33, 0xf2, 0x45, 0x78, 0x6b, 0xd1, 0x07, + 0x48, 0xe8, 0x36, 0xad, 0xc4, 0x27, 0x50, 0x99, 0xf8, 0x38, 0x64, 0x71, 0x63, 0x54, 0xb9, 0x9f, + 0xf6, 0x7d, 0x6b, 0xd6, 0x9e, 0xf2, 0x44, 0x4a, 0xb1, 0x1f, 0xc2, 0x86, 0xc4, 0x39, 0x3d, 0x26, + 0xe6, 0xdb, 0xc4, 0xbc, 0x39, 0xc7, 0x7c, 0x70, 0x8c, 0xec, 0x95, 0x49, 0x22, 0xcd, 0x6a, 0x73, + 0xce, 0x16, 0x34, 0x64, 0xee, 0x10, 0xff, 0xe5, 0x73, 0x3c, 0x28, 0x09, 0x2f, 0xcc, 0x33, 0x7e, + 0x18, 0xd4, 0x0a, 0x9a, 0xae, 0x49, 0xfb, 0x7c, 0x41, 0xe3, 0x09, 0xf6, 0x18, 0xca, 0x5c, 0xa5, + 0xa6, 0x58, 0xcd, 0xa0, 0x7a, 0x57, 0xf6, 0x36, 0x93, 0x5e, 0x4d, 0x08, 0xad, 0xe4, 0xc4, 0xdf, + 0x01, 0xfb, 0x18, 0x36, 0x78, 0xaf, 0xc9, 0x82, 0xfb, 0xad, 0xc5, 0x89, 0x48, 0x44, 0x3b, 0x33, + 0xe9, 0xad, 0xc1, 0x15, 0x7f, 0xea, 0x92, 0x9a, 0x2d, 0x38, 0x27, 0xbe, 0x37, 0xb0, 0x38, 0xff, + 0x3d, 0xe2, 0x17, 0xcd, 0xd1, 0x38, 0x19, 0xe7, 0xa5, 0x71, 0xbb, 0xe4, 0xcb, 0xa0, 0x7d, 0xe4, + 0x3b, 0x27, 0xcf, 0xc1, 0xd4, 0x76, 0x4c, 0x9e, 0xe7, 0xdb, 0xdf, 0x26, 0xcf, 0x6d, 0xe4, 0xa3, + 0x3c, 0x19, 0x64, 0xa6, 0x53, 0xdb, 0x24, 0x75, 0xa3, 0xac, 0xd1, 0x37, 0x7b, 0x13, 0x2a, 0xbe, + 0x35, 0x9c, 0xfa, 0x81, 0xfd, 0xd2, 0xd2, 0x03, 0xdb, 0x3d, 0xae, 0xbe, 0x43, 0xfd, 0xb8, 0x16, + 0x43, 0x7b, 0xb6, 0x7b, 0x8c, 0x93, 0xd7, 0x3a, 0x0d, 0x2d, 0xdf, 0xe5, 0xe1, 0xe3, 0xef, 0xca, + 0x93, 0xb7, 0x49, 0x08, 0x94, 0x3e, 0x1a, 0x58, 0xf1, 0xf7, 0xdc, 0xe4, 0x08, 0xf8, 0xe4, 0x78, + 0xf0, 0x8d, 0x26, 0x47, 0x8f, 0x26, 0xc7, 0x5d, 0x28, 0xd8, 0x6e, 0x68, 0xf9, 0x2f, 0x0d, 0xa7, + 0xfa, 0x70, 0x61, 0x06, 0xc7, 0x38, 0x76, 0x07, 0xf2, 0x81, 0x63, 0xa3, 0x14, 0xaa, 0xbe, 0xbf, + 0x40, 0x16, 0xa1, 0xd8, 0x3d, 0x28, 0xc6, 0x37, 0x9f, 0xaa, 0x1f, 0x2c, 0xd0, 0xcd, 0x90, 0xec, + 0x06, 0x64, 0x4e, 0x70, 0x42, 0x3d, 0x5a, 0x3c, 0x1d, 0x40, 0x38, 0x2a, 0x15, 0x23, 0x54, 0x2e, + 0x49, 0xa9, 0x78, 0xbc, 0xa0, 0x54, 0xec, 0xd8, 0x8e, 0xc3, 0x95, 0x8a, 0x91, 0xf8, 0xc2, 0x2d, + 0x99, 0x38, 0xb0, 0x25, 0x1f, 0x2e, 0x6e, 0xc9, 0x88, 0x7b, 0x4e, 0x77, 0xc4, 0x4a, 0x01, 0xb9, + 0xbc, 0xb9, 0xe7, 0xfe, 0x23, 0xb9, 0xaf, 0x92, 0xbe, 0x70, 0x0d, 0x82, 0x38, 0x8d, 0x9a, 0xb2, + 0x70, 0xf8, 0xdb, 0xe6, 0x69, 0xf5, 0x63, 0x7e, 0xf9, 0x80, 0x43, 0x5a, 0xe6, 0x29, 0x7b, 0x1f, + 0xd6, 0xa2, 0xe8, 0x1e, 0x2c, 0x2e, 0xa8, 0x7e, 0xb2, 0x50, 0x83, 0x24, 0x01, 0x6b, 0x40, 0x79, + 0x84, 0x4a, 0xe6, 0x98, 0xeb, 0x9c, 0xd5, 0x27, 0x54, 0x91, 0xad, 0x48, 0xe8, 0x9c, 0xa7, 0x93, + 0x6a, 0x09, 0x2e, 0xf6, 0x00, 0x98, 0x3d, 0xe2, 0xe3, 0xb9, 0xe3, 0x7b, 0x63, 0xae, 0x57, 0x56, + 0x3f, 0xa5, 0xd9, 0xb5, 0x04, 0x43, 0xe7, 0x7f, 0x96, 0x6b, 0xea, 0xe3, 0x40, 0x28, 0x2f, 0xdf, + 0xa3, 0x7a, 0x0a, 0x91, 0x1a, 0xdf, 0x90, 0x14, 0x5b, 0x5e, 0x09, 0x69, 0xf7, 0x02, 0xae, 0xcb, + 0x7c, 0x0a, 0x38, 0x5d, 0x5f, 0xce, 0x58, 0x7f, 0xe5, 0x95, 0xac, 0x48, 0x1b, 0xb1, 0x3e, 0x81, + 0x8a, 0x69, 0x99, 0xd3, 0x09, 0xe9, 0x71, 0x34, 0x45, 0xbf, 0x2f, 0x0b, 0x3f, 0xd9, 0x73, 0xa9, + 0x95, 0x4d, 0xd9, 0x8f, 0xf9, 0x09, 0xac, 0x47, 0x2e, 0xc6, 0x50, 0x78, 0x23, 0x7f, 0x20, 0x17, + 0x1b, 0x7b, 0x10, 0xb5, 0xb5, 0x69, 0xf4, 0x49, 0x45, 0x3e, 0x86, 0x35, 0xda, 0xdb, 0x03, 0xd7, + 0x98, 0x04, 0x47, 0x5e, 0x58, 0xfd, 0x55, 0x59, 0x4d, 0xe9, 0x09, 0xa8, 0x56, 0x46, 0xa2, 0x28, + 0x85, 0x5b, 0xd2, 0x6c, 0x9d, 0x0e, 0x43, 0xab, 0xfa, 0x43, 0xbe, 0x25, 0xc5, 0xc0, 0x7a, 0x68, + 0xb1, 0xc7, 0x00, 0xc6, 0x64, 0xe2, 0x9c, 0xf1, 0xa9, 0xf9, 0x23, 0x9a, 0x9a, 0x9b, 0xd2, 0xd4, + 0xac, 0x21, 0x92, 0xe6, 0x66, 0xd1, 0x88, 0x3e, 0xd9, 0x23, 0x28, 0x4f, 0xbc, 0x20, 0xd4, 0xcd, + 0xb1, 0x43, 0xed, 0xaf, 0xc9, 0x6b, 0x7b, 0xdf, 0x0b, 0xc2, 0xc6, 0xd8, 0xa1, 0x8d, 0x69, 0x12, + 0x7f, 0xb3, 0x36, 0x5c, 0x48, 0xc8, 0x6d, 0x83, 0x4e, 0xdb, 0xab, 0xdb, 0x54, 0xe2, 0x75, 0xa9, + 0x44, 0x49, 0x7e, 0x8b, 0x50, 0xb3, 0x0d, 0x6f, 0x1e, 0x44, 0x06, 0x11, 0x8d, 0x41, 0x1c, 0x6f, + 0x59, 0xe7, 0x0a, 0x0b, 0x41, 0xa3, 0x80, 0xcb, 0x27, 0xb0, 0x3e, 0xa3, 0xc2, 0x06, 0x06, 0xd5, + 0x86, 0x3c, 0x93, 0xa5, 0xa8, 0xe8, 0xb5, 0x88, 0x11, 0x61, 0x01, 0xf5, 0x9d, 0xe7, 0x38, 0xd3, + 0x89, 0x10, 0xa5, 0xd5, 0xa6, 0xe8, 0x3b, 0x02, 0x72, 0x29, 0x29, 0xd9, 0x8c, 0xd6, 0xb8, 0xba, + 0x23, 0xdb, 0x8c, 0xd6, 0x58, 0xfd, 0x67, 0x59, 0x28, 0x44, 0x56, 0x0e, 0x2b, 0x41, 0xfe, 0xa0, + 0xf3, 0xac, 0xd3, 0x7d, 0xd1, 0xe1, 0xb7, 0xbb, 0x6a, 0xbd, 0x5e, 0x53, 0xeb, 0x2b, 0x26, 0xab, + 0x00, 0xd0, 0xfd, 0x0d, 0xbd, 0x57, 0xaf, 0x75, 0xf8, 0x6d, 0x2f, 0xba, 0x35, 0xc2, 0xd3, 0xab, + 0x6c, 0x03, 0xd6, 0x76, 0x0e, 0x3a, 0x14, 0x13, 0xc7, 0x41, 0x69, 0x04, 0x35, 0x3f, 0xe7, 0x27, + 0x81, 0x1c, 0x94, 0x41, 0xd0, 0x5e, 0xad, 0xdf, 0xd4, 0x5a, 0x11, 0x28, 0x4b, 0xe1, 0x75, 0xdd, + 0x03, 0xad, 0x2e, 0x72, 0xca, 0xb1, 0x8b, 0xb0, 0x11, 0xb3, 0x45, 0x59, 0x2a, 0x79, 0xac, 0xd9, + 0xbe, 0xd6, 0xfd, 0xac, 0x59, 0xef, 0x2b, 0x40, 0xc7, 0x8a, 0x4f, 0x9f, 0x2a, 0x25, 0x56, 0x86, + 0x42, 0xa3, 0xd5, 0xeb, 0xb7, 0x3a, 0xf5, 0xbe, 0x52, 0xc6, 0x0a, 0xef, 0xb4, 0xda, 0xfd, 0xa6, + 0xa6, 0xac, 0xb1, 0x02, 0x64, 0x3e, 0xeb, 0xb6, 0x3a, 0x4a, 0x85, 0xee, 0xb1, 0xd4, 0xf6, 0xf6, + 0xdb, 0x4d, 0x65, 0x1d, 0xa1, 0xbd, 0xae, 0xd6, 0x57, 0x14, 0x84, 0xbe, 0x68, 0x75, 0x1a, 0xdd, + 0x17, 0xca, 0x06, 0x2b, 0x42, 0xf6, 0xa0, 0x83, 0xc5, 0x30, 0xb6, 0x06, 0x45, 0xfa, 0xd4, 0x6b, + 0xed, 0xb6, 0x72, 0x41, 0x3a, 0x8b, 0xdc, 0x44, 0x14, 0x9d, 0x6c, 0xf6, 0xb0, 0x0e, 0x17, 0xb1, + 0x2d, 0x71, 0x92, 0xa8, 0x2f, 0x61, 0x3e, 0x7b, 0xad, 0xce, 0x41, 0x4f, 0xb9, 0x8c, 0xc4, 0xf4, + 0x49, 0x98, 0x2a, 0xe6, 0xd3, 0xea, 0x50, 0x57, 0xde, 0xc0, 0xef, 0x46, 0xb3, 0xdd, 0xec, 0x37, + 0x95, 0x9b, 0xd8, 0x2a, 0xad, 0xb9, 0xdf, 0xae, 0xd5, 0x9b, 0xca, 0x16, 0x26, 0xda, 0xdd, 0xfa, + 0x33, 0xbd, 0xbb, 0xaf, 0xdc, 0x62, 0x9b, 0xa0, 0x74, 0x3b, 0x7a, 0xe3, 0x60, 0xbf, 0xdd, 0xaa, + 0xd7, 0xfa, 0x4d, 0xfd, 0x59, 0xf3, 0x0b, 0x45, 0xc5, 0x6e, 0xdf, 0xd7, 0x9a, 0xba, 0xc8, 0xeb, + 0x36, 0x53, 0xa0, 0xbc, 0x73, 0xf0, 0x93, 0x9f, 0x7c, 0xa1, 0x8b, 0x76, 0xbf, 0x89, 0xd5, 0x9a, + 0x51, 0xe8, 0x07, 0xcf, 0x94, 0xbb, 0x73, 0xa0, 0xde, 0x33, 0xe5, 0x2d, 0xec, 0xb7, 0x68, 0x20, + 0x94, 0x7b, 0x48, 0xa0, 0x35, 0xeb, 0x07, 0x5a, 0xaf, 0xf5, 0xbc, 0xa9, 0xd7, 0xfb, 0x4d, 0xe5, + 0x6d, 0xea, 0xa8, 0x56, 0xe7, 0x99, 0x72, 0x1f, 0x5b, 0x82, 0x5f, 0x7c, 0x78, 0xde, 0x61, 0x0c, + 0x2a, 0x33, 0x5a, 0x82, 0xbd, 0x8b, 0x24, 0xdb, 0x5a, 0xb7, 0xd6, 0xa8, 0xd7, 0x7a, 0x7d, 0xe5, + 0x3d, 0xec, 0x86, 0xde, 0x7e, 0xbb, 0xd5, 0x57, 0x1e, 0x60, 0x5b, 0x9f, 0xd6, 0xfa, 0xbb, 0x4d, + 0x4d, 0x79, 0x88, 0x23, 0xdd, 0x6f, 0xed, 0x35, 0x75, 0xd1, 0xed, 0x8f, 0xb0, 0x8c, 0x9d, 0x56, + 0xbb, 0xad, 0x3c, 0xa6, 0xe3, 0xb6, 0x9a, 0xd6, 0x6f, 0xd1, 0x58, 0x7f, 0x88, 0x19, 0xd4, 0xf6, + 0xf7, 0xdb, 0x5f, 0x28, 0x1f, 0x61, 0x03, 0xf7, 0x0e, 0xda, 0xfd, 0x96, 0x7e, 0xb0, 0xdf, 0xa8, + 0xf5, 0x9b, 0xca, 0xc7, 0x34, 0x11, 0xba, 0xbd, 0x7e, 0x63, 0xaf, 0xad, 0x7c, 0x42, 0x79, 0xd2, + 0x34, 0xac, 0xb7, 0xbb, 0x9d, 0xa6, 0xf2, 0x44, 0xfd, 0x0d, 0x28, 0x44, 0x96, 0x2f, 0x66, 0xd3, + 0xea, 0x74, 0x9a, 0x9a, 0xb2, 0x82, 0x45, 0xb5, 0x9b, 0x3b, 0x7d, 0x25, 0x45, 0x67, 0x8f, 0xad, + 0xa7, 0xbb, 0x7d, 0x65, 0x15, 0x3f, 0xbb, 0x07, 0xd8, 0x6b, 0x69, 0x6a, 0x6e, 0x73, 0xaf, 0xa5, + 0x64, 0xf0, 0xab, 0xd6, 0xe9, 0xb7, 0x94, 0x2c, 0xcd, 0x9b, 0x56, 0xe7, 0x69, 0xbb, 0xa9, 0xe4, + 0x10, 0xba, 0x57, 0xd3, 0x9e, 0x29, 0x79, 0x9e, 0x69, 0xa3, 0xf9, 0xb9, 0x52, 0x60, 0x39, 0x58, + 0x6d, 0x3f, 0x52, 0x8a, 0x08, 0x6a, 0x34, 0x1b, 0x07, 0xfb, 0x0a, 0xa8, 0xf7, 0x20, 0x5f, 0x3b, + 0x3c, 0xdc, 0xf3, 0x4c, 0x3a, 0xee, 0xdc, 0x39, 0x68, 0xb7, 0xf9, 0x3a, 0xda, 0xee, 0xf6, 0xfb, + 0xdd, 0x3d, 0x25, 0x85, 0x33, 0xb7, 0xdf, 0xdd, 0x57, 0x56, 0xd5, 0x16, 0x14, 0xa2, 0xdd, 0x54, + 0xba, 0x9b, 0x55, 0x80, 0xcc, 0xbe, 0xd6, 0x7c, 0xce, 0x0f, 0xcc, 0x3b, 0xcd, 0xcf, 0xb1, 0x9a, + 0xf8, 0x85, 0x19, 0xa5, 0xb1, 0x20, 0x7e, 0x89, 0x8a, 0x2e, 0x67, 0xb5, 0x5b, 0x9d, 0x66, 0x4d, + 0x53, 0xb2, 0xea, 0x47, 0x89, 0xb3, 0x48, 0x21, 0x78, 0xb0, 0xf8, 0x5a, 0x4b, 0x14, 0xdf, 0x7a, + 0xda, 0xe9, 0x6a, 0x4d, 0x7e, 0xdb, 0x4b, 0x74, 0xe4, 0xaa, 0xfa, 0x0e, 0x14, 0x63, 0xa1, 0x89, + 0x13, 0xab, 0xae, 0x75, 0x7b, 0x3d, 0xde, 0xef, 0x2b, 0x98, 0xa6, 0xbe, 0xe1, 0xe9, 0x94, 0xda, + 0x83, 0x8d, 0x48, 0x5e, 0x53, 0x20, 0x3c, 0x99, 0x37, 0x9b, 0x90, 0x6d, 0x5b, 0x2f, 0x2d, 0x27, + 0x8a, 0xe8, 0xa6, 0x04, 0x42, 0xbb, 0x83, 0x2f, 0x5b, 0xf1, 0x85, 0x5c, 0x4a, 0xa0, 0x82, 0xd6, + 0x91, 0xee, 0x04, 0xd3, 0x4d, 0x82, 0xdf, 0x4d, 0x41, 0x21, 0xde, 0x05, 0xee, 0xc0, 0x6a, 0xbf, + 0x27, 0xce, 0x32, 0x36, 0x1f, 0xcc, 0x9e, 0x40, 0xe8, 0x47, 0x5f, 0xda, 0x6a, 0xbf, 0xc7, 0xde, + 0x85, 0x1c, 0xbf, 0xc2, 0x28, 0x0e, 0xa1, 0x36, 0x93, 0x3b, 0x4b, 0x9f, 0x70, 0x9a, 0xa0, 0x61, + 0x1f, 0x41, 0x31, 0xae, 0xad, 0xf0, 0xca, 0x5c, 0x4e, 0x32, 0xc4, 0x68, 0x6d, 0x46, 0xa9, 0xb6, + 0xa1, 0x92, 0xcc, 0x90, 0xdd, 0x00, 0xe0, 0x59, 0x4a, 0xde, 0x28, 0x09, 0xc2, 0xae, 0x42, 0x74, + 0xb3, 0xb2, 0x41, 0x15, 0x5b, 0x8b, 0x6f, 0x5a, 0x36, 0xd4, 0xbf, 0x9e, 0x06, 0x98, 0xe9, 0x91, + 0xd8, 0x11, 0xb1, 0xaf, 0x29, 0x2b, 0x8e, 0xb1, 0xaf, 0x41, 0xd1, 0xf1, 0x0c, 0x53, 0x7e, 0x01, + 0xa1, 0x80, 0x00, 0x1a, 0x1a, 0xf9, 0x96, 0x51, 0x91, 0xc7, 0x90, 0xb0, 0x4b, 0x90, 0x1b, 0x79, + 0xfe, 0xd8, 0x08, 0x45, 0xf8, 0xbe, 0x48, 0xe1, 0x76, 0xc0, 0x8f, 0x56, 0x51, 0x9b, 0x76, 0x29, + 0x82, 0x1f, 0xc7, 0xa0, 0x2c, 0x80, 0x6d, 0x84, 0xa1, 0x71, 0x69, 0xb9, 0x43, 0xc7, 0x0b, 0x2c, + 0x13, 0xed, 0xae, 0x1c, 0xa9, 0xcc, 0x10, 0x81, 0xb6, 0xcf, 0x78, 0x6b, 0xfd, 0xb1, 0xed, 0x1a, + 0xa1, 0x38, 0x70, 0xa0, 0xd6, 0x46, 0x10, 0xac, 0xee, 0x97, 0x81, 0x27, 0x5c, 0x4f, 0xfc, 0x94, + 0xb6, 0x80, 0x00, 0xaa, 0xee, 0x1b, 0x00, 0x56, 0x30, 0x34, 0x26, 0x3c, 0xf3, 0x22, 0x65, 0x5e, + 0x14, 0x90, 0xed, 0x33, 0xd6, 0x86, 0x4a, 0x7f, 0x80, 0xdb, 0x97, 0xd7, 0x30, 0x42, 0xa3, 0xee, + 0x39, 0xc2, 0x29, 0x74, 0x67, 0x5e, 0xe1, 0x7e, 0x90, 0x24, 0xe3, 0xc7, 0xc9, 0x73, 0xbc, 0x57, + 0x6b, 0x70, 0x61, 0x09, 0xd9, 0xb7, 0x8a, 0xab, 0x73, 0xa2, 0xd1, 0xa9, 0x85, 0x21, 0xdd, 0x98, + 0x89, 0x77, 0xea, 0x54, 0x14, 0xf7, 0xcf, 0x37, 0xe9, 0x6b, 0x14, 0x39, 0x23, 0x42, 0x32, 0xc5, + 0x20, 0xc5, 0xa1, 0x96, 0x77, 0x61, 0x1d, 0x91, 0x23, 0xdb, 0x72, 0x4c, 0x41, 0xc2, 0x2f, 0x7c, + 0xac, 0x0d, 0x3d, 0x67, 0x07, 0xa1, 0x44, 0xa7, 0xfe, 0xd5, 0x2c, 0xc0, 0xcc, 0x46, 0x4b, 0x9c, + 0x68, 0xa7, 0x92, 0x27, 0xda, 0x8f, 0xe0, 0x92, 0xb8, 0x0e, 0x14, 0x1f, 0x0b, 0xdb, 0xae, 0x3e, + 0x30, 0xa2, 0xe0, 0x01, 0x26, 0xb0, 0xfc, 0x64, 0xb8, 0xe5, 0x6e, 0x1b, 0xa8, 0xf1, 0xad, 0xcb, + 0x3c, 0xe1, 0xd9, 0x24, 0x19, 0xfc, 0x20, 0xeb, 0x11, 0x33, 0xf6, 0xfe, 0xd9, 0x84, 0xbd, 0x0f, + 0x17, 0x7d, 0x6b, 0xe4, 0x5b, 0xc1, 0x91, 0x1e, 0x06, 0x72, 0x61, 0x3c, 0x46, 0x6f, 0x43, 0x20, + 0xfb, 0x41, 0x5c, 0xd6, 0xfb, 0x70, 0x51, 0x58, 0x6f, 0x73, 0xd5, 0xe3, 0xf7, 0xc6, 0x37, 0x38, + 0x52, 0xae, 0xdd, 0x1b, 0x00, 0xc2, 0x70, 0x8d, 0xde, 0x11, 0x29, 0x68, 0x45, 0x6e, 0xa4, 0x8a, + 0xdb, 0xb5, 0x64, 0x7d, 0x8a, 0xe3, 0x3e, 0x9e, 0x60, 0x2a, 0x64, 0x50, 0x9c, 0xd2, 0xd1, 0x54, + 0xe5, 0x51, 0xe5, 0x01, 0xbd, 0x93, 0x42, 0xb7, 0x9d, 0x3d, 0xd3, 0xd2, 0x08, 0xc7, 0xde, 0x83, + 0x0b, 0x72, 0xb3, 0xa3, 0xab, 0xfe, 0x25, 0xaa, 0x88, 0x32, 0x6b, 0xa8, 0xc6, 0x2f, 0xfd, 0xbf, + 0x03, 0x4c, 0xaa, 0x79, 0x44, 0x5d, 0x26, 0xea, 0xf5, 0xb8, 0xda, 0x82, 0xf8, 0x2d, 0xa0, 0x2a, + 0xf2, 0x93, 0x80, 0xb5, 0x45, 0x53, 0x0d, 0x91, 0x74, 0x24, 0xf0, 0x3e, 0x5c, 0x9c, 0xb5, 0x4e, + 0x37, 0x42, 0x3d, 0x3c, 0xb2, 0x74, 0xcb, 0x35, 0xe9, 0x0e, 0x57, 0x41, 0xdb, 0x88, 0x1b, 0x5a, + 0x0b, 0xfb, 0x47, 0x16, 0x1a, 0x5b, 0x92, 0x8b, 0x6e, 0xfd, 0xd5, 0x2e, 0xba, 0x8f, 0xa1, 0x9a, + 0x38, 0xe6, 0x96, 0xbb, 0x9b, 0xdf, 0x81, 0xdc, 0x94, 0x0f, 0xb7, 0xe3, 0x1e, 0xbf, 0x0f, 0x1b, + 0x47, 0x46, 0xa0, 0x27, 0x78, 0xc9, 0x73, 0x58, 0xd0, 0xd6, 0x8f, 0x8c, 0x60, 0x5f, 0xe2, 0x51, + 0x7f, 0x3f, 0x05, 0x95, 0xa4, 0xd5, 0xca, 0xef, 0xc0, 0x38, 0xd3, 0xb1, 0xcb, 0x23, 0x5a, 0xb2, + 0x5a, 0x94, 0xc4, 0xb5, 0x30, 0x39, 0xd6, 0x79, 0x2a, 0x5a, 0x0b, 0x93, 0xe3, 0x3a, 0xa5, 0xd9, + 0xdb, 0x90, 0x9f, 0x1c, 0x73, 0xe1, 0x70, 0xde, 0xec, 0xcb, 0x4d, 0x78, 0x28, 0xf1, 0xdb, 0x90, + 0x9f, 0x0a, 0xd2, 0xcc, 0x79, 0xa4, 0x53, 0x22, 0x55, 0xff, 0xf9, 0x2a, 0x94, 0x65, 0x7f, 0xcd, + 0x37, 0x39, 0xfd, 0xfe, 0x56, 0x51, 0x0b, 0x5b, 0x14, 0x59, 0xa8, 0x53, 0xdc, 0x32, 0xf6, 0x13, + 0x3f, 0xfa, 0x86, 0x23, 0x23, 0xa8, 0x4d, 0x43, 0xaf, 0xee, 0xf1, 0x13, 0x37, 0xcf, 0x89, 0xe2, + 0x99, 0xf9, 0xca, 0x40, 0x99, 0x20, 0x42, 0x99, 0xdf, 0x17, 0xd7, 0x25, 0xe8, 0x82, 0x14, 0x45, + 0xcc, 0x64, 0x17, 0xe6, 0x4b, 0x39, 0xba, 0x1f, 0x45, 0xc1, 0x30, 0x8f, 0x60, 0x7d, 0x16, 0x9c, + 0x1e, 0x05, 0xd9, 0xcc, 0xb3, 0xac, 0xc5, 0x91, 0xe9, 0xe2, 0x46, 0xf4, 0x9a, 0x1d, 0xe8, 0x9e, + 0x63, 0x46, 0xb7, 0x60, 0xf2, 0x91, 0x83, 0xbe, 0xeb, 0x98, 0xe2, 0x8e, 0x1c, 0xa7, 0x71, 0xad, + 0x93, 0x88, 0x26, 0x76, 0xe2, 0x77, 0xac, 0x13, 0x71, 0x1b, 0xe6, 0x5f, 0xa4, 0x60, 0x63, 0xc1, + 0xbf, 0x82, 0x92, 0x73, 0xf6, 0x3e, 0x0f, 0x7e, 0xb2, 0x5b, 0x50, 0x1e, 0x1b, 0xe1, 0xf0, 0x48, + 0x9f, 0xf8, 0xd6, 0xc8, 0x3e, 0x8d, 0x1e, 0x19, 0x22, 0xd8, 0x3e, 0x81, 0x28, 0xf0, 0x68, 0x32, + 0x21, 0xaf, 0xd2, 0xd8, 0x0e, 0x85, 0xe0, 0x03, 0x02, 0x71, 0x37, 0x5c, 0x14, 0x94, 0x98, 0x39, + 0x27, 0x28, 0xf1, 0x2a, 0x14, 0x5d, 0x2f, 0xd4, 0x3d, 0x57, 0x9f, 0x1c, 0x8b, 0x2b, 0xf4, 0x79, + 0xd7, 0x0b, 0xbb, 0xee, 0xfe, 0x31, 0xbb, 0x07, 0xca, 0x34, 0xb0, 0xf4, 0x81, 0xe3, 0x79, 0xe3, + 0xc8, 0xc8, 0xe1, 0xb2, 0xa3, 0x32, 0x0d, 0xac, 0x6d, 0x04, 0xf3, 0xfa, 0xab, 0xd7, 0x21, 0xd7, + 0x8a, 0xbd, 0x41, 0x71, 0xfc, 0x4d, 0x5a, 0xbc, 0xc7, 0xe1, 0x41, 0xb1, 0x4e, 0x6f, 0x7b, 0xec, + 0x19, 0x13, 0x76, 0x1f, 0xd2, 0x63, 0x63, 0x22, 0xe2, 0x73, 0xaa, 0xf1, 0x59, 0x11, 0xc7, 0x3e, + 0xd8, 0x33, 0x26, 0x7c, 0xbb, 0x41, 0xa2, 0xab, 0x1f, 0x43, 0x21, 0x02, 0x7c, 0xab, 0x8d, 0xe5, + 0x5f, 0xaf, 0x42, 0xb1, 0x21, 0xfb, 0x98, 0xd1, 0x30, 0x0e, 0xfd, 0xa9, 0x8b, 0x5a, 0x5a, 0xf4, + 0x4a, 0xc1, 0xd0, 0x70, 0xfb, 0x02, 0x14, 0x4d, 0xe8, 0xd5, 0x57, 0x4c, 0xe8, 0xeb, 0x00, 0x3e, + 0x39, 0x43, 0xc8, 0x1f, 0x92, 0x8e, 0x63, 0x41, 0x5b, 0x66, 0xcb, 0x3c, 0x5d, 0x1e, 0xec, 0x91, + 0xf9, 0xe6, 0xc1, 0x1e, 0xd9, 0xa5, 0xc1, 0x1e, 0x77, 0x67, 0x9b, 0x0a, 0x4e, 0x6c, 0x2c, 0xb8, + 0xc8, 0xb7, 0xb6, 0x49, 0x7c, 0x25, 0x04, 0x4b, 0xff, 0x1e, 0x54, 0xa2, 0xd6, 0x89, 0xfc, 0x20, + 0x71, 0x0b, 0x45, 0xe0, 0xb8, 0x53, 0x7a, 0x2d, 0x94, 0x93, 0xc9, 0x85, 0x5a, 0x7a, 0x4d, 0x14, + 0xcc, 0xdf, 0x48, 0x01, 0x13, 0xc6, 0xfb, 0xce, 0xd4, 0x71, 0xfa, 0xd6, 0x29, 0xc9, 0x83, 0xfb, + 0xb0, 0x21, 0x7c, 0xe6, 0x52, 0x0c, 0x99, 0x38, 0x38, 0xe4, 0x88, 0xd9, 0xc1, 0xe1, 0xb2, 0x8b, + 0x82, 0xab, 0x4b, 0x2f, 0x0a, 0x2e, 0xbf, 0x80, 0x78, 0x13, 0x4a, 0xf2, 0x35, 0x3b, 0xae, 0x84, + 0x81, 0x31, 0xbb, 0x61, 0xf7, 0x6f, 0x57, 0x01, 0x66, 0x0e, 0x86, 0x5f, 0x76, 0xa4, 0xce, 0x92, + 0x21, 0x49, 0x2f, 0x1b, 0x92, 0x7b, 0xa0, 0xc8, 0x74, 0xd2, 0x7d, 0xcf, 0xca, 0x8c, 0x30, 0x52, + 0x6e, 0xec, 0x40, 0xbe, 0x93, 0x47, 0x61, 0x79, 0x22, 0x1a, 0x41, 0xc4, 0xec, 0x91, 0xe4, 0x15, + 0x6b, 0xaf, 0x60, 0x07, 0x5c, 0x12, 0xb3, 0x4f, 0xe1, 0x4a, 0xcc, 0xa9, 0x9f, 0xd8, 0xe1, 0x91, + 0x37, 0x0d, 0xc5, 0x3a, 0x0d, 0x84, 0x6c, 0xba, 0x14, 0xe5, 0xf4, 0x82, 0xa3, 0xf9, 0x7a, 0x0d, + 0x50, 0x3d, 0x1f, 0x4d, 0x1d, 0x47, 0x0f, 0xad, 0xd3, 0x50, 0x3c, 0x7c, 0x50, 0x4d, 0xf8, 0x66, + 0xa4, 0xe1, 0xd5, 0x0a, 0x23, 0x91, 0x50, 0xff, 0x41, 0x1a, 0xb2, 0x3f, 0x9e, 0x5a, 0xfe, 0x19, + 0xfb, 0x18, 0x8a, 0x41, 0x38, 0x0e, 0xe5, 0xc3, 0xdb, 0x2b, 0x3c, 0x03, 0xc2, 0xd3, 0xd9, 0xab, + 0x35, 0xb6, 0xdc, 0x90, 0x3b, 0x2d, 0x91, 0x96, 0xb6, 0x9d, 0x4d, 0xc8, 0x06, 0xa1, 0x35, 0x09, + 0x44, 0x8c, 0x1d, 0x4f, 0xb0, 0x2d, 0xc8, 0xba, 0x9e, 0x69, 0x05, 0xc9, 0x48, 0xba, 0x0e, 0xea, + 0x19, 0x1c, 0xc1, 0x54, 0xc8, 0xc5, 0x23, 0xbe, 0x70, 0x80, 0xca, 0x31, 0x74, 0x37, 0xc2, 0x32, + 0x4c, 0xdb, 0x3d, 0x8c, 0xee, 0xcf, 0xc6, 0x69, 0xdc, 0x50, 0x49, 0xad, 0x37, 0x0e, 0xa3, 0xcb, + 0xec, 0x22, 0xc9, 0xb6, 0xa0, 0x84, 0x9f, 0x2f, 0x7c, 0x3b, 0xb4, 0x7a, 0x8f, 0x23, 0x99, 0x2e, + 0x81, 0x50, 0x29, 0x37, 0xad, 0xd0, 0x1a, 0x86, 0xbd, 0xaf, 0x44, 0x78, 0x1c, 0x45, 0x51, 0x45, + 0x10, 0xf6, 0x3d, 0x60, 0x03, 0x63, 0x78, 0x7c, 0xe8, 0x7b, 0x53, 0xd7, 0xd4, 0xbf, 0x9a, 0x5a, + 0xbe, 0x6d, 0x45, 0xe1, 0x70, 0x25, 0xa9, 0x53, 0xb4, 0x8d, 0x19, 0xd9, 0x8f, 0x39, 0x95, 0x6a, + 0xc2, 0x5a, 0xa2, 0xab, 0x16, 0xfc, 0x40, 0xbd, 0x66, 0xbb, 0x59, 0xef, 0x73, 0x03, 0x52, 0x38, + 0x1f, 0x56, 0x65, 0xe7, 0x45, 0x5a, 0xf2, 0x6a, 0x64, 0x24, 0x2b, 0x33, 0x4b, 0x3e, 0x91, 0xa6, + 0xf6, 0xb4, 0xa9, 0xe4, 0xd4, 0x3f, 0x58, 0x85, 0x8d, 0xbe, 0x6f, 0xb8, 0x81, 0xc1, 0x75, 0x0e, + 0x37, 0xf4, 0x3d, 0x87, 0x7d, 0x0f, 0x0a, 0xe1, 0xd0, 0x91, 0x87, 0xf0, 0x66, 0x24, 0x30, 0xe6, + 0x48, 0x1f, 0xf4, 0x87, 0xdc, 0xfb, 0x9c, 0x0f, 0xf9, 0x07, 0x7b, 0x0f, 0xb2, 0x03, 0xeb, 0xd0, + 0x76, 0x85, 0xcc, 0xbc, 0x38, 0xcf, 0xb8, 0x8d, 0xc8, 0xdd, 0x15, 0x8d, 0x53, 0xb1, 0xf7, 0x21, + 0x37, 0xf4, 0xc6, 0xd1, 0x16, 0x35, 0xbb, 0x87, 0x25, 0x15, 0x84, 0xd8, 0xdd, 0x15, 0x4d, 0xd0, + 0xb1, 0x8f, 0xa1, 0xe0, 0x7b, 0x8e, 0x83, 0x3d, 0x26, 0x36, 0xaf, 0xea, 0x3c, 0x8f, 0x26, 0xf0, + 0xbb, 0x2b, 0x5a, 0x4c, 0xab, 0x3e, 0x80, 0xbc, 0xa8, 0x2c, 0x76, 0xc0, 0x76, 0xf3, 0x69, 0x4b, + 0x74, 0x64, 0xbd, 0xbb, 0xb7, 0xd7, 0xea, 0xf3, 0x4b, 0xa6, 0x5a, 0xb7, 0xdd, 0xde, 0xae, 0xd5, + 0x9f, 0x29, 0xab, 0xdb, 0x05, 0xc8, 0x71, 0x3f, 0xa3, 0xfa, 0x9b, 0x29, 0x58, 0x9f, 0x6b, 0x00, + 0x7b, 0x02, 0x99, 0x31, 0xea, 0xc0, 0xbc, 0x7b, 0xee, 0x2c, 0x6d, 0xa5, 0x94, 0xe6, 0x9a, 0x31, + 0x72, 0xa8, 0x9f, 0x42, 0x25, 0x09, 0x97, 0x7c, 0x0d, 0x6b, 0x50, 0xd4, 0x9a, 0xb5, 0x86, 0xde, + 0xed, 0xa0, 0x85, 0x8f, 0x16, 0x3f, 0x25, 0x5f, 0x68, 0x2d, 0x72, 0x0f, 0xfc, 0x1a, 0x28, 0xf3, + 0x1d, 0xc3, 0x9e, 0xa2, 0x95, 0x33, 0x9e, 0x38, 0x16, 0x29, 0x93, 0xd2, 0x90, 0xdd, 0x58, 0xd2, + 0x93, 0x82, 0x8c, 0x46, 0xac, 0x32, 0x4c, 0xa4, 0xd5, 0x5f, 0x07, 0xb6, 0xd8, 0x83, 0xbf, 0xbc, + 0xec, 0xff, 0x67, 0x0a, 0x32, 0xfb, 0x8e, 0xe1, 0xb2, 0xdb, 0x90, 0xa5, 0xc7, 0x51, 0x84, 0xe4, + 0x95, 0xd7, 0x01, 0x4e, 0x0b, 0xc2, 0xb1, 0x77, 0x20, 0x1d, 0x0e, 0xa3, 0xbb, 0xad, 0x97, 0xcf, + 0x99, 0x7c, 0xbb, 0x2b, 0x1a, 0x52, 0xb1, 0x7b, 0x90, 0x36, 0xcd, 0x28, 0xa6, 0x5c, 0x78, 0x1f, + 0xd0, 0xf6, 0x6c, 0x58, 0x23, 0xdb, 0xb5, 0xc5, 0x63, 0x2e, 0x48, 0xc2, 0xde, 0x84, 0xb4, 0x39, + 0x74, 0x92, 0x17, 0x04, 0xb8, 0x95, 0x1a, 0x67, 0x68, 0x0e, 0x1d, 0xd4, 0xd5, 0x42, 0xff, 0x4c, + 0xf7, 0xa7, 0x2e, 0x05, 0xc9, 0x05, 0xc2, 0x7e, 0x2a, 0xa1, 0xfe, 0x31, 0xa5, 0x48, 0xbb, 0x40, + 0x5c, 0x92, 0x9b, 0xf8, 0xd6, 0xc4, 0xf0, 0x63, 0xcb, 0xc9, 0x0e, 0xf6, 0x39, 0x60, 0x3b, 0x07, + 0xf4, 0xe6, 0xa4, 0xfa, 0x2e, 0xbd, 0xdc, 0x81, 0x2a, 0xb8, 0x1a, 0x7d, 0x2d, 0x79, 0x9e, 0x4c, + 0x60, 0xd4, 0x3f, 0x4f, 0x43, 0x49, 0xaa, 0x0f, 0xfb, 0x10, 0x0a, 0x66, 0x72, 0x21, 0x5e, 0x59, + 0xa8, 0xf4, 0x83, 0x46, 0xb4, 0x04, 0x4d, 0x31, 0xbd, 0xe9, 0x68, 0x23, 0xd4, 0x5f, 0x1a, 0xbe, + 0xcd, 0xdf, 0x6b, 0x5a, 0x95, 0xcf, 0x18, 0x7a, 0x56, 0xf8, 0x3c, 0xc2, 0xec, 0xae, 0x68, 0xe5, + 0x40, 0x4a, 0x93, 0x9d, 0x20, 0x9a, 0x94, 0x4e, 0xbc, 0x7b, 0xc5, 0x81, 0xbb, 0x2b, 0x5a, 0x84, + 0x47, 0x52, 0xeb, 0xd4, 0x1a, 0x4e, 0xc3, 0xc8, 0x4e, 0x58, 0x8b, 0x1a, 0x44, 0x40, 0x7a, 0x7c, + 0x8f, 0x7f, 0xb2, 0x47, 0x28, 0x27, 0x0d, 0xc7, 0xf1, 0x48, 0xcd, 0xca, 0xca, 0x1e, 0xff, 0x46, + 0x0c, 0xe7, 0x8f, 0xfd, 0x45, 0x29, 0x76, 0x17, 0xb2, 0x5e, 0x78, 0x64, 0x45, 0xda, 0x77, 0xf4, + 0x06, 0x08, 0x82, 0x1a, 0xf5, 0x36, 0xce, 0x14, 0x42, 0xab, 0x3f, 0x4b, 0x41, 0x5e, 0xf4, 0x00, + 0xdb, 0x80, 0xb5, 0x5e, 0xb3, 0xaf, 0x3f, 0xaf, 0x69, 0xad, 0xda, 0x76, 0xbb, 0x29, 0xee, 0x35, + 0x3c, 0xd5, 0x6a, 0x1d, 0x21, 0x27, 0xb5, 0xe6, 0xf3, 0xee, 0xb3, 0x26, 0x77, 0xe0, 0x35, 0x9a, + 0x9d, 0x2f, 0x94, 0x34, 0x77, 0x62, 0x37, 0xf7, 0x6b, 0x1a, 0x4a, 0xc9, 0x12, 0xe4, 0x9b, 0x9f, + 0x37, 0xeb, 0x07, 0x24, 0x26, 0x2b, 0x00, 0x8d, 0x66, 0xad, 0xdd, 0xee, 0xd6, 0x51, 0x6c, 0xe6, + 0x18, 0x83, 0x4a, 0x5d, 0x6b, 0xd6, 0xfa, 0x4d, 0xbd, 0x56, 0xaf, 0x77, 0x0f, 0x3a, 0x7d, 0x25, + 0x8f, 0x25, 0xd6, 0xda, 0xfd, 0xa6, 0x16, 0x83, 0xe8, 0x5d, 0xa6, 0x86, 0xd6, 0xdd, 0x8f, 0x21, + 0xc5, 0xed, 0x22, 0xda, 0x6c, 0x34, 0x56, 0xea, 0x3f, 0xda, 0x80, 0x4a, 0x72, 0x6a, 0xb2, 0x4f, + 0xa0, 0x60, 0x9a, 0x89, 0x31, 0xbe, 0xbe, 0x6c, 0x0a, 0x3f, 0x68, 0x98, 0xd1, 0x30, 0xf3, 0x0f, + 0x76, 0x2b, 0x5a, 0x48, 0xab, 0x0b, 0x0b, 0x29, 0x5a, 0x46, 0x3f, 0x84, 0x75, 0xf1, 0x86, 0x86, + 0x69, 0x84, 0xc6, 0xc0, 0x08, 0xac, 0xe4, 0x2a, 0xa9, 0x13, 0xb2, 0x21, 0x70, 0xbb, 0x2b, 0x5a, + 0x65, 0x98, 0x80, 0xb0, 0xef, 0x43, 0xc5, 0x20, 0xb3, 0x3c, 0xe6, 0xcf, 0xc8, 0x0a, 0x64, 0x0d, + 0x71, 0x12, 0xfb, 0x9a, 0x21, 0x03, 0x70, 0x22, 0x9a, 0xbe, 0x37, 0x99, 0x31, 0x67, 0x13, 0x87, + 0x5d, 0xbe, 0x37, 0x91, 0x78, 0xcb, 0xa6, 0x94, 0x66, 0x1f, 0x43, 0x59, 0xd4, 0x7c, 0xe6, 0x9a, + 0x88, 0x97, 0x2c, 0xaf, 0x36, 0x29, 0x84, 0xbb, 0x2b, 0x5a, 0x69, 0x38, 0x4b, 0xb2, 0xc7, 0xa8, + 0x05, 0xce, 0xd4, 0xe7, 0xbc, 0x3c, 0xd7, 0xa8, 0xb6, 0x11, 0x17, 0x18, 0x71, 0x8a, 0xbd, 0x0f, + 0x40, 0xf5, 0xe4, 0x3c, 0x85, 0x44, 0x70, 0x8a, 0xef, 0x4d, 0x22, 0x96, 0xa2, 0x19, 0x25, 0xa4, + 0xea, 0x71, 0xc7, 0x52, 0x71, 0xb1, 0x7a, 0xe4, 0x5c, 0x9a, 0x55, 0x8f, 0xfb, 0xa4, 0xe2, 0xea, + 0x71, 0x36, 0x58, 0xa8, 0x5e, 0xc4, 0xc5, 0xab, 0xc7, 0x99, 0xa2, 0xea, 0x71, 0x9e, 0xd2, 0x7c, + 0xf5, 0x22, 0x16, 0xaa, 0x1e, 0xe7, 0xf8, 0xfe, 0x82, 0xde, 0x5f, 0x3e, 0x57, 0xef, 0xc7, 0x61, + 0x4b, 0x6a, 0xfe, 0xdf, 0x87, 0x4a, 0x70, 0xe4, 0x9d, 0x48, 0x02, 0x64, 0x4d, 0xe6, 0xee, 0x1d, + 0x79, 0x27, 0xb2, 0x04, 0x59, 0x0b, 0x64, 0x00, 0xd6, 0x96, 0x37, 0x91, 0x2e, 0xef, 0x57, 0xe4, + 0xda, 0x52, 0x0b, 0x9f, 0xdb, 0xd6, 0x09, 0xd6, 0xd6, 0x88, 0x12, 0xd8, 0x29, 0x33, 0x37, 0x4d, + 0x20, 0x1c, 0x2f, 0x89, 0xe0, 0x09, 0x51, 0x12, 0xc4, 0x0e, 0x9b, 0x00, 0xe7, 0xd6, 0xd4, 0x95, + 0xd9, 0x14, 0x79, 0x6e, 0x1d, 0xb8, 0x09, 0xc6, 0x32, 0x27, 0x15, 0xac, 0xb3, 0x55, 0x11, 0x58, + 0x5f, 0x4d, 0x2d, 0x77, 0x68, 0x89, 0xd0, 0xad, 0xc4, 0xaa, 0xe8, 0x09, 0xdc, 0x6c, 0x55, 0x44, + 0x90, 0x78, 0x5e, 0xc7, 0xec, 0x6c, 0x7e, 0x5e, 0x4b, 0xcc, 0x34, 0xaf, 0x63, 0xd6, 0x78, 0x41, + 0xc5, 0xbc, 0x17, 0x16, 0x16, 0x94, 0xc4, 0xcc, 0x17, 0x54, 0xcc, 0xfd, 0x18, 0xc4, 0x6c, 0xe2, + 0x9d, 0x9b, 0x08, 0xf0, 0xe2, 0xb5, 0x16, 0xbd, 0x0b, 0xc3, 0x38, 0x85, 0x73, 0xd5, 0xb7, 0xd0, + 0xce, 0x10, 0x53, 0xe1, 0xa2, 0x3c, 0x57, 0x35, 0xc2, 0xc4, 0x4b, 0xc9, 0x9f, 0x25, 0xa5, 0xc2, + 0x26, 0x76, 0xe8, 0x57, 0xcd, 0xc5, 0xc2, 0xf6, 0xed, 0xd0, 0x9f, 0x15, 0x86, 0x29, 0xf6, 0x1e, + 0xd0, 0x34, 0xe4, 0x2c, 0x96, 0x2c, 0xba, 0xb1, 0x5b, 0x04, 0x43, 0xc1, 0x14, 0xdf, 0x38, 0x59, + 0x44, 0x19, 0x43, 0x73, 0x58, 0x1d, 0xc9, 0x93, 0x85, 0x17, 0x51, 0x6f, 0xd4, 0x71, 0xb2, 0x70, + 0xa2, 0xba, 0x39, 0x64, 0xf7, 0x81, 0xb8, 0x89, 0xfe, 0x30, 0xf1, 0xc6, 0x94, 0xef, 0x4d, 0x38, + 0x75, 0x1e, 0x09, 0x90, 0x16, 0x5b, 0xe0, 0x78, 0x6e, 0xd4, 0xf0, 0xa3, 0x44, 0x0b, 0x10, 0x11, + 0x0b, 0x83, 0x61, 0x9c, 0x52, 0x7f, 0x3b, 0x07, 0x79, 0x21, 0x6b, 0xd9, 0x05, 0x58, 0x17, 0x22, + 0xbf, 0x51, 0xeb, 0xd7, 0xb6, 0x6b, 0x3d, 0x54, 0xd2, 0x18, 0x54, 0xb8, 0xcc, 0x8f, 0x61, 0x29, + 0xdc, 0x07, 0x48, 0xe8, 0xc7, 0xa0, 0x55, 0xdc, 0x07, 0x04, 0x2f, 0x7f, 0xcb, 0x2f, 0xcd, 0xd6, + 0xa1, 0xc4, 0x19, 0x39, 0x80, 0xae, 0x59, 0x12, 0x17, 0x4f, 0x67, 0x25, 0x16, 0x7e, 0x9e, 0x95, + 0x9b, 0xb1, 0x70, 0x40, 0x3e, 0x66, 0x89, 0x0e, 0xbc, 0x18, 0x54, 0xfa, 0xda, 0x41, 0xa7, 0x3e, + 0x2b, 0xa7, 0x48, 0x57, 0xe3, 0x78, 0x36, 0xcf, 0x5b, 0xcd, 0x17, 0x0a, 0x20, 0x13, 0xcf, 0x85, + 0xd2, 0x25, 0x54, 0x33, 0x29, 0x13, 0x4a, 0x96, 0xd9, 0x65, 0xb8, 0xd0, 0xdb, 0xed, 0xbe, 0xd0, + 0x39, 0x53, 0xdc, 0x84, 0x35, 0xb6, 0x09, 0x8a, 0x84, 0xe0, 0xd9, 0x57, 0xb0, 0x48, 0x82, 0x46, + 0x84, 0x3d, 0x65, 0x9d, 0x8e, 0x8c, 0x11, 0xd6, 0xe7, 0xfb, 0xae, 0x82, 0x4d, 0xe1, 0xac, 0xdd, + 0xf6, 0xc1, 0x5e, 0xa7, 0xa7, 0x6c, 0x60, 0x25, 0x08, 0xc2, 0x6b, 0xce, 0xe2, 0x6c, 0x66, 0xbb, + 0xf5, 0x05, 0xda, 0xc0, 0x11, 0xf6, 0xa2, 0xa6, 0x75, 0x5a, 0x9d, 0xa7, 0x3d, 0x65, 0x33, 0xce, + 0xb9, 0xa9, 0x69, 0x5d, 0xad, 0xa7, 0x5c, 0x8c, 0x01, 0xbd, 0x7e, 0xad, 0x7f, 0xd0, 0x53, 0x2e, + 0xc5, 0xb5, 0xdc, 0xd7, 0xba, 0xf5, 0x66, 0xaf, 0xd7, 0x6e, 0xf5, 0xfa, 0xca, 0x65, 0x76, 0x11, + 0x36, 0x66, 0x35, 0x8a, 0x88, 0xab, 0x52, 0x45, 0xb5, 0xa7, 0xcd, 0xbe, 0x72, 0x25, 0xae, 0x46, + 0xbd, 0xdb, 0x6e, 0xd7, 0xe8, 0xb0, 0xf3, 0x2a, 0x12, 0xd1, 0xa9, 0xaf, 0x68, 0xcd, 0x35, 0xac, + 0xd7, 0x41, 0x47, 0x06, 0x5d, 0x97, 0xa6, 0x46, 0xaf, 0xf9, 0xe3, 0x83, 0x66, 0xa7, 0xde, 0x54, + 0xde, 0x98, 0x4d, 0x8d, 0x18, 0x76, 0x23, 0x9e, 0x1a, 0x31, 0xe8, 0x66, 0x5c, 0x66, 0x04, 0xea, + 0x29, 0x5b, 0x98, 0x9f, 0xa8, 0x47, 0xa7, 0xd3, 0xac, 0xf7, 0xb1, 0xad, 0xb7, 0xe2, 0x5e, 0x3c, + 0xd8, 0x7f, 0xaa, 0xd5, 0x1a, 0x4d, 0x45, 0x45, 0x88, 0xd6, 0xec, 0xd4, 0xf6, 0xa2, 0xd1, 0xbe, + 0x2d, 0x8d, 0xf6, 0x7e, 0xab, 0xaf, 0x29, 0x77, 0xe2, 0xd1, 0xa5, 0xe4, 0x9b, 0xec, 0x1a, 0x5c, + 0x96, 0xe7, 0xa1, 0xfe, 0xa2, 0xd5, 0xdf, 0x15, 0x67, 0xb3, 0x77, 0xf9, 0x19, 0x23, 0x21, 0xeb, + 0x8d, 0x3a, 0x3f, 0x84, 0x26, 0x5e, 0x4c, 0xdd, 0xdb, 0x2e, 0xd3, 0x93, 0xcc, 0x42, 0x01, 0x51, + 0x3f, 0x03, 0x26, 0xbf, 0x4e, 0x2a, 0x22, 0x60, 0x19, 0x64, 0x46, 0xbe, 0x37, 0x8e, 0x9e, 0x3c, + 0xc0, 0x6f, 0xb4, 0x9c, 0x27, 0xd3, 0x01, 0x9d, 0x7d, 0xce, 0xae, 0x34, 0xcb, 0x20, 0xf5, 0x8f, + 0x52, 0x50, 0x49, 0x2a, 0x1f, 0xe4, 0x20, 0x1d, 0xe9, 0xae, 0x17, 0xf2, 0xf7, 0x9f, 0x82, 0xf8, + 0xd1, 0xd0, 0x51, 0xc7, 0x0b, 0xe9, 0x01, 0x28, 0x32, 0xe4, 0x63, 0x5d, 0x82, 0xe7, 0x1a, 0xa7, + 0x59, 0x0b, 0x2e, 0x24, 0x1e, 0x78, 0x4d, 0xbc, 0xbe, 0x55, 0x8d, 0x1f, 0x66, 0x9c, 0xab, 0xbf, + 0xc6, 0x82, 0xc5, 0x36, 0x89, 0x8b, 0xe9, 0x99, 0xd9, 0xc5, 0xf4, 0x5d, 0x58, 0x4b, 0xe8, 0x3a, + 0xe4, 0x7f, 0x19, 0x25, 0x6b, 0x5a, 0xb0, 0x47, 0xaf, 0xaf, 0xa6, 0xfa, 0x77, 0x52, 0x50, 0x96, + 0x35, 0x9f, 0xef, 0x9c, 0x13, 0x5d, 0xe2, 0x12, 0xdf, 0xba, 0x6d, 0x46, 0xef, 0x3e, 0x45, 0xa0, + 0x16, 0x3d, 0x45, 0xcf, 0x7d, 0xcd, 0x3b, 0xc7, 0xbd, 0xb8, 0x39, 0x32, 0x88, 0xdd, 0x00, 0xa0, + 0x2b, 0xad, 0x3b, 0xcf, 0x90, 0x40, 0x5c, 0x03, 0x9b, 0x41, 0xd4, 0x9b, 0x50, 0xdc, 0x39, 0x8e, + 0x22, 0x62, 0xe4, 0x57, 0xd0, 0x8a, 0xfc, 0x1e, 0xbc, 0xfa, 0x27, 0x29, 0xa8, 0xcc, 0x5e, 0x8c, + 0xa1, 0x13, 0x68, 0xfe, 0x30, 0x30, 0x9f, 0x0e, 0xab, 0xe6, 0x60, 0xf6, 0x4a, 0xfd, 0xaa, 0xfc, + 0x4a, 0xfd, 0x6d, 0x91, 0x59, 0x5a, 0x16, 0xf9, 0x71, 0x59, 0xe2, 0x96, 0xfd, 0x63, 0x28, 0xe3, + 0x7f, 0xcd, 0x1a, 0x59, 0xbe, 0x6f, 0x45, 0x6f, 0x24, 0x2f, 0x10, 0x27, 0x88, 0xc8, 0xc6, 0xb3, + 0x46, 0x42, 0xd5, 0x5c, 0xfa, 0xa8, 0x0d, 0x3d, 0xb6, 0xf4, 0xdf, 0xd2, 0x50, 0x92, 0xf4, 0xc8, + 0x6f, 0x34, 0xfd, 0xae, 0x43, 0x71, 0xf6, 0xc4, 0x8a, 0xb8, 0xda, 0x1c, 0x03, 0x12, 0x63, 0x95, + 0x9e, 0x1b, 0xab, 0x2a, 0xe4, 0x45, 0xa0, 0xad, 0x70, 0xfe, 0x46, 0xc9, 0xa4, 0x9b, 0x35, 0xfb, + 0x9a, 0xf3, 0x90, 0x0f, 0xa0, 0x2c, 0xf9, 0x48, 0x03, 0x71, 0xfd, 0x77, 0x9e, 0xbe, 0x34, 0xf3, + 0x97, 0x06, 0xec, 0x22, 0xe4, 0x46, 0xc7, 0xba, 0x39, 0xe0, 0x77, 0x3e, 0x8b, 0x5a, 0x76, 0x74, + 0xdc, 0x18, 0xd0, 0x69, 0xd1, 0x28, 0x56, 0x9d, 0xb8, 0xe7, 0xaa, 0x30, 0x8a, 0x14, 0xa4, 0x7b, + 0x90, 0x1f, 0x1d, 0xcb, 0x77, 0x37, 0x17, 0xba, 0x3c, 0x37, 0x3a, 0xa6, 0xcb, 0x9e, 0x0f, 0x61, + 0x53, 0xec, 0xdf, 0x46, 0xa0, 0xf3, 0x57, 0x24, 0xe8, 0xe9, 0x1d, 0xfe, 0x26, 0xda, 0x06, 0xc7, + 0xd5, 0x82, 0x1e, 0x61, 0x70, 0xc6, 0xa9, 0x50, 0x96, 0x26, 0x20, 0x7f, 0xa3, 0xa8, 0xa8, 0x25, + 0x60, 0xec, 0x09, 0x94, 0x47, 0xc7, 0x7c, 0x40, 0xfb, 0xde, 0x9e, 0x25, 0xae, 0x0a, 0x6c, 0xce, + 0x0f, 0x25, 0x85, 0x08, 0x24, 0x28, 0xd9, 0x25, 0xc8, 0x69, 0xc6, 0x49, 0xef, 0xc7, 0x6d, 0x52, + 0x22, 0x8b, 0x9a, 0x48, 0x7d, 0x96, 0x29, 0x54, 0x94, 0x75, 0xf5, 0x1f, 0xa7, 0xa0, 0x32, 0xb3, + 0x01, 0x70, 0x11, 0xb2, 0xfb, 0xf2, 0x8b, 0xde, 0xd5, 0x79, 0x33, 0x01, 0x49, 0x1e, 0xf4, 0xcf, + 0x26, 0xfc, 0xdd, 0xcb, 0x65, 0xef, 0x4a, 0x2d, 0x73, 0x5a, 0xa7, 0x97, 0xbe, 0x25, 0xfc, 0x14, + 0xd2, 0xfd, 0xb3, 0x09, 0xf7, 0x37, 0xe1, 0x96, 0xc8, 0x6d, 0x53, 0xbe, 0x19, 0x52, 0x0c, 0xca, + 0xb3, 0xe6, 0x17, 0xfc, 0x29, 0x86, 0x7d, 0xad, 0xb5, 0x57, 0xd3, 0xbe, 0xa0, 0xf0, 0x22, 0x52, + 0x1a, 0x76, 0xba, 0x5a, 0xb3, 0xf5, 0xb4, 0x43, 0x80, 0x0c, 0x79, 0xa3, 0x66, 0x55, 0xac, 0x99, + 0xe6, 0xce, 0xb1, 0xfc, 0x24, 0x4f, 0x2a, 0xf1, 0x24, 0x4f, 0xf2, 0xf6, 0xf6, 0xea, 0xfc, 0xed, + 0x6d, 0x16, 0xaf, 0xc2, 0x78, 0x49, 0xb3, 0xb7, 0x20, 0x33, 0x3a, 0xb6, 0xce, 0x92, 0x86, 0x5e, + 0x72, 0x01, 0x11, 0x81, 0xfa, 0xf3, 0x14, 0xb0, 0x44, 0x45, 0xb8, 0xed, 0xf1, 0x5d, 0xeb, 0xf2, + 0x09, 0x54, 0xc5, 0x23, 0x91, 0x9c, 0x4a, 0xf2, 0x92, 0x8b, 0x2e, 0xbd, 0xe8, 0xcd, 0x82, 0x41, + 0x67, 0x4f, 0x5f, 0xb1, 0x87, 0xc0, 0x5f, 0xe9, 0xa3, 0x88, 0x92, 0xcc, 0x39, 0x76, 0xa2, 0x36, + 0xa3, 0x99, 0x3d, 0xcb, 0x27, 0x3f, 0x37, 0xc8, 0x1d, 0xec, 0xeb, 0xb3, 0x51, 0xa3, 0x35, 0xaf, + 0xfe, 0x5e, 0x0a, 0x2e, 0x24, 0x27, 0xc4, 0x2f, 0xd6, 0xca, 0xe4, 0xdb, 0x8a, 0xe9, 0xf9, 0xb7, + 0x15, 0x97, 0xcd, 0xa7, 0xcc, 0xd2, 0xf9, 0xf4, 0x5b, 0x29, 0xd8, 0x94, 0x7a, 0x7f, 0x66, 0x2d, + 0xfe, 0x05, 0xd5, 0x4c, 0x7a, 0x62, 0x31, 0x93, 0x78, 0x62, 0x51, 0xfd, 0x83, 0x14, 0x5c, 0x9a, + 0xab, 0x89, 0x66, 0xfd, 0x85, 0xd6, 0x25, 0xf9, 0x14, 0x23, 0x39, 0xf9, 0x79, 0x44, 0x2c, 0xbf, + 0xf6, 0xcb, 0x92, 0x6f, 0x2b, 0xd2, 0x25, 0xfb, 0x0f, 0x61, 0x63, 0x56, 0xc7, 0xba, 0x78, 0x36, + 0xf2, 0x26, 0x94, 0x5c, 0xeb, 0x44, 0x8f, 0x1e, 0x95, 0x14, 0x31, 0x44, 0xae, 0x75, 0x22, 0x08, + 0xd4, 0x1d, 0x59, 0x60, 0xc4, 0x2f, 0xcc, 0x3b, 0x66, 0x22, 0x18, 0xc5, 0x73, 0xcc, 0x08, 0x85, + 0xb9, 0x49, 0x2d, 0xca, 0xbb, 0xd6, 0x09, 0x0d, 0xd6, 0x89, 0xc8, 0xa7, 0x66, 0x9a, 0xe2, 0x40, + 0x7e, 0xd9, 0x4b, 0x51, 0x57, 0xa0, 0x30, 0xf1, 0x13, 0x5d, 0x92, 0x9f, 0xf8, 0xbc, 0xd8, 0x3b, + 0x22, 0x42, 0xe9, 0xbc, 0xc3, 0x7b, 0x1e, 0xb3, 0x24, 0x7e, 0x81, 0x22, 0x33, 0xfb, 0x05, 0x8a, + 0x8f, 0x84, 0xac, 0x20, 0xe3, 0x88, 0x97, 0xac, 0x40, 0xda, 0x36, 0x4f, 0xa9, 0xe0, 0x35, 0x0d, + 0x3f, 0x49, 0xdd, 0xb1, 0xbe, 0x12, 0x41, 0x52, 0xf8, 0xa9, 0x6e, 0x43, 0x49, 0x4b, 0x58, 0x82, + 0x65, 0xc9, 0xa9, 0x12, 0x24, 0x1f, 0xd3, 0x99, 0x75, 0x90, 0x56, 0x9a, 0xf9, 0x54, 0x02, 0x35, + 0x10, 0xd2, 0xe1, 0xb9, 0xe1, 0x0f, 0x8f, 0x0c, 0xbf, 0x6d, 0xb9, 0x87, 0xe1, 0x11, 0x76, 0x39, + 0xf7, 0x75, 0xca, 0x5d, 0x08, 0x1c, 0x14, 0x0d, 0x3d, 0xf6, 0xa2, 0x43, 0xe4, 0xd1, 0xdb, 0xf6, + 0xae, 0x75, 0x22, 0xf8, 0xdf, 0x00, 0xc0, 0xfe, 0x17, 0x68, 0x7e, 0xc2, 0x56, 0xf4, 0x1c, 0x93, + 0xa3, 0xd5, 0x0d, 0xd1, 0x5e, 0x71, 0xc3, 0xa5, 0x61, 0x8d, 0x54, 0x47, 0x8c, 0x3c, 0x6f, 0x90, + 0xe8, 0x84, 0xef, 0x34, 0x8c, 0xec, 0x16, 0x94, 0x23, 0xb3, 0x9d, 0xde, 0x6f, 0xe2, 0xc5, 0x97, + 0x22, 0x58, 0x67, 0x3a, 0x56, 0x7f, 0x3f, 0x0d, 0xe5, 0x1a, 0x0f, 0x57, 0x99, 0x9c, 0x75, 0x27, + 0x21, 0xfb, 0x75, 0xb8, 0x18, 0x1c, 0xdb, 0x13, 0xf1, 0x18, 0x3d, 0x45, 0x89, 0x50, 0xb8, 0xb0, + 0xe8, 0xc4, 0xfb, 0x52, 0x27, 0x0a, 0x96, 0x07, 0xbd, 0x63, 0x7b, 0xc2, 0xa3, 0xd4, 0x5b, 0xe6, + 0x29, 0x85, 0x84, 0xf3, 0xa3, 0x6f, 0x16, 0x2c, 0x20, 0xe8, 0x56, 0x32, 0x66, 0x3f, 0x39, 0x16, + 0xd9, 0x8a, 0x58, 0x00, 0x04, 0xee, 0x1f, 0x73, 0x9a, 0xfb, 0xb0, 0xc1, 0x2f, 0xa6, 0x2c, 0xee, + 0x52, 0xeb, 0x1c, 0x31, 0x9b, 0xdf, 0x3d, 0xd8, 0xa0, 0xfc, 0xc4, 0x23, 0x81, 0xfa, 0xd0, 0x9b, + 0x9c, 0x89, 0x93, 0xb5, 0xb7, 0xce, 0xa9, 0x6a, 0x8b, 0x93, 0x22, 0x48, 0x3c, 0x30, 0x12, 0x24, + 0xa1, 0x57, 0x9b, 0x70, 0xf9, 0x9c, 0x36, 0xbd, 0xee, 0xf4, 0xbe, 0x20, 0x9d, 0xde, 0x5f, 0xdd, + 0x86, 0xcd, 0x65, 0xe5, 0x7d, 0x9b, 0x3c, 0xd4, 0xff, 0x5c, 0x06, 0x98, 0xcd, 0xd8, 0x84, 0xce, + 0x96, 0x9a, 0xd3, 0xd9, 0xbe, 0x55, 0xa4, 0xca, 0x87, 0x50, 0xc1, 0xae, 0xd2, 0x67, 0x1c, 0xe9, + 0xa5, 0x1c, 0x65, 0xa4, 0xea, 0xcf, 0x6e, 0x04, 0x2e, 0x9e, 0xf8, 0x67, 0x96, 0x9e, 0xf8, 0x7f, + 0x00, 0x79, 0x7e, 0x1a, 0x15, 0x88, 0x4b, 0xa8, 0x97, 0xe7, 0x57, 0xdf, 0x03, 0x11, 0xf1, 0x1e, + 0xd1, 0xb1, 0x26, 0x54, 0x50, 0x3e, 0xfa, 0x76, 0x78, 0x34, 0x96, 0xaf, 0xa4, 0xde, 0x58, 0xe4, + 0x8c, 0xc8, 0xf8, 0xd3, 0x82, 0x86, 0x9c, 0x94, 0x54, 0xbc, 0x70, 0x2c, 0x5c, 0xa4, 0xa4, 0xe2, + 0xe5, 0x65, 0x15, 0xaf, 0x3f, 0xe6, 0x8e, 0x51, 0x54, 0xf1, 0xde, 0x83, 0x0b, 0xe2, 0x16, 0x0e, + 0x32, 0x60, 0x77, 0x12, 0x3d, 0x0f, 0x4a, 0x14, 0xef, 0xee, 0xf4, 0xc7, 0x64, 0x00, 0x21, 0xf9, + 0xe7, 0xb0, 0x39, 0x3c, 0x32, 0xdc, 0x43, 0x4b, 0x0f, 0x07, 0x8e, 0x4e, 0x0f, 0x9b, 0xeb, 0x63, + 0x63, 0x22, 0x34, 0xcf, 0xb7, 0x16, 0x2a, 0x5b, 0x27, 0xe2, 0xfe, 0xc0, 0xa1, 0xa8, 0xaa, 0x38, + 0x2e, 0x64, 0x63, 0x38, 0x0f, 0x9f, 0x3b, 0x9e, 0x85, 0x85, 0xe3, 0xd9, 0x79, 0x5d, 0xb4, 0xb4, + 0x44, 0x17, 0x9d, 0x69, 0x94, 0x65, 0x59, 0xa3, 0x64, 0xef, 0x42, 0x5e, 0x5c, 0x6d, 0x14, 0xce, + 0x51, 0xb6, 0xb8, 0x3a, 0xb4, 0x88, 0x04, 0x4b, 0x8a, 0x82, 0x05, 0xe8, 0x42, 0x74, 0x85, 0x97, + 0x24, 0xc3, 0xd8, 0xb6, 0xf0, 0x0c, 0xc6, 0x11, 0x60, 0xc2, 0x11, 0x7a, 0x55, 0xca, 0x38, 0xc6, + 0x09, 0xe3, 0x75, 0x8e, 0xe3, 0xea, 0x7f, 0xcf, 0x42, 0x4e, 0x04, 0x1b, 0xdf, 0x87, 0x8c, 0xe9, + 0x7b, 0x93, 0x38, 0x7a, 0x77, 0x89, 0x6a, 0x4b, 0xbf, 0x65, 0x85, 0x5a, 0xf0, 0x03, 0xc8, 0x19, + 0xa6, 0xa9, 0x8f, 0x8e, 0x93, 0x87, 0xb6, 0x73, 0x5a, 0xe6, 0xee, 0x8a, 0x96, 0x35, 0x48, 0xdd, + 0xfc, 0x04, 0x8a, 0x48, 0x3f, 0x8b, 0xa9, 0x2c, 0x2d, 0xea, 0xce, 0x91, 0x3e, 0xb8, 0xbb, 0xa2, + 0x15, 0x8c, 0x48, 0x37, 0xfc, 0x41, 0xd2, 0xfd, 0x9d, 0x59, 0x68, 0xe0, 0x9c, 0x32, 0x33, 0xe7, + 0x08, 0xff, 0x55, 0xe0, 0xfe, 0xd0, 0x78, 0xc7, 0xce, 0xca, 0xe7, 0x83, 0x0b, 0xfb, 0xfb, 0xee, + 0x8a, 0xc6, 0xf7, 0xad, 0x68, 0xbf, 0xff, 0x28, 0x72, 0x4d, 0xc7, 0xbf, 0xf9, 0xb1, 0xa4, 0x67, + 0x50, 0x0c, 0xc6, 0xfe, 0x69, 0x92, 0x89, 0xc8, 0x66, 0x9a, 0x51, 0x68, 0x5d, 0x7e, 0x81, 0x2d, + 0xde, 0xd5, 0x89, 0x2d, 0xde, 0xe2, 0x9f, 0x40, 0x89, 0x7b, 0x2a, 0x39, 0x5f, 0x61, 0xa1, 0x6b, + 0x67, 0x9b, 0x32, 0x9d, 0x7d, 0xcd, 0xb6, 0xe8, 0x7a, 0xd4, 0x4e, 0xdf, 0x92, 0x8f, 0x17, 0xae, + 0x2f, 0xed, 0x28, 0x2d, 0x3e, 0x69, 0xe0, 0x8d, 0xd5, 0x38, 0x0f, 0x6b, 0xc3, 0xa6, 0xf0, 0xc3, + 0xf3, 0x0d, 0x38, 0xda, 0x33, 0x61, 0x61, 0xbc, 0x12, 0x3b, 0xf4, 0xee, 0x8a, 0xc6, 0x8c, 0xc5, + 0x7d, 0xbb, 0x0e, 0x1b, 0x51, 0x95, 0xf8, 0xa5, 0xd2, 0x59, 0x54, 0x90, 0xdc, 0xa4, 0xd9, 0xbe, + 0xbb, 0xbb, 0xa2, 0xad, 0x1b, 0x49, 0x10, 0x6b, 0xc1, 0x85, 0x28, 0x13, 0xf2, 0x47, 0x8b, 0x9e, + 0x29, 0x2f, 0x8c, 0xa2, 0xbc, 0x57, 0xef, 0xae, 0x68, 0x1b, 0xc6, 0x3c, 0x70, 0x76, 0x3a, 0x7f, + 0x55, 0x83, 0x4b, 0xcb, 0x45, 0x82, 0xbc, 0x2f, 0x64, 0xf8, 0xbe, 0xa0, 0x26, 0xdf, 0x90, 0x4a, + 0xbe, 0x48, 0x20, 0xed, 0x12, 0x3f, 0x82, 0xb5, 0x84, 0x4c, 0x64, 0x25, 0xc8, 0x47, 0xaf, 0x4d, + 0xd3, 0x8d, 0x80, 0x7a, 0x77, 0xff, 0x0b, 0x25, 0x85, 0xe0, 0x56, 0xa7, 0xd7, 0xaf, 0x75, 0x44, + 0xec, 0x45, 0xab, 0x23, 0x62, 0x2f, 0xd4, 0xbf, 0x96, 0x86, 0x62, 0x7c, 0x76, 0xf4, 0xdd, 0x7d, + 0x3c, 0xb1, 0xf3, 0x24, 0x2d, 0x3b, 0x4f, 0xe6, 0x0c, 0x18, 0xfe, 0x30, 0x3c, 0x7f, 0x5b, 0x6c, + 0x3d, 0x69, 0x26, 0x04, 0x8b, 0xb7, 0x92, 0xb3, 0xdf, 0xf0, 0x56, 0xb2, 0x1c, 0x07, 0x9d, 0x4b, + 0xc6, 0x41, 0xcf, 0xbd, 0x38, 0x9e, 0xa7, 0xb7, 0x80, 0xe5, 0x17, 0xc7, 0xe9, 0x67, 0x01, 0x9f, + 0xdb, 0xd6, 0x89, 0x08, 0x1c, 0x16, 0xa9, 0xe4, 0x96, 0x0a, 0xaf, 0xd9, 0x52, 0xbf, 0x89, 0x78, + 0x7e, 0x04, 0x9b, 0xa3, 0xe3, 0xf8, 0x05, 0xe2, 0x99, 0xcb, 0xa0, 0x4c, 0x55, 0x5a, 0x8a, 0x53, + 0xff, 0x4a, 0x0a, 0x60, 0x76, 0x58, 0xf2, 0x0b, 0xfb, 0x1d, 0x25, 0xd7, 0x4e, 0xfa, 0x15, 0xae, + 0x9d, 0xd7, 0xbd, 0x23, 0xf5, 0x15, 0x14, 0xe3, 0xe3, 0xb1, 0xef, 0x3e, 0x5f, 0xbe, 0x55, 0x91, + 0xbf, 0x11, 0xf9, 0x60, 0xe3, 0xf3, 0xa5, 0x5f, 0xb4, 0x2f, 0x12, 0xc5, 0xa7, 0x5f, 0x53, 0xfc, + 0x29, 0x77, 0x84, 0xc6, 0x85, 0xff, 0x92, 0x17, 0x89, 0x3c, 0x7f, 0x33, 0x89, 0xf9, 0xab, 0x4e, + 0x85, 0x37, 0xf7, 0x17, 0x2f, 0xfa, 0x5b, 0x35, 0xf8, 0xbf, 0xa6, 0x22, 0x97, 0x63, 0xfc, 0x16, + 0xf4, 0xb9, 0xca, 0xe7, 0x72, 0xaf, 0xe9, 0xb7, 0x29, 0xee, 0x95, 0x0e, 0x95, 0xcc, 0xab, 0x1c, + 0x2a, 0x6f, 0x41, 0x96, 0x6f, 0x3b, 0xd9, 0xf3, 0x9c, 0x29, 0x1c, 0xff, 0xda, 0x5f, 0x6c, 0x50, + 0x55, 0xa1, 0x6c, 0xf3, 0xf6, 0x6e, 0x46, 0xf9, 0x46, 0xbf, 0x36, 0x41, 0xd7, 0x2f, 0xfe, 0x1f, + 0x2e, 0x28, 0xbf, 0x6b, 0x97, 0xbc, 0xda, 0x55, 0xa0, 0xfe, 0xaf, 0x14, 0xac, 0x25, 0x8e, 0xbb, + 0xbf, 0x43, 0x11, 0x4b, 0xc5, 0x6d, 0xfa, 0xff, 0x20, 0x71, 0x9b, 0x88, 0x14, 0x2d, 0x24, 0x23, + 0x45, 0x51, 0xdc, 0x95, 0x13, 0xa6, 0xc4, 0x32, 0xa3, 0x23, 0xb5, 0xd4, 0xe8, 0xb8, 0x11, 0xff, + 0xce, 0x5c, 0xab, 0xc1, 0x03, 0x33, 0xd7, 0x34, 0x09, 0xc2, 0x3e, 0x85, 0x2b, 0xc2, 0x98, 0xe7, + 0xfd, 0xe3, 0x8d, 0xf4, 0xf8, 0x57, 0xe8, 0x84, 0x71, 0x7c, 0x89, 0x13, 0xf0, 0xdf, 0xdb, 0x18, + 0xd5, 0x22, 0xac, 0xda, 0x82, 0xb5, 0x44, 0x1c, 0x81, 0xf4, 0xab, 0x97, 0x29, 0xf9, 0x57, 0x2f, + 0xd9, 0x16, 0x64, 0x4f, 0x8e, 0x2c, 0xdf, 0x5a, 0xf2, 0x56, 0x2c, 0x47, 0xa8, 0xdf, 0x87, 0xb2, + 0x1c, 0xd3, 0xc4, 0xde, 0x85, 0xac, 0x1d, 0x5a, 0xe3, 0xc8, 0x4d, 0x71, 0x69, 0x31, 0xec, 0xa9, + 0x15, 0x5a, 0x63, 0x8d, 0x13, 0xa9, 0x3f, 0x4b, 0x81, 0x32, 0x8f, 0x93, 0x7e, 0x9a, 0x33, 0x75, + 0xce, 0x4f, 0x73, 0xae, 0x26, 0x2a, 0xb9, 0xec, 0xd7, 0x35, 0xe3, 0xf7, 0x2a, 0x33, 0xe7, 0xbc, + 0x57, 0xc9, 0xee, 0x42, 0xc1, 0xb7, 0xe8, 0x77, 0x0f, 0xcd, 0x25, 0xd7, 0x12, 0x62, 0x9c, 0xfa, + 0x3b, 0x29, 0xc8, 0x8b, 0x00, 0xac, 0xa5, 0x7e, 0xa3, 0xb7, 0x21, 0xcf, 0x7f, 0x03, 0x31, 0x7a, + 0x69, 0x69, 0x21, 0x9a, 0x39, 0xc2, 0xb3, 0x1b, 0x3c, 0x2c, 0x2d, 0xe9, 0x47, 0xda, 0x77, 0x0c, + 0x57, 0x23, 0xb8, 0xf8, 0x19, 0x1d, 0x63, 0x2c, 0x6e, 0x3c, 0xf3, 0xf7, 0x90, 0x80, 0x40, 0x74, + 0xb9, 0x59, 0xfd, 0x01, 0xe4, 0x45, 0x80, 0xd7, 0xd2, 0xaa, 0xbc, 0xee, 0xf7, 0xef, 0xb6, 0x00, + 0x66, 0x11, 0x5f, 0xcb, 0x72, 0x50, 0xef, 0x43, 0x21, 0x0a, 0xf2, 0xc2, 0xf9, 0x37, 0x2b, 0x5a, + 0xdc, 0x77, 0x91, 0x2b, 0xe3, 0x88, 0xf7, 0xd7, 0xdb, 0xde, 0xf0, 0x98, 0x3c, 0xbb, 0x0f, 0x81, + 0x2e, 0xff, 0xf4, 0x17, 0x1e, 0x8e, 0x4a, 0x3e, 0x9e, 0x1f, 0x13, 0xb1, 0xfb, 0x10, 0xcb, 0xcb, + 0xd7, 0x99, 0xf8, 0x6a, 0x2d, 0xba, 0x26, 0x46, 0xb3, 0xec, 0xb1, 0xf0, 0x60, 0xb6, 0xe9, 0xb1, + 0xba, 0x94, 0xfc, 0x13, 0x0a, 0x89, 0x3a, 0x69, 0x12, 0x99, 0x5a, 0x81, 0xb2, 0x1c, 0x99, 0xa2, + 0xd6, 0x60, 0x63, 0xcf, 0x0a, 0x0d, 0x94, 0x3f, 0xd1, 0x73, 0x3a, 0x7c, 0xfe, 0xe2, 0x47, 0x72, + 0xfe, 0xce, 0xd3, 0x69, 0x9c, 0x48, 0xfd, 0x59, 0x06, 0x94, 0x79, 0xdc, 0xab, 0xae, 0xcc, 0xdd, + 0x84, 0x92, 0x47, 0xf3, 0x22, 0xf1, 0x43, 0x49, 0x1c, 0x24, 0x85, 0x9d, 0x27, 0x7e, 0x2d, 0xa3, + 0x60, 0x07, 0xbb, 0xfc, 0xf7, 0x32, 0x2e, 0xf3, 0xfb, 0x51, 0x8e, 0x37, 0xa4, 0x69, 0x5d, 0xa6, + 0xeb, 0x50, 0x6d, 0x6f, 0x48, 0x37, 0xf1, 0x84, 0x97, 0x80, 0x87, 0x4b, 0x96, 0xb5, 0x82, 0x70, + 0x0d, 0xd0, 0x61, 0x93, 0x08, 0x46, 0x0f, 0x03, 0x71, 0xb7, 0xb1, 0xc0, 0x01, 0xfd, 0x20, 0x7a, + 0xe5, 0x7b, 0x28, 0x7e, 0xd5, 0x27, 0x4d, 0xaf, 0x7c, 0xd7, 0x5d, 0xba, 0x88, 0x47, 0x3f, 0x42, + 0x35, 0x14, 0x3f, 0x12, 0x26, 0xde, 0x59, 0x47, 0xd4, 0x6d, 0xfe, 0xbb, 0x47, 0xbe, 0x15, 0x04, + 0xfc, 0x49, 0xb3, 0xa2, 0x78, 0xac, 0x4e, 0x00, 0xe3, 0x27, 0x21, 0xc5, 0xaf, 0x4e, 0x21, 0x09, + 0x88, 0x87, 0xd5, 0xf8, 0x6f, 0x4e, 0x21, 0xc1, 0x15, 0x28, 0x7c, 0xed, 0xb9, 0x16, 0x79, 0x1b, + 0x4a, 0x54, 0xab, 0x3c, 0xa6, 0xf7, 0x8c, 0x89, 0xfa, 0x4f, 0x53, 0xb0, 0x39, 0xdf, 0xab, 0x34, + 0x61, 0xca, 0x50, 0xa8, 0x77, 0xdb, 0x7a, 0xa7, 0xb6, 0xd7, 0x54, 0x56, 0xd8, 0x3a, 0x94, 0xba, + 0xdb, 0x9f, 0x35, 0xeb, 0x7d, 0x0e, 0x48, 0xd1, 0x85, 0xf4, 0x9e, 0xbe, 0xdb, 0x6a, 0x34, 0x9a, + 0x1d, 0x6e, 0x12, 0x74, 0xb7, 0x3f, 0xd3, 0xdb, 0xdd, 0x3a, 0xff, 0x91, 0x9a, 0xe8, 0x20, 0xbe, + 0xa7, 0x64, 0xe8, 0x98, 0x9e, 0xa2, 0xb3, 0x31, 0x99, 0xe5, 0xc1, 0xc7, 0x2f, 0x7a, 0x7a, 0xbd, + 0xd3, 0x57, 0x72, 0x98, 0xea, 0x1c, 0xb4, 0xdb, 0x94, 0xa2, 0x28, 0xc3, 0x7a, 0x77, 0x6f, 0x5f, + 0x6b, 0xf6, 0x7a, 0x7a, 0xaf, 0xf5, 0x93, 0xa6, 0x52, 0xa0, 0x92, 0xb5, 0xd6, 0xd3, 0x56, 0x87, + 0x03, 0x8a, 0x2c, 0x0f, 0xe9, 0xbd, 0x56, 0x87, 0x5f, 0xc4, 0xdf, 0xab, 0x7d, 0xae, 0x94, 0xf0, + 0xa3, 0x77, 0xb0, 0xa7, 0x94, 0xd5, 0xff, 0x90, 0x8e, 0x14, 0x5e, 0x8a, 0xb9, 0xf9, 0x26, 0x4a, + 0xde, 0xb2, 0xb3, 0xae, 0x4d, 0xc8, 0x3a, 0x74, 0xb5, 0x58, 0xfc, 0xfe, 0x2e, 0x25, 0xbe, 0xc9, + 0x6f, 0x8a, 0xde, 0x86, 0xb5, 0xf8, 0xa0, 0x5a, 0x7a, 0x78, 0xbb, 0x1c, 0x01, 0x97, 0x9c, 0x08, + 0xe4, 0x96, 0x9c, 0x08, 0x4c, 0xec, 0x10, 0x8d, 0x59, 0x14, 0xa9, 0x7c, 0xa2, 0x14, 0x11, 0xc2, + 0x7f, 0xcd, 0xf7, 0x1a, 0x50, 0x42, 0x9f, 0xba, 0x76, 0xf4, 0x8b, 0x72, 0x05, 0x04, 0x1c, 0xb8, + 0x76, 0x38, 0x7f, 0x50, 0x5e, 0x5c, 0x38, 0x28, 0x97, 0xf7, 0x5e, 0x48, 0xee, 0xbd, 0xc9, 0x9f, + 0x5a, 0xe5, 0x3f, 0x25, 0x27, 0xfd, 0xd4, 0xea, 0xbb, 0xc0, 0x86, 0x53, 0x9f, 0x5e, 0xea, 0x92, + 0xc8, 0xca, 0x44, 0xa6, 0x08, 0x4c, 0xbc, 0xe9, 0xb1, 0xb7, 0x60, 0x7d, 0x8e, 0x9a, 0x9c, 0x47, + 0x45, 0xad, 0x92, 0x24, 0x65, 0x0f, 0xe0, 0x82, 0x98, 0xba, 0x89, 0xbe, 0x15, 0xd7, 0x16, 0x39, + 0xaa, 0x36, 0xeb, 0x61, 0xf5, 0x57, 0xa0, 0x10, 0x85, 0x57, 0xbd, 0x5a, 0x97, 0x5d, 0x32, 0xae, + 0xea, 0xdf, 0x5f, 0x85, 0x62, 0x1c, 0x6c, 0xf5, 0x8d, 0x66, 0x07, 0xfd, 0xc2, 0x40, 0x70, 0x2c, + 0x4b, 0x90, 0x02, 0x02, 0xa2, 0x91, 0x12, 0x77, 0x7e, 0xa6, 0xbe, 0x1d, 0x29, 0x64, 0x1c, 0x72, + 0xe0, 0xdb, 0xf4, 0xf0, 0x85, 0xed, 0x4a, 0x17, 0x0c, 0x8b, 0x5a, 0x01, 0x01, 0xb4, 0xba, 0xae, + 0x00, 0x7d, 0x13, 0x67, 0xf4, 0xeb, 0xb3, 0xb6, 0x7b, 0x8c, 0x7c, 0xe7, 0xfc, 0xfa, 0x2c, 0xfd, + 0x3e, 0x02, 0x8f, 0xf4, 0xe0, 0xe7, 0xdb, 0xd1, 0xaf, 0x79, 0x5d, 0x83, 0xe2, 0x34, 0xfe, 0x39, + 0x38, 0x31, 0x23, 0xa6, 0xd1, 0x8f, 0xc1, 0x25, 0x47, 0xb5, 0x38, 0x3f, 0xaa, 0xf3, 0x73, 0x1a, + 0x16, 0xe6, 0xb4, 0x1a, 0x42, 0x5e, 0x04, 0x9c, 0xbd, 0xba, 0xc3, 0x5f, 0xd9, 0x55, 0x0a, 0xa4, + 0x0d, 0x27, 0xba, 0xd5, 0x88, 0x9f, 0x73, 0x15, 0xcb, 0xcc, 0x55, 0x4c, 0xfd, 0x5b, 0xab, 0x00, + 0xb3, 0xc0, 0x35, 0xf6, 0xde, 0x5c, 0x90, 0x6c, 0x6a, 0x61, 0x57, 0x9f, 0x8b, 0x8d, 0x9d, 0x7b, + 0x09, 0x66, 0xf5, 0x1b, 0xbc, 0x04, 0xf3, 0x08, 0xd6, 0x02, 0x7f, 0xf8, 0x5a, 0xbf, 0x76, 0x29, + 0xf0, 0x87, 0xb1, 0x5b, 0xfb, 0x21, 0x60, 0x92, 0xde, 0xae, 0x9b, 0xd9, 0xa1, 0x0b, 0x4a, 0x49, + 0x31, 0xf0, 0x87, 0xdd, 0xc1, 0x97, 0x0d, 0x7e, 0xd1, 0xca, 0x0c, 0x42, 0x7d, 0x99, 0x94, 0x58, + 0x37, 0x83, 0xb0, 0x21, 0x0b, 0x8a, 0x3b, 0x50, 0x41, 0xda, 0x05, 0x61, 0x51, 0x36, 0x83, 0xd9, + 0x39, 0x86, 0xfa, 0xdb, 0xd1, 0xf1, 0xe8, 0x9c, 0xcb, 0x94, 0x7d, 0x2c, 0xec, 0x6c, 0x49, 0x47, + 0xa8, 0x2e, 0xf3, 0xb0, 0xf2, 0x77, 0x6b, 0x62, 0xd2, 0xc5, 0x1f, 0x01, 0x5b, 0xfd, 0xa6, 0x3f, + 0x02, 0xb6, 0x05, 0x30, 0x7b, 0x3d, 0x10, 0x57, 0x60, 0x7c, 0x71, 0xa4, 0xc8, 0xaf, 0x84, 0xdc, + 0xbf, 0x05, 0x65, 0xf9, 0xa7, 0x38, 0xe9, 0x42, 0x88, 0xe7, 0x5a, 0xfc, 0xc7, 0x1a, 0xda, 0x5f, + 0x7f, 0xa8, 0xa4, 0xee, 0xab, 0x50, 0x92, 0x7e, 0x2a, 0x05, 0x29, 0x76, 0x8d, 0xe0, 0x48, 0x3c, + 0xdc, 0x6f, 0xb8, 0x87, 0x96, 0x92, 0xba, 0x7f, 0x17, 0x75, 0x6a, 0xf9, 0x87, 0x4a, 0x00, 0x72, + 0x1d, 0xcf, 0x1f, 0x1b, 0x8e, 0xa0, 0xb3, 0xa6, 0x01, 0xd2, 0x3d, 0x84, 0x8b, 0x4b, 0x7f, 0x76, + 0x85, 0x6e, 0x15, 0xd9, 0xe3, 0x89, 0x63, 0xf1, 0x8b, 0x31, 0xbb, 0x67, 0x03, 0xdf, 0x36, 0x95, + 0xd4, 0xfd, 0x27, 0xd1, 0x7d, 0xfc, 0xa8, 0xec, 0x76, 0xb7, 0xd6, 0xe0, 0xdb, 0x5f, 0xfc, 0x2e, + 0x4c, 0x7f, 0x9b, 0x3f, 0xca, 0xaf, 0x35, 0x7b, 0x07, 0xed, 0xbe, 0x78, 0x83, 0xe6, 0xfe, 0x8f, + 0xa0, 0x7a, 0xde, 0x0d, 0x11, 0xac, 0x51, 0x7d, 0xb7, 0x46, 0xb7, 0x70, 0x70, 0xbb, 0xeb, 0xea, + 0x3c, 0x95, 0xe2, 0x97, 0x98, 0xda, 0x4d, 0x0a, 0xa3, 0xbc, 0xff, 0xd3, 0x94, 0xa4, 0xe4, 0x45, + 0x51, 0xfe, 0x31, 0x40, 0x74, 0x93, 0x0c, 0xd2, 0x2c, 0xc3, 0x54, 0x52, 0xec, 0x12, 0xb0, 0x04, + 0xa8, 0xed, 0x0d, 0x0d, 0x47, 0x59, 0xa5, 0x80, 0xc9, 0x08, 0x4e, 0xf7, 0xb8, 0x94, 0x34, 0x7b, + 0x03, 0xae, 0xc4, 0xb0, 0xb6, 0x77, 0xb2, 0xef, 0xdb, 0x9e, 0x6f, 0x87, 0x67, 0x1c, 0x9d, 0xb9, + 0xff, 0xff, 0x8a, 0x93, 0xcc, 0xc4, 0xdc, 0xc0, 0x02, 0x6a, 0xa6, 0x39, 0x83, 0x91, 0x38, 0x52, + 0x56, 0xd8, 0x65, 0xb8, 0x40, 0xb2, 0x78, 0x0e, 0x91, 0x62, 0xd7, 0xe0, 0x72, 0x64, 0x89, 0xce, + 0x23, 0x57, 0x11, 0xa9, 0x59, 0x14, 0x6c, 0xb7, 0x80, 0x4c, 0x6f, 0xff, 0xf0, 0x4f, 0x7f, 0x7e, + 0x23, 0xf5, 0x2f, 0x7f, 0x7e, 0x23, 0xf5, 0x1f, 0x7f, 0x7e, 0x63, 0xe5, 0x67, 0xff, 0xe9, 0x46, + 0xea, 0x27, 0xef, 0x1d, 0xda, 0xe1, 0xd1, 0x74, 0xf0, 0x60, 0xe8, 0x8d, 0x1f, 0x8e, 0x8d, 0xd0, + 0xb7, 0x4f, 0xf9, 0xa6, 0x10, 0x25, 0x5c, 0xeb, 0xe1, 0xe4, 0xf8, 0xf0, 0xe1, 0x64, 0xf0, 0x10, + 0xa7, 0xe7, 0x20, 0x37, 0xf1, 0xbd, 0xd0, 0x7b, 0xfc, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x5e, + 0x02, 0xae, 0x5d, 0x14, 0x85, 0x00, 0x00, } func (m *Type) Marshal() (dAtA []byte, err error) { @@ -18782,6 +18843,20 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.RankOption != nil { + { + size, err := m.RankOption.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5 + i-- + dAtA[i] = 0xca + } if m.SpillMem != 0 { i = encodeVarintPlan(dAtA, i, uint64(m.SpillMem)) i-- @@ -19336,21 +19411,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xe2 } if len(m.SourceStep) > 0 { - dAtA90 := make([]byte, len(m.SourceStep)*10) - var j89 int + dAtA91 := make([]byte, len(m.SourceStep)*10) + var j90 int for _, num1 := range m.SourceStep { num := uint64(num1) for num >= 1<<7 { - dAtA90[j89] = uint8(uint64(num)&0x7f | 0x80) + dAtA91[j90] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j89++ + j90++ } - dAtA90[j89] = uint8(num) - j89++ + dAtA91[j90] = uint8(num) + j90++ } - i -= j89 - copy(dAtA[i:], dAtA90[:j89]) - i = encodeVarintPlan(dAtA, i, uint64(j89)) + i -= j90 + copy(dAtA[i:], dAtA91[:j90]) + i = encodeVarintPlan(dAtA, i, uint64(j90)) i-- dAtA[i] = 0x1 i-- @@ -19387,21 +19462,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xca } if len(m.BindingTags) > 0 { - dAtA93 := make([]byte, len(m.BindingTags)*10) - var j92 int + dAtA94 := make([]byte, len(m.BindingTags)*10) + var j93 int for _, num1 := range m.BindingTags { num := uint64(num1) for num >= 1<<7 { - dAtA93[j92] = uint8(uint64(num)&0x7f | 0x80) + dAtA94[j93] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j92++ + j93++ } - dAtA93[j92] = uint8(num) - j92++ + dAtA94[j93] = uint8(num) + j93++ } - i -= j92 - copy(dAtA[i:], dAtA93[:j92]) - i = encodeVarintPlan(dAtA, i, uint64(j92)) + i -= j93 + copy(dAtA[i:], dAtA94[:j93]) + i = encodeVarintPlan(dAtA, i, uint64(j93)) i-- dAtA[i] = 0x1 i-- @@ -19651,21 +19726,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.Children) > 0 { - dAtA103 := make([]byte, len(m.Children)*10) - var j102 int + dAtA104 := make([]byte, len(m.Children)*10) + var j103 int for _, num1 := range m.Children { num := uint64(num1) for num >= 1<<7 { - dAtA103[j102] = uint8(uint64(num)&0x7f | 0x80) + dAtA104[j103] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j102++ + j103++ } - dAtA103[j102] = uint8(num) - j102++ + dAtA104[j103] = uint8(num) + j103++ } - i -= j102 - copy(dAtA[i:], dAtA103[:j102]) - i = encodeVarintPlan(dAtA, i, uint64(j102)) + i -= j103 + copy(dAtA[i:], dAtA104[:j103]) + i = encodeVarintPlan(dAtA, i, uint64(j103)) i-- dAtA[i] = 0x22 } @@ -20182,21 +20257,21 @@ func (m *PreInsertUkCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x10 } if len(m.Columns) > 0 { - dAtA114 := make([]byte, len(m.Columns)*10) - var j113 int + dAtA115 := make([]byte, len(m.Columns)*10) + var j114 int for _, num1 := range m.Columns { num := uint64(num1) for num >= 1<<7 { - dAtA114[j113] = uint8(uint64(num)&0x7f | 0x80) + dAtA115[j114] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j113++ + j114++ } - dAtA114[j113] = uint8(num) - j113++ + dAtA115[j114] = uint8(num) + j114++ } - i -= j113 - copy(dAtA[i:], dAtA114[:j113]) - i = encodeVarintPlan(dAtA, i, uint64(j113)) + i -= j114 + copy(dAtA[i:], dAtA115[:j114]) + i = encodeVarintPlan(dAtA, i, uint64(j114)) i-- dAtA[i] = 0xa } @@ -20337,6 +20412,16 @@ func (m *RuntimeFilterSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.UseBloomFilter { + i-- + if m.UseBloomFilter { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if m.NotOnPk { i-- if m.NotOnPk { @@ -20407,21 +20492,21 @@ func (m *IdList) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.List) > 0 { - dAtA121 := make([]byte, len(m.List)*10) - var j120 int + dAtA122 := make([]byte, len(m.List)*10) + var j121 int for _, num1 := range m.List { num := uint64(num1) for num >= 1<<7 { - dAtA121[j120] = uint8(uint64(num)&0x7f | 0x80) + dAtA122[j121] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j120++ + j121++ } - dAtA121[j120] = uint8(num) - j120++ + dAtA122[j121] = uint8(num) + j121++ } - i -= j120 - copy(dAtA[i:], dAtA121[:j120]) - i = encodeVarintPlan(dAtA, i, uint64(j120)) + i -= j121 + copy(dAtA[i:], dAtA122[:j121]) + i = encodeVarintPlan(dAtA, i, uint64(j121)) i-- dAtA[i] = 0xa } @@ -20840,21 +20925,21 @@ func (m *Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.Steps) > 0 { - dAtA128 := make([]byte, len(m.Steps)*10) - var j127 int + dAtA129 := make([]byte, len(m.Steps)*10) + var j128 int for _, num1 := range m.Steps { num := uint64(num1) for num >= 1<<7 { - dAtA128[j127] = uint8(uint64(num)&0x7f | 0x80) + dAtA129[j128] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j127++ + j128++ } - dAtA128[j127] = uint8(num) - j127++ + dAtA129[j128] = uint8(num) + j128++ } - i -= j127 - copy(dAtA[i:], dAtA128[:j127]) - i = encodeVarintPlan(dAtA, i, uint64(j127)) + i -= j128 + copy(dAtA[i:], dAtA129[:j128]) + i = encodeVarintPlan(dAtA, i, uint64(j128)) i-- dAtA[i] = 0x12 } @@ -23704,20 +23789,20 @@ func (m *DropTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.FkChildTblsReferToMe) > 0 { - dAtA192 := make([]byte, len(m.FkChildTblsReferToMe)*10) - var j191 int + dAtA193 := make([]byte, len(m.FkChildTblsReferToMe)*10) + var j192 int for _, num := range m.FkChildTblsReferToMe { for num >= 1<<7 { - dAtA192[j191] = uint8(uint64(num)&0x7f | 0x80) + dAtA193[j192] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j191++ + j192++ } - dAtA192[j191] = uint8(num) - j191++ + dAtA193[j192] = uint8(num) + j192++ } - i -= j191 - copy(dAtA[i:], dAtA192[:j191]) - i = encodeVarintPlan(dAtA, i, uint64(j191)) + i -= j192 + copy(dAtA[i:], dAtA193[:j192]) + i = encodeVarintPlan(dAtA, i, uint64(j192)) i-- dAtA[i] = 0x62 } @@ -23753,20 +23838,20 @@ func (m *DropTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x48 } if len(m.ForeignTbl) > 0 { - dAtA195 := make([]byte, len(m.ForeignTbl)*10) - var j194 int + dAtA196 := make([]byte, len(m.ForeignTbl)*10) + var j195 int for _, num := range m.ForeignTbl { for num >= 1<<7 { - dAtA195[j194] = uint8(uint64(num)&0x7f | 0x80) + dAtA196[j195] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j194++ + j195++ } - dAtA195[j194] = uint8(num) - j194++ + dAtA196[j195] = uint8(num) + j195++ } - i -= j194 - copy(dAtA[i:], dAtA195[:j194]) - i = encodeVarintPlan(dAtA, i, uint64(j194)) + i -= j195 + copy(dAtA[i:], dAtA196[:j195]) + i = encodeVarintPlan(dAtA, i, uint64(j195)) i-- dAtA[i] = 0x3a } @@ -24312,20 +24397,20 @@ func (m *TruncateTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x40 } if len(m.ForeignTbl) > 0 { - dAtA204 := make([]byte, len(m.ForeignTbl)*10) - var j203 int + dAtA205 := make([]byte, len(m.ForeignTbl)*10) + var j204 int for _, num := range m.ForeignTbl { for num >= 1<<7 { - dAtA204[j203] = uint8(uint64(num)&0x7f | 0x80) + dAtA205[j204] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j203++ + j204++ } - dAtA204[j203] = uint8(num) - j203++ + dAtA205[j204] = uint8(num) + j204++ } - i -= j203 - copy(dAtA[i:], dAtA204[:j203]) - i = encodeVarintPlan(dAtA, i, uint64(j203)) + i -= j204 + copy(dAtA[i:], dAtA205[:j204]) + i = encodeVarintPlan(dAtA, i, uint64(j204)) i-- dAtA[i] = 0x3a } @@ -24402,20 +24487,20 @@ func (m *ClusterTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x18 } if len(m.AccountIDs) > 0 { - dAtA207 := make([]byte, len(m.AccountIDs)*10) - var j206 int + dAtA208 := make([]byte, len(m.AccountIDs)*10) + var j207 int for _, num := range m.AccountIDs { for num >= 1<<7 { - dAtA207[j206] = uint8(uint64(num)&0x7f | 0x80) + dAtA208[j207] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j206++ + j207++ } - dAtA207[j206] = uint8(num) - j206++ + dAtA208[j207] = uint8(num) + j207++ } - i -= j206 - copy(dAtA[i:], dAtA207[:j206]) - i = encodeVarintPlan(dAtA, i, uint64(j206)) + i -= j207 + copy(dAtA[i:], dAtA208[:j207]) + i = encodeVarintPlan(dAtA, i, uint64(j207)) i-- dAtA[i] = 0x12 } @@ -24627,21 +24712,21 @@ func (m *Prepare) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.ParamTypes) > 0 { - dAtA211 := make([]byte, len(m.ParamTypes)*10) - var j210 int + dAtA212 := make([]byte, len(m.ParamTypes)*10) + var j211 int for _, num1 := range m.ParamTypes { num := uint64(num1) for num >= 1<<7 { - dAtA211[j210] = uint8(uint64(num)&0x7f | 0x80) + dAtA212[j211] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j210++ + j211++ } - dAtA211[j210] = uint8(num) - j210++ + dAtA212[j211] = uint8(num) + j211++ } - i -= j210 - copy(dAtA[i:], dAtA211[:j210]) - i = encodeVarintPlan(dAtA, i, uint64(j210)) + i -= j211 + copy(dAtA[i:], dAtA212[:j211]) + i = encodeVarintPlan(dAtA, i, uint64(j211)) i-- dAtA[i] = 0x22 } @@ -24788,21 +24873,21 @@ func (m *OtherDCL) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.ParamTypes) > 0 { - dAtA214 := make([]byte, len(m.ParamTypes)*10) - var j213 int + dAtA215 := make([]byte, len(m.ParamTypes)*10) + var j214 int for _, num1 := range m.ParamTypes { num := uint64(num1) for num >= 1<<7 { - dAtA214[j213] = uint8(uint64(num)&0x7f | 0x80) + dAtA215[j214] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j213++ + j214++ } - dAtA214[j213] = uint8(num) - j213++ + dAtA215[j214] = uint8(num) + j214++ } - i -= j213 - copy(dAtA[i:], dAtA214[:j213]) - i = encodeVarintPlan(dAtA, i, uint64(j213)) + i -= j214 + copy(dAtA[i:], dAtA215[:j214]) + i = encodeVarintPlan(dAtA, i, uint64(j214)) i-- dAtA[i] = 0xa } @@ -25518,6 +25603,40 @@ func (m *AlterPartitionOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RankOption) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RankOption) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RankOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Mode) > 0 { + i -= len(m.Mode) + copy(dAtA[i:], m.Mode) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Mode))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintPlan(dAtA []byte, offset int, v uint64) int { offset -= sovPlan(v) base := offset @@ -28000,6 +28119,10 @@ func (m *Node) ProtoSize() (n int) { if m.SpillMem != 0 { n += 2 + sovPlan(uint64(m.SpillMem)) } + if m.RankOption != nil { + l = m.RankOption.ProtoSize() + n += 2 + l + sovPlan(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -28293,6 +28416,9 @@ func (m *RuntimeFilterSpec) ProtoSize() (n int) { if m.NotOnPk { n += 2 } + if m.UseBloomFilter { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -30715,6 +30841,22 @@ func (m *AlterPartitionOption) ProtoSize() (n int) { return n } +func (m *RankOption) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Mode) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func sovPlan(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -44833,6 +44975,42 @@ func (m *Node) Unmarshal(dAtA []byte) error { break } } + case 89: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RankOption", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPlan + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPlan + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RankOption == nil { + m.RankOption = &RankOption{} + } + if err := m.RankOption.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPlan(dAtA[iNdEx:]) @@ -46805,6 +46983,26 @@ func (m *RuntimeFilterSpec) Unmarshal(dAtA []byte) error { } } m.NotOnPk = bool(v != 0) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UseBloomFilter", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.UseBloomFilter = bool(v != 0) default: iNdEx = preIndex skippy, err := skipPlan(dAtA[iNdEx:]) @@ -59752,6 +59950,89 @@ func (m *AlterPartitionOption) Unmarshal(dAtA []byte) error { } return nil } +func (m *RankOption) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RankOption: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RankOption: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPlan + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPlan + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Mode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPlan(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPlan + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipPlan(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/pkg/sql/colexec/dispatch/sendfunc.go b/pkg/sql/colexec/dispatch/sendfunc.go index 775f77d9a2210..44b9a2199e110 100644 --- a/pkg/sql/colexec/dispatch/sendfunc.go +++ b/pkg/sql/colexec/dispatch/sendfunc.go @@ -25,8 +25,10 @@ import ( "github.com/matrixorigin/matrixone/pkg/cnservice/cnclient" "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/logutil" "github.com/matrixorigin/matrixone/pkg/pb/pipeline" "github.com/matrixorigin/matrixone/pkg/vm/process" + "go.uber.org/zap" ) // receiverFailureMode defines how to handle receiver failures @@ -397,6 +399,10 @@ func sendBatchToClientSession( if failureMode == FailureModeStrict { // Strict mode: receiver done indicates data loss // This happens when remote CN crashes or cancels + logutil.Debug("sendBatchToClientSession: ReceiverDone=true in strict mode", + zap.String("receiverID", receiverID), + zap.Uint64("msgId", wcs.MsgId), + zap.String("uid", wcs.Uid.String())) return true, moerr.NewInternalError(ctx, fmt.Sprintf( "remote receiver %s is already done, data loss may occur. "+ "This usually indicates the remote CN has failed or been canceled", diff --git a/pkg/sql/colexec/hashbuild/build.go b/pkg/sql/colexec/hashbuild/build.go index 84a6f779893fe..676bfe2267666 100644 --- a/pkg/sql/colexec/hashbuild/build.go +++ b/pkg/sql/colexec/hashbuild/build.go @@ -17,6 +17,7 @@ package hashbuild import ( "bytes" + "github.com/matrixorigin/matrixone/pkg/common/bloomfilter" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/sql/colexec" "github.com/matrixorigin/matrixone/pkg/vm" @@ -143,6 +144,26 @@ func (ctr *container) build(ap *HashBuild, proc *process.Process, analyzer proce return nil } +// calculateBloomFilterProbability calculates the false positive rate for bloom filter +// based on row count. Reference fuzzyfilter experience, choose different false positive rates +// based on row count to balance memory usage and filtering accuracy. +func calculateBloomFilterProbability(rowCount int) float64 { + switch { + case rowCount < 10_0001: + return 0.00001 + case rowCount < 100_0001: + return 0.000003 + case rowCount < 1000_0001: + return 0.000001 + case rowCount < 1_0000_0001: + return 0.0000005 + case rowCount < 10_0000_0001: + return 0.0000002 + default: + return 0.0000001 + } +} + func (ctr *container) handleRuntimeFilter(ap *HashBuild, proc *process.Process) error { if ap.RuntimeFilterSpec == nil { return nil @@ -151,19 +172,64 @@ func (ctr *container) handleRuntimeFilter(ap *HashBuild, proc *process.Process) var runtimeFilter message.RuntimeFilterMessage runtimeFilter.Tag = ap.RuntimeFilterSpec.Tag - if ap.RuntimeFilterSpec.Expr == nil { + spec := ap.RuntimeFilterSpec + + // use bloom filter runtime filter when requested + if spec.UseBloomFilter { + // currently only support single-column key for bloom runtime filter + // composite key still uses original IN / PASS logic + if spec.Expr != nil && spec.Expr.GetF() != nil { + runtimeFilter.Typ = message.RuntimeFilter_PASS + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) + return nil + } + + // No data, directly DROP + if ctr.hashmapBuilder.InputBatchRowCount == 0 || + len(ctr.hashmapBuilder.UniqueJoinKeys) == 0 || + ctr.hashmapBuilder.UniqueJoinKeys[0].Length() == 0 { + runtimeFilter.Typ = message.RuntimeFilter_DROP + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) + return nil + } + + keyVec := ctr.hashmapBuilder.UniqueJoinKeys[0] + rowCount := keyVec.Length() + + // Use common/bloomfilter to build BloomFilter + // Reference fuzzyfilter experience, choose different false positive rates based on row count + probability := calculateBloomFilterProbability(rowCount) + + bf := bloomfilter.New(int64(rowCount), probability) + bf.Add(keyVec) + + data, err := bf.Marshal() + if err != nil { + return err + } + + runtimeFilter.Typ = message.RuntimeFilter_BLOOMFILTER + runtimeFilter.Card = int32(rowCount) + runtimeFilter.Data = data + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) + + // UniqueJoinKeys will be released uniformly in defer + return nil + } + + if spec.Expr == nil { runtimeFilter.Typ = message.RuntimeFilter_PASS - message.SendRuntimeFilter(runtimeFilter, ap.RuntimeFilterSpec, proc.GetMessageBoard()) + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) return nil } else if ctr.hashmapBuilder.InputBatchRowCount == 0 || len(ctr.hashmapBuilder.UniqueJoinKeys) == 0 || ctr.hashmapBuilder.UniqueJoinKeys[0].Length() == 0 { runtimeFilter.Typ = message.RuntimeFilter_DROP - message.SendRuntimeFilter(runtimeFilter, ap.RuntimeFilterSpec, proc.GetMessageBoard()) + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) return nil } hashmapCount := ctr.hashmapBuilder.GetGroupCount() - inFilterCardLimit := ap.RuntimeFilterSpec.UpperLimit + inFilterCardLimit := spec.UpperLimit //inFilterCardLimit := plan.GetInFilterCardLimit() //bloomFilterCardLimit := int64(plan.BloomFilterCardLimit) //v, ok = runtime.ProcessLevelRuntime().GetGlobalVariables("runtime_filter_limit_bloom_filter") @@ -180,7 +246,7 @@ func (ctr *container) handleRuntimeFilter(ap *HashBuild, proc *process.Process) if hashmapCount > uint64(inFilterCardLimit) { runtimeFilter.Typ = message.RuntimeFilter_PASS - message.SendRuntimeFilter(runtimeFilter, ap.RuntimeFilterSpec, proc.GetMessageBoard()) + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) return nil } else { rowCount := ctr.hashmapBuilder.UniqueJoinKeys[0].Length() @@ -188,12 +254,12 @@ func (ctr *container) handleRuntimeFilter(ap *HashBuild, proc *process.Process) var data []byte var err error // Composite primary key - if ap.RuntimeFilterSpec.Expr.GetF() != nil { + if spec.Expr.GetF() != nil { bat := batch.NewWithSize(len(ctr.hashmapBuilder.UniqueJoinKeys)) bat.SetRowCount(rowCount) copy(bat.Vecs, ctr.hashmapBuilder.UniqueJoinKeys) - vec, free, erg := colexec.GetReadonlyResultFromExpression(proc, ap.RuntimeFilterSpec.Expr, []*batch.Batch{bat}) + vec, free, erg := colexec.GetReadonlyResultFromExpression(proc, spec.Expr, []*batch.Batch{bat}) if erg != nil { return erg } @@ -212,7 +278,7 @@ func (ctr *container) handleRuntimeFilter(ap *HashBuild, proc *process.Process) runtimeFilter.Typ = message.RuntimeFilter_IN runtimeFilter.Card = int32(rowCount) runtimeFilter.Data = data - message.SendRuntimeFilter(runtimeFilter, ap.RuntimeFilterSpec, proc.GetMessageBoard()) + message.SendRuntimeFilter(runtimeFilter, spec, proc.GetMessageBoard()) ctr.runtimeFilterIn = true } return nil diff --git a/pkg/sql/colexec/hashbuild/build_test.go b/pkg/sql/colexec/hashbuild/build_test.go index 5e90eddffc19e..47f04e4256756 100644 --- a/pkg/sql/colexec/hashbuild/build_test.go +++ b/pkg/sql/colexec/hashbuild/build_test.go @@ -182,3 +182,79 @@ func newTestCase(t testing.TB, flgs []bool, ts []types.Type, cs []*plan.Expr) bu func newBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch { return testutil.NewBatch(ts, false, int(rows), proc.Mp()) } + +func TestCalculateBloomFilterProbability(t *testing.T) { + tests := []struct { + name string + rowCount int + wantProb float64 + }{ + { + name: "very small row count", + rowCount: 1000, + wantProb: 0.00001, + }, + { + name: "small row count boundary", + rowCount: 10_0000, + wantProb: 0.00001, + }, + { + name: "medium row count lower bound", + rowCount: 10_0001, + wantProb: 0.000003, + }, + { + name: "medium row count upper bound", + rowCount: 100_0000, + wantProb: 0.000003, + }, + { + name: "large row count lower bound", + rowCount: 100_0001, + wantProb: 0.000001, + }, + { + name: "large row count upper bound", + rowCount: 1000_0000, + wantProb: 0.000001, + }, + { + name: "very large row count lower bound", + rowCount: 1000_0001, + wantProb: 0.0000005, + }, + { + name: "very large row count upper bound", + rowCount: 1_0000_0000, + wantProb: 0.0000005, + }, + { + name: "huge row count lower bound", + rowCount: 1_0000_0001, + wantProb: 0.0000002, + }, + { + name: "huge row count upper bound", + rowCount: 10_0000_0000, + wantProb: 0.0000002, + }, + { + name: "extremely large row count", + rowCount: 10_0000_0001, + wantProb: 0.0000001, + }, + { + name: "maximum row count", + rowCount: 100_0000_0000, + wantProb: 0.0000001, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := calculateBloomFilterProbability(tt.rowCount) + require.Equal(t, tt.wantProb, got, "calculateBloomFilterProbability(%d) = %v, want %v", tt.rowCount, got, tt.wantProb) + }) + } +} diff --git a/pkg/sql/colexec/table_function/ivf_search.go b/pkg/sql/colexec/table_function/ivf_search.go index 5725c6d53739a..d18d9de4e64e9 100644 --- a/pkg/sql/colexec/table_function/ivf_search.go +++ b/pkg/sql/colexec/table_function/ivf_search.go @@ -31,6 +31,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/vectorindex/metric" "github.com/matrixorigin/matrixone/pkg/vectorindex/sqlexec" "github.com/matrixorigin/matrixone/pkg/vm" + "github.com/matrixorigin/matrixone/pkg/vm/message" "github.com/matrixorigin/matrixone/pkg/vm/process" ) @@ -45,6 +46,9 @@ type ivfSearchState struct { distances []float64 // holding one call batch, tokenizedState owns it. batch *batch.Batch + + // runtime filter BloomFilter bytes from hash build side (optional) + bloomFilter []byte } // stub function @@ -73,6 +77,8 @@ func (u *ivfSearchState) reset(tf *TableFunction, proc *process.Process) { if u.batch != nil { u.batch.CleanOnlyData() } + // Note: bloomFilter is kept across resets as it's only set once during initialization + // It will be cleared in free() method } func (u *ivfSearchState) call(tf *TableFunction, proc *process.Process) (vm.CallResult, error) { @@ -109,6 +115,47 @@ func (u *ivfSearchState) free(tf *TableFunction, proc *process.Process, pipeline if u.batch != nil { u.batch.Clean(proc.Mp()) } + // Clear bloomFilter bytes to release memory + u.bloomFilter = nil +} + +// waitBloomFilterForTableFunction blocks until it receives a bloomfilter runtime filter +// that matches tf.RuntimeFilterSpecs (if any). It is used when ivf_search acts as probe +// side in a join and build side produces a bloom runtime filter. +// We don't deserialize BloomFilter here, only keep raw bytes, which can be passed to SQL executor / table scan later. +func waitBloomFilterForTableFunction(tf *TableFunction, proc *process.Process) ([]byte, error) { + if len(tf.RuntimeFilterSpecs) == 0 { + return nil, nil + } + spec := tf.RuntimeFilterSpecs[0] + if !spec.UseBloomFilter { + return nil, nil + } + + msgReceiver := message.NewMessageReceiver( + []int32{spec.Tag}, + message.AddrBroadCastOnCurrentCN(), + proc.GetMessageBoard(), + ) + msgs, ctxDone, err := msgReceiver.ReceiveMessage(true, proc.Ctx) + if err != nil || ctxDone { + return nil, err + } + + for i := range msgs { + m, ok := msgs[i].(message.RuntimeFilterMessage) + if !ok { + continue + } + if m.Typ != message.RuntimeFilter_BLOOMFILTER { + continue + } + + // runtime bloomfilter uses common/bloomfilter encoding; pass through bytes directly here + return m.Data, nil + } + + return nil, nil } func ivfSearchPrepare(proc *process.Process, arg *TableFunction) (tvfState, error) { @@ -137,6 +184,13 @@ func ivfSearchPrepare(proc *process.Process, arg *TableFunction) (tvfState, erro func (u *ivfSearchState) start(tf *TableFunction, proc *process.Process, nthRow int, analyzer process.Analyzer) (err error) { if !u.inited { + // receive bloom runtime filter if any + if bf, err := waitBloomFilterForTableFunction(tf, proc); err != nil { + return err + } else { + u.bloomFilter = bf + } + if len(tf.Params) > 0 { err = sonic.Unmarshal([]byte(tf.Params), &u.param) if err != nil { @@ -249,8 +303,12 @@ func runIvfSearchVector[T types.RealNumbers](tf *TableFunction, u *ivfSearchStat Probe: uint(u.tblcfg.Nprobe), OrigFuncName: u.tblcfg.OrigFuncName, BackgroundQueries: make([]*plan.Query, 1), + BloomFilter: u.bloomFilter, } - u.keys, u.distances, err = veccache.Cache.Search(sqlexec.NewSqlProcess(proc), key, algo, fa, rt) + sqlProc := sqlexec.NewSqlProcess(proc) + sqlProc.BloomFilter = u.bloomFilter + + u.keys, u.distances, err = veccache.Cache.Search(sqlProc, key, algo, fa, rt) if err != nil { return err } diff --git a/pkg/sql/colexec/table_function/ivf_search_test.go b/pkg/sql/colexec/table_function/ivf_search_test.go index 265fcd2da8ba9..07d43a963ef3b 100644 --- a/pkg/sql/colexec/table_function/ivf_search_test.go +++ b/pkg/sql/colexec/table_function/ivf_search_test.go @@ -15,9 +15,11 @@ package table_function import ( + "context" "fmt" "os" "testing" + "time" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" @@ -31,6 +33,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/vectorindex/cache" "github.com/matrixorigin/matrixone/pkg/vectorindex/sqlexec" "github.com/matrixorigin/matrixone/pkg/vm" + "github.com/matrixorigin/matrixone/pkg/vm/message" "github.com/matrixorigin/matrixone/pkg/vm/process" "github.com/stretchr/testify/require" ) @@ -429,3 +432,246 @@ func makeBatchIvfSearchFail(proc *process.Process) []failBatch { } return failBatches } + +// mockMessage is a mock Message type to test continue branch +type mockMessage struct { + tag int32 +} + +func (m mockMessage) Serialize() []byte { + return nil +} + +func (m mockMessage) Deserialize([]byte) message.Message { + return nil +} + +func (m mockMessage) NeedBlock() bool { + return false +} + +func (m mockMessage) GetMsgTag() int32 { + return m.tag +} + +func (m mockMessage) GetReceiverAddr() message.MessageAddress { + return message.AddrBroadCastOnCurrentCN() +} + +func (m mockMessage) DebugString() string { + return "mock message" +} + +func (m mockMessage) Destroy() { +} + +func TestWaitBloomFilterForTableFunction(t *testing.T) { + t.Run("return nil when RuntimeFilterSpecs is empty", func(t *testing.T) { + proc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + } + result, err := waitBloomFilterForTableFunction(tf, proc) + require.NoError(t, err) + require.Nil(t, result) + }) + + t.Run("return nil when UseBloomFilter is false", func(t *testing.T) { + proc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{ + { + Tag: 1, + UseBloomFilter: false, + }, + }, + } + result, err := waitBloomFilterForTableFunction(tf, proc) + require.NoError(t, err) + require.Nil(t, result) + }) + + t.Run("return data when BLOOMFILTER message found", func(t *testing.T) { + proc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + mb := message.NewMessageBoard() + proc.SetMessageBoard(mb) + + tag := int32(100) + expectedData := []byte{1, 2, 3, 4, 5} + + // Send a BLOOMFILTER message before calling the function + rtMsg := message.RuntimeFilterMessage{ + Tag: tag, + Typ: message.RuntimeFilter_BLOOMFILTER, + Data: expectedData, + } + message.SendMessage(rtMsg, mb) + + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{ + { + Tag: tag, + UseBloomFilter: true, + }, + }, + } + + // Use a goroutine to call the function since it blocks + done := make(chan bool) + var result []byte + var err error + go func() { + result, err = waitBloomFilterForTableFunction(tf, proc) + done <- true + }() + + // Wait a bit for the message to be received + <-done + + require.NoError(t, err) + require.Equal(t, expectedData, result) + }) + + t.Run("return nil when no matching message found", func(t *testing.T) { + // Create a new process with timeout context for this test + testProc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + mb := message.NewMessageBoard() + testProc.SetMessageBoard(mb) + + tag := int32(200) + + // Send a message with different tag + rtMsg := message.RuntimeFilterMessage{ + Tag: tag + 1, // different tag + Typ: message.RuntimeFilter_BLOOMFILTER, + Data: []byte{1, 2, 3}, + } + message.SendMessage(rtMsg, mb) + + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{ + { + Tag: tag, + UseBloomFilter: true, + }, + }, + } + + // Use context with cancel to avoid blocking forever + ctx, cancel := context.WithCancel(context.Background()) + testProc.Ctx = ctx + + // Cancel context after timeout to avoid blocking forever + go func() { + time.Sleep(100 * time.Millisecond) + cancel() + }() + + done := make(chan bool) + var result []byte + var err error + go func() { + result, err = waitBloomFilterForTableFunction(tf, testProc) + done <- true + }() + + <-done + cancel() // Ensure cancel is called even if goroutine finishes early + + // Should return nil when context is done or no matching message + require.NoError(t, err) + require.Nil(t, result) + }) + + t.Run("continue when message is not RuntimeFilterMessage", func(t *testing.T) { + proc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + mb := message.NewMessageBoard() + proc.SetMessageBoard(mb) + + tag := int32(300) + expectedData := []byte{6, 7, 8, 9, 10} + + // Send a mock message (not RuntimeFilterMessage) + mockMsg := mockMessage{tag: tag} + message.SendMessage(mockMsg, mb) + + // Also send a valid BLOOMFILTER message + rtMsg := message.RuntimeFilterMessage{ + Tag: tag, + Typ: message.RuntimeFilter_BLOOMFILTER, + Data: expectedData, + } + message.SendMessage(rtMsg, mb) + + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{ + { + Tag: tag, + UseBloomFilter: true, + }, + }, + } + + done := make(chan bool) + var result []byte + var err error + go func() { + result, err = waitBloomFilterForTableFunction(tf, proc) + done <- true + }() + + <-done + + // Should skip the mock message and return the BLOOMFILTER message + require.NoError(t, err) + require.Equal(t, expectedData, result) + }) + + t.Run("continue when message Typ is not BLOOMFILTER", func(t *testing.T) { + proc := testutil.NewProcessWithMPool(t, "", mpool.MustNewZero()) + mb := message.NewMessageBoard() + proc.SetMessageBoard(mb) + + tag := int32(400) + expectedData := []byte{11, 12, 13, 14, 15} + + // Send a message with different type + rtMsg1 := message.RuntimeFilterMessage{ + Tag: tag, + Typ: message.RuntimeFilter_IN, // not BLOOMFILTER + Data: []byte{99, 98, 97}, + } + message.SendMessage(rtMsg1, mb) + + // Send a valid BLOOMFILTER message + rtMsg2 := message.RuntimeFilterMessage{ + Tag: tag, + Typ: message.RuntimeFilter_BLOOMFILTER, + Data: expectedData, + } + message.SendMessage(rtMsg2, mb) + + tf := &TableFunction{ + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{ + { + Tag: tag, + UseBloomFilter: true, + }, + }, + } + + done := make(chan bool) + var result []byte + var err error + go func() { + result, err = waitBloomFilterForTableFunction(tf, proc) + done <- true + }() + + <-done + + // Should skip the IN message and return the BLOOMFILTER message + require.NoError(t, err) + require.Equal(t, expectedData, result) + }) +} diff --git a/pkg/sql/colexec/table_function/types.go b/pkg/sql/colexec/table_function/types.go index 36e1d02aadcaf..2676e3e3ad0ec 100644 --- a/pkg/sql/colexec/table_function/types.go +++ b/pkg/sql/colexec/table_function/types.go @@ -30,13 +30,17 @@ var _ vm.Operator = new(TableFunction) type TableFunction struct { ctr container - Rets []*plan.ColDef - Args []*plan.Expr - Attrs []string - Params []byte - FuncName string - Limit *plan.Expr - IsSingle bool + Rets []*plan.ColDef + Args []*plan.Expr + Attrs []string + Params []byte + FuncName string + Limit *plan.Expr + IsSingle bool + + // probe side runtime filter specs (including BloomFilter) + RuntimeFilterSpecs []*plan.RuntimeFilterSpec + OffsetTotal [][2]int64 CanOpt bool diff --git a/pkg/sql/colexec/types2.go b/pkg/sql/colexec/types2.go index 1a6b95a060b7e..20aedda6f17a7 100644 --- a/pkg/sql/colexec/types2.go +++ b/pkg/sql/colexec/types2.go @@ -16,7 +16,9 @@ package colexec import ( "github.com/matrixorigin/matrixone/pkg/common/morpc" + "github.com/matrixorigin/matrixone/pkg/logutil" "github.com/matrixorigin/matrixone/pkg/vm/process" + "go.uber.org/zap" ) func (srv *Server) RecordDispatchPipeline( @@ -24,15 +26,38 @@ func (srv *Server) RecordDispatchPipeline( key := generateRecordKey(session, streamID) + logutil.Debug("RecordDispatchPipeline called", + zap.Uint64("streamID", streamID), + zap.String("receiverUid", dispatchReceiver.Uid.String())) + srv.receivedRunningPipeline.Lock() defer srv.receivedRunningPipeline.Unlock() // check if sender has sent a stop running message. if v, ok := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key]; ok && v.alreadyDone { - dispatchReceiver.Lock() - dispatchReceiver.ReceiverDone = true - dispatchReceiver.Unlock() - return + // Fix: Check if this is a stale record created by CancelPipelineSending + // before RecordDispatchPipeline was called (race condition). + // If receiver is nil, it means CancelPipelineSending created this record + // when the pipeline wasn't registered yet. We should clean it up and + // allow the normal registration to proceed. + if v.receiver == nil || v.receiver.Uid != dispatchReceiver.Uid { + // This is a stale record created by CancelPipelineSending before + // RecordDispatchPipeline was called. Clean it up and proceed with + // normal registration. + logutil.Debug("RecordDispatchPipeline cleaning stale record", + zap.Uint64("streamID", streamID)) + delete(srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline, key) + } else { + // This is a legitimate cancellation - the same receiver was already registered + // and then cancelled. Set ReceiverDone to true. + logutil.Debug("RecordDispatchPipeline setting ReceiverDone=true (legitimate cancellation)", + zap.Uint64("streamID", streamID), + zap.String("existingReceiverUid", v.receiver.Uid.String())) + dispatchReceiver.Lock() + dispatchReceiver.ReceiverDone = true + dispatchReceiver.Unlock() + return + } } value := runningPipelineInfo{ @@ -43,6 +68,9 @@ func (srv *Server) RecordDispatchPipeline( } srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] = value + logutil.Debug("RecordDispatchPipeline registered successfully", + zap.Uint64("streamID", streamID), + zap.String("receiverUid", dispatchReceiver.Uid.String())) } func (srv *Server) RecordBuiltPipeline( @@ -74,29 +102,35 @@ func (srv *Server) CancelPipelineSending( key := generateRecordKey(session, streamID) + logutil.Debug("CancelPipelineSending called", + zap.Uint64("streamID", streamID)) + srv.receivedRunningPipeline.Lock() defer srv.receivedRunningPipeline.Unlock() if v, ok := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key]; ok { - v.cancelPipeline() - } else { - srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] = generateCanceledRecord() + logutil.Debug("CancelPipelineSending found existing record", + zap.Uint64("streamID", streamID), + zap.Bool("alreadyDone", v.alreadyDone), + zap.Bool("hasReceiver", v.receiver != nil), + zap.Bool("isDispatch", v.isDispatch)) + + if !v.isDispatch { + // Only cancel non-dispatch pipelines (query execution pipelines) + logutil.Debug("CancelPipelineSending canceling non-dispatch pipeline", + zap.Uint64("streamID", streamID)) + v.cancelPipeline() + } } } func (srv *Server) RemoveRelatedPipeline(session morpc.ClientSession, streamID uint64) { key := generateRecordKey(session, streamID) - srv.receivedRunningPipeline.Lock() defer srv.receivedRunningPipeline.Unlock() - delete(srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline, key) } -func generateCanceledRecord() runningPipelineInfo { - return runningPipelineInfo{alreadyDone: true} -} - func generateRecordKey(session morpc.ClientSession, streamID uint64) rpcClientItem { return rpcClientItem{tcp: session, id: streamID} } diff --git a/pkg/sql/colexec/types2_test.go b/pkg/sql/colexec/types2_test.go new file mode 100644 index 0000000000000..c67e6f4a49148 --- /dev/null +++ b/pkg/sql/colexec/types2_test.go @@ -0,0 +1,373 @@ +// Copyright 2021 Matrix Origin +// +// 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 colexec + +import ( + "context" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + + "github.com/matrixorigin/matrixone/pkg/common/morpc" + "github.com/matrixorigin/matrixone/pkg/vm/process" +) + +// mockClientSession is a simple mock implementation of morpc.ClientSession for testing +type mockClientSession struct { + remoteAddr string +} + +func (m *mockClientSession) RemoteAddress() string { + return m.remoteAddr +} + +func (m *mockClientSession) SessionCtx() context.Context { + return context.Background() +} + +func (m *mockClientSession) Write(ctx context.Context, message morpc.Message) error { + return nil +} + +func (m *mockClientSession) AsyncWrite(response morpc.Message) error { + return nil +} + +func (m *mockClientSession) Close() error { + return nil +} + +func (m *mockClientSession) CreateCache(ctx context.Context, cacheID uint64) (morpc.MessageCache, error) { + return nil, nil +} + +func (m *mockClientSession) DeleteCache(cacheID uint64) {} + +func (m *mockClientSession) GetCache(cacheID uint64) (morpc.MessageCache, error) { + return nil, nil +} + +// TestCancelPipelineSending_ShouldNotCancelDispatchReceiver tests that +// CancelPipelineSending should NOT cancel dispatch receivers when StopSending message arrives. +// This is a fix for the bug where StopSending message was incorrectly used to cancel +// dispatch receivers, causing "remote receiver is already done" errors. +func TestCancelPipelineSending_ShouldNotCancelDispatchReceiver(t *testing.T) { + // Setup: Create a server + srv := NewServer(nil) + require.NotNil(t, srv) + + // Create a mock client session + session := &mockClientSession{remoteAddr: "test-addr"} + streamID := uint64(1) + + // Create a dispatch receiver (isDispatch=true) + receiverUid := uuid.Must(uuid.NewV7()) + dispatchReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID, + Uid: receiverUid, + Cs: session, + Err: make(chan error, 1), + } + + // Step 1: Register the dispatch receiver + srv.RecordDispatchPipeline(session, streamID, dispatchReceiver) + + // Verify the receiver is registered and ReceiverDone is false + require.False(t, dispatchReceiver.ReceiverDone, "ReceiverDone should be false after registration") + + // Step 2: Call CancelPipelineSending (simulating StopSending message) + // This should NOT cancel the dispatch receiver + srv.CancelPipelineSending(session, streamID) + + // Step 3: Verify that ReceiverDone is still false + // This is the key test - before the fix, ReceiverDone would be set to true here + require.False(t, dispatchReceiver.ReceiverDone, + "ReceiverDone should remain false after CancelPipelineSending for dispatch receiver. "+ + "StopSending message should not cancel dispatch receivers that are used to receive data.") + + // Verify the receiver is still in the map + key := generateRecordKey(session, streamID) + srv.receivedRunningPipeline.Lock() + record, exists := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists, "Receiver should still be in the map") + require.NotNil(t, record.receiver, "Record should have a receiver") + require.Equal(t, receiverUid, record.receiver.Uid, "Receiver UID should match") + require.True(t, record.isDispatch, "Record should be marked as dispatch") + require.False(t, record.alreadyDone, "Record should not be marked as done") +} + +// TestRecordDispatchPipeline tests RecordDispatchPipeline function +func TestRecordDispatchPipeline(t *testing.T) { + srv := NewServer(nil) + require.NotNil(t, srv) + + session := &mockClientSession{remoteAddr: "test-addr"} + streamID := uint64(2) + + // Test 1: Normal registration + receiverUid := uuid.Must(uuid.NewV7()) + dispatchReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID, + Uid: receiverUid, + Cs: session, + Err: make(chan error, 1), + } + + srv.RecordDispatchPipeline(session, streamID, dispatchReceiver) + + // Verify the receiver is registered + key := generateRecordKey(session, streamID) + srv.receivedRunningPipeline.Lock() + record, exists := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists, "Receiver should be registered") + require.False(t, record.alreadyDone, "Record should not be marked as done") + require.True(t, record.isDispatch, "Record should be marked as dispatch") + require.Equal(t, receiverUid, record.receiver.Uid, "Receiver UID should match") + + // Test 2: Registration when alreadyDone=true and receiver==nil (should clean stale record) + streamID2 := uint64(3) + srv.receivedRunningPipeline.Lock() + srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[generateRecordKey(session, streamID2)] = runningPipelineInfo{ + alreadyDone: true, + receiver: nil, + } + srv.receivedRunningPipeline.Unlock() + + receiverUid2 := uuid.Must(uuid.NewV7()) + dispatchReceiver2 := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID2, + Uid: receiverUid2, + Cs: session, + Err: make(chan error, 1), + } + + srv.RecordDispatchPipeline(session, streamID2, dispatchReceiver2) + + // Verify stale record is cleaned and new receiver is registered + key2 := generateRecordKey(session, streamID2) + srv.receivedRunningPipeline.Lock() + record2, exists2 := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key2] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists2, "Receiver should be registered") + require.False(t, record2.alreadyDone, "Record should not be marked as done") + require.Equal(t, receiverUid2, record2.receiver.Uid, "Receiver UID should match") + + // Test 3: Registration when alreadyDone=true and receiver.Uid != dispatchReceiver.Uid (should clean stale record) + streamID3 := uint64(4) + oldReceiverUid := uuid.Must(uuid.NewV7()) + oldReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID3, + Uid: oldReceiverUid, + Cs: session, + Err: make(chan error, 1), + } + srv.receivedRunningPipeline.Lock() + srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[generateRecordKey(session, streamID3)] = runningPipelineInfo{ + alreadyDone: true, + receiver: oldReceiver, + } + srv.receivedRunningPipeline.Unlock() + + newReceiverUid := uuid.Must(uuid.NewV7()) + newDispatchReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID3, + Uid: newReceiverUid, + Cs: session, + Err: make(chan error, 1), + } + + srv.RecordDispatchPipeline(session, streamID3, newDispatchReceiver) + + // Verify stale record is cleaned and new receiver is registered + key3 := generateRecordKey(session, streamID3) + srv.receivedRunningPipeline.Lock() + record3, exists3 := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key3] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists3, "Receiver should be registered") + require.False(t, record3.alreadyDone, "Record should not be marked as done") + require.Equal(t, newReceiverUid, record3.receiver.Uid, "Receiver UID should match") + + // Test 4: Registration when alreadyDone=true and receiver.Uid == dispatchReceiver.Uid (should set ReceiverDone=true) + streamID4 := uint64(5) + sameReceiverUid := uuid.Must(uuid.NewV7()) + sameReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID4, + Uid: sameReceiverUid, + Cs: session, + Err: make(chan error, 1), + } + srv.receivedRunningPipeline.Lock() + srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[generateRecordKey(session, streamID4)] = runningPipelineInfo{ + alreadyDone: true, + receiver: sameReceiver, + } + srv.receivedRunningPipeline.Unlock() + + // Try to register the same receiver again + srv.RecordDispatchPipeline(session, streamID4, sameReceiver) + + // Verify ReceiverDone is set to true + require.True(t, sameReceiver.ReceiverDone, "ReceiverDone should be set to true when alreadyDone=true and same UID") +} + +// TestRecordBuiltPipeline tests RecordBuiltPipeline function +func TestRecordBuiltPipeline(t *testing.T) { + srv := NewServer(nil) + require.NotNil(t, srv) + + session := &mockClientSession{remoteAddr: "test-addr"} + streamID := uint64(6) + + // Test 1: Normal registration + proc := &process.Process{} + proc.Base = &process.BaseProcess{} + ctx, cancel := context.WithCancel(context.Background()) + proc.Base.GetContextBase().BuildQueryCtx(ctx) + _ = cancel // cancel is not used but needed for context + + srv.RecordBuiltPipeline(session, streamID, proc) + + // Verify the pipeline is registered + key := generateRecordKey(session, streamID) + srv.receivedRunningPipeline.Lock() + record, exists := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists, "Pipeline should be registered") + require.False(t, record.alreadyDone, "Record should not be marked as done") + require.False(t, record.isDispatch, "Record should not be marked as dispatch") + require.NotNil(t, record.queryCancel, "QueryCancel should be set") + + // Test 2: Registration when alreadyDone=true (should return early) + streamID2 := uint64(7) + srv.receivedRunningPipeline.Lock() + srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[generateRecordKey(session, streamID2)] = runningPipelineInfo{ + alreadyDone: true, + } + srv.receivedRunningPipeline.Unlock() + + proc2 := &process.Process{} + proc2.Base = &process.BaseProcess{} + ctx2, cancel2 := context.WithCancel(context.Background()) + proc2.Base.GetContextBase().BuildQueryCtx(ctx2) + _ = cancel2 // cancel2 is not used but needed for context + + srv.RecordBuiltPipeline(session, streamID2, proc2) + + // Verify the record is still the canceled one + key2 := generateRecordKey(session, streamID2) + srv.receivedRunningPipeline.Lock() + record2, exists2 := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key2] + srv.receivedRunningPipeline.Unlock() + + require.True(t, exists2, "Record should still exist") + require.True(t, record2.alreadyDone, "Record should still be marked as done") +} + +// TestCancelPipelineSending tests CancelPipelineSending function +func TestCancelPipelineSending(t *testing.T) { + srv := NewServer(nil) + require.NotNil(t, srv) + + session := &mockClientSession{remoteAddr: "test-addr"} + streamID := uint64(8) + + // Test 1: Cancel when record exists and isDispatch=false (should cancel) + proc := &process.Process{} + proc.Base = &process.BaseProcess{} + ctx, cancel := context.WithCancel(context.Background()) + proc.Base.GetContextBase().BuildQueryCtx(ctx) + + srv.RecordBuiltPipeline(session, streamID, proc) + + // Cancel the pipeline + srv.CancelPipelineSending(session, streamID) + + // Verify context is canceled + err := proc.GetQueryContextError() + require.NotNil(t, err, "Query context should be canceled") + _ = cancel // cancel is not used but needed for context + + // Test 2: Cancel when record exists and isDispatch=true (should not cancel) + streamID2 := uint64(9) + receiverUid := uuid.Must(uuid.NewV7()) + dispatchReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID2, + Uid: receiverUid, + Cs: session, + Err: make(chan error, 1), + } + + srv.RecordDispatchPipeline(session, streamID2, dispatchReceiver) + + // Cancel should not affect dispatch receiver + srv.CancelPipelineSending(session, streamID2) + + require.False(t, dispatchReceiver.ReceiverDone, "Dispatch receiver should not be canceled") +} + +// TestRemoveRelatedPipeline tests RemoveRelatedPipeline function +func TestRemoveRelatedPipeline(t *testing.T) { + srv := NewServer(nil) + require.NotNil(t, srv) + + session := &mockClientSession{remoteAddr: "test-addr"} + streamID := uint64(10) + + // Register a pipeline + receiverUid := uuid.Must(uuid.NewV7()) + dispatchReceiver := &process.WrapCs{ + ReceiverDone: false, + MsgId: streamID, + Uid: receiverUid, + Cs: session, + Err: make(chan error, 1), + } + + srv.RecordDispatchPipeline(session, streamID, dispatchReceiver) + + // Verify the receiver is registered + key := generateRecordKey(session, streamID) + srv.receivedRunningPipeline.Lock() + _, exists := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] + srv.receivedRunningPipeline.Unlock() + require.True(t, exists, "Receiver should be registered") + + // Remove the pipeline + srv.RemoveRelatedPipeline(session, streamID) + + // Verify the pipeline is removed + srv.receivedRunningPipeline.Lock() + _, existsAfter := srv.receivedRunningPipeline.fromRpcClientToRelatedPipeline[key] + srv.receivedRunningPipeline.Unlock() + require.False(t, existsAfter, "Pipeline should be removed") + + // Test removing non-existent pipeline (should not panic) + srv.RemoveRelatedPipeline(session, streamID+1) +} diff --git a/pkg/sql/compile/operator.go b/pkg/sql/compile/operator.go index 103baeafa06e7..44c4337c35587 100644 --- a/pkg/sql/compile/operator.go +++ b/pkg/sql/compile/operator.go @@ -1025,6 +1025,8 @@ func constructTableFunction(n *plan.Node, qry *plan.Query) *table_function.Table arg.Params = n.TableDef.TblFunc.Param arg.IsSingle = n.TableDef.TblFunc.IsSingle arg.Limit = n.Limit + // probe side runtime filter specs + arg.RuntimeFilterSpecs = n.RuntimeFilterProbeList return arg } diff --git a/pkg/sql/compile/scope.go b/pkg/sql/compile/scope.go index 0d20e83c4d999..3fd849dd0a114 100644 --- a/pkg/sql/compile/scope.go +++ b/pkg/sql/compile/scope.go @@ -1072,6 +1072,17 @@ func (s *Scope) buildReaders(c *Compile) (readers []engine.Reader, err error) { crs := new(perfcounter.CounterSet) newCtx := perfcounter.AttachS3RequestKey(ctx, crs) + hint := engine.FilterHint{} + // Pass runtime BloomFilter to reader via FilterHint (only for ivf entries table). + if n := s.DataSource.node; n != nil && n.TableDef != nil && + n.TableDef.TableType == catalog.SystemSI_IVFFLAT_TblType_Entries { + if bfVal := c.proc.Ctx.Value(defines.IvfBloomFilter{}); bfVal != nil { + if bf, ok := bfVal.([]byte); ok && len(bf) > 0 { + hint.BloomFilter = bf + } + } + } + readers, err = s.DataSource.Rel.BuildReaders( newCtx, c.proc, @@ -1081,7 +1092,7 @@ func (s *Scope) buildReaders(c *Compile) (readers []engine.Reader, err error) { s.TxnOffset, len(s.DataSource.OrderBy) > 0, engine.Policy_CheckAll, - engine.FilterHint{}, + hint, ) stats.AddScopePrepareS3Request(statistic.S3Request{ @@ -1135,6 +1146,16 @@ func (s *Scope) buildReaders(c *Compile) (readers []engine.Reader, err error) { crs := new(perfcounter.CounterSet) newCtx := perfcounter.AttachS3RequestKey(ctx, crs) + hint := engine.FilterHint{} + if n := s.DataSource.node; n != nil && n.TableDef != nil && + n.TableDef.TableType == catalog.SystemSI_IVFFLAT_TblType_Entries { + if bfVal := c.proc.Ctx.Value(defines.IvfBloomFilter{}); bfVal != nil { + if bf, ok := bfVal.([]byte); ok && len(bf) > 0 { + hint.BloomFilter = bf + } + } + } + mainRds, err = s.DataSource.Rel.BuildReaders( newCtx, c.proc, @@ -1144,7 +1165,7 @@ func (s *Scope) buildReaders(c *Compile) (readers []engine.Reader, err error) { s.TxnOffset, len(s.DataSource.OrderBy) > 0, engine.Policy_CheckAll, - engine.FilterHint{}, + hint, ) if err != nil { return diff --git a/pkg/sql/compile/scope_test.go b/pkg/sql/compile/scope_test.go index f1c3bc2b34771..6a8308d88245e 100644 --- a/pkg/sql/compile/scope_test.go +++ b/pkg/sql/compile/scope_test.go @@ -591,3 +591,268 @@ func TestScopeGetRelDataError(t *testing.T) { err := s.getRelData(c, nil) require.Error(t, err) } + +// mockRelation is a mock Relation that captures the FilterHint passed to BuildReaders +type mockRelationForBloomFilter struct { + engine.Relation + capturedHint engine.FilterHint +} + +func (m *mockRelationForBloomFilter) BuildReaders( + ctx context.Context, + proc any, + expr *plan.Expr, + relData engine.RelData, + num int, + txnOffset int, + orderBy bool, + policy engine.TombstoneApplyPolicy, + filterHint engine.FilterHint, +) ([]engine.Reader, error) { + m.capturedHint = filterHint + return []engine.Reader{}, nil +} + +func TestBuildReadersBloomFilterHint(t *testing.T) { + t.Run("BloomFilter set when node is IVFFLAT Entries and context has bloom filter", func(t *testing.T) { + proc := testutil.NewProcess(t) + expectedBloomFilter := []byte{1, 2, 3, 4, 5} + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, expectedBloomFilter) + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: &plan.TableDef{ + TableType: catalog.SystemSI_IVFFLAT_TblType_Entries, + }, + }, + FilterExpr: nil, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + // Use MakeFalseExpr to make emptyScan = true, skipping getRelData + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + s.DataSource.RuntimeFilterSpecs = []*plan.RuntimeFilterSpec{} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Equal(t, expectedBloomFilter, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when node is nil", func(t *testing.T) { + proc := testutil.NewProcess(t) + expectedBloomFilter := []byte{1, 2, 3, 4, 5} + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, expectedBloomFilter) + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: nil, // node is nil + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when TableDef is nil", func(t *testing.T) { + proc := testutil.NewProcess(t) + expectedBloomFilter := []byte{1, 2, 3, 4, 5} + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, expectedBloomFilter) + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: nil, // TableDef is nil + }, + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when TableType is not IVFFLAT Entries", func(t *testing.T) { + proc := testutil.NewProcess(t) + expectedBloomFilter := []byte{1, 2, 3, 4, 5} + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, expectedBloomFilter) + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: &plan.TableDef{ + TableType: catalog.SystemSI_IVFFLAT_TblType_Metadata, // different type + }, + }, + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when context has no IvfBloomFilter", func(t *testing.T) { + proc := testutil.NewProcess(t) + // No IvfBloomFilter in context + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: &plan.TableDef{ + TableType: catalog.SystemSI_IVFFLAT_TblType_Entries, + }, + }, + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when context value is not []byte", func(t *testing.T) { + proc := testutil.NewProcess(t) + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, "not a byte slice") + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: &plan.TableDef{ + TableType: catalog.SystemSI_IVFFLAT_TblType_Entries, + }, + }, + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) + + t.Run("BloomFilter not set when context value is empty []byte", func(t *testing.T) { + proc := testutil.NewProcess(t) + ctx := context.WithValue(proc.Ctx, defines.IvfBloomFilter{}, []byte{}) // empty byte slice + proc.Ctx = ctx + + mockRel := &mockRelationForBloomFilter{} + s := &Scope{ + Proc: proc, + DataSource: &Source{ + Rel: mockRel, + node: &plan.Node{ + TableDef: &plan.TableDef{ + TableType: catalog.SystemSI_IVFFLAT_TblType_Entries, + }, + }, + FilterExpr: nil, + FilterList: []*plan.Expr{}, + RuntimeFilterSpecs: []*plan.RuntimeFilterSpec{}, + }, + NodeInfo: engine.Node{ + Mcpu: 1, + }, + TxnOffset: 0, + } + + c := NewMockCompile(t) + c.proc = proc + s.DataSource.FilterList = []*plan.Expr{plan2.MakeFalseExpr()} + + readers, err := s.buildReaders(c) + require.NoError(t, err) + require.NotNil(t, readers) + require.Nil(t, mockRel.capturedHint.BloomFilter) + }) +} diff --git a/pkg/sql/parsers/dialect/mysql/Makefile b/pkg/sql/parsers/dialect/mysql/Makefile index 3768a5ace7e49..fc98194caae51 100644 --- a/pkg/sql/parsers/dialect/mysql/Makefile +++ b/pkg/sql/parsers/dialect/mysql/Makefile @@ -1,5 +1,17 @@ +# Note: There are currently 7 shift/reduce conflicts that are pending resolution. +# The build will fail if new conflicts are introduced (conflicts > 7). mysql_sql.go: mysql_sql.y - go run github.com/matrixorigin/matrixone/pkg/sql/parsers/goyacc -o mysql_sql.go mysql_sql.y + @output=$$(go run github.com/matrixorigin/matrixone/pkg/sql/parsers/goyacc -o mysql_sql.go mysql_sql.y 2>&1); \ + echo "$$output"; \ + conflicts=$$(echo "$$output" | grep "conflicts:" | sed -E 's/.*conflicts: ([0-9]+).*/\1/'); \ + if [ -z "$$conflicts" ]; then \ + conflicts=0; \ + fi; \ + if [ "$$conflicts" -gt 7 ]; then \ + rm -f mysql_sql.go; \ + echo "Error: New conflicts detected! Current conflicts: $$conflicts (expected max: 7)" >&2; \ + exit 1; \ + fi gofmt -w mysql_sql.go rm -f y.output diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.go b/pkg/sql/parsers/dialect/mysql/mysql_sql.go index 5c41392469395..10aa86639ccad 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.go @@ -1358,7 +1358,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line mysql_sql.y:13177 +//line mysql_sql.y:13233 //line yacctab:1 var yyExca = [...]int{ @@ -1370,9 +1370,9 @@ var yyExca = [...]int{ 22, 826, -2, 819, -1, 169, - 246, 1283, - 248, 1156, - -2, 1211, + 246, 1285, + 248, 1158, + -2, 1213, -1, 196, 44, 649, 248, 649, @@ -1381,274 +1381,258 @@ var yyExca = [...]int{ 490, 649, -2, 684, -1, 236, - 676, 2060, + 676, 2062, -2, 548, -1, 550, - 676, 2184, + 676, 2186, -2, 422, -1, 608, - 676, 2243, + 676, 2245, -2, 420, -1, 609, - 676, 2244, + 676, 2246, -2, 421, -1, 610, - 676, 2245, + 676, 2247, -2, 423, -1, 752, 327, 189, 462, 189, 463, 189, - -2, 1958, + -2, 1960, -1, 819, - 86, 1742, - -2, 2120, + 86, 1744, + -2, 2122, -1, 820, - 86, 1761, - -2, 2091, + 86, 1763, + -2, 2093, -1, 824, - 86, 1762, - -2, 2119, + 86, 1764, + -2, 2121, -1, 858, - 86, 1669, - -2, 2324, + 86, 1671, + -2, 2326, -1, 859, - 86, 1670, - -2, 2323, + 86, 1672, + -2, 2325, -1, 860, - 86, 1671, - -2, 2313, + 86, 1673, + -2, 2315, -1, 861, - 86, 2285, - -2, 2306, + 86, 2287, + -2, 2308, -1, 862, - 86, 2286, - -2, 2307, + 86, 2288, + -2, 2309, -1, 863, - 86, 2287, - -2, 2315, + 86, 2289, + -2, 2317, -1, 864, - 86, 2288, - -2, 2295, + 86, 2290, + -2, 2297, -1, 865, - 86, 2289, - -2, 2304, + 86, 2291, + -2, 2306, -1, 866, - 86, 2290, - -2, 2316, + 86, 2292, + -2, 2318, -1, 867, - 86, 2291, - -2, 2317, + 86, 2293, + -2, 2319, -1, 868, - 86, 2292, - -2, 2322, + 86, 2294, + -2, 2324, -1, 869, - 86, 2293, - -2, 2327, + 86, 2295, + -2, 2329, -1, 870, - 86, 2294, - -2, 2328, + 86, 2296, + -2, 2330, -1, 871, - 86, 1738, - -2, 2158, + 86, 1740, + -2, 2160, -1, 872, - 86, 1739, - -2, 1942, + 86, 1741, + -2, 1944, -1, 873, - 86, 1740, - -2, 2167, + 86, 1742, + -2, 2169, -1, 874, - 86, 1741, - -2, 1951, + 86, 1743, + -2, 1953, -1, 876, - 86, 1744, - -2, 1959, - -1, 878, 86, 1746, - -2, 2191, + -2, 1961, + -1, 878, + 86, 1748, + -2, 2193, -1, 880, - 86, 1749, - -2, 1980, - -1, 882, 86, 1751, - -2, 2203, + -2, 1982, + -1, 882, + 86, 1753, + -2, 2205, -1, 883, - 86, 1752, - -2, 2202, + 86, 1754, + -2, 2204, -1, 884, - 86, 1753, - -2, 2027, + 86, 1755, + -2, 2029, -1, 885, - 86, 1754, - -2, 2115, + 86, 1756, + -2, 2117, -1, 888, - 86, 1757, - -2, 2214, - -1, 890, 86, 1759, - -2, 2217, - -1, 891, - 86, 1760, + -2, 2216, + -1, 890, + 86, 1761, -2, 2219, + -1, 891, + 86, 1762, + -2, 2221, -1, 892, - 86, 1763, - -2, 2227, + 86, 1765, + -2, 2229, -1, 893, - 86, 1764, - -2, 2100, + 86, 1766, + -2, 2102, -1, 894, - 86, 1765, - -2, 2145, + 86, 1767, + -2, 2147, -1, 895, - 86, 1766, - -2, 2110, + 86, 1768, + -2, 2112, -1, 896, - 86, 1767, - -2, 2135, + 86, 1769, + -2, 2137, -1, 907, - 86, 1647, - -2, 2318, - -1, 908, - 86, 1648, - -2, 2319, - -1, 909, 86, 1649, -2, 2320, + -1, 908, + 86, 1650, + -2, 2321, + -1, 909, + 86, 1651, + -2, 2322, -1, 1015, 485, 684, 486, 684, -2, 650, -1, 1066, - 128, 1942, - 139, 1942, - 159, 1942, - -2, 1915, + 128, 1944, + 139, 1944, + 159, 1944, + -2, 1917, -1, 1187, - 22, 853, + 22, 855, -2, 802, -1, 1298, 11, 826, 22, 826, - -2, 1524, + -2, 1526, -1, 1382, - 22, 853, + 22, 855, -2, 802, -1, 1752, - 86, 1814, - -2, 2117, + 86, 1816, + -2, 2119, -1, 1753, - 86, 1815, - -2, 2118, + 86, 1817, + -2, 2120, -1, 2382, - 87, 1026, - -2, 1032, + 87, 1028, + -2, 1034, -1, 2398, - 111, 1203, - 155, 1203, - 195, 1203, - 198, 1203, - 288, 1203, - -2, 1196, - -1, 2563, + 111, 1205, + 155, 1205, + 195, 1205, + 198, 1205, + 288, 1205, + -2, 1198, + -1, 2565, 11, 826, 22, 826, - -2, 967, - -1, 2597, - 87, 1901, - 160, 1901, - -2, 2102, - -1, 2598, - 87, 1901, - 160, 1901, - -2, 2101, + -2, 969, -1, 2599, - 87, 1877, - 160, 1877, - -2, 2088, + 87, 1903, + 160, 1903, + -2, 2104, -1, 2600, - 87, 1878, - 160, 1878, - -2, 2093, + 87, 1903, + 160, 1903, + -2, 2103, -1, 2601, 87, 1879, 160, 1879, - -2, 2015, + -2, 2090, -1, 2602, 87, 1880, 160, 1880, - -2, 2008, + -2, 2095, -1, 2603, 87, 1881, 160, 1881, - -2, 1932, + -2, 2017, -1, 2604, 87, 1882, 160, 1882, - -2, 2090, + -2, 2010, -1, 2605, 87, 1883, 160, 1883, - -2, 2013, + -2, 1934, -1, 2606, 87, 1884, 160, 1884, - -2, 2007, + -2, 2092, -1, 2607, 87, 1885, 160, 1885, - -2, 1995, + -2, 2015, -1, 2608, - 87, 1901, - 160, 1901, - -2, 1996, + 87, 1886, + 160, 1886, + -2, 2009, -1, 2609, - 87, 1901, - 160, 1901, + 87, 1887, + 160, 1887, -2, 1997, + -1, 2610, + 87, 1903, + 160, 1903, + -2, 1998, -1, 2611, - 87, 1890, - 160, 1890, - -2, 2135, - -1, 2612, - 87, 1867, - 160, 1867, - -2, 2120, + 87, 1903, + 160, 1903, + -2, 1999, -1, 2613, - 87, 1899, - 160, 1899, - -2, 2091, + 87, 1892, + 160, 1892, + -2, 2137, -1, 2614, - 87, 1899, - 160, 1899, - -2, 2119, + 87, 1869, + 160, 1869, + -2, 2122, -1, 2615, - 87, 1899, - 160, 1899, - -2, 1960, + 87, 1901, + 160, 1901, + -2, 2093, -1, 2616, - 87, 1897, - 160, 1897, - -2, 2110, + 87, 1901, + 160, 1901, + -2, 2121, -1, 2617, - 87, 1894, - 160, 1894, - -2, 1985, + 87, 1901, + 160, 1901, + -2, 1962, -1, 2618, - 86, 1848, - 87, 1848, - 160, 1848, - 420, 1848, - 421, 1848, - 422, 1848, - -2, 1931, + 87, 1899, + 160, 1899, + -2, 2112, -1, 2619, - 86, 1849, - 87, 1849, - 160, 1849, - 420, 1849, - 421, 1849, - 422, 1849, - -2, 1933, + 87, 1896, + 160, 1896, + -2, 1987, -1, 2620, 86, 1850, 87, 1850, @@ -1656,842 +1640,1018 @@ var yyExca = [...]int{ 420, 1850, 421, 1850, 422, 1850, - -2, 2163, + -2, 1933, -1, 2621, + 86, 1851, + 87, 1851, + 160, 1851, + 420, 1851, + 421, 1851, + 422, 1851, + -2, 1935, + -1, 2622, 86, 1852, 87, 1852, 160, 1852, 420, 1852, 421, 1852, 422, 1852, - -2, 2092, - -1, 2622, + -2, 2165, + -1, 2623, 86, 1854, 87, 1854, 160, 1854, 420, 1854, 421, 1854, 422, 1854, - -2, 2070, - -1, 2623, + -2, 2094, + -1, 2624, 86, 1856, 87, 1856, 160, 1856, 420, 1856, 421, 1856, 422, 1856, - -2, 2014, - -1, 2624, + -2, 2072, + -1, 2625, 86, 1858, 87, 1858, 160, 1858, 420, 1858, 421, 1858, 422, 1858, - -2, 1991, - -1, 2625, - 86, 1859, - 87, 1859, - 160, 1859, - 420, 1859, - 421, 1859, - 422, 1859, - -2, 1992, + -2, 2016, -1, 2626, + 86, 1860, + 87, 1860, + 160, 1860, + 420, 1860, + 421, 1860, + 422, 1860, + -2, 1993, + -1, 2627, 86, 1861, 87, 1861, 160, 1861, 420, 1861, 421, 1861, 422, 1861, - -2, 1930, - -1, 2627, - 87, 1904, - 160, 1904, - 420, 1904, - 421, 1904, - 422, 1904, - -2, 1965, + -2, 1994, -1, 2628, - 87, 1904, - 160, 1904, - 420, 1904, - 421, 1904, - 422, 1904, - -2, 1981, + 86, 1863, + 87, 1863, + 160, 1863, + 420, 1863, + 421, 1863, + 422, 1863, + -2, 1932, -1, 2629, - 87, 1907, - 160, 1907, - 420, 1907, - 421, 1907, - 422, 1907, - -2, 1961, + 87, 1906, + 160, 1906, + 420, 1906, + 421, 1906, + 422, 1906, + -2, 1967, -1, 2630, - 87, 1907, - 160, 1907, - 420, 1907, - 421, 1907, - 422, 1907, - -2, 2030, + 87, 1906, + 160, 1906, + 420, 1906, + 421, 1906, + 422, 1906, + -2, 1983, -1, 2631, - 87, 1904, - 160, 1904, - 420, 1904, - 421, 1904, - 422, 1904, - -2, 2052, - -1, 2863, - 111, 1203, - 155, 1203, - 195, 1203, - 198, 1203, - 288, 1203, - -2, 1197, - -1, 2883, + 87, 1909, + 160, 1909, + 420, 1909, + 421, 1909, + 422, 1909, + -2, 1963, + -1, 2632, + 87, 1909, + 160, 1909, + 420, 1909, + 421, 1909, + 422, 1909, + -2, 2032, + -1, 2633, + 87, 1906, + 160, 1906, + 420, 1906, + 421, 1906, + 422, 1906, + -2, 2054, + -1, 2865, + 111, 1205, + 155, 1205, + 195, 1205, + 198, 1205, + 288, 1205, + -2, 1199, + -1, 2885, 84, 746, 160, 746, - -2, 1398, - -1, 3325, - 198, 1203, - 312, 1487, - -2, 1459, - -1, 3524, - 111, 1203, - 155, 1203, - 195, 1203, - 198, 1203, - -2, 1339, - -1, 3527, - 111, 1203, - 155, 1203, - 195, 1203, - 198, 1203, - -2, 1339, - -1, 3539, + -2, 1400, + -1, 3331, + 198, 1205, + 312, 1489, + -2, 1461, + -1, 3530, + 111, 1205, + 155, 1205, + 195, 1205, + 198, 1205, + -2, 1341, + -1, 3533, + 111, 1205, + 155, 1205, + 195, 1205, + 198, 1205, + -2, 1341, + -1, 3545, 84, 746, 160, 746, - -2, 1398, - -1, 3560, - 198, 1203, - 312, 1487, - -2, 1460, - -1, 3722, - 111, 1203, - 155, 1203, - 195, 1203, - 198, 1203, - -2, 1340, - -1, 3748, - 87, 1301, - 160, 1301, - -2, 1203, - -1, 3896, - 87, 1301, - 160, 1301, - -2, 1203, - -1, 4069, - 87, 1305, - 160, 1305, - -2, 1203, - -1, 4124, - 87, 1306, - 160, 1306, - -2, 1203, + -2, 1400, + -1, 3567, + 198, 1205, + 312, 1489, + -2, 1462, + -1, 3729, + 111, 1205, + 155, 1205, + 195, 1205, + 198, 1205, + -2, 1342, + -1, 3756, + 87, 1303, + 160, 1303, + -2, 1205, + -1, 3904, + 87, 1303, + 160, 1303, + -2, 1205, + -1, 4077, + 87, 1307, + 160, 1307, + -2, 1205, + -1, 4132, + 87, 1308, + 160, 1308, + -2, 1205, } const yyPrivate = 57344 -const yyLast = 57024 +const yyLast = 56694 var yyAct = [...]int{ - 786, 762, 4177, 788, 4146, 2914, 225, 4169, 1652, 2026, - 4073, 1732, 3545, 3644, 4079, 4072, 3965, 4080, 3896, 3311, - 3988, 3943, 2137, 771, 4023, 3345, 3421, 3776, 3574, 1728, - 2908, 764, 3841, 1564, 3874, 3934, 1334, 3422, 3895, 3966, - 3710, 3810, 1792, 2820, 816, 1065, 1496, 651, 2911, 3865, - 3944, 1188, 3648, 3505, 3946, 3510, 3639, 2449, 1779, 3561, - 3729, 1794, 1971, 1182, 670, 1735, 676, 676, 1502, 2886, - 3266, 3320, 676, 694, 703, 3281, 3719, 703, 3692, 760, - 3419, 2595, 3242, 3029, 3724, 3528, 3470, 3269, 2121, 2124, - 2139, 3030, 37, 3028, 3497, 3006, 2937, 69, 3340, 3530, - 2557, 3329, 2162, 3025, 3322, 210, 2825, 3464, 2086, 2722, - 2593, 1797, 3098, 715, 3058, 2851, 3384, 2236, 2194, 2452, - 2687, 3016, 3249, 3243, 3247, 1986, 1557, 3245, 711, 3328, - 3291, 2410, 1178, 3240, 2864, 759, 2220, 142, 2350, 2665, - 754, 3206, 1653, 2349, 3244, 3146, 3072, 2647, 2202, 2195, - 1642, 2541, 2232, 2167, 2203, 946, 1637, 1890, 2840, 2835, - 2117, 2558, 1645, 2939, 2231, 700, 2536, 2919, 2450, 2016, - 1641, 2878, 986, 221, 8, 6, 1461, 2398, 2409, 1947, - 2591, 220, 7, 1793, 2266, 36, 2090, 1428, 1126, 1726, - 2233, 763, 1604, 1674, 1573, 669, 1542, 2389, 1506, 2445, - 1536, 651, 753, 1485, 2087, 1786, 2759, 2392, 1717, 1204, - 2352, 23, 2201, 772, 761, 2198, 1656, 1766, 2183, 1611, - 1943, 1731, 1985, 708, 1471, 225, 1058, 225, 1946, 1117, - 1118, 2565, 1725, 1481, 2537, 985, 676, 1541, 1538, 685, - 1404, 911, 1024, 1798, 211, 1497, 717, 1409, 718, 1630, - 1505, 1097, 962, 1380, 1595, 207, 24, 983, 25, 17, - 714, 702, 10, 27, 1010, 203, 968, 1467, 1335, 976, - 2240, 977, 2758, 3953, 913, 914, 1266, 1267, 1268, 1265, - 3862, 2795, 1059, 755, 2795, 2795, 16, 1266, 1267, 1268, - 1265, 1266, 1267, 1268, 1265, 2567, 1114, 3542, 3430, 3298, - 3216, 1092, 1074, 3215, 3115, 3114, 2250, 1913, 1183, 3681, - 957, 14, 1405, 3513, 1184, 2710, 3414, 2653, 2651, 672, - 2650, 2648, 1406, 1903, 971, 1618, 967, 1614, 1110, 650, - 1113, 209, 1115, 1109, 671, 681, 699, 2348, 706, 1399, - 1540, 15, 1071, 1464, 1465, 1466, 33, 1044, 3921, 1373, - 1110, 2138, 934, 932, 1667, 1110, 3213, 2362, 2355, 695, - 1910, 1408, 3199, 688, 3196, 3201, 3198, 4158, 1183, 1519, - 1897, 1395, 1616, 1093, 1266, 1267, 1268, 1265, 3637, 2787, - 2785, 755, 949, 8, 697, 1108, 677, 3094, 3092, 2172, - 1073, 7, 1266, 1267, 1268, 1265, 3929, 3817, 3811, 3640, - 3420, 2217, 3948, 1329, 2197, 912, 3175, 2189, 2490, 4183, - 3942, 4155, 3475, 3825, 698, 923, 3881, 208, 1264, 696, - 1419, 3564, 4051, 2789, 4108, 3654, 3473, 208, 1228, 3697, - 2696, 3693, 2237, 3529, 2704, 2401, 1660, 1651, 3940, 208, - 65, 199, 170, 208, 65, 199, 170, 3849, 1087, 1082, - 1077, 1081, 1085, 933, 931, 3488, 2740, 973, 3823, 966, - 3882, 2369, 3576, 3999, 1581, 1414, 1657, 1410, 970, 969, - 1413, 1412, 208, 934, 208, 3567, 1090, 208, 1069, 1070, - 1080, 1420, 932, 1075, 3173, 2248, 3562, 1453, 1665, 958, - 1659, 3584, 3585, 2819, 713, 1039, 1037, 3563, 1038, 756, - 204, 930, 1718, 1436, 1683, 1722, 208, 208, 2815, 965, - 1664, 2400, 204, 3023, 2393, 2585, 204, 1979, 208, 1921, - 857, 3118, 1698, 141, 924, 1672, 3106, 1434, 975, 1721, - 2871, 1088, 1263, 964, 3568, 3851, 2586, 963, 1515, 1919, - 1543, 1516, 1545, 951, 3200, 204, 3197, 204, 3066, 3067, - 204, 1091, 3065, 2572, 2100, 1669, 2571, 2101, 2102, 2573, - 956, 2134, 1493, 208, 65, 199, 170, 141, 2817, 2666, - 208, 65, 199, 170, 208, 65, 199, 170, 1078, 1671, - 2869, 1236, 1033, 2812, 1238, 4048, 902, 954, 901, 903, - 904, 204, 905, 906, 1925, 1926, 2000, 1045, 208, 65, - 199, 170, 1089, 2837, 3951, 3315, 1734, 1503, 1504, 1256, - 1501, 1261, 1239, 2838, 1500, 1503, 1504, 1617, 1615, 1068, - 3313, 1067, 2816, 1243, 1041, 974, 1244, 3951, 4037, 3950, - 2872, 1723, 3583, 2790, 2453, 1199, 204, 2813, 2337, 1196, - 1518, 3949, 1079, 204, 4083, 4084, 1977, 204, 3950, 4036, - 4044, 955, 4107, 1435, 1246, 1720, 3932, 3664, 3099, 3572, - 3949, 4035, 2836, 4150, 4151, 4025, 4028, 169, 197, 206, - 198, 204, 3814, 2691, 676, 676, 1193, 2482, 2252, 4053, - 4054, 3569, 3573, 3571, 3570, 676, 1192, 3423, 1043, 3423, - 196, 4025, 2118, 4049, 4050, 2961, 4057, 4056, 4055, 4058, - 3962, 2843, 1207, 1210, 3437, 703, 703, 3100, 676, 3101, - 1232, 1738, 3935, 3936, 3937, 3938, 2108, 1713, 3702, 1086, - 3498, 2244, 1111, 1112, 3262, 2524, 3503, 1116, 972, 3136, - 927, 1120, 3578, 3579, 3017, 2388, 1234, 2180, 2531, 3853, - 3854, 1624, 1623, 974, 1207, 1210, 3586, 1191, 1237, 1240, - 2822, 4046, 1241, 3134, 712, 1083, 2701, 2249, 1084, 1259, - 1260, 1258, 2488, 2818, 2788, 1042, 1491, 961, 195, 1231, - 3638, 1306, 1719, 1211, 1233, 3093, 2527, 2528, 2814, 3011, - 1398, 2526, 700, 700, 700, 3586, 3673, 1978, 3952, 1922, - 1074, 1202, 1529, 3858, 3699, 3861, 3440, 3565, 2797, 3140, - 2794, 2588, 3474, 3577, 3256, 928, 1437, 2534, 1517, 1920, - 1185, 3267, 1184, 3663, 1184, 1211, 1242, 4082, 1192, 1253, - 668, 3665, 4116, 1184, 3804, 3601, 1223, 3279, 2874, 3260, - 1071, 3981, 2132, 2133, 2238, 2112, 2238, 3116, 2238, 1254, - 1255, 3598, 3886, 1744, 1747, 1748, 1737, 1736, 3113, 1338, - 3878, 1235, 2271, 3655, 1745, 3341, 3342, 2239, 1094, 929, - 3343, 1076, 3344, 1074, 1110, 1110, 1110, 950, 1110, 3317, - 948, 2255, 2257, 2258, 3292, 1110, 3976, 2879, 1073, 1339, - 3880, 1110, 3221, 1184, 3477, 3257, 3258, 701, 2251, 2400, - 935, 749, 4052, 1245, 751, 1248, 705, 2649, 1249, 750, - 704, 3259, 3021, 1071, 1040, 1212, 2395, 3833, 1300, 3834, - 3678, 3679, 3680, 3591, 3207, 1619, 3967, 1209, 1208, 3983, - 3254, 3546, 3989, 3805, 3312, 3828, 1251, 1401, 1403, 2913, - 1407, 2909, 2910, 3582, 2913, 3553, 1187, 2379, 3484, 1480, - 3268, 3347, 3847, 3687, 1424, 912, 3824, 3481, 1427, 66, - 3230, 1073, 1433, 699, 699, 699, 1186, 1070, 1220, 1209, - 1208, 2786, 1378, 3836, 1406, 1383, 1216, 1217, 3476, 1406, - 171, 2522, 1666, 1222, 3698, 3602, 695, 695, 695, 2705, - 171, 1302, 1303, 1304, 1305, 986, 3852, 1307, 1708, 205, - 3961, 1709, 171, 1180, 1411, 3835, 171, 3767, 4189, 2500, - 926, 697, 697, 697, 1503, 1504, 3483, 1201, 1492, 3581, - 2499, 701, 3651, 3756, 1198, 3887, 3268, 1214, 701, 1503, - 1504, 2849, 701, 3879, 1247, 171, 2588, 171, 4172, 1553, - 171, 698, 698, 698, 1552, 2842, 696, 696, 696, 2455, - 676, 1478, 976, 1531, 977, 1221, 701, 676, 1416, 2119, - 3762, 651, 651, 1195, 1197, 1200, 1499, 1477, 3263, 171, - 171, 651, 651, 1252, 3137, 1568, 1568, 3018, 676, 1476, - 2468, 171, 2530, 66, 3855, 3990, 2448, 2471, 2520, 2521, - 66, 1495, 1494, 3900, 66, 4045, 3866, 1418, 1250, 703, - 1596, 670, 2846, 2847, 1566, 1566, 1607, 1350, 1351, 1570, - 3321, 2962, 1746, 2963, 2964, 1179, 2950, 2845, 66, 3703, - 3195, 225, 3318, 2951, 2952, 2953, 171, 4071, 2491, 3531, - 651, 1575, 2448, 171, 1297, 3635, 1429, 171, 2990, 713, - 2256, 2109, 1714, 2465, 2470, 2244, 3346, 1430, 1431, 4022, - 1539, 3255, 1440, 1441, 1442, 1443, 1444, 3471, 1446, 3060, - 3062, 171, 3341, 3342, 1452, 1228, 3833, 3426, 3834, 3777, - 3778, 3779, 3783, 3781, 3782, 3784, 3780, 1382, 1530, 4173, - 1384, 3337, 1649, 3077, 3078, 2697, 2577, 1654, 2486, 2353, - 2454, 2241, 2107, 2084, 1663, 2456, 1426, 2458, 1445, 1562, - 1563, 2469, 2855, 2859, 2860, 2861, 2856, 2858, 2857, 1906, - 1482, 1486, 1486, 1486, 3375, 3139, 2399, 1487, 1488, 1451, - 1450, 1449, 3836, 1448, 1696, 3338, 3899, 1473, 1046, 1699, - 1439, 707, 3491, 1034, 3769, 1482, 1482, 2380, 1568, 3465, - 1568, 1192, 2959, 2267, 1438, 1463, 2681, 3829, 1673, 2457, - 978, 3830, 1460, 1458, 3835, 1227, 980, 981, 982, 2809, - 2111, 2253, 2254, 2372, 3148, 3147, 1423, 1269, 1470, 1929, - 1520, 1521, 1928, 940, 947, 1299, 1479, 3276, 3758, 1415, - 2371, 1658, 3757, 1489, 1309, 1911, 1074, 1507, 1670, 1927, - 1510, 1508, 1509, 1074, 1511, 1512, 1597, 1513, 936, 3763, - 3764, 700, 1733, 2512, 700, 700, 1625, 937, 1568, 4070, - 1318, 975, 1551, 4170, 4171, 1639, 1640, 1036, 1707, 3730, - 1035, 2981, 2982, 1662, 944, 1192, 1796, 4185, 1644, 942, - 941, 1648, 2459, 3061, 1582, 3297, 1576, 1780, 1827, 1828, - 1845, 1831, 1647, 1547, 1549, 1588, 1034, 4191, 940, 1846, - 681, 1905, 4179, 1560, 1561, 2374, 2373, 2464, 1608, 2955, - 1594, 2462, 1853, 1472, 1855, 1609, 1856, 1857, 1858, 1754, - 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, - 1765, 1417, 1421, 1422, 2391, 1777, 1778, 1628, 2305, 1631, - 1632, 2304, 1730, 2991, 2993, 2994, 2995, 2992, 1693, 939, - 2246, 1633, 1634, 3427, 942, 941, 943, 1192, 2954, 2956, - 3277, 2885, 1620, 4032, 1690, 1691, 1264, 1749, 1681, 1914, - 1711, 1684, 1915, 2884, 1917, 4180, 3381, 1472, 676, 676, - 1036, 4167, 3339, 1035, 1854, 1888, 1930, 1932, 1907, 1933, - 4126, 1935, 1936, 1830, 1676, 670, 1596, 2588, 2980, 4094, - 1047, 1944, 1568, 1949, 1950, 4091, 1952, 1531, 676, 1727, - 1189, 4085, 3377, 676, 1264, 2555, 1568, 1189, 1899, 4067, - 986, 1715, 699, 1972, 1228, 699, 699, 1835, 1836, 1837, - 2668, 1891, 1705, 1724, 1701, 1704, 1568, 1729, 1700, 1706, - 1851, 3494, 1531, 1852, 1844, 695, 3829, 694, 695, 695, - 3945, 4016, 2390, 1034, 4127, 2556, 3439, 1695, 4015, 2342, - 1865, 1866, 1703, 4127, 2696, 1768, 1694, 1999, 1775, 1776, - 697, 3351, 4095, 697, 697, 3349, 2006, 2006, 4092, 1531, - 1887, 1531, 1531, 2828, 2281, 676, 676, 1702, 2073, 1944, - 2077, 4009, 4068, 1568, 2081, 2082, 3984, 2485, 1226, 2097, - 698, 651, 3972, 698, 698, 696, 2829, 2830, 696, 696, - 2161, 1266, 1267, 1268, 1265, 651, 2885, 1568, 1951, 3381, - 1716, 3236, 1682, 1225, 1264, 1685, 1686, 1266, 1267, 1268, - 1265, 1264, 1953, 3919, 3918, 3205, 1894, 1036, 3203, 2003, - 1035, 3913, 3912, 2556, 676, 1944, 1568, 2556, 2144, 3080, - 676, 676, 676, 711, 711, 1606, 1859, 3171, 3911, 1264, - 2154, 2155, 2156, 2157, 2281, 3910, 1379, 2163, 2791, 2246, - 2686, 2028, 2673, 2277, 225, 3973, 2237, 225, 225, 2099, - 225, 1889, 2135, 2075, 1940, 1941, 1942, 2441, 2347, 1895, - 1938, 916, 917, 918, 919, 3890, 1955, 1956, 1957, 1958, - 1226, 1904, 3889, 1908, 2009, 2341, 3920, 2414, 1912, 2340, - 2312, 2127, 2128, 2228, 2281, 2281, 916, 917, 918, 919, - 1845, 1845, 2205, 1948, 3864, 2130, 2083, 2113, 3607, 3555, - 1459, 2281, 1845, 1845, 2104, 1482, 2106, 1964, 2281, 2222, - 2146, 2147, 2148, 1974, 1975, 2428, 3520, 2125, 2126, 1486, - 1939, 1783, 1973, 2159, 1992, 1969, 1968, 1980, 3457, 3453, - 2143, 1486, 1554, 1228, 4198, 2008, 1997, 3502, 2246, 2120, - 1982, 4181, 1579, 1972, 1991, 2246, 3359, 1568, 2235, 2171, - 2216, 3055, 2174, 2175, 3542, 2177, 1988, 2207, 2777, 2765, - 1998, 2757, 3084, 2001, 2002, 2887, 1987, 2281, 1989, 1990, - 3794, 2588, 3556, 2010, 2011, 1983, 1984, 2800, 2699, 2074, - 2005, 2007, 1996, 2698, 2080, 1658, 2690, 1074, 2712, 3521, - 1074, 2079, 1993, 1994, 1739, 1740, 1741, 1742, 1743, 1074, - 2085, 3458, 3454, 2455, 2458, 2229, 1266, 1267, 1268, 1265, - 700, 2114, 2004, 921, 2103, 2694, 2105, 2435, 2212, 3360, - 2682, 2675, 1524, 1525, 2556, 1527, 1528, 1071, 1532, 1533, - 1534, 2414, 1264, 3605, 1264, 2141, 1784, 1727, 921, 1071, - 1788, 1789, 1790, 1791, 2200, 2670, 2149, 2150, 2142, 2662, - 1829, 2660, 2427, 2098, 2658, 2300, 2200, 2656, 1839, 2280, - 2168, 1264, 1583, 1584, 1585, 1586, 1587, 2285, 1589, 1590, - 1591, 1592, 1593, 2227, 2413, 1073, 1599, 1600, 1601, 1602, - 2166, 2152, 2343, 2264, 2265, 2185, 2319, 1073, 2414, 1266, - 1267, 1268, 1265, 2671, 2676, 1909, 1678, 1074, 1315, 1213, - 2218, 2318, 1176, 2303, 2294, 2455, 2458, 2293, 1171, 2206, - 2292, 1892, 1297, 1972, 2129, 2215, 1556, 2213, 2671, 2282, - 2245, 1281, 2663, 1687, 2661, 2224, 938, 2657, 2226, 3302, - 2657, 1834, 1833, 3131, 4192, 2279, 2354, 1071, 2356, 2459, - 2358, 2359, 2260, 4154, 2454, 2448, 2453, 2414, 2451, 2456, - 676, 1531, 676, 1531, 2230, 2342, 3977, 3293, 1483, 1264, - 2443, 3731, 2375, 1834, 1833, 2483, 1468, 3534, 754, 2243, - 1469, 676, 676, 676, 1264, 2335, 1264, 1264, 3954, 1558, - 1264, 699, 1514, 1264, 3863, 1073, 676, 676, 676, 676, - 1559, 2268, 2281, 2246, 2259, 2283, 1688, 3821, 3532, 2411, - 3978, 3760, 1976, 2457, 695, 3732, 3759, 3745, 2415, 2416, - 2417, 3535, 2420, 1531, 1768, 3706, 2262, 2263, 2261, 3512, - 1555, 2273, 1284, 1285, 1286, 1287, 1288, 1281, 1995, 697, - 3382, 3373, 3365, 2313, 2314, 3361, 2316, 1774, 3294, 1531, - 3271, 2459, 3533, 2323, 3014, 1871, 2454, 2448, 2453, 3013, - 2451, 2456, 2853, 1771, 1773, 1770, 2477, 1772, 3085, 698, - 2796, 2709, 2674, 2579, 696, 1279, 1289, 1290, 1282, 1283, - 1284, 1285, 1286, 1287, 1288, 1281, 2366, 1864, 2368, 1484, - 945, 2225, 3295, 2360, 2210, 1468, 2209, 1892, 2208, 1469, - 1455, 1454, 1892, 1892, 1194, 2432, 2648, 3412, 2719, 2434, - 2642, 2436, 2730, 2169, 2484, 2457, 1282, 1283, 1284, 1285, - 1286, 1287, 1288, 1281, 676, 2006, 1787, 3223, 2274, 2344, - 2336, 2338, 2339, 2560, 2560, 2097, 2560, 1266, 1267, 1268, - 1265, 1170, 1166, 1167, 1168, 1169, 1787, 2735, 3415, 2734, - 2733, 2731, 2170, 1268, 1265, 2173, 651, 651, 2176, 2357, - 1612, 2178, 2169, 2361, 1192, 1266, 1267, 1268, 1265, 4034, - 1568, 676, 1934, 1265, 2437, 3772, 2652, 3771, 3102, 2948, - 2381, 1266, 1267, 1268, 1265, 2946, 676, 2447, 2925, 2923, - 3413, 4188, 1192, 2632, 670, 1338, 3707, 3708, 3751, 2583, - 1607, 4164, 2097, 1317, 2446, 2638, 2779, 2640, 2780, 3700, - 225, 4163, 1266, 1267, 1268, 1265, 1316, 2221, 4162, 2732, - 2634, 2721, 4160, 4159, 4098, 1339, 1266, 1267, 1268, 1265, - 2440, 4066, 1074, 2574, 2562, 2575, 2566, 1266, 1267, 1268, - 1265, 4065, 1486, 2564, 3979, 2421, 2644, 2433, 2422, 2423, - 2678, 3500, 3002, 2596, 2580, 2581, 4187, 2821, 2425, 2426, - 2460, 2461, 1849, 2466, 3915, 2568, 2688, 2689, 2692, 3701, - 3903, 2235, 1071, 3000, 2998, 3893, 2590, 1850, 1568, 2987, - 1568, 3883, 1568, 2424, 789, 799, 3812, 1192, 2430, 3734, - 3733, 2431, 3677, 2852, 790, 2711, 791, 795, 798, 794, - 792, 793, 3547, 3536, 2429, 1266, 1267, 1268, 1265, 2702, - 2637, 3501, 3001, 3499, 1613, 2643, 3261, 2529, 3127, 3097, - 1073, 1568, 1192, 2270, 2535, 3096, 2743, 2275, 2985, 1266, - 1267, 1268, 1265, 2999, 2997, 2284, 2569, 1612, 2984, 2986, - 2983, 2750, 1266, 1267, 1268, 1265, 1568, 2975, 2706, 796, - 1566, 1105, 1106, 1107, 2738, 1289, 1290, 1282, 1283, 1284, - 1285, 1286, 1287, 1288, 1281, 2584, 2969, 2968, 2967, 2587, - 2966, 2792, 2291, 3150, 2664, 1566, 2736, 2737, 2576, 2751, - 2298, 2346, 797, 2145, 2188, 1104, 2187, 2186, 1101, 2633, - 2182, 2181, 2636, 2136, 1918, 1916, 2798, 1679, 2723, 3164, - 2723, 2802, 2315, 2804, 1397, 2754, 2755, 2320, 2321, 2322, - 676, 676, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, - 2333, 2334, 749, 2635, 1192, 751, 3506, 2752, 2727, 4190, - 750, 1568, 3511, 4184, 1531, 2708, 3248, 4182, 1547, 1549, - 1531, 2077, 3856, 3857, 2741, 2717, 2703, 1174, 3645, 2883, - 2684, 1266, 1267, 1268, 1265, 2889, 4152, 2296, 2890, 4115, - 2693, 2695, 3163, 4114, 4111, 4041, 4040, 2700, 4076, 3842, - 4020, 3964, 2783, 1550, 3711, 3958, 2900, 1272, 1273, 1274, - 1275, 1276, 1277, 1278, 1270, 2596, 1192, 2713, 2714, 1266, - 1267, 1268, 1265, 3939, 2922, 1266, 1267, 1268, 1265, 1727, - 3930, 1192, 1192, 1192, 2006, 2739, 1173, 1192, 2729, 2932, - 2933, 2934, 2935, 1192, 2942, 3907, 2943, 2944, 3902, 2945, - 3901, 2947, 2716, 2865, 3860, 3846, 3844, 2295, 3813, 2880, - 3753, 3715, 2942, 3704, 2867, 2870, 3689, 3688, 3684, 3682, - 1074, 2901, 3669, 3676, 2560, 3672, 3671, 2917, 1098, 1099, - 1100, 1103, 3668, 1102, 1266, 1267, 1268, 1265, 3003, 2850, - 3657, 2903, 2917, 2928, 2929, 2866, 2028, 651, 2931, 1266, - 1267, 1268, 1265, 2891, 2938, 2077, 3667, 3643, 3641, 1192, - 2097, 2097, 2097, 2097, 2097, 2097, 3614, 1266, 1267, 1268, - 1265, 3611, 3609, 3007, 3496, 3478, 1192, 2097, 3466, 3450, - 2560, 2832, 3448, 2834, 2831, 3443, 3008, 3393, 3371, 2916, - 2848, 2920, 3370, 3368, 3367, 2920, 3063, 3362, 1568, 3357, - 2873, 3356, 2278, 3272, 2927, 3234, 8, 2882, 2888, 676, - 676, 2760, 2761, 3233, 7, 3224, 3217, 2766, 3212, 3210, - 3031, 2351, 3141, 3138, 1892, 3656, 1892, 3117, 3095, 3070, - 2902, 2905, 1948, 2996, 3595, 2988, 2978, 3031, 2918, 2915, - 2976, 2972, 2971, 2924, 2970, 1892, 1892, 2810, 2801, 2793, - 2930, 2685, 1266, 1267, 1268, 1265, 2376, 857, 856, 3051, - 2921, 1266, 1267, 1268, 1265, 225, 2364, 2363, 2191, 2893, - 225, 2184, 3445, 3019, 2896, 2965, 1902, 3064, 1901, 1606, - 1266, 1267, 1268, 1265, 1680, 2977, 3167, 1346, 1342, 1341, - 1177, 4140, 1845, 2276, 1845, 925, 3996, 3112, 3081, 1266, - 1267, 1268, 1265, 3009, 2899, 3992, 3838, 3837, 3015, 2892, - 3826, 3126, 3822, 1266, 1267, 1268, 1265, 1568, 2897, 2898, - 3133, 3670, 3652, 208, 3048, 199, 170, 3624, 2677, 3527, - 2680, 2489, 3526, 3524, 2492, 2493, 2494, 2495, 2496, 2497, - 2498, 3054, 3493, 2501, 2502, 2503, 2504, 2505, 2506, 2507, - 2508, 2509, 2510, 2511, 3053, 2513, 2514, 2515, 2516, 2517, - 3071, 2518, 3068, 3052, 3032, 3033, 3034, 3035, 3036, 3037, - 3086, 1266, 1267, 1268, 1265, 3090, 3166, 3462, 3460, 1891, - 3459, 3456, 3455, 3107, 3111, 3449, 3447, 3428, 1074, 3418, - 3417, 1639, 1640, 3404, 2720, 3119, 204, 2726, 3403, 1644, - 1074, 2749, 1648, 1266, 1267, 1268, 1265, 3303, 2744, 2745, - 3238, 3109, 3235, 1647, 3088, 2095, 2747, 2748, 3211, 3087, - 3202, 3214, 3120, 3169, 3160, 3152, 676, 1531, 3165, 3012, - 3151, 3130, 2753, 3145, 3225, 3226, 3227, 3229, 3103, 3231, - 3232, 3135, 3110, 3123, 3079, 3122, 3108, 3105, 1192, 2659, - 2655, 3121, 2654, 2324, 1192, 1266, 1267, 1268, 1265, 2317, - 3251, 1739, 1892, 2311, 2310, 2309, 2308, 2306, 1632, 3129, - 3265, 3143, 2302, 2301, 3142, 676, 2299, 2290, 1633, 1634, - 2287, 675, 675, 3162, 2286, 2190, 1885, 683, 1884, 3282, - 1192, 3149, 2776, 676, 1883, 676, 1192, 1192, 1266, 1267, - 1268, 1265, 3158, 3159, 1848, 2097, 2411, 2775, 3301, 3237, - 1832, 3156, 1847, 1838, 1580, 2917, 1578, 4139, 4097, 1266, - 1267, 1268, 1265, 3204, 3155, 4014, 3157, 1336, 2477, 3991, - 3925, 3275, 2774, 208, 1266, 1267, 1268, 1265, 3922, 3909, - 3327, 3904, 3330, 2773, 3330, 3330, 3807, 2894, 2895, 1192, - 3278, 2917, 3219, 3806, 3209, 3788, 3208, 2917, 2917, 1266, - 1267, 1268, 1265, 3040, 2772, 3770, 3766, 3352, 2865, 3744, - 1266, 1267, 1268, 1265, 3039, 2771, 3728, 3625, 1568, 1568, - 3305, 3348, 3253, 2288, 3285, 3622, 3593, 1074, 3592, 1074, - 3290, 1266, 1267, 1268, 1265, 1074, 3589, 3588, 3314, 3316, - 3153, 3154, 1266, 1267, 1268, 1265, 204, 1566, 1566, 3554, - 2917, 3353, 3354, 3299, 3551, 3549, 3514, 3310, 3274, 3325, - 3161, 1627, 1074, 3284, 1638, 676, 1629, 1071, 1643, 3288, - 3289, 3251, 1646, 1635, 3296, 1462, 3042, 3300, 3004, 801, - 143, 3326, 2926, 2876, 1531, 143, 2875, 2077, 2077, 3176, - 3177, 683, 3335, 3309, 2447, 3178, 3179, 3180, 3181, 2868, - 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, - 3192, 2446, 3336, 3331, 3332, 1073, 2833, 2778, 2669, 3350, - 1266, 1267, 1268, 1265, 2578, 2519, 2839, 2412, 1892, 1280, - 1279, 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, - 1281, 1192, 2770, 2383, 2382, 2743, 2345, 1769, 2307, 682, - 4008, 2769, 143, 3416, 204, 3358, 1280, 1279, 1289, 1290, - 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, 2151, 1266, - 1267, 1268, 1265, 3333, 1898, 4006, 2768, 3304, 1266, 1267, - 1268, 1265, 3306, 3307, 1712, 1661, 3395, 2767, 1636, 1396, - 3378, 3379, 1381, 3364, 3363, 1377, 3372, 3369, 1376, 3366, - 676, 1375, 2596, 1266, 1267, 1268, 1265, 1374, 3089, 3376, - 3091, 3389, 1373, 3390, 1266, 1267, 1268, 1265, 1372, 4132, - 2764, 1371, 2957, 2958, 4130, 2763, 1370, 3308, 1369, 1892, - 2762, 1368, 3397, 1367, 1892, 4004, 2756, 2973, 2974, 1366, - 3400, 3401, 3402, 2746, 1365, 1364, 2221, 1266, 1267, 1268, - 1265, 3406, 1266, 1267, 1268, 1265, 1363, 1266, 1267, 1268, - 1265, 4002, 3010, 1266, 1267, 1268, 1265, 1362, 1361, 1360, - 1266, 1267, 1268, 1265, 3468, 1359, 1358, 1357, 2163, 1356, - 1355, 3144, 3590, 2742, 1072, 3429, 1354, 1353, 3479, 143, - 3894, 1352, 2723, 3485, 2718, 3432, 1349, 3431, 1348, 1347, - 1345, 1344, 3435, 1343, 143, 3451, 143, 1340, 3436, 3168, - 1266, 1267, 1268, 1265, 3380, 1333, 3486, 1332, 1330, 1329, - 3441, 1266, 1267, 1268, 1265, 1328, 1327, 1326, 676, 2077, - 1325, 1324, 3480, 1782, 3482, 1323, 3396, 1322, 1321, 1320, - 3519, 1319, 1314, 3472, 1280, 1279, 1289, 1290, 1282, 1283, - 1284, 1285, 1286, 1287, 1288, 1281, 1313, 2560, 2097, 3539, - 1266, 1267, 1268, 1265, 1312, 1311, 1310, 1230, 1175, 1818, - 3385, 3386, 2419, 2397, 1218, 4081, 3467, 3463, 3388, 3490, - 3469, 2854, 3557, 2589, 2193, 1192, 1229, 3050, 3045, 3394, - 3043, 126, 3492, 3046, 3327, 3044, 3391, 1074, 1192, 3495, - 3049, 3038, 68, 3489, 1074, 3047, 3627, 2550, 2551, 67, - 1192, 4033, 3604, 3941, 3628, 3749, 1568, 2683, 3507, 2672, - 1456, 1966, 1967, 3270, 3125, 3518, 1961, 1962, 1963, 3433, - 3434, 3541, 3509, 3323, 3525, 3324, 676, 2487, 2077, 3600, - 3407, 2065, 1192, 3587, 1621, 1566, 3558, 2667, 2707, 3606, - 2688, 2689, 2377, 3548, 1675, 3550, 2370, 3537, 1655, 3597, - 2153, 678, 1224, 3246, 3626, 3239, 3538, 2904, 2877, 3544, - 3580, 2938, 679, 2439, 225, 2407, 1970, 1937, 4143, 680, - 1834, 1833, 1392, 1393, 1390, 1391, 3334, 1192, 3615, 1388, - 1389, 3906, 3618, 1386, 1387, 3594, 3355, 3599, 2532, 3629, - 2525, 3596, 2078, 3031, 1523, 1522, 3603, 1257, 2211, 3399, - 3073, 2378, 2223, 1475, 1474, 3612, 3608, 1447, 1498, 3610, - 3613, 4104, 4102, 4059, 4030, 4029, 3616, 4027, 3968, 675, - 1181, 3617, 3620, 3619, 676, 3926, 3802, 3801, 3739, 3642, - 1190, 3452, 3425, 3424, 3650, 3686, 3410, 2472, 3031, 2442, - 1677, 3409, 3083, 1814, 1472, 1192, 4134, 4133, 4134, 3128, - 1811, 2806, 2805, 1219, 1813, 1810, 1812, 1816, 1817, 2799, - 3646, 2289, 1815, 3647, 1215, 1192, 1568, 1568, 4133, 3636, - 3768, 3405, 3282, 1189, 3540, 3683, 1490, 3685, 212, 3, - 76, 2, 4156, 3543, 3723, 4157, 1, 3723, 916, 917, - 918, 919, 2784, 1189, 1896, 1566, 1780, 1394, 920, 3713, - 1192, 3738, 1192, 3631, 3717, 3718, 2917, 3712, 915, 3674, - 1544, 3741, 2570, 3743, 2131, 1572, 1900, 922, 3056, 1568, - 3057, 3398, 3059, 3691, 3696, 3714, 2811, 3695, 3705, 3694, - 2242, 3020, 2523, 2387, 3264, 1457, 979, 676, 1840, 1192, - 1192, 1692, 3726, 1192, 1192, 3666, 1206, 3716, 1780, 1689, - 1205, 1203, 1785, 2207, 3727, 3737, 803, 2196, 3005, 3541, - 2979, 1733, 3798, 1733, 4142, 4176, 4096, 3720, 3587, 3785, - 3750, 3790, 1074, 1972, 4145, 1710, 3799, 3754, 3747, 787, - 4021, 3774, 3775, 3742, 3746, 3786, 3787, 3931, 3808, 3809, - 4100, 3933, 3818, 2247, 3752, 3580, 1262, 3104, 1006, 844, - 814, 1568, 1331, 1668, 3174, 3172, 1821, 1822, 1823, 1824, - 1825, 1826, 1819, 1820, 3444, 3796, 813, 3504, 2844, 3795, - 3803, 3446, 3076, 3877, 3839, 1007, 2179, 3928, 3791, 3740, - 1566, 3816, 1622, 1626, 3820, 3797, 3832, 1280, 1279, 1289, - 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, 2438, - 3885, 3987, 3748, 3461, 3815, 3843, 3319, 3845, 2912, 143, - 143, 143, 1072, 3827, 1650, 3982, 3552, 3831, 3819, 3662, - 3658, 3660, 3659, 3661, 719, 2110, 649, 1056, 3789, 3875, - 2192, 3848, 3869, 1280, 1279, 1289, 1290, 1282, 1283, 1284, - 1285, 1286, 1287, 1288, 1281, 1192, 720, 2418, 4047, 3908, - 959, 3487, 2396, 960, 952, 2863, 3892, 2862, 3898, 3859, - 2538, 1750, 3735, 3736, 1271, 1767, 3193, 3194, 1308, 758, - 3870, 2272, 3650, 2841, 3575, 3069, 75, 3872, 74, 3871, - 73, 72, 233, 805, 232, 1298, 3840, 3884, 3888, 1192, - 3709, 4017, 4147, 784, 1568, 783, 782, 2545, 2549, 2550, - 2551, 2546, 2554, 2547, 2552, 781, 1733, 2548, 780, 2553, - 779, 2543, 2544, 3905, 3867, 2542, 2540, 2539, 2092, 1074, - 2091, 3082, 3408, 1566, 2158, 2160, 3280, 3916, 2941, 2936, - 2017, 3914, 2015, 1535, 2467, 1526, 2474, 2014, 4078, 3442, - 3653, 3997, 1537, 3998, 3765, 2989, 3649, 1960, 2463, 2034, - 3960, 2960, 3947, 2031, 2030, 2949, 3761, 3927, 3755, 2062, - 3873, 3722, 3559, 1574, 3560, 3566, 1892, 3955, 2406, 3956, - 1125, 1121, 1123, 1124, 1122, 2728, 3374, 2444, 3969, 3241, - 2827, 2826, 1892, 2824, 2823, 3621, 1432, 3959, 3623, 4043, - 3690, 3957, 2545, 2549, 2550, 2551, 2546, 2554, 2547, 2552, - 2594, 2592, 2548, 3963, 2553, 1172, 3986, 3387, 3383, 3630, - 1192, 1402, 3971, 1400, 2204, 3392, 3041, 2219, 1568, 3124, - 2093, 4011, 2089, 2088, 1096, 1095, 4018, 4001, 4003, 4005, - 4007, 3980, 1603, 3220, 1385, 3985, 3222, 45, 3022, 2533, - 4019, 3850, 3994, 1965, 953, 2394, 110, 1566, 41, 3923, - 3924, 4010, 4000, 3515, 3516, 3517, 3170, 123, 109, 187, - 3522, 3523, 60, 186, 59, 121, 184, 58, 104, 4026, - 4024, 1568, 103, 120, 3875, 4038, 182, 57, 217, 216, - 219, 4042, 218, 215, 2645, 2646, 4039, 214, 1610, 213, - 4069, 4031, 3725, 4013, 910, 44, 4077, 43, 188, 4060, - 1566, 42, 111, 61, 4061, 40, 4063, 4064, 4062, 39, + 786, 762, 4185, 788, 4154, 2917, 225, 4177, 1652, 2026, + 4081, 1732, 3552, 4087, 3351, 4088, 3973, 4080, 3651, 3317, + 3904, 3951, 771, 3996, 2137, 4031, 3784, 3427, 3581, 3882, + 2911, 3849, 3942, 1334, 3428, 3903, 3974, 764, 3717, 3818, + 1792, 816, 2914, 3655, 1065, 1188, 1496, 651, 3873, 3511, + 3952, 3954, 1502, 3646, 2822, 3516, 1971, 3326, 1779, 2451, + 3568, 1794, 2888, 3736, 670, 3726, 676, 676, 1182, 1735, + 3284, 3425, 676, 694, 703, 3269, 3699, 703, 3032, 210, + 3033, 3245, 2124, 1564, 3534, 3031, 3476, 3272, 3503, 3731, + 2139, 3009, 2121, 3346, 2940, 3335, 3536, 2086, 37, 2559, + 3028, 3328, 2827, 2162, 3470, 2595, 1797, 3061, 2724, 3101, + 3390, 715, 2454, 2853, 3019, 2194, 3250, 2236, 3252, 3248, + 69, 2689, 2410, 3247, 3243, 2866, 2427, 1986, 711, 3294, + 3149, 2350, 759, 3209, 3246, 2232, 1178, 142, 1641, 36, + 754, 1728, 3334, 2349, 2597, 2667, 2220, 2560, 2202, 2649, + 3075, 1630, 1645, 1557, 1653, 946, 1890, 2117, 1637, 2167, + 2195, 2231, 2543, 1461, 2203, 2090, 2842, 2942, 2837, 2538, + 2922, 700, 986, 2452, 2016, 2880, 221, 8, 2409, 1642, + 220, 7, 6, 1947, 2593, 2398, 1793, 1126, 1726, 2266, + 2087, 763, 1573, 2233, 1536, 1542, 669, 2389, 1059, 753, + 2352, 651, 1604, 1985, 2761, 2447, 1786, 1204, 2392, 1717, + 1766, 2201, 1656, 772, 761, 2198, 23, 2183, 1611, 1505, + 708, 1943, 1674, 1541, 1058, 225, 1725, 225, 2567, 1117, + 1118, 688, 1946, 1538, 985, 1485, 676, 1428, 717, 1404, + 2539, 1024, 685, 1798, 211, 650, 911, 968, 1497, 1595, + 24, 25, 17, 10, 1097, 1409, 1467, 702, 203, 962, + 1731, 983, 1010, 760, 1380, 207, 2240, 913, 1481, 1335, + 718, 914, 1471, 714, 2569, 27, 1266, 1267, 1268, 1265, + 3961, 2760, 1266, 1267, 1268, 1265, 976, 16, 977, 1266, + 1267, 1268, 1265, 2484, 3870, 755, 2797, 2797, 1114, 712, + 2797, 3548, 3436, 3219, 1113, 3301, 1115, 1506, 1092, 3218, + 3118, 3117, 15, 2250, 1913, 1405, 1183, 672, 3688, 3519, + 1184, 3420, 2712, 2655, 2653, 1074, 2652, 957, 681, 2650, + 1406, 1903, 1618, 1614, 706, 1110, 209, 1109, 671, 2348, + 1399, 971, 1071, 967, 1073, 1540, 3929, 1183, 699, 1464, + 1465, 1466, 1044, 934, 2138, 1373, 1110, 1667, 3216, 932, + 695, 2362, 1110, 14, 2355, 1910, 1408, 3202, 33, 3199, + 3204, 3201, 4166, 2789, 2787, 1519, 1897, 1395, 3644, 3097, + 1093, 3095, 2172, 3937, 677, 698, 8, 1616, 3825, 3819, + 7, 3647, 1108, 755, 1266, 1267, 1268, 1265, 3426, 949, + 2217, 1329, 1266, 1267, 1268, 1265, 3956, 2197, 912, 2898, + 3178, 208, 3481, 2189, 2492, 2400, 4191, 2791, 3950, 4163, + 3833, 208, 1264, 4059, 923, 4116, 3479, 1228, 2698, 3661, + 2237, 3700, 3535, 3889, 2873, 208, 697, 3310, 2401, 1651, + 1660, 696, 3948, 208, 208, 65, 199, 170, 3704, 2706, + 1419, 3857, 3831, 3494, 933, 1087, 1082, 1077, 1081, 1085, + 931, 2742, 1672, 208, 65, 199, 170, 2369, 4007, 208, + 1657, 1069, 1410, 1581, 973, 1070, 966, 3890, 1414, 1413, + 1412, 934, 200, 1090, 2871, 970, 969, 1080, 932, 191, + 1075, 1665, 1669, 201, 1659, 1832, 208, 65, 199, 170, + 1039, 1037, 713, 1038, 3176, 1453, 958, 1921, 204, 3859, + 208, 1420, 141, 1664, 3026, 2248, 1671, 204, 3121, 208, + 2393, 2587, 208, 65, 199, 170, 965, 127, 208, 65, + 199, 170, 1436, 924, 2874, 1263, 204, 902, 1088, 901, + 903, 904, 204, 905, 906, 975, 2588, 2821, 3068, 3203, + 964, 3200, 1515, 1919, 963, 1516, 1434, 208, 1091, 3109, + 951, 2574, 3069, 3070, 2573, 2101, 2102, 2575, 141, 204, + 1925, 1926, 2817, 857, 930, 1698, 1543, 956, 1545, 2100, + 2668, 2839, 1033, 204, 2000, 1078, 4056, 208, 65, 199, + 170, 2840, 204, 1683, 1734, 204, 1979, 208, 65, 199, + 170, 204, 1045, 1261, 954, 1236, 141, 3321, 1238, 1089, + 1503, 1504, 1243, 150, 151, 1244, 152, 153, 2134, 3319, + 3959, 154, 2819, 1068, 155, 1493, 3958, 2792, 1256, 1041, + 204, 1067, 1617, 1615, 4091, 4092, 1239, 3671, 1718, 3957, + 2838, 1722, 974, 1246, 4052, 3959, 4045, 2814, 2337, 1079, + 4115, 1501, 1199, 3940, 1518, 1500, 1503, 1504, 3958, 4044, + 204, 3102, 1196, 3957, 4043, 1721, 4158, 4159, 955, 3429, + 204, 3429, 1202, 4033, 676, 676, 2818, 4033, 2693, 4036, + 4061, 4062, 1435, 3822, 1193, 676, 1192, 169, 197, 206, + 198, 125, 2252, 1043, 4057, 4058, 2964, 4065, 4064, 4063, + 4066, 2815, 3103, 2533, 3104, 703, 703, 2118, 676, 1738, + 196, 190, 189, 3943, 3944, 3945, 3946, 71, 2108, 1713, + 169, 197, 206, 198, 3970, 1977, 1086, 3443, 3509, 3504, + 2244, 3709, 2876, 2845, 1232, 149, 3265, 2526, 2388, 3139, + 2112, 1241, 2180, 196, 2824, 972, 3593, 1191, 974, 3020, + 3841, 4054, 3842, 1624, 1623, 1259, 1260, 3549, 2790, 3137, + 1234, 1258, 1083, 195, 2703, 1084, 2490, 1723, 3836, 3263, + 1042, 1306, 1237, 1240, 3861, 3862, 3680, 1922, 192, 193, + 194, 1398, 3645, 1231, 961, 1207, 1210, 2249, 700, 700, + 700, 1720, 3014, 3670, 1120, 3960, 749, 3096, 1233, 751, + 1529, 3672, 3480, 927, 750, 1242, 3844, 4090, 3841, 3869, + 3842, 3446, 3143, 1074, 1185, 2796, 1184, 2820, 1192, 3259, + 1184, 2528, 1517, 1920, 1223, 3260, 3261, 202, 3812, 1491, + 1071, 1184, 1073, 2238, 2238, 1437, 2238, 3119, 3843, 2529, + 2530, 3262, 2816, 3116, 1737, 1736, 3866, 3706, 137, 2799, + 2271, 2536, 195, 2239, 138, 1338, 1211, 3662, 1254, 1255, + 3270, 2590, 1184, 1253, 3844, 1094, 1978, 668, 1076, 1110, + 3608, 1110, 1110, 3323, 4124, 1235, 1110, 3282, 928, 1339, + 3989, 1110, 1245, 3295, 950, 1110, 1074, 948, 1201, 2132, + 2133, 3605, 701, 4060, 2470, 2251, 3843, 3888, 1207, 1210, + 2450, 2473, 3349, 1071, 3350, 1073, 3347, 3348, 1719, 1040, + 1212, 139, 2255, 2257, 2258, 3984, 2881, 2651, 3483, 3894, + 1300, 1195, 1197, 1200, 64, 1619, 3224, 1401, 1403, 3813, + 1407, 2400, 929, 935, 705, 3257, 3685, 3686, 3687, 3886, + 3832, 704, 3598, 912, 1424, 3024, 2395, 1187, 1427, 1186, + 3210, 3975, 1433, 1070, 66, 2788, 1378, 3991, 2472, 1383, + 3860, 3553, 1216, 1217, 171, 699, 699, 699, 3482, 1211, + 701, 1406, 1406, 66, 171, 1666, 701, 695, 695, 695, + 1220, 1302, 1303, 1304, 1305, 986, 1222, 1307, 171, 3271, + 3997, 1180, 3318, 3705, 2707, 2916, 171, 171, 2379, 1411, + 1209, 1208, 698, 698, 698, 3353, 1503, 1504, 147, 205, + 3560, 148, 1480, 3855, 3694, 2471, 171, 1248, 1503, 1504, + 1249, 62, 171, 3785, 3786, 3787, 3791, 3789, 3790, 3792, + 3788, 1198, 66, 2912, 2913, 701, 2916, 2532, 66, 3487, + 676, 1708, 205, 1531, 1709, 701, 1416, 676, 1251, 171, + 3233, 651, 651, 697, 697, 697, 1499, 2524, 696, 696, + 696, 651, 651, 171, 2119, 1568, 1568, 2844, 676, 3609, + 3266, 1492, 171, 926, 3140, 171, 3271, 3490, 2590, 4053, + 3837, 171, 3021, 2457, 3838, 1418, 3969, 140, 46, 703, + 1596, 670, 3895, 3775, 63, 4197, 1607, 66, 1350, 1351, + 2244, 2502, 2965, 2501, 2966, 2967, 3658, 66, 3764, 3863, + 171, 225, 3887, 1209, 1208, 1575, 3324, 144, 145, 1214, + 651, 146, 3710, 2851, 2848, 2849, 1478, 4180, 2953, 1553, + 1744, 1747, 1748, 2109, 1714, 2954, 2955, 2956, 3837, 2847, + 171, 1745, 3953, 2522, 2523, 3489, 1247, 1552, 1221, 1570, + 171, 1495, 1494, 1477, 1476, 2111, 3258, 2857, 2861, 2862, + 2863, 2858, 2860, 2859, 3998, 3874, 4079, 3770, 3327, 3908, + 1530, 2256, 1649, 1179, 3198, 2493, 3537, 1654, 1382, 2450, + 1384, 976, 1297, 977, 1663, 1252, 3642, 1430, 1431, 1429, + 3063, 3065, 1440, 1441, 1442, 1443, 1444, 2467, 1446, 713, + 3352, 1439, 3347, 3348, 1452, 4030, 1566, 1566, 1539, 3432, + 1250, 3477, 3343, 1228, 1696, 2699, 1562, 1563, 2579, 1699, + 2488, 3381, 2353, 2241, 2456, 3080, 3081, 2107, 1568, 2458, + 1568, 1192, 1673, 2084, 1426, 1445, 3142, 1451, 1450, 1487, + 1488, 1449, 1448, 1463, 1046, 707, 1460, 1470, 2399, 1547, + 1549, 3497, 3344, 2460, 1906, 1479, 980, 981, 982, 1560, + 1561, 3777, 1489, 2962, 1625, 1473, 3471, 1415, 4181, 2683, + 1508, 1509, 1458, 1511, 1512, 1507, 1513, 1658, 1510, 1628, + 2811, 1631, 1632, 2459, 1670, 2253, 2254, 1597, 2380, 3151, + 3150, 2267, 1733, 1633, 1634, 1520, 1521, 700, 1568, 1074, + 700, 700, 3907, 1227, 2374, 2373, 1074, 1639, 1640, 1482, + 1486, 1486, 1486, 2372, 1707, 1192, 1796, 1662, 1620, 940, + 978, 1034, 1647, 1423, 1551, 1421, 1422, 1928, 1827, 1828, + 1845, 1831, 1582, 681, 1482, 1482, 1576, 1524, 1525, 1846, + 1527, 1528, 1588, 1532, 1533, 1534, 1594, 1644, 4078, 1929, + 1648, 1608, 1853, 947, 1855, 1609, 1856, 1857, 1858, 2371, + 1911, 1927, 2514, 3766, 3064, 1730, 936, 3765, 937, 1417, + 944, 2958, 3737, 1438, 4199, 942, 941, 1583, 1584, 1585, + 1586, 1587, 2391, 1589, 1590, 1591, 1592, 1593, 2461, 1746, + 2557, 1599, 1600, 1601, 1602, 2993, 1905, 1192, 1715, 2830, + 756, 4040, 4178, 4179, 1749, 1036, 3771, 3772, 1035, 1914, + 1711, 2466, 1915, 1681, 1917, 2464, 1684, 1034, 676, 676, + 2957, 2959, 2831, 2832, 4193, 1888, 1930, 1932, 1830, 1933, + 1682, 1935, 1936, 1685, 1686, 670, 1596, 1676, 2886, 1780, + 975, 1944, 1568, 1949, 1950, 3433, 1952, 1531, 676, 2984, + 2985, 2305, 943, 676, 2304, 1693, 1568, 1472, 1899, 3345, + 986, 2487, 1264, 1972, 1891, 1724, 1705, 1701, 1704, 1700, + 1472, 1690, 1691, 3387, 699, 1226, 1568, 699, 699, 1835, + 1836, 1837, 1531, 1907, 1225, 4187, 695, 694, 1727, 695, + 695, 1706, 1851, 1034, 1844, 1852, 4175, 2246, 2590, 1729, + 2390, 1036, 4134, 1703, 1035, 1768, 3300, 1999, 1775, 1776, + 4102, 698, 1865, 1866, 698, 698, 2006, 2006, 2558, 1531, + 1047, 1531, 1531, 4206, 4099, 676, 676, 1264, 2073, 1944, + 2077, 4093, 1887, 1568, 2081, 2082, 4075, 3279, 4024, 2097, + 4023, 651, 4189, 1754, 1755, 1756, 1757, 1758, 1759, 1760, + 1761, 1762, 1763, 1764, 1765, 651, 1951, 1568, 4188, 1777, + 1778, 1226, 697, 2003, 1695, 697, 697, 696, 4017, 4135, + 696, 696, 3992, 1694, 1953, 4135, 2983, 1036, 940, 1702, + 1035, 2887, 2887, 4103, 676, 1944, 1568, 3383, 2144, 1228, + 676, 676, 676, 711, 711, 2670, 1859, 4100, 3980, 2558, + 2154, 2155, 2156, 2157, 2281, 1894, 3500, 2163, 1854, 4076, + 1189, 1264, 3387, 1264, 225, 2075, 2028, 225, 225, 3445, + 225, 3548, 2135, 1111, 1112, 2342, 1889, 3927, 1116, 939, + 2161, 1938, 1895, 3926, 942, 941, 2280, 3921, 2698, 3357, + 1904, 2281, 1908, 3355, 3239, 2246, 2009, 1912, 1716, 3920, + 2994, 2996, 2997, 2998, 2995, 2127, 2128, 3919, 3918, 3208, + 1845, 1845, 2205, 3206, 3898, 2113, 1266, 1267, 1268, 1265, + 3280, 3981, 1845, 1845, 1940, 1941, 1942, 2558, 3083, 2222, + 2146, 2147, 2148, 1974, 1975, 1939, 1955, 1956, 1957, 1958, + 3897, 1968, 2120, 2171, 1969, 3872, 2174, 2175, 2143, 2177, + 3928, 2104, 1948, 2106, 3614, 1987, 2414, 1989, 1990, 2430, + 2281, 2429, 2279, 1972, 2125, 2126, 1964, 1568, 2235, 2793, + 2216, 1996, 2281, 3562, 2010, 2011, 1992, 3526, 3463, 1988, + 2281, 2281, 2207, 2688, 1983, 1984, 1980, 2246, 1997, 2098, + 1973, 1266, 1267, 1268, 1265, 1982, 916, 917, 918, 919, + 2074, 1993, 1994, 1189, 2675, 2008, 2005, 2007, 2237, 1264, + 3459, 1658, 1991, 2246, 3365, 2079, 2099, 2085, 2281, 2229, + 2103, 2004, 2105, 2159, 3058, 2443, 2347, 2590, 1998, 2114, + 1074, 2001, 2002, 1074, 1482, 2212, 700, 3174, 2732, 2341, + 2340, 1228, 1074, 2080, 2312, 2228, 3563, 1071, 1486, 1073, + 3527, 3464, 1266, 1267, 1268, 1265, 2141, 2130, 2779, 1071, + 1486, 1073, 2142, 2149, 2150, 2083, 2767, 1170, 1166, 1167, + 1168, 1169, 1459, 2737, 2200, 2736, 2735, 2733, 2759, 2168, + 2714, 2457, 2460, 3460, 1783, 1554, 2200, 3366, 3087, 1266, + 1267, 1268, 1265, 1105, 1106, 1107, 1727, 2558, 2428, 1860, + 1861, 1862, 1863, 2889, 2185, 1867, 1868, 1869, 1870, 1872, + 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, + 2802, 2701, 2696, 2700, 2692, 2206, 2437, 1104, 2457, 2460, + 1101, 2414, 2684, 1972, 2215, 2277, 2300, 2213, 2145, 1264, + 1074, 2285, 2677, 2227, 2166, 2734, 2226, 2152, 921, 2218, + 2224, 1264, 1379, 1264, 1909, 1678, 2354, 1071, 2356, 1073, + 2358, 2359, 2672, 1315, 1213, 1176, 2664, 2662, 2660, 2225, + 676, 1531, 676, 1531, 2260, 2230, 1171, 916, 917, 918, + 919, 2658, 2375, 2283, 789, 799, 3508, 2413, 754, 2335, + 2243, 676, 676, 676, 790, 2414, 791, 795, 798, 794, + 792, 793, 3802, 3612, 2343, 2673, 676, 676, 676, 676, + 2319, 2318, 2303, 699, 2259, 2678, 2268, 2461, 1297, 2411, + 2129, 2294, 2456, 2450, 2455, 695, 2453, 2458, 2415, 2416, + 2417, 2261, 2420, 1531, 1768, 2673, 2262, 2263, 2445, 2665, + 2663, 2659, 2273, 938, 3305, 1281, 1834, 1833, 2293, 796, + 698, 3296, 2292, 3985, 2659, 1834, 1833, 2282, 1579, 1531, + 2414, 3738, 3134, 2245, 2461, 2313, 2314, 1558, 2316, 2456, + 2450, 2455, 4200, 2453, 2458, 2323, 2479, 2342, 1559, 1483, + 1556, 2459, 797, 1264, 1264, 1264, 4162, 2264, 2265, 1687, + 1098, 1099, 1100, 1103, 1264, 1102, 2485, 3986, 2366, 2650, + 2368, 697, 2738, 2739, 2169, 3739, 696, 3962, 1280, 1279, + 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 2434, 1264, 3871, 2486, 2436, 1264, 2438, 2307, 2459, 921, + 2281, 3540, 3297, 3538, 676, 2006, 2246, 1514, 2336, 2338, + 2339, 3418, 3829, 2562, 2562, 2097, 2562, 1280, 1279, 1289, + 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, 2357, + 1871, 1468, 1688, 2361, 3768, 1469, 651, 651, 2344, 1864, + 3767, 3753, 3713, 3518, 1192, 3541, 3298, 3539, 3388, 3379, + 1568, 676, 3371, 3367, 1555, 3274, 2439, 2381, 3017, 2449, + 2721, 3016, 2855, 2448, 2798, 2711, 676, 945, 2676, 2581, + 1484, 2360, 1192, 2634, 670, 2210, 1774, 2209, 1269, 2208, + 1607, 1338, 2097, 1455, 2644, 2640, 1299, 2642, 1454, 1194, + 225, 3226, 1771, 1773, 1770, 1309, 1772, 2442, 1266, 1267, + 1268, 1265, 2636, 1787, 3088, 1339, 2421, 1268, 1265, 3421, + 1468, 1934, 2566, 2564, 1469, 2568, 1787, 2576, 2274, 2577, + 4042, 1318, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 2680, 1265, 2424, 2598, 1612, 1074, 2169, 2432, 2582, 2583, + 2433, 3780, 3779, 3105, 801, 143, 2462, 2463, 2694, 2468, + 143, 2235, 1071, 2951, 1073, 2949, 2592, 2928, 1568, 2435, + 1568, 2926, 1568, 1266, 1267, 1268, 1265, 1192, 4196, 2645, + 3714, 3715, 2570, 2431, 2654, 2713, 2422, 2423, 3759, 2639, + 1284, 1285, 1286, 1287, 1288, 1281, 2425, 2426, 3707, 3506, + 1317, 2585, 1266, 1267, 1268, 1265, 4172, 2531, 2537, 4171, + 1612, 1568, 1192, 1316, 1849, 4170, 2745, 1266, 1267, 1268, + 1265, 2781, 4168, 2782, 682, 2571, 3419, 143, 4167, 1850, + 4106, 2752, 1266, 1267, 1268, 1265, 1568, 4074, 2708, 3005, + 4073, 1486, 3987, 4195, 1547, 1549, 1266, 1267, 1268, 1265, + 2690, 2691, 3003, 2586, 2823, 2723, 3001, 2491, 3708, 3507, + 2494, 2495, 2496, 2497, 2498, 2499, 2500, 3923, 3911, 2503, + 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, + 2635, 2515, 2516, 2517, 2518, 2519, 2800, 2520, 2589, 2756, + 2757, 2804, 2638, 2806, 2740, 3901, 3891, 3167, 2990, 3004, + 676, 676, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1270, + 3820, 2704, 3002, 3741, 1192, 3740, 3000, 2729, 3684, 2753, + 3554, 1568, 2296, 3542, 1531, 2710, 1266, 1267, 1268, 1265, + 1531, 2077, 2719, 2705, 3505, 2743, 3264, 3130, 3100, 2885, + 1266, 1267, 1268, 1265, 3099, 2891, 2988, 2987, 2892, 2646, + 2695, 2725, 1566, 2725, 2697, 2785, 2702, 2986, 2989, 1072, + 3166, 2637, 2978, 2972, 143, 2971, 2970, 2969, 2903, 2686, + 2794, 1266, 1267, 1268, 1265, 2598, 2666, 1566, 1192, 143, + 1613, 143, 2715, 2716, 2578, 2346, 2925, 1266, 1267, 1268, + 1265, 2430, 2295, 1192, 1192, 1192, 2006, 2731, 2741, 1192, + 2188, 2935, 2936, 2937, 2938, 1192, 2945, 3512, 2946, 2947, + 2187, 2948, 2718, 2950, 2186, 2182, 2869, 2181, 2867, 1266, + 1267, 1268, 1265, 2136, 2945, 1918, 1606, 1916, 1727, 1679, + 1397, 2872, 2854, 3517, 3251, 1174, 2562, 4192, 2904, 2920, + 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 3006, 2852, 4190, 1074, 2920, 2931, 2932, 2868, 3652, 651, + 2934, 2893, 749, 2028, 4160, 751, 2941, 2077, 3864, 3865, + 750, 1192, 2097, 2097, 2097, 2097, 2097, 2097, 2834, 4123, + 2836, 4122, 2882, 4119, 1266, 1267, 1268, 1265, 1192, 2097, + 3153, 4049, 2562, 4048, 1173, 3850, 2923, 4028, 2833, 3972, + 2923, 2754, 3718, 3966, 2850, 3947, 3938, 3915, 3066, 3011, + 1568, 4084, 2919, 3910, 3909, 3676, 2906, 2884, 2875, 8, + 1550, 676, 676, 7, 3664, 2890, 3868, 2930, 3854, 2918, + 2762, 2763, 3034, 3663, 3852, 2278, 2768, 3821, 1266, 1267, + 1268, 1265, 1266, 1267, 1268, 1265, 2905, 3761, 2908, 3034, + 3722, 1266, 1267, 1268, 1265, 2921, 3711, 3696, 2927, 3602, + 1266, 1267, 1268, 1265, 4198, 2933, 3054, 3695, 1266, 1267, + 1268, 1265, 3691, 3451, 3689, 3683, 3679, 225, 3022, 3678, + 3675, 1948, 225, 2980, 3674, 2902, 1266, 1267, 1268, 1265, + 3650, 2968, 3648, 3067, 3621, 1739, 1740, 1741, 1742, 1743, + 1266, 1267, 1268, 1265, 1845, 3618, 1845, 3616, 2894, 3115, + 3010, 3502, 2841, 1266, 1267, 1268, 1265, 3484, 3472, 2900, + 2901, 3456, 2924, 3129, 3012, 3454, 3449, 2895, 3018, 1568, + 3399, 3377, 3136, 3376, 2899, 3374, 3373, 1784, 2276, 3057, + 3368, 1788, 1789, 1790, 1791, 3363, 3362, 3051, 3170, 3275, + 3237, 1829, 3236, 3056, 3055, 3227, 3089, 3015, 3169, 1839, + 3220, 3093, 3035, 3036, 3037, 3038, 3039, 3040, 3168, 3074, + 3215, 3071, 3213, 3084, 2351, 1266, 1267, 1268, 1265, 3144, + 3141, 3120, 1632, 3098, 1891, 1266, 1267, 1268, 1265, 3114, + 3073, 2999, 1633, 1634, 3053, 1266, 1267, 1268, 1265, 2991, + 2981, 3110, 2979, 2975, 2974, 1639, 1640, 2973, 2812, 2095, + 2960, 2961, 1892, 3122, 2803, 1647, 1266, 1267, 1268, 1265, + 3112, 2795, 2687, 1074, 2376, 2976, 2977, 2364, 3091, 2363, + 3214, 3123, 2191, 3217, 2751, 1074, 2184, 3090, 676, 1531, + 1644, 3133, 1902, 1648, 857, 856, 3228, 3229, 3230, 3232, + 3013, 3234, 3235, 3138, 3113, 1901, 1680, 1346, 3108, 1342, + 1192, 3106, 2778, 3125, 3132, 3126, 1192, 3124, 3111, 1341, + 1177, 925, 3254, 4148, 2288, 675, 675, 4004, 4000, 3846, + 3146, 683, 3268, 2777, 3845, 3834, 3145, 676, 3152, 1266, + 1267, 1268, 1265, 3830, 3677, 208, 3165, 199, 170, 3161, + 3162, 3285, 1192, 1976, 3158, 676, 3160, 676, 1192, 1192, + 1266, 1267, 1268, 1265, 3156, 3157, 3659, 2097, 2411, 3631, + 3304, 3240, 2776, 3533, 3532, 3159, 3530, 2920, 3499, 1995, + 3207, 1266, 1267, 1268, 1265, 3468, 3466, 3465, 3462, 3461, + 3455, 2479, 3278, 3453, 143, 143, 143, 1072, 2775, 1266, + 1267, 1268, 1265, 3333, 3434, 3336, 3424, 3336, 3336, 3212, + 3211, 3423, 1192, 2920, 3410, 3409, 3222, 3281, 204, 2920, + 2920, 1266, 1267, 1268, 1265, 1266, 1267, 1268, 1265, 3306, + 3358, 3241, 2774, 3354, 3238, 2867, 3205, 3256, 1892, 2773, + 3172, 1568, 1568, 1892, 1892, 3320, 3322, 3163, 3311, 3155, + 3154, 3148, 3288, 3082, 2661, 2657, 2656, 2324, 3293, 1266, + 1267, 1268, 1265, 2317, 3302, 2311, 1266, 1267, 1268, 1265, + 1298, 3277, 1074, 2920, 1074, 2310, 3287, 2309, 2308, 2306, + 1074, 2302, 3291, 3292, 2301, 2299, 3316, 2290, 676, 1071, + 3303, 1073, 2287, 2170, 3254, 683, 2173, 2286, 3332, 2176, + 3299, 2190, 2178, 3308, 3309, 1885, 1884, 1531, 1074, 2449, + 2077, 2077, 3341, 2448, 1883, 3315, 1848, 1847, 1838, 1580, + 3179, 3180, 1578, 4147, 3359, 3360, 3181, 3182, 3183, 3184, + 4105, 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, + 3194, 3195, 208, 3356, 2772, 3331, 3342, 4022, 1336, 3337, + 3338, 3999, 3933, 3930, 3917, 3912, 3815, 3814, 2221, 3796, + 3778, 3774, 3752, 3735, 1192, 3632, 3629, 1292, 2745, 1296, + 3600, 1266, 1267, 1268, 1265, 2771, 3422, 3599, 3364, 3596, + 3595, 3561, 1566, 1566, 3558, 1293, 1295, 1291, 3556, 1294, 1280, 1279, 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, - 1288, 1281, 38, 4093, 34, 13, 12, 35, 22, 21, - 4086, 1697, 4087, 20, 4088, 26, 4089, 32, 4090, 31, - 136, 4103, 2715, 4105, 4106, 135, 30, 134, 133, 4101, - 4099, 132, 131, 130, 129, 128, 4109, 29, 3947, 19, - 1192, 52, 51, 50, 4110, 49, 1280, 1279, 1289, 1290, - 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, 48, 3898, - 4122, 47, 9, 124, 119, 117, 28, 4125, 4124, 4123, - 1577, 118, 115, 116, 682, 4131, 4141, 4129, 4149, 114, - 113, 4148, 4128, 4135, 4136, 4137, 4138, 112, 107, 105, - 87, 86, 85, 100, 99, 98, 97, 4161, 4153, 96, - 95, 4120, 1192, 93, 94, 1005, 84, 83, 82, 81, - 143, 80, 102, 4165, 3986, 4166, 108, 1292, 4168, 1296, - 106, 91, 4174, 101, 92, 4178, 90, 89, 4175, 88, - 79, 78, 77, 168, 167, 1293, 1295, 1291, 166, 1294, - 1280, 1279, 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, - 1288, 1281, 4186, 165, 164, 162, 163, 161, 160, 159, - 158, 4149, 4194, 1733, 4148, 4193, 157, 156, 53, 54, - 55, 56, 178, 4178, 4195, 177, 179, 181, 143, 4199, - 183, 180, 185, 175, 173, 143, 176, 174, 172, 70, - 11, 122, 18, 1923, 1924, 4, 0, 0, 143, 0, - 0, 143, 143, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, - 0, 0, 0, 1954, 1860, 1861, 1862, 1863, 1959, 0, - 1867, 1868, 1869, 1870, 1872, 1873, 1874, 1875, 1876, 1877, - 1878, 1879, 1880, 1881, 1882, 0, 0, 0, 0, 0, - 208, 65, 199, 170, 0, 0, 0, 0, 0, 3792, - 0, 0, 0, 3793, 208, 65, 199, 170, 0, 200, - 0, 0, 0, 0, 0, 0, 191, 0, 0, 0, - 201, 0, 0, 200, 0, 0, 0, 0, 0, 0, - 191, 0, 0, 0, 201, 0, 0, 0, 0, 141, - 2012, 2013, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 141, 127, 2269, 1318, 0, 0, 0, - 0, 0, 0, 204, 0, 0, 0, 0, 127, 0, - 0, 0, 0, 0, 0, 0, 0, 204, 0, 1280, + 1288, 1281, 1266, 1267, 1268, 1265, 3520, 4016, 2770, 3369, + 3384, 3385, 3370, 3375, 2769, 204, 3164, 3378, 1627, 1385, + 1638, 1629, 1643, 676, 3902, 2598, 1646, 1635, 3395, 1462, + 3396, 4140, 2766, 3045, 3382, 1266, 1267, 1268, 1265, 3314, + 3007, 1266, 1267, 1268, 1265, 2765, 3339, 3307, 3403, 3372, + 2929, 2878, 2877, 3312, 3313, 2870, 3406, 3407, 3408, 1266, + 1267, 1268, 1265, 2764, 2270, 2835, 2780, 2671, 2275, 3412, + 2580, 2521, 1266, 1267, 1268, 1265, 2284, 2412, 1280, 1279, + 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 1266, 1267, 1268, 1265, 2383, 2382, 2345, 3474, 2758, 1769, + 204, 2163, 2151, 1898, 1712, 3435, 2748, 1661, 1636, 4014, + 2744, 3485, 1396, 2291, 1381, 3438, 3491, 3437, 1377, 1376, + 1375, 2298, 3457, 3441, 1374, 1266, 1267, 1268, 1265, 1373, + 1372, 3442, 1371, 1266, 1267, 1268, 1265, 1266, 1267, 1268, + 1265, 3492, 3447, 2315, 1370, 1369, 1368, 1367, 2320, 2321, + 2322, 676, 2077, 2325, 2326, 2327, 2328, 2329, 2330, 2331, + 2332, 2333, 2334, 3525, 2720, 1366, 3486, 1365, 3488, 4012, + 1782, 3478, 1364, 1363, 1362, 1577, 1361, 1360, 2725, 682, + 2562, 2097, 3545, 1359, 1358, 3386, 1357, 1356, 1355, 1354, + 1353, 1266, 1267, 1268, 1265, 3469, 3473, 1266, 1267, 1268, + 1265, 1352, 1349, 1348, 3475, 1347, 1345, 3402, 3564, 1344, + 1343, 1192, 1340, 1333, 1332, 143, 1330, 1329, 1328, 1327, + 3333, 3498, 3495, 1326, 1192, 1325, 1324, 1323, 3501, 1322, + 1321, 1320, 1319, 1314, 1313, 1312, 1192, 1311, 3611, 1310, + 1230, 3513, 1568, 1074, 1175, 3391, 3392, 3547, 3524, 4010, + 1074, 3597, 3515, 2419, 2397, 1218, 4138, 3531, 4089, 3394, + 2856, 2591, 676, 2193, 2077, 3496, 1229, 126, 1192, 3043, + 3048, 3594, 3565, 68, 3634, 3049, 3046, 67, 3544, 3543, + 3042, 3047, 3635, 143, 3050, 3604, 2552, 2553, 3401, 3400, + 143, 3397, 3551, 3052, 3041, 4041, 3949, 2941, 3757, 2685, + 225, 3587, 2674, 143, 1456, 3273, 143, 143, 1966, 1967, + 3622, 3128, 3625, 1192, 3329, 3601, 3330, 2489, 3606, 3607, + 143, 3439, 3440, 3413, 3603, 3613, 1961, 1962, 1963, 3034, + 3610, 3636, 3633, 675, 1181, 2065, 1621, 678, 3615, 3617, + 2669, 2690, 2691, 679, 1190, 3619, 3620, 680, 3626, 3624, + 2709, 3627, 3623, 1675, 2370, 1655, 2377, 2153, 1224, 3249, + 676, 3242, 2907, 2879, 2441, 2407, 1970, 1219, 1937, 3657, + 4151, 3693, 1834, 1833, 3034, 1392, 1393, 1390, 1391, 3643, + 3914, 1192, 3361, 1566, 2534, 1892, 2527, 1892, 1388, 1389, + 3654, 3653, 1386, 1387, 2078, 1523, 1522, 1257, 2211, 3405, + 3076, 1192, 1568, 1568, 2378, 2223, 1892, 1892, 3285, 1279, + 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 3730, 1475, 3690, 3730, 3692, 1474, 1447, 1498, 4112, 4110, + 4067, 4038, 4037, 4035, 3976, 3934, 3810, 1192, 3746, 1192, + 1606, 3719, 2920, 3809, 3747, 3681, 3724, 3725, 3749, 3649, + 3751, 3638, 3521, 3522, 3523, 3546, 1568, 3458, 3703, 3528, + 3529, 3721, 3702, 3555, 3701, 3557, 3431, 3550, 3430, 3712, + 3416, 2474, 2444, 1677, 676, 3415, 1192, 1192, 3723, 3734, + 1192, 1192, 3733, 3086, 1472, 3720, 4142, 4141, 3547, 2679, + 3131, 2682, 2808, 3673, 2207, 3745, 2807, 3798, 1733, 2801, + 1733, 3755, 2289, 1215, 4141, 3793, 4142, 3594, 3758, 3727, + 1972, 3776, 3411, 3807, 3762, 1189, 3782, 3783, 212, 3, + 3794, 3795, 3698, 1490, 76, 3816, 3817, 916, 917, 918, + 919, 1074, 1189, 2, 4164, 4165, 1, 3587, 1568, 2786, + 1896, 1394, 920, 1566, 1780, 915, 1544, 2572, 3750, 2131, + 1572, 1900, 3804, 922, 3059, 2722, 3803, 3060, 2728, 3404, + 3062, 3847, 2813, 2242, 3023, 2525, 3805, 2387, 3267, 2746, + 2747, 1457, 3840, 979, 1840, 1692, 1206, 2749, 2750, 1689, + 1205, 1203, 1785, 803, 3744, 2196, 3008, 2982, 3823, 3827, + 3806, 4150, 4184, 2755, 3851, 4104, 3853, 1780, 4153, 1710, + 3835, 3839, 1280, 1279, 1289, 1290, 1282, 1283, 1284, 1285, + 1286, 1287, 1288, 1281, 787, 3665, 3883, 3666, 4029, 3877, + 3939, 3828, 1739, 1892, 4108, 3941, 3826, 2247, 1262, 3856, + 3107, 1006, 844, 1192, 814, 1331, 1668, 3177, 3175, 813, + 3510, 2846, 3867, 2096, 3900, 3811, 3906, 3079, 3885, 1007, + 2179, 3936, 3824, 1622, 1626, 2440, 3878, 3879, 3657, 3893, + 3995, 3756, 3325, 3880, 2915, 1650, 3990, 3559, 3892, 3669, + 3896, 3667, 3668, 719, 2110, 649, 1056, 1192, 3797, 1566, + 2192, 720, 1568, 2418, 4055, 3916, 959, 3493, 2396, 960, + 952, 2865, 2864, 2540, 1733, 1750, 3742, 3743, 3913, 1526, + 1271, 1767, 3196, 3197, 1308, 3754, 1537, 3875, 758, 2896, + 2897, 2272, 2843, 3582, 3072, 3760, 75, 3922, 143, 74, + 73, 143, 143, 72, 143, 233, 805, 1574, 232, 1074, + 2547, 2551, 2552, 2553, 2548, 2556, 2549, 2554, 3968, 3955, + 2550, 3848, 2555, 3935, 3716, 4025, 4155, 784, 783, 3799, + 782, 781, 780, 779, 2545, 2546, 2544, 3963, 2542, 3964, + 2541, 2092, 2091, 3085, 1072, 3924, 3977, 143, 2547, 2551, + 2552, 2553, 2548, 2556, 2549, 2554, 1072, 3414, 2550, 2158, + 2555, 2160, 3800, 3283, 2944, 2939, 3801, 2017, 2015, 3971, + 3965, 1535, 143, 2469, 3994, 2476, 2014, 3979, 1192, 4086, + 3448, 3660, 4005, 4006, 3773, 2992, 1568, 3656, 1960, 4019, + 2465, 2034, 2963, 2031, 4026, 4009, 4011, 4013, 4015, 3988, + 3993, 2030, 2952, 1566, 3769, 3763, 2062, 4002, 3881, 3729, + 3566, 3567, 3573, 4027, 2406, 1125, 1121, 1123, 4008, 1124, + 1122, 2730, 3571, 3380, 2446, 3244, 2829, 2828, 2826, 3931, + 3932, 1892, 2825, 1432, 4034, 4032, 3967, 4051, 3697, 1568, + 2596, 2594, 3883, 1172, 3393, 4046, 3389, 1402, 1400, 2204, + 3398, 4050, 3044, 4047, 1298, 2219, 3127, 2093, 4077, 2089, + 2088, 1096, 1095, 3583, 4085, 1603, 3223, 4068, 3225, 4018, + 45, 4070, 994, 3025, 2535, 3858, 3574, 1965, 953, 2394, + 4071, 4072, 110, 41, 123, 109, 187, 3569, 60, 186, + 59, 4101, 3591, 3592, 121, 184, 58, 4094, 3570, 4095, + 104, 4096, 103, 4097, 120, 182, 4098, 57, 217, 1818, + 216, 3092, 219, 3094, 4111, 218, 4113, 4114, 4109, 4107, + 215, 2647, 4069, 2648, 4117, 3955, 214, 1566, 1192, 1610, + 213, 4039, 1892, 3732, 4118, 3575, 4021, 1892, 910, 44, + 43, 188, 42, 111, 990, 991, 61, 3906, 4130, 2221, + 40, 39, 38, 34, 13, 1034, 3925, 4133, 4132, 4136, + 4131, 12, 4139, 4137, 4149, 3748, 4157, 35, 22, 4156, + 21, 4143, 4144, 4145, 4146, 1697, 20, 26, 32, 31, + 1566, 136, 135, 30, 3147, 4169, 134, 133, 132, 4128, + 1192, 4161, 131, 130, 129, 128, 29, 19, 52, 51, + 50, 4173, 3994, 4174, 49, 48, 4176, 47, 9, 124, + 4182, 119, 3171, 4186, 117, 3173, 4183, 28, 118, 1280, 1279, 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, - 1281, 0, 0, 0, 0, 0, 0, 0, 0, 2140, - 0, 0, 0, 0, 0, 2140, 2140, 2140, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3993, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 150, 151, 0, 152, 153, 0, 0, 0, 154, 0, - 0, 155, 0, 0, 150, 151, 0, 152, 153, 0, + 1281, 115, 3978, 3590, 116, 2455, 114, 3982, 3983, 1036, + 4194, 113, 1035, 112, 107, 105, 87, 86, 85, 4157, + 4202, 1733, 4156, 4201, 100, 99, 98, 1923, 1924, 97, + 3579, 4186, 4203, 96, 95, 93, 94, 4207, 4003, 1280, + 1279, 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, + 1281, 1020, 3576, 3580, 3578, 3577, 1005, 1954, 84, 83, + 995, 82, 1959, 1814, 81, 80, 102, 108, 106, 91, + 1811, 101, 92, 90, 1813, 1810, 1812, 1816, 1817, 89, + 1818, 88, 1815, 79, 78, 77, 168, 997, 167, 166, + 165, 164, 162, 163, 208, 65, 199, 170, 161, 160, + 159, 158, 157, 3585, 3586, 156, 53, 54, 55, 56, + 178, 177, 179, 200, 181, 183, 180, 185, 175, 173, + 191, 176, 174, 172, 201, 731, 730, 737, 727, 70, + 11, 122, 18, 4, 2012, 2013, 0, 0, 734, 735, + 0, 736, 740, 141, 0, 721, 0, 0, 0, 2565, + 0, 0, 0, 0, 0, 745, 3593, 0, 127, 0, + 3340, 0, 0, 1019, 1017, 0, 0, 204, 3572, 0, + 0, 0, 0, 0, 3584, 0, 0, 0, 0, 0, + 4120, 4121, 0, 0, 0, 0, 0, 4125, 4126, 4127, + 1016, 0, 0, 2140, 0, 0, 0, 0, 0, 2140, + 2140, 2140, 989, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 996, 1029, 0, 2096, 0, 0, 0, + 0, 0, 0, 0, 143, 0, 1821, 1822, 1823, 1824, + 1825, 1826, 1819, 1820, 0, 0, 0, 1025, 0, 0, + 0, 0, 0, 0, 150, 151, 0, 152, 153, 0, 0, 0, 154, 0, 0, 155, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 731, 730, 737, 727, 0, 0, 0, 0, - 0, 0, 3917, 0, 0, 734, 735, 0, 736, 740, - 0, 0, 721, 0, 0, 0, 0, 0, 0, 0, - 0, 4074, 745, 0, 169, 197, 206, 198, 125, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 169, 197, - 206, 198, 125, 0, 0, 0, 0, 196, 190, 189, - 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, - 0, 196, 190, 189, 0, 0, 0, 0, 71, 0, - 0, 0, 149, 0, 0, 0, 0, 0, 3970, 0, - 0, 0, 0, 3974, 3975, 0, 149, 0, 2096, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4074, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3995, 192, 193, 194, 0, 0, - 0, 0, 0, 0, 0, 994, 0, 0, 0, 192, - 193, 194, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4074, 0, 0, - 0, 0, 0, 143, 202, 0, 143, 143, 0, 143, - 0, 0, 0, 0, 0, 0, 0, 0, 202, 0, - 0, 0, 0, 0, 0, 137, 0, 0, 0, 195, - 0, 138, 0, 0, 0, 0, 0, 990, 991, 137, - 0, 0, 0, 195, 0, 138, 0, 0, 1034, 1072, - 0, 0, 143, 0, 0, 0, 722, 724, 723, 0, - 0, 1072, 4197, 0, 0, 0, 0, 729, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 143, 0, 733, - 0, 0, 0, 0, 0, 2365, 748, 2367, 139, 0, - 0, 0, 0, 726, 0, 0, 4112, 4113, 0, 0, - 0, 64, 139, 4117, 4118, 4119, 2384, 2385, 2386, 0, - 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, - 0, 2402, 2403, 2404, 2405, 0, 0, 731, 730, 737, - 727, 0, 1036, 0, 0, 1035, 0, 0, 0, 0, - 734, 735, 0, 736, 740, 0, 0, 721, 0, 0, - 66, 0, 0, 0, 0, 0, 0, 745, 0, 1298, - 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1020, 0, 0, 0, 0, 0, - 0, 0, 0, 995, 0, 147, 205, 0, 148, 0, - 0, 0, 0, 171, 0, 0, 0, 0, 62, 147, - 205, 0, 148, 749, 0, 0, 751, 171, 0, 0, - 997, 750, 62, 0, 0, 0, 0, 0, 0, 0, - 0, 728, 732, 738, 0, 739, 741, 0, 0, 742, - 743, 744, 0, 0, 746, 747, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1537, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 140, 46, 0, 0, 0, 0, - 0, 63, 0, 0, 0, 5, 0, 0, 140, 46, - 0, 0, 0, 0, 0, 63, 1019, 1017, 0, 0, - 0, 0, 0, 0, 144, 145, 1574, 0, 146, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 144, 145, - 0, 2140, 146, 1016, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 989, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 996, 1029, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 722, 724, 723, 0, 0, 0, 0, 0, 0, - 1025, 0, 729, 0, 2063, 0, 0, 0, 0, 2024, - 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, - 0, 748, 0, 0, 0, 0, 0, 0, 726, 0, - 725, 0, 716, 0, 0, 0, 1026, 1030, 0, 0, - 2065, 2033, 0, 0, 0, 0, 0, 0, 0, 0, - 2066, 2067, 0, 0, 0, 0, 1013, 0, 1011, 1015, - 1033, 0, 0, 0, 1012, 1009, 1008, 0, 1014, 999, - 1000, 998, 1001, 1002, 1003, 1004, 2032, 1031, 0, 1032, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1027, 1028, 0, 0, 2040, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1266, 1267, 1268, 1265, 0, 0, 0, - 0, 0, 0, 0, 2563, 0, 0, 1023, 0, 0, - 0, 0, 0, 1022, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1018, 0, - 0, 0, 0, 0, 0, 0, 728, 732, 738, 0, - 739, 741, 2056, 0, 742, 743, 744, 0, 0, 746, - 747, 0, 0, 0, 0, 2807, 2808, 0, 0, 0, - 0, 1144, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2096, 0, 1818, 0, 0, 0, 0, 0, 143, - 0, 0, 0, 0, 0, 0, 0, 2063, 0, 0, - 0, 0, 2024, 0, 2881, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1021, 0, 0, 0, - 0, 0, 992, 993, 0, 987, 2023, 2025, 2022, 0, - 988, 2019, 0, 2065, 2033, 0, 2044, 0, 0, 0, - 0, 0, 0, 2066, 2067, 0, 0, 2050, 0, 0, - 0, 0, 0, 0, 0, 2035, 0, 2018, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2038, 2072, 2032, - 0, 2039, 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, - 2053, 2055, 2058, 2059, 2060, 0, 0, 2040, 0, 0, - 0, 0, 2048, 2057, 2049, 1129, 0, 0, 0, 1119, - 0, 0, 0, 0, 2027, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 725, 1152, 1156, 1158, 1160, - 1162, 1163, 1165, 0, 1170, 1166, 1167, 1168, 1169, 0, - 1147, 1148, 1149, 1150, 1127, 1128, 1153, 0, 1130, 2064, - 1132, 1133, 1134, 1135, 1131, 1136, 1137, 1138, 1139, 1140, - 1143, 1145, 1141, 1142, 1151, 2056, 0, 0, 0, 0, - 0, 0, 1155, 1157, 1159, 1161, 1164, 1814, 0, 0, - 0, 2020, 2021, 0, 1811, 0, 0, 0, 1813, 1810, - 1812, 1816, 1817, 0, 3074, 3075, 1815, 0, 0, 2061, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1146, 0, 0, 0, 2037, 0, 0, 0, - 0, 0, 0, 2036, 0, 0, 0, 0, 0, 0, - 0, 0, 143, 0, 0, 0, 0, 0, 0, 2023, - 2907, 2022, 143, 0, 2906, 0, 0, 2054, 0, 2044, - 0, 0, 0, 0, 0, 0, 2042, 0, 0, 0, - 2050, 0, 0, 0, 0, 0, 0, 0, 0, 2069, - 2068, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2038, 2072, 0, 0, 2039, 2041, 2043, 0, 2045, 2046, - 2047, 2051, 2052, 2053, 2055, 2058, 2059, 2060, 0, 0, - 0, 0, 0, 0, 0, 2048, 2057, 2049, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2027, 0, 0, - 0, 0, 2029, 0, 0, 0, 0, 0, 0, 1799, - 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, - 1821, 1822, 1823, 1824, 1825, 1826, 1819, 1820, 0, 0, - 0, 0, 2064, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2071, 0, 0, 2070, 0, 2096, - 2096, 2096, 2096, 2096, 2096, 0, 0, 0, 0, 0, - 0, 1144, 0, 0, 2020, 2021, 2096, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2061, 0, 0, 0, 0, 731, 730, 737, - 727, 3218, 0, 0, 0, 0, 0, 0, 0, 2037, - 734, 735, 0, 736, 740, 0, 2036, 721, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 745, 0, 0, - 0, 0, 0, 0, 1144, 0, 0, 0, 0, 0, - 2054, 0, 0, 0, 0, 0, 0, 0, 0, 2042, - 3273, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2069, 2068, 143, 0, 0, 0, 3286, 143, - 3287, 0, 0, 749, 0, 1818, 751, 0, 0, 0, - 0, 750, 0, 0, 0, 0, 0, 0, 0, 0, - 143, 0, 0, 0, 0, 1129, 0, 0, 0, 0, - 0, 0, 143, 1154, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2029, 1152, 1156, 1158, 1160, - 1162, 1163, 1165, 0, 1170, 1166, 1167, 1168, 1169, 0, - 1147, 1148, 1149, 1150, 1127, 1128, 1153, 0, 1130, 0, - 1132, 1133, 1134, 1135, 1131, 1136, 1137, 1138, 1139, 1140, - 1143, 1145, 1141, 1142, 1151, 0, 0, 2071, 1129, 0, - 2070, 0, 1155, 1157, 1159, 1161, 1164, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1152, - 1156, 1158, 1160, 1162, 1163, 1165, 0, 1170, 1166, 1167, - 1168, 1169, 0, 1147, 1148, 1149, 1150, 1127, 1128, 1153, - 2140, 1130, 1146, 1132, 1133, 1134, 1135, 1131, 1136, 1137, - 1138, 1139, 1140, 1143, 1145, 1141, 1142, 1151, 0, 0, - 0, 722, 724, 723, 0, 1155, 1157, 1159, 1161, 1164, - 0, 2063, 729, 0, 0, 0, 0, 0, 208, 0, - 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, - 0, 748, 0, 0, 0, 0, 0, 0, 726, 1814, - 0, 3721, 0, 0, 0, 1146, 1811, 2065, 0, 0, - 1813, 1810, 1812, 1816, 1817, 0, 0, 0, 1815, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1072, - 0, 143, 0, 0, 0, 0, 0, 143, 0, 0, - 0, 0, 0, 0, 2096, 0, 0, 0, 0, 0, - 0, 204, 2063, 0, 0, 0, 0, 0, 0, 0, - 0, 2040, 0, 0, 143, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3438, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2065, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2724, - 2725, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 728, 732, 738, 2056, - 739, 741, 3897, 0, 742, 743, 744, 0, 0, 746, - 747, 0, 2040, 0, 0, 0, 0, 0, 0, 0, - 0, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, - 1808, 1809, 1821, 1822, 1823, 1824, 1825, 1826, 1819, 1820, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2140, 0, 0, 0, 0, 0, 0, - 2056, 0, 0, 2044, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2050, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1154, 2038, 2072, 0, 0, 2039, 2041, + 0, 0, 0, 0, 1814, 0, 0, 0, 0, 0, + 0, 1811, 0, 1026, 1030, 1813, 1810, 1812, 1816, 1817, + 0, 0, 0, 1815, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1013, 0, 1011, 1015, 1033, 0, 0, + 0, 1012, 1009, 1008, 3589, 1014, 999, 1000, 998, 1001, + 1002, 1003, 1004, 0, 1031, 0, 1032, 0, 169, 197, + 206, 198, 125, 0, 0, 0, 0, 1027, 1028, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 196, 190, 189, 0, 0, 0, 0, 71, 722, + 724, 723, 0, 0, 0, 0, 0, 0, 0, 0, + 729, 0, 0, 0, 1023, 0, 149, 0, 0, 0, + 1022, 0, 733, 0, 0, 0, 0, 0, 0, 748, + 3588, 0, 0, 0, 0, 1018, 726, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3450, 0, + 0, 0, 0, 0, 0, 3452, 0, 0, 0, 192, + 193, 194, 0, 0, 2717, 0, 1799, 1800, 1801, 1802, + 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1821, 1822, 1823, + 1824, 1825, 1826, 1819, 1820, 0, 0, 3467, 1280, 1279, + 1289, 1290, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, + 0, 0, 0, 0, 0, 0, 0, 143, 202, 0, + 0, 0, 2269, 1021, 0, 0, 0, 143, 0, 992, + 993, 0, 987, 0, 0, 0, 0, 988, 0, 137, + 0, 0, 0, 195, 0, 138, 1280, 1279, 1289, 1290, + 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1281, 0, 0, + 0, 2063, 0, 0, 0, 0, 2024, 0, 0, 0, + 0, 0, 0, 0, 728, 732, 738, 0, 739, 741, + 0, 0, 742, 743, 744, 0, 0, 746, 747, 2365, + 0, 2367, 0, 0, 0, 0, 0, 2065, 2033, 0, + 0, 0, 139, 0, 0, 0, 0, 2066, 2067, 0, + 2384, 2385, 2386, 0, 0, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2402, 2403, 2404, 2405, 0, + 0, 0, 0, 2032, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2040, 0, 0, 0, 0, 2096, 2096, 2096, 2096, + 2096, 2096, 0, 1892, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 2096, 0, 0, 0, 0, 0, 1892, + 0, 0, 3628, 0, 0, 3630, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, + 205, 0, 148, 0, 0, 0, 3637, 171, 0, 0, + 0, 0, 62, 0, 0, 0, 0, 0, 0, 2056, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1144, 0, + 0, 0, 0, 725, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1537, 0, 0, 0, 0, 0, 0, + 0, 143, 0, 0, 0, 0, 143, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 140, 46, + 0, 0, 0, 2063, 0, 63, 0, 143, 2024, 5, + 0, 0, 0, 2023, 2025, 2022, 0, 0, 2019, 143, + 1574, 0, 0, 2044, 0, 0, 0, 0, 144, 145, + 0, 0, 146, 0, 2050, 2140, 0, 0, 0, 2065, + 2033, 0, 2035, 0, 2018, 0, 0, 0, 0, 2066, + 2067, 0, 0, 0, 2038, 2072, 0, 0, 2039, 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, 2053, 2055, 2058, - 2059, 2060, 0, 0, 0, 0, 0, 0, 0, 2048, - 2057, 2049, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2044, 725, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2050, 1154, 0, 0, 0, - 0, 2140, 0, 0, 0, 0, 2064, 0, 0, 0, - 0, 0, 0, 0, 0, 2038, 2072, 0, 0, 2039, - 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, 2053, 2055, - 2058, 2059, 2060, 0, 0, 0, 0, 0, 0, 0, - 2048, 2057, 2049, 0, 0, 0, 0, 0, 0, 0, + 2059, 2060, 0, 0, 0, 2032, 0, 0, 0, 2048, + 2057, 2049, 1129, 0, 0, 0, 0, 0, 0, 0, + 0, 2027, 0, 2040, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1152, 1156, 1158, 1160, 1162, 1163, 1165, + 0, 1170, 1166, 1167, 1168, 1169, 0, 1147, 1148, 1149, + 1150, 1127, 1128, 1153, 0, 1130, 2064, 1132, 1133, 1134, + 1135, 1131, 1136, 1137, 1138, 1139, 1140, 1143, 1145, 1141, + 1142, 1151, 0, 0, 0, 0, 0, 0, 0, 1155, + 1157, 1159, 1161, 1164, 0, 0, 0, 0, 2020, 2021, + 0, 2056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2061, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1146, 0, 0, 0, 2037, 0, 0, 0, 0, 0, 0, - 2036, 0, 0, 0, 0, 0, 0, 2064, 0, 143, - 0, 0, 0, 0, 0, 0, 143, 0, 0, 3675, - 0, 0, 0, 0, 2054, 0, 0, 0, 0, 0, - 0, 0, 0, 2042, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2061, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2096, 0, 0, - 0, 0, 0, 0, 2037, 0, 0, 0, 0, 0, - 0, 2036, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2054, 0, 0, 0, 0, - 0, 0, 0, 0, 2042, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3773, 0, 0, 0, 0, 0, 0, 0, - 0, 171, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 821, 0, 0, 0, 0, 0, 0, 0, 0, - 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, - 0, 0, 0, 143, 773, 0, 0, 0, 339, 0, - 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, - 351, 542, 543, 544, 514, 545, 515, 546, 547, 812, - 570, 521, 436, 388, 588, 587, 0, 0, 881, 889, - 0, 0, 0, 0, 0, 0, 0, 0, 877, 0, - 0, 0, 0, 765, 0, 0, 802, 857, 856, 789, - 799, 0, 0, 313, 231, 516, 636, 518, 517, 790, - 0, 791, 795, 798, 794, 792, 793, 0, 872, 0, - 0, 0, 0, 0, 0, 757, 769, 0, 774, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2036, 0, 0, 0, 0, 0, 1072, 0, 143, 0, + 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, + 0, 2096, 0, 0, 2054, 0, 0, 0, 0, 0, + 0, 0, 0, 2042, 0, 2023, 2910, 2022, 0, 0, + 2909, 0, 143, 0, 0, 2044, 2069, 2068, 0, 0, + 0, 0, 0, 0, 0, 0, 2050, 0, 0, 2809, + 2810, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2038, 2072, 0, 0, + 2039, 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, 2053, + 2055, 2058, 2059, 2060, 0, 0, 0, 0, 2883, 2029, + 0, 2048, 2057, 2049, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2027, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2071, 0, 0, 2070, 0, 2726, 2727, 2064, 0, + 0, 0, 0, 0, 0, 1318, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1144, 0, 0, + 2020, 2021, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2061, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2037, 0, 0, 0, 0, + 0, 0, 2036, 4001, 0, 0, 0, 0, 731, 730, + 737, 727, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 734, 735, 0, 736, 740, 2054, 0, 721, 0, + 1144, 0, 0, 0, 0, 2042, 0, 0, 745, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2069, 2068, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3077, 3078, 0, 0, 0, 0, 0, 0, 0, 0, + 1154, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1129, 0, 0, 749, 1119, 0, 751, 0, 0, + 4082, 0, 750, 0, 0, 0, 0, 0, 0, 0, + 0, 2029, 1152, 1156, 1158, 1160, 1162, 1163, 1165, 0, + 1170, 1166, 1167, 1168, 1169, 0, 1147, 1148, 1149, 1150, + 1127, 1128, 1153, 0, 1130, 0, 1132, 1133, 1134, 1135, + 1131, 1136, 1137, 1138, 1139, 1140, 1143, 1145, 1141, 1142, + 1151, 0, 0, 2071, 0, 0, 2070, 0, 1155, 1157, + 1159, 1161, 1164, 0, 1129, 0, 0, 143, 0, 0, + 1266, 1267, 1268, 1265, 143, 0, 0, 0, 0, 0, + 4082, 0, 0, 0, 0, 1152, 1156, 1158, 1160, 1162, + 1163, 1165, 0, 1170, 1166, 1167, 1168, 1169, 1146, 1147, + 1148, 1149, 1150, 1127, 1128, 1153, 0, 1130, 0, 1132, + 1133, 1134, 1135, 1131, 1136, 1137, 1138, 1139, 1140, 1143, + 1145, 1141, 1142, 1151, 0, 2096, 0, 0, 0, 0, + 0, 1155, 1157, 1159, 1161, 1164, 4082, 0, 2063, 0, + 0, 0, 722, 724, 723, 208, 731, 730, 737, 727, + 1818, 0, 0, 729, 0, 0, 0, 0, 0, 734, + 735, 0, 736, 740, 0, 733, 721, 0, 3728, 0, + 0, 1146, 748, 0, 2065, 0, 745, 0, 0, 726, + 0, 0, 0, 716, 0, 0, 0, 3221, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4205, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, + 0, 0, 749, 0, 0, 751, 0, 0, 2040, 0, + 750, 0, 0, 0, 0, 0, 3276, 0, 0, 0, + 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3289, 0, 3290, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2056, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 728, 732, 738, + 0, 739, 741, 0, 0, 742, 743, 744, 0, 0, + 746, 747, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1814, 0, 0, 0, 0, 0, + 0, 1811, 0, 0, 0, 1813, 1810, 1812, 1816, 1817, + 0, 0, 0, 1815, 0, 143, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 722, 724, 723, 0, 0, 0, 0, 0, 0, 0, + 2044, 729, 0, 0, 0, 0, 0, 2140, 0, 0, + 0, 2050, 0, 733, 0, 0, 0, 0, 0, 1154, + 748, 0, 0, 0, 0, 0, 0, 726, 0, 0, + 0, 2038, 2072, 0, 0, 2039, 2041, 2043, 0, 2045, + 2046, 2047, 2051, 2052, 2053, 2055, 2058, 2059, 2060, 0, + 0, 0, 0, 0, 0, 0, 2048, 2057, 2049, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1154, 0, 0, 0, 725, 0, 0, 0, + 0, 0, 0, 2064, 0, 0, 1799, 1800, 1801, 1802, + 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1821, 1822, 1823, + 1824, 1825, 1826, 1819, 1820, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3444, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2061, 0, 728, 732, 738, 0, 739, + 741, 0, 0, 742, 743, 744, 0, 0, 746, 747, + 2037, 0, 0, 143, 0, 0, 0, 2036, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2054, 0, 0, 0, 0, 0, 0, 0, 0, + 2042, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 821, 0, 0, 0, 0, 0, 0, + 2140, 0, 404, 0, 0, 534, 567, 556, 640, 522, + 0, 0, 0, 0, 0, 0, 773, 0, 0, 0, + 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, + 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, + 547, 812, 570, 521, 436, 388, 588, 587, 171, 0, + 881, 889, 0, 0, 725, 0, 0, 0, 0, 0, + 877, 0, 0, 0, 0, 765, 0, 0, 802, 857, + 856, 789, 799, 0, 0, 313, 231, 516, 636, 518, + 517, 790, 0, 791, 795, 798, 794, 792, 793, 0, + 872, 0, 0, 0, 0, 0, 0, 757, 769, 0, + 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2140, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 767, 0, 0, 0, 0, + 822, 0, 768, 0, 0, 817, 796, 800, 0, 0, + 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, + 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, + 362, 363, 304, 0, 422, 337, 353, 334, 401, 797, + 820, 824, 333, 895, 818, 470, 307, 0, 469, 400, + 456, 461, 386, 379, 0, 306, 458, 384, 378, 366, + 343, 896, 367, 368, 357, 412, 376, 413, 358, 390, + 389, 391, 0, 0, 0, 0, 0, 498, 499, 3682, + 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 629, 815, 0, 633, 0, 472, 0, + 0, 879, 0, 0, 0, 442, 0, 0, 369, 0, + 0, 0, 819, 0, 425, 406, 892, 0, 0, 423, + 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, + 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, + 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, + 355, 322, 298, 328, 326, 329, 432, 330, 300, 410, + 453, 0, 350, 420, 382, 301, 381, 411, 452, 451, + 311, 479, 485, 486, 575, 0, 491, 664, 665, 666, + 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3781, 505, 506, 507, 509, 510, 511, + 512, 576, 593, 560, 530, 493, 584, 527, 531, 532, + 360, 596, 1842, 1841, 1843, 484, 370, 371, 0, 342, + 341, 383, 302, 348, 294, 295, 659, 876, 402, 598, + 631, 632, 523, 0, 891, 871, 873, 874, 878, 882, + 883, 884, 885, 886, 888, 890, 894, 658, 0, 577, + 592, 662, 591, 655, 408, 0, 429, 589, 536, 0, + 581, 555, 0, 582, 551, 586, 0, 525, 0, 437, + 465, 477, 494, 497, 526, 611, 612, 613, 299, 496, + 615, 616, 617, 618, 619, 620, 621, 614, 893, 558, + 535, 561, 476, 538, 537, 0, 0, 572, 823, 573, + 574, 392, 393, 394, 395, 880, 599, 318, 495, 418, + 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, + 564, 565, 562, 667, 0, 622, 623, 0, 0, 489, + 490, 347, 354, 508, 356, 317, 407, 349, 474, 364, + 0, 501, 566, 502, 625, 628, 626, 627, 399, 359, + 361, 433, 365, 375, 421, 473, 405, 426, 315, 464, + 435, 380, 552, 579, 902, 875, 901, 903, 904, 900, + 905, 906, 887, 778, 0, 830, 898, 897, 899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 767, 143, 0, 0, 0, 822, 0, - 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, - 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, - 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, - 304, 0, 422, 337, 353, 334, 401, 797, 820, 824, - 333, 895, 818, 470, 307, 0, 469, 400, 456, 461, - 386, 379, 0, 306, 458, 384, 378, 366, 343, 896, - 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, - 0, 0, 0, 0, 0, 498, 499, 0, 0, 647, + 607, 606, 605, 604, 603, 602, 601, 600, 0, 0, + 549, 450, 327, 288, 323, 324, 331, 656, 652, 455, + 657, 785, 296, 529, 373, 0, 417, 346, 594, 595, + 0, 646, 864, 837, 838, 839, 775, 840, 834, 835, + 776, 836, 865, 828, 861, 862, 804, 831, 841, 860, + 842, 863, 866, 867, 907, 908, 848, 832, 260, 909, + 845, 868, 859, 858, 843, 829, 869, 870, 811, 806, + 846, 847, 833, 852, 853, 854, 777, 825, 826, 827, + 849, 850, 807, 808, 809, 810, 0, 0, 0, 480, + 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, + 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, + 637, 639, 855, 641, 440, 441, 648, 0, 851, 644, + 645, 642, 377, 427, 446, 434, 821, 660, 519, 520, + 661, 630, 0, 770, 0, 404, 0, 0, 534, 567, + 556, 640, 522, 0, 0, 0, 0, 0, 0, 773, + 0, 0, 0, 339, 1893, 0, 372, 571, 553, 563, + 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, + 545, 515, 546, 547, 812, 570, 521, 436, 388, 588, + 587, 0, 0, 881, 889, 0, 0, 0, 0, 0, + 0, 0, 0, 877, 0, 2122, 0, 0, 765, 0, + 0, 802, 857, 856, 789, 799, 0, 0, 313, 231, + 516, 636, 518, 517, 790, 0, 791, 795, 798, 794, + 792, 793, 0, 872, 0, 0, 0, 0, 0, 0, + 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 629, 815, 0, 633, 0, 472, 0, 0, 879, - 0, 0, 0, 442, 0, 0, 369, 0, 0, 0, - 819, 0, 425, 406, 892, 0, 0, 423, 374, 457, - 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, - 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, - 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, - 298, 328, 326, 329, 432, 330, 300, 410, 453, 0, - 350, 420, 382, 301, 381, 411, 452, 451, 311, 479, - 485, 486, 575, 0, 491, 664, 665, 666, 500, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 143, 505, 506, 507, 509, 510, 511, 512, 576, - 593, 560, 530, 493, 584, 527, 531, 532, 360, 596, - 1842, 1841, 1843, 484, 370, 371, 0, 342, 341, 383, - 302, 348, 294, 295, 659, 876, 402, 598, 631, 632, - 523, 0, 891, 871, 873, 874, 878, 882, 883, 884, - 885, 886, 888, 890, 894, 658, 0, 577, 592, 662, - 591, 655, 408, 0, 429, 589, 536, 0, 581, 555, - 0, 582, 551, 586, 0, 525, 0, 437, 465, 477, - 494, 497, 526, 611, 612, 613, 299, 496, 615, 616, - 617, 618, 619, 620, 621, 614, 893, 558, 535, 561, - 476, 538, 537, 0, 0, 572, 823, 573, 574, 392, - 393, 394, 395, 880, 599, 318, 495, 418, 0, 559, - 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, - 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, + 0, 0, 0, 0, 0, 0, 0, 766, 767, 0, + 0, 0, 0, 822, 0, 768, 0, 0, 2123, 796, + 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, + 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, + 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, + 334, 401, 797, 820, 824, 333, 895, 818, 470, 307, + 0, 469, 400, 456, 461, 386, 379, 0, 306, 458, + 384, 378, 366, 343, 896, 367, 368, 357, 412, 376, + 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, + 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 629, 815, 0, 633, + 0, 472, 0, 0, 879, 0, 0, 0, 442, 0, + 0, 369, 0, 0, 0, 819, 0, 425, 406, 892, + 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, + 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, + 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, + 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, + 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, + 411, 452, 451, 311, 479, 485, 486, 575, 0, 491, + 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, + 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, + 527, 531, 532, 360, 596, 0, 0, 0, 484, 370, + 371, 0, 342, 341, 383, 302, 348, 294, 295, 659, + 876, 402, 598, 631, 632, 523, 0, 891, 871, 873, + 874, 878, 882, 883, 884, 885, 886, 888, 890, 894, + 658, 0, 577, 592, 662, 591, 655, 408, 0, 429, + 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, + 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, + 613, 299, 496, 615, 616, 617, 618, 619, 620, 621, + 614, 893, 558, 535, 561, 476, 538, 537, 0, 0, + 572, 823, 573, 574, 392, 393, 394, 395, 880, 599, + 318, 495, 418, 0, 559, 0, 0, 0, 0, 0, + 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, + 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, + 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, + 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, + 426, 315, 464, 435, 380, 552, 579, 902, 875, 901, + 903, 904, 900, 905, 906, 887, 778, 0, 830, 898, + 897, 899, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, + 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, + 656, 652, 455, 657, 785, 296, 529, 373, 0, 417, + 346, 594, 595, 0, 646, 864, 837, 838, 839, 775, + 840, 834, 835, 776, 836, 865, 828, 861, 862, 804, + 831, 841, 860, 842, 863, 866, 867, 907, 908, 848, + 832, 260, 909, 845, 868, 859, 858, 843, 829, 869, + 870, 811, 806, 846, 847, 833, 852, 853, 854, 777, + 825, 826, 827, 849, 850, 807, 808, 809, 810, 0, + 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, + 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, + 0, 634, 635, 637, 639, 855, 641, 440, 441, 648, + 0, 851, 644, 645, 642, 377, 427, 446, 434, 0, + 660, 519, 520, 661, 630, 0, 770, 208, 821, 0, + 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, + 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, + 0, 773, 0, 0, 0, 339, 0, 0, 372, 571, + 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, + 544, 514, 545, 515, 546, 547, 1301, 570, 521, 436, + 388, 588, 587, 0, 0, 881, 889, 0, 0, 0, + 0, 0, 0, 0, 0, 877, 0, 0, 0, 0, + 765, 0, 0, 802, 857, 856, 789, 799, 0, 0, + 313, 231, 516, 636, 518, 517, 790, 0, 791, 795, + 798, 794, 792, 793, 0, 872, 0, 0, 0, 0, + 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, + 767, 0, 0, 0, 0, 822, 0, 768, 0, 0, + 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, + 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, + 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, + 337, 353, 334, 401, 797, 820, 824, 333, 895, 818, + 470, 307, 0, 469, 400, 456, 461, 386, 379, 0, + 306, 458, 384, 378, 366, 343, 896, 367, 368, 357, + 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, + 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 629, 815, + 0, 633, 0, 472, 0, 0, 879, 0, 0, 0, + 442, 0, 0, 369, 0, 0, 0, 819, 0, 425, + 406, 892, 0, 0, 423, 374, 457, 414, 463, 444, + 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, + 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, + 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, + 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, + 301, 381, 411, 452, 451, 311, 479, 485, 486, 575, + 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, + 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, + 493, 584, 527, 531, 532, 360, 596, 0, 0, 0, + 484, 370, 371, 0, 342, 341, 383, 302, 348, 294, + 295, 659, 876, 402, 598, 631, 632, 523, 0, 891, + 871, 873, 874, 878, 882, 883, 884, 885, 886, 888, + 890, 894, 658, 0, 577, 592, 662, 591, 655, 408, + 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, + 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, + 611, 612, 613, 299, 496, 615, 616, 617, 618, 619, + 620, 621, 614, 893, 558, 535, 561, 476, 538, 537, + 0, 0, 572, 823, 573, 574, 392, 393, 394, 395, + 880, 599, 318, 495, 418, 0, 559, 0, 0, 0, + 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, + 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, + 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, + 628, 626, 627, 399, 359, 361, 433, 365, 375, 421, + 473, 405, 426, 315, 464, 435, 380, 552, 579, 902, + 875, 901, 903, 904, 900, 905, 906, 887, 778, 0, + 830, 898, 897, 899, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, + 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, + 324, 331, 656, 652, 455, 657, 785, 296, 529, 373, + 171, 417, 346, 594, 595, 0, 646, 864, 837, 838, + 839, 775, 840, 834, 835, 776, 836, 865, 828, 861, + 862, 804, 831, 841, 860, 842, 863, 866, 867, 907, + 908, 848, 832, 260, 909, 845, 868, 859, 858, 843, + 829, 869, 870, 811, 806, 846, 847, 833, 852, 853, + 854, 777, 825, 826, 827, 849, 850, 807, 808, 809, + 810, 0, 0, 0, 480, 481, 482, 504, 0, 466, + 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, + 590, 624, 0, 634, 635, 637, 639, 855, 641, 440, + 441, 648, 0, 851, 644, 645, 642, 377, 427, 446, + 434, 821, 660, 519, 520, 661, 630, 0, 770, 0, + 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, + 0, 0, 0, 0, 773, 0, 0, 0, 339, 4204, + 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, + 351, 542, 543, 544, 514, 545, 515, 546, 547, 812, + 570, 521, 436, 388, 588, 587, 0, 0, 881, 889, + 0, 0, 0, 0, 0, 0, 0, 0, 877, 0, + 0, 0, 0, 765, 0, 0, 802, 857, 856, 789, + 799, 0, 0, 313, 231, 516, 636, 518, 517, 790, + 0, 791, 795, 798, 794, 792, 793, 0, 872, 0, + 0, 0, 0, 0, 0, 757, 769, 0, 774, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 766, 767, 0, 0, 0, 0, 822, 0, + 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, + 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, + 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, + 304, 0, 422, 337, 353, 334, 401, 797, 820, 824, + 333, 895, 818, 470, 307, 0, 469, 400, 456, 461, + 386, 379, 0, 306, 458, 384, 378, 366, 343, 896, + 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, + 0, 0, 0, 0, 0, 498, 499, 0, 0, 647, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 629, 815, 0, 633, 0, 472, 0, 0, 879, + 0, 0, 0, 442, 0, 0, 369, 0, 0, 0, + 819, 0, 425, 406, 892, 0, 0, 423, 374, 457, + 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, + 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, + 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, + 298, 328, 326, 329, 432, 330, 300, 410, 453, 0, + 350, 420, 382, 301, 381, 411, 452, 451, 311, 479, + 485, 486, 575, 0, 491, 664, 665, 666, 500, 0, + 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 505, 506, 507, 509, 510, 511, 512, 576, + 593, 560, 530, 493, 584, 527, 531, 532, 360, 596, + 0, 0, 0, 484, 370, 371, 0, 342, 341, 383, + 302, 348, 294, 295, 659, 876, 402, 598, 631, 632, + 523, 0, 891, 871, 873, 874, 878, 882, 883, 884, + 885, 886, 888, 890, 894, 658, 0, 577, 592, 662, + 591, 655, 408, 0, 429, 589, 536, 0, 581, 555, + 0, 582, 551, 586, 0, 525, 0, 437, 465, 477, + 494, 497, 526, 611, 612, 613, 299, 496, 615, 616, + 617, 618, 619, 620, 621, 614, 893, 558, 535, 561, + 476, 538, 537, 0, 0, 572, 823, 573, 574, 392, + 393, 394, 395, 880, 599, 318, 495, 418, 0, 559, + 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, + 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, 380, @@ -2513,18 +2673,18 @@ var yyAct = [...]int{ 377, 427, 446, 434, 821, 660, 519, 520, 661, 630, 0, 770, 0, 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, 773, 0, 0, - 0, 339, 1893, 0, 372, 571, 553, 563, 554, 539, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, 812, 570, 521, 436, 388, 588, 587, 0, 0, 881, 889, 0, 0, 0, 0, 0, 0, 0, - 0, 877, 0, 2122, 0, 0, 765, 0, 0, 802, + 0, 877, 0, 0, 0, 0, 765, 0, 0, 802, 857, 856, 789, 799, 0, 0, 313, 231, 516, 636, 518, 517, 790, 0, 791, 795, 798, 794, 792, 793, 0, 872, 0, 0, 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, 767, 0, 0, 0, - 0, 822, 0, 768, 0, 0, 2123, 796, 800, 0, + 0, 822, 0, 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, @@ -2535,7 +2695,7 @@ var yyAct = [...]int{ 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, 815, 0, 633, 0, 472, 0, 0, 879, 0, 0, 0, 442, 0, 0, 369, - 0, 0, 0, 819, 0, 425, 406, 892, 0, 0, + 0, 0, 0, 819, 0, 425, 406, 892, 4083, 0, 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, @@ -2575,105 +2735,170 @@ var yyAct = [...]int{ 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, 855, 641, 440, 441, 648, 0, 851, - 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, - 520, 661, 630, 0, 770, 208, 821, 0, 0, 0, - 0, 0, 0, 0, 0, 404, 0, 0, 534, 567, - 556, 640, 522, 0, 0, 0, 0, 0, 0, 773, - 0, 0, 0, 339, 0, 0, 372, 571, 553, 563, - 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, - 545, 515, 546, 547, 1301, 570, 521, 436, 388, 588, - 587, 0, 0, 881, 889, 0, 0, 0, 0, 0, - 0, 0, 0, 877, 0, 0, 0, 0, 765, 0, - 0, 802, 857, 856, 789, 799, 0, 0, 313, 231, - 516, 636, 518, 517, 790, 0, 791, 795, 798, 794, - 792, 793, 0, 872, 0, 0, 0, 0, 0, 0, - 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 766, 767, 0, - 0, 0, 0, 822, 0, 768, 0, 0, 817, 796, - 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, - 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, - 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, - 334, 401, 797, 820, 824, 333, 895, 818, 470, 307, - 0, 469, 400, 456, 461, 386, 379, 0, 306, 458, - 384, 378, 366, 343, 896, 367, 368, 357, 412, 376, - 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, - 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 629, 815, 0, 633, - 0, 472, 0, 0, 879, 0, 0, 0, 442, 0, - 0, 369, 0, 0, 0, 819, 0, 425, 406, 892, - 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, - 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, - 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, - 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, - 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, - 411, 452, 451, 311, 479, 485, 486, 575, 0, 491, - 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, - 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, - 527, 531, 532, 360, 596, 0, 0, 0, 484, 370, - 371, 0, 342, 341, 383, 302, 348, 294, 295, 659, - 876, 402, 598, 631, 632, 523, 0, 891, 871, 873, - 874, 878, 882, 883, 884, 885, 886, 888, 890, 894, - 658, 0, 577, 592, 662, 591, 655, 408, 0, 429, - 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, - 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, - 613, 299, 496, 615, 616, 617, 618, 619, 620, 621, - 614, 893, 558, 535, 561, 476, 538, 537, 0, 0, - 572, 823, 573, 574, 392, 393, 394, 395, 880, 599, - 318, 495, 418, 0, 559, 0, 0, 0, 0, 0, - 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, - 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, - 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, - 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, - 426, 315, 464, 435, 380, 552, 579, 902, 875, 901, - 903, 904, 900, 905, 906, 887, 778, 0, 830, 898, - 897, 899, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, - 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, - 656, 652, 455, 657, 785, 296, 529, 373, 171, 417, - 346, 594, 595, 0, 646, 864, 837, 838, 839, 775, - 840, 834, 835, 776, 836, 865, 828, 861, 862, 804, - 831, 841, 860, 842, 863, 866, 867, 907, 908, 848, - 832, 260, 909, 845, 868, 859, 858, 843, 829, 869, - 870, 811, 806, 846, 847, 833, 852, 853, 854, 777, - 825, 826, 827, 849, 850, 807, 808, 809, 810, 0, - 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, - 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, - 0, 634, 635, 637, 639, 855, 641, 440, 441, 648, - 0, 851, 644, 645, 642, 377, 427, 446, 434, 821, - 660, 519, 520, 661, 630, 0, 770, 0, 404, 0, - 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, - 0, 0, 773, 0, 0, 0, 339, 4196, 0, 372, - 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, - 543, 544, 514, 545, 515, 546, 547, 812, 570, 521, - 436, 388, 588, 587, 0, 0, 881, 889, 0, 0, - 0, 0, 0, 0, 0, 0, 877, 0, 0, 0, - 0, 765, 0, 0, 802, 857, 856, 789, 799, 0, - 0, 313, 231, 516, 636, 518, 517, 790, 0, 791, - 795, 798, 794, 792, 793, 0, 872, 0, 0, 0, - 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 767, 0, 0, 0, 0, 822, 0, 768, 0, - 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, - 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, - 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, - 422, 337, 353, 334, 401, 797, 820, 824, 333, 895, - 818, 470, 307, 0, 469, 400, 456, 461, 386, 379, - 0, 306, 458, 384, 378, 366, 343, 896, 367, 368, - 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, - 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, - 815, 0, 633, 0, 472, 0, 0, 879, 0, 0, - 0, 442, 0, 0, 369, 0, 0, 0, 819, 0, - 425, 406, 892, 0, 0, 423, 374, 457, 414, 463, - 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, - 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, - 448, 449, 335, 320, 424, 321, 355, 322, 298, 328, - 326, 329, 432, 330, 300, 410, 453, 0, 350, 420, - 382, 301, 381, 411, 452, 451, 311, 479, 485, 486, - 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, + 644, 645, 642, 377, 427, 446, 434, 821, 660, 519, + 520, 661, 630, 0, 770, 0, 404, 0, 0, 534, + 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, + 773, 0, 0, 0, 339, 1893, 0, 372, 571, 553, + 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, + 514, 545, 515, 546, 547, 812, 570, 521, 436, 388, + 588, 587, 0, 0, 881, 889, 0, 0, 0, 0, + 0, 0, 0, 0, 877, 0, 0, 0, 0, 765, + 0, 0, 802, 857, 856, 789, 799, 0, 0, 313, + 231, 516, 636, 518, 517, 790, 0, 791, 795, 798, + 794, 792, 793, 0, 872, 0, 0, 0, 0, 0, + 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 767, + 0, 0, 0, 0, 822, 0, 768, 0, 0, 817, + 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, + 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, + 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, + 353, 334, 401, 797, 820, 824, 333, 895, 818, 470, + 307, 0, 469, 400, 456, 461, 386, 379, 0, 306, + 458, 384, 378, 366, 343, 896, 367, 368, 357, 412, + 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, + 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 629, 815, 0, + 633, 0, 472, 0, 0, 879, 0, 0, 0, 442, + 0, 0, 369, 0, 0, 0, 819, 0, 425, 406, + 892, 0, 0, 423, 374, 457, 414, 463, 444, 471, + 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, + 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, + 335, 320, 424, 321, 355, 322, 298, 328, 326, 329, + 432, 330, 300, 410, 453, 0, 350, 420, 382, 301, + 381, 411, 452, 451, 311, 479, 485, 486, 575, 0, + 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 505, 506, + 507, 509, 510, 511, 512, 576, 593, 560, 530, 493, + 584, 527, 531, 532, 360, 596, 0, 0, 0, 484, + 370, 371, 0, 342, 341, 383, 302, 348, 294, 295, + 659, 876, 402, 598, 631, 632, 523, 0, 891, 871, + 873, 874, 878, 882, 883, 884, 885, 886, 888, 890, + 894, 658, 0, 577, 592, 662, 591, 655, 408, 0, + 429, 589, 536, 0, 581, 555, 0, 582, 551, 586, + 0, 525, 0, 437, 465, 477, 494, 497, 526, 611, + 612, 613, 299, 496, 615, 616, 617, 618, 619, 620, + 621, 614, 893, 558, 535, 561, 476, 538, 537, 0, + 0, 572, 823, 573, 574, 392, 393, 394, 395, 880, + 599, 318, 495, 418, 0, 559, 0, 0, 0, 0, + 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, + 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, + 407, 349, 474, 364, 0, 501, 566, 502, 625, 628, + 626, 627, 399, 359, 361, 433, 365, 375, 421, 473, + 405, 426, 315, 464, 435, 380, 552, 579, 902, 875, + 901, 903, 904, 900, 905, 906, 887, 778, 0, 830, + 898, 897, 899, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, + 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, + 331, 656, 652, 455, 657, 785, 296, 529, 373, 0, + 417, 346, 594, 595, 0, 646, 864, 837, 838, 839, + 775, 840, 834, 835, 776, 836, 865, 828, 861, 862, + 804, 831, 841, 860, 842, 863, 866, 867, 907, 908, + 848, 832, 260, 909, 845, 868, 859, 858, 843, 829, + 869, 870, 811, 806, 846, 847, 833, 852, 853, 854, + 777, 825, 826, 827, 849, 850, 807, 808, 809, 810, + 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, + 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, + 624, 0, 634, 635, 637, 639, 855, 641, 440, 441, + 648, 0, 851, 644, 645, 642, 377, 427, 446, 434, + 821, 660, 519, 520, 661, 630, 0, 770, 0, 404, + 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, + 0, 0, 0, 773, 0, 0, 0, 339, 0, 0, + 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, + 542, 543, 544, 514, 545, 515, 546, 547, 812, 570, + 521, 436, 388, 588, 587, 0, 0, 881, 889, 0, + 0, 0, 0, 0, 0, 0, 0, 877, 0, 0, + 0, 0, 765, 0, 0, 802, 857, 856, 789, 799, + 0, 0, 313, 231, 516, 636, 518, 517, 790, 0, + 791, 795, 798, 794, 792, 793, 0, 872, 0, 0, + 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 767, 1605, 0, 0, 0, 822, 0, 768, + 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, + 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, + 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, + 0, 422, 337, 353, 334, 401, 797, 820, 824, 333, + 895, 818, 470, 307, 0, 469, 400, 456, 461, 386, + 379, 0, 306, 458, 384, 378, 366, 343, 896, 367, + 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, + 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 629, 815, 0, 633, 0, 472, 0, 0, 879, 0, + 0, 0, 442, 0, 0, 369, 0, 0, 0, 819, + 0, 425, 406, 892, 0, 0, 423, 374, 457, 414, + 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, + 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, + 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, + 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, + 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, + 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, + 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, + 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, + 348, 294, 295, 659, 876, 402, 598, 631, 632, 523, + 0, 891, 871, 873, 874, 878, 882, 883, 884, 885, + 886, 888, 890, 894, 658, 0, 577, 592, 662, 591, + 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, + 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, + 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, + 618, 619, 620, 621, 614, 893, 558, 535, 561, 476, + 538, 537, 0, 0, 572, 823, 573, 574, 392, 393, + 394, 395, 880, 599, 318, 495, 418, 0, 559, 0, + 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, + 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, + 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, + 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, + 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, + 579, 902, 875, 901, 903, 904, 900, 905, 906, 887, + 778, 0, 830, 898, 897, 899, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, + 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, + 288, 323, 324, 331, 656, 652, 455, 657, 785, 296, + 529, 373, 0, 417, 346, 594, 595, 0, 646, 864, + 837, 838, 839, 775, 840, 834, 835, 776, 836, 865, + 828, 861, 862, 804, 831, 841, 860, 842, 863, 866, + 867, 907, 908, 848, 832, 260, 909, 845, 868, 859, + 858, 843, 829, 869, 870, 811, 806, 846, 847, 833, + 852, 853, 854, 777, 825, 826, 827, 849, 850, 807, + 808, 809, 810, 0, 0, 0, 480, 481, 482, 504, + 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, + 0, 578, 590, 624, 0, 634, 635, 637, 639, 855, + 641, 440, 441, 648, 0, 851, 644, 645, 642, 377, + 427, 446, 434, 0, 660, 519, 520, 661, 630, 821, + 770, 0, 2297, 0, 0, 0, 0, 0, 404, 0, + 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, + 0, 0, 773, 0, 0, 0, 339, 0, 0, 372, + 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, + 543, 544, 514, 545, 515, 546, 547, 812, 570, 521, + 436, 388, 588, 587, 0, 0, 881, 889, 0, 0, + 0, 0, 0, 0, 0, 0, 877, 0, 0, 0, + 0, 765, 0, 0, 802, 857, 856, 789, 799, 0, + 0, 313, 231, 516, 636, 518, 517, 790, 0, 791, + 795, 798, 794, 792, 793, 0, 872, 0, 0, 0, + 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 766, 767, 0, 0, 0, 0, 822, 0, 768, 0, + 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, + 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, + 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, + 422, 337, 353, 334, 401, 797, 820, 824, 333, 895, + 818, 470, 307, 0, 469, 400, 456, 461, 386, 379, + 0, 306, 458, 384, 378, 366, 343, 896, 367, 368, + 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, + 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, + 815, 0, 633, 0, 472, 0, 0, 879, 0, 0, + 0, 442, 0, 0, 369, 0, 0, 0, 819, 0, + 425, 406, 892, 0, 0, 423, 374, 457, 414, 463, + 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, + 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, + 448, 449, 335, 320, 424, 321, 355, 322, 298, 328, + 326, 329, 432, 330, 300, 410, 453, 0, 350, 420, + 382, 301, 381, 411, 452, 451, 311, 479, 485, 486, + 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, 0, @@ -2720,7 +2945,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 766, 767, 0, 0, 0, 0, 822, + 0, 0, 0, 766, 767, 1886, 0, 0, 0, 822, 0, 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, @@ -2732,7 +2957,7 @@ var yyAct = [...]int{ 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, 815, 0, 633, 0, 472, 0, 0, 879, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 819, 0, 425, 406, 892, 4075, 0, 423, 374, + 0, 819, 0, 425, 406, 892, 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, @@ -2775,7 +3000,7 @@ var yyAct = [...]int{ 642, 377, 427, 446, 434, 821, 660, 519, 520, 661, 630, 0, 770, 0, 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, 773, 0, - 0, 0, 339, 1893, 0, 372, 571, 553, 563, 554, + 0, 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, 812, 570, 521, 436, 388, 588, 587, 0, 0, 881, 889, 0, 0, 0, 0, 0, 0, @@ -2851,7 +3076,7 @@ var yyAct = [...]int{ 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, - 767, 1605, 0, 0, 0, 822, 0, 768, 0, 0, + 767, 0, 0, 0, 0, 822, 0, 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, @@ -2902,101 +3127,231 @@ var yyAct = [...]int{ 810, 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, 855, 641, 440, - 441, 648, 0, 851, 644, 645, 642, 377, 427, 446, - 434, 0, 660, 519, 520, 661, 630, 821, 770, 0, - 2297, 0, 0, 0, 0, 0, 404, 0, 0, 534, - 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, - 773, 0, 0, 0, 339, 0, 0, 372, 571, 553, - 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, - 514, 545, 515, 546, 547, 812, 570, 521, 436, 388, - 588, 587, 0, 0, 881, 889, 0, 0, 0, 0, - 0, 0, 0, 0, 877, 0, 0, 0, 0, 765, - 0, 0, 802, 857, 856, 789, 799, 0, 0, 313, - 231, 516, 636, 518, 517, 790, 0, 791, 795, 798, - 794, 792, 793, 0, 872, 0, 0, 0, 0, 0, - 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 766, 767, - 0, 0, 0, 0, 822, 0, 768, 0, 0, 817, - 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, - 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, - 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, - 353, 334, 401, 797, 820, 824, 333, 895, 818, 470, - 307, 0, 469, 400, 456, 461, 386, 379, 0, 306, - 458, 384, 378, 366, 343, 896, 367, 368, 357, 412, - 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, - 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 629, 815, 0, - 633, 0, 472, 0, 0, 879, 0, 0, 0, 442, - 0, 0, 369, 0, 0, 0, 819, 0, 425, 406, - 892, 0, 0, 423, 374, 457, 414, 463, 444, 471, - 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, - 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, - 335, 320, 424, 321, 355, 322, 298, 328, 326, 329, - 432, 330, 300, 410, 453, 0, 350, 420, 382, 301, - 381, 411, 452, 451, 311, 479, 485, 486, 575, 0, - 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 505, 506, - 507, 509, 510, 511, 512, 576, 593, 560, 530, 493, - 584, 527, 531, 532, 360, 596, 0, 0, 0, 484, - 370, 371, 0, 342, 341, 383, 302, 348, 294, 295, - 659, 876, 402, 598, 631, 632, 523, 0, 891, 871, - 873, 874, 878, 882, 883, 884, 885, 886, 888, 890, - 894, 658, 0, 577, 592, 662, 591, 655, 408, 0, - 429, 589, 536, 0, 581, 555, 0, 582, 551, 586, - 0, 525, 0, 437, 465, 477, 494, 497, 526, 611, - 612, 613, 299, 496, 615, 616, 617, 618, 619, 620, - 621, 614, 893, 558, 535, 561, 476, 538, 537, 0, - 0, 572, 823, 573, 574, 392, 393, 394, 395, 880, - 599, 318, 495, 418, 0, 559, 0, 0, 0, 0, - 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, - 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, - 407, 349, 474, 364, 0, 501, 566, 502, 625, 628, - 626, 627, 399, 359, 361, 433, 365, 375, 421, 473, - 405, 426, 315, 464, 435, 380, 552, 579, 902, 875, - 901, 903, 904, 900, 905, 906, 887, 778, 0, 830, - 898, 897, 899, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, - 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, - 331, 656, 652, 455, 657, 785, 296, 529, 373, 0, - 417, 346, 594, 595, 0, 646, 864, 837, 838, 839, - 775, 840, 834, 835, 776, 836, 865, 828, 861, 862, - 804, 831, 841, 860, 842, 863, 866, 867, 907, 908, - 848, 832, 260, 909, 845, 868, 859, 858, 843, 829, - 869, 870, 811, 806, 846, 847, 833, 852, 853, 854, - 777, 825, 826, 827, 849, 850, 807, 808, 809, 810, - 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, - 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, - 624, 0, 634, 635, 637, 639, 855, 641, 440, 441, - 648, 0, 851, 644, 645, 642, 377, 427, 446, 434, - 821, 660, 519, 520, 661, 630, 0, 770, 0, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 773, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 812, 570, - 521, 436, 388, 588, 587, 0, 0, 881, 889, 0, - 0, 0, 0, 0, 0, 0, 0, 877, 0, 0, - 0, 0, 765, 0, 0, 802, 857, 856, 789, 799, - 0, 0, 313, 231, 516, 636, 518, 517, 790, 0, - 791, 795, 798, 794, 792, 793, 0, 872, 0, 0, - 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, + 441, 648, 0, 3639, 644, 3640, 3641, 377, 427, 446, + 434, 821, 660, 519, 520, 661, 630, 0, 770, 0, + 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, + 0, 0, 0, 0, 773, 0, 0, 0, 339, 0, + 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, + 351, 542, 543, 544, 514, 545, 515, 546, 547, 812, + 570, 521, 436, 388, 588, 587, 0, 0, 881, 889, + 0, 0, 0, 0, 0, 0, 0, 0, 877, 0, + 0, 0, 0, 765, 0, 0, 802, 857, 856, 789, + 799, 0, 0, 313, 231, 516, 636, 518, 517, 2783, + 0, 2784, 795, 798, 794, 792, 793, 0, 872, 0, + 0, 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 767, 1886, 0, 0, 0, 822, 0, 768, - 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 797, 820, 824, 333, - 895, 818, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 896, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, + 0, 0, 766, 767, 0, 0, 0, 0, 822, 0, + 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, + 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, + 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, + 304, 0, 422, 337, 353, 334, 401, 797, 820, 824, + 333, 895, 818, 470, 307, 0, 469, 400, 456, 461, + 386, 379, 0, 306, 458, 384, 378, 366, 343, 896, + 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, + 0, 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 815, 0, 633, 0, 472, 0, 0, 879, 0, - 0, 0, 442, 0, 0, 369, 0, 0, 0, 819, - 0, 425, 406, 892, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, + 0, 629, 815, 0, 633, 0, 472, 0, 0, 879, + 0, 0, 0, 442, 0, 0, 369, 0, 0, 0, + 819, 0, 425, 406, 892, 0, 0, 423, 374, 457, + 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, + 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, + 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, + 298, 328, 326, 329, 432, 330, 300, 410, 453, 0, + 350, 420, 382, 301, 381, 411, 452, 451, 311, 479, + 485, 486, 575, 0, 491, 664, 665, 666, 500, 0, + 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 505, 506, 507, 509, 510, 511, 512, 576, + 593, 560, 530, 493, 584, 527, 531, 532, 360, 596, + 0, 0, 0, 484, 370, 371, 0, 342, 341, 383, + 302, 348, 294, 295, 659, 876, 402, 598, 631, 632, + 523, 0, 891, 871, 873, 874, 878, 882, 883, 884, + 885, 886, 888, 890, 894, 658, 0, 577, 592, 662, + 591, 655, 408, 0, 429, 589, 536, 0, 581, 555, + 0, 582, 551, 586, 0, 525, 0, 437, 465, 477, + 494, 497, 526, 611, 612, 613, 299, 496, 615, 616, + 617, 618, 619, 620, 621, 614, 893, 558, 535, 561, + 476, 538, 537, 0, 0, 572, 823, 573, 574, 392, + 393, 394, 395, 880, 599, 318, 495, 418, 0, 559, + 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, + 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, + 354, 508, 356, 317, 407, 349, 474, 364, 0, 501, + 566, 502, 625, 628, 626, 627, 399, 359, 361, 433, + 365, 375, 421, 473, 405, 426, 315, 464, 435, 380, + 552, 579, 902, 875, 901, 903, 904, 900, 905, 906, + 887, 778, 0, 830, 898, 897, 899, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 607, 606, + 605, 604, 603, 602, 601, 600, 0, 0, 549, 450, + 327, 288, 323, 324, 331, 656, 652, 455, 657, 785, + 296, 529, 373, 0, 417, 346, 594, 595, 0, 646, + 864, 837, 838, 839, 775, 840, 834, 835, 776, 836, + 865, 828, 861, 862, 804, 831, 841, 860, 842, 863, + 866, 867, 907, 908, 848, 832, 260, 909, 845, 868, + 859, 858, 843, 829, 869, 870, 811, 806, 846, 847, + 833, 852, 853, 854, 777, 825, 826, 827, 849, 850, + 807, 808, 809, 810, 0, 0, 0, 480, 481, 482, + 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, + 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, + 855, 641, 440, 441, 648, 0, 851, 644, 645, 642, + 377, 427, 446, 434, 821, 660, 519, 520, 661, 630, + 0, 770, 0, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 1751, 0, 0, 0, 773, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 812, 570, 521, 436, 388, 588, 587, 0, + 0, 881, 889, 0, 0, 0, 0, 0, 0, 0, + 0, 877, 0, 0, 0, 0, 765, 0, 0, 802, + 857, 856, 789, 799, 0, 0, 313, 231, 516, 636, + 518, 517, 790, 0, 791, 795, 798, 794, 792, 793, + 0, 872, 0, 0, 0, 0, 0, 0, 0, 769, + 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 766, 767, 0, 0, 0, + 0, 822, 0, 768, 0, 0, 817, 796, 800, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 797, 820, 824, 333, 895, 818, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 896, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 815, 0, 633, 0, 472, + 0, 0, 879, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 819, 0, 425, 406, 892, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 1752, 1753, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 876, 402, + 598, 631, 632, 523, 0, 891, 871, 873, 874, 878, + 882, 883, 884, 885, 886, 888, 890, 894, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 893, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 823, + 573, 574, 392, 393, 394, 395, 880, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 902, 875, 901, 903, 904, + 900, 905, 906, 887, 778, 0, 830, 898, 897, 899, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 785, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 864, 837, 838, 839, 775, 840, 834, + 835, 776, 836, 865, 828, 861, 862, 804, 831, 841, + 860, 842, 863, 866, 867, 907, 908, 848, 832, 260, + 909, 845, 868, 859, 858, 843, 829, 869, 870, 811, + 806, 846, 847, 833, 852, 853, 854, 777, 825, 826, + 827, 849, 850, 807, 808, 809, 810, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 855, 641, 440, 441, 648, 0, 851, + 644, 645, 642, 377, 427, 446, 434, 821, 660, 519, + 520, 661, 630, 0, 770, 0, 404, 0, 0, 534, + 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, + 773, 0, 0, 0, 339, 0, 0, 372, 571, 553, + 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, + 514, 545, 515, 546, 547, 812, 570, 521, 436, 388, + 588, 587, 0, 0, 881, 889, 0, 0, 0, 0, + 0, 0, 0, 0, 877, 0, 0, 0, 0, 765, + 0, 0, 802, 857, 856, 789, 799, 0, 0, 313, + 231, 516, 636, 518, 517, 790, 0, 791, 795, 798, + 794, 792, 793, 0, 872, 0, 0, 0, 0, 0, + 0, 0, 769, 0, 774, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 767, + 0, 0, 0, 0, 822, 0, 768, 0, 0, 817, + 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, + 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, + 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, + 353, 334, 401, 797, 820, 824, 333, 895, 818, 470, + 307, 0, 469, 400, 456, 461, 386, 379, 0, 306, + 458, 384, 378, 366, 343, 896, 367, 368, 357, 412, + 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, + 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 629, 815, 0, + 633, 0, 472, 0, 0, 879, 0, 0, 0, 442, + 0, 0, 369, 0, 0, 0, 819, 0, 425, 406, + 892, 0, 0, 423, 374, 457, 414, 463, 444, 471, + 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, + 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, + 335, 320, 424, 321, 355, 322, 298, 328, 326, 329, + 432, 330, 300, 410, 453, 0, 350, 420, 382, 301, + 381, 411, 452, 451, 311, 479, 485, 486, 575, 0, + 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 505, 506, + 507, 509, 510, 511, 512, 576, 593, 560, 530, 493, + 584, 527, 531, 532, 360, 596, 0, 0, 0, 484, + 370, 371, 0, 342, 341, 383, 302, 348, 294, 295, + 659, 876, 402, 598, 631, 632, 523, 0, 891, 871, + 873, 874, 878, 882, 883, 884, 885, 886, 888, 890, + 894, 658, 0, 577, 592, 662, 591, 655, 408, 0, + 429, 589, 536, 0, 581, 555, 0, 582, 551, 586, + 0, 525, 0, 437, 465, 477, 494, 497, 526, 611, + 612, 613, 299, 496, 615, 616, 617, 618, 619, 620, + 621, 614, 893, 558, 535, 561, 476, 538, 537, 0, + 0, 572, 823, 573, 574, 392, 393, 394, 395, 880, + 599, 318, 495, 418, 0, 559, 0, 0, 0, 0, + 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, + 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, + 407, 349, 474, 364, 0, 501, 566, 502, 625, 628, + 626, 627, 399, 359, 361, 433, 365, 375, 421, 473, + 405, 426, 315, 464, 435, 380, 552, 579, 902, 875, + 901, 903, 904, 900, 905, 906, 887, 778, 0, 830, + 898, 897, 899, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, + 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, + 331, 656, 652, 455, 657, 785, 296, 529, 373, 0, + 417, 346, 594, 595, 0, 646, 864, 837, 838, 839, + 775, 840, 834, 835, 776, 836, 865, 828, 861, 862, + 804, 831, 841, 860, 842, 863, 866, 867, 907, 908, + 848, 832, 260, 909, 845, 868, 859, 858, 843, 829, + 869, 870, 811, 806, 846, 847, 833, 852, 853, 854, + 777, 825, 826, 827, 849, 850, 807, 808, 809, 810, + 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, + 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, + 624, 0, 634, 635, 637, 639, 855, 641, 440, 441, + 648, 0, 851, 644, 645, 642, 377, 427, 446, 434, + 821, 660, 519, 520, 661, 630, 0, 770, 0, 404, + 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, + 0, 0, 0, 773, 0, 0, 0, 339, 0, 0, + 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, + 542, 543, 544, 514, 545, 515, 546, 547, 812, 570, + 521, 436, 388, 588, 587, 0, 0, 881, 889, 0, + 0, 0, 0, 0, 0, 0, 0, 877, 0, 0, + 0, 0, 0, 0, 0, 802, 857, 856, 789, 799, + 0, 0, 313, 231, 516, 636, 518, 517, 790, 0, + 791, 795, 798, 794, 792, 793, 0, 872, 0, 0, + 0, 0, 0, 0, 757, 769, 0, 774, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 767, 0, 0, 0, 0, 822, 0, 768, + 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, + 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, + 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, + 0, 422, 337, 353, 334, 401, 797, 820, 824, 333, + 895, 818, 470, 307, 0, 469, 400, 456, 461, 386, + 379, 0, 306, 458, 384, 378, 366, 343, 896, 367, + 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, + 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 629, 815, 0, 633, 0, 472, 0, 0, 879, 0, + 0, 0, 442, 0, 0, 369, 0, 0, 0, 819, + 0, 425, 406, 892, 0, 0, 423, 374, 457, 414, + 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, + 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, @@ -3034,686 +3389,685 @@ var yyAct = [...]int{ 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, 855, 641, 440, 441, 648, 0, 851, 644, 645, 642, 377, - 427, 446, 434, 821, 660, 519, 520, 661, 630, 0, - 770, 0, 404, 0, 0, 534, 567, 556, 640, 522, - 0, 0, 0, 0, 0, 0, 773, 0, 0, 0, - 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, - 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, - 547, 812, 570, 521, 436, 388, 588, 587, 0, 0, - 881, 889, 0, 0, 0, 0, 0, 0, 0, 0, - 877, 0, 0, 0, 0, 765, 0, 0, 802, 857, - 856, 789, 799, 0, 0, 313, 231, 516, 636, 518, - 517, 790, 0, 791, 795, 798, 794, 792, 793, 0, - 872, 0, 0, 0, 0, 0, 0, 757, 769, 0, - 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 427, 446, 434, 0, 660, 519, 520, 661, 630, 0, + 770, 208, 65, 199, 170, 0, 0, 0, 0, 0, + 0, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 200, 0, 0, 0, 0, 0, 0, 191, 0, 339, + 0, 201, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 141, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 766, 767, 0, 0, 0, 0, - 822, 0, 768, 0, 0, 817, 796, 800, 0, 0, - 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, - 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, - 362, 363, 304, 0, 422, 337, 353, 334, 401, 797, - 820, 824, 333, 895, 818, 470, 307, 0, 469, 400, - 456, 461, 386, 379, 0, 306, 458, 384, 378, 366, - 343, 896, 367, 368, 357, 412, 376, 413, 358, 390, - 389, 391, 0, 0, 0, 0, 0, 498, 499, 0, - 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 629, 815, 0, 633, 0, 472, 0, - 0, 879, 0, 0, 0, 442, 0, 0, 369, 0, - 0, 0, 819, 0, 425, 406, 892, 0, 0, 423, - 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, - 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, - 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, - 355, 322, 298, 328, 326, 329, 432, 330, 300, 410, - 453, 0, 350, 420, 382, 301, 381, 411, 452, 451, - 311, 479, 485, 486, 575, 0, 491, 664, 665, 666, - 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 505, 506, 507, 509, 510, 511, - 512, 576, 593, 560, 530, 493, 584, 527, 531, 532, - 360, 596, 0, 0, 0, 484, 370, 371, 0, 342, - 341, 383, 302, 348, 294, 295, 659, 876, 402, 598, - 631, 632, 523, 0, 891, 871, 873, 874, 878, 882, - 883, 884, 885, 886, 888, 890, 894, 658, 0, 577, - 592, 662, 591, 655, 408, 0, 429, 589, 536, 0, - 581, 555, 0, 582, 551, 586, 0, 525, 0, 437, - 465, 477, 494, 497, 526, 611, 612, 613, 299, 496, - 615, 616, 617, 618, 619, 620, 621, 614, 893, 558, - 535, 561, 476, 538, 537, 0, 0, 572, 823, 573, - 574, 392, 393, 394, 395, 880, 599, 318, 495, 418, - 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, - 564, 565, 562, 667, 0, 622, 623, 0, 0, 489, - 490, 347, 354, 508, 356, 317, 407, 349, 474, 364, - 0, 501, 566, 502, 625, 628, 626, 627, 399, 359, - 361, 433, 365, 375, 421, 473, 405, 426, 315, 464, - 435, 380, 552, 579, 902, 875, 901, 903, 904, 900, - 905, 906, 887, 778, 0, 830, 898, 897, 899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 607, 606, 605, 604, 603, 602, 601, 600, 0, 0, - 549, 450, 327, 288, 323, 324, 331, 656, 652, 455, - 657, 785, 296, 529, 373, 0, 417, 346, 594, 595, - 0, 646, 864, 837, 838, 839, 775, 840, 834, 835, - 776, 836, 865, 828, 861, 862, 804, 831, 841, 860, - 842, 863, 866, 867, 907, 908, 848, 832, 260, 909, - 845, 868, 859, 858, 843, 829, 869, 870, 811, 806, - 846, 847, 833, 852, 853, 854, 777, 825, 826, 827, - 849, 850, 807, 808, 809, 810, 0, 0, 0, 480, - 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, - 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, - 637, 639, 855, 641, 440, 441, 648, 0, 851, 644, - 645, 642, 377, 427, 446, 434, 821, 660, 519, 520, - 661, 630, 0, 770, 0, 404, 0, 0, 534, 567, - 556, 640, 522, 0, 0, 0, 0, 0, 0, 773, - 0, 0, 0, 339, 0, 0, 372, 571, 553, 563, - 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, - 545, 515, 546, 547, 812, 570, 521, 436, 388, 588, - 587, 0, 0, 881, 889, 0, 0, 0, 0, 0, - 0, 0, 0, 877, 0, 0, 0, 0, 765, 0, - 0, 802, 857, 856, 789, 799, 0, 0, 313, 231, - 516, 636, 518, 517, 790, 0, 791, 795, 798, 794, - 792, 793, 0, 872, 0, 0, 0, 0, 0, 0, - 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 766, 767, 0, - 0, 0, 0, 822, 0, 768, 0, 0, 817, 796, - 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, - 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, - 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, - 334, 401, 797, 820, 824, 333, 895, 818, 470, 307, - 0, 469, 400, 456, 461, 386, 379, 0, 306, 458, - 384, 378, 366, 343, 896, 367, 368, 357, 412, 376, - 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, - 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 629, 815, 0, 633, - 0, 472, 0, 0, 879, 0, 0, 0, 442, 0, - 0, 369, 0, 0, 0, 819, 0, 425, 406, 892, - 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, - 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, - 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, - 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, - 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, - 411, 452, 451, 311, 479, 485, 486, 575, 0, 491, - 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, - 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, - 527, 531, 532, 360, 596, 0, 0, 0, 484, 370, - 371, 0, 342, 341, 383, 302, 348, 294, 295, 659, - 876, 402, 598, 631, 632, 523, 0, 891, 871, 873, - 874, 878, 882, 883, 884, 885, 886, 888, 890, 894, - 658, 0, 577, 592, 662, 591, 655, 408, 0, 429, - 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, - 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, - 613, 299, 496, 615, 616, 617, 618, 619, 620, 621, - 614, 893, 558, 535, 561, 476, 538, 537, 0, 0, - 572, 823, 573, 574, 392, 393, 394, 395, 880, 599, - 318, 495, 418, 0, 559, 0, 0, 0, 0, 0, - 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, - 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, - 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, - 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, - 426, 315, 464, 435, 380, 552, 579, 902, 875, 901, - 903, 904, 900, 905, 906, 887, 778, 0, 830, 898, - 897, 899, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, - 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, - 656, 652, 455, 657, 785, 296, 529, 373, 0, 417, - 346, 594, 595, 0, 646, 864, 837, 838, 839, 775, - 840, 834, 835, 776, 836, 865, 828, 861, 862, 804, - 831, 841, 860, 842, 863, 866, 867, 907, 908, 848, - 832, 260, 909, 845, 868, 859, 858, 843, 829, 869, - 870, 811, 806, 846, 847, 833, 852, 853, 854, 777, - 825, 826, 827, 849, 850, 807, 808, 809, 810, 0, - 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, - 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, - 0, 634, 635, 637, 639, 855, 641, 440, 441, 648, - 0, 3632, 644, 3633, 3634, 377, 427, 446, 434, 821, - 660, 519, 520, 661, 630, 0, 770, 0, 404, 0, - 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, - 0, 0, 773, 0, 0, 0, 339, 0, 0, 372, - 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, - 543, 544, 514, 545, 515, 546, 547, 812, 570, 521, - 436, 388, 588, 587, 0, 0, 881, 889, 0, 0, - 0, 0, 0, 0, 0, 0, 877, 0, 0, 0, - 0, 765, 0, 0, 802, 857, 856, 789, 799, 0, - 0, 313, 231, 516, 636, 518, 517, 2781, 0, 2782, - 795, 798, 794, 792, 793, 0, 872, 0, 0, 0, - 0, 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 767, 0, 0, 0, 0, 822, 0, 768, 0, - 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, - 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, - 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, - 422, 337, 353, 334, 401, 797, 820, 824, 333, 895, - 818, 470, 307, 0, 469, 400, 456, 461, 386, 379, - 0, 306, 458, 384, 378, 366, 343, 896, 367, 368, - 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, - 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, - 815, 0, 633, 0, 472, 0, 0, 879, 0, 0, - 0, 442, 0, 0, 369, 0, 0, 0, 819, 0, - 425, 406, 892, 0, 0, 423, 374, 457, 414, 463, - 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, - 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, - 448, 449, 335, 320, 424, 321, 355, 322, 298, 328, - 326, 329, 432, 330, 300, 410, 453, 0, 350, 420, - 382, 301, 381, 411, 452, 451, 311, 479, 485, 486, - 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 505, 506, 507, 509, 510, 511, 512, 576, 593, 560, - 530, 493, 584, 527, 531, 532, 360, 596, 0, 0, - 0, 484, 370, 371, 0, 342, 341, 383, 302, 348, - 294, 295, 659, 876, 402, 598, 631, 632, 523, 0, - 891, 871, 873, 874, 878, 882, 883, 884, 885, 886, - 888, 890, 894, 658, 0, 577, 592, 662, 591, 655, - 408, 0, 429, 589, 536, 0, 581, 555, 0, 582, - 551, 586, 0, 525, 0, 437, 465, 477, 494, 497, - 526, 611, 612, 613, 299, 496, 615, 616, 617, 618, - 619, 620, 621, 614, 893, 558, 535, 561, 476, 538, - 537, 0, 0, 572, 823, 573, 574, 392, 393, 394, - 395, 880, 599, 318, 495, 418, 0, 559, 0, 0, - 0, 0, 0, 0, 0, 0, 564, 565, 562, 667, - 0, 622, 623, 0, 0, 489, 490, 347, 354, 508, - 356, 317, 407, 349, 474, 364, 0, 501, 566, 502, - 625, 628, 626, 627, 399, 359, 361, 433, 365, 375, - 421, 473, 405, 426, 315, 464, 435, 380, 552, 579, - 902, 875, 901, 903, 904, 900, 905, 906, 887, 778, - 0, 830, 898, 897, 899, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 607, 606, 605, 604, - 603, 602, 601, 600, 0, 0, 549, 450, 327, 288, - 323, 324, 331, 656, 652, 455, 657, 785, 296, 529, - 373, 0, 417, 346, 594, 595, 0, 646, 864, 837, - 838, 839, 775, 840, 834, 835, 776, 836, 865, 828, - 861, 862, 804, 831, 841, 860, 842, 863, 866, 867, - 907, 908, 848, 832, 260, 909, 845, 868, 859, 858, - 843, 829, 869, 870, 811, 806, 846, 847, 833, 852, - 853, 854, 777, 825, 826, 827, 849, 850, 807, 808, - 809, 810, 0, 0, 0, 480, 481, 482, 504, 0, - 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, - 578, 590, 624, 0, 634, 635, 637, 639, 855, 641, - 440, 441, 648, 0, 851, 644, 645, 642, 377, 427, - 446, 434, 821, 660, 519, 520, 661, 630, 0, 770, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 169, 197, 206, 198, 125, + 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, + 223, 0, 0, 0, 442, 0, 0, 369, 196, 190, + 189, 488, 0, 425, 406, 235, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 243, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 608, 609, 610, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 467, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 226, 580, 583, 513, 236, 0, 577, 592, + 550, 591, 237, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 139, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 234, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 66, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 241, 308, 455, 242, + 0, 296, 529, 373, 171, 417, 346, 594, 595, 62, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 238, 46, 224, 227, 229, + 228, 0, 63, 578, 590, 624, 5, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 144, 239, 519, 520, 240, + 630, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 1751, 0, 0, 0, 773, 0, 0, 0, 339, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 812, 570, 521, 436, 388, 588, 587, 0, 0, 881, - 889, 0, 0, 0, 0, 0, 0, 0, 0, 877, - 0, 0, 0, 0, 765, 0, 0, 802, 857, 856, - 789, 799, 0, 0, 313, 231, 516, 636, 518, 517, - 790, 0, 791, 795, 798, 794, 792, 793, 0, 872, - 0, 0, 0, 0, 0, 0, 0, 769, 0, 774, + 141, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 2457, 2460, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 766, 767, 0, 0, 0, 0, 822, - 0, 768, 0, 0, 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 797, 820, - 824, 333, 895, 818, 470, 307, 0, 469, 400, 456, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 896, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 815, 0, 633, 0, 472, 0, 0, - 879, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 819, 0, 425, 406, 892, 0, 0, 423, 374, + 0, 0, 629, 0, 0, 633, 2461, 472, 0, 0, + 0, 2456, 0, 2455, 442, 2453, 2458, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 1752, 1753, 575, 0, 491, 664, 665, 666, 500, + 2459, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 876, 402, 598, 631, - 632, 523, 0, 891, 871, 873, 874, 878, 882, 883, - 884, 885, 886, 888, 890, 894, 658, 0, 577, 592, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 893, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 823, 573, 574, - 392, 393, 394, 395, 880, 599, 318, 495, 418, 0, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 902, 875, 901, 903, 904, 900, 905, - 906, 887, 778, 0, 830, 898, 897, 899, 0, 0, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 785, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 864, 837, 838, 839, 775, 840, 834, 835, 776, - 836, 865, 828, 861, 862, 804, 831, 841, 860, 842, - 863, 866, 867, 907, 908, 848, 832, 260, 909, 845, - 868, 859, 858, 843, 829, 869, 870, 811, 806, 846, - 847, 833, 852, 853, 854, 777, 825, 826, 827, 849, - 850, 807, 808, 809, 810, 0, 0, 0, 480, 481, + 0, 296, 529, 373, 171, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 855, 641, 440, 441, 648, 0, 851, 644, 645, - 642, 377, 427, 446, 434, 821, 660, 519, 520, 661, - 630, 0, 770, 0, 404, 0, 0, 534, 567, 556, - 640, 522, 0, 0, 0, 0, 0, 0, 773, 0, - 0, 0, 339, 0, 0, 372, 571, 553, 563, 554, - 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, - 515, 546, 547, 812, 570, 521, 436, 388, 588, 587, - 0, 0, 881, 889, 0, 0, 0, 0, 0, 0, - 0, 0, 877, 0, 0, 0, 0, 765, 0, 0, - 802, 857, 856, 789, 799, 0, 0, 313, 231, 516, - 636, 518, 517, 790, 0, 791, 795, 798, 794, 792, - 793, 0, 872, 0, 0, 0, 0, 0, 0, 0, - 769, 0, 774, 0, 0, 0, 0, 0, 0, 0, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 766, 767, 0, 0, - 0, 0, 822, 0, 768, 0, 0, 817, 796, 800, - 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, - 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, - 438, 385, 362, 363, 304, 0, 422, 337, 353, 334, - 401, 797, 820, 824, 333, 895, 818, 470, 307, 0, - 469, 400, 456, 461, 386, 379, 0, 306, 458, 384, - 378, 366, 343, 896, 367, 368, 357, 412, 376, 413, - 358, 390, 389, 391, 0, 0, 0, 0, 0, 498, - 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 629, 815, 0, 633, 0, - 472, 0, 0, 879, 0, 0, 0, 442, 0, 0, - 369, 0, 0, 0, 819, 0, 425, 406, 892, 0, - 0, 423, 374, 457, 414, 463, 444, 471, 419, 415, - 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, - 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, - 424, 321, 355, 322, 298, 328, 326, 329, 432, 330, - 300, 410, 453, 0, 350, 420, 382, 301, 381, 411, - 452, 451, 311, 479, 485, 486, 575, 0, 491, 664, - 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 505, 506, 507, 509, - 510, 511, 512, 576, 593, 560, 530, 493, 584, 527, - 531, 532, 360, 596, 0, 0, 0, 484, 370, 371, - 0, 342, 341, 383, 302, 348, 294, 295, 659, 876, - 402, 598, 631, 632, 523, 0, 891, 871, 873, 874, - 878, 882, 883, 884, 885, 886, 888, 890, 894, 658, - 0, 577, 592, 662, 591, 655, 408, 0, 429, 589, - 536, 0, 581, 555, 0, 582, 551, 586, 0, 525, - 0, 437, 465, 477, 494, 497, 526, 611, 612, 613, - 299, 496, 615, 616, 617, 618, 619, 620, 621, 614, - 893, 558, 535, 561, 476, 538, 537, 0, 0, 572, - 823, 573, 574, 392, 393, 394, 395, 880, 599, 318, - 495, 418, 0, 559, 0, 0, 0, 0, 0, 0, - 0, 0, 564, 565, 562, 667, 0, 622, 623, 0, - 0, 489, 490, 347, 354, 508, 356, 317, 407, 349, - 474, 364, 0, 501, 566, 502, 625, 628, 626, 627, - 399, 359, 361, 433, 365, 375, 421, 473, 405, 426, - 315, 464, 435, 380, 552, 579, 902, 875, 901, 903, - 904, 900, 905, 906, 887, 778, 0, 830, 898, 897, - 899, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 607, 606, 605, 604, 603, 602, 601, 600, - 0, 0, 549, 450, 327, 288, 323, 324, 331, 656, - 652, 455, 657, 785, 296, 529, 373, 0, 417, 346, - 594, 595, 0, 646, 864, 837, 838, 839, 775, 840, - 834, 835, 776, 836, 865, 828, 861, 862, 804, 831, - 841, 860, 842, 863, 866, 867, 907, 908, 848, 832, - 260, 909, 845, 868, 859, 858, 843, 829, 869, 870, - 811, 806, 846, 847, 833, 852, 853, 854, 777, 825, - 826, 827, 849, 850, 807, 808, 809, 810, 0, 0, - 0, 480, 481, 482, 504, 0, 466, 528, 654, 0, - 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, - 634, 635, 637, 639, 855, 641, 440, 441, 648, 0, - 851, 644, 645, 642, 377, 427, 446, 434, 821, 660, - 519, 520, 661, 630, 0, 770, 0, 404, 0, 0, - 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, - 0, 773, 0, 0, 0, 339, 0, 0, 372, 571, - 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, - 544, 514, 545, 515, 546, 547, 812, 570, 521, 436, - 388, 588, 587, 0, 0, 881, 889, 0, 0, 0, - 0, 0, 0, 0, 0, 877, 0, 0, 0, 0, - 0, 0, 0, 802, 857, 856, 789, 799, 0, 0, - 313, 231, 516, 636, 518, 517, 790, 0, 791, 795, - 798, 794, 792, 793, 0, 872, 0, 0, 0, 0, - 0, 0, 757, 769, 0, 774, 0, 0, 0, 0, + 0, 0, 0, 0, 1337, 0, 0, 230, 0, 0, + 789, 799, 0, 0, 313, 231, 516, 636, 518, 517, + 790, 0, 791, 795, 798, 794, 792, 793, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, - 767, 0, 0, 0, 0, 822, 0, 768, 0, 0, - 817, 796, 800, 0, 0, 0, 0, 303, 443, 462, - 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, - 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, - 337, 353, 334, 401, 797, 820, 824, 333, 895, 818, - 470, 307, 0, 469, 400, 456, 461, 386, 379, 0, - 306, 458, 384, 378, 366, 343, 896, 367, 368, 357, - 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, - 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 629, 815, - 0, 633, 0, 472, 0, 0, 879, 0, 0, 0, - 442, 0, 0, 369, 0, 0, 0, 819, 0, 425, - 406, 892, 0, 0, 423, 374, 457, 414, 463, 444, - 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, - 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, - 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, - 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, - 301, 381, 411, 452, 451, 311, 479, 485, 486, 575, - 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, - 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, - 493, 584, 527, 531, 532, 360, 596, 0, 0, 0, - 484, 370, 371, 0, 342, 341, 383, 302, 348, 294, - 295, 659, 876, 402, 598, 631, 632, 523, 0, 891, - 871, 873, 874, 878, 882, 883, 884, 885, 886, 888, - 890, 894, 658, 0, 577, 592, 662, 591, 655, 408, - 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, - 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, - 611, 612, 613, 299, 496, 615, 616, 617, 618, 619, - 620, 621, 614, 893, 558, 535, 561, 476, 538, 537, - 0, 0, 572, 823, 573, 574, 392, 393, 394, 395, - 880, 599, 318, 495, 418, 0, 559, 0, 0, 0, - 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, - 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, - 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, - 628, 626, 627, 399, 359, 361, 433, 365, 375, 421, - 473, 405, 426, 315, 464, 435, 380, 552, 579, 902, - 875, 901, 903, 904, 900, 905, 906, 887, 778, 0, - 830, 898, 897, 899, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, - 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, - 324, 331, 656, 652, 455, 657, 785, 296, 529, 373, - 0, 417, 346, 594, 595, 0, 646, 864, 837, 838, - 839, 775, 840, 834, 835, 776, 836, 865, 828, 861, - 862, 804, 831, 841, 860, 842, 863, 866, 867, 907, - 908, 848, 832, 260, 909, 845, 868, 859, 858, 843, - 829, 869, 870, 811, 806, 846, 847, 833, 852, 853, - 854, 777, 825, 826, 827, 849, 850, 807, 808, 809, - 810, 0, 0, 0, 480, 481, 482, 504, 0, 466, - 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, - 590, 624, 0, 634, 635, 637, 639, 855, 641, 440, - 441, 648, 0, 851, 644, 645, 642, 377, 427, 446, - 434, 0, 660, 519, 520, 661, 630, 0, 770, 208, - 65, 199, 170, 0, 0, 0, 0, 0, 0, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 200, 0, - 0, 0, 0, 0, 0, 191, 0, 339, 0, 201, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 141, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, - 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, - 0, 0, 204, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, - 0, 0, 0, 169, 197, 206, 198, 125, 0, 0, - 629, 0, 0, 633, 0, 472, 0, 0, 223, 0, - 0, 0, 442, 0, 0, 369, 196, 190, 189, 488, - 0, 425, 406, 235, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 243, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 608, 609, 610, 500, 0, 416, + 0, 0, 0, 0, 0, 796, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 797, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 208, 65, 199, 170, 0, 0, 0, 0, 0, + 0, 404, 686, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 693, 0, 0, 0, + 0, 0, 0, 0, 692, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 467, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 226, 580, 583, 513, 236, 0, 577, 592, 550, 591, - 237, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 139, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 234, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 66, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 241, 308, 455, 242, 0, 296, - 529, 373, 171, 417, 346, 594, 595, 62, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 238, 46, 224, 227, 229, 228, 0, - 63, 578, 590, 624, 5, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 144, 239, 519, 520, 240, 630, 208, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 141, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 204, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 2455, 2458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 690, + 691, 0, 629, 0, 0, 633, 0, 472, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 687, 689, 318, 495, 418, 701, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 66, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 171, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 1144, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 2459, 472, 0, 0, 0, 2454, - 0, 2453, 442, 2451, 2456, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 2457, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 171, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1337, 0, 0, 230, 0, 0, 789, 799, - 0, 0, 313, 231, 516, 636, 518, 517, 790, 0, - 791, 795, 798, 794, 792, 793, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1129, 0, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 2620, 2623, 2624, 2625, 2626, + 2627, 2628, 0, 2633, 2629, 2630, 2631, 2632, 0, 2615, + 2616, 2617, 2618, 1127, 2599, 2621, 0, 2600, 400, 2601, + 2602, 2603, 2604, 1131, 2605, 2606, 2607, 2608, 2609, 2612, + 2613, 2610, 2611, 2619, 412, 376, 413, 358, 390, 389, + 391, 1155, 1157, 1159, 1161, 1164, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, + 0, 2614, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 2622, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 2457, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 796, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 797, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 0, 472, 0, 0, 0, 0, - 0, 0, 442, 0, 0, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 0, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 208, - 65, 199, 170, 0, 0, 0, 0, 0, 0, 404, - 686, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 693, 0, 0, 0, 0, 0, - 0, 0, 692, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 2461, 472, 0, 0, + 0, 2456, 0, 2455, 442, 2453, 2458, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 2459, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 2478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, - 0, 0, 0, 0, 0, 0, 0, 690, 691, 0, - 629, 0, 0, 633, 0, 472, 0, 0, 0, 0, - 0, 0, 442, 0, 0, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 687, 689, 318, 495, 418, 701, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 66, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 171, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 1144, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 2477, 472, 0, 0, + 0, 2483, 2480, 2482, 442, 0, 2481, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 2475, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 2478, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 2477, 472, 0, 0, + 0, 2483, 2480, 2482, 442, 0, 2481, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, + 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, + 0, 0, 0, 0, 2164, 0, 0, 0, 0, 339, + 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, + 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, + 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 2165, 0, 0, 0, 313, 231, 516, 636, 518, 517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 1266, 1267, 1268, 1265, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, + 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, + 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, + 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, + 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, + 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, + 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, + 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, + 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, + 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, + 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, + 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, + 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, + 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, + 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, + 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, + 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, + 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, + 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, + 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, + 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, + 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, + 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, + 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, + 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, + 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, + 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, + 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, + 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, + 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, + 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, + 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, + 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, + 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, + 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, + 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, + 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, + 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, + 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, + 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, + 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, + 642, 377, 427, 446, 434, 208, 660, 519, 520, 661, + 630, 0, 0, 0, 0, 404, 0, 0, 534, 567, + 556, 640, 522, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 339, 0, 0, 372, 571, 553, 563, + 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, + 545, 515, 546, 547, 141, 570, 521, 436, 388, 588, + 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 204, 2214, + 0, 230, 0, 0, 0, 0, 0, 0, 313, 231, + 516, 636, 518, 517, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 303, 443, 462, 314, 431, + 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, + 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, + 334, 401, 0, 459, 487, 333, 478, 0, 470, 307, + 0, 469, 400, 456, 461, 386, 379, 0, 306, 458, + 384, 378, 366, 343, 503, 367, 368, 357, 412, 376, + 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, + 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 629, 0, 0, 633, + 0, 472, 0, 0, 0, 0, 0, 0, 442, 0, + 0, 369, 0, 0, 0, 488, 0, 425, 406, 663, + 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, + 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, + 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, + 320, 424, 321, 355, 322, 298, 328, 326, 329, 432, + 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, + 411, 452, 451, 311, 479, 485, 486, 575, 0, 491, + 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 505, 506, 507, + 509, 510, 511, 512, 576, 593, 560, 530, 493, 584, + 527, 531, 532, 360, 596, 0, 0, 0, 484, 370, + 371, 0, 342, 341, 383, 302, 348, 294, 295, 659, + 332, 402, 598, 631, 632, 523, 0, 585, 524, 533, + 325, 557, 569, 568, 398, 483, 0, 580, 583, 513, + 658, 0, 577, 592, 662, 591, 655, 408, 0, 429, + 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, + 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, + 613, 299, 496, 615, 616, 617, 618, 619, 620, 621, + 614, 468, 558, 535, 561, 476, 538, 537, 0, 0, + 572, 492, 573, 574, 392, 393, 394, 395, 352, 599, + 318, 495, 418, 0, 559, 0, 0, 0, 0, 0, + 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, + 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, + 349, 474, 364, 0, 501, 566, 502, 625, 628, 626, + 627, 399, 359, 361, 433, 365, 375, 421, 473, 405, + 426, 315, 464, 435, 380, 552, 579, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 283, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, + 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, + 656, 652, 455, 657, 0, 296, 529, 373, 171, 417, + 346, 594, 595, 0, 646, 244, 245, 246, 247, 248, + 249, 250, 251, 289, 252, 253, 254, 255, 256, 257, + 258, 261, 262, 263, 264, 265, 266, 267, 268, 597, + 259, 260, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 0, 0, 0, 290, + 291, 292, 293, 0, 0, 284, 285, 286, 287, 0, + 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, + 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, + 0, 634, 635, 637, 639, 638, 641, 440, 441, 648, + 0, 643, 644, 645, 642, 377, 427, 446, 434, 208, + 660, 519, 520, 661, 630, 0, 0, 0, 0, 404, + 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, + 542, 543, 544, 514, 545, 515, 546, 547, 141, 570, + 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 204, 2199, 0, 230, 0, 0, 0, 0, + 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1129, 0, 0, 0, 0, 0, 0, 303, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 2618, 2621, 2622, 2623, 2624, 2625, 2626, - 0, 2631, 2627, 2628, 2629, 2630, 0, 2613, 2614, 2615, - 2616, 1127, 2597, 2619, 0, 2598, 400, 2599, 2600, 2601, - 2602, 1131, 2603, 2604, 2605, 2606, 2607, 2610, 2611, 2608, - 2609, 2617, 412, 376, 413, 358, 390, 389, 391, 1155, - 1157, 1159, 1161, 1164, 498, 499, 0, 0, 647, 0, + 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, + 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, + 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, + 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, + 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, + 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, 0, 0, - 0, 0, 442, 0, 0, 369, 0, 0, 0, 2612, + 0, 0, 442, 0, 0, 369, 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, @@ -3744,7 +4098,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 2620, 373, 0, 417, 346, 594, 595, 0, 646, 244, + 529, 373, 171, 417, 346, 594, 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, @@ -3756,34 +4110,34 @@ var yyAct = [...]int{ 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 1055, 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 230, 1062, 1063, 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 2455, 2458, + 0, 0, 0, 0, 0, 0, 0, 1066, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, + 443, 1049, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, + 478, 1036, 470, 307, 1035, 469, 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 2459, 472, 0, 0, 0, 2454, - 0, 2453, 442, 2451, 2456, 369, 0, 0, 0, 488, + 629, 0, 0, 633, 0, 472, 0, 0, 0, 0, + 0, 0, 442, 0, 0, 369, 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, + 463, 444, 471, 1053, 415, 297, 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 2457, 350, + 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3796,14 +4150,14 @@ var yyAct = [...]int{ 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, + 618, 619, 620, 1054, 614, 468, 558, 535, 561, 476, + 538, 537, 0, 0, 572, 1057, 573, 574, 392, 393, + 394, 395, 352, 599, 1052, 495, 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, + 502, 625, 628, 626, 627, 1064, 1050, 1060, 1051, 365, + 375, 421, 473, 405, 426, 315, 464, 435, 1061, 552, 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, @@ -3818,213 +4172,83 @@ var yyAct = [...]int{ 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, + 641, 440, 441, 648, 0, 643, 644, 645, 642, 1048, + 427, 446, 434, 208, 660, 519, 520, 661, 630, 0, + 0, 0, 0, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 141, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 2476, + 0, 0, 0, 0, 0, 0, 2094, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 2475, 472, 0, 0, 0, 2481, - 2478, 2480, 442, 0, 2479, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 2473, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 0, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 2476, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 2475, 472, 0, 0, 0, 2481, - 2478, 2480, 442, 0, 2479, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 0, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 0, 660, 519, 520, 661, 630, 404, - 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, - 0, 0, 2164, 0, 0, 0, 0, 339, 0, 0, - 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, - 542, 543, 544, 514, 545, 515, 546, 547, 0, 570, - 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 0, 0, 2165, 0, - 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, - 1266, 1267, 1268, 1265, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, - 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, - 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, - 0, 422, 337, 353, 334, 401, 0, 459, 487, 333, - 478, 0, 470, 307, 0, 469, 400, 456, 461, 386, - 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, - 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, - 0, 0, 0, 0, 498, 499, 0, 0, 647, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 629, 0, 0, 633, 0, 472, 0, 0, 0, 0, - 0, 0, 442, 0, 0, 369, 0, 0, 0, 488, - 0, 425, 406, 663, 0, 0, 423, 374, 457, 414, - 463, 444, 471, 419, 415, 297, 445, 336, 387, 310, - 312, 653, 338, 340, 344, 345, 396, 397, 409, 430, - 447, 448, 449, 335, 320, 424, 321, 355, 322, 298, - 328, 326, 329, 432, 330, 300, 410, 453, 0, 350, - 420, 382, 301, 381, 411, 452, 451, 311, 479, 485, - 486, 575, 0, 491, 664, 665, 666, 500, 0, 416, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 505, 506, 507, 509, 510, 511, 512, 576, 593, - 560, 530, 493, 584, 527, 531, 532, 360, 596, 0, - 0, 0, 484, 370, 371, 0, 342, 341, 383, 302, - 348, 294, 295, 659, 332, 402, 598, 631, 632, 523, - 0, 585, 524, 533, 325, 557, 569, 568, 398, 483, - 0, 580, 583, 513, 658, 0, 577, 592, 662, 591, - 655, 408, 0, 429, 589, 536, 0, 581, 555, 0, - 582, 551, 586, 0, 525, 0, 437, 465, 477, 494, - 497, 526, 611, 612, 613, 299, 496, 615, 616, 617, - 618, 619, 620, 621, 614, 468, 558, 535, 561, 476, - 538, 537, 0, 0, 572, 492, 573, 574, 392, 393, - 394, 395, 352, 599, 318, 495, 418, 0, 559, 0, - 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, - 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, - 508, 356, 317, 407, 349, 474, 364, 0, 501, 566, - 502, 625, 628, 626, 627, 399, 359, 361, 433, 365, - 375, 421, 473, 405, 426, 315, 464, 435, 380, 552, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, - 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, - 288, 323, 324, 331, 656, 652, 455, 657, 0, 296, - 529, 373, 0, 417, 346, 594, 595, 0, 646, 244, - 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, - 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, - 266, 267, 268, 597, 259, 260, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 0, 0, 0, 290, 291, 292, 293, 0, 0, 284, - 285, 286, 287, 0, 0, 0, 480, 481, 482, 504, - 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, - 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, - 641, 440, 441, 648, 0, 643, 644, 645, 642, 377, - 427, 446, 434, 208, 660, 519, 520, 661, 630, 0, - 0, 0, 0, 404, 0, 0, 534, 567, 556, 640, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 171, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, - 546, 547, 141, 570, 521, 436, 388, 588, 587, 0, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 204, 2214, 0, 230, - 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 1062, 1063, 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1066, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4032,7 +4256,7 @@ var yyAct = [...]int{ 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, - 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 0, 459, 487, 333, 478, 1036, 470, 307, 1035, 469, 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, @@ -4062,14 +4286,14 @@ var yyAct = [...]int{ 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, - 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, - 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, - 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 1064, + 2115, 1060, 2116, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 1061, 552, 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, - 455, 657, 0, 296, 529, 373, 171, 417, 346, 594, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, @@ -4079,3430 +4303,3173 @@ var yyAct = [...]int{ 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, - 644, 645, 642, 377, 427, 446, 434, 208, 660, 519, - 520, 661, 630, 0, 0, 0, 0, 404, 0, 0, - 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 339, 0, 0, 372, 571, - 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, - 544, 514, 545, 515, 546, 547, 141, 570, 521, 436, - 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 3027, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 204, 2199, 0, 230, 0, 0, 0, 0, 0, 0, - 313, 231, 516, 636, 518, 517, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 303, 443, 462, - 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, - 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, - 337, 353, 334, 401, 0, 459, 487, 333, 478, 0, - 470, 307, 0, 469, 400, 456, 461, 386, 379, 0, - 306, 458, 384, 378, 366, 343, 503, 367, 368, 357, - 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, - 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 629, 0, - 0, 633, 0, 472, 0, 0, 0, 0, 0, 0, - 442, 0, 0, 369, 0, 0, 0, 488, 0, 425, - 406, 663, 0, 0, 423, 374, 457, 414, 463, 444, - 471, 419, 415, 297, 445, 336, 387, 310, 312, 653, - 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, - 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, - 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, - 301, 381, 411, 452, 451, 311, 479, 485, 486, 575, - 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, - 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, - 493, 584, 527, 531, 532, 360, 596, 0, 0, 0, - 484, 370, 371, 0, 342, 341, 383, 302, 348, 294, - 295, 659, 332, 402, 598, 631, 632, 523, 0, 585, - 524, 533, 325, 557, 569, 568, 398, 483, 0, 580, - 583, 513, 658, 0, 577, 592, 662, 591, 655, 408, - 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, - 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, - 611, 612, 613, 299, 496, 615, 616, 617, 618, 619, - 620, 621, 614, 468, 558, 535, 561, 476, 538, 537, - 0, 0, 572, 492, 573, 574, 392, 393, 394, 395, - 352, 599, 318, 495, 418, 0, 559, 0, 0, 0, - 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, - 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, - 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, - 628, 626, 627, 399, 359, 361, 433, 365, 375, 421, - 473, 405, 426, 315, 464, 435, 380, 552, 579, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, - 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, - 324, 331, 656, 652, 455, 657, 0, 296, 529, 373, - 171, 417, 346, 594, 595, 0, 646, 244, 245, 246, - 247, 248, 249, 250, 251, 289, 252, 253, 254, 255, - 256, 257, 258, 261, 262, 263, 264, 265, 266, 267, - 268, 597, 259, 260, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 0, 0, - 0, 290, 291, 292, 293, 0, 0, 284, 285, 286, - 287, 0, 0, 0, 480, 481, 482, 504, 0, 466, - 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, - 590, 624, 0, 634, 635, 637, 639, 638, 641, 440, - 441, 648, 0, 643, 644, 645, 642, 377, 427, 446, - 434, 0, 660, 519, 520, 661, 630, 404, 0, 0, - 534, 567, 556, 640, 522, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 339, 1055, 0, 372, 571, - 553, 563, 554, 539, 540, 541, 548, 351, 542, 543, - 544, 514, 545, 515, 546, 547, 0, 570, 521, 436, - 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 230, 1062, 1063, 0, 0, 0, 0, - 313, 231, 516, 636, 518, 517, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1066, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 3030, + 0, 0, 0, 3029, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 1571, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 303, 443, 1049, - 314, 431, 475, 319, 439, 454, 309, 403, 428, 0, - 0, 305, 460, 438, 385, 362, 363, 304, 0, 422, - 337, 353, 334, 401, 0, 459, 487, 333, 478, 1036, - 470, 307, 1035, 469, 400, 456, 461, 386, 379, 0, - 306, 458, 384, 378, 366, 343, 503, 367, 368, 357, - 412, 376, 413, 358, 390, 389, 391, 0, 0, 0, - 0, 0, 498, 499, 0, 0, 647, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 629, 0, - 0, 633, 0, 472, 0, 0, 0, 0, 0, 0, - 442, 0, 0, 369, 0, 0, 0, 488, 0, 425, - 406, 663, 0, 0, 423, 374, 457, 414, 463, 444, - 471, 1053, 415, 297, 445, 336, 387, 310, 312, 653, - 338, 340, 344, 345, 396, 397, 409, 430, 447, 448, - 449, 335, 320, 424, 321, 355, 322, 298, 328, 326, - 329, 432, 330, 300, 410, 453, 0, 350, 420, 382, - 301, 381, 411, 452, 451, 311, 479, 485, 486, 575, - 0, 491, 664, 665, 666, 500, 0, 416, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, - 506, 507, 509, 510, 511, 512, 576, 593, 560, 530, - 493, 584, 527, 531, 532, 360, 596, 0, 0, 0, - 484, 370, 371, 0, 342, 341, 383, 302, 348, 294, - 295, 659, 332, 402, 598, 631, 632, 523, 0, 585, - 524, 533, 325, 557, 569, 568, 398, 483, 0, 580, - 583, 513, 658, 0, 577, 592, 662, 591, 655, 408, - 0, 429, 589, 536, 0, 581, 555, 0, 582, 551, - 586, 0, 525, 0, 437, 465, 477, 494, 497, 526, - 611, 612, 613, 299, 496, 615, 616, 617, 618, 619, - 620, 1054, 614, 468, 558, 535, 561, 476, 538, 537, - 0, 0, 572, 1057, 573, 574, 392, 393, 394, 395, - 352, 599, 1052, 495, 418, 0, 559, 0, 0, 0, - 0, 0, 0, 0, 0, 564, 565, 562, 667, 0, - 622, 623, 0, 0, 489, 490, 347, 354, 508, 356, - 317, 407, 349, 474, 364, 0, 501, 566, 502, 625, - 628, 626, 627, 1064, 1050, 1060, 1051, 365, 375, 421, - 473, 405, 426, 315, 464, 435, 1061, 552, 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 607, 606, 605, 604, 603, - 602, 601, 600, 0, 0, 549, 450, 327, 288, 323, - 324, 331, 656, 652, 455, 657, 0, 296, 529, 373, - 0, 417, 346, 594, 595, 0, 646, 244, 245, 246, - 247, 248, 249, 250, 251, 289, 252, 253, 254, 255, - 256, 257, 258, 261, 262, 263, 264, 265, 266, 267, - 268, 597, 259, 260, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 0, 0, - 0, 290, 291, 292, 293, 0, 0, 284, 285, 286, - 287, 0, 0, 0, 480, 481, 482, 504, 0, 466, - 528, 654, 0, 0, 0, 0, 0, 0, 0, 578, - 590, 624, 0, 634, 635, 637, 639, 638, 641, 440, - 441, 648, 0, 643, 644, 645, 642, 1048, 427, 446, - 434, 208, 660, 519, 520, 661, 630, 0, 0, 0, - 0, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 141, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2094, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 1567, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 1565, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 171, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1567, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 1062, 1063, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1066, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4152, 0, 230, + 857, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 1036, 470, 307, 1035, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 1064, 2115, 1060, - 2116, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 1061, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 3024, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1567, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 3027, 0, 0, - 0, 3026, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 1571, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1781, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1567, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 1565, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1567, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 2561, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4144, 0, 230, 857, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2563, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 2164, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2165, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1567, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 3253, 3255, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1781, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 2559, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2561, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 2584, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 2164, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2165, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 674, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 3250, 3252, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 2582, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 673, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 857, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4129, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 673, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 857, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 3884, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4121, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 3876, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 4020, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1795, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 4012, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1795, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3891, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 3800, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 3283, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3302, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2094, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 3508, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3899, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 3808, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 3286, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2561, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 2940, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2094, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2803, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 3514, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3417, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2234, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2679, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2563, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 2639, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 2943, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 2408, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2805, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 1945, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2681, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 2076, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 1569, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 2641, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 1981, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 2408, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 1945, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 1598, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 2076, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 1569, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 1981, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 684, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 1598, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 984, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 674, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 684, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 3228, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 984, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 1931, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 3231, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 1548, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 1931, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 1546, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 1548, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 1425, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, + 0, 0, 0, 303, 443, 1546, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 1425, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 419, 415, 297, 445, 336, - 387, 310, 312, 752, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 621, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 0, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 0, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 404, 0, 0, 534, 567, 556, 640, 522, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, - 0, 0, 372, 571, 553, 563, 554, 539, 540, 541, - 548, 351, 542, 543, 544, 514, 545, 515, 546, 547, - 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 313, 231, 516, 636, 518, 517, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 419, 415, 297, + 445, 336, 387, 310, 312, 752, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 621, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 0, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 0, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 404, 0, 0, 534, 567, 556, 640, + 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 372, 571, 553, 563, 554, 539, + 540, 541, 548, 351, 542, 543, 544, 514, 545, 515, + 546, 547, 0, 570, 521, 436, 388, 588, 587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 313, 231, 516, 636, + 518, 517, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 443, 462, 314, 431, 475, 319, 439, 454, - 309, 403, 428, 0, 0, 305, 460, 438, 385, 362, - 363, 304, 0, 422, 337, 353, 334, 401, 0, 459, - 487, 333, 478, 0, 470, 307, 0, 469, 400, 456, - 461, 386, 379, 0, 306, 458, 384, 378, 366, 343, - 503, 367, 368, 357, 412, 376, 413, 358, 390, 389, - 391, 0, 0, 0, 0, 0, 498, 499, 0, 0, - 647, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 629, 0, 0, 633, 0, 472, 0, 0, - 0, 0, 0, 0, 442, 0, 0, 369, 0, 0, - 0, 488, 0, 425, 406, 663, 0, 0, 423, 374, - 457, 414, 463, 444, 471, 709, 415, 297, 445, 336, - 387, 310, 312, 653, 338, 340, 344, 345, 396, 397, - 409, 430, 447, 448, 449, 335, 320, 424, 321, 355, - 322, 298, 328, 326, 329, 432, 330, 300, 410, 453, - 0, 350, 420, 382, 301, 381, 411, 452, 451, 311, - 479, 485, 486, 575, 0, 491, 664, 665, 666, 500, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 509, 510, 511, 512, - 576, 593, 560, 530, 493, 584, 527, 531, 532, 360, - 596, 0, 0, 0, 484, 370, 371, 0, 342, 341, - 383, 302, 348, 294, 295, 659, 332, 402, 598, 631, - 632, 523, 0, 585, 524, 533, 325, 557, 569, 568, - 398, 483, 0, 580, 583, 513, 658, 0, 577, 592, - 662, 591, 655, 408, 0, 429, 589, 536, 0, 581, - 555, 0, 582, 551, 586, 0, 525, 0, 437, 465, - 477, 494, 497, 526, 611, 612, 613, 299, 496, 615, - 616, 617, 618, 619, 620, 710, 614, 468, 558, 535, - 561, 476, 538, 537, 0, 0, 572, 492, 573, 574, - 392, 393, 394, 395, 352, 599, 318, 495, 418, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 0, 564, - 565, 562, 667, 0, 622, 623, 0, 0, 489, 490, - 347, 354, 508, 356, 317, 407, 349, 474, 364, 0, - 501, 566, 502, 625, 628, 626, 627, 399, 359, 361, - 433, 365, 375, 421, 473, 405, 426, 315, 464, 435, - 380, 552, 579, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 606, 605, 604, 603, 602, 601, 600, 0, 0, 549, - 450, 327, 288, 323, 324, 331, 656, 652, 455, 657, - 0, 296, 529, 373, 0, 417, 346, 594, 595, 0, - 646, 244, 245, 246, 247, 248, 249, 250, 251, 289, - 252, 253, 254, 255, 256, 257, 258, 261, 262, 263, - 264, 265, 266, 267, 268, 597, 259, 260, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 0, 0, 0, 290, 291, 292, 293, 0, - 2063, 284, 285, 286, 287, 0, 0, 0, 480, 481, - 482, 504, 0, 466, 528, 654, 0, 0, 0, 0, - 0, 0, 0, 578, 590, 624, 0, 634, 635, 637, - 639, 638, 641, 440, 441, 648, 2065, 643, 644, 645, - 642, 377, 427, 446, 434, 0, 660, 519, 520, 661, - 630, 2063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2065, 0, 0, - 2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 303, 443, 462, 314, 431, 475, 319, + 439, 454, 309, 403, 428, 0, 0, 305, 460, 438, + 385, 362, 363, 304, 0, 422, 337, 353, 334, 401, + 0, 459, 487, 333, 478, 0, 470, 307, 0, 469, + 400, 456, 461, 386, 379, 0, 306, 458, 384, 378, + 366, 343, 503, 367, 368, 357, 412, 376, 413, 358, + 390, 389, 391, 0, 0, 0, 0, 0, 498, 499, + 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 629, 0, 0, 633, 0, 472, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 369, + 0, 0, 0, 488, 0, 425, 406, 663, 0, 0, + 423, 374, 457, 414, 463, 444, 471, 709, 415, 297, + 445, 336, 387, 310, 312, 653, 338, 340, 344, 345, + 396, 397, 409, 430, 447, 448, 449, 335, 320, 424, + 321, 355, 322, 298, 328, 326, 329, 432, 330, 300, + 410, 453, 0, 350, 420, 382, 301, 381, 411, 452, + 451, 311, 479, 485, 486, 575, 0, 491, 664, 665, + 666, 500, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 505, 506, 507, 509, 510, + 511, 512, 576, 593, 560, 530, 493, 584, 527, 531, + 532, 360, 596, 0, 0, 0, 484, 370, 371, 0, + 342, 341, 383, 302, 348, 294, 295, 659, 332, 402, + 598, 631, 632, 523, 0, 585, 524, 533, 325, 557, + 569, 568, 398, 483, 0, 580, 583, 513, 658, 0, + 577, 592, 662, 591, 655, 408, 0, 429, 589, 536, + 0, 581, 555, 0, 582, 551, 586, 0, 525, 0, + 437, 465, 477, 494, 497, 526, 611, 612, 613, 299, + 496, 615, 616, 617, 618, 619, 620, 710, 614, 468, + 558, 535, 561, 476, 538, 537, 0, 0, 572, 492, + 573, 574, 392, 393, 394, 395, 352, 599, 318, 495, + 418, 0, 559, 0, 0, 0, 0, 0, 0, 0, + 0, 564, 565, 562, 667, 0, 622, 623, 0, 0, + 489, 490, 347, 354, 508, 356, 317, 407, 349, 474, + 364, 0, 501, 566, 502, 625, 628, 626, 627, 399, + 359, 361, 433, 365, 375, 421, 473, 405, 426, 315, + 464, 435, 380, 552, 579, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 607, 606, 605, 604, 603, 602, 601, 600, 0, + 0, 549, 450, 327, 288, 323, 324, 331, 656, 652, + 455, 657, 0, 296, 529, 373, 0, 417, 346, 594, + 595, 0, 646, 244, 245, 246, 247, 248, 249, 250, + 251, 289, 252, 253, 254, 255, 256, 257, 258, 261, + 262, 263, 264, 265, 266, 267, 268, 597, 259, 260, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 0, 0, 0, 290, 291, 292, + 293, 0, 2063, 284, 285, 286, 287, 0, 0, 0, + 480, 481, 482, 504, 0, 466, 528, 654, 0, 0, + 0, 0, 0, 0, 0, 578, 590, 624, 0, 634, + 635, 637, 639, 638, 641, 440, 441, 648, 2065, 643, + 644, 645, 642, 377, 427, 446, 434, 0, 660, 519, + 520, 661, 630, 2063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3905, 0, 0, 0, 0, 0, 0, 2065, + 0, 2063, 2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2040, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3868, 0, 0, 0, 2056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2065, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2056, + 0, 2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3876, 0, 0, + 0, 2056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2044, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2050, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2044, 0, 0, 0, 0, 2056, + 0, 0, 0, 0, 0, 2050, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2038, 2072, 0, 0, 2039, 2041, 2043, - 0, 2045, 2046, 2047, 2051, 2052, 2053, 2055, 2058, 2059, - 2060, 0, 0, 2044, 0, 0, 0, 0, 2048, 2057, - 2049, 0, 0, 0, 2050, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2038, 2072, 0, 0, 2039, + 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, 2053, 2055, + 2058, 2059, 2060, 0, 0, 2044, 0, 0, 0, 0, + 2048, 2057, 2049, 0, 0, 0, 2050, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2038, 2072, 0, 0, + 2039, 2041, 2043, 2044, 2045, 2046, 2047, 2051, 2052, 2053, + 2055, 2058, 2059, 2060, 2050, 0, 0, 2064, 0, 0, + 0, 2048, 2057, 2049, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2038, 2072, 0, 0, 2039, 2041, 2043, 0, 2045, 2046, 2047, 2051, 2052, 2053, 2055, 2058, - 2059, 2060, 0, 0, 0, 2064, 0, 0, 0, 2048, - 2057, 2049, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2061, 2064, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2037, 0, 0, 0, 0, 0, 0, 2036, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2059, 2060, 0, 0, 0, 0, 0, 0, 0, 2048, + 2057, 2049, 0, 0, 0, 0, 0, 2061, 2064, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2054, 0, 0, 2061, 0, 0, 0, - 0, 0, 2042, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2037, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2037, 0, 0, 0, 0, 0, + 0, 2036, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2064, 0, 0, 0, + 0, 0, 0, 0, 0, 2054, 0, 0, 2061, 0, + 0, 0, 0, 0, 2042, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2037, 0, 0, 0, 0, + 0, 0, 2036, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2061, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2054, 0, 0, 0, + 0, 0, 0, 2037, 0, 2042, 0, 0, 0, 0, 2036, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2054, 0, 0, 0, 0, 0, @@ -7510,37 +7477,38 @@ var yyAct = [...]int{ } var yyPact = [...]int{ - 4257, -1000, -1000, -1000, -342, 16216, -1000, -1000, -1000, -1000, + 4251, -1000, -1000, -1000, -337, 15848, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 50980, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 51348, -1000, -1000, -1000, + -1000, -1000, 492, 50980, -334, 31480, 49030, -1000, -1000, 2852, + -1000, 49680, 17818, 50980, 613, 606, 50980, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 445, 51348, -338, 31848, 49398, -1000, -1000, 2690, - -1000, 50048, 18186, 51348, 572, 568, 51348, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 999, -1000, 55530, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 947, 5305, 54880, + 11921, -220, -1000, 1740, -34, 2749, 557, -198, -204, 598, + 1198, 1203, 1461, 1202, 50980, 1182, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 229, + 1022, 50330, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 975, -1000, 55898, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 877, 4744, 55248, - 12289, -223, -1000, 1650, -43, 2583, 484, -204, -205, 555, - 1120, 1132, 1221, 1146, 51348, 1093, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 212, - 1012, 50698, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 3984, 254, 998, 1022, + 23026, 151, 143, 1740, 506, -67, 210, -1000, 1810, 450, + 212, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 11921, 11921, 15848, -378, 15848, 11921, 50980, 50980, + -1000, -1000, -1000, -1000, -334, 49680, 947, 5305, 11921, 2749, + 557, -198, -204, 598, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 4567, 249, 972, 1012, - 23394, 141, 139, 1650, 505, -74, 203, -1000, 2278, 4271, - 208, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 12289, 12289, 16216, -380, 16216, 12289, 51348, 51348, - -1000, -1000, -1000, -1000, -338, 50048, 877, 4744, 12289, 2583, - 484, -204, -205, 555, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -67, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -74, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -7555,8 +7523,8 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 143, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 139, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -7573,433 +7541,433 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5235, + -1000, 1767, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2472, 3278, + 1756, 2748, 904, 49030, 50980, -1000, 157, 904, -1000, -1000, + -1000, 1740, 3641, -1000, 50980, 50980, 226, 2041, -1000, 584, + 574, 431, 544, 361, 1755, -1000, -1000, -1000, -1000, -1000, + -1000, 834, 3606, -1000, 50980, 50980, 3291, 50980, -1000, 2443, + 871, -1000, 5533, 3441, 1401, 1053, 3303, -1000, -1000, 3274, + -1000, 383, 359, 366, 771, 488, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 379, -1000, 3489, -1000, -1000, 356, -1000, + -1000, 347, -1000, -1000, -1000, 123, -1000, -1000, -1000, -1000, + -1000, -1000, 23, -1000, -1000, 1302, 2188, 11921, 2244, -1000, + 2969, 1813, -1000, -1000, -1000, 7344, 14533, 14533, 14533, 14533, + 50980, -1000, -1000, 3134, 11921, 3273, 3271, 3269, 3268, -1000, + -1000, -1000, -1000, -1000, -1000, 3267, 1754, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 2178, -1000, -1000, -1000, + 15186, -1000, 3266, 3265, 3264, 3263, 3261, 3260, 3259, 3257, + 3253, 3252, 3251, 3250, 3248, 3247, 2982, 17158, 3246, 2747, + 2737, 3244, 3243, 3240, 2735, 3239, 3237, 3236, 2982, 2982, + 3235, 3224, 3223, 3222, 3221, 3220, 3218, 3217, 3211, 3210, + 3208, 3207, 3206, 3201, 3199, 3181, 3180, 3179, 3178, 3166, + 3164, 3163, 3158, 3154, 3153, 3152, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5139, - -1000, 1719, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2374, 3222, - 1713, 2578, 836, 49398, 51348, -1000, 149, 836, -1000, -1000, - -1000, 1650, 3532, -1000, 51348, 51348, 218, 1936, -1000, 561, - 557, 550, 461, 366, 1710, -1000, -1000, -1000, -1000, -1000, - -1000, 732, 3497, -1000, 51348, 51348, 3230, 51348, -1000, 2293, - 768, -1000, 5584, 3365, 1480, 995, 3243, -1000, -1000, 3221, - -1000, 369, 335, 377, 649, 444, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 360, -1000, 3419, -1000, -1000, 356, -1000, - -1000, 351, -1000, -1000, -1000, 131, -1000, -1000, -1000, -1000, - -1000, -1000, 20, -1000, -1000, 1246, 2072, 12289, 2309, -1000, - 4019, 1727, -1000, -1000, -1000, 7712, 14901, 14901, 14901, 14901, - 51348, -1000, -1000, 3008, 12289, 3220, 3219, 3218, 3210, -1000, - -1000, -1000, -1000, -1000, -1000, 3196, 1709, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2071, -1000, -1000, -1000, - 15554, -1000, 3195, 3193, 3192, 3191, 3189, 3185, 3184, 3181, - 3180, 3179, 3173, 3172, 3171, 3169, 2821, 17526, 3161, 2577, - 2576, 3157, 3155, 3154, 2575, 3153, 3152, 3150, 2821, 2821, - 3145, 3141, 3140, 3134, 3133, 3131, 3130, 3129, 3123, 3122, - 3121, 3110, 3099, 3098, 3093, 3087, 3085, 3082, 3080, 3075, - 3072, 3066, 3061, 3055, 3052, 3049, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1742, -1000, 3148, 3624, 3049, -1000, 3479, 3475, 3464, 3462, + -269, 3146, 2398, -1000, -1000, 112, 50980, 50980, 298, 50980, + -289, 439, -80, -81, -82, 1030, -1000, -55, -1000, -1000, + 1153, -1000, 1149, 54230, 984, -1000, -1000, 50980, 937, 937, + 937, 50980, 283, 1124, 937, 937, 937, 937, 937, 987, + 937, 3522, 996, 995, 992, 991, 937, -18, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2040, 2035, 3364, 1096, -1000, + -1000, -1000, -1000, 1662, 50980, -1000, 3063, 439, -315, 1975, + 1975, 3586, 3586, 3521, 3517, 879, 878, 851, 1975, 697, + -1000, 2012, 2012, 2012, 2012, 1975, 581, 876, 3525, 3525, + 171, 2012, 99, 1975, 1975, 99, 1975, 1975, -1000, 2054, + 306, -275, -1000, -1000, -1000, -1000, 2012, 2012, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 3484, 3483, 947, 947, 50980, + 947, 250, 50980, 947, 947, 947, 50980, 957, -321, 73, + 53580, 52930, 2501, 2443, 870, 852, 1675, 2006, -1000, 1889, + 50980, 50980, 1889, 1889, 26280, 25630, -1000, 50980, -1000, 3624, + 3049, 2955, 1921, 2952, 3049, -87, 439, 947, 947, 947, + 947, 947, 335, 947, 947, 947, 947, 947, 50980, 50980, + 48380, 947, 947, 947, 947, 9956, 1810, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1446, -1000, 3046, 3512, 2900, -1000, 3400, 3396, 3391, 3389, - -275, 3043, 2262, -1000, -1000, 111, 51348, 51348, 295, 51348, - -294, 434, -89, -90, -95, 1032, -1000, -85, -1000, -1000, - 1200, -1000, 1082, 54598, 936, -1000, -1000, 51348, 874, 874, - 874, 51348, 254, 985, 874, 874, 874, 874, 874, 940, - 874, 3433, 967, 965, 964, 963, 874, -36, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1933, 1932, 3300, 1067, -1000, - -1000, -1000, -1000, 1510, 51348, -1000, 2929, 434, -321, 1800, - 1800, 3476, 3476, 3430, 3429, 794, 782, 766, 1800, 624, - -1000, 1911, 1911, 1911, 1911, 1800, 518, 806, 3436, 3436, - 130, 1911, 99, 1800, 1800, 99, 1800, 1800, -1000, 1919, - 292, -281, -1000, -1000, -1000, -1000, 1911, 1911, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 3413, 3412, 877, 877, 51348, - 877, 242, 51348, 877, 877, 877, 51348, 889, -326, 37, - 53948, 53298, 2344, 2293, 757, 752, 1542, 1862, -1000, 1821, - 51348, 51348, 1821, 1821, 26648, 25998, -1000, 51348, -1000, 3512, - 2900, 2809, 1625, 2807, 2900, -96, 434, 877, 877, 877, - 877, 877, 330, 877, 877, 877, 877, 877, 51348, 51348, - 48748, 877, 877, 877, 877, 10324, 2278, -1000, -1000, -1000, + 15848, 2158, 2327, 208, -7, -311, 288, -1000, -1000, 50980, + 3414, 333, -1000, -1000, -1000, 3052, -1000, 3055, 3055, 3055, + 3055, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 3055, 3055, 3061, 3142, -1000, -1000, 3054, 3054, 3054, + 3052, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 3056, 3056, 3060, 3060, + 3056, 50980, -127, -1000, -1000, 11921, 50980, 3435, 408, 3141, + 904, -1000, -1000, 50980, 321, 430, 3624, 3433, 3525, 3572, + -1000, -1000, 1746, 2397, 2734, -1000, 361, -1000, 515, 361, + -1000, 509, 509, 1952, -1000, 1363, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 50980, 23, 483, -1000, -1000, 2724, 3138, + -1000, 686, 1315, 1631, -1000, 392, 4282, 40580, 2443, 40580, + 50980, -1000, -1000, -1000, -1000, -1000, -1000, 114, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 16216, 2175, 2151, 202, -22, -318, 278, -1000, -1000, 51348, - 3342, 321, -1000, -1000, -1000, 2915, -1000, 2920, 2920, 2920, - 2920, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2920, 2920, 2927, 3042, -1000, -1000, 2918, 2918, 2918, - 2915, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2922, 2922, 2926, 2926, - 2922, 51348, -129, -1000, -1000, 12289, 51348, 3358, 404, 3039, - 836, -1000, -1000, 51348, 318, 493, 3512, 3354, 3436, 3469, - -1000, -1000, 1707, 2255, 2572, -1000, 366, -1000, 426, 366, - -1000, 585, 585, 1806, -1000, 1296, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 51348, 20, 430, -1000, -1000, 2547, 3038, - -1000, 684, 1378, 1543, -1000, 256, 4449, 40948, 2293, 40948, - 51348, -1000, -1000, -1000, -1000, -1000, -1000, 126, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 382, -1000, 11921, 11921, 11921, 11921, 11921, -1000, + 1023, 13880, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 14533, + 14533, 14533, 14533, 14533, 14533, 14533, 14533, 14533, 14533, 14533, + 14533, 3133, 2036, 14533, 14533, 14533, 14533, 28230, 1921, 3203, + 1674, 315, 1813, 1813, 1813, 1813, 11921, -1000, 2061, 2188, + 11921, 11921, 11921, 11921, 34730, 50980, -1000, -1000, 5356, 11921, + 11921, 4056, 11921, 3459, 11921, 11921, 11921, 2951, 6029, 50980, + 11921, -1000, 2950, 2949, -1000, -1000, 2197, 11921, -1000, -1000, + 11921, -1000, -1000, 11921, 14533, 11921, -1000, 11921, 11921, 11921, + -1000, -1000, 3855, 3459, 3459, 3459, 1972, 11921, 11921, 3459, + 3459, 3459, 1963, 3459, 3459, 3459, 3459, 3459, 3459, 3459, + 3459, 3459, 3459, 3459, 2947, 2939, 2938, 11268, 3525, -220, + -1000, 9303, 3433, 3525, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -271, 3137, 50980, 2733, 2720, -343, + -344, 1237, -344, 1745, -1000, -290, 1190, 297, 50980, -1000, + -1000, 50980, 2395, 50980, 2393, 307, 261, 50980, 50980, 64, + 1192, 1154, 1177, -1000, -1000, 50980, 52280, -1000, 50980, 2073, + 50980, 50980, 3452, -1000, 50980, 50980, 937, 937, 937, -1000, + 46430, 40580, 50980, 50980, 2443, 50980, 50980, 50980, 937, 937, + 937, 937, 50980, -1000, 3392, 40580, 3371, 957, -1000, 50980, + 1662, 3450, 50980, -1000, -1000, -1000, -1000, 3586, 14533, 14533, + -1000, -1000, 11921, -1000, 350, 47730, 2012, 1975, 1975, -1000, + -1000, 50980, -1000, -1000, -1000, 2012, 50980, 2012, 2012, 3586, + 2012, -1000, -1000, -1000, 1975, 1975, -1000, -1000, 11921, -1000, + -1000, 2012, 2012, -1000, -1000, 3586, 50980, 104, 3586, 3586, + 125, -1000, -1000, -1000, 1975, 50980, 50980, 937, 50980, -1000, + 50980, 50980, -1000, -1000, 50980, 50980, 4665, 50980, 46430, 47080, + 3482, -1000, 40580, 50980, 50980, 1655, -1000, 983, 37980, -1000, + 50980, 1606, -1000, 75, -1000, 59, 73, 1889, 73, 1889, + 977, -1000, 685, 707, 24330, 615, 40580, 6682, -1000, -1000, + 1889, 1889, 6682, 6682, 1815, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1647, -1000, 384, 3525, -1000, -1000, -1000, -1000, + -1000, 2391, -303, 50980, 46430, 40580, 2443, 50980, 947, 50980, + 50980, 50980, 50980, 50980, -1000, 3136, 1738, -1000, 3440, 50980, + 50980, 50980, 50980, 1613, -1000, -1000, 21068, 1735, -1000, -1000, + 2092, -1000, 11921, 15848, -257, 11921, 15848, 15848, 11921, 15848, + -1000, 11921, 320, -1000, -1000, -1000, -1000, 2385, -1000, 2383, + -1000, -1000, -1000, -1000, -1000, 2714, 2714, -1000, 2382, -1000, + -1000, -1000, -1000, 2378, -1000, -1000, 2368, -1000, -1000, -1000, + -1000, -159, 2934, 1302, -1000, 2710, 3300, -221, -1000, 22376, + 50980, 50980, 408, -354, 2031, 2029, 2027, 3493, -1000, -221, + -1000, 21722, 50980, 3525, -1000, -229, 3433, 11921, 50980, -1000, + 3501, -1000, -1000, 361, -1000, -1000, -1000, 509, 657, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 1734, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -69, -76, + 1635, -1000, 50980, -1000, -1000, 392, 40580, 43180, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 270, -1000, -1000, 176, -1000, + 973, 290, 1926, -1000, -1000, 264, 221, 236, 1057, 2188, + -1000, 2071, 2071, 2094, -1000, 805, -1000, -1000, -1000, -1000, + 3134, -1000, -1000, -1000, 2367, 3387, -1000, 2113, 2113, 1843, + 1843, 1843, 1843, 1843, 2057, 2057, -1000, -1000, -1000, 7344, + 3133, 14533, 14533, 14533, 14533, 1027, 1027, 1956, 4515, -1000, + -1000, -1000, -1000, 11921, 175, 2074, -1000, 11921, 2672, 1725, + 2569, 1552, 1920, -1000, 3052, 11921, 1732, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 384, -1000, 12289, 12289, 12289, 12289, 12289, -1000, - 736, 14248, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 14901, - 14901, 14901, 14901, 14901, 14901, 14901, 14901, 14901, 14901, 14901, - 14901, 3001, 1887, 14901, 14901, 14901, 14901, 28598, 1625, 3186, - 1531, 317, 1727, 1727, 1727, 1727, 12289, -1000, 1984, 2072, - 12289, 12289, 12289, 12289, 35098, 51348, -1000, -1000, 4989, 12289, - 12289, 5481, 12289, 3387, 12289, 12289, 12289, 2806, 6397, 51348, - 12289, -1000, 2805, 2797, -1000, -1000, 2135, 12289, -1000, -1000, - 12289, -1000, -1000, 12289, 14901, 12289, -1000, 12289, 12289, 12289, - -1000, -1000, 3115, 3387, 3387, 3387, 1900, 12289, 12289, 3387, - 3387, 3387, 1868, 3387, 3387, 3387, 3387, 3387, 3387, 3387, - 3387, 3387, 3387, 3387, 2787, 2781, 2779, 11636, 3436, -223, - -1000, 9671, 3354, 3436, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -277, 3028, 51348, 2566, 2564, -351, - -352, 1182, -352, 1706, -1000, -295, 1105, 290, 51348, -1000, - -1000, 51348, 2253, 51348, 2252, 293, 273, 51348, 51348, 88, - 1110, 1089, 1087, -1000, -1000, 51348, 52648, -1000, 51348, 2014, - 51348, 51348, 3381, -1000, 51348, 51348, 874, 874, 874, -1000, - 46798, 40948, 51348, 51348, 2293, 51348, 51348, 51348, 874, 874, - 874, 874, 51348, -1000, 3312, 40948, 3304, 889, -1000, 51348, - 1510, 3380, 51348, -1000, -1000, -1000, -1000, 3476, 14901, 14901, - -1000, -1000, 12289, -1000, 271, 48098, 1911, 1800, 1800, -1000, - -1000, 51348, -1000, -1000, -1000, 1911, 51348, 1911, 1911, 3476, - 1911, -1000, -1000, -1000, 1800, 1800, -1000, -1000, 12289, -1000, - -1000, 1911, 1911, -1000, -1000, 3476, 51348, 116, 3476, 3476, - 122, -1000, -1000, -1000, 1800, 51348, 51348, 874, 51348, -1000, - 51348, 51348, -1000, -1000, 51348, 51348, 4988, 51348, 46798, 47448, - 3410, -1000, 40948, 51348, 51348, 1506, -1000, 933, 38348, -1000, - 51348, 1459, -1000, 50, -1000, 51, 37, 1821, 37, 1821, - 932, -1000, 683, 802, 24698, 600, 40948, 7050, -1000, -1000, - 1821, 1821, 7050, 7050, 1729, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1505, -1000, 327, 3436, -1000, -1000, -1000, -1000, - -1000, 2251, -306, 51348, 46798, 40948, 2293, 51348, 877, 51348, - 51348, 51348, 51348, 51348, -1000, 3022, 1692, -1000, 3363, 51348, - 51348, 51348, 51348, 1533, -1000, -1000, 21436, 1691, -1000, -1000, - 1998, -1000, 12289, 16216, -250, 12289, 16216, 16216, 12289, 16216, - -1000, 12289, 315, -1000, -1000, -1000, -1000, 2249, -1000, 2248, - -1000, -1000, -1000, -1000, -1000, 2559, 2559, -1000, 2245, -1000, - -1000, -1000, -1000, 2244, -1000, -1000, 2242, -1000, -1000, -1000, - -1000, -165, 2778, 1246, -1000, 2556, 3241, -224, -1000, 22744, - 51348, 51348, 404, -360, 1930, 1928, 1926, 3423, -1000, -224, - -1000, 22090, 51348, 3436, -1000, -228, 3354, 12289, 51348, -1000, - 3428, -1000, -1000, 366, -1000, -1000, -1000, 585, 503, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1684, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -75, -84, - 1493, -1000, 51348, -1000, -1000, 256, 40948, 43548, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 272, -1000, -1000, 180, -1000, - 931, 281, 1803, -1000, -1000, 234, 214, 222, 1023, 2072, - -1000, 1997, 1997, 2016, -1000, 764, -1000, -1000, -1000, -1000, - 3008, -1000, -1000, -1000, 2172, 1893, -1000, 1845, 1845, 1739, - 1739, 1739, 1739, 1739, 1931, 1931, -1000, -1000, -1000, 7712, - 3001, 14901, 14901, 14901, 14901, 969, 969, 2955, 4218, -1000, - -1000, -1000, -1000, 12289, 177, 1964, -1000, 12289, 2637, 1453, - 2546, 1745, 1802, -1000, 2915, 12289, 1678, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2930, 2925, 2827, + 3605, 2920, 11921, -1000, -1000, 1915, 1911, 1884, -1000, 2375, + 10615, -1000, -1000, -1000, 2918, 1727, 2917, -1000, -1000, -1000, + 2914, 1875, 1367, 2912, 1917, 2911, 2910, 2908, 2898, 1634, + 11921, 11921, 11921, 11921, 2896, 1874, 1873, 11921, 11921, 11921, + 11921, 2890, 11921, 11921, 11921, 11921, 11921, 11921, 11921, 11921, + 11921, 11921, 50980, 173, 173, 173, 1630, 1629, -1000, -1000, + 1867, -1000, 2188, -1000, -1000, 3433, -1000, 3130, 2353, 1616, + -1000, -1000, -331, 2652, 972, 50980, -291, 50980, 972, 50980, + 50980, 2023, 972, -294, 2707, -1000, -1000, 2705, -1000, 50980, + 50980, 50980, 50980, -96, 3434, -1000, -1000, 1189, 1139, 1131, + -1000, 50980, -1000, 2702, 3439, 3500, 974, 50980, 3129, 3128, + 50980, 50980, 50980, 312, -1000, -1000, 1340, -1000, 290, 4, + 619, 1429, 3290, 914, -128, 50980, 50980, 50980, 50980, 3449, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 45780, -1000, + 3111, 1850, -1000, -1000, 1813, 1813, 2188, 50980, 50980, 50980, + 3289, 50980, 50980, 3586, 3586, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 2012, 3586, 3586, 1688, 1975, 2012, -1000, -1000, + 2012, -354, -1000, 2012, -1000, -354, 1717, -354, 50980, -1000, + -1000, -1000, 3448, 3063, 1615, -1000, -1000, -1000, 3571, 1719, + 925, 925, 1161, 646, 3570, 19768, -1000, 1918, 1306, 970, + 3393, 365, -1000, 1918, -156, 906, 1918, 1918, 1918, 1918, + 1918, 1918, 1918, 817, 815, 1918, 1918, 1918, 1918, 1918, + 1918, 1918, 1918, 1918, 1918, 1918, 1197, 1918, 1918, 1918, + 1918, 1918, -1000, 1918, 3105, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 862, 743, 311, 3474, 440, -1000, 458, 1340, + 660, 3472, 476, 50980, 50980, 3781, 1358, -1000, -1000, -1000, + -1000, -1000, 28880, 28880, 23680, 28880, -1000, 188, 1889, 73, + 56, -1000, -1000, 1606, 6682, 1606, 6682, 2352, -1000, -1000, + 968, -1000, -1000, 1429, -1000, 50980, 50980, -1000, -1000, 3104, + 2021, -1000, -1000, 17158, -1000, 6682, 6682, -1000, -1000, 30830, + 50980, -1000, 9, -1000, 40, 3433, -1000, -1000, -1000, 1338, + -1000, -1000, 1598, 1429, 3298, 50980, 1338, 1338, 1338, -1000, + -1000, 18468, 50980, 50980, -1000, -1000, -1000, -303, 3586, 9956, + -1000, 37980, -1000, -1000, 45130, -1000, 44480, 2039, -1000, 15848, + 2296, 203, -1000, 280, -317, 199, 2129, 198, 2188, -1000, + -1000, 2889, 2888, 1844, -1000, 1831, 2887, 1830, 1829, 2344, + -1000, 95, -1000, 3419, 1435, -1000, 3101, -1000, 1825, 3360, + -1000, 1594, -1000, 2020, 1805, -1000, -1000, -1000, 11921, 43830, + 11921, 1077, 1435, 1795, 3357, 1594, 3433, 2700, -1000, 1573, + -1000, 2282, 1715, 220, -1000, -1000, -1000, 50980, 2724, 1785, + 43180, 1478, -1000, 965, 1714, 1712, -1000, 40580, 360, 40580, + -1000, 40580, -1000, -1000, 428, -1000, 50980, 3430, -1000, -1000, + -1000, 2652, 2017, -352, 50980, -1000, -1000, -1000, -1000, -1000, + 1743, -1000, 1027, 1027, 1956, 4467, -1000, 14533, -1000, 14533, + 3197, -1000, 2015, -1000, 11921, 2202, 4816, 11921, 4816, 1632, + 27580, 34730, -102, 3423, 3143, 50980, -1000, -1000, 11921, 11921, + -1000, 3139, -1000, -1000, -1000, -1000, 11921, 11921, 2787, -1000, + 50980, -1000, -1000, -1000, -1000, 27580, -1000, 14533, -1000, -1000, + -1000, -1000, 11921, 1599, 1599, 3131, 1741, 173, 173, 173, + 3096, 3078, 3065, 1729, 173, 3047, 3041, 3008, 2977, 2872, + 2865, 2831, 2805, 2766, 2745, 1721, -1000, 3100, -1000, -1000, + 2189, 13227, 9303, -1000, -1000, 310, 1559, 2338, 2699, 140, + -1000, 2016, -1000, 474, -1000, 50980, 3602, -1000, 1711, 2692, + 42530, -1000, 50980, -1000, -1000, 3599, 3595, -1000, -1000, 50980, + 50980, -1000, -1000, -1000, 1106, -1000, 2686, -1000, 326, 301, + 2222, 332, 1261, 18468, 3063, 3099, 3063, 153, 1918, 690, + 40580, 846, -1000, 50980, 2403, 2014, 3297, 802, 3413, 50980, + 50980, 3089, 398, 3086, 3085, 3447, 571, 5308, 50980, 1421, + -1000, 1694, 450, -1000, 50980, -1000, -1000, 50980, -1000, 2443, + -1000, 1975, -1000, -1000, 3586, -1000, -1000, -1000, 11921, 11921, + -205, 3586, 1975, 1975, -1000, 2012, -1000, 50980, -1000, -354, + 571, 5308, 3446, 4887, 719, 2513, -1000, 50980, -1000, -1000, + -1000, 971, -1000, 1140, 937, 50980, 2128, 1140, 2124, 3084, + -1000, -1000, 50980, 50980, 50980, 50980, -1000, -1000, 50980, -1000, + 50980, 50980, 50980, 50980, 50980, 41880, -1000, 50980, 50980, -1000, + 50980, 2122, 50980, 2120, 1086, -1000, 1918, 1918, 1065, -1000, + -1000, 654, -1000, 41880, 2335, 2334, 2333, 2331, 2685, 2682, + 2681, 1918, 1918, 2330, 2680, 41230, 2678, 1403, 2325, 2315, + 2314, 2326, 2677, 1353, -1000, 2669, 2284, 2280, 2267, 50980, + 3074, 2588, -1000, -1000, 2222, 153, 1918, 411, 50980, 2013, + 2010, 690, 653, 653, 618, -2, 24980, -1000, -1000, -1000, + 50980, 37980, 37980, 37980, 37980, 37980, 37980, -1000, 3345, 3320, + 3067, -1000, 3327, 3321, 3335, 3344, 2684, 50980, 37980, 3063, + -1000, 41230, -1000, -1000, -1000, 1921, 1687, 3819, 1113, 11921, + 6682, -1000, -1000, 43, 53, -1000, -1000, -1000, -1000, 40580, + 2668, 615, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3496, + 50980, 50980, 918, 2886, 1518, -1000, -1000, -1000, 5308, 3055, + 3055, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 3055, 3055, 3061, -1000, -1000, 3054, 3054, 3054, 3052, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3056, + 3056, 3060, 3060, 3056, -1000, -1000, -1000, 3584, -1000, 1517, + -1000, -1000, 1679, -1000, 2063, -338, 15848, 1930, 1923, -1000, + 11921, 15848, 11921, -258, 403, -261, -1000, -1000, -1000, 2661, + -1000, -1000, -1000, 2312, -1000, 2306, -1000, 192, 238, 2110, + -221, 9303, 497, 50980, -221, 50980, 9303, -1000, 50980, 168, + -364, -365, 162, 2659, 456, -221, 3496, 95, 11921, 3386, + -1000, -1000, 50980, 2305, -1000, -1000, -1000, 3593, 40580, 2443, + 1865, 39930, -1000, 354, -1000, 268, 647, 2658, -1000, 990, + 137, 2657, 2652, -1000, -1000, -1000, -1000, 14533, 1813, -1000, + -1000, -1000, 2188, 11921, 2884, -1000, 1108, 1108, 2524, 2883, + 2882, -1000, 3055, 3055, -1000, 3052, 3054, 3052, 1108, 1108, + 2880, -1000, 3050, -1000, 3423, -1000, 2343, 2651, -1000, 2641, + 2631, 11921, -1000, 2873, 4068, 1627, -21, -189, 173, 173, + -1000, -1000, -1000, -1000, 173, 173, 173, 173, -1000, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 905, -101, -281, -103, -282, -1000, 2869, 1503, -1000, -1000, + -1000, -1000, -1000, 4056, 1499, 628, 628, 2652, 2650, 50980, + 2648, -297, 50980, -1000, -366, -372, 2638, 50980, 50980, 582, + 2049, -1000, 2633, -1000, -1000, 50980, 50980, 50980, 51630, 736, + 50980, 50980, 2630, -1000, 2628, 2867, 1484, -1000, -1000, 50980, + -1000, -1000, -1000, 2864, 3445, 19118, 3443, 2408, -1000, -1000, + -1000, 30180, 653, -1000, -1000, -1000, 777, 395, 2304, 634, + -1000, 50980, 614, 3372, 2007, 2627, 50980, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 3413, -1000, 1382, -354, 529, + 36680, 16508, -1000, 422, 50980, -1000, 50980, 19118, 19118, 422, + 536, 1980, -1000, 904, 1422, 146, 37980, 50980, -1000, 37330, + 2862, -1000, -1000, 1429, 3586, -1000, 2440, 2440, -129, -354, + 3586, 3586, 1975, -1000, -1000, 536, -1000, 422, -1000, 1766, + 20418, 674, 533, 521, -1000, 760, -1000, -1000, 899, 3388, + 5308, -1000, 50980, -1000, 50980, -1000, 50980, 50980, 937, 11921, + 3388, 50980, 962, -1000, 1220, 553, 543, 887, 887, 1483, + -1000, 3423, -1000, -1000, 1479, -1000, -1000, -1000, -1000, 50980, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2777, 2773, 2946, - 3494, 2770, 12289, -1000, -1000, 1793, 1790, 1787, -1000, 2400, - 10983, -1000, -1000, -1000, 2769, 1666, 2766, -1000, -1000, -1000, - 2765, 1786, 1294, 2760, 2928, 2759, 2758, 2757, 2756, 1490, - 12289, 12289, 12289, 12289, 2752, 1784, 1769, 12289, 12289, 12289, - 12289, 2746, 12289, 12289, 12289, 12289, 12289, 12289, 12289, 12289, - 12289, 12289, 51348, 163, 163, 163, 1489, 1485, -1000, -1000, - 1765, -1000, 2072, -1000, -1000, 3354, -1000, 3000, 2239, 1468, - -1000, -1000, -333, 2509, 929, 51348, -297, 51348, 929, 51348, - 51348, 1925, 929, -298, 2555, -1000, -1000, 2554, -1000, 51348, - 51348, 51348, 51348, -102, 3356, -1000, -1000, 1100, 1079, 1172, - -1000, 51348, -1000, 2544, 3355, 3427, 913, 51348, 2998, 2997, - 51348, 51348, 51348, 309, -1000, -1000, 1332, -1000, 281, -2, - 579, 1304, 3229, 872, -131, 51348, 51348, 51348, 51348, 3379, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 46148, -1000, - 2981, 1757, -1000, -1000, 1727, 1727, 2072, 51348, 51348, 51348, - 3228, 51348, 51348, 3476, 3476, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1911, 3476, 3476, 1662, 1800, 1911, -1000, -1000, - 1911, -360, -1000, 1911, -1000, -360, 1628, -360, 51348, -1000, - -1000, -1000, 3377, 2929, 1467, -1000, -1000, -1000, 3468, 1661, - 868, 868, 1097, 822, 3466, 20136, -1000, 1807, 1382, 928, - 3333, 361, -1000, 1807, -162, 849, 1807, 1807, 1807, 1807, - 1807, 1807, 1807, 724, 713, 1807, 1807, 1807, 1807, 1807, - 1807, 1807, 1807, 1807, 1807, 1807, 1128, 1807, 1807, 1807, - 1807, 1807, -1000, 1807, 2979, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 797, 657, 299, 3408, 400, -1000, 395, 1332, - 695, 3406, 432, 51348, 51348, 3728, 1423, -1000, -1000, -1000, - -1000, -1000, 29248, 29248, 24048, 29248, -1000, 209, 1821, 37, - 48, -1000, -1000, 1459, 7050, 1459, 7050, 2236, -1000, -1000, - 926, -1000, -1000, 1304, -1000, 51348, 51348, -1000, -1000, 2978, - 1905, -1000, -1000, 17526, -1000, 7050, 7050, -1000, -1000, 31198, - 51348, -1000, 3, -1000, 30, 3354, -1000, -1000, -1000, 1277, - -1000, -1000, 1456, 1304, 3240, 51348, 1277, 1277, 1277, -1000, - -1000, 18836, 51348, 51348, -1000, -1000, -1000, -306, 3476, 10324, - -1000, 38348, -1000, -1000, 45498, -1000, 44848, 1945, -1000, 16216, - 2083, 195, -1000, 260, -323, 193, 2011, 192, 2072, -1000, - -1000, 2745, 2743, 1740, -1000, 1737, 2742, 1734, 1732, 2232, - -1000, 84, -1000, 3346, 1310, -1000, 2972, -1000, 1728, 3297, - -1000, 1452, -1000, 1904, 1704, -1000, -1000, -1000, 12289, 44198, - 12289, 1044, 1310, 1703, 3295, 1452, 3354, 2539, -1000, 1450, - -1000, 2188, 1597, 215, -1000, -1000, -1000, 51348, 2547, 1698, - 43548, 1344, -1000, 925, 1594, 1589, -1000, 40948, 352, 40948, - -1000, 40948, -1000, -1000, 413, -1000, 51348, 3348, -1000, -1000, - -1000, 2509, 1903, -359, 51348, -1000, -1000, -1000, -1000, -1000, - 1671, -1000, 969, 969, 2955, 3925, -1000, 14901, -1000, 14901, - 3147, -1000, 1943, -1000, 12289, 2058, 5539, 12289, 5539, 1916, - 27948, 35098, -107, 3352, 3136, 51348, -1000, -1000, 12289, 12289, - -1000, 3096, -1000, -1000, -1000, -1000, 12289, 12289, 2764, -1000, - 51348, -1000, -1000, -1000, -1000, 27948, -1000, 14901, -1000, -1000, - -1000, -1000, 12289, 1439, 1439, 3089, 1644, 163, 163, 163, - 3083, 3078, 3073, 1642, 163, 3040, 3029, 3004, 2995, 2868, - 2857, 2836, 2825, 2800, 2785, 1641, -1000, 2971, -1000, -1000, - 2064, 13595, 9671, -1000, -1000, 316, 1448, 2229, 2537, 125, - -1000, 1902, -1000, 423, -1000, 51348, 3492, -1000, 1588, 2536, - 42898, -1000, 51348, -1000, -1000, 3485, 3484, -1000, -1000, 51348, - 51348, -1000, -1000, -1000, 1075, -1000, 2535, -1000, 262, 247, - 2115, 338, 1385, 18836, 2929, 2970, 2929, 175, 1807, 658, - 40948, 744, -1000, 51348, 2154, 1894, 3238, 837, 3339, 51348, - 51348, 2953, 494, 2940, 2937, 3372, 532, 5602, 51348, 1396, - -1000, 1576, 4271, -1000, 51348, -1000, -1000, 51348, -1000, 2293, - -1000, 1800, -1000, -1000, 3476, -1000, -1000, 12289, 12289, 3476, - 1800, 1800, -1000, 1911, -1000, 51348, -1000, -360, 532, 5602, - 3371, 5191, 617, 2533, -1000, 51348, -1000, -1000, -1000, 927, - -1000, 1074, 874, 51348, 2036, 1074, 2035, 2936, -1000, -1000, - 51348, 51348, 51348, 51348, -1000, -1000, 51348, -1000, 51348, 51348, - 51348, 51348, 51348, 42248, -1000, 51348, 51348, -1000, 51348, 2032, - 51348, 2026, 1064, -1000, 1807, 1807, 1034, -1000, -1000, 653, - -1000, 42248, 2228, 2226, 2225, 2224, 2532, 2530, 2529, 1807, - 1807, 2205, 2528, 41598, 2524, 1265, 2198, 2196, 2186, 2197, - 2523, 1086, -1000, 2521, 2192, 2191, 2170, 51348, 2932, 2461, - -1000, -1000, 2115, 175, 1807, 398, 51348, 1891, 1886, 658, - 638, 638, 575, -3, 25348, -1000, -1000, -1000, 51348, 38348, - 38348, 38348, 38348, 38348, 38348, -1000, 3272, 2874, 2930, -1000, - 3261, 3259, 3276, 3271, 3247, 51348, 38348, 2929, -1000, 41598, - -1000, -1000, -1000, 1625, 1634, 3823, 1072, 12289, 7050, -1000, - -1000, 47, 39, -1000, -1000, -1000, -1000, 40948, 2517, 600, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3426, 51348, 51348, - 866, 2737, 1429, -1000, -1000, -1000, 5602, 2920, 2920, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2920, 2920, - 2927, -1000, -1000, 2918, 2918, 2918, 2915, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2922, 2922, 2926, - 2926, 2922, -1000, -1000, -1000, 3473, -1000, 1427, -1000, -1000, - 1573, -1000, 1907, -345, 16216, 1949, 1940, -1000, 12289, 16216, - 12289, -251, 381, -253, -1000, -1000, -1000, 2516, -1000, -1000, - -1000, 2183, -1000, 2177, -1000, 189, 243, 2025, -224, 9671, - 464, 51348, -224, 51348, 9671, -1000, 51348, 173, -370, -371, - 162, 2515, 459, -224, 3426, 84, 12289, 3319, -1000, -1000, - 51348, 2176, -1000, -1000, -1000, 3482, 40948, 2293, 1756, 40298, - -1000, 348, -1000, 270, 637, 2511, -1000, 959, 124, 2510, - 2509, -1000, -1000, -1000, -1000, 14901, 1727, -1000, -1000, -1000, - 2072, 12289, 2726, -1000, 1073, 1073, 2297, 2723, 2718, -1000, - 2920, 2920, -1000, 2915, 2918, 2915, 1073, 1073, 2717, -1000, - 2914, -1000, 3352, -1000, 2335, 2721, -1000, 2669, 2579, 12289, - -1000, 2716, 3869, 1437, -41, -193, 163, 163, -1000, -1000, - -1000, -1000, 163, 163, 163, 163, -1000, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 841, -106, - -286, -108, -287, -1000, 2713, 1418, -1000, -1000, -1000, -1000, - -1000, 5481, 1415, 592, 592, 2509, 2507, 51348, 2506, -299, - 51348, -1000, -372, -375, 2504, 51348, 51348, 538, 1965, -1000, - 2503, -1000, -1000, 51348, 51348, 51348, 51998, 636, 51348, 51348, - 2501, -1000, 2493, 2705, 1401, -1000, -1000, 51348, -1000, -1000, - -1000, 2703, 3369, 19486, 3367, 2300, -1000, -1000, -1000, 30548, - 638, -1000, -1000, -1000, 762, 455, 2174, 622, -1000, 51348, - 565, 3310, 1882, 2491, 51348, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3339, -1000, 1112, -360, 479, 37048, 16876, - -1000, 414, 51348, -1000, 51348, 19486, 19486, 414, 527, 1906, - -1000, 836, 1241, 140, 38348, 51348, -1000, 37698, 2700, -1000, - -1000, 1304, 3476, -1000, 2072, 2072, -360, 3476, 3476, 1800, - -1000, -1000, 527, -1000, 414, -1000, 1763, 20786, 606, 534, - 519, -1000, 756, -1000, -1000, 831, 3327, 5602, -1000, 51348, - -1000, 51348, -1000, 51348, 51348, 874, 12289, 3327, 51348, 921, - -1000, 1183, 502, 501, 823, 823, 1355, -1000, 3352, -1000, - -1000, 1351, -1000, -1000, -1000, -1000, 51348, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 27948, 27948, 3404, + 27580, 27580, 3470, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 2624, 2623, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 2489, 2487, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 50980, 1677, -1000, + 2005, 2618, 2408, 30180, 2004, 1889, 2614, 2613, 653, -1000, + 2611, 2609, -1000, 2403, 2001, 975, 50980, -1000, 1427, 50980, + 50980, -1000, 1452, -1000, 2000, 3282, 3296, 3282, -1000, 3282, + -1000, -1000, -1000, -1000, 3342, 2608, -1000, 3340, -1000, 3339, + -1000, -1000, -1000, -1000, 1452, -1000, -1000, -1000, -1000, -1000, + 1113, -1000, 3495, 1140, 1140, 1140, 2848, -1000, -1000, -1000, + -1000, 1478, 2847, -1000, -1000, -1000, 3617, -1000, -1000, -1000, + -1000, -1000, -1000, 18468, 3401, 3575, 3569, 39280, -1000, -338, + 1966, -1000, 2173, 196, 2064, 50980, -1000, -1000, -1000, 2844, + 2839, -232, 207, 3567, 3565, 1194, -1000, 2837, 1465, -221, + -1000, -1000, 1435, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -373, -221, -1000, 1435, -1000, 192, -1000, -1000, 3395, -1000, + -1000, 2443, -1000, 267, -1000, -1000, -1000, -1000, -1000, -1000, + 278, -1000, 50980, -1000, 1459, 136, -1000, 2188, -1000, -1000, + -1000, -1000, -1000, 4816, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 2604, -1000, -1000, 11921, -1000, -1000, + -1000, 2556, -1000, -1000, 11921, 2826, 2603, 2823, 2599, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 51348, 1629, -1000, 1877, 2485, 2300, - 30548, 1874, 1821, 2482, 2481, 638, -1000, 2480, 2476, -1000, - 2154, 1873, 958, 51348, -1000, 1292, 51348, 51348, -1000, 1399, - -1000, 1872, 3227, 3235, 3227, -1000, 3227, -1000, -1000, -1000, - -1000, 3267, 2475, -1000, 3260, -1000, 3057, -1000, -1000, -1000, - -1000, 1399, -1000, -1000, -1000, -1000, -1000, 1072, -1000, 3425, - 1074, 1074, 1074, 2691, -1000, -1000, -1000, -1000, 1344, 2686, - -1000, -1000, -1000, 3506, -1000, -1000, -1000, -1000, -1000, -1000, - 18836, 3338, 3471, 3465, 39648, -1000, -345, 1942, -1000, 2027, - 191, 1983, 51348, -1000, -1000, -1000, 2683, 2682, -230, 225, - 3462, 3461, 1142, -1000, 2680, 1339, -224, -1000, -1000, 1310, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -377, -224, -1000, - 1310, -1000, 189, -1000, -1000, 3323, -1000, -1000, 2293, -1000, - 268, -1000, -1000, -1000, -1000, -1000, -1000, 255, -1000, 51348, - -1000, 1336, 121, -1000, 2072, -1000, -1000, -1000, -1000, -1000, - 5539, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2473, -1000, -1000, 12289, -1000, -1000, -1000, 2565, -1000, - -1000, 12289, 2679, 2470, 2678, 2467, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 3624, -1000, 3556, 1673, + 2822, 2821, 1641, 2820, 2819, -1000, 11921, 2818, 4056, 1074, + 2596, 1074, -1000, -1000, -1000, -1000, 50980, -1000, -1000, -1000, + 29530, 961, -354, -1000, 390, -1000, 578, 2595, -1000, -1000, + 50980, 2222, 725, 2222, 831, 50980, -303, -1000, -112, 1261, + 5308, 1007, 422, 2811, 1446, -1000, -1000, -1000, -1000, 422, + -1000, 2589, 289, -1000, -1000, -1000, -1000, 2302, -1000, -1000, + 2227, 1778, 296, -1000, -1000, -1000, -1000, -1000, -1000, 2381, + 50980, 38630, 2407, 1995, -355, -1000, 3040, -1000, 1918, 1918, + 1918, 961, 50980, 1640, -1000, 1918, 1918, 2809, -1000, -1000, + 961, 2807, 2806, -134, 908, 1981, 1979, -1000, 2291, 28880, + 37980, 37330, 1439, -1000, 1462, -1000, -1000, -1000, -1000, -1000, + 352, -1000, -1000, -1000, 3586, 908, -1000, 642, 2288, 14533, + 3022, 14533, 3018, 694, 3015, 1636, -1000, 50980, -1000, -1000, + 50980, 3920, 3014, -1000, 3013, 3287, 620, 3011, 3004, 50980, + 2542, -1000, 3388, 50980, 849, 3397, -1000, -1000, -1000, 503, + -1000, -1000, -1000, 756, -1000, 50980, -1000, 50980, -1000, 1798, + -1000, 27580, -1000, -1000, 1617, -1000, 2588, 2585, -1000, -1000, + 289, 2583, 6682, -1000, -1000, -1000, -1000, -1000, 3372, 2572, + 2381, 50980, -1000, 50980, 1427, 1427, 3624, 50980, 9303, -1000, + -1000, 11921, 3000, -1000, 11921, -1000, -1000, -1000, 2802, -1000, + -1000, -1000, -1000, -1000, 2999, 3383, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1842, -1000, 11921, 12574, -1000, 934, 15848, + -262, 388, -1000, -1000, -1000, -240, 2570, -1000, -1000, 3548, + 2568, 2436, 50980, -1000, -1000, 1435, -1000, 1435, -232, -1000, + -1000, 1429, -1000, -1000, 1210, 821, -1000, 2799, 291, -1000, + 2516, -1000, 2507, 173, -1000, 173, -1000, 323, 11921, -1000, + 2562, -1000, -1000, -1000, 2558, -1000, -1000, 2498, -1000, 2777, + -1000, 2557, -1000, -1000, 2554, -1000, -1000, 401, 961, 50980, + 2553, 2286, -1000, 595, -356, -1000, 2552, 2222, 2550, 2222, + 50980, 700, -1000, 2545, 2535, -1000, -1000, 5308, -135, -134, + 19118, -135, -1000, -1000, 427, 469, -1000, -1000, 2226, 689, + -1000, -1000, 2534, 701, -1000, 1427, -1000, 1994, 2142, 2480, + 34730, 27580, 28230, 2528, -1000, -1000, -1000, 36680, 1842, 1842, + 5532, -1000, 382, 56235, -1000, 2997, 1208, 1909, -1000, 2283, + -1000, 2281, -1000, 3586, 1439, 142, -1000, -1000, 1847, 11921, + -1000, 1208, 2513, 3543, -1000, 4018, 50980, 3581, 50980, 2996, + 1993, 14533, -1000, 899, 3356, -1000, -1000, 3920, -1000, -1000, + 2151, 14533, -1000, -1000, 2525, 28230, 1066, 1992, 1986, 1125, + 2995, -1000, 781, 3616, -1000, -1000, -1000, 1063, 2994, -1000, + 2109, 2108, -1000, 50980, -1000, 34730, 34730, 668, 668, 34730, + 34730, 2993, 887, -1000, -1000, 14533, -1000, -1000, 1918, -1000, + -1000, -1000, 1918, 1797, -1000, -1000, -1000, -1000, -1000, -1000, + 2407, -1000, -1000, 1338, -1000, 3525, -1000, -1000, 2188, 50980, + 2188, -1000, 36030, -1000, 3542, 3535, -1000, 2188, 262, 269, + 2991, 2990, -1000, -338, 50980, 50980, -243, 2278, -1000, 2515, + 217, -1000, -1000, 1313, -240, -245, 125, 27580, 1964, -1000, + 2776, 376, -147, -1000, -1000, -1000, -1000, 2768, -1000, 648, + -1000, -1000, -1000, 1302, 2767, 2762, -1000, -1000, -1000, -1000, + 50980, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2473, -303, + 2512, -303, 2506, 699, 2222, -1000, -1000, -114, -1000, -1000, + 448, -1000, -1000, -1000, 682, 2446, -1000, -1000, 468, -1000, + -1000, -1000, 2381, 2504, -1000, -1000, 134, -1000, 1944, 1608, + -1000, -1000, -1000, -1000, -1000, -1000, 896, -1000, 422, 56197, + -1000, 1306, -1000, 1210, 896, 33430, 766, 331, -1000, 2264, + -1000, -1000, 3624, -1000, 1302, 746, -1000, 678, -1000, 1603, + -1000, 1577, 35380, 2263, 3057, -1000, 56146, 1031, -1000, -1000, + 1956, -1000, -1000, -1000, -1000, -1000, -1000, 2492, 2491, -1000, + -1000, -1000, -1000, -1000, 2236, 2989, 22, 3468, 2485, -1000, + -1000, 2988, 1571, 1570, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1562, 1550, 34730, -1000, -1000, 1956, + 2235, 27580, 1918, -1000, -1000, 1546, 1540, -1000, -1000, -1000, + -1000, -1000, -316, 2987, 11921, 11921, -1000, -1000, -1000, 2986, + -1000, -1000, 3534, -243, -251, 2484, 184, 249, -1000, 2483, + -1000, -123, 3350, -150, -1000, -1000, 706, -222, 163, 150, + 144, -1000, -1000, -1000, 11921, -1000, -1000, -1000, 120, -1000, + 1929, -1000, -303, -1000, -303, 2222, 2481, 50980, 774, -1000, + -1000, -1000, -1000, 275, -1000, -1000, -1000, -1000, -1000, -1000, + 2480, 2477, -1000, 630, 3533, -1000, 56235, -1000, 1918, -1000, + 630, 1511, -1000, 1918, 1918, -1000, 569, -1000, 1901, -1000, + 2210, -1000, 3525, -1000, 534, -1000, 637, -1000, -1000, -1000, + 1485, -1000, -1000, -1000, 56146, 671, -1000, 892, 2985, -1000, + -1000, 2761, 11921, 2982, 1918, 2760, -94, 34730, 3285, 3205, + 3145, 3043, 1481, -1000, -1000, 27580, -1000, -1000, 34080, -1000, + 2981, 1453, 1451, 50980, 2436, -1000, -1000, 2475, -1000, 954, + 205, 249, -1000, 3532, 213, 3531, 3530, 1241, 3349, -1000, + -1000, 2083, -1000, 187, 182, 169, -1000, -1000, -1000, -1000, + -303, 2473, 2471, -1000, -1000, 2469, -303, 608, -1000, 346, + -1000, -1000, -1000, 327, -1000, 3529, 719, -1000, 27580, -1000, + -1000, 33430, 1842, 1842, -1000, -1000, 2208, -1000, -1000, -1000, + -1000, 2205, -1000, -1000, -1000, 1449, -1000, 50980, 1080, 8650, + -1000, 2494, -1000, 50980, -1000, 3295, -1000, 324, 1444, 327, + 668, 327, 668, 327, 668, 327, 668, 340, -1000, -1000, + -1000, 1437, 11921, -1000, -1000, 1423, -1000, -1000, -1000, 2964, + 2198, 207, 209, 3528, -1000, 2436, 3527, 2436, 2436, -1000, + 177, -141, 706, -1000, -1000, -1000, -1000, -1000, -1000, -303, + -1000, 2461, -1000, -1000, -1000, -1000, 1918, 1918, 2459, 2457, + 522, -1000, -1000, 1918, 1918, 1918, -1000, 32780, 674, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 671, 56235, -1000, 8650, + 1415, -1000, 2188, -1000, 887, -1000, -1000, 3293, 3068, 3591, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3512, -1000, 3460, 1612, 2675, 2674, 1611, - 2673, 2671, -1000, 12289, 2670, 5481, 1037, 2466, 1037, -1000, - -1000, -1000, -1000, 51348, -1000, -1000, -1000, 29898, 897, -360, - -1000, 390, -1000, 544, 2463, -1000, -1000, 51348, 2115, 633, - 2115, 692, 51348, -306, -1000, -110, 1385, 5602, 978, 414, - 2635, 1321, -1000, -1000, -1000, -1000, 414, -1000, 2462, 280, - -1000, -1000, -1000, -1000, 2171, -1000, -1000, 2169, 1549, 294, - -1000, -1000, -1000, -1000, -1000, -1000, 2290, 51348, 38998, 2296, - 1861, -361, -1000, 2910, -1000, 1807, 1807, 1807, 897, 51348, - 1599, -1000, 1807, 1807, 2626, -1000, -1000, 897, 2625, 2622, - -133, 851, 1866, 1835, -1000, 2161, 29248, 38348, 37698, 1335, - -1000, 1565, -1000, -1000, -1000, -1000, -1000, -1000, 3476, 851, - -1000, 602, 2160, 14901, 2909, 14901, 2908, 619, 2903, 1582, - -1000, 51348, -1000, -1000, 51348, 379, 2891, -1000, 2890, 3138, - 591, 2882, 2880, 51348, 2527, -1000, 3327, 51348, 799, 3337, - -1000, -1000, -1000, 458, -1000, -1000, -1000, 662, -1000, 51348, - -1000, 51348, -1000, 1648, -1000, 27948, -1000, -1000, 1581, -1000, - 2461, 2460, -1000, -1000, 280, 2459, 7050, -1000, -1000, -1000, - -1000, -1000, 3310, 2454, 2290, 51348, -1000, 51348, 1292, 1292, - 3512, 51348, 9671, -1000, -1000, 12289, 2879, -1000, 12289, -1000, - -1000, -1000, 2620, -1000, -1000, -1000, -1000, -1000, 2871, 3335, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2152, -1000, 12289, - 12942, -1000, 873, 16216, -262, 376, -1000, -1000, -1000, -232, - 2446, -1000, -1000, 3458, 2445, 2316, 51348, -1000, -1000, 1310, - -1000, 1310, -230, -1000, -1000, 1304, -1000, -1000, 1225, 727, - -1000, 2615, 287, -1000, 2518, -1000, 2433, 163, -1000, 163, - -1000, 343, 12289, -1000, 2444, -1000, -1000, -1000, 2420, -1000, - -1000, 2415, -1000, 2614, -1000, 2414, -1000, -1000, 2413, -1000, - -1000, 411, 897, 51348, 2411, 2150, -1000, 569, -365, -1000, - 2407, 2115, 2406, 2115, 51348, 629, -1000, 2405, 2404, -1000, - -1000, 5602, -135, -133, 19486, -135, -1000, -1000, 408, 416, - -1000, -1000, 2127, 676, -1000, -1000, 2401, 641, -1000, 1292, - -1000, 1857, 2048, 2342, 35098, 27948, 28598, 2399, -1000, -1000, - -1000, 37048, 2152, 2152, 5825, -1000, 384, 56565, -1000, 2870, - 1145, 1829, -1000, 2148, -1000, 2147, -1000, 3476, 1335, 138, - -1000, -1000, 1752, -1000, 1145, 2533, 3457, -1000, 3592, 51348, - 3546, 51348, 2863, 1849, 14901, -1000, 831, 3293, -1000, -1000, - 379, -1000, -1000, 2051, 14901, -1000, -1000, 2398, 28598, 971, - 1848, 1843, 1008, 2860, -1000, 685, 3505, -1000, -1000, -1000, - 1026, 2859, -1000, 2024, 2022, -1000, 51348, -1000, 35098, 35098, - 804, 804, 35098, 35098, 2849, 823, -1000, -1000, 14901, -1000, - -1000, 1807, -1000, -1000, -1000, 1807, 1585, -1000, -1000, -1000, - -1000, -1000, -1000, 2296, -1000, -1000, 1277, -1000, 3436, -1000, - -1000, 2072, 51348, 2072, -1000, 36398, -1000, 3456, 3455, -1000, - 2072, 258, 263, 2847, 2840, -1000, -345, 51348, 51348, -234, - 2144, -1000, 2396, 206, -1000, -1000, 1256, -232, -236, 122, - 27948, 1839, -1000, 2605, 382, -154, -1000, -1000, -1000, -1000, - 2603, -1000, 805, -1000, -1000, -1000, 1246, 2600, 2599, -1000, - -1000, -1000, -1000, 51348, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2337, -306, 2394, -306, 2393, 628, 2115, -1000, -1000, - -118, -1000, -1000, 474, -1000, -1000, -1000, 647, 2310, -1000, - -1000, 415, -1000, -1000, -1000, 2290, 2392, -1000, -1000, 120, - -1000, 1826, 1577, -1000, -1000, -1000, -1000, -1000, -1000, 817, - -1000, 414, 56514, -1000, 1382, -1000, 1225, 817, 33798, 677, - 314, -1000, 2139, -1000, -1000, 3512, -1000, 669, -1000, 612, - -1000, 1555, -1000, 1548, 35748, 2133, 3143, -1000, 5906, 945, - -1000, -1000, 2955, -1000, -1000, -1000, -1000, -1000, -1000, 2388, - 2386, -1000, -1000, -1000, -1000, -1000, 2128, 2835, 71, 3399, - 2383, -1000, -1000, 2833, 1518, 1511, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1495, 1494, 35098, -1000, - -1000, 2955, 2122, 27948, 1807, -1000, -1000, 1487, 1486, -1000, - -1000, -1000, -1000, -1000, -314, 2832, 12289, 12289, -1000, -1000, - -1000, 2824, -1000, -1000, 3454, -234, -238, 2368, 187, 248, - -1000, 2361, -1000, -127, 3287, -158, -1000, -1000, 1054, -226, - 165, 153, 128, -1000, -1000, -1000, 12289, -1000, -1000, -1000, - 113, -1000, 1820, -1000, -306, -1000, -306, 2115, 2343, 51348, - 678, -1000, -1000, -1000, -1000, 251, -1000, -1000, -1000, -1000, - -1000, -1000, 2342, 2339, -1000, 595, 3447, -1000, 56565, -1000, - 1807, -1000, 595, 1455, -1000, 1807, 1807, -1000, 530, -1000, - 1824, -1000, 2102, -1000, 3436, -1000, 485, -1000, 599, -1000, - -1000, -1000, 1449, -1000, -1000, -1000, 5906, 603, -1000, 803, - 2823, -1000, -1000, 2598, 12289, 2821, 1807, 2589, -99, 35098, - 3117, 3091, 3031, 3006, 1444, -1000, -1000, 27948, -1000, -1000, - 34448, -1000, 2819, 1411, 1404, 51348, 2316, -1000, -1000, 2338, - -1000, 888, 223, 248, -1000, 3446, 200, 3444, 3443, 1243, - 3285, -1000, -1000, 2012, -1000, 184, 172, 151, -1000, -1000, - -1000, -1000, -306, 2337, 2334, -1000, -1000, 2333, -306, 614, - -1000, 346, -1000, -1000, -1000, 326, -1000, 3442, 617, -1000, - 27948, -1000, -1000, 33798, 2152, 2152, -1000, -1000, 2099, -1000, - -1000, -1000, -1000, 2089, -1000, -1000, -1000, 1372, -1000, 51348, - 1031, 9018, -1000, 2341, -1000, 51348, -1000, 3232, -1000, 334, - 1364, 326, 804, 326, 804, 326, 804, 326, 804, 340, - -1000, -1000, -1000, 1358, 12289, -1000, -1000, 1352, -1000, -1000, - -1000, 2812, 2082, 225, 197, 3441, -1000, 2316, 3440, 2316, - 2316, -1000, 179, -142, 1054, -1000, -1000, -1000, -1000, -1000, - -1000, -306, -1000, 2332, -1000, -1000, -1000, -1000, 1807, 1807, - 2331, 2327, 470, -1000, -1000, 1807, 1807, 1807, -1000, 33148, - 606, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 603, 56565, - -1000, 9018, 1343, -1000, 2072, -1000, 823, -1000, -1000, 3081, - 3076, 3481, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 2811, 2584, -1000, 51348, 3386, 27298, 194, -1000, - -1000, -1000, 2324, -1000, 2316, -1000, -1000, 1785, -156, -1000, - -1000, -284, 2081, 2080, -1000, -1000, 51348, 2076, 2069, 2059, - -1000, 51348, 602, -1000, 56565, 1334, -1000, 9018, -1000, -1000, - 3483, -1000, 3502, 996, 996, 326, 326, 326, 326, 12289, - -1000, -1000, -1000, 51348, -1000, 1255, -1000, -1000, -1000, 1552, - -1000, -1000, -1000, -1000, 2305, -159, -1000, -1000, 2301, -1000, - -1000, -1000, -1000, -1000, -1000, 1230, 2533, -1000, -1000, -1000, - -1000, -1000, 2109, 689, -1000, 2302, 1177, -1000, 1776, -1000, - 32498, 51348, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 51348, 8365, -1000, 1545, -1000, -1000, 2072, 51348, -1000, + 2957, 2756, -1000, 50980, 3458, 26930, 197, -1000, -1000, -1000, + 2442, -1000, 2436, -1000, -1000, 1908, -148, -1000, -1000, -279, + 2196, 2190, -1000, -1000, 50980, 2183, 2177, 2174, -1000, 50980, + 642, -1000, 56235, 1409, -1000, 8650, -1000, -1000, 3611, -1000, + 3608, 1095, 1095, 327, 327, 327, 327, 11921, -1000, -1000, + -1000, 50980, -1000, 1398, -1000, -1000, -1000, 1383, -1000, -1000, + -1000, -1000, 2430, -152, -1000, -1000, 2415, -1000, -1000, -1000, + -1000, -1000, -1000, 1337, 2513, -1000, -1000, -1000, -1000, -1000, + 2206, 786, -1000, 2547, 1214, -1000, 1894, -1000, 32130, 50980, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 50980, + 7997, -1000, 1364, -1000, -1000, 2188, 50980, -1000, } var yyPgo = [...]int{ - 0, 175, 3528, 244, 181, 4215, 105, 262, 311, 286, - 259, 258, 4212, 4211, 4210, 3349, 3342, 4209, 4208, 4207, - 4206, 4204, 4203, 4202, 4201, 4200, 4197, 4196, 4195, 4192, - 4191, 4190, 4189, 4188, 4187, 4186, 4180, 4179, 4178, 4177, - 4176, 4175, 4174, 4173, 4158, 4154, 4153, 256, 4152, 4151, - 4150, 4149, 4147, 4146, 4144, 4143, 4141, 4140, 4136, 4132, - 4131, 4129, 4128, 4127, 4126, 4125, 4124, 4123, 4120, 4119, - 4116, 4115, 4114, 4113, 4112, 4111, 4110, 4109, 4108, 4107, - 4100, 4099, 4093, 4092, 4091, 263, 4086, 3331, 4085, 4084, - 4083, 4082, 4081, 4078, 4065, 4063, 4062, 4061, 4059, 363, - 4057, 4055, 4054, 4053, 4052, 4051, 4048, 4047, 4046, 4045, - 4040, 4039, 4037, 346, 4035, 4033, 4031, 4029, 211, 4028, - 341, 4027, 173, 185, 4026, 4025, 4024, 4022, 4009, 4005, - 4003, 4002, 4001, 3998, 3997, 3995, 3994, 3993, 241, 193, - 65, 3992, 52, 3991, 240, 210, 3989, 219, 3988, 153, - 3987, 147, 3985, 3984, 3983, 3982, 3980, 3979, 3978, 3977, - 3976, 3973, 3972, 3968, 3967, 3966, 3965, 3964, 3963, 3962, - 3959, 3958, 3957, 3948, 3946, 3945, 53, 3944, 266, 3943, - 78, 3941, 177, 3939, 70, 3938, 3937, 86, 3936, 3933, - 92, 137, 265, 3019, 255, 3932, 192, 3925, 3924, 251, - 178, 3923, 3922, 319, 3920, 204, 231, 186, 108, 120, - 3919, 136, 3917, 253, 51, 46, 245, 154, 3916, 3915, - 62, 176, 132, 3914, 215, 103, 3913, 3911, 116, 3908, - 3907, 146, 3905, 254, 180, 3901, 110, 3900, 3890, 3889, - 22, 3887, 3886, 202, 195, 3884, 3883, 106, 3881, 3880, - 63, 133, 3879, 82, 144, 168, 127, 3877, 2795, 131, - 90, 3876, 123, 109, 3875, 81, 3874, 3873, 3872, 3871, - 188, 3870, 3868, 145, 59, 3865, 3864, 3862, 76, 3861, - 85, 3860, 33, 3859, 58, 3858, 3856, 3855, 3854, 3853, - 3851, 3849, 3848, 3847, 3846, 3845, 3844, 56, 3843, 3841, - 3840, 3839, 7, 14, 17, 3838, 28, 3837, 169, 3836, - 3834, 166, 3833, 200, 3832, 3830, 104, 96, 3829, 98, - 163, 3828, 9, 34, 75, 3826, 3825, 3824, 224, 3822, - 3821, 3820, 275, 3818, 3817, 3816, 151, 3815, 3812, 3811, - 2890, 3810, 3808, 3805, 3796, 3795, 3793, 61, 3792, 1, - 218, 41, 3791, 138, 143, 3790, 40, 32, 3786, 45, - 125, 222, 141, 107, 3784, 3783, 3782, 677, 199, 100, - 29, 0, 102, 223, 161, 3781, 3780, 3778, 261, 3776, - 239, 203, 234, 267, 264, 250, 3775, 3774, 57, 3773, - 158, 31, 54, 135, 79, 23, 214, 3771, 499, 10, - 184, 3769, 217, 3768, 8, 15, 142, 149, 3767, 3766, - 36, 268, 3765, 3764, 3761, 134, 3757, 3755, 187, 84, - 3754, 3753, 3752, 3751, 3750, 42, 3749, 183, 16, 3748, - 113, 3747, 248, 3746, 221, 152, 189, 179, 164, 232, - 228, 91, 83, 3730, 1896, 160, 117, 25, 3728, 226, - 3727, 282, 126, 3726, 88, 3725, 246, 260, 208, 3724, - 190, 11, 49, 39, 30, 48, 12, 272, 206, 3723, - 3721, 21, 50, 3719, 68, 3716, 19, 3715, 3714, 43, - 3708, 71, 5, 3706, 3702, 18, 20, 3701, 38, 213, - 171, 130, 99, 60, 3700, 3699, 170, 249, 3683, 156, - 150, 162, 3682, 80, 3681, 3677, 3676, 3675, 754, 252, - 3673, 3672, 3670, 3668, 3667, 3666, 3655, 3654, 216, 3653, - 118, 44, 3652, 3650, 3649, 3648, 89, 157, 3647, 3646, - 3643, 3642, 35, 139, 3641, 13, 3640, 26, 24, 37, - 3637, 112, 3630, 3, 191, 3629, 3625, 4, 3624, 3616, - 2, 3615, 3614, 129, 3612, 101, 27, 167, 119, 3610, - 3608, 95, 212, 148, 3607, 3606, 111, 243, 205, 3602, - 97, 235, 257, 3601, 209, 3600, 3599, 3596, 3591, 3588, - 1240, 3586, 3585, 238, 69, 93, 3584, 220, 122, 3583, - 3582, 94, 159, 124, 121, 55, 87, 3581, 115, 207, - 3580, 197, 3576, 247, 3572, 3571, 114, 3570, 3568, 3567, - 3566, 194, 3565, 3564, 196, 237, 3562, 3560, 274, 3558, - 3548, 3547, 3544, 3542, 3536, 3535, 3532, 3531, 3530, 233, - 198, 3526, + 0, 182, 3638, 244, 180, 4303, 79, 253, 363, 287, + 252, 251, 4302, 4301, 4300, 3397, 3393, 4299, 4293, 4292, + 4291, 4289, 4288, 4287, 4286, 4285, 4284, 4282, 4281, 4280, + 4279, 4278, 4277, 4276, 4275, 4272, 4271, 4270, 4269, 4268, + 4263, 4262, 4261, 4260, 4259, 4258, 4256, 250, 4255, 4254, + 4253, 4251, 4249, 4243, 4242, 4241, 4239, 4238, 4237, 4236, + 4235, 4234, 4231, 4229, 4228, 4226, 4206, 4205, 4204, 4203, + 4199, 4196, 4195, 4194, 4188, 4187, 4186, 4185, 4184, 4183, + 4181, 4176, 4174, 4171, 4158, 275, 4157, 3387, 4154, 4151, + 4149, 4148, 4147, 4145, 4144, 4140, 4139, 4138, 4137, 231, + 4136, 4135, 4134, 4133, 4132, 4128, 4127, 4126, 4123, 4122, + 4121, 4119, 4118, 368, 4117, 4116, 4115, 4110, 216, 4108, + 312, 4107, 176, 139, 4101, 4094, 4093, 4092, 4091, 4090, + 4086, 4083, 4082, 4081, 4080, 4079, 4078, 4076, 246, 222, + 69, 4073, 43, 4071, 239, 200, 4070, 218, 4069, 159, + 4066, 149, 4063, 4061, 4060, 4055, 4052, 4050, 4048, 4047, + 4045, 4044, 4042, 4040, 4036, 4035, 4034, 4030, 4029, 4028, + 4026, 4025, 4024, 4023, 4022, 4019, 49, 4018, 247, 4017, + 76, 4015, 185, 4014, 75, 4013, 4010, 86, 4008, 4006, + 98, 137, 258, 2224, 265, 4005, 202, 4002, 4001, 254, + 178, 4000, 3999, 317, 3997, 190, 228, 165, 97, 121, + 3996, 146, 3995, 264, 45, 46, 248, 126, 164, 3992, + 3990, 56, 163, 136, 3989, 215, 100, 3988, 3987, 110, + 3986, 3984, 150, 3983, 249, 184, 3981, 105, 3980, 3978, + 3977, 24, 3976, 3973, 199, 196, 3972, 3968, 102, 3967, + 3966, 68, 124, 3965, 81, 123, 173, 119, 3964, 2779, + 122, 90, 3963, 134, 108, 3961, 144, 3960, 3959, 3957, + 3956, 187, 3955, 3954, 130, 60, 3952, 3951, 3950, 65, + 3949, 84, 3948, 83, 3946, 58, 3945, 3944, 3942, 3941, + 3933, 3932, 3931, 3930, 3928, 3927, 3925, 3924, 53, 3923, + 3922, 3921, 3920, 7, 13, 15, 3919, 28, 3916, 174, + 3915, 3913, 169, 3911, 194, 3908, 3907, 101, 94, 3905, + 93, 167, 3904, 9, 29, 70, 3903, 3901, 3899, 272, + 3897, 3883, 3882, 271, 3881, 3880, 3878, 162, 3876, 3875, + 3874, 495, 3873, 3872, 3871, 3870, 3868, 3867, 61, 3866, + 1, 217, 39, 3865, 131, 143, 3864, 38, 31, 3861, + 44, 127, 203, 133, 104, 3848, 3846, 3845, 293, 205, + 99, 141, 0, 103, 220, 147, 3843, 3840, 3839, 257, + 3836, 242, 235, 240, 256, 262, 219, 3834, 3833, 59, + 3832, 166, 37, 51, 132, 263, 22, 214, 3831, 1400, + 10, 189, 3828, 210, 3824, 8, 17, 154, 160, 3823, + 3822, 33, 269, 3821, 3820, 3815, 125, 3812, 3811, 237, + 89, 3810, 3809, 3808, 3807, 3806, 40, 3805, 186, 16, + 3804, 111, 3803, 270, 3801, 260, 135, 188, 183, 161, + 226, 232, 80, 78, 3800, 1993, 157, 117, 14, 3798, + 224, 3796, 198, 153, 3795, 92, 3794, 238, 273, 209, + 3793, 193, 11, 48, 36, 30, 42, 12, 281, 204, + 3792, 3791, 21, 50, 3789, 52, 3787, 19, 3786, 3785, + 54, 3784, 57, 5, 3782, 3781, 20, 23, 3780, 35, + 213, 175, 129, 96, 63, 3779, 3775, 138, 151, 3774, + 158, 179, 152, 3773, 71, 3772, 3771, 3770, 3769, 299, + 259, 3768, 3767, 3765, 3761, 3760, 3759, 3758, 3757, 212, + 3756, 115, 41, 3755, 3754, 3752, 3751, 82, 156, 3750, + 3748, 3747, 3746, 32, 145, 3745, 18, 3744, 27, 25, + 34, 3740, 109, 3738, 3, 191, 3734, 3719, 4, 3718, + 3715, 2, 3712, 3711, 142, 3710, 95, 26, 170, 112, + 3707, 3706, 91, 211, 148, 3705, 3703, 106, 243, 206, + 3702, 120, 234, 261, 3701, 207, 3700, 3699, 3696, 3695, + 3694, 1320, 3693, 3691, 233, 62, 85, 3688, 221, 118, + 3687, 3685, 88, 168, 116, 114, 55, 87, 3684, 113, + 208, 3683, 197, 3682, 255, 3680, 3679, 107, 3677, 3674, + 3673, 3671, 192, 3670, 3669, 195, 223, 3667, 3666, 267, + 3665, 3662, 3661, 3660, 3659, 3656, 3655, 3654, 3653, 3644, + 268, 307, 3643, } -//line mysql_sql.y:13177 +//line mysql_sql.y:13233 type yySymType struct { union interface{} id int @@ -9054,241 +9022,241 @@ func (st *yySymType) zeroFillOptUnion() bool { } var yyR1 = [...]int{ - 0, 624, 627, 627, 5, 5, 2, 6, 6, 3, + 0, 625, 628, 628, 5, 5, 2, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 128, 128, 362, 362, 363, 363, 130, 358, 358, 357, - 357, 131, 132, 133, 603, 603, 134, 135, 167, 602, - 602, 602, 602, 602, 169, 169, 169, 169, 169, 169, - 169, 479, 129, 129, 129, 129, 226, 226, 227, 227, + 128, 128, 363, 363, 364, 364, 130, 359, 359, 358, + 358, 131, 132, 133, 604, 604, 134, 135, 167, 603, + 603, 603, 603, 603, 169, 169, 169, 169, 169, 169, + 169, 480, 129, 129, 129, 129, 227, 227, 228, 228, 144, 144, 145, 145, 173, 173, 173, 173, 173, 127, - 609, 609, 609, 610, 610, 124, 156, 155, 158, 158, + 610, 610, 610, 611, 611, 124, 156, 155, 158, 158, 157, 157, 154, 154, 150, 153, 153, 152, 152, 151, - 146, 148, 148, 147, 149, 149, 125, 113, 126, 552, - 552, 551, 551, 550, 550, 504, 504, 505, 505, 349, - 349, 349, 549, 549, 549, 548, 548, 547, 547, 546, - 546, 544, 544, 545, 543, 542, 542, 542, 540, 540, - 540, 536, 536, 538, 537, 537, 539, 531, 531, 534, - 534, 532, 532, 532, 532, 535, 530, 530, 530, 529, - 529, 112, 112, 112, 446, 446, 111, 111, 460, 460, - 460, 460, 460, 458, 458, 458, 458, 458, 458, 457, - 457, 456, 456, 461, 461, 459, 459, 459, 459, 459, - 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, - 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, - 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, - 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, - 459, 459, 459, 459, 459, 459, 100, 100, 100, 100, - 100, 100, 100, 107, 105, 105, 105, 106, 615, 615, - 614, 614, 616, 616, 616, 616, 617, 617, 103, 103, - 103, 104, 455, 455, 455, 101, 102, 102, 445, 445, - 450, 450, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 454, 454, 454, 452, 452, - 451, 451, 453, 453, 91, 91, 91, 91, 91, 91, - 95, 96, 97, 97, 97, 97, 94, 93, 444, 444, - 444, 444, 444, 444, 444, 444, 444, 92, 92, 92, + 146, 148, 148, 147, 149, 149, 125, 113, 126, 553, + 553, 552, 552, 551, 551, 505, 505, 506, 506, 350, + 350, 350, 550, 550, 550, 549, 549, 548, 548, 547, + 547, 545, 545, 546, 544, 543, 543, 543, 541, 541, + 541, 537, 537, 539, 538, 538, 540, 532, 532, 535, + 535, 533, 533, 533, 533, 536, 531, 531, 531, 530, + 530, 112, 112, 112, 447, 447, 111, 111, 461, 461, + 461, 461, 461, 459, 459, 459, 459, 459, 459, 458, + 458, 457, 457, 462, 462, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 100, 100, 100, 100, + 100, 100, 100, 107, 105, 105, 105, 106, 616, 616, + 615, 615, 617, 617, 617, 617, 618, 618, 103, 103, + 103, 104, 456, 456, 456, 101, 102, 102, 446, 446, + 451, 451, 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 450, 450, 450, 455, 455, 455, 453, 453, + 452, 452, 454, 454, 91, 91, 91, 91, 91, 91, + 95, 96, 97, 97, 97, 97, 94, 93, 445, 445, + 445, 445, 445, 445, 445, 445, 445, 92, 92, 92, 92, 92, 92, 86, 86, 86, 86, 86, 85, 85, - 87, 87, 442, 442, 441, 108, 108, 109, 612, 612, - 611, 613, 613, 613, 613, 110, 116, 116, 116, 116, + 87, 87, 443, 443, 442, 108, 108, 109, 613, 613, + 612, 614, 614, 614, 614, 110, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 118, 118, 117, 119, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 577, 577, 577, 577, 577, 578, 578, - 376, 377, 628, 379, 375, 375, 375, 573, 573, 574, - 575, 576, 576, 576, 576, 114, 14, 232, 232, 478, - 478, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 13, 84, 89, 89, 90, 312, 312, 313, 307, - 307, 314, 314, 172, 315, 315, 315, 320, 320, 321, - 321, 308, 308, 308, 308, 308, 308, 308, 308, 308, - 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, - 308, 308, 308, 292, 292, 292, 287, 287, 287, 287, - 287, 287, 287, 288, 288, 289, 289, 290, 290, 290, - 290, 291, 291, 368, 368, 316, 316, 316, 318, 318, - 317, 311, 309, 309, 309, 309, 309, 309, 309, 310, - 310, 310, 310, 310, 319, 319, 82, 88, 88, 88, - 88, 590, 590, 83, 83, 83, 601, 601, 508, 508, - 390, 390, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 513, 514, - 386, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 98, 98, 98, 578, 578, 578, 578, 578, 579, 579, + 377, 378, 629, 380, 376, 376, 376, 574, 574, 575, + 576, 577, 577, 577, 577, 114, 14, 233, 233, 479, + 479, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 13, 84, 89, 89, 90, 313, 313, 314, 308, + 308, 315, 315, 172, 316, 316, 316, 321, 321, 322, + 322, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 309, 309, 309, 293, 293, 293, 288, 288, 288, 288, + 288, 288, 288, 289, 289, 290, 290, 291, 291, 291, + 291, 292, 292, 369, 369, 317, 317, 317, 319, 319, + 318, 312, 310, 310, 310, 310, 310, 310, 310, 311, + 311, 311, 311, 311, 320, 320, 82, 88, 88, 88, + 88, 591, 591, 83, 83, 83, 602, 602, 509, 509, + 391, 391, 390, 390, 390, 390, 390, 390, 390, 390, + 390, 390, 390, 390, 390, 390, 390, 390, 514, 515, + 387, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 79, 80, 81, 54, 57, 58, 171, 174, 174, 174, 174, - 53, 53, 53, 431, 431, 52, 629, 629, 361, 361, + 53, 53, 53, 432, 432, 52, 630, 630, 362, 362, 67, 66, 56, 68, 69, 70, 71, 72, 73, 51, - 65, 65, 65, 65, 65, 65, 65, 65, 76, 525, - 525, 631, 631, 631, 74, 75, 507, 507, 507, 64, + 65, 65, 65, 65, 65, 65, 65, 65, 76, 526, + 526, 632, 632, 632, 74, 75, 508, 508, 508, 64, 63, 62, 61, 60, 60, 50, 50, 49, 49, 55, - 162, 59, 163, 163, 383, 383, 383, 385, 385, 381, - 630, 630, 474, 474, 384, 384, 48, 48, 48, 48, - 77, 382, 382, 360, 380, 380, 380, 12, 12, 10, + 162, 59, 163, 163, 384, 384, 384, 386, 386, 382, + 631, 631, 475, 475, 385, 385, 48, 48, 48, 48, + 77, 383, 383, 361, 381, 381, 381, 12, 12, 10, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 26, 27, 29, - 439, 439, 436, 28, 20, 19, 19, 23, 22, 18, + 440, 440, 437, 28, 20, 19, 19, 23, 22, 18, 18, 21, 24, 25, 25, 9, 9, 9, 9, 15, - 15, 16, 200, 200, 259, 259, 584, 584, 580, 580, - 581, 581, 581, 582, 582, 583, 583, 120, 519, 519, - 519, 519, 519, 519, 8, 8, 225, 225, 518, 518, - 518, 518, 518, 518, 443, 443, 443, 562, 562, 562, - 563, 224, 224, 217, 217, 520, 520, 407, 564, 564, - 528, 528, 527, 527, 526, 526, 222, 222, 223, 223, - 203, 203, 139, 139, 533, 533, 533, 533, 541, 541, - 503, 503, 297, 297, 351, 351, 352, 352, 190, 190, - 191, 191, 191, 191, 191, 191, 618, 618, 619, 620, - 621, 621, 622, 622, 622, 623, 623, 623, 623, 623, - 570, 570, 572, 572, 571, 221, 221, 215, 215, 216, - 216, 216, 214, 214, 213, 212, 212, 211, 209, 209, - 209, 210, 210, 210, 231, 231, 193, 193, 193, 192, - 192, 192, 192, 192, 332, 332, 332, 332, 332, 332, - 332, 332, 332, 332, 332, 332, 194, 197, 197, 198, - 198, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 329, 329, 330, 330, 330, 330, 330, 137, 137, - 512, 512, 328, 328, 195, 195, 196, 196, 196, 196, - 327, 327, 326, 208, 208, 207, 206, 206, 206, 201, - 201, 201, 201, 201, 202, 338, 338, 337, 337, 336, - 336, 336, 336, 339, 123, 136, 136, 138, 230, 230, - 219, 218, 335, 334, 334, 334, 334, 229, 229, 228, - 228, 220, 220, 205, 205, 205, 205, 333, 204, 331, - 608, 608, 607, 607, 606, 604, 604, 604, 605, 605, - 605, 605, 554, 554, 554, 554, 554, 369, 369, 369, - 374, 374, 372, 372, 372, 372, 372, 378, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 33, 33, 33, + 15, 16, 200, 200, 260, 260, 585, 585, 581, 581, + 582, 582, 582, 583, 583, 584, 584, 120, 520, 520, + 520, 520, 520, 520, 8, 8, 226, 226, 519, 519, + 519, 519, 519, 519, 444, 444, 444, 563, 563, 563, + 564, 225, 225, 218, 218, 521, 521, 408, 565, 565, + 529, 529, 528, 528, 527, 527, 223, 223, 224, 224, + 203, 203, 139, 139, 534, 534, 534, 534, 542, 542, + 504, 504, 298, 298, 352, 352, 353, 353, 190, 190, + 191, 191, 191, 191, 191, 191, 619, 619, 620, 621, + 622, 622, 623, 623, 623, 624, 624, 624, 624, 624, + 571, 571, 573, 573, 572, 222, 222, 215, 215, 216, + 216, 216, 217, 217, 214, 214, 213, 212, 212, 211, + 209, 209, 209, 210, 210, 210, 232, 232, 193, 193, + 193, 192, 192, 192, 192, 192, 333, 333, 333, 333, + 333, 333, 333, 333, 333, 333, 333, 333, 194, 197, + 197, 198, 198, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 330, 330, 331, 331, 331, 331, 331, + 137, 137, 513, 513, 329, 329, 195, 195, 196, 196, + 196, 196, 328, 328, 327, 208, 208, 207, 206, 206, + 206, 201, 201, 201, 201, 201, 202, 339, 339, 338, + 338, 337, 337, 337, 337, 340, 123, 136, 136, 138, + 231, 231, 220, 219, 336, 335, 335, 335, 335, 230, + 230, 229, 229, 221, 221, 205, 205, 205, 205, 334, + 204, 332, 609, 609, 608, 608, 607, 605, 605, 605, + 606, 606, 606, 606, 555, 555, 555, 555, 555, 370, + 370, 370, 375, 375, 373, 373, 373, 373, 373, 379, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 39, 242, 243, 40, 244, 244, 245, 245, 246, 246, - 247, 248, 249, 249, 249, 249, 423, 423, 38, 233, - 233, 234, 234, 235, 235, 236, 237, 237, 237, 241, - 238, 239, 239, 626, 626, 625, 37, 37, 30, 177, - 177, 178, 178, 178, 180, 180, 293, 293, 293, 179, - 179, 181, 181, 181, 585, 587, 587, 589, 588, 588, - 588, 591, 591, 591, 591, 591, 592, 592, 592, 592, - 593, 593, 31, 159, 159, 184, 184, 164, 596, 596, - 596, 595, 595, 597, 597, 598, 598, 355, 355, 356, - 356, 175, 176, 176, 166, 161, 183, 183, 183, 183, - 183, 185, 185, 261, 261, 160, 165, 168, 170, 586, - 594, 594, 594, 440, 440, 437, 438, 438, 435, 434, - 434, 434, 600, 600, 599, 599, 599, 370, 370, 32, - 430, 430, 432, 433, 433, 433, 424, 424, 424, 424, - 36, 428, 428, 429, 429, 429, 429, 429, 429, 429, - 429, 429, 429, 429, 425, 425, 427, 427, 422, 422, - 422, 422, 422, 422, 422, 422, 35, 35, 182, 182, - 421, 421, 418, 418, 240, 240, 416, 416, 417, 417, - 415, 415, 415, 419, 419, 43, 78, 44, 45, 46, - 42, 420, 420, 186, 186, 186, 186, 186, 186, 189, - 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 141, 140, 140, 140, 140, 140, 143, 143, 354, - 354, 353, 353, 142, 294, 294, 41, 272, 272, 495, - 495, 490, 490, 490, 490, 490, 510, 510, 510, 491, - 491, 491, 492, 492, 492, 494, 494, 494, 493, 493, - 493, 493, 493, 509, 509, 511, 511, 511, 462, 462, - 463, 463, 463, 466, 466, 482, 482, 483, 483, 481, - 481, 488, 488, 487, 487, 486, 486, 485, 485, 484, - 484, 484, 484, 477, 477, 476, 476, 464, 464, 464, - 464, 464, 465, 465, 465, 475, 475, 480, 480, 325, - 325, 324, 324, 280, 280, 281, 281, 323, 323, 278, - 278, 279, 279, 279, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, 322, 560, - 560, 561, 283, 283, 295, 295, 295, 295, 295, 295, - 282, 282, 284, 284, 260, 260, 258, 258, 250, 250, - 250, 250, 250, 250, 251, 251, 252, 252, 253, 253, - 253, 257, 257, 256, 256, 256, 256, 254, 254, 255, - 255, 255, 255, 255, 255, 448, 448, 557, 557, 558, - 558, 553, 553, 553, 556, 556, 556, 556, 556, 556, - 556, 556, 559, 559, 559, 555, 555, 262, 348, 348, - 348, 371, 371, 371, 371, 373, 347, 347, 347, 277, - 277, 276, 276, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 447, 447, 387, 387, 388, - 388, 306, 305, 305, 305, 305, 305, 303, 304, 302, - 302, 302, 302, 302, 299, 299, 298, 298, 298, 300, - 300, 300, 300, 300, 426, 426, 296, 296, 286, 286, - 286, 285, 285, 285, 489, 394, 394, 394, 394, 394, - 394, 394, 394, 394, 394, 394, 394, 394, 396, 396, - 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, - 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, - 396, 396, 396, 396, 396, 301, 345, 345, 345, 346, - 346, 346, 346, 346, 346, 346, 346, 397, 397, 403, - 403, 569, 569, 568, 263, 263, 263, 264, 264, 264, - 264, 264, 264, 264, 264, 264, 273, 273, 273, 471, - 471, 471, 471, 472, 472, 472, 472, 473, 473, 473, - 469, 469, 470, 470, 408, 409, 409, 516, 516, 517, - 517, 467, 467, 468, 344, 344, 344, 344, 344, 344, - 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, - 344, 344, 344, 344, 344, 344, 344, 524, 524, 524, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 579, 579, 579, 565, - 565, 565, 566, 566, 566, 566, 566, 566, 566, 566, - 566, 566, 566, 566, 567, 567, 567, 567, 567, 567, - 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, - 567, 343, 343, 343, 342, 342, 342, 342, 342, 342, - 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, - 342, 342, 410, 410, 411, 411, 521, 521, 521, 521, - 521, 521, 522, 522, 523, 523, 523, 523, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 395, 340, - 340, 340, 412, 404, 404, 405, 405, 406, 406, 398, - 398, 398, 398, 398, 398, 399, 399, 401, 401, 401, - 401, 401, 401, 401, 401, 401, 401, 401, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 400, - 400, 402, 402, 414, 414, 414, 413, 413, 413, 413, - 413, 413, 413, 275, 275, 275, 275, 392, 392, 392, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 391, 391, 265, 265, 265, 265, 269, 269, 271, 271, - 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 270, 270, 270, 270, 270, 268, 268, 268, - 268, 268, 266, 266, 266, 266, 266, 266, 266, 266, - 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - 266, 121, 122, 122, 267, 350, 350, 496, 496, 499, - 499, 497, 497, 498, 500, 500, 500, 501, 501, 501, - 502, 502, 502, 506, 506, 359, 359, 359, 367, 367, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, + 33, 33, 39, 243, 244, 40, 245, 245, 246, 246, + 247, 247, 248, 249, 250, 250, 250, 250, 424, 424, + 38, 234, 234, 235, 235, 236, 236, 237, 238, 238, + 238, 242, 239, 240, 240, 627, 627, 626, 37, 37, + 30, 177, 177, 178, 178, 178, 180, 180, 294, 294, + 294, 179, 179, 181, 181, 181, 586, 588, 588, 590, + 589, 589, 589, 592, 592, 592, 592, 592, 593, 593, + 593, 593, 594, 594, 31, 159, 159, 184, 184, 164, + 597, 597, 597, 596, 596, 598, 598, 599, 599, 356, + 356, 357, 357, 175, 176, 176, 166, 161, 183, 183, + 183, 183, 183, 185, 185, 262, 262, 160, 165, 168, + 170, 587, 595, 595, 595, 441, 441, 438, 439, 439, + 436, 435, 435, 435, 601, 601, 600, 600, 600, 371, + 371, 32, 431, 431, 433, 434, 434, 434, 425, 425, + 425, 425, 36, 429, 429, 430, 430, 430, 430, 430, + 430, 430, 430, 430, 430, 430, 426, 426, 428, 428, + 423, 423, 423, 423, 423, 423, 423, 423, 35, 35, + 182, 182, 422, 422, 419, 419, 241, 241, 417, 417, + 418, 418, 416, 416, 416, 420, 420, 43, 78, 44, + 45, 46, 42, 421, 421, 186, 186, 186, 186, 186, + 186, 189, 189, 189, 189, 189, 188, 188, 188, 188, + 187, 187, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 141, 140, 140, 140, 140, 140, 143, + 143, 355, 355, 354, 354, 142, 295, 295, 41, 273, + 273, 496, 496, 491, 491, 491, 491, 491, 511, 511, + 511, 492, 492, 492, 493, 493, 493, 495, 495, 495, + 494, 494, 494, 494, 494, 510, 510, 512, 512, 512, + 463, 463, 464, 464, 464, 467, 467, 483, 483, 484, + 484, 482, 482, 489, 489, 488, 488, 487, 487, 486, + 486, 485, 485, 485, 485, 478, 478, 477, 477, 465, + 465, 465, 465, 465, 466, 466, 466, 476, 476, 481, + 481, 326, 326, 325, 325, 281, 281, 282, 282, 324, + 324, 279, 279, 280, 280, 280, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 561, 561, 562, 284, 284, 296, 296, 296, 296, + 296, 296, 283, 283, 285, 285, 261, 261, 259, 259, + 251, 251, 251, 251, 251, 251, 252, 252, 253, 253, + 254, 254, 254, 258, 258, 257, 257, 257, 257, 255, + 255, 256, 256, 256, 256, 256, 256, 449, 449, 558, + 558, 559, 559, 554, 554, 554, 557, 557, 557, 557, + 557, 557, 557, 557, 560, 560, 560, 556, 556, 263, + 349, 349, 349, 372, 372, 372, 372, 374, 348, 348, + 348, 278, 278, 277, 277, 275, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 275, 448, 448, 388, + 388, 389, 389, 307, 306, 306, 306, 306, 306, 304, + 305, 303, 303, 303, 303, 303, 300, 300, 299, 299, + 299, 301, 301, 301, 301, 301, 427, 427, 297, 297, + 287, 287, 287, 286, 286, 286, 490, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 302, 346, 346, + 346, 347, 347, 347, 347, 347, 347, 347, 347, 398, + 398, 404, 404, 570, 570, 569, 264, 264, 264, 265, + 265, 265, 265, 265, 265, 265, 265, 265, 274, 274, + 274, 472, 472, 472, 472, 473, 473, 473, 473, 474, + 474, 474, 470, 470, 471, 471, 409, 410, 410, 517, + 517, 518, 518, 468, 468, 469, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, 345, 525, + 525, 525, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 580, 580, + 580, 566, 566, 566, 567, 567, 567, 567, 567, 567, + 567, 567, 567, 567, 567, 567, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 344, 344, 344, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 411, 411, 412, 412, 522, 522, + 522, 522, 522, 522, 523, 523, 524, 524, 524, 524, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 396, 341, 341, 341, 413, 405, 405, 406, 406, 407, + 407, 399, 399, 399, 399, 399, 399, 400, 400, 402, + 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 401, 401, 403, 403, 415, 415, 415, 414, 414, + 414, 414, 414, 414, 414, 276, 276, 276, 276, 393, + 393, 393, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 266, 266, 266, 266, 270, 270, + 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, + 272, 272, 272, 272, 271, 271, 271, 271, 271, 269, + 269, 269, 269, 269, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 121, 122, 122, 268, 351, 351, 497, + 497, 500, 500, 498, 498, 499, 501, 501, 501, 502, + 502, 502, 503, 503, 503, 507, 507, 360, 360, 360, + 368, 368, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 367, 367, 367, 366, 366, 366, + 366, 366, 366, 366, 366, 366, 366, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, } var yyR2 = [...]int{ @@ -9376,115 +9344,115 @@ var yyR2 = [...]int{ 0, 2, 0, 2, 0, 4, 1, 3, 1, 1, 6, 4, 5, 7, 4, 5, 0, 1, 3, 8, 0, 6, 0, 4, 6, 1, 1, 1, 1, 1, - 2, 3, 1, 3, 6, 0, 3, 0, 1, 2, - 4, 4, 0, 1, 3, 1, 3, 3, 0, 1, - 1, 0, 2, 2, 0, 2, 3, 3, 3, 1, - 3, 3, 3, 3, 1, 2, 2, 1, 2, 2, - 1, 2, 2, 1, 2, 2, 7, 0, 1, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 2, 0, 4, 7, 6, 6, 3, 5, - 0, 2, 0, 2, 1, 3, 1, 2, 3, 5, - 0, 1, 2, 1, 3, 1, 1, 1, 1, 4, - 4, 4, 3, 4, 3, 2, 2, 2, 2, 2, - 3, 2, 3, 2, 4, 1, 3, 4, 0, 2, - 1, 3, 1, 1, 2, 2, 3, 0, 1, 2, - 4, 1, 3, 1, 3, 2, 3, 1, 4, 3, - 0, 1, 1, 2, 5, 2, 2, 2, 0, 2, - 3, 3, 0, 1, 3, 1, 3, 0, 1, 2, - 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, + 2, 3, 1, 3, 6, 0, 3, 0, 1, 3, + 5, 5, 0, 5, 0, 1, 3, 1, 3, 3, + 0, 1, 1, 0, 2, 2, 0, 2, 3, 3, + 3, 1, 3, 3, 3, 3, 1, 2, 2, 1, + 2, 2, 1, 2, 2, 1, 2, 2, 7, 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 0, 4, 7, 6, 6, + 3, 5, 0, 2, 0, 2, 1, 3, 1, 2, + 3, 5, 0, 1, 2, 1, 3, 1, 1, 1, + 1, 4, 4, 4, 3, 4, 3, 2, 2, 2, + 2, 2, 3, 2, 3, 2, 4, 1, 3, 4, + 0, 2, 1, 3, 1, 1, 2, 2, 3, 0, + 1, 2, 4, 1, 3, 1, 3, 2, 3, 1, + 4, 3, 0, 1, 1, 2, 5, 2, 2, 2, + 0, 2, 3, 3, 0, 1, 3, 1, 3, 0, + 1, 2, 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 7, 1, 1, 9, 1, 3, 0, 1, 1, 3, - 1, 3, 0, 1, 1, 1, 0, 2, 14, 1, - 3, 0, 1, 1, 3, 1, 1, 2, 4, 1, - 1, 1, 1, 0, 1, 2, 9, 9, 7, 1, - 2, 3, 3, 3, 0, 4, 1, 1, 1, 1, - 1, 0, 1, 1, 1, 1, 1, 4, 1, 1, - 1, 3, 3, 4, 3, 3, 0, 1, 1, 1, - 0, 2, 7, 8, 10, 2, 2, 8, 0, 3, - 3, 0, 3, 0, 3, 0, 5, 1, 3, 0, - 3, 3, 0, 2, 9, 8, 0, 2, 2, 3, - 3, 0, 2, 0, 2, 4, 4, 4, 5, 1, - 0, 2, 2, 1, 3, 2, 1, 3, 2, 1, - 3, 2, 0, 1, 3, 4, 3, 1, 1, 4, - 1, 3, 1, 1, 1, 1, 0, 1, 1, 1, - 11, 0, 2, 3, 3, 2, 2, 3, 1, 1, - 3, 3, 3, 1, 1, 3, 3, 4, 0, 2, - 2, 2, 2, 2, 2, 2, 6, 8, 0, 4, - 1, 1, 0, 3, 0, 1, 0, 1, 1, 2, - 4, 4, 4, 0, 1, 8, 2, 4, 4, 4, - 9, 0, 2, 8, 9, 5, 5, 7, 7, 0, - 3, 3, 3, 2, 0, 3, 3, 3, 0, 3, - 11, 9, 11, 8, 6, 9, 7, 10, 7, 6, - 8, 2, 2, 9, 4, 5, 3, 0, 4, 1, - 3, 0, 3, 6, 0, 2, 10, 0, 2, 0, - 2, 0, 3, 2, 4, 3, 0, 2, 1, 0, - 2, 3, 0, 2, 3, 0, 2, 1, 0, 3, - 2, 4, 3, 0, 1, 0, 1, 1, 0, 6, - 0, 3, 5, 0, 4, 0, 3, 1, 3, 4, - 5, 0, 3, 1, 3, 2, 3, 1, 2, 0, - 4, 6, 5, 0, 2, 0, 2, 4, 5, 4, - 5, 1, 5, 6, 5, 0, 3, 0, 1, 1, - 3, 3, 3, 0, 4, 1, 3, 3, 3, 0, - 1, 1, 3, 2, 3, 3, 3, 4, 4, 3, - 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 1, 5, 4, 1, - 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 2, 4, 0, 5, - 5, 5, 5, 6, 0, 1, 1, 3, 1, 1, - 1, 1, 1, 7, 9, 7, 9, 2, 1, 7, - 9, 7, 9, 8, 5, 0, 1, 0, 1, 1, - 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 3, 1, 3, - 5, 1, 1, 1, 1, 1, 1, 3, 5, 0, - 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, - 2, 3, 3, 2, 2, 1, 5, 6, 4, 1, - 1, 1, 5, 4, 1, 1, 2, 0, 1, 1, - 2, 5, 0, 1, 1, 2, 2, 3, 3, 1, - 1, 2, 2, 2, 0, 1, 2, 2, 2, 0, - 4, 7, 3, 3, 0, 3, 0, 3, 1, 1, - 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, - 1, 3, 5, 2, 2, 2, 2, 4, 1, 1, - 2, 5, 6, 8, 6, 6, 6, 1, 1, 1, - 1, 1, 1, 3, 9, 1, 4, 4, 4, 7, - 9, 7, 7, 7, 9, 7, 7, 0, 2, 0, - 1, 1, 2, 4, 1, 2, 2, 1, 2, 2, - 1, 2, 2, 2, 2, 2, 0, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 2, 5, 0, 1, 3, 0, 1, 0, 2, 0, - 2, 0, 1, 6, 8, 8, 6, 6, 5, 5, - 5, 6, 6, 6, 6, 5, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, - 4, 4, 6, 8, 6, 4, 5, 4, 4, 4, - 3, 4, 6, 6, 7, 4, 1, 1, 1, 1, + 1, 1, 7, 1, 1, 9, 1, 3, 0, 1, + 1, 3, 1, 3, 0, 1, 1, 1, 0, 2, + 14, 1, 3, 0, 1, 1, 3, 1, 1, 2, + 4, 1, 1, 1, 1, 0, 1, 2, 9, 9, + 7, 1, 2, 3, 3, 3, 0, 4, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 4, + 1, 1, 1, 3, 3, 4, 3, 3, 0, 1, + 1, 1, 0, 2, 7, 8, 10, 2, 2, 8, + 0, 3, 3, 0, 3, 0, 3, 0, 5, 1, + 3, 0, 3, 3, 0, 2, 9, 8, 0, 2, + 2, 3, 3, 0, 2, 0, 2, 4, 4, 4, + 5, 1, 0, 2, 2, 1, 3, 2, 1, 3, + 2, 1, 3, 2, 0, 1, 3, 4, 3, 1, + 1, 4, 1, 3, 1, 1, 1, 1, 0, 1, + 1, 1, 11, 0, 2, 3, 3, 2, 2, 3, + 1, 1, 3, 3, 3, 1, 1, 3, 3, 4, + 0, 2, 2, 2, 2, 2, 2, 2, 6, 8, + 0, 4, 1, 1, 0, 3, 0, 1, 0, 1, + 1, 2, 4, 4, 4, 0, 1, 8, 2, 4, + 4, 4, 9, 0, 2, 8, 9, 5, 5, 7, + 7, 0, 3, 3, 3, 2, 0, 3, 3, 3, + 0, 3, 11, 9, 11, 8, 6, 9, 7, 10, + 7, 6, 8, 2, 2, 9, 4, 5, 3, 0, + 4, 1, 3, 0, 3, 6, 0, 2, 10, 0, + 2, 0, 2, 0, 3, 2, 4, 3, 0, 2, + 1, 0, 2, 3, 0, 2, 3, 0, 2, 1, + 0, 3, 2, 4, 3, 0, 1, 0, 1, 1, + 0, 6, 0, 3, 5, 0, 4, 0, 3, 1, + 3, 4, 5, 0, 3, 1, 3, 2, 3, 1, + 2, 0, 4, 6, 5, 0, 2, 0, 2, 4, + 5, 4, 5, 1, 5, 6, 5, 0, 3, 0, + 1, 1, 3, 3, 3, 0, 4, 1, 3, 3, + 3, 0, 1, 1, 3, 2, 3, 3, 3, 4, + 4, 3, 3, 3, 3, 4, 4, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 1, 5, + 4, 1, 3, 3, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 2, 4, + 0, 5, 5, 5, 5, 6, 0, 1, 1, 3, + 1, 1, 1, 1, 1, 7, 9, 7, 9, 2, + 1, 7, 9, 7, 9, 8, 5, 0, 1, 0, + 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 3, + 1, 3, 5, 1, 1, 1, 1, 1, 1, 3, + 5, 0, 1, 1, 2, 1, 2, 2, 1, 1, + 2, 2, 2, 3, 3, 2, 2, 1, 5, 6, + 4, 1, 1, 1, 5, 4, 1, 1, 2, 0, + 1, 1, 2, 5, 0, 1, 1, 2, 2, 3, + 3, 1, 1, 2, 2, 2, 0, 1, 2, 2, + 2, 0, 4, 7, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 1, 1, 1, 3, 5, 2, 2, 2, 2, 4, + 1, 1, 2, 5, 6, 8, 6, 6, 6, 1, + 1, 1, 1, 1, 1, 3, 9, 1, 4, 4, + 4, 7, 9, 7, 7, 7, 9, 7, 7, 0, + 2, 0, 1, 1, 2, 4, 1, 2, 2, 1, + 2, 2, 1, 2, 2, 2, 2, 2, 0, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 2, 5, 0, 1, 3, 0, 1, 0, + 2, 0, 2, 0, 1, 6, 8, 8, 6, 6, + 5, 5, 5, 6, 6, 6, 6, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, + 1, 1, 4, 4, 6, 8, 6, 4, 5, 4, + 4, 4, 3, 4, 6, 6, 7, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 8, 4, 2, 3, 2, 4, 2, - 2, 4, 6, 2, 2, 4, 6, 4, 2, 4, - 4, 4, 0, 1, 2, 3, 1, 1, 1, 1, - 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 8, 4, 2, 3, 2, + 4, 2, 2, 4, 6, 2, 2, 4, 6, 4, + 2, 4, 4, 4, 0, 1, 2, 3, 1, 1, + 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, - 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, - 3, 3, 3, 2, 1, 1, 1, 3, 4, 3, - 4, 3, 4, 3, 4, 3, 4, 1, 3, 4, - 4, 5, 4, 5, 3, 4, 5, 6, 1, 0, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, - 1, 2, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, - 1, 2, 3, 5, 1, 1, 3, 0, 1, 0, - 3, 0, 3, 3, 0, 3, 5, 0, 3, 5, - 0, 1, 1, 0, 1, 1, 2, 2, 0, 1, + 3, 0, 1, 1, 3, 0, 1, 1, 3, 1, + 3, 3, 3, 3, 3, 2, 1, 1, 1, 3, + 4, 3, 4, 3, 4, 3, 4, 3, 4, 1, + 3, 4, 4, 5, 4, 5, 3, 4, 5, 6, + 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 2, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 4, 4, 1, 2, 3, 5, 1, 1, 3, 0, + 1, 0, 3, 0, 3, 3, 0, 3, 5, 0, + 3, 5, 0, 1, 1, 0, 1, 1, 2, 2, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -9526,18 +9494,18 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, } var yyChk = [...]int{ - -1000, -624, -627, -2, -5, 648, -1, -4, -122, -91, + -1000, -625, -628, -2, -5, 648, -1, -4, -122, -91, -7, -14, -124, -125, -8, -120, -9, -10, -12, -98, -115, -117, -119, -118, -47, -11, -114, -85, -86, -100, -108, -111, -112, -113, -126, -121, -123, -190, -127, -128, -129, -173, -132, -134, -135, -186, 638, -92, -93, -94, -95, -96, -97, -33, -32, -31, -30, -159, -164, -167, - -169, -130, 571, 644, 474, 14, 523, -15, -16, -570, - -17, 267, -375, -376, -377, -379, -628, -48, -49, -50, + -169, -130, 571, 644, 474, 14, 523, -15, -16, -571, + -17, 267, -376, -377, -378, -380, -629, -48, -49, -50, -60, -61, -62, -63, -64, -74, -75, -76, -51, -52, -53, -56, -54, -67, -66, -68, -69, -70, -71, -72, -73, -55, -59, -162, -163, -77, -57, -78, -58, -171, @@ -9552,8 +9520,8 @@ var yyChk = [...]int{ 261, 39, 328, 329, 330, 402, 260, 238, 240, 15, 32, 43, 377, -192, 86, 559, 239, -194, 13, 673, -6, -3, -2, -146, -150, -154, -157, -158, -155, -156, - -4, -122, 121, 252, 639, -371, 394, 640, 642, 641, - 89, 97, -364, -366, 474, 267, 398, 404, 637, 668, + -4, -122, 121, 252, 639, -372, 394, 640, 642, 641, + 89, 97, -365, -367, 474, 267, 398, 404, 637, 668, 671, 558, 561, 285, 573, 574, 575, 576, 577, 578, 579, 580, 582, 583, 584, 585, 586, 587, 588, 598, 599, 589, 590, 591, 592, 593, 594, 595, 596, 600, @@ -9594,362 +9562,363 @@ var yyChk = [...]int{ 330, 426, 427, 428, 438, 431, 432, 433, 434, 435, 436, 437, 476, 477, 647, 495, 497, 498, 496, 244, 672, 381, 382, 247, 649, 650, 99, 651, 653, 652, - 29, 654, 662, 659, 660, 661, 572, 232, 657, -453, - -451, -371, 559, 285, 637, 404, 558, 561, 398, 377, - 668, 671, 402, 267, 328, 329, 330, 474, 375, -244, - -371, 672, -203, 251, 40, -258, -371, -203, -87, -16, - -15, -192, -193, -258, 246, -380, 24, 456, -99, 457, - 241, 242, 86, 78, -371, -9, -113, -8, -120, -85, - -190, 461, -378, -371, 328, 328, -378, 246, -373, 277, - 437, -371, -508, 252, -457, -430, 278, -456, -432, -459, - -433, 33, 237, 239, 238, 571, 274, 16, 402, 248, + 29, 654, 662, 659, 660, 661, 572, 232, 657, -454, + -452, -372, 559, 285, 637, 404, 558, 561, 398, 377, + 668, 671, 402, 267, 328, 329, 330, 474, 375, -245, + -372, 672, -203, 251, 40, -259, -372, -203, -87, -16, + -15, -192, -193, -259, 246, -381, 24, 456, -99, 457, + 241, 242, 86, 78, -372, -9, -113, -8, -120, -85, + -190, 461, -379, -372, 328, 328, -379, 246, -374, 277, + 437, -372, -509, 252, -458, -431, 278, -457, -433, -460, + -434, 33, 237, 239, 238, 571, 274, 16, 402, 248, 14, 13, 403, 260, 26, 27, 29, 15, 404, 406, 30, 407, 410, 411, 412, 43, 415, 416, 267, 89, - 97, 92, 285, -243, -371, -406, -398, 118, -401, -393, - -394, -396, -349, -544, -391, 86, 145, 146, 153, 119, - 674, -395, -489, 37, 121, 577, 581, 617, 524, -341, - -342, -343, -344, -345, -346, 562, -371, -545, -543, 92, + 97, 92, 285, -244, -372, -407, -399, 118, -402, -394, + -395, -397, -350, -545, -392, 86, 145, 146, 153, 119, + 674, -396, -490, 37, 121, 577, 581, 617, 524, -342, + -343, -344, -345, -346, -347, 562, -372, -546, -544, 92, 102, 104, 108, 109, 107, 105, 157, 190, 106, 93, - 158, -193, 89, -565, 587, -365, 610, 623, 624, 625, - 626, 609, 62, -515, -523, 245, -521, 156, 195, 263, + 158, -193, 89, -566, 587, -366, 610, 623, 624, 625, + 626, 609, 62, -516, -524, 245, -522, 156, 195, 263, 191, 14, 151, 449, 192, 618, 619, 620, 584, 606, 526, 588, 598, 613, 579, 580, 582, 574, 575, 576, - 578, 589, 591, 605, -524, 601, 611, 612, 597, 621, + 578, 589, 591, 605, -525, 601, 611, 612, 597, 621, 622, 659, 614, 615, 616, 653, 91, 90, 604, 603, 590, 585, 586, 592, 573, 583, 593, 594, 602, 607, 608, 386, 111, 387, 388, 516, 378, 81, 389, 252, 456, 71, 390, 391, 392, 393, 394, 523, 395, 72, 396, 385, 267, 439, 397, 194, 212, 528, 527, 529, 520, 517, 515, 518, 519, 521, 522, 595, 596, 600, - -136, -138, 628, -618, -332, -619, 6, 7, 8, 9, - -620, 158, -609, 458, 567, 92, 516, 246, 321, 375, - 17, 658, 557, 658, 557, 335, 168, 165, -444, 168, - 117, 174, 173, 250, 168, -444, -371, 171, 658, 170, - 655, 331, -420, -177, 375, 439, 348, 98, 277, -424, - -421, 555, -509, 325, 321, 297, 247, 114, -178, 257, - 256, 112, 516, 245, 413, 316, 57, 59, -580, -581, - 234, 235, 236, -572, 549, -571, -371, 658, 663, 388, + -136, -138, 628, -619, -333, -620, 6, 7, 8, 9, + -621, 158, -610, 458, 567, 92, 516, 246, 321, 375, + 17, 658, 557, 658, 557, 335, 168, 165, -445, 168, + 117, 174, 173, 250, 168, -445, -372, 171, 658, 170, + 655, 331, -421, -177, 375, 439, 348, 98, 277, -425, + -422, 555, -510, 325, 321, 297, 247, 114, -178, 257, + 256, 112, 516, 245, 413, 316, 57, 59, -581, -582, + 234, 235, 236, -573, 549, -572, -372, 658, 663, 388, 100, 101, 655, 656, 28, 246, 399, 273, 494, 492, - 493, 495, 496, 497, 498, -65, -525, -507, 489, 488, - -384, 481, 487, 479, 491, 482, 376, 350, 571, 349, - 237, 649, 556, 550, -359, 423, 459, 513, 514, 400, + 493, 495, 496, 497, 498, -65, -526, -508, 489, 488, + -385, 481, 487, 479, 491, 482, 376, 350, 571, 349, + 237, 649, 556, 550, -360, 423, 459, 513, 514, 400, 460, 500, 502, 483, 111, 198, 195, 247, 249, 246, - 655, 375, 516, 439, 98, 348, 246, -580, 663, 165, - 500, 502, 458, 277, 437, 42, -450, 449, -449, -451, - 501, 512, 90, 91, 499, -359, 111, 480, 480, -618, - -332, -191, -193, -123, -570, 557, 658, 247, 375, 439, + 655, 375, 516, 439, 98, 348, 246, -581, 663, 165, + 500, 502, 458, 277, 437, 42, -451, 449, -450, -452, + 501, 512, 90, 91, 499, -360, 111, 480, 480, -619, + -333, -191, -193, -123, -571, 557, 658, 247, 375, 439, 277, 248, 246, 552, 555, 249, 516, 245, 328, 399, 273, 348, 98, 170, 655, -197, -198, -199, 230, 231, 232, 70, 235, 233, 67, 33, 34, 35, -1, 125, - 673, -398, -398, -6, 676, -6, -398, -371, -371, 160, - -265, -269, -266, -268, -267, -271, -270, 195, 196, 156, + 673, -399, -399, -6, 676, -6, -399, -372, -372, 160, + -266, -270, -267, -269, -268, -272, -271, 195, 196, 156, 199, 205, 201, 202, 203, 204, 206, 207, 208, 209, 210, 213, 214, 211, 32, 212, 263, 191, 192, 193, 194, 215, 177, 197, 564, 223, 178, 224, 179, 225, 180, 226, 181, 182, 227, 183, 186, 187, 188, 189, - 185, 159, -232, 92, 33, 86, 159, 92, -222, 269, - -203, -258, -250, 159, 674, -222, -618, -213, -214, 11, - -258, -347, -371, 458, 128, -99, 78, -99, 457, 78, - -99, 457, 241, -573, -574, -575, -577, 241, 457, 456, - 242, 312, -118, 159, 285, 17, -378, -378, 84, -258, - -432, 277, -457, -430, 37, 83, 160, 250, 160, 83, + 185, 159, -233, 92, 33, 86, 159, 92, -223, 269, + -203, -259, -251, 159, 674, -223, -619, -213, -214, 11, + -259, -348, -372, 458, 128, -99, 78, -99, 457, 78, + -99, 457, 241, -574, -575, -576, -578, 241, 457, 456, + 242, 312, -118, 159, 285, 17, -379, -379, 84, -259, + -433, 277, -458, -431, 37, 83, 160, 250, 160, 83, 86, 400, 375, 439, 401, 516, 246, 413, 249, 277, 414, 375, 439, 246, 249, 516, 277, 375, 246, 249, 439, 277, 414, 375, 479, 480, 249, 28, 405, 408, - 409, 480, -529, 512, 160, 117, 114, 115, 116, -398, - 135, -413, 128, 129, 130, 131, 132, 133, 134, 142, + 409, 480, -530, 512, 160, 117, 114, 115, 116, -399, + 135, -414, 128, 129, 130, 131, 132, 133, 134, 142, 141, 152, 145, 146, 147, 148, 149, 150, 151, 143, - 144, 138, 118, 136, 140, 137, 120, 155, -193, -398, - -406, 62, -396, -396, -396, -396, -371, -489, -403, -398, - 86, 86, 86, 86, 86, 159, 105, 92, -398, 86, + 144, 138, 118, 136, 140, 137, 120, 155, -193, -399, + -407, 62, -397, -397, -397, -397, -372, -490, -404, -399, + 86, 86, 86, 86, 86, 159, 105, 92, -399, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, -522, 86, 86, -410, -411, 86, 86, -391, -347, + 86, -523, 86, 86, -411, -412, 86, 86, -392, -348, 86, 92, 92, 86, 86, 86, 92, 86, 86, 86, - -411, -411, 86, 86, 86, 86, 86, 86, 86, 86, + -412, -412, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, -214, 160, -213, 86, -213, -214, -194, -193, 33, 34, 33, 34, - 33, 34, 33, 34, -621, 646, 86, 102, 669, 228, - -226, -371, -227, -371, -144, 17, 674, -371, 655, -603, + 33, 34, 33, 34, -622, 646, 86, 102, 669, 228, + -227, -372, -228, -372, -144, 17, 674, -372, 655, -604, 33, 560, 560, 560, 560, 237, 16, 339, 55, 505, - 566, 172, 173, 174, -371, 171, 250, -371, -418, 252, - -418, -418, -242, -371, 273, 399, 249, 552, 249, -178, - -418, -418, -418, -418, -418, 248, -418, 24, 246, 246, - 246, 246, -418, 523, 128, 128, 60, -582, 176, 160, - -572, -221, 86, -603, 664, 665, 666, -383, 136, 140, - -383, -328, 18, -328, 24, 24, 275, 275, 275, -383, - 315, -629, -630, 17, 138, -381, -630, -381, -381, -383, - -631, 248, 490, 44, 276, 275, -215, -216, 22, -215, - 484, 480, -474, 485, 486, -385, -630, -384, -383, -383, - -384, -383, -383, -383, 33, 246, 249, 516, 348, 650, - -629, -629, 32, 32, -508, -508, -258, -508, -508, 550, - -360, -371, -508, -508, -508, -312, -313, -258, -583, 251, - 666, -615, -614, 503, -617, 505, 165, -451, 165, -451, - 89, -432, 277, 277, 160, 128, 24, -452, 128, 139, - -451, -451, -452, -452, -282, 42, -370, 156, -371, 92, - -282, 42, -612, -611, -258, -214, -194, -193, 87, 87, - 87, 560, -603, -508, -508, -508, -508, -508, -509, -508, - -508, -508, -508, -508, -378, -233, -371, -244, 252, -508, - -508, -508, -508, -195, -196, 147, -398, -371, -199, -3, + 566, 172, 173, 174, -372, 171, 250, -372, -419, 252, + -419, -419, -243, -372, 273, 399, 249, 552, 249, -178, + -419, -419, -419, -419, -419, 248, -419, 24, 246, 246, + 246, 246, -419, 523, 128, 128, 60, -583, 176, 160, + -573, -222, 86, -604, 664, 665, 666, -384, 136, 140, + -384, -329, 18, -329, 24, 24, 275, 275, 275, -384, + 315, -630, -631, 17, 138, -382, -631, -382, -382, -384, + -632, 248, 490, 44, 276, 275, -215, -216, 22, -215, + 484, 480, -475, 485, 486, -386, -631, -385, -384, -384, + -385, -384, -384, -384, 33, 246, 249, 516, 348, 650, + -630, -630, 32, 32, -509, -509, -259, -509, -509, 550, + -361, -372, -509, -509, -509, -313, -314, -259, -584, 251, + 666, -616, -615, 503, -618, 505, 165, -452, 165, -452, + 89, -433, 277, 277, 160, 128, 24, -453, 128, 139, + -452, -452, -453, -453, -283, 42, -371, 156, -372, 92, + -283, 42, -613, -612, -259, -214, -194, -193, 87, 87, + 87, 560, -604, -509, -509, -509, -509, -509, -510, -509, + -509, -509, -509, -509, -379, -234, -372, -245, 252, -509, + -509, -509, -509, -195, -196, 147, -399, -372, -199, -3, -148, -147, 122, 123, 125, 640, 394, 639, 643, 637, - -451, 42, -502, 421, 420, -496, -498, 86, -497, 86, - -497, -497, -497, -497, -497, 86, 86, -499, 86, -499, - -499, -496, -500, 86, -500, -501, 86, -501, -500, -371, - -478, 566, -404, -406, -371, 40, -518, 62, -190, 86, - 32, 86, -222, -371, 192, 170, 654, 36, -519, 62, + -452, 42, -503, 421, 420, -497, -499, 86, -498, 86, + -498, -498, -498, -498, -498, 86, 86, -500, 86, -500, + -500, -497, -501, 86, -501, -502, 86, -502, -501, -372, + -479, 566, -405, -407, -372, 40, -519, 62, -190, 86, + 32, 86, -223, -372, 192, 170, 654, 36, -520, 62, -190, 86, 32, -214, -139, 40, -216, 21, 159, 102, - 92, -118, -99, 78, -118, -99, -99, 87, 160, -576, - 108, 109, -578, 92, 210, 201, -371, -116, 92, -543, + 92, -118, -99, 78, -118, -99, -99, 87, 160, -577, + 108, 109, -579, 92, 210, 201, -372, -116, 92, -544, -7, -11, -8, -9, -10, -47, -85, -190, 558, 561, - -546, -544, 86, 33, 448, 83, 17, -458, 246, 516, - 399, 273, 249, 375, -456, -439, -436, -434, -370, -432, - -435, -434, -461, -347, 480, -140, 463, 462, 327, -398, - -398, -398, -398, -398, 107, 118, 366, 108, 109, -393, - -414, 33, 323, 324, -394, -394, -394, -394, -394, -394, - -394, -394, -394, -394, -394, -394, -402, -412, -489, 86, - 138, 136, 140, 137, 120, -396, -396, -394, -394, -284, - -370, 156, 87, 160, -398, -569, -568, 122, -398, -398, - -398, -398, -425, -427, -347, 86, -371, -566, -567, 530, + -547, -545, 86, 33, 448, 83, 17, -459, 246, 516, + 399, 273, 249, 375, -457, -440, -437, -435, -371, -433, + -436, -435, -462, -348, 480, -140, 463, 462, 327, -399, + -399, -399, -399, -399, 107, 118, 366, 108, 109, -394, + -415, 33, 323, 324, -395, -395, -395, -395, -395, -395, + -395, -395, -395, -395, -395, -395, -403, -413, -490, 86, + 138, 136, 140, 137, 120, -397, -397, -395, -395, -285, + -371, 156, 87, 160, -399, -570, -569, 122, -399, -399, + -399, -399, -426, -428, -348, 86, -372, -567, -568, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 390, 385, 391, 389, 378, 397, 392, 393, 194, 547, - 548, 541, 542, 543, 544, 545, 546, -404, -404, -398, - -566, -404, -340, 34, 33, -406, -406, -406, 87, -398, - -579, 364, 363, 365, -217, -371, -404, 87, 87, 87, - 102, -406, -406, -404, -394, -404, -404, -404, -404, -567, - -340, -340, -340, -340, 147, -406, -406, -340, -340, -340, - -340, 147, -340, -340, -340, -340, -340, -340, -340, -340, - -340, -340, -340, 87, 87, 87, 147, -406, -215, -138, - -527, -526, -398, 42, -139, -216, -622, 647, 86, -347, - -610, 92, 92, 674, -144, 159, 17, 246, -144, 159, - 655, 170, -144, 17, -371, -371, 102, -371, 102, 246, - 516, 246, 516, -258, -258, 506, 507, 169, 173, 172, - -371, 171, -371, -371, 118, -371, -371, 36, -244, -233, - -418, -418, -418, -587, -371, 93, -440, -437, -434, -371, - -371, -430, -371, -360, -258, -418, -418, -418, -418, -258, - -293, 54, 55, 56, -434, -179, 57, 58, -583, -571, - 36, -220, -371, -328, -396, -396, -398, 375, 516, 246, - -434, 277, -629, -383, -383, -361, -360, -385, -380, -385, - -385, -328, -381, -383, -383, -398, -385, -381, -328, -371, - 480, -328, -328, -474, -383, -382, -371, -382, -418, -360, - -361, -361, -258, -258, -307, -314, -308, -315, 269, 243, - 383, 384, 240, 238, 11, 239, -322, 316, -419, 524, - -288, -289, 78, 43, -291, 267, 425, 418, 279, 283, + 548, 541, 542, 543, 544, 545, 546, -405, -405, -399, + -567, -405, -341, 34, 33, -407, -407, -407, 87, -399, + -580, 364, 363, 365, -218, -372, -405, 87, 87, 87, + 102, -407, -407, -405, -395, -405, -405, -405, -405, -568, + -341, -341, -341, -341, 147, -407, -407, -341, -341, -341, + -341, 147, -341, -341, -341, -341, -341, -341, -341, -341, + -341, -341, -341, 87, 87, 87, 147, -407, -215, -138, + -528, -527, -399, 42, -139, -216, -623, 647, 86, -348, + -611, 92, 92, 674, -144, 159, 17, 246, -144, 159, + 655, 170, -144, 17, -372, -372, 102, -372, 102, 246, + 516, 246, 516, -259, -259, 506, 507, 169, 173, 172, + -372, 171, -372, -372, 118, -372, -372, 36, -245, -234, + -419, -419, -419, -588, -372, 93, -441, -438, -435, -372, + -372, -431, -372, -361, -259, -419, -419, -419, -419, -259, + -294, 54, 55, 56, -435, -179, 57, 58, -584, -572, + 36, -221, -372, -329, -397, -397, -399, 375, 516, 246, + -435, 277, -630, -384, -384, -362, -361, -386, -381, -386, + -386, -329, -382, -384, -384, -399, -386, -382, -329, -372, + 480, -329, -329, -475, -384, -383, -372, -383, -419, -361, + -362, -362, -259, -259, -308, -315, -309, -316, 269, 243, + 383, 384, 240, 238, 11, 239, -323, 316, -420, 524, + -289, -290, 78, 43, -292, 267, 425, 418, 279, 283, 96, 284, 458, 285, 248, 287, 288, 289, 304, 306, 259, 290, 291, 292, 449, 293, 164, 305, 294, 295, - 296, 401, -283, 6, 351, 42, 52, 53, 472, 471, - 569, 566, 280, -371, -587, -585, 32, -371, 32, -440, - -434, -371, -371, 160, 250, -206, -208, -205, -201, -202, - -207, -331, -333, -204, 86, -258, -193, -371, -451, 160, - 504, 506, 507, -615, -452, -615, -452, 250, 33, 448, - -455, 448, 33, -430, -449, 500, 502, -445, 92, 449, - -435, -454, 83, 156, -526, -452, -452, -454, -454, 155, - 160, -613, 505, 506, 234, -215, 102, -240, 657, -260, - -258, -587, -439, -430, -371, -508, -260, -260, -260, -373, - -373, 86, 159, 37, -371, -371, -371, -371, -327, 160, - -326, 17, -372, -371, 36, 92, 159, -149, -147, 124, - -398, -6, 639, -398, -6, -6, -398, -6, -398, -506, - 422, 102, 102, -350, 92, -350, 102, 102, 102, 572, - 87, 92, -443, 83, -520, -407, -564, 628, -224, 87, - -217, -562, -563, -217, -223, -371, -518, -250, 128, 128, - 128, 25, -520, -224, 87, -562, -215, 629, -139, -212, - -211, -398, -371, 24, -118, -99, -574, 159, 160, -220, - -458, -438, -435, -460, 147, -371, -446, 160, 566, 677, - 90, 250, -600, -599, 440, 87, 160, -530, 251, 523, - 92, 674, 456, 228, 229, 107, 366, 108, 109, -489, - -406, -402, -396, -396, -394, -394, -400, 264, -400, 117, - -398, 675, -397, -568, 124, -398, 36, 160, 36, 160, - 84, 160, 87, -496, -398, 159, 87, 87, 17, 17, - 87, -398, 87, 87, 87, 87, 17, 17, -398, 87, + 296, 401, -284, 6, 351, 42, 52, 53, 472, 471, + 569, 566, 280, -372, -588, -586, 32, -372, 32, -441, + -435, -372, -372, 160, 250, -206, -208, -205, -201, -202, + -207, -332, -334, -204, 86, -259, -193, -372, -452, 160, + 504, 506, 507, -616, -453, -616, -453, 250, 33, 448, + -456, 448, 33, -431, -450, 500, 502, -446, 92, 449, + -436, -455, 83, 156, -527, -453, -453, -455, -455, 155, + 160, -614, 505, 506, 234, -215, 102, -241, 657, -261, + -259, -588, -440, -431, -372, -509, -261, -261, -261, -374, + -374, 86, 159, 37, -372, -372, -372, -372, -328, 160, + -327, 17, -373, -372, 36, 92, 159, -149, -147, 124, + -399, -6, 639, -399, -6, -6, -399, -6, -399, -507, + 422, 102, 102, -351, 92, -351, 102, 102, 102, 572, + 87, 92, -444, 83, -521, -408, -565, 628, -225, 87, + -218, -563, -564, -218, -224, -372, -519, -251, 128, 128, + 128, 25, -521, -225, 87, -563, -215, 629, -139, -212, + -211, -399, -372, 24, -118, -99, -575, 159, 160, -221, + -459, -439, -436, -461, 147, -372, -447, 160, 566, 677, + 90, 250, -601, -600, 440, 87, 160, -531, 251, 523, + 92, 674, 456, 228, 229, 107, 366, 108, 109, -490, + -407, -403, -397, -397, -395, -395, -401, 264, -401, 117, + -399, 675, -398, -569, 124, -399, 36, 160, 36, 160, + 84, 160, 87, -497, -399, 159, 87, 87, 17, 17, + 87, -399, 87, 87, 87, 87, 17, 17, -399, 87, 159, 87, 87, 87, 87, 84, 87, 160, 87, 87, - 87, 87, 160, -406, -406, -398, -406, 87, 87, 87, - -398, -398, -398, -406, 87, -398, -398, -398, -398, -398, - -398, -398, -398, -398, -398, -220, -468, 475, -468, -468, - 160, 160, 160, 87, -139, 86, 102, 160, 670, -354, - -353, 92, -145, 250, -371, 655, -371, -145, -371, -371, - 128, -145, 655, 92, 92, -258, -360, -258, -360, 563, - 40, 170, 174, 174, 173, -371, 92, 37, 24, 24, - 314, -243, 86, 86, -258, -258, -258, -589, 426, -601, - 160, 42, -599, 516, -175, 327, -422, 84, -182, 334, - 17, 566, -258, -258, -258, -258, -272, 36, 17, -200, - -259, -371, 86, 87, 160, -371, -371, -371, -431, 84, - -371, -361, -328, -328, -385, -328, -328, 160, 23, -383, - -385, -385, -250, -381, -250, 159, -250, -360, -495, 36, - -221, 160, 21, 269, -257, -368, -254, -256, 254, -388, - -255, 257, -558, 255, 253, 112, 258, 312, 113, 248, - -368, -368, 254, -292, 250, 36, -368, -310, 248, 369, - 312, 255, 21, 269, -309, 248, 113, -371, 254, 258, - 255, 253, -367, 128, -359, 155, 250, 44, 401, -367, - 570, 269, -367, -367, -367, -367, -367, -367, -367, 286, - 286, -367, -367, -367, -367, -367, -367, -367, -367, -367, - -367, -367, 165, -367, -367, -367, -367, -367, -367, 86, - 281, 282, 314, -590, 426, 32, 381, 381, 382, -601, - 377, 43, 32, -183, 375, -313, -311, -382, 32, -334, - -335, -336, -337, -339, -338, 69, 73, 75, 79, 70, - 71, 72, 76, 81, 74, 32, 160, -369, -374, 36, - -371, 92, -369, -193, -208, -206, -369, 86, -452, -614, - -616, 508, 505, 511, -454, -454, 102, 250, 86, 128, - -454, -454, 42, -370, -611, 512, 506, -139, 160, 83, - -260, -234, -235, -236, -237, -265, -347, 196, 199, 201, - 202, 203, 204, 206, 207, 208, 209, 210, 213, 214, - 211, 212, 263, 191, 192, 193, 194, 215, 177, 197, - 564, 178, 179, 180, 181, 182, 183, 186, 187, 188, - 189, 185, -371, -244, -240, -328, -196, -208, -371, 92, - -371, 147, 125, -6, 123, -153, -152, -151, 126, 637, - 643, 125, 125, 125, 87, 87, 87, 160, 87, 87, - 87, 160, 87, 160, 102, -533, 485, 41, 160, 86, - 87, 160, 62, 160, 128, 87, 160, -398, -371, 92, - -398, 192, 87, 62, -139, 92, 160, -209, 38, 39, - 159, 458, -371, -544, 87, -460, 160, 250, 159, 159, - -436, 404, -370, -438, 21, 566, -347, 40, -354, 128, - 674, -371, 87, -400, -400, 117, -396, -393, 87, 125, - -398, 123, -263, -265, 420, 421, -398, -263, -264, -270, - 156, 195, 263, 194, 193, 191, 420, 421, -282, -427, - 563, -209, 87, -371, -398, -398, 87, -398, -398, 17, - -371, -282, -394, -398, -214, -214, 87, 87, -467, -468, - -467, -467, 87, 87, 87, 87, -467, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 86, 102, - 104, 102, 104, -526, -623, 64, 645, 63, 448, 107, - 317, 160, 102, 92, 675, 160, 128, 375, -371, 17, - 159, 92, -371, 92, -371, 17, 17, -258, -258, 174, - 92, -602, 321, 375, 516, 246, 375, 321, 516, 246, - -479, 102, 412, -245, -246, -247, -248, -249, 138, 161, - 162, -234, -221, 86, -221, -592, 487, 428, 438, -367, - -390, -389, 377, 43, -513, 449, 434, 435, -437, 277, - -360, -598, 99, 128, 83, 355, 359, 361, 360, 356, - 357, 358, -416, -417, -415, -419, -360, -585, 86, 86, - -190, 36, 136, -182, 334, 86, 86, 36, -490, 345, - -265, -258, -200, -371, 17, 160, -584, 159, -1, -371, - -371, -430, -383, -328, -398, -398, -328, -383, -383, -385, - -371, -250, -490, -265, 36, -308, 243, 239, -464, 314, - 315, -465, -480, 317, -482, 86, -262, -347, -255, -557, - -558, -418, -371, 113, -557, 113, 86, -262, -347, -347, - -311, -347, -371, -371, -371, -371, -318, -317, -347, -320, - 33, -321, -371, -371, -371, -371, 113, -371, 113, -287, - 42, 49, 50, 51, 334, 285, 335, -367, -367, 198, - -290, 42, 448, 450, 451, -320, 102, 102, 102, 102, - 92, 92, 92, -367, -367, 102, 92, -374, 92, -559, - 173, 46, 47, 102, 102, 102, 102, 42, 92, -295, - 42, 297, 301, 298, 299, 300, 92, 102, 42, 102, - 42, 102, 42, -371, 86, -560, -561, 92, -479, -592, - -367, 381, -451, 128, 128, -390, -594, 96, 429, -594, - -597, 327, -185, 516, 33, -225, 243, 239, -585, -442, - -441, -347, -205, -205, -205, -205, -205, -205, 69, 80, - 69, -218, 86, 69, 74, 69, 74, 69, -336, 69, - 80, -442, -207, -221, -374, 87, -608, -607, -606, -604, - 77, 251, 78, -404, -454, 505, 509, 510, -438, -386, - 92, -445, -231, 24, -258, -258, -511, 307, 308, 87, - 160, -265, -330, 19, 159, 121, -6, -149, -151, -398, - -6, -398, 639, 394, 640, 92, 102, 102, -541, 469, - 464, 466, 113, -407, -528, -527, 62, -190, -217, -520, - -563, -526, -371, 675, 675, 675, 675, 92, 62, -190, - -520, -231, -533, -211, -210, 45, -371, 102, 17, -435, - -430, 147, 147, -371, 405, -446, 92, 427, 92, 246, - 675, 92, -354, -393, -398, 87, -273, 182, 181, -273, - 36, 87, 87, -497, -497, -496, -499, -496, -273, -273, - 87, 86, -209, 87, 24, 87, 87, 87, -398, 87, - 87, 160, -516, 525, -517, 599, -467, -467, -467, -467, - -467, -467, -467, -467, -467, -467, -467, -467, -467, -467, - -467, -467, -467, -409, -408, 269, 470, 652, 652, 470, - 652, 652, 87, 160, -566, 160, -362, 322, -362, -353, - 92, -371, 92, 655, -371, 675, 675, 92, -258, -360, - -189, 344, -188, 122, 92, -371, -371, -371, 314, -371, - 314, -371, -371, 92, 92, 87, 160, -347, 87, 36, - -251, -252, -253, -262, -254, -256, 36, -593, 96, -588, - 92, -371, 93, -594, 158, 379, 42, 430, 431, 446, - 374, 102, 102, 436, -586, -371, -184, 246, 375, -596, - 53, 128, 92, -258, -415, -359, 155, 288, -250, 348, - -325, -324, -371, 92, -251, -190, -258, -258, -251, -251, - -190, -491, 347, 21, 102, 146, -222, 84, 159, -208, - -259, -371, 147, 87, -328, -250, -328, -328, -383, -491, - -190, -476, 318, 86, -474, 86, -474, 113, 356, -483, - -481, 269, -316, 46, 48, -265, -555, -371, -553, -555, - -371, -553, -553, -418, -398, -316, -262, 250, 32, 239, - -319, 353, 354, 359, 361, -447, 313, 118, -447, 160, - -209, 160, -371, -282, -282, 32, 92, 92, -260, 87, - 160, 128, 92, -593, -588, 128, -452, 92, 92, -594, - 92, 92, -598, 128, -261, 246, -360, 160, -225, -225, - -328, 160, 128, -229, -228, 83, 84, -230, 83, -228, - -228, 69, -219, 92, 69, 69, -328, -606, -605, 24, - -558, -558, -558, 87, 87, 15, -236, 42, -329, 20, - 21, 147, 125, 123, 125, 125, -371, 87, 87, -503, - 630, -537, -539, 464, 21, 21, 15, 251, 87, -520, - 675, -520, -541, 46, 47, -430, -446, 449, -258, 160, - 675, -263, -301, 92, -398, 87, -398, 87, 92, 87, - 92, -214, 21, 87, 160, 87, 87, 87, 160, 87, - 87, -398, 87, -566, -363, 192, 92, -363, -371, -372, - -187, 250, -250, 36, 412, 22, 578, 340, 92, -371, - -479, 314, -479, 314, 246, -371, -240, -423, 565, -247, - -265, 244, -190, 87, 160, -190, 92, -591, 440, 102, - 42, 102, 158, 432, -514, -176, 96, -260, 33, -225, - -595, 96, 128, 674, 86, -367, -367, -367, -187, -371, - 87, 160, -367, -367, 87, -187, 87, 87, -280, 566, - -492, 268, 102, 146, 102, 146, 102, -369, -208, -371, - -328, -584, 159, -328, -492, -466, 319, 102, -394, 86, - -394, 86, -475, 316, 86, 87, 160, -371, -347, -277, - -276, -274, 107, 118, 42, 418, -275, 96, 155, 302, - 305, 304, 280, 303, -306, -387, 83, 424, 353, 354, - -419, 630, 554, 253, 112, 113, 406, -388, 86, 86, - 84, 322, 86, 86, -555, 87, -316, -347, 42, -319, - 42, 367, 313, -317, -371, 155, -282, 87, -561, 92, - -591, 92, -454, -596, 92, -176, -260, -585, -214, -441, - -526, -398, 86, -398, 87, 86, 69, 11, 19, -391, - -398, -406, 659, 661, 662, 252, -6, 640, 394, -297, - 631, 92, 21, 92, -535, 92, -442, -503, -142, -294, - -359, 285, 87, -300, 138, 566, 87, 87, -467, -467, - -470, -469, -473, 470, 314, 478, -406, 92, 92, 87, - 87, 92, 92, 375, -187, -258, 92, 102, 341, 342, - 343, 674, 92, -479, 92, -479, -371, 314, 92, 92, - -238, -265, -180, 566, -280, -253, -180, 21, 566, 378, - 42, 102, 42, 433, 92, -184, 128, 108, 109, -355, - -356, 92, -425, -282, -284, 92, -324, -391, -391, -278, - -190, 36, -279, -322, -419, -141, -140, -278, 86, -493, - 164, 102, 146, 102, 102, -328, -328, -493, -482, 21, - 87, -461, 87, -461, 86, 128, -394, -481, -484, 62, - -274, 107, -394, 92, -284, -285, 42, 301, 297, 128, - 128, -286, 42, 281, 282, -296, 86, 312, 15, 198, - 86, 113, 113, -258, -425, -425, -556, 355, 356, 357, - 362, 359, 360, 358, 361, -556, -425, -425, 86, -448, - -447, -394, -367, -367, 155, -595, -215, -220, -554, -371, - 253, 21, 21, -512, 566, 660, 86, 86, -371, -371, - -351, 632, 102, 92, 466, -297, -504, 633, -531, -474, - -282, 128, 87, 76, 564, 567, 87, -472, 120, 432, - 436, -392, -395, 102, 104, 190, 158, 87, 87, -371, - -358, -357, 92, -240, 92, -240, 92, 314, -479, 565, - -181, 61, 512, 92, 93, 427, 92, 93, 378, -176, - 92, 675, 160, 128, 87, -462, 269, -190, 160, -322, - -359, -142, -462, -281, -323, -371, 92, -510, 173, 346, - 566, 102, 146, 102, -214, -494, 173, 346, -465, 87, - 87, 87, -461, 102, 87, -488, -485, 86, -322, 271, - 138, 92, 92, 102, 86, -521, 32, 92, -426, 86, - 87, 87, 87, 87, -425, 102, -282, -367, 87, 87, - 160, 662, 86, -406, -406, 86, 21, -351, -505, 634, - 92, -540, 469, -534, -532, 464, 465, 466, 467, 92, - 565, 66, 568, -471, -472, 436, -392, -395, 628, 476, - 476, 476, 675, 160, 128, -240, -240, -479, 92, -241, - -371, 312, 449, -356, 92, -428, -463, 321, 21, -322, - -367, -463, 87, 160, -367, -367, 346, 102, 146, 102, - -215, 346, -477, 320, 87, -488, -322, -487, -486, 319, - 272, 86, 87, -398, -410, -367, 87, -299, -298, 562, - -425, -428, 84, -428, 84, -428, 84, -428, 84, 87, - -282, -371, 253, -137, 86, 87, 87, -352, -371, -535, - 92, -542, 251, -538, -539, 468, -532, 21, 466, 21, - 21, -143, 160, 66, 117, 477, 477, 477, -240, -357, - 92, 92, -240, -239, 36, 471, 405, -429, 259, 367, - 368, 96, 566, 353, 354, 372, 371, 370, 373, 21, - -464, -282, -323, -391, -391, 102, 102, 87, 160, -371, - 268, 86, -405, -399, -398, 268, 87, -371, -305, -303, - -304, 83, 483, 310, 311, 87, -556, -556, -556, -556, - -306, 87, 160, -404, 87, 160, -549, 86, 102, -537, - -536, -538, 21, -535, 21, -535, -535, 473, 566, -471, - -240, 92, -367, -367, 92, 92, 352, -367, -367, -367, - -347, 86, -476, -486, -485, -405, 87, 160, -447, -304, - 83, -303, 83, 16, 15, -428, -428, -428, -428, 86, - 87, -371, -552, 32, 87, -548, -547, -348, -543, -371, - 469, 470, 92, -535, 128, 567, -626, -625, 651, 102, - 102, -371, 102, 102, 102, -461, -466, 87, -399, -302, - 307, 308, 32, 173, -302, -404, -551, -550, -349, 87, - 160, 159, 92, 568, 92, 87, -482, 107, 42, 309, - 87, 160, 128, -547, -371, -550, 42, -398, 159, -371, + 87, 87, 160, -407, -407, -399, -407, 87, 87, 87, + -399, -399, -399, -407, 87, -399, -399, -399, -399, -399, + -399, -399, -399, -399, -399, -221, -469, 475, -469, -469, + 160, 160, 160, 87, -139, 86, 102, 160, 670, -355, + -354, 92, -145, 250, -372, 655, -372, -145, -372, -372, + 128, -145, 655, 92, 92, -259, -361, -259, -361, 563, + 40, 170, 174, 174, 173, -372, 92, 37, 24, 24, + 314, -244, 86, 86, -259, -259, -259, -590, 426, -602, + 160, 42, -600, 516, -175, 327, -423, 84, -182, 334, + 17, 566, -259, -259, -259, -259, -273, 36, 17, -200, + -260, -372, 86, 87, 160, -372, -372, -372, -432, 84, + -372, -362, -329, -329, -386, -329, -329, -217, 160, 23, + 21, -384, -386, -386, -251, -382, -251, 159, -251, -361, + -496, 36, -222, 160, 21, 269, -258, -369, -255, -257, + 254, -389, -256, 257, -559, 255, 253, 112, 258, 312, + 113, 248, -369, -369, 254, -293, 250, 36, -369, -311, + 248, 369, 312, 255, 21, 269, -310, 248, 113, -372, + 254, 258, 255, 253, -368, 128, -360, 155, 250, 44, + 401, -368, 570, 269, -368, -368, -368, -368, -368, -368, + -368, 286, 286, -368, -368, -368, -368, -368, -368, -368, + -368, -368, -368, -368, 165, -368, -368, -368, -368, -368, + -368, 86, 281, 282, 314, -591, 426, 32, 381, 381, + 382, -602, 377, 43, 32, -183, 375, -314, -312, -383, + 32, -335, -336, -337, -338, -340, -339, 69, 73, 75, + 79, 70, 71, 72, 76, 81, 74, 32, 160, -370, + -375, 36, -372, 92, -370, -193, -208, -206, -370, 86, + -453, -615, -617, 508, 505, 511, -455, -455, 102, 250, + 86, 128, -455, -455, 42, -371, -612, 512, 506, -139, + 160, 83, -261, -235, -236, -237, -238, -266, -348, 196, + 199, 201, 202, 203, 204, 206, 207, 208, 209, 210, + 213, 214, 211, 212, 263, 191, 192, 193, 194, 215, + 177, 197, 564, 178, 179, 180, 181, 182, 183, 186, + 187, 188, 189, 185, -372, -245, -241, -329, -196, -208, + -372, 92, -372, 147, 125, -6, 123, -153, -152, -151, + 126, 637, 643, 125, 125, 125, 87, 87, 87, 160, + 87, 87, 87, 160, 87, 160, 102, -534, 485, 41, + 160, 86, 87, 160, 62, 160, 128, 87, 160, -399, + -372, 92, -399, 192, 87, 62, -139, 92, 160, -209, + 38, 39, 159, 458, -372, -545, 87, -461, 160, 250, + 159, 159, -437, 404, -371, -439, 21, 566, -348, 40, + -355, 128, 674, -372, 87, -401, -401, 117, -397, -394, + 87, 125, -399, 123, -264, -266, 420, 421, -399, -264, + -265, -271, 156, 195, 263, 194, 193, 191, 420, 421, + -283, -428, 563, -209, 87, -372, -399, -399, 87, -399, + -399, 17, -372, -283, -395, -399, -214, -214, 87, 87, + -468, -469, -468, -468, 87, 87, 87, 87, -468, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 86, 102, 104, 102, 104, -527, -624, 64, 645, 63, + 448, 107, 317, 160, 102, 92, 675, 160, 128, 375, + -372, 17, 159, 92, -372, 92, -372, 17, 17, -259, + -259, 174, 92, -603, 321, 375, 516, 246, 375, 321, + 516, 246, -480, 102, 412, -246, -247, -248, -249, -250, + 138, 161, 162, -235, -222, 86, -222, -593, 487, 428, + 438, -368, -391, -390, 377, 43, -514, 449, 434, 435, + -438, 277, -361, -599, 99, 128, 83, 355, 359, 361, + 360, 356, 357, 358, -417, -418, -416, -420, -361, -586, + 86, 86, -190, 36, 136, -182, 334, 86, 86, 36, + -491, 345, -266, -259, -200, -372, 17, 160, -585, 159, + -1, -372, -372, -431, -384, -329, -399, -399, 614, -329, + -384, -384, -386, -372, -251, -491, -266, 36, -309, 243, + 239, -465, 314, 315, -466, -481, 317, -483, 86, -263, + -348, -256, -558, -559, -419, -372, 113, -558, 113, 86, + -263, -348, -348, -312, -348, -372, -372, -372, -372, -319, + -318, -348, -321, 33, -322, -372, -372, -372, -372, 113, + -372, 113, -288, 42, 49, 50, 51, 334, 285, 335, + -368, -368, 198, -291, 42, 448, 450, 451, -321, 102, + 102, 102, 102, 92, 92, 92, -368, -368, 102, 92, + -375, 92, -560, 173, 46, 47, 102, 102, 102, 102, + 42, 92, -296, 42, 297, 301, 298, 299, 300, 92, + 102, 42, 102, 42, 102, 42, -372, 86, -561, -562, + 92, -480, -593, -368, 381, -452, 128, 128, -391, -595, + 96, 429, -595, -598, 327, -185, 516, 33, -226, 243, + 239, -586, -443, -442, -348, -205, -205, -205, -205, -205, + -205, 69, 80, 69, -219, 86, 69, 74, 69, 74, + 69, -337, 69, 80, -443, -207, -222, -375, 87, -609, + -608, -607, -605, 77, 251, 78, -405, -455, 505, 509, + 510, -439, -387, 92, -446, -232, 24, -259, -259, -512, + 307, 308, 87, 160, -266, -331, 19, 159, 121, -6, + -149, -151, -399, -6, -399, 639, 394, 640, 92, 102, + 102, -542, 469, 464, 466, 113, -408, -529, -528, 62, + -190, -218, -521, -564, -527, -372, 675, 675, 675, 675, + 92, 62, -190, -521, -232, -534, -211, -210, 45, -372, + 102, 17, -436, -431, 147, 147, -372, 405, -447, 92, + 427, 92, 246, 675, 92, -355, -394, -399, 87, -274, + 182, 181, -274, 36, 87, 87, -498, -498, -497, -500, + -497, -274, -274, 87, 86, -209, 87, 24, 87, 87, + 87, -399, 87, 87, 160, -517, 525, -518, 599, -468, + -468, -468, -468, -468, -468, -468, -468, -468, -468, -468, + -468, -468, -468, -468, -468, -468, -410, -409, 269, 470, + 652, 652, 470, 652, 652, 87, 160, -567, 160, -363, + 322, -363, -354, 92, -372, 92, 655, -372, 675, 675, + 92, -259, -361, -189, 344, -188, 122, 92, -372, -372, + -372, 314, -372, 314, -372, -372, 92, 92, 87, 160, + -348, 87, 36, -252, -253, -254, -263, -255, -257, 36, + -594, 96, -589, 92, -372, 93, -595, 158, 379, 42, + 430, 431, 446, 374, 102, 102, 436, -587, -372, -184, + 246, 375, -597, 53, 128, 92, -259, -416, -360, 155, + 288, -251, 348, -326, -325, -372, 92, -252, -190, -259, + -259, -252, -252, -190, -492, 347, 21, 102, 146, -223, + 84, 159, -208, -260, -372, 147, 87, -329, -217, -217, + 566, -251, -329, -329, -384, -492, -190, -477, 318, 86, + -475, 86, -475, 113, 356, -484, -482, 269, -317, 46, + 48, -266, -556, -372, -554, -556, -372, -554, -554, -419, + -399, -317, -263, 250, 32, 239, -320, 353, 354, 359, + 361, -448, 313, 118, -448, 160, -209, 160, -372, -283, + -283, 32, 92, 92, -261, 87, 160, 128, 92, -594, + -589, 128, -453, 92, 92, -595, 92, 92, -599, 128, + -262, 246, -361, 160, -226, -226, -329, 160, 128, -230, + -229, 83, 84, -231, 83, -229, -229, 69, -220, 92, + 69, 69, -329, -607, -606, 24, -559, -559, -559, 87, + 87, 15, -237, 42, -330, 20, 21, 147, 125, 123, + 125, 125, -372, 87, 87, -504, 630, -538, -540, 464, + 21, 21, 15, 251, 87, -521, 675, -521, -542, 46, + 47, -431, -447, 449, -259, 160, 675, -264, -302, 92, + -399, 87, -399, 87, 92, 87, 92, -214, 21, 87, + 160, 87, 87, 87, 160, 87, 87, -399, 87, -567, + -364, 192, 92, -364, -372, -373, -187, 250, -251, 36, + 412, 22, 578, 340, 92, -372, -480, 314, -480, 314, + 246, -372, -241, -424, 565, -248, -266, 244, -190, 87, + 160, -190, 92, -592, 440, 102, 42, 102, 158, 432, + -515, -176, 96, -261, 33, -226, -596, 96, 128, 674, + 86, -368, -368, -368, -187, -372, 87, 160, -368, -368, + 87, -187, 87, 87, -281, 566, -493, 268, 102, 146, + 102, 146, 102, -370, -208, -372, -329, -585, 159, 405, + -329, -493, -467, 319, 102, -395, 86, -395, 86, -476, + 316, 86, 87, 160, -372, -348, -278, -277, -275, 107, + 118, 42, 418, -276, 96, 155, 302, 305, 304, 280, + 303, -307, -388, 83, 424, 353, 354, -420, 630, 554, + 253, 112, 113, 406, -389, 86, 86, 84, 322, 86, + 86, -556, 87, -317, -348, 42, -320, 42, 367, 313, + -318, -372, 155, -283, 87, -562, 92, -592, 92, -455, + -597, 92, -176, -261, -586, -214, -442, -527, -399, 86, + -399, 87, 86, 69, 11, 19, -392, -399, -407, 659, + 661, 662, 252, -6, 640, 394, -298, 631, 92, 21, + 92, -536, 92, -443, -504, -142, -295, -360, 285, 87, + -301, 138, 566, 87, 87, -468, -468, -471, -470, -474, + 470, 314, 478, -407, 92, 92, 87, 87, 92, 92, + 375, -187, -259, 92, 102, 341, 342, 343, 674, 92, + -480, 92, -480, -372, 314, 92, 92, -239, -266, -180, + 566, -281, -254, -180, 21, 566, 378, 42, 102, 42, + 433, 92, -184, 128, 108, 109, -356, -357, 92, -426, + -283, -285, 92, -325, -392, -392, -279, -190, 36, -280, + -323, -420, -141, -140, -279, 86, -494, 164, 102, 146, + 102, 102, -329, -329, -407, -494, -483, 21, 87, -462, + 87, -462, 86, 128, -395, -482, -485, 62, -275, 107, + -395, 92, -285, -286, 42, 301, 297, 128, 128, -287, + 42, 281, 282, -297, 86, 312, 15, 198, 86, 113, + 113, -259, -426, -426, -557, 355, 356, 357, 362, 359, + 360, 358, 361, -557, -426, -426, 86, -449, -448, -395, + -368, -368, 155, -596, -215, -221, -555, -372, 253, 21, + 21, -513, 566, 660, 86, 86, -372, -372, -352, 632, + 102, 92, 466, -298, -505, 633, -532, -475, -283, 128, + 87, 76, 564, 567, 87, -473, 120, 432, 436, -393, + -396, 102, 104, 190, 158, 87, 87, -372, -359, -358, + 92, -241, 92, -241, 92, 314, -480, 565, -181, 61, + 512, 92, 93, 427, 92, 93, 378, -176, 92, 675, + 160, 128, 87, -463, 269, -190, 160, -323, -360, -142, + -463, -282, -324, -372, 92, -511, 173, 346, 566, 102, + 146, 102, -214, -495, 173, 346, -466, 87, 87, 87, + -462, 102, 87, -489, -486, 86, -323, 271, 138, 92, + 92, 102, 86, -522, 32, 92, -427, 86, 87, 87, + 87, 87, -426, 102, -283, -368, 87, 87, 160, 662, + 86, -407, -407, 86, 21, -352, -506, 634, 92, -541, + 469, -535, -533, 464, 465, 466, 467, 92, 565, 66, + 568, -472, -473, 436, -393, -396, 628, 476, 476, 476, + 675, 160, 128, -241, -241, -480, 92, -242, -372, 312, + 449, -357, 92, -429, -464, 321, 21, -323, -368, -464, + 87, 160, -368, -368, 346, 102, 146, 102, -215, 346, + -478, 320, 87, -489, -323, -488, -487, 319, 272, 86, + 87, -399, -411, -368, 87, -300, -299, 562, -426, -429, + 84, -429, 84, -429, 84, -429, 84, 87, -283, -372, + 253, -137, 86, 87, 87, -353, -372, -536, 92, -543, + 251, -539, -540, 468, -533, 21, 466, 21, 21, -143, + 160, 66, 117, 477, 477, 477, -241, -358, 92, 92, + -241, -240, 36, 471, 405, -430, 259, 367, 368, 96, + 566, 353, 354, 372, 371, 370, 373, 21, -465, -283, + -324, -392, -392, 102, 102, 87, 160, -372, 268, 86, + -406, -400, -399, 268, 87, -372, -306, -304, -305, 83, + 483, 310, 311, 87, -557, -557, -557, -557, -307, 87, + 160, -405, 87, 160, -550, 86, 102, -538, -537, -539, + 21, -536, 21, -536, -536, 473, 566, -472, -241, 92, + -368, -368, 92, 92, 352, -368, -368, -368, -348, 86, + -477, -487, -486, -406, 87, 160, -448, -305, 83, -304, + 83, 16, 15, -429, -429, -429, -429, 86, 87, -372, + -553, 32, 87, -549, -548, -349, -544, -372, 469, 470, + 92, -536, 128, 567, -627, -626, 651, 102, 102, -372, + 102, 102, 102, -462, -467, 87, -400, -303, 307, 308, + 32, 173, -303, -405, -552, -551, -350, 87, 160, 159, + 92, 568, 92, 87, -483, 107, 42, 309, 87, 160, + 128, -548, -372, -551, 42, -399, 159, -372, } var yyDef = [...]int{ @@ -9958,8 +9927,8 @@ var yyDef = [...]int{ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 324, 325, 326, - 327, 328, 329, 998, 999, 1000, 1001, 1002, 1003, 1004, - 1005, 1006, 0, 0, 0, 0, 0, 735, 736, 0, + 327, 328, 329, 1000, 1001, 1002, 1003, 1004, 1005, 1006, + 1007, 1008, 0, 0, 0, 0, 0, 735, 736, 0, 699, 0, 0, 0, 0, 0, 0, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, @@ -9968,411 +9937,412 @@ var yyDef = [...]int{ 446, 447, 448, 449, 450, 0, 358, 354, 266, 267, 268, 269, 270, 271, 272, 365, 366, 548, 0, 0, 0, 0, 818, -2, 110, 0, 0, 0, 0, 0, - 347, 0, 338, 338, 0, 0, 1007, 1008, 1009, 1010, - 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, -2, + 347, 0, 338, 338, 0, 0, 1009, 1010, 1011, 1012, + 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, -2, 748, 0, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 424, 425, 426, 420, 421, 423, 422, -2, 0, 0, 748, - 0, 0, 0, 826, 0, 0, 0, 869, 887, 23, + 0, 0, 0, 826, 0, 0, 0, 871, 889, 23, 0, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 19, 0, 19, 0, 0, 0, - 1451, 1452, 1453, 1454, 2257, 2227, -2, 1990, 1964, 2151, - 2152, 2047, 2059, 1958, 2295, 2296, 2297, 2298, 2299, 2300, - 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, - 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, - 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, - 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, - 2341, 2342, 2343, 2344, 1920, 1921, 1922, 1923, 1924, 1925, - 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, - 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, - 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, - 1956, 1957, 1959, 1960, 1961, 1962, 1963, 1965, 1966, 1967, - 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, - 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, - 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, - 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, - 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, - 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2048, 2049, - 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2061, - 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, - 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, - 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, - 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, - 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, - 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, - 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, - 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, - 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2153, - 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, - 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, - 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, - -2, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, - 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, - 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, - 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, - 2224, 2225, 2226, 2228, 2229, 2230, 2231, 2232, 2233, 2234, - 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, -2, -2, - -2, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, - 2255, 2256, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, - 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, - 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 0, - 322, 320, 1934, 1958, 1964, 1990, 2047, 2059, 2060, 2099, - 2151, 2152, 2184, 2227, 2243, 2244, 2245, 2257, 0, 0, - 1024, 0, 796, 0, 0, 801, 1398, 796, 359, 737, - 738, 826, 852, 697, 0, 397, 0, 1980, 401, 2234, + 1453, 1454, 1455, 1456, 2259, 2229, -2, 1992, 1966, 2153, + 2154, 2049, 2061, 1960, 2297, 2298, 2299, 2300, 2301, 2302, + 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, + 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, + 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, + 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, + 2343, 2344, 2345, 2346, 1922, 1923, 1924, 1925, 1926, 1927, + 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, + 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, + 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, + 1958, 1959, 1961, 1962, 1963, 1964, 1965, 1967, 1968, 1969, + 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, + 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, + 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, + 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, + 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, + 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2050, 2051, + 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2063, + 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, + 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, + 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, + 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, + 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, + 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, + 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, + 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, + 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2155, + 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, + 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, + 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, + -2, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, + 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, + 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, + 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, + 2226, 2227, 2228, 2230, 2231, 2232, 2233, 2234, 2235, 2236, + 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, -2, -2, + -2, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, + 2257, 2258, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, + 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, + 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 0, + 322, 320, 1936, 1960, 1966, 1992, 2049, 2061, 2062, 2101, + 2153, 2154, 2186, 2229, 2245, 2246, 2247, 2259, 0, 0, + 1026, 0, 796, 0, 0, 801, 1400, 796, 359, 737, + 738, 826, 854, 697, 0, 397, 0, 1982, 401, 2236, 0, 0, 0, 0, 694, 391, 392, 393, 394, 395, - 396, 0, 0, 997, 0, 0, 387, 0, 353, 2049, - 2256, 1455, 0, 0, 0, 0, 0, 209, 1150, 211, - 1152, 215, 223, 0, 0, 0, 228, 229, 232, 233, + 396, 0, 0, 999, 0, 0, 387, 0, 353, 2051, + 2258, 1457, 0, 0, 0, 0, 0, 209, 1152, 211, + 1154, 215, 223, 0, 0, 0, 228, 229, 232, 233, 234, 235, 236, 0, 240, 0, 242, 245, 0, 247, - 248, 0, 251, 252, 253, 0, 263, 264, 265, 1153, - 1154, 1155, -2, 138, 1022, 1891, 1777, 0, 1784, 1797, - 1808, 1537, 1538, 1539, 1540, 0, 0, 0, 0, 0, - 0, 1548, 1549, 0, 1579, 2299, 2340, 2341, 0, 1557, - 1558, 1559, 1560, 1561, 1562, 0, 149, 161, 162, 1830, - 1831, 1832, 1833, 1834, 1835, 1836, 0, 1838, 1839, 1840, - 1748, 1524, 1451, 0, 2308, 0, 2330, 2335, 2336, 2337, - 2338, 2329, 0, 0, 1732, 0, 1722, 0, 0, -2, - -2, 0, 0, 2124, -2, 2342, 2343, 2344, 2305, 2326, - 2334, 2309, 2310, 2333, 2301, 2302, 2303, 2296, 2297, 2298, - 2300, 2312, 2314, 2325, 0, 2321, 2331, 2332, 2232, 0, - 0, 2279, 0, 0, 0, 2274, 163, 164, -2, -2, + 248, 0, 251, 252, 253, 0, 263, 264, 265, 1155, + 1156, 1157, -2, 138, 1024, 1893, 1779, 0, 1786, 1799, + 1810, 1539, 1540, 1541, 1542, 0, 0, 0, 0, 0, + 0, 1550, 1551, 0, 1581, 2301, 2342, 2343, 0, 1559, + 1560, 1561, 1562, 1563, 1564, 0, 149, 161, 162, 1832, + 1833, 1834, 1835, 1836, 1837, 1838, 0, 1840, 1841, 1842, + 1750, 1526, 1453, 0, 2310, 0, 2332, 2337, 2338, 2339, + 2340, 2331, 0, 0, 1734, 0, 1724, 0, 0, -2, + -2, 0, 0, 2126, -2, 2344, 2345, 2346, 2307, 2328, + 2336, 2311, 2312, 2335, 2303, 2304, 2305, 2298, 2299, 2300, + 2302, 2314, 2316, 2327, 0, 2323, 2333, 2334, 2234, 0, + 0, 2281, 0, 0, 0, 2276, 163, 164, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, 1743, -2, 1745, -2, 1747, - -2, 1750, -2, -2, -2, -2, 1755, 1756, -2, 1758, - -2, -2, -2, -2, -2, -2, -2, 1734, 1735, 1736, - 1737, 1726, 1727, 1728, 1729, 1730, 1731, -2, -2, -2, - 852, 945, 0, 852, 0, 827, 874, 877, 880, 883, + -2, -2, -2, -2, -2, 1745, -2, 1747, -2, 1749, + -2, 1752, -2, -2, -2, -2, 1757, 1758, -2, 1760, + -2, -2, -2, -2, -2, -2, -2, 1736, 1737, 1738, + 1739, 1728, 1729, 1730, 1731, 1732, 1733, -2, -2, -2, + 854, 947, 0, 854, 0, 827, 876, 879, 882, 885, 830, 0, 0, 111, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 349, 337, 339, - 0, 343, 0, 0, 339, 336, 330, 0, 1192, 1192, - 1192, 0, 0, 0, 1192, 1192, 1192, 1192, 1192, 0, - 1192, 0, 0, 0, 0, 0, 1192, 0, 1059, 1157, - 1158, 1159, 1190, 1191, 1284, 0, 0, 0, 753, 749, + 0, 343, 0, 0, 339, 336, 330, 0, 1194, 1194, + 1194, 0, 0, 0, 1194, 1194, 1194, 1194, 1194, 0, + 1194, 0, 0, 0, 0, 0, 1194, 0, 1061, 1159, + 1160, 1161, 1192, 1193, 1286, 0, 0, 0, 753, 749, 750, 751, 752, 840, 0, 842, 845, 0, 0, 674, - 674, 912, 912, 0, 620, 0, 0, 0, 674, 0, + 674, 914, 914, 0, 620, 0, 0, 0, 674, 0, 634, 626, 0, 0, 0, 674, 0, 0, 847, 847, 0, 677, 684, 674, 674, -2, 674, 674, 671, 674, - 0, 0, 1206, 640, 641, 642, 626, 626, 645, 646, - 647, 657, 658, 685, 1915, 0, 0, 548, 548, 0, - 548, 548, 0, 548, 548, 548, 0, 755, 2006, 2094, - 1987, 2065, 1944, 2049, 2256, 0, 295, 2124, 300, 0, - 1989, 2009, 0, 0, 2028, 0, -2, 0, 375, 852, + 0, 0, 1208, 640, 641, 642, 626, 626, 645, 646, + 647, 657, 658, 685, 1917, 0, 0, 548, 548, 0, + 548, 548, 0, 548, 548, 548, 0, 755, 2008, 2096, + 1989, 2067, 1946, 2051, 2258, 0, 295, 2126, 300, 0, + 1991, 2011, 0, 0, 2030, 0, -2, 0, 375, 854, 0, 0, 826, 0, 0, 0, 0, 548, 548, 548, - 548, 548, 1283, 548, 548, 548, 548, 548, 0, 0, - 0, 548, 548, 548, 548, 0, 888, 889, 891, 892, - 893, 894, 895, 896, 897, 898, 899, 900, 5, 6, + 548, 548, 1285, 548, 548, 548, 548, 548, 0, 0, + 0, 548, 548, 548, 548, 0, 890, 891, 893, 894, + 895, 896, 897, 898, 899, 900, 901, 902, 5, 6, 19, 0, 0, 0, 0, 0, 0, 117, 116, 0, - 1892, 1910, 1843, 1844, 1845, 1897, 1847, 1901, 1901, 1901, - 1901, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, - 1885, 1901, 1901, 0, 0, 1890, 1867, 1899, 1899, 1899, - 1897, 1894, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, - 1856, 1857, 1858, 1859, 1860, 1861, 1904, 1904, 1907, 1907, - 1904, 0, 439, 437, 438, 1773, 0, 0, 0, 0, - 796, 800, 1396, 0, 0, 0, 852, -2, 0, 0, - 698, 398, 1456, 0, 0, 402, 0, 403, 0, 0, + 1894, 1912, 1845, 1846, 1847, 1899, 1849, 1903, 1903, 1903, + 1903, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, + 1887, 1903, 1903, 0, 0, 1892, 1869, 1901, 1901, 1901, + 1899, 1896, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, + 1858, 1859, 1860, 1861, 1862, 1863, 1906, 1906, 1909, 1909, + 1906, 0, 439, 437, 438, 1775, 0, 0, 0, 0, + 796, 800, 1398, 0, 0, 0, 854, -2, 0, 0, + 698, 398, 1458, 0, 0, 402, 0, 403, 0, 0, 405, 0, 0, 0, 427, 0, 430, 413, 414, 415, 416, 417, 409, 0, 189, 0, 389, 390, 0, 0, 355, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 220, 216, 224, 227, 237, 244, 0, 256, 258, 261, 217, 225, 230, 231, 238, 259, 218, 221, 222, 226, 260, 262, 219, 239, 243, 257, 241, 246, 249, - 250, 255, 0, 190, 0, 0, 0, 0, 0, 1783, - 0, 0, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -2, 1777, - 0, 0, 1543, 1544, 1545, 1546, 0, 1550, 0, 1580, - 0, 0, 0, 0, 0, 0, 1837, 1841, 0, 1773, - 1773, 0, 1773, 1769, 0, 0, 0, 0, 0, 0, - 1773, 1705, 0, 0, 1707, 1723, 0, 0, 1709, 1710, - 0, 1713, 1714, 1773, 0, 1773, 1718, 1773, 1773, 1773, - 1701, 1702, 0, 1769, 1769, 1769, 1769, 0, 0, 1769, - 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, - 1769, 1769, 1769, 1769, 0, 0, 0, 0, 847, 0, - 853, 0, -2, 0, 871, 873, 875, 876, 878, 879, - 881, 882, 884, 885, 832, 0, 0, 113, 0, 0, + 250, 255, 0, 190, 0, 0, 0, 0, 0, 1785, + 0, 0, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2, 1779, + 0, 0, 1545, 1546, 1547, 1548, 0, 1552, 0, 1582, + 0, 0, 0, 0, 0, 0, 1839, 1843, 0, 1775, + 1775, 0, 1775, 1771, 0, 0, 0, 0, 0, 0, + 1775, 1707, 0, 0, 1709, 1725, 0, 0, 1711, 1712, + 0, 1715, 1716, 1775, 0, 1775, 1720, 1775, 1775, 1775, + 1703, 1704, 0, 1771, 1771, 1771, 1771, 0, 0, 1771, + 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, + 1771, 1771, 1771, 1771, 0, 0, 0, 0, 847, 0, + 855, 0, -2, 0, 873, 875, 877, 878, 880, 881, + 883, 884, 886, 887, 832, 0, 0, 113, 0, 0, 0, 96, 0, 0, 94, 0, 0, 0, 0, 72, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 0, 346, 332, 2086, 0, 331, 0, 0, - 0, 0, 0, 1021, 0, 0, 1192, 1192, 1192, 1060, - 0, 0, 0, 0, 0, 0, 0, 0, 1192, 1192, - 1192, 1192, 0, 1212, 0, 0, 0, 755, 754, 0, - 841, 0, 0, 71, 609, 610, 611, 912, 0, 0, + 0, 341, 0, 346, 332, 2088, 0, 331, 0, 0, + 0, 0, 0, 1023, 0, 0, 1194, 1194, 1194, 1062, + 0, 0, 0, 0, 0, 0, 0, 0, 1194, 1194, + 1194, 1194, 0, 1214, 0, 0, 0, 755, 754, 0, + 841, 0, 0, 71, 609, 610, 611, 914, 0, 0, 613, 614, 0, 615, 0, 0, 626, 674, 674, 632, - 633, 628, 627, 680, 681, 677, 0, 677, 677, 912, + 633, 628, 627, 680, 681, 677, 0, 677, 677, 914, 0, 651, 652, 653, 674, 674, 659, 848, 0, 660, - 661, 677, 0, 682, 683, 912, 0, 0, 912, 912, - 0, 669, 670, 672, 674, 0, 0, 1192, 0, 690, - 628, 628, 1916, 1917, 0, 0, 1203, 0, 0, 0, + 661, 677, 0, 682, 683, 914, 0, 0, 914, 914, + 0, 669, 670, 672, 674, 0, 0, 1194, 0, 690, + 628, 628, 1918, 1919, 0, 0, 1205, 0, 0, 0, 0, 693, 0, 0, 0, 455, 456, 0, 0, 756, - 0, 274, 278, 0, 281, 0, 2094, 0, 2094, 0, + 0, 274, 278, 0, 281, 0, 2096, 0, 2096, 0, 0, 288, 0, 0, 0, 0, 0, 0, 318, 319, - 0, 0, 0, 0, 309, 312, 1390, 1391, 1147, 1148, - 313, 314, 367, 368, 0, 847, 870, 872, 866, 867, - 868, 0, 1194, 0, 0, 0, 0, 0, 548, 0, - 0, 0, 0, 0, 731, 0, 1039, 733, 0, 0, - 0, 0, 0, 920, 914, 916, 992, 149, 890, 8, + 0, 0, 0, 0, 309, 312, 1392, 1393, 1149, 1150, + 313, 314, 367, 368, 0, 847, 872, 874, 868, 869, + 870, 0, 1196, 0, 0, 0, 0, 0, 548, 0, + 0, 0, 0, 0, 731, 0, 1041, 733, 0, 0, + 0, 0, 0, 922, 916, 918, 994, 149, 892, 8, 134, 131, 0, 19, 0, 0, 19, 19, 0, 19, - 323, 0, 1913, 1911, 1912, 1846, 1898, 0, 1872, 0, - 1873, 1874, 1875, 1886, 1887, 0, 0, 1868, 0, 1869, - 1870, 1871, 1862, 0, 1863, 1864, 0, 1865, 1866, 321, - 436, 0, 0, 1774, 1025, 0, 774, 788, 769, 0, - 777, 0, 0, 1398, 0, 0, 0, 0, 757, 788, + 323, 0, 1915, 1913, 1914, 1848, 1900, 0, 1874, 0, + 1875, 1876, 1877, 1888, 1889, 0, 0, 1870, 0, 1871, + 1872, 1873, 1864, 0, 1865, 1866, 0, 1867, 1868, 321, + 436, 0, 0, 1776, 1027, 0, 774, 788, 769, 0, + 777, 0, 0, 1400, 0, 0, 0, 0, 757, 788, 759, 0, 777, 847, 824, 0, 802, 0, 0, 399, 0, 410, 404, 0, 411, 406, 407, 0, 0, 429, 431, 432, 433, 434, 418, 419, 695, 384, 385, 386, 376, 377, 378, 379, 380, 381, 382, 383, 0, 0, 388, 159, 0, 356, 357, 0, 0, 0, 203, 204, - 205, 206, 207, 208, 210, 194, 720, 722, 1139, 1151, - 0, 1142, 0, 213, 254, 186, 0, 0, 0, 1778, - 1779, 1780, 1781, 1782, 1787, 0, 1789, 1791, 1793, 1795, - 0, 1813, -2, -2, 1525, 1526, 1527, 1528, 1529, 1530, - 1531, 1532, 1533, 1534, 1535, 1536, 1798, 1811, 1812, 0, - 0, 0, 0, 0, 0, 1809, 1809, 1804, 0, 1563, - 1392, 1393, 1541, 0, 0, 1577, 1581, 0, 0, 0, - 0, 0, 0, 1174, 1897, 0, 150, 1768, 1672, 1673, - 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, - 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, - 1694, 1695, 1696, 1697, 1698, 1699, 1700, 0, 0, 1777, - 0, 0, 0, 1770, 1771, 0, 0, 0, 1660, 0, - 0, 1666, 1667, 1668, 0, 783, 0, 1733, 1706, 1724, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 944, 946, + 205, 206, 207, 208, 210, 194, 720, 722, 1141, 1153, + 0, 1144, 0, 213, 254, 186, 0, 0, 0, 1780, + 1781, 1782, 1783, 1784, 1789, 0, 1791, 1793, 1795, 1797, + 0, 1815, -2, -2, 1527, 1528, 1529, 1530, 1531, 1532, + 1533, 1534, 1535, 1536, 1537, 1538, 1800, 1813, 1814, 0, + 0, 0, 0, 0, 0, 1811, 1811, 1806, 0, 1565, + 1394, 1395, 1543, 0, 0, 1579, 1583, 0, 0, 0, + 0, 0, 0, 1176, 1899, 0, 150, 1770, 1674, 1675, + 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, + 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, + 1696, 1697, 1698, 1699, 1700, 1701, 1702, 0, 0, 1779, + 0, 0, 0, 1772, 1773, 0, 0, 0, 1662, 0, + 0, 1668, 1669, 1670, 0, 783, 0, 1735, 1708, 1726, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 946, 948, 0, 792, 794, 795, 821, 802, 828, 0, 0, 0, - 109, 114, 0, 1251, 102, 0, 0, 0, 102, 0, - 0, 0, 102, 0, 0, 75, 1207, 76, 1209, 0, + 109, 114, 0, 1253, 102, 0, 0, 0, 102, 0, + 0, 0, 102, 0, 0, 75, 1209, 76, 1211, 0, 0, 0, 0, 0, 0, 350, 351, 0, 0, 345, - 333, 2086, 335, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1075, 1076, 546, 1133, 0, 0, - 0, 1149, 1178, 1188, 0, 0, 0, 0, 0, 1257, - 1061, 1066, 1067, 1068, 1062, 1063, 1069, 1070, 0, 843, - 0, 0, 961, 612, 675, 676, 913, 616, 0, 0, - 623, 2049, 628, 912, 912, 635, 629, 636, 679, 637, - 638, 639, 677, 912, 912, 849, 674, 677, 662, 678, - 677, 1398, 666, 0, 673, 1398, 691, 1398, 0, 689, - 643, 644, 1259, 845, 453, 454, 459, 461, 0, 513, - 513, 513, 493, 513, 0, 0, 481, 1918, 0, 0, - 0, 0, 490, 1918, 0, 0, 1918, 1918, 1918, 1918, - 1918, 1918, 1918, 0, 0, 1918, 1918, 1918, 1918, 1918, - 1918, 1918, 1918, 1918, 1918, 1918, 0, 1918, 1918, 1918, - 1918, 1918, 1376, 1918, 0, 1204, 503, 504, 505, 506, - 511, 512, 0, 0, 541, 0, 0, 1074, 0, 546, - 0, 0, 1116, 0, 0, 925, 0, 926, 927, 928, - 923, 963, 987, 987, 0, 987, 967, 1398, 0, 0, + 333, 2088, 335, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1077, 1078, 546, 1135, 0, 0, + 0, 1151, 1180, 1190, 0, 0, 0, 0, 0, 1259, + 1063, 1068, 1069, 1070, 1064, 1065, 1071, 1072, 0, 843, + 0, 0, 963, 612, 675, 676, 915, 616, 0, 0, + 623, 2051, 628, 914, 914, 635, 629, 636, 679, 637, + 638, 639, 677, 914, 914, 852, 674, 677, 662, 678, + 677, 1400, 666, 0, 673, 1400, 691, 1400, 0, 689, + 643, 644, 1261, 845, 453, 454, 459, 461, 0, 513, + 513, 513, 493, 513, 0, 0, 481, 1920, 0, 0, + 0, 0, 490, 1920, 0, 0, 1920, 1920, 1920, 1920, + 1920, 1920, 1920, 0, 0, 1920, 1920, 1920, 1920, 1920, + 1920, 1920, 1920, 1920, 1920, 1920, 0, 1920, 1920, 1920, + 1920, 1920, 1378, 1920, 0, 1206, 503, 504, 505, 506, + 511, 512, 0, 0, 541, 0, 0, 1076, 0, 546, + 0, 0, 1118, 0, 0, 927, 0, 928, 929, 930, + 925, 965, 989, 989, 0, 989, 969, 1400, 0, 0, 0, 286, 287, 275, 0, 276, 0, 0, 289, 290, - 0, 292, 293, 294, 301, 1987, 2065, 296, 298, 0, + 0, 292, 293, 294, 301, 1989, 2067, 296, 298, 0, 0, 302, 315, 316, 317, 0, 0, 307, 308, 0, - 0, 370, 371, 373, 0, 802, 1208, 73, 1195, 717, - 1394, 718, 719, 723, 0, 0, 726, 727, 728, 729, - 730, 1041, 0, 0, 1125, 1126, 1127, 1194, 912, 0, - 921, 0, 917, 993, 0, 995, 0, 0, 132, 19, - 0, 125, 122, 0, 0, 0, 0, 0, 1893, 1842, - 1914, 0, 0, 0, 1895, 0, 0, 0, 0, 0, + 0, 370, 371, 373, 0, 802, 1210, 73, 1197, 717, + 1396, 718, 719, 723, 0, 0, 726, 727, 728, 729, + 730, 1043, 0, 0, 1127, 1128, 1129, 1196, 914, 0, + 923, 0, 919, 995, 0, 997, 0, 0, 132, 19, + 0, 125, 122, 0, 0, 0, 0, 0, 1895, 1844, + 1916, 0, 0, 0, 1897, 0, 0, 0, 0, 0, 115, 804, 764, 0, 768, 785, 0, 789, 0, 0, - 781, 773, 778, 0, 0, 798, 765, 1397, 0, 0, - 0, 0, 758, 0, 0, 763, 802, 0, 825, 854, - 855, 858, 1457, 0, 412, 408, 428, 0, 0, 0, - 0, 197, 1136, 0, 198, 202, 192, 0, 0, 0, - 1141, 0, 1138, 1143, 0, 212, 0, 0, 187, 188, - 1242, 1251, 0, 0, 0, 1788, 1790, 1792, 1794, 1796, - 0, 1799, 1809, 1809, 1805, 0, 1800, 0, 1802, 0, - 1778, 1547, 0, 1582, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 858, 0, 0, 1650, 1651, 0, 0, - 1655, 0, 1657, 1658, 1659, 1661, 0, 0, 0, 1665, - 0, 1704, 1725, 1708, 1711, 0, 1715, 0, 1717, 1719, - 1720, 1721, 0, 852, 852, 0, 0, 1621, 1621, 1621, - 0, 0, 0, 0, 1621, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1566, 0, 1567, 1568, - 0, 0, 0, 947, 822, 0, 0, 0, 0, 0, - 1249, 0, 92, 0, 97, 0, 0, 93, 98, 0, - 0, 95, 0, 104, 77, 0, 0, 1215, 1216, 0, - 0, 352, 340, 342, 0, 334, 0, 1193, 0, 0, - 0, 0, -2, 1041, 845, 0, 845, 1086, 1918, 550, - 0, 0, 1135, 0, 1105, 0, 0, 0, -2, 0, - 0, 0, 1188, 0, 0, 0, 1261, 0, 0, 0, + 781, 773, 778, 0, 0, 798, 765, 1399, 0, 0, + 0, 0, 758, 0, 0, 763, 802, 0, 825, 856, + 857, 860, 1459, 0, 412, 408, 428, 0, 0, 0, + 0, 197, 1138, 0, 198, 202, 192, 0, 0, 0, + 1143, 0, 1140, 1145, 0, 212, 0, 0, 187, 188, + 1244, 1253, 0, 0, 0, 1790, 1792, 1794, 1796, 1798, + 0, 1801, 1811, 1811, 1807, 0, 1802, 0, 1804, 0, + 1780, 1549, 0, 1584, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 860, 0, 0, 1652, 1653, 0, 0, + 1657, 0, 1659, 1660, 1661, 1663, 0, 0, 0, 1667, + 0, 1706, 1727, 1710, 1713, 0, 1717, 0, 1719, 1721, + 1722, 1723, 0, 854, 854, 0, 0, 1623, 1623, 1623, + 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1568, 0, 1569, 1570, + 0, 0, 0, 949, 822, 0, 0, 0, 0, 0, + 1251, 0, 92, 0, 97, 0, 0, 93, 98, 0, + 0, 95, 0, 104, 77, 0, 0, 1217, 1218, 0, + 0, 352, 340, 342, 0, 334, 0, 1195, 0, 0, + 0, 0, -2, 1043, 845, 0, 845, 1088, 1920, 550, + 0, 0, 1137, 0, 1107, 0, 0, 0, -2, 0, + 0, 0, 1190, 0, 0, 0, 1263, 0, 0, 0, 742, 746, 23, 846, 0, 619, 617, 0, 621, 0, - 622, 674, 630, 631, 912, 654, 655, 0, 0, 912, - 674, 674, 665, 677, 686, 0, 687, 1398, 1261, 0, - 0, 1203, 1327, 1295, 471, 0, 1411, 1412, 514, 0, - 1418, 1427, 1192, 1489, 0, 1427, 0, 0, 1429, 1430, - 0, 0, 0, 0, 494, 495, 0, 480, 0, 0, - 0, 0, 0, 0, 479, 0, 0, 524, 0, 0, - 0, 0, 0, 1919, 1918, 1918, 0, 488, 489, 0, - 492, 0, 0, 0, 0, 0, 0, 0, 0, 1918, - 1918, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1367, 0, 0, 0, 0, 0, 0, 0, - 1382, 1383, 0, 1086, 1918, 0, 0, 0, 0, 550, - 1130, 1130, 1103, 1121, 0, 457, 458, 521, 0, 0, - 0, 0, 0, 0, 0, 953, 0, 0, 0, 952, - 0, 0, 0, 0, 0, 0, 0, 845, 988, 0, - 990, 991, 965, -2, 0, 925, 970, 1773, 0, 279, - 280, 0, 0, 285, 303, 305, 277, 0, 0, 0, - 304, 306, 310, 311, 369, 372, 374, 864, 0, 0, - 1285, 0, 1042, 1043, 1045, 1046, 0, -2, -2, -2, + 622, 674, 630, 631, 914, 654, 655, 849, 0, 0, + 0, 914, 674, 674, 665, 677, 686, 0, 687, 1400, + 1263, 0, 0, 1205, 1329, 1297, 471, 0, 1413, 1414, + 514, 0, 1420, 1429, 1194, 1491, 0, 1429, 0, 0, + 1431, 1432, 0, 0, 0, 0, 494, 495, 0, 480, + 0, 0, 0, 0, 0, 0, 479, 0, 0, 524, + 0, 0, 0, 0, 0, 1921, 1920, 1920, 0, 488, + 489, 0, 492, 0, 0, 0, 0, 0, 0, 0, + 0, 1920, 1920, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1369, 0, 0, 0, 0, 0, + 0, 0, 1384, 1385, 0, 1088, 1920, 0, 0, 0, + 0, 550, 1132, 1132, 1105, 1123, 0, 457, 458, 521, + 0, 0, 0, 0, 0, 0, 0, 955, 0, 0, + 0, 954, 0, 0, 0, 0, 0, 0, 0, 845, + 990, 0, 992, 993, 967, -2, 0, 927, 972, 1775, + 0, 279, 280, 0, 0, 285, 303, 305, 277, 0, + 0, 0, 304, 306, 310, 311, 369, 372, 374, 866, + 0, 0, 1287, 0, 1044, 1045, 1047, 1048, 0, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - 1971, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, 1973, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, 1040, 734, 1128, 903, 915, 922, 994, 996, - 150, 918, 0, 135, 19, 134, 126, 127, 0, 19, - 0, 0, 0, 0, 1903, 1902, 1888, 0, 1889, 1900, - 1905, 0, 1908, 0, 440, 808, 0, 0, 788, 790, - 0, 0, 788, 0, 0, 797, 0, 0, 0, 0, - 0, 0, 0, 788, 864, 804, 0, 861, 859, 860, - 0, 0, 696, 160, 435, 0, 0, 0, 0, 0, - 721, 0, 1140, 194, 0, 0, 214, 0, 0, 0, - 1251, 1246, 1772, 1801, 1803, 0, 1810, 1806, 1542, 1551, - 1578, 0, 0, 1584, 1596, 1596, 0, 0, 0, 1587, - 1901, 1901, 1590, 1897, 1899, 1897, 1596, 1596, 0, 1175, - 0, 1176, 858, 151, 0, 0, 1656, 0, 0, 0, - 784, 0, 0, 0, 1617, 1619, 1621, 1621, 1628, 1622, - 1629, 1630, 1621, 1621, 1621, 1621, 1635, 1621, 1621, 1621, - 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1615, 0, - 0, 1831, 1832, 793, 0, 0, 835, 836, 837, 838, - 839, 0, 0, 62, 62, 1251, 0, 0, 0, 0, - 0, 108, 0, 0, 0, 0, 0, 1219, 1224, 344, - 0, 78, 79, 81, 0, 0, 0, 0, 0, 0, - 0, 91, 0, 0, 1027, 1028, 1030, 0, 1033, 1034, - 1035, 0, 0, 1404, 0, 1090, 1087, 1088, 1089, 0, - 1130, 551, 552, 553, 554, 0, 0, 0, 1134, 0, - 0, 1098, 0, 0, 0, 1179, 1180, 1181, 1182, 1183, - 1184, 1185, 1186, -2, 1198, 0, 1398, 0, 0, 1404, - 1234, 0, 0, 1239, 0, 1404, 1404, 0, 1269, 0, - 1258, 796, 0, -2, 0, 0, 744, 0, 0, 962, - 618, 624, 912, 648, 850, 851, 1398, 912, 912, 674, - 692, 688, 1269, 1260, 0, 460, 513, 0, 1315, 0, - 0, 1321, 0, 1328, 464, 0, 515, 0, 1417, 1445, - 1428, 1445, 1490, 1445, 1445, 1192, 0, 515, 0, 0, - 482, 0, 0, 0, 0, 0, 478, 518, 858, 465, - 467, 468, 469, 522, 523, 525, 0, 527, 528, 484, - 496, 497, 498, 499, 500, 501, 502, 0, 0, 0, - 491, 507, 508, 509, 510, 466, 1344, 1345, 1346, 1349, - 1350, 1351, 1352, 0, 0, 1355, 1356, 1357, 1358, 1359, - 1442, 1443, 1444, 1360, 1361, 1362, 1363, 1364, 1365, 1366, - 1384, 1385, 1386, 1387, 1388, 1389, 1368, 1369, 1370, 1371, - 1372, 1373, 1374, 1375, 0, 0, 1379, 0, 0, 1090, - 0, 0, 0, 0, 0, 1130, 544, 0, 0, 545, - 1105, 0, 1123, 0, 1117, 1118, 0, 0, 766, 912, - 362, 0, 957, 948, 0, 932, 0, 934, 954, 935, - 955, 0, 0, 939, 0, 941, 0, 937, 938, 943, - 936, 912, 924, 964, 989, 966, 969, 971, 972, 978, - 0, 0, 0, 0, 273, 282, 283, 284, 291, 0, - 570, 297, 820, 0, 1395, 724, 725, 1286, 1287, 732, - 0, 1047, 901, 0, 0, 130, 133, 0, 128, 0, - 0, 0, 0, 120, 118, 1896, 0, 0, 810, 174, - 0, 0, 0, 786, 0, 791, 788, 772, 782, 771, - 779, 780, 799, 1399, 1400, 1401, 1402, 0, 788, 762, - 761, 823, 808, 856, 857, 0, 1458, 400, 0, 1137, - 194, 199, 200, 201, 195, 193, 1144, 0, 1146, 0, - 1244, 0, 0, 1807, 1583, 1552, 1585, 1597, 1598, 1586, - 0, 1554, 1555, 1588, 1589, 1591, 1592, 1593, 1594, 1595, - 1556, 0, 1177, 1652, 0, 1654, 1662, 1663, 0, 1712, - 1716, 0, 0, 0, 0, 0, 1626, 1627, 1631, 1632, - 1633, 1634, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, - 1644, 1645, 1646, 852, 1616, 0, 0, 0, 0, 0, - 0, 0, 833, 0, 0, 0, 64, 0, 64, 1250, - 1252, 103, 105, 0, 99, 100, 101, 992, 1228, 1398, - 1217, 0, 1218, 0, 0, 80, 82, 0, 2050, 0, - 0, 0, 0, 1194, 1020, 1036, 1032, 0, 0, 0, - 0, 1405, 1406, 1408, 1409, 1410, 0, 1058, 0, 0, - 1078, 1079, 1080, 1092, 0, 556, 557, 0, 0, 0, - 569, 565, 566, 567, 547, 1129, 1112, 0, 0, 1101, - 0, 0, 1111, 0, 1199, 1918, 1918, 1918, 1228, 0, - 0, 1329, 1918, 1918, 0, 1236, 1238, 1228, 0, 0, - 1333, 1272, 0, 0, 1263, 0, 987, 0, 0, 912, - 743, 746, 747, 844, 625, 663, 667, 664, 912, 1272, - 452, 1293, 0, 0, 0, 0, 0, 1325, 0, 0, - 1297, 0, 483, 516, 0, -2, 0, 1446, 0, 1431, - 1446, 0, 0, 1445, 0, 472, 515, 0, 0, 0, - 529, 534, 535, 0, 531, 532, 1485, 0, 533, 0, - 520, 0, 526, 1347, 1348, 0, 1353, 1354, 0, 1378, - 0, 0, 463, 536, 0, 0, 0, 537, 538, 543, - 1131, 1132, 1098, 0, 1112, 0, 1122, 0, 1119, 1120, - 852, 0, 0, 929, 958, 0, 0, 930, 0, 931, - 933, 956, 0, 950, 940, 942, 361, 973, 0, 0, - 975, 976, 977, 968, 299, 865, 1044, 0, 886, 0, - 0, 919, 0, 19, 0, 0, 123, 1906, 1909, 812, - 0, 809, 175, 0, 0, 0, 0, 776, 787, 770, - 1403, 760, 810, 862, 863, 196, 191, 1145, 1254, 0, - 1245, 0, 1509, 1565, 0, 1664, 0, 1621, 1618, 1621, - 1620, 1612, 0, 1569, 0, 1571, 1572, 1573, 0, 1575, - 1576, 0, 831, 0, 60, 0, 63, 61, 0, 107, - 1213, 0, 1228, 0, 0, 0, 1223, 0, 0, 83, - 0, 0, 0, 0, 0, 0, 89, 0, 0, 1029, - 1031, 0, 1064, 1333, 0, 1064, 1091, 1077, 0, 0, - 558, 559, 0, 562, 568, 1093, 0, 0, 1095, 1096, - 1097, 0, 0, 1109, 0, 0, 0, 0, 1187, 1189, - 1205, 0, 0, 0, -2, 1240, 0, -2, 1233, 0, - 1278, 0, 1270, 0, 1262, 0, 1265, 912, 912, -2, - 740, 745, 0, 668, 1278, 1295, 0, 1316, 0, 0, - 0, 0, 0, 0, 0, 1296, 0, 1309, 517, 1447, - -2, 1461, 1463, 0, 1204, 1466, 1467, 0, 0, 0, - 0, 0, 0, 1516, 1475, 0, 0, 1479, 1480, 1481, - 0, 0, 1484, 0, 1825, 1826, 0, 1488, 0, 0, - 0, 0, 0, 0, 0, 1425, 473, 474, 0, 476, - 477, 1918, 1486, 519, 470, 1918, 486, 1377, 1380, 1381, - 542, 539, 540, 1101, 1104, 1115, 1124, 767, 847, 363, - 364, 959, 0, 949, 951, 982, 979, 0, 0, 1048, - 902, 910, 2279, 2281, 2278, 124, 129, 0, 0, 814, - 0, 811, 0, 805, 807, 185, 775, 812, 145, 177, - 0, 0, 1553, 0, 0, 0, 1653, 1703, 1624, 1625, - 0, 1613, 0, 1607, 1608, 1609, 1614, 0, 0, 834, - 829, 65, 106, 0, 1214, 1220, 1221, 1222, 1225, 1226, - 1227, 69, 1194, 0, 1194, 0, 0, 0, 1023, 1037, - 0, 1050, 1057, 1071, 1210, 1407, 1056, 0, 0, 555, - 560, 0, 563, 564, 1113, 1112, 0, 1099, 1100, 0, - 1107, 0, 0, 1200, 1201, 1202, 1330, 1331, 1332, 1288, - 1235, 0, -2, 1341, 0, 1231, 1254, 1288, 0, 1266, - 0, 1273, 0, 1271, 1264, 852, 741, 1275, 462, 1327, - 1317, 0, 1319, 0, 0, 0, 0, 1298, -2, 0, - 1462, 1464, 1465, 1468, 1469, 1470, 1521, 1522, 1523, 0, - 0, 1473, 1518, 1519, 1520, 1474, 0, 0, 0, 0, - 0, 1823, 1824, 1514, 0, 0, 1432, 1434, 1435, 1436, - 1437, 1438, 1439, 1440, 1441, 1433, 0, 0, 0, 1424, - 1426, 475, 0, 0, 1918, 1114, 360, 0, 0, 983, - 985, 980, 981, 904, 0, 0, 0, 0, 119, 121, - 136, 0, 813, 176, 0, 814, 147, 0, 168, 0, - 1255, 0, 1564, 0, 0, 0, 1623, 1610, 0, 0, - 0, 0, 0, 1827, 1828, 1829, 0, 1570, 1574, 1229, - 0, 67, 0, 84, 1194, 85, 1194, 0, 0, 0, - 0, 1072, 1073, 1081, 1082, 0, 1084, 1085, 561, 1094, - 1102, 1106, 1109, 0, 1161, 1290, 0, 1237, 1203, 1343, - 1918, 1241, 1290, 0, 1335, 1918, 1918, 1256, 0, 1268, - 0, 1280, 0, 1274, 847, 451, 0, 1277, 1313, 1318, - 1320, 1322, 0, 1326, 1324, 1299, -2, 0, 1307, 0, - 0, 1471, 1472, 0, 0, 1722, 1918, 0, 1504, 0, - 1161, 1161, 1161, 1161, 0, 530, 485, 0, 960, 974, - 0, 911, 0, 0, 0, 0, 0, 803, 137, 0, - 146, 165, 0, 178, 179, 0, 0, 0, 0, 1247, - 0, 1512, 1513, 0, 1599, 0, 0, 0, 1603, 1604, - 1605, 1606, 1194, 69, 0, 86, 87, 0, 1194, 0, - 1049, 0, 1083, 1108, 1110, 1160, 1230, 0, 1327, 1342, - 0, 1232, 1334, 0, 0, 0, 1267, 1279, 0, 1282, - 739, 1276, 1294, 0, 1323, 1300, 1308, 0, 1303, 0, - 0, 0, 1517, 0, 1478, 0, 1483, 1492, 1505, 0, - 0, 1413, 0, 1415, 0, 1419, 0, 1421, 0, 0, - 487, 984, 986, 0, 1773, 906, 907, 0, 816, 806, - 148, 152, 0, 174, 171, 0, 180, 0, 0, 0, - 0, 1243, 0, 1510, 0, 1600, 1601, 1602, 66, 68, - 70, 1194, 88, 0, 1051, 1052, 1065, 1162, 1918, 1918, - 0, 0, 0, 1168, 1169, 1918, 1918, 1918, 1173, 0, - 1315, 1347, 1336, 1337, 1338, 1281, 1314, 1302, 0, -2, - 1310, 0, 0, 1775, 1785, 1786, 1476, 1482, 1491, 1493, - 1494, 0, 1506, 1507, 1508, 1515, 1161, 1161, 1161, 1161, - 1423, 905, 0, 0, 815, 0, 139, 0, 0, 169, - 170, 172, 0, 181, 0, 183, 184, 0, 0, 1611, - 90, 1053, 0, 0, 1165, 1166, 0, 0, 0, 0, - 1291, 0, 1293, 1304, -2, 0, 1312, 0, 1477, 1495, - 0, 1496, 0, 0, 0, 1414, 1416, 1420, 1422, 1773, - 908, 817, 1253, 0, 153, 0, 155, 157, 158, 1448, - 166, 167, 173, 182, 0, 0, 1038, 1054, 0, 1163, - 1164, 1167, 1170, 1171, 1172, 0, 1295, 1311, 1776, 1497, - 1499, 1500, 0, 0, 1498, 0, 140, 141, 0, 154, - 0, 0, 1248, 1511, 1055, 1292, 1289, 1501, 1503, 1502, - 909, 0, 0, 156, 1449, 142, 143, 144, 0, 1450, + -2, -2, -2, -2, 1042, 734, 1130, 905, 917, 924, + 996, 998, 150, 920, 0, 135, 19, 134, 126, 127, + 0, 19, 0, 0, 0, 0, 1905, 1904, 1890, 0, + 1891, 1902, 1907, 0, 1910, 0, 440, 808, 0, 0, + 788, 790, 0, 0, 788, 0, 0, 797, 0, 0, + 0, 0, 0, 0, 0, 788, 866, 804, 0, 863, + 861, 862, 0, 0, 696, 160, 435, 0, 0, 0, + 0, 0, 721, 0, 1142, 194, 0, 0, 214, 0, + 0, 0, 1253, 1248, 1774, 1803, 1805, 0, 1812, 1808, + 1544, 1553, 1580, 0, 0, 1586, 1598, 1598, 0, 0, + 0, 1589, 1903, 1903, 1592, 1899, 1901, 1899, 1598, 1598, + 0, 1177, 0, 1178, 860, 151, 0, 0, 1658, 0, + 0, 0, 784, 0, 0, 0, 1619, 1621, 1623, 1623, + 1630, 1624, 1631, 1632, 1623, 1623, 1623, 1623, 1637, 1623, + 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, + 1617, 0, 0, 1833, 1834, 793, 0, 0, 835, 836, + 837, 838, 839, 0, 0, 62, 62, 1253, 0, 0, + 0, 0, 0, 108, 0, 0, 0, 0, 0, 1221, + 1226, 344, 0, 78, 79, 81, 0, 0, 0, 0, + 0, 0, 0, 91, 0, 0, 1029, 1030, 1032, 0, + 1035, 1036, 1037, 0, 0, 1406, 0, 1092, 1089, 1090, + 1091, 0, 1132, 551, 552, 553, 554, 0, 0, 0, + 1136, 0, 0, 1100, 0, 0, 0, 1181, 1182, 1183, + 1184, 1185, 1186, 1187, 1188, -2, 1200, 0, 1400, 0, + 0, 1406, 1236, 0, 0, 1241, 0, 1406, 1406, 0, + 1271, 0, 1260, 796, 0, -2, 0, 0, 744, 0, + 0, 964, 618, 624, 914, 648, 852, 852, 0, 1400, + 914, 914, 674, 692, 688, 1271, 1262, 0, 460, 513, + 0, 1317, 0, 0, 1323, 0, 1330, 464, 0, 515, + 0, 1419, 1447, 1430, 1447, 1492, 1447, 1447, 1194, 0, + 515, 0, 0, 482, 0, 0, 0, 0, 0, 478, + 518, 860, 465, 467, 468, 469, 522, 523, 525, 0, + 527, 528, 484, 496, 497, 498, 499, 500, 501, 502, + 0, 0, 0, 491, 507, 508, 509, 510, 466, 1346, + 1347, 1348, 1351, 1352, 1353, 1354, 0, 0, 1357, 1358, + 1359, 1360, 1361, 1444, 1445, 1446, 1362, 1363, 1364, 1365, + 1366, 1367, 1368, 1386, 1387, 1388, 1389, 1390, 1391, 1370, + 1371, 1372, 1373, 1374, 1375, 1376, 1377, 0, 0, 1381, + 0, 0, 1092, 0, 0, 0, 0, 0, 1132, 544, + 0, 0, 545, 1107, 0, 1125, 0, 1119, 1120, 0, + 0, 766, 914, 362, 0, 959, 950, 0, 934, 0, + 936, 956, 937, 957, 0, 0, 941, 0, 943, 0, + 939, 940, 945, 938, 914, 926, 966, 991, 968, 971, + 973, 974, 980, 0, 0, 0, 0, 273, 282, 283, + 284, 291, 0, 570, 297, 820, 0, 1397, 724, 725, + 1288, 1289, 732, 0, 1049, 903, 0, 0, 130, 133, + 0, 128, 0, 0, 0, 0, 120, 118, 1898, 0, + 0, 810, 174, 0, 0, 0, 786, 0, 791, 788, + 772, 782, 771, 779, 780, 799, 1401, 1402, 1403, 1404, + 0, 788, 762, 761, 823, 808, 858, 859, 0, 1460, + 400, 0, 1139, 194, 199, 200, 201, 195, 193, 1146, + 0, 1148, 0, 1246, 0, 0, 1809, 1585, 1554, 1587, + 1599, 1600, 1588, 0, 1556, 1557, 1590, 1591, 1593, 1594, + 1595, 1596, 1597, 1558, 0, 1179, 1654, 0, 1656, 1664, + 1665, 0, 1714, 1718, 0, 0, 0, 0, 0, 1628, + 1629, 1633, 1634, 1635, 1636, 1638, 1639, 1640, 1641, 1642, + 1643, 1644, 1645, 1646, 1647, 1648, 854, 1618, 0, 0, + 0, 0, 0, 0, 0, 833, 0, 0, 0, 64, + 0, 64, 1252, 1254, 103, 105, 0, 99, 100, 101, + 994, 1230, 1400, 1219, 0, 1220, 0, 0, 80, 82, + 0, 2052, 0, 0, 0, 0, 1196, 1022, 1038, 1034, + 0, 0, 0, 0, 1407, 1408, 1410, 1411, 1412, 0, + 1060, 0, 0, 1080, 1081, 1082, 1094, 0, 556, 557, + 0, 0, 0, 569, 565, 566, 567, 547, 1131, 1114, + 0, 0, 1103, 0, 0, 1113, 0, 1201, 1920, 1920, + 1920, 1230, 0, 0, 1331, 1920, 1920, 0, 1238, 1240, + 1230, 0, 0, 1335, 1274, 0, 0, 1265, 0, 989, + 0, 0, 914, 743, 746, 747, 844, 625, 850, 851, + 0, 663, 667, 664, 914, 1274, 452, 1295, 0, 0, + 0, 0, 0, 1327, 0, 0, 1299, 0, 483, 516, + 0, -2, 0, 1448, 0, 1433, 1448, 0, 0, 1447, + 0, 472, 515, 0, 0, 0, 529, 534, 535, 0, + 531, 532, 1487, 0, 533, 0, 520, 0, 526, 1349, + 1350, 0, 1355, 1356, 0, 1380, 0, 0, 463, 536, + 0, 0, 0, 537, 538, 543, 1133, 1134, 1100, 0, + 1114, 0, 1124, 0, 1121, 1122, 854, 0, 0, 931, + 960, 0, 0, 932, 0, 933, 935, 958, 0, 952, + 942, 944, 361, 975, 0, 0, 977, 978, 979, 970, + 299, 867, 1046, 0, 888, 0, 0, 921, 0, 19, + 0, 0, 123, 1908, 1911, 812, 0, 809, 175, 0, + 0, 0, 0, 776, 787, 770, 1405, 760, 810, 864, + 865, 196, 191, 1147, 1256, 0, 1247, 0, 1511, 1567, + 0, 1666, 0, 1623, 1620, 1623, 1622, 1614, 0, 1571, + 0, 1573, 1574, 1575, 0, 1577, 1578, 0, 831, 0, + 60, 0, 63, 61, 0, 107, 1215, 0, 1230, 0, + 0, 0, 1225, 0, 0, 83, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 1031, 1033, 0, 1066, 1335, + 0, 1066, 1093, 1079, 0, 0, 558, 559, 0, 562, + 568, 1095, 0, 0, 1097, 1098, 1099, 0, 0, 1111, + 0, 0, 0, 0, 1189, 1191, 1207, 0, 0, 0, + -2, 1242, 0, -2, 1235, 0, 1280, 0, 1272, 0, + 1264, 0, 1267, 914, 914, -2, 740, 745, 0, 0, + 668, 1280, 1297, 0, 1318, 0, 0, 0, 0, 0, + 0, 0, 1298, 0, 1311, 517, 1449, -2, 1463, 1465, + 0, 1206, 1468, 1469, 0, 0, 0, 0, 0, 0, + 1518, 1477, 0, 0, 1481, 1482, 1483, 0, 0, 1486, + 0, 1827, 1828, 0, 1490, 0, 0, 0, 0, 0, + 0, 0, 1427, 473, 474, 0, 476, 477, 1920, 1488, + 519, 470, 1920, 486, 1379, 1382, 1383, 542, 539, 540, + 1103, 1106, 1117, 1126, 767, 847, 363, 364, 961, 0, + 951, 953, 984, 981, 0, 0, 1050, 904, 912, 2281, + 2283, 2280, 124, 129, 0, 0, 814, 0, 811, 0, + 805, 807, 185, 775, 812, 145, 177, 0, 0, 1555, + 0, 0, 0, 1655, 1705, 1626, 1627, 0, 1615, 0, + 1609, 1610, 1611, 1616, 0, 0, 834, 829, 65, 106, + 0, 1216, 1222, 1223, 1224, 1227, 1228, 1229, 69, 1196, + 0, 1196, 0, 0, 0, 1025, 1039, 0, 1052, 1059, + 1073, 1212, 1409, 1058, 0, 0, 555, 560, 0, 563, + 564, 1115, 1114, 0, 1101, 1102, 0, 1109, 0, 0, + 1202, 1203, 1204, 1332, 1333, 1334, 1290, 1237, 0, -2, + 1343, 0, 1233, 1256, 1290, 0, 1268, 0, 1275, 0, + 1273, 1266, 854, 741, 853, 1277, 462, 1329, 1319, 0, + 1321, 0, 0, 0, 0, 1300, -2, 0, 1464, 1466, + 1467, 1470, 1471, 1472, 1523, 1524, 1525, 0, 0, 1475, + 1520, 1521, 1522, 1476, 0, 0, 0, 0, 0, 1825, + 1826, 1516, 0, 0, 1434, 1436, 1437, 1438, 1439, 1440, + 1441, 1442, 1443, 1435, 0, 0, 0, 1426, 1428, 475, + 0, 0, 1920, 1116, 360, 0, 0, 985, 987, 982, + 983, 906, 0, 0, 0, 0, 119, 121, 136, 0, + 813, 176, 0, 814, 147, 0, 168, 0, 1257, 0, + 1566, 0, 0, 0, 1625, 1612, 0, 0, 0, 0, + 0, 1829, 1830, 1831, 0, 1572, 1576, 1231, 0, 67, + 0, 84, 1196, 85, 1196, 0, 0, 0, 0, 1074, + 1075, 1083, 1084, 0, 1086, 1087, 561, 1096, 1104, 1108, + 1111, 0, 1163, 1292, 0, 1239, 1205, 1345, 1920, 1243, + 1292, 0, 1337, 1920, 1920, 1258, 0, 1270, 0, 1282, + 0, 1276, 847, 451, 0, 1279, 1315, 1320, 1322, 1324, + 0, 1328, 1326, 1301, -2, 0, 1309, 0, 0, 1473, + 1474, 0, 0, 1724, 1920, 0, 1506, 0, 1163, 1163, + 1163, 1163, 0, 530, 485, 0, 962, 976, 0, 913, + 0, 0, 0, 0, 0, 803, 137, 0, 146, 165, + 0, 178, 179, 0, 0, 0, 0, 1249, 0, 1514, + 1515, 0, 1601, 0, 0, 0, 1605, 1606, 1607, 1608, + 1196, 69, 0, 86, 87, 0, 1196, 0, 1051, 0, + 1085, 1110, 1112, 1162, 1232, 0, 1329, 1344, 0, 1234, + 1336, 0, 0, 0, 1269, 1281, 0, 1284, 739, 1278, + 1296, 0, 1325, 1302, 1310, 0, 1305, 0, 0, 0, + 1519, 0, 1480, 0, 1485, 1494, 1507, 0, 0, 1415, + 0, 1417, 0, 1421, 0, 1423, 0, 0, 487, 986, + 988, 0, 1775, 908, 909, 0, 816, 806, 148, 152, + 0, 174, 171, 0, 180, 0, 0, 0, 0, 1245, + 0, 1512, 0, 1602, 1603, 1604, 66, 68, 70, 1196, + 88, 0, 1053, 1054, 1067, 1164, 1920, 1920, 0, 0, + 0, 1170, 1171, 1920, 1920, 1920, 1175, 0, 1317, 1349, + 1338, 1339, 1340, 1283, 1316, 1304, 0, -2, 1312, 0, + 0, 1777, 1787, 1788, 1478, 1484, 1493, 1495, 1496, 0, + 1508, 1509, 1510, 1517, 1163, 1163, 1163, 1163, 1425, 907, + 0, 0, 815, 0, 139, 0, 0, 169, 170, 172, + 0, 181, 0, 183, 184, 0, 0, 1613, 90, 1055, + 0, 0, 1167, 1168, 0, 0, 0, 0, 1293, 0, + 1295, 1306, -2, 0, 1314, 0, 1479, 1497, 0, 1498, + 0, 0, 0, 1416, 1418, 1422, 1424, 1775, 910, 817, + 1255, 0, 153, 0, 155, 157, 158, 1450, 166, 167, + 173, 182, 0, 0, 1040, 1056, 0, 1165, 1166, 1169, + 1172, 1173, 1174, 0, 1297, 1313, 1778, 1499, 1501, 1502, + 0, 0, 1500, 0, 140, 141, 0, 154, 0, 0, + 1250, 1513, 1057, 1294, 1291, 1503, 1505, 1504, 911, 0, + 0, 156, 1451, 142, 143, 144, 0, 1452, } var yyTok1 = [...]int{ @@ -10850,13 +10820,13 @@ yydefault: case 2: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:851 +//line mysql_sql.y:852 { yylex.(*Lexer).AppendStmt(yyDollar[1].statementUnion()) } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:858 +//line mysql_sql.y:859 { if yyDollar[1].statementUnion() != nil { yylex.(*Lexer).AppendStmt(yyDollar[1].statementUnion()) @@ -10864,7 +10834,7 @@ yydefault: } case 5: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:864 +//line mysql_sql.y:865 { if yyDollar[3].statementUnion() != nil { yylex.(*Lexer).AppendStmt(yyDollar[3].statementUnion()) @@ -10873,7 +10843,7 @@ yydefault: case 6: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:872 +//line mysql_sql.y:873 { yyLOCAL = tree.NewCompoundStmt(yyDollar[2].statementsUnion()) } @@ -10881,7 +10851,7 @@ yydefault: case 7: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:878 +//line mysql_sql.y:879 { yyLOCAL = []tree.Statement{yyDollar[1].statementUnion()} } @@ -10889,7 +10859,7 @@ yydefault: case 8: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:882 +//line mysql_sql.y:883 { yyLOCAL = append(yyDollar[1].statementsUnion(), yyDollar[3].statementUnion()) } @@ -10897,7 +10867,7 @@ yydefault: case 18: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:897 +//line mysql_sql.y:898 { yyLOCAL = yyDollar[1].statementUnion() } @@ -10905,7 +10875,7 @@ yydefault: case 19: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:901 +//line mysql_sql.y:902 { yyLOCAL = tree.Statement(nil) } @@ -10913,7 +10883,7 @@ yydefault: case 20: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:907 +//line mysql_sql.y:908 { yyLOCAL = yyDollar[1].statementUnion() } @@ -10921,7 +10891,7 @@ yydefault: case 22: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:912 +//line mysql_sql.y:913 { yyLOCAL = yyDollar[1].statementUnion() } @@ -10929,7 +10899,7 @@ yydefault: case 23: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:916 +//line mysql_sql.y:917 { yyLOCAL = tree.Statement(nil) } @@ -10937,7 +10907,7 @@ yydefault: case 51: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:949 +//line mysql_sql.y:950 { yyLOCAL = yyDollar[1].selectUnion() } @@ -10945,7 +10915,7 @@ yydefault: case 60: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:963 +//line mysql_sql.y:964 { var timestamp = yyDollar[2].str var isS3 = false @@ -10960,7 +10930,7 @@ yydefault: case 61: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:974 +//line mysql_sql.y:975 { var timestamp = yyDollar[2].str var isS3 = true @@ -10974,32 +10944,32 @@ yydefault: yyVAL.union = yyLOCAL case 62: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:986 +//line mysql_sql.y:987 { yyVAL.str = "" } case 63: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:990 +//line mysql_sql.y:991 { yyVAL.str = yyDollar[2].str } case 64: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:995 +//line mysql_sql.y:996 { yyVAL.str = "" } case 65: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:999 +//line mysql_sql.y:1000 { yyVAL.str = yyDollar[2].str } case 66: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1005 +//line mysql_sql.y:1006 { yyLOCAL = &tree.CreateCDC{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11016,7 +10986,7 @@ yydefault: case 67: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1020 +//line mysql_sql.y:1021 { yyLOCAL = yyDollar[1].strsUnion() } @@ -11024,7 +10994,7 @@ yydefault: case 68: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1024 +//line mysql_sql.y:1025 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } @@ -11032,7 +11002,7 @@ yydefault: case 69: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1028 +//line mysql_sql.y:1029 { yyLOCAL = []string{} } @@ -11040,7 +11010,7 @@ yydefault: case 70: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1032 +//line mysql_sql.y:1033 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) @@ -11049,7 +11019,7 @@ yydefault: case 71: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1039 +//line mysql_sql.y:1040 { yyLOCAL = &tree.ShowCDC{ Option: yyDollar[3].allCDCOptionUnion(), @@ -11059,7 +11029,7 @@ yydefault: case 72: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1047 +//line mysql_sql.y:1048 { yyLOCAL = &tree.PauseCDC{ Option: yyDollar[3].allCDCOptionUnion(), @@ -11069,7 +11039,7 @@ yydefault: case 73: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1055 +//line mysql_sql.y:1056 { yyLOCAL = tree.NewDropCDC(yyDollar[3].allCDCOptionUnion(), yyDollar[4].boolValUnion()) } @@ -11077,7 +11047,7 @@ yydefault: case 74: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1061 +//line mysql_sql.y:1062 { yyLOCAL = &tree.AllOrNotCDC{ All: true, @@ -11088,7 +11058,7 @@ yydefault: case 75: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1068 +//line mysql_sql.y:1069 { yyLOCAL = &tree.AllOrNotCDC{ All: false, @@ -11099,7 +11069,7 @@ yydefault: case 76: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1077 +//line mysql_sql.y:1078 { yyLOCAL = &tree.ResumeCDC{ TaskName: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -11109,7 +11079,7 @@ yydefault: case 77: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1085 +//line mysql_sql.y:1086 { yyLOCAL = &tree.RestartCDC{ TaskName: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -11119,7 +11089,7 @@ yydefault: case 78: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1093 +//line mysql_sql.y:1094 { yyLOCAL = &tree.CreateSnapShot{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11131,7 +11101,7 @@ yydefault: case 79: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1103 +//line mysql_sql.y:1104 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELCLUSTER, @@ -11145,7 +11115,7 @@ yydefault: case 80: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1113 +//line mysql_sql.y:1114 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELACCOUNT, @@ -11159,7 +11129,7 @@ yydefault: case 81: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1123 +//line mysql_sql.y:1124 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELACCOUNT, @@ -11173,7 +11143,7 @@ yydefault: case 82: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1133 +//line mysql_sql.y:1134 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELDATABASE, @@ -11187,7 +11157,7 @@ yydefault: case 83: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1143 +//line mysql_sql.y:1144 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELTABLE, @@ -11201,7 +11171,7 @@ yydefault: case 84: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1155 +//line mysql_sql.y:1156 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11216,7 +11186,7 @@ yydefault: case 85: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1166 +//line mysql_sql.y:1167 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11231,7 +11201,7 @@ yydefault: case 86: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1177 +//line mysql_sql.y:1178 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11247,7 +11217,7 @@ yydefault: case 87: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1189 +//line mysql_sql.y:1190 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11263,7 +11233,7 @@ yydefault: case 88: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1201 +//line mysql_sql.y:1202 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11280,7 +11250,7 @@ yydefault: case 89: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1214 +//line mysql_sql.y:1215 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11295,7 +11265,7 @@ yydefault: case 90: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1225 +//line mysql_sql.y:1226 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -11312,7 +11282,7 @@ yydefault: case 91: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:1240 +//line mysql_sql.y:1241 { yyLOCAL = yyDollar[1].item.(int64) } @@ -11320,7 +11290,7 @@ yydefault: case 92: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1247 +//line mysql_sql.y:1248 { var account tree.Identifier var database tree.Identifier @@ -11356,7 +11326,7 @@ yydefault: case 93: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1279 +//line mysql_sql.y:1280 { var account tree.Identifier var database tree.Identifier @@ -11397,7 +11367,7 @@ yydefault: case 94: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1316 +//line mysql_sql.y:1317 { yyLOCAL = &tree.RestoreSnapShot{ Level: tree.RESTORELEVELCLUSTER, @@ -11408,7 +11378,7 @@ yydefault: case 95: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1323 +//line mysql_sql.y:1324 { result := &tree.RestoreSnapShot{ Level: tree.RESTORELEVELACCOUNT, @@ -11426,7 +11396,7 @@ yydefault: case 96: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1339 +//line mysql_sql.y:1340 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -11434,7 +11404,7 @@ yydefault: case 97: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1343 +//line mysql_sql.y:1344 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11445,7 +11415,7 @@ yydefault: case 98: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1352 +//line mysql_sql.y:1353 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11456,7 +11426,7 @@ yydefault: case 99: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1359 +//line mysql_sql.y:1360 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11467,32 +11437,32 @@ yydefault: yyVAL.union = yyLOCAL case 100: yyDollar = yyS[yypt-5 : yypt+1] -//line mysql_sql.y:1369 +//line mysql_sql.y:1370 { yyVAL.str = yyDollar[4].cstrUnion().Compare() } case 101: yyDollar = yyS[yypt-5 : yypt+1] -//line mysql_sql.y:1373 +//line mysql_sql.y:1374 { yyVAL.str = strings.ToLower(yyDollar[4].str) } case 102: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1378 +//line mysql_sql.y:1379 { yyVAL.str = "" } case 103: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:1382 +//line mysql_sql.y:1383 { yyVAL.str = yyDollar[3].cstrUnion().Compare() } case 104: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1388 +//line mysql_sql.y:1389 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELACCOUNT, @@ -11504,7 +11474,7 @@ yydefault: case 105: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1396 +//line mysql_sql.y:1397 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELDATABASE, @@ -11517,7 +11487,7 @@ yydefault: case 106: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1405 +//line mysql_sql.y:1406 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELTABLE, @@ -11531,7 +11501,7 @@ yydefault: case 107: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1415 +//line mysql_sql.y:1416 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELACCOUNT, @@ -11545,7 +11515,7 @@ yydefault: case 108: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1425 +//line mysql_sql.y:1426 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELCLUSTER, @@ -11557,7 +11527,7 @@ yydefault: case 109: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1435 +//line mysql_sql.y:1436 { var connectionId uint64 switch v := yyDollar[3].item.(type) { @@ -11580,7 +11550,7 @@ yydefault: case 110: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1455 +//line mysql_sql.y:1456 { yyLOCAL = tree.KillOption{ Exist: false, @@ -11590,7 +11560,7 @@ yydefault: case 111: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1461 +//line mysql_sql.y:1462 { yyLOCAL = tree.KillOption{ Exist: true, @@ -11601,7 +11571,7 @@ yydefault: case 112: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1468 +//line mysql_sql.y:1469 { yyLOCAL = tree.KillOption{ Exist: true, @@ -11612,7 +11582,7 @@ yydefault: case 113: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StatementOption -//line mysql_sql.y:1476 +//line mysql_sql.y:1477 { yyLOCAL = tree.StatementOption{ Exist: false, @@ -11622,7 +11592,7 @@ yydefault: case 114: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.StatementOption -//line mysql_sql.y:1482 +//line mysql_sql.y:1483 { yyLOCAL = tree.StatementOption{ Exist: true, @@ -11633,7 +11603,7 @@ yydefault: case 115: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1491 +//line mysql_sql.y:1492 { yyLOCAL = &tree.CallStmt{ Name: yyDollar[2].procNameUnion(), @@ -11644,7 +11614,7 @@ yydefault: case 116: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1500 +//line mysql_sql.y:1501 { yyLOCAL = &tree.LeaveStmt{ Name: tree.Identifier(yyDollar[2].cstrUnion().Compare()), @@ -11654,7 +11624,7 @@ yydefault: case 117: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1508 +//line mysql_sql.y:1509 { yyLOCAL = &tree.IterateStmt{ Name: tree.Identifier(yyDollar[2].cstrUnion().Compare()), @@ -11664,7 +11634,7 @@ yydefault: case 118: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1516 +//line mysql_sql.y:1517 { yyLOCAL = &tree.WhileStmt{ Name: "", @@ -11676,7 +11646,7 @@ yydefault: case 119: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1524 +//line mysql_sql.y:1525 { yyLOCAL = &tree.WhileStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11688,7 +11658,7 @@ yydefault: case 120: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1534 +//line mysql_sql.y:1535 { yyLOCAL = &tree.RepeatStmt{ Name: "", @@ -11700,7 +11670,7 @@ yydefault: case 121: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1542 +//line mysql_sql.y:1543 { yyLOCAL = &tree.RepeatStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11712,7 +11682,7 @@ yydefault: case 122: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1552 +//line mysql_sql.y:1553 { yyLOCAL = &tree.LoopStmt{ Name: "", @@ -11723,7 +11693,7 @@ yydefault: case 123: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1559 +//line mysql_sql.y:1560 { yyLOCAL = &tree.LoopStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -11734,7 +11704,7 @@ yydefault: case 124: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1568 +//line mysql_sql.y:1569 { yyLOCAL = &tree.IfStmt{ Cond: yyDollar[2].exprUnion(), @@ -11747,7 +11717,7 @@ yydefault: case 125: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1578 +//line mysql_sql.y:1579 { yyLOCAL = nil } @@ -11755,7 +11725,7 @@ yydefault: case 126: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1582 +//line mysql_sql.y:1583 { yyLOCAL = yyDollar[1].elseIfClauseListUnion() } @@ -11763,7 +11733,7 @@ yydefault: case 127: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1588 +//line mysql_sql.y:1589 { yyLOCAL = []*tree.ElseIfStmt{yyDollar[1].elseIfClauseUnion()} } @@ -11771,7 +11741,7 @@ yydefault: case 128: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1592 +//line mysql_sql.y:1593 { yyLOCAL = append(yyDollar[1].elseIfClauseListUnion(), yyDollar[2].elseIfClauseUnion()) } @@ -11779,7 +11749,7 @@ yydefault: case 129: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ElseIfStmt -//line mysql_sql.y:1598 +//line mysql_sql.y:1599 { yyLOCAL = &tree.ElseIfStmt{ Cond: yyDollar[2].exprUnion(), @@ -11790,7 +11760,7 @@ yydefault: case 130: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1607 +//line mysql_sql.y:1608 { yyLOCAL = &tree.CaseStmt{ Expr: yyDollar[2].exprUnion(), @@ -11802,7 +11772,7 @@ yydefault: case 131: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.WhenStmt -//line mysql_sql.y:1617 +//line mysql_sql.y:1618 { yyLOCAL = []*tree.WhenStmt{yyDollar[1].whenClause2Union()} } @@ -11810,7 +11780,7 @@ yydefault: case 132: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.WhenStmt -//line mysql_sql.y:1621 +//line mysql_sql.y:1622 { yyLOCAL = append(yyDollar[1].whenClauseList2Union(), yyDollar[2].whenClause2Union()) } @@ -11818,7 +11788,7 @@ yydefault: case 133: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.WhenStmt -//line mysql_sql.y:1627 +//line mysql_sql.y:1628 { yyLOCAL = &tree.WhenStmt{ Cond: yyDollar[2].exprUnion(), @@ -11829,7 +11799,7 @@ yydefault: case 134: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1636 +//line mysql_sql.y:1637 { yyLOCAL = nil } @@ -11837,7 +11807,7 @@ yydefault: case 135: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1640 +//line mysql_sql.y:1641 { yyLOCAL = yyDollar[2].statementsUnion() } @@ -11845,7 +11815,7 @@ yydefault: case 136: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1646 +//line mysql_sql.y:1647 { ep := &tree.ExportParam{ Outfile: true, @@ -11865,7 +11835,7 @@ yydefault: case 137: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1664 +//line mysql_sql.y:1665 { yyLOCAL = &tree.Load{ Local: yyDollar[3].boolValUnion(), @@ -11881,7 +11851,7 @@ yydefault: case 138: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1678 +//line mysql_sql.y:1679 { yyLOCAL = &tree.LoadExtension{ Name: tree.Identifier(yyDollar[2].str), @@ -11891,7 +11861,7 @@ yydefault: case 139: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:1685 +//line mysql_sql.y:1686 { yyLOCAL = nil } @@ -11899,7 +11869,7 @@ yydefault: case 140: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:1689 +//line mysql_sql.y:1690 { yyLOCAL = yyDollar[2].updateExprsUnion() } @@ -11907,7 +11877,7 @@ yydefault: case 141: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:1695 +//line mysql_sql.y:1696 { yyLOCAL = tree.UpdateExprs{yyDollar[1].updateExprUnion()} } @@ -11915,7 +11885,7 @@ yydefault: case 142: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:1699 +//line mysql_sql.y:1700 { yyLOCAL = append(yyDollar[1].updateExprsUnion(), yyDollar[3].updateExprUnion()) } @@ -11923,7 +11893,7 @@ yydefault: case 143: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:1705 +//line mysql_sql.y:1706 { yyLOCAL = &tree.UpdateExpr{ Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, @@ -11934,7 +11904,7 @@ yydefault: case 144: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:1712 +//line mysql_sql.y:1713 { yyLOCAL = &tree.UpdateExpr{ Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, @@ -11945,7 +11915,7 @@ yydefault: case 145: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:1720 +//line mysql_sql.y:1721 { yyLOCAL = false } @@ -11953,7 +11923,7 @@ yydefault: case 146: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:1724 +//line mysql_sql.y:1725 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -11969,7 +11939,7 @@ yydefault: case 147: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:1736 +//line mysql_sql.y:1737 { yyLOCAL = true } @@ -11977,7 +11947,7 @@ yydefault: case 148: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:1740 +//line mysql_sql.y:1741 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -11993,7 +11963,7 @@ yydefault: case 149: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:1754 +//line mysql_sql.y:1755 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } @@ -12001,7 +11971,7 @@ yydefault: case 150: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:1758 +//line mysql_sql.y:1759 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) @@ -12010,7 +11980,7 @@ yydefault: case 151: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:1763 +//line mysql_sql.y:1764 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) @@ -12020,7 +11990,7 @@ yydefault: case 152: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:1770 +//line mysql_sql.y:1771 { yyLOCAL = nil } @@ -12028,7 +11998,7 @@ yydefault: case 153: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:1774 +//line mysql_sql.y:1775 { yyLOCAL = nil } @@ -12036,7 +12006,7 @@ yydefault: case 154: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:1778 +//line mysql_sql.y:1779 { yyLOCAL = yyDollar[2].loadColumnsUnion() } @@ -12044,7 +12014,7 @@ yydefault: case 155: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:1784 +//line mysql_sql.y:1785 { switch yyDollar[1].loadColumnUnion().(type) { case *tree.UnresolvedName: @@ -12057,7 +12027,7 @@ yydefault: case 156: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:1793 +//line mysql_sql.y:1794 { switch yyDollar[3].loadColumnUnion().(type) { case *tree.UnresolvedName: @@ -12070,7 +12040,7 @@ yydefault: case 157: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.LoadColumn -//line mysql_sql.y:1804 +//line mysql_sql.y:1805 { yyLOCAL = yyDollar[1].unresolvedNameUnion() } @@ -12078,7 +12048,7 @@ yydefault: case 158: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.LoadColumn -//line mysql_sql.y:1808 +//line mysql_sql.y:1809 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -12086,7 +12056,7 @@ yydefault: case 159: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:1814 +//line mysql_sql.y:1815 { yyLOCAL = []*tree.VarExpr{yyDollar[1].varExprUnion()} } @@ -12094,7 +12064,7 @@ yydefault: case 160: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:1818 +//line mysql_sql.y:1819 { yyLOCAL = append(yyDollar[1].varExprsUnion(), yyDollar[3].varExprUnion()) } @@ -12102,7 +12072,7 @@ yydefault: case 161: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:1824 +//line mysql_sql.y:1825 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -12110,7 +12080,7 @@ yydefault: case 162: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:1828 +//line mysql_sql.y:1829 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -12118,7 +12088,7 @@ yydefault: case 163: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:1834 +//line mysql_sql.y:1835 { v := strings.ToLower(yyDollar[1].str) var isGlobal bool @@ -12140,7 +12110,7 @@ yydefault: case 164: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:1854 +//line mysql_sql.y:1855 { // vs := strings.Split($1, ".") // var r string @@ -12162,7 +12132,7 @@ yydefault: case 165: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:1873 +//line mysql_sql.y:1874 { yyLOCAL = 0 } @@ -12170,7 +12140,7 @@ yydefault: case 166: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:1877 +//line mysql_sql.y:1878 { yyLOCAL = yyDollar[2].item.(int64) } @@ -12178,7 +12148,7 @@ yydefault: case 167: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:1881 +//line mysql_sql.y:1882 { yyLOCAL = yyDollar[2].item.(int64) } @@ -12186,7 +12156,7 @@ yydefault: case 168: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:1886 +//line mysql_sql.y:1887 { yyLOCAL = nil } @@ -12194,7 +12164,7 @@ yydefault: case 169: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:1890 +//line mysql_sql.y:1891 { yyLOCAL = &tree.Lines{ StartingBy: yyDollar[2].str, @@ -12207,7 +12177,7 @@ yydefault: case 170: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:1899 +//line mysql_sql.y:1900 { yyLOCAL = &tree.Lines{ StartingBy: yyDollar[3].str, @@ -12219,32 +12189,32 @@ yydefault: yyVAL.union = yyLOCAL case 171: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1909 +//line mysql_sql.y:1910 { yyVAL.str = "" } case 173: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:1916 +//line mysql_sql.y:1917 { yyVAL.str = yyDollar[3].str } case 174: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1921 +//line mysql_sql.y:1922 { yyVAL.str = "\n" } case 176: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:1928 +//line mysql_sql.y:1929 { yyVAL.str = yyDollar[3].str } case 177: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:1933 +//line mysql_sql.y:1934 { yyLOCAL = nil } @@ -12252,7 +12222,7 @@ yydefault: case 178: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:1937 +//line mysql_sql.y:1938 { res := &tree.Fields{ Terminated: &tree.Terminated{ @@ -12282,7 +12252,7 @@ yydefault: case 179: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Fields -//line mysql_sql.y:1965 +//line mysql_sql.y:1966 { yyLOCAL = []*tree.Fields{yyDollar[1].fieldsUnion()} } @@ -12290,7 +12260,7 @@ yydefault: case 180: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.Fields -//line mysql_sql.y:1969 +//line mysql_sql.y:1970 { yyLOCAL = append(yyDollar[1].fieldsListUnion(), yyDollar[2].fieldsUnion()) } @@ -12298,7 +12268,7 @@ yydefault: case 181: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:1975 +//line mysql_sql.y:1976 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -12310,7 +12280,7 @@ yydefault: case 182: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:1983 +//line mysql_sql.y:1984 { str := yyDollar[4].str if str != "\\" && len(str) > 1 { @@ -12334,7 +12304,7 @@ yydefault: case 183: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2003 +//line mysql_sql.y:2004 { str := yyDollar[3].str if str != "\\" && len(str) > 1 { @@ -12357,7 +12327,7 @@ yydefault: case 184: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2022 +//line mysql_sql.y:2023 { str := yyDollar[3].str if str != "\\" && len(str) > 1 { @@ -12380,7 +12350,7 @@ yydefault: case 186: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2047 +//line mysql_sql.y:2048 { yyLOCAL = &tree.DuplicateKeyError{} } @@ -12388,7 +12358,7 @@ yydefault: case 187: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2051 +//line mysql_sql.y:2052 { yyLOCAL = &tree.DuplicateKeyIgnore{} } @@ -12396,7 +12366,7 @@ yydefault: case 188: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2055 +//line mysql_sql.y:2056 { yyLOCAL = &tree.DuplicateKeyReplace{} } @@ -12404,7 +12374,7 @@ yydefault: case 189: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2060 +//line mysql_sql.y:2061 { yyLOCAL = false } @@ -12412,7 +12382,7 @@ yydefault: case 190: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2064 +//line mysql_sql.y:2065 { yyLOCAL = true } @@ -12420,7 +12390,7 @@ yydefault: case 191: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2070 +//line mysql_sql.y:2071 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypePrivilege, @@ -12437,7 +12407,7 @@ yydefault: case 192: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2083 +//line mysql_sql.y:2084 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypeRole, @@ -12452,7 +12422,7 @@ yydefault: case 193: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2094 +//line mysql_sql.y:2095 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypeProxy, @@ -12468,7 +12438,7 @@ yydefault: case 194: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2107 +//line mysql_sql.y:2108 { yyLOCAL = false } @@ -12476,7 +12446,7 @@ yydefault: case 195: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2111 +//line mysql_sql.y:2112 { yyLOCAL = true } @@ -12484,7 +12454,7 @@ yydefault: case 196: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2121 +//line mysql_sql.y:2122 { yyLOCAL = &tree.Revoke{ Typ: tree.RevokeTypePrivilege, @@ -12501,7 +12471,7 @@ yydefault: case 197: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2134 +//line mysql_sql.y:2135 { yyLOCAL = &tree.Revoke{ Typ: tree.RevokeTypeRole, @@ -12516,7 +12486,7 @@ yydefault: case 198: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2147 +//line mysql_sql.y:2148 { yyLOCAL = &tree.PrivilegeLevel{ Level: tree.PRIVILEGE_LEVEL_TYPE_STAR, @@ -12526,7 +12496,7 @@ yydefault: case 199: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2153 +//line mysql_sql.y:2154 { yyLOCAL = &tree.PrivilegeLevel{ Level: tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR, @@ -12536,7 +12506,7 @@ yydefault: case 200: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2159 +//line mysql_sql.y:2160 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = &tree.PrivilegeLevel{ @@ -12548,7 +12518,7 @@ yydefault: case 201: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2167 +//line mysql_sql.y:2168 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -12562,7 +12532,7 @@ yydefault: case 202: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2177 +//line mysql_sql.y:2178 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = &tree.PrivilegeLevel{ @@ -12574,7 +12544,7 @@ yydefault: case 203: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2187 +//line mysql_sql.y:2188 { yyLOCAL = tree.OBJECT_TYPE_TABLE } @@ -12582,7 +12552,7 @@ yydefault: case 204: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2191 +//line mysql_sql.y:2192 { yyLOCAL = tree.OBJECT_TYPE_DATABASE } @@ -12590,7 +12560,7 @@ yydefault: case 205: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2195 +//line mysql_sql.y:2196 { yyLOCAL = tree.OBJECT_TYPE_FUNCTION } @@ -12598,7 +12568,7 @@ yydefault: case 206: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2199 +//line mysql_sql.y:2200 { yyLOCAL = tree.OBJECT_TYPE_PROCEDURE } @@ -12606,7 +12576,7 @@ yydefault: case 207: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2203 +//line mysql_sql.y:2204 { yyLOCAL = tree.OBJECT_TYPE_VIEW } @@ -12614,7 +12584,7 @@ yydefault: case 208: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2207 +//line mysql_sql.y:2208 { yyLOCAL = tree.OBJECT_TYPE_ACCOUNT } @@ -12622,7 +12592,7 @@ yydefault: case 209: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Privilege -//line mysql_sql.y:2213 +//line mysql_sql.y:2214 { yyLOCAL = []*tree.Privilege{yyDollar[1].privilegeUnion()} } @@ -12630,7 +12600,7 @@ yydefault: case 210: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Privilege -//line mysql_sql.y:2217 +//line mysql_sql.y:2218 { yyLOCAL = append(yyDollar[1].privilegesUnion(), yyDollar[3].privilegeUnion()) } @@ -12638,7 +12608,7 @@ yydefault: case 211: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Privilege -//line mysql_sql.y:2223 +//line mysql_sql.y:2224 { yyLOCAL = &tree.Privilege{ Type: yyDollar[1].privilegeTypeUnion(), @@ -12649,7 +12619,7 @@ yydefault: case 212: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Privilege -//line mysql_sql.y:2230 +//line mysql_sql.y:2231 { yyLOCAL = &tree.Privilege{ Type: yyDollar[1].privilegeTypeUnion(), @@ -12660,7 +12630,7 @@ yydefault: case 213: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.UnresolvedName -//line mysql_sql.y:2239 +//line mysql_sql.y:2240 { yyLOCAL = []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()} } @@ -12668,7 +12638,7 @@ yydefault: case 214: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.UnresolvedName -//line mysql_sql.y:2243 +//line mysql_sql.y:2244 { yyLOCAL = append(yyDollar[1].unresolveNamesUnion(), yyDollar[3].unresolvedNameUnion()) } @@ -12676,7 +12646,7 @@ yydefault: case 215: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2249 +//line mysql_sql.y:2250 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALL } @@ -12684,7 +12654,7 @@ yydefault: case 216: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2253 +//line mysql_sql.y:2254 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ACCOUNT } @@ -12692,7 +12662,7 @@ yydefault: case 217: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2257 +//line mysql_sql.y:2258 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_ACCOUNT } @@ -12700,7 +12670,7 @@ yydefault: case 218: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2261 +//line mysql_sql.y:2262 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ACCOUNT } @@ -12708,7 +12678,7 @@ yydefault: case 219: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2265 +//line mysql_sql.y:2266 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_UPGRADE_ACCOUNT } @@ -12716,7 +12686,7 @@ yydefault: case 220: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2269 +//line mysql_sql.y:2270 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALL } @@ -12724,7 +12694,7 @@ yydefault: case 221: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2273 +//line mysql_sql.y:2274 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_TABLE } @@ -12732,7 +12702,7 @@ yydefault: case 222: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2277 +//line mysql_sql.y:2278 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_VIEW } @@ -12740,7 +12710,7 @@ yydefault: case 223: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2281 +//line mysql_sql.y:2282 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE } @@ -12748,7 +12718,7 @@ yydefault: case 224: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2285 +//line mysql_sql.y:2286 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_USER } @@ -12756,7 +12726,7 @@ yydefault: case 225: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2289 +//line mysql_sql.y:2290 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_USER } @@ -12764,7 +12734,7 @@ yydefault: case 226: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2293 +//line mysql_sql.y:2294 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_USER } @@ -12772,7 +12742,7 @@ yydefault: case 227: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2297 +//line mysql_sql.y:2298 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLESPACE } @@ -12780,7 +12750,7 @@ yydefault: case 228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2301 +//line mysql_sql.y:2302 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_TRIGGER } @@ -12788,7 +12758,7 @@ yydefault: case 229: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2305 +//line mysql_sql.y:2306 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DELETE } @@ -12796,7 +12766,7 @@ yydefault: case 230: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2309 +//line mysql_sql.y:2310 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_TABLE } @@ -12804,7 +12774,7 @@ yydefault: case 231: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2313 +//line mysql_sql.y:2314 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_VIEW } @@ -12812,7 +12782,7 @@ yydefault: case 232: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2317 +//line mysql_sql.y:2318 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_EXECUTE } @@ -12820,7 +12790,7 @@ yydefault: case 233: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2321 +//line mysql_sql.y:2322 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_INDEX } @@ -12828,7 +12798,7 @@ yydefault: case 234: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2325 +//line mysql_sql.y:2326 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_INSERT } @@ -12836,7 +12806,7 @@ yydefault: case 235: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2329 +//line mysql_sql.y:2330 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SELECT } @@ -12844,7 +12814,7 @@ yydefault: case 236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2333 +//line mysql_sql.y:2334 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SUPER } @@ -12852,7 +12822,7 @@ yydefault: case 237: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2337 +//line mysql_sql.y:2338 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_DATABASE } @@ -12860,7 +12830,7 @@ yydefault: case 238: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2341 +//line mysql_sql.y:2342 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_DATABASE } @@ -12868,7 +12838,7 @@ yydefault: case 239: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2345 +//line mysql_sql.y:2346 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_DATABASES } @@ -12876,7 +12846,7 @@ yydefault: case 240: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2349 +//line mysql_sql.y:2350 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CONNECT } @@ -12884,7 +12854,7 @@ yydefault: case 241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2353 +//line mysql_sql.y:2354 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_MANAGE_GRANTS } @@ -12892,7 +12862,7 @@ yydefault: case 242: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2357 +//line mysql_sql.y:2358 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_OWNERSHIP } @@ -12900,7 +12870,7 @@ yydefault: case 243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2361 +//line mysql_sql.y:2362 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_TABLES } @@ -12908,7 +12878,7 @@ yydefault: case 244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2365 +//line mysql_sql.y:2366 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLE } @@ -12916,7 +12886,7 @@ yydefault: case 245: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2369 +//line mysql_sql.y:2370 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_UPDATE } @@ -12924,7 +12894,7 @@ yydefault: case 246: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2373 +//line mysql_sql.y:2374 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_GRANT_OPTION } @@ -12932,7 +12902,7 @@ yydefault: case 247: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2377 +//line mysql_sql.y:2378 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REFERENCES } @@ -12940,7 +12910,7 @@ yydefault: case 248: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2381 +//line mysql_sql.y:2382 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REFERENCE } @@ -12948,7 +12918,7 @@ yydefault: case 249: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2385 +//line mysql_sql.y:2386 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REPLICATION_SLAVE } @@ -12956,7 +12926,7 @@ yydefault: case 250: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2389 +//line mysql_sql.y:2390 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REPLICATION_CLIENT } @@ -12964,7 +12934,7 @@ yydefault: case 251: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2393 +//line mysql_sql.y:2394 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_USAGE } @@ -12972,7 +12942,7 @@ yydefault: case 252: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2397 +//line mysql_sql.y:2398 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_RELOAD } @@ -12980,7 +12950,7 @@ yydefault: case 253: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2401 +//line mysql_sql.y:2402 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_FILE } @@ -12988,7 +12958,7 @@ yydefault: case 254: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2405 +//line mysql_sql.y:2406 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TEMPORARY_TABLES } @@ -12996,7 +12966,7 @@ yydefault: case 255: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2409 +//line mysql_sql.y:2410 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_LOCK_TABLES } @@ -13004,7 +12974,7 @@ yydefault: case 256: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2413 +//line mysql_sql.y:2414 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_VIEW } @@ -13012,7 +12982,7 @@ yydefault: case 257: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2417 +//line mysql_sql.y:2418 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_VIEW } @@ -13020,7 +12990,7 @@ yydefault: case 258: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2421 +//line mysql_sql.y:2422 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ROLE } @@ -13028,7 +12998,7 @@ yydefault: case 259: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2425 +//line mysql_sql.y:2426 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_ROLE } @@ -13036,7 +13006,7 @@ yydefault: case 260: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2429 +//line mysql_sql.y:2430 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ROLE } @@ -13044,7 +13014,7 @@ yydefault: case 261: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2433 +//line mysql_sql.y:2434 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ROUTINE } @@ -13052,7 +13022,7 @@ yydefault: case 262: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2437 +//line mysql_sql.y:2438 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ROUTINE } @@ -13060,7 +13030,7 @@ yydefault: case 263: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2441 +//line mysql_sql.y:2442 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_EVENT } @@ -13068,7 +13038,7 @@ yydefault: case 264: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2445 +//line mysql_sql.y:2446 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHUTDOWN } @@ -13076,7 +13046,7 @@ yydefault: case 265: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2449 +//line mysql_sql.y:2450 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_TRUNCATE } @@ -13084,7 +13054,7 @@ yydefault: case 273: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2464 +//line mysql_sql.y:2465 { yyLOCAL = &tree.SetLogserviceSettings{ Name: yyDollar[4].str, @@ -13095,7 +13065,7 @@ yydefault: case 274: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2473 +//line mysql_sql.y:2474 { yyLOCAL = &tree.SetTransaction{ Global: false, @@ -13106,7 +13076,7 @@ yydefault: case 275: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2480 +//line mysql_sql.y:2481 { yyLOCAL = &tree.SetTransaction{ Global: true, @@ -13117,7 +13087,7 @@ yydefault: case 276: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2487 +//line mysql_sql.y:2488 { yyLOCAL = &tree.SetTransaction{ Global: false, @@ -13128,7 +13098,7 @@ yydefault: case 277: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2496 +//line mysql_sql.y:2497 { var connID uint32 switch v := yyDollar[5].item.(type) { @@ -13148,7 +13118,7 @@ yydefault: case 278: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.TransactionCharacteristic -//line mysql_sql.y:2514 +//line mysql_sql.y:2515 { yyLOCAL = []*tree.TransactionCharacteristic{yyDollar[1].transactionCharacteristicUnion()} } @@ -13156,7 +13126,7 @@ yydefault: case 279: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.TransactionCharacteristic -//line mysql_sql.y:2518 +//line mysql_sql.y:2519 { yyLOCAL = append(yyDollar[1].transactionCharacteristicListUnion(), yyDollar[3].transactionCharacteristicUnion()) } @@ -13164,7 +13134,7 @@ yydefault: case 280: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.TransactionCharacteristic -//line mysql_sql.y:2524 +//line mysql_sql.y:2525 { yyLOCAL = &tree.TransactionCharacteristic{ IsLevel: true, @@ -13175,7 +13145,7 @@ yydefault: case 281: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.TransactionCharacteristic -//line mysql_sql.y:2531 +//line mysql_sql.y:2532 { yyLOCAL = &tree.TransactionCharacteristic{ Access: yyDollar[1].accessModeUnion(), @@ -13185,7 +13155,7 @@ yydefault: case 282: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2539 +//line mysql_sql.y:2540 { yyLOCAL = tree.ISOLATION_LEVEL_REPEATABLE_READ } @@ -13193,7 +13163,7 @@ yydefault: case 283: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2543 +//line mysql_sql.y:2544 { yyLOCAL = tree.ISOLATION_LEVEL_READ_COMMITTED } @@ -13201,7 +13171,7 @@ yydefault: case 284: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2547 +//line mysql_sql.y:2548 { yyLOCAL = tree.ISOLATION_LEVEL_READ_UNCOMMITTED } @@ -13209,7 +13179,7 @@ yydefault: case 285: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2551 +//line mysql_sql.y:2552 { yyLOCAL = tree.ISOLATION_LEVEL_SERIALIZABLE } @@ -13217,7 +13187,7 @@ yydefault: case 286: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccessModeType -//line mysql_sql.y:2557 +//line mysql_sql.y:2558 { yyLOCAL = tree.ACCESS_MODE_READ_WRITE } @@ -13225,7 +13195,7 @@ yydefault: case 287: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccessModeType -//line mysql_sql.y:2561 +//line mysql_sql.y:2562 { yyLOCAL = tree.ACCESS_MODE_READ_ONLY } @@ -13233,7 +13203,7 @@ yydefault: case 288: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2567 +//line mysql_sql.y:2568 { yyLOCAL = &tree.SetRole{ SecondaryRole: false, @@ -13244,7 +13214,7 @@ yydefault: case 289: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2574 +//line mysql_sql.y:2575 { yyLOCAL = &tree.SetRole{ SecondaryRole: true, @@ -13255,7 +13225,7 @@ yydefault: case 290: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2581 +//line mysql_sql.y:2582 { yyLOCAL = &tree.SetRole{ SecondaryRole: true, @@ -13266,7 +13236,7 @@ yydefault: case 291: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2590 +//line mysql_sql.y:2591 { dr := yyDollar[4].setDefaultRoleUnion() dr.Users = yyDollar[6].usersUnion() @@ -13276,7 +13246,7 @@ yydefault: case 292: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2620 +//line mysql_sql.y:2621 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_NONE, Roles: nil} } @@ -13284,7 +13254,7 @@ yydefault: case 293: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2624 +//line mysql_sql.y:2625 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_ALL, Roles: nil} } @@ -13292,7 +13262,7 @@ yydefault: case 294: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2628 +//line mysql_sql.y:2629 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_NORMAL, Roles: yyDollar[1].rolesUnion()} } @@ -13300,7 +13270,7 @@ yydefault: case 295: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2634 +//line mysql_sql.y:2635 { yyLOCAL = &tree.SetVar{Assignments: yyDollar[2].varAssignmentExprsUnion()} } @@ -13308,7 +13278,7 @@ yydefault: case 296: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2640 +//line mysql_sql.y:2641 { yyLOCAL = &tree.SetPassword{Password: yyDollar[4].str} } @@ -13316,21 +13286,21 @@ yydefault: case 297: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2644 +//line mysql_sql.y:2645 { yyLOCAL = &tree.SetPassword{User: yyDollar[4].userUnion(), Password: yyDollar[6].str} } yyVAL.union = yyLOCAL case 299: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:2651 +//line mysql_sql.y:2652 { yyVAL.str = yyDollar[3].str } case 300: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.VarAssignmentExpr -//line mysql_sql.y:2657 +//line mysql_sql.y:2658 { yyLOCAL = []*tree.VarAssignmentExpr{yyDollar[1].varAssignmentExprUnion()} } @@ -13338,7 +13308,7 @@ yydefault: case 301: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.VarAssignmentExpr -//line mysql_sql.y:2661 +//line mysql_sql.y:2662 { yyLOCAL = append(yyDollar[1].varAssignmentExprsUnion(), yyDollar[3].varAssignmentExprUnion()) } @@ -13346,7 +13316,7 @@ yydefault: case 302: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2667 +//line mysql_sql.y:2668 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -13358,7 +13328,7 @@ yydefault: case 303: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2675 +//line mysql_sql.y:2676 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -13371,7 +13341,7 @@ yydefault: case 304: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2684 +//line mysql_sql.y:2685 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -13384,7 +13354,7 @@ yydefault: case 305: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2693 +//line mysql_sql.y:2694 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -13396,7 +13366,7 @@ yydefault: case 306: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2701 +//line mysql_sql.y:2702 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -13408,7 +13378,7 @@ yydefault: case 307: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2709 +//line mysql_sql.y:2710 { vs := strings.Split(yyDollar[1].str, ".") var isGlobal bool @@ -13435,7 +13405,7 @@ yydefault: case 308: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2732 +//line mysql_sql.y:2733 { v := strings.ToLower(yyDollar[1].str) var isGlobal bool @@ -13458,7 +13428,7 @@ yydefault: case 309: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2751 +//line mysql_sql.y:2752 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13469,7 +13439,7 @@ yydefault: case 310: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2758 +//line mysql_sql.y:2759 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13480,7 +13450,7 @@ yydefault: case 311: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2765 +//line mysql_sql.y:2766 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13492,7 +13462,7 @@ yydefault: case 312: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2773 +//line mysql_sql.y:2774 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13503,7 +13473,7 @@ yydefault: case 313: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2780 +//line mysql_sql.y:2781 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13514,7 +13484,7 @@ yydefault: case 314: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:2787 +//line mysql_sql.y:2788 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -13525,7 +13495,7 @@ yydefault: case 315: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:2796 +//line mysql_sql.y:2797 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } @@ -13533,7 +13503,7 @@ yydefault: case 316: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:2800 +//line mysql_sql.y:2801 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } @@ -13541,39 +13511,39 @@ yydefault: case 317: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:2804 +//line mysql_sql.y:2805 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 318: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:2810 +//line mysql_sql.y:2811 { yyVAL.str = string(yyDollar[1].str) } case 319: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:2814 +//line mysql_sql.y:2815 { yyVAL.str = yyDollar[1].str } case 320: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:2820 +//line mysql_sql.y:2821 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 321: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:2824 +//line mysql_sql.y:2825 { yyVAL.str = yyDollar[1].cstrUnion().Compare() + "." + yyDollar[3].cstrUnion().Compare() } case 322: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:2830 +//line mysql_sql.y:2831 { yyLOCAL = []string{yyDollar[1].str} } @@ -13581,7 +13551,7 @@ yydefault: case 323: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:2834 +//line mysql_sql.y:2835 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } @@ -13589,7 +13559,7 @@ yydefault: case 330: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2848 +//line mysql_sql.y:2849 { yyLOCAL = &tree.SavePoint{Name: tree.Identifier(yyDollar[2].cstrUnion().Compare())} } @@ -13597,7 +13567,7 @@ yydefault: case 331: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2854 +//line mysql_sql.y:2855 { yyLOCAL = &tree.ReleaseSavePoint{Name: tree.Identifier(yyDollar[3].cstrUnion().Compare())} } @@ -13605,7 +13575,7 @@ yydefault: case 332: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2860 +//line mysql_sql.y:2861 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[3].cstrUnion().Compare())} } @@ -13613,7 +13583,7 @@ yydefault: case 333: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2865 +//line mysql_sql.y:2866 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[4].cstrUnion().Compare())} } @@ -13621,7 +13591,7 @@ yydefault: case 334: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2870 +//line mysql_sql.y:2871 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[5].cstrUnion().Compare())} } @@ -13629,7 +13599,7 @@ yydefault: case 335: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2875 +//line mysql_sql.y:2876 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[4].cstrUnion().Compare())} } @@ -13637,7 +13607,7 @@ yydefault: case 336: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2881 +//line mysql_sql.y:2882 { yyLOCAL = &tree.RollbackTransaction{Type: yyDollar[2].completionTypeUnion()} } @@ -13645,7 +13615,7 @@ yydefault: case 337: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2887 +//line mysql_sql.y:2888 { yyLOCAL = &tree.CommitTransaction{Type: yyDollar[2].completionTypeUnion()} } @@ -13653,7 +13623,7 @@ yydefault: case 338: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2892 +//line mysql_sql.y:2893 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -13661,7 +13631,7 @@ yydefault: case 339: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2896 +//line mysql_sql.y:2897 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -13669,7 +13639,7 @@ yydefault: case 340: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2900 +//line mysql_sql.y:2901 { yyLOCAL = tree.COMPLETION_TYPE_CHAIN } @@ -13677,7 +13647,7 @@ yydefault: case 341: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2904 +//line mysql_sql.y:2905 { yyLOCAL = tree.COMPLETION_TYPE_CHAIN } @@ -13685,7 +13655,7 @@ yydefault: case 342: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2908 +//line mysql_sql.y:2909 { yyLOCAL = tree.COMPLETION_TYPE_RELEASE } @@ -13693,7 +13663,7 @@ yydefault: case 343: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2912 +//line mysql_sql.y:2913 { yyLOCAL = tree.COMPLETION_TYPE_RELEASE } @@ -13701,7 +13671,7 @@ yydefault: case 344: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2916 +//line mysql_sql.y:2917 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -13709,7 +13679,7 @@ yydefault: case 345: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2920 +//line mysql_sql.y:2921 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -13717,7 +13687,7 @@ yydefault: case 346: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:2924 +//line mysql_sql.y:2925 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -13725,7 +13695,7 @@ yydefault: case 347: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2930 +//line mysql_sql.y:2931 { yyLOCAL = &tree.BeginTransaction{} } @@ -13733,7 +13703,7 @@ yydefault: case 348: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2934 +//line mysql_sql.y:2935 { yyLOCAL = &tree.BeginTransaction{} } @@ -13741,7 +13711,7 @@ yydefault: case 349: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2938 +//line mysql_sql.y:2939 { yyLOCAL = &tree.BeginTransaction{} } @@ -13749,7 +13719,7 @@ yydefault: case 350: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2942 +//line mysql_sql.y:2943 { m := tree.MakeTransactionModes(tree.READ_WRITE_MODE_READ_WRITE) yyLOCAL = &tree.BeginTransaction{Modes: m} @@ -13758,7 +13728,7 @@ yydefault: case 351: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2947 +//line mysql_sql.y:2948 { m := tree.MakeTransactionModes(tree.READ_WRITE_MODE_READ_ONLY) yyLOCAL = &tree.BeginTransaction{Modes: m} @@ -13767,7 +13737,7 @@ yydefault: case 352: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2952 +//line mysql_sql.y:2953 { yyLOCAL = &tree.BeginTransaction{} } @@ -13775,7 +13745,7 @@ yydefault: case 353: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2958 +//line mysql_sql.y:2959 { name := yyDollar[2].cstrUnion() secondaryRole := false @@ -13792,7 +13762,7 @@ yydefault: case 354: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2971 +//line mysql_sql.y:2972 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := false @@ -13809,7 +13779,7 @@ yydefault: case 355: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2984 +//line mysql_sql.y:2985 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := false @@ -13826,7 +13796,7 @@ yydefault: case 356: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2997 +//line mysql_sql.y:2998 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := true @@ -13843,7 +13813,7 @@ yydefault: case 357: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3010 +//line mysql_sql.y:3011 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := true @@ -13860,7 +13830,7 @@ yydefault: case 359: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3026 +//line mysql_sql.y:3027 { yyDollar[2].statementUnion().(*tree.Update).With = yyDollar[1].withClauseUnion() yyLOCAL = yyDollar[2].statementUnion() @@ -13869,7 +13839,7 @@ yydefault: case 360: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3033 +//line mysql_sql.y:3034 { // Single-table syntax yyLOCAL = &tree.Update{ @@ -13884,7 +13854,7 @@ yydefault: case 361: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3044 +//line mysql_sql.y:3045 { // Multiple-table syntax yyLOCAL = &tree.Update{ @@ -13897,7 +13867,7 @@ yydefault: case 362: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:3055 +//line mysql_sql.y:3056 { yyLOCAL = tree.UpdateExprs{yyDollar[1].updateExprUnion()} } @@ -13905,7 +13875,7 @@ yydefault: case 363: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:3059 +//line mysql_sql.y:3060 { yyLOCAL = append(yyDollar[1].updateExprsUnion(), yyDollar[3].updateExprUnion()) } @@ -13913,7 +13883,7 @@ yydefault: case 364: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:3065 +//line mysql_sql.y:3066 { yyLOCAL = &tree.UpdateExpr{Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, Expr: yyDollar[3].exprUnion()} } @@ -13921,7 +13891,7 @@ yydefault: case 367: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3075 +//line mysql_sql.y:3076 { yyLOCAL = &tree.LockTableStmt{TableLocks: yyDollar[3].tableLocksUnion()} } @@ -13929,7 +13899,7 @@ yydefault: case 368: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableLock -//line mysql_sql.y:3081 +//line mysql_sql.y:3082 { yyLOCAL = []tree.TableLock{yyDollar[1].tableLockUnion()} } @@ -13937,7 +13907,7 @@ yydefault: case 369: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableLock -//line mysql_sql.y:3085 +//line mysql_sql.y:3086 { yyLOCAL = append(yyDollar[1].tableLocksUnion(), yyDollar[3].tableLockUnion()) } @@ -13945,7 +13915,7 @@ yydefault: case 370: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLock -//line mysql_sql.y:3091 +//line mysql_sql.y:3092 { yyLOCAL = tree.TableLock{Table: *yyDollar[1].tableNameUnion(), LockType: yyDollar[2].tableLockTypeUnion()} } @@ -13953,7 +13923,7 @@ yydefault: case 371: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3097 +//line mysql_sql.y:3098 { yyLOCAL = tree.TableLockRead } @@ -13961,7 +13931,7 @@ yydefault: case 372: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3101 +//line mysql_sql.y:3102 { yyLOCAL = tree.TableLockReadLocal } @@ -13969,7 +13939,7 @@ yydefault: case 373: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3105 +//line mysql_sql.y:3106 { yyLOCAL = tree.TableLockWrite } @@ -13977,7 +13947,7 @@ yydefault: case 374: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3109 +//line mysql_sql.y:3110 { yyLOCAL = tree.TableLockLowPriorityWrite } @@ -13985,7 +13955,7 @@ yydefault: case 375: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3115 +//line mysql_sql.y:3116 { yyLOCAL = &tree.UnLockTableStmt{} } @@ -13993,7 +13963,7 @@ yydefault: case 383: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3128 +//line mysql_sql.y:3129 { yyLOCAL = yyDollar[1].selectUnion() } @@ -14001,7 +13971,7 @@ yydefault: case 384: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3134 +//line mysql_sql.y:3135 { yyLOCAL = tree.NewPrepareStmt(tree.Identifier(yyDollar[2].str), yyDollar[4].statementUnion()) } @@ -14009,7 +13979,7 @@ yydefault: case 385: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3138 +//line mysql_sql.y:3139 { yyLOCAL = tree.NewPrepareString(tree.Identifier(yyDollar[2].str), yyDollar[4].str) } @@ -14017,7 +13987,7 @@ yydefault: case 386: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3142 +//line mysql_sql.y:3143 { yyLOCAL = tree.NewPrepareVar(tree.Identifier(yyDollar[2].str), yyDollar[4].varExprUnion()) } @@ -14025,7 +13995,7 @@ yydefault: case 387: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3148 +//line mysql_sql.y:3149 { yyLOCAL = tree.NewExecute(tree.Identifier(yyDollar[2].str)) } @@ -14033,7 +14003,7 @@ yydefault: case 388: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3152 +//line mysql_sql.y:3153 { yyLOCAL = tree.NewExecuteWithVariables(tree.Identifier(yyDollar[2].str), yyDollar[4].varExprsUnion()) } @@ -14041,7 +14011,7 @@ yydefault: case 389: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3158 +//line mysql_sql.y:3159 { yyLOCAL = tree.NewDeallocate(tree.Identifier(yyDollar[3].str), false) } @@ -14049,7 +14019,7 @@ yydefault: case 390: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3164 +//line mysql_sql.y:3165 { yyLOCAL = tree.NewReset(tree.Identifier(yyDollar[3].str)) } @@ -14057,7 +14027,7 @@ yydefault: case 396: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3175 +//line mysql_sql.y:3176 { yyLOCAL = yyDollar[1].selectUnion() } @@ -14065,7 +14035,7 @@ yydefault: case 397: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3181 +//line mysql_sql.y:3182 { yyLOCAL = &tree.ShowColumns{Table: yyDollar[2].unresolvedObjectNameUnion()} } @@ -14073,7 +14043,7 @@ yydefault: case 398: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3185 +//line mysql_sql.y:3186 { yyLOCAL = &tree.ShowColumns{Table: yyDollar[2].unresolvedObjectNameUnion(), ColName: yyDollar[3].unresolvedNameUnion()} } @@ -14081,7 +14051,7 @@ yydefault: case 399: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3189 +//line mysql_sql.y:3190 { yyLOCAL = tree.NewExplainFor("", uint64(yyDollar[4].item.(int64))) } @@ -14089,7 +14059,7 @@ yydefault: case 400: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3193 +//line mysql_sql.y:3194 { yyLOCAL = tree.NewExplainFor(yyDollar[4].str, uint64(yyDollar[7].item.(int64))) } @@ -14097,7 +14067,7 @@ yydefault: case 401: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3197 +//line mysql_sql.y:3198 { yyLOCAL = tree.NewExplainStmt(yyDollar[2].statementUnion(), "text") } @@ -14105,7 +14075,7 @@ yydefault: case 402: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3201 +//line mysql_sql.y:3202 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.VerboseOption, "NULL"), @@ -14116,7 +14086,7 @@ yydefault: case 403: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3208 +//line mysql_sql.y:3209 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -14127,7 +14097,7 @@ yydefault: case 404: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3215 +//line mysql_sql.y:3216 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -14139,7 +14109,7 @@ yydefault: case 405: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3223 +//line mysql_sql.y:3224 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.PhyPlanOption, "NULL"), @@ -14150,7 +14120,7 @@ yydefault: case 406: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3230 +//line mysql_sql.y:3231 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.PhyPlanOption, "NULL"), @@ -14162,7 +14132,7 @@ yydefault: case 407: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3238 +//line mysql_sql.y:3239 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.PhyPlanOption, "NULL"), @@ -14174,7 +14144,7 @@ yydefault: case 408: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3246 +//line mysql_sql.y:3247 { yyLOCAL = tree.MakeExplainStmt(yyDollar[5].statementUnion(), yyDollar[3].explainOptionsUnion()) } @@ -14182,7 +14152,7 @@ yydefault: case 409: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3250 +//line mysql_sql.y:3251 { yyLOCAL = tree.MakeExplainStmt(yyDollar[3].statementUnion(), nil) } @@ -14190,7 +14160,7 @@ yydefault: case 410: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3254 +//line mysql_sql.y:3255 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.VerboseOption, "NULL"), @@ -14201,7 +14171,7 @@ yydefault: case 411: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3261 +//line mysql_sql.y:3262 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -14212,7 +14182,7 @@ yydefault: case 412: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3268 +//line mysql_sql.y:3269 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -14224,7 +14194,7 @@ yydefault: case 427: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.OptionElem -//line mysql_sql.y:3306 +//line mysql_sql.y:3307 { yyLOCAL = []tree.OptionElem{yyDollar[1].explainOptionUnion()} } @@ -14232,7 +14202,7 @@ yydefault: case 428: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.OptionElem -//line mysql_sql.y:3310 +//line mysql_sql.y:3311 { yyLOCAL = append(yyDollar[1].explainOptionsUnion(), yyDollar[3].explainOptionUnion()) } @@ -14240,45 +14210,45 @@ yydefault: case 429: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.OptionElem -//line mysql_sql.y:3316 +//line mysql_sql.y:3317 { yyLOCAL = tree.MakeOptionElem(yyDollar[1].str, yyDollar[2].str) } yyVAL.union = yyLOCAL case 430: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3322 +//line mysql_sql.y:3323 { yyVAL.str = yyDollar[1].str } case 431: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3327 +//line mysql_sql.y:3328 { yyVAL.str = "true" } case 432: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3328 +//line mysql_sql.y:3329 { yyVAL.str = "false" } case 433: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3329 +//line mysql_sql.y:3330 { yyVAL.str = yyDollar[1].str } case 434: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3330 +//line mysql_sql.y:3331 { yyVAL.str = yyDollar[1].str } case 435: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3334 +//line mysql_sql.y:3335 { yyLOCAL = tree.NewAnalyzeStmt(yyDollar[3].tableNameUnion(), yyDollar[5].identifierListUnion()) } @@ -14286,7 +14256,7 @@ yydefault: case 436: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3340 +//line mysql_sql.y:3341 { yyLOCAL = &tree.UpgradeStatement{ Target: yyDollar[3].upgrade_targetUnion(), @@ -14297,7 +14267,7 @@ yydefault: case 437: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Target -//line mysql_sql.y:3349 +//line mysql_sql.y:3350 { yyLOCAL = &tree.Target{ AccountName: yyDollar[1].str, @@ -14308,7 +14278,7 @@ yydefault: case 438: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Target -//line mysql_sql.y:3356 +//line mysql_sql.y:3357 { yyLOCAL = &tree.Target{ AccountName: "", @@ -14319,7 +14289,7 @@ yydefault: case 439: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3364 +//line mysql_sql.y:3365 { yyLOCAL = -1 } @@ -14327,7 +14297,7 @@ yydefault: case 440: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3368 +//line mysql_sql.y:3369 { res := yyDollar[3].item.(int64) if res <= 0 { @@ -14340,7 +14310,7 @@ yydefault: case 451: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3392 +//line mysql_sql.y:3393 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNameUnion() @@ -14365,7 +14335,7 @@ yydefault: case 452: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3415 +//line mysql_sql.y:3416 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNameUnion() @@ -14377,7 +14347,7 @@ yydefault: case 453: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3425 +//line mysql_sql.y:3426 { var table = yyDollar[3].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -14388,7 +14358,7 @@ yydefault: case 454: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3432 +//line mysql_sql.y:3433 { var table = yyDollar[3].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -14399,7 +14369,7 @@ yydefault: case 455: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3441 +//line mysql_sql.y:3442 { alterTables := yyDollar[3].renameTableOptionsUnion() renameTables := tree.NewRenameTable(alterTables) @@ -14409,7 +14379,7 @@ yydefault: case 456: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.AlterTable -//line mysql_sql.y:3449 +//line mysql_sql.y:3450 { yyLOCAL = []*tree.AlterTable{yyDollar[1].renameTableOptionUnion()} } @@ -14417,7 +14387,7 @@ yydefault: case 457: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.AlterTable -//line mysql_sql.y:3453 +//line mysql_sql.y:3454 { yyLOCAL = append(yyDollar[1].renameTableOptionsUnion(), yyDollar[3].renameTableOptionUnion()) } @@ -14425,7 +14395,7 @@ yydefault: case 458: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AlterTable -//line mysql_sql.y:3459 +//line mysql_sql.y:3460 { var table = yyDollar[1].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -14437,7 +14407,7 @@ yydefault: case 459: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOptions -//line mysql_sql.y:3469 +//line mysql_sql.y:3470 { yyLOCAL = []tree.AlterTableOption{yyDollar[1].alterTableOptionUnion()} } @@ -14445,7 +14415,7 @@ yydefault: case 460: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOptions -//line mysql_sql.y:3473 +//line mysql_sql.y:3474 { yyLOCAL = append(yyDollar[1].alterTableOptionsUnion(), yyDollar[3].alterTableOptionUnion()) } @@ -14453,7 +14423,7 @@ yydefault: case 461: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:3479 +//line mysql_sql.y:3480 { yyLOCAL = yyDollar[1].alterPartitionOptionUnion() } @@ -14461,7 +14431,7 @@ yydefault: case 462: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:3483 +//line mysql_sql.y:3484 { yyDollar[3].partitionByUnion().Num = uint64(yyDollar[4].int64ValUnion()) var PartBy = yyDollar[3].partitionByUnion() @@ -14487,7 +14457,7 @@ yydefault: case 463: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3507 +//line mysql_sql.y:3508 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -14499,7 +14469,7 @@ yydefault: case 464: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:3517 +//line mysql_sql.y:3518 { var typ = tree.AlterPartitionAddPartition var partitions = yyDollar[3].partitionsUnion() @@ -14513,7 +14483,7 @@ yydefault: case 465: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:3527 +//line mysql_sql.y:3528 { var typ = tree.AlterPartitionDropPartition var partitionNames = yyDollar[3].PartitionNamesUnion() @@ -14533,7 +14503,7 @@ yydefault: case 466: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:3543 +//line mysql_sql.y:3544 { var typ = tree.AlterPartitionTruncatePartition var partitionNames = yyDollar[3].PartitionNamesUnion() @@ -14553,7 +14523,7 @@ yydefault: case 467: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:3561 +//line mysql_sql.y:3562 { yyLOCAL = nil } @@ -14561,7 +14531,7 @@ yydefault: case 468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:3565 +//line mysql_sql.y:3566 { yyLOCAL = yyDollar[1].PartitionNamesUnion() } @@ -14569,7 +14539,7 @@ yydefault: case 469: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:3571 +//line mysql_sql.y:3572 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -14577,7 +14547,7 @@ yydefault: case 470: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:3575 +//line mysql_sql.y:3576 { yyLOCAL = append(yyDollar[1].PartitionNamesUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -14585,7 +14555,7 @@ yydefault: case 471: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3581 +//line mysql_sql.y:3582 { var def = yyDollar[2].tableDefUnion() opt := tree.NewAlterOptionAdd(def) @@ -14595,7 +14565,7 @@ yydefault: case 472: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3587 +//line mysql_sql.y:3588 { var typ = tree.AlterTableModifyColumn var newColumn = yyDollar[3].columnTableDefUnion() @@ -14607,7 +14577,7 @@ yydefault: case 473: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3595 +//line mysql_sql.y:3596 { // Type OldColumnName NewColumn Position var typ = tree.AlterTableChangeColumn @@ -14621,7 +14591,7 @@ yydefault: case 474: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3605 +//line mysql_sql.y:3606 { var typ = tree.AlterTableRenameColumn var oldColumnName = yyDollar[3].unresolvedNameUnion() @@ -14633,7 +14603,7 @@ yydefault: case 475: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3613 +//line mysql_sql.y:3614 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -14647,7 +14617,7 @@ yydefault: case 476: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3623 +//line mysql_sql.y:3624 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -14661,7 +14631,7 @@ yydefault: case 477: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3633 +//line mysql_sql.y:3634 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -14675,7 +14645,7 @@ yydefault: case 478: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3643 +//line mysql_sql.y:3644 { var orderByClauseType = tree.AlterTableOrderByColumn var orderByColumnList = yyDollar[3].alterColumnOrderByUnion() @@ -14686,7 +14656,7 @@ yydefault: case 479: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3650 +//line mysql_sql.y:3651 { yyLOCAL = tree.AlterTableOption(yyDollar[2].alterTableOptionUnion()) } @@ -14694,7 +14664,7 @@ yydefault: case 480: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3654 +//line mysql_sql.y:3655 { yyLOCAL = tree.AlterTableOption(yyDollar[2].alterTableOptionUnion()) } @@ -14702,7 +14672,7 @@ yydefault: case 481: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3658 +//line mysql_sql.y:3659 { yyLOCAL = tree.AlterTableOption(yyDollar[1].tableOptionUnion()) } @@ -14710,7 +14680,7 @@ yydefault: case 482: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3662 +//line mysql_sql.y:3663 { yyLOCAL = tree.AlterTableOption(yyDollar[3].alterTableOptionUnion()) } @@ -14718,7 +14688,7 @@ yydefault: case 483: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3666 +//line mysql_sql.y:3667 { var column = yyDollar[3].columnTableDefUnion() var position = yyDollar[4].alterColPositionUnion() @@ -14729,7 +14699,7 @@ yydefault: case 484: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3673 +//line mysql_sql.y:3674 { var checkType = yyDollar[1].str var enforce bool @@ -14739,7 +14709,7 @@ yydefault: case 485: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3679 +//line mysql_sql.y:3680 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[4].str) } @@ -14747,7 +14717,7 @@ yydefault: case 486: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3683 +//line mysql_sql.y:3684 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[5].str) } @@ -14755,7 +14725,7 @@ yydefault: case 487: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3687 +//line mysql_sql.y:3688 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[5].str) } @@ -14763,7 +14733,7 @@ yydefault: case 488: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3691 +//line mysql_sql.y:3692 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -14771,7 +14741,7 @@ yydefault: case 489: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3695 +//line mysql_sql.y:3696 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -14779,7 +14749,7 @@ yydefault: case 490: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3699 +//line mysql_sql.y:3700 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -14787,7 +14757,7 @@ yydefault: case 491: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3703 +//line mysql_sql.y:3704 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -14795,33 +14765,33 @@ yydefault: case 492: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3707 +//line mysql_sql.y:3708 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } yyVAL.union = yyLOCAL case 493: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:3712 +//line mysql_sql.y:3713 { yyVAL.str = "" } case 513: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:3746 +//line mysql_sql.y:3747 { yyVAL.str = "" } case 514: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3750 +//line mysql_sql.y:3751 { yyVAL.str = string("COLUMN") } case 515: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:3755 +//line mysql_sql.y:3756 { var typ = tree.ColumnPositionNone var relativeColumn *tree.UnresolvedName @@ -14831,7 +14801,7 @@ yydefault: case 516: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:3761 +//line mysql_sql.y:3762 { var typ = tree.ColumnPositionFirst var relativeColumn *tree.UnresolvedName @@ -14841,7 +14811,7 @@ yydefault: case 517: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:3767 +//line mysql_sql.y:3768 { var typ = tree.ColumnPositionAfter var relativeColumn = yyDollar[2].unresolvedNameUnion() @@ -14851,7 +14821,7 @@ yydefault: case 518: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.AlterColumnOrder -//line mysql_sql.y:3775 +//line mysql_sql.y:3776 { yyLOCAL = []*tree.AlterColumnOrder{yyDollar[1].alterColumnOrderUnion()} } @@ -14859,7 +14829,7 @@ yydefault: case 519: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.AlterColumnOrder -//line mysql_sql.y:3779 +//line mysql_sql.y:3780 { yyLOCAL = append(yyDollar[1].alterColumnOrderByUnion(), yyDollar[3].alterColumnOrderUnion()) } @@ -14867,7 +14837,7 @@ yydefault: case 520: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AlterColumnOrder -//line mysql_sql.y:3785 +//line mysql_sql.y:3786 { var column = yyDollar[1].unresolvedNameUnion() var direction = yyDollar[2].directionUnion() @@ -14877,7 +14847,7 @@ yydefault: case 521: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3793 +//line mysql_sql.y:3794 { var name = yyDollar[1].unresolvedObjectNameUnion() yyLOCAL = tree.NewAlterOptionTableName(name) @@ -14886,7 +14856,7 @@ yydefault: case 522: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3800 +//line mysql_sql.y:3801 { var dropType = tree.AlterTableDropIndex var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -14896,7 +14866,7 @@ yydefault: case 523: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3806 +//line mysql_sql.y:3807 { var dropType = tree.AlterTableDropKey var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -14906,7 +14876,7 @@ yydefault: case 524: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3812 +//line mysql_sql.y:3813 { var dropType = tree.AlterTableDropColumn var name = tree.Identifier(yyDollar[1].cstrUnion().Compare()) @@ -14916,7 +14886,7 @@ yydefault: case 525: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3818 +//line mysql_sql.y:3819 { var dropType = tree.AlterTableDropColumn var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -14926,7 +14896,7 @@ yydefault: case 526: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3824 +//line mysql_sql.y:3825 { var dropType = tree.AlterTableDropForeignKey var name = tree.Identifier(yyDollar[3].cstrUnion().Compare()) @@ -14937,7 +14907,7 @@ yydefault: case 527: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3831 +//line mysql_sql.y:3832 { yyLOCAL = &tree.AlterOptionDrop{ Typ: tree.AlterTableDropForeignKey, @@ -14948,7 +14918,7 @@ yydefault: case 528: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3838 +//line mysql_sql.y:3839 { var dropType = tree.AlterTableDropPrimaryKey var name = tree.Identifier("") @@ -14958,7 +14928,7 @@ yydefault: case 529: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3846 +//line mysql_sql.y:3847 { var indexName = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var visibility = yyDollar[3].indexVisibilityUnion() @@ -14968,7 +14938,7 @@ yydefault: case 530: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3852 +//line mysql_sql.y:3853 { val := int64(yyDollar[6].item.(int64)) if val <= 0 { @@ -14984,7 +14954,7 @@ yydefault: case 531: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3864 +//line mysql_sql.y:3865 { var keyType = tree.INDEX_TYPE_HNSW var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -14994,7 +14964,7 @@ yydefault: case 532: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3870 +//line mysql_sql.y:3871 { var checkType = yyDollar[1].str var enforce = yyDollar[3].boolValUnion() @@ -15004,7 +14974,7 @@ yydefault: case 533: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:3876 +//line mysql_sql.y:3877 { var checkType = yyDollar[1].str var enforce = yyDollar[3].boolValUnion() @@ -15014,7 +14984,7 @@ yydefault: case 534: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.VisibleType -//line mysql_sql.y:3884 +//line mysql_sql.y:3885 { yyLOCAL = tree.VISIBLE_TYPE_VISIBLE } @@ -15022,7 +14992,7 @@ yydefault: case 535: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.VisibleType -//line mysql_sql.y:3888 +//line mysql_sql.y:3889 { yyLOCAL = tree.VISIBLE_TYPE_INVISIBLE } @@ -15030,7 +15000,7 @@ yydefault: case 536: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3894 +//line mysql_sql.y:3895 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].exprUnion() @@ -15050,7 +15020,7 @@ yydefault: case 537: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3912 +//line mysql_sql.y:3913 { var accountName = "" var dbName = yyDollar[3].str @@ -15069,7 +15039,7 @@ yydefault: case 538: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3927 +//line mysql_sql.y:3928 { var accountName = "" var dbName = yyDollar[3].str @@ -15088,7 +15058,7 @@ yydefault: case 539: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3942 +//line mysql_sql.y:3943 { var accountName = yyDollar[4].str var dbName = "" @@ -15107,7 +15077,7 @@ yydefault: case 540: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3957 +//line mysql_sql.y:3958 { assignments := []*tree.VarAssignmentExpr{ { @@ -15123,7 +15093,7 @@ yydefault: case 541: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AlterAccountAuthOption -//line mysql_sql.y:3970 +//line mysql_sql.y:3971 { yyLOCAL = tree.AlterAccountAuthOption{ Exist: false, @@ -15133,7 +15103,7 @@ yydefault: case 542: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterAccountAuthOption -//line mysql_sql.y:3976 +//line mysql_sql.y:3977 { yyLOCAL = tree.AlterAccountAuthOption{ Exist: true, @@ -15146,7 +15116,7 @@ yydefault: case 543: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3987 +//line mysql_sql.y:3988 { // Create temporary variables with meaningful names ifExists := yyDollar[3].boolValUnion() @@ -15162,7 +15132,7 @@ yydefault: case 544: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3999 +//line mysql_sql.y:4000 { ifExists := yyDollar[3].boolValUnion() var Username = yyDollar[4].usernameRecordUnion().Username @@ -15177,7 +15147,7 @@ yydefault: case 545: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4010 +//line mysql_sql.y:4011 { ifExists := yyDollar[3].boolValUnion() var Username = yyDollar[4].usernameRecordUnion().Username @@ -15192,7 +15162,7 @@ yydefault: case 546: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:4022 +//line mysql_sql.y:4023 { yyLOCAL = nil } @@ -15200,7 +15170,7 @@ yydefault: case 547: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:4026 +//line mysql_sql.y:4027 { var UserName = yyDollar[3].str yyLOCAL = tree.NewRole( @@ -15211,7 +15181,7 @@ yydefault: case 548: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4034 +//line mysql_sql.y:4035 { yyLOCAL = false } @@ -15219,7 +15189,7 @@ yydefault: case 549: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4038 +//line mysql_sql.y:4039 { yyLOCAL = true } @@ -15227,7 +15197,7 @@ yydefault: case 550: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4043 +//line mysql_sql.y:4044 { yyLOCAL = nil } @@ -15235,7 +15205,7 @@ yydefault: case 551: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4047 +//line mysql_sql.y:4048 { yyLOCAL = yyDollar[1].userMiscOptionUnion() } @@ -15243,7 +15213,7 @@ yydefault: case 552: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4063 +//line mysql_sql.y:4064 { yyLOCAL = tree.NewUserMiscOptionAccountUnlock() } @@ -15251,7 +15221,7 @@ yydefault: case 553: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4067 +//line mysql_sql.y:4068 { yyLOCAL = tree.NewUserMiscOptionAccountLock() } @@ -15259,7 +15229,7 @@ yydefault: case 554: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4071 +//line mysql_sql.y:4072 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireNone() } @@ -15267,7 +15237,7 @@ yydefault: case 555: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4075 +//line mysql_sql.y:4076 { var Value = yyDollar[3].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordExpireInterval( @@ -15278,7 +15248,7 @@ yydefault: case 556: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4082 +//line mysql_sql.y:4083 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireNever() } @@ -15286,7 +15256,7 @@ yydefault: case 557: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4086 +//line mysql_sql.y:4087 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireDefault() } @@ -15294,7 +15264,7 @@ yydefault: case 558: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4090 +//line mysql_sql.y:4091 { yyLOCAL = tree.NewUserMiscOptionPasswordHistoryDefault() } @@ -15302,7 +15272,7 @@ yydefault: case 559: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4094 +//line mysql_sql.y:4095 { var Value = yyDollar[3].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordHistoryCount( @@ -15313,7 +15283,7 @@ yydefault: case 560: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4101 +//line mysql_sql.y:4102 { yyLOCAL = tree.NewUserMiscOptionPasswordReuseIntervalDefault() } @@ -15321,7 +15291,7 @@ yydefault: case 561: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4105 +//line mysql_sql.y:4106 { var Value = yyDollar[4].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordReuseIntervalCount( @@ -15332,7 +15302,7 @@ yydefault: case 562: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4112 +//line mysql_sql.y:4113 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentNone() } @@ -15340,7 +15310,7 @@ yydefault: case 563: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4116 +//line mysql_sql.y:4117 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentDefault() } @@ -15348,7 +15318,7 @@ yydefault: case 564: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4120 +//line mysql_sql.y:4121 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentOptional() } @@ -15356,7 +15326,7 @@ yydefault: case 565: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4124 +//line mysql_sql.y:4125 { var Value = yyDollar[2].item.(int64) yyLOCAL = tree.NewUserMiscOptionFailedLoginAttempts( @@ -15367,7 +15337,7 @@ yydefault: case 566: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4131 +//line mysql_sql.y:4132 { var Value = yyDollar[2].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordLockTimeCount( @@ -15378,27 +15348,27 @@ yydefault: case 567: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4138 +//line mysql_sql.y:4139 { yyLOCAL = tree.NewUserMiscOptionPasswordLockTimeUnbounded() } yyVAL.union = yyLOCAL case 568: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:4144 +//line mysql_sql.y:4145 { yyVAL.item = nil } case 569: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4149 +//line mysql_sql.y:4150 { yyVAL.item = nil } case 609: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4198 +//line mysql_sql.y:4199 { yyLOCAL = &tree.ShowLogserviceReplicas{} } @@ -15406,7 +15376,7 @@ yydefault: case 610: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4204 +//line mysql_sql.y:4205 { yyLOCAL = &tree.ShowLogserviceStores{} } @@ -15414,7 +15384,7 @@ yydefault: case 611: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4210 +//line mysql_sql.y:4211 { yyLOCAL = &tree.ShowLogserviceSettings{} } @@ -15422,7 +15392,7 @@ yydefault: case 612: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4216 +//line mysql_sql.y:4217 { yyLOCAL = &tree.ShowCollation{ Like: yyDollar[3].comparisionExprUnion(), @@ -15433,7 +15403,7 @@ yydefault: case 613: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4225 +//line mysql_sql.y:4226 { yyLOCAL = &tree.ShowStages{ Like: yyDollar[3].comparisionExprUnion(), @@ -15443,7 +15413,7 @@ yydefault: case 614: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4233 +//line mysql_sql.y:4234 { yyLOCAL = &tree.ShowSnapShots{ Where: yyDollar[3].whereUnion(), @@ -15453,7 +15423,7 @@ yydefault: case 615: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4241 +//line mysql_sql.y:4242 { yyLOCAL = &tree.ShowPitr{ Where: yyDollar[3].whereUnion(), @@ -15463,7 +15433,7 @@ yydefault: case 616: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4249 +//line mysql_sql.y:4250 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELACCOUNT, @@ -15473,7 +15443,7 @@ yydefault: case 617: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4255 +//line mysql_sql.y:4256 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELDATABASE, @@ -15484,7 +15454,7 @@ yydefault: case 618: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4262 +//line mysql_sql.y:4263 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELTABLE, @@ -15496,7 +15466,7 @@ yydefault: case 619: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4270 +//line mysql_sql.y:4271 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELACCOUNT, @@ -15507,7 +15477,7 @@ yydefault: case 620: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4279 +//line mysql_sql.y:4280 { yyLOCAL = &tree.ShowGrants{ShowGrantType: tree.GrantForUser} } @@ -15515,7 +15485,7 @@ yydefault: case 621: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4283 +//line mysql_sql.y:4284 { yyLOCAL = &tree.ShowGrants{Username: yyDollar[4].usernameRecordUnion().Username, Hostname: yyDollar[4].usernameRecordUnion().Hostname, Roles: yyDollar[5].rolesUnion(), ShowGrantType: tree.GrantForUser} } @@ -15523,7 +15493,7 @@ yydefault: case 622: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4287 +//line mysql_sql.y:4288 { s := &tree.ShowGrants{} roles := []*tree.Role{ @@ -15537,7 +15507,7 @@ yydefault: case 623: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:4298 +//line mysql_sql.y:4299 { yyLOCAL = nil } @@ -15545,7 +15515,7 @@ yydefault: case 624: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:4302 +//line mysql_sql.y:4303 { yyLOCAL = yyDollar[2].rolesUnion() } @@ -15553,25 +15523,25 @@ yydefault: case 625: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4308 +//line mysql_sql.y:4309 { yyLOCAL = &tree.ShowTableStatus{DbName: yyDollar[5].str, Like: yyDollar[6].comparisionExprUnion(), Where: yyDollar[7].whereUnion()} } yyVAL.union = yyLOCAL case 626: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4313 +//line mysql_sql.y:4314 { } case 628: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4317 +//line mysql_sql.y:4318 { } case 630: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4322 +//line mysql_sql.y:4323 { yyLOCAL = &tree.ShowFunctionOrProcedureStatus{ Like: yyDollar[4].comparisionExprUnion(), @@ -15583,7 +15553,7 @@ yydefault: case 631: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4332 +//line mysql_sql.y:4333 { yyLOCAL = &tree.ShowFunctionOrProcedureStatus{ Like: yyDollar[4].comparisionExprUnion(), @@ -15595,7 +15565,7 @@ yydefault: case 632: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4342 +//line mysql_sql.y:4343 { yyLOCAL = &tree.ShowRolesStmt{ Like: yyDollar[3].comparisionExprUnion(), @@ -15605,7 +15575,7 @@ yydefault: case 633: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4350 +//line mysql_sql.y:4351 { yyLOCAL = &tree.ShowNodeList{} } @@ -15613,7 +15583,7 @@ yydefault: case 634: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4356 +//line mysql_sql.y:4357 { yyLOCAL = &tree.ShowLocks{} } @@ -15621,7 +15591,7 @@ yydefault: case 635: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4362 +//line mysql_sql.y:4363 { yyLOCAL = &tree.ShowTableNumber{DbName: yyDollar[4].str} } @@ -15629,7 +15599,7 @@ yydefault: case 636: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4368 +//line mysql_sql.y:4369 { yyLOCAL = &tree.ShowColumnNumber{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -15637,7 +15607,7 @@ yydefault: case 637: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4374 +//line mysql_sql.y:4375 { yyLOCAL = &tree.ShowTableValues{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -15645,7 +15615,7 @@ yydefault: case 638: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4380 +//line mysql_sql.y:4381 { yyLOCAL = &tree.ShowTableSize{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -15653,7 +15623,7 @@ yydefault: case 639: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4386 +//line mysql_sql.y:4387 { s := yyDollar[2].statementUnion().(*tree.ShowTarget) s.Like = yyDollar[3].comparisionExprUnion() @@ -15664,7 +15634,7 @@ yydefault: case 640: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4395 +//line mysql_sql.y:4396 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowConfig} } @@ -15672,7 +15642,7 @@ yydefault: case 641: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4399 +//line mysql_sql.y:4400 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowCharset} } @@ -15680,7 +15650,7 @@ yydefault: case 642: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4403 +//line mysql_sql.y:4404 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowEngines} } @@ -15688,7 +15658,7 @@ yydefault: case 643: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4407 +//line mysql_sql.y:4408 { yyLOCAL = &tree.ShowTarget{DbName: yyDollar[3].str, Type: tree.ShowTriggers} } @@ -15696,7 +15666,7 @@ yydefault: case 644: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4411 +//line mysql_sql.y:4412 { yyLOCAL = &tree.ShowTarget{DbName: yyDollar[3].str, Type: tree.ShowEvents} } @@ -15704,7 +15674,7 @@ yydefault: case 645: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4415 +//line mysql_sql.y:4416 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowPlugins} } @@ -15712,7 +15682,7 @@ yydefault: case 646: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4419 +//line mysql_sql.y:4420 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowPrivileges} } @@ -15720,7 +15690,7 @@ yydefault: case 647: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4423 +//line mysql_sql.y:4424 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowProfiles} } @@ -15728,7 +15698,7 @@ yydefault: case 648: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4429 +//line mysql_sql.y:4430 { yyLOCAL = &tree.ShowIndex{ TableName: yyDollar[4].unresolvedObjectNameUnion(), @@ -15739,18 +15709,18 @@ yydefault: yyVAL.union = yyLOCAL case 649: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4438 +//line mysql_sql.y:4439 { } case 650: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:4440 +//line mysql_sql.y:4441 { } case 654: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4449 +//line mysql_sql.y:4450 { yyLOCAL = &tree.ShowVariables{ Global: yyDollar[2].boolValUnion(), @@ -15762,7 +15732,7 @@ yydefault: case 655: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4459 +//line mysql_sql.y:4460 { yyLOCAL = &tree.ShowStatus{ Global: yyDollar[2].boolValUnion(), @@ -15774,7 +15744,7 @@ yydefault: case 656: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4468 +//line mysql_sql.y:4469 { yyLOCAL = false } @@ -15782,7 +15752,7 @@ yydefault: case 657: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4472 +//line mysql_sql.y:4473 { yyLOCAL = true } @@ -15790,7 +15760,7 @@ yydefault: case 658: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4476 +//line mysql_sql.y:4477 { yyLOCAL = false } @@ -15798,7 +15768,7 @@ yydefault: case 659: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4482 +//line mysql_sql.y:4483 { yyLOCAL = &tree.ShowWarnings{} } @@ -15806,7 +15776,7 @@ yydefault: case 660: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4488 +//line mysql_sql.y:4489 { yyLOCAL = &tree.ShowErrors{} } @@ -15814,7 +15784,7 @@ yydefault: case 661: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4494 +//line mysql_sql.y:4495 { yyLOCAL = &tree.ShowProcessList{Full: yyDollar[2].fullOptUnion()} } @@ -15822,7 +15792,7 @@ yydefault: case 662: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4500 +//line mysql_sql.y:4501 { yyLOCAL = &tree.ShowSequences{ DBName: yyDollar[3].str, @@ -15833,7 +15803,7 @@ yydefault: case 663: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4509 +//line mysql_sql.y:4510 { yyLOCAL = &tree.ShowTables{ Open: false, @@ -15848,7 +15818,7 @@ yydefault: case 664: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4520 +//line mysql_sql.y:4521 { yyLOCAL = &tree.ShowTables{ Open: true, @@ -15862,7 +15832,7 @@ yydefault: case 665: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4532 +//line mysql_sql.y:4533 { yyLOCAL = &tree.ShowDatabases{ Like: yyDollar[3].comparisionExprUnion(), @@ -15874,7 +15844,7 @@ yydefault: case 666: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4540 +//line mysql_sql.y:4541 { yyLOCAL = &tree.ShowDatabases{Like: yyDollar[3].comparisionExprUnion(), Where: yyDollar[4].whereUnion()} } @@ -15882,7 +15852,7 @@ yydefault: case 667: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4546 +//line mysql_sql.y:4547 { yyLOCAL = &tree.ShowColumns{ Ext: false, @@ -15898,7 +15868,7 @@ yydefault: case 668: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4558 +//line mysql_sql.y:4559 { yyLOCAL = &tree.ShowColumns{ Ext: true, @@ -15914,7 +15884,7 @@ yydefault: case 669: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4572 +//line mysql_sql.y:4573 { yyLOCAL = &tree.ShowAccounts{Like: yyDollar[3].comparisionExprUnion()} } @@ -15922,7 +15892,7 @@ yydefault: case 670: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4578 +//line mysql_sql.y:4579 { yyLOCAL = &tree.ShowPublications{Like: yyDollar[3].comparisionExprUnion()} } @@ -15930,7 +15900,7 @@ yydefault: case 671: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4584 +//line mysql_sql.y:4585 { yyLOCAL = &tree.ShowAccountUpgrade{} } @@ -15938,7 +15908,7 @@ yydefault: case 672: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4590 +//line mysql_sql.y:4591 { yyLOCAL = &tree.ShowSubscriptions{Like: yyDollar[3].comparisionExprUnion()} } @@ -15946,7 +15916,7 @@ yydefault: case 673: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4594 +//line mysql_sql.y:4595 { yyLOCAL = &tree.ShowSubscriptions{All: true, Like: yyDollar[4].comparisionExprUnion()} } @@ -15954,7 +15924,7 @@ yydefault: case 674: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:4599 +//line mysql_sql.y:4600 { yyLOCAL = nil } @@ -15962,7 +15932,7 @@ yydefault: case 675: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:4603 +//line mysql_sql.y:4604 { yyLOCAL = tree.NewComparisonExpr(tree.LIKE, nil, yyDollar[2].exprUnion()) } @@ -15970,27 +15940,27 @@ yydefault: case 676: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:4607 +//line mysql_sql.y:4608 { yyLOCAL = tree.NewComparisonExpr(tree.ILIKE, nil, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL case 677: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4612 +//line mysql_sql.y:4613 { yyVAL.str = "" } case 678: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:4616 +//line mysql_sql.y:4617 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } case 679: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4622 +//line mysql_sql.y:4623 { yyLOCAL = yyDollar[2].unresolvedObjectNameUnion() } @@ -15998,7 +15968,7 @@ yydefault: case 684: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4635 +//line mysql_sql.y:4636 { yyLOCAL = false } @@ -16006,7 +15976,7 @@ yydefault: case 685: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4639 +//line mysql_sql.y:4640 { yyLOCAL = true } @@ -16014,7 +15984,7 @@ yydefault: case 686: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4645 +//line mysql_sql.y:4646 { yyLOCAL = &tree.ShowCreateTable{ Name: yyDollar[4].unresolvedObjectNameUnion(), @@ -16025,7 +15995,7 @@ yydefault: case 687: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4653 +//line mysql_sql.y:4654 { yyLOCAL = &tree.ShowCreateView{ Name: yyDollar[4].unresolvedObjectNameUnion(), @@ -16036,7 +16006,7 @@ yydefault: case 688: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4660 +//line mysql_sql.y:4661 { yyLOCAL = &tree.ShowCreateDatabase{ IfNotExists: yyDollar[4].ifNotExistsUnion(), @@ -16048,7 +16018,7 @@ yydefault: case 689: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4668 +//line mysql_sql.y:4669 { yyLOCAL = &tree.ShowCreatePublications{Name: yyDollar[4].str} } @@ -16056,7 +16026,7 @@ yydefault: case 690: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4674 +//line mysql_sql.y:4675 { yyLOCAL = &tree.ShowBackendServers{} } @@ -16064,7 +16034,7 @@ yydefault: case 691: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4680 +//line mysql_sql.y:4681 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedObjectName(tblName) @@ -16073,7 +16043,7 @@ yydefault: case 692: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4685 +//line mysql_sql.y:4686 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -16082,14 +16052,14 @@ yydefault: yyVAL.union = yyLOCAL case 693: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:4693 +//line mysql_sql.y:4694 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) } case 694: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4699 +//line mysql_sql.y:4700 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedObjectName(tblName) @@ -16098,7 +16068,7 @@ yydefault: case 695: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4704 +//line mysql_sql.y:4705 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -16108,7 +16078,7 @@ yydefault: case 696: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:4710 +//line mysql_sql.y:4711 { yyLOCAL = tree.NewUnresolvedObjectName(yyDollar[1].cstrUnion().Compare(), yyDollar[3].cstrUnion().Compare(), yyDollar[5].cstrUnion().Compare()) } @@ -16116,7 +16086,7 @@ yydefault: case 697: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4716 +//line mysql_sql.y:4717 { yyLOCAL = tree.NewTruncateTable(yyDollar[2].tableNameUnion()) } @@ -16124,7 +16094,7 @@ yydefault: case 698: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4720 +//line mysql_sql.y:4721 { yyLOCAL = tree.NewTruncateTable(yyDollar[3].tableNameUnion()) } @@ -16132,7 +16102,7 @@ yydefault: case 717: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4748 +//line mysql_sql.y:4749 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNamesUnion() @@ -16142,7 +16112,7 @@ yydefault: case 718: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4756 +//line mysql_sql.y:4757 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].exprUnion() @@ -16152,7 +16122,7 @@ yydefault: case 719: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4764 +//line mysql_sql.y:4765 { var ifExists = yyDollar[3].boolValUnion() var users = yyDollar[4].usersUnion() @@ -16162,7 +16132,7 @@ yydefault: case 720: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:4772 +//line mysql_sql.y:4773 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } @@ -16170,7 +16140,7 @@ yydefault: case 721: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:4776 +//line mysql_sql.y:4777 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } @@ -16178,7 +16148,7 @@ yydefault: case 722: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:4782 +//line mysql_sql.y:4783 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -16193,7 +16163,7 @@ yydefault: case 723: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4795 +//line mysql_sql.y:4796 { var ifExists = yyDollar[3].boolValUnion() var roles = yyDollar[4].rolesUnion() @@ -16203,7 +16173,7 @@ yydefault: case 724: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4803 +//line mysql_sql.y:4804 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var tableName = yyDollar[6].tableNameUnion() @@ -16214,7 +16184,7 @@ yydefault: case 725: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4812 +//line mysql_sql.y:4813 { var ifExists = yyDollar[4].boolValUnion() var names = yyDollar[5].tableNamesUnion() @@ -16224,7 +16194,7 @@ yydefault: case 726: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4818 +//line mysql_sql.y:4819 { var ifExists = yyDollar[3].boolValUnion() var names = yyDollar[4].tableNamesUnion() @@ -16234,7 +16204,7 @@ yydefault: case 727: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4826 +//line mysql_sql.y:4827 { var ifExists = yyDollar[3].boolValUnion() var names = yyDollar[4].tableNamesUnion() @@ -16244,7 +16214,7 @@ yydefault: case 728: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4834 +//line mysql_sql.y:4835 { var ifExists = yyDollar[3].boolValUnion() var names = yyDollar[4].tableNamesUnion() @@ -16254,7 +16224,7 @@ yydefault: case 729: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4842 +//line mysql_sql.y:4843 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var ifExists = yyDollar[3].boolValUnion() @@ -16264,7 +16234,7 @@ yydefault: case 730: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4848 +//line mysql_sql.y:4849 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var ifExists = yyDollar[3].boolValUnion() @@ -16274,7 +16244,7 @@ yydefault: case 731: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4856 +//line mysql_sql.y:4857 { yyLOCAL = tree.NewDeallocate(tree.Identifier(yyDollar[3].str), true) } @@ -16282,7 +16252,7 @@ yydefault: case 732: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4862 +//line mysql_sql.y:4863 { var name = yyDollar[3].functionNameUnion() var args = yyDollar[5].funcArgsUnion() @@ -16292,7 +16262,7 @@ yydefault: case 733: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4870 +//line mysql_sql.y:4871 { var name = yyDollar[3].procNameUnion() var ifExists = false @@ -16302,7 +16272,7 @@ yydefault: case 734: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4876 +//line mysql_sql.y:4877 { var name = yyDollar[5].procNameUnion() var ifExists = true @@ -16312,7 +16282,7 @@ yydefault: case 737: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4886 +//line mysql_sql.y:4887 { yyDollar[2].statementUnion().(*tree.Delete).With = yyDollar[1].withClauseUnion() yyLOCAL = yyDollar[2].statementUnion() @@ -16321,7 +16291,7 @@ yydefault: case 738: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4891 +//line mysql_sql.y:4892 { yyDollar[2].statementUnion().(*tree.Delete).With = yyDollar[1].withClauseUnion() yyLOCAL = yyDollar[2].statementUnion() @@ -16330,7 +16300,7 @@ yydefault: case 739: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4898 +//line mysql_sql.y:4899 { // Single-Table Syntax t := &tree.AliasedTableExpr{ @@ -16350,7 +16320,7 @@ yydefault: case 740: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4914 +//line mysql_sql.y:4915 { // Multiple-Table Syntax yyLOCAL = &tree.Delete{ @@ -16363,7 +16333,7 @@ yydefault: case 741: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4925 +//line mysql_sql.y:4926 { // Multiple-Table Syntax yyLOCAL = &tree.Delete{ @@ -16376,7 +16346,7 @@ yydefault: case 742: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExprs -//line mysql_sql.y:4936 +//line mysql_sql.y:4937 { yyLOCAL = tree.TableExprs{yyDollar[1].tableNameUnion()} } @@ -16384,7 +16354,7 @@ yydefault: case 743: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExprs -//line mysql_sql.y:4940 +//line mysql_sql.y:4941 { yyLOCAL = append(yyDollar[1].tableExprsUnion(), yyDollar[3].tableNameUnion()) } @@ -16392,7 +16362,7 @@ yydefault: case 744: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:4946 +//line mysql_sql.y:4947 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{ExplicitSchema: false} @@ -16402,7 +16372,7 @@ yydefault: case 745: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:4952 +//line mysql_sql.y:4953 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -16412,33 +16382,33 @@ yydefault: yyVAL.union = yyLOCAL case 746: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4961 +//line mysql_sql.y:4962 { } case 747: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:4963 +//line mysql_sql.y:4964 { } case 748: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4966 +//line mysql_sql.y:4967 { } case 753: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4975 +//line mysql_sql.y:4976 { } case 755: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4979 +//line mysql_sql.y:4980 { } case 757: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4984 +//line mysql_sql.y:4985 { rep := yyDollar[4].replaceUnion() rep.Table = yyDollar[2].tableExprUnion() @@ -16449,7 +16419,7 @@ yydefault: case 758: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:4993 +//line mysql_sql.y:4994 { vc := tree.NewValuesClause(yyDollar[2].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -16460,7 +16430,7 @@ yydefault: case 759: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5000 +//line mysql_sql.y:5001 { yyLOCAL = &tree.Replace{ Rows: yyDollar[1].selectUnion(), @@ -16470,7 +16440,7 @@ yydefault: case 760: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5006 +//line mysql_sql.y:5007 { vc := tree.NewValuesClause(yyDollar[5].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -16482,7 +16452,7 @@ yydefault: case 761: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5014 +//line mysql_sql.y:5015 { vc := tree.NewValuesClause(yyDollar[4].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -16493,7 +16463,7 @@ yydefault: case 762: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5021 +//line mysql_sql.y:5022 { yyLOCAL = &tree.Replace{ Columns: yyDollar[2].identifierListUnion(), @@ -16504,7 +16474,7 @@ yydefault: case 763: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5028 +//line mysql_sql.y:5029 { if yyDollar[2].assignmentsUnion() == nil { yylex.Error("the set list of replace can not be empty") @@ -16526,7 +16496,7 @@ yydefault: case 764: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5048 +//line mysql_sql.y:5049 { ins := yyDollar[4].insertUnion() ins.Table = yyDollar[2].tableExprUnion() @@ -16538,7 +16508,7 @@ yydefault: case 765: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5056 +//line mysql_sql.y:5057 { ins := yyDollar[5].insertUnion() ins.Table = yyDollar[3].tableExprUnion() @@ -16550,7 +16520,7 @@ yydefault: case 766: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5066 +//line mysql_sql.y:5067 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].str)} } @@ -16558,7 +16528,7 @@ yydefault: case 767: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5070 +//line mysql_sql.y:5071 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].str)) } @@ -16566,7 +16536,7 @@ yydefault: case 768: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5076 +//line mysql_sql.y:5077 { vc := tree.NewValuesClause(yyDollar[2].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -16577,7 +16547,7 @@ yydefault: case 769: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5083 +//line mysql_sql.y:5084 { yyLOCAL = &tree.Insert{ Rows: yyDollar[1].selectUnion(), @@ -16587,7 +16557,7 @@ yydefault: case 770: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5089 +//line mysql_sql.y:5090 { vc := tree.NewValuesClause(yyDollar[5].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -16599,7 +16569,7 @@ yydefault: case 771: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5097 +//line mysql_sql.y:5098 { vc := tree.NewValuesClause(yyDollar[4].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -16610,7 +16580,7 @@ yydefault: case 772: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5104 +//line mysql_sql.y:5105 { yyLOCAL = &tree.Insert{ Columns: yyDollar[2].identifierListUnion(), @@ -16621,7 +16591,7 @@ yydefault: case 773: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:5111 +//line mysql_sql.y:5112 { if yyDollar[2].assignmentsUnion() == nil { yylex.Error("the set list of insert can not be empty") @@ -16643,7 +16613,7 @@ yydefault: case 774: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:5130 +//line mysql_sql.y:5131 { yyLOCAL = []*tree.UpdateExpr{} } @@ -16651,7 +16621,7 @@ yydefault: case 775: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:5134 +//line mysql_sql.y:5135 { yyLOCAL = yyDollar[5].updateExprsUnion() } @@ -16659,7 +16629,7 @@ yydefault: case 776: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:5138 +//line mysql_sql.y:5139 { yyLOCAL = []*tree.UpdateExpr{nil} } @@ -16667,7 +16637,7 @@ yydefault: case 777: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:5143 +//line mysql_sql.y:5144 { yyLOCAL = nil } @@ -16675,7 +16645,7 @@ yydefault: case 778: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:5147 +//line mysql_sql.y:5148 { yyLOCAL = []*tree.Assignment{yyDollar[1].assignmentUnion()} } @@ -16683,7 +16653,7 @@ yydefault: case 779: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:5151 +//line mysql_sql.y:5152 { yyLOCAL = append(yyDollar[1].assignmentsUnion(), yyDollar[3].assignmentUnion()) } @@ -16691,7 +16661,7 @@ yydefault: case 780: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Assignment -//line mysql_sql.y:5157 +//line mysql_sql.y:5158 { yyLOCAL = &tree.Assignment{ Column: tree.Identifier(yyDollar[1].str), @@ -16702,7 +16672,7 @@ yydefault: case 781: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5166 +//line mysql_sql.y:5167 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].str)} } @@ -16710,27 +16680,27 @@ yydefault: case 782: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5170 +//line mysql_sql.y:5171 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].str)) } yyVAL.union = yyLOCAL case 783: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:5176 +//line mysql_sql.y:5177 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) } case 784: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:5180 +//line mysql_sql.y:5181 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) } case 785: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:5186 +//line mysql_sql.y:5187 { yyLOCAL = []tree.Exprs{yyDollar[1].exprsUnion()} } @@ -16738,7 +16708,7 @@ yydefault: case 786: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:5190 +//line mysql_sql.y:5191 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[3].exprsUnion()) } @@ -16746,20 +16716,20 @@ yydefault: case 787: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:5196 +//line mysql_sql.y:5197 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL case 788: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5201 +//line mysql_sql.y:5202 { } case 790: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:5205 +//line mysql_sql.y:5206 { yyLOCAL = nil } @@ -16767,7 +16737,7 @@ yydefault: case 792: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:5212 +//line mysql_sql.y:5213 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } @@ -16775,7 +16745,7 @@ yydefault: case 793: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:5216 +//line mysql_sql.y:5217 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } @@ -16783,7 +16753,7 @@ yydefault: case 795: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:5223 +//line mysql_sql.y:5224 { yyLOCAL = &tree.DefaultVal{} } @@ -16791,7 +16761,7 @@ yydefault: case 796: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5228 +//line mysql_sql.y:5229 { yyLOCAL = nil } @@ -16799,7 +16769,7 @@ yydefault: case 797: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5232 +//line mysql_sql.y:5233 { yyLOCAL = yyDollar[3].identifierListUnion() } @@ -16807,7 +16777,7 @@ yydefault: case 798: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5238 +//line mysql_sql.y:5239 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -16815,7 +16785,7 @@ yydefault: case 799: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5242 +//line mysql_sql.y:5243 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -16823,7 +16793,7 @@ yydefault: case 800: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:5248 +//line mysql_sql.y:5249 { yyLOCAL = yyDollar[2].tableNameUnion() } @@ -16831,7 +16801,7 @@ yydefault: case 801: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:5252 +//line mysql_sql.y:5253 { yyLOCAL = yyDollar[1].tableNameUnion() } @@ -16839,7 +16809,7 @@ yydefault: case 802: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ExportParam -//line mysql_sql.y:5257 +//line mysql_sql.y:5258 { yyLOCAL = nil } @@ -16847,7 +16817,7 @@ yydefault: case 803: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.ExportParam -//line mysql_sql.y:5261 +//line mysql_sql.y:5262 { yyLOCAL = &tree.ExportParam{ Outfile: true, @@ -16863,7 +16833,7 @@ yydefault: case 804: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:5274 +//line mysql_sql.y:5275 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -16878,7 +16848,7 @@ yydefault: case 805: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:5285 +//line mysql_sql.y:5286 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -16893,7 +16863,7 @@ yydefault: case 806: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:5296 +//line mysql_sql.y:5297 { str := yyDollar[7].str if str != "\\" && len(str) > 1 { @@ -16919,7 +16889,7 @@ yydefault: case 807: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:5318 +//line mysql_sql.y:5319 { str := yyDollar[4].str if str != "\\" && len(str) > 1 { @@ -16945,7 +16915,7 @@ yydefault: case 808: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:5341 +//line mysql_sql.y:5342 { yyLOCAL = &tree.Lines{ TerminatedBy: &tree.Terminated{ @@ -16957,7 +16927,7 @@ yydefault: case 809: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:5349 +//line mysql_sql.y:5350 { yyLOCAL = &tree.Lines{ TerminatedBy: &tree.Terminated{ @@ -16969,7 +16939,7 @@ yydefault: case 810: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5358 +//line mysql_sql.y:5359 { yyLOCAL = true } @@ -16977,7 +16947,7 @@ yydefault: case 811: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5362 +//line mysql_sql.y:5363 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -16993,7 +16963,7 @@ yydefault: case 812: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:5375 +//line mysql_sql.y:5376 { yyLOCAL = 0 } @@ -17001,7 +16971,7 @@ yydefault: case 813: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:5379 +//line mysql_sql.y:5380 { yyLOCAL = yyDollar[2].item.(int64) } @@ -17009,7 +16979,7 @@ yydefault: case 814: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:5384 +//line mysql_sql.y:5385 { yyLOCAL = []string{} } @@ -17017,7 +16987,7 @@ yydefault: case 815: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:5388 +//line mysql_sql.y:5389 { yyLOCAL = yyDollar[3].strsUnion() } @@ -17025,7 +16995,7 @@ yydefault: case 816: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:5394 +//line mysql_sql.y:5395 { yyLOCAL = make([]string, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].cstrUnion().Compare()) @@ -17034,7 +17004,7 @@ yydefault: case 817: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:5399 +//line mysql_sql.y:5400 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].cstrUnion().Compare()) } @@ -17042,7 +17012,7 @@ yydefault: case 819: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5406 +//line mysql_sql.y:5407 { yyLOCAL = &tree.Select{Select: yyDollar[1].selectStatementUnion()} } @@ -17050,7 +17020,7 @@ yydefault: case 820: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5412 +//line mysql_sql.y:5413 { yyLOCAL = &tree.Select{Select: yyDollar[1].selectStatementUnion(), TimeWindow: yyDollar[2].timeWindowUnion(), OrderBy: yyDollar[3].orderByUnion(), Limit: yyDollar[4].limitUnion(), Ep: yyDollar[5].exportParmUnion(), SelectLockInfo: yyDollar[6].selectLockInfoUnion()} } @@ -17058,7 +17028,7 @@ yydefault: case 821: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5416 +//line mysql_sql.y:5417 { yyLOCAL = &tree.Select{Select: yyDollar[1].selectStatementUnion(), TimeWindow: yyDollar[2].timeWindowUnion(), OrderBy: yyDollar[3].orderByUnion(), Ep: yyDollar[4].exportParmUnion()} } @@ -17066,7 +17036,7 @@ yydefault: case 822: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5420 +//line mysql_sql.y:5421 { yyLOCAL = &tree.Select{Select: yyDollar[1].selectStatementUnion(), TimeWindow: yyDollar[2].timeWindowUnion(), OrderBy: yyDollar[3].orderByUnion(), Limit: yyDollar[4].limitUnion(), Ep: yyDollar[5].exportParmUnion()} } @@ -17074,7 +17044,7 @@ yydefault: case 823: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5424 +//line mysql_sql.y:5425 { yyLOCAL = &tree.Select{Select: yyDollar[2].selectStatementUnion(), TimeWindow: yyDollar[3].timeWindowUnion(), OrderBy: yyDollar[4].orderByUnion(), Limit: yyDollar[5].limitUnion(), Ep: yyDollar[6].exportParmUnion(), SelectLockInfo: yyDollar[7].selectLockInfoUnion(), With: yyDollar[1].withClauseUnion()} } @@ -17082,7 +17052,7 @@ yydefault: case 824: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5428 +//line mysql_sql.y:5429 { yyLOCAL = &tree.Select{Select: yyDollar[2].selectStatementUnion(), OrderBy: yyDollar[3].orderByUnion(), Ep: yyDollar[4].exportParmUnion(), With: yyDollar[1].withClauseUnion()} } @@ -17090,7 +17060,7 @@ yydefault: case 825: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:5432 +//line mysql_sql.y:5433 { yyLOCAL = &tree.Select{Select: yyDollar[2].selectStatementUnion(), OrderBy: yyDollar[3].orderByUnion(), Limit: yyDollar[4].limitUnion(), Ep: yyDollar[5].exportParmUnion(), With: yyDollar[1].withClauseUnion()} } @@ -17098,7 +17068,7 @@ yydefault: case 826: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:5437 +//line mysql_sql.y:5438 { yyLOCAL = nil } @@ -17106,7 +17076,7 @@ yydefault: case 827: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:5441 +//line mysql_sql.y:5442 { yyLOCAL = yyDollar[1].timeWindowUnion() } @@ -17114,7 +17084,7 @@ yydefault: case 828: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:5447 +//line mysql_sql.y:5448 { yyLOCAL = &tree.TimeWindow{ Interval: yyDollar[1].timeIntervalUnion(), @@ -17126,7 +17096,7 @@ yydefault: case 829: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.Interval -//line mysql_sql.y:5457 +//line mysql_sql.y:5458 { str := fmt.Sprintf("%v", yyDollar[5].item) v, errStr := util.GetInt64(yyDollar[5].item) @@ -17144,7 +17114,7 @@ yydefault: case 830: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Sliding -//line mysql_sql.y:5472 +//line mysql_sql.y:5473 { yyLOCAL = nil } @@ -17152,7 +17122,7 @@ yydefault: case 831: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Sliding -//line mysql_sql.y:5476 +//line mysql_sql.y:5477 { str := fmt.Sprintf("%v", yyDollar[3].item) v, errStr := util.GetInt64(yyDollar[3].item) @@ -17169,7 +17139,7 @@ yydefault: case 832: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:5490 +//line mysql_sql.y:5491 { yyLOCAL = nil } @@ -17177,7 +17147,7 @@ yydefault: case 833: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:5494 +//line mysql_sql.y:5495 { yyLOCAL = &tree.Fill{ Mode: yyDollar[3].fillModeUnion(), @@ -17187,7 +17157,7 @@ yydefault: case 834: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:5500 +//line mysql_sql.y:5501 { yyLOCAL = &tree.Fill{ Mode: tree.FillValue, @@ -17198,7 +17168,7 @@ yydefault: case 835: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:5509 +//line mysql_sql.y:5510 { yyLOCAL = tree.FillPrev } @@ -17206,7 +17176,7 @@ yydefault: case 836: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:5513 +//line mysql_sql.y:5514 { yyLOCAL = tree.FillNext } @@ -17214,7 +17184,7 @@ yydefault: case 837: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:5517 +//line mysql_sql.y:5518 { yyLOCAL = tree.FillNone } @@ -17222,7 +17192,7 @@ yydefault: case 838: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:5521 +//line mysql_sql.y:5522 { yyLOCAL = tree.FillNull } @@ -17230,7 +17200,7 @@ yydefault: case 839: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:5525 +//line mysql_sql.y:5526 { yyLOCAL = tree.FillLinear } @@ -17238,7 +17208,7 @@ yydefault: case 840: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.With -//line mysql_sql.y:5531 +//line mysql_sql.y:5532 { yyLOCAL = &tree.With{ IsRecursive: false, @@ -17249,7 +17219,7 @@ yydefault: case 841: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.With -//line mysql_sql.y:5538 +//line mysql_sql.y:5539 { yyLOCAL = &tree.With{ IsRecursive: true, @@ -17260,7 +17230,7 @@ yydefault: case 842: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.CTE -//line mysql_sql.y:5547 +//line mysql_sql.y:5548 { yyLOCAL = []*tree.CTE{yyDollar[1].cteUnion()} } @@ -17268,7 +17238,7 @@ yydefault: case 843: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.CTE -//line mysql_sql.y:5551 +//line mysql_sql.y:5552 { yyLOCAL = append(yyDollar[1].cteListUnion(), yyDollar[3].cteUnion()) } @@ -17276,7 +17246,7 @@ yydefault: case 844: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.CTE -//line mysql_sql.y:5557 +//line mysql_sql.y:5558 { yyLOCAL = &tree.CTE{ Name: &tree.AliasClause{Alias: tree.Identifier(yyDollar[1].cstrUnion().Compare()), Cols: yyDollar[2].identifierListUnion()}, @@ -17287,7 +17257,7 @@ yydefault: case 845: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5565 +//line mysql_sql.y:5566 { yyLOCAL = nil } @@ -17295,7 +17265,7 @@ yydefault: case 846: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:5569 +//line mysql_sql.y:5570 { yyLOCAL = yyDollar[2].identifierListUnion() } @@ -17303,7 +17273,7 @@ yydefault: case 847: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:5574 +//line mysql_sql.y:5575 { yyLOCAL = nil } @@ -17311,169 +17281,231 @@ yydefault: case 848: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:5578 +//line mysql_sql.y:5579 { yyLOCAL = yyDollar[1].limitUnion() } yyVAL.union = yyLOCAL case 849: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:5584 +//line mysql_sql.y:5585 { - yyLOCAL = &tree.Limit{Count: yyDollar[2].exprUnion()} + l := &tree.Limit{Count: yyDollar[2].exprUnion()} + if yyDollar[3].limitUnion() != nil { + l.ByRank = yyDollar[3].limitUnion().ByRank + l.Option = yyDollar[3].limitUnion().Option + } + yyLOCAL = l } yyVAL.union = yyLOCAL case 850: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:5588 +//line mysql_sql.y:5594 { - yyLOCAL = &tree.Limit{Offset: yyDollar[2].exprUnion(), Count: yyDollar[4].exprUnion()} + l := &tree.Limit{Offset: yyDollar[2].exprUnion(), Count: yyDollar[4].exprUnion()} + if yyDollar[5].limitUnion() != nil { + l.ByRank = yyDollar[5].limitUnion().ByRank + l.Option = yyDollar[5].limitUnion().Option + } + yyLOCAL = l } yyVAL.union = yyLOCAL case 851: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:5592 +//line mysql_sql.y:5603 { - yyLOCAL = &tree.Limit{Offset: yyDollar[4].exprUnion(), Count: yyDollar[2].exprUnion()} + l := &tree.Limit{Offset: yyDollar[4].exprUnion(), Count: yyDollar[2].exprUnion()} + if yyDollar[5].limitUnion() != nil { + l.ByRank = yyDollar[5].limitUnion().ByRank + l.Option = yyDollar[5].limitUnion().Option + } + yyLOCAL = l } yyVAL.union = yyLOCAL case 852: yyDollar = yyS[yypt-0 : yypt+1] - var yyLOCAL tree.OrderBy -//line mysql_sql.y:5597 + var yyLOCAL *tree.Limit +//line mysql_sql.y:5613 { yyLOCAL = nil } yyVAL.union = yyLOCAL case 853: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL *tree.Limit +//line mysql_sql.y:5617 + { + // Parse option strings to extract key=value pairs into a map + optionMap := make(map[string]string) + + for _, expr := range yyDollar[5].exprsUnion() { + var str string + // Handle both NumVal (P_char) and StrVal + if numVal, ok := expr.(*tree.NumVal); ok && numVal.ValType == tree.P_char { + str = numVal.String() + } else if strVal, ok := expr.(*tree.StrVal); ok { + str = strVal.String() + } else { + continue + } + + // Remove quotes if present + if len(str) >= 2 && ((str[0] == '\'' && str[len(str)-1] == '\'') || (str[0] == '"' && str[len(str)-1] == '"')) { + str = str[1 : len(str)-1] + } + + // Parse key=value pairs + parts := strings.Split(str, "=") + if len(parts) == 2 { + key := strings.TrimSpace(strings.ToLower(parts[0])) + value := strings.TrimSpace(parts[1]) + optionMap[key] = value + } + } + + yyLOCAL = &tree.Limit{ + ByRank: true, + Option: optionMap, + } + } + yyVAL.union = yyLOCAL + case 854: + yyDollar = yyS[yypt-0 : yypt+1] + var yyLOCAL tree.OrderBy +//line mysql_sql.y:5653 + { + yyLOCAL = nil + } + yyVAL.union = yyLOCAL + case 855: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:5601 +//line mysql_sql.y:5657 { yyLOCAL = yyDollar[1].orderByUnion() } yyVAL.union = yyLOCAL - case 854: + case 856: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:5607 +//line mysql_sql.y:5663 { yyLOCAL = yyDollar[3].orderByUnion() } yyVAL.union = yyLOCAL - case 855: + case 857: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:5613 +//line mysql_sql.y:5669 { yyLOCAL = tree.OrderBy{yyDollar[1].orderUnion()} } yyVAL.union = yyLOCAL - case 856: + case 858: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:5617 +//line mysql_sql.y:5673 { yyLOCAL = append(yyDollar[1].orderByUnion(), yyDollar[3].orderUnion()) } yyVAL.union = yyLOCAL - case 857: + case 859: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Order -//line mysql_sql.y:5623 +//line mysql_sql.y:5679 { yyLOCAL = &tree.Order{Expr: yyDollar[1].exprUnion(), Direction: yyDollar[2].directionUnion(), NullsPosition: yyDollar[3].nullsPositionUnion()} } yyVAL.union = yyLOCAL - case 858: + case 860: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:5628 +//line mysql_sql.y:5684 { yyLOCAL = tree.DefaultDirection } yyVAL.union = yyLOCAL - case 859: + case 861: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:5632 +//line mysql_sql.y:5688 { yyLOCAL = tree.Ascending } yyVAL.union = yyLOCAL - case 860: + case 862: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:5636 +//line mysql_sql.y:5692 { yyLOCAL = tree.Descending } yyVAL.union = yyLOCAL - case 861: + case 863: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.NullsPosition -//line mysql_sql.y:5641 +//line mysql_sql.y:5697 { yyLOCAL = tree.DefaultNullsPosition } yyVAL.union = yyLOCAL - case 862: + case 864: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.NullsPosition -//line mysql_sql.y:5645 +//line mysql_sql.y:5701 { yyLOCAL = tree.NullsFirst } yyVAL.union = yyLOCAL - case 863: + case 865: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.NullsPosition -//line mysql_sql.y:5649 +//line mysql_sql.y:5705 { yyLOCAL = tree.NullsLast } yyVAL.union = yyLOCAL - case 864: + case 866: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:5654 +//line mysql_sql.y:5710 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 865: + case 867: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:5658 +//line mysql_sql.y:5714 { yyLOCAL = &tree.SelectLockInfo{ LockType: tree.SelectLockForUpdate, } } yyVAL.union = yyLOCAL - case 866: + case 868: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5666 +//line mysql_sql.y:5722 { yyLOCAL = &tree.ParenSelect{Select: yyDollar[2].selectUnion()} } yyVAL.union = yyLOCAL - case 867: + case 869: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5670 +//line mysql_sql.y:5726 { yyLOCAL = &tree.ParenSelect{Select: &tree.Select{Select: yyDollar[2].selectStatementUnion()}} } yyVAL.union = yyLOCAL - case 868: + case 870: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5674 +//line mysql_sql.y:5730 { valuesStmt := yyDollar[2].statementUnion().(*tree.ValuesStatement) yyLOCAL = &tree.ParenSelect{Select: &tree.Select{ @@ -17486,18 +17518,18 @@ yydefault: }} } yyVAL.union = yyLOCAL - case 869: + case 871: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5688 +//line mysql_sql.y:5744 { yyLOCAL = yyDollar[1].selectStatementUnion() } yyVAL.union = yyLOCAL - case 870: + case 872: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5692 +//line mysql_sql.y:5748 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -17508,10 +17540,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 871: + case 873: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5702 +//line mysql_sql.y:5758 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -17522,10 +17554,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 872: + case 874: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5712 +//line mysql_sql.y:5768 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -17536,10 +17568,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 873: + case 875: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5722 +//line mysql_sql.y:5778 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -17550,10 +17582,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 874: + case 876: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5734 +//line mysql_sql.y:5790 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -17562,10 +17594,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 875: + case 877: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5742 +//line mysql_sql.y:5798 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -17574,10 +17606,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 876: + case 878: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5750 +//line mysql_sql.y:5806 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -17586,10 +17618,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 877: + case 879: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5759 +//line mysql_sql.y:5815 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -17598,10 +17630,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 878: + case 880: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5767 +//line mysql_sql.y:5823 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -17610,10 +17642,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 879: + case 881: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5775 +//line mysql_sql.y:5831 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -17622,10 +17654,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 880: + case 882: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5783 +//line mysql_sql.y:5839 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -17634,10 +17666,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 881: + case 883: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5791 +//line mysql_sql.y:5847 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -17646,10 +17678,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 882: + case 884: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5799 +//line mysql_sql.y:5855 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -17658,10 +17690,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 883: + case 885: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5807 +//line mysql_sql.y:5863 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -17670,10 +17702,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 884: + case 886: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5815 +//line mysql_sql.y:5871 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -17682,10 +17714,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 885: + case 887: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:5823 +//line mysql_sql.y:5879 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -17694,10 +17726,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 886: + case 888: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:5833 +//line mysql_sql.y:5889 { yyLOCAL = &tree.SelectClause{ Distinct: tree.QuerySpecOptionDistinct&yyDollar[2].selectOptionsUnion() != 0, @@ -17710,146 +17742,146 @@ yydefault: } } yyVAL.union = yyLOCAL - case 887: + case 889: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5846 +//line mysql_sql.y:5902 { yyLOCAL = tree.QuerySpecOptionNone } yyVAL.union = yyLOCAL - case 888: + case 890: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5850 +//line mysql_sql.y:5906 { yyLOCAL = yyDollar[1].selectOptionsUnion() } yyVAL.union = yyLOCAL - case 889: + case 891: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5856 +//line mysql_sql.y:5912 { yyLOCAL = yyDollar[1].selectOptionUnion() } yyVAL.union = yyLOCAL - case 890: + case 892: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5860 +//line mysql_sql.y:5916 { yyLOCAL = yyDollar[1].selectOptionsUnion() | yyDollar[2].selectOptionUnion() } yyVAL.union = yyLOCAL - case 891: + case 893: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5866 +//line mysql_sql.y:5922 { yyLOCAL = tree.QuerySpecOptionSqlSmallResult } yyVAL.union = yyLOCAL - case 892: + case 894: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5870 +//line mysql_sql.y:5926 { yyLOCAL = tree.QuerySpecOptionSqlBigResult } yyVAL.union = yyLOCAL - case 893: + case 895: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5874 +//line mysql_sql.y:5930 { yyLOCAL = tree.QuerySpecOptionSqlBufferResult } yyVAL.union = yyLOCAL - case 894: + case 896: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5878 +//line mysql_sql.y:5934 { yyLOCAL = tree.QuerySpecOptionStraightJoin } yyVAL.union = yyLOCAL - case 895: + case 897: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5882 +//line mysql_sql.y:5938 { yyLOCAL = tree.QuerySpecOptionHighPriority } yyVAL.union = yyLOCAL - case 896: + case 898: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5886 +//line mysql_sql.y:5942 { yyLOCAL = tree.QuerySpecOptionSqlCalcFoundRows } yyVAL.union = yyLOCAL - case 897: + case 899: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5890 +//line mysql_sql.y:5946 { yyLOCAL = tree.QuerySpecOptionSqlNoCache } yyVAL.union = yyLOCAL - case 898: + case 900: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5894 +//line mysql_sql.y:5950 { yyLOCAL = tree.QuerySpecOptionAll } yyVAL.union = yyLOCAL - case 899: + case 901: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5898 +//line mysql_sql.y:5954 { yyLOCAL = tree.QuerySpecOptionDistinct } yyVAL.union = yyLOCAL - case 900: + case 902: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:5902 +//line mysql_sql.y:5958 { yyLOCAL = tree.QuerySpecOptionDistinctRow } yyVAL.union = yyLOCAL - case 901: + case 903: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:5924 +//line mysql_sql.y:5980 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 902: + case 904: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:5928 +//line mysql_sql.y:5984 { yyLOCAL = &tree.Where{Type: tree.AstHaving, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 903: + case 905: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:5933 +//line mysql_sql.y:5989 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 904: + case 906: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:5937 +//line mysql_sql.y:5993 { exprsList := []tree.Exprs{yyDollar[3].exprsUnion()} yyLOCAL = &tree.GroupByClause{ @@ -17860,10 +17892,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 905: + case 907: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:5947 +//line mysql_sql.y:6003 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: yyDollar[6].rowsExprsUnion(), @@ -17873,10 +17905,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 906: + case 908: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:5956 +//line mysql_sql.y:6012 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: []tree.Exprs{yyDollar[5].exprsUnion()}, @@ -17886,10 +17918,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 907: + case 909: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:5965 +//line mysql_sql.y:6021 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: []tree.Exprs{yyDollar[5].exprsUnion()}, @@ -17899,106 +17931,106 @@ yydefault: } } yyVAL.union = yyLOCAL - case 908: + case 910: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:5976 +//line mysql_sql.y:6032 { yyLOCAL = []tree.Exprs{yyDollar[2].exprsUnion()} } yyVAL.union = yyLOCAL - case 909: + case 911: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:5980 +//line mysql_sql.y:6036 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[4].exprsUnion()) } yyVAL.union = yyLOCAL - case 910: + case 912: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5985 +//line mysql_sql.y:6041 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 911: + case 913: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5989 +//line mysql_sql.y:6045 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 912: + case 914: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:5994 +//line mysql_sql.y:6050 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 913: + case 915: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:5998 +//line mysql_sql.y:6054 { yyLOCAL = &tree.Where{Type: tree.AstWhere, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 914: + case 916: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:6004 +//line mysql_sql.y:6060 { yyLOCAL = tree.SelectExprs{yyDollar[1].selectExprUnion()} } yyVAL.union = yyLOCAL - case 915: + case 917: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:6008 +//line mysql_sql.y:6064 { yyLOCAL = append(yyDollar[1].selectExprsUnion(), yyDollar[3].selectExprUnion()) } yyVAL.union = yyLOCAL - case 916: + case 918: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:6014 +//line mysql_sql.y:6070 { yyLOCAL = tree.SelectExpr{Expr: tree.StarExpr()} } yyVAL.union = yyLOCAL - case 917: + case 919: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:6018 +//line mysql_sql.y:6074 { yyLOCAL = tree.SelectExpr{Expr: yyDollar[1].exprUnion(), As: yyDollar[2].cstrUnion()} } yyVAL.union = yyLOCAL - case 918: + case 920: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:6022 +//line mysql_sql.y:6078 { yyLOCAL = tree.SelectExpr{Expr: tree.NewUnresolvedNameWithStar(yyDollar[1].cstrUnion())} } yyVAL.union = yyLOCAL - case 919: + case 921: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:6026 +//line mysql_sql.y:6082 { yyLOCAL = tree.SelectExpr{Expr: tree.NewUnresolvedNameWithStar(yyDollar[1].cstrUnion(), yyDollar[3].cstrUnion())} } yyVAL.union = yyLOCAL - case 920: + case 922: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:6031 +//line mysql_sql.y:6087 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} tn := tree.NewTableName(tree.Identifier(""), prefix, nil) @@ -18007,28 +18039,28 @@ yydefault: } } yyVAL.union = yyLOCAL - case 921: + case 923: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:6039 +//line mysql_sql.y:6095 { yyLOCAL = yyDollar[1].fromUnion() } yyVAL.union = yyLOCAL - case 922: + case 924: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:6045 +//line mysql_sql.y:6101 { yyLOCAL = &tree.From{ Tables: tree.TableExprs{yyDollar[2].tableExprUnion()}, } } yyVAL.union = yyLOCAL - case 923: + case 925: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6053 +//line mysql_sql.y:6109 { if t, ok := yyDollar[1].tableExprUnion().(*tree.JoinTableExpr); ok { yyLOCAL = t @@ -18039,34 +18071,34 @@ yydefault: } } yyVAL.union = yyLOCAL - case 924: + case 926: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6063 +//line mysql_sql.y:6119 { yyLOCAL = &tree.JoinTableExpr{Left: yyDollar[1].tableExprUnion(), Right: yyDollar[3].tableExprUnion(), JoinType: tree.JOIN_TYPE_CROSS} } yyVAL.union = yyLOCAL - case 927: + case 929: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6073 +//line mysql_sql.y:6129 { yyLOCAL = yyDollar[1].joinTableExprUnion() } yyVAL.union = yyLOCAL - case 928: + case 930: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6077 +//line mysql_sql.y:6133 { yyLOCAL = yyDollar[1].applyTableExprUnion() } yyVAL.union = yyLOCAL - case 929: + case 931: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:6083 +//line mysql_sql.y:6139 { if strings.Contains(yyDollar[2].str, ":") { ss := strings.SplitN(yyDollar[2].str, ":", 2) @@ -18087,10 +18119,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 930: + case 932: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:6103 +//line mysql_sql.y:6159 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -18100,10 +18132,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 931: + case 933: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:6112 +//line mysql_sql.y:6168 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -18113,10 +18145,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 932: + case 934: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:6121 +//line mysql_sql.y:6177 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -18125,10 +18157,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 933: + case 935: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:6129 +//line mysql_sql.y:6185 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -18138,10 +18170,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 934: + case 936: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ApplyTableExpr -//line mysql_sql.y:6140 +//line mysql_sql.y:6196 { yyLOCAL = &tree.ApplyTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -18150,27 +18182,27 @@ yydefault: } } yyVAL.union = yyLOCAL - case 935: + case 937: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6150 +//line mysql_sql.y:6206 { yyVAL.str = tree.APPLY_TYPE_CROSS } - case 936: + case 938: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6154 +//line mysql_sql.y:6210 { yyVAL.str = tree.APPLY_TYPE_OUTER } - case 937: + case 939: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6160 +//line mysql_sql.y:6216 { yyVAL.str = tree.JOIN_TYPE_NATURAL } - case 938: + case 940: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6164 +//line mysql_sql.y:6220 { if yyDollar[2].str == tree.JOIN_TYPE_LEFT { yyVAL.str = tree.JOIN_TYPE_NATURAL_LEFT @@ -18178,40 +18210,40 @@ yydefault: yyVAL.str = tree.JOIN_TYPE_NATURAL_RIGHT } } - case 939: + case 941: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6174 +//line mysql_sql.y:6230 { yyVAL.str = tree.JOIN_TYPE_LEFT } - case 940: + case 942: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6178 +//line mysql_sql.y:6234 { yyVAL.str = tree.JOIN_TYPE_LEFT } - case 941: + case 943: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6182 +//line mysql_sql.y:6238 { yyVAL.str = tree.JOIN_TYPE_RIGHT } - case 942: + case 944: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6186 +//line mysql_sql.y:6242 { yyVAL.str = tree.JOIN_TYPE_RIGHT } - case 943: + case 945: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6192 +//line mysql_sql.y:6248 { yyVAL.str = tree.JOIN_TYPE_DEDUP } - case 944: + case 946: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6198 +//line mysql_sql.y:6254 { yyLOCAL = &tree.ValuesStatement{ Rows: yyDollar[2].rowsExprsUnion(), @@ -18220,148 +18252,148 @@ yydefault: } } yyVAL.union = yyLOCAL - case 945: + case 947: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:6208 +//line mysql_sql.y:6264 { yyLOCAL = []tree.Exprs{yyDollar[1].exprsUnion()} } yyVAL.union = yyLOCAL - case 946: + case 948: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:6212 +//line mysql_sql.y:6268 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[3].exprsUnion()) } yyVAL.union = yyLOCAL - case 947: + case 949: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:6218 +//line mysql_sql.y:6274 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 948: + case 950: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6224 +//line mysql_sql.y:6280 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 949: + case 951: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6228 +//line mysql_sql.y:6284 { yyLOCAL = &tree.OnJoinCond{Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 950: + case 952: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6234 +//line mysql_sql.y:6290 { yyVAL.str = yyDollar[1].str } - case 951: + case 953: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6240 +//line mysql_sql.y:6296 { yyVAL.str = yyDollar[2].str } - case 952: + case 954: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6246 +//line mysql_sql.y:6302 { yyVAL.str = tree.JOIN_TYPE_STRAIGHT } - case 953: + case 955: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6252 +//line mysql_sql.y:6308 { yyVAL.str = tree.JOIN_TYPE_INNER } - case 954: + case 956: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6256 +//line mysql_sql.y:6312 { yyVAL.str = tree.JOIN_TYPE_INNER } - case 955: + case 957: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6260 +//line mysql_sql.y:6316 { yyVAL.str = tree.JOIN_TYPE_CROSS } - case 956: + case 958: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6264 +//line mysql_sql.y:6320 { yyVAL.str = tree.JOIN_TYPE_CENTROIDX + ":" + yyDollar[2].str } - case 957: + case 959: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6270 +//line mysql_sql.y:6326 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 958: + case 960: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6274 +//line mysql_sql.y:6330 { yyLOCAL = yyDollar[1].joinCondUnion() } yyVAL.union = yyLOCAL - case 959: + case 961: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6280 +//line mysql_sql.y:6336 { yyLOCAL = &tree.OnJoinCond{Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 960: + case 962: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:6284 +//line mysql_sql.y:6340 { yyLOCAL = &tree.UsingJoinCond{Cols: yyDollar[3].identifierListUnion()} } yyVAL.union = yyLOCAL - case 961: + case 963: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6290 +//line mysql_sql.y:6346 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } yyVAL.union = yyLOCAL - case 962: + case 964: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6294 +//line mysql_sql.y:6350 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } yyVAL.union = yyLOCAL - case 963: + case 965: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6300 +//line mysql_sql.y:6356 { yyLOCAL = yyDollar[1].aliasedTableExprUnion() } yyVAL.union = yyLOCAL - case 964: + case 966: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6304 +//line mysql_sql.y:6360 { yyLOCAL = &tree.AliasedTableExpr{ Expr: yyDollar[1].parenTableExprUnion(), @@ -18372,10 +18404,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 965: + case 967: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6314 +//line mysql_sql.y:6370 { if yyDollar[2].str != "" { yyLOCAL = &tree.AliasedTableExpr{ @@ -18389,26 +18421,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 966: + case 968: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6327 +//line mysql_sql.y:6383 { yyLOCAL = yyDollar[2].tableExprUnion() } yyVAL.union = yyLOCAL - case 967: + case 969: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ParenTableExpr -//line mysql_sql.y:6333 +//line mysql_sql.y:6389 { yyLOCAL = &tree.ParenTableExpr{Expr: yyDollar[1].selectStatementUnion().(*tree.ParenSelect).Select} } yyVAL.union = yyLOCAL - case 968: + case 970: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6339 +//line mysql_sql.y:6395 { name := tree.NewUnresolvedName(yyDollar[1].cstrUnion()) yyLOCAL = &tree.TableFunction{ @@ -18421,10 +18453,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 969: + case 971: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AliasedTableExpr -//line mysql_sql.y:6353 +//line mysql_sql.y:6409 { yyLOCAL = &tree.AliasedTableExpr{ Expr: yyDollar[1].tableNameUnion(), @@ -18435,34 +18467,34 @@ yydefault: } } yyVAL.union = yyLOCAL - case 970: + case 972: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:6364 +//line mysql_sql.y:6420 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 972: + case 974: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:6371 +//line mysql_sql.y:6427 { yyLOCAL = []*tree.IndexHint{yyDollar[1].indexHintUnion()} } yyVAL.union = yyLOCAL - case 973: + case 975: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:6375 +//line mysql_sql.y:6431 { yyLOCAL = append(yyDollar[1].indexHintListUnion(), yyDollar[2].indexHintUnion()) } yyVAL.union = yyLOCAL - case 974: + case 976: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.IndexHint -//line mysql_sql.y:6381 +//line mysql_sql.y:6437 { yyLOCAL = &tree.IndexHint{ IndexNames: yyDollar[4].strsUnion(), @@ -18471,182 +18503,182 @@ yydefault: } } yyVAL.union = yyLOCAL - case 975: + case 977: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:6391 +//line mysql_sql.y:6447 { yyLOCAL = tree.HintUse } yyVAL.union = yyLOCAL - case 976: + case 978: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:6395 +//line mysql_sql.y:6451 { yyLOCAL = tree.HintIgnore } yyVAL.union = yyLOCAL - case 977: + case 979: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:6399 +//line mysql_sql.y:6455 { yyLOCAL = tree.HintForce } yyVAL.union = yyLOCAL - case 978: + case 980: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:6404 +//line mysql_sql.y:6460 { yyLOCAL = tree.HintForScan } yyVAL.union = yyLOCAL - case 979: + case 981: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:6408 +//line mysql_sql.y:6464 { yyLOCAL = tree.HintForJoin } yyVAL.union = yyLOCAL - case 980: + case 982: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:6412 +//line mysql_sql.y:6468 { yyLOCAL = tree.HintForOrderBy } yyVAL.union = yyLOCAL - case 981: + case 983: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:6416 +//line mysql_sql.y:6472 { yyLOCAL = tree.HintForGroupBy } yyVAL.union = yyLOCAL - case 982: + case 984: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6421 +//line mysql_sql.y:6477 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 983: + case 985: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6425 +//line mysql_sql.y:6481 { yyLOCAL = []string{yyDollar[1].cstrUnion().Compare()} } yyVAL.union = yyLOCAL - case 984: + case 986: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6429 +//line mysql_sql.y:6485 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].cstrUnion().Compare()) } yyVAL.union = yyLOCAL - case 985: + case 987: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6433 +//line mysql_sql.y:6489 { yyLOCAL = []string{yyDollar[1].str} } yyVAL.union = yyLOCAL - case 986: + case 988: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6437 +//line mysql_sql.y:6493 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 987: + case 989: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6442 +//line mysql_sql.y:6498 { yyVAL.str = "" } - case 988: + case 990: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6446 +//line mysql_sql.y:6502 { yyVAL.str = yyDollar[1].str } - case 989: + case 991: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6450 +//line mysql_sql.y:6506 { yyVAL.str = yyDollar[2].str } - case 990: + case 992: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6456 +//line mysql_sql.y:6512 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) } - case 991: + case 993: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6460 +//line mysql_sql.y:6516 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].str) } - case 992: + case 994: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:6465 +//line mysql_sql.y:6521 { yyLOCAL = tree.NewCStr("", 1) } yyVAL.union = yyLOCAL - case 993: + case 995: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:6469 +//line mysql_sql.y:6525 { yyLOCAL = yyDollar[1].cstrUnion() } yyVAL.union = yyLOCAL - case 994: + case 996: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:6473 +//line mysql_sql.y:6529 { yyLOCAL = yyDollar[2].cstrUnion() } yyVAL.union = yyLOCAL - case 995: + case 997: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:6477 +//line mysql_sql.y:6533 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 996: + case 998: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:6481 +//line mysql_sql.y:6537 { yyLOCAL = tree.NewCStr(yyDollar[2].str, 1) } yyVAL.union = yyLOCAL - case 997: + case 999: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6487 +//line mysql_sql.y:6543 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1020: + case 1022: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6529 +//line mysql_sql.y:6585 { var Language = yyDollar[3].str var Name = tree.Identifier(yyDollar[5].str) @@ -18658,135 +18690,135 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1021: + case 1023: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6542 +//line mysql_sql.y:6598 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1022: + case 1024: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6548 +//line mysql_sql.y:6604 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1023: + case 1025: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6554 +//line mysql_sql.y:6610 { yyLOCAL = tree.NewCreateProcedure( yyDollar[2].sourceOptionalUnion(), yyDollar[4].procNameUnion(), yyDollar[6].procArgsUnion(), yyDollar[8].str, yyDollar[9].str, ) } yyVAL.union = yyLOCAL - case 1024: + case 1026: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ProcedureName -//line mysql_sql.y:6562 +//line mysql_sql.y:6618 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewProcedureName(tree.Identifier(yyDollar[1].cstrUnion().Compare()), prefix) } yyVAL.union = yyLOCAL - case 1025: + case 1027: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ProcedureName -//line mysql_sql.y:6567 +//line mysql_sql.y:6623 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{SchemaName: tree.Identifier(dbName), ExplicitSchema: true} yyLOCAL = tree.NewProcedureName(tree.Identifier(yyDollar[3].cstrUnion().Compare()), prefix) } yyVAL.union = yyLOCAL - case 1026: + case 1028: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:6574 +//line mysql_sql.y:6630 { yyLOCAL = tree.ProcedureArgs(nil) } yyVAL.union = yyLOCAL - case 1028: + case 1030: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:6581 +//line mysql_sql.y:6637 { yyLOCAL = tree.ProcedureArgs{yyDollar[1].procArgUnion()} } yyVAL.union = yyLOCAL - case 1029: + case 1031: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:6585 +//line mysql_sql.y:6641 { yyLOCAL = append(yyDollar[1].procArgsUnion(), yyDollar[3].procArgUnion()) } yyVAL.union = yyLOCAL - case 1030: + case 1032: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ProcedureArg -//line mysql_sql.y:6591 +//line mysql_sql.y:6647 { yyLOCAL = tree.ProcedureArg(yyDollar[1].procArgDeclUnion()) } yyVAL.union = yyLOCAL - case 1031: + case 1033: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ProcedureArgDecl -//line mysql_sql.y:6597 +//line mysql_sql.y:6653 { yyLOCAL = tree.NewProcedureArgDecl(yyDollar[1].procArgTypeUnion(), yyDollar[2].unresolvedNameUnion(), yyDollar[3].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1032: + case 1034: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:6602 +//line mysql_sql.y:6658 { yyLOCAL = tree.TYPE_IN } yyVAL.union = yyLOCAL - case 1033: + case 1035: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:6606 +//line mysql_sql.y:6662 { yyLOCAL = tree.TYPE_IN } yyVAL.union = yyLOCAL - case 1034: + case 1036: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:6610 +//line mysql_sql.y:6666 { yyLOCAL = tree.TYPE_OUT } yyVAL.union = yyLOCAL - case 1035: + case 1037: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:6614 +//line mysql_sql.y:6670 { yyLOCAL = tree.TYPE_INOUT } yyVAL.union = yyLOCAL - case 1036: + case 1038: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6619 +//line mysql_sql.y:6675 { yyVAL.str = "sql" } - case 1037: + case 1039: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6623 +//line mysql_sql.y:6679 { yyVAL.str = yyDollar[2].str } - case 1038: + case 1040: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6629 +//line mysql_sql.y:6685 { if yyDollar[13].str == "" { yylex.Error("no function body error") @@ -18818,127 +18850,127 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1039: + case 1041: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FunctionName -//line mysql_sql.y:6662 +//line mysql_sql.y:6718 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewFuncName(tree.Identifier(yyDollar[1].cstrUnion().Compare()), prefix) } yyVAL.union = yyLOCAL - case 1040: + case 1042: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FunctionName -//line mysql_sql.y:6667 +//line mysql_sql.y:6723 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{SchemaName: tree.Identifier(dbName), ExplicitSchema: true} yyLOCAL = tree.NewFuncName(tree.Identifier(yyDollar[3].cstrUnion().Compare()), prefix) } yyVAL.union = yyLOCAL - case 1041: + case 1043: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:6674 +//line mysql_sql.y:6730 { yyLOCAL = tree.FunctionArgs(nil) } yyVAL.union = yyLOCAL - case 1043: + case 1045: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:6681 +//line mysql_sql.y:6737 { yyLOCAL = tree.FunctionArgs{yyDollar[1].funcArgUnion()} } yyVAL.union = yyLOCAL - case 1044: + case 1046: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:6685 +//line mysql_sql.y:6741 { yyLOCAL = append(yyDollar[1].funcArgsUnion(), yyDollar[3].funcArgUnion()) } yyVAL.union = yyLOCAL - case 1045: + case 1047: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FunctionArg -//line mysql_sql.y:6691 +//line mysql_sql.y:6747 { yyLOCAL = tree.FunctionArg(yyDollar[1].funcArgDeclUnion()) } yyVAL.union = yyLOCAL - case 1046: + case 1048: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:6697 +//line mysql_sql.y:6753 { yyLOCAL = tree.NewFunctionArgDecl(nil, yyDollar[1].columnTypeUnion(), nil) } yyVAL.union = yyLOCAL - case 1047: + case 1049: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:6701 +//line mysql_sql.y:6757 { yyLOCAL = tree.NewFunctionArgDecl(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), nil) } yyVAL.union = yyLOCAL - case 1048: + case 1050: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:6705 +//line mysql_sql.y:6761 { yyLOCAL = tree.NewFunctionArgDecl(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1049: + case 1051: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6711 +//line mysql_sql.y:6767 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1050: + case 1052: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReturnType -//line mysql_sql.y:6717 +//line mysql_sql.y:6773 { yyLOCAL = tree.NewReturnType(yyDollar[1].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1051: + case 1053: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:6723 +//line mysql_sql.y:6779 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1052: + case 1054: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:6727 +//line mysql_sql.y:6783 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1053: + case 1055: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6732 +//line mysql_sql.y:6788 { yyVAL.str = "" } - case 1055: + case 1057: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6739 +//line mysql_sql.y:6795 { yyVAL.str = yyDollar[2].str } - case 1056: + case 1058: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6745 +//line mysql_sql.y:6801 { var Replace bool var Name = yyDollar[5].tableNameUnion() @@ -18954,10 +18986,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1057: + case 1059: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6760 +//line mysql_sql.y:6816 { var Replace = yyDollar[2].sourceOptionalUnion() var Name = yyDollar[5].tableNameUnion() @@ -18973,10 +19005,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1058: + case 1060: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6777 +//line mysql_sql.y:6833 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = yyDollar[4].exprUnion() @@ -18992,81 +19024,81 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1059: + case 1061: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6794 +//line mysql_sql.y:6850 { yyVAL.str = yyDollar[1].str } - case 1060: + case 1062: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6798 +//line mysql_sql.y:6854 { yyVAL.str = yyVAL.str + yyDollar[2].str } - case 1061: + case 1063: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6804 +//line mysql_sql.y:6860 { yyVAL.str = "ALGORITHM = " + yyDollar[3].str } - case 1062: + case 1064: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6808 +//line mysql_sql.y:6864 { yyVAL.str = "DEFINER = " } - case 1063: + case 1065: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:6812 +//line mysql_sql.y:6868 { yyVAL.str = "SQL SECURITY " + yyDollar[3].str } - case 1064: + case 1066: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6817 +//line mysql_sql.y:6873 { yyVAL.str = "" } - case 1065: + case 1067: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:6821 +//line mysql_sql.y:6877 { yyVAL.str = "WITH " + yyDollar[2].str + " CHECK OPTION" } - case 1071: + case 1073: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6835 +//line mysql_sql.y:6891 { yyVAL.str = "" } - case 1074: + case 1076: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6843 +//line mysql_sql.y:6899 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1075: + case 1077: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6849 +//line mysql_sql.y:6905 { var str = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1076: + case 1078: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6854 +//line mysql_sql.y:6910 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1077: + case 1079: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AccountAuthOption -//line mysql_sql.y:6860 +//line mysql_sql.y:6916 { var Equal = yyDollar[2].str var AdminName = yyDollar[3].exprUnion() @@ -19078,36 +19110,36 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1078: + case 1080: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6873 +//line mysql_sql.y:6929 { var str = yyDollar[1].str yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1079: + case 1081: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6878 +//line mysql_sql.y:6934 { var str = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1080: + case 1082: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6883 +//line mysql_sql.y:6939 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1081: + case 1083: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:6889 +//line mysql_sql.y:6945 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByPassword, @@ -19115,10 +19147,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1082: + case 1084: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:6896 +//line mysql_sql.y:6952 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByPassword, @@ -19126,10 +19158,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1083: + case 1085: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:6903 +//line mysql_sql.y:6959 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByRandomPassword, @@ -19137,10 +19169,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1084: + case 1086: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:6910 +//line mysql_sql.y:6966 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedWithSSL, @@ -19148,10 +19180,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1085: + case 1087: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:6917 +//line mysql_sql.y:6973 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedWithSSL, @@ -19159,20 +19191,20 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1086: + case 1088: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:6925 +//line mysql_sql.y:6981 { as := tree.NewAccountStatus() as.Exist = false yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1087: + case 1089: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:6931 +//line mysql_sql.y:6987 { as := tree.NewAccountStatus() as.Exist = true @@ -19180,10 +19212,10 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1088: + case 1090: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:6938 +//line mysql_sql.y:6994 { as := tree.NewAccountStatus() as.Exist = true @@ -19191,10 +19223,10 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1089: + case 1091: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:6945 +//line mysql_sql.y:7001 { as := tree.NewAccountStatus() as.Exist = true @@ -19202,20 +19234,20 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1090: + case 1092: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountComment -//line mysql_sql.y:6953 +//line mysql_sql.y:7009 { ac := tree.NewAccountComment() ac.Exist = false yyLOCAL = *ac } yyVAL.union = yyLOCAL - case 1091: + case 1093: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountComment -//line mysql_sql.y:6959 +//line mysql_sql.y:7015 { ac := tree.NewAccountComment() ac.Exist = true @@ -19223,10 +19255,10 @@ yydefault: yyLOCAL = *ac } yyVAL.union = yyLOCAL - case 1092: + case 1094: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6968 +//line mysql_sql.y:7024 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Users = yyDollar[4].usersUnion() @@ -19242,10 +19274,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1093: + case 1095: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6985 +//line mysql_sql.y:7041 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19262,10 +19294,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1094: + case 1096: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7001 +//line mysql_sql.y:7057 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19283,30 +19315,30 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1095: + case 1097: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7020 +//line mysql_sql.y:7076 { yyLOCAL = &tree.AccountsSetOption{ All: true, } } yyVAL.union = yyLOCAL - case 1096: + case 1098: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7026 +//line mysql_sql.y:7082 { yyLOCAL = &tree.AccountsSetOption{ SetAccounts: yyDollar[2].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1097: + case 1099: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7034 +//line mysql_sql.y:7090 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19324,20 +19356,20 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1098: + case 1100: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:7052 +//line mysql_sql.y:7108 { yyLOCAL = tree.StageStatus{ Exist: false, } } yyVAL.union = yyLOCAL - case 1099: + case 1101: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:7058 +//line mysql_sql.y:7114 { yyLOCAL = tree.StageStatus{ Exist: true, @@ -19345,10 +19377,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1100: + case 1102: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:7065 +//line mysql_sql.y:7121 { yyLOCAL = tree.StageStatus{ Exist: true, @@ -19356,20 +19388,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1101: + case 1103: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageComment -//line mysql_sql.y:7073 +//line mysql_sql.y:7129 { yyLOCAL = tree.StageComment{ Exist: false, } } yyVAL.union = yyLOCAL - case 1102: + case 1104: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageComment -//line mysql_sql.y:7079 +//line mysql_sql.y:7135 { yyLOCAL = tree.StageComment{ Exist: true, @@ -19377,20 +19409,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1103: + case 1105: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageUrl -//line mysql_sql.y:7087 +//line mysql_sql.y:7143 { yyLOCAL = tree.StageUrl{ Exist: false, } } yyVAL.union = yyLOCAL - case 1104: + case 1106: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageUrl -//line mysql_sql.y:7093 +//line mysql_sql.y:7149 { yyLOCAL = tree.StageUrl{ Exist: true, @@ -19398,20 +19430,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1105: + case 1107: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageCredentials -//line mysql_sql.y:7101 +//line mysql_sql.y:7157 { yyLOCAL = tree.StageCredentials{ Exist: false, } } yyVAL.union = yyLOCAL - case 1106: + case 1108: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.StageCredentials -//line mysql_sql.y:7107 +//line mysql_sql.y:7163 { yyLOCAL = tree.StageCredentials{ Exist: true, @@ -19419,61 +19451,61 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1107: + case 1109: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:7116 +//line mysql_sql.y:7172 { yyLOCAL = yyDollar[1].strsUnion() } yyVAL.union = yyLOCAL - case 1108: + case 1110: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:7120 +//line mysql_sql.y:7176 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } yyVAL.union = yyLOCAL - case 1109: + case 1111: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:7125 +//line mysql_sql.y:7181 { yyLOCAL = []string{} } yyVAL.union = yyLOCAL - case 1110: + case 1112: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:7129 +//line mysql_sql.y:7185 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1111: + case 1113: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:7136 +//line mysql_sql.y:7192 { yyVAL.str = yyDollar[3].str } - case 1112: + case 1114: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:7141 +//line mysql_sql.y:7197 { yyVAL.str = "" } - case 1113: + case 1115: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7145 +//line mysql_sql.y:7201 { yyVAL.str = yyDollar[2].str } - case 1114: + case 1116: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7151 +//line mysql_sql.y:7207 { var ifNotExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19484,10 +19516,10 @@ yydefault: yyLOCAL = tree.NewAlterStage(ifNotExists, name, urlOption, credentialsOption, statusOption, comment) } yyVAL.union = yyLOCAL - case 1115: + case 1117: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7163 +//line mysql_sql.y:7219 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19498,116 +19530,116 @@ yydefault: yyLOCAL = tree.NewAlterPublication(ifExists, name, accountsSet, dbName, table, comment) } yyVAL.union = yyLOCAL - case 1116: + case 1118: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7174 +//line mysql_sql.y:7230 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1117: + case 1119: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7178 +//line mysql_sql.y:7234 { yyLOCAL = &tree.AccountsSetOption{ All: true, } } yyVAL.union = yyLOCAL - case 1118: + case 1120: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7184 +//line mysql_sql.y:7240 { yyLOCAL = &tree.AccountsSetOption{ SetAccounts: yyDollar[2].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1119: + case 1121: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7190 +//line mysql_sql.y:7246 { yyLOCAL = &tree.AccountsSetOption{ AddAccounts: yyDollar[3].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1120: + case 1122: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:7196 +//line mysql_sql.y:7252 { yyLOCAL = &tree.AccountsSetOption{ DropAccounts: yyDollar[3].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1121: + case 1123: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:7203 +//line mysql_sql.y:7259 { yyVAL.str = "" } - case 1122: + case 1124: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7207 +//line mysql_sql.y:7263 { yyVAL.str = yyDollar[2].str } - case 1123: + case 1125: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:7212 +//line mysql_sql.y:7268 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1124: + case 1126: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:7216 +//line mysql_sql.y:7272 { yyLOCAL = yyDollar[2].tableNamesUnion() } yyVAL.union = yyLOCAL - case 1125: + case 1127: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7222 +//line mysql_sql.y:7278 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropPublication(ifExists, name) } yyVAL.union = yyLOCAL - case 1126: + case 1128: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7230 +//line mysql_sql.y:7286 { var ifNotExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropStage(ifNotExists, name) } yyVAL.union = yyLOCAL - case 1127: + case 1129: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7238 +//line mysql_sql.y:7294 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropSnapShot(ifExists, name) } yyVAL.union = yyLOCAL - case 1128: + case 1130: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7246 +//line mysql_sql.y:7302 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -19619,16 +19651,16 @@ yydefault: } yyVAL.union = yyLOCAL - case 1129: + case 1131: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:7259 +//line mysql_sql.y:7315 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1130: + case 1132: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:7264 +//line mysql_sql.y:7320 { var Exist = false var IsComment bool @@ -19641,10 +19673,10 @@ yydefault: } yyVAL.union = yyLOCAL - case 1131: + case 1133: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:7276 +//line mysql_sql.y:7332 { var Exist = true var IsComment = true @@ -19656,10 +19688,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1132: + case 1134: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:7287 +//line mysql_sql.y:7343 { var Exist = true var IsComment = false @@ -19671,26 +19703,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1133: + case 1135: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:7395 +//line mysql_sql.y:7451 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } yyVAL.union = yyLOCAL - case 1134: + case 1136: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:7399 +//line mysql_sql.y:7455 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } yyVAL.union = yyLOCAL - case 1135: + case 1137: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:7405 +//line mysql_sql.y:7461 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -19702,26 +19734,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1136: + case 1138: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:7418 +//line mysql_sql.y:7474 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } yyVAL.union = yyLOCAL - case 1137: + case 1139: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:7422 +//line mysql_sql.y:7478 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } yyVAL.union = yyLOCAL - case 1138: + case 1140: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:7428 +//line mysql_sql.y:7484 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -19733,50 +19765,50 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1139: + case 1141: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:7441 +//line mysql_sql.y:7497 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: "%"} } yyVAL.union = yyLOCAL - case 1140: + case 1142: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:7445 +//line mysql_sql.y:7501 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: yyDollar[3].str} } yyVAL.union = yyLOCAL - case 1141: + case 1143: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:7449 +//line mysql_sql.y:7505 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: yyDollar[2].str} } yyVAL.union = yyLOCAL - case 1142: + case 1144: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:7454 +//line mysql_sql.y:7510 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1143: + case 1145: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:7458 +//line mysql_sql.y:7514 { yyLOCAL = yyDollar[1].userIdentifiedUnion() } yyVAL.union = yyLOCAL - case 1144: + case 1146: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:7464 +//line mysql_sql.y:7520 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedByPassword, @@ -19784,20 +19816,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1145: + case 1147: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:7471 +//line mysql_sql.y:7527 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedByRandomPassword, } } yyVAL.union = yyLOCAL - case 1146: + case 1148: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:7477 +//line mysql_sql.y:7533 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedWithSSL, @@ -19805,16 +19837,16 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1147: + case 1149: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:7486 +//line mysql_sql.y:7542 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1149: + case 1151: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7493 +//line mysql_sql.y:7549 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Roles = yyDollar[4].rolesUnion() @@ -19824,26 +19856,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1150: + case 1152: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:7504 +//line mysql_sql.y:7560 { yyLOCAL = []*tree.Role{yyDollar[1].roleUnion()} } yyVAL.union = yyLOCAL - case 1151: + case 1153: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:7508 +//line mysql_sql.y:7564 { yyLOCAL = append(yyDollar[1].rolesUnion(), yyDollar[3].roleUnion()) } yyVAL.union = yyLOCAL - case 1152: + case 1154: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:7514 +//line mysql_sql.y:7570 { var UserName = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewRole( @@ -19851,66 +19883,66 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1153: + case 1155: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:7523 +//line mysql_sql.y:7579 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1154: + case 1156: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:7527 +//line mysql_sql.y:7583 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1155: + case 1157: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:7531 +//line mysql_sql.y:7587 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1156: + case 1158: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:7536 +//line mysql_sql.y:7592 { yyLOCAL = tree.INDEX_CATEGORY_NONE } yyVAL.union = yyLOCAL - case 1157: + case 1159: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:7540 +//line mysql_sql.y:7596 { yyLOCAL = tree.INDEX_CATEGORY_FULLTEXT } yyVAL.union = yyLOCAL - case 1158: + case 1160: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:7544 +//line mysql_sql.y:7600 { yyLOCAL = tree.INDEX_CATEGORY_SPATIAL } yyVAL.union = yyLOCAL - case 1159: + case 1161: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:7548 +//line mysql_sql.y:7604 { yyLOCAL = tree.INDEX_CATEGORY_UNIQUE } yyVAL.union = yyLOCAL - case 1160: + case 1162: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7554 +//line mysql_sql.y:7610 { var io *tree.IndexOption = nil if yyDollar[11].indexOptionUnion() == nil && yyDollar[5].indexTypeUnion() != tree.INDEX_TYPE_INVALID { @@ -19941,18 +19973,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1161: + case 1163: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7585 +//line mysql_sql.y:7641 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1162: + case 1164: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7589 +//line mysql_sql.y:7645 { // Merge the options if yyDollar[1].indexOptionUnion() == nil { @@ -19985,20 +20017,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1163: + case 1165: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7623 +//line mysql_sql.y:7679 { io := tree.NewIndexOption() io.KeyBlockSize = uint64(yyDollar[3].item.(int64)) yyLOCAL = io } yyVAL.union = yyLOCAL - case 1164: + case 1166: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7629 +//line mysql_sql.y:7685 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -20011,60 +20043,60 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1165: + case 1167: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7641 +//line mysql_sql.y:7697 { io := tree.NewIndexOption() io.AlgoParamVectorOpType = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1166: + case 1168: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7647 +//line mysql_sql.y:7703 { io := tree.NewIndexOption() io.Comment = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1167: + case 1169: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7653 +//line mysql_sql.y:7709 { io := tree.NewIndexOption() io.ParserName = yyDollar[3].cstrUnion().Compare() yyLOCAL = io } yyVAL.union = yyLOCAL - case 1168: + case 1170: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7659 +//line mysql_sql.y:7715 { io := tree.NewIndexOption() io.Visible = tree.VISIBLE_TYPE_VISIBLE yyLOCAL = io } yyVAL.union = yyLOCAL - case 1169: + case 1171: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7665 +//line mysql_sql.y:7721 { io := tree.NewIndexOption() io.Visible = tree.VISIBLE_TYPE_INVISIBLE yyLOCAL = io } yyVAL.union = yyLOCAL - case 1170: + case 1172: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7671 +//line mysql_sql.y:7727 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -20076,10 +20108,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1171: + case 1173: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7682 +//line mysql_sql.y:7738 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -20091,10 +20123,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1172: + case 1174: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7693 +//line mysql_sql.y:7749 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -20106,36 +20138,36 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1173: + case 1175: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:7704 +//line mysql_sql.y:7760 { io := tree.NewIndexOption() io.Async = true yyLOCAL = io } yyVAL.union = yyLOCAL - case 1174: + case 1176: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:7713 +//line mysql_sql.y:7769 { yyLOCAL = []*tree.KeyPart{yyDollar[1].keyPartUnion()} } yyVAL.union = yyLOCAL - case 1175: + case 1177: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:7717 +//line mysql_sql.y:7773 { yyLOCAL = append(yyDollar[1].keyPartsUnion(), yyDollar[3].keyPartUnion()) } yyVAL.union = yyLOCAL - case 1176: + case 1178: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.KeyPart -//line mysql_sql.y:7723 +//line mysql_sql.y:7779 { // Order is parsed but just ignored as MySQL dtree. var ColName = yyDollar[1].unresolvedNameUnion() @@ -20150,10 +20182,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1177: + case 1179: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.KeyPart -//line mysql_sql.y:7737 +//line mysql_sql.y:7793 { var ColName *tree.UnresolvedName var Length int @@ -20167,74 +20199,74 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1178: + case 1180: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7751 +//line mysql_sql.y:7807 { yyLOCAL = tree.INDEX_TYPE_INVALID } yyVAL.union = yyLOCAL - case 1179: + case 1181: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7755 +//line mysql_sql.y:7811 { yyLOCAL = tree.INDEX_TYPE_BTREE } yyVAL.union = yyLOCAL - case 1180: + case 1182: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7759 +//line mysql_sql.y:7815 { yyLOCAL = tree.INDEX_TYPE_IVFFLAT } yyVAL.union = yyLOCAL - case 1181: + case 1183: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7763 +//line mysql_sql.y:7819 { yyLOCAL = tree.INDEX_TYPE_HNSW } yyVAL.union = yyLOCAL - case 1182: + case 1184: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7767 +//line mysql_sql.y:7823 { yyLOCAL = tree.INDEX_TYPE_MASTER } yyVAL.union = yyLOCAL - case 1183: + case 1185: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7771 +//line mysql_sql.y:7827 { yyLOCAL = tree.INDEX_TYPE_HASH } yyVAL.union = yyLOCAL - case 1184: + case 1186: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7775 +//line mysql_sql.y:7831 { yyLOCAL = tree.INDEX_TYPE_RTREE } yyVAL.union = yyLOCAL - case 1185: + case 1187: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:7779 +//line mysql_sql.y:7835 { yyLOCAL = tree.INDEX_TYPE_BSI } yyVAL.union = yyLOCAL - case 1186: + case 1188: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7785 +//line mysql_sql.y:7841 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].str) @@ -20248,10 +20280,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1187: + case 1189: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7799 +//line mysql_sql.y:7855 { var t = tree.NewCloneDatabase() t.DstDatabase = tree.Identifier(yyDollar[4].str) @@ -20261,92 +20293,92 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1188: + case 1190: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SubscriptionOption -//line mysql_sql.y:7809 +//line mysql_sql.y:7865 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1189: + case 1191: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.SubscriptionOption -//line mysql_sql.y:7813 +//line mysql_sql.y:7869 { var From = tree.Identifier(yyDollar[2].str) var Publication = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewSubscriptionOption(From, Publication) } yyVAL.union = yyLOCAL - case 1192: + case 1194: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7824 +//line mysql_sql.y:7880 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1193: + case 1195: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7828 +//line mysql_sql.y:7884 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1194: + case 1196: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7833 +//line mysql_sql.y:7889 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1195: + case 1197: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7837 +//line mysql_sql.y:7893 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1196: + case 1198: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:7842 +//line mysql_sql.y:7898 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1197: + case 1199: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:7846 +//line mysql_sql.y:7902 { yyLOCAL = yyDollar[1].createOptionsUnion() } yyVAL.union = yyLOCAL - case 1198: + case 1200: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:7852 +//line mysql_sql.y:7908 { yyLOCAL = []tree.CreateOption{yyDollar[1].createOptionUnion()} } yyVAL.union = yyLOCAL - case 1199: + case 1201: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:7856 +//line mysql_sql.y:7912 { yyLOCAL = append(yyDollar[1].createOptionsUnion(), yyDollar[2].createOptionUnion()) } yyVAL.union = yyLOCAL - case 1200: + case 1202: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:7862 +//line mysql_sql.y:7918 { var IsDefault = yyDollar[1].defaultOptionalUnion() var Charset = yyDollar[4].str @@ -20356,10 +20388,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1201: + case 1203: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:7871 +//line mysql_sql.y:7927 { var IsDefault = yyDollar[1].defaultOptionalUnion() var Collate = yyDollar[4].str @@ -20369,35 +20401,35 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1202: + case 1204: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:7880 +//line mysql_sql.y:7936 { var Encrypt = yyDollar[4].str yyLOCAL = tree.NewCreateOptionEncryption(Encrypt) } yyVAL.union = yyLOCAL - case 1203: + case 1205: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7886 +//line mysql_sql.y:7942 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1204: + case 1206: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7890 +//line mysql_sql.y:7946 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1205: + case 1207: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7896 +//line mysql_sql.y:7952 { var TableName = yyDollar[4].tableNameUnion() var Options = yyDollar[7].connectorOptionsUnion() @@ -20407,18 +20439,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1206: + case 1208: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7907 +//line mysql_sql.y:7963 { yyLOCAL = &tree.ShowConnectors{} } yyVAL.union = yyLOCAL - case 1207: + case 1209: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7913 +//line mysql_sql.y:7969 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -20435,10 +20467,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1208: + case 1210: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7931 +//line mysql_sql.y:7987 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -20455,10 +20487,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1209: + case 1211: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7949 +//line mysql_sql.y:8005 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -20475,10 +20507,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1210: + case 1212: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7967 +//line mysql_sql.y:8023 { var Replace = yyDollar[2].sourceOptionalUnion() var IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -20494,26 +20526,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1211: + case 1213: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7983 +//line mysql_sql.y:8039 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1212: + case 1214: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7987 +//line mysql_sql.y:8043 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1213: + case 1215: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:7993 +//line mysql_sql.y:8049 { t := tree.NewDataBranchCreateTable() t.CreateTable.Table = *yyDollar[5].tableNameUnion() @@ -20524,10 +20556,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1214: + case 1216: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8003 +//line mysql_sql.y:8059 { t := tree.NewDataBranchCreateDatabase() t.DstDatabase = tree.Identifier(yyDollar[4].str) @@ -20537,30 +20569,30 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1215: + case 1217: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8012 +//line mysql_sql.y:8068 { t := tree.NewDataBranchDeleteTable() t.TableName = *yyDollar[5].tableNameUnion() yyLOCAL = t } yyVAL.union = yyLOCAL - case 1216: + case 1218: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8018 +//line mysql_sql.y:8074 { t := tree.NewDataBranchDeleteDatabase() t.DatabaseName = tree.Identifier(yyDollar[5].str) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1217: + case 1219: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8024 +//line mysql_sql.y:8080 { t := tree.NewDataBranchDiff() t.TargetTable = *yyDollar[4].tableNameUnion() @@ -20569,10 +20601,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1218: + case 1220: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8032 +//line mysql_sql.y:8088 { t := tree.NewDataBranchMerge() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -20581,38 +20613,38 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1219: + case 1221: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:8041 +//line mysql_sql.y:8097 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1220: + case 1222: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:8045 +//line mysql_sql.y:8101 { yyLOCAL = &tree.DiffOutputOpt{ As: *yyDollar[3].tableNameUnion(), } } yyVAL.union = yyLOCAL - case 1221: + case 1223: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:8051 +//line mysql_sql.y:8107 { yyLOCAL = &tree.DiffOutputOpt{ DirPath: yyDollar[3].str, } } yyVAL.union = yyLOCAL - case 1222: + case 1224: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:8057 +//line mysql_sql.y:8113 { x := yyDollar[3].item.(int64) yyLOCAL = &tree.DiffOutputOpt{ @@ -20620,76 +20652,76 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1223: + case 1225: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:8064 +//line mysql_sql.y:8120 { yyLOCAL = &tree.DiffOutputOpt{ Count: true, } } yyVAL.union = yyLOCAL - case 1224: + case 1226: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8071 +//line mysql_sql.y:8127 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1225: + case 1227: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8075 +//line mysql_sql.y:8131 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_FAIL, } } yyVAL.union = yyLOCAL - case 1226: + case 1228: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8081 +//line mysql_sql.y:8137 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_SKIP, } } yyVAL.union = yyLOCAL - case 1227: + case 1229: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8087 +//line mysql_sql.y:8143 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_ACCEPT, } } yyVAL.union = yyLOCAL - case 1228: + case 1230: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:8095 +//line mysql_sql.y:8151 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1229: + case 1231: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:8099 +//line mysql_sql.y:8155 { yyLOCAL = &tree.ToAccountOpt{ AccountName: tree.Identifier(yyDollar[3].cstrUnion().Compare()), } } yyVAL.union = yyLOCAL - case 1230: + case 1232: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8107 +//line mysql_sql.y:8163 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -20702,10 +20734,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1231: + case 1233: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8119 +//line mysql_sql.y:8175 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -20715,10 +20747,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1232: + case 1234: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8128 +//line mysql_sql.y:8184 { t := tree.NewCreateTable() t.IsClusterTable = true @@ -20731,10 +20763,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1233: + case 1235: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8140 +//line mysql_sql.y:8196 { t := tree.NewCreateTable() t.IsDynamicTable = true @@ -20745,10 +20777,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1234: + case 1236: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8150 +//line mysql_sql.y:8206 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -20759,10 +20791,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1235: + case 1237: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8160 +//line mysql_sql.y:8216 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -20774,10 +20806,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1236: + case 1238: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8171 +//line mysql_sql.y:8227 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -20788,10 +20820,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1237: + case 1239: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8181 +//line mysql_sql.y:8237 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -20803,10 +20835,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1238: + case 1240: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8192 +//line mysql_sql.y:8248 { t := tree.NewCreateTable() t.IsAsLike = true @@ -20815,10 +20847,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1239: + case 1241: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8200 +//line mysql_sql.y:8256 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -20828,10 +20860,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1240: + case 1242: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8209 +//line mysql_sql.y:8265 { t := tree.NewCloneTable() t.CreateTable.Table = *yyDollar[5].tableNameUnion() @@ -20842,19 +20874,19 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1241: + case 1243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8221 +//line mysql_sql.y:8277 { yyLOCAL = yyDollar[1].loadParamUnion() yyLOCAL.Tail = yyDollar[2].tailParamUnion() } yyVAL.union = yyLOCAL - case 1242: + case 1244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8228 +//line mysql_sql.y:8284 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -20865,10 +20897,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1243: + case 1245: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8238 +//line mysql_sql.y:8294 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -20882,10 +20914,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1244: + case 1246: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8251 +//line mysql_sql.y:8307 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -20894,10 +20926,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1245: + case 1247: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8259 +//line mysql_sql.y:8315 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -20907,10 +20939,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1246: + case 1248: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8268 +//line mysql_sql.y:8324 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -20919,55 +20951,55 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1247: + case 1249: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8277 +//line mysql_sql.y:8333 { yyVAL.str = "" } - case 1248: + case 1250: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:8281 +//line mysql_sql.y:8337 { yyVAL.str = yyDollar[4].str } - case 1249: + case 1251: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8287 +//line mysql_sql.y:8343 { yyLOCAL = yyDollar[1].strsUnion() } yyVAL.union = yyLOCAL - case 1250: + case 1252: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8291 +//line mysql_sql.y:8347 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } yyVAL.union = yyLOCAL - case 1251: + case 1253: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8296 +//line mysql_sql.y:8352 { yyLOCAL = []string{} } yyVAL.union = yyLOCAL - case 1252: + case 1254: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8300 +//line mysql_sql.y:8356 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1253: + case 1255: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.TailParameter -//line mysql_sql.y:8307 +//line mysql_sql.y:8363 { yyLOCAL = &tree.TailParameter{ Charset: yyDollar[1].str, @@ -20979,22 +21011,22 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1254: + case 1256: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8319 +//line mysql_sql.y:8375 { yyVAL.str = "" } - case 1255: + case 1257: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8323 +//line mysql_sql.y:8379 { yyVAL.str = yyDollar[2].str } - case 1256: + case 1258: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8329 +//line mysql_sql.y:8385 { var Name = yyDollar[4].tableNameUnion() var Type = yyDollar[5].columnTypeUnion() @@ -21016,10 +21048,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1257: + case 1259: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:8350 +//line mysql_sql.y:8406 { locale := "" fstr := "bigint" @@ -21034,44 +21066,44 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1258: + case 1260: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:8364 +//line mysql_sql.y:8420 { yyLOCAL = yyDollar[2].columnTypeUnion() } yyVAL.union = yyLOCAL - case 1259: + case 1261: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:8368 +//line mysql_sql.y:8424 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1260: + case 1262: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:8372 +//line mysql_sql.y:8428 { yyLOCAL = &tree.TypeOption{ Type: yyDollar[2].columnTypeUnion(), } } yyVAL.union = yyLOCAL - case 1261: + case 1263: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8378 +//line mysql_sql.y:8434 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1262: + case 1264: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8382 +//line mysql_sql.y:8438 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -21079,10 +21111,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1263: + case 1265: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8389 +//line mysql_sql.y:8445 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -21090,10 +21122,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1264: + case 1266: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8396 +//line mysql_sql.y:8452 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -21101,10 +21133,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1265: + case 1267: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8403 +//line mysql_sql.y:8459 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -21112,42 +21144,42 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1266: + case 1268: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8410 +//line mysql_sql.y:8466 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1267: + case 1269: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8414 +//line mysql_sql.y:8470 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1268: + case 1270: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8418 +//line mysql_sql.y:8474 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1269: + case 1271: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8422 +//line mysql_sql.y:8478 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1270: + case 1272: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8426 +//line mysql_sql.y:8482 { yyLOCAL = &tree.MinValueOption{ Minus: false, @@ -21155,10 +21187,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1271: + case 1273: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8433 +//line mysql_sql.y:8489 { yyLOCAL = &tree.MinValueOption{ Minus: true, @@ -21166,18 +21198,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1272: + case 1274: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8440 +//line mysql_sql.y:8496 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1273: + case 1275: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8444 +//line mysql_sql.y:8500 { yyLOCAL = &tree.MaxValueOption{ Minus: false, @@ -21185,10 +21217,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1274: + case 1276: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8451 +//line mysql_sql.y:8507 { yyLOCAL = &tree.MaxValueOption{ Minus: true, @@ -21196,46 +21228,46 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1275: + case 1277: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8458 +//line mysql_sql.y:8514 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1276: + case 1278: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8462 +//line mysql_sql.y:8518 { yyLOCAL = &tree.CycleOption{ Cycle: false, } } yyVAL.union = yyLOCAL - case 1277: + case 1279: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8468 +//line mysql_sql.y:8524 { yyLOCAL = &tree.CycleOption{ Cycle: true, } } yyVAL.union = yyLOCAL - case 1278: + case 1280: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8474 +//line mysql_sql.y:8530 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1279: + case 1281: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8478 +//line mysql_sql.y:8534 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -21243,10 +21275,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1280: + case 1282: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8485 +//line mysql_sql.y:8541 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -21254,10 +21286,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1281: + case 1283: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8492 +//line mysql_sql.y:8548 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -21265,10 +21297,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1282: + case 1284: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8499 +//line mysql_sql.y:8555 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -21276,58 +21308,58 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1283: + case 1285: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8506 +//line mysql_sql.y:8562 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1284: + case 1286: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8510 +//line mysql_sql.y:8566 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1285: + case 1287: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8515 +//line mysql_sql.y:8571 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1286: + case 1288: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8519 +//line mysql_sql.y:8575 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1287: + case 1289: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8523 +//line mysql_sql.y:8579 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1288: + case 1290: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:8528 +//line mysql_sql.y:8584 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1289: + case 1291: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:8532 +//line mysql_sql.y:8588 { yyDollar[3].partitionByUnion().Num = uint64(yyDollar[4].int64ValUnion()) var PartBy = yyDollar[3].partitionByUnion() @@ -21340,18 +21372,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1290: + case 1292: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8545 +//line mysql_sql.y:8601 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1291: + case 1293: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8549 +//line mysql_sql.y:8605 { var ColumnList = []*tree.UnresolvedName{yyDollar[3].unresolvedNameUnion()} yyLOCAL = tree.NewClusterByOption( @@ -21360,10 +21392,10 @@ yydefault: } yyVAL.union = yyLOCAL - case 1292: + case 1294: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8557 +//line mysql_sql.y:8613 { var ColumnList = yyDollar[4].unresolveNamesUnion() yyLOCAL = tree.NewClusterByOption( @@ -21371,18 +21403,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1293: + case 1295: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8565 +//line mysql_sql.y:8621 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1294: + case 1296: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8569 +//line mysql_sql.y:8625 { var IsSubPartition = true var PType = yyDollar[3].partitionByUnion() @@ -21394,42 +21426,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1295: + case 1297: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8581 +//line mysql_sql.y:8637 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1296: + case 1298: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8585 +//line mysql_sql.y:8641 { yyLOCAL = yyDollar[2].partitionsUnion() } yyVAL.union = yyLOCAL - case 1297: + case 1299: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8591 +//line mysql_sql.y:8647 { yyLOCAL = []*tree.Partition{yyDollar[1].partitionUnion()} } yyVAL.union = yyLOCAL - case 1298: + case 1300: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8595 +//line mysql_sql.y:8651 { yyLOCAL = append(yyDollar[1].partitionsUnion(), yyDollar[3].partitionUnion()) } yyVAL.union = yyLOCAL - case 1299: + case 1301: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:8601 +//line mysql_sql.y:8657 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -21443,10 +21475,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1300: + case 1302: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:8614 +//line mysql_sql.y:8670 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -21460,42 +21492,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1301: + case 1303: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8628 +//line mysql_sql.y:8684 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1302: + case 1304: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8632 +//line mysql_sql.y:8688 { yyLOCAL = yyDollar[2].subPartitionsUnion() } yyVAL.union = yyLOCAL - case 1303: + case 1305: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8638 +//line mysql_sql.y:8694 { yyLOCAL = []*tree.SubPartition{yyDollar[1].subPartitionUnion()} } yyVAL.union = yyLOCAL - case 1304: + case 1306: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8642 +//line mysql_sql.y:8698 { yyLOCAL = append(yyDollar[1].subPartitionsUnion(), yyDollar[3].subPartitionUnion()) } yyVAL.union = yyLOCAL - case 1305: + case 1307: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:8648 +//line mysql_sql.y:8704 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options []tree.TableOption @@ -21505,10 +21537,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1306: + case 1308: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:8657 +//line mysql_sql.y:8713 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options = yyDollar[3].tableOptionsUnion() @@ -21518,53 +21550,53 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1307: + case 1309: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8668 +//line mysql_sql.y:8724 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1308: + case 1310: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8672 +//line mysql_sql.y:8728 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1309: + case 1311: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8677 +//line mysql_sql.y:8733 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1310: + case 1312: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8681 +//line mysql_sql.y:8737 { expr := tree.NewMaxValue() var valueList = tree.Exprs{expr} yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1311: + case 1313: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8687 +//line mysql_sql.y:8743 { var valueList = yyDollar[5].exprsUnion() yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1312: + case 1314: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8692 +//line mysql_sql.y:8748 { var valueList = yyDollar[4].exprsUnion() yyLOCAL = tree.NewValuesIn( @@ -21572,18 +21604,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1313: + case 1315: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8700 +//line mysql_sql.y:8756 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1314: + case 1316: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8704 +//line mysql_sql.y:8760 { res := yyDollar[2].item.(int64) if res == 0 { @@ -21593,18 +21625,18 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1315: + case 1317: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8714 +//line mysql_sql.y:8770 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1316: + case 1318: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8718 +//line mysql_sql.y:8774 { res := yyDollar[2].item.(int64) if res == 0 { @@ -21614,10 +21646,10 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1317: + case 1319: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8729 +//line mysql_sql.y:8785 { rangeTyp := tree.NewRangeType() rangeTyp.Expr = yyDollar[3].exprUnion() @@ -21626,10 +21658,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1318: + case 1320: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8737 +//line mysql_sql.y:8793 { rangeTyp := tree.NewRangeType() rangeTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -21638,10 +21670,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1319: + case 1321: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8745 +//line mysql_sql.y:8801 { listTyp := tree.NewListType() listTyp.Expr = yyDollar[3].exprUnion() @@ -21650,10 +21682,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1320: + case 1322: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8753 +//line mysql_sql.y:8809 { listTyp := tree.NewListType() listTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -21662,10 +21694,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1322: + case 1324: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8764 +//line mysql_sql.y:8820 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -21675,10 +21707,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1323: + case 1325: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8773 +//line mysql_sql.y:8829 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -21689,10 +21721,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1324: + case 1326: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8783 +//line mysql_sql.y:8839 { Linear := yyDollar[1].boolValUnion() Expr := yyDollar[4].exprUnion() @@ -21702,58 +21734,58 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1325: + case 1327: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8793 +//line mysql_sql.y:8849 { yyLOCAL = 2 } yyVAL.union = yyLOCAL - case 1326: + case 1328: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8797 +//line mysql_sql.y:8853 { yyLOCAL = yyDollar[3].item.(int64) } yyVAL.union = yyLOCAL - case 1327: + case 1329: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8802 +//line mysql_sql.y:8858 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1328: + case 1330: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8806 +//line mysql_sql.y:8862 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1329: + case 1331: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ConnectorOption -//line mysql_sql.y:8812 +//line mysql_sql.y:8868 { yyLOCAL = []*tree.ConnectorOption{yyDollar[1].connectorOptionUnion()} } yyVAL.union = yyLOCAL - case 1330: + case 1332: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.ConnectorOption -//line mysql_sql.y:8816 +//line mysql_sql.y:8872 { yyLOCAL = append(yyDollar[1].connectorOptionsUnion(), yyDollar[3].connectorOptionUnion()) } yyVAL.union = yyLOCAL - case 1331: + case 1333: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConnectorOption -//line mysql_sql.y:8822 +//line mysql_sql.y:8878 { var Key = tree.Identifier(yyDollar[1].cstrUnion().Compare()) var Val = yyDollar[3].exprUnion() @@ -21763,10 +21795,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1332: + case 1334: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConnectorOption -//line mysql_sql.y:8831 +//line mysql_sql.y:8887 { var Key = tree.Identifier(yyDollar[1].str) var Val = yyDollar[3].exprUnion() @@ -21776,42 +21808,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1333: + case 1335: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8841 +//line mysql_sql.y:8897 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1334: + case 1336: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8845 +//line mysql_sql.y:8901 { yyLOCAL = yyDollar[3].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 1335: + case 1337: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8851 +//line mysql_sql.y:8907 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1336: + case 1338: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8855 +//line mysql_sql.y:8911 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[3].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1337: + case 1339: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8861 +//line mysql_sql.y:8917 { var Key = tree.Identifier(yyDollar[1].cstrUnion().Compare()) var Val = yyDollar[3].exprUnion() @@ -21821,10 +21853,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1338: + case 1340: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8870 +//line mysql_sql.y:8926 { var Key = tree.Identifier(yyDollar[1].str) var Val = yyDollar[3].exprUnion() @@ -21834,364 +21866,364 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1339: + case 1341: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8880 +//line mysql_sql.y:8936 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1340: + case 1342: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8884 +//line mysql_sql.y:8940 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 1341: + case 1343: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8890 +//line mysql_sql.y:8946 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1342: + case 1344: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8894 +//line mysql_sql.y:8950 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[3].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1343: + case 1345: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8898 +//line mysql_sql.y:8954 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1344: + case 1346: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8904 +//line mysql_sql.y:8960 { yyLOCAL = tree.NewTableOptionAUTOEXTEND_SIZE(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1345: + case 1347: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8908 +//line mysql_sql.y:8964 { yyLOCAL = tree.NewTableOptionAutoIncrement(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1346: + case 1348: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8912 +//line mysql_sql.y:8968 { yyLOCAL = tree.NewTableOptionAvgRowLength(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1347: + case 1349: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8916 +//line mysql_sql.y:8972 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1348: + case 1350: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8920 +//line mysql_sql.y:8976 { yyLOCAL = tree.NewTableOptionCollate(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1349: + case 1351: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8924 +//line mysql_sql.y:8980 { yyLOCAL = tree.NewTableOptionChecksum(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1350: + case 1352: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8928 +//line mysql_sql.y:8984 { str := util.DealCommentString(yyDollar[3].str) yyLOCAL = tree.NewTableOptionComment(str) } yyVAL.union = yyLOCAL - case 1351: + case 1353: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8933 +//line mysql_sql.y:8989 { yyLOCAL = tree.NewTableOptionCompression(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1352: + case 1354: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8937 +//line mysql_sql.y:8993 { yyLOCAL = tree.NewTableOptionConnection(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1353: + case 1355: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8941 +//line mysql_sql.y:8997 { yyLOCAL = tree.NewTableOptionDataDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1354: + case 1356: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8945 +//line mysql_sql.y:9001 { yyLOCAL = tree.NewTableOptionIndexDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1355: + case 1357: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8949 +//line mysql_sql.y:9005 { yyLOCAL = tree.NewTableOptionDelayKeyWrite(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1356: + case 1358: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8953 +//line mysql_sql.y:9009 { yyLOCAL = tree.NewTableOptionEncryption(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1357: + case 1359: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8957 +//line mysql_sql.y:9013 { yyLOCAL = tree.NewTableOptionEngine(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1358: + case 1360: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8961 +//line mysql_sql.y:9017 { yyLOCAL = tree.NewTableOptionEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1359: + case 1361: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8965 +//line mysql_sql.y:9021 { yyLOCAL = tree.NewTableOptionInsertMethod(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1360: + case 1362: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8969 +//line mysql_sql.y:9025 { yyLOCAL = tree.NewTableOptionKeyBlockSize(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1361: + case 1363: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8973 +//line mysql_sql.y:9029 { yyLOCAL = tree.NewTableOptionMaxRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1362: + case 1364: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8977 +//line mysql_sql.y:9033 { yyLOCAL = tree.NewTableOptionMinRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1363: + case 1365: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8981 +//line mysql_sql.y:9037 { t := tree.NewTableOptionPackKeys() t.Value = yyDollar[3].item.(int64) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1364: + case 1366: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8987 +//line mysql_sql.y:9043 { t := tree.NewTableOptionPackKeys() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1365: + case 1367: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8993 +//line mysql_sql.y:9049 { yyLOCAL = tree.NewTableOptionPassword(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1366: + case 1368: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:8997 +//line mysql_sql.y:9053 { yyLOCAL = tree.NewTableOptionRowFormat(yyDollar[3].rowFormatTypeUnion()) } yyVAL.union = yyLOCAL - case 1367: + case 1369: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9001 +//line mysql_sql.y:9057 { yyLOCAL = tree.NewTTableOptionStartTrans(true) } yyVAL.union = yyLOCAL - case 1368: + case 1370: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9005 +//line mysql_sql.y:9061 { yyLOCAL = tree.NewTTableOptionSecondaryEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1369: + case 1371: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9009 +//line mysql_sql.y:9065 { t := tree.NewTableOptionStatsAutoRecalc() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1370: + case 1372: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9015 +//line mysql_sql.y:9071 { t := tree.NewTableOptionStatsAutoRecalc() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1371: + case 1373: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9021 +//line mysql_sql.y:9077 { t := tree.NewTableOptionStatsPersistent() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1372: + case 1374: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9027 +//line mysql_sql.y:9083 { t := tree.NewTableOptionStatsPersistent() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1373: + case 1375: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9033 +//line mysql_sql.y:9089 { t := tree.NewTableOptionStatsSamplePages() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1374: + case 1376: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9039 +//line mysql_sql.y:9095 { t := tree.NewTableOptionStatsSamplePages() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1375: + case 1377: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9045 +//line mysql_sql.y:9101 { yyLOCAL = tree.NewTableOptionTablespace(yyDollar[3].cstrUnion().Compare(), "") } yyVAL.union = yyLOCAL - case 1376: + case 1378: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9049 +//line mysql_sql.y:9105 { yyLOCAL = tree.NewTableOptionTablespace("", yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1377: + case 1379: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9053 +//line mysql_sql.y:9109 { yyLOCAL = tree.NewTableOptionUnion(yyDollar[4].tableNamesUnion()) } yyVAL.union = yyLOCAL - case 1378: + case 1380: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9057 +//line mysql_sql.y:9113 { var Preperties = yyDollar[3].propertiesUnion() yyLOCAL = tree.NewTableOptionProperties(Preperties) } yyVAL.union = yyLOCAL - case 1379: + case 1381: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:9064 +//line mysql_sql.y:9120 { yyLOCAL = []tree.Property{yyDollar[1].propertyUnion()} } yyVAL.union = yyLOCAL - case 1380: + case 1382: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:9068 +//line mysql_sql.y:9124 { yyLOCAL = append(yyDollar[1].propertiesUnion(), yyDollar[3].propertyUnion()) } yyVAL.union = yyLOCAL - case 1381: + case 1383: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Property -//line mysql_sql.y:9074 +//line mysql_sql.y:9130 { var Key = yyDollar[1].str var Value = yyDollar[3].str @@ -22201,96 +22233,96 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1382: + case 1384: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9085 +//line mysql_sql.y:9141 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1383: + case 1385: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9089 +//line mysql_sql.y:9145 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1384: + case 1386: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9095 +//line mysql_sql.y:9151 { yyLOCAL = tree.ROW_FORMAT_DEFAULT } yyVAL.union = yyLOCAL - case 1385: + case 1387: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9099 +//line mysql_sql.y:9155 { yyLOCAL = tree.ROW_FORMAT_DYNAMIC } yyVAL.union = yyLOCAL - case 1386: + case 1388: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9103 +//line mysql_sql.y:9159 { yyLOCAL = tree.ROW_FORMAT_FIXED } yyVAL.union = yyLOCAL - case 1387: + case 1389: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9107 +//line mysql_sql.y:9163 { yyLOCAL = tree.ROW_FORMAT_COMPRESSED } yyVAL.union = yyLOCAL - case 1388: + case 1390: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9111 +//line mysql_sql.y:9167 { yyLOCAL = tree.ROW_FORMAT_REDUNDANT } yyVAL.union = yyLOCAL - case 1389: + case 1391: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9115 +//line mysql_sql.y:9171 { yyLOCAL = tree.ROW_FORMAT_COMPACT } yyVAL.union = yyLOCAL - case 1394: + case 1396: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9129 +//line mysql_sql.y:9185 { yyLOCAL = tree.TableNames{yyDollar[1].tableNameUnion()} } yyVAL.union = yyLOCAL - case 1395: + case 1397: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9133 +//line mysql_sql.y:9189 { yyLOCAL = append(yyDollar[1].tableNamesUnion(), yyDollar[3].tableNameUnion()) } yyVAL.union = yyLOCAL - case 1396: + case 1398: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:9142 +//line mysql_sql.y:9198 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewTableName(tree.Identifier(tblName), prefix, yyDollar[2].atTimeStampUnion()) } yyVAL.union = yyLOCAL - case 1397: + case 1399: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:9148 +//line mysql_sql.y:9204 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -22298,18 +22330,18 @@ yydefault: yyLOCAL = tree.NewTableName(tree.Identifier(tblName), prefix, yyDollar[4].atTimeStampUnion()) } yyVAL.union = yyLOCAL - case 1398: + case 1400: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9156 +//line mysql_sql.y:9212 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1399: + case 1401: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9160 +//line mysql_sql.y:9216 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPTIME, @@ -22317,10 +22349,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1400: + case 1402: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9167 +//line mysql_sql.y:9223 { var str = yyDollar[4].cstrUnion().Compare() yyLOCAL = &tree.AtTimeStamp{ @@ -22330,10 +22362,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1401: + case 1403: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9176 +//line mysql_sql.y:9232 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPSNAPSHOT, @@ -22342,10 +22374,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1402: + case 1404: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9184 +//line mysql_sql.y:9240 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATMOTIMESTAMP, @@ -22353,10 +22385,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1403: + case 1405: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9191 +//line mysql_sql.y:9247 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ASOFTIMESTAMP, @@ -22364,74 +22396,74 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1404: + case 1406: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9199 +//line mysql_sql.y:9255 { yyLOCAL = tree.TableDefs(nil) } yyVAL.union = yyLOCAL - case 1406: + case 1408: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9206 +//line mysql_sql.y:9262 { yyLOCAL = tree.TableDefs{yyDollar[1].tableDefUnion()} } yyVAL.union = yyLOCAL - case 1407: + case 1409: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9210 +//line mysql_sql.y:9266 { yyLOCAL = append(yyDollar[1].tableDefsUnion(), yyDollar[3].tableDefUnion()) } yyVAL.union = yyLOCAL - case 1408: + case 1410: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9216 +//line mysql_sql.y:9272 { yyLOCAL = tree.TableDef(yyDollar[1].columnTableDefUnion()) } yyVAL.union = yyLOCAL - case 1409: + case 1411: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9220 +//line mysql_sql.y:9276 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1410: + case 1412: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9224 +//line mysql_sql.y:9280 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1411: + case 1413: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9230 +//line mysql_sql.y:9286 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1412: + case 1414: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9234 +//line mysql_sql.y:9290 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1413: + case 1415: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9240 +//line mysql_sql.y:9296 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -22445,10 +22477,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1414: + case 1416: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9253 +//line mysql_sql.y:9309 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -22462,10 +22494,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1415: + case 1417: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9266 +//line mysql_sql.y:9322 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -22507,10 +22539,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1416: + case 1418: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9307 +//line mysql_sql.y:9363 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -22551,10 +22583,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1417: + case 1419: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9349 +//line mysql_sql.y:9405 { if yyDollar[1].str != "" { switch v := yyDollar[2].tableDefUnion().(type) { @@ -22569,18 +22601,18 @@ yydefault: yyLOCAL = yyDollar[2].tableDefUnion() } yyVAL.union = yyLOCAL - case 1418: + case 1420: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9363 +//line mysql_sql.y:9419 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1419: + case 1421: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9369 +//line mysql_sql.y:9425 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -22594,10 +22626,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1420: + case 1422: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9382 +//line mysql_sql.y:9438 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -22611,10 +22643,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1421: + case 1423: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9395 +//line mysql_sql.y:9451 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -22628,10 +22660,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1422: + case 1424: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9408 +//line mysql_sql.y:9464 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -22645,10 +22677,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1423: + case 1425: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9421 +//line mysql_sql.y:9477 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var KeyParts = yyDollar[6].keyPartsUnion() @@ -22664,10 +22696,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1424: + case 1426: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9436 +//line mysql_sql.y:9492 { var Expr = yyDollar[3].exprUnion() var Enforced = yyDollar[5].boolValUnion() @@ -22677,327 +22709,327 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1425: + case 1427: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9446 +//line mysql_sql.y:9502 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1427: + case 1429: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9452 +//line mysql_sql.y:9508 { yyVAL.str = "" } - case 1428: + case 1430: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9456 +//line mysql_sql.y:9512 { yyVAL.str = yyDollar[1].str } - case 1431: + case 1433: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9466 +//line mysql_sql.y:9522 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = "" } yyVAL.union = yyLOCAL - case 1432: + case 1434: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9472 +//line mysql_sql.y:9528 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1433: + case 1435: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9478 +//line mysql_sql.y:9534 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].cstrUnion().Compare() yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1445: + case 1447: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9500 +//line mysql_sql.y:9556 { yyVAL.str = "" } - case 1446: + case 1448: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9504 +//line mysql_sql.y:9560 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1447: + case 1449: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ColumnTableDef -//line mysql_sql.y:9510 +//line mysql_sql.y:9566 { yyLOCAL = tree.NewColumnTableDef(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), yyDollar[3].columnAttributesUnion()) } yyVAL.union = yyLOCAL - case 1448: + case 1450: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9516 +//line mysql_sql.y:9572 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1449: + case 1451: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9520 +//line mysql_sql.y:9576 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1450: + case 1452: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9525 +//line mysql_sql.y:9581 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(dbNameCStr, tblNameCStr, yyDollar[5].cstrUnion()) } yyVAL.union = yyLOCAL - case 1451: + case 1453: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9533 +//line mysql_sql.y:9589 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1452: + case 1454: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9537 +//line mysql_sql.y:9593 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1453: + case 1455: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9541 +//line mysql_sql.y:9597 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1454: + case 1456: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9545 +//line mysql_sql.y:9601 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1455: + case 1457: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9551 +//line mysql_sql.y:9607 { yyLOCAL = yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) } yyVAL.union = yyLOCAL - case 1456: + case 1458: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9557 +//line mysql_sql.y:9613 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1457: + case 1459: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9561 +//line mysql_sql.y:9617 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1458: + case 1460: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9566 +//line mysql_sql.y:9622 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(dbNameCStr, tblNameCStr, yyDollar[5].cstrUnion()) } yyVAL.union = yyLOCAL - case 1459: + case 1461: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9573 +//line mysql_sql.y:9629 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1460: + case 1462: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9577 +//line mysql_sql.y:9633 { yyLOCAL = yyDollar[1].columnAttributesUnion() } yyVAL.union = yyLOCAL - case 1461: + case 1463: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9583 +//line mysql_sql.y:9639 { yyLOCAL = []tree.ColumnAttribute{yyDollar[1].columnAttributeUnion()} } yyVAL.union = yyLOCAL - case 1462: + case 1464: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9587 +//line mysql_sql.y:9643 { yyLOCAL = append(yyDollar[1].columnAttributesUnion(), yyDollar[2].columnAttributeUnion()) } yyVAL.union = yyLOCAL - case 1463: + case 1465: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9593 +//line mysql_sql.y:9649 { yyLOCAL = tree.NewAttributeNull(true) } yyVAL.union = yyLOCAL - case 1464: + case 1466: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9597 +//line mysql_sql.y:9653 { yyLOCAL = tree.NewAttributeNull(false) } yyVAL.union = yyLOCAL - case 1465: + case 1467: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9601 +//line mysql_sql.y:9657 { yyLOCAL = tree.NewAttributeDefault(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1466: + case 1468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9605 +//line mysql_sql.y:9661 { yyLOCAL = tree.NewAttributeAutoIncrement() } yyVAL.union = yyLOCAL - case 1467: + case 1469: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9609 +//line mysql_sql.y:9665 { yyLOCAL = yyDollar[1].columnAttributeUnion() } yyVAL.union = yyLOCAL - case 1468: + case 1470: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9613 +//line mysql_sql.y:9669 { str := util.DealCommentString(yyDollar[2].str) yyLOCAL = tree.NewAttributeComment(tree.NewNumVal(str, str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1469: + case 1471: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9618 +//line mysql_sql.y:9674 { yyLOCAL = tree.NewAttributeCollate(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1470: + case 1472: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9622 +//line mysql_sql.y:9678 { yyLOCAL = tree.NewAttributeColumnFormat(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1471: + case 1473: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9626 +//line mysql_sql.y:9682 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1472: + case 1474: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9630 +//line mysql_sql.y:9686 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1473: + case 1475: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9634 +//line mysql_sql.y:9690 { yyLOCAL = tree.NewAttributeStorage(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1474: + case 1476: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9638 +//line mysql_sql.y:9694 { yyLOCAL = tree.NewAttributeAutoRandom(int(yyDollar[2].int64ValUnion())) } yyVAL.union = yyLOCAL - case 1475: + case 1477: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9642 +//line mysql_sql.y:9698 { yyLOCAL = yyDollar[1].attributeReferenceUnion() } yyVAL.union = yyLOCAL - case 1476: + case 1478: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9646 +//line mysql_sql.y:9702 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), false, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1477: + case 1479: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9650 +//line mysql_sql.y:9706 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), yyDollar[6].boolValUnion(), yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1478: + case 1480: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9654 +//line mysql_sql.y:9710 { name := tree.NewUnresolvedColName(yyDollar[3].str) var es tree.Exprs = nil @@ -23012,98 +23044,98 @@ yydefault: yyLOCAL = tree.NewAttributeOnUpdate(expr) } yyVAL.union = yyLOCAL - case 1479: + case 1481: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9668 +//line mysql_sql.y:9724 { yyLOCAL = tree.NewAttributeLowCardinality() } yyVAL.union = yyLOCAL - case 1480: + case 1482: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9672 +//line mysql_sql.y:9728 { yyLOCAL = tree.NewAttributeVisable(true) } yyVAL.union = yyLOCAL - case 1481: + case 1483: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9676 +//line mysql_sql.y:9732 { yyLOCAL = tree.NewAttributeVisable(false) } yyVAL.union = yyLOCAL - case 1482: + case 1484: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9680 +//line mysql_sql.y:9736 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1483: + case 1485: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9684 +//line mysql_sql.y:9740 { yyLOCAL = tree.NewAttributeHeader(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1484: + case 1486: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9688 +//line mysql_sql.y:9744 { yyLOCAL = tree.NewAttributeHeaders() } yyVAL.union = yyLOCAL - case 1485: + case 1487: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9694 +//line mysql_sql.y:9750 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1486: + case 1488: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9698 +//line mysql_sql.y:9754 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1487: + case 1489: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9703 +//line mysql_sql.y:9759 { yyVAL.str = "" } - case 1488: + case 1490: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9707 +//line mysql_sql.y:9763 { yyVAL.str = yyDollar[1].str } - case 1489: + case 1491: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9713 +//line mysql_sql.y:9769 { yyVAL.str = "" } - case 1490: + case 1492: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9717 +//line mysql_sql.y:9773 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } - case 1491: + case 1493: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AttributeReference -//line mysql_sql.y:9723 +//line mysql_sql.y:9779 { var TableName = yyDollar[2].tableNameUnion() var KeyParts = yyDollar[3].keyPartsUnion() @@ -23119,10 +23151,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1492: + case 1494: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9740 +//line mysql_sql.y:9796 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -23130,10 +23162,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1493: + case 1495: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9747 +//line mysql_sql.y:9803 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -23141,10 +23173,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1494: + case 1496: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9754 +//line mysql_sql.y:9810 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -23152,10 +23184,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1495: + case 1497: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9761 +//line mysql_sql.y:9817 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -23163,10 +23195,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1496: + case 1498: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9768 +//line mysql_sql.y:9824 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[2].referenceOptionTypeUnion(), @@ -23174,354 +23206,354 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1497: + case 1499: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9777 +//line mysql_sql.y:9833 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1498: + case 1500: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9783 +//line mysql_sql.y:9839 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1499: + case 1501: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9789 +//line mysql_sql.y:9845 { yyLOCAL = tree.REFERENCE_OPTION_RESTRICT } yyVAL.union = yyLOCAL - case 1500: + case 1502: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9793 +//line mysql_sql.y:9849 { yyLOCAL = tree.REFERENCE_OPTION_CASCADE } yyVAL.union = yyLOCAL - case 1501: + case 1503: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9797 +//line mysql_sql.y:9853 { yyLOCAL = tree.REFERENCE_OPTION_SET_NULL } yyVAL.union = yyLOCAL - case 1502: + case 1504: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9801 +//line mysql_sql.y:9857 { yyLOCAL = tree.REFERENCE_OPTION_NO_ACTION } yyVAL.union = yyLOCAL - case 1503: + case 1505: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9805 +//line mysql_sql.y:9861 { yyLOCAL = tree.REFERENCE_OPTION_SET_DEFAULT } yyVAL.union = yyLOCAL - case 1504: + case 1506: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:9810 +//line mysql_sql.y:9866 { yyLOCAL = tree.MATCH_INVALID } yyVAL.union = yyLOCAL - case 1506: + case 1508: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:9817 +//line mysql_sql.y:9873 { yyLOCAL = tree.MATCH_FULL } yyVAL.union = yyLOCAL - case 1507: + case 1509: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:9821 +//line mysql_sql.y:9877 { yyLOCAL = tree.MATCH_PARTIAL } yyVAL.union = yyLOCAL - case 1508: + case 1510: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:9825 +//line mysql_sql.y:9881 { yyLOCAL = tree.MATCH_SIMPLE } yyVAL.union = yyLOCAL - case 1509: + case 1511: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:9830 +//line mysql_sql.y:9886 { yyLOCAL = tree.FULLTEXT_DEFAULT } yyVAL.union = yyLOCAL - case 1510: + case 1512: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:9834 +//line mysql_sql.y:9890 { yyLOCAL = tree.FULLTEXT_NL } yyVAL.union = yyLOCAL - case 1511: + case 1513: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:9838 +//line mysql_sql.y:9894 { yyLOCAL = tree.FULLTEXT_NL_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1512: + case 1514: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:9842 +//line mysql_sql.y:9898 { yyLOCAL = tree.FULLTEXT_BOOLEAN } yyVAL.union = yyLOCAL - case 1513: + case 1515: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:9846 +//line mysql_sql.y:9902 { yyLOCAL = tree.FULLTEXT_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1514: + case 1516: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:9851 +//line mysql_sql.y:9907 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1515: + case 1517: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:9855 +//line mysql_sql.y:9911 { yyLOCAL = yyDollar[2].keyPartsUnion() } yyVAL.union = yyLOCAL - case 1516: + case 1518: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9860 +//line mysql_sql.y:9916 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 1517: + case 1519: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9864 +//line mysql_sql.y:9920 { yyLOCAL = yyDollar[2].item.(int64) } yyVAL.union = yyLOCAL - case 1524: + case 1526: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Subquery -//line mysql_sql.y:9880 +//line mysql_sql.y:9936 { yyLOCAL = &tree.Subquery{Select: yyDollar[1].selectStatementUnion(), Exists: false} } yyVAL.union = yyLOCAL - case 1525: + case 1527: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9886 +//line mysql_sql.y:9942 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_AND, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1526: + case 1528: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9890 +//line mysql_sql.y:9946 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_OR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1527: + case 1529: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9894 +//line mysql_sql.y:9950 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_XOR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1528: + case 1530: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9898 +//line mysql_sql.y:9954 { yyLOCAL = tree.NewBinaryExpr(tree.PLUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1529: + case 1531: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9902 +//line mysql_sql.y:9958 { yyLOCAL = tree.NewBinaryExpr(tree.MINUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1530: + case 1532: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9906 +//line mysql_sql.y:9962 { yyLOCAL = tree.NewBinaryExpr(tree.MULTI, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1531: + case 1533: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9910 +//line mysql_sql.y:9966 { yyLOCAL = tree.NewBinaryExpr(tree.DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1532: + case 1534: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9914 +//line mysql_sql.y:9970 { yyLOCAL = tree.NewBinaryExpr(tree.INTEGER_DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1533: + case 1535: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9918 +//line mysql_sql.y:9974 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1534: + case 1536: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9922 +//line mysql_sql.y:9978 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1535: + case 1537: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9926 +//line mysql_sql.y:9982 { yyLOCAL = tree.NewBinaryExpr(tree.LEFT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1536: + case 1538: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9930 +//line mysql_sql.y:9986 { yyLOCAL = tree.NewBinaryExpr(tree.RIGHT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1537: + case 1539: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9934 +//line mysql_sql.y:9990 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1538: + case 1540: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9940 +//line mysql_sql.y:9996 { yyLOCAL = yyDollar[1].unresolvedNameUnion() } yyVAL.union = yyLOCAL - case 1539: + case 1541: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9944 +//line mysql_sql.y:10000 { yyLOCAL = yyDollar[1].varExprUnion() } yyVAL.union = yyLOCAL - case 1540: + case 1542: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9948 +//line mysql_sql.y:10004 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1541: + case 1543: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9952 +//line mysql_sql.y:10008 { yyLOCAL = tree.NewParentExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1542: + case 1544: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9956 +//line mysql_sql.y:10012 { yyLOCAL = tree.NewTuple(append(yyDollar[2].exprsUnion(), yyDollar[4].exprUnion())) } yyVAL.union = yyLOCAL - case 1543: + case 1545: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9960 +//line mysql_sql.y:10016 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_PLUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1544: + case 1546: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9964 +//line mysql_sql.y:10020 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MINUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1545: + case 1547: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9968 +//line mysql_sql.y:10024 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_TILDE, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1546: + case 1548: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9972 +//line mysql_sql.y:10028 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MARK, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1547: + case 1549: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:9976 +//line mysql_sql.y:10032 { hint := strings.ToLower(yyDollar[2].cstrUnion().Compare()) switch hint { @@ -23564,35 +23596,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1548: + case 1550: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10018 +//line mysql_sql.y:10074 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1549: + case 1551: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10022 +//line mysql_sql.y:10078 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1550: + case 1552: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10026 +//line mysql_sql.y:10082 { yyDollar[2].subqueryUnion().Exists = true yyLOCAL = yyDollar[2].subqueryUnion() } yyVAL.union = yyLOCAL - case 1551: + case 1553: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10031 +//line mysql_sql.y:10087 { yyLOCAL = &tree.CaseExpr{ Expr: yyDollar[2].exprUnion(), @@ -23601,42 +23633,42 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1552: + case 1554: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10039 +//line mysql_sql.y:10095 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1553: + case 1555: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10043 +//line mysql_sql.y:10099 { yyLOCAL = tree.NewSerialExtractExpr(yyDollar[3].exprUnion(), yyDollar[5].exprUnion(), yyDollar[7].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1554: + case 1556: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10047 +//line mysql_sql.y:10103 { yyLOCAL = tree.NewBitCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1555: + case 1557: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10051 +//line mysql_sql.y:10107 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1556: + case 1558: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10055 +//line mysql_sql.y:10111 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char) @@ -23647,66 +23679,66 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1557: + case 1559: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10065 +//line mysql_sql.y:10121 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1558: + case 1560: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10069 +//line mysql_sql.y:10125 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1559: + case 1561: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10073 +//line mysql_sql.y:10129 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1560: + case 1562: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10077 +//line mysql_sql.y:10133 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1561: + case 1563: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10081 +//line mysql_sql.y:10137 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1562: + case 1564: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10085 +//line mysql_sql.y:10141 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1563: + case 1565: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10089 +//line mysql_sql.y:10145 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1564: + case 1566: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10093 +//line mysql_sql.y:10149 { val, err := tree.NewFullTextMatchFuncExpression(yyDollar[3].keyPartsUnion(), yyDollar[7].str, yyDollar[8].fullTextSearchTypeUnion()) if err != nil { @@ -23716,16 +23748,16 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1565: + case 1567: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10104 +//line mysql_sql.y:10160 { yyVAL.str = yyDollar[1].str } - case 1566: + case 1568: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10110 +//line mysql_sql.y:10166 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -23735,10 +23767,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1567: + case 1569: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10119 +//line mysql_sql.y:10175 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -23748,10 +23780,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1568: + case 1570: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10128 +//line mysql_sql.y:10184 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -23761,10 +23793,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1569: + case 1571: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10139 +//line mysql_sql.y:10195 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, "block") @@ -23775,10 +23807,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1570: + case 1572: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10149 +//line mysql_sql.y:10205 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, yyDollar[8].str) @@ -23789,10 +23821,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1571: + case 1573: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10159 +//line mysql_sql.y:10215 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), true, nil) if err != nil { @@ -23802,10 +23834,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1572: + case 1574: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10168 +//line mysql_sql.y:10224 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), true, nil) if err != nil { @@ -23815,10 +23847,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1573: + case 1575: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10178 +//line mysql_sql.y:10234 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), "block") @@ -23829,10 +23861,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1574: + case 1576: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10188 +//line mysql_sql.y:10244 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), yyDollar[8].str) @@ -23843,10 +23875,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1575: + case 1577: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10198 +//line mysql_sql.y:10254 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -23856,10 +23888,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1576: + case 1578: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10207 +//line mysql_sql.y:10263 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -23869,58 +23901,58 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1577: + case 1579: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10217 +//line mysql_sql.y:10273 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1578: + case 1580: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10221 +//line mysql_sql.y:10277 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1579: + case 1581: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10226 +//line mysql_sql.y:10282 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1580: + case 1582: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10230 +//line mysql_sql.y:10286 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1581: + case 1583: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:10236 +//line mysql_sql.y:10292 { yyLOCAL = []*tree.When{yyDollar[1].whenClauseUnion()} } yyVAL.union = yyLOCAL - case 1582: + case 1584: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:10240 +//line mysql_sql.y:10296 { yyLOCAL = append(yyDollar[1].whenClauseListUnion(), yyDollar[2].whenClauseUnion()) } yyVAL.union = yyLOCAL - case 1583: + case 1585: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.When -//line mysql_sql.y:10246 +//line mysql_sql.y:10302 { yyLOCAL = &tree.When{ Cond: yyDollar[2].exprUnion(), @@ -23928,9 +23960,9 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1584: + case 1586: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10255 +//line mysql_sql.y:10311 { t := yyVAL.columnTypeUnion() str := strings.ToLower(t.InternalType.FamilyString) @@ -23943,10 +23975,10 @@ yydefault: } } } - case 1585: + case 1587: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10267 +//line mysql_sql.y:10323 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -23964,10 +23996,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1586: + case 1588: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10284 +//line mysql_sql.y:10340 { locale := "" yyLOCAL = &tree.T{ @@ -23982,10 +24014,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1588: + case 1590: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10301 +//line mysql_sql.y:10357 { locale := "" yyLOCAL = &tree.T{ @@ -23999,10 +24031,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1589: + case 1591: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10314 +//line mysql_sql.y:10370 { locale := "" yyLOCAL = &tree.T{ @@ -24016,10 +24048,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1590: + case 1592: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10327 +//line mysql_sql.y:10383 { locale := "" yyLOCAL = &tree.T{ @@ -24032,10 +24064,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1591: + case 1593: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10339 +//line mysql_sql.y:10395 { locale := "" yyLOCAL = &tree.T{ @@ -24050,10 +24082,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1592: + case 1594: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10353 +//line mysql_sql.y:10409 { locale := "" yyLOCAL = &tree.T{ @@ -24069,10 +24101,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1593: + case 1595: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10368 +//line mysql_sql.y:10424 { locale := "" yyLOCAL = &tree.T{ @@ -24088,10 +24120,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1594: + case 1596: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10383 +//line mysql_sql.y:10439 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -24109,10 +24141,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1595: + case 1597: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10400 +//line mysql_sql.y:10456 { locale := "" yyLOCAL = &tree.T{ @@ -24127,95 +24159,95 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1596: + case 1598: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10415 +//line mysql_sql.y:10471 { } - case 1600: + case 1602: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10422 +//line mysql_sql.y:10478 { yyLOCAL = &tree.FrameBound{Type: tree.Following, UnBounded: true} } yyVAL.union = yyLOCAL - case 1601: + case 1603: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10426 +//line mysql_sql.y:10482 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1602: + case 1604: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10430 +//line mysql_sql.y:10486 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1603: + case 1605: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10436 +//line mysql_sql.y:10492 { yyLOCAL = &tree.FrameBound{Type: tree.CurrentRow} } yyVAL.union = yyLOCAL - case 1604: + case 1606: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10440 +//line mysql_sql.y:10496 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, UnBounded: true} } yyVAL.union = yyLOCAL - case 1605: + case 1607: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10444 +//line mysql_sql.y:10500 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1606: + case 1608: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10448 +//line mysql_sql.y:10504 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1607: + case 1609: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10454 +//line mysql_sql.y:10510 { yyLOCAL = tree.Rows } yyVAL.union = yyLOCAL - case 1608: + case 1610: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10458 +//line mysql_sql.y:10514 { yyLOCAL = tree.Range } yyVAL.union = yyLOCAL - case 1609: + case 1611: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10462 +//line mysql_sql.y:10518 { yyLOCAL = tree.Groups } yyVAL.union = yyLOCAL - case 1610: + case 1612: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10468 +//line mysql_sql.y:10524 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -24224,10 +24256,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1611: + case 1613: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10476 +//line mysql_sql.y:10532 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -24237,82 +24269,82 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1612: + case 1614: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10486 +//line mysql_sql.y:10542 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1613: + case 1615: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10490 +//line mysql_sql.y:10546 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1614: + case 1616: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10496 +//line mysql_sql.y:10552 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1615: + case 1617: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10501 +//line mysql_sql.y:10557 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1616: + case 1618: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10505 +//line mysql_sql.y:10561 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1617: + case 1619: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10510 +//line mysql_sql.y:10566 { yyVAL.str = "," } - case 1618: + case 1620: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:10514 +//line mysql_sql.y:10570 { yyVAL.str = yyDollar[2].str } - case 1619: + case 1621: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10519 +//line mysql_sql.y:10575 { yyVAL.str = "1,vector_l2_ops,random,false" } - case 1620: + case 1622: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:10523 +//line mysql_sql.y:10579 { yyVAL.str = yyDollar[2].str } - case 1621: + case 1623: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:10528 +//line mysql_sql.y:10584 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1623: + case 1625: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:10535 +//line mysql_sql.y:10591 { hasFrame := true var f *tree.FrameClause @@ -24337,10 +24369,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1624: + case 1626: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10561 +//line mysql_sql.y:10617 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24353,10 +24385,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1625: + case 1627: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10573 +//line mysql_sql.y:10629 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24369,10 +24401,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1626: + case 1628: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10585 +//line mysql_sql.y:10641 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24384,10 +24416,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1627: + case 1629: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10596 +//line mysql_sql.y:10652 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24399,10 +24431,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1628: + case 1630: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10607 +//line mysql_sql.y:10663 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_char) @@ -24414,10 +24446,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1629: + case 1631: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10618 +//line mysql_sql.y:10674 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24428,10 +24460,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1630: + case 1632: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10628 +//line mysql_sql.y:10684 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24442,10 +24474,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1631: + case 1633: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10638 +//line mysql_sql.y:10694 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24457,10 +24489,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1632: + case 1634: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10649 +//line mysql_sql.y:10705 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24472,10 +24504,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1633: + case 1635: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10660 +//line mysql_sql.y:10716 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24487,10 +24519,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1634: + case 1636: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10671 +//line mysql_sql.y:10727 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24502,10 +24534,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1635: + case 1637: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10682 +//line mysql_sql.y:10738 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_char) @@ -24517,10 +24549,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1636: + case 1638: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10693 +//line mysql_sql.y:10749 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24532,10 +24564,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1637: + case 1639: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10704 +//line mysql_sql.y:10760 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24547,10 +24579,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1638: + case 1640: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10715 +//line mysql_sql.y:10771 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24562,10 +24594,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1639: + case 1641: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10726 +//line mysql_sql.y:10782 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24577,10 +24609,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1640: + case 1642: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10737 +//line mysql_sql.y:10793 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24592,10 +24624,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1641: + case 1643: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10748 +//line mysql_sql.y:10804 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24607,10 +24639,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1642: + case 1644: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10759 +//line mysql_sql.y:10815 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24622,10 +24654,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1643: + case 1645: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10770 +//line mysql_sql.y:10826 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24637,10 +24669,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1644: + case 1646: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10781 +//line mysql_sql.y:10837 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24652,10 +24684,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1645: + case 1647: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10792 +//line mysql_sql.y:10848 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24667,10 +24699,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1646: + case 1648: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10803 +//line mysql_sql.y:10859 { name := tree.NewUnresolvedColName(yyDollar[1].str) var columnList tree.Exprs @@ -24688,10 +24720,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1650: + case 1652: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10827 +//line mysql_sql.y:10883 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24701,10 +24733,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1651: + case 1653: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10836 +//line mysql_sql.y:10892 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24714,10 +24746,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1652: + case 1654: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10845 +//line mysql_sql.y:10901 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24727,10 +24759,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1653: + case 1655: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10854 +//line mysql_sql.y:10910 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24740,10 +24772,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1654: + case 1656: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10863 +//line mysql_sql.y:10919 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -24755,10 +24787,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1655: + case 1657: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10874 +//line mysql_sql.y:10930 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24768,10 +24800,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1656: + case 1658: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10883 +//line mysql_sql.y:10939 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24782,10 +24814,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1657: + case 1659: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10893 +//line mysql_sql.y:10949 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24795,10 +24827,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1658: + case 1660: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10902 +//line mysql_sql.y:10958 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24808,10 +24840,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1659: + case 1661: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10911 +//line mysql_sql.y:10967 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24821,10 +24853,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1660: + case 1662: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10920 +//line mysql_sql.y:10976 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24834,10 +24866,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1661: + case 1663: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10929 +//line mysql_sql.y:10985 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(0), "0", false, tree.P_int64) @@ -24850,10 +24882,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1662: + case 1664: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10941 +//line mysql_sql.y:10997 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(1), "1", false, tree.P_int64) @@ -24865,10 +24897,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1663: + case 1665: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10952 +//line mysql_sql.y:11008 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(2), "2", false, tree.P_int64) @@ -24882,10 +24914,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1664: + case 1666: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10965 +//line mysql_sql.y:11021 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(3), "3", false, tree.P_int64) @@ -24898,10 +24930,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1665: + case 1667: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10977 +//line mysql_sql.y:11033 { column := tree.NewUnresolvedColName(yyDollar[3].str) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -24912,16 +24944,16 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1672: + case 1674: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10999 +//line mysql_sql.y:11055 { yyVAL.str = yyDollar[1].str } - case 1701: + case 1703: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11035 +//line mysql_sql.y:11091 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -24935,10 +24967,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1702: + case 1704: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11048 +//line mysql_sql.y:11104 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -24952,10 +24984,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1703: + case 1705: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11061 +//line mysql_sql.y:11117 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -24967,10 +24999,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1704: + case 1706: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11073 +//line mysql_sql.y:11129 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24980,10 +25012,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1705: + case 1707: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11082 +//line mysql_sql.y:11138 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24992,10 +25024,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1706: + case 1708: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11090 +//line mysql_sql.y:11146 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25004,10 +25036,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1707: + case 1709: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11098 +//line mysql_sql.y:11154 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -25021,10 +25053,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1708: + case 1710: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11111 +//line mysql_sql.y:11167 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25034,10 +25066,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1709: + case 1711: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11120 +//line mysql_sql.y:11176 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -25049,10 +25081,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1710: + case 1712: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11131 +//line mysql_sql.y:11187 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -25064,10 +25096,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1711: + case 1713: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11142 +//line mysql_sql.y:11198 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25077,10 +25109,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1712: + case 1714: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11151 +//line mysql_sql.y:11207 { cn := tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char) es := yyDollar[3].exprsUnion() @@ -25093,10 +25125,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1713: + case 1715: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11163 +//line mysql_sql.y:11219 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25107,10 +25139,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1714: + case 1716: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11173 +//line mysql_sql.y:11229 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25121,10 +25153,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1715: + case 1717: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11183 +//line mysql_sql.y:11239 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25134,10 +25166,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1716: + case 1718: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11192 +//line mysql_sql.y:11248 { es := tree.Exprs{yyDollar[3].exprUnion()} es = append(es, yyDollar[5].exprUnion()) @@ -25149,10 +25181,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1717: + case 1719: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11203 +//line mysql_sql.y:11259 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25162,10 +25194,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1718: + case 1720: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11212 +//line mysql_sql.y:11268 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25176,10 +25208,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1719: + case 1721: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11222 +//line mysql_sql.y:11278 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25189,10 +25221,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1720: + case 1722: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11231 +//line mysql_sql.y:11287 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25202,10 +25234,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1721: + case 1723: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11240 +//line mysql_sql.y:11296 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25215,34 +25247,34 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1722: + case 1724: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11250 +//line mysql_sql.y:11306 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1723: + case 1725: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11254 +//line mysql_sql.y:11310 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1724: + case 1726: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11260 +//line mysql_sql.y:11316 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1725: + case 1727: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11264 +//line mysql_sql.y:11320 { ival, errStr := util.GetInt64(yyDollar[2].item) if errStr != "" { @@ -25253,20 +25285,20 @@ yydefault: yyLOCAL = tree.NewNumVal(ival, str, false, tree.P_int64) } yyVAL.union = yyLOCAL - case 1732: + case 1734: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:11283 +//line mysql_sql.y:11339 { } - case 1733: + case 1735: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:11285 +//line mysql_sql.y:11341 { } - case 1768: + case 1770: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11327 +//line mysql_sql.y:11383 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -25278,106 +25310,106 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1769: + case 1771: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11339 +//line mysql_sql.y:11395 { yyLOCAL = tree.FUNC_TYPE_DEFAULT } yyVAL.union = yyLOCAL - case 1770: + case 1772: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11343 +//line mysql_sql.y:11399 { yyLOCAL = tree.FUNC_TYPE_DISTINCT } yyVAL.union = yyLOCAL - case 1771: + case 1773: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11347 +//line mysql_sql.y:11403 { yyLOCAL = tree.FUNC_TYPE_ALL } yyVAL.union = yyLOCAL - case 1772: + case 1774: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Tuple -//line mysql_sql.y:11353 +//line mysql_sql.y:11409 { yyLOCAL = tree.NewTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 1773: + case 1775: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11358 +//line mysql_sql.y:11414 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1774: + case 1776: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11362 +//line mysql_sql.y:11418 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1775: + case 1777: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11368 +//line mysql_sql.y:11424 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1776: + case 1778: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11372 +//line mysql_sql.y:11428 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1777: + case 1779: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11378 +//line mysql_sql.y:11434 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1778: + case 1780: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11382 +//line mysql_sql.y:11438 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1779: + case 1781: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11389 +//line mysql_sql.y:11445 { yyLOCAL = tree.NewAndExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1780: + case 1782: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11393 +//line mysql_sql.y:11449 { yyLOCAL = tree.NewOrExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1781: + case 1783: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11397 +//line mysql_sql.y:11453 { name := tree.NewUnresolvedColName("concat") yyLOCAL = &tree.FuncExpr{ @@ -25387,355 +25419,355 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1782: + case 1784: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11406 +//line mysql_sql.y:11462 { yyLOCAL = tree.NewXorExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1783: + case 1785: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11410 +//line mysql_sql.y:11466 { yyLOCAL = tree.NewNotExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1784: + case 1786: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11414 +//line mysql_sql.y:11470 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1785: + case 1787: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11419 +//line mysql_sql.y:11475 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1786: + case 1788: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11423 +//line mysql_sql.y:11479 { yyLOCAL = tree.NewMaxValue() } yyVAL.union = yyLOCAL - case 1787: + case 1789: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11429 +//line mysql_sql.y:11485 { yyLOCAL = tree.NewIsNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1788: + case 1790: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11433 +//line mysql_sql.y:11489 { yyLOCAL = tree.NewIsNotNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1789: + case 1791: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11437 +//line mysql_sql.y:11493 { yyLOCAL = tree.NewIsUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1790: + case 1792: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11441 +//line mysql_sql.y:11497 { yyLOCAL = tree.NewIsNotUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1791: + case 1793: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11445 +//line mysql_sql.y:11501 { yyLOCAL = tree.NewIsTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1792: + case 1794: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11449 +//line mysql_sql.y:11505 { yyLOCAL = tree.NewIsNotTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1793: + case 1795: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11453 +//line mysql_sql.y:11509 { yyLOCAL = tree.NewIsFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1794: + case 1796: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11457 +//line mysql_sql.y:11513 { yyLOCAL = tree.NewIsNotFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1795: + case 1797: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11461 +//line mysql_sql.y:11517 { yyLOCAL = tree.NewComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1796: + case 1798: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11465 +//line mysql_sql.y:11521 { yyLOCAL = tree.NewSubqueryComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[3].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[4].subqueryUnion()) yyLOCAL = tree.NewSubqueryComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[3].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[4].subqueryUnion()) } yyVAL.union = yyLOCAL - case 1798: + case 1800: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11473 +//line mysql_sql.y:11529 { yyLOCAL = tree.NewComparisonExpr(tree.IN, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1799: + case 1801: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11477 +//line mysql_sql.y:11533 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_IN, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1800: + case 1802: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11481 +//line mysql_sql.y:11537 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.LIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1801: + case 1803: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11485 +//line mysql_sql.y:11541 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_LIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1802: + case 1804: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11489 +//line mysql_sql.y:11545 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.ILIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1803: + case 1805: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11493 +//line mysql_sql.y:11549 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_ILIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1804: + case 1806: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11497 +//line mysql_sql.y:11553 { yyLOCAL = tree.NewComparisonExpr(tree.REG_MATCH, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1805: + case 1807: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11501 +//line mysql_sql.y:11557 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_REG_MATCH, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1806: + case 1808: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11505 +//line mysql_sql.y:11561 { yyLOCAL = tree.NewRangeCond(false, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1807: + case 1809: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11509 +//line mysql_sql.y:11565 { yyLOCAL = tree.NewRangeCond(true, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[6].exprUnion()) } yyVAL.union = yyLOCAL - case 1809: + case 1811: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11515 +//line mysql_sql.y:11571 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1810: + case 1812: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11519 +//line mysql_sql.y:11575 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1811: + case 1813: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11525 +//line mysql_sql.y:11581 { yyLOCAL = yyDollar[1].tupleUnion() } yyVAL.union = yyLOCAL - case 1812: + case 1814: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11529 +//line mysql_sql.y:11585 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1813: + case 1815: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11536 +//line mysql_sql.y:11592 { yyLOCAL = tree.ALL } yyVAL.union = yyLOCAL - case 1814: + case 1816: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11540 +//line mysql_sql.y:11596 { yyLOCAL = tree.ANY } yyVAL.union = yyLOCAL - case 1815: + case 1817: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11544 +//line mysql_sql.y:11600 { yyLOCAL = tree.SOME } yyVAL.union = yyLOCAL - case 1816: + case 1818: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11550 +//line mysql_sql.y:11606 { yyLOCAL = tree.EQUAL } yyVAL.union = yyLOCAL - case 1817: + case 1819: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11554 +//line mysql_sql.y:11610 { yyLOCAL = tree.LESS_THAN } yyVAL.union = yyLOCAL - case 1818: + case 1820: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11558 +//line mysql_sql.y:11614 { yyLOCAL = tree.GREAT_THAN } yyVAL.union = yyLOCAL - case 1819: + case 1821: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11562 +//line mysql_sql.y:11618 { yyLOCAL = tree.LESS_THAN_EQUAL } yyVAL.union = yyLOCAL - case 1820: + case 1822: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11566 +//line mysql_sql.y:11622 { yyLOCAL = tree.GREAT_THAN_EQUAL } yyVAL.union = yyLOCAL - case 1821: + case 1823: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11570 +//line mysql_sql.y:11626 { yyLOCAL = tree.NOT_EQUAL } yyVAL.union = yyLOCAL - case 1822: + case 1824: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11574 +//line mysql_sql.y:11630 { yyLOCAL = tree.NULL_SAFE_EQUAL } yyVAL.union = yyLOCAL - case 1823: + case 1825: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11580 +//line mysql_sql.y:11636 { yyLOCAL = tree.NewAttributePrimaryKey() } yyVAL.union = yyLOCAL - case 1824: + case 1826: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11584 +//line mysql_sql.y:11640 { yyLOCAL = tree.NewAttributeUniqueKey() } yyVAL.union = yyLOCAL - case 1825: + case 1827: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11588 +//line mysql_sql.y:11644 { yyLOCAL = tree.NewAttributeUnique() } yyVAL.union = yyLOCAL - case 1826: + case 1828: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11592 +//line mysql_sql.y:11648 { yyLOCAL = tree.NewAttributeKey() } yyVAL.union = yyLOCAL - case 1827: + case 1829: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11598 +//line mysql_sql.y:11654 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -25749,35 +25781,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1828: + case 1830: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11611 +//line mysql_sql.y:11667 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 1829: + case 1831: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11616 +//line mysql_sql.y:11672 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 1830: + case 1832: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11622 +//line mysql_sql.y:11678 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1831: + case 1833: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11626 +//line mysql_sql.y:11682 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -25791,51 +25823,51 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1832: + case 1834: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11639 +//line mysql_sql.y:11695 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 1833: + case 1835: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11644 +//line mysql_sql.y:11700 { yyLOCAL = tree.NewNumVal(true, "true", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 1834: + case 1836: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11648 +//line mysql_sql.y:11704 { yyLOCAL = tree.NewNumVal(false, "false", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 1835: + case 1837: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11652 +//line mysql_sql.y:11708 { yyLOCAL = tree.NewNumVal("null", "null", false, tree.P_null) } yyVAL.union = yyLOCAL - case 1836: + case 1838: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11656 +//line mysql_sql.y:11712 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_hexnum) } yyVAL.union = yyLOCAL - case 1837: + case 1839: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11660 +//line mysql_sql.y:11716 { if strings.HasPrefix(yyDollar[2].str, "0x") { yyDollar[2].str = yyDollar[2].str[2:] @@ -25843,69 +25875,69 @@ yydefault: yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_bit) } yyVAL.union = yyLOCAL - case 1838: + case 1840: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11667 +//line mysql_sql.y:11723 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 1839: + case 1841: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11671 +//line mysql_sql.y:11727 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_bit) } yyVAL.union = yyLOCAL - case 1840: + case 1842: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11675 +//line mysql_sql.y:11731 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1841: + case 1843: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11679 +//line mysql_sql.y:11735 { yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_ScoreBinary) } yyVAL.union = yyLOCAL - case 1842: + case 1844: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11685 +//line mysql_sql.y:11741 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.Unsigned = yyDollar[2].unsignedOptUnion() yyLOCAL.InternalType.Zerofill = yyDollar[3].zeroFillOptUnion() } yyVAL.union = yyLOCAL - case 1846: + case 1848: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11696 +//line mysql_sql.y:11752 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.DisplayWith = yyDollar[2].lengthOptUnion() } yyVAL.union = yyLOCAL - case 1847: + case 1849: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11701 +//line mysql_sql.y:11757 { yyLOCAL = yyDollar[1].columnTypeUnion() } yyVAL.union = yyLOCAL - case 1848: + case 1850: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11707 +//line mysql_sql.y:11763 { locale := "" yyLOCAL = &tree.T{ @@ -25918,10 +25950,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1849: + case 1851: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11719 +//line mysql_sql.y:11775 { locale := "" yyLOCAL = &tree.T{ @@ -25934,10 +25966,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1850: + case 1852: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11731 +//line mysql_sql.y:11787 { locale := "" yyLOCAL = &tree.T{ @@ -25950,10 +25982,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1851: + case 1853: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11743 +//line mysql_sql.y:11799 { locale := "" yyLOCAL = &tree.T{ @@ -25967,10 +25999,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1852: + case 1854: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11756 +//line mysql_sql.y:11812 { locale := "" yyLOCAL = &tree.T{ @@ -25984,10 +26016,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1853: + case 1855: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11769 +//line mysql_sql.y:11825 { locale := "" yyLOCAL = &tree.T{ @@ -26001,10 +26033,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1854: + case 1856: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11782 +//line mysql_sql.y:11838 { locale := "" yyLOCAL = &tree.T{ @@ -26018,10 +26050,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1855: + case 1857: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11795 +//line mysql_sql.y:11851 { locale := "" yyLOCAL = &tree.T{ @@ -26035,10 +26067,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1856: + case 1858: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11808 +//line mysql_sql.y:11864 { locale := "" yyLOCAL = &tree.T{ @@ -26052,10 +26084,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1857: + case 1859: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11821 +//line mysql_sql.y:11877 { locale := "" yyLOCAL = &tree.T{ @@ -26069,10 +26101,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1858: + case 1860: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11834 +//line mysql_sql.y:11890 { locale := "" yyLOCAL = &tree.T{ @@ -26086,10 +26118,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1859: + case 1861: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11847 +//line mysql_sql.y:11903 { locale := "" yyLOCAL = &tree.T{ @@ -26103,10 +26135,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1860: + case 1862: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11860 +//line mysql_sql.y:11916 { locale := "" yyLOCAL = &tree.T{ @@ -26120,10 +26152,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1861: + case 1863: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11873 +//line mysql_sql.y:11929 { locale := "" yyLOCAL = &tree.T{ @@ -26137,10 +26169,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1862: + case 1864: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11888 +//line mysql_sql.y:11944 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -26168,10 +26200,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1863: + case 1865: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11915 +//line mysql_sql.y:11971 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -26213,10 +26245,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1864: + case 1866: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11957 +//line mysql_sql.y:12013 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -26253,10 +26285,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1865: + case 1867: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:11993 +//line mysql_sql.y:12049 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -26293,10 +26325,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1866: + case 1868: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12029 +//line mysql_sql.y:12085 { locale := "" yyLOCAL = &tree.T{ @@ -26312,10 +26344,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1867: + case 1869: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12046 +//line mysql_sql.y:12102 { locale := "" yyLOCAL = &tree.T{ @@ -26328,10 +26360,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1868: + case 1870: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12058 +//line mysql_sql.y:12114 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -26352,10 +26384,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1869: + case 1871: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12078 +//line mysql_sql.y:12134 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -26376,10 +26408,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1870: + case 1872: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12098 +//line mysql_sql.y:12154 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -26400,10 +26432,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1871: + case 1873: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12118 +//line mysql_sql.y:12174 { locale := "" yyLOCAL = &tree.T{ @@ -26418,10 +26450,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1872: + case 1874: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12134 +//line mysql_sql.y:12190 { locale := "" yyLOCAL = &tree.T{ @@ -26435,10 +26467,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1873: + case 1875: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12147 +//line mysql_sql.y:12203 { locale := "" yyLOCAL = &tree.T{ @@ -26452,10 +26484,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1874: + case 1876: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12160 +//line mysql_sql.y:12216 { locale := "" yyLOCAL = &tree.T{ @@ -26469,10 +26501,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1875: + case 1877: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12173 +//line mysql_sql.y:12229 { locale := "" yyLOCAL = &tree.T{ @@ -26486,10 +26518,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1876: + case 1878: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12186 +//line mysql_sql.y:12242 { locale := "" yyLOCAL = &tree.T{ @@ -26502,10 +26534,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1877: + case 1879: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12198 +//line mysql_sql.y:12254 { locale := "" yyLOCAL = &tree.T{ @@ -26518,10 +26550,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1878: + case 1880: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12210 +//line mysql_sql.y:12266 { locale := "" yyLOCAL = &tree.T{ @@ -26534,10 +26566,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1879: + case 1881: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12222 +//line mysql_sql.y:12278 { locale := "" yyLOCAL = &tree.T{ @@ -26550,10 +26582,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1880: + case 1882: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12234 +//line mysql_sql.y:12290 { locale := "" yyLOCAL = &tree.T{ @@ -26566,10 +26598,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1881: + case 1883: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12246 +//line mysql_sql.y:12302 { locale := "" yyLOCAL = &tree.T{ @@ -26582,10 +26614,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1882: + case 1884: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12258 +//line mysql_sql.y:12314 { locale := "" yyLOCAL = &tree.T{ @@ -26598,10 +26630,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1883: + case 1885: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12270 +//line mysql_sql.y:12326 { locale := "" yyLOCAL = &tree.T{ @@ -26614,10 +26646,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1884: + case 1886: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12282 +//line mysql_sql.y:12338 { locale := "" yyLOCAL = &tree.T{ @@ -26630,10 +26662,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1885: + case 1887: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12294 +//line mysql_sql.y:12350 { locale := "" yyLOCAL = &tree.T{ @@ -26646,10 +26678,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1886: + case 1888: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12306 +//line mysql_sql.y:12362 { locale := "" yyLOCAL = &tree.T{ @@ -26663,10 +26695,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1887: + case 1889: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12319 +//line mysql_sql.y:12375 { locale := "" yyLOCAL = &tree.T{ @@ -26680,10 +26712,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1888: + case 1890: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12332 +//line mysql_sql.y:12388 { locale := "" yyLOCAL = &tree.T{ @@ -26697,10 +26729,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1889: + case 1891: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12345 +//line mysql_sql.y:12401 { locale := "" yyLOCAL = &tree.T{ @@ -26714,10 +26746,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1890: + case 1892: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12358 +//line mysql_sql.y:12414 { locale := "" yyLOCAL = &tree.T{ @@ -26731,20 +26763,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1891: + case 1893: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12373 +//line mysql_sql.y:12429 { yyLOCAL = &tree.Do{ Exprs: yyDollar[2].exprsUnion(), } } yyVAL.union = yyLOCAL - case 1892: + case 1894: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12381 +//line mysql_sql.y:12437 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -26753,10 +26785,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1893: + case 1895: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12390 +//line mysql_sql.y:12446 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -26765,10 +26797,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1894: + case 1896: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12400 +//line mysql_sql.y:12456 { locale := "" yyLOCAL = &tree.T{ @@ -26781,75 +26813,75 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1895: + case 1897: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12423 +//line mysql_sql.y:12479 { yyLOCAL = make([]string, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1896: + case 1898: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12428 +//line mysql_sql.y:12484 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1897: + case 1899: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12434 +//line mysql_sql.y:12490 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1899: + case 1901: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12441 +//line mysql_sql.y:12497 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1900: + case 1902: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12445 +//line mysql_sql.y:12501 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 1901: + case 1903: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12450 +//line mysql_sql.y:12506 { yyLOCAL = int32(-1) } yyVAL.union = yyLOCAL - case 1902: + case 1904: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12454 +//line mysql_sql.y:12510 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 1903: + case 1905: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12460 +//line mysql_sql.y:12516 { yyLOCAL = tree.GetDisplayWith(int32(yyDollar[2].item.(int64))) } yyVAL.union = yyLOCAL - case 1904: + case 1906: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12466 +//line mysql_sql.y:12522 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.NotDefineDisplayWidth, @@ -26857,10 +26889,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1905: + case 1907: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12473 +//line mysql_sql.y:12529 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -26868,10 +26900,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1906: + case 1908: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12480 +//line mysql_sql.y:12536 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -26879,10 +26911,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1907: + case 1909: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12489 +//line mysql_sql.y:12545 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: 38, // this is the default precision for decimal @@ -26890,10 +26922,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1908: + case 1910: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12496 +//line mysql_sql.y:12552 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -26901,10 +26933,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1909: + case 1911: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12503 +//line mysql_sql.y:12559 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -26912,52 +26944,52 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1910: + case 1912: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12512 +//line mysql_sql.y:12568 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1911: + case 1913: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12516 +//line mysql_sql.y:12572 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1912: + case 1914: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12520 +//line mysql_sql.y:12576 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1913: + case 1915: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12526 +//line mysql_sql.y:12582 { } - case 1914: + case 1916: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12528 +//line mysql_sql.y:12584 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1918: + case 1920: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12538 +//line mysql_sql.y:12594 { yyVAL.str = "" } - case 1919: + case 1921: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12542 +//line mysql_sql.y:12598 { yyVAL.str = string(yyDollar[1].str) } diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.y b/pkg/sql/parsers/dialect/mysql/mysql_sql.y index e28d13a01a0ea..bb641978c4efc 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.y +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.y @@ -580,6 +580,7 @@ import ( %type order %type order_list order_by_clause order_by_opt %type limit_opt limit_clause +%type limit_rank_suffix %type insert_column optype_opt %type optype %type column_list column_list_opt partition_clause_opt partition_id_list insert_column_list accounts_list restore_db_scope restore_table_scope @@ -5580,17 +5581,72 @@ limit_opt: } limit_clause: - LIMIT expression + LIMIT expression limit_rank_suffix { - $$ = &tree.Limit{Count: $2} + l := &tree.Limit{Count: $2} + if $3 != nil { + l.ByRank = $3.ByRank + l.Option = $3.Option + } + $$ = l } -| LIMIT expression ',' expression +| LIMIT expression ',' expression limit_rank_suffix { - $$ = &tree.Limit{Offset: $2, Count: $4} + l := &tree.Limit{Offset: $2, Count: $4} + if $5 != nil { + l.ByRank = $5.ByRank + l.Option = $5.Option + } + $$ = l } -| LIMIT expression OFFSET expression +| LIMIT expression OFFSET expression limit_rank_suffix + { + l := &tree.Limit{Offset: $4, Count: $2} + if $5 != nil { + l.ByRank = $5.ByRank + l.Option = $5.Option + } + $$ = l + } + +limit_rank_suffix: { - $$ = &tree.Limit{Offset: $4, Count: $2} + $$ = nil + } +| BY RANK WITH OPTION expression_list + { + // Parse option strings to extract key=value pairs into a map + optionMap := make(map[string]string) + + for _, expr := range $5 { + var str string + // Handle both NumVal (P_char) and StrVal + if numVal, ok := expr.(*tree.NumVal); ok && numVal.ValType == tree.P_char { + str = numVal.String() + } else if strVal, ok := expr.(*tree.StrVal); ok { + str = strVal.String() + } else { + continue + } + + // Remove quotes if present + if len(str) >= 2 && ((str[0] == '\'' && str[len(str)-1] == '\'') || (str[0] == '"' && str[len(str)-1] == '"')) { + str = str[1 : len(str)-1] + } + + // Parse key=value pairs + parts := strings.Split(str, "=") + if len(parts) == 2 { + key := strings.TrimSpace(strings.ToLower(parts[0])) + value := strings.TrimSpace(parts[1]) + optionMap[key] = value + } + } + + $$ = &tree.Limit{ + ByRank: true, + Option: optionMap, + } } order_by_opt: diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go index 82e580fa1057b..45640079177a9 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go @@ -3522,3 +3522,93 @@ func TestFaultTolerance(t *testing.T) { } } } + +func TestLimitByRank(t *testing.T) { + ctx := context.TODO() + testCases := []struct { + input string + output string // expected output from tree.String + checkFn func(*testing.T, tree.Statement) + }{ + { + input: "SELECT a, b, c FROM T LIMIT 20 BY RANK WITH OPTION 'fudge_factor=3.0', 'nprobe=10'", + output: "select a, b, c from t limit 20 by rank with option 'fudge_factor=3.0', 'nprobe=10'", + checkFn: func(t *testing.T, stmt tree.Statement) { + selectStmt, ok := stmt.(*tree.Select) + require.True(t, ok) + require.NotNil(t, selectStmt.Limit) + require.True(t, selectStmt.Limit.ByRank) + require.NotNil(t, selectStmt.Limit.Option) + require.Equal(t, "3.0", selectStmt.Limit.Option["fudge_factor"]) + require.Equal(t, "10", selectStmt.Limit.Option["nprobe"]) + }, + }, + { + input: "SELECT * FROM T LIMIT 10 BY RANK WITH OPTION 'fudge_factor=2.5', 'mode=pre'", + output: "select * from t limit 10 by rank with option 'fudge_factor=2.5', 'mode=pre'", + checkFn: func(t *testing.T, stmt tree.Statement) { + selectStmt, ok := stmt.(*tree.Select) + require.True(t, ok) + require.NotNil(t, selectStmt.Limit) + require.True(t, selectStmt.Limit.ByRank) + require.NotNil(t, selectStmt.Limit.Option) + require.Equal(t, "2.5", selectStmt.Limit.Option["fudge_factor"]) + require.Equal(t, "pre", selectStmt.Limit.Option["mode"]) + }, + }, + { + input: "SELECT * FROM T LIMIT 10 BY RANK WITH OPTION 'fudge_factor=1.0', 'mode=post'", + output: "select * from t limit 10 by rank with option 'fudge_factor=1.0', 'mode=post'", + checkFn: func(t *testing.T, stmt tree.Statement) { + selectStmt, ok := stmt.(*tree.Select) + require.True(t, ok) + require.NotNil(t, selectStmt.Limit) + require.True(t, selectStmt.Limit.ByRank) + require.NotNil(t, selectStmt.Limit.Option) + require.Equal(t, "1.0", selectStmt.Limit.Option["fudge_factor"]) + require.Equal(t, "post", selectStmt.Limit.Option["mode"]) + }, + }, + { + input: "SELECT * FROM T LIMIT 5, 10 BY RANK WITH OPTION 'nprobe=20'", + output: "select * from t limit 10 offset 5 by rank with option 'nprobe=20'", + checkFn: func(t *testing.T, stmt tree.Statement) { + selectStmt, ok := stmt.(*tree.Select) + require.True(t, ok) + require.NotNil(t, selectStmt.Limit) + require.True(t, selectStmt.Limit.ByRank) + require.NotNil(t, selectStmt.Limit.Option) + require.Equal(t, "20", selectStmt.Limit.Option["nprobe"]) + require.NotNil(t, selectStmt.Limit.Offset) + }, + }, + { + input: "SELECT * FROM T LIMIT 10 OFFSET 5 BY RANK WITH OPTION 'fudge_factor=4.0'", + output: "select * from t limit 10 offset 5 by rank with option 'fudge_factor=4.0'", + checkFn: func(t *testing.T, stmt tree.Statement) { + selectStmt, ok := stmt.(*tree.Select) + require.True(t, ok) + require.NotNil(t, selectStmt.Limit) + require.True(t, selectStmt.Limit.ByRank) + require.NotNil(t, selectStmt.Limit.Option) + require.Equal(t, "4.0", selectStmt.Limit.Option["fudge_factor"]) + require.NotNil(t, selectStmt.Limit.Offset) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.input, func(t *testing.T) { + ast, err := ParseOne(ctx, tc.input, 1) + require.NoError(t, err, "Failed to parse: %s", tc.input) + if tc.checkFn != nil { + tc.checkFn(t, ast) + } + // Test tree.String conversion + if tc.output != "" { + out := tree.String(ast, dialect.MYSQL) + require.Equal(t, tc.output, out, "tree.String output mismatch for input: %s", tc.input) + } + }) + } +} diff --git a/pkg/sql/parsers/dialect/postgresql/Makefile b/pkg/sql/parsers/dialect/postgresql/Makefile index c8e697af58bee..a217cdad13218 100644 --- a/pkg/sql/parsers/dialect/postgresql/Makefile +++ b/pkg/sql/parsers/dialect/postgresql/Makefile @@ -1,5 +1,17 @@ +# Note: There are currently 7 shift/reduce conflicts that are pending resolution. +# The build will fail if new conflicts are introduced (conflicts > 7). postgresql_sql.go: postgresql_sql.y - go run github.com/matrixorigin/matrixone/pkg/sql/parsers/goyacc -o postgresql_sql.go postgresql_sql.y + @output=$$(go run github.com/matrixorigin/matrixone/pkg/sql/parsers/goyacc -o postgresql_sql.go postgresql_sql.y 2>&1); \ + echo "$$output"; \ + conflicts=$$(echo "$$output" | grep "conflicts:" | sed -E 's/.*conflicts: ([0-9]+).*/\1/'); \ + if [ -z "$$conflicts" ]; then \ + conflicts=0; \ + fi; \ + if [ "$$conflicts" -gt 7 ]; then \ + rm -f postgresql_sql.go; \ + echo "Error: New conflicts detected! Current conflicts: $$conflicts (expected max: 7)" >&2; \ + exit 1; \ + fi gofmt -w postgresql_sql.go rm -f y.output diff --git a/pkg/sql/parsers/tree/select.go b/pkg/sql/parsers/tree/select.go index 8f187a7c41956..4e1c54601d21d 100644 --- a/pkg/sql/parsers/tree/select.go +++ b/pkg/sql/parsers/tree/select.go @@ -16,6 +16,7 @@ package tree import ( "fmt" + "sort" "strings" ) @@ -268,6 +269,9 @@ func (np NullsPosition) String() string { // the LIMIT clause. type Limit struct { Offset, Count Expr + ByRank bool + Option map[string]string // parsed options like {"fudge_factor": "3.0", "nprobe": "10", "mode": "pre"} + Mode string // "pre" or "post" } func (node *Limit) Format(ctx *FmtCtx) { @@ -283,6 +287,38 @@ func (node *Limit) Format(ctx *FmtCtx) { } ctx.WriteString("offset ") node.Offset.Format(ctx) + needSpace = true + } + if node != nil && node.ByRank { + if needSpace { + ctx.WriteByte(' ') + } + ctx.WriteString("by rank") + needSpace = true + } + if node != nil && node.Option != nil && len(node.Option) > 0 { + if needSpace { + ctx.WriteByte(' ') + } + ctx.WriteString("with option ") + // Sort keys to ensure deterministic output order + keys := make([]string, 0, len(node.Option)) + for key := range node.Option { + keys = append(keys, key) + } + sort.Strings(keys) + first := true + for _, key := range keys { + if !first { + ctx.WriteString(", ") + } + ctx.WriteString("'") + ctx.WriteString(key) + ctx.WriteString("=") + ctx.WriteString(node.Option[key]) + ctx.WriteString("'") + first = false + } } } diff --git a/pkg/sql/plan/agg_pushdown_pullup.go b/pkg/sql/plan/agg_pushdown_pullup.go index 37e6b56b8bcec..a0cc3e0a295ff 100644 --- a/pkg/sql/plan/agg_pushdown_pullup.go +++ b/pkg/sql/plan/agg_pushdown_pullup.go @@ -118,8 +118,8 @@ func applyAggPushdown(agg, join, leftChild *plan.Node, builder *QueryBuilder) { //newGroupBy := DeepCopyExprList(agg.GroupBy) newGroupBy := []*plan.Expr{DeepCopyExpr(filterTag(join.OnList[0], leftChildTag))} - newGroupTag := builder.genNewTag() - newAggTag := builder.genNewTag() + newGroupTag := builder.genNewBindTag() + newAggTag := builder.genNewBindTag() newNodeID := builder.appendNode( &plan.Node{ NodeType: plan.Node_AGG, diff --git a/pkg/sql/plan/apply_indices.go b/pkg/sql/plan/apply_indices.go index b197dd7c95cd6..8eeba2bba474f 100644 --- a/pkg/sql/plan/apply_indices.go +++ b/pkg/sql/plan/apply_indices.go @@ -672,7 +672,7 @@ func (builder *QueryBuilder) tryIndexOnlyScan(idxDef *IndexDef, node *plan.Node, return -1 } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() idxObjRef, idxTableDef, e := builder.compCtx.ResolveIndexTableByRef(node.ObjRef, idxDef.IndexTableName, scanSnapshot) if e != nil { panic(e) @@ -759,7 +759,7 @@ func (builder *QueryBuilder) getIndexForNonEquiCond(indexes []*IndexDef, node *p } func (builder *QueryBuilder) applyIndexJoin(idxDef *IndexDef, node *plan.Node, filterType int, filterIdx []int32, scanSnapshot *Snapshot) (int32, int32) { - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() idxObjRef, idxTableDef, err := builder.compCtx.ResolveIndexTableByRef(node.ObjRef, idxDef.IndexTableName, scanSnapshot) if err != nil { panic(err) @@ -989,7 +989,7 @@ func (builder *QueryBuilder) applyIndicesForJoins(nodeID int32, node *plan.Node, continue } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() idxObjRef, idxTableDef, err := builder.compCtx.ResolveIndexTableByRef(leftChild.ObjRef, idxDef.IndexTableName, scanSnapshot) if err != nil { panic(err) diff --git a/pkg/sql/plan/apply_indices_hnsw.go b/pkg/sql/plan/apply_indices_hnsw.go index 5424d1ca3e3fe..e10ee34da7956 100644 --- a/pkg/sql/plan/apply_indices_hnsw.go +++ b/pkg/sql/plan/apply_indices_hnsw.go @@ -103,7 +103,7 @@ func (builder *QueryBuilder) applyIndicesForSortUsingHnsw(nodeID int32, projNode origFuncName) // JOIN between source table and hnsw_search table function - tableFuncTag := builder.genNewTag() + tableFuncTag := builder.genNewBindTag() tableFuncNode := &plan.Node{ NodeType: plan.Node_FUNCTION_SCAN, Stats: &plan.Stats{}, diff --git a/pkg/sql/plan/apply_indices_ivfflat.go b/pkg/sql/plan/apply_indices_ivfflat.go index c0b9499830c77..107679aef65a3 100644 --- a/pkg/sql/plan/apply_indices_ivfflat.go +++ b/pkg/sql/plan/apply_indices_ivfflat.go @@ -48,12 +48,16 @@ func (builder *QueryBuilder) applyIndicesForSortUsingIvfflat(nodeID int32, projN } var limit *plan.Expr + var rankOption *plan.RankOption if sortNode.Limit != nil { limit = sortNode.Limit + rankOption = sortNode.RankOption } else if scanNode.Limit != nil { limit = scanNode.Limit + rankOption = scanNode.RankOption } else if projNode.Limit != nil { limit = projNode.Limit + rankOption = projNode.RankOption } if limit == nil { return nodeID, nil @@ -91,6 +95,7 @@ func (builder *QueryBuilder) applyIndicesForSortUsingIvfflat(nodeID int32, projN } nProbe := int64(5) + // Get nprobe from system variable nProbeIf, err := builder.compCtx.ResolveVariable("probe_limit", true, false) if err != nil { return nodeID, err @@ -123,8 +128,8 @@ func (builder *QueryBuilder) applyIndicesForSortUsingIvfflat(nodeID int32, projN partType.Id, origFuncName) - // JOIN between source table and hnsw_search table function - tableFuncTag := builder.genNewTag() + // build ivf_search table function node + tableFuncTag := builder.genNewBindTag() tableFuncNode := &plan.Node{ NodeType: plan.Node_FUNCTION_SCAN, Stats: &plan.Stats{}, @@ -197,42 +202,224 @@ func (builder *QueryBuilder) applyIndicesForSortUsingIvfflat(nodeID int32, projN tableFuncNode.Limit = DeepCopyExpr(limit) } - // oncond - wherePkEqPk, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*Expr{ - { + // Determine join structure based on rankOption.mode: + // mode != "pre": JOIN( scanNode, ivf_search ) + // mode == "pre": JOIN( scanNode, JOIN(ivf_search, secondScan) ) + var joinRootID int32 + + pushdownEnabled := false + if rankOption != nil && rankOption.Mode == "pre" { + pushdownEnabled = true + } + + if pushdownEnabled { + // secondScanNode: copy original scanNode for JOIN(ivf, table) + secondScanNodeID := builder.copyNode(ctx, scanNode.NodeId) + secondScanNode := builder.qry.Nodes[secondScanNodeID] + + for i := range secondScanNode.BindingTags { + secondScanNode.BindingTags[i] = builder.genNewBindTag() + } + + // second scan is only used for runtime filter & inner join, should not inherit limit/offset from original table. + // Otherwise BloomFilter will only see the truncated primary key set, causing data loss. + secondScanNode.Limit = nil + secondScanNode.Offset = nil + + // Add a PROJECT node above secondScanNode to output only the primary key column + secondProjectTag := builder.genNewBindTag() + secondPkExpr := &plan.Expr{ + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: secondScanNode.BindingTags[0], + ColPos: pkPos, + Name: scanNode.TableDef.Cols[pkPos].Name, + }, + }, + } + secondProjectNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{secondScanNodeID}, + ProjectList: []*plan.Expr{secondPkExpr}, + BindingTags: []int32{secondProjectTag}, + }, ctx) + + // inner join: (ivf_search table function JOIN second table project) + innerJoinOn, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*Expr{ + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: tableFuncTag, + ColPos: 0, // tf.pkid + }, + }, + }, + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: secondProjectTag, + ColPos: 0, // only pk column from second scan + }, + }, + }, + }) + + innerJoinNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_JOIN, + Children: []int32{tableFuncNodeID, secondProjectNodeID}, + JoinType: plan.Node_INNER, + OnList: []*Expr{innerJoinOn}, + // Don't set Limit/Offset on JOIN - they should be applied after SORT + }, ctx) + + // Construct BloomFilter type runtime filter for inner join + table function + rfTag := builder.genNewMsgTag() + + // build side: primary key from secondScanNode (consistent with BloomFilter build column) + buildExpr := &plan.Expr{ + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: secondProjectTag, + ColPos: 0, + }, + }, + } + buildSpec := MakeRuntimeFilter(rfTag, false, 0, buildExpr, false) + buildSpec.UseBloomFilter = true + innerJoinNode := builder.qry.Nodes[innerJoinNodeID] + innerJoinNode.RuntimeFilterBuildList = []*plan.RuntimeFilterSpec{buildSpec} + + // probe side: pkid column from table function + probeExpr := &plan.Expr{ + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: tableFuncTag, + ColPos: 0, + }, + }, + } + probeSpec := MakeRuntimeFilter(rfTag, false, 0, probeExpr, false) + probeSpec.UseBloomFilter = true + tableFuncNode.RuntimeFilterProbeList = []*plan.RuntimeFilterSpec{probeSpec} + + // outer join: original table JOIN (inner ivf join) + outerOn, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*Expr{ + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: scanNode.BindingTags[0], + ColPos: pkPos, // tbl.pk + }, + }, + }, + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: tableFuncTag, // tf pkid from inner join subtree + ColPos: 0, + }, + }, + }, + }) + + outerJoinNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_JOIN, + Children: []int32{scanNode.NodeId, innerJoinNodeID}, + JoinType: plan.Node_INNER, + OnList: []*Expr{outerOn}, + // Don't set Limit/Offset on JOIN - they should be applied after SORT + }, ctx) + + // Manually construct a runtime filter for outer join: + // - build side: right child inner join (smaller set, contains actual pkid) + // - probe side: left child table scan (original table), performs block/row pruning at scan stage. + // Note: + // 1) We don't use BloomFilter here, but use the existing IN-list runtime filter pipeline; + // 2) UpperLimit is set to avoid all filters being degraded to PASS due to 0. + rfTag2 := builder.genNewMsgTag() + + // probe: primary key column from original table (scanNode left child) + probeExpr2 := &plan.Expr{ Typ: pkType, Expr: &plan.Expr_Col{ Col: &plan.ColRef{ RelPos: scanNode.BindingTags[0], - ColPos: pkPos, // tbl.pk + ColPos: pkPos, }, }, - }, - { + } + probeSpec2 := MakeRuntimeFilter(rfTag2, false, 0, DeepCopyExpr(probeExpr2), false) + scanNode.RuntimeFilterProbeList = append(scanNode.RuntimeFilterProbeList, probeSpec2) + + // build: placeholder column, HashBuild will generate IN-list based on build side join key's UniqueJoinKeys[0] + buildExpr2 := &plan.Expr{ Typ: pkType, Expr: &plan.Expr_Col{ Col: &plan.ColRef{ - RelPos: tableFuncTag, // last idxTbl (may be join) relPos - ColPos: 0, // idxTbl.pk + RelPos: -1, + ColPos: 0, }, }, - }, - }) - - joinNodeID := builder.appendNode(&plan.Node{ - NodeType: plan.Node_JOIN, - Children: []int32{scanNode.NodeId, tableFuncNodeID}, - JoinType: plan.Node_INNER, - OnList: []*Expr{wherePkEqPk}, - // Don't set Limit/Offset on JOIN - they should be applied after SORT - }, ctx) + } + + // Set inLimit to "unlimited" to ensure this runtime filter won't be disabled due to upper limit. + // Use int32 max value directly here. + const unlimitedInFilterCard = int32(1<<31 - 1) + buildSpec2 := MakeRuntimeFilter(rfTag2, false, unlimitedInFilterCard, buildExpr2, false) + + outerJoinNode := builder.qry.Nodes[outerJoinNodeID] + outerJoinNode.RuntimeFilterBuildList = append(outerJoinNode.RuntimeFilterBuildList, buildSpec2) + + // Outer join doesn't add extra project, let global column pruning optimizer handle it + joinRootID = outerJoinNodeID + } else { + // JOIN( table, ivf ) + wherePkEqPk, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*Expr{ + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: scanNode.BindingTags[0], + ColPos: pkPos, // tbl.pk + }, + }, + }, + { + Typ: pkType, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: tableFuncTag, + ColPos: 0, // tf.pkid + }, + }, + }, + }) + + joinNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_JOIN, + Children: []int32{scanNode.NodeId, tableFuncNodeID}, + JoinType: plan.Node_INNER, + OnList: []*Expr{wherePkEqPk}, + // Don't set Limit/Offset on JOIN - they should be applied after SORT + }, ctx) + + // In non-nested mode, outer join also doesn't add extra project, let optimizer handle column pruning + joinRootID = joinNodeID + } // Keep FilterList on scanNode so filters are applied during table scan // Clear Limit/Offset from scanNode since they should be applied after SORT scanNode.Limit = nil scanNode.Offset = nil - // Create SortBy with distance column from table function + // Create SortBy, still sort directly by table function's score, let remap map ColRef to corresponding output column orderByScore := []*OrderBySpec{ { Expr: &plan.Expr{ @@ -250,7 +437,7 @@ func (builder *QueryBuilder) applyIndicesForSortUsingIvfflat(nodeID int32, projN sortByID := builder.appendNode(&plan.Node{ NodeType: plan.Node_SORT, - Children: []int32{joinNodeID}, + Children: []int32{joinRootID}, OrderBy: orderByScore, Limit: limit, // Apply LIMIT after sorting Offset: DeepCopyExpr(sortNode.Offset), // Apply OFFSET after sorting diff --git a/pkg/sql/plan/apply_indices_master.go b/pkg/sql/plan/apply_indices_master.go index 58aa7b5508513..ee2e9bf077d08 100644 --- a/pkg/sql/plan/apply_indices_master.go +++ b/pkg/sql/plan/apply_indices_master.go @@ -126,7 +126,7 @@ func makeIndexTblScan(builder *QueryBuilder, bindCtx *BindContext, filterExp *pl idxTableDef *TableDef, idxObjRef *ObjectRef, scanSnapshot *Snapshot, colDefs []*plan.ColDef) (int32, int32) { // a. Scan * WHERE prefix_eq(`__mo_index_idx_col`,serial_full("0","value")) - idxScanTag := builder.genNewTag() + idxScanTag := builder.genNewBindTag() args := filterExp.GetF().Args var filterList *plan.Expr diff --git a/pkg/sql/plan/bind_delete.go b/pkg/sql/plan/bind_delete.go index 0969c43930624..43e153a9764ff 100644 --- a/pkg/sql/plan/bind_delete.go +++ b/pkg/sql/plan/bind_delete.go @@ -166,7 +166,7 @@ func (builder *QueryBuilder) bindDelete(ctx CompilerContext, stmt *tree.Delete, idxTableDef.Name2ColIndex[col.Name] = int32(colIdx) } } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDef) idxScanNodes[i][j] = &plan.Node{ @@ -252,7 +252,7 @@ func (builder *QueryBuilder) bindDelete(ctx CompilerContext, stmt *tree.Delete, dmlNode := &plan.Node{ NodeType: plan.Node_MULTI_UPDATE, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, } selectNodeTag := selectNode.BindingTags[0] var lockTargets []*plan.LockTarget @@ -355,7 +355,7 @@ func (builder *QueryBuilder) bindDelete(ctx CompilerContext, stmt *tree.Delete, NodeType: plan.Node_LOCK_OP, Children: []int32{lastNodeID}, TableDef: dmlCtx.tableDefs[0], - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, LockTargets: lockTargets, }, bindCtx) diff --git a/pkg/sql/plan/bind_insert.go b/pkg/sql/plan/bind_insert.go index 10159ef9f39f6..7c93933d93476 100644 --- a/pkg/sql/plan/bind_insert.go +++ b/pkg/sql/plan/bind_insert.go @@ -133,7 +133,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( selectNode := builder.qry.Nodes[lastNodeID] selectTag := selectNode.BindingTags[0] - scanTag := builder.genNewTag() + scanTag := builder.genNewBindTag() updateExprs := make(map[string]*plan.Expr) if len(astUpdateExprs) == 0 { @@ -259,7 +259,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( NodeType: plan.Node_LOCK_OP, Children: []int32{lastNodeID}, TableDef: tableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, LockTargets: lockTargets, }, bindCtx) reCheckifNeedLockWholeTable(builder) @@ -563,7 +563,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( } // step 2: append unique dedup join on the `__mo_index_idx_col` if expression - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDefs[i]) idxScanNode := &plan.Node{ @@ -649,7 +649,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( if newProjLen > len(selectNode.ProjectList) { newProjList := make([]*plan.Expr, 0, newProjLen) - finalProjTag := builder.genNewTag() + finalProjTag := builder.genNewBindTag() pkPos := colName2Idx[tableDef.Name+"."+tableDef.Pkey.PkeyColName] // input batch columns @@ -836,7 +836,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( now, we need to join the index table to fetch the right rowid. */ - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDefs[i]) idxScanNode := &plan.Node{ @@ -891,7 +891,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindInsert( dmlNode := &plan.Node{ NodeType: plan.Node_MULTI_UPDATE, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, } insertCols := make([]plan.ColRef, len(tableDef.Cols)-1) @@ -1133,8 +1133,8 @@ func (builder *QueryBuilder) appendNodesForInsertStmt( projList1 := make([]*plan.Expr, 0, len(tableDef.Cols)-1) projList2 := make([]*plan.Expr, 0, len(tableDef.Cols)-1) - projTag1 := builder.genNewTag() - preInsertTag := builder.genNewTag() + projTag1 := builder.genNewBindTag() + preInsertTag := builder.genNewBindTag() var ( compPkeyExpr *plan.Expr @@ -1272,7 +1272,7 @@ func (builder *QueryBuilder) appendNodesForInsertStmt( NodeType: plan.Node_PROJECT, ProjectList: projList2, Children: []int32{lastNodeID}, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, tmpCtx) return lastNodeID, colName2Idx, skipUniqueIdx, nil @@ -1288,7 +1288,7 @@ func (builder *QueryBuilder) buildValueScan( var err error proc := builder.compCtx.GetProcess() - lastTag := builder.genNewTag() + lastTag := builder.genNewBindTag() colCount := len(colNames) rowsetData := &plan.RowsetData{ Cols: make([]*plan.ColData, colCount), @@ -1403,7 +1403,7 @@ func (builder *QueryBuilder) buildValueScan( return 0, err } - lastTag = builder.genNewTag() + lastTag = builder.genNewBindTag() nodeID = builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, ProjectList: projectList, diff --git a/pkg/sql/plan/bind_load.go b/pkg/sql/plan/bind_load.go index 09ab7c9711bb4..3d41757ff5904 100644 --- a/pkg/sql/plan/bind_load.go +++ b/pkg/sql/plan/bind_load.go @@ -42,7 +42,7 @@ func (builder *QueryBuilder) bindExternalScan( stmt *tree.Load, bindCtx *BindContext, dmlCtx *DMLContext) (int32, map[string]*plan.Expr, error) { - externalScanTag := builder.genNewTag() + externalScanTag := builder.genNewBindTag() err := dmlCtx.ResolveTables(builder.compCtx, tree.TableExprs{stmt.Table}, nil, nil, true) if err != nil { return -1, nil, err diff --git a/pkg/sql/plan/bind_replace.go b/pkg/sql/plan/bind_replace.go index 44e3a9756e4da..597d1667353fc 100644 --- a/pkg/sql/plan/bind_replace.go +++ b/pkg/sql/plan/bind_replace.go @@ -59,7 +59,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( selectNode := builder.qry.Nodes[lastNodeID] selectTag := selectNode.BindingTags[0] - fullProjTag := builder.genNewTag() + fullProjTag := builder.genNewBindTag() fullProjList := make([]*plan.Expr, 0, len(selectNode.ProjectList)+len(tableDef.Cols)) for i, expr := range selectNode.ProjectList { fullProjList = append(fullProjList, &plan.Expr{ @@ -80,7 +80,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( // get old columns from existing main table { - oldScanTag := builder.genNewTag() + oldScanTag := builder.genNewBindTag() builder.addNameByColRef(oldScanTag, tableDef) @@ -186,7 +186,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( // detect primary key confliction { - scanTag := builder.genNewTag() + scanTag := builder.genNewBindTag() // handle primary/unique key confliction builder.addNameByColRef(scanTag, tableDef) @@ -268,7 +268,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( continue } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDefs[i]) idxScanNode := &plan.Node{ @@ -352,7 +352,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( // get old RowID for index tables for i := range tableDef.Indexes { - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDefs[i]) idxScanNode := &plan.Node{ @@ -408,7 +408,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( lockTargets := make([]*plan.LockTarget, 0) updateCtxList := make([]*plan.UpdateCtx, 0) - finalProjTag := builder.genNewTag() + finalProjTag := builder.genNewBindTag() finalProjList := make([]*plan.Expr, 0, len(tableDef.Cols)+len(tableDef.Indexes)*2) var newPkIdx int32 @@ -580,7 +580,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( NodeType: plan.Node_LOCK_OP, Children: []int32{lastNodeID}, TableDef: tableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, LockTargets: lockTargets, }, bindCtx) reCheckifNeedLockWholeTable(builder) @@ -589,7 +589,7 @@ func (builder *QueryBuilder) appendDedupAndMultiUpdateNodesForBindReplace( lastNodeID = builder.appendNode(&plan.Node{ NodeType: plan.Node_MULTI_UPDATE, Children: []int32{lastNodeID}, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, UpdateCtxList: updateCtxList, }, bindCtx) @@ -614,8 +614,8 @@ func (builder *QueryBuilder) appendNodesForReplaceStmt( projList1 := make([]*plan.Expr, 0, len(tableDef.Cols)-1) projList2 := make([]*plan.Expr, 0, len(tableDef.Cols)-1) - projTag1 := builder.genNewTag() - preInsertTag := builder.genNewTag() + projTag1 := builder.genNewBindTag() + preInsertTag := builder.genNewBindTag() var ( compPkeyExpr *plan.Expr @@ -778,7 +778,7 @@ func (builder *QueryBuilder) appendNodesForReplaceStmt( NodeType: plan.Node_PROJECT, ProjectList: projList2, Children: []int32{lastNodeID}, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, tmpCtx) return lastNodeID, colName2Idx, skipUniqueIdx, nil diff --git a/pkg/sql/plan/bind_update.go b/pkg/sql/plan/bind_update.go index 2738124dbff39..eb5115541a32b 100644 --- a/pkg/sql/plan/bind_update.go +++ b/pkg/sql/plan/bind_update.go @@ -270,7 +270,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } if updatePkOrUk { - newProjTag := builder.genNewTag() + newProjTag := builder.genNewBindTag() newProjList := make([]*plan.Expr, len(selectNode.ProjectList)) for i := range selectNode.ProjectList { newProjList[i] = &plan.Expr{ @@ -325,7 +325,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) newProjNode.ProjectList = append(newProjNode.ProjectList, newPkExpr) } - scanTag := builder.genNewTag() + scanTag := builder.genNewBindTag() scanNodeID := builder.appendNode(&plan.Node{ NodeType: plan.Node_TABLE_SCAN, TableDef: tableDef, @@ -406,7 +406,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) if err != nil { return 0, err } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDef) idxScanNode := &plan.Node{ @@ -549,7 +549,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) if err != nil { return 0, err } - idxTag := builder.genNewTag() + idxTag := builder.genNewBindTag() builder.addNameByColRef(idxTag, idxTableDef) idxScanNodes[i][j] = &plan.Node{ @@ -624,7 +624,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) lockTargets := make([]*plan.LockTarget, 0) updateCtxList := make([]*plan.UpdateCtx, 0) - finalProjTag := builder.genNewTag() + finalProjTag := builder.genNewBindTag() finalColName2Idx := make(map[string]int32) var finalProjList []*plan.Expr @@ -846,7 +846,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) dmlNode := &plan.Node{ NodeType: plan.Node_MULTI_UPDATE, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, UpdateCtxList: updateCtxList, } @@ -854,7 +854,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) NodeType: plan.Node_LOCK_OP, Children: []int32{lastNodeID}, TableDef: dmlCtx.tableDefs[0], - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, LockTargets: lockTargets, }, bindCtx) reCheckifNeedLockWholeTable(builder) diff --git a/pkg/sql/plan/build_constraint_util.go b/pkg/sql/plan/build_constraint_util.go index 3961448d25c19..892f94dfba504 100644 --- a/pkg/sql/plan/build_constraint_util.go +++ b/pkg/sql/plan/build_constraint_util.go @@ -615,7 +615,7 @@ func initInsertStmt(builder *QueryBuilder, bindCtx *BindContext, stmt *tree.Inse // append ProjectNode projectCtx := NewBindContext(builder, bindCtx) - lastTag := builder.genNewTag() + lastTag := builder.genNewBindTag() info.rootId = builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, ProjectList: projectList, @@ -675,7 +675,7 @@ func initInsertStmt(builder *QueryBuilder, bindCtx *BindContext, stmt *tree.Inse NodeType: plan.Node_TABLE_SCAN, ObjRef: rightObjRef, TableDef: rightTableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, rightCtx) rightTag := builder.qry.Nodes[rightId].BindingTags[0] baseNodeTag := builder.qry.Nodes[info.rootId].BindingTags[0] @@ -802,7 +802,7 @@ func initInsertStmt(builder *QueryBuilder, bindCtx *BindContext, stmt *tree.Inse NodeType: plan.Node_PROJECT, ProjectList: info.projectList, Children: []int32{info.rootId}, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, bindCtx) bindCtx.results = info.projectList } @@ -1137,7 +1137,7 @@ func buildValueScan( var err error proc := builder.compCtx.GetProcess() - lastTag := builder.genNewTag() + lastTag := builder.genNewBindTag() colCount := len(updateColumns) rowsetData := &plan.RowsetData{ Cols: make([]*plan.ColData, colCount), @@ -1294,7 +1294,7 @@ func buildValueScan( return err } - lastTag = builder.genNewTag() + lastTag = builder.genNewBindTag() info.rootId = builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, ProjectList: projectList, diff --git a/pkg/sql/plan/build_ddl.go b/pkg/sql/plan/build_ddl.go index 39aa5e27b81f5..4ce680a077678 100644 --- a/pkg/sql/plan/build_ddl.go +++ b/pkg/sql/plan/build_ddl.go @@ -971,7 +971,7 @@ func buildCreateTable( Stats: nil, ObjRef: nil, TableDef: createTable.TableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, bindContext) err = builder.addBinding(nodeID, tree.AliasClause{}, bindContext) @@ -4870,7 +4870,7 @@ func constructAddedPartitionDefs( Stats: nil, ObjRef: nil, TableDef: tableDef, - BindingTags: []int32{partBuilder.genNewTag()}, + BindingTags: []int32{partBuilder.genNewBindTag()}, }, partBindCtx) if err := partBuilder.addBinding(nodeID, tree.AliasClause{}, partBindCtx); err != nil { return nil, err diff --git a/pkg/sql/plan/build_dml_util.go b/pkg/sql/plan/build_dml_util.go index efc03469e1ba5..57740750c2070 100644 --- a/pkg/sql/plan/build_dml_util.go +++ b/pkg/sql/plan/build_dml_util.go @@ -4447,7 +4447,7 @@ func buildPreInsertFullTextIndex(stmt *tree.Insert, ctx CompilerContext, builder }, Cols: ftcols, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: args, //Children: []int32{lastNodeId}, } @@ -4471,7 +4471,7 @@ func buildPreInsertFullTextIndex(stmt *tree.Insert, ctx CompilerContext, builder NodeType: plan.Node_APPLY, Children: []int32{lastNodeId, tableFuncId}, ApplyType: plan.Node_CROSSAPPLY, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, ProjectList: apply_project, }, bindCtx) diff --git a/pkg/sql/plan/current_account.go b/pkg/sql/plan/current_account.go index c68146583715c..2fbfe7c92310f 100644 --- a/pkg/sql/plan/current_account.go +++ b/pkg/sql/plan/current_account.go @@ -78,7 +78,7 @@ func (builder *QueryBuilder) buildCurrentAccount(tbl *tree.TableFunction, ctx *B }, }, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/distinct_agg.go b/pkg/sql/plan/distinct_agg.go index 0b2cda94d1107..d702142385599 100644 --- a/pkg/sql/plan/distinct_agg.go +++ b/pkg/sql/plan/distinct_agg.go @@ -47,8 +47,8 @@ func (builder *QueryBuilder) optimizeDistinctAgg(nodeID int32) { oldGroupBy := node.GroupBy toCount := aggFunc.Args[0] - newGroupTag := builder.genNewTag() - newAggregateTag := builder.genNewTag() + newGroupTag := builder.genNewBindTag() + newAggregateTag := builder.genNewBindTag() aggNodeID := builder.appendNode(&plan.Node{ NodeType: plan.Node_AGG, Children: []int32{node.Children[0]}, diff --git a/pkg/sql/plan/explain/explain_expr.go b/pkg/sql/plan/explain/explain_expr.go index 270759179bd9a..39fb745a1169b 100644 --- a/pkg/sql/plan/explain/explain_expr.go +++ b/pkg/sql/plan/explain/explain_expr.go @@ -40,7 +40,14 @@ func describeMessage(m *plan.MsgHeader, buf *bytes.Buffer) { } func describeColRef(col *plan.ColRef, buf *bytes.Buffer) { - if len(col.Name) > 0 && !strings.HasPrefix(col.Name, catalog.PrefixIndexTableName) { + if strings.HasPrefix(col.Name, catalog.PrefixIndexTableName) { + dotIdx := strings.Index(col.Name, ".") + if dotIdx > 0 { + buf.WriteString(col.Name[dotIdx+1:]) + } else { + buf.WriteString(col.Name) + } + } else if len(col.Name) > 0 { buf.WriteString(col.Name) } else { buf.WriteString("#[") diff --git a/pkg/sql/plan/flatten_subquery.go b/pkg/sql/plan/flatten_subquery.go index 97c8231681b39..b0976309d10c6 100644 --- a/pkg/sql/plan/flatten_subquery.go +++ b/pkg/sql/plan/flatten_subquery.go @@ -274,7 +274,7 @@ func (builder *QueryBuilder) flattenSubquery(nodeID int32, subquery *plan.Subque } func (builder *QueryBuilder) insertMarkJoin(left, right int32, joinPreds []*plan.Expr, outerPred *plan.Expr, negate bool, ctx *BindContext) (nodeID int32, markExpr *plan.Expr, err error) { - markTag := builder.genNewTag() + markTag := builder.genNewBindTag() for i, pred := range joinPreds { if !pred.Typ.NotNullable { diff --git a/pkg/sql/plan/fulltext.go b/pkg/sql/plan/fulltext.go index 227d4f3509e53..dfef79657accb 100644 --- a/pkg/sql/plan/fulltext.go +++ b/pkg/sql/plan/fulltext.go @@ -109,7 +109,7 @@ func (builder *QueryBuilder) buildFullTextIndexScan(tbl *tree.TableFunction, ctx }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } @@ -225,7 +225,7 @@ func (builder *QueryBuilder) buildFullTextIndexTokenize(tbl *tree.TableFunction, }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } diff --git a/pkg/sql/plan/function/func_binary.go b/pkg/sql/plan/function/func_binary.go index 73c4f1b17bfd2..dbe47e1156337 100644 --- a/pkg/sql/plan/function/func_binary.go +++ b/pkg/sql/plan/function/func_binary.go @@ -1910,8 +1910,9 @@ func addTimeToString(ivecs []*vector.Vector, result vector.FunctionResultWrapper time2Param := vector.GenerateFunctionStrParameter(ivecs[1]) rs := vector.MustFunctionResult[types.Datetime](result) - scale := int32(6) // Use max scale for string inputs - rs.TempSetType(types.New(types.T_datetime, 0, scale)) + scale := int32(6) // Use max scale for parsing inputs + // MySQL ADDTIME with string inputs returns DATETIME with scale 6 (microsecond precision) + rs.TempSetType(types.New(types.T_datetime, 0, 6)) for i := uint64(0); i < uint64(length); i++ { if selectList != nil && selectList.Contains(i) { @@ -2155,8 +2156,9 @@ func subTimeFromString(ivecs []*vector.Vector, result vector.FunctionResultWrapp time2Param := vector.GenerateFunctionStrParameter(ivecs[1]) rs := vector.MustFunctionResult[types.Datetime](result) - scale := int32(6) // Use max scale for string inputs - rs.TempSetType(types.New(types.T_datetime, 0, scale)) + scale := int32(6) // Use max scale for parsing inputs + // MySQL SUBTIME with string inputs returns DATETIME with scale 6 (microsecond precision) + rs.TempSetType(types.New(types.T_datetime, 0, 6)) for i := uint64(0); i < uint64(length); i++ { if selectList != nil && selectList.Contains(i) { diff --git a/pkg/sql/plan/function/func_binary_test.go b/pkg/sql/plan/function/func_binary_test.go index 6019b193bec19..a7ad31159b5b3 100644 --- a/pkg/sql/plan/function/func_binary_test.go +++ b/pkg/sql/plan/function/func_binary_test.go @@ -1983,6 +1983,93 @@ func TestTimeDiffInDateTime(t *testing.T) { } } +func initTimeDiffStringTestCase() []tcTemp { + // Test cases for TimeDiffString with string inputs (including colon format) + // expr1, expr2, expected result + testCases := []struct { + expr1, expr2 string + expected types.Time + desc string + }{ + { + expr1: "2000:01:01 00:00:00", + expr2: "2000:01:01 00:00:00.000001", + expected: types.Time(-1), // -1 microsecond + desc: "colon format microsecond diff", + }, + { + expr1: "2000:01:01 00:00:00", + expr2: "2000:01:01 00:00:00", + expected: types.Time(0), + desc: "colon format zero diff", + }, + { + expr1: "2000:01:01 00:00:01", + expr2: "2000:01:01 00:00:00", + expected: types.Time(1000000), // 1 second = 1000000 microseconds + desc: "colon format one second diff", + }, + { + expr1: "2000:01:01 01:00:00", + expr2: "2000:01:01 00:00:00", + expected: types.Time(3600000000), // 1 hour = 3600000000 microseconds + desc: "colon format one hour diff", + }, + { + expr1: "2000:01:01 00:00:00", + expr2: "2000:01:01 00:00:01", + expected: types.Time(-1000000), // -1 second + desc: "colon format negative one second", + }, + { + expr1: "2000-01-01 15:30:45", + expr2: "2000-01-01 10:20:30", + expected: types.Time(18615000000), // 5:10:15 = 18615000000 microseconds + desc: "dash format datetime diff", + }, + { + expr1: "15:30:45", + expr2: "10:20:30", + expected: types.Time(18615000000), // 5:10:15 + desc: "time format diff", + }, + } + + inputs1 := make([]string, len(testCases)) + inputs2 := make([]string, len(testCases)) + expected := make([]types.Time, len(testCases)) + nulls := make([]bool, len(testCases)) + + for i, tc := range testCases { + inputs1[i] = tc.expr1 + inputs2[i] = tc.expr2 + expected[i] = tc.expected + nulls[i] = false + } + + return []tcTemp{ + { + info: "test timediff string inputs with colon format", + inputs: []FunctionTestInput{ + NewFunctionTestInput(types.T_varchar.ToType(), inputs1, nulls), + NewFunctionTestInput(types.T_varchar.ToType(), inputs2, nulls), + }, + expect: NewFunctionTestResult(types.T_time.ToType(), false, expected, nulls), + }, + } +} + +func TestTimeDiffString(t *testing.T) { + testCases := initTimeDiffStringTestCase() + + proc := testutil.NewProcess(t) + for _, tc := range testCases { + fcTC := NewFunctionTestCase(proc, tc.inputs, tc.expect, TimeDiffString) + s, info := fcTC.Run() + require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info)) + } +} + // TIMESTAMPDIFF func initTimestampDiffTestCase() []tcTemp { diff --git a/pkg/sql/plan/function/type_check.go b/pkg/sql/plan/function/type_check.go index f41451eb8cb09..657613e07d4ab 100644 --- a/pkg/sql/plan/function/type_check.go +++ b/pkg/sql/plan/function/type_check.go @@ -1715,7 +1715,7 @@ func initFixed3() { {toType: types.T_int8, preferLevel: 2}, {toType: types.T_int16, preferLevel: 2}, {toType: types.T_int32, preferLevel: 2}, - {toType: types.T_int64, preferLevel: 2}, + {toType: types.T_int64, preferLevel: 1}, {toType: types.T_uint8, preferLevel: 2}, {toType: types.T_uint16, preferLevel: 2}, {toType: types.T_uint64, preferLevel: 1}, diff --git a/pkg/sql/plan/generate_series.go b/pkg/sql/plan/generate_series.go index 071f19be051d1..4f408d722f206 100644 --- a/pkg/sql/plan/generate_series.go +++ b/pkg/sql/plan/generate_series.go @@ -68,7 +68,7 @@ func (builder *QueryBuilder) buildGenerateSeries(tbl *tree.TableFunction, ctx *B }, Cols: generateSeriesColDefs[retsIdx], }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } @@ -97,7 +97,7 @@ func (builder *QueryBuilder) buildGenerateRandomInt64(tbl *tree.TableFunction, c }, }, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } @@ -127,7 +127,7 @@ func (builder *QueryBuilder) buildGenerateRandomFloat64(tbl *tree.TableFunction, }, }, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/hnsw.go b/pkg/sql/plan/hnsw.go index 1e29159a71309..2948153bdb1f6 100644 --- a/pkg/sql/plan/hnsw.go +++ b/pkg/sql/plan/hnsw.go @@ -92,7 +92,7 @@ func (builder *QueryBuilder) buildHnswCreate(tbl *tree.TableFunction, ctx *BindC }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } @@ -126,7 +126,7 @@ func (builder *QueryBuilder) buildHnswSearch(tbl *tree.TableFunction, ctx *BindC }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } diff --git a/pkg/sql/plan/ivfflat.go b/pkg/sql/plan/ivfflat.go index eeeb1dbd50d0c..f9f5d16d68834 100644 --- a/pkg/sql/plan/ivfflat.go +++ b/pkg/sql/plan/ivfflat.go @@ -89,7 +89,7 @@ func (builder *QueryBuilder) buildIvfCreate(tbl *tree.TableFunction, ctx *BindCo }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } @@ -123,7 +123,7 @@ func (builder *QueryBuilder) buildIvfSearch(tbl *tree.TableFunction, ctx *BindCo }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } diff --git a/pkg/sql/plan/meta_scan.go b/pkg/sql/plan/meta_scan.go index cead65cf00108..d0cbe8a01ee37 100644 --- a/pkg/sql/plan/meta_scan.go +++ b/pkg/sql/plan/meta_scan.go @@ -150,7 +150,7 @@ func (builder *QueryBuilder) buildMetaScan(tbl *tree.TableFunction, ctx *BindCon }, Cols: MetaColDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/metadata_scan.go b/pkg/sql/plan/metadata_scan.go index 21ad14ece4020..cdccabb6eab81 100644 --- a/pkg/sql/plan/metadata_scan.go +++ b/pkg/sql/plan/metadata_scan.go @@ -98,7 +98,7 @@ func (builder *QueryBuilder) buildMetadataScan(tbl *tree.TableFunction, ctx *Bin }, Cols: MetadataScanColDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/opt_misc.go b/pkg/sql/plan/opt_misc.go index 997e583e1304a..7c97fe1c71c5c 100644 --- a/pkg/sql/plan/opt_misc.go +++ b/pkg/sql/plan/opt_misc.go @@ -787,7 +787,7 @@ func (builder *QueryBuilder) rewriteDistinctToAGG(nodeID int32) { node.NodeType = plan.Node_AGG node.GroupBy = project.ProjectList node.BindingTags = project.BindingTags - node.BindingTags = append(node.BindingTags, builder.genNewTag()) + node.BindingTags = append(node.BindingTags, builder.genNewBindTag()) node.Children[0] = project.Children[0] node.SpillMem = builder.aggSpillMem } diff --git a/pkg/sql/plan/parse_jsonl_tvf.go b/pkg/sql/plan/parse_jsonl_tvf.go index db54958eb2a8c..b773943d9f8e2 100644 --- a/pkg/sql/plan/parse_jsonl_tvf.go +++ b/pkg/sql/plan/parse_jsonl_tvf.go @@ -197,7 +197,7 @@ func (builder *QueryBuilder) buildParseJsonl(tvfName string, tbl *tree.TableFunc }, Cols: cols, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } diff --git a/pkg/sql/plan/partition_binder_test.go b/pkg/sql/plan/partition_binder_test.go index d035eadb89bdb..52e95466a55dc 100644 --- a/pkg/sql/plan/partition_binder_test.go +++ b/pkg/sql/plan/partition_binder_test.go @@ -254,7 +254,7 @@ func newTestPartitionBinder() *PartitionBinder { Stats: nil, ObjRef: nil, TableDef: newTestTableDef(1, []string{"a"}, []types.T{types.T_int32}), - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, }, bindContext) err := builder.addBinding(nodeID, tree.AliasClause{}, bindContext) diff --git a/pkg/sql/plan/plugin.go b/pkg/sql/plan/plugin.go index 28d644c6535db..79562edbc1525 100644 --- a/pkg/sql/plan/plugin.go +++ b/pkg/sql/plan/plugin.go @@ -57,7 +57,7 @@ func (builder *QueryBuilder) buildPluginExec(tbl *tree.TableFunction, ctx *BindC }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, TblFuncExprList: exprs, Children: children, } diff --git a/pkg/sql/plan/processlist.go b/pkg/sql/plan/processlist.go index d960dcb05f9b9..f0a0f23c15ac0 100644 --- a/pkg/sql/plan/processlist.go +++ b/pkg/sql/plan/processlist.go @@ -60,7 +60,7 @@ func (builder *QueryBuilder) buildProcesslist(tbl *tree.TableFunction, ctx *Bind }, Cols: sessionsColDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/pushdown.go b/pkg/sql/plan/pushdown.go index 812de380f61f4..7842be3b56ae5 100644 --- a/pkg/sql/plan/pushdown.go +++ b/pkg/sql/plan/pushdown.go @@ -623,7 +623,7 @@ func (builder *QueryBuilder) pushdownVectorIndexTopToTableScan(nodeID int32) { } scanNode := builder.qry.Nodes[projNode.Children[0]] - if scanNode.NodeType != plan.Node_TABLE_SCAN || scanNode.Offset != nil { + if scanNode.NodeType != plan.Node_TABLE_SCAN || scanNode.Offset != nil || scanNode.BlockOrderBy != nil { return } limitVal := node.Limit.GetLit().GetU64Val() @@ -635,7 +635,7 @@ func (builder *QueryBuilder) pushdownVectorIndexTopToTableScan(nodeID int32) { } scanNode.BlockOrderBy = append(scanNode.BlockOrderBy, &plan.OrderBySpec{ - Expr: DeepCopyExpr(orderFunc), + Expr: orderFunc, Collation: node.OrderBy[0].Collation, Flag: node.OrderBy[0].Flag, }) @@ -644,5 +644,19 @@ func (builder *QueryBuilder) pushdownVectorIndexTopToTableScan(nodeID int32) { // if there is a limit, outcnt is limit number scanNode.Stats.Outcnt = float64(scanNode.Stats.BlockNum) * float64(limitVal) scanNode.Stats.Cost = float64(scanNode.Stats.BlockNum * objectio.BlockMaxRows) + + orderFuncTag := builder.genNewBindTag() + scanNode.BindingTags = append(scanNode.BindingTags, orderFuncTag) + projNode.ProjectList[orderCol.ColPos] = &plan.Expr{ + Typ: orderFunc.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: orderFuncTag, + ColPos: 0, + }, + }, + } + + builder.nameByColRef[[2]int32{orderFuncTag, 0}] = "__dist_func__" } } diff --git a/pkg/sql/plan/pushdown_test.go b/pkg/sql/plan/pushdown_test.go index 59f59262e0708..2fd69420c6ced 100644 --- a/pkg/sql/plan/pushdown_test.go +++ b/pkg/sql/plan/pushdown_test.go @@ -28,8 +28,8 @@ func setupLeftJoinBase(t *testing.T) (*MockCompilerContext, *QueryBuilder, *plan ctx := NewMockCompilerContext(true) builder := NewQueryBuilder(plan.Query_SELECT, ctx, false, false) - leftTag := builder.genNewTag() - rightTag := builder.genNewTag() + leftTag := builder.genNewBindTag() + rightTag := builder.genNewBindTag() intType := Type{Id: int32(types.T_int64)} diff --git a/pkg/sql/plan/query_builder.go b/pkg/sql/plan/query_builder.go index 2b2a60908d8b5..cad5eda07d12c 100644 --- a/pkg/sql/plan/query_builder.go +++ b/pkg/sql/plan/query_builder.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "fmt" + "maps" "slices" "strconv" "strings" @@ -83,7 +84,7 @@ func NewQueryBuilder(queryType plan.Query_StatementType, ctx CompilerContext, is compCtx: ctx, ctxByNode: []*BindContext{}, nameByColRef: make(map[[2]int32]string), - nextTag: 0, + nextBindTag: 0, mysqlCompatible: mysqlCompatible, aggSpillMem: aggSpillMem, tag2Table: make(map[int32]*TableDef), @@ -216,9 +217,9 @@ func (builder *QueryBuilder) buildRemapErrorMessage( func (builder *QueryBuilder) remapSingleColRef(col *plan.ColRef, colMap map[[2]int32][2]int32, remapInfo *RemapInfo) error { mapID := [2]int32{col.RelPos, col.ColPos} - if ids, ok := colMap[mapID]; ok { - col.RelPos = ids[0] - col.ColPos = ids[1] + if mappedCol, ok := colMap[mapID]; ok { + col.RelPos = mappedCol[0] + col.ColPos = mappedCol[1] col.Name = builder.nameByColRef[mapID] } else { colName := "" @@ -286,6 +287,7 @@ func (m *ColRefRemapping) String() string { return sb.String() } +// XXX: It's dangerous to copy binding/message tags if both old and new nodes are eventually used. func (builder *QueryBuilder) copyNode(ctx *BindContext, nodeId int32) int32 { node := builder.qry.Nodes[nodeId] newNode := DeepCopyNode(node) @@ -457,11 +459,11 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt localToGlobal: make([][2]int32, 0), } - tag := node.BindingTags[0] + colTag := node.BindingTags[0] newTableDef := DeepCopyTableDef(node.TableDef, false) for i, col := range node.TableDef.Cols { - globalRef := [2]int32{tag, int32(i)} + globalRef := [2]int32{colTag, int32(i)} if colRefCnt[globalRef] == 0 { continue } @@ -470,17 +472,20 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt newTableDef.Cols = append(newTableDef.Cols, DeepCopyColDef(col)) } + if len(node.BindingTags) > 1 { + orderFuncTag := node.BindingTags[1] + internalRemapping.addColRef([2]int32{orderFuncTag, 0}) + + } + if len(newTableDef.Cols) == 0 { - internalRemapping.addColRef([2]int32{tag, 0}) + internalRemapping.addColRef([2]int32{colTag, 0}) newTableDef.Cols = append(newTableDef.Cols, DeepCopyColDef(node.TableDef.Cols[0])) } node.TableDef = newTableDef - colMap := make(map[[2]int32][2]int32) - for global, local := range internalRemapping.globalToLocal { - colMap[global] = local - } + colMap := maps.Clone(internalRemapping.globalToLocal) for localIdx, global := range internalRemapping.localToGlobal { colMap[[2]int32{0, int32(localIdx)}] = global } @@ -561,36 +566,39 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt }) } - if len(node.ProjectList) == 0 { - if len(node.TableDef.Cols) == 0 { - globalRef := [2]int32{tag, 0} - remapping.addColRef(globalRef) + if len(node.BindingTags) > 1 { + orderFuncTag := node.BindingTags[1] + + if colRefCnt[[2]int32{orderFuncTag, 0}] > 0 { + remapping.addColRef([2]int32{orderFuncTag, 0}) node.ProjectList = append(node.ProjectList, &plan.Expr{ - Typ: node.TableDef.Cols[0].Typ, - Expr: &plan.Expr_Col{ - Col: &plan.ColRef{ - RelPos: 0, - ColPos: 0, - Name: builder.nameByColRef[globalRef], - }, - }, - }) - } else { - remapping.addColRef(internalRemapping.localToGlobal[0]) - node.ProjectList = append(node.ProjectList, &plan.Expr{ - Typ: node.TableDef.Cols[0].Typ, + Typ: node.BlockOrderBy[0].Expr.Typ, Expr: &plan.Expr_Col{ Col: &plan.ColRef{ RelPos: 0, - ColPos: 0, - Name: builder.nameByColRef[internalRemapping.localToGlobal[0]], + ColPos: int32(len(node.TableDef.Cols)), + Name: "__dist_func__", }, }, }) } } + if len(node.ProjectList) == 0 && len(node.TableDef.Cols) > 0 { + remapping.addColRef(internalRemapping.localToGlobal[0]) + node.ProjectList = append(node.ProjectList, &plan.Expr{ + Typ: node.TableDef.Cols[0].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: 0, + ColPos: 0, + Name: builder.nameByColRef[internalRemapping.localToGlobal[0]], + }, + }, + }) + } + case plan.Node_INTERSECT, plan.Node_INTERSECT_ALL, plan.Node_UNION, plan.Node_UNION_ALL, plan.Node_MINUS, plan.Node_MINUS_ALL: @@ -618,15 +626,10 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt } } - internalMap := make(map[[2]int32][2]int32) - leftRemapping, err := builder.remapAllColRefs(leftID, step, colRefCnt, colRefBool, sinkColRef) if err != nil { return nil, err } - for k, v := range leftRemapping.globalToLocal { - internalMap[k] = v - } _, err = builder.remapAllColRefs(rightID, step, colRefCnt, colRefBool, sinkColRef) if err != nil { @@ -637,7 +640,7 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt for idx, expr := range node.ProjectList { increaseRefCnt(expr, -1, colRefCnt) remapInfo.srcExprIdx = idx - err := builder.remapColRefForExpr(expr, internalMap, &remapInfo) + err := builder.remapColRefForExpr(expr, leftRemapping.globalToLocal, &remapInfo) if err != nil { return nil, err } @@ -658,17 +661,13 @@ func (builder *QueryBuilder) remapAllColRefs(nodeID int32, step int32, colRefCnt } } - internalMap := make(map[[2]int32][2]int32) - leftID := node.Children[0] leftRemapping, err := builder.remapAllColRefs(leftID, step, colRefCnt, colRefBool, sinkColRef) if err != nil { return nil, err } - for k, v := range leftRemapping.globalToLocal { - internalMap[k] = v - } + internalMap := maps.Clone(leftRemapping.globalToLocal) rightID := node.Children[1] rightRemapping, err := builder.remapAllColRefs(rightID, step, colRefCnt, colRefBool, sinkColRef) @@ -2083,6 +2082,7 @@ func (builder *QueryBuilder) createQuery() (*Query, error) { builder.generateRuntimeFilters(rootID) builder.pushdownVectorIndexTopToTableScan(rootID) + builder.removeSimpleProjections(rootID, plan.Node_UNKNOWN, false, colRefCnt) ReCalcNodeStats(rootID, builder, true, false, false) builder.forceJoinOnOneCN(rootID, false) // after this ,never call ReCalcNodeStats again !!! @@ -2326,7 +2326,7 @@ func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree. utIdx := i - 1 lastNewNodeIdx := len(newNodes) - 1 if unionTypes[utIdx] == plan.Node_INTERSECT || unionTypes[utIdx] == plan.Node_INTERSECT_ALL { - lastTag = builder.genNewTag() + lastTag = builder.genNewBindTag() leftNodeTag := builder.qry.Nodes[newNodes[lastNewNodeIdx]].BindingTags[0] newNodeID := builder.appendNode(&plan.Node{ NodeType: unionTypes[utIdx], @@ -2345,7 +2345,7 @@ func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree. lastNodeID := newNodes[0] for i := 1; i < len(newNodes); i++ { utIdx := i - 1 - lastTag = builder.genNewTag() + lastTag = builder.genNewBindTag() leftNodeTag := builder.qry.Nodes[lastNodeID].BindingTags[0] lastNodeID = builder.appendNode(&plan.Node{ @@ -2357,9 +2357,9 @@ func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree. } // set ctx base on selects[0] and it's ctx - ctx.groupTag = builder.genNewTag() - ctx.aggregateTag = builder.genNewTag() - ctx.projectTag = builder.genNewTag() + ctx.groupTag = builder.genNewBindTag() + ctx.aggregateTag = builder.genNewBindTag() + ctx.projectTag = builder.genNewBindTag() for i, v := range ctx.headings { ctx.aliasMap[v] = &aliasItem{ idx: int32(i), @@ -2452,6 +2452,17 @@ func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree. } } } + + // Parse RankOption if ByRank is true + if astLimit.ByRank && astLimit.Option != nil && len(astLimit.Option) > 0 { + rankOption, err := parseRankOption(astLimit.Option, builder.GetContext()) + if err != nil { + return 0, err + } + if rankOption != nil && rankOption.Mode != "" { + node.RankOption = rankOption + } + } } // append result PROJECT node @@ -2467,7 +2478,7 @@ func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree. }, }) } - ctx.resultTag = builder.genNewTag() + ctx.resultTag = builder.genNewBindTag() lastNodeID = builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, @@ -2582,7 +2593,7 @@ func (builder *QueryBuilder) bindRecursiveCte( cteBindType: CteBindTypeInitStmt, cte: cteRef, recScanNodeId: -1}) - initCtx.sinkTag = builder.genNewTag() + initCtx.sinkTag = builder.genNewBindTag() initLastNodeID, err1 := builder.bindSelect(&tree.Select{Select: *left}, initCtx, false) if err1 != nil { err = err1 @@ -2871,13 +2882,13 @@ func (builder *QueryBuilder) bindSelect(stmt *tree.Select, ctx *BindContext, isR astLimit := stmt.Limit astTimeWindow := stmt.TimeWindow - ctx.groupTag = builder.genNewTag() - ctx.aggregateTag = builder.genNewTag() - ctx.projectTag = builder.genNewTag() - ctx.windowTag = builder.genNewTag() - ctx.sampleTag = builder.genNewTag() + ctx.groupTag = builder.genNewBindTag() + ctx.aggregateTag = builder.genNewBindTag() + ctx.projectTag = builder.genNewBindTag() + ctx.windowTag = builder.genNewBindTag() + ctx.sampleTag = builder.genNewBindTag() if astTimeWindow != nil { - ctx.timeTag = builder.genNewTag() // ctx.timeTag > 0 + ctx.timeTag = builder.genNewBindTag() // ctx.timeTag > 0 if astTimeWindow.Sliding != nil { ctx.sliding = true } @@ -3047,8 +3058,9 @@ func (builder *QueryBuilder) bindSelect(stmt *tree.Select, ctx *BindContext, isR // bind limit/offset clause var boundOffsetExpr *Expr var boundCountExpr *Expr + var rankOption *plan.RankOption if astLimit != nil { - if boundOffsetExpr, boundCountExpr, err = builder.bindLimit(ctx, astLimit); err != nil { + if boundOffsetExpr, boundCountExpr, rankOption, err = builder.bindLimit(ctx, astLimit); err != nil { return } @@ -3152,11 +3164,14 @@ func (builder *QueryBuilder) bindSelect(stmt *tree.Select, ctx *BindContext, isR } // attach limit/offset to last node - if boundCountExpr != nil || boundOffsetExpr != nil { + if boundCountExpr != nil || boundOffsetExpr != nil || rankOption != nil { node := builder.qry.Nodes[nodeID] node.Limit = boundCountExpr node.Offset = boundOffsetExpr + if rankOption != nil { + node.RankOption = rankOption + } } // append result PROJECT node @@ -3231,8 +3246,7 @@ func (builder *QueryBuilder) bindSelectClause( return } - if builder.isForUpdate { - tableDef := builder.qry.Nodes[nodeID].GetTableDef() + if tableDef := builder.qry.Nodes[nodeID].GetTableDef(); tableDef != nil && builder.isForUpdate { pkPos, pkTyp := getPkPos(tableDef, false) lastTag := builder.qry.Nodes[nodeID].BindingTags[0] lockTarget := &plan.LockTarget{ @@ -3259,7 +3273,7 @@ func (builder *QueryBuilder) bindSelectClause( Children: []int32{nodeID}, TableDef: tableDef, LockTargets: []*plan.LockTarget{lockTarget}, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, } if astLimit == nil { @@ -3330,7 +3344,8 @@ func (builder *QueryBuilder) bindWhere( clause *tree.Where, nodeID int32, ) (newNodeID int32, boundFilterList []*plan.Expr, notCacheable bool, err error) { - whereList, err := splitAndBindCondition(clause.Expr, NoAlias, ctx) + convertedExpr := builder.convertAccountToAccountIdIfNeeded(ctx, clause.Expr) + whereList, err := splitAndBindCondition(convertedExpr, NoAlias, ctx) if err != nil { return } @@ -3355,6 +3370,100 @@ func (builder *QueryBuilder) bindWhere( return } +// isAccountConvertibleTable checks if a binding refers to statement_info or metric table. +// It checks both binding.table (which might be an alias) and the actual table name from node.TableDef.Name. +func isAccountConvertibleTable(binding *Binding, builder *QueryBuilder, dbName, tableName string) bool { + if binding == nil { + return false + } + if binding.db != dbName { + return false + } + // Check if binding.table matches (no alias case) + if binding.table == tableName { + return true + } + // Check the actual table name from node.TableDef.Name (alias case) + if int(binding.nodeId) < len(builder.qry.Nodes) { + node := builder.qry.Nodes[binding.nodeId] + if node != nil && node.TableDef != nil && node.TableDef.Name == tableName { + return true + } + } + return false +} + +// buildAccountConvertibleTableAliasMap builds a map of table aliases/names that refer to statement_info or metric table. +// The key is the table alias/name used in the query, the value indicates if it refers to statement_info or metric. +func (builder *QueryBuilder) buildAccountConvertibleTableAliasMap(ctx *BindContext) map[string]bool { + tableAliasMap := make(map[string]bool) + for tableName, binding := range ctx.bindingByTable { + // Check for statement_info table in system database + if isAccountConvertibleTable(binding, builder, catalog.MO_SYSTEM, catalog.MO_STATEMENT) { + tableAliasMap[tableName] = true + tableAliasMap[catalog.MO_STATEMENT] = true + } + // Check for metric table in system_metrics database + if isAccountConvertibleTable(binding, builder, catalog.MO_SYSTEM_METRICS, catalog.MO_METRIC) { + tableAliasMap[tableName] = true + tableAliasMap[catalog.MO_METRIC] = true + } + } + return tableAliasMap +} + +// hasStatementInfoOrMetricTable checks if the query involves statement_info or metric table +// It checks both binding.table (which might be an alias) and the actual table name from node.TableDef.Name +func hasStatementInfoOrMetricTable(ctx *BindContext, builder *QueryBuilder) bool { + for _, binding := range ctx.bindingByTable { + if isAccountConvertibleTable(binding, builder, catalog.MO_SYSTEM, catalog.MO_STATEMENT) { + return true + } + if isAccountConvertibleTable(binding, builder, catalog.MO_SYSTEM_METRICS, catalog.MO_METRIC) { + return true + } + } + return false +} + +// convertAccountToAccountIdIfNeeded converts account to account_id if the query involves statement_info or metric table. +// This conversion is primarily designed for compatibility with mo-cloud's business-level usage of the account field. +// When mo-cloud queries statement_info or metric using account names (e.g., WHERE account = 'sys'), this function automatically +// converts the account filter to account_id filter by looking up the corresponding account_id from mo_catalog.mo_account. +// This provides a more user-friendly interface while maintaining compatibility with the underlying account_id-based storage. +func (builder *QueryBuilder) convertAccountToAccountIdIfNeeded(ctx *BindContext, expr tree.Expr) tree.Expr { + if !hasStatementInfoOrMetricTable(ctx, builder) { + return expr + } + + currentAccountID, err := builder.compCtx.GetAccountId() + if err != nil { + return expr + } + + isSystemAccount := currentAccountID == catalog.System_Account + currentAccountName := "sys" + if !isSystemAccount { + currentAccountName = builder.compCtx.GetAccountName() + } + + tableAliasMap := builder.buildAccountConvertibleTableAliasMap(ctx) + // Create account_id resolver function that queries account_id from mo_catalog.mo_account + accountIdResolver := func(accountName string) (uint32, error) { + accountIds, err := builder.compCtx.ResolveAccountIds([]string{accountName}) + if err != nil { + return 0, err + } + if len(accountIds) == 0 { + // Account not found, return 0 to indicate not found + return 0, nil + } + return accountIds[0], nil + } + convertedExpr, _ := util.ConvertAccountToAccountIdWithTableCheck(expr, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + return convertedExpr +} + func (builder *QueryBuilder) bindGroupBy( ctx *BindContext, clause *tree.GroupByClause, @@ -3641,7 +3750,7 @@ func (builder *QueryBuilder) bindOrderBy( func (builder *QueryBuilder) bindLimit( ctx *BindContext, astLimit *tree.Limit, -) (boundOffsetExpr, boundCountExpr *Expr, err error) { +) (boundOffsetExpr, boundCountExpr *Expr, rankOption *plan.RankOption, err error) { limitBinder := NewLimitBinder(builder, ctx) if astLimit.Offset != nil { if boundOffsetExpr, err = limitBinder.BindExpr(astLimit.Offset, 0, true); err != nil { @@ -3659,6 +3768,31 @@ func (builder *QueryBuilder) bindLimit( } } } + + // Parse RankOption if ByRank is true + if astLimit.ByRank && astLimit.Option != nil && len(astLimit.Option) > 0 { + rankOption = &plan.RankOption{} + + // Helper function to get value from map case-insensitively + getOptionValue := func(key string) (string, bool) { + keyLower := strings.ToLower(key) + for k, v := range astLimit.Option { + if strings.ToLower(k) == keyLower { + return v, true + } + } + return "", false + } + + if mode, ok := getOptionValue("mode"); ok { + modeLower := strings.ToLower(strings.TrimSpace(mode)) + if modeLower != "pre" && modeLower != "post" { + return nil, nil, nil, moerr.NewInvalidInputf(builder.GetContext(), "mode must be 'pre' or 'post', got '%s'", mode) + } + rankOption.Mode = modeLower + } + } + return } @@ -3721,7 +3855,7 @@ func (builder *QueryBuilder) bindValues( NodeType: plan.Node_VALUE_SCAN, RowsetData: rowSetData, TableDef: tableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Uuid: nodeUUID[:], NotCacheable: true, }, ctx) @@ -4005,7 +4139,7 @@ func (builder *QueryBuilder) appendResultProjectionNode(ctx *BindContext, nodeID }) } - ctx.resultTag = builder.genNewTag() + ctx.resultTag = builder.genNewBindTag() return builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, ProjectList: ctx.results, @@ -4642,7 +4776,7 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p Stats: nil, ObjRef: &plan.ObjectRef{DbName: schema, SchemaName: table}, TableDef: tableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, ScanSnapshot: snapshot, }, ctx) @@ -4707,7 +4841,7 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p ObjRef: obj, TableDef: tableDef, ExternScan: externScan, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, ScanSnapshot: snapshot, }, ctx) @@ -4768,7 +4902,6 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p if err != nil { return 0, err } - acctName := builder.compCtx.GetUserName() if sub := builder.compCtx.GetQueryingSubscription(); sub != nil { currentAccountID = uint32(sub.AccountId) builder.qry.Nodes[nodeID].NotCacheable = true @@ -4784,7 +4917,7 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p } builder.qry.Nodes[nodeID].FilterList = accountFilterExprs } else if dbName == catalog.MO_SYSTEM_METRICS && (tableName == catalog.MO_METRIC || tableName == catalog.MO_SQL_STMT_CU) { - motablesFilter := util.BuildSysMetricFilter(acctName) + motablesFilter := util.BuildSysMetricFilter(uint64(currentAccountID)) ctx.binder = NewWhereBinder(builder, ctx) accountFilterExprs, err := splitAndBindCondition(motablesFilter, NoAlias, ctx) if err != nil { @@ -4792,7 +4925,7 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p } builder.qry.Nodes[nodeID].FilterList = accountFilterExprs } else if dbName == catalog.MO_SYSTEM && tableName == catalog.MO_STATEMENT { - motablesFilter := util.BuildSysStatementInfoFilter(acctName) + motablesFilter := util.BuildSysStatementInfoFilter(uint64(currentAccountID)) ctx.binder = NewWhereBinder(builder, ctx) accountFilterExprs, err := splitAndBindCondition(motablesFilter, NoAlias, ctx) if err != nil { @@ -4845,9 +4978,9 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p return } -func (builder *QueryBuilder) genNewTag() int32 { - builder.nextTag++ - return builder.nextTag +func (builder *QueryBuilder) genNewBindTag() int32 { + builder.nextBindTag++ + return builder.nextBindTag } func (builder *QueryBuilder) genNewMsgTag() (ret int32) { @@ -5233,6 +5366,43 @@ func (builder *QueryBuilder) GetContext() context.Context { return builder.compCtx.GetContext() } +// parseRankOption parses rank options from a map of option key-value pairs. +// It extracts the "mode" option case-insensitively and validates it. +// Returns a RankOption with the parsed mode if valid, or nil if no mode is specified. +// Returns an error if the mode value is invalid (must be "pre" or "post"). +func parseRankOption(options map[string]string, ctx context.Context) (*plan.RankOption, error) { + if len(options) == 0 { + return nil, nil + } + + rankOption := &plan.RankOption{} + + // Helper function to get value from map case-insensitively + getOptionValue := func(key string) (string, bool) { + keyLower := strings.ToLower(key) + for k, v := range options { + if strings.ToLower(k) == keyLower { + return v, true + } + } + return "", false + } + + if mode, ok := getOptionValue("mode"); ok { + modeLower := strings.ToLower(strings.TrimSpace(mode)) + if modeLower != "pre" && modeLower != "post" { + return nil, moerr.NewInvalidInputf(ctx, "mode must be 'pre' or 'post', got '%s'", mode) + } + rankOption.Mode = modeLower + } + + if rankOption.Mode == "" { + return nil, nil + } + + return rankOption, nil +} + func (builder *QueryBuilder) checkExprCanPushdown(expr *Expr, node *Node) bool { switch node.NodeType { case plan.Node_FUNCTION_SCAN: diff --git a/pkg/sql/plan/query_builder_test.go b/pkg/sql/plan/query_builder_test.go index aefad93fa0054..476c6626abc13 100644 --- a/pkg/sql/plan/query_builder_test.go +++ b/pkg/sql/plan/query_builder_test.go @@ -380,7 +380,7 @@ func TestQueryBuilder_bindLimit(t *testing.T) { stmts, _ := parsers.Parse(context.TODO(), dialect.MYSQL, "select a from select_test.bind_select limit 1, 5", 1) astLimit := stmts[0].(*tree.Select).Limit - boundOffsetExpr, boundCountExpr, err := builder.bindLimit(bindCtx, astLimit) + boundOffsetExpr, boundCountExpr, _, err := builder.bindLimit(bindCtx, astLimit) require.NoError(t, err) require.Equal(t, int32(types.T_uint64), boundOffsetExpr.Typ.Id) offsetExpr, ok := boundOffsetExpr.Expr.(*plan.Expr_Lit) @@ -807,3 +807,117 @@ func TestQueryBuilder_buildRemapErrorMessage(t *testing.T) { }) } } + +func TestParseRankOption(t *testing.T) { + ctx := context.TODO() + + t.Run("valid mode pre", func(t *testing.T) { + options := map[string]string{ + "mode": "pre", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "pre", rankOption.Mode) + }) + + t.Run("valid mode post", func(t *testing.T) { + options := map[string]string{ + "mode": "post", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "post", rankOption.Mode) + }) + + t.Run("valid mode case insensitive", func(t *testing.T) { + options := map[string]string{ + "MODE": "PRE", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "pre", rankOption.Mode) + }) + + t.Run("valid mode with whitespace", func(t *testing.T) { + options := map[string]string{ + "mode": " post ", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "post", rankOption.Mode) + }) + + t.Run("invalid mode value", func(t *testing.T) { + options := map[string]string{ + "mode": "invalid", + } + rankOption, err := parseRankOption(options, ctx) + require.Error(t, err) + require.Nil(t, rankOption) + require.Contains(t, err.Error(), "mode must be 'pre' or 'post'") + require.Contains(t, err.Error(), "invalid") + }) + + t.Run("empty options map", func(t *testing.T) { + options := map[string]string{} + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.Nil(t, rankOption) + }) + + t.Run("nil options map", func(t *testing.T) { + var options map[string]string = nil + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.Nil(t, rankOption) + }) + + t.Run("options without mode", func(t *testing.T) { + options := map[string]string{ + "fudge_factor": "3.0", + "nprobe": "10", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.Nil(t, rankOption) + }) + + t.Run("options with mode and other options", func(t *testing.T) { + options := map[string]string{ + "mode": "pre", + "fudge_factor": "3.0", + "nprobe": "10", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "pre", rankOption.Mode) + }) + + t.Run("case insensitive key matching", func(t *testing.T) { + options := map[string]string{ + "MoDe": "post", + } + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + require.Equal(t, "post", rankOption.Mode) + }) + + t.Run("multiple mode keys with different cases", func(t *testing.T) { + options := map[string]string{ + "mode": "pre", + "MODE": "post", + } + // Should match the first one found (order is not guaranteed in map iteration) + rankOption, err := parseRankOption(options, ctx) + require.NoError(t, err) + require.NotNil(t, rankOption) + // The actual value depends on map iteration order, but should be either "pre" or "post" + require.Contains(t, []string{"pre", "post"}, rankOption.Mode) + }) +} diff --git a/pkg/sql/plan/result_scan.go b/pkg/sql/plan/result_scan.go index 7189cb4a5aa68..bbd602dae8ccb 100644 --- a/pkg/sql/plan/result_scan.go +++ b/pkg/sql/plan/result_scan.go @@ -129,7 +129,7 @@ func (builder *QueryBuilder) buildResultScan(tbl *tree.TableFunction, ctx *BindC }, Stats: &plan.Stats{}, TableDef: tableDef, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, NotCacheable: true, } nodeID := builder.appendNode(node, ctx) diff --git a/pkg/sql/plan/stage.go b/pkg/sql/plan/stage.go index e180796d1516e..e06425dd724b3 100644 --- a/pkg/sql/plan/stage.go +++ b/pkg/sql/plan/stage.go @@ -46,7 +46,7 @@ func (builder *QueryBuilder) buildStageList(tbl *tree.TableFunction, ctx *BindCo }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/system_view.go b/pkg/sql/plan/system_view.go index 3f9ef73cbe2c4..1736fa212a087 100644 --- a/pkg/sql/plan/system_view.go +++ b/pkg/sql/plan/system_view.go @@ -97,7 +97,7 @@ func (builder *QueryBuilder) buildMoLocks(tbl *tree.TableFunction, ctx *BindCont }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } @@ -167,7 +167,7 @@ func (builder *QueryBuilder) buildMoConfigurations(tbl *tree.TableFunction, ctx }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } @@ -269,7 +269,7 @@ func (builder *QueryBuilder) buildMoTransactions(tbl *tree.TableFunction, ctx *B }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } @@ -339,7 +339,7 @@ func (builder *QueryBuilder) buildMoCache(tbl *tree.TableFunction, ctx *BindCont }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/plan/types.go b/pkg/sql/plan/types.go index eb37429738c0d..d7e6a2a84fb44 100644 --- a/pkg/sql/plan/types.go +++ b/pkg/sql/plan/types.go @@ -173,8 +173,8 @@ type QueryBuilder struct { tag2Table map[int32]*TableDef tag2NodeID map[int32]int32 - nextTag int32 - nextMsgTag int32 + nextBindTag int32 + nextMsgTag int32 isPrepareStatement bool mysqlCompatible bool diff --git a/pkg/sql/plan/unnest.go b/pkg/sql/plan/unnest.go index 156853fa2782e..0964c2a5f8bff 100644 --- a/pkg/sql/plan/unnest.go +++ b/pkg/sql/plan/unnest.go @@ -95,7 +95,7 @@ func (builder *QueryBuilder) buildUnnest(tbl *tree.TableFunction, ctx *BindConte }, Cols: colDefs, }, - BindingTags: []int32{builder.genNewTag()}, + BindingTags: []int32{builder.genNewBindTag()}, Children: children, TblFuncExprList: exprs, } diff --git a/pkg/sql/util/util.go b/pkg/sql/util/util.go index 22cd0a70d34ba..744887c0e941f 100644 --- a/pkg/sql/util/util.go +++ b/pkg/sql/util/util.go @@ -142,14 +142,12 @@ func BuildMoDataBaseFilter(curAccountId uint64) tree.Expr { return tree.NewOrExpr(left, right) } -func BuildSysStatementInfoFilter(acctName string) tree.Expr { - equalAccount := makeStringEqualAst("account", strings.Split(acctName, ":")[0]) - return equalAccount +func BuildSysStatementInfoFilter(curAccountId uint64) tree.Expr { + return makeAccountIdEqualAst(curAccountId) } -func BuildSysMetricFilter(acctName string) tree.Expr { - equalAccount := makeStringEqualAst("account", strings.Split(acctName, ":")[0]) - return equalAccount +func BuildSysMetricFilter(curAccountId uint64) tree.Expr { + return makeAccountIdEqualAst(curAccountId) } // Build the filter condition AST expression for mo_tables, as follows: @@ -261,6 +259,160 @@ func IsClusterTableAttribute(name string) bool { return name == clusterTableAttributeName } +// AccountIdResolver is a function type that resolves account name to account_id. +// It returns the account_id if found, or an error if not found or on failure. +// If the account is not found, it should return (0, nil) to indicate the account doesn't exist. +type AccountIdResolver func(accountName string) (uint32, error) + +// ConvertAccountToAccountIdWithTableCheck converts account column references to account_id comparisons in AST. +// This conversion is primarily designed for compatibility with mo-cloud's business-level usage of the account field. +// +// The function only handles EQUAL operations (account = 'xxx') for system accounts. For other operations (IN, LIKE, etc.), it keeps the original condition unchanged. +// +// For system accounts (account_id = 0): +// - If account = 'sys', it directly converts to account_id = 0 without query +// - If account = 'xxx' and accountIdResolver is provided, it queries account_id: +// - If account_id is found, replaces with account_id = (can be pushed down to tablescan) +// - If account_id is not found, keeps the original account = 'xxx' condition +// +// For non-system accounts: +// - No conversion is performed because account_id filter is already added in tablescan during plan building. QueryBuiler::buildTable pkg/sql/plan/query_builder.go:4889 +// +// tableAliasMap is a map of table names/aliases that refer to statement_info or metric table. If nil, only checks for unqualified column names +// or table name "statement_info"/"metric". This map is used to verify if table-qualified column names (e.g., s.account, m.account) refer to statement_info or metric. +// +// This allows mo-cloud to query statement_info or metric table using account names (e.g., WHERE account = 'sys' or WHERE s.account = 'sys') +// instead of account_ids, providing a more intuitive interface while maintaining compatibility with the underlying account_id-based storage and access control. +// +// Returns the converted AST expression and a boolean indicating if any conversion was made. +func ConvertAccountToAccountIdWithTableCheck(astExpr tree.Expr, isSystemAccount bool, currentAccountName string, currentAccountID uint32, tableAliasMap map[string]bool, accountIdResolver AccountIdResolver) (tree.Expr, bool) { + switch expr := astExpr.(type) { + case *tree.ComparisonExpr: + // Check if Left is account column from statement_info table + if isAccountColumnFromStatementInfoOrMetric(expr.Left, tableAliasMap) { + // For non-system account, do nothing because account_id filter is already added in tablescan + if !isSystemAccount { + return astExpr, false + } + // Only handle EQUAL operation for account column + // For other operations (IN, LIKE, etc.), keep original condition unchanged + if expr.Op != tree.EQUAL { + return astExpr, false + } + // Optimization: if account = 'sys', directly convert to account_id = 0 without query + if accountValue, ok := extractAccountValue(expr.Right); ok { + if strings.EqualFold(accountValue, "sys") { + accountIdColName := tree.NewUnresolvedColName("account_id") + accountIdConst := tree.NewNumVal(uint64(0), "0", false, tree.P_uint64) + return tree.NewComparisonExpr(tree.EQUAL, accountIdColName, accountIdConst), true + } + if accountIdResolver != nil { + accountId, err := accountIdResolver(accountValue) + if err == nil && accountId != 0 { + // Account found, replace with account_id = + accountIdColName := tree.NewUnresolvedColName("account_id") + accountIdConst := tree.NewNumVal(uint64(accountId), strconv.Itoa(int(accountId)), false, tree.P_uint64) + return tree.NewComparisonExpr(tree.EQUAL, accountIdColName, accountIdConst), true + } + // Account not found or error, keep original account = 'xxx' condition + return astExpr, false + } + } + // If resolver is not available, keep original condition + return astExpr, false + } + // Recursively process Left and Right + newLeft, leftConverted := ConvertAccountToAccountIdWithTableCheck(expr.Left, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + newRight, rightConverted := ConvertAccountToAccountIdWithTableCheck(expr.Right, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + if leftConverted || rightConverted { + return &tree.ComparisonExpr{ + Op: expr.Op, + SubOp: expr.SubOp, + Left: newLeft, + Right: newRight, + Escape: expr.Escape, + }, true + } + + case *tree.AndExpr: + newLeft, leftConverted := ConvertAccountToAccountIdWithTableCheck(expr.Left, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + newRight, rightConverted := ConvertAccountToAccountIdWithTableCheck(expr.Right, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + if leftConverted || rightConverted { + return &tree.AndExpr{Left: newLeft, Right: newRight}, true + } + + case *tree.OrExpr: + newLeft, leftConverted := ConvertAccountToAccountIdWithTableCheck(expr.Left, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + newRight, rightConverted := ConvertAccountToAccountIdWithTableCheck(expr.Right, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + if leftConverted || rightConverted { + return &tree.OrExpr{Left: newLeft, Right: newRight}, true + } + + case *tree.NotExpr: + newExpr, converted := ConvertAccountToAccountIdWithTableCheck(expr.Expr, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + if converted { + return &tree.NotExpr{Expr: newExpr}, true + } + + case *tree.ParenExpr: + newExpr, converted := ConvertAccountToAccountIdWithTableCheck(expr.Expr, isSystemAccount, currentAccountName, currentAccountID, tableAliasMap, accountIdResolver) + if converted { + return &tree.ParenExpr{Expr: newExpr}, true + } + } + + return astExpr, false +} + +// isAccountColumnFromStatementInfoOrMetric checks if the expression is an account column reference from statement_info or metric table. +// This is used to identify account column comparisons that need to be converted to account_id comparisons +// for compatibility with mo-cloud's business-level usage of the account field. +// +// For table-qualified column names (e.g., s.account or statement_info.account), it checks if the table name/alias +// refers to statement_info or metric table using tableAliasMap. If tableAliasMap is nil, it only checks if table name is "statement_info" or "metric". +// For unqualified column names, it returns true (will be checked by hasStatementInfoOrMetricTable in caller). +func isAccountColumnFromStatementInfoOrMetric(expr tree.Expr, tableAliasMap map[string]bool) bool { + if unresolvedName, ok := expr.(*tree.UnresolvedName); ok { + colName := unresolvedName.ColName() + if !strings.EqualFold(colName, "account") { + return false + } + // If column name has table qualification, check if table refers to statement_info or metric + if unresolvedName.NumParts >= 2 { + tblName := unresolvedName.TblName() + // Check if table name is "statement_info" (case-insensitive) + if strings.EqualFold(tblName, catalog.MO_STATEMENT) { + return true + } + // Check if table name is "metric" (case-insensitive) + if strings.EqualFold(tblName, catalog.MO_METRIC) { + return true + } + // If tableAliasMap is provided, check if the table alias refers to statement_info or metric + if tableAliasMap != nil { + return tableAliasMap[tblName] + } + // If no tableAliasMap and table name is not "statement_info" or "metric", don't convert + return false + } + // For unqualified column names, return true (will be checked by hasStatementInfoOrMetricTable in caller) + return true + } + return false +} + +// extractAccountValue extracts the account value from an expression (for string literals). +// This helper function is used to extract account name values from AST expressions +// when converting account comparisons to account_id comparisons for mo-cloud compatibility. +func extractAccountValue(expr tree.Expr) (string, bool) { + if numVal, ok := expr.(*tree.NumVal); ok { + if numVal.ValType == tree.P_char { + return numVal.String(), true + } + } + return "", false +} + const partitionDelimiter = "%!%" // IsValidNameForPartitionTable diff --git a/pkg/sql/util/util_test.go b/pkg/sql/util/util_test.go index 91eb9c4b01796..c8699067ff29c 100644 --- a/pkg/sql/util/util_test.go +++ b/pkg/sql/util/util_test.go @@ -16,8 +16,11 @@ package util import ( "fmt" - "github.com/stretchr/testify/require" "testing" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/stretchr/testify/require" ) type kase struct { @@ -74,3 +77,489 @@ func Test_SplitNameOfPartitionTable(t *testing.T) { } } } + +func TestConvertAccountToAccountIdWithTableCheck(t *testing.T) { + tests := []struct { + name string + astExpr tree.Expr + isSystemAccount bool + currentAccountName string + currentAccountID uint32 + accountIdResolver AccountIdResolver + wantConverted bool + checkResult func(t *testing.T, result tree.Expr) + }{ + { + name: "system account - account equals (no resolver, should not convert)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("test_account", "test_account", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: false, // No resolver provided, keep original condition + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.EQUAL, compExpr.Op) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "system account - account equals sys (optimization)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.EQUAL, compExpr.Op) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + // Should be direct comparison, not subquery (optimization) + _, ok = compExpr.Right.(*tree.Subquery) + require.False(t, ok, "Right should NOT be a subquery for sys optimization") + // Should be account_id = 0 + numVal, ok := compExpr.Right.(*tree.NumVal) + require.True(t, ok, "Right should be a NumVal") + require.Equal(t, "0", numVal.String()) + }, + }, + { + name: "system account - account equals SYS (case insensitive)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("SYS", "SYS", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.EQUAL, compExpr.Op) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + // Should be direct comparison, not subquery (optimization) + _, ok = compExpr.Right.(*tree.Subquery) + require.False(t, ok, "Right should NOT be a subquery for sys optimization") + // Should be account_id = 0 + numVal, ok := compExpr.Right.(*tree.NumVal) + require.True(t, ok, "Right should be a NumVal") + require.Equal(t, "0", numVal.String()) + }, + }, + { + name: "system account - table qualified column (s.account)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedName( + tree.NewCStr("s", 0), + tree.NewCStr("account", 1), + ), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: false, // 表别名 "s" 在没有 tableAliasMap 时不会被转换 + checkResult: func(t *testing.T, result tree.Expr) { + // 没有 tableAliasMap 时,表别名不会被转换 + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + unresolvedName, ok := compExpr.Left.(*tree.UnresolvedName) + require.True(t, ok) + require.Equal(t, "account", unresolvedName.ColName()) + require.Equal(t, "s", unresolvedName.TblName()) + }, + }, + { + name: "system account - full table name qualified column (statement_info.account)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedName( + tree.NewCStr("statement_info", 0), + tree.NewCStr("account", 1), + ), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, // 完整表名 "statement_info" 会被转换 + checkResult: func(t *testing.T, result tree.Expr) { + // 应该被转换为 account_id = 0 + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.EQUAL, compExpr.Op) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + // Should be direct comparison, not subquery (optimization) + _, ok = compExpr.Right.(*tree.Subquery) + require.False(t, ok, "Right should NOT be a subquery for sys optimization") + // Should be account_id = 0 + numVal, ok := compExpr.Right.(*tree.NumVal) + require.True(t, ok, "Right should be a NumVal") + require.Equal(t, "0", numVal.String()) + }, + }, + { + name: "system account - account IN (should not convert)", + astExpr: tree.NewComparisonExpr( + tree.IN, + tree.NewUnresolvedColName("account"), + tree.NewTuple(tree.Exprs{ + tree.NewNumVal("acc1", "acc1", false, tree.P_char), + tree.NewNumVal("acc2", "acc2", false, tree.P_char), + }), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: false, // IN operation is not converted + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.IN, compExpr.Op) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "non-system account - account equals currentAccountName (should not convert)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("my_account", "my_account", false, tree.P_char), + ), + isSystemAccount: false, + currentAccountName: "my_account", + currentAccountID: 100, + wantConverted: false, // Non-system account: no conversion, account_id filter already in tablescan + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "non-system account - account not equals currentAccountName", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("other_account", "other_account", false, tree.P_char), + ), + isSystemAccount: false, + currentAccountName: "my_account", + currentAccountID: 100, + wantConverted: false, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "non-system account - account IN (should not convert)", + astExpr: tree.NewComparisonExpr( + tree.IN, + tree.NewUnresolvedColName("account"), + tree.NewTuple(tree.Exprs{ + tree.NewNumVal("acc1", "acc1", false, tree.P_char), + }), + ), + isSystemAccount: false, + currentAccountName: "my_account", + currentAccountID: 100, + wantConverted: false, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "non-account column - should not convert", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("user_id"), + tree.NewNumVal(int64(123), "123", false, tree.P_int64), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: false, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "user_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "AND expression with account (sys)", + astExpr: tree.NewAndExpr( + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("status"), + tree.NewNumVal("active", "active", false, tree.P_char), + ), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + andExpr, ok := result.(*tree.AndExpr) + require.True(t, ok) + leftComp, ok := andExpr.Left.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", leftComp.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "OR expression with account (sys)", + astExpr: tree.NewOrExpr( + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + orExpr, ok := result.(*tree.OrExpr) + require.True(t, ok) + leftComp, ok := orExpr.Left.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", leftComp.Left.(*tree.UnresolvedName).ColName()) + rightComp, ok := orExpr.Right.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", rightComp.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "NOT expression with account (sys)", + astExpr: &tree.NotExpr{ + Expr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + }, + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + notExpr, ok := result.(*tree.NotExpr) + require.True(t, ok) + compExpr, ok := notExpr.Expr.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "ParenExpr with account (sys)", + astExpr: &tree.ParenExpr{ + Expr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + }, + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + parenExpr, ok := result.(*tree.ParenExpr) + require.True(t, ok) + compExpr, ok := parenExpr.Expr.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "complex nested expression (sys)", + astExpr: tree.NewAndExpr( + &tree.ParenExpr{ + Expr: tree.NewOrExpr( + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("sys", "sys", false, tree.P_char), + ), + ), + }, + tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("status"), + tree.NewNumVal("active", "active", false, tree.P_char), + ), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + andExpr, ok := result.(*tree.AndExpr) + require.True(t, ok) + parenExpr, ok := andExpr.Left.(*tree.ParenExpr) + require.True(t, ok) + orExpr, ok := parenExpr.Expr.(*tree.OrExpr) + require.True(t, ok) + leftComp, ok := orExpr.Left.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account_id", leftComp.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "system account - account equals with resolver (account found)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("test_account", "test_account", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + accountIdResolver: func(accountName string) (uint32, error) { + if accountName == "test_account" { + return 123, nil + } + return 0, nil + }, + wantConverted: true, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, tree.EQUAL, compExpr.Op) + require.Equal(t, "account_id", compExpr.Left.(*tree.UnresolvedName).ColName()) + numVal, ok := compExpr.Right.(*tree.NumVal) + require.True(t, ok, "Right should be a NumVal") + val, _ := numVal.Uint64() + require.Equal(t, uint64(123), val) + }, + }, + { + name: "system account - account equals with resolver (account not found)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("non_exist_account", "non_exist_account", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + accountIdResolver: func(accountName string) (uint32, error) { + // Account not found, return 0 + return 0, nil + }, + wantConverted: false, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + { + name: "system account - account equals with resolver (resolver error)", + astExpr: tree.NewComparisonExpr( + tree.EQUAL, + tree.NewUnresolvedColName("account"), + tree.NewNumVal("test_account", "test_account", false, tree.P_char), + ), + isSystemAccount: true, + currentAccountName: "", + currentAccountID: 0, + accountIdResolver: func(accountName string) (uint32, error) { + return 0, moerr.NewInternalErrorNoCtx("resolver error") + }, + wantConverted: false, + checkResult: func(t *testing.T, result tree.Expr) { + compExpr, ok := result.(*tree.ComparisonExpr) + require.True(t, ok) + require.Equal(t, "account", compExpr.Left.(*tree.UnresolvedName).ColName()) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, converted := ConvertAccountToAccountIdWithTableCheck( + tt.astExpr, + tt.isSystemAccount, + tt.currentAccountName, + tt.currentAccountID, + nil, // tableAliasMap + tt.accountIdResolver, + ) + require.Equal(t, tt.wantConverted, converted, "conversion status mismatch") + if tt.checkResult != nil { + tt.checkResult(t, result) + } + }) + } +} + +func TestExtractAccountValue(t *testing.T) { + tests := []struct { + name string + expr tree.Expr + expected string + ok bool + }{ + { + name: "string literal", + expr: tree.NewNumVal("test_account", "test_account", false, tree.P_char), + expected: "test_account", + ok: true, + }, + { + name: "non-string literal", + expr: tree.NewNumVal(int64(123), "123", false, tree.P_int64), + expected: "", + ok: false, + }, + { + name: "not NumVal", + expr: tree.NewUnresolvedColName("account"), + expected: "", + ok: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, ok := extractAccountValue(tt.expr) + require.Equal(t, tt.ok, ok) + if tt.ok { + require.Equal(t, tt.expected, result) + } + }) + } +} diff --git a/pkg/taskservice/daemon_task.go b/pkg/taskservice/daemon_task.go index adcb7fed2fc87..ac222bf588239 100644 --- a/pkg/taskservice/daemon_task.go +++ b/pkg/taskservice/daemon_task.go @@ -167,34 +167,106 @@ func (t *restartTask) Handle(ctx context.Context) error { defer cancel() tasks, err := t.runner.service.QueryDaemonTask(ctx, WithTaskIDCond(EQ, t.task.task.ID)) if err != nil { + t.runner.logger.Error("cdc.task.restart.query_failed", + zap.Uint64("task-id", t.task.task.ID), + zap.Error(err), + ) return moerr.AttachCause(ctx, err) } if len(tasks) != 1 { + t.runner.logger.Error("cdc.task.restart.query_wrong_count", + zap.Uint64("task-id", t.task.task.ID), + zap.Int("task-count", len(tasks)), + ) return moerr.NewInternalErrorf(ctx, "count of tasks is wrong %d", len(tasks)) } tk := tasks[0] - // We cannot resume a task which is not on local runner. - if !strings.EqualFold(tk.TaskRunner, t.runner.runnerID) { + start := time.Now() + t.runner.logger.Info("cdc.task.restart.start", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + zap.String("task-runner", tk.TaskRunner), + zap.String("target-runner", t.runner.runnerID), + zap.String("current-status", tk.TaskStatus.String()), + ) + + // We cannot restart a task which is not on local runner. + // However, if TaskRunner is empty, we allow the local runner to take over. + if tk.TaskRunner != "" && !strings.EqualFold(tk.TaskRunner, t.runner.runnerID) { + t.runner.logger.Warn("cdc.task.restart.wrong_runner", + zap.Uint64("task-id", tk.ID), + zap.String("task-runner", tk.TaskRunner), + zap.String("local-runner", t.runner.runnerID), + ) return moerr.NewInternalErrorf(ctx, "the task is not on local runner, prev runner %s, "+ "local runner %s", tk.TaskRunner, t.runner.runnerID) } + // If TaskRunner is empty, assign it to the current runner + if tk.TaskRunner == "" { + tk.TaskRunner = t.runner.runnerID + t.runner.logger.Info("cdc.task.restart.assign_runner", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + zap.String("assigned-runner", tk.TaskRunner), + ) + } + tk.TaskStatus = task.TaskStatus_Running nowTime := time.Now() tk.LastRun = nowTime tk.LastHeartbeat = nowTime _, err = t.runner.service.UpdateDaemonTask(ctx, []task.DaemonTask{tk}) if err != nil { + t.runner.logger.Error("cdc.task.restart.update_status_failed", + zap.Uint64("task-id", tk.ID), + zap.Error(err), + ) return moerr.AttachCause(ctx, err) } + t.runner.logger.Info("cdc.task.restart.status_updated", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + zap.String("new-status", tk.TaskStatus.String()), + zap.Time("last-run", tk.LastRun), + ) + ar := t.task.activeRoutine.Load() if ar == nil || *ar == nil { + t.runner.logger.Error("cdc.task.restart.active_routine_nil", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + ) return moerr.NewInternalErrorf(ctx, "cannot handle restart operation, "+ "active routine not set for task %d", t.task.task.ID) } - return (*ar).Restart() + + t.runner.logger.Info("cdc.task.restart.calling_active_routine", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + ) + + err = (*ar).Restart() + if err != nil { + t.runner.logger.Error("cdc.task.restart.failed", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + zap.Error(err), + zap.Duration("elapsed", time.Since(start)), + ) + return err + } + + t.runner.logger.Info("cdc.task.restart.finish", + zap.Uint64("task-id", tk.ID), + zap.String("task-name", taskNameFromDetails(tk)), + zap.String("new-status", tk.TaskStatus.String()), + zap.Duration("elapsed", time.Since(start)), + ) + + return nil } type pauseTask struct { @@ -527,14 +599,36 @@ func (r *taskRunner) resumeTasks(ctx context.Context) []task.DaemonTask { // restartTasks gets the tasks that need to restart. // - status equals to task.TaskStatus_RestartRequested and runner equals to local func (r *taskRunner) restartTasks(ctx context.Context) []task.DaemonTask { - // We only resume the tasks that already running on this runner. For the tasks that - // run on other runners and heartbeat timeout, startTasks() will handle them. - return r.mergeTasks( - r.queryDaemonTasks(ctx, - WithTaskStatusCond(task.TaskStatus_RestartRequested), - WithTaskRunnerCond(EQ, r.runnerID), - ), + // Handle the tasks which is in RestartRequested status: + // 1. the task is on current runner + // 2. the task is on other runners, but heartbeat timeout or null. In the handler, + // do NOT restart the active routine in this case. + localRestart := r.queryDaemonTasks(ctx, + WithTaskStatusCond(task.TaskStatus_RestartRequested), + WithTaskRunnerCond(EQ, r.runnerID), + ) + laggedRestart := r.queryDaemonTasks(ctx, + WithTaskStatusCond(task.TaskStatus_RestartRequested), + WithLastHeartbeat(LE, time.Now().UnixNano()-r.options.heartbeatTimeout.Nanoseconds()), ) + tasks := r.mergeTasks(localRestart, laggedRestart) + if len(tasks) > 0 { + for _, t := range tasks { + r.logger.Info("cdc.task.restart.enqueue", + zap.Uint64("task-id", t.ID), + zap.String("task-name", taskNameFromDetails(t)), + zap.String("current-status", t.TaskStatus.String()), + zap.String("task-runner", t.TaskRunner), + zap.String("local-runner", r.runnerID), + ) + } + } else { + r.logger.Debug("cdc.task.restart.enqueue.none", + zap.Int("local-candidates", len(localRestart)), + zap.Int("lagged-candidates", len(laggedRestart)), + ) + } + return tasks } // pauseTasks gets the tasks that need to pause. diff --git a/pkg/taskservice/daemon_task_test.go b/pkg/taskservice/daemon_task_test.go index ee1d78c49ff38..35ce5163101c0 100644 --- a/pkg/taskservice/daemon_task_test.go +++ b/pkg/taskservice/daemon_task_test.go @@ -222,3 +222,29 @@ func TestRestartDaemonTask(t *testing.T) { }, WithRunnerParallelism(1), WithRunnerFetchInterval(time.Millisecond)) } + +// TestRestartDaemonTaskWithEmptyRunner tests restart when TaskRunner is empty. +// This covers the bug fix where tasks with empty TaskRunner couldn't be restarted. +func TestRestartDaemonTaskWithEmptyRunner(t *testing.T) { + runTaskRunnerTest(t, func(r *taskRunner, s TaskService, store TaskStorage) { + // Create a task with empty TaskRunner (simulating newly created task) + dt := newDaemonTaskForTest(1, task.TaskStatus_Created, "") + mustAddTestDaemonTask(t, store, 1, dt) + var started atomic.Bool + r.testRegisterExecutor(t, task.TaskCode_ConnectorKafkaSink, &started) + waitStarted(&started, time.Second*5) + + // Update task status to RestartRequested (TaskRunner still empty) + dt.TaskStatus = task.TaskStatus_RestartRequested + mustUpdateTestDaemonTask(t, store, 1, []task.DaemonTask{dt}) + + // Wait for restart to complete + expectTaskStatus(t, store, dt, task.TaskStatus_RestartRequested, task.TaskStatus_Running) + + // Verify TaskRunner was assigned + updatedTasks := mustGetTestDaemonTask(t, store, 1, WithTaskIDCond(EQ, 1)) + assert.Len(t, updatedTasks, 1, "Should have exactly one task") + assert.Equal(t, r.runnerID, updatedTasks[0].TaskRunner, "TaskRunner should be assigned to current runner") + }, WithRunnerParallelism(1), + WithRunnerFetchInterval(time.Millisecond)) +} diff --git a/pkg/util/export/etl/db/db_holder.go b/pkg/util/export/etl/db/db_holder.go index 1f979695814d9..2c2203a410c29 100644 --- a/pkg/util/export/etl/db/db_holder.go +++ b/pkg/util/export/etl/db/db_holder.go @@ -20,6 +20,7 @@ import ( "database/sql" "encoding/csv" "fmt" + "strconv" "strings" "sync" "sync/atomic" @@ -326,22 +327,27 @@ func IsRecordExisted(ctx context.Context, record []string, tbl *table.Table, get if tbl.Table == "statement_info" { const stmtIDIndex = 0 // Replace with actual index for statement ID if different - const accountIndex = 3 // Replace with actual index for account - const statusIndex = 15 // Replace with actual index for status - const requestAtIndex = 12 // Replace with actual index for request_at + const accountIdIndex = 4 // Replace with actual index for account_id (after account at index 3) + const statusIndex = 16 // Replace with actual index for status (shifted by 1 due to account_id) + const requestAtIndex = 13 // Replace with actual index for request_at (shifted by 1 due to account_id) if len(record) <= statusIndex { // Use the largest index you will access return false, nil } - return isStatementExisted(ctx, dbConn, record[stmtIDIndex], record[statusIndex], record[requestAtIndex], record[accountIndex]) + accountIdStr := record[accountIdIndex] + accountId, err := strconv.ParseUint(accountIdStr, 10, 32) + if err != nil { + return false, err + } + return isStatementExisted(ctx, dbConn, record[stmtIDIndex], record[statusIndex], record[requestAtIndex], uint32(accountId)) } return false, nil } -func isStatementExisted(ctx context.Context, db *sql.DB, stmtId string, status string, request_at, account string) (bool, error) { +func isStatementExisted(ctx context.Context, db *sql.DB, stmtId string, status string, request_at string, accountId uint32) (bool, error) { var exists bool - query := "SELECT EXISTS(SELECT 1 FROM `system`.statement_info WHERE statement_id = ? AND status = ? AND request_at = ? AND account = ?)" - err := db.QueryRowContext(ctx, query, stmtId, status, request_at, account).Scan(&exists) + query := "SELECT EXISTS(SELECT 1 FROM `system`.statement_info WHERE statement_id = ? AND status = ? AND request_at = ? AND account_id = ?)" + err := db.QueryRowContext(ctx, query, stmtId, status, request_at, accountId).Scan(&exists) if err != nil { return false, err } diff --git a/pkg/util/export/etl/db/db_holder_test.go b/pkg/util/export/etl/db/db_holder_test.go index 0fa3c94542008..615aaca4d1856 100644 --- a/pkg/util/export/etl/db/db_holder_test.go +++ b/pkg/util/export/etl/db/db_holder_test.go @@ -91,14 +91,14 @@ func TestIsRecordExisted(t *testing.T) { defer db.Close() ctx := context.TODO() - // Assuming index 12 is for 'request_at', adding a mock value for it - record := []string{"12345", "", "", "sys", "", "", "", "", "", "", "", "", "2021-10-10 10:00:00", "", "", "active"} + // Updated indices: account_id at index 4, request_at at index 13, status at index 16 + record := []string{"12345", "", "", "sys", "0", "", "", "", "", "", "", "", "", "2021-10-10 10:00:00", "", "", "active"} table := &table.Table{Table: "statement_info"} // Set up your mock expectations mock.ExpectQuery(regexp.QuoteMeta( - "SELECT EXISTS(SELECT 1 FROM `system`.statement_info WHERE statement_id = ? AND status = ? AND request_at = ? AND account = ?)", - )).WithArgs(record[0], record[15], record[12], "sys").WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow(true)) + "SELECT EXISTS(SELECT 1 FROM `system`.statement_info WHERE statement_id = ? AND status = ? AND request_at = ? AND account_id = ?)", + )).WithArgs(record[0], record[16], record[13], uint32(0)).WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow(true)) // Define a function that returns the mocked DB connection getDBConn := func(forceNewConn bool, randomCN bool) (*sql.DB, error) { diff --git a/pkg/util/export/etl/tae.go b/pkg/util/export/etl/tae.go index 0390885d6c89e..b5a0c77a1c4c1 100644 --- a/pkg/util/export/etl/tae.go +++ b/pkg/util/export/etl/tae.go @@ -109,6 +109,12 @@ func (w *TAEWriter) WriteStrings(Line []string) error { return moerr.NewInternalErrorf(w.ctx, "the input value is not int64 type for column %d: %v, err: %s", colIdx, field, err) } elems[colIdx] = table.Int64Field(val) + case types.T_uint32: + val, err := strconv.ParseUint(field, 10, 32) + if err != nil { + return moerr.NewInternalErrorf(w.ctx, "the input value is not uint32 type for column %d: %v, err: %s", colIdx, field, err) + } + elems[colIdx] = table.Uint32Field(uint32(val)) case types.T_uint64: val, err := strconv.ParseUint(field, 10, 64) if err != nil { @@ -211,6 +217,9 @@ func getOneRowData(ctx context.Context, bat *batch.Batch, Line []table.ColumnFie case types.T_int64: cols := vector.MustFixedColNoTypeCheck[int64](vec) cols[rowIdx] = field.Integer + case types.T_uint32: + cols := vector.MustFixedColNoTypeCheck[uint32](vec) + cols[rowIdx] = uint32(field.Integer) case types.T_uint64: cols := vector.MustFixedColNoTypeCheck[uint64](vec) cols[rowIdx] = uint64(field.Integer) @@ -397,6 +406,9 @@ func GetVectorArrayLen(ctx context.Context, vec *vector.Vector) (int, error) { case types.T_int64: cols := vector.MustFixedColNoTypeCheck[int64](vec) return len(cols), nil + case types.T_uint32: + cols := vector.MustFixedColNoTypeCheck[uint32](vec) + return len(cols), nil case types.T_uint64: cols := vector.MustFixedColNoTypeCheck[uint64](vec) return len(cols), nil @@ -424,6 +436,9 @@ func ValToString(ctx context.Context, vec *vector.Vector, rowIdx int) (string, e case types.T_int64: cols := vector.MustFixedColNoTypeCheck[int64](vec) return fmt.Sprintf("%d", cols[rowIdx]), nil + case types.T_uint32: + cols := vector.MustFixedColNoTypeCheck[uint32](vec) + return fmt.Sprintf("%d", cols[rowIdx]), nil case types.T_uint64: cols := vector.MustFixedColNoTypeCheck[uint64](vec) return fmt.Sprintf("%d", cols[rowIdx]), nil diff --git a/pkg/util/export/etl/tae_test.go b/pkg/util/export/etl/tae_test.go index ca24285a3f126..d64f0e5eaff53 100644 --- a/pkg/util/export/etl/tae_test.go +++ b/pkg/util/export/etl/tae_test.go @@ -185,12 +185,15 @@ func TestTAEWriter_WriteRow(t *testing.T) { TransactionID: _1TxnID, SessionID: _1SesID, Account: "MO", + AccountID: 0, User: "moroot", Database: "system", Statement: []byte("show tables"), StatementFingerprint: "show tables", StatementTag: "", ExecPlan: nil, + RequestAt: time.Now(), + ResponseAt: time.Now(), }, ) return arr @@ -239,9 +242,11 @@ func TestTAEWriter_WriteRow(t *testing.T) { for _, item := range items { row := item.GetTable().GetRow(tt.fields.ctx) item.FillRow(tt.fields.ctx, row) - writer.WriteRow(row) + err := writer.WriteRow(row) + require.Nil(t, err) } - writer.FlushAndClose() + _, err := writer.FlushAndClose() + require.Nil(t, err) folder := path.Dir(filePath) entrys, err := fileservice.SortedList(fs.List(ctx, folder)) diff --git a/pkg/util/export/table/table.go b/pkg/util/export/table/table.go index e92a8bb3c3f60..c60f4b93046c8 100644 --- a/pkg/util/export/table/table.go +++ b/pkg/util/export/table/table.go @@ -632,6 +632,10 @@ func Uint64Field(val uint64) ColumnField { return ColumnField{Type: TUint64, Integer: int64(val)} } +func Uint32Field(val uint32) ColumnField { + return ColumnField{Type: TUint32, Integer: int64(val)} +} + func Int64Field(val int64) ColumnField { return ColumnField{Type: TInt64, Integer: val} } @@ -732,6 +736,8 @@ func (r *Row) Reset() { r.Columns[idx] = Uint64Field(0) case types.T_int64: r.Columns[idx] = Int64Field(0) + case types.T_uint32: + r.Columns[idx] = Uint32Field(0) case types.T_uint64: r.Columns[idx] = Uint64Field(0) case types.T_float64: @@ -788,6 +794,8 @@ func (r *Row) ToStrings() []string { col[idx] = fmt.Sprintf("%d", uint64(r.Columns[idx].Integer)) case types.T_int64: col[idx] = fmt.Sprintf("%d", r.Columns[idx].Integer) + case types.T_uint32: + col[idx] = fmt.Sprintf("%d", uint32(r.Columns[idx].Integer)) case types.T_uint64: col[idx] = fmt.Sprintf("%d", uint64(r.Columns[idx].Integer)) case types.T_float64: @@ -888,6 +896,8 @@ func (r *Row) Size() (size int64) { size += 8 case types.T_int64: size += 8 + case types.T_uint32: + size += 4 case types.T_uint64: size += 8 case types.T_float64: diff --git a/pkg/util/metric/m_register.go b/pkg/util/metric/m_register.go index 09e8702610a76..7ae95e23963e6 100644 --- a/pkg/util/metric/m_register.go +++ b/pkg/util/metric/m_register.go @@ -17,6 +17,7 @@ package metric import prom "github.com/prometheus/client_golang/prometheus" const constTenantKey = "account" +const constTenantIdKey = "account_id" // this constant lable is used for sys_* and process_* table var sysTenantID = prom.Labels{constTenantKey: "sys"} diff --git a/pkg/util/metric/m_server.go b/pkg/util/metric/m_server.go index df7ded76b9ebc..7f39fb1223e67 100644 --- a/pkg/util/metric/m_server.go +++ b/pkg/util/metric/m_server.go @@ -14,6 +14,8 @@ package metric +import "strconv" + var ( ConnFactory = NewGaugeVec( GaugeOpts{ @@ -21,7 +23,7 @@ var ( Name: "connections", Help: "Number of process connections", }, - []string{constTenantKey}, + []string{constTenantKey, constTenantIdKey}, ) StorageUsageFactory = NewGaugeVec( @@ -30,7 +32,7 @@ var ( Name: "storage_usage", Help: "Storage usage of each account", }, - []string{constTenantKey}, + []string{constTenantKey, constTenantIdKey}, ) ObjectCountFactory = NewGaugeVec( @@ -39,7 +41,7 @@ var ( Name: "object_count", Help: "object number of each account", }, - []string{constTenantKey}, + []string{constTenantKey, constTenantIdKey}, ) SnapshotUsageFactory = NewGaugeVec( @@ -48,22 +50,22 @@ var ( Name: "snapshot_usage", Help: "Snapshot usage of each account", }, - []string{constTenantKey}, + []string{constTenantKey, constTenantIdKey}, ) ) -func ConnectionCounter(account string) Gauge { - return ConnFactory.WithLabelValues(account) +func ConnectionCounter(account string, accountId uint32) Gauge { + return ConnFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10)) } -func StorageUsage(account string) Gauge { - return StorageUsageFactory.WithLabelValues(account) +func StorageUsage(account string, accountId uint32) Gauge { + return StorageUsageFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10)) } -func ObjectCount(account string) Gauge { - return ObjectCountFactory.WithLabelValues(account) +func ObjectCount(account string, accountId uint32) Gauge { + return ObjectCountFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10)) } -func SnapshotUsage(account string) Gauge { - return SnapshotUsageFactory.WithLabelValues(account) +func SnapshotUsage(account string, accountId uint32) Gauge { + return SnapshotUsageFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10)) } diff --git a/pkg/util/metric/m_server_test.go b/pkg/util/metric/m_server_test.go index 07a418e573a51..a6c2f366e16e9 100644 --- a/pkg/util/metric/m_server_test.go +++ b/pkg/util/metric/m_server_test.go @@ -37,7 +37,7 @@ func TestConnectionCounter(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := ConnectionCounter(tt.args.account) + c := ConnectionCounter(tt.args.account, 0) c.Inc() dtom := new(dto.Metric) c.Write(dtom) diff --git a/pkg/util/metric/m_sql.go b/pkg/util/metric/m_sql.go index 5799524c2505f..8ce4486cbc141 100644 --- a/pkg/util/metric/m_sql.go +++ b/pkg/util/metric/m_sql.go @@ -14,6 +14,8 @@ package metric +import "strconv" + var ( StatementCounterFactory = NewCounterVec( CounterOpts{ @@ -21,7 +23,7 @@ var ( Name: "statement_total", Help: "Counter of executed sql statement", }, - []string{constTenantKey, "type"}, + []string{constTenantKey, constTenantIdKey, "type"}, false, ) @@ -31,7 +33,7 @@ var ( Name: "statement_duration_total", Help: "Statement duration of each query type for each account", }, - []string{constTenantKey, "type"}, + []string{constTenantKey, constTenantIdKey, "type"}, false, ) @@ -41,7 +43,7 @@ var ( Name: "transaction_total", Help: "Counter of transaction", }, - []string{constTenantKey}, + []string{constTenantKey, constTenantIdKey}, false, ) @@ -51,7 +53,7 @@ var ( Name: "transaction_errors", Help: "Counter of errors on execute commit/rollback statement", }, - []string{constTenantKey, "type"}, + []string{constTenantKey, constTenantIdKey, "type"}, false, ) @@ -61,7 +63,7 @@ var ( Name: "statement_errors", Help: "Counter of executed sql statement failed.", }, - []string{constTenantKey, "type"}, + []string{constTenantKey, constTenantIdKey, "type"}, false, ) @@ -71,7 +73,7 @@ var ( Name: "statement_cu", Help: "Counter of executed sql statement cu", }, - []string{constTenantKey, "sql_source_type"}, + []string{constTenantKey, constTenantIdKey, "sql_source_type"}, false, ) ) @@ -93,30 +95,31 @@ var ( ) // StatementCounter accept t as tree.QueryType -func StatementCounter(tenant string, t string) Counter { - return StatementCounterFactory.WithLabelValues(tenant, t) +func StatementCounter(tenant string, tenantId uint32, t string) Counter { + return StatementCounterFactory.WithLabelValues(tenant, strconv.FormatUint(uint64(tenantId), 10), t) } -func StatementDuration(tenant string, t string) Counter { - return StatementDurationFactory.WithLabelValues(tenant, t) +func StatementDuration(tenant string, tenantId uint32, t string) Counter { + return StatementDurationFactory.WithLabelValues(tenant, strconv.FormatUint(uint64(tenantId), 10), t) } -func TransactionCounter(tenant string) Counter { - return TransactionCounterFactory.WithLabelValues(tenant) +func TransactionCounter(tenant string, tenantId uint32) Counter { + return TransactionCounterFactory.WithLabelValues(tenant, strconv.FormatUint(uint64(tenantId), 10)) } -func TransactionErrorsCounter(account string, t SQLType) Counter { - return TransactionErrorsFactory.WithLabelValues(account, string(t)) +func TransactionErrorsCounter(account string, accountId uint32, t SQLType) Counter { + return TransactionErrorsFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10), string(t)) } // StatementErrorsCounter accept t as tree.QueryType -func StatementErrorsCounter(account string, t string) Counter { - return StatementErrorsFactory.WithLabelValues(account, t) +func StatementErrorsCounter(account string, accountId uint32, t string) Counter { + return StatementErrorsFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10), t) } -// StatementCUCounter accept @account, @sqlSourceType +// StatementCUCounter accept @account, @accountId, @sqlSourceType // @account is the account name of the user who executes the sql statement. +// @accountId is the account id of the user who executes the sql statement. // @sqlSourceType is the type of sql source, such as InternalSql, CloudNoUserSql, ExternalSql, CloudUserSql etc. -func StatementCUCounter(account string, sqlSourceType string) Counter { - return StatementCUCounterFactory.WithLabelValues(account, sqlSourceType) +func StatementCUCounter(account string, accountId uint32, sqlSourceType string) Counter { + return StatementCUCounterFactory.WithLabelValues(account, strconv.FormatUint(uint64(accountId), 10), sqlSourceType) } diff --git a/pkg/util/metric/mometric/cron_task.go b/pkg/util/metric/mometric/cron_task.go index 8252d9ff7bf0d..5948bba376201 100644 --- a/pkg/util/metric/mometric/cron_task.go +++ b/pkg/util/metric/mometric/cron_task.go @@ -96,6 +96,7 @@ func GetMetricStorageUsageExecutor( const ( ShowAllAccountSQL = "SHOW ACCOUNTS;" ShowAccountSQL = "SHOW ACCOUNTS like %q;" + ColumnAccountId = "account_id" // result column in `show accounts`, or column in table mo_catalog.mo_account ColumnAccountName = "account_name" // result column in `show accounts`, or column in table mo_catalog.mo_account ColumnSize = "size" // result column in `show accounts`, or column in table mo_catalog.mo_account ColumnCreatedTime = "created_time" // column in table mo_catalog.mo_account @@ -139,7 +140,7 @@ func checkServerStarted(service string, logger *log.MOLogger) bool { } // after 1.3.0, turn it as CONST var -var accountIdx, sizeIdx, snapshotSizeIdx uint64 +var accountIdIdx, accountIdx, sizeIdx, snapshotSizeIdx uint64 var objectCountIdx uint64 var name2IdxErr error var name2IdxOnce sync.Once @@ -157,6 +158,10 @@ func GetColumnIdxFromShowAccountResult(ctx context.Context, result ie.InternalEx } name2idx[colName] = colIdx } + if _, ok := name2idx[ColumnAccountId]; !ok { + // adapt version, account_id might not exist in older versions + name2idx[ColumnAccountId] = math.MaxUint64 + } if _, ok := name2idx[ColumnAccountName]; !ok { name2IdxErr = moerr.NewInternalErrorf(ctx, "column not found in 'show account': %s", ColumnAccountName) return @@ -173,7 +178,7 @@ func GetColumnIdxFromShowAccountResult(ctx context.Context, result ie.InternalEx logutil.Errorf("column object count does not exists: %v", name2idx) name2idx[ColumnObjectCount] = math.MaxUint64 } - accountIdx, sizeIdx, snapshotSizeIdx = name2idx[ColumnAccountName], name2idx[ColumnSize], name2idx[ColumnSnapshotSize] + accountIdIdx, accountIdx, sizeIdx, snapshotSizeIdx = name2idx[ColumnAccountId], name2idx[ColumnAccountName], name2idx[ColumnSize], name2idx[ColumnSnapshotSize] objectCountIdx = name2idx[ColumnObjectCount] }) return name2IdxErr @@ -273,6 +278,14 @@ func CalculateStorageUsage( return err } + var accountId uint32 = 0 + if accountIdIdx != math.MaxUint64 { + accountIdVal, err := result.GetUint64(ctx, rowIdx, accountIdIdx) + if err == nil { + accountId = uint32(accountIdVal) + } + } + sizeMB, err = result.GetFloat64(ctx, rowIdx, sizeIdx) if err != nil { return err @@ -298,13 +311,14 @@ func CalculateStorageUsage( logger.Debug("storage_usage", zap.String("account", account), + zap.Uint32("account_id", accountId), zap.Float64("sizeMB", sizeMB), zap.Float64("snapshot", snapshotSizeMB), zap.Float64("object_count", objectCount)) - metric.ObjectCount(account).Set(objectCount) - metric.StorageUsage(account).Set(sizeMB) - metric.SnapshotUsage(account).Set(snapshotSizeMB) + metric.ObjectCount(account, accountId).Set(objectCount) + metric.StorageUsage(account, accountId).Set(sizeMB) + metric.SnapshotUsage(account, accountId).Set(snapshotSizeMB) } // next round @@ -427,6 +441,14 @@ func checkNewAccountSize(ctx context.Context, logger *log.MOLogger, sqlExecutor continue } + var accountId uint32 = 0 + if accountIdIdx != math.MaxUint64 { + accountIdVal, err := showRet.GetUint64(ctx, 0, accountIdIdx) + if err == nil { + accountId = uint32(accountIdVal) + } + } + sizeMB, err = showRet.GetFloat64(ctx, 0, sizeIdx) if err != nil { logger.Error("failed to fetch new account size", zap.Error(err), zap.String("account", account)) @@ -445,12 +467,12 @@ func checkNewAccountSize(ctx context.Context, logger *log.MOLogger, sqlExecutor // done query. // update new accounts metric - logger.Info("new account storage_usage", zap.String("account", account), zap.Float64("sizeMB", sizeMB), + logger.Info("new account storage_usage", zap.String("account", account), zap.Uint32("account_id", accountId), zap.Float64("sizeMB", sizeMB), zap.Float64("snapshot", snapshotSizeMB), zap.String("created_time", createdTime)) - metric.StorageUsage(account).Set(sizeMB) - metric.SnapshotUsage(account).Set(snapshotSizeMB) + metric.StorageUsage(account, accountId).Set(sizeMB) + metric.SnapshotUsage(account, accountId).Set(snapshotSizeMB) v2.GetTraceCheckStorageUsageNewIncCounter().Inc() } diff --git a/pkg/util/metric/mometric/metric.go b/pkg/util/metric/mometric/metric.go index a2eb199a263fe..1cf86c05c5af4 100644 --- a/pkg/util/metric/mometric/metric.go +++ b/pkg/util/metric/mometric/metric.go @@ -441,6 +441,7 @@ var ( metricNodeColumn = table.StringDefaultColumn(`node`, ALL_IN_ONE_MODE, `mo node uuid`) metricRoleColumn = table.StringDefaultColumn(`role`, ALL_IN_ONE_MODE, `mo node role, like: CN, DN, LOG`) metricAccountColumn = table.StringDefaultColumn(`account`, `sys`, `account name`) + metricAccountIdColumn = table.UInt32Column(`account_id`, `account id`) metricTypeColumn = table.StringColumn(`type`, `sql type, like: insert, select, ...`) sqlSourceTypeColumn = table.StringColumn(`sql_source_type`, `sql_source_type, val like: external_sql, cloud_nonuser_sql, cloud_user_sql, internal_sql, ...`) @@ -450,9 +451,9 @@ var SingleMetricTable = &table.Table{ Account: table.AccountSys, Database: MetricDBConst, Table: `metric`, - Columns: []table.Column{metricNameColumn, metricCollectTimeColumn, metricValueColumn, metricNodeColumn, metricRoleColumn, metricAccountColumn, metricTypeColumn}, + Columns: []table.Column{metricNameColumn, metricCollectTimeColumn, metricValueColumn, metricNodeColumn, metricRoleColumn, metricAccountColumn, metricAccountIdColumn, metricTypeColumn}, PrimaryKeyColumn: []table.Column{}, - ClusterBy: []table.Column{metricAccountColumn, metricNameColumn, metricCollectTimeColumn}, + ClusterBy: []table.Column{metricCollectTimeColumn, metricAccountIdColumn, metricNameColumn}, Engine: table.NormalTableEngine, Comment: `metric data`, PathBuilder: table.NewAccountDatePathBuilder(), diff --git a/pkg/util/metric/mometric/metric_collector.go b/pkg/util/metric/mometric/metric_collector.go index 82ef632a691fc..c5223f5879b66 100644 --- a/pkg/util/metric/mometric/metric_collector.go +++ b/pkg/util/metric/mometric/metric_collector.go @@ -20,6 +20,7 @@ import ( "fmt" "math" "runtime" + "strconv" "sync" "sync/atomic" "time" @@ -361,11 +362,27 @@ func (s *mfsetETL) GetBatch(ctx context.Context, buf *bytes.Buffer) table.Export // table `sql_statement_cu` NO column `metric_name` if row.Table.GetName() == SingleMetricTable.GetName() { row.SetColumnVal(metricNameColumn, table.StringField(mf.GetName())) + // Extract account_id from labels for SingleMetricTable + var accountId uint32 = 0 + for _, lbl := range metric.Label { + if lbl.GetName() == "account_id" { + if parsedId, err := strconv.ParseUint(lbl.GetValue(), 10, 32); err == nil { + accountId = uint32(parsedId) + } + break + } + } + row.SetColumnVal(metricAccountIdColumn, table.Uint32Field(accountId)) } row.SetColumnVal(metricNodeColumn, table.StringField(mf.GetNode())) row.SetColumnVal(metricRoleColumn, table.StringField(mf.GetRole())) // custom labels for _, lbl := range metric.Label { + // Skip account_id label - it's handled separately for SingleMetricTable only + // SqlStatementCUTable doesn't have account_id column + if lbl.GetName() == "account_id" { + continue + } row.SetVal(lbl.GetName(), table.StringField(lbl.GetValue())) } diff --git a/pkg/util/metric/v2/cdc_metrics.go b/pkg/util/metric/v2/cdc_metrics.go index 5fe3ea7c3b671..33095f9787e4a 100644 --- a/pkg/util/metric/v2/cdc_metrics.go +++ b/pkg/util/metric/v2/cdc_metrics.go @@ -77,6 +77,43 @@ var ( Help: "Duration of table stream processing rounds", Buckets: prometheus.ExponentialBuckets(0.001, 2, 15), // 1ms to 16s }, []string{"table"}) + + // CdcTableStreamRetryCounter tracks retry attempts by error type and outcome + CdcTableStreamRetryCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "mo", + Subsystem: "cdc", + Name: "table_stream_retry_total", + Help: "Total number of table stream retry attempts by error type and outcome", + }, []string{"table", "error_type", "outcome"}) // outcome: attempted, succeeded, exhausted, failed + + // CdcTableStreamRetryDelayHistogram tracks retry backoff delays + CdcTableStreamRetryDelayHistogram = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "mo", + Subsystem: "cdc", + Name: "table_stream_retry_delay_seconds", + Help: "Retry backoff delay duration for table streams", + Buckets: prometheus.ExponentialBuckets(0.005, 2, 12), // 5ms to 10s + }, []string{"table", "error_type"}) + + // CdcTableStreamAuxiliaryErrorCounter tracks auxiliary errors that don't replace original errors + CdcTableStreamAuxiliaryErrorCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "mo", + Subsystem: "cdc", + Name: "table_stream_auxiliary_error_total", + Help: "Total number of auxiliary errors encountered during retries (preserved original error)", + }, []string{"table", "auxiliary_error_type"}) + + // CdcTableStreamOriginalErrorPreservedCounter tracks when original errors are preserved + CdcTableStreamOriginalErrorPreservedCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "mo", + Subsystem: "cdc", + Name: "table_stream_original_error_preserved_total", + Help: "Total number of times original error was preserved during retries", + }, []string{"table", "original_error_type"}) ) // CDC Data Processing Metrics @@ -265,6 +302,15 @@ var ( Name: "table_last_activity_timestamp", Help: "Unix timestamp of last activity for each table", }, []string{"table"}) + + // CdcTableNoProgressCounter counts rounds where snapshot did not advance + CdcTableNoProgressCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "mo", + Subsystem: "cdc", + Name: "table_snapshot_no_progress_total", + Help: "Number of times a table round observed snapshot timestamp not advancing", + }, []string{"table"}) ) // CDC Initial Sync Metrics @@ -370,6 +416,10 @@ func initCDCMetrics() { registry.MustRegister(CdcTableStreamTotalGauge) registry.MustRegister(CdcTableStreamRoundCounter) registry.MustRegister(CdcTableStreamRoundDuration) + registry.MustRegister(CdcTableStreamRetryCounter) + registry.MustRegister(CdcTableStreamRetryDelayHistogram) + registry.MustRegister(CdcTableStreamAuxiliaryErrorCounter) + registry.MustRegister(CdcTableStreamOriginalErrorPreservedCounter) // Data processing metrics registry.MustRegister(CdcRowsProcessedCounter) @@ -397,6 +447,7 @@ func initCDCMetrics() { registry.MustRegister(CdcHeartbeatCounter) registry.MustRegister(CdcTableStuckGauge) registry.MustRegister(CdcTableLastActivityTimestamp) + registry.MustRegister(CdcTableNoProgressCounter) // Initial sync metrics registry.MustRegister(CdcInitialSyncStatusGauge) diff --git a/pkg/util/metric/v2/dashboard/grafana_dashboard_cdc.go b/pkg/util/metric/v2/dashboard/grafana_dashboard_cdc.go index 1f445f4a07967..50e2886b33998 100644 --- a/pkg/util/metric/v2/dashboard/grafana_dashboard_cdc.go +++ b/pkg/util/metric/v2/dashboard/grafana_dashboard_cdc.go @@ -248,6 +248,59 @@ func (c *DashboardCreator) initCDCTableStreamRow() dashboard.Option { axis.Unit("s"), axis.Min(0), ), + c.withTimeSeries( + "Retry Attempts /s", + 6, + []string{ + `sum(rate(` + c.getMetricWithFilter("mo_cdc_table_stream_retry_total", `outcome="attempted"`) + `[$interval])) by (table, error_type)`, + }, + []string{ + "{{ table }} ({{ error_type }})", + }, + timeseries.Axis(tsaxis.Unit("short")), + ), + c.withTimeSeries( + "Retry Outcomes /s", + 6, + []string{ + `sum(rate(` + c.getMetricWithFilter("mo_cdc_table_stream_retry_total", `outcome!="attempted"`) + `[$interval])) by (table, error_type, outcome)`, + }, + []string{ + "{{ table }} ({{ error_type }}, {{ outcome }})", + }, + timeseries.Axis(tsaxis.Unit("short")), + ), + c.getHistogramWithExtraBy( + "Retry Backoff Delay (s)", + c.getMetricWithFilter("mo_cdc_table_stream_retry_delay_seconds_bucket", ""), + []float64{0.50, 0.90, 0.99}, + 6, + "error_type", + axis.Unit("s"), + axis.Min(0), + ), + c.withTimeSeries( + "Auxiliary Errors /s", + 6, + []string{ + `sum(rate(` + c.getMetricWithFilter("mo_cdc_table_stream_auxiliary_error_total", "") + `[$interval])) by (table, auxiliary_error_type)`, + }, + []string{ + "{{ table }} ({{ auxiliary_error_type }})", + }, + timeseries.Axis(tsaxis.Unit("short")), + ), + c.withTimeSeries( + "Original Error Preserved /s", + 6, + []string{ + `sum(rate(` + c.getMetricWithFilter("mo_cdc_table_stream_original_error_preserved_total", "") + `[$interval])) by (table, original_error_type)`, + }, + []string{ + "{{ table }} ({{ original_error_type }})", + }, + timeseries.Axis(tsaxis.Unit("short")), + ), ) } diff --git a/pkg/util/test/cron_task_test.go b/pkg/util/test/cron_task_test.go index 4476be3a26e3c..69f0a40d30987 100644 --- a/pkg/util/test/cron_task_test.go +++ b/pkg/util/test/cron_task_test.go @@ -100,7 +100,7 @@ func TestCalculateStorageUsage(t *testing.T) { err = mometric.CalculateStorageUsage(ctx, "", ieFactory) require.Nil(t, err) - s := metric.StorageUsage("sys") + s := metric.StorageUsage("sys", 0) dm := &dto.Metric{} s.Write(dm) logutil.Infof("size: %f", dm.GetGauge().GetValue()) diff --git a/pkg/util/trace/impl/motrace/buffer_pipe_test.go b/pkg/util/trace/impl/motrace/buffer_pipe_test.go index 5fea28765ba9f..f0fa7ba19e08a 100644 --- a/pkg/util/trace/impl/motrace/buffer_pipe_test.go +++ b/pkg/util/trace/impl/motrace/buffer_pipe_test.go @@ -532,7 +532,7 @@ log_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000 }, buf: buf, }, - want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 + want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 `, }, { @@ -573,8 +573,8 @@ log_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000 }, buf: buf, }, - want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 -00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 + want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 +00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 `, }, { @@ -651,7 +651,7 @@ func Test_genCsvData_diffAccount(t *testing.T) { buf: buf, }, wantReqCnt: 1, - want: []string{`00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 + want: []string{`00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 `}, }, { @@ -693,8 +693,8 @@ func Test_genCsvData_diffAccount(t *testing.T) { buf: buf, }, wantReqCnt: 1, - want: []string{`00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 -`, `00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,sys,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 + want: []string{`00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 +`, `00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,sys,0,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,0,0,0.0000 `}, }, } @@ -798,9 +798,9 @@ func Test_genCsvData_LongQueryTime(t *testing.T) { buf: buf, queryT: int64(time.Second), }, - want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,999999999,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,1,0,0.0000 -00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,999999999,Running,0,,"{""code"":200,""message"":""no exec plan""}",0,0,"[5,0,0,0,0,0,0,0,0,0,0]",,,0,,0,2,0,0.0000 -00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000000000,Failed,20101,internal error: test error,"{""key"":""val""}",1,1,"[5,1,2.000,3,4,5,0,0,44.0161,0,0]",,,0,internal,0,3,0,44.0161 + want: `00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,999999999,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0,0,0]",,,0,,0,1,0,0.0000 +00000000-0000-0000-0000-000000000001,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,999999999,Running,0,,"{""code"":200,""message"":""no exec plan""}",0,0,"[5,0,0,0,0,0,0,0,0,0,0]",,,0,,0,2,0,0.0000 +00000000-0000-0000-0000-000000000002,00000000000000000000000000000001,00000000-0000-0000-0000-000000000001,MO,0,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000000000,Failed,20101,internal error: test error,"{""key"":""val""}",1,1,"[5,1,2.000,3,4,5,0,0,44.0161,0,0]",,,0,internal,0,3,0,44.0161 `, }, } diff --git a/pkg/util/trace/impl/motrace/report_statement.go b/pkg/util/trace/impl/motrace/report_statement.go index 74d1e05b92177..736fca4829a5a 100644 --- a/pkg/util/trace/impl/motrace/report_statement.go +++ b/pkg/util/trace/impl/motrace/report_statement.go @@ -174,6 +174,7 @@ type StatementInfo struct { SessionID [16]byte `jons:"session_id"` ConnectionId uint32 `json:"connection_id"` Account string `json:"account"` + AccountID uint32 `json:"account_id"` User string `json:"user"` Host string `json:"host"` RoleId uint32 `json:"role_id"` @@ -358,6 +359,7 @@ func (s *StatementInfo) free() { s.SessionID = NilSesID s.ConnectionId = 0 s.Account = "" + s.AccountID = 0 s.User = "" s.Host = "" s.RoleId = 0 @@ -401,6 +403,7 @@ func (s *StatementInfo) CloneWithoutExecPlan() *StatementInfo { stmt.SessionID = s.SessionID stmt.ConnectionId = s.ConnectionId stmt.Account = s.Account + stmt.AccountID = s.AccountID stmt.User = s.User stmt.Host = s.Host stmt.RoleId = s.RoleId @@ -453,6 +456,7 @@ func (s *StatementInfo) FillRow(ctx context.Context, row *table.Row) { } row.SetColumnVal(sesIDCol, table.UuidField(s.SessionID[:])) row.SetColumnVal(accountCol, table.StringField(s.Account)) + row.SetColumnVal(accountIdCol, table.Uint32Field(s.AccountID)) row.SetColumnVal(roleIdCol, table.Int64Field(int64(s.RoleId))) row.SetColumnVal(userCol, table.StringField(s.User)) row.SetColumnVal(hostCol, table.StringField(s.Host)) @@ -679,8 +683,8 @@ func (s *StatementInfo) EndStatement(ctx context.Context, err error, sentRows in s.MarkResponseAt() // --- Start of metric part // duration is filled in s.MarkResponseAt() - incStatementCounter(s.Account, s.QueryType) - addStatementDurationCounter(s.Account, s.QueryType, s.Duration) + incStatementCounter(s.Account, s.AccountID, s.QueryType) + addStatementDurationCounter(s.Account, s.AccountID, s.QueryType, s.Duration) // --- END of metric part if err != nil { outBytes += ResponseErrPacketSize + int64(len(err.Error())) @@ -694,7 +698,7 @@ func (s *StatementInfo) EndStatement(ctx context.Context, err error, sentRows in logutil.Warnf("negative cu: %f, %s", s.statsArray.GetCU(), uuid.UUID(s.StatementID).String()) v2.GetTraceNegativeCUCounter("cu").Inc() } else { - metric.StatementCUCounter(s.Account, s.SqlSourceType).Add(s.statsArray.GetCU()) + metric.StatementCUCounter(s.Account, s.AccountID, s.SqlSourceType).Add(s.statsArray.GetCU()) } s.Status = StatementStatusSuccess if err != nil { @@ -730,11 +734,11 @@ func (s *StatementInfo) CopyStatementInfo() string { return builder.String() } -func addStatementDurationCounter(tenant, queryType string, duration time.Duration) { - metric.StatementDuration(tenant, queryType).Add(float64(duration)) +func addStatementDurationCounter(tenant string, tenantId uint32, queryType string, duration time.Duration) { + metric.StatementDuration(tenant, tenantId, queryType).Add(float64(duration)) } -func incStatementCounter(tenant, queryType string) { - metric.StatementCounter(tenant, queryType).Inc() +func incStatementCounter(tenant string, tenantId uint32, queryType string) { + metric.StatementCounter(tenant, tenantId, queryType).Inc() } type StatementInfoStatus int diff --git a/pkg/util/trace/impl/motrace/schema.go b/pkg/util/trace/impl/motrace/schema.go index 4ddcf2348f901..9ce8e368499e6 100644 --- a/pkg/util/trace/impl/motrace/schema.go +++ b/pkg/util/trace/impl/motrace/schema.go @@ -51,6 +51,7 @@ var ( txnIDCol = table.UuidStringColumn("transaction_id", "txn uniq id") sesIDCol = table.UuidStringColumn("session_id", "session uniq id") accountCol = table.StringColumn("account", "account name") + accountIdCol = table.UInt32Column("account_id", "account id") roleIdCol = table.Int64Column("role_id", "role id") userCol = table.StringColumn("user", "user name") hostCol = table.StringColumn("host", "user client ip") @@ -86,6 +87,7 @@ var ( txnIDCol, sesIDCol, accountCol, + accountIdCol, userCol, hostCol, dbCol, @@ -115,7 +117,7 @@ var ( cuCol, }, PrimaryKeyColumn: nil, - ClusterBy: []table.Column{accountCol, reqAtCol}, + ClusterBy: []table.Column{reqAtCol, accountIdCol}, // Engine Engine: table.NormalTableEngine, Comment: "record each statement and stats info" + catalog.MO_COMMENT_NO_DEL_HINT, diff --git a/pkg/vectorindex/ivfflat/search.go b/pkg/vectorindex/ivfflat/search.go index 003e36b2969ad..7335b03876998 100644 --- a/pkg/vectorindex/ivfflat/search.go +++ b/pkg/vectorindex/ivfflat/search.go @@ -197,7 +197,9 @@ func (idx *IvfflatSearchIndex[T]) Search( return resid, distances, nil } + var rowCount int64 for _, bat := range res.Batches { + rowCount += int64(bat.RowCount()) for i := 0; i < bat.RowCount(); i++ { if bat.Vecs[1].IsNull(uint64(i)) { continue diff --git a/pkg/vectorindex/sqlexec/sqlexec.go b/pkg/vectorindex/sqlexec/sqlexec.go index b2db8f68f1be6..cb87ff1acc5cd 100644 --- a/pkg/vectorindex/sqlexec/sqlexec.go +++ b/pkg/vectorindex/sqlexec/sqlexec.go @@ -72,6 +72,10 @@ func (s *SqlContext) SetResolveVariableFunc(f func(varName string, isSystemVar, type SqlProcess struct { Proc *process.Process SqlCtx *SqlContext + + // Optional BloomFilter bytes attached by vector index runtime. + // Used to drive additional filtering in internal SQL executor (e.g. ivf entries scan). + BloomFilter []byte } func NewSqlProcess(proc *process.Process) *SqlProcess { @@ -117,6 +121,14 @@ func RunSql(sqlproc *SqlProcess, sql string) (executor.Result, error) { //------------------------------------------------------- topContext := proc.GetTopContext() + // Attach optional Ivf BloomFilter to context for internal executor. + if len(sqlproc.BloomFilter) > 0 { + topContext = context.WithValue( + topContext, + defines.IvfBloomFilter{}, + sqlproc.BloomFilter, + ) + } accountId, err := defines.GetAccountId(proc.Ctx) if err != nil { return executor.Result{}, err diff --git a/pkg/vectorindex/types.go b/pkg/vectorindex/types.go index bcd82de42ece0..cffacdc960194 100644 --- a/pkg/vectorindex/types.go +++ b/pkg/vectorindex/types.go @@ -108,6 +108,8 @@ type RuntimeConfig struct { Probe uint OrigFuncName string BackgroundQueries []*plan.Query + // Optional BloomFilter bytes for entries table scan (runtime filter) + BloomFilter []byte } type VectorIndexCdc[T types.RealNumbers] struct { diff --git a/pkg/vm/engine/disttae/txn_table.go b/pkg/vm/engine/disttae/txn_table.go index 07eec5506bc8b..10fd4367aba25 100644 --- a/pkg/vm/engine/disttae/txn_table.go +++ b/pkg/vm/engine/disttae/txn_table.go @@ -2250,13 +2250,20 @@ func (tbl *txnTable) PKPersistedBetween( filter, err := readutil.ConstructBlockPKFilter( catalog.IsFakePkName(tbl.tableDef.Pkey.PkeyColName), basePKFilter, + nil, ) if err != nil { return false, err } buildUnsortedFilter := func() objectio.ReadFilterSearchFuncType { - return LinearSearchOffsetByValFactory(keys) + inner := LinearSearchOffsetByValFactory(keys) + return func(cacheVectors containers.Vectors) []int64 { + if len(cacheVectors) == 0 || cacheVectors[0].Length() == 0 { + return nil + } + return inner(&cacheVectors[0]) + } } cacheVectors := containers.NewVectors(1) @@ -2287,7 +2294,7 @@ func (tbl *txnTable) PKPersistedBetween( searchFunc = buildUnsortedFilter() } - sels := searchFunc(&cacheVectors[0]) + sels := searchFunc(cacheVectors) release() if len(sels) > 0 { return true, nil diff --git a/pkg/vm/engine/readutil/filter_test.go b/pkg/vm/engine/readutil/filter_test.go index 556af0fdf852e..47cafeffa03e2 100644 --- a/pkg/vm/engine/readutil/filter_test.go +++ b/pkg/vm/engine/readutil/filter_test.go @@ -15,6 +15,7 @@ package readutil import ( + "context" "fmt" "math/rand" "slices" @@ -22,6 +23,9 @@ import ( "testing" "time" + "github.com/matrixorigin/matrixone/pkg/common/moerr" + + "github.com/matrixorigin/matrixone/pkg/common/bloomfilter" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" @@ -31,6 +35,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/sql/plan/function" "github.com/matrixorigin/matrixone/pkg/testutil" "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" "github.com/stretchr/testify/require" ) @@ -1072,6 +1077,7 @@ func TestConstructBlockPKFilter(t *testing.T) { blkPKFilter, err := ConstructBlockPKFilter( false, basePKFilter, + nil, ) require.NoError(t, err) @@ -1240,8 +1246,9 @@ func TestConstructBlockPKFilter(t *testing.T) { basePKFilter.String(), common.MoVectorToString(inputVec, 100)) - sel1 := blkPKFilter.SortedSearchFunc(inputVec) - sel2 := blkPKFilter.UnSortedSearchFunc(inputVec) + cacheVectors := containers.Vectors{*inputVec} + sel1 := blkPKFilter.SortedSearchFunc(cacheVectors) + sel2 := blkPKFilter.UnSortedSearchFunc(cacheVectors) require.Equal(t, sel1, sel2, msg) } @@ -1539,3 +1546,388 @@ func TestMergeBaseFilterInKind(t *testing.T) { } } } + +// TestConstructBlockPKFilterWithBloomFilter tests the BloomFilter integration +// with composite and non-composite primary keys (lines 482-803 in pk_filter.go) +func TestConstructBlockPKFilterWithBloomFilter(t *testing.T) { + mp := mpool.MustNewZero() + + // Helper function to create a composite primary key vector + createCompositePKVec := func(tuples [][]any, mp *mpool.MPool) *vector.Vector { + vec := vector.NewVec(types.T_varchar.ToType()) + packer := types.NewPacker() + defer packer.Close() + + for _, tuple := range tuples { + packer.Reset() + for _, val := range tuple { + switch v := val.(type) { + case int8: + packer.EncodeInt8(v) + case int16: + packer.EncodeInt16(v) + case int32: + packer.EncodeInt32(v) + case int64: + packer.EncodeInt64(v) + case uint8: + packer.EncodeUint8(v) + case uint16: + packer.EncodeUint16(v) + case uint32: + packer.EncodeUint32(v) + case uint64: + packer.EncodeUint64(v) + case string: + packer.EncodeStringType([]byte(v)) + case []byte: + packer.EncodeStringType(v) + default: + t.Fatalf("unsupported type: %T", v) + } + } + vector.AppendBytes(vec, packer.Bytes(), false, mp) + } + return vec + } + + // Helper function to create a BloomFilter with values + createBloomFilter := func(values []any, mp *mpool.MPool) ([]byte, error) { + // Create a vector with the last column values from composite PK + // For non-composite PK, use the values directly + vec := vector.NewVec(types.T_int64.ToType()) + for _, val := range values { + switch v := val.(type) { + case int64: + vector.AppendFixed(vec, v, false, mp) + case int32: + vector.AppendFixed(vec, int64(v), false, mp) + case int16: + vector.AppendFixed(vec, int64(v), false, mp) + case int8: + vector.AppendFixed(vec, int64(v), false, mp) + default: + vec.Free(mp) + return nil, moerr.NewInvalidInputf(context.Background(), "unsupported type for BF: %T", v) + } + } + + // Use larger capacity to reduce false positive rate + // For small value sets, use at least 100 capacity to get better accuracy + capacity := int64(len(values)) + if capacity < 100 { + capacity = 100 + } + bf := bloomfilter.New(capacity, 0.001) // Use lower false positive rate + bf.Add(vec) + vec.Free(mp) + + return bf.Marshal() + } + + t.Run("non-composite PK with BloomFilter only", func(t *testing.T) { + // Create BloomFilter with values [10, 20, 30] + bfData, err := createBloomFilter([]any{int64(10), int64(20), int64(30)}, mp) + require.NoError(t, err) + + // Create input vector with values [5, 10, 15, 20, 25, 30, 35] + inputVec := vector.NewVec(types.T_int64.ToType()) + for _, v := range []int64{5, 10, 15, 20, 25, 30, 35} { + vector.AppendFixed(inputVec, v, false, mp) + } + defer inputVec.Free(mp) + + // Create filter with only BloomFilter (no base filter) + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + require.True(t, readFilter.Valid) + require.NotNil(t, readFilter.UnSortedSearchFunc) + + // Test the search function + // For non-composite PK, we still need len(cacheVectors) >= 2 to match the function signature + // Use the same vector for both positions (PK column) + cacheVectors := containers.Vectors{*inputVec, *inputVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + // Should return indices of values that exist in BF: [10, 20, 30] -> indices [1, 3, 5] + require.Equal(t, []int64{1, 3, 5}, result) + }) + + t.Run("composite PK with BloomFilter only - int64 last column", func(t *testing.T) { + // Create composite PK tuples: (col1, col2, lastCol) + // We'll extract lastCol values: [100, 200, 300] + tuples := [][]any{ + {int32(1), int32(2), int64(100)}, + {int32(1), int32(3), int64(200)}, + {int32(2), int32(1), int64(300)}, + } + + compositePKVec := createCompositePKVec(tuples, mp) + defer compositePKVec.Free(mp) + + // Create BloomFilter with last column values [100, 200, 300] + bfData, err := createBloomFilter([]any{int64(100), int64(200), int64(300)}, mp) + require.NoError(t, err) + + // Create filter with only BloomFilter + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + require.True(t, readFilter.Valid) + require.NotNil(t, readFilter.UnSortedSearchFunc) + + // Test the search function with optimization (len(cacheVectors) >= 2) + // Create last column vector for optimization + lastColVec := vector.NewVec(types.T_int64.ToType()) + for _, tuple := range tuples { + lastVal := tuple[len(tuple)-1].(int64) + vector.AppendFixed(lastColVec, lastVal, false, mp) + } + defer lastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *lastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + // Should return all indices [0, 1, 2] since all last columns match + require.Equal(t, []int64{0, 1, 2}, result) + }) + + t.Run("composite PK with BloomFilter - partial match", func(t *testing.T) { + // Create composite PK tuples with last column values: [100, 200, 300, 400] + tuples := [][]any{ + {int32(1), int32(2), int64(100)}, + {int32(1), int32(3), int64(200)}, + {int32(2), int32(1), int64(300)}, + {int32(2), int32(2), int64(400)}, + } + + compositePKVec := createCompositePKVec(tuples, mp) + defer compositePKVec.Free(mp) + + // Create BloomFilter with only [100, 300] (partial match) + bfData, err := createBloomFilter([]any{int64(100), int64(300)}, mp) + require.NoError(t, err) + + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + + // Create last column vector for optimization + lastColVec := vector.NewVec(types.T_int64.ToType()) + for _, tuple := range tuples { + lastVal := tuple[len(tuple)-1].(int64) + vector.AppendFixed(lastColVec, lastVal, false, mp) + } + defer lastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *lastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + // Should return indices containing [0, 2] for values 100 and 300 + // Note: BloomFilter may have false positives, so we check that it contains the expected indices + require.Contains(t, result, int64(0), "Should contain index 0 (value 100)") + require.Contains(t, result, int64(2), "Should contain index 2 (value 300)") + require.GreaterOrEqual(t, len(result), 2, "Should have at least 2 matches") + }) + + t.Run("composite PK with BloomFilter - no match", func(t *testing.T) { + tuples := [][]any{ + {int32(1), int32(2), int64(100)}, + {int32(1), int32(3), int64(200)}, + } + + compositePKVec := createCompositePKVec(tuples, mp) + defer compositePKVec.Free(mp) + + // Create BloomFilter with values that don't match: [999, 888] + bfData, err := createBloomFilter([]any{int64(999), int64(888)}, mp) + require.NoError(t, err) + + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + + // Create last column vector for optimization + lastColVec := vector.NewVec(types.T_int64.ToType()) + for _, tuple := range tuples { + lastVal := tuple[len(tuple)-1].(int64) + vector.AppendFixed(lastColVec, lastVal, false, mp) + } + defer lastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *lastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + // Should return empty slice since no matches (not nil, but empty slice) + require.Empty(t, result) + }) + + t.Run("composite PK with BloomFilter and base filter (wrap function)", func(t *testing.T) { + // Note: For composite PK, base filter operates on the entire composite key (VARCHAR type), + // while BloomFilter operates on the last column (__mo_index_pri_col). + // These two filters cannot be combined in the same way as non-composite PK. + // This test verifies that when both are provided, the code handles it gracefully. + // In practice, for composite PK with BloomFilter, base filter should typically be disabled. + + // Create composite PK tuples + tuples := [][]any{ + {int32(1), int32(2), int64(100)}, + {int32(1), int32(3), int64(200)}, + {int32(2), int32(1), int64(300)}, + {int32(2), int32(2), int64(400)}, + } + + compositePKVec := createCompositePKVec(tuples, mp) + defer compositePKVec.Free(mp) + + // Create BloomFilter with [100, 200, 300] + bfData, err := createBloomFilter([]any{int64(100), int64(200), int64(300)}, mp) + require.NoError(t, err) + + // For composite PK, base filter should have Oid = T_varchar (the composite key type) + // But since we're testing BloomFilter which operates on the last column, + // we disable base filter to avoid type mismatch + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + require.True(t, readFilter.Valid) + + // With only BloomFilter, should return indices 0, 1, 2 (values 100, 200, 300) + // Create last column vector for optimization + lastColVec := vector.NewVec(types.T_int64.ToType()) + for _, tuple := range tuples { + lastVal := tuple[len(tuple)-1].(int64) + vector.AppendFixed(lastColVec, lastVal, false, mp) + } + defer lastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *lastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + require.NotNil(t, result) + require.Contains(t, result, int64(0), "Should contain index 0 (value 100)") + require.Contains(t, result, int64(1), "Should contain index 1 (value 200)") + require.Contains(t, result, int64(2), "Should contain index 2 (value 300)") + require.GreaterOrEqual(t, len(result), 3, "Should have at least 3 matches") + }) + + t.Run("composite PK with different last column types - int32", func(t *testing.T) { + tuples := [][]any{ + {int32(1), int32(2), int32(100)}, + {int32(1), int32(3), int32(200)}, + } + + compositePKVec := createCompositePKVec(tuples, mp) + defer compositePKVec.Free(mp) + + // Create BloomFilter with int32 values (converted to int64 for BF) + bfData, err := createBloomFilter([]any{int64(100), int64(200)}, mp) + require.NoError(t, err) + + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + + // Create last column vector for optimization + lastColVec := vector.NewVec(types.T_int32.ToType()) + for _, tuple := range tuples { + lastVal := tuple[len(tuple)-1].(int32) + vector.AppendFixed(lastColVec, lastVal, false, mp) + } + defer lastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *lastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + require.Equal(t, []int64{0, 1}, result) + }) + + t.Run("empty composite PK vector", func(t *testing.T) { + compositePKVec := vector.NewVec(types.T_varchar.ToType()) + defer compositePKVec.Free(mp) + + bfData, err := createBloomFilter([]any{int64(100)}, mp) + require.NoError(t, err) + + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + + // For empty vector, optimization path should return nil + emptyLastColVec := vector.NewVec(types.T_int64.ToType()) + defer emptyLastColVec.Free(mp) + cacheVectors := containers.Vectors{*compositePKVec, *emptyLastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + require.Nil(t, result) + }) + + t.Run("composite PK with invalid tuple data", func(t *testing.T) { + // Create a vector with invalid composite PK data + vec := vector.NewVec(types.T_varchar.ToType()) + // Append invalid data (not a valid tuple) + vector.AppendBytes(vec, []byte("invalid"), false, mp) + defer vec.Free(mp) + + bfData, err := createBloomFilter([]any{int64(100)}, mp) + require.NoError(t, err) + + basePKFilter := BasePKFilter{ + Valid: false, + } + + readFilter, err := ConstructBlockPKFilter( + false, + basePKFilter, + bfData, + ) + require.NoError(t, err) + + // Should handle invalid data gracefully + // For invalid data, optimization path should return nil + invalidLastColVec := vector.NewVec(types.T_int64.ToType()) + defer invalidLastColVec.Free(mp) + cacheVectors := containers.Vectors{*vec, *invalidLastColVec} + result := readFilter.UnSortedSearchFunc(cacheVectors) + // Should return nil or empty since extraction fails + require.Nil(t, result) + }) +} diff --git a/pkg/vm/engine/readutil/pk_filter.go b/pkg/vm/engine/readutil/pk_filter.go index c51cdf7c3bbb8..20a9fc6d0f8e0 100644 --- a/pkg/vm/engine/readutil/pk_filter.go +++ b/pkg/vm/engine/readutil/pk_filter.go @@ -16,12 +16,15 @@ package readutil import ( "bytes" + + "github.com/matrixorigin/matrixone/pkg/common/bloomfilter" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/logutil" "github.com/matrixorigin/matrixone/pkg/objectio" "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" "go.uber.org/zap" ) @@ -50,414 +53,557 @@ func DirectConstructBlockPKFilter( func ConstructBlockPKFilter( isFakePK bool, basePKFilter BasePKFilter, + bloomFilter []byte, ) (f objectio.BlockReadFilter, err error) { - if !basePKFilter.Valid { + if !basePKFilter.Valid && len(bloomFilter) == 0 { return objectio.BlockReadFilter{}, nil } var readFilter objectio.BlockReadFilter var sortedSearchFunc, unSortedSearchFunc func(*vector.Vector) []int64 - readFilter.HasFakePK = isFakePK - - switch basePKFilter.Op { - case function.EQUAL: - switch basePKFilter.Oid { - case types.T_int8: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int8{types.DecodeInt8(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int8{types.DecodeInt8(basePKFilter.LB)}, nil) - case types.T_int16: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int16{types.DecodeInt16(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int16{types.DecodeInt16(basePKFilter.LB)}, nil) - case types.T_int32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int32{types.DecodeInt32(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int32{types.DecodeInt32(basePKFilter.LB)}, nil) - case types.T_int64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int64{types.DecodeInt64(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int64{types.DecodeInt64(basePKFilter.LB)}, nil) - case types.T_float32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]float32{types.DecodeFloat32(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]float32{types.DecodeFloat32(basePKFilter.LB)}, nil) - case types.T_float64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]float64{types.DecodeFloat64(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]float64{types.DecodeFloat64(basePKFilter.LB)}, nil) - case types.T_uint8: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint8{uint8(types.DecodeUint8(basePKFilter.LB))}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint8{uint8(types.DecodeUint8(basePKFilter.LB))}, nil) - case types.T_uint16: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint16{uint16(types.DecodeUint16(basePKFilter.LB))}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint16{uint16(types.DecodeUint16(basePKFilter.LB))}, nil) - case types.T_uint32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint32{types.DecodeUint32(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint32{types.DecodeUint32(basePKFilter.LB)}, nil) - case types.T_uint64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint64{types.DecodeUint64(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint64{types.DecodeUint64(basePKFilter.LB)}, nil) - case types.T_date: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Date{types.DecodeDate(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Date{types.DecodeDate(basePKFilter.LB)}, nil) - case types.T_time: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Time{types.DecodeTime(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Time{types.DecodeTime(basePKFilter.LB)}, nil) - case types.T_datetime: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Datetime{types.DecodeDatetime(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Datetime{types.DecodeDatetime(basePKFilter.LB)}, nil) - case types.T_timestamp: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Timestamp{types.DecodeTimestamp(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Timestamp{types.DecodeTimestamp(basePKFilter.LB)}, nil) - case types.T_decimal64: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Decimal64{types.DecodeDecimal64(basePKFilter.LB)}, types.CompareDecimal64) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Decimal64{types.DecodeDecimal64(basePKFilter.LB)}, types.CompareDecimal64) - case types.T_decimal128: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Decimal128{types.DecodeDecimal128(basePKFilter.LB)}, types.CompareDecimal128) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Decimal128{types.DecodeDecimal128(basePKFilter.LB)}, types.CompareDecimal128) - case types.T_varchar, types.T_char, types.T_binary, types.T_json: - sortedSearchFunc = vector.VarlenBinarySearchOffsetByValFactory([][]byte{basePKFilter.LB}) - unSortedSearchFunc = vector.VarlenLinearSearchOffsetByValFactory([][]byte{basePKFilter.LB}) - case types.T_enum: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Enum{types.DecodeEnum(basePKFilter.LB)}) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Enum{types.DecodeEnum(basePKFilter.LB)}, nil) - case types.T_uuid: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Uuid{types.Uuid(basePKFilter.LB)}, types.CompareUuid) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Uuid{types.Uuid(basePKFilter.LB)}, types.CompareUuid) - default: - } + if basePKFilter.Valid { + readFilter.HasFakePK = isFakePK - case function.PREFIX_EQ: - sortedSearchFunc = vector.CollectOffsetsByPrefixEqFactory(basePKFilter.LB) - unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixEqFactory(basePKFilter.LB) - - case function.PREFIX_BETWEEN: - sortedSearchFunc = vector.CollectOffsetsByPrefixBetweenFactory(basePKFilter.LB, basePKFilter.UB) - unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixBetweenFactory(basePKFilter.LB, basePKFilter.UB) - - case function.IN: - vec := basePKFilter.Vec - - switch vec.GetType().Oid { - case types.T_bit: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec), nil) - case types.T_int8: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int8](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int8](vec), nil) - case types.T_int16: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int16](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int16](vec), nil) - case types.T_int32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int32](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int32](vec), nil) - case types.T_int64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int64](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int64](vec), nil) - case types.T_uint8: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint8](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint8](vec), nil) - case types.T_uint16: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint16](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint16](vec), nil) - case types.T_uint32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint32](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint32](vec), nil) - case types.T_uint64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec), nil) - case types.T_float32: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float32](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float32](vec), nil) - case types.T_float64: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float64](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float64](vec), nil) - case types.T_date: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Date](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Date](vec), nil) - case types.T_time: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Time](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Time](vec), nil) - case types.T_datetime: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Datetime](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Datetime](vec), nil) - case types.T_timestamp: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Timestamp](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Timestamp](vec), nil) - case types.T_decimal64: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal64](vec), types.CompareDecimal64) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal64](vec), types.CompareDecimal64) - case types.T_decimal128: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal128](vec), types.CompareDecimal128) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal128](vec), types.CompareDecimal128) - case types.T_char, types.T_varchar, types.T_binary, types.T_varbinary, types.T_json, types.T_blob, types.T_text, - types.T_array_float32, types.T_array_float64, types.T_datalink: - sortedSearchFunc = vector.VarlenBinarySearchOffsetByValFactory(vector.InefficientMustBytesCol(vec)) - unSortedSearchFunc = vector.VarlenLinearSearchOffsetByValFactory(vector.InefficientMustBytesCol(vec)) - case types.T_enum: - sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Enum](vec)) - unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Enum](vec), nil) - case types.T_uuid: - sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Uuid](vec), types.CompareUuid) - unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Uuid](vec), types.CompareUuid) - default: - } + switch basePKFilter.Op { + case function.EQUAL: + switch basePKFilter.Oid { + case types.T_int8: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int8{types.DecodeInt8(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int8{types.DecodeInt8(basePKFilter.LB)}, nil) + case types.T_int16: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int16{types.DecodeInt16(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int16{types.DecodeInt16(basePKFilter.LB)}, nil) + case types.T_int32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int32{types.DecodeInt32(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int32{types.DecodeInt32(basePKFilter.LB)}, nil) + case types.T_int64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]int64{types.DecodeInt64(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]int64{types.DecodeInt64(basePKFilter.LB)}, nil) + case types.T_float32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]float32{types.DecodeFloat32(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]float32{types.DecodeFloat32(basePKFilter.LB)}, nil) + case types.T_float64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]float64{types.DecodeFloat64(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]float64{types.DecodeFloat64(basePKFilter.LB)}, nil) + case types.T_uint8: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint8{uint8(types.DecodeUint8(basePKFilter.LB))}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint8{uint8(types.DecodeUint8(basePKFilter.LB))}, nil) + case types.T_uint16: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint16{uint16(types.DecodeUint16(basePKFilter.LB))}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint16{uint16(types.DecodeUint16(basePKFilter.LB))}, nil) + case types.T_uint32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint32{types.DecodeUint32(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint32{types.DecodeUint32(basePKFilter.LB)}, nil) + case types.T_uint64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]uint64{types.DecodeUint64(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]uint64{types.DecodeUint64(basePKFilter.LB)}, nil) + case types.T_date: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Date{types.DecodeDate(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Date{types.DecodeDate(basePKFilter.LB)}, nil) + case types.T_time: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Time{types.DecodeTime(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Time{types.DecodeTime(basePKFilter.LB)}, nil) + case types.T_datetime: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Datetime{types.DecodeDatetime(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Datetime{types.DecodeDatetime(basePKFilter.LB)}, nil) + case types.T_timestamp: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Timestamp{types.DecodeTimestamp(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Timestamp{types.DecodeTimestamp(basePKFilter.LB)}, nil) + case types.T_decimal64: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Decimal64{types.DecodeDecimal64(basePKFilter.LB)}, types.CompareDecimal64) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Decimal64{types.DecodeDecimal64(basePKFilter.LB)}, types.CompareDecimal64) + case types.T_decimal128: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Decimal128{types.DecodeDecimal128(basePKFilter.LB)}, types.CompareDecimal128) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Decimal128{types.DecodeDecimal128(basePKFilter.LB)}, types.CompareDecimal128) + case types.T_varchar, types.T_char, types.T_binary, types.T_json: + sortedSearchFunc = vector.VarlenBinarySearchOffsetByValFactory([][]byte{basePKFilter.LB}) + unSortedSearchFunc = vector.VarlenLinearSearchOffsetByValFactory([][]byte{basePKFilter.LB}) + case types.T_enum: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory([]types.Enum{types.DecodeEnum(basePKFilter.LB)}) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory([]types.Enum{types.DecodeEnum(basePKFilter.LB)}, nil) + case types.T_uuid: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory([]types.Uuid{types.Uuid(basePKFilter.LB)}, types.CompareUuid) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory([]types.Uuid{types.Uuid(basePKFilter.LB)}, types.CompareUuid) + default: + } - case function.PREFIX_IN: - vec := basePKFilter.Vec - - sortedSearchFunc = vector.CollectOffsetsByPrefixInFactory(vec) - unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixInFactory(vec) - - case function.LESS_EQUAL, function.LESS_THAN: - closed := basePKFilter.Op == function.LESS_EQUAL - switch basePKFilter.Oid { - case types.T_int8: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt8(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt8(basePKFilter.LB), closed, false) - case types.T_int16: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt16(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt16(basePKFilter.LB), closed, false) - case types.T_int32: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt32(basePKFilter.LB), closed, false) - case types.T_int64: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt64(basePKFilter.LB), closed, false) - case types.T_float32: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat32(basePKFilter.LB), closed, false) - case types.T_float64: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat64(basePKFilter.LB), closed, false) - case types.T_uint8: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint8(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint8(basePKFilter.LB), closed, false) - case types.T_uint16: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint16(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint16(basePKFilter.LB), closed, false) - case types.T_uint32: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint32(basePKFilter.LB), closed, false) - case types.T_uint64: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint64(basePKFilter.LB), closed, false) - case types.T_date: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDate(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDate(basePKFilter.LB), closed, false) - case types.T_time: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTime(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTime(basePKFilter.LB), closed, false) - case types.T_datetime: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDatetime(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDatetime(basePKFilter.LB), closed, false) - case types.T_timestamp: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTimestamp(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTimestamp(basePKFilter.LB), closed, false) - case types.T_decimal64: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, true, types.CompareDecimal64) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, false, types.CompareDecimal64) - case types.T_decimal128: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, true, types.CompareDecimal128) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, false, types.CompareDecimal128) - case types.T_varchar, types.T_char, types.T_binary, types.T_json: - sortedSearchFunc = vector.VarlenSearchOffsetByLess(basePKFilter.LB, closed, true) - unSortedSearchFunc = vector.VarlenSearchOffsetByLess(basePKFilter.LB, closed, false) - case types.T_enum: - sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeEnum(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeEnum(basePKFilter.LB), closed, false) - case types.T_uuid: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.Uuid(basePKFilter.LB), closed, true, types.CompareUuid) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.Uuid(basePKFilter.LB), closed, false, types.CompareUuid) - default: - } + case function.PREFIX_EQ: + sortedSearchFunc = vector.CollectOffsetsByPrefixEqFactory(basePKFilter.LB) + unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixEqFactory(basePKFilter.LB) + + case function.PREFIX_BETWEEN: + sortedSearchFunc = vector.CollectOffsetsByPrefixBetweenFactory(basePKFilter.LB, basePKFilter.UB) + unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixBetweenFactory(basePKFilter.LB, basePKFilter.UB) + + case function.IN: + vec := basePKFilter.Vec + + switch vec.GetType().Oid { + case types.T_bit: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec), nil) + case types.T_int8: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int8](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int8](vec), nil) + case types.T_int16: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int16](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int16](vec), nil) + case types.T_int32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int32](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int32](vec), nil) + case types.T_int64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int64](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[int64](vec), nil) + case types.T_uint8: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint8](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint8](vec), nil) + case types.T_uint16: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint16](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint16](vec), nil) + case types.T_uint32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint32](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint32](vec), nil) + case types.T_uint64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[uint64](vec), nil) + case types.T_float32: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float32](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float32](vec), nil) + case types.T_float64: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float64](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[float64](vec), nil) + case types.T_date: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Date](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Date](vec), nil) + case types.T_time: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Time](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Time](vec), nil) + case types.T_datetime: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Datetime](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Datetime](vec), nil) + case types.T_timestamp: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Timestamp](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Timestamp](vec), nil) + case types.T_decimal64: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal64](vec), types.CompareDecimal64) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal64](vec), types.CompareDecimal64) + case types.T_decimal128: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal128](vec), types.CompareDecimal128) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Decimal128](vec), types.CompareDecimal128) + case types.T_char, types.T_varchar, types.T_binary, types.T_varbinary, types.T_json, types.T_blob, types.T_text, + types.T_array_float32, types.T_array_float64, types.T_datalink: + sortedSearchFunc = vector.VarlenBinarySearchOffsetByValFactory(vector.InefficientMustBytesCol(vec)) + unSortedSearchFunc = vector.VarlenLinearSearchOffsetByValFactory(vector.InefficientMustBytesCol(vec)) + case types.T_enum: + sortedSearchFunc = vector.OrderedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Enum](vec)) + unSortedSearchFunc = vector.OrderedLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Enum](vec), nil) + case types.T_uuid: + sortedSearchFunc = vector.FixedSizedBinarySearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Uuid](vec), types.CompareUuid) + unSortedSearchFunc = vector.FixedSizeLinearSearchOffsetByValFactory(vector.MustFixedColNoTypeCheck[types.Uuid](vec), types.CompareUuid) + default: + } + + case function.PREFIX_IN: + vec := basePKFilter.Vec + + sortedSearchFunc = vector.CollectOffsetsByPrefixInFactory(vec) + unSortedSearchFunc = vector.LinearCollectOffsetsByPrefixInFactory(vec) + + case function.LESS_EQUAL, function.LESS_THAN: + closed := basePKFilter.Op == function.LESS_EQUAL + switch basePKFilter.Oid { + case types.T_int8: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt8(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt8(basePKFilter.LB), closed, false) + case types.T_int16: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt16(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt16(basePKFilter.LB), closed, false) + case types.T_int32: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt32(basePKFilter.LB), closed, false) + case types.T_int64: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeInt64(basePKFilter.LB), closed, false) + case types.T_float32: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat32(basePKFilter.LB), closed, false) + case types.T_float64: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeFloat64(basePKFilter.LB), closed, false) + case types.T_uint8: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint8(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint8(basePKFilter.LB), closed, false) + case types.T_uint16: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint16(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint16(basePKFilter.LB), closed, false) + case types.T_uint32: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint32(basePKFilter.LB), closed, false) + case types.T_uint64: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeUint64(basePKFilter.LB), closed, false) + case types.T_date: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDate(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDate(basePKFilter.LB), closed, false) + case types.T_time: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTime(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTime(basePKFilter.LB), closed, false) + case types.T_datetime: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDatetime(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeDatetime(basePKFilter.LB), closed, false) + case types.T_timestamp: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTimestamp(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeTimestamp(basePKFilter.LB), closed, false) + case types.T_decimal64: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, true, types.CompareDecimal64) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, false, types.CompareDecimal64) + case types.T_decimal128: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, true, types.CompareDecimal128) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, false, types.CompareDecimal128) + case types.T_varchar, types.T_char, types.T_binary, types.T_json: + sortedSearchFunc = vector.VarlenSearchOffsetByLess(basePKFilter.LB, closed, true) + unSortedSearchFunc = vector.VarlenSearchOffsetByLess(basePKFilter.LB, closed, false) + case types.T_enum: + sortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeEnum(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByLess(types.DecodeEnum(basePKFilter.LB), closed, false) + case types.T_uuid: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.Uuid(basePKFilter.LB), closed, true, types.CompareUuid) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByLessTypeChecked(types.Uuid(basePKFilter.LB), closed, false, types.CompareUuid) + default: + } + + case function.GREAT_EQUAL, function.GREAT_THAN: + closed := basePKFilter.Op == function.GREAT_EQUAL + switch basePKFilter.Oid { + case types.T_int8: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt8(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt8(basePKFilter.LB), closed, false) + case types.T_int16: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt16(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt16(basePKFilter.LB), closed, false) + case types.T_int32: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt32(basePKFilter.LB), closed, false) + case types.T_int64: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt64(basePKFilter.LB), closed, false) + case types.T_float32: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat32(basePKFilter.LB), closed, false) + case types.T_float64: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat64(basePKFilter.LB), closed, false) + case types.T_uint8: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint8(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint8(basePKFilter.LB), closed, false) + case types.T_uint16: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint16(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint16(basePKFilter.LB), closed, false) + case types.T_uint32: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint32(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint32(basePKFilter.LB), closed, false) + case types.T_uint64: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint64(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint64(basePKFilter.LB), closed, false) + case types.T_date: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDate(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDate(basePKFilter.LB), closed, false) + case types.T_time: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTime(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTime(basePKFilter.LB), closed, false) + case types.T_datetime: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDatetime(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDatetime(basePKFilter.LB), closed, false) + case types.T_timestamp: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTimestamp(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTimestamp(basePKFilter.LB), closed, false) + case types.T_decimal64: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, true, types.CompareDecimal64) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, false, types.CompareDecimal64) + case types.T_decimal128: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, true, types.CompareDecimal128) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, false, types.CompareDecimal128) + case types.T_varchar, types.T_char, types.T_json, types.T_binary: + sortedSearchFunc = vector.VarlenSearchOffsetByGreat(basePKFilter.LB, closed, true) + unSortedSearchFunc = vector.VarlenSearchOffsetByGreat(basePKFilter.LB, closed, false) + case types.T_enum: + sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeEnum(basePKFilter.LB), closed, true) + unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeEnum(basePKFilter.LB), closed, false) + case types.T_uuid: + sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.Uuid(basePKFilter.LB), closed, true, types.CompareUuid) + unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.Uuid(basePKFilter.LB), closed, false, types.CompareUuid) + default: + } - case function.GREAT_EQUAL, function.GREAT_THAN: - closed := basePKFilter.Op == function.GREAT_EQUAL - switch basePKFilter.Oid { - case types.T_int8: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt8(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt8(basePKFilter.LB), closed, false) - case types.T_int16: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt16(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt16(basePKFilter.LB), closed, false) - case types.T_int32: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt32(basePKFilter.LB), closed, false) - case types.T_int64: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeInt64(basePKFilter.LB), closed, false) - case types.T_float32: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat32(basePKFilter.LB), closed, false) - case types.T_float64: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeFloat64(basePKFilter.LB), closed, false) - case types.T_uint8: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint8(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint8(basePKFilter.LB), closed, false) - case types.T_uint16: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint16(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint16(basePKFilter.LB), closed, false) - case types.T_uint32: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint32(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint32(basePKFilter.LB), closed, false) - case types.T_uint64: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint64(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeUint64(basePKFilter.LB), closed, false) - case types.T_date: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDate(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDate(basePKFilter.LB), closed, false) - case types.T_time: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTime(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTime(basePKFilter.LB), closed, false) - case types.T_datetime: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDatetime(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeDatetime(basePKFilter.LB), closed, false) - case types.T_timestamp: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTimestamp(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeTimestamp(basePKFilter.LB), closed, false) - case types.T_decimal64: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, true, types.CompareDecimal64) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal64(basePKFilter.LB), closed, false, types.CompareDecimal64) - case types.T_decimal128: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, true, types.CompareDecimal128) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.DecodeDecimal128(basePKFilter.LB), closed, false, types.CompareDecimal128) - case types.T_varchar, types.T_char, types.T_json, types.T_binary: - sortedSearchFunc = vector.VarlenSearchOffsetByGreat(basePKFilter.LB, closed, true) - unSortedSearchFunc = vector.VarlenSearchOffsetByGreat(basePKFilter.LB, closed, false) - case types.T_enum: - sortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeEnum(basePKFilter.LB), closed, true) - unSortedSearchFunc = vector.OrderedSearchOffsetsByGreat(types.DecodeEnum(basePKFilter.LB), closed, false) - case types.T_uuid: - sortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.Uuid(basePKFilter.LB), closed, true, types.CompareUuid) - unSortedSearchFunc = vector.FixedSizeSearchOffsetsByGTTypeChecked(types.Uuid(basePKFilter.LB), closed, false, types.CompareUuid) - default: + case function.BETWEEN, RangeLeftOpen, RangeRightOpen, RangeBothOpen: + var hint int + switch basePKFilter.Op { + case function.BETWEEN: + hint = 0 + case RangeLeftOpen: + hint = 1 + case RangeRightOpen: + hint = 2 + case RangeBothOpen: + hint = 3 + } + switch basePKFilter.Oid { + case types.T_int8: + lb := types.DecodeInt8(basePKFilter.LB) + ub := types.DecodeInt8(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_int16: + lb := types.DecodeInt16(basePKFilter.LB) + ub := types.DecodeInt16(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_int32: + lb := types.DecodeInt32(basePKFilter.LB) + ub := types.DecodeInt32(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_int64: + lb := types.DecodeInt64(basePKFilter.LB) + ub := types.DecodeInt64(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_float32: + lb := types.DecodeFloat32(basePKFilter.LB) + ub := types.DecodeFloat32(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_float64: + lb := types.DecodeFloat64(basePKFilter.LB) + ub := types.DecodeFloat64(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_uint8: + lb := types.DecodeUint8(basePKFilter.LB) + ub := types.DecodeUint8(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_uint16: + lb := types.DecodeUint16(basePKFilter.LB) + ub := types.DecodeUint16(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_uint32: + lb := types.DecodeUint32(basePKFilter.LB) + ub := types.DecodeUint32(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_uint64: + lb := types.DecodeUint64(basePKFilter.LB) + ub := types.DecodeUint64(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_date: + lb := types.DecodeDate(basePKFilter.LB) + ub := types.DecodeDate(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_time: + lb := types.DecodeTime(basePKFilter.LB) + ub := types.DecodeTime(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_datetime: + lb := types.DecodeDatetime(basePKFilter.LB) + ub := types.DecodeDatetime(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_timestamp: + lb := types.DecodeTimestamp(basePKFilter.LB) + ub := types.DecodeTimestamp(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + case types.T_decimal64: + val1 := types.DecodeDecimal64(basePKFilter.LB) + val2 := types.DecodeDecimal64(basePKFilter.UB) + + sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareDecimal64) + unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareDecimal64) + case types.T_decimal128: + val1 := types.DecodeDecimal128(basePKFilter.LB) + val2 := types.DecodeDecimal128(basePKFilter.UB) + + sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareDecimal128) + unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareDecimal128) + case types.T_text, types.T_datalink, types.T_varchar, types.T_char, types.T_binary, types.T_json: + lb := string(basePKFilter.LB) + ub := string(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenString(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenString(lb, ub, hint) + case types.T_enum: + lb := types.DecodeEnum(basePKFilter.LB) + ub := types.DecodeEnum(basePKFilter.UB) + sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) + unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) + + case types.T_uuid: + val1 := types.Uuid(basePKFilter.LB) + val2 := types.Uuid(basePKFilter.UB) + + sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareUuid) + unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareUuid) + default: + } } + } - case function.BETWEEN, RangeLeftOpen, RangeRightOpen, RangeBothOpen: - var hint int - switch basePKFilter.Op { - case function.BETWEEN: - hint = 0 - case RangeLeftOpen: - hint = 1 - case RangeRightOpen: - hint = 2 - case RangeBothOpen: - hint = 3 + // If no BloomFilter, keep original behavior: only use BasePKFilter's search functions. + // Wrap the inner functions to match the new signature + wrapInner := func(inner func(*vector.Vector) []int64) func(containers.Vectors) []int64 { + if inner == nil { + return nil } - switch basePKFilter.Oid { - case types.T_int8: - lb := types.DecodeInt8(basePKFilter.LB) - ub := types.DecodeInt8(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_int16: - lb := types.DecodeInt16(basePKFilter.LB) - ub := types.DecodeInt16(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_int32: - lb := types.DecodeInt32(basePKFilter.LB) - ub := types.DecodeInt32(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_int64: - lb := types.DecodeInt64(basePKFilter.LB) - ub := types.DecodeInt64(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_float32: - lb := types.DecodeFloat32(basePKFilter.LB) - ub := types.DecodeFloat32(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_float64: - lb := types.DecodeFloat64(basePKFilter.LB) - ub := types.DecodeFloat64(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_uint8: - lb := types.DecodeUint8(basePKFilter.LB) - ub := types.DecodeUint8(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_uint16: - lb := types.DecodeUint16(basePKFilter.LB) - ub := types.DecodeUint16(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_uint32: - lb := types.DecodeUint32(basePKFilter.LB) - ub := types.DecodeUint32(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_uint64: - lb := types.DecodeUint64(basePKFilter.LB) - ub := types.DecodeUint64(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_date: - lb := types.DecodeDate(basePKFilter.LB) - ub := types.DecodeDate(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_time: - lb := types.DecodeTime(basePKFilter.LB) - ub := types.DecodeTime(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_datetime: - lb := types.DecodeDatetime(basePKFilter.LB) - ub := types.DecodeDatetime(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_timestamp: - lb := types.DecodeTimestamp(basePKFilter.LB) - ub := types.DecodeTimestamp(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - case types.T_decimal64: - val1 := types.DecodeDecimal64(basePKFilter.LB) - val2 := types.DecodeDecimal64(basePKFilter.UB) - - sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareDecimal64) - unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareDecimal64) - case types.T_decimal128: - val1 := types.DecodeDecimal128(basePKFilter.LB) - val2 := types.DecodeDecimal128(basePKFilter.UB) - - sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareDecimal128) - unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareDecimal128) - case types.T_text, types.T_datalink, types.T_varchar, types.T_char, types.T_binary, types.T_json: - lb := string(basePKFilter.LB) - ub := string(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenString(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenString(lb, ub, hint) - case types.T_enum: - lb := types.DecodeEnum(basePKFilter.LB) - ub := types.DecodeEnum(basePKFilter.UB) - sortedSearchFunc = vector.CollectOffsetsByBetweenFactory(lb, ub, hint) - unSortedSearchFunc = vector.LinearCollectOffsetsByBetweenFactory(lb, ub, hint) - - case types.T_uuid: - val1 := types.Uuid(basePKFilter.LB) - val2 := types.Uuid(basePKFilter.UB) - - sortedSearchFunc = vector.CollectOffsetsByBetweenWithCompareFactory(val1, val2, types.CompareUuid) - unSortedSearchFunc = vector.FixedSizedLinearCollectOffsetsByBetweenFactory(val1, val2, types.CompareUuid) - default: + return func(cacheVectors containers.Vectors) []int64 { + if len(cacheVectors) == 0 || cacheVectors[0].Length() == 0 { + return nil + } + return inner(&cacheVectors[0]) } } - if sortedSearchFunc != nil { - readFilter.SortedSearchFunc = sortedSearchFunc - readFilter.UnSortedSearchFunc = unSortedSearchFunc - readFilter.Valid = true - return readFilter, nil - } else { + if len(bloomFilter) == 0 { + if sortedSearchFunc != nil { + readFilter.SortedSearchFunc = wrapInner(sortedSearchFunc) + readFilter.UnSortedSearchFunc = wrapInner(unSortedSearchFunc) + readFilter.Valid = true + return readFilter, nil + } + // No BF, and no search func constructed from PK, equivalent to "no block filtering" logutil.Warn("ConstructBlockPKFilter skipped data type", zap.Int("expr op", basePKFilter.Op), zap.String("data type", basePKFilter.Oid.String())) + return readFilter, nil } + // Case with BloomFilter: wrap existing search func. + var bf bloomfilter.BloomFilter + if err := bf.Unmarshal(bloomFilter); err != nil { + return objectio.BlockReadFilter{}, err + } + + // Reusable temporary variables (defined outside closure to avoid allocation on each call) + var ( + reusableSels []int64 + reusableExists map[int]bool + ) + + // Pure BloomFilter searchFunc: directly filter entire column with BloomFilter. + // This function only works when optimization is enabled (len(cacheVectors) >= 2). + // When optimization is enabled, cacheVectors[1] contains __mo_index_pri_col which is used for BF filtering. + // If len(cacheVectors) < 2, skip BF filtering and return nil. + bfOnlySearch := func(cacheVectors containers.Vectors) []int64 { + if len(cacheVectors) < 2 || cacheVectors[0].Length() == 0 || cacheVectors[1].Length() == 0 { + return nil + } + rowCount := cacheVectors[0].Length() + lastColVec := &cacheVectors[1] + sels := reusableSels[:0] + if cap(sels) < rowCount { + sels = make([]int64, 0, rowCount) + } + bf.Test(lastColVec, func(exist bool, row int) { + if exist && row >= 0 && row < rowCount { + sels = append(sels, int64(row)) + } + }) + reusableSels = sels + return sels + } + + // Wrap: if inner is nil, degenerate to pure BF; otherwise run inner first, then intersect with BF results. + // The inner function receives *vector.Vector (PK column) for PK filtering. + // cacheVectors[0] is used for PK filtering, cacheVectors[1] (if exists) is used for BF filtering. + // When optimization is enabled (len(cacheVectors) >= 2), cacheVectors[1] contains __mo_index_pri_col. + wrap := func(inner func(*vector.Vector) []int64) func(containers.Vectors) []int64 { + if inner == nil { + return bfOnlySearch + } + return func(cacheVectors containers.Vectors) []int64 { + if len(cacheVectors) == 0 || cacheVectors[0].Length() == 0 { + return nil + } + + pkVec := &cacheVectors[0] + rowCount := pkVec.Length() + offsets := inner(pkVec) + innerCount := len(offsets) + + if innerCount == 0 { + return offsets + } + + // Test BloomFilter on rows filtered by inner function. + // Only works when optimization is enabled (len(cacheVectors) >= 2). + if len(cacheVectors) < 2 || cacheVectors[1].Length() == 0 { + // No optimization: skip BF filtering, return all offsets that passed inner filter. + return offsets + } + + // Optimization enabled: use cacheVectors[1] (__mo_index_pri_col) for BF filtering. + lastColVec := &cacheVectors[1] + var exists map[int]bool + var bfHits int + + // Reuse exists map - use more efficient reallocation for large maps + if reusableExists == nil || rowCount > len(reusableExists)*2 { + reusableExists = make(map[int]bool, rowCount) + } else if len(reusableExists) > 0 { + // For small maps, clear by reallocating (more efficient than delete loop) + if len(reusableExists) < 100 { + // For small maps, use delete loop + for k := range reusableExists { + delete(reusableExists, k) + } + } else { + // For larger maps, reallocate is more efficient + reusableExists = make(map[int]bool, rowCount) + } + } + exists = reusableExists + + // Test BloomFilter on lastColVec, but only for rows that passed inner filter. + rowSet := make(map[int]bool, len(offsets)) + for _, off := range offsets { + if int(off) >= 0 && int(off) < rowCount { + rowSet[int(off)] = true + } + } + bf.Test(lastColVec, func(exist bool, row int) { + // Add strict boundary check to prevent index out of range + if exist && row >= 0 && row < rowCount && rowSet[row] { + exists[row] = true + bfHits++ + } + }) + + out := offsets[:0] + for _, off := range offsets { + if exists[int(off)] { + out = append(out, off) + } + } + return out + } + } + + readFilter.SortedSearchFunc = wrap(sortedSearchFunc) + readFilter.UnSortedSearchFunc = wrap(unSortedSearchFunc) + readFilter.Valid = true + // Set cleanup function to release BloomFilter when filter is no longer needed + readFilter.Cleanup = func() { + // Release BloomFilter memory + bf.Clean() + // Clear reusableExists map by reallocating for better memory efficiency + if reusableExists != nil { + reusableExists = nil + } + } return readFilter, nil } diff --git a/pkg/vm/engine/readutil/reader.go b/pkg/vm/engine/readutil/reader.go index 6431b0c095bea..0ae4b1180e399 100644 --- a/pkg/vm/engine/readutil/reader.go +++ b/pkg/vm/engine/readutil/reader.go @@ -27,6 +27,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/defines" "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/matrixorigin/matrixone/pkg/logutil" @@ -50,6 +51,10 @@ import ( // ----------------------------------------------------------------- func (mixin *withFilterMixin) reset() { + // Cleanup reusableTempVec and other resources before resetting filter + if mixin.filterState.filter.Cleanup != nil { + mixin.filterState.filter.Cleanup() + } mixin.filterState.filter = objectio.BlockReadFilter{} mixin.filterState.memFilter = MemPKFilter{} mixin.columns.indexOfFirstSortedColumn = -1 @@ -137,12 +142,44 @@ func (mixin *withFilterMixin) tryUpdateColumns(cols []string) { } if pkPos != -1 { - // here we will select the primary key column from the vectors, and - // use the search function to find the offset of the primary key. - // it returns the offset of the primary key in the pk vector. - // if the primary key is not found, it returns empty slice - mixin.filterState.seqnums = []uint16{mixin.columns.seqnums[pkPos]} - mixin.filterState.colTypes = mixin.columns.colTypes[pkPos : pkPos+1] + // For composite primary key, optimize BloomFilter filtering by using __mo_index_pri_col directly + // if all conditions are met (IVF entries table, has BF, last PK col is __mo_index_pri_col, query includes it). + if mixin.tableDef.Pkey != nil && len(mixin.tableDef.Pkey.Names) > 1 { + // Composite primary key: check optimization conditions. + lastPKColName := strings.ToLower(mixin.tableDef.Pkey.Names[len(mixin.tableDef.Pkey.Names)-1]) + + // Check all conditions for optimization (must all be satisfied): + // 1. Table type is IVF entries table. + isIVFEntriesTable := mixin.tableDef.TableType == catalog.SystemSI_IVFFLAT_TblType_Entries + // 2. Has bloom filter. + hasBF := mixin.filterState.hasBF + // 3. Last PK column is __mo_index_pri_col. + isLastColPriCol := lastPKColName == strings.ToLower(catalog.IndexTablePrimaryColName) + // 4. Query includes __mo_index_pri_col. + lastPKColPos := -1 + for i, col := range cols { + if strings.ToLower(col) == lastPKColName { + lastPKColPos = i + break + } + } + + if isIVFEntriesTable && hasBF && isLastColPriCol && lastPKColPos != -1 { + // All conditions met: use both PK column and __mo_index_pri_col for filtering. + // cacheVectors[0] will be used for PK filtering. + // cacheVectors[1] will be used for BF filtering (directly, no unpacking needed). + mixin.filterState.seqnums = []uint16{mixin.columns.seqnums[pkPos], mixin.columns.seqnums[lastPKColPos]} + mixin.filterState.colTypes = []types.Type{mixin.columns.colTypes[pkPos], mixin.columns.colTypes[lastPKColPos]} + } else { + // Conditions not met: use composite PK column only. + mixin.filterState.seqnums = []uint16{mixin.columns.seqnums[pkPos]} + mixin.filterState.colTypes = mixin.columns.colTypes[pkPos : pkPos+1] + } + } else { + // Single primary key or non-composite: use the primary key column directly. + mixin.filterState.seqnums = []uint16{mixin.columns.seqnums[pkPos]} + mixin.filterState.colTypes = mixin.columns.colTypes[pkPos : pkPos+1] + } } if mixin.tableDef.Pkey != nil { @@ -232,6 +269,7 @@ type withFilterMixin struct { seqnums []uint16 // seqnums of the columns in the filter pkSeqNum int32 colTypes []types.Type + hasBF bool // whether bloom filter is available } orderByLimit *objectio.BlockReadTopOp @@ -366,6 +404,7 @@ func NewReader( blockFilter, err := ConstructBlockPKFilter( catalog.IsFakePkName(tableDef.Pkey.PkeyColName), baseFilter, + filterHint.BloomFilter, ) if err != nil { return nil, err @@ -384,6 +423,7 @@ func NewReader( r.filterState.expr = expr r.filterState.filter = blockFilter r.filterState.memFilter = memFilter + r.filterState.hasBF = len(filterHint.BloomFilter) > 0 r.threshHold = threshHold return r, nil } @@ -402,12 +442,12 @@ func (r *reader) SetOrderBy(orderby []*plan.OrderBySpec) { r.source.SetOrderBy(orderby) } -func (r *reader) SetBlockTop(orderby []*plan.OrderBySpec, limit uint64) { - if len(orderby) == 0 || limit == 0 { +func (r *reader) SetBlockTop(orderBy []*plan.OrderBySpec, limit uint64) { + if len(orderBy) == 0 || limit == 0 { return } - orderFunc := orderby[0].Expr.GetF() + orderFunc := orderBy[0].Expr.GetF() if orderFunc == nil { panic("order function is nil") } @@ -548,6 +588,19 @@ func (r *reader) Read( return true, nil } if state == engine.InMem { + if r.orderByLimit != nil { + sels, dists, err := blockio.HandleOrderByLimitOnIVFFlatIndex(ctx, nil, outBatch.Vecs[r.orderByLimit.ColPos], r.orderByLimit) + if err != nil { + return false, err + } + + outBatch.Shuffle(sels, mp) + + distVec := vector.NewVec(types.T_float64.ToType()) + vector.AppendFixedList(distVec, dists, nil, mp) + outBatch.Vecs = append(outBatch.Vecs, distVec) + } + return false, nil } //read block diff --git a/pkg/vm/engine/tae/blockio/read.go b/pkg/vm/engine/tae/blockio/read.go index 6c6176cbf8da3..37c1aafc88aa4 100644 --- a/pkg/vm/engine/tae/blockio/read.go +++ b/pkg/vm/engine/tae/blockio/read.go @@ -18,7 +18,7 @@ import ( "container/heap" "context" "fmt" - "slices" + "sort" "time" "github.com/matrixorigin/matrixone/pkg/common/moerr" @@ -60,7 +60,7 @@ func removeIf[T any](data []T, pred func(t T) bool) []T { // ReadDataByFilter only read block data from storage by filter, don't apply deletes. // Right now, it cannot support filter by physical address column. -// len(columns) == len(colTypes) == 1 +// len(columns) == len(colTypes) >= 1 (supports multiple columns for optimization) func ReadDataByFilter( ctx context.Context, tableName string, @@ -94,7 +94,7 @@ func ReadDataByFilter( defer release() defer deleteMask.Release() - sels = searchFunc(&cacheVectors[0]) + sels = searchFunc(cacheVectors) if !deleteMask.IsEmpty() { sels = removeIf(sels, func(i int64) bool { return deleteMask.Contains(uint64(i)) @@ -377,6 +377,166 @@ func BlockDataReadBackup( return } +func HandleOrderByLimitOnIVFFlatIndex( + ctx context.Context, + selectRows []int64, + vecCol *vector.Vector, + orderByLimit *objectio.BlockReadTopOp, +) ([]int64, []float64, error) { + if selectRows == nil { + selectRows = make([]int64, vecCol.Length()) + for i := range selectRows { + selectRows[i] = int64(i) + } + } + + var sels []int64 + var dists []float64 + + nullsBm := vecCol.GetNulls() + + if int(orderByLimit.Limit) < len(selectRows) { + // apply topn if needed + hp := make(vectorindex.SearchResultMaxHeap, 0, orderByLimit.Limit) + + switch orderByLimit.Typ { + case types.T_array_float32: + distFunc, err := metric.ResolveDistanceFn[float32](orderByLimit.Metric) + if err != nil { + return nil, nil, err + } + + rhs := types.BytesToArray[float32](orderByLimit.NumVec) + + for _, row := range selectRows { + if nullsBm.Contains(uint64(row)) { + continue + } + dist, err := distFunc(types.BytesToArray[float32](vecCol.GetBytesAt(int(row))), rhs) + if err != nil { + return nil, nil, err + } + dist64 := float64(dist) + + heapItem := &vectorindex.SearchResult{ + Id: row, + Distance: dist64, + } + if len(hp) >= int(orderByLimit.Limit) { + if dist64 < hp[0].GetDistance() { + hp[0] = heapItem + heap.Fix(&hp, 0) + } + } else { + heap.Push(&hp, heapItem) + } + } + + case types.T_array_float64: + distFunc, err := metric.ResolveDistanceFn[float64](orderByLimit.Metric) + if err != nil { + return nil, nil, err + } + + rhs := types.BytesToArray[float64](orderByLimit.NumVec) + + for _, row := range selectRows { + if nullsBm.Contains(uint64(row)) { + continue + } + dist, err := distFunc(types.BytesToArray[float64](vecCol.GetBytesAt(int(row))), rhs) + if err != nil { + return nil, nil, err + } + + heapItem := &vectorindex.SearchResult{ + Id: row, + Distance: dist, + } + if len(hp) >= int(orderByLimit.Limit) { + if dist < hp[0].GetDistance() { + hp[0] = heapItem + heap.Fix(&hp, 0) + } + } else { + heap.Push(&hp, heapItem) + } + } + + default: + return nil, nil, moerr.NewInternalError(ctx, fmt.Sprintf("only support float32/float64 type for topn: %s", orderByLimit.Typ)) + } + + sRes := make([]vectorindex.SearchResult, len(hp)) + for i := range sRes { + sRes[i] = *hp[i].(*vectorindex.SearchResult) + } + sort.Slice(sRes, func(i, j int) bool { + return sRes[i].Id < sRes[j].Id + }) + + sels = make([]int64, len(sRes)) + dists = make([]float64, len(sRes)) + + for i := range sRes { + sels[i] = sRes[i].Id + dists[i] = sRes[i].Distance + } + } else { + sels = make([]int64, 0, len(selectRows)) + dists = make([]float64, 0, len(selectRows)) + + switch orderByLimit.Typ { + case types.T_array_float32: + distFunc, err := metric.ResolveDistanceFn[float32](orderByLimit.Metric) + if err != nil { + return nil, nil, err + } + + rhs := types.BytesToArray[float32](orderByLimit.NumVec) + + for _, row := range selectRows { + if nullsBm.Contains(uint64(row)) { + continue + } + dist, err := distFunc(types.BytesToArray[float32](vecCol.GetBytesAt(int(row))), rhs) + if err != nil { + return nil, nil, err + } + + sels = append(sels, row) + dists = append(dists, float64(dist)) + } + + case types.T_array_float64: + distFunc, err := metric.ResolveDistanceFn[float64](orderByLimit.Metric) + if err != nil { + return nil, nil, err + } + + rhs := types.BytesToArray[float64](orderByLimit.NumVec) + + for _, row := range selectRows { + if nullsBm.Contains(uint64(row)) { + continue + } + dist, err := distFunc(types.BytesToArray[float64](vecCol.GetBytesAt(int(row))), rhs) + if err != nil { + return nil, nil, err + } + + sels = append(sels, row) + dists = append(dists, float64(dist)) + } + + default: + return nil, nil, moerr.NewInternalError(ctx, fmt.Sprintf("only support float32/float64 type for topn: %s", orderByLimit.Typ)) + } + } + + return sels, dists, nil +} + // BlockDataReadInner only read data,don't apply deletes. func BlockDataReadInner( ctx context.Context, @@ -420,80 +580,19 @@ func BlockDataReadInner( // len(selectRows) > 0 means it was already filtered by pk filter if len(selectRows) > 0 { - if orderByLimit != nil && int(orderByLimit.Limit) < len(selectRows) { - // apply topn if needed - hp := make(vectorindex.SearchResultMaxHeap, 0, orderByLimit.Limit) - lhs := cacheVectors[orderByLimit.ColPos] - - switch orderByLimit.Typ { - case types.T_array_float32: - distFunc, err := metric.ResolveDistanceFn[float32](orderByLimit.Metric) - if err != nil { - return err - } - - rhs := types.BytesToArray[float32](orderByLimit.NumVec) + var dists []float64 - for _, row := range selectRows { - dist, err := distFunc(types.BytesToArray[float32](lhs.GetBytesAt(int(row))), rhs) - if err != nil { - return err - } - dist64 := float64(dist) - - heapItem := &vectorindex.SearchResult{ - Id: row, - Distance: dist64, - } - if len(hp) >= int(orderByLimit.Limit) { - if dist64 < hp[0].GetDistance() { - hp[0] = heapItem - heap.Fix(&hp, 0) - } - } else { - heap.Push(&hp, heapItem) - } - } - - case types.T_array_float64: - distFunc, err := metric.ResolveDistanceFn[float64](orderByLimit.Metric) - if err != nil { - return err - } - - rhs := types.BytesToArray[float64](orderByLimit.NumVec) - - for _, row := range selectRows { - dist64, err := distFunc(types.BytesToArray[float64](lhs.GetBytesAt(int(row))), rhs) - if err != nil { - return err - } - - heapItem := &vectorindex.SearchResult{ - Id: row, - Distance: dist64, - } - if len(hp) >= int(orderByLimit.Limit) { - if dist64 < hp[0].GetDistance() { - hp[0] = heapItem - heap.Fix(&hp, 0) - } - } else { - heap.Push(&hp, heapItem) - } - } - - default: - return moerr.NewInternalErrorNoCtx(fmt.Sprintf("only support float32/float64 type for topn: %s", orderByLimit.Typ)) + if orderByLimit != nil { + vecColPos := orderByLimit.ColPos + if phyAddrColumnPos >= 0 && vecColPos > int32(phyAddrColumnPos) { + vecColPos-- } + vecCol := &cacheVectors[vecColPos] - sels := make([]int64, 0, orderByLimit.Limit) - for len(hp) > 0 { - sels = append(sels, heap.Pop(&hp).(*vectorindex.SearchResult).Id) + selectRows, dists, err = HandleOrderByLimitOnIVFFlatIndex(ctx, selectRows, vecCol, orderByLimit) + if err != nil { + return err } - - slices.Sort(sels) - selectRows = sels } // phyAddrColumnPos >= 0 means one of the columns is the physical address column @@ -514,6 +613,10 @@ func BlockDataReadInner( if outputColPos == phyAddrColumnPos { continue } + if orderByLimit != nil && loadedColumnPos == int(orderByLimit.ColPos) { + loadedColumnPos++ + continue + } if err = outputBat.Vecs[outputColPos].PreExtendWithArea( len(selectRows), 0, mp, ); err != nil { @@ -526,6 +629,16 @@ func BlockDataReadInner( } loadedColumnPos++ } + + if orderByLimit != nil { + if len(outputBat.Vecs) == len(columns) { + distVec := vector.NewVec(types.T_float64.ToType()) + vector.AppendFixedList(distVec, dists, nil, mp) + outputBat.Vecs = append(outputBat.Vecs, distVec) + } else { + vector.AppendFixedList(outputBat.Vecs[len(outputBat.Vecs)-1], dists, nil, mp) + } + } return } diff --git a/pkg/vm/engine/types.go b/pkg/vm/engine/types.go index 054e1a72b196d..abd4b70aa997a 100644 --- a/pkg/vm/engine/types.go +++ b/pkg/vm/engine/types.go @@ -1319,5 +1319,6 @@ func GetPrefetchOnSubscribed() (bool, []*regexp.Regexp) { } type FilterHint struct { - Must bool + Must bool + BloomFilter []byte } diff --git a/pkg/vm/message/runtimeFilterMsg.go b/pkg/vm/message/runtimeFilterMsg.go index 0735c28a1b6e8..42756b3e0dfb1 100644 --- a/pkg/vm/message/runtimeFilterMsg.go +++ b/pkg/vm/message/runtimeFilterMsg.go @@ -26,6 +26,7 @@ const ( RuntimeFilter_BITMAP = 1 RuntimeFilter_MIN_MAX = 2 RuntimeFilter_BINARY_FUSE = 3 + RuntimeFilter_BLOOMFILTER = 4 RuntimeFilter_PASS = 100 RuntimeFilter_DROP = 101 ) diff --git a/proto/plan.proto b/proto/plan.proto index 7ef80ded4af75..20cf44ce4d290 100644 --- a/proto/plan.proto +++ b/proto/plan.proto @@ -814,6 +814,7 @@ message Node { // LIMIT Expr limit = 15; Expr offset = 16; + RankOption rank_option = 89; TableDef table_def = 17; ObjectRef obj_ref = 18; @@ -988,6 +989,7 @@ message RuntimeFilterSpec { int32 upper_limit = 3; Expr expr = 4; bool not_on_pk = 5; + bool use_bloom_filter = 6; } message IdList { @@ -1688,3 +1690,7 @@ enum AlterPartitionType { TruncatePartitionTables = 2; RedefinePartitionTables = 3; } + +message RankOption { + string mode = 1; // "pre" or "post" +} diff --git a/test/distributed/cases/dml/show/database_statistics.result b/test/distributed/cases/dml/show/database_statistics.result index 417231beaf2b2..9e01dc3f9a325 100644 --- a/test/distributed/cases/dml/show/database_statistics.result +++ b/test/distributed/cases/dml/show/database_statistics.result @@ -9,7 +9,7 @@ Number of tables in mysql 6 show table_number from mo_catalog; Number of tables in mo_catalog -39 +40 show table_number from system; Number of tables in system 6 @@ -113,25 +113,25 @@ Number of columns in mo_table_partitions use system_metrics; show column_number from metric; Number of columns in metric -7 +8 show column_number from sql_statement_total; Number of columns in sql_statement_total -6 +7 show column_number from sql_statement_errors; Number of columns in sql_statement_errors -6 +7 show column_number from sql_statement_cu; Number of columns in sql_statement_cu 6 show column_number from sql_transaction_total; Number of columns in sql_transaction_total -5 +6 show column_number from sql_transaction_errors; Number of columns in sql_transaction_errors -6 +7 show column_number from server_connections; Number of columns in server_connections -5 +6 show column_number from process_cpu_percent; Number of columns in process_cpu_percent 5 @@ -168,7 +168,7 @@ Number of columns in sys_net_sent_bytes use system; show column_number from statement_info; Number of columns in statement_info -28 +31 show column_number from rawlog; Number of columns in rawlog 23 @@ -272,6 +272,7 @@ show table_values from external_table; max(col1) min(col1) max(col2) min(col2) max(col3) min(col3) max(col4) min(col4) max(col6) min(col6) max(col7) min(col7) 100 10 10.34 1.34 你好 aaa 2011-10-11 2011-10-10 true false DROP TABLE IF EXISTS partition_table; + create table partition_table( empno int unsigned auto_increment, ename varchar(15), @@ -285,6 +286,7 @@ primary key(empno, deptno) ) PARTITION BY KEY(deptno) PARTITIONS 4; + show table_number from test_db; Number of tables in test_db 8 @@ -295,20 +297,26 @@ select mo_table_rows("test_db", "partition_table"),mo_table_size("test_db", "par mo_table_rows(test_db, partition_table) mo_table_size(test_db, partition_table) 0 0 INSERT INTO partition_table VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); + INSERT INTO partition_table VALUES (7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30); + show table_values from partition_table; max(empno) min(empno) max(ename) min(ename) max(job) min(job) max(mgr) min(mgr) max(hiredate) min(hiredate) max(sal) min(sal) max(comm) min(comm) max(deptno) min(deptno) 7499 7369 SMITH ALLEN SALESMAN CLERK 7902 7698 1981-02-20 1980-12-17 1600.00 800.00 300.00 300.00 30 20 INSERT INTO partition_table VALUES (7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30); + INSERT INTO partition_table VALUES (7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20); + show table_values from partition_table; max(empno) min(empno) max(ename) min(ename) max(job) min(job) max(mgr) min(mgr) max(hiredate) min(hiredate) max(sal) min(sal) max(comm) min(comm) max(deptno) min(deptno) 7566 7369 WARD ALLEN SALESMAN CLERK 7902 7698 1981-04-02 1980-12-17 2975.00 800.00 500.00 300.00 30 20 set mo_table_stats.use_old_impl = yes; + select mo_table_rows("test_db", "partition_table"),mo_table_size("test_db", "partition_table"); mo_table_rows(test_db, partition_table) mo_table_size(test_db, partition_table) 4 512 set mo_table_stats.use_old_impl = no; + create table t2( col1 json ); @@ -449,7 +457,7 @@ Number of columns in mo_columns use system; show column_number from statement_info; Number of columns in statement_info -28 +31 drop database if exists test_db; create database test_db; show table_number from test_db; diff --git a/test/distributed/cases/fulltext/fulltext1.result b/test/distributed/cases/fulltext/fulltext1.result index af372f6c05ee6..aa39cf71f8a69 100644 --- a/test/distributed/cases/fulltext/fulltext1.result +++ b/test/distributed/cases/fulltext/fulltext1.result @@ -141,14 +141,14 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.a = #[1,0]) + Join Cond: (t1.a = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on test.t1 [ForceOneCN] Filter Cond: (t1.c = 100) Block Filter Cond: (t1.c = 100) Runtime Filter Probe: t1.a -> Index Table Scan on t1.index2 [ForceOneCN] - Filter Cond: prefix_eq(#[0,0]) - Block Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) + Block Filter Cond: prefix_eq(__mo_index_idx_col) drop table t1; drop database test; diff --git a/test/distributed/cases/function/func_datetime_addtime.result b/test/distributed/cases/function/func_datetime_addtime.result index 2a5f0b490e2b1..3375898494835 100644 --- a/test/distributed/cases/function/func_datetime_addtime.result +++ b/test/distributed/cases/function/func_datetime_addtime.result @@ -1,30 +1,30 @@ -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS result1; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS result1; result1 -null +2008-01-02 01:01:01.000001 SELECT TIME(ADDTIME('12:30:45', '01:15:30')) AS time_add_time; time_add_time 13:46:15 SELECT TIME(ADDTIME('23:59:59', '00:00:01')) AS time_wrap; time_wrap -00:00:00 +24:00:00 SELECT TIME(ADDTIME('00:00:00', '25:00:00')) AS time_with_days; time_with_days -01:00:00 +25:00:00 SELECT ADDTIME('2007-12-31 23:59:59', '00:00:01') AS datetime_add_second; datetime_add_second 2008-01-01 00:00:00 -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS datetime_add_time_with_days; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS datetime_add_time_with_days; datetime_add_time_with_days -null +2008-01-02 01:01:01.000001 SELECT ADDTIME('2024-01-01 00:00:00', '24:00:00') AS datetime_add_day; datetime_add_day 2024-01-02 00:00:00 SELECT ADDTIME('2007-12-31 23:59:59', '00:00:01') AS timestamp_add_second; timestamp_add_second 2008-01-01 00:00:00 -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS string_datetime; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS string_datetime; string_datetime -null +2008-01-02 01:01:01.000001 SELECT TIME(ADDTIME('12:30:45', '01:15:30')) AS string_time; string_time 13:46:15 @@ -42,7 +42,10 @@ zero_time 00:00:00 SELECT TIME(ADDTIME('23:59:59.999999', '00:00:00.000001')) AS microsecond_precision; microsecond_precision -00:00:00 +24:00:00 +SELECT TIME(ADDTIME('25:59:59', '10:00:01')) AS time_wrap_36; +time_wrap_36 +36:00:00 CREATE TABLE t1(dt DATETIME, t TIME); INSERT INTO t1 VALUES ('2007-12-31 23:59:59', '01:00:00'), ('2024-01-01 12:00:00', '02:30:00'); SELECT ADDTIME(dt, t) AS result FROM t1; diff --git a/test/distributed/cases/function/func_datetime_addtime.test b/test/distributed/cases/function/func_datetime_addtime.test index 3da96ac4e1bfc..c131b023a60e7 100644 --- a/test/distributed/cases/function/func_datetime_addtime.test +++ b/test/distributed/cases/function/func_datetime_addtime.test @@ -1,5 +1,5 @@ # Basic test case from requirements -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS result1; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS result1; # Additional test cases # TIME + TIME @@ -9,14 +9,14 @@ SELECT TIME(ADDTIME('00:00:00', '25:00:00')) AS time_with_days; # DATETIME + TIME SELECT ADDTIME('2007-12-31 23:59:59', '00:00:01') AS datetime_add_second; -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS datetime_add_time_with_days; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS datetime_add_time_with_days; SELECT ADDTIME('2024-01-01 00:00:00', '24:00:00') AS datetime_add_day; # TIMESTAMP + TIME SELECT ADDTIME('2007-12-31 23:59:59', '00:00:01') AS timestamp_add_second; # String inputs -SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS string_datetime; +SELECT CAST(ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS string_datetime; SELECT TIME(ADDTIME('12:30:45', '01:15:30')) AS string_time; # NULL handling @@ -27,6 +27,7 @@ SELECT ADDTIME(NULL, NULL) AS null_both; # Edge cases SELECT TIME(ADDTIME('00:00:00', '00:00:00')) AS zero_time; SELECT TIME(ADDTIME('23:59:59.999999', '00:00:00.000001')) AS microsecond_precision; +SELECT TIME(ADDTIME('25:59:59', '10:00:01')) AS time_wrap_36; # Table usage CREATE TABLE t1(dt DATETIME, t TIME); diff --git a/test/distributed/cases/function/func_datetime_subtime.result b/test/distributed/cases/function/func_datetime_subtime.result index 50573010cb178..8f73ff30a3769 100644 --- a/test/distributed/cases/function/func_datetime_subtime.result +++ b/test/distributed/cases/function/func_datetime_subtime.result @@ -1,6 +1,6 @@ -SELECT SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS result1; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS result1; result1 -null +2007-12-30 22:58:58.999997 SELECT TIME(SUBTIME('15:30:45', '01:15:30')) AS time_sub_time; time_sub_time 14:15:15 @@ -10,9 +10,9 @@ time_sub_zero SELECT TIME(SUBTIME('00:00:00', '00:00:01')) AS zero_sub_second; zero_sub_second 23:59:59 -SELECT SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS datetime_sub_time; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS datetime_sub_time; datetime_sub_time -null +2007-12-30 22:58:58.999997 SELECT SUBTIME('2007-12-31 10:30:45', '02:15:30') AS datetime_sub_hours; datetime_sub_hours 2007-12-31 08:15:15 @@ -34,9 +34,9 @@ negative_result SELECT SUBTIME('2007-12-31 00:00:00', '1 0:0:0') AS negative_datetime; negative_datetime 2007-12-30 00:00:00 -SELECT SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000001') AS with_microseconds; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000001') AS CHAR) AS with_microseconds; with_microseconds -null +2007-12-31 23:59:59.999998 SELECT TIME(SUBTIME('15:30:45.500000', '00:00:00.200000')) AS time_with_microseconds; time_with_microseconds 15:30:45 @@ -62,9 +62,9 @@ SELECT * FROM t1 WHERE SUBTIME(dt, t) < '2007-12-31 00:00:00'; dt t 2007-12-31 23:59:59 25:01:01 DROP TABLE t1; -SELECT SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000000') AS no_change; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000000') AS CHAR) AS no_change; no_change -null +2007-12-31 23:59:59.999999 SELECT SUBTIME('2007-12-31 00:00:00', '0 0:0:1') AS one_second_before; one_second_before 2007-12-30 23:59:59 diff --git a/test/distributed/cases/function/func_datetime_subtime.test b/test/distributed/cases/function/func_datetime_subtime.test index f0b0cff285dd5..8729233937e1d 100644 --- a/test/distributed/cases/function/func_datetime_subtime.test +++ b/test/distributed/cases/function/func_datetime_subtime.test @@ -1,5 +1,5 @@ # Basic test case from requirements -SELECT SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS result1; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS result1; # Additional test cases # TIME - TIME @@ -8,7 +8,7 @@ SELECT TIME(SUBTIME('15:30:45', '00:00:00')) AS time_sub_zero; SELECT TIME(SUBTIME('00:00:00', '00:00:01')) AS zero_sub_second; # DATETIME - TIME -SELECT SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS datetime_sub_time; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002') AS CHAR) AS datetime_sub_time; SELECT SUBTIME('2007-12-31 10:30:45', '02:15:30') AS datetime_sub_hours; SELECT SUBTIME('2007-12-31 00:00:00', '00:00:01') AS datetime_sub_second; @@ -24,7 +24,7 @@ SELECT TIME(SUBTIME('01:00:00', '02:00:00')) AS negative_result; SELECT SUBTIME('2007-12-31 00:00:00', '1 0:0:0') AS negative_datetime; # With microseconds -SELECT SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000001') AS with_microseconds; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000001') AS CHAR) AS with_microseconds; SELECT TIME(SUBTIME('15:30:45.500000', '00:00:00.200000')) AS time_with_microseconds; # NULL handling @@ -45,7 +45,7 @@ SELECT * FROM t1 WHERE SUBTIME(dt, t) < '2007-12-31 00:00:00'; DROP TABLE t1; # Edge cases -SELECT SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000000') AS no_change; +SELECT CAST(SUBTIME('2007-12-31 23:59:59.999999', '0 0:0:0.000000') AS CHAR) AS no_change; SELECT SUBTIME('2007-12-31 00:00:00', '0 0:0:1') AS one_second_before; SELECT SUBTIME('2007-12-31 23:59:59', '0 0:1:0') AS one_minute_before; diff --git a/test/distributed/cases/function/func_datetime_timediff.result b/test/distributed/cases/function/func_datetime_timediff.result index 1892f697c2574..eaf58fe1a1424 100644 --- a/test/distributed/cases/function/func_datetime_timediff.result +++ b/test/distributed/cases/function/func_datetime_timediff.result @@ -1,24 +1,24 @@ SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00.000001') AS result1; result1 -null +00:00:00.000001000 SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00.000001') AS microsecond_diff; microsecond_diff -null +00:00:00.000001000 SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00') AS zero_diff; zero_diff -null +00:00:00 SELECT TIMEDIFF('2000:01:01 00:00:01', '2000:01:01 00:00:00') AS one_second_diff; one_second_diff -null +00:00:01 SELECT TIMEDIFF('2000:01:01 01:00:00', '2000:01:01 00:00:00') AS one_hour_diff; one_hour_diff -null +01:00:00 SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:01') AS negative_one_second; negative_one_second -null +00:00:01 SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 01:00:00') AS negative_one_hour; negative_one_hour -null +-1:00:00 SELECT TIMEDIFF('15:30:45', '10:20:30') AS time_diff; time_diff 05:10:15 diff --git a/test/distributed/cases/ivf/pre.result b/test/distributed/cases/ivf/pre.result new file mode 100644 index 0000000000000..33501f873aa34 --- /dev/null +++ b/test/distributed/cases/ivf/pre.result @@ -0,0 +1,31 @@ +SET experimental_ivf_index = 1; +create database if not exists dd1; +use dd1; +CREATE TABLE `mini_vector_data` (`id` VARCHAR(64) NOT NULL, `text` TEXT DEFAULT NULL, `vec` vecf32(8) DEFAULT NULL COMMENT '8-dim embedding vector', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`)); +CREATE INDEX `idx_vec` USING ivfflat ON `mini_vector_data` (`vec`) lists = 16 op_type 'vector_l2_ops'; +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id1','hello world','[0.12,-0.33,0.51,0.27,-0.48,0.19,0.72,-0.11]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id2','greeting message','[0.44,0.09,-0.31,0.62,0.18,-0.55,0.21,0.33]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id3','vector search test','[-0.21,0.73,-0.12,0.51,-0.44,0.09,0.14,0.82]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id4','example data','[0.51,0.25,0.09,-0.33,0.74,-0.28,0.41,0.17]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id5','embedding sample','[0.08,-0.41,0.66,0.12,0.53,-0.15,0.38,-0.22]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id6','short text','[0.32,0.71,-0.26,0.14,-0.03,0.66,-0.41,0.19]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id7','random note','[-0.55,0.12,0.44,-0.19,0.27,0.51,0.11,-0.03]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id8','semantic item','[0.23,-0.14,0.82,0.39,-0.52,0.08,0.26,0.73]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id9','testing vectors','[0.61,0.33,-0.48,0.09,0.12,0.54,-0.29,0.41]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id10','additional entry','[0.19,-0.22,0.33,0.77,-0.04,0.12,0.58,-0.31]'); +WITH q AS (SELECT id, text, l2_distance(vec, '[0.1,-0.2,0.3,0.4,-0.1,0.2,0.0,0.5]') AS dist FROM mini_vector_data) SELECT * FROM q ORDER BY dist LIMIT 5 by rank with option 'mode=pre'; +id text dist +id8 semantic item 0.7760798852372132 +id1 hello world 1.0551303640156267 +id10 additional entry 1.0718208877650799 +id2 greeting message 1.1550325221482527 +id3 vector search test 1.1828778308075465 +WITH q AS (SELECT id, text, l2_distance(vec, '[0.1,-0.2,0.3,0.4,-0.1,0.2,0.0,0.5]') AS dist FROM mini_vector_data) SELECT * FROM q ORDER BY dist LIMIT 5 by rank with option 'mode=post'; +id text dist +id8 semantic item 0.7760798852372132 +id1 hello world 1.0551303640156267 +id10 additional entry 1.0718208877650799 +id2 greeting message 1.1550325221482527 +id3 vector search test 1.1828778308075465 +SET experimental_ivf_index = 0; +drop database if exists dd1; \ No newline at end of file diff --git a/test/distributed/cases/ivf/pre.sql b/test/distributed/cases/ivf/pre.sql new file mode 100644 index 0000000000000..188f19f2b8c39 --- /dev/null +++ b/test/distributed/cases/ivf/pre.sql @@ -0,0 +1,19 @@ +SET experimental_ivf_index = 1; +create database if not exists dd1; +use dd1; +CREATE TABLE `mini_vector_data` (`id` VARCHAR(64) NOT NULL, `text` TEXT DEFAULT NULL, `vec` vecf32(8) DEFAULT NULL COMMENT '8-dim embedding vector', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`)); +CREATE INDEX `idx_vec` USING ivfflat ON `mini_vector_data` (`vec`) lists = 16 op_type 'vector_l2_ops'; +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id1','hello world','[0.12,-0.33,0.51,0.27,-0.48,0.19,0.72,-0.11]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id2','greeting message','[0.44,0.09,-0.31,0.62,0.18,-0.55,0.21,0.33]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id3','vector search test','[-0.21,0.73,-0.12,0.51,-0.44,0.09,0.14,0.82]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id4','example data','[0.51,0.25,0.09,-0.33,0.74,-0.28,0.41,0.17]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id5','embedding sample','[0.08,-0.41,0.66,0.12,0.53,-0.15,0.38,-0.22]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id6','short text','[0.32,0.71,-0.26,0.14,-0.03,0.66,-0.41,0.19]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id7','random note','[-0.55,0.12,0.44,-0.19,0.27,0.51,0.11,-0.03]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id8','semantic item','[0.23,-0.14,0.82,0.39,-0.52,0.08,0.26,0.73]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id9','testing vectors','[0.61,0.33,-0.48,0.09,0.12,0.54,-0.29,0.41]'); +INSERT INTO mini_vector_data (id, text, vec) VALUES ('id10','additional entry','[0.19,-0.22,0.33,0.77,-0.04,0.12,0.58,-0.31]'); +WITH q AS (SELECT id, text, l2_distance(vec, '[0.1,-0.2,0.3,0.4,-0.1,0.2,0.0,0.5]') AS dist FROM mini_vector_data) SELECT * FROM q ORDER BY dist LIMIT 5 by rank with option 'mode=pre'; +WITH q AS (SELECT id, text, l2_distance(vec, '[0.1,-0.2,0.3,0.4,-0.1,0.2,0.0,0.5]') AS dist FROM mini_vector_data) SELECT * FROM q ORDER BY dist LIMIT 5 by rank with option 'mode=post'; +SET experimental_ivf_index = 0; +drop database if exists dd1; \ No newline at end of file diff --git a/test/distributed/cases/log/column_metric.result b/test/distributed/cases/log/column_metric.result index 4e07591f8eeb0..e4d9628623a7f 100644 --- a/test/distributed/cases/log/column_metric.result +++ b/test/distributed/cases/log/column_metric.result @@ -1,6 +1,6 @@ select metric_name, collecttime, value, `node`, role, account, type from system_metrics.metric limit 0; -metric_name collecttime value node role account type -select count(1) cnt, metric_name, collecttime, `node`, role, account, type from system_metrics.metric group by metric_name, collecttime, `node`, role, account, type having cnt > 1; +metric_name collecttime value node role account type +select count(1) cnt, metric_name, collecttime, `node`, role, account, type from system_metrics.metric group by metric_name, collecttime, `node`, role, account, account_id, type having cnt > 1; cnt metric_name collecttime node role account type select count(1) > 0 exist from system_metrics.metric where collecttime > date_sub(now(), interval 5 minute) and metric_name = 'server_storage_usage'; exist diff --git a/test/distributed/cases/log/column_metric.sql b/test/distributed/cases/log/column_metric.sql index a6e455ae5792e..fdbc52095c853 100644 --- a/test/distributed/cases/log/column_metric.sql +++ b/test/distributed/cases/log/column_metric.sql @@ -1,5 +1,5 @@ select metric_name, collecttime, value, `node`, role, account, type from system_metrics.metric limit 0; -- issue https://github.com/matrixorigin/MO-Cloud/issues/2569 -select count(1) cnt, metric_name, collecttime, `node`, role, account, type from system_metrics.metric group by metric_name, collecttime, `node`, role, account, type having cnt > 1; +select count(1) cnt, metric_name, collecttime, `node`, role, account, type from system_metrics.metric group by metric_name, collecttime, `node`, role, account, account_id, type having cnt > 1; -- issue https://github.com/matrixorigin/MO-Cloud/issues/2569, check server_storage_usage exist select count(1) > 0 exist from system_metrics.metric where collecttime > date_sub(now(), interval 5 minute) and metric_name = 'server_storage_usage'; diff --git a/test/distributed/cases/log/show_table.result b/test/distributed/cases/log/show_table.result index 93cbf496a18f0..9736c4ec5bb67 100644 --- a/test/distributed/cases/log/show_table.result +++ b/test/distributed/cases/log/show_table.result @@ -1,9 +1,9 @@ SHOW CREATE TABLE system_metrics.metric; Table Create Table -metric CREATE TABLE `metric` (\n `metric_name` varchar(1024) DEFAULT 'sys' COMMENT 'metric name, like: sql_statement_total, server_connections, process_cpu_percent, sys_memory_used, ...',\n `collecttime` datetime(6) NOT NULL COMMENT 'metric data collect time',\n `value` double DEFAULT '0.0' COMMENT 'metric value',\n `node` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node uuid',\n `role` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node role, like: CN, DN, LOG',\n `account` varchar(1024) DEFAULT 'sys' COMMENT 'account name',\n `type` varchar(1024) NOT NULL COMMENT 'sql type, like: insert, select, ...'\n) COMMENT='metric data' CLUSTER BY (`account`, `metric_name`, `collecttime`) +metric CREATE TABLE `metric` (\n `metric_name` varchar(1024) DEFAULT 'sys' COMMENT 'metric name, like: sql_statement_total, server_connections, process_cpu_percent, sys_memory_used, ...',\n `collecttime` datetime(6) NOT NULL COMMENT 'metric data collect time',\n `value` double DEFAULT '0.0' COMMENT 'metric value',\n `node` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node uuid',\n `role` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node role, like: CN, DN, LOG',\n `account` varchar(1024) DEFAULT 'sys' COMMENT 'account name',\n `account_id` int unsigned DEFAULT '0' COMMENT 'account id',\n `type` varchar(1024) NOT NULL COMMENT 'sql type, like: insert, select, ...'\n) COMMENT='metric data' CLUSTER BY (`collecttime`, `account_id`, `metric_name`) SHOW CREATE TABLE system.statement_info; Table Create Table -statement_info CREATE TABLE `statement_info` (\n `statement_id` varchar(36) NOT NULL COMMENT 'statement uniq id',\n `transaction_id` varchar(36) NOT NULL COMMENT 'txn uniq id',\n `session_id` varchar(36) NOT NULL COMMENT 'session uniq id',\n `account` varchar(1024) NOT NULL COMMENT 'account name',\n `user` varchar(1024) NOT NULL COMMENT 'user name',\n `host` varchar(1024) NOT NULL COMMENT 'user client ip',\n `database` varchar(1024) NOT NULL COMMENT 'what database current session stay in.',\n `statement` text NOT NULL COMMENT 'sql statement',\n `statement_tag` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `statement_fingerprint` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `node_uuid` varchar(36) NOT NULL COMMENT 'node uuid, which node gen this data.',\n `node_type` varchar(1024) NOT NULL COMMENT 'node type in MO, val in [DN, CN, LOG]',\n `request_at` datetime(6) NOT NULL COMMENT 'request accept datetime',\n `response_at` datetime(6) NOT NULL COMMENT 'response send datetime',\n `duration` bigint unsigned DEFAULT '0' COMMENT 'exec time, unit: ns',\n `status` varchar(1024) NOT NULL COMMENT 'sql statement running status, enum: Running, Success, Failed',\n `err_code` varchar(1024) DEFAULT '0' COMMENT 'error code info',\n `error` text NOT NULL COMMENT 'error message',\n `exec_plan` text DEFAULT '{}' COMMENT 'statement execution plan',\n `rows_read` bigint DEFAULT '0' COMMENT 'rows read total',\n `bytes_scan` bigint DEFAULT '0' COMMENT 'bytes scan total',\n `stats` text DEFAULT '[]' COMMENT 'global stats info in exec_plan',\n `statement_type` varchar(1024) NOT NULL COMMENT 'statement type, val in [Insert, Delete, Update, Drop Table, Drop User, ...]',\n `query_type` varchar(1024) NOT NULL COMMENT 'query type, val in [DQL, DDL, DML, DCL, TCL]',\n `role_id` bigint DEFAULT '0' COMMENT 'role id',\n `sql_source_type` text NOT NULL COMMENT 'sql statement source type',\n `aggr_count` bigint DEFAULT '0' COMMENT 'the number of statements aggregated',\n `result_count` bigint DEFAULT '0' COMMENT 'the number of rows of sql execution results',\n `connection_id` bigint DEFAULT '0' COMMENT 'connection id',\n `cu` double DEFAULT '0.0' COMMENT 'cu cost'\n) COMMENT='record each statement and stats info[mo_no_del_hint]' CLUSTER BY (`account`, `request_at`) +statement_info CREATE TABLE `statement_info` (\n `statement_id` varchar(36) NOT NULL COMMENT 'statement uniq id',\n `transaction_id` varchar(36) NOT NULL COMMENT 'txn uniq id',\n `session_id` varchar(36) NOT NULL COMMENT 'session uniq id',\n `account` varchar(1024) NOT NULL COMMENT 'account name',\n `account_id` int unsigned DEFAULT '0' COMMENT 'account id',\n `user` varchar(1024) NOT NULL COMMENT 'user name',\n `host` varchar(1024) NOT NULL COMMENT 'user client ip',\n `database` varchar(1024) NOT NULL COMMENT 'what database current session stay in.',\n `statement` text NOT NULL COMMENT 'sql statement',\n `statement_tag` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `statement_fingerprint` text NOT NULL COMMENT 'note tag in statement(Reserved)',\n `node_uuid` varchar(36) NOT NULL COMMENT 'node uuid, which node gen this data.',\n `node_type` varchar(1024) NOT NULL COMMENT 'node type in MO, val in [DN, CN, LOG]',\n `request_at` datetime(6) NOT NULL COMMENT 'request accept datetime',\n `response_at` datetime(6) NOT NULL COMMENT 'response send datetime',\n `duration` bigint unsigned DEFAULT '0' COMMENT 'exec time, unit: ns',\n `status` varchar(1024) NOT NULL COMMENT 'sql statement running status, enum: Running, Success, Failed',\n `err_code` varchar(1024) DEFAULT '0' COMMENT 'error code info',\n `error` text NOT NULL COMMENT 'error message',\n `exec_plan` text DEFAULT '{}' COMMENT 'statement execution plan',\n `rows_read` bigint DEFAULT '0' COMMENT 'rows read total',\n `bytes_scan` bigint DEFAULT '0' COMMENT 'bytes scan total',\n `stats` text DEFAULT '[]' COMMENT 'global stats info in exec_plan',\n `statement_type` varchar(1024) NOT NULL COMMENT 'statement type, val in [Insert, Delete, Update, Drop Table, Drop User, ...]',\n `query_type` varchar(1024) NOT NULL COMMENT 'query type, val in [DQL, DDL, DML, DCL, TCL]',\n `role_id` bigint DEFAULT '0' COMMENT 'role id',\n `sql_source_type` text NOT NULL COMMENT 'sql statement source type',\n `aggr_count` bigint DEFAULT '0' COMMENT 'the number of statements aggregated',\n `result_count` bigint DEFAULT '0' COMMENT 'the number of rows of sql execution results',\n `connection_id` bigint DEFAULT '0' COMMENT 'connection id',\n `cu` double DEFAULT '0.0' COMMENT 'cu cost'\n) COMMENT='record each statement and stats info[mo_no_del_hint]' CLUSTER BY (`request_at`, `account_id`) SHOW CREATE TABLE system.rawlog; Table Create Table rawlog CREATE TABLE `rawlog` (\n `raw_item` varchar(1024) NOT NULL COMMENT 'raw log item',\n `node_uuid` varchar(36) NOT NULL COMMENT 'node uuid, which node gen this data.',\n `node_type` varchar(1024) NOT NULL COMMENT 'node type in MO, val in [DN, CN, LOG]',\n `span_id` varchar(16) DEFAULT '0' COMMENT 'span uniq id',\n `trace_id` varchar(36) NOT NULL COMMENT 'trace uniq id',\n `logger_name` varchar(1024) NOT NULL COMMENT 'logger name',\n `timestamp` datetime(6) NOT NULL COMMENT 'timestamp of action',\n `level` varchar(1024) NOT NULL COMMENT 'log level, enum: debug, info, warn, error, panic, fatal',\n `caller` varchar(1024) NOT NULL COMMENT 'where it log, like: package/file.go:123',\n `message` text NOT NULL COMMENT 'log message',\n `extra` text DEFAULT '{}' COMMENT 'log dynamic fields',\n `err_code` varchar(1024) DEFAULT '0' COMMENT 'error code info',\n `error` text NOT NULL COMMENT 'error message',\n `stack` varchar(2048) NOT NULL COMMENT 'stack info',\n `span_name` varchar(1024) NOT NULL COMMENT 'span name, for example: step name of execution plan, function name in code, ...',\n `parent_span_id` varchar(16) DEFAULT '0' COMMENT 'parent span uniq id',\n `start_time` datetime(6) NOT NULL COMMENT 'start time',\n `end_time` datetime(6) NOT NULL COMMENT 'end time',\n `duration` bigint unsigned DEFAULT '0' COMMENT 'exec time, unit: ns',\n `resource` text DEFAULT '{}' COMMENT 'static resource information',\n `span_kind` varchar(1024) NOT NULL COMMENT 'span kind, enum: internal, statement, remote',\n `statement_id` varchar(36) NOT NULL COMMENT 'statement id',\n `session_id` varchar(36) NOT NULL COMMENT 'session id'\n) COMMENT='read merge data from log, error, span[mo_no_del_hint]' CLUSTER BY (`timestamp`) diff --git a/test/distributed/cases/mo_cloud/mo_cloud.result b/test/distributed/cases/mo_cloud/mo_cloud.result index 30e1d9f307fed..af0a3b53fc82c 100644 --- a/test/distributed/cases/mo_cloud/mo_cloud.result +++ b/test/distributed/cases/mo_cloud/mo_cloud.result @@ -203,8 +203,9 @@ value DOUBLE(0) null null node VARCHAR(1024) null null role VARCHAR(1024) null null account VARCHAR(1024) null null +account_id INT UNSIGNED(32) null null type VARCHAR(1024) null null -__mo_cbkey_007account011metric_name011collecttime VARCHAR(65535) null null +__mo_cbkey_011collecttime010account_id011metric_name VARCHAR(65535) null null SELECT concat(DATE_FORMAT(date_add(`request_at`,Interval 1 MINUTE),'%Y-%m-%d %H'),':',LPAD(CAST(1 * floor(minute(date_add(`request_at`,Interval 1 MINUTE)) / 1) as int),2,0),':00') AS stat_ts, AVG(duration) AS value, `query_type` AS type FROM `system`.`statement_info` WHERE request_at >= '2023-07-28 04:20:43' AND request_at <= '2023-07-28 04:50:43' AND `query_type` in ('DQL','DDL','DML','DCL','TCL','Other') GROUP BY `query_type`, concat(DATE_FORMAT(date_add(`request_at`,Interval 1 MINUTE),'%Y-%m-%d %H'),':',LPAD(CAST(1 * floor(minute(date_add(`request_at`,Interval 1 MINUTE)) / 1) as int),2,0),':00') ORDER BY concat(DATE_FORMAT(date_add(`request_at`,Interval 1 MINUTE),'%Y-%m-%d %H'),':',LPAD(CAST(1 * floor(minute(date_add(`request_at`,Interval 1 MINUTE)) / 1) as int),2,0),':00')LIMIT 100; stat_ts value type SELECT count(*) FROM (select `statement`,system.statement_info.statement_id,IF(`status`='Running', TIMESTAMPDIFF(MICROSECOND,`request_at`,now())*1000, `duration`) AS `duration`,`status`,`query_type`,`request_at`,system.statement_info.response_at,`user`,`database`,`transaction_id`,`session_id`,`rows_read`,`bytes_scan`,`result_count` from system.statement_info left join mo_catalog.statement_mo ON system.statement_info.statement_id = mo_catalog.statement_mo.statement_id where 1=1 AND `request_at` >= '2023-07-28 04:09:33' AND system.statement_info.statement_id LIKE '%cd%' AND system.statement_info.account = 'c3daefe4_2197_4192_a10e_d0acc5d9da30' AND `user` IN ('ab') AND `session_id` LIKE '%ef%' AND `duration` > 1000000000 AND `statement` LIKE '%show%' ESCAPE '\\\\' )t; @@ -251,19 +252,19 @@ Table Create Table user CREATE TABLE `user` (\n `Host` char(255) NOT NULL DEFAULT '',\n `User` char(32) NOT NULL DEFAULT '',\n `Select_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Insert_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Update_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Delete_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Drop_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Reload_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Shutdown_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Process_priv` varchar(10) NOT NULL DEFAULT 'N',\n `File_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Grant_priv` varchar(10) NOT NULL DEFAULT 'N',\n `References_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Index_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Alter_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Show_db_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Super_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_tmp_table_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Lock_tables_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Execute_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Repl_slave_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Repl_client_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_view_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Show_view_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_routine_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Alter_routine_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_user_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Event_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Trigger_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Create_tablespace_priv` varchar(10) NOT NULL DEFAULT 'N',\n `ssl_type` varchar(10) NOT NULL DEFAULT '',\n `ssl_cipher` blob NOT NULL,\n `x509_issuer` blob NOT NULL,\n `x509_subject` blob NOT NULL,\n `max_questions` int unsigned NOT NULL DEFAULT '0',\n `max_updates` int unsigned NOT NULL DEFAULT '0',\n `max_connections` int unsigned NOT NULL DEFAULT '0',\n `max_user_connections` int unsigned NOT NULL DEFAULT '0',\n `plugin` char(64) NOT NULL DEFAULT 'caching_sha2_password',\n `authentication_string` text DEFAULT NULL,\n `password_expired` varchar(10) NOT NULL DEFAULT 'N',\n `password_last_changed` timestamp NULL DEFAULT NULL,\n `password_lifetime` smallint unsigned DEFAULT NULL,\n `account_locked` varchar(10) NOT NULL DEFAULT 'N',\n `Create_role_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Drop_role_priv` varchar(10) NOT NULL DEFAULT 'N',\n `Password_reuse_history` smallint unsigned DEFAULT NULL,\n `Password_reuse_time` smallint unsigned DEFAULT NULL,\n `Password_require_current` varchar(10) DEFAULT NULL,\n `User_attributes` json DEFAULT NULL,\n PRIMARY KEY (`Host`,`User`)\n) SHOW CREATE TABLE system_metrics.metric; Table Create Table -metric CREATE TABLE `metric` (\n `metric_name` varchar(1024) DEFAULT 'sys' COMMENT 'metric name, like: sql_statement_total, server_connections, process_cpu_percent, sys_memory_used, ...',\n `collecttime` datetime(6) NOT NULL COMMENT 'metric data collect time',\n `value` double DEFAULT '0.0' COMMENT 'metric value',\n `node` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node uuid',\n `role` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node role, like: CN, DN, LOG',\n `account` varchar(1024) DEFAULT 'sys' COMMENT 'account name',\n `type` varchar(1024) NOT NULL COMMENT 'sql type, like: insert, select, ...'\n) COMMENT='metric data' CLUSTER BY (`account`, `metric_name`, `collecttime`) +metric CREATE TABLE `metric` (\n `metric_name` varchar(1024) DEFAULT 'sys' COMMENT 'metric name, like: sql_statement_total, server_connections, process_cpu_percent, sys_memory_used, ...',\n `collecttime` datetime(6) NOT NULL COMMENT 'metric data collect time',\n `value` double DEFAULT '0.0' COMMENT 'metric value',\n `node` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node uuid',\n `role` varchar(1024) DEFAULT 'monolithic' COMMENT 'mo node role, like: CN, DN, LOG',\n `account` varchar(1024) DEFAULT 'sys' COMMENT 'account name',\n `account_id` int unsigned DEFAULT '0' COMMENT 'account id',\n `type` varchar(1024) NOT NULL COMMENT 'sql type, like: insert, select, ...'\n) COMMENT='metric data' CLUSTER BY (`collecttime`, `account_id`, `metric_name`) SHOW CREATE TABLE system_metrics.server_connections; View Create View character_set_client collation_connection -server_connections CREATE VIEW IF NOT EXISTS `system_metrics`.`server_connections` as select `collecttime`, `value`, `node`, `role`, `account` from `system_metrics`.`metric` where `metric_name` = "server_connections" utf8mb4 utf8mb4_general_ci +server_connections CREATE VIEW IF NOT EXISTS `system_metrics`.`server_connections` as select `collecttime`, `value`, `node`, `role`, `account`, `account_id` from `system_metrics`.`metric` where `metric_name` = "server_connections" utf8mb4 utf8mb4_general_ci SHOW CREATE TABLE system_metrics.server_storage_usage; View Create View character_set_client collation_connection -server_storage_usage CREATE VIEW IF NOT EXISTS `system_metrics`.`server_storage_usage` as select `collecttime`, `value`, `node`, `role`, `account` from `system_metrics`.`metric` where `metric_name` = "server_storage_usage" utf8mb4 utf8mb4_general_ci +server_storage_usage CREATE VIEW IF NOT EXISTS `system_metrics`.`server_storage_usage` as select `collecttime`, `value`, `node`, `role`, `account`, `account_id` from `system_metrics`.`metric` where `metric_name` = "server_storage_usage" utf8mb4 utf8mb4_general_ci SHOW CREATE TABLE system_metrics.sql_statement_errors; View Create View character_set_client collation_connection -sql_statement_errors CREATE VIEW IF NOT EXISTS `system_metrics`.`sql_statement_errors` as select `collecttime`, `value`, `node`, `role`, `account`, `type` from `system_metrics`.`metric` where `metric_name` = "sql_statement_errors" utf8mb4 utf8mb4_general_ci +sql_statement_errors CREATE VIEW IF NOT EXISTS `system_metrics`.`sql_statement_errors` as select `collecttime`, `value`, `node`, `role`, `account`, `account_id`, `type` from `system_metrics`.`metric` where `metric_name` = "sql_statement_errors" utf8mb4 utf8mb4_general_ci SHOW CREATE TABLE system_metrics.sql_transaction_total; View Create View character_set_client collation_connection -sql_transaction_total CREATE VIEW IF NOT EXISTS `system_metrics`.`sql_transaction_total` as select `collecttime`, `value`, `node`, `role`, `account` from `system_metrics`.`metric` where `metric_name` = "sql_transaction_total" utf8mb4 utf8mb4_general_ci +sql_transaction_total CREATE VIEW IF NOT EXISTS `system_metrics`.`sql_transaction_total` as select `collecttime`, `value`, `node`, `role`, `account`, `account_id` from `system_metrics`.`metric` where `metric_name` = "sql_transaction_total" utf8mb4 utf8mb4_general_ci SHOW GLOBAL VARIABLES LIKE 'save_query_result'; Variable_name Value save_query_result off @@ -399,106 +400,106 @@ DESC `mo_sample_data_tpch_sf1`.`supplier` ; Unknown database mo_sample_data_tpch_sf1 DESC `mysql`.`columns_priv` ; Field Type Null Key Default Extra Comment -Host CHAR(255) NO PRI -Db CHAR(64) NO PRI -User CHAR(32) NO PRI -Table_name CHAR(64) NO PRI -Column_name CHAR(64) NO PRI +Host CHAR(255) NO PRI +Db CHAR(64) NO PRI +User CHAR(32) NO PRI +Table_name CHAR(64) NO PRI +Column_name CHAR(64) NO PRI Timestamp TIMESTAMP(0) NO CURRENT_TIMESTAMP() -Column_priv VARCHAR(10) NO +Column_priv VARCHAR(10) NO DESC `mysql`.`db` ; Field Type Null Key Default Extra Comment -Host CHAR(255) NO PRI -Db CHAR(64) NO PRI -User CHAR(32) NO PRI -Select_priv VARCHAR(10) NO N -Insert_priv VARCHAR(10) NO N -Update_priv VARCHAR(10) NO N -Delete_priv VARCHAR(10) NO N -Create_priv VARCHAR(10) NO N -Drop_priv VARCHAR(10) NO N -Grant_priv VARCHAR(10) NO N -References_priv VARCHAR(10) NO N -Index_priv VARCHAR(10) NO N -Alter_priv VARCHAR(10) NO N -Create_tmp_table_priv VARCHAR(10) NO N -Lock_tables_priv VARCHAR(10) NO N -Create_view_priv VARCHAR(10) NO N -Show_view_priv VARCHAR(10) NO N -Create_routine_priv VARCHAR(10) NO N -Alter_routine_priv VARCHAR(10) NO N -Execute_priv VARCHAR(10) NO N -Event_priv VARCHAR(10) NO N -Trigger_priv VARCHAR(10) NO N +Host CHAR(255) NO PRI +Db CHAR(64) NO PRI +User CHAR(32) NO PRI +Select_priv VARCHAR(10) NO N +Insert_priv VARCHAR(10) NO N +Update_priv VARCHAR(10) NO N +Delete_priv VARCHAR(10) NO N +Create_priv VARCHAR(10) NO N +Drop_priv VARCHAR(10) NO N +Grant_priv VARCHAR(10) NO N +References_priv VARCHAR(10) NO N +Index_priv VARCHAR(10) NO N +Alter_priv VARCHAR(10) NO N +Create_tmp_table_priv VARCHAR(10) NO N +Lock_tables_priv VARCHAR(10) NO N +Create_view_priv VARCHAR(10) NO N +Show_view_priv VARCHAR(10) NO N +Create_routine_priv VARCHAR(10) NO N +Alter_routine_priv VARCHAR(10) NO N +Execute_priv VARCHAR(10) NO N +Event_priv VARCHAR(10) NO N +Trigger_priv VARCHAR(10) NO N DESC `mysql`.`procs_priv` ; Field Type Null Key Default Extra Comment -Host CHAR(255) NO PRI -Db CHAR(64) NO PRI -User CHAR(32) NO PRI -Routine_name CHAR(64) NO PRI +Host CHAR(255) NO PRI +Db CHAR(64) NO PRI +User CHAR(32) NO PRI +Routine_name CHAR(64) NO PRI Routine_type VARCHAR(10) NO PRI null -Grantor VARCHAR(288) NO MUL -Proc_priv VARCHAR(10) NO +Grantor VARCHAR(288) NO MUL +Proc_priv VARCHAR(10) NO Timestamp TIMESTAMP(0) NO CURRENT_TIMESTAMP() DESC `mysql`.`tables_priv` ; Field Type Null Key Default Extra Comment -Host CHAR(255) NO PRI -Db CHAR(64) NO PRI -User CHAR(32) NO PRI -Table_name CHAR(64) NO PRI -Grantor VARCHAR(288) NO MUL +Host CHAR(255) NO PRI +Db CHAR(64) NO PRI +User CHAR(32) NO PRI +Table_name CHAR(64) NO PRI +Grantor VARCHAR(288) NO MUL Timestamp TIMESTAMP(0) NO CURRENT_TIMESTAMP() -Table_priv VARCHAR(10) NO -Column_priv VARCHAR(10) NO +Table_priv VARCHAR(10) NO +Column_priv VARCHAR(10) NO DESC `mysql`.`user` ; Field Type Null Key Default Extra Comment -Host CHAR(255) NO PRI -User CHAR(32) NO PRI -Select_priv VARCHAR(10) NO N -Insert_priv VARCHAR(10) NO N -Update_priv VARCHAR(10) NO N -Delete_priv VARCHAR(10) NO N -Create_priv VARCHAR(10) NO N -Drop_priv VARCHAR(10) NO N -Reload_priv VARCHAR(10) NO N -Shutdown_priv VARCHAR(10) NO N -Process_priv VARCHAR(10) NO N -File_priv VARCHAR(10) NO N -Grant_priv VARCHAR(10) NO N -References_priv VARCHAR(10) NO N -Index_priv VARCHAR(10) NO N -Alter_priv VARCHAR(10) NO N -Show_db_priv VARCHAR(10) NO N -Super_priv VARCHAR(10) NO N -Create_tmp_table_priv VARCHAR(10) NO N -Lock_tables_priv VARCHAR(10) NO N -Execute_priv VARCHAR(10) NO N -Repl_slave_priv VARCHAR(10) NO N -Repl_client_priv VARCHAR(10) NO N -Create_view_priv VARCHAR(10) NO N -Show_view_priv VARCHAR(10) NO N -Create_routine_priv VARCHAR(10) NO N -Alter_routine_priv VARCHAR(10) NO N -Create_user_priv VARCHAR(10) NO N -Event_priv VARCHAR(10) NO N -Trigger_priv VARCHAR(10) NO N -Create_tablespace_priv VARCHAR(10) NO N -ssl_type VARCHAR(10) NO +Host CHAR(255) NO PRI +User CHAR(32) NO PRI +Select_priv VARCHAR(10) NO N +Insert_priv VARCHAR(10) NO N +Update_priv VARCHAR(10) NO N +Delete_priv VARCHAR(10) NO N +Create_priv VARCHAR(10) NO N +Drop_priv VARCHAR(10) NO N +Reload_priv VARCHAR(10) NO N +Shutdown_priv VARCHAR(10) NO N +Process_priv VARCHAR(10) NO N +File_priv VARCHAR(10) NO N +Grant_priv VARCHAR(10) NO N +References_priv VARCHAR(10) NO N +Index_priv VARCHAR(10) NO N +Alter_priv VARCHAR(10) NO N +Show_db_priv VARCHAR(10) NO N +Super_priv VARCHAR(10) NO N +Create_tmp_table_priv VARCHAR(10) NO N +Lock_tables_priv VARCHAR(10) NO N +Execute_priv VARCHAR(10) NO N +Repl_slave_priv VARCHAR(10) NO N +Repl_client_priv VARCHAR(10) NO N +Create_view_priv VARCHAR(10) NO N +Show_view_priv VARCHAR(10) NO N +Create_routine_priv VARCHAR(10) NO N +Alter_routine_priv VARCHAR(10) NO N +Create_user_priv VARCHAR(10) NO N +Event_priv VARCHAR(10) NO N +Trigger_priv VARCHAR(10) NO N +Create_tablespace_priv VARCHAR(10) NO N +ssl_type VARCHAR(10) NO ssl_cipher BLOB(0) NO null x509_issuer BLOB(0) NO null x509_subject BLOB(0) NO null -max_questions INT UNSIGNED(32) NO 0 -max_updates INT UNSIGNED(32) NO 0 -max_connections INT UNSIGNED(32) NO 0 -max_user_connections INT UNSIGNED(32) NO 0 -plugin CHAR(64) NO caching_sha2_password +max_questions INT UNSIGNED(32) NO 0 +max_updates INT UNSIGNED(32) NO 0 +max_connections INT UNSIGNED(32) NO 0 +max_user_connections INT UNSIGNED(32) NO 0 +plugin CHAR(64) NO caching_sha2_password authentication_string TEXT(0) YES null -password_expired VARCHAR(10) NO N +password_expired VARCHAR(10) NO N password_last_changed TIMESTAMP(0) YES null password_lifetime SMALLINT UNSIGNED(16) YES null -account_locked VARCHAR(10) NO N -Create_role_priv VARCHAR(10) NO N -Drop_role_priv VARCHAR(10) NO N +account_locked VARCHAR(10) NO N +Create_role_priv VARCHAR(10) NO N +Drop_role_priv VARCHAR(10) NO N Password_reuse_history SMALLINT UNSIGNED(16) YES null Password_reuse_time SMALLINT UNSIGNED(16) YES null Password_require_current VARCHAR(10) YES null @@ -511,6 +512,7 @@ value DOUBLE(0) YES 0.0 metric value node VARCHAR(1024) YES monolithic mo node uuid role VARCHAR(1024) YES monolithic mo node role, like: CN, DN, LOG account VARCHAR(1024) YES sys account name +account_id INT UNSIGNED(32) YES 0 account id type VARCHAR(1024) NO null sql type, like: insert, select, ... DESC `system_metrics`.`server_connections` ; Field Type Null Key Default Extra Comment @@ -519,6 +521,7 @@ value DOUBLE(0) YES null node VARCHAR(1024) YES null role VARCHAR(1024) YES null account VARCHAR(1024) YES null +account_id INT UNSIGNED(32) YES null DESC `system_metrics`.`server_storage_usage` ; Field Type Null Key Default Extra Comment collecttime DATETIME(6) NO null @@ -526,6 +529,7 @@ value DOUBLE(0) YES null node VARCHAR(1024) YES null role VARCHAR(1024) YES null account VARCHAR(1024) YES null +account_id INT UNSIGNED(32) YES null DESC `system_metrics`.`sql_statement_errors` ; Field Type Null Key Default Extra Comment collecttime DATETIME(6) NO null @@ -533,6 +537,7 @@ value DOUBLE(0) YES null node VARCHAR(1024) YES null role VARCHAR(1024) YES null account VARCHAR(1024) YES null +account_id INT UNSIGNED(32) YES null type VARCHAR(1024) NO null DESC `system_metrics`.`sql_transaction_total` ; Field Type Null Key Default Extra Comment @@ -541,6 +546,7 @@ value DOUBLE(0) YES null node VARCHAR(1024) YES null role VARCHAR(1024) YES null account VARCHAR(1024) YES null +account_id INT UNSIGNED(32) YES null INSERT INTO `mo_catalog`.`statement_mo` (`statement_id`,`account`,`response_at`,`stu`,`account_id`) VALUES ('057247c5-2d0c-11ee-9e81-96ce077ba0f3','91731e77_49ea_4a8a_b1c7_d5512c7ae96e','2023-07-28 06:00:20','0.0003963262009632',2); no such table mo_catalog.statement_mo INSERT INTO `mo_mo`.`statement_time` (`cluster`,`last_time`) VALUES ('ab','2023-07-28 04:50:00'); @@ -590,11 +596,11 @@ count(*) SELECT datname AS name, IF (table_cnt IS NULL, 0, table_cnt) AS tables, role_name AS owner FROM (SELECT dat_id, datname, mo_database.created_time, IF(role_name IS NULL, '-', role_name) AS role_name FROM mo_catalog.mo_database LEFT JOIN mo_catalog.mo_role ON mo_database.owner = role_id) AS x LEFT JOIN(SELECT count(*) AS table_cnt, reldatabase_id FROM mo_catalog.mo_tables WHERE relkind IN ('r','v','e','cluster') GROUP BY reldatabase_id) AS y ON x.dat_id = y.reldatabase_id order by name; name tables owner information_schema 24 accountadmin -mo_catalog 23 - +mo_catalog 24 - mo_mo 0 accountadmin mysql 6 accountadmin system 1 accountadmin -system_metrics 9 accountadmin +system_metrics 11 accountadmin SELECT mo_catalog.mo_database.datname,mo_catalog.mo_tables.relname,mo_catalog.mo_tables.relkind, if (role_name IS NULL,'-', role_name) AS `owner` FROM mo_catalog.mo_database LEFT JOIN mo_catalog.mo_tables ON mo_catalog.mo_database.datname = mo_catalog.mo_tables.reldatabase LEFT JOIN mo_catalog.mo_role ON mo_catalog.mo_tables.owner=role_id WHERE (relname NOT LIKE "__mo_index_secondary_%" AND relname NOT LIKE "__mo_index_unique_%" OR relname IS NULL) ORDER BY reldatabase, relname; datname relname relkind owner mo_mo null null - diff --git a/test/distributed/cases/optimizer/explain_check.sql b/test/distributed/cases/optimizer/explain_check.sql index 52ecdbfbc5f62..d0fcea10dacef 100644 --- a/test/distributed/cases/optimizer/explain_check.sql +++ b/test/distributed/cases/optimizer/explain_check.sql @@ -40,12 +40,18 @@ explain (check '["= 5"]') select * from t4 where c1 + 2 = 5; -- check ReadSize format (ReadSize=xx|xx|xx), filter condition, and other key fields -- verify: ReadSize format with pipe separator, Analyze info fields, Table Scan node, and filter condition -- Note: ReadSize values may vary (cache state, data distribution), so we only verify format, not specific values +-- Temporarily disabled due to timeConsumed random value issue. Re-enable after bvt tool supports regex matching for result sets. +-- @bvt:issue#23146 explain (analyze true, check '["Table Scan", "ReadSize=", "|", "bytes", "InputSize=", "OutputSize=", "MemorySize=", "timeConsumed=", "inputRows=", "outputRows=", "= 3", "Filter Cond"]') select * from t4 where c1 + 2 = 5; +-- @bvt:issue -- @separator:table -- check ReadSize format (ReadSize=xx|xx|xx), filter condition, and other key fields -- verify: ReadSize format with pipe separator, Analyze info fields, Table Scan node, and filter condition -- Note: ReadSize values may vary (cache state, data distribution), so we only verify format, not specific values +-- Temporarily disabled due to timeConsumed random value issue. Re-enable after bvt tool supports regex matching for result sets. +-- @bvt:issue#23146 explain (analyze true, check '["Table Scan", "ReadSize=", "|", "bytes", "InputSize=", "OutputSize=", "MemorySize=", "timeConsumed=", "inputRows=", "outputRows=", "= 3", "Filter Cond"]') select * from t4 where c1 + 2 = 5; +-- @bvt:issue -- the following should fail -- @separator:table diff --git a/test/distributed/cases/optimizer/explain_index.result b/test/distributed/cases/optimizer/explain_index.result index eefccee505f52..a52337ee0a2e4 100644 --- a/test/distributed/cases/optimizer/explain_index.result +++ b/test/distributed/cases/optimizer/explain_index.result @@ -16,8 +16,8 @@ explain select c3,c4,c5 from t1 where c3=1; TP QUERY PLAN Project -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_eq(#[0,0]) - Block Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) + Block Filter Cond: prefix_eq(__mo_index_idx_col) select c3,c4,c5 from t1 where c3=1; c3 c4 c5 1 2 0 @@ -44,8 +44,8 @@ explain select c3,c4,c5 from t1 where c3 in (1,5,10,20); TP QUERY PLAN Project -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_in(#[0,0]) - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col) + Block Filter Cond: prefix_in(__mo_index_idx_col) select c3,c4,c5 from t1 where c3 in (1,5,10,20); c3 c4 c5 1 2 0 @@ -92,8 +92,8 @@ explain select c3,c4,c5 from t1 where c3 between 4 and 7 and c5=5; TP QUERY PLAN Project -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_between(#[0,0]), (serial_extract(#[0,0], 2, INT)) = 5) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col), (serial_extract(__mo_index_idx_col, 2, INT)) = 5) + Block Filter Cond: prefix_between(__mo_index_idx_col) select c3,c4,c5 from t1 where c3 between 4 and 7 and c5=5; c3 c4 c5 6 2 5 @@ -154,15 +154,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_cpkey_col = #[1,0]) + Join Cond: (t1.__mo_cpkey_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c3 = 1) Block Filter Cond: (t1.c3 = 1) Runtime Filter Probe: t1.__mo_cpkey_col -> Index Table Scan on t1.t1i1 [ForceOneCN] - Filter Cond: prefix_eq(#[0,0]) - Block Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) + Block Filter Cond: prefix_eq(__mo_index_idx_col) select * from t1 where c3=1; c1 c2 c3 c4 c5 1 3 1 2 0 @@ -190,8 +190,8 @@ Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_between(#[0,0]) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col) + Block Filter Cond: prefix_between(__mo_index_idx_col) select count(*) from t1 where c3 between 100 and 200; count(*) 1010 @@ -211,8 +211,8 @@ Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_in(#[0,0]) - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col) + Block Filter Cond: prefix_in(__mo_index_idx_col) select count(*) from t1 where c3 in(1,13,15,90,99); count(*) 50 @@ -222,8 +222,8 @@ Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_between(#[0,0]), (serial_extract(#[0,0], 2, INT)) < 100) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col), (serial_extract(__mo_index_idx_col, 2, INT)) < 100) + Block Filter Cond: prefix_between(__mo_index_idx_col) select count(*) from t1 where c3 between 1 and 100 and c5 <100; count(*) 1000 @@ -233,8 +233,8 @@ Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: prefix_between(#[0,0]), (serial_extract(#[0,0], 2, INT)) = -1) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col), (serial_extract(__mo_index_idx_col, 2, INT)) = -1) + Block Filter Cond: prefix_between(__mo_index_idx_col) select count(*) from t1 where c3 between 100 and 200 and c5 =-1; count(*) 110 @@ -243,15 +243,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_cpkey_col = #[1,0]) + Join Cond: (t1.__mo_cpkey_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c2 < 650), t1.c3 BETWEEN 200 AND 300 Block Filter Cond: (t1.c2 < 650) Runtime Filter Probe: t1.__mo_cpkey_col -> Index Table Scan on t1.t1i1 [ForceOneCN] - Filter Cond: prefix_between(#[0,0]), (serial_extract(#[0,1], 1, INT)) < 650) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col), (serial_extract(__mo_index_pri_col, 1, INT)) < 650) + Block Filter Cond: prefix_between(__mo_index_idx_col) select * from t1 where c3 between 200 and 300 and c2 <650; c1 c2 c3 c4 c5 200 600 200 1 -1 @@ -276,15 +276,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_cpkey_col = #[1,0]) + Join Cond: (t1.__mo_cpkey_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: t1.c2 in ([271386 271461 271485]), t1.c3 BETWEEN 100 AND 500 Block Filter Cond: t1.c2 in ([271386 271461 271485]) Runtime Filter Probe: t1.__mo_cpkey_col -> Index Table Scan on t1.t1i1 [ForceOneCN] - Filter Cond: prefix_between(#[0,0]), serial_extract(#[0,1], 1, INT)) in ([271386 271461 271485]) - Block Filter Cond: prefix_between(#[0,0]) + Filter Cond: prefix_between(__mo_index_idx_col), serial_extract(__mo_index_pri_col, 1, INT)) in ([271386 271461 271485]) + Block Filter Cond: prefix_between(__mo_index_idx_col) select * from t1 where c3 between 100 and 500 and c2 in (271461, 271485, 271386); c1 c2 c3 c4 c5 90462 271386 462 3 1 @@ -295,22 +295,22 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_cpkey_col = #[1,0]) + Join Cond: (t1.__mo_cpkey_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c3 BETWEEN 100 AND 500 or t1.c3 BETWEEN 1000 AND 1100 or t1.c3 BETWEEN 1300 AND 1500) Runtime Filter Probe: t1.__mo_cpkey_col -> Index Table Scan on t1.t1i1 [ForceOneCN] - Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_between(#[0,0])) - Block Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_between(#[0,0])) + Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col)) + Block Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col)) explain select count(*) from t1 where c3 between 100 and 500 or c3 between 1000 and 1100 or c3 between 1300 and 1500; TP QUERY PLAN Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_between(#[0,0])) - Block Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_between(#[0,0])) + Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col)) + Block Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col)) select count(*) from t1 where c3 between 100 and 500 or c3 between 1000 and 1100 or c3 between 1300 and 1500; count(*) 7030 @@ -336,22 +336,22 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_cpkey_col = #[1,0]) + Join Cond: (t1.__mo_cpkey_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c3 BETWEEN 100 AND 500 or t1.c3 BETWEEN 1000 AND 1100 or t1.c3 in ([271386 271461 271485])) Runtime Filter Probe: t1.__mo_cpkey_col -> Index Table Scan on t1.t1i1 [ForceOneCN] - Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_in(#[0,0])) - Block Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_in(#[0,0])) + Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_in(__mo_index_idx_col)) + Block Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_in(__mo_index_idx_col)) explain select count(*) from t1 where c3 between 100 and 500 or c3 between 1000 and 1100 or c3 in (271461, 271485, 271386); TP QUERY PLAN Project -> Aggregate Aggregate Functions: starcount(1) -> Index Table Scan on t1.t1i1 - Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_in(#[0,0])) - Block Filter Cond: (prefix_between(#[0,0]) or prefix_between(#[0,0]) or prefix_in(#[0,0])) + Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_in(__mo_index_idx_col)) + Block Filter Cond: (prefix_between(__mo_index_idx_col) or prefix_between(__mo_index_idx_col) or prefix_in(__mo_index_idx_col)) select count(*) from t1 where c3 between 100 and 500 or c3 between 1000 and 1100 or c3 in (271461, 271485, 271386); count(*) 5020 @@ -371,15 +371,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t2.c1 = #[1,0]) + Join Cond: (t2.c1 = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t2 [ForceOneCN] Filter Cond: t2.c2 in ([1 2 3 4 5 6 7 8 9]) Block Filter Cond: t2.c2 in ([1 2 3 4 5 6 7 8 9]) Runtime Filter Probe: t2.c1 -> Index Table Scan on t2.t2i1 [ForceOneCN] - Filter Cond: prefix_in(#[0,0]) - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col) + Block Filter Cond: prefix_in(__mo_index_idx_col) select * from t2 where c2 in (1,2,3,4,5,6,7,8,9); c1 c2 c3 c4 c5 1 2 1 3 2 @@ -405,15 +405,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t2.c1 = #[1,0]) + Join Cond: (t2.c1 = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t2 [ForceOneCN] Filter Cond: t2.c2 in ([1 2 3 4 5 6 7 8 9]), t2.c3 in ([1 2 3]) Block Filter Cond: t2.c2 in ([1 2 3 4 5 6 7 8 9]) Runtime Filter Probe: t2.c1 -> Index Table Scan on t2.t2i1 [ForceOneCN] - Filter Cond: prefix_in(#[0,0]), serial_extract(#[0,0], 1, INT)) in ([1 2 3]) - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col), serial_extract(__mo_index_idx_col, 1, INT)) in ([1 2 3]) + Block Filter Cond: prefix_in(__mo_index_idx_col) select * from t2 where c2 in (1,2,3,4,5,6,7,8,9) and c3 in (1,2,3); c1 c2 c3 c4 c5 1 2 1 3 2 @@ -427,15 +427,15 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t2.c1 = #[1,0]) + Join Cond: (t2.c1 = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t2 [ForceOneCN] Filter Cond: t2.c4 in ([1 2 3 4 5 6 7 8 9]), t2.c5 in ([2 3 4]) Block Filter Cond: t2.c4 in ([1 2 3 4 5 6 7 8 9]) Runtime Filter Probe: t2.c1 -> Index Table Scan on t2.t2i2 [ForceOneCN] - Filter Cond: prefix_in(#[0,0]), serial_extract(#[0,0], 1, INT)) in ([2 3 4]) - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col), serial_extract(__mo_index_idx_col, 1, INT)) in ([2 3 4]) + Block Filter Cond: prefix_in(__mo_index_idx_col) select * from t2 where c4 in (1,2,3,4,5,6,7,8,9) and c5 in (2,3,4); c1 c2 c3 c4 c5 1 2 1 3 2 @@ -452,18 +452,18 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t2.c1 = #[1,0]) + Join Cond: (t2.c1 = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t2 [ForceOneCN] Filter Cond: t2.c4 in ([1 2 3 4 5 6 7 8 9]), t2.c1 BETWEEN 1 AND 10000 Block Filter Cond: t2.c4 in ([1 2 3 4 5 6 7 8 9]), t2.c1 BETWEEN 1 AND 10000 Runtime Filter Probe: t2.c1 -> Index Table Scan on t2.t2i2 [ForceOneCN] - Filter Cond: prefix_in(#[0,0]), serial_extract(#[0,0], 2, INT)) BETWEEN 1 AND 10000 - Block Filter Cond: prefix_in(#[0,0]) + Filter Cond: prefix_in(__mo_index_idx_col), serial_extract(__mo_index_idx_col, 2, INT)) BETWEEN 1 AND 10000 + Block Filter Cond: prefix_in(__mo_index_idx_col) select * from t2 where c4 in (1,2,3,4,5,6,7,8,9) and c1 between 1 and 10000; c1 c2 c3 c4 c5 1 2 1 3 2 2 3 2 6 3 3 4 3 9 4 -drop database d1; \ No newline at end of file +drop database d1; diff --git a/test/distributed/cases/optimizer/index.result b/test/distributed/cases/optimizer/index.result index 386b354709393..9788c6ddf68f9 100644 --- a/test/distributed/cases/optimizer/index.result +++ b/test/distributed/cases/optimizer/index.result @@ -29,15 +29,15 @@ Project Runtime Filter Probe: t2.__mo_cpkey_col Match Prefix -> Join Join Type: INDEX - Join Cond: (t1.c1 = #[1,0]) + Join Cond: (t1.c1 = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c3 = 11) Block Filter Cond: (t1.c3 = 11) Runtime Filter Probe: t1.c1 -> Index Table Scan on t1.id1 [ForceOneCN] - Filter Cond: (#[0,0] = 11) - Block Filter Cond: (#[0,0] = 11) + Filter Cond: (__mo_index_idx_col = 11) + Block Filter Cond: (__mo_index_idx_col = 11) select * from t1,t2 where t1.c1=t2.c0 and t1.c3=11; c1 c2 c3 c0 c1 c2 c3 11 11 11 11 11 11 11 @@ -263,7 +263,7 @@ explain SELECT pseudo1 FROM t14 WHERE pseudo='joce'; TP QUERY PLAN Project -> Index Table Scan on t14.pseudo - Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) SELECT pseudo1 FROM t14 WHERE pseudo='joce'; pseudo1 testtt @@ -279,11 +279,11 @@ TP QUERY PLAN Project -> Join Join Type: INDEX - Join Cond: (t1.__mo_fake_pk_col = #[1,0]) + Join Cond: (t1.__mo_fake_pk_col = __mo_index_pri_col) Runtime Filter Build: #[-1,0] -> Table Scan on d1.t1 [ForceOneCN] Filter Cond: (t1.c1 = 1) Runtime Filter Probe: t1.__mo_fake_pk_col -> Index Table Scan on t1.c1 [ForceOneCN] - Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) drop database d1; diff --git a/test/distributed/cases/optimizer/like.result b/test/distributed/cases/optimizer/like.result index 242210eced3cd..8c05c50296745 100644 --- a/test/distributed/cases/optimizer/like.result +++ b/test/distributed/cases/optimizer/like.result @@ -76,9 +76,9 @@ explain select * from t1 where c2 like '123'; TP QUERY PLAN Project -> Index Table Scan on t1.c2 - Filter Cond: prefix_eq(#[0,0]) - Block Filter Cond: prefix_eq(#[0,0]) + Filter Cond: prefix_eq(__mo_index_idx_col) + Block Filter Cond: prefix_eq(__mo_index_idx_col) select * from t1 where c2 like '123'; c1 c2 c3 123 123 123 -drop database if exists d1; \ No newline at end of file +drop database if exists d1;